[initial version of Tizen_5.5] 33/210633/1
authorzhongyuan <zy123.yuan@samsung.com>
Tue, 23 Jul 2019 07:27:13 +0000 (15:27 +0800)
committerzhongyuan <zy123.yuan@samsung.com>
Tue, 23 Jul 2019 07:27:53 +0000 (15:27 +0800)
Change-Id: I062a68073c7f5cbff97ec820766ceb042c0e0c21

1029 files changed:
selector/ClassSelector_tct.js [new file with mode: 0755]
selector/DynamicPseudoSelector_index.js [new file with mode: 0755]
selector/DynamicPseudoSelector_tct.js [new file with mode: 0755]
selector/IdSelector_tct.js [new file with mode: 0755]
selector/README [new file with mode: 0755]
selector/TestClassSelector.js [new file with mode: 0755]
selector/TestClassSelector_index.js [new file with mode: 0755]
selector/TestDynamicPseudoSelector.js [new file with mode: 0755]
selector/TestIdSelector.js [new file with mode: 0755]
selector/TestIdSelector_index.js [new file with mode: 0755]
selector/TestTypeSelector.js [new file with mode: 0755]
selector/TestTypeSelector_index.js [new file with mode: 0755]
selector/TestUniversalSelector.js [new file with mode: 0755]
selector/TypeSelector_tct.js [new file with mode: 0755]
selector/UniversalSelector_index.js [new file with mode: 0755]
selector/UniversalSelector_tct.js [new file with mode: 0755]
selector/install.sh [new file with mode: 0755]
selector/selector.wgt [new file with mode: 0644]
tct-webwidget-w3c-tests-5.5.zip [new file with mode: 0644]
webWidgetTCT_device/DeviceAPI.wgt [new file with mode: 0755]
webWidgetTCT_device/DeviceAPI/.project [new file with mode: 0755]
webWidgetTCT_device/DeviceAPI/.rds_delta [new file with mode: 0755]
webWidgetTCT_device/DeviceAPI/.sdk_delta.info [new file with mode: 0755]
webWidgetTCT_device/DeviceAPI/.settings/.jsdtscope [new file with mode: 0755]
webWidgetTCT_device/DeviceAPI/.settings/org.eclipse.wst.css.core.prefs [new file with mode: 0755]
webWidgetTCT_device/DeviceAPI/.settings/org.eclipse.wst.jsdt.ui.superType.container [new file with mode: 0755]
webWidgetTCT_device/DeviceAPI/.settings/org.eclipse.wst.jsdt.ui.superType.name [new file with mode: 0755]
webWidgetTCT_device/DeviceAPI/.sign/.manifest.tmp [new file with mode: 0755]
webWidgetTCT_device/DeviceAPI/.sign/author-signature.xml [new file with mode: 0755]
webWidgetTCT_device/DeviceAPI/.sign/signature1.xml [new file with mode: 0755]
webWidgetTCT_device/DeviceAPI/.tproject [new file with mode: 0755]
webWidgetTCT_device/DeviceAPI/DeviceAPI.wgt [new file with mode: 0755]
webWidgetTCT_device/DeviceAPI/config.xml [new file with mode: 0755]
webWidgetTCT_device/DeviceAPI/css/style.css [new file with mode: 0755]
webWidgetTCT_device/DeviceAPI/icon.png [new file with mode: 0755]
webWidgetTCT_device/DeviceAPI/index.html [new file with mode: 0755]
webWidgetTCT_device/DeviceAPI/js/main.js [new file with mode: 0755]
webWidgetTCT_device/DeviceAPI/widget/f01/css/style.css [new file with mode: 0755]
webWidgetTCT_device/DeviceAPI/widget/f01/icon.png [new file with mode: 0755]
webWidgetTCT_device/DeviceAPI/widget/f01/index.html [new file with mode: 0755]
webWidgetTCT_device/DeviceAPI/widget/f01/js/main.js [new file with mode: 0755]
webWidgetTCT_device/DeviceAPI/widget/f01/js/promise.min.js [new file with mode: 0755]
webWidgetTCT_device/DeviceAPI/widget/f01/preview.png [new file with mode: 0755]
webWidgetTCT_device/DeviceAPI/widget/f01/resources/data.json [new file with mode: 0755]
webWidgetTCT_device/DeviceAPI/widget/f01/support/path.js [new file with mode: 0755]
webWidgetTCT_device/DeviceAPI/widget/f01/support/test.html [new file with mode: 0755]
webWidgetTCT_device/DeviceAPI/widget/f01/support/test.xml [new file with mode: 0755]
webWidgetTCT_device/DeviceAPI/widget/f01/support/test_timeout.xml [new file with mode: 0755]
webWidgetTCT_device/DeviceAPI/widget/f02/css/style.css [new file with mode: 0755]
webWidgetTCT_device/DeviceAPI/widget/f02/icon.png [new file with mode: 0755]
webWidgetTCT_device/DeviceAPI/widget/f02/index.html [new file with mode: 0755]
webWidgetTCT_device/DeviceAPI/widget/f02/js/main.js [new file with mode: 0755]
webWidgetTCT_device/DeviceAPI/widget/f02/js/promise.min.js [new file with mode: 0755]
webWidgetTCT_device/DeviceAPI/widget/f02/preview.png [new file with mode: 0755]
webWidgetTCT_device/DeviceAPI/widget/f02/resources/data.json [new file with mode: 0755]
webWidgetTCT_device/DeviceAPI/widget/f02/support/path.js [new file with mode: 0755]
webWidgetTCT_device/DeviceAPI/widget/f02/support/test.html [new file with mode: 0755]
webWidgetTCT_device/DeviceAPI/widget/f02/support/test.xml [new file with mode: 0755]
webWidgetTCT_device/DeviceAPI/widget/f02/support/test_timeout.xml [new file with mode: 0755]
webWidgetTCT_device/DeviceAPI/widget/f03/css/style.css [new file with mode: 0755]
webWidgetTCT_device/DeviceAPI/widget/f03/icon.png [new file with mode: 0755]
webWidgetTCT_device/DeviceAPI/widget/f03/index.html [new file with mode: 0755]
webWidgetTCT_device/DeviceAPI/widget/f03/js/main.js [new file with mode: 0755]
webWidgetTCT_device/DeviceAPI/widget/f03/js/promise.min.js [new file with mode: 0755]
webWidgetTCT_device/DeviceAPI/widget/f03/preview.png [new file with mode: 0755]
webWidgetTCT_device/DeviceAPI/widget/f03/resources/data.json [new file with mode: 0755]
webWidgetTCT_device/DeviceAPI/widget/f03/support/path.js [new file with mode: 0755]
webWidgetTCT_device/DeviceAPI/widget/f03/support/test.html [new file with mode: 0755]
webWidgetTCT_device/DeviceAPI/widget/f03/support/test.xml [new file with mode: 0755]
webWidgetTCT_device/DeviceAPI/widget/f03/support/test_timeout.xml [new file with mode: 0755]
webWidgetTCT_device/LICENSE [new file with mode: 0755]
webWidgetTCT_device/LICENSE.BSD-2.0 [new file with mode: 0755]
webWidgetTCT_device/README.md [new file with mode: 0755]
webWidgetTCT_device/doc/.gitignore [new file with mode: 0755]
webWidgetTCT_device/doc/README.md [new file with mode: 0755]
webWidgetTCT_device/doc/Tizen Avengers - WebApi Guidelines.pdf [new file with mode: 0755]
webWidgetTCT_device/doc/html/css/doctor.css [new file with mode: 0755]
webWidgetTCT_device/doc/html/css/print.css [new file with mode: 0755]
webWidgetTCT_device/doc/html/images/logo.png [new file with mode: 0755]
webWidgetTCT_device/doc/html/images/plugin_flow.png [new file with mode: 0755]
webWidgetTCT_device/doc/html/images/tizen-logo_32h.png [new file with mode: 0755]
webWidgetTCT_device/doc/html/index.html [new file with mode: 0755]
webWidgetTCT_device/doc/html/js/blank.html [new file with mode: 0755]
webWidgetTCT_device/doc/html/js/doctor.js [new file with mode: 0755]
webWidgetTCT_device/doc/html/js/lang-css.js [new file with mode: 0755]
webWidgetTCT_device/doc/html/js/moostrap-scrollspy.js [new file with mode: 0755]
webWidgetTCT_device/doc/html/js/mootools-yui-compressed.js [new file with mode: 0755]
webWidgetTCT_device/doc/html/js/prettify.js [new file with mode: 0755]
webWidgetTCT_device/doc/package.json [new file with mode: 0755]
webWidgetTCT_device/doc/src/assets/images/plugin_flow.png [new file with mode: 0755]
webWidgetTCT_device/doc/src/assets/images/tizen-logo_32h.png [new file with mode: 0755]
webWidgetTCT_device/doc/src/assets/webapi-plugins-devel-test.zip [new file with mode: 0755]
webWidgetTCT_device/doc/src/devel_package.md [new file with mode: 0755]
webWidgetTCT_device/doc/src/guideline.md [new file with mode: 0755]
webWidgetTCT_device/doc/src/implementation_cc.md [new file with mode: 0755]
webWidgetTCT_device/doc/src/implementation_js.md [new file with mode: 0755]
webWidgetTCT_device/doc/src/index.md [new file with mode: 0755]
webWidgetTCT_device/doc/src/plugin_structure.md [new file with mode: 0755]
webWidgetTCT_device/doc/src/tools.md [new file with mode: 0755]
webWidgetTCT_device/doc/src/widl.md [new file with mode: 0755]
webWidgetTCT_device/install.sh [new file with mode: 0755]
webWidgetTCT_device/packaging/webapi-plugins.pc [new file with mode: 0755]
webWidgetTCT_device/packaging/webapi-plugins.spec [new file with mode: 0755]
webWidgetTCT_device/res/tvsounds/back.pcm [new file with mode: 0755]
webWidgetTCT_device/res/tvsounds/cancel.pcm [new file with mode: 0755]
webWidgetTCT_device/res/tvsounds/del.pcm [new file with mode: 0755]
webWidgetTCT_device/res/tvsounds/enter.pcm [new file with mode: 0755]
webWidgetTCT_device/res/tvsounds/keypad.pcm [new file with mode: 0755]
webWidgetTCT_device/res/tvsounds/move.pcm [new file with mode: 0755]
webWidgetTCT_device/res/tvsounds/preparing.pcm [new file with mode: 0755]
webWidgetTCT_device/res/tvsounds/select.pcm [new file with mode: 0755]
webWidgetTCT_device/res/tvsounds/warning.pcm [new file with mode: 0755]
webWidgetTCT_device/src/account/account.gyp [new file with mode: 0755]
webWidgetTCT_device/src/account/account_api.js [new file with mode: 0755]
webWidgetTCT_device/src/account/account_extension.cc [new file with mode: 0755]
webWidgetTCT_device/src/account/account_extension.h [new file with mode: 0755]
webWidgetTCT_device/src/account/account_instance.cc [new file with mode: 0755]
webWidgetTCT_device/src/account/account_instance.h [new file with mode: 0755]
webWidgetTCT_device/src/account/account_manager.cc [new file with mode: 0755]
webWidgetTCT_device/src/account/account_manager.h [new file with mode: 0755]
webWidgetTCT_device/src/alarm/alarm.gyp [new file with mode: 0755]
webWidgetTCT_device/src/alarm/alarm_api.js [new file with mode: 0755]
webWidgetTCT_device/src/alarm/alarm_extension.cc [new file with mode: 0755]
webWidgetTCT_device/src/alarm/alarm_extension.h [new file with mode: 0755]
webWidgetTCT_device/src/alarm/alarm_instance.cc [new file with mode: 0755]
webWidgetTCT_device/src/alarm/alarm_instance.h [new file with mode: 0755]
webWidgetTCT_device/src/alarm/alarm_manager.cc [new file with mode: 0755]
webWidgetTCT_device/src/alarm/alarm_manager.h [new file with mode: 0755]
webWidgetTCT_device/src/alarm/alarm_utils.cc [new file with mode: 0755]
webWidgetTCT_device/src/alarm/alarm_utils.h [new file with mode: 0755]
webWidgetTCT_device/src/application/application.cc [new file with mode: 0755]
webWidgetTCT_device/src/application/application.gyp [new file with mode: 0755]
webWidgetTCT_device/src/application/application.h [new file with mode: 0755]
webWidgetTCT_device/src/application/application_api.js [new file with mode: 0755]
webWidgetTCT_device/src/application/application_extension.cc [new file with mode: 0755]
webWidgetTCT_device/src/application/application_extension.h [new file with mode: 0755]
webWidgetTCT_device/src/application/application_instance.cc [new file with mode: 0755]
webWidgetTCT_device/src/application/application_instance.h [new file with mode: 0755]
webWidgetTCT_device/src/application/application_manager.cc [new file with mode: 0755]
webWidgetTCT_device/src/application/application_manager.h [new file with mode: 0755]
webWidgetTCT_device/src/application/application_utils.cc [new file with mode: 0755]
webWidgetTCT_device/src/application/application_utils.h [new file with mode: 0755]
webWidgetTCT_device/src/application/requested_application_control.cc [new file with mode: 0755]
webWidgetTCT_device/src/application/requested_application_control.h [new file with mode: 0755]
webWidgetTCT_device/src/archive/archive.gyp [new file with mode: 0755]
webWidgetTCT_device/src/archive/archive_api.js [new file with mode: 0755]
webWidgetTCT_device/src/archive/archive_callback_data.cc [new file with mode: 0755]
webWidgetTCT_device/src/archive/archive_callback_data.h [new file with mode: 0755]
webWidgetTCT_device/src/archive/archive_extension.cc [new file with mode: 0755]
webWidgetTCT_device/src/archive/archive_extension.h [new file with mode: 0755]
webWidgetTCT_device/src/archive/archive_file.cc [new file with mode: 0755]
webWidgetTCT_device/src/archive/archive_file.h [new file with mode: 0755]
webWidgetTCT_device/src/archive/archive_file_entry.cc [new file with mode: 0755]
webWidgetTCT_device/src/archive/archive_file_entry.h [new file with mode: 0755]
webWidgetTCT_device/src/archive/archive_instance.cc [new file with mode: 0755]
webWidgetTCT_device/src/archive/archive_instance.h [new file with mode: 0755]
webWidgetTCT_device/src/archive/archive_manager.cc [new file with mode: 0755]
webWidgetTCT_device/src/archive/archive_manager.h [new file with mode: 0755]
webWidgetTCT_device/src/archive/archive_utils.cc [new file with mode: 0755]
webWidgetTCT_device/src/archive/archive_utils.h [new file with mode: 0755]
webWidgetTCT_device/src/archive/defs.h [new file with mode: 0755]
webWidgetTCT_device/src/archive/filesystem_file.cc [new file with mode: 0755]
webWidgetTCT_device/src/archive/filesystem_file.h [new file with mode: 0755]
webWidgetTCT_device/src/archive/filesystem_node.cc [new file with mode: 0755]
webWidgetTCT_device/src/archive/filesystem_node.h [new file with mode: 0755]
webWidgetTCT_device/src/archive/filesystem_path.cc [new file with mode: 0755]
webWidgetTCT_device/src/archive/filesystem_path.h [new file with mode: 0755]
webWidgetTCT_device/src/archive/un_zip.cc [new file with mode: 0755]
webWidgetTCT_device/src/archive/un_zip.h [new file with mode: 0755]
webWidgetTCT_device/src/archive/un_zip_extract_request.cc [new file with mode: 0755]
webWidgetTCT_device/src/archive/un_zip_extract_request.h [new file with mode: 0755]
webWidgetTCT_device/src/archive/zip.cc [new file with mode: 0755]
webWidgetTCT_device/src/archive/zip.h [new file with mode: 0755]
webWidgetTCT_device/src/archive/zip_add_request.cc [new file with mode: 0755]
webWidgetTCT_device/src/archive/zip_add_request.h [new file with mode: 0755]
webWidgetTCT_device/src/badge/badge.gyp [new file with mode: 0755]
webWidgetTCT_device/src/badge/badge_api.js [new file with mode: 0755]
webWidgetTCT_device/src/badge/badge_extension.cc [new file with mode: 0755]
webWidgetTCT_device/src/badge/badge_extension.h [new file with mode: 0755]
webWidgetTCT_device/src/badge/badge_instance.cc [new file with mode: 0755]
webWidgetTCT_device/src/badge/badge_instance.h [new file with mode: 0755]
webWidgetTCT_device/src/badge/badge_manager.cc [new file with mode: 0755]
webWidgetTCT_device/src/badge/badge_manager.h [new file with mode: 0755]
webWidgetTCT_device/src/bluetooth/bluetooth.gyp [new file with mode: 0755]
webWidgetTCT_device/src/bluetooth/bluetooth_adapter.cc [new file with mode: 0755]
webWidgetTCT_device/src/bluetooth/bluetooth_adapter.h [new file with mode: 0755]
webWidgetTCT_device/src/bluetooth/bluetooth_api.js [new file with mode: 0755]
webWidgetTCT_device/src/bluetooth/bluetooth_class.cc [new file with mode: 0755]
webWidgetTCT_device/src/bluetooth/bluetooth_class.h [new file with mode: 0755]
webWidgetTCT_device/src/bluetooth/bluetooth_device.cc [new file with mode: 0755]
webWidgetTCT_device/src/bluetooth/bluetooth_device.h [new file with mode: 0755]
webWidgetTCT_device/src/bluetooth/bluetooth_extension.cc [new file with mode: 0755]
webWidgetTCT_device/src/bluetooth/bluetooth_extension.h [new file with mode: 0755]
webWidgetTCT_device/src/bluetooth/bluetooth_gatt_service.cc [new file with mode: 0755]
webWidgetTCT_device/src/bluetooth/bluetooth_gatt_service.h [new file with mode: 0755]
webWidgetTCT_device/src/bluetooth/bluetooth_health_application.cc [new file with mode: 0755]
webWidgetTCT_device/src/bluetooth/bluetooth_health_application.h [new file with mode: 0755]
webWidgetTCT_device/src/bluetooth/bluetooth_health_channel.cc [new file with mode: 0755]
webWidgetTCT_device/src/bluetooth/bluetooth_health_channel.h [new file with mode: 0755]
webWidgetTCT_device/src/bluetooth/bluetooth_health_profile_handler.cc [new file with mode: 0755]
webWidgetTCT_device/src/bluetooth/bluetooth_health_profile_handler.h [new file with mode: 0755]
webWidgetTCT_device/src/bluetooth/bluetooth_instance.cc [new file with mode: 0755]
webWidgetTCT_device/src/bluetooth/bluetooth_instance.h [new file with mode: 0755]
webWidgetTCT_device/src/bluetooth/bluetooth_le_adapter.cc [new file with mode: 0755]
webWidgetTCT_device/src/bluetooth/bluetooth_le_adapter.h [new file with mode: 0755]
webWidgetTCT_device/src/bluetooth/bluetooth_le_device.cc [new file with mode: 0755]
webWidgetTCT_device/src/bluetooth/bluetooth_le_device.h [new file with mode: 0755]
webWidgetTCT_device/src/bluetooth/bluetooth_service_handler.cc [new file with mode: 0755]
webWidgetTCT_device/src/bluetooth/bluetooth_service_handler.h [new file with mode: 0755]
webWidgetTCT_device/src/bluetooth/bluetooth_socket.cc [new file with mode: 0755]
webWidgetTCT_device/src/bluetooth/bluetooth_socket.h [new file with mode: 0755]
webWidgetTCT_device/src/bluetooth/bluetooth_util.cc [new file with mode: 0755]
webWidgetTCT_device/src/bluetooth/bluetooth_util.h [new file with mode: 0755]
webWidgetTCT_device/src/bookmark/bookmark.gyp [new file with mode: 0755]
webWidgetTCT_device/src/bookmark/bookmark_api.js [new file with mode: 0755]
webWidgetTCT_device/src/bookmark/bookmark_extension.cc [new file with mode: 0755]
webWidgetTCT_device/src/bookmark/bookmark_extension.h [new file with mode: 0755]
webWidgetTCT_device/src/bookmark/bookmark_instance.cc [new file with mode: 0755]
webWidgetTCT_device/src/bookmark/bookmark_instance.h [new file with mode: 0755]
webWidgetTCT_device/src/calendar/calendar.cc [new file with mode: 0755]
webWidgetTCT_device/src/calendar/calendar.gyp [new file with mode: 0755]
webWidgetTCT_device/src/calendar/calendar.h [new file with mode: 0755]
webWidgetTCT_device/src/calendar/calendar_api.js [new file with mode: 0755]
webWidgetTCT_device/src/calendar/calendar_extension.cc [new file with mode: 0755]
webWidgetTCT_device/src/calendar/calendar_extension.h [new file with mode: 0755]
webWidgetTCT_device/src/calendar/calendar_instance.cc [new file with mode: 0755]
webWidgetTCT_device/src/calendar/calendar_instance.h [new file with mode: 0755]
webWidgetTCT_device/src/calendar/calendar_item.cc [new file with mode: 0755]
webWidgetTCT_device/src/calendar/calendar_item.h [new file with mode: 0755]
webWidgetTCT_device/src/calendar/calendar_manager.cc [new file with mode: 0755]
webWidgetTCT_device/src/calendar/calendar_manager.h [new file with mode: 0755]
webWidgetTCT_device/src/calendar/calendar_plugin.cc [new file with mode: 0755]
webWidgetTCT_device/src/calendar/calendar_privilege.h [new file with mode: 0755]
webWidgetTCT_device/src/calendar/calendar_record.cc [new file with mode: 0755]
webWidgetTCT_device/src/calendar/calendar_record.h [new file with mode: 0755]
webWidgetTCT_device/src/calendar/js/calendar.js [new file with mode: 0755]
webWidgetTCT_device/src/calendar/js/calendar_alarm.js [new file with mode: 0755]
webWidgetTCT_device/src/calendar/js/calendar_attendee.js [new file with mode: 0755]
webWidgetTCT_device/src/calendar/js/calendar_item.js [new file with mode: 0755]
webWidgetTCT_device/src/calendar/js/calendar_manager.js [new file with mode: 0755]
webWidgetTCT_device/src/calendar/js/calendar_recurrence_rule.js [new file with mode: 0755]
webWidgetTCT_device/src/calendar/js/common.js [new file with mode: 0755]
webWidgetTCT_device/src/callhistory/callhistory.cc [new file with mode: 0755]
webWidgetTCT_device/src/callhistory/callhistory.gyp [new file with mode: 0755]
webWidgetTCT_device/src/callhistory/callhistory.h [new file with mode: 0755]
webWidgetTCT_device/src/callhistory/callhistory_api.js [new file with mode: 0755]
webWidgetTCT_device/src/callhistory/callhistory_extension.cc [new file with mode: 0755]
webWidgetTCT_device/src/callhistory/callhistory_extension.h [new file with mode: 0755]
webWidgetTCT_device/src/callhistory/callhistory_instance.cc [new file with mode: 0755]
webWidgetTCT_device/src/callhistory/callhistory_instance.h [new file with mode: 0755]
webWidgetTCT_device/src/callhistory/callhistory_types.h [new file with mode: 0755]
webWidgetTCT_device/src/callhistory/callhistory_utils.cc [new file with mode: 0755]
webWidgetTCT_device/src/callhistory/callhistory_utils.h [new file with mode: 0755]
webWidgetTCT_device/src/common/GDBus/connection.cpp [new file with mode: 0755]
webWidgetTCT_device/src/common/GDBus/connection.h [new file with mode: 0755]
webWidgetTCT_device/src/common/GDBus/proxy.cpp [new file with mode: 0755]
webWidgetTCT_device/src/common/GDBus/proxy.h [new file with mode: 0755]
webWidgetTCT_device/src/common/XW_Extension.cc [new file with mode: 0755]
webWidgetTCT_device/src/common/XW_Extension.h [new file with mode: 0755]
webWidgetTCT_device/src/common/XW_Extension_Data.h [new file with mode: 0755]
webWidgetTCT_device/src/common/XW_Extension_EntryPoints.h [new file with mode: 0755]
webWidgetTCT_device/src/common/XW_Extension_Permissions.h [new file with mode: 0755]
webWidgetTCT_device/src/common/XW_Extension_Runtime.h [new file with mode: 0755]
webWidgetTCT_device/src/common/XW_Extension_SyncMessage.h [new file with mode: 0755]
webWidgetTCT_device/src/common/assert.h [new file with mode: 0755]
webWidgetTCT_device/src/common/callback_user_data.cc [new file with mode: 0755]
webWidgetTCT_device/src/common/callback_user_data.h [new file with mode: 0755]
webWidgetTCT_device/src/common/common.gyp [new file with mode: 0755]
webWidgetTCT_device/src/common/common.gypi [new file with mode: 0755]
webWidgetTCT_device/src/common/converter.cc [new file with mode: 0755]
webWidgetTCT_device/src/common/converter.h [new file with mode: 0755]
webWidgetTCT_device/src/common/current_application.cc [new file with mode: 0755]
webWidgetTCT_device/src/common/current_application.h [new file with mode: 0755]
webWidgetTCT_device/src/common/dbus_operation.cc [new file with mode: 0755]
webWidgetTCT_device/src/common/dbus_operation.h [new file with mode: 0755]
webWidgetTCT_device/src/common/deleter.h [new file with mode: 0755]
webWidgetTCT_device/src/common/extension.cc [new file with mode: 0755]
webWidgetTCT_device/src/common/extension.h [new file with mode: 0755]
webWidgetTCT_device/src/common/filesystem/deviced.cc [new file with mode: 0755]
webWidgetTCT_device/src/common/filesystem/deviced.h [new file with mode: 0755]
webWidgetTCT_device/src/common/filesystem/filesystem_provider.cc [new file with mode: 0755]
webWidgetTCT_device/src/common/filesystem/filesystem_provider.h [new file with mode: 0755]
webWidgetTCT_device/src/common/filesystem/filesystem_provider_capiusb.cc [new file with mode: 0755]
webWidgetTCT_device/src/common/filesystem/filesystem_provider_capiusb.h [new file with mode: 0755]
webWidgetTCT_device/src/common/filesystem/filesystem_provider_storage.cc [new file with mode: 0755]
webWidgetTCT_device/src/common/filesystem/filesystem_provider_storage.h [new file with mode: 0755]
webWidgetTCT_device/src/common/filesystem/storage.cc [new file with mode: 0755]
webWidgetTCT_device/src/common/filesystem/storage.h [new file with mode: 0755]
webWidgetTCT_device/src/common/filter-utils.cc [new file with mode: 0755]
webWidgetTCT_device/src/common/filter-utils.h [new file with mode: 0755]
webWidgetTCT_device/src/common/logger.cc [new file with mode: 0755]
webWidgetTCT_device/src/common/logger.h [new file with mode: 0755]
webWidgetTCT_device/src/common/optional.h [new file with mode: 0755]
webWidgetTCT_device/src/common/picojson.h [new file with mode: 0755]
webWidgetTCT_device/src/common/pkg-config.gypi [new file with mode: 0755]
webWidgetTCT_device/src/common/platform_exception.cc [new file with mode: 0755]
webWidgetTCT_device/src/common/platform_exception.h [new file with mode: 0755]
webWidgetTCT_device/src/common/platform_result.cc [new file with mode: 0755]
webWidgetTCT_device/src/common/platform_result.h [new file with mode: 0755]
webWidgetTCT_device/src/common/scope_exit.h [new file with mode: 0755]
webWidgetTCT_device/src/common/task-queue.cpp [new file with mode: 0755]
webWidgetTCT_device/src/common/task-queue.h [new file with mode: 0755]
webWidgetTCT_device/src/common/tools.cc [new file with mode: 0755]
webWidgetTCT_device/src/common/tools.h [new file with mode: 0755]
webWidgetTCT_device/src/common/tvsapi_subscribe_helper.cc [new file with mode: 0755]
webWidgetTCT_device/src/common/tvsapi_subscribe_helper.h [new file with mode: 0755]
webWidgetTCT_device/src/common/typeutil.h [new file with mode: 0755]
webWidgetTCT_device/src/common/utils.h [new file with mode: 0755]
webWidgetTCT_device/src/common/video_source_types.cc [new file with mode: 0755]
webWidgetTCT_device/src/common/video_source_types.h [new file with mode: 0755]
webWidgetTCT_device/src/common/xwalk_js2c.gypi [new file with mode: 0755]
webWidgetTCT_device/src/contact/addressbook.cc [new file with mode: 0755]
webWidgetTCT_device/src/contact/addressbook.h [new file with mode: 0755]
webWidgetTCT_device/src/contact/contact.gyp [new file with mode: 0755]
webWidgetTCT_device/src/contact/contact_api.js [new file with mode: 0755]
webWidgetTCT_device/src/contact/contact_extension.cc [new file with mode: 0755]
webWidgetTCT_device/src/contact/contact_extension.h [new file with mode: 0755]
webWidgetTCT_device/src/contact/contact_instance.cc [new file with mode: 0755]
webWidgetTCT_device/src/contact/contact_instance.h [new file with mode: 0755]
webWidgetTCT_device/src/contact/contact_manager.cc [new file with mode: 0755]
webWidgetTCT_device/src/contact/contact_manager.h [new file with mode: 0755]
webWidgetTCT_device/src/contact/contact_util.cc [new file with mode: 0755]
webWidgetTCT_device/src/contact/contact_util.h [new file with mode: 0755]
webWidgetTCT_device/src/contact/js/address_book.js [new file with mode: 0755]
webWidgetTCT_device/src/contact/js/common.js [new file with mode: 0755]
webWidgetTCT_device/src/contact/js/contact.js [new file with mode: 0755]
webWidgetTCT_device/src/contact/js/contact_data_structures.js [new file with mode: 0755]
webWidgetTCT_device/src/contact/js/contact_manager.js [new file with mode: 0755]
webWidgetTCT_device/src/contact/js/person.js [new file with mode: 0755]
webWidgetTCT_device/src/contact/person.cc [new file with mode: 0755]
webWidgetTCT_device/src/contact/person.h [new file with mode: 0755]
webWidgetTCT_device/src/content/content.gyp [new file with mode: 0755]
webWidgetTCT_device/src/content/content_api.js [new file with mode: 0755]
webWidgetTCT_device/src/content/content_extension.cc [new file with mode: 0755]
webWidgetTCT_device/src/content/content_extension.h [new file with mode: 0755]
webWidgetTCT_device/src/content/content_filter.cc [new file with mode: 0755]
webWidgetTCT_device/src/content/content_filter.h [new file with mode: 0755]
webWidgetTCT_device/src/content/content_instance.cc [new file with mode: 0755]
webWidgetTCT_device/src/content/content_instance.h [new file with mode: 0755]
webWidgetTCT_device/src/content/content_manager.cc [new file with mode: 0755]
webWidgetTCT_device/src/content/content_manager.h [new file with mode: 0755]
webWidgetTCT_device/src/content/js/common.js [new file with mode: 0755]
webWidgetTCT_device/src/content/js/datatypes.js [new file with mode: 0755]
webWidgetTCT_device/src/content/js/manager.js [new file with mode: 0755]
webWidgetTCT_device/src/content/js/playlist.js [new file with mode: 0755]
webWidgetTCT_device/src/datacontrol/datacontrol.gyp [new file with mode: 0755]
webWidgetTCT_device/src/datacontrol/datacontrol_api.js [new file with mode: 0755]
webWidgetTCT_device/src/datacontrol/datacontrol_extension.cc [new file with mode: 0755]
webWidgetTCT_device/src/datacontrol/datacontrol_extension.h [new file with mode: 0755]
webWidgetTCT_device/src/datacontrol/datacontrol_instance.cc [new file with mode: 0755]
webWidgetTCT_device/src/datacontrol/datacontrol_instance.h [new file with mode: 0755]
webWidgetTCT_device/src/download/download.gyp [new file with mode: 0755]
webWidgetTCT_device/src/download/download_api.js [new file with mode: 0755]
webWidgetTCT_device/src/download/download_extension.cc [new file with mode: 0755]
webWidgetTCT_device/src/download/download_extension.h [new file with mode: 0755]
webWidgetTCT_device/src/download/download_instance.cc [new file with mode: 0755]
webWidgetTCT_device/src/download/download_instance.h [new file with mode: 0755]
webWidgetTCT_device/src/exif/exif.gyp [new file with mode: 0755]
webWidgetTCT_device/src/exif/exif_api.js [new file with mode: 0755]
webWidgetTCT_device/src/exif/exif_extension.cc [new file with mode: 0755]
webWidgetTCT_device/src/exif/exif_extension.h [new file with mode: 0755]
webWidgetTCT_device/src/exif/exif_gps_location.cc [new file with mode: 0755]
webWidgetTCT_device/src/exif/exif_gps_location.h [new file with mode: 0755]
webWidgetTCT_device/src/exif/exif_information.cc [new file with mode: 0755]
webWidgetTCT_device/src/exif/exif_information.h [new file with mode: 0755]
webWidgetTCT_device/src/exif/exif_instance.cc [new file with mode: 0755]
webWidgetTCT_device/src/exif/exif_instance.h [new file with mode: 0755]
webWidgetTCT_device/src/exif/exif_tag_saver.cc [new file with mode: 0755]
webWidgetTCT_device/src/exif/exif_tag_saver.h [new file with mode: 0755]
webWidgetTCT_device/src/exif/exif_util.cc [new file with mode: 0755]
webWidgetTCT_device/src/exif/exif_util.h [new file with mode: 0755]
webWidgetTCT_device/src/exif/get_exif_info.cc [new file with mode: 0755]
webWidgetTCT_device/src/exif/get_exif_info.h [new file with mode: 0755]
webWidgetTCT_device/src/exif/jpeg_file.cc [new file with mode: 0755]
webWidgetTCT_device/src/exif/jpeg_file.h [new file with mode: 0755]
webWidgetTCT_device/src/exif/rational.cc [new file with mode: 0755]
webWidgetTCT_device/src/exif/rational.h [new file with mode: 0755]
webWidgetTCT_device/src/filesystem/filesystem.gyp [new file with mode: 0755]
webWidgetTCT_device/src/filesystem/filesystem_api.js [new file with mode: 0755]
webWidgetTCT_device/src/filesystem/filesystem_extension.cc [new file with mode: 0755]
webWidgetTCT_device/src/filesystem/filesystem_extension.h [new file with mode: 0755]
webWidgetTCT_device/src/filesystem/filesystem_file.cc [new file with mode: 0755]
webWidgetTCT_device/src/filesystem/filesystem_file.h [new file with mode: 0755]
webWidgetTCT_device/src/filesystem/filesystem_instance.cc [new file with mode: 0755]
webWidgetTCT_device/src/filesystem/filesystem_instance.h [new file with mode: 0755]
webWidgetTCT_device/src/filesystem/filesystem_manager.cc [new file with mode: 0755]
webWidgetTCT_device/src/filesystem/filesystem_manager.h [new file with mode: 0755]
webWidgetTCT_device/src/filesystem/filesystem_stat.cc [new file with mode: 0755]
webWidgetTCT_device/src/filesystem/filesystem_stat.h [new file with mode: 0755]
webWidgetTCT_device/src/filesystem/filesystem_utils.cc [new file with mode: 0755]
webWidgetTCT_device/src/filesystem/filesystem_utils.h [new file with mode: 0755]
webWidgetTCT_device/src/filesystem/js/base64.js [new file with mode: 0755]
webWidgetTCT_device/src/filesystem/js/common.js [new file with mode: 0755]
webWidgetTCT_device/src/filesystem/js/file.js [new file with mode: 0755]
webWidgetTCT_device/src/filesystem/js/file_stream.js [new file with mode: 0755]
webWidgetTCT_device/src/filesystem/js/file_system_manager.js [new file with mode: 0755]
webWidgetTCT_device/src/humanactivitymonitor/humanactivitymonitor.gyp [new file with mode: 0755]
webWidgetTCT_device/src/humanactivitymonitor/humanactivitymonitor_api.js [new file with mode: 0755]
webWidgetTCT_device/src/humanactivitymonitor/humanactivitymonitor_extension.cc [new file with mode: 0755]
webWidgetTCT_device/src/humanactivitymonitor/humanactivitymonitor_extension.h [new file with mode: 0755]
webWidgetTCT_device/src/humanactivitymonitor/humanactivitymonitor_instance.cc [new file with mode: 0755]
webWidgetTCT_device/src/humanactivitymonitor/humanactivitymonitor_instance.h [new file with mode: 0755]
webWidgetTCT_device/src/humanactivitymonitor/humanactivitymonitor_manager.cc [new file with mode: 0755]
webWidgetTCT_device/src/humanactivitymonitor/humanactivitymonitor_manager.h [new file with mode: 0755]
webWidgetTCT_device/src/inputdevice/inputdevice.gyp [new file with mode: 0755]
webWidgetTCT_device/src/inputdevice/inputdevice_api.js [new file with mode: 0755]
webWidgetTCT_device/src/inputdevice/inputdevice_extension.cc [new file with mode: 0755]
webWidgetTCT_device/src/inputdevice/inputdevice_extension.h [new file with mode: 0755]
webWidgetTCT_device/src/inputdevice/inputdevice_instance.cc [new file with mode: 0755]
webWidgetTCT_device/src/inputdevice/inputdevice_instance.h [new file with mode: 0755]
webWidgetTCT_device/src/keymanager/keymanager.gyp [new file with mode: 0755]
webWidgetTCT_device/src/keymanager/keymanager_api.js [new file with mode: 0755]
webWidgetTCT_device/src/keymanager/keymanager_extension.cc [new file with mode: 0755]
webWidgetTCT_device/src/keymanager/keymanager_extension.h [new file with mode: 0755]
webWidgetTCT_device/src/keymanager/keymanager_instance.cc [new file with mode: 0755]
webWidgetTCT_device/src/keymanager/keymanager_instance.h [new file with mode: 0755]
webWidgetTCT_device/src/mediacontroller/mediacontroller.gyp [new file with mode: 0755]
webWidgetTCT_device/src/mediacontroller/mediacontroller_api.js [new file with mode: 0755]
webWidgetTCT_device/src/mediacontroller/mediacontroller_client.cc [new file with mode: 0755]
webWidgetTCT_device/src/mediacontroller/mediacontroller_client.h [new file with mode: 0755]
webWidgetTCT_device/src/mediacontroller/mediacontroller_extension.cc [new file with mode: 0755]
webWidgetTCT_device/src/mediacontroller/mediacontroller_extension.h [new file with mode: 0755]
webWidgetTCT_device/src/mediacontroller/mediacontroller_instance.cc [new file with mode: 0755]
webWidgetTCT_device/src/mediacontroller/mediacontroller_instance.h [new file with mode: 0755]
webWidgetTCT_device/src/mediacontroller/mediacontroller_server.cc [new file with mode: 0755]
webWidgetTCT_device/src/mediacontroller/mediacontroller_server.h [new file with mode: 0755]
webWidgetTCT_device/src/mediacontroller/mediacontroller_types.cc [new file with mode: 0755]
webWidgetTCT_device/src/mediacontroller/mediacontroller_types.h [new file with mode: 0755]
webWidgetTCT_device/src/mediakey/mediakey.gyp [new file with mode: 0755]
webWidgetTCT_device/src/mediakey/mediakey_api.js [new file with mode: 0755]
webWidgetTCT_device/src/mediakey/mediakey_extension.cc [new file with mode: 0755]
webWidgetTCT_device/src/mediakey/mediakey_extension.h [new file with mode: 0755]
webWidgetTCT_device/src/mediakey/mediakey_instance.cc [new file with mode: 0755]
webWidgetTCT_device/src/mediakey/mediakey_instance.h [new file with mode: 0755]
webWidgetTCT_device/src/mediakey/mediakey_manager.cc [new file with mode: 0755]
webWidgetTCT_device/src/mediakey/mediakey_manager.h [new file with mode: 0755]
webWidgetTCT_device/src/messageport/messageport.gyp [new file with mode: 0755]
webWidgetTCT_device/src/messageport/messageport_api.js [new file with mode: 0755]
webWidgetTCT_device/src/messageport/messageport_extension.cc [new file with mode: 0755]
webWidgetTCT_device/src/messageport/messageport_extension.h [new file with mode: 0755]
webWidgetTCT_device/src/messageport/messageport_instance.cc [new file with mode: 0755]
webWidgetTCT_device/src/messageport/messageport_instance.h [new file with mode: 0755]
webWidgetTCT_device/src/messaging/DBus/DBusTypes.cpp [new file with mode: 0755]
webWidgetTCT_device/src/messaging/DBus/DBusTypes.h [new file with mode: 0755]
webWidgetTCT_device/src/messaging/DBus/EmailSignalProxy.cpp [new file with mode: 0755]
webWidgetTCT_device/src/messaging/DBus/EmailSignalProxy.h [new file with mode: 0755]
webWidgetTCT_device/src/messaging/DBus/LoadAttachmentProxy.cpp [new file with mode: 0755]
webWidgetTCT_device/src/messaging/DBus/LoadAttachmentProxy.h [new file with mode: 0755]
webWidgetTCT_device/src/messaging/DBus/LoadBodyProxy.cpp [new file with mode: 0755]
webWidgetTCT_device/src/messaging/DBus/LoadBodyProxy.h [new file with mode: 0755]
webWidgetTCT_device/src/messaging/DBus/MessageProxy.cpp [new file with mode: 0755]
webWidgetTCT_device/src/messaging/DBus/MessageProxy.h [new file with mode: 0755]
webWidgetTCT_device/src/messaging/DBus/SendProxy.cpp [new file with mode: 0755]
webWidgetTCT_device/src/messaging/DBus/SendProxy.h [new file with mode: 0755]
webWidgetTCT_device/src/messaging/DBus/SyncProxy.cpp [new file with mode: 0755]
webWidgetTCT_device/src/messaging/DBus/SyncProxy.h [new file with mode: 0755]
webWidgetTCT_device/src/messaging/MsgCommon/AbstractFilter.cpp [new file with mode: 0755]
webWidgetTCT_device/src/messaging/MsgCommon/AbstractFilter.h [new file with mode: 0755]
webWidgetTCT_device/src/messaging/MsgCommon/Any.cpp [new file with mode: 0755]
webWidgetTCT_device/src/messaging/MsgCommon/Any.h [new file with mode: 0755]
webWidgetTCT_device/src/messaging/MsgCommon/AttributeFilter.cpp [new file with mode: 0755]
webWidgetTCT_device/src/messaging/MsgCommon/AttributeFilter.h [new file with mode: 0755]
webWidgetTCT_device/src/messaging/MsgCommon/AttributeRangeFilter.cpp [new file with mode: 0755]
webWidgetTCT_device/src/messaging/MsgCommon/AttributeRangeFilter.h [new file with mode: 0755]
webWidgetTCT_device/src/messaging/MsgCommon/CompositeFilter.cpp [new file with mode: 0755]
webWidgetTCT_device/src/messaging/MsgCommon/CompositeFilter.h [new file with mode: 0755]
webWidgetTCT_device/src/messaging/MsgCommon/FilterIterator.cpp [new file with mode: 0755]
webWidgetTCT_device/src/messaging/MsgCommon/FilterIterator.h [new file with mode: 0755]
webWidgetTCT_device/src/messaging/MsgCommon/SortMode.cpp [new file with mode: 0755]
webWidgetTCT_device/src/messaging/MsgCommon/SortMode.h [new file with mode: 0755]
webWidgetTCT_device/src/messaging/change_listener_container.cc [new file with mode: 0755]
webWidgetTCT_device/src/messaging/change_listener_container.h [new file with mode: 0755]
webWidgetTCT_device/src/messaging/conversation_callback_data.cc [new file with mode: 0755]
webWidgetTCT_device/src/messaging/conversation_callback_data.h [new file with mode: 0755]
webWidgetTCT_device/src/messaging/conversations_change_callback.cc [new file with mode: 0755]
webWidgetTCT_device/src/messaging/conversations_change_callback.h [new file with mode: 0755]
webWidgetTCT_device/src/messaging/email_manager.cc [new file with mode: 0755]
webWidgetTCT_device/src/messaging/email_manager.h [new file with mode: 0755]
webWidgetTCT_device/src/messaging/find_msg_callback_user_data.cc [new file with mode: 0755]
webWidgetTCT_device/src/messaging/find_msg_callback_user_data.h [new file with mode: 0755]
webWidgetTCT_device/src/messaging/folders_callback_data.cc [new file with mode: 0755]
webWidgetTCT_device/src/messaging/folders_callback_data.h [new file with mode: 0755]
webWidgetTCT_device/src/messaging/folders_change_callback.cc [new file with mode: 0755]
webWidgetTCT_device/src/messaging/folders_change_callback.h [new file with mode: 0755]
webWidgetTCT_device/src/messaging/message.cc [new file with mode: 0755]
webWidgetTCT_device/src/messaging/message.h [new file with mode: 0755]
webWidgetTCT_device/src/messaging/message_attachment.cc [new file with mode: 0755]
webWidgetTCT_device/src/messaging/message_attachment.h [new file with mode: 0755]
webWidgetTCT_device/src/messaging/message_body.cc [new file with mode: 0755]
webWidgetTCT_device/src/messaging/message_body.h [new file with mode: 0755]
webWidgetTCT_device/src/messaging/message_callback_user_data.cc [new file with mode: 0755]
webWidgetTCT_device/src/messaging/message_callback_user_data.h [new file with mode: 0755]
webWidgetTCT_device/src/messaging/message_conversation.cc [new file with mode: 0755]
webWidgetTCT_device/src/messaging/message_conversation.h [new file with mode: 0755]
webWidgetTCT_device/src/messaging/message_email.cc [new file with mode: 0755]
webWidgetTCT_device/src/messaging/message_email.h [new file with mode: 0755]
webWidgetTCT_device/src/messaging/message_folder.cc [new file with mode: 0755]
webWidgetTCT_device/src/messaging/message_folder.h [new file with mode: 0755]
webWidgetTCT_device/src/messaging/message_mms.cc [new file with mode: 0755]
webWidgetTCT_device/src/messaging/message_mms.h [new file with mode: 0755]
webWidgetTCT_device/src/messaging/message_service.cc [new file with mode: 0755]
webWidgetTCT_device/src/messaging/message_service.h [new file with mode: 0755]
webWidgetTCT_device/src/messaging/message_service_email.cc [new file with mode: 0755]
webWidgetTCT_device/src/messaging/message_service_email.h [new file with mode: 0755]
webWidgetTCT_device/src/messaging/message_service_short_msg.cc [new file with mode: 0755]
webWidgetTCT_device/src/messaging/message_service_short_msg.h [new file with mode: 0755]
webWidgetTCT_device/src/messaging/message_sms.cc [new file with mode: 0755]
webWidgetTCT_device/src/messaging/message_sms.h [new file with mode: 0755]
webWidgetTCT_device/src/messaging/message_storage.cc [new file with mode: 0755]
webWidgetTCT_device/src/messaging/message_storage.h [new file with mode: 0755]
webWidgetTCT_device/src/messaging/message_storage_email.cc [new file with mode: 0755]
webWidgetTCT_device/src/messaging/message_storage_email.h [new file with mode: 0755]
webWidgetTCT_device/src/messaging/message_storage_short_msg.cc [new file with mode: 0755]
webWidgetTCT_device/src/messaging/message_storage_short_msg.h [new file with mode: 0755]
webWidgetTCT_device/src/messaging/messages_callback_user_data.cc [new file with mode: 0755]
webWidgetTCT_device/src/messaging/messages_callback_user_data.h [new file with mode: 0755]
webWidgetTCT_device/src/messaging/messages_change_callback.cc [new file with mode: 0755]
webWidgetTCT_device/src/messaging/messages_change_callback.h [new file with mode: 0755]
webWidgetTCT_device/src/messaging/messaging.gyp [new file with mode: 0755]
webWidgetTCT_device/src/messaging/messaging_api.js [new file with mode: 0755]
webWidgetTCT_device/src/messaging/messaging_database_manager.cc [new file with mode: 0755]
webWidgetTCT_device/src/messaging/messaging_database_manager.h [new file with mode: 0755]
webWidgetTCT_device/src/messaging/messaging_extension.cc [new file with mode: 0755]
webWidgetTCT_device/src/messaging/messaging_extension.h [new file with mode: 0755]
webWidgetTCT_device/src/messaging/messaging_instance.cc [new file with mode: 0755]
webWidgetTCT_device/src/messaging/messaging_instance.h [new file with mode: 0755]
webWidgetTCT_device/src/messaging/messaging_manager.cc [new file with mode: 0755]
webWidgetTCT_device/src/messaging/messaging_manager.h [new file with mode: 0755]
webWidgetTCT_device/src/messaging/messaging_util.cc [new file with mode: 0755]
webWidgetTCT_device/src/messaging/messaging_util.h [new file with mode: 0755]
webWidgetTCT_device/src/messaging/short_message_manager.cc [new file with mode: 0755]
webWidgetTCT_device/src/messaging/short_message_manager.h [new file with mode: 0755]
webWidgetTCT_device/src/networkbearerselection/networkbearerselection.gyp [new file with mode: 0755]
webWidgetTCT_device/src/networkbearerselection/networkbearerselection_api.js [new file with mode: 0755]
webWidgetTCT_device/src/networkbearerselection/networkbearerselection_extension.cc [new file with mode: 0755]
webWidgetTCT_device/src/networkbearerselection/networkbearerselection_extension.h [new file with mode: 0755]
webWidgetTCT_device/src/networkbearerselection/networkbearerselection_instance.cc [new file with mode: 0755]
webWidgetTCT_device/src/networkbearerselection/networkbearerselection_instance.h [new file with mode: 0755]
webWidgetTCT_device/src/networkbearerselection/networkbearerselection_manager.cc [new file with mode: 0755]
webWidgetTCT_device/src/networkbearerselection/networkbearerselection_manager.h [new file with mode: 0755]
webWidgetTCT_device/src/nfc/aid_data.cc [new file with mode: 0755]
webWidgetTCT_device/src/nfc/aid_data.h [new file with mode: 0755]
webWidgetTCT_device/src/nfc/defs.h [new file with mode: 0755]
webWidgetTCT_device/src/nfc/nfc.gyp [new file with mode: 0755]
webWidgetTCT_device/src/nfc/nfc_adapter.cc [new file with mode: 0755]
webWidgetTCT_device/src/nfc/nfc_adapter.h [new file with mode: 0755]
webWidgetTCT_device/src/nfc/nfc_api.js [new file with mode: 0755]
webWidgetTCT_device/src/nfc/nfc_extension.cc [new file with mode: 0755]
webWidgetTCT_device/src/nfc/nfc_extension.h [new file with mode: 0755]
webWidgetTCT_device/src/nfc/nfc_instance.cc [new file with mode: 0755]
webWidgetTCT_device/src/nfc/nfc_instance.h [new file with mode: 0755]
webWidgetTCT_device/src/nfc/nfc_message_utils.cc [new file with mode: 0755]
webWidgetTCT_device/src/nfc/nfc_message_utils.h [new file with mode: 0755]
webWidgetTCT_device/src/nfc/nfc_util.cc [new file with mode: 0755]
webWidgetTCT_device/src/nfc/nfc_util.h [new file with mode: 0755]
webWidgetTCT_device/src/notification/notification.gyp [new file with mode: 0755]
webWidgetTCT_device/src/notification/notification_api.js [new file with mode: 0755]
webWidgetTCT_device/src/notification/notification_extension.cc [new file with mode: 0755]
webWidgetTCT_device/src/notification/notification_extension.h [new file with mode: 0755]
webWidgetTCT_device/src/notification/notification_instance.cc [new file with mode: 0755]
webWidgetTCT_device/src/notification/notification_instance.h [new file with mode: 0755]
webWidgetTCT_device/src/notification/notification_manager.cc [new file with mode: 0755]
webWidgetTCT_device/src/notification/notification_manager.h [new file with mode: 0755]
webWidgetTCT_device/src/notification/status_notification.cc [new file with mode: 0755]
webWidgetTCT_device/src/notification/status_notification.h [new file with mode: 0755]
webWidgetTCT_device/src/package/package.gyp [new file with mode: 0755]
webWidgetTCT_device/src/package/package_api.js [new file with mode: 0755]
webWidgetTCT_device/src/package/package_extension.cc [new file with mode: 0755]
webWidgetTCT_device/src/package/package_extension.h [new file with mode: 0755]
webWidgetTCT_device/src/package/package_info_provider.cc [new file with mode: 0755]
webWidgetTCT_device/src/package/package_info_provider.h [new file with mode: 0755]
webWidgetTCT_device/src/package/package_instance.cc [new file with mode: 0755]
webWidgetTCT_device/src/package/package_instance.h [new file with mode: 0755]
webWidgetTCT_device/src/power/power.gyp [new file with mode: 0755]
webWidgetTCT_device/src/power/power_api.js [new file with mode: 0755]
webWidgetTCT_device/src/power/power_extension.cc [new file with mode: 0755]
webWidgetTCT_device/src/power/power_extension.h [new file with mode: 0755]
webWidgetTCT_device/src/power/power_instance.cc [new file with mode: 0755]
webWidgetTCT_device/src/power/power_instance.h [new file with mode: 0755]
webWidgetTCT_device/src/power/power_manager.cc [new file with mode: 0755]
webWidgetTCT_device/src/power/power_manager.h [new file with mode: 0755]
webWidgetTCT_device/src/power/power_platform_proxy.cc [new file with mode: 0755]
webWidgetTCT_device/src/power/power_platform_proxy.h [new file with mode: 0755]
webWidgetTCT_device/src/push/push.gyp [new file with mode: 0755]
webWidgetTCT_device/src/push/push_api.js [new file with mode: 0755]
webWidgetTCT_device/src/push/push_extension.cc [new file with mode: 0755]
webWidgetTCT_device/src/push/push_extension.h [new file with mode: 0755]
webWidgetTCT_device/src/push/push_instance.cc [new file with mode: 0755]
webWidgetTCT_device/src/push/push_instance.h [new file with mode: 0755]
webWidgetTCT_device/src/push/push_manager.cc [new file with mode: 0755]
webWidgetTCT_device/src/push/push_manager.h [new file with mode: 0755]
webWidgetTCT_device/src/radio/radio.gyp [new file with mode: 0755]
webWidgetTCT_device/src/radio/radio_api.js [new file with mode: 0755]
webWidgetTCT_device/src/radio/radio_extension.cc [new file with mode: 0755]
webWidgetTCT_device/src/radio/radio_extension.h [new file with mode: 0755]
webWidgetTCT_device/src/radio/radio_instance.cc [new file with mode: 0755]
webWidgetTCT_device/src/radio/radio_instance.h [new file with mode: 0755]
webWidgetTCT_device/src/radio/radio_manager.cc [new file with mode: 0755]
webWidgetTCT_device/src/radio/radio_manager.h [new file with mode: 0755]
webWidgetTCT_device/src/secureelement/secureelement.gyp [new file with mode: 0755]
webWidgetTCT_device/src/secureelement/secureelement_api.js [new file with mode: 0755]
webWidgetTCT_device/src/secureelement/secureelement_channel.cc [new file with mode: 0755]
webWidgetTCT_device/src/secureelement/secureelement_channel.h [new file with mode: 0755]
webWidgetTCT_device/src/secureelement/secureelement_extension.cc [new file with mode: 0755]
webWidgetTCT_device/src/secureelement/secureelement_extension.h [new file with mode: 0755]
webWidgetTCT_device/src/secureelement/secureelement_instance.cc [new file with mode: 0755]
webWidgetTCT_device/src/secureelement/secureelement_instance.h [new file with mode: 0755]
webWidgetTCT_device/src/secureelement/secureelement_reader.cc [new file with mode: 0755]
webWidgetTCT_device/src/secureelement/secureelement_reader.h [new file with mode: 0755]
webWidgetTCT_device/src/secureelement/secureelement_seservice.cc [new file with mode: 0755]
webWidgetTCT_device/src/secureelement/secureelement_seservice.h [new file with mode: 0755]
webWidgetTCT_device/src/secureelement/secureelement_session.cc [new file with mode: 0755]
webWidgetTCT_device/src/secureelement/secureelement_session.h [new file with mode: 0755]
webWidgetTCT_device/src/sensor/sensor.gyp [new file with mode: 0755]
webWidgetTCT_device/src/sensor/sensor_api.js [new file with mode: 0755]
webWidgetTCT_device/src/sensor/sensor_extension.cc [new file with mode: 0755]
webWidgetTCT_device/src/sensor/sensor_extension.h [new file with mode: 0755]
webWidgetTCT_device/src/sensor/sensor_instance.cc [new file with mode: 0755]
webWidgetTCT_device/src/sensor/sensor_instance.h [new file with mode: 0755]
webWidgetTCT_device/src/sensor/sensor_service.cc [new file with mode: 0755]
webWidgetTCT_device/src/sensor/sensor_service.h [new file with mode: 0755]
webWidgetTCT_device/src/smartcontroller/smartcontroller.gyp [new file with mode: 0755]
webWidgetTCT_device/src/smartcontroller/smartcontroller_api.js [new file with mode: 0755]
webWidgetTCT_device/src/smartcontroller/smartcontroller_data.cc [new file with mode: 0755]
webWidgetTCT_device/src/smartcontroller/smartcontroller_data.h [new file with mode: 0755]
webWidgetTCT_device/src/smartcontroller/smartcontroller_extension.cc [new file with mode: 0755]
webWidgetTCT_device/src/smartcontroller/smartcontroller_extension.h [new file with mode: 0755]
webWidgetTCT_device/src/smartcontroller/smartcontroller_instance.cc [new file with mode: 0755]
webWidgetTCT_device/src/smartcontroller/smartcontroller_instance.h [new file with mode: 0755]
webWidgetTCT_device/src/smartcontroller/smartcontroller_manager.cc [new file with mode: 0755]
webWidgetTCT_device/src/smartcontroller/smartcontroller_manager.h [new file with mode: 0755]
webWidgetTCT_device/src/sound/sound.gyp [new file with mode: 0755]
webWidgetTCT_device/src/sound/sound_api.js [new file with mode: 0755]
webWidgetTCT_device/src/sound/sound_extension.cc [new file with mode: 0755]
webWidgetTCT_device/src/sound/sound_extension.h [new file with mode: 0755]
webWidgetTCT_device/src/sound/sound_instance.cc [new file with mode: 0755]
webWidgetTCT_device/src/sound/sound_instance.h [new file with mode: 0755]
webWidgetTCT_device/src/sound/sound_manager.cc [new file with mode: 0755]
webWidgetTCT_device/src/sound/sound_manager.h [new file with mode: 0755]
webWidgetTCT_device/src/systeminfo/systeminfo-utils.cpp [new file with mode: 0755]
webWidgetTCT_device/src/systeminfo/systeminfo-utils.h [new file with mode: 0755]
webWidgetTCT_device/src/systeminfo/systeminfo.gyp [new file with mode: 0755]
webWidgetTCT_device/src/systeminfo/systeminfo_api.js [new file with mode: 0755]
webWidgetTCT_device/src/systeminfo/systeminfo_device_capability.cc [new file with mode: 0755]
webWidgetTCT_device/src/systeminfo/systeminfo_device_capability.h [new file with mode: 0755]
webWidgetTCT_device/src/systeminfo/systeminfo_extension.cc [new file with mode: 0755]
webWidgetTCT_device/src/systeminfo/systeminfo_extension.h [new file with mode: 0755]
webWidgetTCT_device/src/systeminfo/systeminfo_instance.cc [new file with mode: 0755]
webWidgetTCT_device/src/systeminfo/systeminfo_instance.h [new file with mode: 0755]
webWidgetTCT_device/src/systeminfo/systeminfo_manager.cc [new file with mode: 0755]
webWidgetTCT_device/src/systeminfo/systeminfo_manager.h [new file with mode: 0755]
webWidgetTCT_device/src/systeminfo/systeminfo_properties_manager.cc [new file with mode: 0755]
webWidgetTCT_device/src/systeminfo/systeminfo_properties_manager.h [new file with mode: 0755]
webWidgetTCT_device/src/systeminfo/systeminfo_sim_details_manager.cc [new file with mode: 0755]
webWidgetTCT_device/src/systeminfo/systeminfo_sim_details_manager.h [new file with mode: 0755]
webWidgetTCT_device/src/systemsetting/systemsetting.gyp [new file with mode: 0755]
webWidgetTCT_device/src/systemsetting/systemsetting_api.js [new file with mode: 0755]
webWidgetTCT_device/src/systemsetting/systemsetting_extension.cc [new file with mode: 0755]
webWidgetTCT_device/src/systemsetting/systemsetting_extension.h [new file with mode: 0755]
webWidgetTCT_device/src/systemsetting/systemsetting_instance.cc [new file with mode: 0755]
webWidgetTCT_device/src/systemsetting/systemsetting_instance.h [new file with mode: 0755]
webWidgetTCT_device/src/time/time.gyp [new file with mode: 0755]
webWidgetTCT_device/src/time/time_api.js [new file with mode: 0755]
webWidgetTCT_device/src/time/time_extension.cc [new file with mode: 0755]
webWidgetTCT_device/src/time/time_extension.h [new file with mode: 0755]
webWidgetTCT_device/src/time/time_instance.cc [new file with mode: 0755]
webWidgetTCT_device/src/time/time_instance.h [new file with mode: 0755]
webWidgetTCT_device/src/tizen-wrt.gyp [new file with mode: 0755]
webWidgetTCT_device/src/tizen/tizen.gyp [new file with mode: 0755]
webWidgetTCT_device/src/tizen/tizen.h [new file with mode: 0755]
webWidgetTCT_device/src/tizen/tizen_api.js [new file with mode: 0755]
webWidgetTCT_device/src/tizen/tizen_extension.cc [new file with mode: 0755]
webWidgetTCT_device/src/tizen/tizen_extension.h [new file with mode: 0755]
webWidgetTCT_device/src/tool/desc_gentool.cc [new file with mode: 0755]
webWidgetTCT_device/src/tool/tool.gyp [new file with mode: 0755]
webWidgetTCT_device/src/tvaudio/tvaudio.gyp [new file with mode: 0755]
webWidgetTCT_device/src/tvaudio/tvaudio_api.js [new file with mode: 0755]
webWidgetTCT_device/src/tvaudio/tvaudio_extension.cc [new file with mode: 0755]
webWidgetTCT_device/src/tvaudio/tvaudio_extension.h [new file with mode: 0755]
webWidgetTCT_device/src/tvaudio/tvaudio_instance.cc [new file with mode: 0755]
webWidgetTCT_device/src/tvaudio/tvaudio_instance.h [new file with mode: 0755]
webWidgetTCT_device/src/tvaudio/tvaudio_manager.cc [new file with mode: 0755]
webWidgetTCT_device/src/tvaudio/tvaudio_manager.h [new file with mode: 0755]
webWidgetTCT_device/src/tvchannel/channel_info.cc [new file with mode: 0755]
webWidgetTCT_device/src/tvchannel/channel_info.h [new file with mode: 0755]
webWidgetTCT_device/src/tvchannel/criteria_filter.cc [new file with mode: 0755]
webWidgetTCT_device/src/tvchannel/criteria_filter.h [new file with mode: 0755]
webWidgetTCT_device/src/tvchannel/program_info.cc [new file with mode: 0755]
webWidgetTCT_device/src/tvchannel/program_info.h [new file with mode: 0755]
webWidgetTCT_device/src/tvchannel/tune_option.cc [new file with mode: 0755]
webWidgetTCT_device/src/tvchannel/tune_option.h [new file with mode: 0755]
webWidgetTCT_device/src/tvchannel/tvchannel.gyp [new file with mode: 0755]
webWidgetTCT_device/src/tvchannel/tvchannel_api.js [new file with mode: 0755]
webWidgetTCT_device/src/tvchannel/tvchannel_extension.cc [new file with mode: 0755]
webWidgetTCT_device/src/tvchannel/tvchannel_extension.h [new file with mode: 0755]
webWidgetTCT_device/src/tvchannel/tvchannel_instance.cc [new file with mode: 0755]
webWidgetTCT_device/src/tvchannel/tvchannel_instance.h [new file with mode: 0755]
webWidgetTCT_device/src/tvchannel/tvchannel_manager.cc [new file with mode: 0755]
webWidgetTCT_device/src/tvchannel/tvchannel_manager.h [new file with mode: 0755]
webWidgetTCT_device/src/tvchannel/types.cc [new file with mode: 0755]
webWidgetTCT_device/src/tvchannel/types.h [new file with mode: 0755]
webWidgetTCT_device/src/tvdisplay/tvdisplay.gyp [new file with mode: 0755]
webWidgetTCT_device/src/tvdisplay/tvdisplay_api.js [new file with mode: 0755]
webWidgetTCT_device/src/tvdisplay/tvdisplay_extension.cc [new file with mode: 0755]
webWidgetTCT_device/src/tvdisplay/tvdisplay_extension.h [new file with mode: 0755]
webWidgetTCT_device/src/tvdisplay/tvdisplay_instance.cc [new file with mode: 0755]
webWidgetTCT_device/src/tvdisplay/tvdisplay_instance.h [new file with mode: 0755]
webWidgetTCT_device/src/tvinfo/tvinfo.gyp [new file with mode: 0755]
webWidgetTCT_device/src/tvinfo/tvinfo_api.js [new file with mode: 0755]
webWidgetTCT_device/src/tvinfo/tvinfo_extension.cc [new file with mode: 0755]
webWidgetTCT_device/src/tvinfo/tvinfo_extension.h [new file with mode: 0755]
webWidgetTCT_device/src/tvinfo/tvinfo_instance.cc [new file with mode: 0755]
webWidgetTCT_device/src/tvinfo/tvinfo_instance.h [new file with mode: 0755]
webWidgetTCT_device/src/tvinfo/tvinfo_manager.cc [new file with mode: 0755]
webWidgetTCT_device/src/tvinfo/tvinfo_manager.h [new file with mode: 0755]
webWidgetTCT_device/src/tvinputdevice/tvinputdevice.gyp [new file with mode: 0755]
webWidgetTCT_device/src/tvinputdevice/tvinputdevice_api.js [new file with mode: 0755]
webWidgetTCT_device/src/tvinputdevice/tvinputdevice_extension.cc [new file with mode: 0755]
webWidgetTCT_device/src/tvinputdevice/tvinputdevice_extension.h [new file with mode: 0755]
webWidgetTCT_device/src/tvinputdevice/tvinputdevice_instance.cc [new file with mode: 0755]
webWidgetTCT_device/src/tvinputdevice/tvinputdevice_instance.h [new file with mode: 0755]
webWidgetTCT_device/src/tvwindow/tvwindow.gyp [new file with mode: 0755]
webWidgetTCT_device/src/tvwindow/tvwindow_api.js [new file with mode: 0755]
webWidgetTCT_device/src/tvwindow/tvwindow_extension.cc [new file with mode: 0755]
webWidgetTCT_device/src/tvwindow/tvwindow_extension.h [new file with mode: 0755]
webWidgetTCT_device/src/tvwindow/tvwindow_instance.cc [new file with mode: 0755]
webWidgetTCT_device/src/tvwindow/tvwindow_instance.h [new file with mode: 0755]
webWidgetTCT_device/src/tvwindow/tvwindow_manager.cc [new file with mode: 0755]
webWidgetTCT_device/src/tvwindow/tvwindow_manager.h [new file with mode: 0755]
webWidgetTCT_device/src/utils/utils.gyp [new file with mode: 0755]
webWidgetTCT_device/src/utils/utils_api.js [new file with mode: 0755]
webWidgetTCT_device/src/utils/utils_extension.cc [new file with mode: 0755]
webWidgetTCT_device/src/utils/utils_extension.h [new file with mode: 0755]
webWidgetTCT_device/src/utils/utils_instance.cc [new file with mode: 0755]
webWidgetTCT_device/src/utils/utils_instance.h [new file with mode: 0755]
webWidgetTCT_device/src/websetting/websetting.gyp [new file with mode: 0755]
webWidgetTCT_device/src/websetting/websetting_api.js [new file with mode: 0755]
webWidgetTCT_device/src/websetting/websetting_extension.cc [new file with mode: 0755]
webWidgetTCT_device/src/websetting/websetting_extension.h [new file with mode: 0755]
webWidgetTCT_device/test/common/loader.js [new file with mode: 0755]
webWidgetTCT_device/test/fs [new file with mode: 0755]
webWidgetTCT_device/test/index.js [new file with mode: 0755]
webWidgetTCT_device/test/prerequisite.js [new file with mode: 0755]
webWidgetTCT_device/test/tct/common/testharness.css [new file with mode: 0755]
webWidgetTCT_device/test/tct/common/testharness.js [new file with mode: 0755]
webWidgetTCT_device/test/tct/common/unitcommon.js [new file with mode: 0755]
webWidgetTCT_device/test/tct/tct.js [new file with mode: 0755]
webWidgetTCT_device/test/tct/tests/TestAlarm.js [new file with mode: 0755]
webWidgetTCT_device/test/tct/tests/TestAnimationTiming.js [new file with mode: 0755]
webWidgetTCT_device/test/tct/tests/TestApplication.js [new file with mode: 0755]
webWidgetTCT_device/test/tct/tests/TestCSS.js [new file with mode: 0755]
webWidgetTCT_device/test/tct/tests/TestContent.js [new file with mode: 0755]
webWidgetTCT_device/test/tct/tests/TestDataControl.js [new file with mode: 0755]
webWidgetTCT_device/test/tct/tests/TestDom.js [new file with mode: 0755]
webWidgetTCT_device/test/tct/tests/TestEvent.js [new file with mode: 0755]
webWidgetTCT_device/test/tct/tests/TestFilesystem.js [new file with mode: 0755]
webWidgetTCT_device/test/tct/tests/TestHtml.js [new file with mode: 0755]
webWidgetTCT_device/test/tct/tests/TestMessagePort.js [new file with mode: 0755]
webWidgetTCT_device/test/tct/tests/TestPackage.js [new file with mode: 0755]
webWidgetTCT_device/test/tct/tests/TestPageVisibility.js [new file with mode: 0755]
webWidgetTCT_device/test/tct/tests/TestPreference.js [new file with mode: 0755]
webWidgetTCT_device/test/tct/tests/TestSensor.js [new file with mode: 0755]
webWidgetTCT_device/test/tct/tests/TestSysteminfo.js [new file with mode: 0755]
webWidgetTCT_device/test/tct/tests/TestTime.js [new file with mode: 0755]
webWidgetTCT_device/test/tct/tests/TestWebWidget.js [new file with mode: 0755]
webWidgetTCT_device/test/tct/tests/TestWidgetService.js [new file with mode: 0755]
webWidgetTCT_device/test/tct/tests/TestXMLHttpRequest.js [new file with mode: 0755]
webWidgetTCT_device/test/tct/tests/generate.sh [new file with mode: 0755]
webWidgetTCT_device/test/tct/tests/support/path.js [new file with mode: 0755]
webWidgetTCT_device/test/tct/tests/support/test.html [new file with mode: 0755]
webWidgetTCT_device/test/tct/tests/support/test.xml [new file with mode: 0755]
webWidgetTCT_device/test/tct/tests/support/test_timeout.xml [new file with mode: 0755]
webWidgetTCT_device/test/utc/README [new file with mode: 0755]
webWidgetTCT_device/test/utc/changeClockSettingFile.sh [new file with mode: 0755]
webWidgetTCT_device/test/utc/common/TestEngine.js [new file with mode: 0755]
webWidgetTCT_device/test/utc/config/ConfigAlarm.js [new file with mode: 0755]
webWidgetTCT_device/test/utc/config/ConfigApplication.js [new file with mode: 0755]
webWidgetTCT_device/test/utc/config/ConfigClock.js [new file with mode: 0755]
webWidgetTCT_device/test/utc/config/ConfigContent.js [new file with mode: 0755]
webWidgetTCT_device/test/utc/config/ConfigFilesystem.js [new file with mode: 0755]
webWidgetTCT_device/test/utc/config/ConfigHumanActivityMonitor.js [new file with mode: 0755]
webWidgetTCT_device/test/utc/config/ConfigMessagePort.js [new file with mode: 0755]
webWidgetTCT_device/test/utc/config/ConfigPackage.js [new file with mode: 0755]
webWidgetTCT_device/test/utc/config/ConfigPower.js [new file with mode: 0755]
webWidgetTCT_device/test/utc/config/ConfigSystemSetting.js [new file with mode: 0755]
webWidgetTCT_device/test/utc/config/ConfigSysteminfo.js [new file with mode: 0755]
webWidgetTCT_device/test/utc/tests/ClockSettingCIS.js [new file with mode: 0755]
webWidgetTCT_device/test/utc/tests/ClockSettingCommon.js [new file with mode: 0755]
webWidgetTCT_device/test/utc/tests/ClockSettingDCM.js [new file with mode: 0755]
webWidgetTCT_device/test/utc/tests/ClockSettingORA.js [new file with mode: 0755]
webWidgetTCT_device/test/utc/tests/TestAlarm.js [new file with mode: 0755]
webWidgetTCT_device/test/utc/tests/TestApplication.js [new file with mode: 0755]
webWidgetTCT_device/test/utc/tests/TestClock.js [new file with mode: 0755]
webWidgetTCT_device/test/utc/tests/TestFilesystem.js [new file with mode: 0755]
webWidgetTCT_device/test/utc/tests/TestMessagePort.js [new file with mode: 0755]
webWidgetTCT_device/test/utc/tests/TestPackage.js [new file with mode: 0755]
webWidgetTCT_device/test/utc/tests/TestSysteminfo.js [new file with mode: 0755]
webWidgetTCT_device/test/utc/utc.js [new file with mode: 0755]
webWidgetTCT_device/tools/check-coding-style [new file with mode: 0755]
webWidgetTCT_device/tools/generate_api.py [new file with mode: 0755]
webWidgetTCT_device/tools/generate_manifest.py [new file with mode: 0755]
webWidgetTCT_device/tools/gyp/.gitignore [new file with mode: 0755]
webWidgetTCT_device/tools/gyp/AUTHORS [new file with mode: 0755]
webWidgetTCT_device/tools/gyp/LICENSE [new file with mode: 0755]
webWidgetTCT_device/tools/gyp/gyp [new file with mode: 0755]
webWidgetTCT_device/tools/gyp/gyp.bat [new file with mode: 0755]
webWidgetTCT_device/tools/gyp/pylib/gyp/MSVSNew.py [new file with mode: 0755]
webWidgetTCT_device/tools/gyp/pylib/gyp/MSVSProject.py [new file with mode: 0755]
webWidgetTCT_device/tools/gyp/pylib/gyp/MSVSSettings.py [new file with mode: 0755]
webWidgetTCT_device/tools/gyp/pylib/gyp/MSVSSettings_test.py [new file with mode: 0755]
webWidgetTCT_device/tools/gyp/pylib/gyp/MSVSToolFile.py [new file with mode: 0755]
webWidgetTCT_device/tools/gyp/pylib/gyp/MSVSUserFile.py [new file with mode: 0755]
webWidgetTCT_device/tools/gyp/pylib/gyp/MSVSUtil.py [new file with mode: 0755]
webWidgetTCT_device/tools/gyp/pylib/gyp/MSVSVersion.py [new file with mode: 0755]
webWidgetTCT_device/tools/gyp/pylib/gyp/SCons.py [new file with mode: 0755]
webWidgetTCT_device/tools/gyp/pylib/gyp/__init__.py [new file with mode: 0755]
webWidgetTCT_device/tools/gyp/pylib/gyp/common.py [new file with mode: 0755]
webWidgetTCT_device/tools/gyp/pylib/gyp/common_test.py [new file with mode: 0755]
webWidgetTCT_device/tools/gyp/pylib/gyp/easy_xml.py [new file with mode: 0755]
webWidgetTCT_device/tools/gyp/pylib/gyp/easy_xml_test.py [new file with mode: 0755]
webWidgetTCT_device/tools/gyp/pylib/gyp/generator/__init__.py [new file with mode: 0755]
webWidgetTCT_device/tools/gyp/pylib/gyp/generator/android.py [new file with mode: 0755]
webWidgetTCT_device/tools/gyp/pylib/gyp/generator/dump_dependency_json.py [new file with mode: 0755]
webWidgetTCT_device/tools/gyp/pylib/gyp/generator/eclipse.py [new file with mode: 0755]
webWidgetTCT_device/tools/gyp/pylib/gyp/generator/gypd.py [new file with mode: 0755]
webWidgetTCT_device/tools/gyp/pylib/gyp/generator/gypsh.py [new file with mode: 0755]
webWidgetTCT_device/tools/gyp/pylib/gyp/generator/make.py [new file with mode: 0755]
webWidgetTCT_device/tools/gyp/pylib/gyp/generator/msvs.py [new file with mode: 0755]
webWidgetTCT_device/tools/gyp/pylib/gyp/generator/msvs_test.py [new file with mode: 0755]
webWidgetTCT_device/tools/gyp/pylib/gyp/generator/ninja.py [new file with mode: 0755]
webWidgetTCT_device/tools/gyp/pylib/gyp/generator/ninja_test.py [new file with mode: 0755]
webWidgetTCT_device/tools/gyp/pylib/gyp/generator/scons.py [new file with mode: 0755]
webWidgetTCT_device/tools/gyp/pylib/gyp/generator/xcode.py [new file with mode: 0755]
webWidgetTCT_device/tools/gyp/pylib/gyp/input.py [new file with mode: 0755]
webWidgetTCT_device/tools/gyp/pylib/gyp/mac_tool.py [new file with mode: 0755]
webWidgetTCT_device/tools/gyp/pylib/gyp/msvs_emulation.py [new file with mode: 0755]
webWidgetTCT_device/tools/gyp/pylib/gyp/ninja_syntax.py [new file with mode: 0755]
webWidgetTCT_device/tools/gyp/pylib/gyp/sun_tool.py [new file with mode: 0755]
webWidgetTCT_device/tools/gyp/pylib/gyp/win_tool.py [new file with mode: 0755]
webWidgetTCT_device/tools/gyp/pylib/gyp/xcode_emulation.py [new file with mode: 0755]
webWidgetTCT_device/tools/gyp/pylib/gyp/xcodeproj_file.py [new file with mode: 0755]
webWidgetTCT_device/tools/gyp/pylib/gyp/xml_fix.py [new file with mode: 0755]
webWidgetTCT_device/tools/gyp/pylintrc [new file with mode: 0755]
webWidgetTCT_device/tools/increment-version.py [new file with mode: 0755]
webWidgetTCT_device/tools/js_minimize.py [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/WebServiceTest/config.xml [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/WebServiceTest/css/style.css [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/WebServiceTest/icon.png [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/WebServiceTest/index.html [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/WebServiceTest/js/app.js [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/WebServiceTest/service/message-port.js [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/WebServiceTest/service/service.js [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/deploy.sh [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/Documents/tizen_WebAPI_test_dummy [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/Downloads/tizen_WebAPI_test_dummy [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/Images/webapi-tizen-messaging-test_image.jpg [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/Music/webapi-tizen-messaging-test_noise.mp3 [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/Sounds/tizen_WebAPI_test_dummy [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/Videos/tizen_WebAPI_test_dummy [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_audio_default.mp3 [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_audio_lyrics.mp3 [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_audio_no_tag.mp3 [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_image_default.jpg [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_image_geolocation.jpg [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_image_orientation_1.jpg [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_image_orientation_2.jpg [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_image_orientation_3.jpg [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_image_orientation_4.jpg [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_image_orientation_5.jpg [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_image_orientation_6.jpg [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_image_orientation_7.jpg [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_image_orientation_8.jpg [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_video.mp4 [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_video_tagged.mp4 [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-systemsetting-tizen-tests/tct-systemsetting-tizen-tests_audio.mp3 [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-systemsetting-tizen-tests/tct-systemsetting-tizen-tests_image.jpg [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct/preconfigure.js [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/webapi-tizen-contact-test_image1.png [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/webapi-tizen-contact-test_image2.png [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/webapi-tizen-contact-test_ring1.mp3 [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/webapi-tizen-contact-test_ring2.mp3 [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/appcontrol_exit.html [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/appcontrol_launch.html [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/appcontrol_launch_explicit.html [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/appcontrol_reply_failure.html [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/appcontrol_reply_result.html [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/appcontrol_reply_result_with_data.html [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/appcontrol_run_test.html [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/config.xml [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/css/style.css [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/icon.png [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/index.html [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/resources/COPYING [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/resources/blacklist.clamshell [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/resources/blacklist.default [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/resources/blacklist.js [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/resources/testharness.css [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/resources/testharness.js [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/resources/testharnessreport.js [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/resources/unitcommon.js [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/tests/Application_getRequestedAppControl.js [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/tests/Application_getRequestedAppControl_extra_argument.js [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/tests/Application_hide.js [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/tests/Application_hide_extra_argument.js [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/tests/RequestedApplicationControl_appControl_attribute.js [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/tests/RequestedApplicationControl_callerAppId_attribute.js [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/tests/RequestedApplicationControl_extend.js [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/tests/RequestedApplicationControl_replyFailure_exist.js [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/tests/RequestedApplicationControl_replyResult_data_TypeMismatch.js [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/tests/RequestedApplicationControl_replyResult_exist.js [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/install/TCTAppControlMock/appcontrol_launch_explicit.html [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/install/TCTAppControlMock/config.xml [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/install/TCTAppControlMock/css/style.css [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/install/TCTAppControlMock/icon.png [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/install/TCTAppControlMock/index.html [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/install/TCTAppControlMock/js/main.js [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/install/TCTPackageInfoTest/config.xml [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/install/TCTPackageInfoTest/css/style.css [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/install/TCTPackageInfoTest/icon.png [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/install/TCTPackageInfoTest/index.html [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/install/TCTbroadcastApp/config.xml [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/install/TCTbroadcastApp/css/style.css [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/install/TCTbroadcastApp/icon.png [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/install/TCTbroadcastApp/images/tizen_32.png [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/install/TCTbroadcastApp/index.html [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/install/TCTbroadcastApp/js/main.js [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/install/UnitTest-AlarmTest1/config.xml [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/install/UnitTest-AlarmTest1/icon.png [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/install/UnitTest-AlarmTest1/index.html [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/install/tct-bt-helper/config.xml [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/install/tct-bt-helper/css/style.css [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/install/tct-bt-helper/icon.png [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/install/tct-bt-helper/images/tizen_32.png [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/install/tct-bt-helper/index.html [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/install/tct-bt-helper/js/main.js [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/push/TCTAppInfoEventTest1/config.xml [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/push/TCTAppInfoEventTest1/css/style.css [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/push/TCTAppInfoEventTest1/icon.png [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/push/TCTAppInfoEventTest1/index.html [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/push/TCTAppInfoEventTest2/config.xml [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/push/TCTAppInfoEventTest2/css/style.css [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/push/TCTAppInfoEventTest2/icon.png [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/push/TCTAppInfoEventTest2/index.html [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/push/TCTPackageManagerTest1.1.1/config.xml [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/push/TCTPackageManagerTest1.1.1/css/style.css [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/push/TCTPackageManagerTest1.1.1/icon.png [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/push/TCTPackageManagerTest1.1.1/index.html [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/push/TCTPackageManagerTest2.2.2/config.xml [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/push/TCTPackageManagerTest2.2.2/css/style.css [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/push/TCTPackageManagerTest2.2.2/icon.png [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/tct/push/TCTPackageManagerTest2.2.2/index.html [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/utc/copy/opt/usr/media/Images/imagefile1.jpg [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/utc/copy/opt/usr/media/Music/musicfile1.mp3 [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/utc/copy/opt/usr/media/Music/musicfile2.mp3 [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/utc/copy/opt/usr/media/Music/musicfile3.mp3 [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest1/app_control.html [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest1/config.xml [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest1/css/style.css [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest1/icon.png [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest1/images/tizen_32.png [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest1/index.html [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest1/js/app_control.js [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest1/js/main.js [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest2/app_control.html [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest2/config.xml [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest2/css/style.css [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest2/icon.png [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest2/images/tizen_32.png [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest2/index.html [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest2/js/app_control.js [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest2/js/main.js [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest3/app_control.html [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest3/config.xml [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest3/css/style.css [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest3/icon.png [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest3/images/tizen_32.png [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest3/index.html [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest3/js/app_control.js [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest3/js/main.js [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-BT-Server/config.xml [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-BT-Server/css/style.css [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-BT-Server/icon.png [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-BT-Server/images/tizen_32.png [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-BT-Server/index.html [new file with mode: 0755]
webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-BT-Server/js/main.js [new file with mode: 0755]
webWidgetTCT_device/tools/mergejs.py [new file with mode: 0755]
webWidgetTCT_device/tools/redirect-stdout.sh [new file with mode: 0755]
webWidgetTCT_device/tools/skeleton_generator/README.md [new file with mode: 0755]
webWidgetTCT_device/tools/skeleton_generator/WAPIOven.py [new file with mode: 0755]
webWidgetTCT_device/tools/skeleton_generator/WebIDL.py [new file with mode: 0755]
webWidgetTCT_device/tools/skeleton_generator/tpl/tpl_api.js [new file with mode: 0755]
webWidgetTCT_device/tools/skeleton_generator/tpl/tpl_extension.cc [new file with mode: 0755]
webWidgetTCT_device/tools/skeleton_generator/tpl/tpl_extension.h [new file with mode: 0755]
webWidgetTCT_device/tools/skeleton_generator/tpl/tpl_instance.cc [new file with mode: 0755]
webWidgetTCT_device/tools/skeleton_generator/tpl/tpl_instance.h [new file with mode: 0755]
webWidgetTCT_device/tools/slimit/CHANGES [new file with mode: 0755]
webWidgetTCT_device/tools/slimit/CREDIT [new file with mode: 0755]
webWidgetTCT_device/tools/slimit/LICENSE [new file with mode: 0755]
webWidgetTCT_device/tools/slimit/__init__.py [new file with mode: 0755]
webWidgetTCT_device/tools/slimit/ast.py [new file with mode: 0755]
webWidgetTCT_device/tools/slimit/lexer.py [new file with mode: 0755]
webWidgetTCT_device/tools/slimit/lextab.py [new file with mode: 0755]
webWidgetTCT_device/tools/slimit/mangler.py [new file with mode: 0755]
webWidgetTCT_device/tools/slimit/minifier.py [new file with mode: 0755]
webWidgetTCT_device/tools/slimit/parser.py [new file with mode: 0755]
webWidgetTCT_device/tools/slimit/ply/__init__.py [new file with mode: 0755]
webWidgetTCT_device/tools/slimit/ply/cpp.py [new file with mode: 0755]
webWidgetTCT_device/tools/slimit/ply/ctokens.py [new file with mode: 0755]
webWidgetTCT_device/tools/slimit/ply/lex.py [new file with mode: 0755]
webWidgetTCT_device/tools/slimit/ply/yacc.py [new file with mode: 0755]
webWidgetTCT_device/tools/slimit/scope.py [new file with mode: 0755]
webWidgetTCT_device/tools/slimit/tests/__init__.py [new file with mode: 0755]
webWidgetTCT_device/tools/slimit/tests/test_cmd.py [new file with mode: 0755]
webWidgetTCT_device/tools/slimit/tests/test_ecmavisitor.py [new file with mode: 0755]
webWidgetTCT_device/tools/slimit/tests/test_lexer.py [new file with mode: 0755]
webWidgetTCT_device/tools/slimit/tests/test_mangler.py [new file with mode: 0755]
webWidgetTCT_device/tools/slimit/tests/test_minifier.py [new file with mode: 0755]
webWidgetTCT_device/tools/slimit/tests/test_nodevisitor.py [new file with mode: 0755]
webWidgetTCT_device/tools/slimit/tests/test_parser.py [new file with mode: 0755]
webWidgetTCT_device/tools/slimit/unicode_chars.py [new file with mode: 0755]
webWidgetTCT_device/tools/slimit/visitors/__init__.py [new file with mode: 0755]
webWidgetTCT_device/tools/slimit/visitors/ecmavisitor.py [new file with mode: 0755]
webWidgetTCT_device/tools/slimit/visitors/minvisitor.py [new file with mode: 0755]
webWidgetTCT_device/tools/slimit/visitors/nodevisitor.py [new file with mode: 0755]
webWidgetTCT_device/tools/slimit/visitors/scopevisitor.py [new file with mode: 0755]
webWidgetTCT_device/tools/slimit/yacctab.py [new file with mode: 0755]
webWidgetTCT_device/tools/target/install-fake-app.sh [new file with mode: 0755]
webWidgetTCT_device/tools/target/remove-fake-app.sh [new file with mode: 0755]
webWidgetTCT_device/webapi-plugins.manifest [new file with mode: 0755]

diff --git a/selector/ClassSelector_tct.js b/selector/ClassSelector_tct.js
new file mode 100755 (executable)
index 0000000..f20d0ba
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+ * 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.
+ */
+
+(function() {
+    function runTests() {
+        // gather tests to run
+        var selectedTests = {};
+        for (var i = 0; i < arguments.length; ++i) {
+            var arg = arguments[i];
+            if (!(arg instanceof Array)) {
+                arg = String(arg).split(' ');
+            }
+            for (var j = 0; j < arg.length; ++j) {
+                selectedTests[arg[j].toLowerCase()] = '';
+            }
+        }
+
+        // load node.js modules
+        var fs = requireTCT('fs');
+
+        // checks if object is empty
+        function isEmptyObject(object) {
+            for (var prop in object) {
+                if (object.hasOwnProperty(prop)) {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        // constants
+        var testsDir = 'tct/tests/';
+        var testRegExp = /^Test(.*)\.js$/;
+        var testPrefix = 'Test';
+        var extension = '.js';
+
+        // find available tests
+        var availableTests = {};
+        //var testFiles = fs.readdirSync(testsDir);
+        var testFiles = [
+            //"TestApplication.js",
+            //"TestFilesystem.js",
+            //"TestMessagePort.js",
+            //"TestSysteminfo.js",
+            //"TestPreference.js",
+            //"TestSensor.js",
+            //"TestHtml.js",
+            //"TestDynamicPseudoSelector.js",
+            "TestClassSelector.js",
+        ];
+
+        for (var ii = 0; ii < testFiles.length; ++ii) {
+            var match = testRegExp.exec(testFiles[ii]);
+            if (match) {
+                match = match[1];
+                availableTests[match.toLowerCase()] = match;
+            }
+        }
+
+        // if no tests are selected, run all
+        if (isEmptyObject(selectedTests)) {
+            selectedTests = availableTests;
+        }
+
+        // load tizen modules
+        if (typeof (tizen) === 'undefined') {
+            requireTCT('common/loader.js')();
+        }
+
+        // load test engine
+        requireTCT('tct/common/testharness.js');
+        requireTCT('tct/common/unitcommon.js');
+
+        // stores test cases
+        var testCases = [];
+        var stats = { modules : {}, tests : {} };
+
+        function add_test_case(m, f) {
+            if (!stats.modules[m]) {
+                stats.modules[m] = {};
+                stats.modules[m].all = 0;
+                stats.modules[m].pass = 0;
+                stats.modules[m].fail = 0;
+                stats.modules[m].timeout = 0;
+                stats.modules[m].notrun = 0;
+            }
+            ++stats.modules[m].all;
+            stats.tests[f.name] = m;
+            testCases.push(f);
+        }
+        expose(add_test_case, 'add_test_case');
+
+        // load tests
+        for (var test in selectedTests) {
+            if (availableTests[test]) {
+                console.log('Loading test: ' + availableTests[test]);
+                try {
+                    requireTCT(testsDir + testPrefix + availableTests[test] + extension);
+                } catch (e) {
+                    console.log('Failed to load: ' + availableTests[test]);
+                    console.log(e);
+                }
+            }
+        }
+
+        // handle test case
+        var currentTest = 0;
+
+        function onResult(test) {
+            if (test) {
+                // store statistics
+                var m = stats.tests[test.name];
+                switch (test.status) {
+                case 0:
+                    ++stats.modules[m].pass;
+                    break;
+                case 1:
+                    ++stats.modules[m].fail;
+                    break;
+                case 2:
+                    ++stats.modules[m].timeout;
+                    break;
+                case 3:
+                    ++stats.modules[m].notrun;
+                    break;
+                }
+            }
+
+            // launch next test case
+            if (currentTest < testCases.length) {
+                setTimeout(testCases[currentTest], 0);
+                ++currentTest;
+            } else {
+                done();
+            }
+        }
+        function onFinish() {
+            var total = 0;
+            var pass = 0;
+            var fail = 0;
+            var timeout = 0;
+            var notrun = 0;
+            console.log('============ Test suites:');
+            for (var m in stats.modules) {
+                if (stats.modules.hasOwnProperty(m)) {
+                    var s = stats.modules[m];
+                    var nr = s.all - s.pass - s.fail - s.timeout;
+                    console.log('[' + m + '] - ' + s.pass + ' passed, ' + s.fail + ' failed, ' + s.timeout + ' timed out, ' + nr + ' not run.');
+                    total += s.all;
+                    pass += s.pass;
+                    fail += s.fail;
+                    timeout += s.timeout;
+                    notrun += nr;
+                }
+            }
+            console.log('============ Summary:');
+            console.log('Test cases all: ' + total);
+            console.log('Test cases passed: ' + pass);
+            console.log('Test cases failed: ' + fail);
+            console.log('Test cases timed out: ' + timeout);
+            console.log('Test cases not run: ' + notrun);
+            // terminate process
+            process.exit();
+        }
+
+        // register callbacks
+        add_result_callback(onResult);
+        add_completion_callback(onFinish);
+
+        // start testing
+        console.log('Running tests');
+        onResult();
+    }
+
+    if (!module.parent) {
+        // standalone script
+        //runTests(process.argv.slice(2));
+        runTests([
+                //"Application",
+                //"Filesystem",
+                //"MessagePort",
+                //"Systeminfo",
+                //"Preference",
+                //"Sensor",
+                //"Html",
+                //"DynamicPseudoSelector",
+                "ClassSelector",
+                ]);
+    } else {
+        module.exports = runTests;
+    }
+})();
+
diff --git a/selector/DynamicPseudoSelector_index.js b/selector/DynamicPseudoSelector_index.js
new file mode 100755 (executable)
index 0000000..f4d1300
--- /dev/null
@@ -0,0 +1,5 @@
+(function() {
+    load('/home/owner/share/wrt-service-tct/prerequisite.js');
+    requireTCT('./tct/DynamicPseudoSelector_tct.js')('alarm application datacontrol filesystem messageport package systeminfo');
+    //require('./utc/utc.js')('alarm application datacontrol filesystem messageport package systeminfo');
+})();
diff --git a/selector/DynamicPseudoSelector_tct.js b/selector/DynamicPseudoSelector_tct.js
new file mode 100755 (executable)
index 0000000..506e5cb
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+ * 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.
+ */
+
+(function() {
+    function runTests() {
+        // gather tests to run
+        var selectedTests = {};
+        for (var i = 0; i < arguments.length; ++i) {
+            var arg = arguments[i];
+            if (!(arg instanceof Array)) {
+                arg = String(arg).split(' ');
+            }
+            for (var j = 0; j < arg.length; ++j) {
+                selectedTests[arg[j].toLowerCase()] = '';
+            }
+        }
+
+        // load node.js modules
+        var fs = requireTCT('fs');
+
+        // checks if object is empty
+        function isEmptyObject(object) {
+            for (var prop in object) {
+                if (object.hasOwnProperty(prop)) {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        // constants
+        var testsDir = 'tct/tests/';
+        var testRegExp = /^Test(.*)\.js$/;
+        var testPrefix = 'Test';
+        var extension = '.js';
+
+        // find available tests
+        var availableTests = {};
+        //var testFiles = fs.readdirSync(testsDir);
+        var testFiles = [
+            //"TestApplication.js",
+            //"TestFilesystem.js",
+            //"TestMessagePort.js",
+            //"TestSysteminfo.js",
+            //"TestPreference.js",
+            //"TestSensor.js",
+            //"TestHtml.js",
+            "TestDynamicPseudoSelector.js",
+            //"TestTypeSelector.js",
+        ];
+
+        for (var ii = 0; ii < testFiles.length; ++ii) {
+            var match = testRegExp.exec(testFiles[ii]);
+            if (match) {
+                match = match[1];
+                availableTests[match.toLowerCase()] = match;
+            }
+        }
+
+        // if no tests are selected, run all
+        if (isEmptyObject(selectedTests)) {
+            selectedTests = availableTests;
+        }
+
+        // load tizen modules
+        if (typeof (tizen) === 'undefined') {
+            requireTCT('common/loader.js')();
+        }
+
+        // load test engine
+        requireTCT('tct/common/testharness.js');
+        requireTCT('tct/common/unitcommon.js');
+
+        // stores test cases
+        var testCases = [];
+        var stats = { modules : {}, tests : {} };
+
+        function add_test_case(m, f) {
+            if (!stats.modules[m]) {
+                stats.modules[m] = {};
+                stats.modules[m].all = 0;
+                stats.modules[m].pass = 0;
+                stats.modules[m].fail = 0;
+                stats.modules[m].timeout = 0;
+                stats.modules[m].notrun = 0;
+            }
+            ++stats.modules[m].all;
+            stats.tests[f.name] = m;
+            testCases.push(f);
+        }
+        expose(add_test_case, 'add_test_case');
+
+        // load tests
+        for (var test in selectedTests) {
+            if (availableTests[test]) {
+                console.log('Loading test: ' + availableTests[test]);
+                try {
+                    requireTCT(testsDir + testPrefix + availableTests[test] + extension);
+                } catch (e) {
+                    console.log('Failed to load: ' + availableTests[test]);
+                    console.log(e);
+                }
+            }
+        }
+
+        // handle test case
+        var currentTest = 0;
+
+        function onResult(test) {
+            if (test) {
+                // store statistics
+                var m = stats.tests[test.name];
+                switch (test.status) {
+                case 0:
+                    ++stats.modules[m].pass;
+                    break;
+                case 1:
+                    ++stats.modules[m].fail;
+                    break;
+                case 2:
+                    ++stats.modules[m].timeout;
+                    break;
+                case 3:
+                    ++stats.modules[m].notrun;
+                    break;
+                }
+            }
+
+            // launch next test case
+            if (currentTest < testCases.length) {
+                setTimeout(testCases[currentTest], 0);
+                ++currentTest;
+            } else {
+                done();
+            }
+        }
+        function onFinish() {
+            var total = 0;
+            var pass = 0;
+            var fail = 0;
+            var timeout = 0;
+            var notrun = 0;
+            console.log('============ Test suites:');
+            for (var m in stats.modules) {
+                if (stats.modules.hasOwnProperty(m)) {
+                    var s = stats.modules[m];
+                    var nr = s.all - s.pass - s.fail - s.timeout;
+                    console.log('[' + m + '] - ' + s.pass + ' passed, ' + s.fail + ' failed, ' + s.timeout + ' timed out, ' + nr + ' not run.');
+                    total += s.all;
+                    pass += s.pass;
+                    fail += s.fail;
+                    timeout += s.timeout;
+                    notrun += nr;
+                }
+            }
+            console.log('============ Summary:');
+            console.log('Test cases all: ' + total);
+            console.log('Test cases passed: ' + pass);
+            console.log('Test cases failed: ' + fail);
+            console.log('Test cases timed out: ' + timeout);
+            console.log('Test cases not run: ' + notrun);
+            // terminate process
+            process.exit();
+        }
+
+        // register callbacks
+        add_result_callback(onResult);
+        add_completion_callback(onFinish);
+
+        // start testing
+        console.log('Running tests');
+        onResult();
+    }
+
+    if (!module.parent) {
+        // standalone script
+        //runTests(process.argv.slice(2));
+        runTests([
+                //"Application",
+                //"Filesystem",
+                //"MessagePort",
+                //"Systeminfo",
+                //"Preference",
+                //"Sensor",
+                //"Html",
+                "DynamicPseudoSelector",
+                //"TypeSelector",
+                ]);
+    } else {
+        module.exports = runTests;
+    }
+})();
+
diff --git a/selector/IdSelector_tct.js b/selector/IdSelector_tct.js
new file mode 100755 (executable)
index 0000000..420d5ed
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+ * 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.
+ */
+
+(function() {
+    function runTests() {
+        // gather tests to run
+        var selectedTests = {};
+        for (var i = 0; i < arguments.length; ++i) {
+            var arg = arguments[i];
+            if (!(arg instanceof Array)) {
+                arg = String(arg).split(' ');
+            }
+            for (var j = 0; j < arg.length; ++j) {
+                selectedTests[arg[j].toLowerCase()] = '';
+            }
+        }
+
+        // load node.js modules
+        var fs = requireTCT('fs');
+
+        // checks if object is empty
+        function isEmptyObject(object) {
+            for (var prop in object) {
+                if (object.hasOwnProperty(prop)) {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        // constants
+        var testsDir = 'tct/tests/';
+        var testRegExp = /^Test(.*)\.js$/;
+        var testPrefix = 'Test';
+        var extension = '.js';
+
+        // find available tests
+        var availableTests = {};
+        //var testFiles = fs.readdirSync(testsDir);
+        var testFiles = [
+            //"TestApplication.js",
+            //"TestFilesystem.js",
+            //"TestMessagePort.js",
+            //"TestSysteminfo.js",
+            //"TestPreference.js",
+            //"TestSensor.js",
+            //"TestHtml.js",
+            //"TestDynamicPseudoSelector.js",
+            "TestIdSelector.js",
+        ];
+
+        for (var ii = 0; ii < testFiles.length; ++ii) {
+            var match = testRegExp.exec(testFiles[ii]);
+            if (match) {
+                match = match[1];
+                availableTests[match.toLowerCase()] = match;
+            }
+        }
+
+        // if no tests are selected, run all
+        if (isEmptyObject(selectedTests)) {
+            selectedTests = availableTests;
+        }
+
+        // load tizen modules
+        if (typeof (tizen) === 'undefined') {
+            requireTCT('common/loader.js')();
+        }
+
+        // load test engine
+        requireTCT('tct/common/testharness.js');
+        requireTCT('tct/common/unitcommon.js');
+
+        // stores test cases
+        var testCases = [];
+        var stats = { modules : {}, tests : {} };
+
+        function add_test_case(m, f) {
+            if (!stats.modules[m]) {
+                stats.modules[m] = {};
+                stats.modules[m].all = 0;
+                stats.modules[m].pass = 0;
+                stats.modules[m].fail = 0;
+                stats.modules[m].timeout = 0;
+                stats.modules[m].notrun = 0;
+            }
+            ++stats.modules[m].all;
+            stats.tests[f.name] = m;
+            testCases.push(f);
+        }
+        expose(add_test_case, 'add_test_case');
+
+        // load tests
+        for (var test in selectedTests) {
+            if (availableTests[test]) {
+                console.log('Loading test: ' + availableTests[test]);
+                try {
+                    requireTCT(testsDir + testPrefix + availableTests[test] + extension);
+                } catch (e) {
+                    console.log('Failed to load: ' + availableTests[test]);
+                    console.log(e);
+                }
+            }
+        }
+
+        // handle test case
+        var currentTest = 0;
+
+        function onResult(test) {
+            if (test) {
+                // store statistics
+                var m = stats.tests[test.name];
+                switch (test.status) {
+                case 0:
+                    ++stats.modules[m].pass;
+                    break;
+                case 1:
+                    ++stats.modules[m].fail;
+                    break;
+                case 2:
+                    ++stats.modules[m].timeout;
+                    break;
+                case 3:
+                    ++stats.modules[m].notrun;
+                    break;
+                }
+            }
+
+            // launch next test case
+            if (currentTest < testCases.length) {
+                setTimeout(testCases[currentTest], 0);
+                ++currentTest;
+            } else {
+                done();
+            }
+        }
+        function onFinish() {
+            var total = 0;
+            var pass = 0;
+            var fail = 0;
+            var timeout = 0;
+            var notrun = 0;
+            console.log('============ Test suites:');
+            for (var m in stats.modules) {
+                if (stats.modules.hasOwnProperty(m)) {
+                    var s = stats.modules[m];
+                    var nr = s.all - s.pass - s.fail - s.timeout;
+                    console.log('[' + m + '] - ' + s.pass + ' passed, ' + s.fail + ' failed, ' + s.timeout + ' timed out, ' + nr + ' not run.');
+                    total += s.all;
+                    pass += s.pass;
+                    fail += s.fail;
+                    timeout += s.timeout;
+                    notrun += nr;
+                }
+            }
+            console.log('============ Summary:');
+            console.log('Test cases all: ' + total);
+            console.log('Test cases passed: ' + pass);
+            console.log('Test cases failed: ' + fail);
+            console.log('Test cases timed out: ' + timeout);
+            console.log('Test cases not run: ' + notrun);
+            // terminate process
+            process.exit();
+        }
+
+        // register callbacks
+        add_result_callback(onResult);
+        add_completion_callback(onFinish);
+
+        // start testing
+        console.log('Running tests');
+        onResult();
+    }
+
+    if (!module.parent) {
+        // standalone script
+        //runTests(process.argv.slice(2));
+        runTests([
+                //"Application",
+                //"Filesystem",
+                //"MessagePort",
+                //"Systeminfo",
+                //"Preference",
+                //"Sensor",
+                //"Html",
+                //"DynamicPseudoSelector",
+                "IdSelector",
+                ]);
+    } else {
+        module.exports = runTests;
+    }
+})();
+
diff --git a/selector/README b/selector/README
new file mode 100755 (executable)
index 0000000..22e0863
--- /dev/null
@@ -0,0 +1,12 @@
+1. push files
+$ sdb push *_index.js /home/owner/share/wrt-service-tct/
+$ sdb push *_tct.js /home/owner/share/wrt-service-tct/tct/
+$ sdb push TestClassSelector.js /home/owner/share/wrt-service-tct/tct/tests/
+$ sdb push TestDynamicPseudoSelector.js /home/owner/share/wrt-service-tct/tct/tests/
+$ sdb push TestIdSelector.js /home/owner/share/wrt-service-tct/tct/tests/
+$ sdb push TestTypeSelector.js /home/owner/share/wrt-service-tct/tct/tests/
+$ sdb push TestUniversalSelector.js /home/owner/share/wrt-service-tct/tct/tests/
+
+2. install selector.wgt
+$ sdb root off
+$ sdb install selector.wgt
\ No newline at end of file
diff --git a/selector/TestClassSelector.js b/selector/TestClassSelector.js
new file mode 100755 (executable)
index 0000000..64c9f9b
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+Copyright (c) 2016 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Authors:
+        Xiaoyan Qian <xy.qian@samsung.com>
+
+*/
+
+function Class_selector_test() {
+
+
+setup({timeout: 300000});
+
+var t = async_test('Class_selector_test', {timeout: 300000});
+
+t.step(function () {
+    var d = document.getElementsByTagName("p");
+   d[0].onclick = t.step_func(function() {
+     t.done();
+    })
+   d[1].onclick = t.step_func(function() {
+     assert_true(false,"result is fail");
+    })
+});
+
+}
+
+var moduleName = "tct-classselector-css-test";
+add_test_case(moduleName,Class_selector_test);
diff --git a/selector/TestClassSelector_index.js b/selector/TestClassSelector_index.js
new file mode 100755 (executable)
index 0000000..c0f5d31
--- /dev/null
@@ -0,0 +1,5 @@
+(function() {
+    load('/home/owner/share/wrt-service-tct/prerequisite.js');
+    requireTCT('./tct/ClassSelector_tct.js')('alarm application datacontrol filesystem messageport package systeminfo');
+    //require('./utc/utc.js')('alarm application datacontrol filesystem messageport package systeminfo');
+})();
diff --git a/selector/TestDynamicPseudoSelector.js b/selector/TestDynamicPseudoSelector.js
new file mode 100755 (executable)
index 0000000..6957aa0
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+Copyright (c) 2016 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Authors:
+        Xiaoyan Qian <xy.qian@samsung.com>
+
+*/
+
+
+function Dynamic_pseudo_selector_test() {
+
+
+setup({timeout: 300000});
+
+var t = async_test('Dynamic_pseudo_selector_test', {timeout: 300000});
+
+t.step(function () {
+    var d = document.getElementsByTagName("p");
+   d[1].onclick = t.step_func(function() {
+     t.done();
+    })
+   d[2].onclick = t.step_func(function() {
+     assert_true(false,"result is fail");
+    })
+});
+
+}
+
+var moduleName = "tct-dynamicpseudoselector-css-test";
+add_test_case(moduleName,Dynamic_pseudo_selector_test);
diff --git a/selector/TestIdSelector.js b/selector/TestIdSelector.js
new file mode 100755 (executable)
index 0000000..dbd0d6f
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+Copyright (c) 2016 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Authors:
+        Xiaoyan Qian <xy.qian@samsung.com>
+
+*/
+
+function Id_selector_test() {
+
+setup({timeout: 300000});
+
+var t = async_test('Id_selector_test', {timeout: 300000});
+
+t.step(function () {
+    var d = document.getElementsByTagName("p");
+   d[0].onclick = t.step_func(function() {
+     t.done();
+    })
+   d[1].onclick = t.step_func(function() {
+     assert_true(false,"result is fail");
+    })
+});
+
+}
+var moduleName = "tct-idselector-css-test";
+add_test_case(moduleName,Id_selector_test);
diff --git a/selector/TestIdSelector_index.js b/selector/TestIdSelector_index.js
new file mode 100755 (executable)
index 0000000..ef15351
--- /dev/null
@@ -0,0 +1,5 @@
+(function() {
+    load('/home/owner/share/wrt-service-tct/prerequisite.js');
+    requireTCT('./tct/IdSelector_tct.js')('alarm application datacontrol filesystem messageport package systeminfo');
+    //require('./utc/utc.js')('alarm application datacontrol filesystem messageport package systeminfo');
+})();
diff --git a/selector/TestTypeSelector.js b/selector/TestTypeSelector.js
new file mode 100755 (executable)
index 0000000..17490f9
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+Copyright (c) 2016 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Authors:
+        Xiaoyan Qian <xy.qian@samsung.com>
+
+*/
+
+function Type_selector_test() {
+
+setup({timeout: 300000});
+
+var t = async_test('Type_selector_test', {timeout: 300000});
+
+t.step(function () {
+    var d = document.getElementsByTagName("p");
+   d[2].onclick = t.step_func(function() {
+     t.done();
+    })
+   d[3].onclick = t.step_func(function() {
+     console.log("insert+++++++++++");
+     assert_true(false,"result is fail");
+    })
+
+});
+
+}
+
+var moduleName = "tct-typeselector-css-test";
+add_test_case(moduleName,Type_selector_test);
diff --git a/selector/TestTypeSelector_index.js b/selector/TestTypeSelector_index.js
new file mode 100755 (executable)
index 0000000..0df5f74
--- /dev/null
@@ -0,0 +1,5 @@
+(function() {
+    load('/home/owner/share/wrt-service-tct/prerequisite.js');
+    requireTCT('./tct/TypeSelector_tct.js')('alarm application datacontrol filesystem messageport package systeminfo');
+    //require('./utc/utc.js')('alarm application datacontrol filesystem messageport package systeminfo');
+})();
diff --git a/selector/TestUniversalSelector.js b/selector/TestUniversalSelector.js
new file mode 100755 (executable)
index 0000000..e80ea7f
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+Copyright (c) 2016 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Authors:
+        Xiaoyan Qian <xy.qian@samsung.com>
+
+*/
+
+function Universal_selector_test() {
+
+setup({timeout: 300000});
+
+var t = async_test('Universal_selector_test', {timeout: 300000});
+
+t.step(function () {
+    var d = document.getElementsByTagName("p");
+   d[0].onclick = t.step_func(function() {
+     t.done();
+    })
+   d[1].onclick = t.step_func(function() {
+     assert_true(false,"result is fail");
+    })
+});
+
+}
+
+var moduleName = "tct-universalselector-css-test";
+add_test_case(moduleName,Universal_selector_test);
diff --git a/selector/TypeSelector_tct.js b/selector/TypeSelector_tct.js
new file mode 100755 (executable)
index 0000000..ef778e7
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+ * 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.
+ */
+
+(function() {
+    function runTests() {
+        // gather tests to run
+        var selectedTests = {};
+        for (var i = 0; i < arguments.length; ++i) {
+            var arg = arguments[i];
+            if (!(arg instanceof Array)) {
+                arg = String(arg).split(' ');
+            }
+            for (var j = 0; j < arg.length; ++j) {
+                selectedTests[arg[j].toLowerCase()] = '';
+            }
+        }
+
+        // load node.js modules
+        var fs = requireTCT('fs');
+
+        // checks if object is empty
+        function isEmptyObject(object) {
+            for (var prop in object) {
+                if (object.hasOwnProperty(prop)) {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        // constants
+        var testsDir = 'tct/tests/';
+        var testRegExp = /^Test(.*)\.js$/;
+        var testPrefix = 'Test';
+        var extension = '.js';
+
+        // find available tests
+        var availableTests = {};
+        //var testFiles = fs.readdirSync(testsDir);
+        var testFiles = [
+            //"TestApplication.js",
+            //"TestFilesystem.js",
+            //"TestMessagePort.js",
+            //"TestSysteminfo.js",
+            //"TestPreference.js",
+            //"TestSensor.js",
+            //"TestHtml.js",
+            //"TestDynamicPseudoSelector.js",
+            "TestTypeSelector.js",
+        ];
+
+        for (var ii = 0; ii < testFiles.length; ++ii) {
+            var match = testRegExp.exec(testFiles[ii]);
+            if (match) {
+                match = match[1];
+                availableTests[match.toLowerCase()] = match;
+            }
+        }
+
+        // if no tests are selected, run all
+        if (isEmptyObject(selectedTests)) {
+            selectedTests = availableTests;
+        }
+
+        // load tizen modules
+        if (typeof (tizen) === 'undefined') {
+            requireTCT('common/loader.js')();
+        }
+
+        // load test engine
+        requireTCT('tct/common/testharness.js');
+        requireTCT('tct/common/unitcommon.js');
+
+        // stores test cases
+        var testCases = [];
+        var stats = { modules : {}, tests : {} };
+
+        function add_test_case(m, f) {
+            if (!stats.modules[m]) {
+                stats.modules[m] = {};
+                stats.modules[m].all = 0;
+                stats.modules[m].pass = 0;
+                stats.modules[m].fail = 0;
+                stats.modules[m].timeout = 0;
+                stats.modules[m].notrun = 0;
+            }
+            ++stats.modules[m].all;
+            stats.tests[f.name] = m;
+            testCases.push(f);
+        }
+        expose(add_test_case, 'add_test_case');
+
+        // load tests
+        for (var test in selectedTests) {
+            if (availableTests[test]) {
+                console.log('Loading test: ' + availableTests[test]);
+                try {
+                    requireTCT(testsDir + testPrefix + availableTests[test] + extension);
+                } catch (e) {
+                    console.log('Failed to load: ' + availableTests[test]);
+                    console.log(e);
+                }
+            }
+        }
+
+        // handle test case
+        var currentTest = 0;
+
+        function onResult(test) {
+            if (test) {
+                // store statistics
+                var m = stats.tests[test.name];
+                switch (test.status) {
+                case 0:
+                    ++stats.modules[m].pass;
+                    break;
+                case 1:
+                    ++stats.modules[m].fail;
+                    break;
+                case 2:
+                    ++stats.modules[m].timeout;
+                    break;
+                case 3:
+                    ++stats.modules[m].notrun;
+                    break;
+                }
+            }
+
+            // launch next test case
+            if (currentTest < testCases.length) {
+                setTimeout(testCases[currentTest], 0);
+                ++currentTest;
+            } else {
+                done();
+            }
+        }
+        function onFinish() {
+            var total = 0;
+            var pass = 0;
+            var fail = 0;
+            var timeout = 0;
+            var notrun = 0;
+            console.log('============ Test suites:');
+            for (var m in stats.modules) {
+                if (stats.modules.hasOwnProperty(m)) {
+                    var s = stats.modules[m];
+                    var nr = s.all - s.pass - s.fail - s.timeout;
+                    console.log('[' + m + '] - ' + s.pass + ' passed, ' + s.fail + ' failed, ' + s.timeout + ' timed out, ' + nr + ' not run.');
+                    total += s.all;
+                    pass += s.pass;
+                    fail += s.fail;
+                    timeout += s.timeout;
+                    notrun += nr;
+                }
+            }
+            console.log('============ Summary:');
+            console.log('Test cases all: ' + total);
+            console.log('Test cases passed: ' + pass);
+            console.log('Test cases failed: ' + fail);
+            console.log('Test cases timed out: ' + timeout);
+            console.log('Test cases not run: ' + notrun);
+            // terminate process
+            process.exit();
+        }
+
+        // register callbacks
+        add_result_callback(onResult);
+        add_completion_callback(onFinish);
+
+        // start testing
+        console.log('Running tests');
+        onResult();
+    }
+
+    if (!module.parent) {
+        // standalone script
+        //runTests(process.argv.slice(2));
+        runTests([
+                //"Application",
+                //"Filesystem",
+                //"MessagePort",
+                //"Systeminfo",
+                //"Preference",
+                //"Sensor",
+                //"Html",
+                //"DynamicPseudoSelector",
+                "TypeSelector",
+                ]);
+    } else {
+        module.exports = runTests;
+    }
+})();
+
diff --git a/selector/UniversalSelector_index.js b/selector/UniversalSelector_index.js
new file mode 100755 (executable)
index 0000000..eb62724
--- /dev/null
@@ -0,0 +1,5 @@
+(function() {
+    load('/home/owner/share/wrt-service-tct/prerequisite.js');
+    requireTCT('./tct/UniversalSelector_tct.js')('alarm application datacontrol filesystem messageport package systeminfo');
+    //require('./utc/utc.js')('alarm application datacontrol filesystem messageport package systeminfo');
+})();
diff --git a/selector/UniversalSelector_tct.js b/selector/UniversalSelector_tct.js
new file mode 100755 (executable)
index 0000000..bee605f
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+ * 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.
+ */
+
+(function() {
+    function runTests() {
+        // gather tests to run
+        var selectedTests = {};
+        for (var i = 0; i < arguments.length; ++i) {
+            var arg = arguments[i];
+            if (!(arg instanceof Array)) {
+                arg = String(arg).split(' ');
+            }
+            for (var j = 0; j < arg.length; ++j) {
+                selectedTests[arg[j].toLowerCase()] = '';
+            }
+        }
+
+        // load node.js modules
+        var fs = requireTCT('fs');
+
+        // checks if object is empty
+        function isEmptyObject(object) {
+            for (var prop in object) {
+                if (object.hasOwnProperty(prop)) {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        // constants
+        var testsDir = 'tct/tests/';
+        var testRegExp = /^Test(.*)\.js$/;
+        var testPrefix = 'Test';
+        var extension = '.js';
+
+        // find available tests
+        var availableTests = {};
+        //var testFiles = fs.readdirSync(testsDir);
+        var testFiles = [
+            //"TestApplication.js",
+            //"TestFilesystem.js",
+            //"TestMessagePort.js",
+            //"TestSysteminfo.js",
+            //"TestPreference.js",
+            //"TestSensor.js",
+            //"TestHtml.js",
+            //"TestDynamicPseudoSelector.js",
+            "TestUniversalSelector.js",
+        ];
+
+        for (var ii = 0; ii < testFiles.length; ++ii) {
+            var match = testRegExp.exec(testFiles[ii]);
+            if (match) {
+                match = match[1];
+                availableTests[match.toLowerCase()] = match;
+            }
+        }
+
+        // if no tests are selected, run all
+        if (isEmptyObject(selectedTests)) {
+            selectedTests = availableTests;
+        }
+
+        // load tizen modules
+        if (typeof (tizen) === 'undefined') {
+            requireTCT('common/loader.js')();
+        }
+
+        // load test engine
+        requireTCT('tct/common/testharness.js');
+        requireTCT('tct/common/unitcommon.js');
+
+        // stores test cases
+        var testCases = [];
+        var stats = { modules : {}, tests : {} };
+
+        function add_test_case(m, f) {
+            if (!stats.modules[m]) {
+                stats.modules[m] = {};
+                stats.modules[m].all = 0;
+                stats.modules[m].pass = 0;
+                stats.modules[m].fail = 0;
+                stats.modules[m].timeout = 0;
+                stats.modules[m].notrun = 0;
+            }
+            ++stats.modules[m].all;
+            stats.tests[f.name] = m;
+            testCases.push(f);
+        }
+        expose(add_test_case, 'add_test_case');
+
+        // load tests
+        for (var test in selectedTests) {
+            if (availableTests[test]) {
+                console.log('Loading test: ' + availableTests[test]);
+                try {
+                    requireTCT(testsDir + testPrefix + availableTests[test] + extension);
+                } catch (e) {
+                    console.log('Failed to load: ' + availableTests[test]);
+                    console.log(e);
+                }
+            }
+        }
+
+        // handle test case
+        var currentTest = 0;
+
+        function onResult(test) {
+            if (test) {
+                // store statistics
+                var m = stats.tests[test.name];
+                switch (test.status) {
+                case 0:
+                    ++stats.modules[m].pass;
+                    break;
+                case 1:
+                    ++stats.modules[m].fail;
+                    break;
+                case 2:
+                    ++stats.modules[m].timeout;
+                    break;
+                case 3:
+                    ++stats.modules[m].notrun;
+                    break;
+                }
+            }
+
+            // launch next test case
+            if (currentTest < testCases.length) {
+                setTimeout(testCases[currentTest], 0);
+                ++currentTest;
+            } else {
+                done();
+            }
+        }
+        function onFinish() {
+            var total = 0;
+            var pass = 0;
+            var fail = 0;
+            var timeout = 0;
+            var notrun = 0;
+            console.log('============ Test suites:');
+            for (var m in stats.modules) {
+                if (stats.modules.hasOwnProperty(m)) {
+                    var s = stats.modules[m];
+                    var nr = s.all - s.pass - s.fail - s.timeout;
+                    console.log('[' + m + '] - ' + s.pass + ' passed, ' + s.fail + ' failed, ' + s.timeout + ' timed out, ' + nr + ' not run.');
+                    total += s.all;
+                    pass += s.pass;
+                    fail += s.fail;
+                    timeout += s.timeout;
+                    notrun += nr;
+                }
+            }
+            console.log('============ Summary:');
+            console.log('Test cases all: ' + total);
+            console.log('Test cases passed: ' + pass);
+            console.log('Test cases failed: ' + fail);
+            console.log('Test cases timed out: ' + timeout);
+            console.log('Test cases not run: ' + notrun);
+            // terminate process
+            process.exit();
+        }
+
+        // register callbacks
+        add_result_callback(onResult);
+        add_completion_callback(onFinish);
+
+        // start testing
+        console.log('Running tests');
+        onResult();
+    }
+
+    if (!module.parent) {
+        // standalone script
+        //runTests(process.argv.slice(2));
+        runTests([
+                //"Application",
+                //"Filesystem",
+                //"MessagePort",
+                //"Systeminfo",
+                //"Preference",
+                //"Sensor",
+                //"Html",
+                //"DynamicPseudoSelector",
+                "UniversalSelector",
+                ]);
+    } else {
+        module.exports = runTests;
+    }
+})();
+
diff --git a/selector/install.sh b/selector/install.sh
new file mode 100755 (executable)
index 0000000..a4227e9
--- /dev/null
@@ -0,0 +1,9 @@
+sdb push *_index.js /home/owner/share/wrt-service-tct/
+sdb push *_tct.js /home/owner/share/wrt-service-tct/tct/
+sdb push TestClassSelector.js /home/owner/share/wrt-service-tct/tct/tests/
+sdb push TestDynamicPseudoSelector.js /home/owner/share/wrt-service-tct/tct/tests/
+sdb push TestIdSelector.js /home/owner/share/wrt-service-tct/tct/tests/
+sdb push TestTypeSelector.js /home/owner/share/wrt-service-tct/tct/tests/
+sdb push TestUniversalSelector.js /home/owner/share/wrt-service-tct/tct/tests/
+sdb root off
+sdb install selector.wgt
diff --git a/selector/selector.wgt b/selector/selector.wgt
new file mode 100644 (file)
index 0000000..d8dc665
Binary files /dev/null and b/selector/selector.wgt differ
diff --git a/tct-webwidget-w3c-tests-5.5.zip b/tct-webwidget-w3c-tests-5.5.zip
new file mode 100644 (file)
index 0000000..fc34d56
Binary files /dev/null and b/tct-webwidget-w3c-tests-5.5.zip differ
diff --git a/webWidgetTCT_device/DeviceAPI.wgt b/webWidgetTCT_device/DeviceAPI.wgt
new file mode 100755 (executable)
index 0000000..9633b90
Binary files /dev/null and b/webWidgetTCT_device/DeviceAPI.wgt differ
diff --git a/webWidgetTCT_device/DeviceAPI/.project b/webWidgetTCT_device/DeviceAPI/.project
new file mode 100755 (executable)
index 0000000..1727956
--- /dev/null
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>DeviceAPI</name>
+       <comment></comment>
+       <projects>
+       </projects>
+       <buildSpec>
+               <buildCommand>
+                       <name>json.validation.builder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.tizen.web.project.builder.WebBuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+       </buildSpec>
+       <natures>
+               <nature>json.validation.nature</nature>
+               <nature>org.eclipse.wst.jsdt.core.jsNature</nature>
+               <nature>org.tizen.web.project.builder.WebNature</nature>
+       </natures>
+</projectDescription>
diff --git a/webWidgetTCT_device/DeviceAPI/.rds_delta b/webWidgetTCT_device/DeviceAPI/.rds_delta
new file mode 100755 (executable)
index 0000000..f0b27ea
--- /dev/null
@@ -0,0 +1,6 @@
+#delete
+#add
+#modify
+res/wgt/author-signature.xml
+res/wgt/signature1.xml
+res/wgt/js/main.js
diff --git a/webWidgetTCT_device/DeviceAPI/.sdk_delta.info b/webWidgetTCT_device/DeviceAPI/.sdk_delta.info
new file mode 100755 (executable)
index 0000000..cde096b
Binary files /dev/null and b/webWidgetTCT_device/DeviceAPI/.sdk_delta.info differ
diff --git a/webWidgetTCT_device/DeviceAPI/.settings/.jsdtscope b/webWidgetTCT_device/DeviceAPI/.settings/.jsdtscope
new file mode 100755 (executable)
index 0000000..291328b
--- /dev/null
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+       <classpathentry kind="con" path="org.tizen.web.project.initializer.WebLibraryInitializer"/>
+       <classpathentry kind="con" path="org.eclipselabs.jsdt.jquery.core.CoflictLibrary_2.0"/>
+       <classpathentry kind="con" path="org.tizen.web.project.initializer.TizenLibraryInitializer"/>
+       <classpathentry kind="con" path="org.tizen.web.project.initializer.HTML5LibraryInitializer"/>
+       <classpathentry kind="con" path="org.tizen.web.project.initializer.W3CLibraryInitializer"/>
+       <classpathentry kind="con" path="org.tizen.web.project.initializer.ext.RESTSupport"/>
+       <classpathentry kind="output" path=""/>
+</classpath>
diff --git a/webWidgetTCT_device/DeviceAPI/.settings/org.eclipse.wst.css.core.prefs b/webWidgetTCT_device/DeviceAPI/.settings/org.eclipse.wst.css.core.prefs
new file mode 100755 (executable)
index 0000000..5ddc6bd
--- /dev/null
@@ -0,0 +1,2 @@
+css-profile/<project>=org.eclipse.wst.css.core.cssprofile.css3
+eclipse.preferences.version=1
diff --git a/webWidgetTCT_device/DeviceAPI/.settings/org.eclipse.wst.jsdt.ui.superType.container b/webWidgetTCT_device/DeviceAPI/.settings/org.eclipse.wst.jsdt.ui.superType.container
new file mode 100755 (executable)
index 0000000..3bd5d0a
--- /dev/null
@@ -0,0 +1 @@
+org.eclipse.wst.jsdt.launching.baseBrowserLibrary
\ No newline at end of file
diff --git a/webWidgetTCT_device/DeviceAPI/.settings/org.eclipse.wst.jsdt.ui.superType.name b/webWidgetTCT_device/DeviceAPI/.settings/org.eclipse.wst.jsdt.ui.superType.name
new file mode 100755 (executable)
index 0000000..05bd71b
--- /dev/null
@@ -0,0 +1 @@
+Window
\ No newline at end of file
diff --git a/webWidgetTCT_device/DeviceAPI/.sign/.manifest.tmp b/webWidgetTCT_device/DeviceAPI/.sign/.manifest.tmp
new file mode 100755 (executable)
index 0000000..fb9488c
--- /dev/null
@@ -0,0 +1,39 @@
+config.xml__DEL__IaFg+DlZiEJ3CDnipRmad7FqLlS1gHTOfw3beaqOcR4=
+css/style.css__DEL__Yc5/Km/O7fXXLzDC0Xc34K+k00+3OFIEkRFZXNT7pAI=
+icon.png__DEL__vPjxjOppORd6hn9Bw4sh06gqtDoJzoFbV/8e9FyIdvk=
+index.html__DEL__OulODbDyVLVkrAt1JY1p5ujQfa68rT7rK4KqKGjy8WQ=
+js/main.js__DEL__Y70KO81iedWikOsKqwv959SbEe0/nlJizVr0wIfQRUo=
+widget/f01/css/style.css__DEL__nXAg4Qivxlan9WfoAzI9/fD/RrSEfNXSN0xA5zJGi9Q=
+widget/f01/icon.png__DEL__vPjxjOppORd6hn9Bw4sh06gqtDoJzoFbV/8e9FyIdvk=
+widget/f01/index.html__DEL__QqyltSWHIW6QRmqzbxVlMv4kVBU3dALI5aHDAl+Ask4=
+widget/f01/js/main.js__DEL__8vD6xTeutprpK8ki2spu+cRNMvO+yEbmUxJaxHoo4Sg=
+widget/f01/js/promise.min.js__DEL__oj5MqYs/G1IPTgEBRyHtkAONiUmPlBIhTa4Q/AVJAJ4=
+widget/f01/preview.png__DEL__vPjxjOppORd6hn9Bw4sh06gqtDoJzoFbV/8e9FyIdvk=
+widget/f01/resources/data.json__DEL__UyeLMMdHeFZdYHXXmI1H8qX9a2Er3Vk8q0MwKchKT4Q=
+widget/f01/support/path.js__DEL__KF8MXnGeA15nLQ1NneTQCxi20AoYsMbJHEfjm+YtqrA=
+widget/f01/support/test.html__DEL__ktrpfhA7eDb9MZjT8cX2/0pnMSmUJJ0G0FPTOnktzAY=
+widget/f01/support/test.xml__DEL__d4LdoLKyi/WWoLEWrYreyiDmefHFbbhsmu8GhpQNIxw=
+widget/f01/support/test_timeout.xml__DEL__mI+ZuKxWXOvyiJZGUZUC8/DQ4/dG2GDiLE5ygBEWuW4=
+widget/f02/css/style.css__DEL__nXAg4Qivxlan9WfoAzI9/fD/RrSEfNXSN0xA5zJGi9Q=
+widget/f02/icon.png__DEL__vPjxjOppORd6hn9Bw4sh06gqtDoJzoFbV/8e9FyIdvk=
+widget/f02/index.html__DEL__83hfIZJ0aZ0j8uQCpZDJoaA2+n+ZwiO1FAjpdPKBEeQ=
+widget/f02/js/main.js__DEL__8vD6xTeutprpK8ki2spu+cRNMvO+yEbmUxJaxHoo4Sg=
+widget/f02/js/promise.min.js__DEL__oj5MqYs/G1IPTgEBRyHtkAONiUmPlBIhTa4Q/AVJAJ4=
+widget/f02/preview.png__DEL__vPjxjOppORd6hn9Bw4sh06gqtDoJzoFbV/8e9FyIdvk=
+widget/f02/resources/data.json__DEL__UyeLMMdHeFZdYHXXmI1H8qX9a2Er3Vk8q0MwKchKT4Q=
+widget/f02/support/path.js__DEL__KF8MXnGeA15nLQ1NneTQCxi20AoYsMbJHEfjm+YtqrA=
+widget/f02/support/test.html__DEL__ktrpfhA7eDb9MZjT8cX2/0pnMSmUJJ0G0FPTOnktzAY=
+widget/f02/support/test.xml__DEL__d4LdoLKyi/WWoLEWrYreyiDmefHFbbhsmu8GhpQNIxw=
+widget/f02/support/test_timeout.xml__DEL__mI+ZuKxWXOvyiJZGUZUC8/DQ4/dG2GDiLE5ygBEWuW4=
+widget/f03/css/style.css__DEL__nXAg4Qivxlan9WfoAzI9/fD/RrSEfNXSN0xA5zJGi9Q=
+widget/f03/icon.png__DEL__vPjxjOppORd6hn9Bw4sh06gqtDoJzoFbV/8e9FyIdvk=
+widget/f03/index.html__DEL__MIJD6vp9+UytB576LegsHg6xJ/ktKPwLLxihGrGrQWc=
+widget/f03/js/main.js__DEL__8vD6xTeutprpK8ki2spu+cRNMvO+yEbmUxJaxHoo4Sg=
+widget/f03/js/promise.min.js__DEL__oj5MqYs/G1IPTgEBRyHtkAONiUmPlBIhTa4Q/AVJAJ4=
+widget/f03/preview.png__DEL__vPjxjOppORd6hn9Bw4sh06gqtDoJzoFbV/8e9FyIdvk=
+widget/f03/resources/data.json__DEL__UyeLMMdHeFZdYHXXmI1H8qX9a2Er3Vk8q0MwKchKT4Q=
+widget/f03/support/path.js__DEL__KF8MXnGeA15nLQ1NneTQCxi20AoYsMbJHEfjm+YtqrA=
+widget/f03/support/test.html__DEL__ktrpfhA7eDb9MZjT8cX2/0pnMSmUJJ0G0FPTOnktzAY=
+widget/f03/support/test.xml__DEL__d4LdoLKyi/WWoLEWrYreyiDmefHFbbhsmu8GhpQNIxw=
+widget/f03/support/test_timeout.xml__DEL__mI+ZuKxWXOvyiJZGUZUC8/DQ4/dG2GDiLE5ygBEWuW4=
+author-signature.xml__DEL__gwtv3VCfD9aIh+1A2j5SRxNO3aoY4wj0hW0+Ymqcrsw=
diff --git a/webWidgetTCT_device/DeviceAPI/.sign/author-signature.xml b/webWidgetTCT_device/DeviceAPI/.sign/author-signature.xml
new file mode 100755 (executable)
index 0000000..b298921
--- /dev/null
@@ -0,0 +1,206 @@
+<Signature xmlns="http://www.w3.org/2000/09/xmldsig#" Id="AuthorSignature">
+<SignedInfo>
+<CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></CanonicalizationMethod>
+<SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"></SignatureMethod>
+<Reference URI="config.xml">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>IaFg+DlZiEJ3CDnipRmad7FqLlS1gHTOfw3beaqOcR4=</DigestValue>
+</Reference>
+<Reference URI="css%2Fstyle.css">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>Yc5/Km/O7fXXLzDC0Xc34K+k00+3OFIEkRFZXNT7pAI=</DigestValue>
+</Reference>
+<Reference URI="icon.png">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>vPjxjOppORd6hn9Bw4sh06gqtDoJzoFbV/8e9FyIdvk=</DigestValue>
+</Reference>
+<Reference URI="index.html">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>OulODbDyVLVkrAt1JY1p5ujQfa68rT7rK4KqKGjy8WQ=</DigestValue>
+</Reference>
+<Reference URI="js%2Fmain.js">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>Y70KO81iedWikOsKqwv959SbEe0/nlJizVr0wIfQRUo=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff01%2Fcss%2Fstyle.css">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>nXAg4Qivxlan9WfoAzI9/fD/RrSEfNXSN0xA5zJGi9Q=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff01%2Ficon.png">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>vPjxjOppORd6hn9Bw4sh06gqtDoJzoFbV/8e9FyIdvk=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff01%2Findex.html">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>QqyltSWHIW6QRmqzbxVlMv4kVBU3dALI5aHDAl+Ask4=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff01%2Fjs%2Fmain.js">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>8vD6xTeutprpK8ki2spu+cRNMvO+yEbmUxJaxHoo4Sg=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff01%2Fjs%2Fpromise.min.js">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>oj5MqYs/G1IPTgEBRyHtkAONiUmPlBIhTa4Q/AVJAJ4=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff01%2Fpreview.png">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>vPjxjOppORd6hn9Bw4sh06gqtDoJzoFbV/8e9FyIdvk=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff01%2Fresources%2Fdata.json">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>UyeLMMdHeFZdYHXXmI1H8qX9a2Er3Vk8q0MwKchKT4Q=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff01%2Fsupport%2Fpath.js">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>KF8MXnGeA15nLQ1NneTQCxi20AoYsMbJHEfjm+YtqrA=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff01%2Fsupport%2Ftest.html">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>ktrpfhA7eDb9MZjT8cX2/0pnMSmUJJ0G0FPTOnktzAY=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff01%2Fsupport%2Ftest.xml">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>d4LdoLKyi/WWoLEWrYreyiDmefHFbbhsmu8GhpQNIxw=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff01%2Fsupport%2Ftest_timeout.xml">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>mI+ZuKxWXOvyiJZGUZUC8/DQ4/dG2GDiLE5ygBEWuW4=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff02%2Fcss%2Fstyle.css">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>nXAg4Qivxlan9WfoAzI9/fD/RrSEfNXSN0xA5zJGi9Q=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff02%2Ficon.png">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>vPjxjOppORd6hn9Bw4sh06gqtDoJzoFbV/8e9FyIdvk=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff02%2Findex.html">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>83hfIZJ0aZ0j8uQCpZDJoaA2+n+ZwiO1FAjpdPKBEeQ=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff02%2Fjs%2Fmain.js">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>8vD6xTeutprpK8ki2spu+cRNMvO+yEbmUxJaxHoo4Sg=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff02%2Fjs%2Fpromise.min.js">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>oj5MqYs/G1IPTgEBRyHtkAONiUmPlBIhTa4Q/AVJAJ4=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff02%2Fpreview.png">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>vPjxjOppORd6hn9Bw4sh06gqtDoJzoFbV/8e9FyIdvk=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff02%2Fresources%2Fdata.json">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>UyeLMMdHeFZdYHXXmI1H8qX9a2Er3Vk8q0MwKchKT4Q=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff02%2Fsupport%2Fpath.js">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>KF8MXnGeA15nLQ1NneTQCxi20AoYsMbJHEfjm+YtqrA=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff02%2Fsupport%2Ftest.html">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>ktrpfhA7eDb9MZjT8cX2/0pnMSmUJJ0G0FPTOnktzAY=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff02%2Fsupport%2Ftest.xml">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>d4LdoLKyi/WWoLEWrYreyiDmefHFbbhsmu8GhpQNIxw=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff02%2Fsupport%2Ftest_timeout.xml">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>mI+ZuKxWXOvyiJZGUZUC8/DQ4/dG2GDiLE5ygBEWuW4=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff03%2Fcss%2Fstyle.css">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>nXAg4Qivxlan9WfoAzI9/fD/RrSEfNXSN0xA5zJGi9Q=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff03%2Ficon.png">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>vPjxjOppORd6hn9Bw4sh06gqtDoJzoFbV/8e9FyIdvk=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff03%2Findex.html">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>MIJD6vp9+UytB576LegsHg6xJ/ktKPwLLxihGrGrQWc=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff03%2Fjs%2Fmain.js">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>8vD6xTeutprpK8ki2spu+cRNMvO+yEbmUxJaxHoo4Sg=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff03%2Fjs%2Fpromise.min.js">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>oj5MqYs/G1IPTgEBRyHtkAONiUmPlBIhTa4Q/AVJAJ4=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff03%2Fpreview.png">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>vPjxjOppORd6hn9Bw4sh06gqtDoJzoFbV/8e9FyIdvk=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff03%2Fresources%2Fdata.json">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>UyeLMMdHeFZdYHXXmI1H8qX9a2Er3Vk8q0MwKchKT4Q=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff03%2Fsupport%2Fpath.js">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>KF8MXnGeA15nLQ1NneTQCxi20AoYsMbJHEfjm+YtqrA=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff03%2Fsupport%2Ftest.html">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>ktrpfhA7eDb9MZjT8cX2/0pnMSmUJJ0G0FPTOnktzAY=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff03%2Fsupport%2Ftest.xml">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>d4LdoLKyi/WWoLEWrYreyiDmefHFbbhsmu8GhpQNIxw=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff03%2Fsupport%2Ftest_timeout.xml">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>mI+ZuKxWXOvyiJZGUZUC8/DQ4/dG2GDiLE5ygBEWuW4=</DigestValue>
+</Reference>
+<Reference URI="#prop">
+<Transforms>
+<Transform Algorithm="http://www.w3.org/2006/12/xml-c14n11"></Transform>
+</Transforms>
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>lpo8tUDs054eLlBQXiDPVDVKfw30ZZdtkRs1jd7H5K8=</DigestValue>
+</Reference>
+</SignedInfo>
+<SignatureValue>
+EEv4fS+Gm4wnunSbNcSEc7yCRWMEnC3jtd+mW7LMZpV0H8XNictQkto+i/BegucPN3axhYt+MuWp
+FLxyiMuaOmagH1kutBEWLEeW63IvgFyBjWO1e03/526dYIKQ86fSPU+PIznw55VHpDKqHywPK7Ey
+wEaHPBLnjEhVhinyy+M=
+</SignatureValue>
+<KeyInfo>
+<X509Data>
+<X509Certificate>
+MIIClTCCAX2gAwIBAgIGAVV0lzdfMA0GCSqGSIb3DQEBBQUAMFYxGjAYBgNVBAoMEVRpemVuIEFz
+c29jaWF0aW9uMRowGAYDVQQLDBFUaXplbiBBc3NvY2lhdGlvbjEcMBoGA1UEAwwTVGl6ZW4gRGV2
+ZWxvcGVycyBDQTAeFw0xMjExMDEwMDAwMDBaFw0xOTAxMDEwMDAwMDBaMBExDzANBgNVBAMMBmF1
+dGhvcjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAtLhrwScC65u3n/L9Xg0xTjt2Z8bI9ctL
+PmnqDYDQ6OvJe/gpgvng4Q9sJV5FLcmZ1wtGvnNUFnlUsDiSKjxwiKnFDH1VNy1J4Jv+hmVp+wpG
+Op/ZkX1Gn+HrHBlJNJ3FDgu4f9rIOajI5G4pWw6C9OsGdzGGT8owI/nq6h+9kDECAwEAAaMyMDAw
+DAYDVR0TAQH/BAIwADALBgNVHQ8EBAMCB4AwEwYDVR0lBAwwCgYIKwYBBQUHAwMwDQYJKoZIhvcN
+AQEFBQADggEBAKUnZQiqW9EI88dI6CNJVjryj7u6ud8oAS4IzNOLSxcsJ65GvE0k5v6KizcUdU/r
+kXo+39surSUvR/XEe5jGtLY8u1Mb572NEO+WdLh5O0Uk4oQXEf/0LEVbTPFu88PgOTkSbxJtbvR4
+9/8pGpwXp4qOZaTs0H6nfPbrRcKrjDoXkZhxh92rKWlcx5C6wZuZ+pF87TS+c7cqcUPNKwWldXk3
+FhR20TOC/VyeGpiyLfMGqimKxmf4eeVHZsjpd7HGSZ5GyQ3l3MMiyTZWsLuOjQlkY0QcfzhkEq4Q
+9cedt761xrQhh9UtvsH7FlhYRe8ScqcVxsyhBqKn1jm62ETPAso=
+</X509Certificate>
+<X509Certificate>
+MIIDOTCCAiGgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMRowGAYDVQQKDBFUaXplbiBBc3NvY2lh
+dGlvbjEaMBgGA1UECwwRVGl6ZW4gQXNzb2NpYXRpb24xHjAcBgNVBAMMFVRpemVuIERldmVsb3Bl
+cnMgUm9vdDAeFw0xMjAxMDEwMDAwMDBaFw0yNzAxMDEwMDAwMDBaMFYxGjAYBgNVBAoMEVRpemVu
+IEFzc29jaWF0aW9uMRowGAYDVQQLDBFUaXplbiBBc3NvY2lhdGlvbjEcMBoGA1UEAwwTVGl6ZW4g
+RGV2ZWxvcGVycyBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANVGhRGmMIUyBA7o
+PCz8Sxut6z6HNkF4oDIuzuKaMzRYPeWodwe9O0gmqAkToQHfwg2giRhE5GoPld0fq+OYMMwSasCu
+g8dwODx1eDeSYVuOLWRxpAmbTXOsSFi6VoWeyaPEm18JBHvZBsU5YQtgZ6Kp7MqzvQg3pXOxtajj
+vyHxiatJl+xXrHgcXC1wgyG3buty7u/Fi2mvKXJ0PRJcCjjK81dqe/Vr20sRUCrbk02zbm5ggFt/
+jIEhV8wbFRQpliobc7J4dSTKhFfrqGM8rdd54LYhD7gSI1CFSe16pUXfcVR7FhJztRaiGLnCrwBE
+dyTZ248+D4L/qR/D0axb3jcCAwEAAaMQMA4wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOC
+AQEAnOXXQ/1O/QTDHyrmQDtFziqPY3xWlJBqJtEqXiT7Y+Ljpe66e+Ee/OjQMlZe8gu21/8cKklH
+95RxjopMWCVedXDUbWdvS2+CdyvVW/quT2E0tjqIzXDekUTYwwhlPWlGxvfj3VsxqSFq3p8Brl04
+1Gx5RKAGyKVsMfTLhbbwSWwApuBUxYfcNpKwLWGPXkysu+HctY03OKv4/xKBnVWiN8ex/Sgesi0M
++OBAOMdZMPK32uJBTeKFx1xZgTLIhk45V0hPOomPjZloiv0LSS11eyd451ufjW0iHRE7WlpR6EvI
+W6TFyZgMpQq+kg4hWl2SBTf3s2VI8Ygz7gj8TMlClg==
+</X509Certificate>
+</X509Data>
+</KeyInfo>
+<Object Id="prop"><SignatureProperties xmlns:dsp="http://www.w3.org/2009/xmldsig-properties"><SignatureProperty Id="profile" Target="#AuthorSignature"><dsp:Profile URI="http://www.w3.org/ns/widgets-digsig#profile"></dsp:Profile></SignatureProperty><SignatureProperty Id="role" Target="#AuthorSignature"><dsp:Role URI="http://www.w3.org/ns/widgets-digsig#role-author"></dsp:Role></SignatureProperty><SignatureProperty Id="identifier" Target="#AuthorSignature"><dsp:Identifier></dsp:Identifier></SignatureProperty></SignatureProperties></Object>
+</Signature>
\ No newline at end of file
diff --git a/webWidgetTCT_device/DeviceAPI/.sign/signature1.xml b/webWidgetTCT_device/DeviceAPI/.sign/signature1.xml
new file mode 100755 (executable)
index 0000000..b8cba71
--- /dev/null
@@ -0,0 +1,208 @@
+<Signature xmlns="http://www.w3.org/2000/09/xmldsig#" Id="DistributorSignature">
+<SignedInfo>
+<CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></CanonicalizationMethod>
+<SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"></SignatureMethod>
+<Reference URI="author-signature.xml">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>gwtv3VCfD9aIh+1A2j5SRxNO3aoY4wj0hW0+Ymqcrsw=</DigestValue>
+</Reference>
+<Reference URI="config.xml">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>IaFg+DlZiEJ3CDnipRmad7FqLlS1gHTOfw3beaqOcR4=</DigestValue>
+</Reference>
+<Reference URI="css%2Fstyle.css">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>Yc5/Km/O7fXXLzDC0Xc34K+k00+3OFIEkRFZXNT7pAI=</DigestValue>
+</Reference>
+<Reference URI="icon.png">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>vPjxjOppORd6hn9Bw4sh06gqtDoJzoFbV/8e9FyIdvk=</DigestValue>
+</Reference>
+<Reference URI="index.html">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>OulODbDyVLVkrAt1JY1p5ujQfa68rT7rK4KqKGjy8WQ=</DigestValue>
+</Reference>
+<Reference URI="js%2Fmain.js">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>Y70KO81iedWikOsKqwv959SbEe0/nlJizVr0wIfQRUo=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff01%2Fcss%2Fstyle.css">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>nXAg4Qivxlan9WfoAzI9/fD/RrSEfNXSN0xA5zJGi9Q=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff01%2Ficon.png">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>vPjxjOppORd6hn9Bw4sh06gqtDoJzoFbV/8e9FyIdvk=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff01%2Findex.html">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>QqyltSWHIW6QRmqzbxVlMv4kVBU3dALI5aHDAl+Ask4=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff01%2Fjs%2Fmain.js">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>8vD6xTeutprpK8ki2spu+cRNMvO+yEbmUxJaxHoo4Sg=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff01%2Fjs%2Fpromise.min.js">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>oj5MqYs/G1IPTgEBRyHtkAONiUmPlBIhTa4Q/AVJAJ4=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff01%2Fpreview.png">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>vPjxjOppORd6hn9Bw4sh06gqtDoJzoFbV/8e9FyIdvk=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff01%2Fresources%2Fdata.json">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>UyeLMMdHeFZdYHXXmI1H8qX9a2Er3Vk8q0MwKchKT4Q=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff01%2Fsupport%2Fpath.js">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>KF8MXnGeA15nLQ1NneTQCxi20AoYsMbJHEfjm+YtqrA=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff01%2Fsupport%2Ftest.html">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>ktrpfhA7eDb9MZjT8cX2/0pnMSmUJJ0G0FPTOnktzAY=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff01%2Fsupport%2Ftest.xml">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>d4LdoLKyi/WWoLEWrYreyiDmefHFbbhsmu8GhpQNIxw=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff01%2Fsupport%2Ftest_timeout.xml">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>mI+ZuKxWXOvyiJZGUZUC8/DQ4/dG2GDiLE5ygBEWuW4=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff02%2Fcss%2Fstyle.css">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>nXAg4Qivxlan9WfoAzI9/fD/RrSEfNXSN0xA5zJGi9Q=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff02%2Ficon.png">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>vPjxjOppORd6hn9Bw4sh06gqtDoJzoFbV/8e9FyIdvk=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff02%2Findex.html">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>83hfIZJ0aZ0j8uQCpZDJoaA2+n+ZwiO1FAjpdPKBEeQ=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff02%2Fjs%2Fmain.js">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>8vD6xTeutprpK8ki2spu+cRNMvO+yEbmUxJaxHoo4Sg=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff02%2Fjs%2Fpromise.min.js">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>oj5MqYs/G1IPTgEBRyHtkAONiUmPlBIhTa4Q/AVJAJ4=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff02%2Fpreview.png">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>vPjxjOppORd6hn9Bw4sh06gqtDoJzoFbV/8e9FyIdvk=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff02%2Fresources%2Fdata.json">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>UyeLMMdHeFZdYHXXmI1H8qX9a2Er3Vk8q0MwKchKT4Q=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff02%2Fsupport%2Fpath.js">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>KF8MXnGeA15nLQ1NneTQCxi20AoYsMbJHEfjm+YtqrA=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff02%2Fsupport%2Ftest.html">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>ktrpfhA7eDb9MZjT8cX2/0pnMSmUJJ0G0FPTOnktzAY=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff02%2Fsupport%2Ftest.xml">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>d4LdoLKyi/WWoLEWrYreyiDmefHFbbhsmu8GhpQNIxw=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff02%2Fsupport%2Ftest_timeout.xml">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>mI+ZuKxWXOvyiJZGUZUC8/DQ4/dG2GDiLE5ygBEWuW4=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff03%2Fcss%2Fstyle.css">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>nXAg4Qivxlan9WfoAzI9/fD/RrSEfNXSN0xA5zJGi9Q=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff03%2Ficon.png">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>vPjxjOppORd6hn9Bw4sh06gqtDoJzoFbV/8e9FyIdvk=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff03%2Findex.html">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>MIJD6vp9+UytB576LegsHg6xJ/ktKPwLLxihGrGrQWc=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff03%2Fjs%2Fmain.js">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>8vD6xTeutprpK8ki2spu+cRNMvO+yEbmUxJaxHoo4Sg=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff03%2Fjs%2Fpromise.min.js">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>oj5MqYs/G1IPTgEBRyHtkAONiUmPlBIhTa4Q/AVJAJ4=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff03%2Fpreview.png">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>vPjxjOppORd6hn9Bw4sh06gqtDoJzoFbV/8e9FyIdvk=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff03%2Fresources%2Fdata.json">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>UyeLMMdHeFZdYHXXmI1H8qX9a2Er3Vk8q0MwKchKT4Q=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff03%2Fsupport%2Fpath.js">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>KF8MXnGeA15nLQ1NneTQCxi20AoYsMbJHEfjm+YtqrA=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff03%2Fsupport%2Ftest.html">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>ktrpfhA7eDb9MZjT8cX2/0pnMSmUJJ0G0FPTOnktzAY=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff03%2Fsupport%2Ftest.xml">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>d4LdoLKyi/WWoLEWrYreyiDmefHFbbhsmu8GhpQNIxw=</DigestValue>
+</Reference>
+<Reference URI="widget%2Ff03%2Fsupport%2Ftest_timeout.xml">
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>mI+ZuKxWXOvyiJZGUZUC8/DQ4/dG2GDiLE5ygBEWuW4=</DigestValue>
+</Reference>
+<Reference URI="#prop">
+<Transforms>
+<Transform Algorithm="http://www.w3.org/2006/12/xml-c14n11"></Transform>
+</Transforms>
+<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></DigestMethod>
+<DigestValue>u/jU3U4Zm5ihTMSjKGlGYbWzDfRkGphPPHx3gJIYEJ4=</DigestValue>
+</Reference>
+</SignedInfo>
+<SignatureValue>
+nxwIsen7jj8292zFZBTHl++ax3yN3cUibEIm7fF08ahn1hDA896RdbJvQkxdH+5aHTRKbJ4J/1Uw
+gTPRy80zDjLmkCFFCcd6vdLVc1MvWzfA4FzeGDiAM5qsrQklGRi928J2NU17zXo/BI3DVC8CiJuY
+syweZc3fl7Vd9wSKZEg=
+</SignatureValue>
+<KeyInfo>
+<X509Data>
+<X509Certificate>
+MIICnTCCAgYCCQDE9MbMmJ/yCzANBgkqhkiG9w0BAQUFADCBkDELMAkGA1UEBhMCS1IxDjAMBgNV
+BAgMBVN1d29uMQ4wDAYDVQQHDAVTdXdvbjEWMBQGA1UECgwNVGl6ZW4gVGVzdCBDQTEiMCAGA1UE
+CwwZVGl6ZW4gRGlzdHJpYnV0b3IgVGVzdCBDQTElMCMGA1UEAwwcVGl6ZW4gUGFydG5lciBEaXN0
+cmlidXRvciBDQTAeFw0xMjEwMjcwNzQ4MzNaFw0yMjEwMjUwNzQ4MzNaMIGUMQswCQYDVQQGEwJL
+UjEOMAwGA1UECAwFU3V3b24xDjAMBgNVBAcMBVN1d29uMRYwFAYDVQQKDA1UaXplbiBUZXN0IENB
+MSIwIAYDVQQLDBlUaXplbiBEaXN0cmlidXRvciBUZXN0IENBMSkwJwYDVQQDDCBUaXplbiBQYXJ0
+bmVyIERpc3RyaWJ1dG9yIFNpZ25lcjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAy9mg2x4B
+zxlK3LJL81GsLq/pJfK1evdCKG/IOBpdoRO0rLhYnsL5+KvToPFa5g9GTZo32LikpW1NZ7++3EHE
+fnO2IGLUau4kquvhmz1LNg5xBTx7IbucmwLMRGo1BPGdsAQQLyXeQKJ5PCERmVg4MIoiL2zT/JsL
+sZ9UPT6GEB8CAwEAATANBgkqhkiG9w0BAQUFAAOBgQAw5xPBFR1XKuZ8QpsCtSE0zXVHvwIa+Ha4
+YBdRtGwEoZmiKGZV/wAhPRdmR0kISkTz20kIGz/ZwRZCVGhsr5hkkpFknYlKeKkEJ/tJfZl4D7ec
+GFAnynOzlWZqSIPz+yxX8ah9E6lTv4Vs9DhNb08nxVvxLqlpyVdk9RUsCx/yIA==
+</X509Certificate>
+<X509Certificate>
+MIICtTCCAh6gAwIBAgIJAKORBcIiXygIMA0GCSqGSIb3DQEBBQUAMIGVMQswCQYDVQQGEwJLUjEO
+MAwGA1UECAwFU3V3b24xDjAMBgNVBAcMBVN1d29uMRYwFAYDVQQKDA1UaXplbiBUZXN0IENBMSIw
+IAYDVQQLDBlUaXplbiBEaXN0cmlidXRvciBUZXN0IENBMSowKAYDVQQDDCFUaXplbiBQYXJ0bmVy
+IERpc3RyaWJ1dG9yIFJvb3QgQ0EwHhcNMTIxMDI3MDc0NTIwWhcNMjIxMDI1MDc0NTIwWjCBkDEL
+MAkGA1UEBhMCS1IxDjAMBgNVBAgMBVN1d29uMQ4wDAYDVQQHDAVTdXdvbjEWMBQGA1UECgwNVGl6
+ZW4gVGVzdCBDQTEiMCAGA1UECwwZVGl6ZW4gRGlzdHJpYnV0b3IgVGVzdCBDQTElMCMGA1UEAwwc
+VGl6ZW4gUGFydG5lciBEaXN0cmlidXRvciBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA
+2ZQrdEowjqxUmB8FX8ej19VKY6jGHKNIRE5wrhBkuZ1b0FLRPiN3/Cl9wMkCnyJui4QhC28g1aBg
+w/JnaObcDqW1NgFVH3006+gZvCTDlw1nIEjvZa6P+uWOOi05xPPAE0feKPkO1POnOjnapfkkEVNU
+8TXsLbLYBylWT8rxZC8CAwEAAaMQMA4wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQBJ
+yJ7p6qs0JI+1iKOk/sYWVP6dMueY72qOc/wVj5c3ejOlgJNNXDMAQ14QcRRexffc68ipTwybU/3m
+tcNwydzKJe+GFa4b2zyKOvOgrfs4MKSR0T9XEPmTKeR+NDT2CbA6/kQoRYm0fSORzD2UXJzNZWe/
+WjwSA66hv4q+0QZQFQ==
+</X509Certificate>
+</X509Data>
+</KeyInfo>
+<Object Id="prop"><SignatureProperties xmlns:dsp="http://www.w3.org/2009/xmldsig-properties"><SignatureProperty Id="profile" Target="#DistributorSignature"><dsp:Profile URI="http://www.w3.org/ns/widgets-digsig#profile"></dsp:Profile></SignatureProperty><SignatureProperty Id="role" Target="#DistributorSignature"><dsp:Role URI="http://www.w3.org/ns/widgets-digsig#role-distributor"></dsp:Role></SignatureProperty><SignatureProperty Id="identifier" Target="#DistributorSignature"><dsp:Identifier></dsp:Identifier></SignatureProperty></SignatureProperties></Object>
+</Signature>
\ No newline at end of file
diff --git a/webWidgetTCT_device/DeviceAPI/.tproject b/webWidgetTCT_device/DeviceAPI/.tproject
new file mode 100755 (executable)
index 0000000..de5a150
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<tproject xmlns="http://www.tizen.org/tproject">
+    <platforms>
+        <platform>
+            <name>wearable-3.0</name>
+        </platform>
+    </platforms>
+    <package>
+        <blacklist/>
+        <resFallback autoGen="true"/>
+    </package>
+</tproject>
diff --git a/webWidgetTCT_device/DeviceAPI/DeviceAPI.wgt b/webWidgetTCT_device/DeviceAPI/DeviceAPI.wgt
new file mode 100755 (executable)
index 0000000..9633b90
Binary files /dev/null and b/webWidgetTCT_device/DeviceAPI/DeviceAPI.wgt differ
diff --git a/webWidgetTCT_device/DeviceAPI/config.xml b/webWidgetTCT_device/DeviceAPI/config.xml
new file mode 100755 (executable)
index 0000000..0dc4096
--- /dev/null
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<widget xmlns="http://www.w3.org/ns/widgets" xmlns:tizen="http://tizen.org/ns/widgets" id="http://yourdomain/DeviceAPI" version="1.0.0" viewmodes="maximized">
+    <tizen:app-widget id="Qny4t67cv7.DeviceAPI.f02" primary="true">
+        <tizen:widget-label>f02</tizen:widget-label>
+        <tizen:widget-content src="widget/f02/index.html">
+            <tizen:widget-size preview="icon.png">2x2</tizen:widget-size>
+        </tizen:widget-content>
+        <tizen:widget-metadata key="testKey" value="testValue"/>
+    </tizen:app-widget>
+    <tizen:app-widget id="Qny4t67cv7.DeviceAPI.f01" primary="false">
+        <tizen:widget-label>f01</tizen:widget-label>
+        <tizen:widget-content src="widget/f01/index.html">
+            <tizen:widget-size preview="icon.png">2x2</tizen:widget-size>
+        </tizen:widget-content>
+    </tizen:app-widget>
+    <tizen:app-widget id="Qny4t67cv7.DeviceAPI.f03" primary="false">
+        <tizen:widget-label>f03</tizen:widget-label>
+        <tizen:widget-content src="widget/f03/index.html">
+            <tizen:widget-size preview="icon.png">2x2</tizen:widget-size>
+        </tizen:widget-content>
+    </tizen:app-widget>
+    <tizen:application id="Qny4t67cv7.DeviceAPI" package="Qny4t67cv7" required_version="3.0"/>
+    <content src="index.html"/>
+    <feature name="http://tizen.org/feature/screen.size.all"/>
+    <feature name="http://tizen.org/feature/sensor.photometer"/>
+    <feature name="http://tizen.org/feature/sensor.magnetometer"/>
+    <feature name="http://tizen.org/feature/sensor.barometer"/>
+    <feature name="http://tizen.org/feature/sensor.proximity"/>
+    <feature name="http://tizen.org/feature/sensor.ultraviolet"/>
+    <feature name="http://tizen.org/feature/sensor.heart_rate_monitor"/>
+    <feature name="http://tizen.org/feature/battery"/>
+    <feature name="http://tizen.org/feature/screen"/>
+    <feature name="http://tizen.org/feature/network.wifi"/>
+    <feature name="http://tizen.org/feature/network.telephony"/>
+    <feature name="http://tizen.org/feature/network.bluetooth"/>
+    <feature name="http://tizen.org/feature/screen.size.all"/>
+    <icon src="icon.png"/>
+    <name>DeviceAPI</name>
+    <tizen:privilege name="http://tizen.org/privilege/application.launch"/>
+    <tizen:privilege name="http://tizen.org/privilege/application.info"/>
+    <tizen:privilege name="http://tizen.org/privilege/appmanager.certificate"/>
+    <tizen:privilege name="http://tizen.org/privilege/appmanager.kill"/>
+    <tizen:privilege name="http://tizen.org/privilege/filesystem.read"/>
+    <tizen:privilege name="http://tizen.org/privilege/filesystem.write"/>
+    <tizen:privilege name="http://tizen.org/privilege/healthinfo"/>
+    <tizen:privilege name="http://tizen.org/privilege/system"/>
+    <tizen:privilege name="http://tizen.org/privilege/telephony"/>
+    <tizen:privilege name="http://tizen.org/privilege/widget.viewer"/>
+    <tizen:profile name="wearable"/>
+</widget>
diff --git a/webWidgetTCT_device/DeviceAPI/css/style.css b/webWidgetTCT_device/DeviceAPI/css/style.css
new file mode 100755 (executable)
index 0000000..3821d78
--- /dev/null
@@ -0,0 +1,24 @@
+html,
+body {
+    width: 100%;
+    height: 100%;
+    margin: 0 auto;
+    padding: 0;
+    background-color: #222222;
+    color: #ffffff;
+}
+.page {
+    width: 100%;
+    height: 100%;
+    display: table;
+}
+.contents {
+    display: table-cell;
+    vertical-align: middle;
+    text-align: center;
+    -webkit-tap-highlight-color: transparent;
+}
+#content-text {
+    font-weight: bold;
+    font-size: 5em;
+}
\ No newline at end of file
diff --git a/webWidgetTCT_device/DeviceAPI/icon.png b/webWidgetTCT_device/DeviceAPI/icon.png
new file mode 100755 (executable)
index 0000000..1f02568
Binary files /dev/null and b/webWidgetTCT_device/DeviceAPI/icon.png differ
diff --git a/webWidgetTCT_device/DeviceAPI/index.html b/webWidgetTCT_device/DeviceAPI/index.html
new file mode 100755 (executable)
index 0000000..5be3c97
--- /dev/null
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+    <meta charset="utf-8" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
+    <meta name="description" content="Tizen Wearable Web Basic Template" />
+
+    <title>Tizen Wearable Web Basic Application</title>
+
+    <link rel="stylesheet" type="text/css" href="css/style.css" />
+    <script src="js/main.js"></script>
+</head>
+
+<body>
+    <div id="main" class="page">
+        <div class="contents">
+            <span id="content-text">Basic</span>
+        </div>
+    </div>
+</body>
+
+</html>
diff --git a/webWidgetTCT_device/DeviceAPI/js/main.js b/webWidgetTCT_device/DeviceAPI/js/main.js
new file mode 100755 (executable)
index 0000000..4a98eea
--- /dev/null
@@ -0,0 +1,54 @@
+window.onload = function() {
+    // TODO:: Do your initialization job
+
+    // add eventListener for tizenhwkey
+    document.addEventListener('tizenhwkey', function(e) {
+        if (e.keyName === "back") {
+            try {
+                tizen.application.getCurrentApplication().exit();
+            } catch (ignore) {}
+        }
+    });
+
+    // Sample code
+    var mainPage = document.querySelector('#main');
+    var instance;
+    var successCallback = function(instances) {
+        instance = instances[0];
+    };
+    var myWidget;
+    try
+       {
+       myWidget = tizen.widgetservice.getWidget('Qny4t67cv7.DeviceAPI.f02');
+       }
+    catch (error)
+       {
+       console.log("[youngj] Error: " + error.message);
+       }
+    
+    myWidget.getInstances(successCallback);
+    console.log("[youngj] getinstance");
+       
+    mainPage.addEventListener("click", function() {
+       console.log("main clicked");
+        var contentText = document.querySelector('#content-text');
+
+        contentText.innerHTML = (contentText.innerHTML === "Basic") ? "Tizen" : "Basic";
+               
+        var data =
+       {
+          data1: 'test1',
+          data2: 'test2'
+       };
+
+       try
+       {
+               instance.sendContent(data, true);
+          console.log("[youngj]Data has been successfully sent");
+       }
+       catch (error)
+       {
+          console.log("[youngj] Error: " + error.message);
+       }
+    });
+};
diff --git a/webWidgetTCT_device/DeviceAPI/widget/f01/css/style.css b/webWidgetTCT_device/DeviceAPI/widget/f01/css/style.css
new file mode 100755 (executable)
index 0000000..0e9859c
--- /dev/null
@@ -0,0 +1,17 @@
+body {
+    margin: 0;
+}
+.main-container {
+    margin: 0;
+    padding: 0;
+    width: 360px;
+    height: 360px;
+    background-color: black;
+}
+#xhr-result{
+    text-align: center;
+    width: 100%;
+    height: 50%;
+    font-size: 80px;
+    color: white;
+}
diff --git a/webWidgetTCT_device/DeviceAPI/widget/f01/icon.png b/webWidgetTCT_device/DeviceAPI/widget/f01/icon.png
new file mode 100755 (executable)
index 0000000..1f02568
Binary files /dev/null and b/webWidgetTCT_device/DeviceAPI/widget/f01/icon.png differ
diff --git a/webWidgetTCT_device/DeviceAPI/widget/f01/index.html b/webWidgetTCT_device/DeviceAPI/widget/f01/index.html
new file mode 100755 (executable)
index 0000000..d226047
--- /dev/null
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="UTF-8">
+  </head>
+  <body>
+  <div style="text-align:center; font-size:20px"> f01 </div>
+       <script>
+       </script>
+  </body>
+</html>
+
diff --git a/webWidgetTCT_device/DeviceAPI/widget/f01/js/main.js b/webWidgetTCT_device/DeviceAPI/widget/f01/js/main.js
new file mode 100755 (executable)
index 0000000..2ad4738
--- /dev/null
@@ -0,0 +1,27 @@
+(function(){
+    function getDataUsingXHR() {
+        return new Promise(function(resolve, reject) {
+            var xhr = new XMLHttpRequest();
+            var url = "resources/data.json";
+
+            xhr.onreadystatechange = function() {
+                if (xhr.readyState == 4 && xhr.status == 200) {
+                    resolve(JSON.parse(xhr.responseText));
+                }
+            };
+            xhr.open("GET", url);
+            //xhr.send();
+        });
+    }
+
+    var xhrResult = document.getElementById('xhr-result');
+
+    function checkXHR() {
+        getDataUsingXHR().then(function(data){
+            console.log(data);
+            xhrResult.textContent = data.test[0].value;
+        });
+    }
+
+    checkXHR();
+})();
diff --git a/webWidgetTCT_device/DeviceAPI/widget/f01/js/promise.min.js b/webWidgetTCT_device/DeviceAPI/widget/f01/js/promise.min.js
new file mode 100755 (executable)
index 0000000..398916c
--- /dev/null
@@ -0,0 +1 @@
+!function(e){function t(){}function n(e,t){return function(){e.apply(t,arguments)}}function o(e){if("object"!=typeof this)throw new TypeError("Promises must be constructed via new");if("function"!=typeof e)throw new TypeError("not a function");this._state=0,this._handled=!1,this._value=void 0,this._deferreds=[],s(e,this)}function i(e,t){for(;3===e._state;)e=e._value;return 0===e._state?void e._deferreds.push(t):(e._handled=!0,void a(function(){var n=1===e._state?t.onFulfilled:t.onRejected;if(null===n)return void(1===e._state?r:f)(t.promise,e._value);var o;try{o=n(e._value)}catch(i){return void f(t.promise,i)}r(t.promise,o)}))}function r(e,t){try{if(t===e)throw new TypeError("A promise cannot be resolved with itself.");if(t&&("object"==typeof t||"function"==typeof t)){var i=t.then;if(t instanceof o)return e._state=3,e._value=t,void u(e);if("function"==typeof i)return void s(n(i,t),e)}e._state=1,e._value=t,u(e)}catch(r){f(e,r)}}function f(e,t){e._state=2,e._value=t,u(e)}function u(e){2===e._state&&0===e._deferreds.length&&setTimeout(function(){e._handled||d(e._value)},1);for(var t=0,n=e._deferreds.length;n>t;t++)i(e,e._deferreds[t]);e._deferreds=null}function c(e,t,n){this.onFulfilled="function"==typeof e?e:null,this.onRejected="function"==typeof t?t:null,this.promise=n}function s(e,t){var n=!1;try{e(function(e){n||(n=!0,r(t,e))},function(e){n||(n=!0,f(t,e))})}catch(o){if(n)return;n=!0,f(t,o)}}var l=setTimeout,a="function"==typeof setImmediate&&setImmediate||function(e){l(e,1)},d=function(e){"undefined"!=typeof console&&console&&console.warn("Possible Unhandled Promise Rejection:",e)};o.prototype["catch"]=function(e){return this.then(null,e)},o.prototype.then=function(e,n){var r=new o(t);return i(this,new c(e,n,r)),r},o.all=function(e){var t=Array.prototype.slice.call(e);return new o(function(e,n){function o(r,f){try{if(f&&("object"==typeof f||"function"==typeof f)){var u=f.then;if("function"==typeof u)return void u.call(f,function(e){o(r,e)},n)}t[r]=f,0===--i&&e(t)}catch(c){n(c)}}if(0===t.length)return e([]);for(var i=t.length,r=0;r<t.length;r++)o(r,t[r])})},o.resolve=function(e){return e&&"object"==typeof e&&e.constructor===o?e:new o(function(t){t(e)})},o.reject=function(e){return new o(function(t,n){n(e)})},o.race=function(e){return new o(function(t,n){for(var o=0,i=e.length;i>o;o++)e[o].then(t,n)})},o._setImmediateFn=function(e){a=e},o._setUnhandledRejectionFn=function(e){d=e},"undefined"!=typeof module&&module.exports?module.exports=o:e.Promise||(e.Promise=o)}(this);
diff --git a/webWidgetTCT_device/DeviceAPI/widget/f01/preview.png b/webWidgetTCT_device/DeviceAPI/widget/f01/preview.png
new file mode 100755 (executable)
index 0000000..1f02568
Binary files /dev/null and b/webWidgetTCT_device/DeviceAPI/widget/f01/preview.png differ
diff --git a/webWidgetTCT_device/DeviceAPI/widget/f01/resources/data.json b/webWidgetTCT_device/DeviceAPI/widget/f01/resources/data.json
new file mode 100755 (executable)
index 0000000..8311964
--- /dev/null
@@ -0,0 +1,8 @@
+{
+  "test": [
+    {
+      "id":1,
+      "value": "success"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/webWidgetTCT_device/DeviceAPI/widget/f01/support/path.js b/webWidgetTCT_device/DeviceAPI/widget/f01/support/path.js
new file mode 100755 (executable)
index 0000000..cfe0667
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+Copyright (c) 2012 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+* Redistributions of works must retain the original copyright notice, this list
+  of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the original copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+* Neither the name of Intel Corporation nor the names of its contributors
+  may be used to endorse or promote products derived from this work without
+  specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Authors:
+        Cao, Jun <junx.cao@intel.com>
+        Fan,Weiwei <weiwix.fan@intel.com>
+
+*/
+
+//port can not use 8000,because 8000 port is used by testkit-lite
+var otherDomain = "http://127.0.0.1:8081";
diff --git a/webWidgetTCT_device/DeviceAPI/widget/f01/support/test.html b/webWidgetTCT_device/DeviceAPI/widget/f01/support/test.html
new file mode 100755 (executable)
index 0000000..dfa5ffa
--- /dev/null
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2012 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+* Redistributions of works must retain the original copyright notice, this list
+  of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the original copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+* Neither the name of Intel Corporation nor the names of its contributors
+  may be used to endorse or promote products derived from this work without
+  specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Authors:
+         Cao, Jun <junx.cao@intel.com>
+
+-->
+
+<html>
+  <head>
+    <title>XMLHttpRequest Test: xhr2_XMLHttpRequestEventTarget_onerror_event</title>
+    <link rel="author" title="Intel" href="http://www.intel.com" />
+    <link rel="help" href="http://www.w3.org/TR/2012/WD-XMLHttpRequest-20121206/#handler-xhr-onerror" />
+    <meta name="flags" content="" />
+    <meta name="assert" content="Check if the onerror event when the request has failed" />
+  </head>
+  <body>
+    test
+  </body>
+</html>
diff --git a/webWidgetTCT_device/DeviceAPI/widget/f01/support/test.xml b/webWidgetTCT_device/DeviceAPI/widget/f01/support/test.xml
new file mode 100755 (executable)
index 0000000..8070fdd
--- /dev/null
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2012 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+* Redistributions of works must retain the original copyright notice, this list
+  of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the original copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+* Neither the name of Intel Corporation nor the names of its contributors
+  may be used to endorse or promote products derived from this work without
+  specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Authors:
+        Cao, Jun <junx.cao@intel.com>
+        Fan,Weiwei <weiwix.fan@intel.com>
+-->
+
+<res>
+ <result>ok</result>
+</res>
diff --git a/webWidgetTCT_device/DeviceAPI/widget/f01/support/test_timeout.xml b/webWidgetTCT_device/DeviceAPI/widget/f01/support/test_timeout.xml
new file mode 100755 (executable)
index 0000000..03b463d
--- /dev/null
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2012 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+* Redistributions of works must retain the original copyright notice, this list
+  of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the original copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+* Neither the name of Intel Corporation nor the names of its contributors
+  may be used to endorse or promote products derived from this work without
+  specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Authors:
+        Cao, Jun <junx.cao@intel.com>
+        Fan,Weiwei <weiwix.fan@intel.com>
+-->
+
+<res>
+ <result>okokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokok</result>
+</res>
diff --git a/webWidgetTCT_device/DeviceAPI/widget/f02/css/style.css b/webWidgetTCT_device/DeviceAPI/widget/f02/css/style.css
new file mode 100755 (executable)
index 0000000..0e9859c
--- /dev/null
@@ -0,0 +1,17 @@
+body {
+    margin: 0;
+}
+.main-container {
+    margin: 0;
+    padding: 0;
+    width: 360px;
+    height: 360px;
+    background-color: black;
+}
+#xhr-result{
+    text-align: center;
+    width: 100%;
+    height: 50%;
+    font-size: 80px;
+    color: white;
+}
diff --git a/webWidgetTCT_device/DeviceAPI/widget/f02/icon.png b/webWidgetTCT_device/DeviceAPI/widget/f02/icon.png
new file mode 100755 (executable)
index 0000000..1f02568
Binary files /dev/null and b/webWidgetTCT_device/DeviceAPI/widget/f02/icon.png differ
diff --git a/webWidgetTCT_device/DeviceAPI/widget/f02/index.html b/webWidgetTCT_device/DeviceAPI/widget/f02/index.html
new file mode 100755 (executable)
index 0000000..c4448d5
--- /dev/null
@@ -0,0 +1,140 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="UTF-8">
+  </head>
+  <body>
+    <div id="backgroundtest1" style="background: rgb(255, 0, 0);width: 20px;height: 20px;" ></div>
+    <div id="backgroundtest2" style="background-color: #000;width: 20px;height: 20px;" ></div>
+    <div id="backgroundtest3" style="background-color: red;width: 20px;height: 20px;" ></div>
+    <div id="backgroundtest4" style="background-image: url(icon.png);width: 20px;height: 20px;" ></div>
+    <div id="backgroundtest5" style="background-image: none;width: 20px;height: 20px;" ></div>
+    <div id="backgroundtest6" style="background-image: url(icon.png);background-repeat:repeat-x;width: 20px;height: 20px;" ></div>
+    <div id="backgroundtest7" style="background-image: url(icon.png);background-repeat:repeat;width: 20px;height: 20px;" ></div>
+    <div id="backgroundtest8" style="background-image: url(icon.png);background-repeat:repeat-y;width: 20px;height: 20px;" ></div>
+    <div id="backgroundtest9" style="background-image: url(icon.png);background-repeat:no-repeat;width: 20px;height: 20px;" ></div>
+    <div id="backgroundtest10" style="background-image: url(icon.png);background-size:100% 10px;width: 20px;height: 20px;" ></div>
+    <div id="backgroundtest11" style="background-image: url(icon.png);background-size:50%;background-repeat:no-repeat;width: 20px;height: 20px;" ></div>
+    <div id="backgroundtest12" style="background-image: none;background-size:50%;background-repeat:no-repeat;width: 20px;height: 20px;" ></div>
+    <div id="backgroundtest13" style="background-image: none;background-size:50%;background-repeat:repeat;width: 20px;height: 20px;" ></div>
+    <div id="backgroundtest14" style="background-image: url(icon.png);background-size:50%;background-repeat:repeat;width: 20px;height: 20px;" ></div>
+    <div id="backgroundtest15" style="background-image: url(icon.png);background-size:50%;background-repeat:repeat-y;width: 20px;height: 20px;" ></div>
+    <div id="backgroundtest16" style="background-image: none;background-size:50%;background-repeat:repeat-y;width: 20px;height: 20px;" ></div>
+    <div id="backgroundtest17" style="background-image: url(icon.png);background-size:50%;background-repeat:repeat-x;width: 20px;height: 20px;" ></div>
+    <div id="backgroundtest18" style="background-image: none;background-size:50%;background-repeat:repeat-x;width: 20px;height: 20px;" ></div>
+    <div id="backgroundtest19" style="background-image: none;background-size:50px 70px;background-repeat:no-repeat;width: 20px;height: 20px;" ></div>
+    <div id="backgroundtest20" style="background-image: url(icon.png);background-size:50px 70px;background-repeat:no-repeat;width: 20px;height: 20px;" ></div>
+    <div id="backgroundtest21" style="background-image: none;background-size:50px 70px;background-repeat:repeat;width: 20px;height: 20px;" ></div>
+    <div id="backgroundtest22" style="background-image: url(icon.png);background-size:50px 70px;background-repeat:repeat;width: 20px;height: 20px;" ></div>
+    <div id="backgroundtest23" style="background-image: none;background-size:50px 70px;background-repeat:repeat-x;width: 20px;height: 20px;" ></div>
+    <div id="backgroundtest24" style="background-image: url(icon.png);background-size:50px 70px;background-repeat:repeat-x;width: 20px;height: 20px;" ></div>
+    <div id="backgroundtest25" style="background-image: none;background-size:50px 70px;background-repeat:repeat-y;width: 20px;height: 20px;" ></div>
+    <div id="backgroundtest26" style="background-image: url(icon.png);background-size:50px 70px;background-repeat:repeat-y;width: 20px;height: 20px;" ></div>
+    <div id="backgroundtest27" style="background-image: none;background-size: contain;background-repeat: no-repeat;width: 20px;height: 20px;" ></div>
+    <div id="backgroundtest28" style="background-image: url(icon.png);background-size: contain;background-repeat: no-repeat;width: 20px;height: 20px;" ></div>
+    <div id="backgroundtest29" style="background-image: none;background-size: contain;background-repeat: repeat;width: 20px;height: 20px;" ></div>
+    <div id="backgroundtest30" style="background-image: url(icon.png);background-size: contain;background-repeat: repeat;width: 20px;height: 20px;" ></div>
+    <div id="backgroundtest31" style="background-image: none;background-size: contain;background-repeat: repeat-y;width: 20px;height: 20px;" ></div>
+    <div id="backgroundtest32" style="background-image: url(icon.png);background-size: contain;background-repeat: repeat-y;width: 20px;height: 20px;" ></div>
+    <div id="backgroundtest33" style="background-image: none;background-size: cover;background-repeat: repeat-y;width: 20px;height: 20px;" ></div>
+    <div id="backgroundtest34" style="background-image: url(icon.png);background-size: cover;background-repeat: repeat-y;width: 20px;height: 20px;" ></div>
+    <div id="backgroundtest35" style="background-image: none;background-size: cover;background-repeat: repeat-x;width: 20px;height: 20px;" ></div>
+    <div id="backgroundtest36" style="background-image: url(icon.png);background-size: cover;background-repeat: repeat-x;width: 20px;height: 20px;" ></div>
+    <div id="backgroundtest37" style="background-image: none;background-size: cover;background-repeat: no-repeat;width: 20px;height: 20px;" ></div>
+    <div id="backgroundtest38" style="background-image: url(icon.png);background-size: cover;background-repeat: no-repeat;width: 20px;height: 20px;" ></div>
+    <div id="paddingtest1" style="border: 0; padding: 1px 2px 3px 4px;width: 20px;height: 20px;" ></div>
+    <div id="paddingtest2" style="border: 0; padding-bottom: 1px; padding-left: 2px; padding-right: 3px; padding-top: 4px;width: 20px;height: 20px;" ></div>
+    <div id="paddingtest3" style="border: 0; padding-bottom: 10%; padding-left: 20%; padding-right: 30%; padding-top: 40%;width: 20px;height: 20px;" ></div>
+    <div id="displaytest1" style="display: block; visibility: visible; width: 20px;height: 20px;" ></div>
+    <div id="displaytest2" style="display: inline; visibility: hidden; width: 20px;height: 20px;" ></div>
+    <div id="positiontest1" style="position: static; z-index: auto; width: 20px;height: 30px;" ></div>
+    <div id="positiontest2" style="position: relative; top: 1px; right: 2px; width: 20px;height: 20px;" ></div>
+    <div id="positiontest3" style="position: relative; bottom: 3px; left: 4px; width: 20px;height: 20px;" ></div>
+    <div id="positiontest4" style="direction: ltr; vertical-align: baseline; overflow: visible; width: 20px;" ></div>
+    <div id="positiontest5" style="line-height: 2px; width: 20px;" ></div>
+    <div id="margintest1" style="border: 0; margin: 1px 2px 3px 4px;width: 20px;height: 20px;" ></div>
+    <div id="margintest2" style="border: 0; margin-bottom: 1px; margin-left: 2px; margin-right: 3px; margin-top: 4px;width: 20px;height: 20px;" ></div>
+    <div id="fonttest1" style="font-style: oblique; font-weight: normal; font-size: 16px;" >this is test</div>
+    <div id="colortest1" style="color: red; opacity: 0.3; width: 20px;height: 20px;" ></div>
+    <div id="texttest1" style="text-align: left; text-decoration: none; width: 20px;height: 20px;" >this is</div>
+    <div id="transformtest1" style="transform: none; transform-origin: center; width: 20px;height: 20px;" >this is a text</div>
+    <div id="bordertest1" style="border-bottom-style: solid; width: 20px; height: 20px;" ></div> 
+    <div id="bordertest2" style="border-bottom-style: none; width: 20px; height: 20px;" ></div>
+    <div id="bordertest3" style="border: 8px solid #000; width: 20px; height: 20px;" ></div>
+    <div id="bordertest4" style="border: 8px solid #000; border-top-color: rgb(85,85,85); width: 20px; height: 20px;" ></div>
+    <div id="bordertest5" style="border: 8px solid #000; border-right-color: rgb(85,85,85); width: 20px; height: 20px;" ></div>
+    <div id="bordertest6" style="border: 8px solid #000; border-bottom-color: rgb(85,85,85); width: 20px; height: 20px;" ></div>
+    <div id="bordertest7" style="border: 8px solid #000; border-left-color: rgb(85,85,85); width: 20px; height: 20px;" ></div>
+    <div id="bordertest8" style="border: 8px solid #000; border-tyle: solid; width: 20px; height: 20px;" ></div>
+    <div id="bordertest9" style="border: 8px solid #000; border-top-tyle: solid; width: 20px; height: 20px;" ></div>
+    <div id="bordertest10" style="border: 8px solid black; border-top-tyle: solid; width: 20px; height: 20px;" ></div>
+    <div id="bordertest11" style="border: 8px none black; border-top-tyle: none; width: 20px; height: 20px;" ></div>
+    <div id="bordertest12" style="border: 8px solid black; border-right-tyle: solid; width: 20px; height: 20px;" ></div>
+    <div id="bordertest13" style="border: 8px solid black; border-right-tyle: solid; width: 20px; height: 20px;" ></div>
+    <div id="bordertest14" style="border: 8px none black; border-right-tyle: none; width: 20px; height: 20px;" ></div>
+    <div id="bordertest15" style="border: 8px solid black; border-left-tyle: solid; width: 20px; height: 20px;" ></div>
+    <div id="bordertest16" style="border: 8px solid black; border-left-tyle: solid; width: 20px; height: 20px;" ></div>
+    <div id="bordertest17" style="border: 8px none black; border-left-tyle: none; width: 20px; height: 20px;" ></div>
+    <div id="bordertest18" style="border: 50px none black; border-left-tyle: none; width: 20px; height: 20px;" ></div>
+    <div id="bordertest19" style="border: 50px none black; border-left-tyle: none; width: 20px; height: 20px;" ></div>
+    <div id="bordertest20" style="border-top: 10px none black; border-right: 20px none red; border-bottom: 30px none blue; border-left: 40px none green; width: 50px; height: 50px;" ></div>
+    <div id="bordertest21" style="border-right-width: 2px; border-bottom-width: 3px; border-left-width: 4px; width: 20px; height: 20px;" ></div>
+    <div id="bordertest22" style="border-image-source: url(icon.png); border-image-slice: 1; border-image-width: 2px; width: 20px; height: 20px;" ></div>    
+       <script>
+        // XXX: TCT should be modified
+        var flag = 0;
+        var full_content = "";
+        window.run = window.load = function(path) {
+            var xhr = new XMLHttpRequest();
+            xhr.open("GET", path, false);
+            xhr.send(null);
+            var geval = eval;
+            return geval(xhr.responseText);
+        }
+        window.append = function(path, content) {
+        
+        path = path.replace('/tmp/',"");
+
+        
+        openStreamWSuccess = function (fs) {
+            fs.write(full_content);
+            fs.close();
+            full_content = "";
+        };
+        openStreamError = function (error) {
+            console.log("openStream() error callback invoked: name: " + error.name + ", msg: " + error.message);
+        };
+
+        resolveError = function (error) {
+            console.log("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+        };     
+       
+       resolveSuccess = function (dir) {
+       full_content = full_content + content;
+       if (flag == 0){
+       f = dir.createFile(path);
+       flag = 1;
+       f.openStream("a", openStreamWSuccess, openStreamError, "UTF-8");
+       }
+       else{        
+        f.openStream("a", openStreamWSuccess, openStreamError, "UTF-8");
+        }
+        };
+               
+               tizen.filesystem.resolve("/tmp", resolveSuccess, resolveError, "rw");
+               
+               
+               }
+        window.read = function(path) {
+            var xhr = new XMLHttpRequest();
+            xhr.open("GET", path, false);
+            xhr.send(null);
+            return xhr.responseText;
+        }
+        window.print = console.log;
+
+        load("/home/owner/share/wrt-service-tct/index.js");
+       </script>
+  </body>
+</html>
+
diff --git a/webWidgetTCT_device/DeviceAPI/widget/f02/js/main.js b/webWidgetTCT_device/DeviceAPI/widget/f02/js/main.js
new file mode 100755 (executable)
index 0000000..2ad4738
--- /dev/null
@@ -0,0 +1,27 @@
+(function(){
+    function getDataUsingXHR() {
+        return new Promise(function(resolve, reject) {
+            var xhr = new XMLHttpRequest();
+            var url = "resources/data.json";
+
+            xhr.onreadystatechange = function() {
+                if (xhr.readyState == 4 && xhr.status == 200) {
+                    resolve(JSON.parse(xhr.responseText));
+                }
+            };
+            xhr.open("GET", url);
+            //xhr.send();
+        });
+    }
+
+    var xhrResult = document.getElementById('xhr-result');
+
+    function checkXHR() {
+        getDataUsingXHR().then(function(data){
+            console.log(data);
+            xhrResult.textContent = data.test[0].value;
+        });
+    }
+
+    checkXHR();
+})();
diff --git a/webWidgetTCT_device/DeviceAPI/widget/f02/js/promise.min.js b/webWidgetTCT_device/DeviceAPI/widget/f02/js/promise.min.js
new file mode 100755 (executable)
index 0000000..398916c
--- /dev/null
@@ -0,0 +1 @@
+!function(e){function t(){}function n(e,t){return function(){e.apply(t,arguments)}}function o(e){if("object"!=typeof this)throw new TypeError("Promises must be constructed via new");if("function"!=typeof e)throw new TypeError("not a function");this._state=0,this._handled=!1,this._value=void 0,this._deferreds=[],s(e,this)}function i(e,t){for(;3===e._state;)e=e._value;return 0===e._state?void e._deferreds.push(t):(e._handled=!0,void a(function(){var n=1===e._state?t.onFulfilled:t.onRejected;if(null===n)return void(1===e._state?r:f)(t.promise,e._value);var o;try{o=n(e._value)}catch(i){return void f(t.promise,i)}r(t.promise,o)}))}function r(e,t){try{if(t===e)throw new TypeError("A promise cannot be resolved with itself.");if(t&&("object"==typeof t||"function"==typeof t)){var i=t.then;if(t instanceof o)return e._state=3,e._value=t,void u(e);if("function"==typeof i)return void s(n(i,t),e)}e._state=1,e._value=t,u(e)}catch(r){f(e,r)}}function f(e,t){e._state=2,e._value=t,u(e)}function u(e){2===e._state&&0===e._deferreds.length&&setTimeout(function(){e._handled||d(e._value)},1);for(var t=0,n=e._deferreds.length;n>t;t++)i(e,e._deferreds[t]);e._deferreds=null}function c(e,t,n){this.onFulfilled="function"==typeof e?e:null,this.onRejected="function"==typeof t?t:null,this.promise=n}function s(e,t){var n=!1;try{e(function(e){n||(n=!0,r(t,e))},function(e){n||(n=!0,f(t,e))})}catch(o){if(n)return;n=!0,f(t,o)}}var l=setTimeout,a="function"==typeof setImmediate&&setImmediate||function(e){l(e,1)},d=function(e){"undefined"!=typeof console&&console&&console.warn("Possible Unhandled Promise Rejection:",e)};o.prototype["catch"]=function(e){return this.then(null,e)},o.prototype.then=function(e,n){var r=new o(t);return i(this,new c(e,n,r)),r},o.all=function(e){var t=Array.prototype.slice.call(e);return new o(function(e,n){function o(r,f){try{if(f&&("object"==typeof f||"function"==typeof f)){var u=f.then;if("function"==typeof u)return void u.call(f,function(e){o(r,e)},n)}t[r]=f,0===--i&&e(t)}catch(c){n(c)}}if(0===t.length)return e([]);for(var i=t.length,r=0;r<t.length;r++)o(r,t[r])})},o.resolve=function(e){return e&&"object"==typeof e&&e.constructor===o?e:new o(function(t){t(e)})},o.reject=function(e){return new o(function(t,n){n(e)})},o.race=function(e){return new o(function(t,n){for(var o=0,i=e.length;i>o;o++)e[o].then(t,n)})},o._setImmediateFn=function(e){a=e},o._setUnhandledRejectionFn=function(e){d=e},"undefined"!=typeof module&&module.exports?module.exports=o:e.Promise||(e.Promise=o)}(this);
diff --git a/webWidgetTCT_device/DeviceAPI/widget/f02/preview.png b/webWidgetTCT_device/DeviceAPI/widget/f02/preview.png
new file mode 100755 (executable)
index 0000000..1f02568
Binary files /dev/null and b/webWidgetTCT_device/DeviceAPI/widget/f02/preview.png differ
diff --git a/webWidgetTCT_device/DeviceAPI/widget/f02/resources/data.json b/webWidgetTCT_device/DeviceAPI/widget/f02/resources/data.json
new file mode 100755 (executable)
index 0000000..8311964
--- /dev/null
@@ -0,0 +1,8 @@
+{
+  "test": [
+    {
+      "id":1,
+      "value": "success"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/webWidgetTCT_device/DeviceAPI/widget/f02/support/path.js b/webWidgetTCT_device/DeviceAPI/widget/f02/support/path.js
new file mode 100755 (executable)
index 0000000..cfe0667
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+Copyright (c) 2012 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+* Redistributions of works must retain the original copyright notice, this list
+  of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the original copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+* Neither the name of Intel Corporation nor the names of its contributors
+  may be used to endorse or promote products derived from this work without
+  specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Authors:
+        Cao, Jun <junx.cao@intel.com>
+        Fan,Weiwei <weiwix.fan@intel.com>
+
+*/
+
+//port can not use 8000,because 8000 port is used by testkit-lite
+var otherDomain = "http://127.0.0.1:8081";
diff --git a/webWidgetTCT_device/DeviceAPI/widget/f02/support/test.html b/webWidgetTCT_device/DeviceAPI/widget/f02/support/test.html
new file mode 100755 (executable)
index 0000000..dfa5ffa
--- /dev/null
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2012 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+* Redistributions of works must retain the original copyright notice, this list
+  of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the original copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+* Neither the name of Intel Corporation nor the names of its contributors
+  may be used to endorse or promote products derived from this work without
+  specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Authors:
+         Cao, Jun <junx.cao@intel.com>
+
+-->
+
+<html>
+  <head>
+    <title>XMLHttpRequest Test: xhr2_XMLHttpRequestEventTarget_onerror_event</title>
+    <link rel="author" title="Intel" href="http://www.intel.com" />
+    <link rel="help" href="http://www.w3.org/TR/2012/WD-XMLHttpRequest-20121206/#handler-xhr-onerror" />
+    <meta name="flags" content="" />
+    <meta name="assert" content="Check if the onerror event when the request has failed" />
+  </head>
+  <body>
+    test
+  </body>
+</html>
diff --git a/webWidgetTCT_device/DeviceAPI/widget/f02/support/test.xml b/webWidgetTCT_device/DeviceAPI/widget/f02/support/test.xml
new file mode 100755 (executable)
index 0000000..8070fdd
--- /dev/null
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2012 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+* Redistributions of works must retain the original copyright notice, this list
+  of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the original copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+* Neither the name of Intel Corporation nor the names of its contributors
+  may be used to endorse or promote products derived from this work without
+  specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Authors:
+        Cao, Jun <junx.cao@intel.com>
+        Fan,Weiwei <weiwix.fan@intel.com>
+-->
+
+<res>
+ <result>ok</result>
+</res>
diff --git a/webWidgetTCT_device/DeviceAPI/widget/f02/support/test_timeout.xml b/webWidgetTCT_device/DeviceAPI/widget/f02/support/test_timeout.xml
new file mode 100755 (executable)
index 0000000..03b463d
--- /dev/null
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2012 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+* Redistributions of works must retain the original copyright notice, this list
+  of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the original copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+* Neither the name of Intel Corporation nor the names of its contributors
+  may be used to endorse or promote products derived from this work without
+  specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Authors:
+        Cao, Jun <junx.cao@intel.com>
+        Fan,Weiwei <weiwix.fan@intel.com>
+-->
+
+<res>
+ <result>okokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokok</result>
+</res>
diff --git a/webWidgetTCT_device/DeviceAPI/widget/f03/css/style.css b/webWidgetTCT_device/DeviceAPI/widget/f03/css/style.css
new file mode 100755 (executable)
index 0000000..0e9859c
--- /dev/null
@@ -0,0 +1,17 @@
+body {
+    margin: 0;
+}
+.main-container {
+    margin: 0;
+    padding: 0;
+    width: 360px;
+    height: 360px;
+    background-color: black;
+}
+#xhr-result{
+    text-align: center;
+    width: 100%;
+    height: 50%;
+    font-size: 80px;
+    color: white;
+}
diff --git a/webWidgetTCT_device/DeviceAPI/widget/f03/icon.png b/webWidgetTCT_device/DeviceAPI/widget/f03/icon.png
new file mode 100755 (executable)
index 0000000..1f02568
Binary files /dev/null and b/webWidgetTCT_device/DeviceAPI/widget/f03/icon.png differ
diff --git a/webWidgetTCT_device/DeviceAPI/widget/f03/index.html b/webWidgetTCT_device/DeviceAPI/widget/f03/index.html
new file mode 100755 (executable)
index 0000000..30f9cf6
--- /dev/null
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="UTF-8">
+  </head>
+  <body>
+  <div style="text-align:center; font-size:20px"> f03 </div>
+       <script>
+       </script>
+  </body>
+</html>
+
diff --git a/webWidgetTCT_device/DeviceAPI/widget/f03/js/main.js b/webWidgetTCT_device/DeviceAPI/widget/f03/js/main.js
new file mode 100755 (executable)
index 0000000..2ad4738
--- /dev/null
@@ -0,0 +1,27 @@
+(function(){
+    function getDataUsingXHR() {
+        return new Promise(function(resolve, reject) {
+            var xhr = new XMLHttpRequest();
+            var url = "resources/data.json";
+
+            xhr.onreadystatechange = function() {
+                if (xhr.readyState == 4 && xhr.status == 200) {
+                    resolve(JSON.parse(xhr.responseText));
+                }
+            };
+            xhr.open("GET", url);
+            //xhr.send();
+        });
+    }
+
+    var xhrResult = document.getElementById('xhr-result');
+
+    function checkXHR() {
+        getDataUsingXHR().then(function(data){
+            console.log(data);
+            xhrResult.textContent = data.test[0].value;
+        });
+    }
+
+    checkXHR();
+})();
diff --git a/webWidgetTCT_device/DeviceAPI/widget/f03/js/promise.min.js b/webWidgetTCT_device/DeviceAPI/widget/f03/js/promise.min.js
new file mode 100755 (executable)
index 0000000..398916c
--- /dev/null
@@ -0,0 +1 @@
+!function(e){function t(){}function n(e,t){return function(){e.apply(t,arguments)}}function o(e){if("object"!=typeof this)throw new TypeError("Promises must be constructed via new");if("function"!=typeof e)throw new TypeError("not a function");this._state=0,this._handled=!1,this._value=void 0,this._deferreds=[],s(e,this)}function i(e,t){for(;3===e._state;)e=e._value;return 0===e._state?void e._deferreds.push(t):(e._handled=!0,void a(function(){var n=1===e._state?t.onFulfilled:t.onRejected;if(null===n)return void(1===e._state?r:f)(t.promise,e._value);var o;try{o=n(e._value)}catch(i){return void f(t.promise,i)}r(t.promise,o)}))}function r(e,t){try{if(t===e)throw new TypeError("A promise cannot be resolved with itself.");if(t&&("object"==typeof t||"function"==typeof t)){var i=t.then;if(t instanceof o)return e._state=3,e._value=t,void u(e);if("function"==typeof i)return void s(n(i,t),e)}e._state=1,e._value=t,u(e)}catch(r){f(e,r)}}function f(e,t){e._state=2,e._value=t,u(e)}function u(e){2===e._state&&0===e._deferreds.length&&setTimeout(function(){e._handled||d(e._value)},1);for(var t=0,n=e._deferreds.length;n>t;t++)i(e,e._deferreds[t]);e._deferreds=null}function c(e,t,n){this.onFulfilled="function"==typeof e?e:null,this.onRejected="function"==typeof t?t:null,this.promise=n}function s(e,t){var n=!1;try{e(function(e){n||(n=!0,r(t,e))},function(e){n||(n=!0,f(t,e))})}catch(o){if(n)return;n=!0,f(t,o)}}var l=setTimeout,a="function"==typeof setImmediate&&setImmediate||function(e){l(e,1)},d=function(e){"undefined"!=typeof console&&console&&console.warn("Possible Unhandled Promise Rejection:",e)};o.prototype["catch"]=function(e){return this.then(null,e)},o.prototype.then=function(e,n){var r=new o(t);return i(this,new c(e,n,r)),r},o.all=function(e){var t=Array.prototype.slice.call(e);return new o(function(e,n){function o(r,f){try{if(f&&("object"==typeof f||"function"==typeof f)){var u=f.then;if("function"==typeof u)return void u.call(f,function(e){o(r,e)},n)}t[r]=f,0===--i&&e(t)}catch(c){n(c)}}if(0===t.length)return e([]);for(var i=t.length,r=0;r<t.length;r++)o(r,t[r])})},o.resolve=function(e){return e&&"object"==typeof e&&e.constructor===o?e:new o(function(t){t(e)})},o.reject=function(e){return new o(function(t,n){n(e)})},o.race=function(e){return new o(function(t,n){for(var o=0,i=e.length;i>o;o++)e[o].then(t,n)})},o._setImmediateFn=function(e){a=e},o._setUnhandledRejectionFn=function(e){d=e},"undefined"!=typeof module&&module.exports?module.exports=o:e.Promise||(e.Promise=o)}(this);
diff --git a/webWidgetTCT_device/DeviceAPI/widget/f03/preview.png b/webWidgetTCT_device/DeviceAPI/widget/f03/preview.png
new file mode 100755 (executable)
index 0000000..1f02568
Binary files /dev/null and b/webWidgetTCT_device/DeviceAPI/widget/f03/preview.png differ
diff --git a/webWidgetTCT_device/DeviceAPI/widget/f03/resources/data.json b/webWidgetTCT_device/DeviceAPI/widget/f03/resources/data.json
new file mode 100755 (executable)
index 0000000..8311964
--- /dev/null
@@ -0,0 +1,8 @@
+{
+  "test": [
+    {
+      "id":1,
+      "value": "success"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/webWidgetTCT_device/DeviceAPI/widget/f03/support/path.js b/webWidgetTCT_device/DeviceAPI/widget/f03/support/path.js
new file mode 100755 (executable)
index 0000000..cfe0667
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+Copyright (c) 2012 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+* Redistributions of works must retain the original copyright notice, this list
+  of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the original copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+* Neither the name of Intel Corporation nor the names of its contributors
+  may be used to endorse or promote products derived from this work without
+  specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Authors:
+        Cao, Jun <junx.cao@intel.com>
+        Fan,Weiwei <weiwix.fan@intel.com>
+
+*/
+
+//port can not use 8000,because 8000 port is used by testkit-lite
+var otherDomain = "http://127.0.0.1:8081";
diff --git a/webWidgetTCT_device/DeviceAPI/widget/f03/support/test.html b/webWidgetTCT_device/DeviceAPI/widget/f03/support/test.html
new file mode 100755 (executable)
index 0000000..dfa5ffa
--- /dev/null
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2012 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+* Redistributions of works must retain the original copyright notice, this list
+  of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the original copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+* Neither the name of Intel Corporation nor the names of its contributors
+  may be used to endorse or promote products derived from this work without
+  specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Authors:
+         Cao, Jun <junx.cao@intel.com>
+
+-->
+
+<html>
+  <head>
+    <title>XMLHttpRequest Test: xhr2_XMLHttpRequestEventTarget_onerror_event</title>
+    <link rel="author" title="Intel" href="http://www.intel.com" />
+    <link rel="help" href="http://www.w3.org/TR/2012/WD-XMLHttpRequest-20121206/#handler-xhr-onerror" />
+    <meta name="flags" content="" />
+    <meta name="assert" content="Check if the onerror event when the request has failed" />
+  </head>
+  <body>
+    test
+  </body>
+</html>
diff --git a/webWidgetTCT_device/DeviceAPI/widget/f03/support/test.xml b/webWidgetTCT_device/DeviceAPI/widget/f03/support/test.xml
new file mode 100755 (executable)
index 0000000..8070fdd
--- /dev/null
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2012 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+* Redistributions of works must retain the original copyright notice, this list
+  of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the original copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+* Neither the name of Intel Corporation nor the names of its contributors
+  may be used to endorse or promote products derived from this work without
+  specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Authors:
+        Cao, Jun <junx.cao@intel.com>
+        Fan,Weiwei <weiwix.fan@intel.com>
+-->
+
+<res>
+ <result>ok</result>
+</res>
diff --git a/webWidgetTCT_device/DeviceAPI/widget/f03/support/test_timeout.xml b/webWidgetTCT_device/DeviceAPI/widget/f03/support/test_timeout.xml
new file mode 100755 (executable)
index 0000000..03b463d
--- /dev/null
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2012 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+* Redistributions of works must retain the original copyright notice, this list
+  of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the original copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+* Neither the name of Intel Corporation nor the names of its contributors
+  may be used to endorse or promote products derived from this work without
+  specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Authors:
+        Cao, Jun <junx.cao@intel.com>
+        Fan,Weiwei <weiwix.fan@intel.com>
+-->
+
+<res>
+ <result>okokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokok</result>
+</res>
diff --git a/webWidgetTCT_device/LICENSE b/webWidgetTCT_device/LICENSE
new file mode 100755 (executable)
index 0000000..d645695
--- /dev/null
@@ -0,0 +1,202 @@
+
+                                 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/webWidgetTCT_device/LICENSE.BSD-2.0 b/webWidgetTCT_device/LICENSE.BSD-2.0
new file mode 100755 (executable)
index 0000000..5d7d3f3
--- /dev/null
@@ -0,0 +1,13 @@
+
+Copyright (c) 2015 Samsung Electronics Co, Ltd. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+
diff --git a/webWidgetTCT_device/README.md b/webWidgetTCT_device/README.md
new file mode 100755 (executable)
index 0000000..c31fc23
--- /dev/null
@@ -0,0 +1,28 @@
+# install\r
+$ ./tools/launcher/deploy.sh\r
+$ sdb push test/ /home/owner/share/wrt-service-tct/\r
+\r
+# install DeviceAPI.wgt\r
+$ sdb root off\r
+$ sdb install DeviceAPI.wgt\r
+\r
+# run\r
+1. Add f01 widget on home screen\r
+2. Add f02 widget on home screen\r
+\r
+- caution: manual TC test\r
+$ sdb dlog | grep -w StarFish\r
+=> You can see the guide command during Application API test. Then install the wgts following the guide (ex.pkgcmd -i -t wgt -q -p...)\r
+=> Run the 6 Manual tcs following the command\r
+=> If you want remove manual tcs, please remove last 6 code of test/tct/tests/TestApplication.js\r
+\r
+\r
+# result and checking progress\r
+- Test progress\r
+$ sdb dlog | grep -w StarFish\r
+# sdb dlog | grep -w StarFish | tee -a webwidget.log\r
+# sdb dlog | grep -w StarFish >> webwidget.log\r
+\r
+- result\r
+/tmp/summary-*.html : result file\r
+/tmp/log-tct*.log : log file\r
diff --git a/webWidgetTCT_device/doc/.gitignore b/webWidgetTCT_device/doc/.gitignore
new file mode 100755 (executable)
index 0000000..eb03e3e
--- /dev/null
@@ -0,0 +1,2 @@
+node_modules
+*.log
diff --git a/webWidgetTCT_device/doc/README.md b/webWidgetTCT_device/doc/README.md
new file mode 100755 (executable)
index 0000000..ee76f14
--- /dev/null
@@ -0,0 +1,36 @@
+HTML is generated from markdown files by:
+=====================================================
+
+npm install # only once to install required packages
+npm run-script generate
+
+PDF is generated by "Print to PDF" in Chrome browser.
+
+=====================================================
+Troubleshooting:
+=====================================================
+You need to have nodejs and nmp installed on your PC
+https://nodejs.org/
+https://www.npmjs.com/
+
+You can test your install with the following commands:
+node -v
+npm -v
+
+If you are using Debian:
+sudo apt-get install nodejs-legacy
+
+=====================================================
+Some npm modules have dependencies on libraries published on github.
+However because of IT security policies ports 22 (ssh) and 9418 (git)
+are filtered for connections outside of company network.
+These dependencies cannot be resolved by local npm proxy.
+Luckily there's an easy way to solve this.
+You just need to tell git to use port 443 (https) instead.
+
+git config --global url.https://.insteadOf git://
+
+=====================================================
+Server certificate verification failed? - try this command:
+
+git config --global http.sslverify false
diff --git a/webWidgetTCT_device/doc/Tizen Avengers - WebApi Guidelines.pdf b/webWidgetTCT_device/doc/Tizen Avengers - WebApi Guidelines.pdf
new file mode 100755 (executable)
index 0000000..6e2ab6b
Binary files /dev/null and b/webWidgetTCT_device/doc/Tizen Avengers - WebApi Guidelines.pdf differ
diff --git a/webWidgetTCT_device/doc/html/css/doctor.css b/webWidgetTCT_device/doc/html/css/doctor.css
new file mode 100755 (executable)
index 0000000..506db6a
--- /dev/null
@@ -0,0 +1 @@
+/*! normalize.css v3.0.0 | MIT License | git.io/normalize */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}h1{font-size:2em;margin:0.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace, monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:0.35em 0.625em 0.75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}*:before,*:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:62.5%;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#eee;background-color:#222628}input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#428bca;text-decoration:none}a:hover,a:focus{color:#2a6496;text-decoration:underline}a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.img-responsive,.thumbnail>img,.thumbnail a>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{padding:4px;line-height:1.42857143;background-color:#222628;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out;display:inline-block;max-width:100%;height:auto}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 .small,h2 .small,h3 .small,h4 .small,h5 .small,h6 .small,.h1 .small,.h2 .small,.h3 .small,.h4 .small,.h5 .small,.h6 .small{font-weight:normal;line-height:1;color:#999}h1,.h1,h2,.h2,h3,.h3{margin-top:20px;margin-bottom:10px}h1 small,.h1 small,h2 small,.h2 small,h3 small,.h3 small,h1 .small,.h1 .small,h2 .small,.h2 .small,h3 .small,.h3 .small{font-size:65%}h4,.h4,h5,.h5,h6,.h6{margin-top:10px;margin-bottom:10px}h4 small,.h4 small,h5 small,.h5 small,h6 small,.h6 small,h4 .small,.h4 .small,h5 .small,.h5 .small,h6 .small,.h6 .small{font-size:75%}h1,.h1{font-size:36px}h2,.h2{font-size:30px}h3,.h3{font-size:24px}h4,.h4{font-size:18px}h5,.h5{font-size:14px}h6,.h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:200;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}small,.small{font-size:85%}cite{font-style:normal}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-muted{color:#999}.text-primary{color:#428bca}a.text-primary:hover{color:#3071a9}.text-success{color:#3c763d}a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#428bca}a.bg-primary:hover{background-color:#3071a9}.bg-success{background-color:#dff0d8}a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ul,ol{margin-top:0;margin-bottom:10px}ul ul,ol ul,ul ol,ol ol{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none;margin-left:-5px}.list-inline>li{display:inline-block;padding-left:5px;padding-right:5px}dl{margin-top:0;margin-bottom:20px}dt,dd{line-height:1.42857143}dt{font-weight:bold}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #999}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote p:last-child,blockquote ul:last-child,blockquote ol:last-child{margin-bottom:0}blockquote footer,blockquote small,blockquote .small{display:block;font-size:80%;line-height:1.42857143;color:#999}blockquote footer:before,blockquote small:before,blockquote .small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0;text-align:right}.blockquote-reverse footer:before,blockquote.pull-right footer:before,.blockquote-reverse small:before,blockquote.pull-right small:before,.blockquote-reverse .small:before,blockquote.pull-right .small:before{content:''}.blockquote-reverse footer:after,blockquote.pull-right footer:after,.blockquote-reverse small:after,blockquote.pull-right small:after,.blockquote-reverse .small:after,blockquote.pull-right .small:after{content:'\00A0 \2014'}blockquote:before,blockquote:after{content:""}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#f0ad4e;background-color:#222;white-space:nowrap;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;box-shadow:inset 0 -1px 0 rgba(0,0,0,0.25)}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;word-break:break-all;word-wrap:break-word;color:#999;background-color:#222;border:1px solid rgba(0,0,0,0.15);border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}.row{margin-left:-15px;margin-right:-15px}.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12{position:relative;min-height:1px;padding-left:15px;padding-right:15px}.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:0}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:0}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:0}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:0}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:0}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:0}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:0}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:0}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{max-width:100%;background-color:transparent}th{text-align:left}.table{width:100%;margin-bottom:20px}.table>thead>tr>th,.table>tbody>tr>th,.table>tfoot>tr>th,.table>thead>tr>td,.table>tbody>tr>td,.table>tfoot>tr>td{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #000}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #000}.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>th,.table>caption+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>td,.table>thead:first-child>tr:first-child>td{border-top:0}.table>tbody+tbody{border-top:2px solid #000}.table .table{background-color:#222628}.table-condensed>thead>tr>th,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>tbody>tr>td,.table-condensed>tfoot>tr>td{padding:5px}.table-bordered{border:1px solid #000}.table-bordered>thead>tr>th,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>td,.table-bordered>tfoot>tr>td{border:1px solid #000}.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{border-bottom-width:2px}.table-striped>tbody>tr:nth-child(odd)>td,.table-striped>tbody>tr:nth-child(odd)>th{background-color:#151919}.table-hover>tbody>tr:hover>td,.table-hover>tbody>tr:hover>th{background-color:#222628}table col[class*="col-"]{position:static;float:none;display:table-column}table td[class*="col-"],table th[class*="col-"]{position:static;float:none;display:table-cell}.table>thead>tr>td.active,.table>tbody>tr>td.active,.table>tfoot>tr>td.active,.table>thead>tr>th.active,.table>tbody>tr>th.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>tbody>tr.active>td,.table>tfoot>tr.active>td,.table>thead>tr.active>th,.table>tbody>tr.active>th,.table>tfoot>tr.active>th{background-color:#222628}.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover,.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th{background-color:#16191a}.table>thead>tr>td.success,.table>tbody>tr>td.success,.table>tfoot>tr>td.success,.table>thead>tr>th.success,.table>tbody>tr>th.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>tbody>tr.success>td,.table>tfoot>tr.success>td,.table>thead>tr.success>th,.table>tbody>tr.success>th,.table>tfoot>tr.success>th{background-color:#dff0d8}.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover,.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th{background-color:#d0e9c6}.table>thead>tr>td.info,.table>tbody>tr>td.info,.table>tfoot>tr>td.info,.table>thead>tr>th.info,.table>tbody>tr>th.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>tbody>tr.info>td,.table>tfoot>tr.info>td,.table>thead>tr.info>th,.table>tbody>tr.info>th,.table>tfoot>tr.info>th{background-color:#d9edf7}.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover,.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th{background-color:#c4e3f3}.table>thead>tr>td.warning,.table>tbody>tr>td.warning,.table>tfoot>tr>td.warning,.table>thead>tr>th.warning,.table>tbody>tr>th.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>tbody>tr.warning>td,.table>tfoot>tr.warning>td,.table>thead>tr.warning>th,.table>tbody>tr.warning>th,.table>tfoot>tr.warning>th{background-color:#fcf8e3}.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover,.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th{background-color:#faf2cc}.table>thead>tr>td.danger,.table>tbody>tr>td.danger,.table>tfoot>tr>td.danger,.table>thead>tr>th.danger,.table>tbody>tr>th.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>tbody>tr.danger>td,.table>tfoot>tr.danger>td,.table>thead>tr.danger>th,.table>tbody>tr.danger>th,.table>tfoot>tr.danger>th{background-color:#f2dede}.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover,.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th{background-color:#ebcccc}@media (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;overflow-x:scroll;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #000;-webkit-overflow-scrolling:touch}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>thead>tr>th,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tfoot>tr>td{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>thead>tr>th:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.table-responsive>.table-bordered>thead>tr>th:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>th,.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}}fieldset{padding:0;margin:0;border:0;min-width:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;margin-bottom:5px;font-weight:bold}input[type="search"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type="radio"],input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;line-height:normal}input[type="file"]{display:block}input[type="range"]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border-color ease-in-out .15s, box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s, box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{cursor:not-allowed;background-color:#eee;opacity:1}textarea.form-control{height:auto}input[type="search"]{-webkit-appearance:none}input[type="date"]{line-height:34px}.form-group{margin-bottom:15px}.radio,.checkbox{display:block;min-height:20px;margin-top:10px;margin-bottom:10px;padding-left:20px}.radio label,.checkbox label{display:inline;font-weight:normal;cursor:pointer}.radio input[type="radio"],.radio-inline input[type="radio"],.checkbox input[type="checkbox"],.checkbox-inline input[type="checkbox"]{float:left;margin-left:-20px}.radio+.radio,.checkbox+.checkbox{margin-top:-5px}.radio-inline,.checkbox-inline{display:inline-block;padding-left:20px;margin-bottom:0;vertical-align:middle;font-weight:normal;cursor:pointer}.radio-inline+.radio-inline,.checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px}input[type="radio"][disabled],input[type="checkbox"][disabled],.radio[disabled],.radio-inline[disabled],.checkbox[disabled],.checkbox-inline[disabled],fieldset[disabled] input[type="radio"],fieldset[disabled] input[type="checkbox"],fieldset[disabled] .radio,fieldset[disabled] .radio-inline,fieldset[disabled] .checkbox,fieldset[disabled] .checkbox-inline{cursor:not-allowed}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}textarea.input-sm,select[multiple].input-sm{height:auto}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-lg{height:46px;line-height:46px}textarea.input-lg,select[multiple].input-lg{height:auto}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.has-feedback .form-control-feedback{position:absolute;top:25px;right:0;display:block;width:34px;height:34px;line-height:34px;text-align:center}.has-success .help-block,.has-success .control-label,.has-success .radio,.has-success .checkbox,.has-success .radio-inline,.has-success .checkbox-inline{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;border-color:#3c763d;background-color:#dff0d8}.has-success .form-control-feedback{color:#3c763d}.has-warning .help-block,.has-warning .control-label,.has-warning .radio,.has-warning .checkbox,.has-warning .radio-inline,.has-warning .checkbox-inline{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;border-color:#8a6d3b;background-color:#fcf8e3}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .help-block,.has-error .control-label,.has-error .radio,.has-error .checkbox,.has-error .radio-inline,.has-error .checkbox-inline{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;border-color:#a94442;background-color:#f2dede}.has-error .form-control-feedback{color:#a94442}.form-control-static{margin-bottom:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#fff}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .radio,.form-inline .checkbox{display:inline-block;margin-top:0;margin-bottom:0;padding-left:0;vertical-align:middle}.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{float:none;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .control-label,.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{margin-top:0;margin-bottom:0;padding-top:7px}.form-horizontal .radio,.form-horizontal .checkbox{min-height:27px}.form-horizontal .form-group{margin-left:-15px;margin-right:-15px}.form-horizontal .form-control-static{padding-top:7px}@media (min-width:768px){.form-horizontal .control-label{text-align:right}}.form-horizontal .has-feedback .form-control-feedback{top:0;right:15px}.btn{display:inline-block;margin-bottom:0;font-weight:normal;text-align:center;vertical-align:middle;cursor:pointer;background-image:none;border:1px solid transparent;white-space:nowrap;padding:6px 12px;font-size:14px;line-height:1.42857143;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.btn:focus,.btn:active:focus,.btn.active:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:hover,.btn:focus{color:#333;text-decoration:none}.btn:active,.btn.active{outline:0;background-image:none;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;pointer-events:none;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default:hover,.btn-default:focus,.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{color:#333;background-color:#ebebeb;border-color:#adadad}.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{background-image:none}.btn-default.disabled,.btn-default[disabled],fieldset[disabled] .btn-default,.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled:active,.btn-default[disabled]:active,fieldset[disabled] .btn-default:active,.btn-default.disabled.active,.btn-default[disabled].active,fieldset[disabled] .btn-default.active{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#428bca;border-color:#357ebd}.btn-primary:hover,.btn-primary:focus,.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{color:#fff;background-color:#3276b1;border-color:#285e8e}.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled,.btn-primary[disabled],fieldset[disabled] .btn-primary,.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled:active,.btn-primary[disabled]:active,fieldset[disabled] .btn-primary:active,.btn-primary.disabled.active,.btn-primary[disabled].active,fieldset[disabled] .btn-primary.active{background-color:#428bca;border-color:#357ebd}.btn-primary .badge{color:#428bca;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success:hover,.btn-success:focus,.btn-success:active,.btn-success.active,.open .dropdown-toggle.btn-success{color:#fff;background-color:#47a447;border-color:#398439}.btn-success:active,.btn-success.active,.open .dropdown-toggle.btn-success{background-image:none}.btn-success.disabled,.btn-success[disabled],fieldset[disabled] .btn-success,.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled:active,.btn-success[disabled]:active,fieldset[disabled] .btn-success:active,.btn-success.disabled.active,.btn-success[disabled].active,fieldset[disabled] .btn-success.active{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info:hover,.btn-info:focus,.btn-info:active,.btn-info.active,.open .dropdown-toggle.btn-info{color:#fff;background-color:#39b3d7;border-color:#269abc}.btn-info:active,.btn-info.active,.open .dropdown-toggle.btn-info{background-image:none}.btn-info.disabled,.btn-info[disabled],fieldset[disabled] .btn-info,.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled:active,.btn-info[disabled]:active,fieldset[disabled] .btn-info:active,.btn-info.disabled.active,.btn-info[disabled].active,fieldset[disabled] .btn-info.active{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning:hover,.btn-warning:focus,.btn-warning:active,.btn-warning.active,.open .dropdown-toggle.btn-warning{color:#fff;background-color:#ed9c28;border-color:#d58512}.btn-warning:active,.btn-warning.active,.open .dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-warning,.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled:active,.btn-warning[disabled]:active,fieldset[disabled] .btn-warning:active,.btn-warning.disabled.active,.btn-warning[disabled].active,fieldset[disabled] .btn-warning.active{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger:hover,.btn-danger:focus,.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{color:#fff;background-color:#d2322d;border-color:#ac2925}.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled,.btn-danger[disabled],fieldset[disabled] .btn-danger,.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled:active,.btn-danger[disabled]:active,fieldset[disabled] .btn-danger:active,.btn-danger.disabled.active,.btn-danger[disabled].active,fieldset[disabled] .btn-danger.active{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{color:#428bca;font-weight:normal;cursor:pointer;border-radius:0}.btn-link,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:hover,.btn-link:focus,.btn-link:active{border-color:transparent}.btn-link:hover,.btn-link:focus{color:#2a6496;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,fieldset[disabled] .btn-link:hover,.btn-link[disabled]:focus,fieldset[disabled] .btn-link:focus{color:#999;text-decoration:none}.btn-lg,.btn-group-lg>.btn{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.btn-sm,.btn-group-sm>.btn{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-xs,.btn-group-xs>.btn{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%;padding-left:0;padding-right:0}.btn-block+.btn-block{margin-top:5px}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;transition:height .35s ease}@font-face{font-family:'Glyphicons Halflings';src:url('../fonts/glyphicons-halflings-regular.eot');src:url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'),url('../fonts/glyphicons-halflings-regular.woff') format('woff'),url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'),url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:normal;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\2a"}.glyphicon-plus:before{content:"\2b"}.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;float:left}.btn-group>.btn:hover,.btn-group-vertical>.btn:hover,.btn-group>.btn:focus,.btn-group-vertical>.btn:focus,.btn-group>.btn:active,.btn-group-vertical>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn.active{z-index:2}.btn-group>.btn:focus,.btn-group-vertical>.btn:focus{outline:none}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child>.btn:last-child,.btn-group>.btn-group:first-child>.dropdown-toggle{border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn-group:last-child>.btn:first-child{border-bottom-left-radius:0;border-top-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-left:8px;padding-right:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-left:12px;padding-right:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-bottom-left-radius:4px;border-top-right-radius:0;border-top-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-right-radius:0;border-top-left-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{float:none;display:table-cell;width:1%}.btn-group-justified>.btn-group .btn{width:100%}[data-toggle="buttons"]>.btn>input[type="radio"],[data-toggle="buttons"]>.btn>input[type="checkbox"]{display:none}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#222628;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.thumbnail>img,.thumbnail a>img{margin-left:auto;margin-right:auto}a.thumbnail:hover,a.thumbnail:focus,a.thumbnail.active{border-color:#428bca}.thumbnail .caption{padding:9px;color:#eee}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:bold}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable{padding-right:35px}.alert-dismissable .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{background-color:#dff0d8;border-color:#d6e9c6;color:#3c763d}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{background-color:#d9edf7;border-color:#bce8f1;color:#31708f}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{background-color:#fcf8e3;border-color:#faebcc;color:#8a6d3b}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{background-color:#f2dede;border-color:#ebccd1;color:#a94442}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}.clearfix:before,.clearfix:after,.container:before,.container:after,.container-fluid:before,.container-fluid:after,.row:before,.row:after,.form-horizontal .form-group:before,.form-horizontal .form-group:after,.btn-toolbar:before,.btn-toolbar:after,.btn-group-vertical>.btn-group:before,.btn-group-vertical>.btn-group:after{content:" ";display:table}.clearfix:after,.container:after,.container-fluid:after,.row:after,.form-horizontal .form-group:after,.btn-toolbar:after,.btn-group-vertical>.btn-group:after{clear:both}.center-block{display:block;margin-left:auto;margin-right:auto}.pull-right{float:right !important}.pull-left{float:left !important}.hide{display:none !important}.show{display:block !important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none !important;visibility:hidden !important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-xs,.visible-sm,.visible-md,.visible-lg{display:none !important}@media (max-width:767px){.visible-xs{display:block !important}table.visible-xs{display:table}tr.visible-xs{display:table-row !important}th.visible-xs,td.visible-xs{display:table-cell !important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block !important}table.visible-sm{display:table}tr.visible-sm{display:table-row !important}th.visible-sm,td.visible-sm{display:table-cell !important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block !important}table.visible-md{display:table}tr.visible-md{display:table-row !important}th.visible-md,td.visible-md{display:table-cell !important}}@media (min-width:1200px){.visible-lg{display:block !important}table.visible-lg{display:table}tr.visible-lg{display:table-row !important}th.visible-lg,td.visible-lg{display:table-cell !important}}@media (max-width:767px){.hidden-xs{display:none !important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none !important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none !important}}@media (min-width:1200px){.hidden-lg{display:none !important}}.visible-print{display:none !important}@media print{.visible-print{display:block !important}table.visible-print{display:table}tr.visible-print{display:table-row !important}th.visible-print,td.visible-print{display:table-cell !important}}@media print{.hidden-print{display:none !important}}pre{background:none repeat scroll 0 0 rgba(0,0,0,0.3);-ms-box-shadow:0 1px 0 rgba(255,255,255,0.1),0 1px 7px 0 rgba(0,0,0,0.8) inset;-o-box-shadow:0 1px 0 rgba(255,255,255,0.1),0 1px 7px 0 rgba(0,0,0,0.8) inset;-moz-box-shadow:0 1px 0 rgba(255,255,255,0.1),0 1px 7px 0 rgba(0,0,0,0.8) inset;-webkit-box-shadow:0 1px 0 rgba(255,255,255,0.1),0 1px 7px 0 rgba(0,0,0,0.8) inset;box-shadow:0 1px 0 rgba(255,255,255,0.1),0 1px 7px 0 rgba(0,0,0,0.8) inset}pre.prettyprint{margin-bottom:20px}.alert{padding:8px 35px 8px 14px;margin-bottom:20px;border:0px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;text-shadow:none;background:none repeat scroll 0 0 rgba(0,0,0,0.3);-ms-box-shadow:0 1px 0 rgba(255,255,255,0.1),0 1px 7px 0 rgba(0,0,0,0.8) inset;-o-box-shadow:0 1px 0 rgba(255,255,255,0.1),0 1px 7px 0 rgba(0,0,0,0.8) inset;-moz-box-shadow:0 1px 0 rgba(255,255,255,0.1),0 1px 7px 0 rgba(0,0,0,0.8) inset;-webkit-box-shadow:0 1px 0 rgba(255,255,255,0.1),0 1px 7px 0 rgba(0,0,0,0.8) inset;box-shadow:0 1px 0 rgba(255,255,255,0.1),0 1px 7px 0 rgba(0,0,0,0.8) inset}a.brand{background-repeat:no-repeat;background-position:8px center;height:40px;display:block}#nav{position:fixed;top:0;padding:0;left:0;width:250px;height:100%;background:#303335;border-right:1px solid #1E1F20;-webkit-box-shadow:inset rgba(0,0,0,0.3) -1px 0 3px 0;box-shadow:inset rgba(0,0,0,0.3) -1px 0 3px 0;text-shadow:rgba(0,0,0,0.7) 0 1px 0;overflow-x:hidden;overflow-y:auto}#nav ul{margin:0;padding:0}#nav li{list-style:none;margin:0}#nav a{display:block;font-weight:bold;text-decoration:none;color:#ffffff;-webkit-transition:all .4s ease-out 0s;transition:all .4s ease-out 0s}#nav #sections{background:#202323;-webkit-box-shadow:0 0 5px rgba(0,0,0,0.15);box-shadow:0 0 5px rgba(0,0,0,0.15)}#nav #sections>li{-webkit-transition:all .2s ease-out 0s;transition:all .2s ease-out 0s;border-top:1px solid #303434;border-bottom:1px solid #000000}#nav #sections>li a{padding:5px 15px;color:#fff;font-size:14px}#nav #sections>li a:hover{color:#FFC76D;background-color:#303335;box-shadow:0 1px 0 rgba(255,255,255,0.1),0 -1px 0 rgba(0,0,0,0.25),0 -1px 0 rgba(0,0,0,0.25) inset}#nav #sections>li a.active{color:#FFC76D}#nav #sections>li ul li{border-top:1px solid #303434;border-bottom:1px solid #000000}#nav #sections>li ul li a{padding:1px 25px;font-size:13px}#nav #sections>li ul li a:hover{background-color:#303335;box-shadow:0 1px 0 rgba(255,255,255,0.1),0 -1px 0 rgba(0,0,0,0.25),0 -1px 0 rgba(0,0,0,0.25) inset;color:#FFC76D}#nav #sections>li ul li a.active{color:#FFC76D}#nav #sections>li ul>li:first-child{border-top:1px solid black}#nav #sections>li ul>li:last-child{border-bottom:none}#nav #sections li.active{border-right:2px solid red}#nav .extra{color:#0E0D1B;text-shadow:0 1px 0 rgba(55,155,155,0.3);padding:5px 15px;min-height:1.4em;text-transform:uppercase}#nav .extra a{color:#0E0D1B;font-size:14px}#nav .extra a:hover{color:#000000}#nav .extra.generated{font-size:10px}#nav .extra.generated a{display:inline-block;font-size:10px}#nav #travis img{margin-top:10px;display:block}#nav>*:last-child{margin-bottom:20px}#content{margin:0 10px 0 290px;padding:30px 0 20px;min-height:100px;max-width:888px;padding-bottom:600px}#content h1,#content h2,#content h3,#content h4,#content h5{color:white;text-shadow:1px 1px 2px black}#content a.heading-anchor{font-size:12px;font-weight:normal;position:absolute;margin:8px -20px 0;color:#444444}#content a.heading-anchor:hover{color:#FFC76D;font-weight:bold;text-shadow:0 0 5px rgba(0,0,0,0.8)}#content h2.active,#content h3.active{color:#FFC76D !important;text-shadow:0 0 15px rgba(0,0,0,0.8) !important}#content h2:after{height:0px;border-bottom:1px solid #303434;border-top:1px solid #000000;position:relative;margin-top:6px;display:block;z-index:100;content:""}#github-ribbon{position:absolute;top:0;right:0}#github-ribbon img{border:0}.pun,.opn,.clo{color:#ffffff}.fun{color:#dc322f}.str,.atv{color:#f7fdbe}.kwd,.linenums .tag{color:#ffc76d}.typ,.atn,.dec,.var{color:#c28125}.pln{color:#eee}.pun{color:#FFFFFF}.prettyprint{padding:8px;border:1px solid black;background:none repeat scroll 0 0 rgba(0,0,0,0.3);-ms-box-shadow:0 1px 0 rgba(255,255,255,0.1),0 1px 7px 0 rgba(0,0,0,0.8) inset;-o-box-shadow:0 1px 0 rgba(255,255,255,0.1),0 1px 7px 0 rgba(0,0,0,0.8) inset;-moz-box-shadow:0 1px 0 rgba(255,255,255,0.1),0 1px 7px 0 rgba(0,0,0,0.8) inset;-webkit-box-shadow:0 1px 0 rgba(255,255,255,0.1),0 1px 7px 0 rgba(0,0,0,0.8) inset;box-shadow:0 1px 0 rgba(255,255,255,0.1),0 1px 7px 0 rgba(0,0,0,0.8) inset}ol.linenums{_margin:0 0 0 33px}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);box-shadow:inset 0 1px 1px rgba(0,0,0,0.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,0.15)}.well-large{padding:24px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.well-small{padding:9px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}a.travis img{margin-top:15px}div.separator{height:5px;background-color:#484D52;background-image:-webkit-linear-gradient(top, #4e5459 0, #3e4347 100%);background-image:linear-gradient(to bottom, #4e5459 0, #3e4347 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff4e5459', endColorstr='#ff3e4347', GradientType=0);box-shadow:0 1px rgba(0,0,0,0.55),0 -1px rgba(0,0,0,0.55),0 1px rgba(255,255,255,0.1) inset;color:#FFFFFF;position:relative;text-shadow:0 -1px 0 rgba(0,0,0,0.6);z-index:100}div.ace{_height:400px;min-height:400px;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.15);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;background:none repeat scroll 0 0 rgba(0,0,0,0.3);-ms-box-shadow:0 1px 0 rgba(255,255,255,0.1),0 1px 7px 0 rgba(0,0,0,0.8) inset;-o-box-shadow:0 1px 0 rgba(255,255,255,0.1),0 1px 7px 0 rgba(0,0,0,0.8) inset;-moz-box-shadow:0 1px 0 rgba(255,255,255,0.1),0 1px 7px 0 rgba(0,0,0,0.8) inset;-webkit-box-shadow:0 1px 0 rgba(255,255,255,0.1),0 1px 7px 0 rgba(0,0,0,0.8) inset;box-shadow:0 1px 0 rgba(255,255,255,0.1),0 1px 7px 0 rgba(0,0,0,0.8) inset}div.ace.prettyprint{margin-bottom:20px}.acely{margin:0;padding:0;margin-top:8px;background:white;border:0;-ms-box-shadow:0 1px 0 rgba(255,255,255,0.1),0 1px 7px 0 rgba(0,0,0,0.8) inset;-o-box-shadow:0 1px 0 rgba(255,255,255,0.1),0 1px 7px 0 rgba(0,0,0,0.8) inset;-moz-box-shadow:0 1px 0 rgba(255,255,255,0.1),0 1px 7px 0 rgba(0,0,0,0.8) inset;-webkit-box-shadow:0 1px 0 rgba(255,255,255,0.1),0 1px 7px 0 rgba(0,0,0,0.8) inset;box-shadow:0 1px 0 rgba(255,255,255,0.1),0 1px 7px 0 rgba(0,0,0,0.8) inset}.btn{color:#333}.btn:hover,.btn:active{color:black}hr{border-bottom:1px solid #303434;border-top:1px solid #000000;margin:0;margin-bottom:8px;line-height:2px}table.table-bordered{color:black;background:white;-ms-box-shadow:0 1px 0 rgba(255,255,255,0.1),0 1px 7px 0 rgba(0,0,0,0.8) inset;-o-box-shadow:0 1px 0 rgba(255,255,255,0.1),0 1px 7px 0 rgba(0,0,0,0.8) inset;-moz-box-shadow:0 1px 0 rgba(255,255,255,0.1),0 1px 7px 0 rgba(0,0,0,0.8) inset;-webkit-box-shadow:0 1px 0 rgba(255,255,255,0.1),0 1px 7px 0 rgba(0,0,0,0.8) inset;box-shadow:0 1px 0 rgba(255,255,255,0.1),0 1px 7px 0 rgba(0,0,0,0.8) inset}
\ No newline at end of file
diff --git a/webWidgetTCT_device/doc/html/css/print.css b/webWidgetTCT_device/doc/html/css/print.css
new file mode 100755 (executable)
index 0000000..5c0edd8
--- /dev/null
@@ -0,0 +1,111 @@
+/* print */
+
+body {
+  background: #fff;
+  color: #202323;
+}
+
+pre, .prettyprint {
+  background: #202323;
+}
+
+#nav {
+  position: relative;
+  top: auto;
+  left: auto;
+  width: auto;
+  height: auto;
+  padding: 0 15px;
+  background: none;
+  border: none;
+  text-shadow: none;
+  margin: auto;
+  box-shadow: none;
+  color: #202323;
+}
+
+@media (min-width: 768px) {
+  #nav {
+    width: 750px;
+  }
+}
+
+@media (min-width: 992px) {
+  #nav {
+    width: 970px;
+  }
+}
+
+@media (min-width: 1200px) {
+  #nav {
+    width: 1170px;
+  }
+}
+
+#nav #sections {
+  background: #fff;
+  box-shadow: none;
+}
+
+#nav ul {
+  padding: 0 0 0 30px;
+}
+
+#nav li {
+  list-style-type: upper-roman;
+}
+
+#nav li ul li {
+  list-style-type: decimal;
+}
+
+#nav #sections > li,
+#nav #sections > li ul li,
+#nav #sections > li ul > li:first-child {
+  border-top: none;
+  border-bottom: none;
+}
+
+#nav #sections > li,
+#nav #sections > li a {
+  color: #202323;
+}
+
+div.separator {
+  display: none;
+}
+
+a.brand {
+  display: none !important;
+}
+
+#content {
+  margin: auto;
+  padding: 0 15px;
+  max-width: none;
+}
+
+#content h1 {
+  display: none;
+}
+
+#content h1, #content h2, #content h3, #content h4, #content h5 {
+  color: #202323;
+}
+
+/*#content h1, #content h2 {*/
+  /*page-break-before: always;*/
+/*}*/
+
+.heading-anchor {
+  display: none;
+}
+
+.table-striped > tbody > tr:nth-child(odd) > td,
+.table-striped > tbody > tr:nth-child(odd) > th {
+  background-color: #f5f5f5;
+}
+
+.extra.generated {
+  display: none;
+}
diff --git a/webWidgetTCT_device/doc/html/images/logo.png b/webWidgetTCT_device/doc/html/images/logo.png
new file mode 100755 (executable)
index 0000000..a913f5d
Binary files /dev/null and b/webWidgetTCT_device/doc/html/images/logo.png differ
diff --git a/webWidgetTCT_device/doc/html/images/plugin_flow.png b/webWidgetTCT_device/doc/html/images/plugin_flow.png
new file mode 100755 (executable)
index 0000000..42ea946
Binary files /dev/null and b/webWidgetTCT_device/doc/html/images/plugin_flow.png differ
diff --git a/webWidgetTCT_device/doc/html/images/tizen-logo_32h.png b/webWidgetTCT_device/doc/html/images/tizen-logo_32h.png
new file mode 100755 (executable)
index 0000000..c0c9246
Binary files /dev/null and b/webWidgetTCT_device/doc/html/images/tizen-logo_32h.png differ
diff --git a/webWidgetTCT_device/doc/html/index.html b/webWidgetTCT_device/doc/html/index.html
new file mode 100755 (executable)
index 0000000..4206acd
--- /dev/null
@@ -0,0 +1,781 @@
+<!DOCTYPE html>
+<html>
+<head>
+       <meta charset="utf-8">
+       <title>Tizen Avengers - WebApi Guidelines</title>
+       <link href="css/doctor.css" type="text/css" rel="stylesheet">
+       <link href="css/print.css" type="text/css" rel="stylesheet" media="print">
+</head>
+<body>
+<div id="nav">
+    <h1 class="visible-print">Tizen Avengers - WebApi Guidelines</h1>
+       <div class="separator"></div>
+       <a title="Tizen Avengers - WebApi Guidelines" class="brand" href="#" style="background-image:url(images/tizen-logo_32h.png)"></a>
+       <div class="separator"></div>
+       <ul id="sections"><li class="l2"><a href="#revision-history">Revision History</a></li><li class="l2"><a href="#overview">Overview</a></li><li class="l2"><a href="#guideline">Guideline</a><ul><li class="l3"><a href="#guideline/languages">Languages</a></li><li class="l3"><a href="#guideline/codding-style">Codding style</a></li><li class="l3"><a href="#guideline/api-guide">API guide</a></li><li class="l3"><a href="#guideline/unit-test-criteria">Unit test criteria</a></li><li class="l3"><a href="#guideline/source-code">Source code</a></li><li class="l3"><a href="#guideline/license-and-boilerplate">License and Boilerplate</a></li></ul></li><li class="l2"><a href="#plugin-structure">Plugin Structure</a><ul><li class="l3"><a href="#plugin-structure/conventions">Conventions</a></li><li class="l3"><a href="#plugin-structure/structure">Structure</a></li><li class="l3"><a href="#plugin-structure/spec-file">Spec file</a></li><li class="l3"><a href="#plugin-structure/gyp-file">GYP file</a></li><li class="l3"><a href="#plugin-structure/implementation-files">Implementation files</a></li><li class="l3"><a href="#plugin-structure/plugin-flow">Plugin flow</a></li></ul></li><li class="l2"><a href="#widl">WIDL</a><ul><li class="l3"><a href="#widl/conventions">Conventions</a></li><li class="l3"><a href="#widl/architecture">Architecture</a></li><li class="l3"><a href="#widl/example">Example</a></li></ul></li><li class="l2"><a href="#tools">Tools</a><ul><li class="l3"><a href="#tools/generate-stub-code">Generate stub code</a></li><li class="l3"><a href="#tools/using-multiple-javascript-files">Using multiple JavaScript files</a></li></ul></li><li class="l2"><a href="#implementation-javascript">Implementation - JavaScript</a><ul><li class="l3"><a href="#implementation-javascript/interface-creation">Interface creation</a></li><li class="l3"><a href="#implementation-javascript/creating-manager-entity">Creating Manager entity</a></li><li class="l3"><a href="#implementation-javascript/properties-definition">Properties definition</a></li><li class="l3"><a href="#implementation-javascript/methods-definition">Methods definition</a></li><li class="l3"><a href="#implementation-javascript/exporting-interface">Exporting interface</a></li><li class="l3"><a href="#implementation-javascript/utils">Utils</a></li><li class="l3"><a href="#implementation-javascript/exceptions">Exceptions</a></li><li class="l3"><a href="#implementation-javascript/synchronous-methods">Synchronous methods</a></li><li class="l3"><a href="#implementation-javascript/asynchronous-methods">Asynchronous methods</a></li><li class="l3"><a href="#implementation-javascript/listeners">Listeners</a></li></ul></li><li class="l2"><a href="#implementation-c">Implementation - C++</a><ul><li class="l3"><a href="#implementation-c/lifecycle-and-plugin-state">Lifecycle and plugin state</a></li><li class="l3"><a href="#implementation-c/namespace-and-entry-points">Namespace and entry points</a></li><li class="l3"><a href="#implementation-c/plugin-structure">Plugin structure</a></li><li class="l3"><a href="#implementation-c/asynchronous-calls">Asynchronous calls</a></li><li class="l3"><a href="#implementation-c/listeners">Listeners</a></li><li class="l3"><a href="#implementation-c/logger">Logger</a></li><li class="l3"><a href="#implementation-c/error-handling">Error handling</a></li></ul></li><li class="l2"><a href="#devel-package">Devel package</a><ul><li class="l3"><a href="#devel-package/package-structure">Package structure</a></li><li class="l3"><a href="#devel-package/creating-custom-web-device-plugins-module">Creating custom web device plugins module</a></li></ul></li></ul>
+       <div class="separator"></div>
+       <div class="extra generated">
+               Generated by <a href="https://github.com/DimitarChristoff/doctor" target="_blank" title="generate documentation from markdown">Doctor, MD</a>
+       </div>
+</div>
+<div id="content" class="container">
+       <h1 id="tizen-avengers-webapi-guidelines">Tizen Avengers - WebApi Guidelines</h1>
+<h2 id="revision-history">Revision History</h2>
+<table class="table table-striped">
+<thead>
+<tr>
+<th>Version</th>
+<th>Date</th>
+<th>Description</th>
+<th>Editor</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>0.1.0</td>
+<td>2015-05-15</td>
+<td>Initial Draft</td>
+<td>Wojciech Kosowicz<br><a href="mailto:w.kosowicz@samsung.com">&#119;&#x2e;&#x6b;&#111;&#115;&#x6f;&#119;&#x69;&#99;&#x7a;&#x40;&#115;&#x61;&#x6d;&#x73;&#x75;&#x6e;&#x67;&#46;&#99;&#x6f;&#x6d;</a></td>
+</tr>
+<tr>
+<td>0.2.0</td>
+<td>2015-05-22</td>
+<td>Extended version</td>
+<td>Pawel Kaczmarek<br><a href="mailto:p.kaczmarek3@samsung.com">&#x70;&#x2e;&#x6b;&#x61;&#99;&#x7a;&#109;&#x61;&#x72;&#101;&#x6b;&#51;&#64;&#115;&#97;&#x6d;&#x73;&#117;&#110;&#x67;&#46;&#x63;&#x6f;&#x6d;</a></td>
+</tr>
+<tr>
+<td>0.2.1</td>
+<td>2015-06-01</td>
+<td>Proofreading</td>
+<td>Rafal Galka<br><a href="mailto:r.galka@samsung.com">&#114;&#46;&#103;&#x61;&#x6c;&#107;&#97;&#x40;&#115;&#97;&#109;&#x73;&#117;&#x6e;&#103;&#46;&#99;&#x6f;&#x6d;</a></td>
+</tr>
+<tr>
+<td>0.3.0</td>
+<td>2015-06-08</td>
+<td>Supplemented C++ implementation guide</td>
+<td>Rafal Galka<br><a href="mailto:r.galka@samsung.com">&#114;&#46;&#x67;&#97;&#108;&#107;&#x61;&#x40;&#115;&#97;&#109;&#x73;&#x75;&#x6e;&#x67;&#x2e;&#x63;&#111;&#109;</a></td>
+</tr>
+<tr>
+<td>0.4.0</td>
+<td>2015-06-16</td>
+<td>Guideline</td>
+<td>Pawel Kaczmarek<br><a href="mailto:p.kaczmarek3@samsung.com">&#x70;&#x2e;&#x6b;&#x61;&#x63;&#x7a;&#109;&#97;&#114;&#x65;&#x6b;&#x33;&#x40;&#115;&#97;&#109;&#x73;&#x75;&#x6e;&#103;&#46;&#99;&#111;&#109;</a></td>
+</tr>
+<tr>
+<td>0.5.0</td>
+<td>2015-06-18</td>
+<td>Devel package</td>
+<td>Pawel Kaczmarek<br><a href="mailto:p.kaczmarek3@samsung.com">&#x70;&#x2e;&#x6b;&#97;&#x63;&#x7a;&#x6d;&#x61;&#x72;&#101;&#107;&#51;&#x40;&#x73;&#97;&#109;&#x73;&#x75;&#110;&#103;&#46;&#99;&#x6f;&#x6d;</a></td>
+</tr>
+<tr>
+<td>0.5.1</td>
+<td>2015-06-24</td>
+<td>Add info about WAPIOven.py</td>
+<td>Pawel Kaczmarek<br><a href="mailto:p.kaczmarek3@samsung.com">&#x70;&#x2e;&#x6b;&#x61;&#x63;&#122;&#x6d;&#97;&#x72;&#x65;&#107;&#51;&#64;&#x73;&#x61;&#109;&#115;&#x75;&#x6e;&#x67;&#46;&#99;&#x6f;&#109;</a></td>
+</tr>
+</tbody>
+</table>
+<h2 id="overview">Overview</h2>
+<p>This document should be used as a guideline for developers who are creating web
+plugins for Tizen platform. Conventions and practices described here could be
+used to develop new web plugins for Tizen 2.4 platform and higher version.
+Each plugin should be written with great attention on JavaScript.</p>
+<h2 id="guideline">Guideline</h2>
+<h3 id="guideline/languages">Languages</h3>
+<p>C++, JavaScript</p>
+<h3 id="guideline/codding-style">Codding style</h3>
+<p>Use Google style guide,
+C++: <a href="http://google-styleguide.googlecode.com/svn/trunk/cppguide.html">http://google-styleguide.googlecode.com/svn/trunk/cppguide.html</a></p>
+<p>JavaScript: <a href="http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml">http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml</a></p>
+<h3 id="guideline/api-guide">API guide</h3>
+<p>Tizen Web Device API Guide Lines.pptx
+<a href="http://platform.sec.samsung.net/slp/Tizen/Tizen%20Managed%20API/Web%20Device%20API/Tizen%20Web%20Device%20API%20Guide%20Lines.pptx">http://platform.sec.samsung.net/slp/Tizen/Tizen%20Managed%20API/Web%20Device%20API/Tizen%20Web%20Device%20API%20Guide%20Lines.pptx</a></p>
+<h3 id="guideline/unit-test-criteria">Unit test criteria</h3>
+<p>Tizen-Compliance-Tests-Device-API-UnitTest-Criteria.v0.11_SRPOL.xlsx
+<a href="http://platform.sec.samsung.net/slp/Tizen/Tizen%20Managed%20API/Web%20Device%20API/Tizen-Compliance-Tests-Device-API-UnitTest-Criteria.v0.11_SRPOL.xlsx">http://platform.sec.samsung.net/slp/Tizen/Tizen%20Managed%20API/Web%20Device%20API/Tizen-Compliance-Tests-Device-API-UnitTest-Criteria.v0.11_SRPOL.xlsx</a></p>
+<h3 id="guideline/source-code">Source code</h3>
+<p>For Tizen 2.4:</p>
+<pre><code class="lang-sh">$ git clone ssh://&lt;user.id&gt;@168.219.209.56:29418/framework/web/webapi-plugins
+$ cd webapi-plugins
+$ git checkout origin/tizen_2.4
+</code></pre>
+<p>For Tizen 3.0</p>
+<pre><code class="lang-sh">$ git clone ssh://&lt;user.id&gt;@168.219.209.56:29418/framework/web/webapi-plugins
+$ cd webapi-plugins
+$ git checkout origin/tizen_3.0
+</code></pre>
+<h3 id="guideline/license-and-boilerplate">License and Boilerplate</h3>
+<p>Use this boilerplate in every new created source files.</p>
+<pre><code class="lang-sh">/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *    Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+</code></pre>
+<h2 id="plugin-structure">Plugin Structure</h2>
+<h3 id="plugin-structure/conventions">Conventions</h3>
+<p>Each plugin is kept in separate directory inside src/ folder written in lowercase convention.</p>
+<h3 id="plugin-structure/structure">Structure</h3>
+<p>Each plugin contains following structure:</p>
+<ul>
+<li><code>&lt;pluginname&gt;.gyp</code></li>
+<li><code>&lt;pluginname&gt;_api.js</code></li>
+<li><code>&lt;pluginname&gt;_extension.h</code></li>
+<li><code>&lt;pluginname&gt;_extension.cc</code></li>
+<li><code>&lt;pluginname&gt;_instance.h</code></li>
+<li><code>&lt;pluginname&gt;_instance.cc</code></li>
+</ul>
+<h3 id="plugin-structure/spec-file">Spec file</h3>
+<p>Spec file (<code>webapi-plugins.spec</code>) kept inside <code>packaging/</code> directory
+is build specification file used by rpm packaging system where variables are defined.
+Those variables can be used to include or exclude particular modules from
+build for each profile (mobile, TV, wearable).</p>
+<h3 id="plugin-structure/gyp-file">GYP file</h3>
+<p>Each plugin has its own gyp file that contains information specific for it.
+Plugin configuration file (gyp) is the equivalent of CMake.
+It contains information what files to build what libraries to use for linking.
+There can be also found one main gyp file in <code>src/</code> folder (<code>tizen-wrt.gyp</code>)
+that includes others.</p>
+<h3 id="plugin-structure/implementation-files">Implementation files</h3>
+<p>Description of files required in plugin implementation.</p>
+<ul>
+<li><strong>C++ files</strong> (<code>&lt;pluginname&gt;_extension.h, &lt;pluginname&gt;_extension.cc</code>)<br>
+Extension namespace and other objects exported by JavaScript layer are set inside these files.</li>
+<li><strong>C++ files</strong> (<code>&lt;pluginname&gt;_instance.h, &lt;pluginname&gt;_instance.cc</code>)<br>
+These files are responsible for communication between JavaScript layer and Native API.</li>
+<li><strong>JavaScript file</strong> (<code>&lt;pluginname&gt;_api.js</code>)<br>
+This file contains all methods required by each API.
+All operation should be done by JavaScript as much as possible.
+If JavaScript can do something, it should do it.
+This file is responsible for checking privileges, checking arguments, calling C++ methods etc.</li>
+</ul>
+<h3 id="plugin-structure/plugin-flow">Plugin flow</h3>
+<p><img src="images/plugin_flow.png" alt="Plugin flow"></p>
+<p>Explanation of steps:</p>
+<ol>
+<li>From JavaScript Layer information is sent to C++ Layer.
+This information consists of type of call (asynchronous, synchronous)
+arguments given by user, any additional information that is required to
+successfully acquire required data. Data is sent in form of JSON.</li>
+<li>C++ parses acquired JSON. After the data is processed. Appropriate platform
+functions are called with the specified arguments.</li>
+<li>Platform returns specified values to C++ layer.</li>
+<li>Another JSON is formed. It consists of data that was acquired from platform.</li>
+</ol>
+<h2 id="widl">WIDL</h2>
+<h3 id="widl/conventions">Conventions</h3>
+<p>Currently WIDL version that is used in Samsung is described here: <a href="http://www.w3.org/TR/WebIDL/">http://www.w3.org/TR/WebIDL/</a>.
+This is document from 19 April 2012.</p>
+<p>WIDL used for plugins creation is closer to previous drafts mainly this from
+21 October 2010. It is described here: <a href="http://www.w3.org/TR/2010/WD-WebIDL-20101021/">http://www.w3.org/TR/2010/WD-WebIDL-20101021/</a>.</p>
+<h3 id="widl/architecture">Architecture</h3>
+<p>Each plugin is separated from each other as a different module.
+We do this by using module key name.</p>
+<pre class="prettyprint linenums"><code>module identifer {
+  definitions
+}
+</code></pre><p>Each module describes space, binding many connected definitions in one namespace.
+Inside each module there are sets of <strong>interface</strong> defined.
+Most of the time there is one major interface defined, which is <strong>NoInterfaceObject</strong>.
+This is manager object which has only one property which is object that actually
+implements manager functionality.</p>
+<pre class="prettyprint linenums"><code>interface identifier : indentifier-of-inherited-interface {
+  interface-member...
+};
+</code></pre><p>Interface is a definition of an object, which can be realized in a system
+(an inheritance and overloading is possible).
+In interface definition you can put following members:</p>
+<ul>
+<li>Constants.</li>
+<li>Attribute : Interface member, which represents variable inside object,
+can be changed, if it is not read only.</li>
+<li>Operation: Interface member, which represents method inside object.
+It is a function of programming language, which can be executed and returns a result.</li>
+<li>Special operation: Performs a specific task. i.e. deleter, getter</li>
+<li>Static operation: It is not called for a specific instance of the interface,
+is called for static object regardless of an instance creation.
+It is connected with the interface itself.</li>
+</ul>
+<pre class="prettyprint linenums"><code>interface identifier {
+  attribute type identifier;
+  [extended-attribute] const type identifier = value;
+  [extended-attribute] attribute type identifier;
+  readonly attribute type identifier;
+  attribute type identifier inherits getter; ///Declared to change read only attribute //inherited from interface
+  attribute type identifier getraises (NoSuchValue); ///Exception declaration
+  return-type identifier(arguments…);
+  return-type identifier(argument-type argument-identifier); ///regular operation
+  return-type identifier(optional argument);
+  special-keywords return-type identifier(arguments); ///special operation
+  [extended-attribute]return-type identifier(arguments…); ///A variable number of //arguments
+  return-type identifier(arguments) raises (identifier) ///raises exception
+  caller return-type identifier(argument);
+  caller return-type (argument);
+  static return-type identifier(arguments);
+};
+</code></pre><p>Next step is to connect manager implementation with Tizen object.</p>
+<pre class="prettyprint linenums"><code>Tizen implements ManagerObject
+</code></pre><p>To provide actual implementations of ManagerObject, instance of its Manager
+interface definition has to be made. Inside this Manager interface all attributes
+and functions that will be available form manager namespace, should be defined.
+There can be attributes which are other interfaces, operations and everything
+that interfaces allows.</p>
+<p>Additional interface can be available as a standalone types not connected to
+global namespace. Those are either obtained from operation of other interfaces
+or constructed with theirs constructor method. Interface which are constructible
+are described as follows:</p>
+<pre class="prettyprint linenums"><code>[Constructor(type arg1, optional type? Arg2)]
+Interface ConstructibleInterface {
+  attributes
+  operations
+  an so on...
+};
+</code></pre><p>As one can see list of parameters is specified for such constructor.
+Not all parameters are mandatory, some can be preceded by <code>optional</code>
+keyword and <code>?</code> mark, after type to mark that this is not obligatory argument.
+Additionally some operations can be followed by <code>raises</code> key word to mark that,
+described exception type can be thrown during execution of such method.</p>
+<p>Because some operations can be asynchronous, it is necessary to provide callbacks
+objects that can be executed by such operation. Callback object is special type
+of <code>interface</code> object with <code>Callback=FunctionOnly</code> extended attribute.</p>
+<pre class="prettyprint linenums"><code>[Callback=FunctionOnly, NoInterfaceObject] interface SomeCallback {
+  void someMethod(type agr1, ...)
+};
+</code></pre><p>On the purpose of listeners which accepts dictionaries, there are callbacks that
+support more than one method. There is another definition of callback which
+lacks of keyword <code>FunctionOnly</code>.</p>
+<pre class="prettyprint linenums"><code>[Callback, NoInterfaceObject] interface SomeDictionaryCallback {
+  void firstmethod(type somearg1, ... );
+  void secondmethod(type somearg2, ... );
+  any additional methods...
+};
+</code></pre><h3 id="widl/example">Example</h3>
+<p>Example of WIDL file:</p>
+<pre class="prettyprint linenums"><code>module Sample {
+
+  enum SampleEnums {
+    &quot;ENUM1&quot;,
+    &quot;ENUM2&quot;,
+    &quot;ENUM3&quot;,
+  };
+
+  typedef (SampleEnums) SampleType;
+
+  [NoInterfaceObject] interface SampleManagerObject {
+    readonly attribute SampleManager sample;
+  };
+
+  Tizen implements SampleManagerObject;
+
+  [NoInterfaceObject] interface SampleManager {
+    void sampleMethod(SampleType param1, Sample2 param2) raises(WebAPIException);
+    double sampleMethod2(SampleType param1) raises(WebAPIException);
+    void sampleMethod3(SampleCallback callback) raises(WebAPIException);
+  };
+
+  [Callback=FunctionOnly, NoInterfaceObject]
+  interface SampleCallback {
+    void onsuccess(Sample1 param1, Sample2 param2);
+  };
+};
+</code></pre><h2 id="tools">Tools</h2>
+<h3 id="tools/generate-stub-code">Generate stub code</h3>
+<p>To generate stub files from the widl you can use stub generator located in
+<code>tools/skeleton_generator/</code> directory and run the python command:</p>
+<pre><code class="lang-sh">$ python WAPIOven.py -d &lt;stub code destination directory name&gt; &lt;widl directory/pluginname&gt;.widl
+</code></pre>
+<p>Path to WAPIOven.py:</p>
+<pre><code class="lang-sh">$ tools/skeleton_generator/WAPIOven.py
+</code></pre>
+<p>You need to install jinja2 for WAPIOven.py:</p>
+<pre><code class="lang-sh">$ sudo apt-get install python-jinja2
+</code></pre>
+<p>Example:</p>
+<pre><code class="lang-sh">$ sudo apt-get install python-jinja2
+$ cd tools/skeleton_generator/
+$ python WAPIOven.py -d ../../src/notification/ /web-device-api/web/widl/tizen/notification.widl
+</code></pre>
+<p>WIDL files can be found in the project repository:</p>
+<pre><code class="lang-sh">$ git clone ssh://&lt;username&gt;@168.219.209.56:29418/doc/web-device-api
+</code></pre>
+<p>The widl files are placed in: <code>web-device-api/web/widl/tizen/</code></p>
+<p>Stub files generated by above command:</p>
+<pre><code class="lang-sh">&lt;pluginname&gt;_api.js
+&lt;pluginname&gt;_extension.h
+&lt;pluginname&gt;_extension.cc
+&lt;pluginname&gt;_instance.h
+&lt;pluginname&gt;_instance.cc
+</code></pre>
+<p>What should be done when skeleton code was generated?</p>
+<ul>
+<li><code>&lt;pluginname&gt;.gyp</code> file should be added</li>
+<li>required privileges should be added in JavaScript file</li>
+<li>entry points should be checked in <code>&lt;pluginname&gt;_extension.cc</code> file</li>
+<li>each method should be implemented in <code>&lt;pluginname&gt;_instance.cc</code> file</li>
+</ul>
+<h3 id="tools/using-multiple-javascript-files">Using multiple JavaScript files</h3>
+<p>To use multiple JavaScript files in one plugin create <code>js/</code> directory inside
+plugin directory and place JavaScript files.</p>
+<p>Inside <code>&lt;pluginname&gt;_api.js</code> required JavaScript files should be added:</p>
+<pre><code class="lang-sh">//= require(&#39;common.js&#39;);
+//= require(&#39;calendar_item.js&#39;);
+//= require(&#39;calendar.js&#39;);
+//= require(&#39;calendar_manager.js&#39;);
+//= require(&#39;calendar_attendee.js&#39;);
+//= require(&#39;calendar_alarm.js&#39;);
+//= require(&#39;calendar_recurrence_rule.js&#39;);
+</code></pre>
+<p>To merge all JavaScript files <code>tools/mergejs.py</code> file is used.
+This script merge all files mentioned in <code>&lt;pluginname&gt;_api.js</code> file into one
+file before build process.</p>
+<h2 id="implementation-javascript">Implementation - JavaScript</h2>
+<p>Each plugin contains JavaScript files. This is the place where user input is
+being processed validated before send to C++ layer.</p>
+<p>Badge API will be used to show the creation of JavaScript file (lot of content
+of this file will be already generated via Stub Generator).</p>
+<h3 id="implementation-javascript/interface-creation">Interface creation</h3>
+<p>The WIDL of BadgeManager – main entity that holds all the API methods
+looks like following:</p>
+<pre class="prettyprint linenums"><code>[NoInterfaceObject] interface BadgeManager {
+  readonly attribute long maxBadgeCount
+  void setBadgeCount(ApplicationId appId, long count) raises(WebAPIException);
+  long getBadgeCount(ApplicationId appId) raises(WebAPIException);
+  void addChangeListener(ApplicationId[]appIdList, BadgeChangeCallback successCallback) raises(WebAPIException);
+  void removeChangeListener(ApplicationId[] appIdList) raises(WebAPIException);
+};
+</code></pre><h3 id="implementation-javascript/creating-manager-entity">Creating Manager entity</h3>
+<p>Object that will hold attributes and methods is defined as JavaScript function:</p>
+<pre class="prettyprint linenums"><code class="lang-js">function BadgeManager() {}
+</code></pre>
+<h3 id="implementation-javascript/properties-definition">Properties definition</h3>
+<p>Properties are defined within the created JavaScript function like this:</p>
+<pre class="prettyprint linenums"><code class="lang-js">var MAX_BADGE_COUNT = 999;
+Object.defineProperties(this, {
+  maxBadgeCount: {value: MAX_BADGE_COUNT, emumerable: true, writable: false}
+});
+</code></pre>
+<p>Because the property was defined as <code>const</code>, writable is set to false.</p>
+<h3 id="implementation-javascript/methods-definition">Methods definition</h3>
+<p>In accordance to WIDL BadgeManager contains setBadgeCount method.
+To define this method within JavaScript use prototype extension functionality:</p>
+<pre class="prettyprint linenums"><code class="lang-js">BadgeManager.prototype.setBadgeCount = function() {};
+</code></pre>
+<h3 id="implementation-javascript/exporting-interface">Exporting interface</h3>
+<p>Once the object is created and all the methods and attributes are set it has to
+be exported so it will be visible when making call to tizen.badge namespace.
+This is done using assigning new object instance to exports variable:</p>
+<pre class="prettyprint linenums"><code class="lang-js">exports = new BadgeManager(); //exported as tizen.badge
+exports = new CalendarManager(); //exported as tizen.calendar
+</code></pre>
+<p>Other namespaces within the module are exported as below:</p>
+<pre class="prettyprint linenums"><code class="lang-js">tizen.CalendarAttendee = CalendarAttendee;
+tizen.CalendarEvent = CalendarEvent;
+tizen.CalendarTask = CalendarTask;
+</code></pre>
+<h3 id="implementation-javascript/utils">Utils</h3>
+<p>In <code>src/utils/utils_api.js</code> file there is a lot of useful tools that allow
+automatization of certain operations. Most often used tools from utils_api.js
+are converter and validator. All tools are available under <code>xwalk.utils</code> namespace.</p>
+<h4 id="converter">Converter</h4>
+<p>A lot of times conversion between JavaScript types will be required.
+The converter tool was created in order to make this operation easier.</p>
+<pre class="prettyprint linenums"><code class="lang-js">var converter_ = xwalk.utils.converter;
+var number = converter_.toLong(result);
+</code></pre>
+<h4 id="validator">Validator</h4>
+<p>When API JavaScript method is called first thing that has to be done in
+JavaScript layer of api implementation is to process and validate arguments
+given by the user. The process of validation consists of ensuring that the
+proper amount of arguments was given and that they were of the expected
+type and throwing exception if necessary.</p>
+<p>Validator helps to ensure that user sent proper values. Validator is available
+at <code>xwalk.utils.validator</code> and predefined js types at <code>xwalk.utils.validator.types</code></p>
+<p>Below can be found example of using validator inside <code>setBadgeCount</code> method
+that requires appId in form of string and long count value:</p>
+<pre class="prettyprint linenums"><code class="lang-js">var validator_ = xwalk.utils.validator;
+var types_ = validator_.Types;
+
+var args = validator_.validateArgs(arguments, [
+  {name: &#39;appId&#39;, type: types_.STRING},
+  {name: &#39;count&#39;, type: types_.LONG}
+]);
+</code></pre>
+<h4 id="privileges">Privileges</h4>
+<p>Some of the API methods require privilege access, then it&#39;s the first step
+in JavaScript file which should be checked.</p>
+<p>Below can be found example of using Privilege in Alarm API:</p>
+<pre class="prettyprint linenums"><code class="lang-js">var Privilege = xwalk.utils.privilege;
+
+// inside add, remove, removeAll methods:
+xwalk.utils.checkPrivilegeAccess(Privilege.ALARM);
+</code></pre>
+<h3 id="implementation-javascript/exceptions">Exceptions</h3>
+<p>At some point whether improper data is received or given to JavaScript might
+require to throw exceptions. The example below shows how to throw properly
+predefined exceptions:</p>
+<pre class="prettyprint linenums"><code class="lang-js">throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR,
+                          &#39;Incorrect number of arguments&#39;);
+</code></pre>
+<p>WebAPIException constructor takes as argument the type of error to be thrown.
+The second additional argument is error message.</p>
+<h3 id="implementation-javascript/synchronous-methods">Synchronous methods</h3>
+<p>In order to perform synchronous operation (one that does not require callback
+and the result is given instantly) callSync() method of Native manager needs
+to be called:</p>
+<pre class="prettyprint linenums"><code class="lang-js">var native_ = new xwalk.utils.NativeManager(extension);
+var ret = native_.callSync(&#39;BadgeManager_setBadgeCount&#39;, {
+  appId: args.appId,
+  count: args.count
+});
+if (native_.isFailure(ret)) {
+  throw native_.getErrorObject(ret);
+}
+</code></pre>
+<p>The first argument is the command name registered in C++ layer that has to be called,
+the second is arguments object that will be passed to this method.
+Result is assigned to ret variable.</p>
+<h3 id="implementation-javascript/asynchronous-methods">Asynchronous methods</h3>
+<p>In order to work with method that requires callback instead of callSync(),
+call() method needs to be called. Apart from the first two arguments that are
+exactly the same as in call() method (c++ method binding, object) it takes
+additional argument that is a function that will be called when the native
+call is processed:</p>
+<pre class="prettyprint linenums"><code class="lang-js">var native_ = new xwalk.utils.NativeManager(extension);
+var callback = function(result) {
+  if (native_.isFailure(result)) {
+    native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+  } else {
+    var calendars = native_.getResultObject(result);
+    var c = [];
+    calendars.forEach(function(i) {
+      c.push(new Calendar(new InternalCalendar(i)));
+    });
+    args.successCallback(c);
+  }
+};
+
+native_.call(&#39;CalendarManager_getCalendars&#39;, callArgs, callback);
+</code></pre>
+<h3 id="implementation-javascript/listeners">Listeners</h3>
+<p>In order to work with listeners NativeManager provides <code>addListener</code> and
+<code>removeListener</code> methods. This method takes two arguments: one is unique
+<code>listenerId</code> that will be processed when making a call from C++ to JavaScript.
+The second one is the function that is called whenever expected event occurs.</p>
+<pre class="prettyprint linenums"><code class="lang-js">var native_ = new xwalk.utils.NativeManager(extension);
+var listenerId = &#39;PLUGIN_LISTENER_NAME&#39;;
+native_.addListener(listenerId, function(data) {
+  // handle event data
+});
+native.callSync(&#39;Calendar_addChangeListener&#39;, {
+  type: this.type,
+  listenerId: listenerId
+});
+</code></pre>
+<h2 id="implementation-c">Implementation - C++</h2>
+<h3 id="implementation-c/lifecycle-and-plugin-state">Lifecycle and plugin state</h3>
+<p>All plugins instances are created by runtime on application launch.
+It&#39;s important to not initialize any database/service connections and platform
+handlers in instance constructor. All resources should be &quot;lazy&quot; initialized
+just before first use, to keep starting time as short as possible.
+Initialized resources can be referenced to instance and kept for further usage.
+Instance destructor is called on application termination and should release all
+used resources to prevent memory leaks.</p>
+<p>Native layer should be considered as stateless. It means that there is
+no strict reference between JavaScript and native data.<br>
+Example: If operation should change some object retrieved from platform,
+identifier should be passed again and additional check if object still exists
+should be made.</p>
+<h3 id="implementation-c/namespace-and-entry-points">Namespace and entry points</h3>
+<p>Extension namespace and other objects exported by JavaScript layer are defined
+inside <code>&lt;pluginname&gt;_extension.cc</code> file.</p>
+<pre class="prettyprint linenums"><code class="lang-cpp">SetExtensionName(&quot;tizen.notification&quot;); //exported in JS as new NotificationManager();
+const char* entry_points[] = {&quot;tizen.StatusNotification&quot;,
+                              &quot;tizen.NotificationDetailInfo&quot;,
+                              NULL};
+</code></pre>
+<h3 id="implementation-c/plugin-structure">Plugin structure</h3>
+<p>In general <code>Instance</code> class (<code>&lt;pluginname&gt;_instance.cc</code>) should be
+treated as command dispatcher and should be as small as possible (similar to Controller in MVC).
+It&#39;s responsibility should be limited to reading/validating arguments,
+forwarding call to business logic component and passing result to JavaScript layer.
+Business logic should be implemented in additional classes with
+<a href="http://en.wikipedia.org/wiki/SOLID_(object-oriented_design)">SOLID</a> principles in mind.</p>
+<p>Commands callable from JavaScript layer should be registered in constructor of
+<code>&lt;PluginName&gt;Instance</code> class which extends <code>common::ParsedInstance</code>.</p>
+<pre class="prettyprint linenums"><code class="lang-cpp">// &lt;pluginname&gt;_instance.h
+class MediaControllerInstance : public common::ParsedInstance {}
+</code></pre>
+<p>Currently there is no difference in registering sync and async commands.
+But good practice is to separate them for readability and maintainability.
+Common practice is to define two macros and call <code>RegisterSyncHandler</code>
+method from <code>common::ParsedInstance</code>.</p>
+<pre class="prettyprint linenums"><code class="lang-cpp">// &lt;pluginname&gt;_instance.cc
+MediaControllerInstance::MediaControllerInstance() {
+  #define REGISTER_SYNC(c, x) \
+      RegisterSyncHandler(c, std::bind(&amp;MediaControllerInstance::x, this, _1, _2));
+  #define REGISTER_ASYNC(c, x) \
+      RegisterSyncHandler(c, std::bind(&amp;MediaControllerInstance::x, this, _1, _2));
+
+  REGISTER_SYNC(&quot;MediaControllerManager_getClient&quot;,
+      MediaControllerManagerGetClient);
+  REGISTER_ASYNC(&quot;MediaControllerClient_findServers&quot;,
+      MediaControllerClientFindServers);
+
+  // ... other commands
+
+  #undef REGISTER_SYNC
+  #undef REGISTER_ASYNC
+}
+</code></pre>
+<p>Static method registered as a handler must have proper signature:</p>
+<pre class="prettyprint linenums"><code class="lang-cpp">void InstanceClass::HandlerName(const picojson::value&amp; args, picojson::object&amp; out);
+</code></pre>
+<ul>
+<li><code>args</code> - object containing arguments passed from JavaScript layer</li>
+<li><code>out</code> - object containing response data returned synchronously to JavaScript
+layer.</li>
+</ul>
+<p><code>ReportSuccess()</code> or <code>ReportError()</code> helpers should be used to ensure
+proper structure of <code>out</code> object.</p>
+<pre class="prettyprint linenums"><code class="lang-cpp">picojson::value data = picojson::value&lt;picojson::object());
+const PlatformResult&amp; result = model_-&gt;DoSomethingWithData(&amp;data);
+if (!result) {
+  LOGGER(ERROR) &lt;&lt; result.message();
+  ReportError(result, &amp;out);
+  return;
+}
+
+ReportSuccess(data, out);
+</code></pre>
+<h3 id="implementation-c/asynchronous-calls">Asynchronous calls</h3>
+<p>To perform asynchronous request <code>common::TaskQueue</code> component should be used.
+You should use lambda expression which calls business logic and passes result to
+JavaScript layer by calling <code>PostMessage(const char* msg)</code>.</p>
+<p>Asynchronous response is not matched to request automatically. You should pass
+<code>callbackId</code> received from JavaScript layer as an argument. It allows to
+call the appropriate user callback in JS async message handler.</p>
+<pre class="prettyprint linenums"><code class="lang-cpp">auto search = [this, args]() -&gt; void {
+
+  // business logic
+  picojson::value servers = picojson::value(picojson::array());
+  PlatformResult result = client_-&gt;FindServers(&amp;servers.get&lt;picojson::array&gt;());
+
+  // response object
+  picojson::value response = picojson::value(picojson::object());
+  picojson::object&amp; response_obj = response.get&lt;picojson::object&gt;();
+  response_obj[&quot;callbackId&quot;] = args.get(&quot;callbackId&quot;);
+  if (result) {
+    ReportSuccess(servers, response_obj);
+  } else {
+    ReportError(result, &amp;response_obj);
+  }
+
+  // post JSON string to JS layer
+  PostMessage(response.serialize().c_str());
+};
+
+TaskQueue::GetInstance().Async(search);
+</code></pre>
+<h3 id="implementation-c/listeners">Listeners</h3>
+<p>Sending events from platform listeners is very similar to sending asynchronous
+responses. <code>PostMessage(const char* msg)</code> should be called with <code>listenerId</code>
+passed from JavaScript layer.</p>
+<pre class="prettyprint linenums"><code class="lang-cpp">auto listener = [this, args](picojson::value* data) -&gt; void {
+
+  if (!data) {
+    LOGGER(ERROR) &lt;&lt; &quot;No data passed to json callback&quot;;
+    return;
+  }
+
+  picojson::object&amp; request_o = data-&gt;get&lt;picojson::object&gt;();
+  request_o[&quot;listenerId&quot;] = args.get(&quot;listenerId&quot;);
+
+  PostMessage(data-&gt;serialize().c_str());
+};
+</code></pre>
+<h3 id="implementation-c/logger">Logger</h3>
+<p>Logger is available from <code>common/logger.h</code> header. There are macros:</p>
+<ul>
+<li><code>LOGGER(priority)</code> prints message with given priority</li>
+<li><code>LOGGER_IF(priority, condition)</code> prints message with given priority when condition is met</li>
+</ul>
+<p>Available log priorities are: <code>DEBUG</code>, <code>INFO</code>, <code>WARN</code>, <code>ERROR</code>
+and should be used to filter messages based on level of importance. Example:</p>
+<pre class="prettyprint linenums"><code class="lang-cpp">LOGGER(ERROR) &lt;&lt; &quot;Scan file failed, error: &quot; &lt;&lt; res;
+LOGGER_IF(DEBUG, variable &lt; 0) &lt;&lt; &quot;Value is lower than zero&quot;;
+</code></pre>
+<h3 id="implementation-c/error-handling">Error handling</h3>
+<p>Regarding to <a href="http://google-styleguide.googlecode.com/svn/trunk/cppguide.html#Exceptions">Google C++ Style Guide</a> we do not use Exceptions.</p>
+<p>To deliver error conditions to JavaScript layer, that can occur in the platform,
+<code>PlatformResult</code> class should be used. All available error codes are defined
+in <code>common/platform_result.h</code></p>
+<p>PlatformResult can be returned anywhere in native layer and it should be
+converted to exception and thrown in JavaScript layer:</p>
+<pre class="prettyprint linenums"><code class="lang-cpp">// C++ layer
+return PlatformResult(ErrorCode::NOT_FOUND_ERR, &quot;Cannot remove notification error&quot;);
+return PlatformResult(ErrorCode::UNKNOWN_ERR, &quot;Cannot get notification id error&quot;);
+</code></pre>
+<pre class="prettyprint linenums"><code class="lang-js">// JavaScript layer
+var native_ = new xwalk.utils.NativeManager(extension);
+if (native_.isFailure(ret)) {
+  throw native_.getErrorObject(ret);
+}
+</code></pre>
+<h2 id="devel-package">Devel package</h2>
+<p>After build process webapi-plugins-devel-xxx.rpm should be generated in gbs directory.
+Package contains required common headers files, gypi files and webapi-plugins.pc file.</p>
+<h3 id="devel-package/package-structure">Package structure</h3>
+<pre><code class="lang-sh">|-usr
+|---include
+|-----webapi-plugins
+|-------src
+|---------common
+|-------tools
+|---------gyp
+|-----------pylib
+|-------------gyp
+|---------------generator
+|---lib
+|-----pkgconfig
+</code></pre>
+<p>File webapi-plugins.pc source:</p>
+<pre class="prettyprint linenums"><code>project_name=webapi-plugins
+dirname=tizen-extensions-crosswalk
+prefix=/usr
+exec_prefix=${prefix}
+libdir=${prefix}/lib/${dirname}
+includedir=${prefix}/include/${project_name}/src
+
+Name: ${project_name}
+Description: ${project_name}
+Version:
+Requires: dbus-1 dlog glib-2.0
+Libs: -L${libdir} -ltizen_common
+Cflags: -I${includedir}
+</code></pre><h3 id="devel-package/creating-custom-web-device-plugins-module">Creating custom web device plugins module</h3>
+<p>To create custom web device plugins module <code>webapi-plugins.spec</code>, <code>tizen-wrt.gyp</code> and <code>src</code> files are needed.
+Skeleton below shows the required structure of test module.</p>
+<pre><code class="lang-sh">├── packaging
+│   └── webapi-plugins.spec
+└── src
+│   ├── test
+│   ├── test_api.js
+│   ├── test_extension.cc
+│   ├── test_extension.h
+│   ├── test.gyp
+│   ├── test_instance.cc
+│   └── test_instance.h
+└── tizen-wrt.gyp
+</code></pre>
+<p>webapi-plugins.spec source:</p>
+<pre class="prettyprint linenums"><code>%define _manifestdir %{TZ_SYS_RW_PACKAGES}
+%define _desktop_icondir %{TZ_SYS_SHARE}/icons/default/small
+
+%define crosswalk_extensions tizen-extensions-crosswalk
+
+Name:       webapi-plugins-test
+Version:    0.1
+Release:    0
+License:    Apache-2.0 and BSD-2.0 and MIT
+Group:      Development/Libraries
+Summary:    Tizen Web APIs implemented
+Source0:    %{name}-%{version}.tar.gz
+
+BuildRequires: ninja
+BuildRequires: pkgconfig(webapi-plugins)
+
+%description
+Tizen Test Web APIs.
+
+%prep
+%setup -q
+
+%build
+
+export GYP_GENERATORS=&#39;ninja&#39;
+GYP_OPTIONS=&quot;--depth=. -Dtizen=1 -Dextension_build_type=Debug -Dextension_host_os=%{tizen_profile_name} -Dprivilege_engine=%{tizen_privilege_engine}&quot;
+GYP_OPTIONS=&quot;$GYP_OPTIONS -Ddisplay_type=x11&quot;
+
+/usr/include/webapi-plugins/tools/gyp/gyp $GYP_OPTIONS src/tizen-wrt.gyp
+
+ninja -C out/Default %{?_smp_mflags}
+
+%install
+mkdir -p %{buildroot}%{_libdir}/%{crosswalk_extensions}
+install -p -m 644 out/Default/libtizen*.so %{buildroot}%{_libdir}/%{crosswalk_extensions}
+
+%files
+%{_libdir}/%{crosswalk_extensions}/libtizen*.so
+</code></pre><p>tizen-wrt.gyp source:</p>
+<pre class="prettyprint linenums"><code>{
+  &#39;includes&#39;:[
+    &#39;/usr/include/webapi-plugins/src/common/common.gypi&#39;,
+  ],
+
+  &#39;targets&#39;: [
+    {
+      &#39;target_name&#39;: &#39;extensions&#39;,
+      &#39;type&#39;: &#39;none&#39;,
+      &#39;dependencies&#39;: [
+        &#39;test/test.gyp:*&#39;,
+      ],
+      &#39;conditions&#39;: [],
+    },
+  ],
+}
+</code></pre><p>test.gyp source:</p>
+<pre class="prettyprint linenums"><code>{
+  &#39;includes&#39;:[
+    &#39;/usr/include/webapi-plugins/src/common/common.gypi&#39;,
+  ],
+  &#39;targets&#39;: [
+    {
+      &#39;target_name&#39;: &#39;tizen_test&#39;,
+      &#39;type&#39;: &#39;loadable_module&#39;,
+      &#39;sources&#39;: [
+        &#39;test_api.js&#39;,
+        &#39;test_extension.cc&#39;,
+        &#39;test_extension.h&#39;,
+        &#39;test_instance.cc&#39;,
+        &#39;test_instance.h&#39;,
+      ],
+      &#39;include_dirs&#39;: [
+        &#39;../&#39;,
+        &#39;&lt;(SHARED_INTERMEDIATE_DIR)&#39;,
+      ],
+      &#39;variables&#39;: {
+        &#39;packages&#39;: [
+          &#39;webapi-plugins&#39;,
+        ],
+      },
+    },
+  ],
+}
+</code></pre><p><a href="../src/assets/webapi-plugins-devel-test.zip">webapi-plugins-devel-test.zip</a> contains test module which depends on webapi-plugins devel package.
+Custom web device plugins module test is placed in <code>src/</code> directory and contains all required files.
+Please see <a href="#plugin-structure">Plugin structure</a> chapter for more details.</p>
+<p>To install custom web device plugins module <code>webapi-plugins-xxx.rpm</code> and <code>webapi-plugins-devel-xxx.rpm</code> must be installed first.
+After build and installation webapi-plugins-devel-test <code>tizen.test</code> namespace should be available.</p>
+<pre class="prettyprint linenums"><code class="lang-javascript">var test = tizen.test.ping();
+console.log(test); // Hello!
+</code></pre>
+
+</div>
+<script src="js/mootools-yui-compressed.js"></script>
+<script src="js/moostrap-scrollspy.js"></script>
+<script src="js/prettify.js"></script>
+<script src="js/lang-css.js"></script>
+<script src="js/ace/ace.js" type="text/javascript" charset="utf-8"></script>
+<script src="js/doctor.js"></script>
+</body>
+</html>
diff --git a/webWidgetTCT_device/doc/html/js/blank.html b/webWidgetTCT_device/doc/html/js/blank.html
new file mode 100755 (executable)
index 0000000..e2dcc43
--- /dev/null
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+<head>
+       <title>IFrame test</title>
+</head>
+<body>
+<div id="main"></div>
+<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/require.js/2.1.5/require.min.js"></script>
+<script type="text/javascript">
+       // overrides here.
+       this.require && require.config({
+               baseUrl: '../../'
+       });
+</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/webWidgetTCT_device/doc/html/js/doctor.js b/webWidgetTCT_device/doc/html/js/doctor.js
new file mode 100755 (executable)
index 0000000..f956f67
--- /dev/null
@@ -0,0 +1,136 @@
+/*jshint mootools:true */
+/*global moostrapScrollspy, prettyPrint, ace, IFrame */
+(function(){
+       'use strict';
+
+       var nav = document.id('nav'),
+               main = document.id('content'),
+               runCode = '<span class="glyphicons .glyphicon-play-circle"></span> Run code',
+               closeCode = '<span class="glyphicons .glyphicon-remove"></span> close';
+
+       // convert code blocks that need ace
+       main.getElements('.lang-ace').each(function(el){
+
+               var code = el.get('html'),
+                       parent = el.getParent('pre'),
+                       edit = new Element('div.ace').set('html', code).inject(parent, 'before');
+
+               new Element('div.alert').adopt(
+                       new Element('button.btn.btn-demo.btn-primary[html=' + runCode + ']'),
+                       new Element('button.btn.btn-demo.btn-close.pull-right.btn-danger[html='+ closeCode +']')
+               ).inject(edit, 'after');
+
+               parent.destroy();
+               var editor = ace.edit(edit);
+               editor.setTheme('ace/theme/clouds_midnight');
+               editor.getSession().setMode('ace/mode/javascript');
+               edit.store('editor', editor);
+       });
+
+       // add heading anchors for linking to h2/h3
+       main.getElements('h2,h3').each(function(el){
+               new Element('a', {
+                       html: '&sect;',
+                       title: 'Link to ' + el.get('text'),
+                       'class': 'heading-anchor',
+                       href: '#' + el.get('id')
+               }).inject(el, 'top');
+       });
+
+       // monitor scroll
+       nav && new moostrapScrollspy('sections', {
+               offset: 0,
+               onReady: function(){
+                       this.scroll();
+                       /* may want to overrride this
+                        var handleClicks = function(e, el){
+                        e.stop();
+                        var target = el.get('href');
+                        window.location.hash = target;
+                        body.scrollTo(0, main.getElement(target).getPosition().y - 40);
+                        };
+
+                        this.element.addEvent('click:relay(li > a)', handleClicks);
+                        main.addEvent('click:relay(a[href^=#])', handleClicks);
+                        */
+               },
+               onActive: function(el, target){
+                       var g = el.getParents('li').getLast();
+                       g.addClass('active');
+                       target.addClass('active');
+                       nav.scrollTo(0, g.getPosition(this.element).y);
+               },
+               onInactive: function(el, target){
+                       target.removeClass('active');
+                       this.element.getElements('li.active').removeClass('active');
+               }
+       });
+
+       /**
+        * @description create an iframe to host the code
+        * @param {HTMLElement} el
+        */
+       var buildWindow = function(el, close){
+               var editor = el.getParent().getPrevious().retrieve('editor');
+
+               var uid = Slick.uidOf(close ? el.getPrevious() : el),
+                       iframe = document.id('demoFrame' + uid);
+
+               if (iframe){
+                       iframe.destroy();
+                       iframe = null;
+               }
+
+               if (close){
+                       return;
+               }
+
+               // make example
+               new IFrame({
+                       src: 'js/blank.html',
+                       styles: {
+                               width: '100%',
+                               height: 400
+                       },
+                       'class': 'acely',
+                       id: 'demoFrame' + uid,
+                       events: {
+                               // when blank.html loads, inject the script
+                               load: function(){
+                                       new Element('script', {
+                                               id: 'code',
+                                               type: 'text/javascript',
+                                               text: editor.getValue()
+                                       }).inject(this.contentDocument.body);
+                               }
+                       }
+               }).inject(el.getParent(), 'bottom');
+
+       };
+
+       /**
+        * @description handle the run this code
+        * @param e
+        * @param el
+        * @returns {boolean}
+        */
+       var run = function(e, el){
+               // delegated event handler.
+
+               e && e.stop();
+               var code = el.getPrevious('div.ace') || el.getParent().getPrevious('div.ace');
+
+               if (!code){
+                       return false;
+               }
+
+               //toggleState(el);
+               buildWindow(el, el.hasClass('btn-close'));
+       };
+
+       main.addEvent('click:relay(button.btn-demo)', run);
+
+
+       prettyPrint();
+
+}());
\ No newline at end of file
diff --git a/webWidgetTCT_device/doc/html/js/lang-css.js b/webWidgetTCT_device/doc/html/js/lang-css.js
new file mode 100755 (executable)
index 0000000..d7a4640
--- /dev/null
@@ -0,0 +1,2 @@
+PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\f\r ]+/,null," \t\r\n\u000c"]],[["str",/^"(?:[^\n\f\r"\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*"/,null],["str",/^'(?:[^\n\f\r'\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*'/,null],["lang-css-str",/^url\(([^"')]+)\)/i],["kwd",/^(?:url|rgb|!important|@import|@page|@media|@charset|inherit)(?=[^\w-]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*)\s*:/i],["com",/^\/\*[^*]*\*+(?:[^*/][^*]*\*+)*\//],
+["com",/^(?:<\!--|--\>)/],["lit",/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],["lit",/^#[\da-f]{3,6}\b/i],["pln",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i],["pun",/^[^\s\w"']+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[["kwd",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[["str",/^[^"')]+/]]),["css-str"]);
diff --git a/webWidgetTCT_device/doc/html/js/moostrap-scrollspy.js b/webWidgetTCT_device/doc/html/js/moostrap-scrollspy.js
new file mode 100755 (executable)
index 0000000..fae2f0c
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+---
+
+name: moostrapScrollspy
+
+description: port of twitter scroll spy to mootools
+
+authors: Arian Stolwijk, Dimitar Christoff
+
+license: MIT-style license.
+
+version: 1.03
+
+requires:
+- Core/Event
+- Core/Element
+- Core/Array
+- Core/Class
+
+provides: moostrapScrollspy
+
+...
+*/
+/*jshint evil:true, mootools:true */
+/*global define */
+;(function(exports){
+
+       'use strict';
+
+       var read = function(option, element){
+               // can take a function as argument instead of an element
+               return (option) ? (typeof option === 'function' ? option.call(this, element) : element.get(option)) : '';
+       };
+
+       var wrap = function() {
+               // work as an AMD module or as global
+
+               return new Class({
+
+                       Implements: [Options, Events],
+
+                       options: {
+                               /* supported events:
+                                onReady: function(){},
+                                onActive: function(navEl, TargetEl){},
+                                onInactive: function(navEl, TargetEl){},
+                                onReset: function(){},
+                                */
+                               offset: 0, // adjust the top offset before an item is deemed 'in view'
+                               mask: 'a',
+                               activeClass: 'active',
+                               wrapper: window,
+                               navElementParse: function(el){
+                                       // can override that to grab els based on another criteria
+                                       var prop = el.get('href'),
+                                               target;
+
+                                       prop.slice(0, 1) == '#' && (target = prop.slice(1));
+
+                                       return target;
+                               }
+                       },
+
+                       initialize: function(element, options){
+                               this.setOptions(options);
+
+                               this.element = document.id(element);
+                               this.wrapper = this.options.wrapper;
+                               this.grabElements();
+                               this.attach();
+
+                               return this;
+                       },
+                       grabElements: function(){
+                               var links = this.links = this.element.getElements(this.options.mask);
+                               var elements = this.elements = [];
+                               var prop = this.options.navElementParse;
+
+                               Array.each(links, function(el){
+                                       var target = document.id(read.apply(this, [prop, el]));
+                                       if (target) {
+                                               elements.push(target);
+                                               el.store('navMonitor', target);
+                                       }
+                               });
+
+                               return this;
+                       },
+
+                       attach: function(){
+                               if (!this.boundScroll) this.boundScroll = this.scroll.bind(this);
+                               this.wrapper.addEvent('scroll', this.boundScroll);
+                               this.fireEvent('ready');
+
+                               return this;
+                       },
+
+                       detach: function(){
+                               this.boundScroll && this.wrapper.removeEvent('scroll', this.boundScroll);
+
+                               return this;
+                       },
+
+                       scroll: function(){
+                               var top = this.wrapper.getScroll().y - this.options.offset,
+                                       index,
+                                       relativeTo = this.wrapper == window ? document.body : this.wrapper;
+
+                               Array.some(this.elements, function(el, i){
+                                       var y = el.getPosition(relativeTo).y;
+                                       y <= top && (index = i);
+                                       return y > top;
+                               });
+
+                               if (index != this.active) {
+                                       if (this.active != null) {
+                                               this.links[this.active].removeClass(this.options.activeClass);
+                                               this.fireEvent('inactive', [this.links[this.active], this.elements[this.active]]);
+                                       }
+                                       this.active = index;
+                                       if (index != null) {
+                                               this.links[index].addClass(this.options.activeClass);
+                                               this.fireEvent('active', [this.links[index], this.elements[index]]);
+                                       }
+                               }
+
+                               return this;
+                       },
+
+                       reset: function(){
+                               var self = this;
+
+                               Array.each(this.links, function(link){
+                                       link.removeClass(self.options.activeClass);
+                               });
+
+                               this.active = null;
+                               this.scroll.delay(100, this);
+                               this.fireEvent('reset');
+
+                               return this;
+                       }
+
+               });
+       };
+
+       if (typeof define === 'function' && define.amd) {
+               // returns an empty module
+               define(wrap);
+       }
+       else {
+               exports.moostrapScrollspy = wrap();
+       }
+
+}(this));
\ No newline at end of file
diff --git a/webWidgetTCT_device/doc/html/js/mootools-yui-compressed.js b/webWidgetTCT_device/doc/html/js/mootools-yui-compressed.js
new file mode 100755 (executable)
index 0000000..569473d
--- /dev/null
@@ -0,0 +1,491 @@
+/*
+---
+MooTools: the javascript framework
+
+web build:
+ - http://mootools.net/core/76bf47062d6c1983d66ce47ad66aa0e0
+
+packager build:
+ - packager build Core/Core Core/Array Core/String Core/Number Core/Function Core/Object Core/Event Core/Browser Core/Class Core/Class.Extras Core/Slick.Parser Core/Slick.Finder Core/Element Core/Element.Style Core/Element.Event Core/Element.Delegation Core/Element.Dimensions Core/Fx Core/Fx.CSS Core/Fx.Tween Core/Fx.Morph Core/Fx.Transitions Core/Request Core/Request.HTML Core/Request.JSON Core/Cookie Core/JSON Core/DOMReady Core/Swiff
+
+copyrights:
+  - [MooTools](http://mootools.net)
+
+licenses:
+  - [MIT License](http://mootools.net/license.txt)
+...
+*/
+
+(function(){this.MooTools={version:"1.4.5",build:"ab8ea8824dc3b24b6666867a2c4ed58ebb762cf0"};var o=this.typeOf=function(i){if(i==null){return"null";}if(i.$family!=null){return i.$family();
+}if(i.nodeName){if(i.nodeType==1){return"element";}if(i.nodeType==3){return(/\S/).test(i.nodeValue)?"textnode":"whitespace";}}else{if(typeof i.length=="number"){if(i.callee){return"arguments";
+}if("item" in i){return"collection";}}}return typeof i;};var j=this.instanceOf=function(t,i){if(t==null){return false;}var s=t.$constructor||t.constructor;
+while(s){if(s===i){return true;}s=s.parent;}if(!t.hasOwnProperty){return false;}return t instanceof i;};var f=this.Function;var p=true;for(var k in {toString:1}){p=null;
+}if(p){p=["hasOwnProperty","valueOf","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","constructor"];}f.prototype.overloadSetter=function(s){var i=this;
+return function(u,t){if(u==null){return this;}if(s||typeof u!="string"){for(var v in u){i.call(this,v,u[v]);}if(p){for(var w=p.length;w--;){v=p[w];if(u.hasOwnProperty(v)){i.call(this,v,u[v]);
+}}}}else{i.call(this,u,t);}return this;};};f.prototype.overloadGetter=function(s){var i=this;return function(u){var v,t;if(typeof u!="string"){v=u;}else{if(arguments.length>1){v=arguments;
+}else{if(s){v=[u];}}}if(v){t={};for(var w=0;w<v.length;w++){t[v[w]]=i.call(this,v[w]);}}else{t=i.call(this,u);}return t;};};f.prototype.extend=function(i,s){this[i]=s;
+}.overloadSetter();f.prototype.implement=function(i,s){this.prototype[i]=s;}.overloadSetter();var n=Array.prototype.slice;f.from=function(i){return(o(i)=="function")?i:function(){return i;
+};};Array.from=function(i){if(i==null){return[];}return(a.isEnumerable(i)&&typeof i!="string")?(o(i)=="array")?i:n.call(i):[i];};Number.from=function(s){var i=parseFloat(s);
+return isFinite(i)?i:null;};String.from=function(i){return i+"";};f.implement({hide:function(){this.$hidden=true;return this;},protect:function(){this.$protected=true;
+return this;}});var a=this.Type=function(u,t){if(u){var s=u.toLowerCase();var i=function(v){return(o(v)==s);};a["is"+u]=i;if(t!=null){t.prototype.$family=(function(){return s;
+}).hide();}}if(t==null){return null;}t.extend(this);t.$constructor=a;t.prototype.$constructor=t;return t;};var e=Object.prototype.toString;a.isEnumerable=function(i){return(i!=null&&typeof i.length=="number"&&e.call(i)!="[object Function]");
+};var q={};var r=function(i){var s=o(i.prototype);return q[s]||(q[s]=[]);};var b=function(t,x){if(x&&x.$hidden){return;}var s=r(this);for(var u=0;u<s.length;
+u++){var w=s[u];if(o(w)=="type"){b.call(w,t,x);}else{w.call(this,t,x);}}var v=this.prototype[t];if(v==null||!v.$protected){this.prototype[t]=x;}if(this[t]==null&&o(x)=="function"){m.call(this,t,function(i){return x.apply(i,n.call(arguments,1));
+});}};var m=function(i,t){if(t&&t.$hidden){return;}var s=this[i];if(s==null||!s.$protected){this[i]=t;}};a.implement({implement:b.overloadSetter(),extend:m.overloadSetter(),alias:function(i,s){b.call(this,i,this.prototype[s]);
+}.overloadSetter(),mirror:function(i){r(this).push(i);return this;}});new a("Type",a);var d=function(s,x,v){var u=(x!=Object),B=x.prototype;if(u){x=new a(s,x);
+}for(var y=0,w=v.length;y<w;y++){var C=v[y],A=x[C],z=B[C];if(A){A.protect();}if(u&&z){x.implement(C,z.protect());}}if(u){var t=B.propertyIsEnumerable(v[0]);
+x.forEachMethod=function(G){if(!t){for(var F=0,D=v.length;F<D;F++){G.call(B,B[v[F]],v[F]);}}for(var E in B){G.call(B,B[E],E);}};}return d;};d("String",String,["charAt","charCodeAt","concat","indexOf","lastIndexOf","match","quote","replace","search","slice","split","substr","substring","trim","toLowerCase","toUpperCase"])("Array",Array,["pop","push","reverse","shift","sort","splice","unshift","concat","join","slice","indexOf","lastIndexOf","filter","forEach","every","map","some","reduce","reduceRight"])("Number",Number,["toExponential","toFixed","toLocaleString","toPrecision"])("Function",f,["apply","call","bind"])("RegExp",RegExp,["exec","test"])("Object",Object,["create","defineProperty","defineProperties","keys","getPrototypeOf","getOwnPropertyDescriptor","getOwnPropertyNames","preventExtensions","isExtensible","seal","isSealed","freeze","isFrozen"])("Date",Date,["now"]);
+Object.extend=m.overloadSetter();Date.extend("now",function(){return +(new Date);});new a("Boolean",Boolean);Number.prototype.$family=function(){return isFinite(this)?"number":"null";
+}.hide();Number.extend("random",function(s,i){return Math.floor(Math.random()*(i-s+1)+s);});var g=Object.prototype.hasOwnProperty;Object.extend("forEach",function(i,t,u){for(var s in i){if(g.call(i,s)){t.call(u,i[s],s,i);
+}}});Object.each=Object.forEach;Array.implement({forEach:function(u,v){for(var t=0,s=this.length;t<s;t++){if(t in this){u.call(v,this[t],t,this);}}},each:function(i,s){Array.forEach(this,i,s);
+return this;}});var l=function(i){switch(o(i)){case"array":return i.clone();case"object":return Object.clone(i);default:return i;}};Array.implement("clone",function(){var s=this.length,t=new Array(s);
+while(s--){t[s]=l(this[s]);}return t;});var h=function(s,i,t){switch(o(t)){case"object":if(o(s[i])=="object"){Object.merge(s[i],t);}else{s[i]=Object.clone(t);
+}break;case"array":s[i]=t.clone();break;default:s[i]=t;}return s;};Object.extend({merge:function(z,u,t){if(o(u)=="string"){return h(z,u,t);}for(var y=1,s=arguments.length;
+y<s;y++){var w=arguments[y];for(var x in w){h(z,x,w[x]);}}return z;},clone:function(i){var t={};for(var s in i){t[s]=l(i[s]);}return t;},append:function(w){for(var v=1,t=arguments.length;
+v<t;v++){var s=arguments[v]||{};for(var u in s){w[u]=s[u];}}return w;}});["Object","WhiteSpace","TextNode","Collection","Arguments"].each(function(i){new a(i);
+});var c=Date.now();String.extend("uniqueID",function(){return(c++).toString(36);});})();Array.implement({every:function(c,d){for(var b=0,a=this.length>>>0;
+b<a;b++){if((b in this)&&!c.call(d,this[b],b,this)){return false;}}return true;},filter:function(d,f){var c=[];for(var e,b=0,a=this.length>>>0;b<a;b++){if(b in this){e=this[b];
+if(d.call(f,e,b,this)){c.push(e);}}}return c;},indexOf:function(c,d){var b=this.length>>>0;for(var a=(d<0)?Math.max(0,b+d):d||0;a<b;a++){if(this[a]===c){return a;
+}}return -1;},map:function(c,e){var d=this.length>>>0,b=Array(d);for(var a=0;a<d;a++){if(a in this){b[a]=c.call(e,this[a],a,this);}}return b;},some:function(c,d){for(var b=0,a=this.length>>>0;
+b<a;b++){if((b in this)&&c.call(d,this[b],b,this)){return true;}}return false;},clean:function(){return this.filter(function(a){return a!=null;});},invoke:function(a){var b=Array.slice(arguments,1);
+return this.map(function(c){return c[a].apply(c,b);});},associate:function(c){var d={},b=Math.min(this.length,c.length);for(var a=0;a<b;a++){d[c[a]]=this[a];
+}return d;},link:function(c){var a={};for(var e=0,b=this.length;e<b;e++){for(var d in c){if(c[d](this[e])){a[d]=this[e];delete c[d];break;}}}return a;},contains:function(a,b){return this.indexOf(a,b)!=-1;
+},append:function(a){this.push.apply(this,a);return this;},getLast:function(){return(this.length)?this[this.length-1]:null;},getRandom:function(){return(this.length)?this[Number.random(0,this.length-1)]:null;
+},include:function(a){if(!this.contains(a)){this.push(a);}return this;},combine:function(c){for(var b=0,a=c.length;b<a;b++){this.include(c[b]);}return this;
+},erase:function(b){for(var a=this.length;a--;){if(this[a]===b){this.splice(a,1);}}return this;},empty:function(){this.length=0;return this;},flatten:function(){var d=[];
+for(var b=0,a=this.length;b<a;b++){var c=typeOf(this[b]);if(c=="null"){continue;}d=d.concat((c=="array"||c=="collection"||c=="arguments"||instanceOf(this[b],Array))?Array.flatten(this[b]):this[b]);
+}return d;},pick:function(){for(var b=0,a=this.length;b<a;b++){if(this[b]!=null){return this[b];}}return null;},hexToRgb:function(b){if(this.length!=3){return null;
+}var a=this.map(function(c){if(c.length==1){c+=c;}return c.toInt(16);});return(b)?a:"rgb("+a+")";},rgbToHex:function(d){if(this.length<3){return null;}if(this.length==4&&this[3]==0&&!d){return"transparent";
+}var b=[];for(var a=0;a<3;a++){var c=(this[a]-0).toString(16);b.push((c.length==1)?"0"+c:c);}return(d)?b:"#"+b.join("");}});String.implement({test:function(a,b){return((typeOf(a)=="regexp")?a:new RegExp(""+a,b)).test(this);
+},contains:function(a,b){return(b)?(b+this+b).indexOf(b+a+b)>-1:String(this).indexOf(a)>-1;},trim:function(){return String(this).replace(/^\s+|\s+$/g,"");
+},clean:function(){return String(this).replace(/\s+/g," ").trim();},camelCase:function(){return String(this).replace(/-\D/g,function(a){return a.charAt(1).toUpperCase();
+});},hyphenate:function(){return String(this).replace(/[A-Z]/g,function(a){return("-"+a.charAt(0).toLowerCase());});},capitalize:function(){return String(this).replace(/\b[a-z]/g,function(a){return a.toUpperCase();
+});},escapeRegExp:function(){return String(this).replace(/([-.*+?^${}()|[\]\/\\])/g,"\\$1");},toInt:function(a){return parseInt(this,a||10);},toFloat:function(){return parseFloat(this);
+},hexToRgb:function(b){var a=String(this).match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/);return(a)?a.slice(1).hexToRgb(b):null;},rgbToHex:function(b){var a=String(this).match(/\d{1,3}/g);
+return(a)?a.rgbToHex(b):null;},substitute:function(a,b){return String(this).replace(b||(/\\?\{([^{}]+)\}/g),function(d,c){if(d.charAt(0)=="\\"){return d.slice(1);
+}return(a[c]!=null)?a[c]:"";});}});Number.implement({limit:function(b,a){return Math.min(a,Math.max(b,this));},round:function(a){a=Math.pow(10,a||0).toFixed(a<0?-a:0);
+return Math.round(this*a)/a;},times:function(b,c){for(var a=0;a<this;a++){b.call(c,a,this);}},toFloat:function(){return parseFloat(this);},toInt:function(a){return parseInt(this,a||10);
+}});Number.alias("each","times");(function(b){var a={};b.each(function(c){if(!Number[c]){a[c]=function(){return Math[c].apply(null,[this].concat(Array.from(arguments)));
+};}});Number.implement(a);})(["abs","acos","asin","atan","atan2","ceil","cos","exp","floor","log","max","min","pow","sin","sqrt","tan"]);Function.extend({attempt:function(){for(var b=0,a=arguments.length;
+b<a;b++){try{return arguments[b]();}catch(c){}}return null;}});Function.implement({attempt:function(a,c){try{return this.apply(c,Array.from(a));}catch(b){}return null;
+},bind:function(e){var a=this,b=arguments.length>1?Array.slice(arguments,1):null,d=function(){};var c=function(){var g=e,h=arguments.length;if(this instanceof c){d.prototype=a.prototype;
+g=new d;}var f=(!b&&!h)?a.call(g):a.apply(g,b&&h?b.concat(Array.slice(arguments)):b||arguments);return g==e?f:g;};return c;},pass:function(b,c){var a=this;
+if(b!=null){b=Array.from(b);}return function(){return a.apply(c,b||arguments);};},delay:function(b,c,a){return setTimeout(this.pass((a==null?[]:a),c),b);
+},periodical:function(c,b,a){return setInterval(this.pass((a==null?[]:a),b),c);}});(function(){var a=Object.prototype.hasOwnProperty;Object.extend({subset:function(d,g){var f={};
+for(var e=0,b=g.length;e<b;e++){var c=g[e];if(c in d){f[c]=d[c];}}return f;},map:function(b,e,f){var d={};for(var c in b){if(a.call(b,c)){d[c]=e.call(f,b[c],c,b);
+}}return d;},filter:function(b,e,g){var d={};for(var c in b){var f=b[c];if(a.call(b,c)&&e.call(g,f,c,b)){d[c]=f;}}return d;},every:function(b,d,e){for(var c in b){if(a.call(b,c)&&!d.call(e,b[c],c)){return false;
+}}return true;},some:function(b,d,e){for(var c in b){if(a.call(b,c)&&d.call(e,b[c],c)){return true;}}return false;},keys:function(b){var d=[];for(var c in b){if(a.call(b,c)){d.push(c);
+}}return d;},values:function(c){var b=[];for(var d in c){if(a.call(c,d)){b.push(c[d]);}}return b;},getLength:function(b){return Object.keys(b).length;},keyOf:function(b,d){for(var c in b){if(a.call(b,c)&&b[c]===d){return c;
+}}return null;},contains:function(b,c){return Object.keyOf(b,c)!=null;},toQueryString:function(b,c){var d=[];Object.each(b,function(h,g){if(c){g=c+"["+g+"]";
+}var f;switch(typeOf(h)){case"object":f=Object.toQueryString(h,g);break;case"array":var e={};h.each(function(k,j){e[j]=k;});f=Object.toQueryString(e,g);
+break;default:f=g+"="+encodeURIComponent(h);}if(h!=null){d.push(f);}});return d.join("&");}});})();(function(){var j=this.document;var g=j.window=this;
+var a=navigator.userAgent.toLowerCase(),b=navigator.platform.toLowerCase(),h=a.match(/(opera|ie|firefox|chrome|version)[\s\/:]([\w\d\.]+)?.*?(safari|version[\s\/:]([\w\d\.]+)|$)/)||[null,"unknown",0],d=h[1]=="ie"&&j.documentMode;
+var n=this.Browser={extend:Function.prototype.extend,name:(h[1]=="version")?h[3]:h[1],version:d||parseFloat((h[1]=="opera"&&h[4])?h[4]:h[2]),Platform:{name:a.match(/ip(?:ad|od|hone)/)?"ios":(a.match(/(?:webos|android)/)||b.match(/mac|win|linux/)||["other"])[0]},Features:{xpath:!!(j.evaluate),air:!!(g.runtime),query:!!(j.querySelector),json:!!(g.JSON)},Plugins:{}};
+n[n.name]=true;n[n.name+parseInt(n.version,10)]=true;n.Platform[n.Platform.name]=true;n.Request=(function(){var p=function(){return new XMLHttpRequest();
+};var o=function(){return new ActiveXObject("MSXML2.XMLHTTP");};var e=function(){return new ActiveXObject("Microsoft.XMLHTTP");};return Function.attempt(function(){p();
+return p;},function(){o();return o;},function(){e();return e;});})();n.Features.xhr=!!(n.Request);var i=(Function.attempt(function(){return navigator.plugins["Shockwave Flash"].description;
+},function(){return new ActiveXObject("ShockwaveFlash.ShockwaveFlash").GetVariable("$version");})||"0 r0").match(/\d+/g);n.Plugins.Flash={version:Number(i[0]||"0."+i[1])||0,build:Number(i[2])||0};
+n.exec=function(o){if(!o){return o;}if(g.execScript){g.execScript(o);}else{var e=j.createElement("script");e.setAttribute("type","text/javascript");e.text=o;
+j.head.appendChild(e);j.head.removeChild(e);}return o;};String.implement("stripScripts",function(o){var e="";var p=this.replace(/<script[^>]*>([\s\S]*?)<\/script>/gi,function(q,r){e+=r+"\n";
+return"";});if(o===true){n.exec(e);}else{if(typeOf(o)=="function"){o(e,p);}}return p;});n.extend({Document:this.Document,Window:this.Window,Element:this.Element,Event:this.Event});
+this.Window=this.$constructor=new Type("Window",function(){});this.$family=Function.from("window").hide();Window.mirror(function(e,o){g[e]=o;});this.Document=j.$constructor=new Type("Document",function(){});
+j.$family=Function.from("document").hide();Document.mirror(function(e,o){j[e]=o;});j.html=j.documentElement;if(!j.head){j.head=j.getElementsByTagName("head")[0];
+}if(j.execCommand){try{j.execCommand("BackgroundImageCache",false,true);}catch(f){}}if(this.attachEvent&&!this.addEventListener){var c=function(){this.detachEvent("onunload",c);
+j.head=j.html=j.window=null;};this.attachEvent("onunload",c);}var l=Array.from;try{l(j.html.childNodes);}catch(f){Array.from=function(o){if(typeof o!="string"&&Type.isEnumerable(o)&&typeOf(o)!="array"){var e=o.length,p=new Array(e);
+while(e--){p[e]=o[e];}return p;}return l(o);};var k=Array.prototype,m=k.slice;["pop","push","reverse","shift","sort","splice","unshift","concat","join","slice"].each(function(e){var o=k[e];
+Array[e]=function(p){return o.apply(Array.from(p),m.call(arguments,1));};});}})();(function(){var b={};var a=this.DOMEvent=new Type("DOMEvent",function(c,g){if(!g){g=window;
+}c=c||g.event;if(c.$extended){return c;}this.event=c;this.$extended=true;this.shift=c.shiftKey;this.control=c.ctrlKey;this.alt=c.altKey;this.meta=c.metaKey;
+var i=this.type=c.type;var h=c.target||c.srcElement;while(h&&h.nodeType==3){h=h.parentNode;}this.target=document.id(h);if(i.indexOf("key")==0){var d=this.code=(c.which||c.keyCode);
+this.key=b[d];if(i=="keydown"){if(d>111&&d<124){this.key="f"+(d-111);}else{if(d>95&&d<106){this.key=d-96;}}}if(this.key==null){this.key=String.fromCharCode(d).toLowerCase();
+}}else{if(i=="click"||i=="dblclick"||i=="contextmenu"||i=="DOMMouseScroll"||i.indexOf("mouse")==0){var j=g.document;j=(!j.compatMode||j.compatMode=="CSS1Compat")?j.html:j.body;
+this.page={x:(c.pageX!=null)?c.pageX:c.clientX+j.scrollLeft,y:(c.pageY!=null)?c.pageY:c.clientY+j.scrollTop};this.client={x:(c.pageX!=null)?c.pageX-g.pageXOffset:c.clientX,y:(c.pageY!=null)?c.pageY-g.pageYOffset:c.clientY};
+if(i=="DOMMouseScroll"||i=="mousewheel"){this.wheel=(c.wheelDelta)?c.wheelDelta/120:-(c.detail||0)/3;}this.rightClick=(c.which==3||c.button==2);if(i=="mouseover"||i=="mouseout"){var k=c.relatedTarget||c[(i=="mouseover"?"from":"to")+"Element"];
+while(k&&k.nodeType==3){k=k.parentNode;}this.relatedTarget=document.id(k);}}else{if(i.indexOf("touch")==0||i.indexOf("gesture")==0){this.rotation=c.rotation;
+this.scale=c.scale;this.targetTouches=c.targetTouches;this.changedTouches=c.changedTouches;var f=this.touches=c.touches;if(f&&f[0]){var e=f[0];this.page={x:e.pageX,y:e.pageY};
+this.client={x:e.clientX,y:e.clientY};}}}}if(!this.client){this.client={};}if(!this.page){this.page={};}});a.implement({stop:function(){return this.preventDefault().stopPropagation();
+},stopPropagation:function(){if(this.event.stopPropagation){this.event.stopPropagation();}else{this.event.cancelBubble=true;}return this;},preventDefault:function(){if(this.event.preventDefault){this.event.preventDefault();
+}else{this.event.returnValue=false;}return this;}});a.defineKey=function(d,c){b[d]=c;return this;};a.defineKeys=a.defineKey.overloadSetter(true);a.defineKeys({"38":"up","40":"down","37":"left","39":"right","27":"esc","32":"space","8":"backspace","9":"tab","46":"delete","13":"enter"});
+})();(function(){var a=this.Class=new Type("Class",function(h){if(instanceOf(h,Function)){h={initialize:h};}var g=function(){e(this);if(g.$prototyping){return this;
+}this.$caller=null;var i=(this.initialize)?this.initialize.apply(this,arguments):this;this.$caller=this.caller=null;return i;}.extend(this).implement(h);
+g.$constructor=a;g.prototype.$constructor=g;g.prototype.parent=c;return g;});var c=function(){if(!this.$caller){throw new Error('The method "parent" cannot be called.');
+}var g=this.$caller.$name,h=this.$caller.$owner.parent,i=(h)?h.prototype[g]:null;if(!i){throw new Error('The method "'+g+'" has no parent.');}return i.apply(this,arguments);
+};var e=function(g){for(var h in g){var j=g[h];switch(typeOf(j)){case"object":var i=function(){};i.prototype=j;g[h]=e(new i);break;case"array":g[h]=j.clone();
+break;}}return g;};var b=function(g,h,j){if(j.$origin){j=j.$origin;}var i=function(){if(j.$protected&&this.$caller==null){throw new Error('The method "'+h+'" cannot be called.');
+}var l=this.caller,m=this.$caller;this.caller=m;this.$caller=i;var k=j.apply(this,arguments);this.$caller=m;this.caller=l;return k;}.extend({$owner:g,$origin:j,$name:h});
+return i;};var f=function(h,i,g){if(a.Mutators.hasOwnProperty(h)){i=a.Mutators[h].call(this,i);if(i==null){return this;}}if(typeOf(i)=="function"){if(i.$hidden){return this;
+}this.prototype[h]=(g)?i:b(this,h,i);}else{Object.merge(this.prototype,h,i);}return this;};var d=function(g){g.$prototyping=true;var h=new g;delete g.$prototyping;
+return h;};a.implement("implement",f.overloadSetter());a.Mutators={Extends:function(g){this.parent=g;this.prototype=d(g);},Implements:function(g){Array.from(g).each(function(j){var h=new j;
+for(var i in h){f.call(this,i,h[i],true);}},this);}};})();(function(){this.Chain=new Class({$chain:[],chain:function(){this.$chain.append(Array.flatten(arguments));
+return this;},callChain:function(){return(this.$chain.length)?this.$chain.shift().apply(this,arguments):false;},clearChain:function(){this.$chain.empty();
+return this;}});var a=function(b){return b.replace(/^on([A-Z])/,function(c,d){return d.toLowerCase();});};this.Events=new Class({$events:{},addEvent:function(d,c,b){d=a(d);
+this.$events[d]=(this.$events[d]||[]).include(c);if(b){c.internal=true;}return this;},addEvents:function(b){for(var c in b){this.addEvent(c,b[c]);}return this;
+},fireEvent:function(e,c,b){e=a(e);var d=this.$events[e];if(!d){return this;}c=Array.from(c);d.each(function(f){if(b){f.delay(b,this,c);}else{f.apply(this,c);
+}},this);return this;},removeEvent:function(e,d){e=a(e);var c=this.$events[e];if(c&&!d.internal){var b=c.indexOf(d);if(b!=-1){delete c[b];}}return this;
+},removeEvents:function(d){var e;if(typeOf(d)=="object"){for(e in d){this.removeEvent(e,d[e]);}return this;}if(d){d=a(d);}for(e in this.$events){if(d&&d!=e){continue;
+}var c=this.$events[e];for(var b=c.length;b--;){if(b in c){this.removeEvent(e,c[b]);}}}return this;}});this.Options=new Class({setOptions:function(){var b=this.options=Object.merge.apply(null,[{},this.options].append(arguments));
+if(this.addEvent){for(var c in b){if(typeOf(b[c])!="function"||!(/^on[A-Z]/).test(c)){continue;}this.addEvent(c,b[c]);delete b[c];}}return this;}});})();
+(function(){var k,n,l,g,a={},c={},m=/\\/g;var e=function(q,p){if(q==null){return null;}if(q.Slick===true){return q;}q=(""+q).replace(/^\s+|\s+$/g,"");g=!!p;
+var o=(g)?c:a;if(o[q]){return o[q];}k={Slick:true,expressions:[],raw:q,reverse:function(){return e(this.raw,true);}};n=-1;while(q!=(q=q.replace(j,b))){}k.length=k.expressions.length;
+return o[k.raw]=(g)?h(k):k;};var i=function(o){if(o==="!"){return" ";}else{if(o===" "){return"!";}else{if((/^!/).test(o)){return o.replace(/^!/,"");}else{return"!"+o;
+}}}};var h=function(u){var r=u.expressions;for(var p=0;p<r.length;p++){var t=r[p];var q={parts:[],tag:"*",combinator:i(t[0].combinator)};for(var o=0;o<t.length;
+o++){var s=t[o];if(!s.reverseCombinator){s.reverseCombinator=" ";}s.combinator=s.reverseCombinator;delete s.reverseCombinator;}t.reverse().push(q);}return u;
+};var f=function(o){return o.replace(/[-[\]{}()*+?.\\^$|,#\s]/g,function(p){return"\\"+p;});};var j=new RegExp("^(?:\\s*(,)\\s*|\\s*(<combinator>+)\\s*|(\\s+)|(<unicode>+|\\*)|\\#(<unicode>+)|\\.(<unicode>+)|\\[\\s*(<unicode1>+)(?:\\s*([*^$!~|]?=)(?:\\s*(?:([\"']?)(.*?)\\9)))?\\s*\\](?!\\])|(:+)(<unicode>+)(?:\\((?:(?:([\"'])([^\\13]*)\\13)|((?:\\([^)]+\\)|[^()]*)+))\\))?)".replace(/<combinator>/,"["+f(">+~`!@$%^&={}\\;</")+"]").replace(/<unicode>/g,"(?:[\\w\\u00a1-\\uFFFF-]|\\\\[^\\s0-9a-f])").replace(/<unicode1>/g,"(?:[:\\w\\u00a1-\\uFFFF-]|\\\\[^\\s0-9a-f])"));
+function b(x,s,D,z,r,C,q,B,A,y,u,F,G,v,p,w){if(s||n===-1){k.expressions[++n]=[];l=-1;if(s){return"";}}if(D||z||l===-1){D=D||" ";var t=k.expressions[n];
+if(g&&t[l]){t[l].reverseCombinator=i(D);}t[++l]={combinator:D,tag:"*"};}var o=k.expressions[n][l];if(r){o.tag=r.replace(m,"");}else{if(C){o.id=C.replace(m,"");
+}else{if(q){q=q.replace(m,"");if(!o.classList){o.classList=[];}if(!o.classes){o.classes=[];}o.classList.push(q);o.classes.push({value:q,regexp:new RegExp("(^|\\s)"+f(q)+"(\\s|$)")});
+}else{if(G){w=w||p;w=w?w.replace(m,""):null;if(!o.pseudos){o.pseudos=[];}o.pseudos.push({key:G.replace(m,""),value:w,type:F.length==1?"class":"element"});
+}else{if(B){B=B.replace(m,"");u=(u||"").replace(m,"");var E,H;switch(A){case"^=":H=new RegExp("^"+f(u));break;case"$=":H=new RegExp(f(u)+"$");break;case"~=":H=new RegExp("(^|\\s)"+f(u)+"(\\s|$)");
+break;case"|=":H=new RegExp("^"+f(u)+"(-|$)");break;case"=":E=function(I){return u==I;};break;case"*=":E=function(I){return I&&I.indexOf(u)>-1;};break;
+case"!=":E=function(I){return u!=I;};break;default:E=function(I){return !!I;};}if(u==""&&(/^[*$^]=$/).test(A)){E=function(){return false;};}if(!E){E=function(I){return I&&H.test(I);
+};}if(!o.attributes){o.attributes=[];}o.attributes.push({key:B,operator:A,value:u,test:E});}}}}}return"";}var d=(this.Slick||{});d.parse=function(o){return e(o);
+};d.escapeRegExp=f;if(!this.Slick){this.Slick=d;}}).apply((typeof exports!="undefined")?exports:this);(function(){var k={},m={},d=Object.prototype.toString;
+k.isNativeCode=function(c){return(/\{\s*\[native code\]\s*\}/).test(""+c);};k.isXML=function(c){return(!!c.xmlVersion)||(!!c.xml)||(d.call(c)=="[object XMLDocument]")||(c.nodeType==9&&c.documentElement.nodeName!="HTML");
+};k.setDocument=function(w){var p=w.nodeType;if(p==9){}else{if(p){w=w.ownerDocument;}else{if(w.navigator){w=w.document;}else{return;}}}if(this.document===w){return;
+}this.document=w;var A=w.documentElement,o=this.getUIDXML(A),s=m[o],r;if(s){for(r in s){this[r]=s[r];}return;}s=m[o]={};s.root=A;s.isXMLDocument=this.isXML(w);
+s.brokenStarGEBTN=s.starSelectsClosedQSA=s.idGetsName=s.brokenMixedCaseQSA=s.brokenGEBCN=s.brokenCheckedQSA=s.brokenEmptyAttributeQSA=s.isHTMLDocument=s.nativeMatchesSelector=false;
+var q,u,y,z,t;var x,v="slick_uniqueid";var c=w.createElement("div");var n=w.body||w.getElementsByTagName("body")[0]||A;n.appendChild(c);try{c.innerHTML='<a id="'+v+'"></a>';
+s.isHTMLDocument=!!w.getElementById(v);}catch(C){}if(s.isHTMLDocument){c.style.display="none";c.appendChild(w.createComment(""));u=(c.getElementsByTagName("*").length>1);
+try{c.innerHTML="foo</foo>";x=c.getElementsByTagName("*");q=(x&&!!x.length&&x[0].nodeName.charAt(0)=="/");}catch(C){}s.brokenStarGEBTN=u||q;try{c.innerHTML='<a name="'+v+'"></a><b id="'+v+'"></b>';
+s.idGetsName=w.getElementById(v)===c.firstChild;}catch(C){}if(c.getElementsByClassName){try{c.innerHTML='<a class="f"></a><a class="b"></a>';c.getElementsByClassName("b").length;
+c.firstChild.className="b";z=(c.getElementsByClassName("b").length!=2);}catch(C){}try{c.innerHTML='<a class="a"></a><a class="f b a"></a>';y=(c.getElementsByClassName("a").length!=2);
+}catch(C){}s.brokenGEBCN=z||y;}if(c.querySelectorAll){try{c.innerHTML="foo</foo>";x=c.querySelectorAll("*");s.starSelectsClosedQSA=(x&&!!x.length&&x[0].nodeName.charAt(0)=="/");
+}catch(C){}try{c.innerHTML='<a class="MiX"></a>';s.brokenMixedCaseQSA=!c.querySelectorAll(".MiX").length;}catch(C){}try{c.innerHTML='<select><option selected="selected">a</option></select>';
+s.brokenCheckedQSA=(c.querySelectorAll(":checked").length==0);}catch(C){}try{c.innerHTML='<a class=""></a>';s.brokenEmptyAttributeQSA=(c.querySelectorAll('[class*=""]').length!=0);
+}catch(C){}}try{c.innerHTML='<form action="s"><input id="action"/></form>';t=(c.firstChild.getAttribute("action")!="s");}catch(C){}s.nativeMatchesSelector=A.matchesSelector||A.mozMatchesSelector||A.webkitMatchesSelector;
+if(s.nativeMatchesSelector){try{s.nativeMatchesSelector.call(A,":slick");s.nativeMatchesSelector=null;}catch(C){}}}try{A.slick_expando=1;delete A.slick_expando;
+s.getUID=this.getUIDHTML;}catch(C){s.getUID=this.getUIDXML;}n.removeChild(c);c=x=n=null;s.getAttribute=(s.isHTMLDocument&&t)?function(G,E){var H=this.attributeGetters[E];
+if(H){return H.call(G);}var F=G.getAttributeNode(E);return(F)?F.nodeValue:null;}:function(F,E){var G=this.attributeGetters[E];return(G)?G.call(F):F.getAttribute(E);
+};s.hasAttribute=(A&&this.isNativeCode(A.hasAttribute))?function(F,E){return F.hasAttribute(E);}:function(F,E){F=F.getAttributeNode(E);return !!(F&&(F.specified||F.nodeValue));
+};var D=A&&this.isNativeCode(A.contains),B=w&&this.isNativeCode(w.contains);s.contains=(D&&B)?function(E,F){return E.contains(F);}:(D&&!B)?function(E,F){return E===F||((E===w)?w.documentElement:E).contains(F);
+}:(A&&A.compareDocumentPosition)?function(E,F){return E===F||!!(E.compareDocumentPosition(F)&16);}:function(E,F){if(F){do{if(F===E){return true;}}while((F=F.parentNode));
+}return false;};s.documentSorter=(A.compareDocumentPosition)?function(F,E){if(!F.compareDocumentPosition||!E.compareDocumentPosition){return 0;}return F.compareDocumentPosition(E)&4?-1:F===E?0:1;
+}:("sourceIndex" in A)?function(F,E){if(!F.sourceIndex||!E.sourceIndex){return 0;}return F.sourceIndex-E.sourceIndex;}:(w.createRange)?function(H,F){if(!H.ownerDocument||!F.ownerDocument){return 0;
+}var G=H.ownerDocument.createRange(),E=F.ownerDocument.createRange();G.setStart(H,0);G.setEnd(H,0);E.setStart(F,0);E.setEnd(F,0);return G.compareBoundaryPoints(Range.START_TO_END,E);
+}:null;A=null;for(r in s){this[r]=s[r];}};var f=/^([#.]?)((?:[\w-]+|\*))$/,h=/\[.+[*$^]=(?:""|'')?\]/,g={};k.search=function(U,z,H,s){var p=this.found=(s)?null:(H||[]);
+if(!U){return p;}else{if(U.navigator){U=U.document;}else{if(!U.nodeType){return p;}}}var F,O,V=this.uniques={},I=!!(H&&H.length),y=(U.nodeType==9);if(this.document!==(y?U:U.ownerDocument)){this.setDocument(U);
+}if(I){for(O=p.length;O--;){V[this.getUID(p[O])]=true;}}if(typeof z=="string"){var r=z.match(f);simpleSelectors:if(r){var u=r[1],v=r[2],A,E;if(!u){if(v=="*"&&this.brokenStarGEBTN){break simpleSelectors;
+}E=U.getElementsByTagName(v);if(s){return E[0]||null;}for(O=0;A=E[O++];){if(!(I&&V[this.getUID(A)])){p.push(A);}}}else{if(u=="#"){if(!this.isHTMLDocument||!y){break simpleSelectors;
+}A=U.getElementById(v);if(!A){return p;}if(this.idGetsName&&A.getAttributeNode("id").nodeValue!=v){break simpleSelectors;}if(s){return A||null;}if(!(I&&V[this.getUID(A)])){p.push(A);
+}}else{if(u=="."){if(!this.isHTMLDocument||((!U.getElementsByClassName||this.brokenGEBCN)&&U.querySelectorAll)){break simpleSelectors;}if(U.getElementsByClassName&&!this.brokenGEBCN){E=U.getElementsByClassName(v);
+if(s){return E[0]||null;}for(O=0;A=E[O++];){if(!(I&&V[this.getUID(A)])){p.push(A);}}}else{var T=new RegExp("(^|\\s)"+e.escapeRegExp(v)+"(\\s|$)");E=U.getElementsByTagName("*");
+for(O=0;A=E[O++];){className=A.className;if(!(className&&T.test(className))){continue;}if(s){return A;}if(!(I&&V[this.getUID(A)])){p.push(A);}}}}}}if(I){this.sort(p);
+}return(s)?null:p;}querySelector:if(U.querySelectorAll){if(!this.isHTMLDocument||g[z]||this.brokenMixedCaseQSA||(this.brokenCheckedQSA&&z.indexOf(":checked")>-1)||(this.brokenEmptyAttributeQSA&&h.test(z))||(!y&&z.indexOf(",")>-1)||e.disableQSA){break querySelector;
+}var S=z,x=U;if(!y){var C=x.getAttribute("id"),t="slickid__";x.setAttribute("id",t);S="#"+t+" "+S;U=x.parentNode;}try{if(s){return U.querySelector(S)||null;
+}else{E=U.querySelectorAll(S);}}catch(Q){g[z]=1;break querySelector;}finally{if(!y){if(C){x.setAttribute("id",C);}else{x.removeAttribute("id");}U=x;}}if(this.starSelectsClosedQSA){for(O=0;
+A=E[O++];){if(A.nodeName>"@"&&!(I&&V[this.getUID(A)])){p.push(A);}}}else{for(O=0;A=E[O++];){if(!(I&&V[this.getUID(A)])){p.push(A);}}}if(I){this.sort(p);
+}return p;}F=this.Slick.parse(z);if(!F.length){return p;}}else{if(z==null){return p;}else{if(z.Slick){F=z;}else{if(this.contains(U.documentElement||U,z)){(p)?p.push(z):p=z;
+return p;}else{return p;}}}}this.posNTH={};this.posNTHLast={};this.posNTHType={};this.posNTHTypeLast={};this.push=(!I&&(s||(F.length==1&&F.expressions[0].length==1)))?this.pushArray:this.pushUID;
+if(p==null){p=[];}var M,L,K;var B,J,D,c,q,G,W;var N,P,o,w,R=F.expressions;search:for(O=0;(P=R[O]);O++){for(M=0;(o=P[M]);M++){B="combinator:"+o.combinator;
+if(!this[B]){continue search;}J=(this.isXMLDocument)?o.tag:o.tag.toUpperCase();D=o.id;c=o.classList;q=o.classes;G=o.attributes;W=o.pseudos;w=(M===(P.length-1));
+this.bitUniques={};if(w){this.uniques=V;this.found=p;}else{this.uniques={};this.found=[];}if(M===0){this[B](U,J,D,q,G,W,c);if(s&&w&&p.length){break search;
+}}else{if(s&&w){for(L=0,K=N.length;L<K;L++){this[B](N[L],J,D,q,G,W,c);if(p.length){break search;}}}else{for(L=0,K=N.length;L<K;L++){this[B](N[L],J,D,q,G,W,c);
+}}}N=this.found;}}if(I||(F.expressions.length>1)){this.sort(p);}return(s)?(p[0]||null):p;};k.uidx=1;k.uidk="slick-uniqueid";k.getUIDXML=function(n){var c=n.getAttribute(this.uidk);
+if(!c){c=this.uidx++;n.setAttribute(this.uidk,c);}return c;};k.getUIDHTML=function(c){return c.uniqueNumber||(c.uniqueNumber=this.uidx++);};k.sort=function(c){if(!this.documentSorter){return c;
+}c.sort(this.documentSorter);return c;};k.cacheNTH={};k.matchNTH=/^([+-]?\d*)?([a-z]+)?([+-]\d+)?$/;k.parseNTHArgument=function(q){var o=q.match(this.matchNTH);
+if(!o){return false;}var p=o[2]||false;var n=o[1]||1;if(n=="-"){n=-1;}var c=+o[3]||0;o=(p=="n")?{a:n,b:c}:(p=="odd")?{a:2,b:1}:(p=="even")?{a:2,b:0}:{a:0,b:n};
+return(this.cacheNTH[q]=o);};k.createNTHPseudo=function(p,n,c,o){return function(s,q){var u=this.getUID(s);if(!this[c][u]){var A=s.parentNode;if(!A){return false;
+}var r=A[p],t=1;if(o){var z=s.nodeName;do{if(r.nodeName!=z){continue;}this[c][this.getUID(r)]=t++;}while((r=r[n]));}else{do{if(r.nodeType!=1){continue;
+}this[c][this.getUID(r)]=t++;}while((r=r[n]));}}q=q||"n";var v=this.cacheNTH[q]||this.parseNTHArgument(q);if(!v){return false;}var y=v.a,x=v.b,w=this[c][u];
+if(y==0){return x==w;}if(y>0){if(w<x){return false;}}else{if(x<w){return false;}}return((w-x)%y)==0;};};k.pushArray=function(p,c,r,o,n,q){if(this.matchSelector(p,c,r,o,n,q)){this.found.push(p);
+}};k.pushUID=function(q,c,s,p,n,r){var o=this.getUID(q);if(!this.uniques[o]&&this.matchSelector(q,c,s,p,n,r)){this.uniques[o]=true;this.found.push(q);}};
+k.matchNode=function(n,o){if(this.isHTMLDocument&&this.nativeMatchesSelector){try{return this.nativeMatchesSelector.call(n,o.replace(/\[([^=]+)=\s*([^'"\]]+?)\s*\]/g,'[$1="$2"]'));
+}catch(u){}}var t=this.Slick.parse(o);if(!t){return true;}var r=t.expressions,s=0,q;for(q=0;(currentExpression=r[q]);q++){if(currentExpression.length==1){var p=currentExpression[0];
+if(this.matchSelector(n,(this.isXMLDocument)?p.tag:p.tag.toUpperCase(),p.id,p.classes,p.attributes,p.pseudos)){return true;}s++;}}if(s==t.length){return false;
+}var c=this.search(this.document,t),v;for(q=0;v=c[q++];){if(v===n){return true;}}return false;};k.matchPseudo=function(q,c,p){var n="pseudo:"+c;if(this[n]){return this[n](q,p);
+}var o=this.getAttribute(q,c);return(p)?p==o:!!o;};k.matchSelector=function(o,v,c,p,q,s){if(v){var t=(this.isXMLDocument)?o.nodeName:o.nodeName.toUpperCase();
+if(v=="*"){if(t<"@"){return false;}}else{if(t!=v){return false;}}}if(c&&o.getAttribute("id")!=c){return false;}var r,n,u;if(p){for(r=p.length;r--;){u=this.getAttribute(o,"class");
+if(!(u&&p[r].regexp.test(u))){return false;}}}if(q){for(r=q.length;r--;){n=q[r];if(n.operator?!n.test(this.getAttribute(o,n.key)):!this.hasAttribute(o,n.key)){return false;
+}}}if(s){for(r=s.length;r--;){n=s[r];if(!this.matchPseudo(o,n.key,n.value)){return false;}}}return true;};var j={" ":function(q,w,n,r,s,u,p){var t,v,o;
+if(this.isHTMLDocument){getById:if(n){v=this.document.getElementById(n);if((!v&&q.all)||(this.idGetsName&&v&&v.getAttributeNode("id").nodeValue!=n)){o=q.all[n];
+if(!o){return;}if(!o[0]){o=[o];}for(t=0;v=o[t++];){var c=v.getAttributeNode("id");if(c&&c.nodeValue==n){this.push(v,w,null,r,s,u);break;}}return;}if(!v){if(this.contains(this.root,q)){return;
+}else{break getById;}}else{if(this.document!==q&&!this.contains(q,v)){return;}}this.push(v,w,null,r,s,u);return;}getByClass:if(r&&q.getElementsByClassName&&!this.brokenGEBCN){o=q.getElementsByClassName(p.join(" "));
+if(!(o&&o.length)){break getByClass;}for(t=0;v=o[t++];){this.push(v,w,n,null,s,u);}return;}}getByTag:{o=q.getElementsByTagName(w);if(!(o&&o.length)){break getByTag;
+}if(!this.brokenStarGEBTN){w=null;}for(t=0;v=o[t++];){this.push(v,w,n,r,s,u);}}},">":function(p,c,r,o,n,q){if((p=p.firstChild)){do{if(p.nodeType==1){this.push(p,c,r,o,n,q);
+}}while((p=p.nextSibling));}},"+":function(p,c,r,o,n,q){while((p=p.nextSibling)){if(p.nodeType==1){this.push(p,c,r,o,n,q);break;}}},"^":function(p,c,r,o,n,q){p=p.firstChild;
+if(p){if(p.nodeType==1){this.push(p,c,r,o,n,q);}else{this["combinator:+"](p,c,r,o,n,q);}}},"~":function(q,c,s,p,n,r){while((q=q.nextSibling)){if(q.nodeType!=1){continue;
+}var o=this.getUID(q);if(this.bitUniques[o]){break;}this.bitUniques[o]=true;this.push(q,c,s,p,n,r);}},"++":function(p,c,r,o,n,q){this["combinator:+"](p,c,r,o,n,q);
+this["combinator:!+"](p,c,r,o,n,q);},"~~":function(p,c,r,o,n,q){this["combinator:~"](p,c,r,o,n,q);this["combinator:!~"](p,c,r,o,n,q);},"!":function(p,c,r,o,n,q){while((p=p.parentNode)){if(p!==this.document){this.push(p,c,r,o,n,q);
+}}},"!>":function(p,c,r,o,n,q){p=p.parentNode;if(p!==this.document){this.push(p,c,r,o,n,q);}},"!+":function(p,c,r,o,n,q){while((p=p.previousSibling)){if(p.nodeType==1){this.push(p,c,r,o,n,q);
+break;}}},"!^":function(p,c,r,o,n,q){p=p.lastChild;if(p){if(p.nodeType==1){this.push(p,c,r,o,n,q);}else{this["combinator:!+"](p,c,r,o,n,q);}}},"!~":function(q,c,s,p,n,r){while((q=q.previousSibling)){if(q.nodeType!=1){continue;
+}var o=this.getUID(q);if(this.bitUniques[o]){break;}this.bitUniques[o]=true;this.push(q,c,s,p,n,r);}}};for(var i in j){k["combinator:"+i]=j[i];}var l={empty:function(c){var n=c.firstChild;
+return !(n&&n.nodeType==1)&&!(c.innerText||c.textContent||"").length;},not:function(c,n){return !this.matchNode(c,n);},contains:function(c,n){return(c.innerText||c.textContent||"").indexOf(n)>-1;
+},"first-child":function(c){while((c=c.previousSibling)){if(c.nodeType==1){return false;}}return true;},"last-child":function(c){while((c=c.nextSibling)){if(c.nodeType==1){return false;
+}}return true;},"only-child":function(o){var n=o;while((n=n.previousSibling)){if(n.nodeType==1){return false;}}var c=o;while((c=c.nextSibling)){if(c.nodeType==1){return false;
+}}return true;},"nth-child":k.createNTHPseudo("firstChild","nextSibling","posNTH"),"nth-last-child":k.createNTHPseudo("lastChild","previousSibling","posNTHLast"),"nth-of-type":k.createNTHPseudo("firstChild","nextSibling","posNTHType",true),"nth-last-of-type":k.createNTHPseudo("lastChild","previousSibling","posNTHTypeLast",true),index:function(n,c){return this["pseudo:nth-child"](n,""+(c+1));
+},even:function(c){return this["pseudo:nth-child"](c,"2n");},odd:function(c){return this["pseudo:nth-child"](c,"2n+1");},"first-of-type":function(c){var n=c.nodeName;
+while((c=c.previousSibling)){if(c.nodeName==n){return false;}}return true;},"last-of-type":function(c){var n=c.nodeName;while((c=c.nextSibling)){if(c.nodeName==n){return false;
+}}return true;},"only-of-type":function(o){var n=o,p=o.nodeName;while((n=n.previousSibling)){if(n.nodeName==p){return false;}}var c=o;while((c=c.nextSibling)){if(c.nodeName==p){return false;
+}}return true;},enabled:function(c){return !c.disabled;},disabled:function(c){return c.disabled;},checked:function(c){return c.checked||c.selected;},focus:function(c){return this.isHTMLDocument&&this.document.activeElement===c&&(c.href||c.type||this.hasAttribute(c,"tabindex"));
+},root:function(c){return(c===this.root);},selected:function(c){return c.selected;}};for(var b in l){k["pseudo:"+b]=l[b];}var a=k.attributeGetters={"for":function(){return("htmlFor" in this)?this.htmlFor:this.getAttribute("for");
+},href:function(){return("href" in this)?this.getAttribute("href",2):this.getAttribute("href");},style:function(){return(this.style)?this.style.cssText:this.getAttribute("style");
+},tabindex:function(){var c=this.getAttributeNode("tabindex");return(c&&c.specified)?c.nodeValue:null;},type:function(){return this.getAttribute("type");
+},maxlength:function(){var c=this.getAttributeNode("maxLength");return(c&&c.specified)?c.nodeValue:null;}};a.MAXLENGTH=a.maxLength=a.maxlength;var e=k.Slick=(this.Slick||{});
+e.version="1.1.7";e.search=function(n,o,c){return k.search(n,o,c);};e.find=function(c,n){return k.search(c,n,null,true);};e.contains=function(c,n){k.setDocument(c);
+return k.contains(c,n);};e.getAttribute=function(n,c){k.setDocument(n);return k.getAttribute(n,c);};e.hasAttribute=function(n,c){k.setDocument(n);return k.hasAttribute(n,c);
+};e.match=function(n,c){if(!(n&&c)){return false;}if(!c||c===n){return true;}k.setDocument(n);return k.matchNode(n,c);};e.defineAttributeGetter=function(c,n){k.attributeGetters[c]=n;
+return this;};e.lookupAttributeGetter=function(c){return k.attributeGetters[c];};e.definePseudo=function(c,n){k["pseudo:"+c]=function(p,o){return n.call(p,o);
+};return this;};e.lookupPseudo=function(c){var n=k["pseudo:"+c];if(n){return function(o){return n.call(this,o);};}return null;};e.override=function(n,c){k.override(n,c);
+return this;};e.isXML=k.isXML;e.uidOf=function(c){return k.getUIDHTML(c);};if(!this.Slick){this.Slick=e;}}).apply((typeof exports!="undefined")?exports:this);
+var Element=function(b,g){var h=Element.Constructors[b];if(h){return h(g);}if(typeof b!="string"){return document.id(b).set(g);}if(!g){g={};}if(!(/^[\w-]+$/).test(b)){var e=Slick.parse(b).expressions[0][0];
+b=(e.tag=="*")?"div":e.tag;if(e.id&&g.id==null){g.id=e.id;}var d=e.attributes;if(d){for(var a,f=0,c=d.length;f<c;f++){a=d[f];if(g[a.key]!=null){continue;
+}if(a.value!=null&&a.operator=="="){g[a.key]=a.value;}else{if(!a.value&&!a.operator){g[a.key]=true;}}}}if(e.classList&&g["class"]==null){g["class"]=e.classList.join(" ");
+}}return document.newElement(b,g);};if(Browser.Element){Element.prototype=Browser.Element.prototype;Element.prototype._fireEvent=(function(a){return function(b,c){return a.call(this,b,c);
+};})(Element.prototype.fireEvent);}new Type("Element",Element).mirror(function(a){if(Array.prototype[a]){return;}var b={};b[a]=function(){var h=[],e=arguments,j=true;
+for(var g=0,d=this.length;g<d;g++){var f=this[g],c=h[g]=f[a].apply(f,e);j=(j&&typeOf(c)=="element");}return(j)?new Elements(h):h;};Elements.implement(b);
+});if(!Browser.Element){Element.parent=Object;Element.Prototype={"$constructor":Element,"$family":Function.from("element").hide()};Element.mirror(function(a,b){Element.Prototype[a]=b;
+});}Element.Constructors={};var IFrame=new Type("IFrame",function(){var e=Array.link(arguments,{properties:Type.isObject,iframe:function(f){return(f!=null);
+}});var c=e.properties||{},b;if(e.iframe){b=document.id(e.iframe);}var d=c.onload||function(){};delete c.onload;c.id=c.name=[c.id,c.name,b?(b.id||b.name):"IFrame_"+String.uniqueID()].pick();
+b=new Element(b||"iframe",c);var a=function(){d.call(b.contentWindow);};if(window.frames[c.id]){a();}else{b.addListener("load",a);}return b;});var Elements=this.Elements=function(a){if(a&&a.length){var e={},d;
+for(var c=0;d=a[c++];){var b=Slick.uidOf(d);if(!e[b]){e[b]=true;this.push(d);}}}};Elements.prototype={length:0};Elements.parent=Array;new Type("Elements",Elements).implement({filter:function(a,b){if(!a){return this;
+}return new Elements(Array.filter(this,(typeOf(a)=="string")?function(c){return c.match(a);}:a,b));}.protect(),push:function(){var d=this.length;for(var b=0,a=arguments.length;
+b<a;b++){var c=document.id(arguments[b]);if(c){this[d++]=c;}}return(this.length=d);}.protect(),unshift:function(){var b=[];for(var c=0,a=arguments.length;
+c<a;c++){var d=document.id(arguments[c]);if(d){b.push(d);}}return Array.prototype.unshift.apply(this,b);}.protect(),concat:function(){var b=new Elements(this);
+for(var c=0,a=arguments.length;c<a;c++){var d=arguments[c];if(Type.isEnumerable(d)){b.append(d);}else{b.push(d);}}return b;}.protect(),append:function(c){for(var b=0,a=c.length;
+b<a;b++){this.push(c[b]);}return this;}.protect(),empty:function(){while(this.length){delete this[--this.length];}return this;}.protect()});(function(){var f=Array.prototype.splice,a={"0":0,"1":1,length:2};
+f.call(a,1,1);if(a[1]==1){Elements.implement("splice",function(){var g=this.length;var e=f.apply(this,arguments);while(g>=this.length){delete this[g--];
+}return e;}.protect());}Array.forEachMethod(function(g,e){Elements.implement(e,g);});Array.mirror(Elements);var d;try{d=(document.createElement("<input name=x>").name=="x");
+}catch(b){}var c=function(e){return(""+e).replace(/&/g,"&amp;").replace(/"/g,"&quot;");};Document.implement({newElement:function(e,g){if(g&&g.checked!=null){g.defaultChecked=g.checked;
+}if(d&&g){e="<"+e;if(g.name){e+=' name="'+c(g.name)+'"';}if(g.type){e+=' type="'+c(g.type)+'"';}e+=">";delete g.name;delete g.type;}return this.id(this.createElement(e)).set(g);
+}});})();(function(){Slick.uidOf(window);Slick.uidOf(document);Document.implement({newTextNode:function(e){return this.createTextNode(e);},getDocument:function(){return this;
+},getWindow:function(){return this.window;},id:(function(){var e={string:function(E,D,l){E=Slick.find(l,"#"+E.replace(/(\W)/g,"\\$1"));return(E)?e.element(E,D):null;
+},element:function(D,E){Slick.uidOf(D);if(!E&&!D.$family&&!(/^(?:object|embed)$/i).test(D.tagName)){var l=D.fireEvent;D._fireEvent=function(F,G){return l(F,G);
+};Object.append(D,Element.Prototype);}return D;},object:function(D,E,l){if(D.toElement){return e.element(D.toElement(l),E);}return null;}};e.textnode=e.whitespace=e.window=e.document=function(l){return l;
+};return function(D,F,E){if(D&&D.$family&&D.uniqueNumber){return D;}var l=typeOf(D);return(e[l])?e[l](D,F,E||document):null;};})()});if(window.$==null){Window.implement("$",function(e,l){return document.id(e,l,this.document);
+});}Window.implement({getDocument:function(){return this.document;},getWindow:function(){return this;}});[Document,Element].invoke("implement",{getElements:function(e){return Slick.search(this,e,new Elements);
+},getElement:function(e){return document.id(Slick.find(this,e));}});var m={contains:function(e){return Slick.contains(this,e);}};if(!document.contains){Document.implement(m);
+}if(!document.createElement("div").contains){Element.implement(m);}var r=function(E,D){if(!E){return D;}E=Object.clone(Slick.parse(E));var l=E.expressions;
+for(var e=l.length;e--;){l[e][0].combinator=D;}return E;};Object.forEach({getNext:"~",getPrevious:"!~",getParent:"!"},function(e,l){Element.implement(l,function(D){return this.getElement(r(D,e));
+});});Object.forEach({getAllNext:"~",getAllPrevious:"!~",getSiblings:"~~",getChildren:">",getParents:"!"},function(e,l){Element.implement(l,function(D){return this.getElements(r(D,e));
+});});Element.implement({getFirst:function(e){return document.id(Slick.search(this,r(e,">"))[0]);},getLast:function(e){return document.id(Slick.search(this,r(e,">")).getLast());
+},getWindow:function(){return this.ownerDocument.window;},getDocument:function(){return this.ownerDocument;},getElementById:function(e){return document.id(Slick.find(this,"#"+(""+e).replace(/(\W)/g,"\\$1")));
+},match:function(e){return !e||Slick.match(this,e);}});if(window.$$==null){Window.implement("$$",function(e){if(arguments.length==1){if(typeof e=="string"){return Slick.search(this.document,e,new Elements);
+}else{if(Type.isEnumerable(e)){return new Elements(e);}}}return new Elements(arguments);});}var w={before:function(l,e){var D=e.parentNode;if(D){D.insertBefore(l,e);
+}},after:function(l,e){var D=e.parentNode;if(D){D.insertBefore(l,e.nextSibling);}},bottom:function(l,e){e.appendChild(l);},top:function(l,e){e.insertBefore(l,e.firstChild);
+}};w.inside=w.bottom;var j={},d={};var k={};Array.forEach(["type","value","defaultValue","accessKey","cellPadding","cellSpacing","colSpan","frameBorder","rowSpan","tabIndex","useMap"],function(e){k[e.toLowerCase()]=e;
+});k.html="innerHTML";k.text=(document.createElement("div").textContent==null)?"innerText":"textContent";Object.forEach(k,function(l,e){d[e]=function(D,E){D[l]=E;
+};j[e]=function(D){return D[l];};});var x=["compact","nowrap","ismap","declare","noshade","checked","disabled","readOnly","multiple","selected","noresize","defer","defaultChecked","autofocus","controls","autoplay","loop"];
+var h={};Array.forEach(x,function(e){var l=e.toLowerCase();h[l]=e;d[l]=function(D,E){D[e]=!!E;};j[l]=function(D){return !!D[e];};});Object.append(d,{"class":function(e,l){("className" in e)?e.className=(l||""):e.setAttribute("class",l);
+},"for":function(e,l){("htmlFor" in e)?e.htmlFor=l:e.setAttribute("for",l);},style:function(e,l){(e.style)?e.style.cssText=l:e.setAttribute("style",l);
+},value:function(e,l){e.value=(l!=null)?l:"";}});j["class"]=function(e){return("className" in e)?e.className||null:e.getAttribute("class");};var f=document.createElement("button");
+try{f.type="button";}catch(z){}if(f.type!="button"){d.type=function(e,l){e.setAttribute("type",l);};}f=null;var p=document.createElement("input");p.value="t";
+p.type="submit";if(p.value!="t"){d.type=function(l,e){var D=l.value;l.type=e;l.value=D;};}p=null;var q=(function(e){e.random="attribute";return(e.getAttribute("random")=="attribute");
+})(document.createElement("div"));Element.implement({setProperty:function(l,D){var E=d[l.toLowerCase()];if(E){E(this,D);}else{if(q){var e=this.retrieve("$attributeWhiteList",{});
+}if(D==null){this.removeAttribute(l);if(q){delete e[l];}}else{this.setAttribute(l,""+D);if(q){e[l]=true;}}}return this;},setProperties:function(e){for(var l in e){this.setProperty(l,e[l]);
+}return this;},getProperty:function(F){var D=j[F.toLowerCase()];if(D){return D(this);}if(q){var l=this.getAttributeNode(F),E=this.retrieve("$attributeWhiteList",{});
+if(!l){return null;}if(l.expando&&!E[F]){var G=this.outerHTML;if(G.substr(0,G.search(/\/?['"]?>(?![^<]*<['"])/)).indexOf(F)<0){return null;}E[F]=true;}}var e=Slick.getAttribute(this,F);
+return(!e&&!Slick.hasAttribute(this,F))?null:e;},getProperties:function(){var e=Array.from(arguments);return e.map(this.getProperty,this).associate(e);
+},removeProperty:function(e){return this.setProperty(e,null);},removeProperties:function(){Array.each(arguments,this.removeProperty,this);return this;},set:function(D,l){var e=Element.Properties[D];
+(e&&e.set)?e.set.call(this,l):this.setProperty(D,l);}.overloadSetter(),get:function(l){var e=Element.Properties[l];return(e&&e.get)?e.get.apply(this):this.getProperty(l);
+}.overloadGetter(),erase:function(l){var e=Element.Properties[l];(e&&e.erase)?e.erase.apply(this):this.removeProperty(l);return this;},hasClass:function(e){return this.className.clean().contains(e," ");
+},addClass:function(e){if(!this.hasClass(e)){this.className=(this.className+" "+e).clean();}return this;},removeClass:function(e){this.className=this.className.replace(new RegExp("(^|\\s)"+e+"(?:\\s|$)"),"$1");
+return this;},toggleClass:function(e,l){if(l==null){l=!this.hasClass(e);}return(l)?this.addClass(e):this.removeClass(e);},adopt:function(){var E=this,e,G=Array.flatten(arguments),F=G.length;
+if(F>1){E=e=document.createDocumentFragment();}for(var D=0;D<F;D++){var l=document.id(G[D],true);if(l){E.appendChild(l);}}if(e){this.appendChild(e);}return this;
+},appendText:function(l,e){return this.grab(this.getDocument().newTextNode(l),e);},grab:function(l,e){w[e||"bottom"](document.id(l,true),this);return this;
+},inject:function(l,e){w[e||"bottom"](this,document.id(l,true));return this;},replaces:function(e){e=document.id(e,true);e.parentNode.replaceChild(this,e);
+return this;},wraps:function(l,e){l=document.id(l,true);return this.replaces(l).grab(l,e);},getSelected:function(){this.selectedIndex;return new Elements(Array.from(this.options).filter(function(e){return e.selected;
+}));},toQueryString:function(){var e=[];this.getElements("input, select, textarea").each(function(D){var l=D.type;if(!D.name||D.disabled||l=="submit"||l=="reset"||l=="file"||l=="image"){return;
+}var E=(D.get("tag")=="select")?D.getSelected().map(function(F){return document.id(F).get("value");}):((l=="radio"||l=="checkbox")&&!D.checked)?null:D.get("value");
+Array.from(E).each(function(F){if(typeof F!="undefined"){e.push(encodeURIComponent(D.name)+"="+encodeURIComponent(F));}});});return e.join("&");}});var i={},A={};
+var B=function(e){return(A[e]||(A[e]={}));};var v=function(l){var e=l.uniqueNumber;if(l.removeEvents){l.removeEvents();}if(l.clearAttributes){l.clearAttributes();
+}if(e!=null){delete i[e];delete A[e];}return l;};var C={input:"checked",option:"selected",textarea:"value"};Element.implement({destroy:function(){var e=v(this).getElementsByTagName("*");
+Array.each(e,v);Element.dispose(this);return null;},empty:function(){Array.from(this.childNodes).each(Element.dispose);return this;},dispose:function(){return(this.parentNode)?this.parentNode.removeChild(this):this;
+},clone:function(G,E){G=G!==false;var L=this.cloneNode(G),D=[L],F=[this],J;if(G){D.append(Array.from(L.getElementsByTagName("*")));F.append(Array.from(this.getElementsByTagName("*")));
+}for(J=D.length;J--;){var H=D[J],K=F[J];if(!E){H.removeAttribute("id");}if(H.clearAttributes){H.clearAttributes();H.mergeAttributes(K);H.removeAttribute("uniqueNumber");
+if(H.options){var O=H.options,e=K.options;for(var I=O.length;I--;){O[I].selected=e[I].selected;}}}var l=C[K.tagName.toLowerCase()];if(l&&K[l]){H[l]=K[l];
+}}if(Browser.ie){var M=L.getElementsByTagName("object"),N=this.getElementsByTagName("object");for(J=M.length;J--;){M[J].outerHTML=N[J].outerHTML;}}return document.id(L);
+}});[Element,Window,Document].invoke("implement",{addListener:function(E,D){if(E=="unload"){var e=D,l=this;D=function(){l.removeListener("unload",D);e();
+};}else{i[Slick.uidOf(this)]=this;}if(this.addEventListener){this.addEventListener(E,D,!!arguments[2]);}else{this.attachEvent("on"+E,D);}return this;},removeListener:function(l,e){if(this.removeEventListener){this.removeEventListener(l,e,!!arguments[2]);
+}else{this.detachEvent("on"+l,e);}return this;},retrieve:function(l,e){var E=B(Slick.uidOf(this)),D=E[l];if(e!=null&&D==null){D=E[l]=e;}return D!=null?D:null;
+},store:function(l,e){var D=B(Slick.uidOf(this));D[l]=e;return this;},eliminate:function(e){var l=B(Slick.uidOf(this));delete l[e];return this;}});if(window.attachEvent&&!window.addEventListener){window.addListener("unload",function(){Object.each(i,v);
+if(window.CollectGarbage){CollectGarbage();}});}Element.Properties={};Element.Properties.style={set:function(e){this.style.cssText=e;},get:function(){return this.style.cssText;
+},erase:function(){this.style.cssText="";}};Element.Properties.tag={get:function(){return this.tagName.toLowerCase();}};Element.Properties.html={set:function(e){if(e==null){e="";
+}else{if(typeOf(e)=="array"){e=e.join("");}}this.innerHTML=e;},erase:function(){this.innerHTML="";}};var t=document.createElement("div");t.innerHTML="<nav></nav>";
+var a=(t.childNodes.length==1);if(!a){var s="abbr article aside audio canvas datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video".split(" "),b=document.createDocumentFragment(),u=s.length;
+while(u--){b.createElement(s[u]);}}t=null;var g=Function.attempt(function(){var e=document.createElement("table");e.innerHTML="<tr><td></td></tr>";return true;
+});var c=document.createElement("tr"),o="<td></td>";c.innerHTML=o;var y=(c.innerHTML==o);c=null;if(!g||!y||!a){Element.Properties.html.set=(function(l){var e={table:[1,"<table>","</table>"],select:[1,"<select>","</select>"],tbody:[2,"<table><tbody>","</tbody></table>"],tr:[3,"<table><tbody><tr>","</tr></tbody></table>"]};
+e.thead=e.tfoot=e.tbody;return function(D){var E=e[this.get("tag")];if(!E&&!a){E=[0,"",""];}if(!E){return l.call(this,D);}var H=E[0],G=document.createElement("div"),F=G;
+if(!a){b.appendChild(G);}G.innerHTML=[E[1],D,E[2]].flatten().join("");while(H--){F=F.firstChild;}this.empty().adopt(F.childNodes);if(!a){b.removeChild(G);
+}G=null;};})(Element.Properties.html.set);}var n=document.createElement("form");n.innerHTML="<select><option>s</option></select>";if(n.firstChild.value!="s"){Element.Properties.value={set:function(G){var l=this.get("tag");
+if(l!="select"){return this.setProperty("value",G);}var D=this.getElements("option");for(var E=0;E<D.length;E++){var F=D[E],e=F.getAttributeNode("value"),H=(e&&e.specified)?F.value:F.get("text");
+if(H==G){return F.selected=true;}}},get:function(){var D=this,l=D.get("tag");if(l!="select"&&l!="option"){return this.getProperty("value");}if(l=="select"&&!(D=D.getSelected()[0])){return"";
+}var e=D.getAttributeNode("value");return(e&&e.specified)?D.value:D.get("text");}};}n=null;if(document.createElement("div").getAttributeNode("id")){Element.Properties.id={set:function(e){this.id=this.getAttributeNode("id").value=e;
+},get:function(){return this.id||null;},erase:function(){this.id=this.getAttributeNode("id").value="";}};}})();(function(){var i=document.html;var d=document.createElement("div");
+d.style.color="red";d.style.color=null;var c=d.style.color=="red";d=null;Element.Properties.styles={set:function(k){this.setStyles(k);}};var h=(i.style.opacity!=null),e=(i.style.filter!=null),j=/alpha\(opacity=([\d.]+)\)/i;
+var a=function(l,k){l.store("$opacity",k);l.style.visibility=k>0||k==null?"visible":"hidden";};var f=(h?function(l,k){l.style.opacity=k;}:(e?function(l,k){var n=l.style;
+if(!l.currentStyle||!l.currentStyle.hasLayout){n.zoom=1;}if(k==null||k==1){k="";}else{k="alpha(opacity="+(k*100).limit(0,100).round()+")";}var m=n.filter||l.getComputedStyle("filter")||"";
+n.filter=j.test(m)?m.replace(j,k):m+k;if(!n.filter){n.removeAttribute("filter");}}:a));var g=(h?function(l){var k=l.style.opacity||l.getComputedStyle("opacity");
+return(k=="")?1:k.toFloat();}:(e?function(l){var m=(l.style.filter||l.getComputedStyle("filter")),k;if(m){k=m.match(j);}return(k==null||m==null)?1:(k[1]/100);
+}:function(l){var k=l.retrieve("$opacity");if(k==null){k=(l.style.visibility=="hidden"?0:1);}return k;}));var b=(i.style.cssFloat==null)?"styleFloat":"cssFloat";
+Element.implement({getComputedStyle:function(m){if(this.currentStyle){return this.currentStyle[m.camelCase()];}var l=Element.getDocument(this).defaultView,k=l?l.getComputedStyle(this,null):null;
+return(k)?k.getPropertyValue((m==b)?"float":m.hyphenate()):null;},setStyle:function(l,k){if(l=="opacity"){if(k!=null){k=parseFloat(k);}f(this,k);return this;
+}l=(l=="float"?b:l).camelCase();if(typeOf(k)!="string"){var m=(Element.Styles[l]||"@").split(" ");k=Array.from(k).map(function(o,n){if(!m[n]){return"";
+}return(typeOf(o)=="number")?m[n].replace("@",Math.round(o)):o;}).join(" ");}else{if(k==String(Number(k))){k=Math.round(k);}}this.style[l]=k;if((k==""||k==null)&&c&&this.style.removeAttribute){this.style.removeAttribute(l);
+}return this;},getStyle:function(q){if(q=="opacity"){return g(this);}q=(q=="float"?b:q).camelCase();var k=this.style[q];if(!k||q=="zIndex"){k=[];for(var p in Element.ShortStyles){if(q!=p){continue;
+}for(var o in Element.ShortStyles[p]){k.push(this.getStyle(o));}return k.join(" ");}k=this.getComputedStyle(q);}if(k){k=String(k);var m=k.match(/rgba?\([\d\s,]+\)/);
+if(m){k=k.replace(m[0],m[0].rgbToHex());}}if(Browser.opera||Browser.ie){if((/^(height|width)$/).test(q)&&!(/px$/.test(k))){var l=(q=="width")?["left","right"]:["top","bottom"],n=0;
+l.each(function(r){n+=this.getStyle("border-"+r+"-width").toInt()+this.getStyle("padding-"+r).toInt();},this);return this["offset"+q.capitalize()]-n+"px";
+}if(Browser.ie&&(/^border(.+)Width|margin|padding/).test(q)&&isNaN(parseFloat(k))){return"0px";}}return k;},setStyles:function(l){for(var k in l){this.setStyle(k,l[k]);
+}return this;},getStyles:function(){var k={};Array.flatten(arguments).each(function(l){k[l]=this.getStyle(l);},this);return k;}});Element.Styles={left:"@px",top:"@px",bottom:"@px",right:"@px",width:"@px",height:"@px",maxWidth:"@px",maxHeight:"@px",minWidth:"@px",minHeight:"@px",backgroundColor:"rgb(@, @, @)",backgroundPosition:"@px @px",color:"rgb(@, @, @)",fontSize:"@px",letterSpacing:"@px",lineHeight:"@px",clip:"rect(@px @px @px @px)",margin:"@px @px @px @px",padding:"@px @px @px @px",border:"@px @ rgb(@, @, @) @px @ rgb(@, @, @) @px @ rgb(@, @, @)",borderWidth:"@px @px @px @px",borderStyle:"@ @ @ @",borderColor:"rgb(@, @, @) rgb(@, @, @) rgb(@, @, @) rgb(@, @, @)",zIndex:"@",zoom:"@",fontWeight:"@",textIndent:"@px",opacity:"@"};
+Element.ShortStyles={margin:{},padding:{},border:{},borderWidth:{},borderStyle:{},borderColor:{}};["Top","Right","Bottom","Left"].each(function(q){var p=Element.ShortStyles;
+var l=Element.Styles;["margin","padding"].each(function(r){var s=r+q;p[r][s]=l[s]="@px";});var o="border"+q;p.border[o]=l[o]="@px @ rgb(@, @, @)";var n=o+"Width",k=o+"Style",m=o+"Color";
+p[o]={};p.borderWidth[n]=p[o][n]=l[n]="@px";p.borderStyle[k]=p[o][k]=l[k]="@";p.borderColor[m]=p[o][m]=l[m]="rgb(@, @, @)";});})();(function(){Element.Properties.events={set:function(b){this.addEvents(b);
+}};[Element,Window,Document].invoke("implement",{addEvent:function(f,h){var i=this.retrieve("events",{});if(!i[f]){i[f]={keys:[],values:[]};}if(i[f].keys.contains(h)){return this;
+}i[f].keys.push(h);var g=f,b=Element.Events[f],d=h,j=this;if(b){if(b.onAdd){b.onAdd.call(this,h,f);}if(b.condition){d=function(k){if(b.condition.call(this,k,f)){return h.call(this,k);
+}return true;};}if(b.base){g=Function.from(b.base).call(this,f);}}var e=function(){return h.call(j);};var c=Element.NativeEvents[g];if(c){if(c==2){e=function(k){k=new DOMEvent(k,j.getWindow());
+if(d.call(j,k)===false){k.stop();}};}this.addListener(g,e,arguments[2]);}i[f].values.push(e);return this;},removeEvent:function(e,d){var c=this.retrieve("events");
+if(!c||!c[e]){return this;}var h=c[e];var b=h.keys.indexOf(d);if(b==-1){return this;}var g=h.values[b];delete h.keys[b];delete h.values[b];var f=Element.Events[e];
+if(f){if(f.onRemove){f.onRemove.call(this,d,e);}if(f.base){e=Function.from(f.base).call(this,e);}}return(Element.NativeEvents[e])?this.removeListener(e,g,arguments[2]):this;
+},addEvents:function(b){for(var c in b){this.addEvent(c,b[c]);}return this;},removeEvents:function(b){var d;if(typeOf(b)=="object"){for(d in b){this.removeEvent(d,b[d]);
+}return this;}var c=this.retrieve("events");if(!c){return this;}if(!b){for(d in c){this.removeEvents(d);}this.eliminate("events");}else{if(c[b]){c[b].keys.each(function(e){this.removeEvent(b,e);
+},this);delete c[b];}}return this;},fireEvent:function(e,c,b){var d=this.retrieve("events");if(!d||!d[e]){return this;}c=Array.from(c);d[e].keys.each(function(f){if(b){f.delay(b,this,c);
+}else{f.apply(this,c);}},this);return this;},cloneEvents:function(e,d){e=document.id(e);var c=e.retrieve("events");if(!c){return this;}if(!d){for(var b in c){this.cloneEvents(e,b);
+}}else{if(c[d]){c[d].keys.each(function(f){this.addEvent(d,f);},this);}}return this;}});Element.NativeEvents={click:2,dblclick:2,mouseup:2,mousedown:2,contextmenu:2,mousewheel:2,DOMMouseScroll:2,mouseover:2,mouseout:2,mousemove:2,selectstart:2,selectend:2,keydown:2,keypress:2,keyup:2,orientationchange:2,touchstart:2,touchmove:2,touchend:2,touchcancel:2,gesturestart:2,gesturechange:2,gestureend:2,focus:2,blur:2,change:2,reset:2,select:2,submit:2,paste:2,input:2,load:2,unload:1,beforeunload:2,resize:1,move:1,DOMContentLoaded:1,readystatechange:1,error:1,abort:1,scroll:1};
+Element.Events={mousewheel:{base:(Browser.firefox)?"DOMMouseScroll":"mousewheel"}};if("onmouseenter" in document.documentElement){Element.NativeEvents.mouseenter=Element.NativeEvents.mouseleave=2;
+}else{var a=function(b){var c=b.relatedTarget;if(c==null){return true;}if(!c){return false;}return(c!=this&&c.prefix!="xul"&&typeOf(this)!="document"&&!this.contains(c));
+};Element.Events.mouseenter={base:"mouseover",condition:a};Element.Events.mouseleave={base:"mouseout",condition:a};}if(!window.addEventListener){Element.NativeEvents.propertychange=2;
+Element.Events.change={base:function(){var b=this.type;return(this.get("tag")=="input"&&(b=="radio"||b=="checkbox"))?"propertychange":"change";},condition:function(b){return this.type!="radio"||(b.event.propertyName=="checked"&&this.checked);
+}};}})();(function(){var c=!!window.addEventListener;Element.NativeEvents.focusin=Element.NativeEvents.focusout=2;var k=function(l,m,n,o,p){while(p&&p!=l){if(m(p,o)){return n.call(p,o,p);
+}p=document.id(p.parentNode);}};var a={mouseenter:{base:"mouseover"},mouseleave:{base:"mouseout"},focus:{base:"focus"+(c?"":"in"),capture:true},blur:{base:c?"blur":"focusout",capture:true}};
+var b="$delegation:";var i=function(l){return{base:"focusin",remove:function(m,o){var p=m.retrieve(b+l+"listeners",{})[o];if(p&&p.forms){for(var n=p.forms.length;
+n--;){p.forms[n].removeEvent(l,p.fns[n]);}}},listen:function(x,r,v,n,t,s){var o=(t.get("tag")=="form")?t:n.target.getParent("form");if(!o){return;}var u=x.retrieve(b+l+"listeners",{}),p=u[s]||{forms:[],fns:[]},m=p.forms,w=p.fns;
+if(m.indexOf(o)!=-1){return;}m.push(o);var q=function(y){k(x,r,v,y,t);};o.addEvent(l,q);w.push(q);u[s]=p;x.store(b+l+"listeners",u);}};};var d=function(l){return{base:"focusin",listen:function(m,n,p,q,r){var o={blur:function(){this.removeEvents(o);
+}};o[l]=function(s){k(m,n,p,s,r);};q.target.addEvents(o);}};};if(!c){Object.append(a,{submit:i("submit"),reset:i("reset"),change:d("change"),select:d("select")});
+}var h=Element.prototype,f=h.addEvent,j=h.removeEvent;var e=function(l,m){return function(r,q,n){if(r.indexOf(":relay")==-1){return l.call(this,r,q,n);
+}var o=Slick.parse(r).expressions[0][0];if(o.pseudos[0].key!="relay"){return l.call(this,r,q,n);}var p=o.tag;o.pseudos.slice(1).each(function(s){p+=":"+s.key+(s.value?"("+s.value+")":"");
+});l.call(this,r,q);return m.call(this,p,o.pseudos[0].value,q);};};var g={addEvent:function(v,q,x){var t=this.retrieve("$delegates",{}),r=t[v];if(r){for(var y in r){if(r[y].fn==x&&r[y].match==q){return this;
+}}}var p=v,u=q,o=x,n=a[v]||{};v=n.base||p;q=function(B){return Slick.match(B,u);};var w=Element.Events[p];if(w&&w.condition){var l=q,m=w.condition;q=function(C,B){return l(C,B)&&m.call(C,B,v);
+};}var z=this,s=String.uniqueID();var A=n.listen?function(B,C){if(!C&&B&&B.target){C=B.target;}if(C){n.listen(z,q,x,B,C,s);}}:function(B,C){if(!C&&B&&B.target){C=B.target;
+}if(C){k(z,q,x,B,C);}};if(!r){r={};}r[s]={match:u,fn:o,delegator:A};t[p]=r;return f.call(this,v,A,n.capture);},removeEvent:function(r,n,t,u){var q=this.retrieve("$delegates",{}),p=q[r];
+if(!p){return this;}if(u){var m=r,w=p[u].delegator,l=a[r]||{};r=l.base||m;if(l.remove){l.remove(this,u);}delete p[u];q[m]=p;return j.call(this,r,w);}var o,v;
+if(t){for(o in p){v=p[o];if(v.match==n&&v.fn==t){return g.removeEvent.call(this,r,n,t,o);}}}else{for(o in p){v=p[o];if(v.match==n){g.removeEvent.call(this,r,n,v.fn,o);
+}}}return this;}};[Element,Window,Document].invoke("implement",{addEvent:e(f,g.addEvent),removeEvent:e(j,g.removeEvent)});})();(function(){var h=document.createElement("div"),e=document.createElement("div");
+h.style.height="0";h.appendChild(e);var d=(e.offsetParent===h);h=e=null;var l=function(m){return k(m,"position")!="static"||a(m);};var i=function(m){return l(m)||(/^(?:table|td|th)$/i).test(m.tagName);
+};Element.implement({scrollTo:function(m,n){if(a(this)){this.getWindow().scrollTo(m,n);}else{this.scrollLeft=m;this.scrollTop=n;}return this;},getSize:function(){if(a(this)){return this.getWindow().getSize();
+}return{x:this.offsetWidth,y:this.offsetHeight};},getScrollSize:function(){if(a(this)){return this.getWindow().getScrollSize();}return{x:this.scrollWidth,y:this.scrollHeight};
+},getScroll:function(){if(a(this)){return this.getWindow().getScroll();}return{x:this.scrollLeft,y:this.scrollTop};},getScrolls:function(){var n=this.parentNode,m={x:0,y:0};
+while(n&&!a(n)){m.x+=n.scrollLeft;m.y+=n.scrollTop;n=n.parentNode;}return m;},getOffsetParent:d?function(){var m=this;if(a(m)||k(m,"position")=="fixed"){return null;
+}var n=(k(m,"position")=="static")?i:l;while((m=m.parentNode)){if(n(m)){return m;}}return null;}:function(){var m=this;if(a(m)||k(m,"position")=="fixed"){return null;
+}try{return m.offsetParent;}catch(n){}return null;},getOffsets:function(){if(this.getBoundingClientRect&&!Browser.Platform.ios){var r=this.getBoundingClientRect(),o=document.id(this.getDocument().documentElement),q=o.getScroll(),t=this.getScrolls(),s=(k(this,"position")=="fixed");
+return{x:r.left.toInt()+t.x+((s)?0:q.x)-o.clientLeft,y:r.top.toInt()+t.y+((s)?0:q.y)-o.clientTop};}var n=this,m={x:0,y:0};if(a(this)){return m;}while(n&&!a(n)){m.x+=n.offsetLeft;
+m.y+=n.offsetTop;if(Browser.firefox){if(!c(n)){m.x+=b(n);m.y+=g(n);}var p=n.parentNode;if(p&&k(p,"overflow")!="visible"){m.x+=b(p);m.y+=g(p);}}else{if(n!=this&&Browser.safari){m.x+=b(n);
+m.y+=g(n);}}n=n.offsetParent;}if(Browser.firefox&&!c(this)){m.x-=b(this);m.y-=g(this);}return m;},getPosition:function(p){var q=this.getOffsets(),n=this.getScrolls();
+var m={x:q.x-n.x,y:q.y-n.y};if(p&&(p=document.id(p))){var o=p.getPosition();return{x:m.x-o.x-b(p),y:m.y-o.y-g(p)};}return m;},getCoordinates:function(o){if(a(this)){return this.getWindow().getCoordinates();
+}var m=this.getPosition(o),n=this.getSize();var p={left:m.x,top:m.y,width:n.x,height:n.y};p.right=p.left+p.width;p.bottom=p.top+p.height;return p;},computePosition:function(m){return{left:m.x-j(this,"margin-left"),top:m.y-j(this,"margin-top")};
+},setPosition:function(m){return this.setStyles(this.computePosition(m));}});[Document,Window].invoke("implement",{getSize:function(){var m=f(this);return{x:m.clientWidth,y:m.clientHeight};
+},getScroll:function(){var n=this.getWindow(),m=f(this);return{x:n.pageXOffset||m.scrollLeft,y:n.pageYOffset||m.scrollTop};},getScrollSize:function(){var o=f(this),n=this.getSize(),m=this.getDocument().body;
+return{x:Math.max(o.scrollWidth,m.scrollWidth,n.x),y:Math.max(o.scrollHeight,m.scrollHeight,n.y)};},getPosition:function(){return{x:0,y:0};},getCoordinates:function(){var m=this.getSize();
+return{top:0,left:0,bottom:m.y,right:m.x,height:m.y,width:m.x};}});var k=Element.getComputedStyle;function j(m,n){return k(m,n).toInt()||0;}function c(m){return k(m,"-moz-box-sizing")=="border-box";
+}function g(m){return j(m,"border-top-width");}function b(m){return j(m,"border-left-width");}function a(m){return(/^(?:body|html)$/i).test(m.tagName);
+}function f(m){var n=m.getDocument();return(!n.compatMode||n.compatMode=="CSS1Compat")?n.html:n.body;}})();Element.alias({position:"setPosition"});[Window,Document,Element].invoke("implement",{getHeight:function(){return this.getSize().y;
+},getWidth:function(){return this.getSize().x;},getScrollTop:function(){return this.getScroll().y;},getScrollLeft:function(){return this.getScroll().x;
+},getScrollHeight:function(){return this.getScrollSize().y;},getScrollWidth:function(){return this.getScrollSize().x;},getTop:function(){return this.getPosition().y;
+},getLeft:function(){return this.getPosition().x;}});(function(){var f=this.Fx=new Class({Implements:[Chain,Events,Options],options:{fps:60,unit:false,duration:500,frames:null,frameSkip:true,link:"ignore"},initialize:function(g){this.subject=this.subject||this;
+this.setOptions(g);},getTransition:function(){return function(g){return -(Math.cos(Math.PI*g)-1)/2;};},step:function(g){if(this.options.frameSkip){var h=(this.time!=null)?(g-this.time):0,i=h/this.frameInterval;
+this.time=g;this.frame+=i;}else{this.frame++;}if(this.frame<this.frames){var j=this.transition(this.frame/this.frames);this.set(this.compute(this.from,this.to,j));
+}else{this.frame=this.frames;this.set(this.compute(this.from,this.to,1));this.stop();}},set:function(g){return g;},compute:function(i,h,g){return f.compute(i,h,g);
+},check:function(){if(!this.isRunning()){return true;}switch(this.options.link){case"cancel":this.cancel();return true;case"chain":this.chain(this.caller.pass(arguments,this));
+return false;}return false;},start:function(k,j){if(!this.check(k,j)){return this;}this.from=k;this.to=j;this.frame=(this.options.frameSkip)?0:-1;this.time=null;
+this.transition=this.getTransition();var i=this.options.frames,h=this.options.fps,g=this.options.duration;this.duration=f.Durations[g]||g.toInt();this.frameInterval=1000/h;
+this.frames=i||Math.round(this.duration/this.frameInterval);this.fireEvent("start",this.subject);b.call(this,h);return this;},stop:function(){if(this.isRunning()){this.time=null;
+d.call(this,this.options.fps);if(this.frames==this.frame){this.fireEvent("complete",this.subject);if(!this.callChain()){this.fireEvent("chainComplete",this.subject);
+}}else{this.fireEvent("stop",this.subject);}}return this;},cancel:function(){if(this.isRunning()){this.time=null;d.call(this,this.options.fps);this.frame=this.frames;
+this.fireEvent("cancel",this.subject).clearChain();}return this;},pause:function(){if(this.isRunning()){this.time=null;d.call(this,this.options.fps);}return this;
+},resume:function(){if((this.frame<this.frames)&&!this.isRunning()){b.call(this,this.options.fps);}return this;},isRunning:function(){var g=e[this.options.fps];
+return g&&g.contains(this);}});f.compute=function(i,h,g){return(h-i)*g+i;};f.Durations={"short":250,normal:500,"long":1000};var e={},c={};var a=function(){var h=Date.now();
+for(var j=this.length;j--;){var g=this[j];if(g){g.step(h);}}};var b=function(h){var g=e[h]||(e[h]=[]);g.push(this);if(!c[h]){c[h]=a.periodical(Math.round(1000/h),g);
+}};var d=function(h){var g=e[h];if(g){g.erase(this);if(!g.length&&c[h]){delete e[h];c[h]=clearInterval(c[h]);}}};})();Fx.CSS=new Class({Extends:Fx,prepare:function(b,e,a){a=Array.from(a);
+var h=a[0],g=a[1];if(g==null){g=h;h=b.getStyle(e);var c=this.options.unit;if(c&&h.slice(-c.length)!=c&&parseFloat(h)!=0){b.setStyle(e,g+c);var d=b.getComputedStyle(e);
+if(!(/px$/.test(d))){d=b.style[("pixel-"+e).camelCase()];if(d==null){var f=b.style.left;b.style.left=g+c;d=b.style.pixelLeft;b.style.left=f;}}h=(g||1)/(parseFloat(d)||1)*(parseFloat(h)||0);
+b.setStyle(e,h+c);}}return{from:this.parse(h),to:this.parse(g)};},parse:function(a){a=Function.from(a)();a=(typeof a=="string")?a.split(" "):Array.from(a);
+return a.map(function(c){c=String(c);var b=false;Object.each(Fx.CSS.Parsers,function(f,e){if(b){return;}var d=f.parse(c);if(d||d===0){b={value:d,parser:f};
+}});b=b||{value:c,parser:Fx.CSS.Parsers.String};return b;});},compute:function(d,c,b){var a=[];(Math.min(d.length,c.length)).times(function(e){a.push({value:d[e].parser.compute(d[e].value,c[e].value,b),parser:d[e].parser});
+});a.$family=Function.from("fx:css:value");return a;},serve:function(c,b){if(typeOf(c)!="fx:css:value"){c=this.parse(c);}var a=[];c.each(function(d){a=a.concat(d.parser.serve(d.value,b));
+});return a;},render:function(a,d,c,b){a.setStyle(d,this.serve(c,b));},search:function(a){if(Fx.CSS.Cache[a]){return Fx.CSS.Cache[a];}var c={},b=new RegExp("^"+a.escapeRegExp()+"$");
+Array.each(document.styleSheets,function(f,e){var d=f.href;if(d&&d.contains("://")&&!d.contains(document.domain)){return;}var g=f.rules||f.cssRules;Array.each(g,function(k,h){if(!k.style){return;
+}var j=(k.selectorText)?k.selectorText.replace(/^\w+/,function(i){return i.toLowerCase();}):null;if(!j||!b.test(j)){return;}Object.each(Element.Styles,function(l,i){if(!k.style[i]||Element.ShortStyles[i]){return;
+}l=String(k.style[i]);c[i]=((/^rgb/).test(l))?l.rgbToHex():l;});});});return Fx.CSS.Cache[a]=c;}});Fx.CSS.Cache={};Fx.CSS.Parsers={Color:{parse:function(a){if(a.match(/^#[0-9a-f]{3,6}$/i)){return a.hexToRgb(true);
+}return((a=a.match(/(\d+),\s*(\d+),\s*(\d+)/)))?[a[1],a[2],a[3]]:false;},compute:function(c,b,a){return c.map(function(e,d){return Math.round(Fx.compute(c[d],b[d],a));
+});},serve:function(a){return a.map(Number);}},Number:{parse:parseFloat,compute:Fx.compute,serve:function(b,a){return(a)?b+a:b;}},String:{parse:Function.from(false),compute:function(b,a){return a;
+},serve:function(a){return a;}}};Fx.Tween=new Class({Extends:Fx.CSS,initialize:function(b,a){this.element=this.subject=document.id(b);this.parent(a);},set:function(b,a){if(arguments.length==1){a=b;
+b=this.property||this.options.property;}this.render(this.element,b,a,this.options.unit);return this;},start:function(c,e,d){if(!this.check(c,e,d)){return this;
+}var b=Array.flatten(arguments);this.property=this.options.property||b.shift();var a=this.prepare(this.element,this.property,b);return this.parent(a.from,a.to);
+}});Element.Properties.tween={set:function(a){this.get("tween").cancel().setOptions(a);return this;},get:function(){var a=this.retrieve("tween");if(!a){a=new Fx.Tween(this,{link:"cancel"});
+this.store("tween",a);}return a;}};Element.implement({tween:function(a,c,b){this.get("tween").start(a,c,b);return this;},fade:function(d){var e=this.get("tween"),g,c=["opacity"].append(arguments),a;
+if(c[1]==null){c[1]="toggle";}switch(c[1]){case"in":g="start";c[1]=1;break;case"out":g="start";c[1]=0;break;case"show":g="set";c[1]=1;break;case"hide":g="set";
+c[1]=0;break;case"toggle":var b=this.retrieve("fade:flag",this.getStyle("opacity")==1);g="start";c[1]=b?0:1;this.store("fade:flag",!b);a=true;break;default:g="start";
+}if(!a){this.eliminate("fade:flag");}e[g].apply(e,c);var f=c[c.length-1];if(g=="set"||f!=0){this.setStyle("visibility",f==0?"hidden":"visible");}else{e.chain(function(){this.element.setStyle("visibility","hidden");
+this.callChain();});}return this;},highlight:function(c,a){if(!a){a=this.retrieve("highlight:original",this.getStyle("background-color"));a=(a=="transparent")?"#fff":a;
+}var b=this.get("tween");b.start("background-color",c||"#ffff88",a).chain(function(){this.setStyle("background-color",this.retrieve("highlight:original"));
+b.callChain();}.bind(this));return this;}});Fx.Morph=new Class({Extends:Fx.CSS,initialize:function(b,a){this.element=this.subject=document.id(b);this.parent(a);
+},set:function(a){if(typeof a=="string"){a=this.search(a);}for(var b in a){this.render(this.element,b,a[b],this.options.unit);}return this;},compute:function(e,d,c){var a={};
+for(var b in e){a[b]=this.parent(e[b],d[b],c);}return a;},start:function(b){if(!this.check(b)){return this;}if(typeof b=="string"){b=this.search(b);}var e={},d={};
+for(var c in b){var a=this.prepare(this.element,c,b[c]);e[c]=a.from;d[c]=a.to;}return this.parent(e,d);}});Element.Properties.morph={set:function(a){this.get("morph").cancel().setOptions(a);
+return this;},get:function(){var a=this.retrieve("morph");if(!a){a=new Fx.Morph(this,{link:"cancel"});this.store("morph",a);}return a;}};Element.implement({morph:function(a){this.get("morph").start(a);
+return this;}});Fx.implement({getTransition:function(){var a=this.options.transition||Fx.Transitions.Sine.easeInOut;if(typeof a=="string"){var b=a.split(":");
+a=Fx.Transitions;a=a[b[0]]||a[b[0].capitalize()];if(b[1]){a=a["ease"+b[1].capitalize()+(b[2]?b[2].capitalize():"")];}}return a;}});Fx.Transition=function(c,b){b=Array.from(b);
+var a=function(d){return c(d,b);};return Object.append(a,{easeIn:a,easeOut:function(d){return 1-c(1-d,b);},easeInOut:function(d){return(d<=0.5?c(2*d,b):(2-c(2*(1-d),b)))/2;
+}});};Fx.Transitions={linear:function(a){return a;}};Fx.Transitions.extend=function(a){for(var b in a){Fx.Transitions[b]=new Fx.Transition(a[b]);}};Fx.Transitions.extend({Pow:function(b,a){return Math.pow(b,a&&a[0]||6);
+},Expo:function(a){return Math.pow(2,8*(a-1));},Circ:function(a){return 1-Math.sin(Math.acos(a));},Sine:function(a){return 1-Math.cos(a*Math.PI/2);},Back:function(b,a){a=a&&a[0]||1.618;
+return Math.pow(b,2)*((a+1)*b-a);},Bounce:function(f){var e;for(var d=0,c=1;1;d+=c,c/=2){if(f>=(7-4*d)/11){e=c*c-Math.pow((11-6*d-11*f)/4,2);break;}}return e;
+},Elastic:function(b,a){return Math.pow(2,10*--b)*Math.cos(20*b*Math.PI*(a&&a[0]||1)/3);}});["Quad","Cubic","Quart","Quint"].each(function(b,a){Fx.Transitions[b]=new Fx.Transition(function(c){return Math.pow(c,a+2);
+});});(function(){var d=function(){},a=("onprogress" in new Browser.Request);var c=this.Request=new Class({Implements:[Chain,Events,Options],options:{url:"",data:"",headers:{"X-Requested-With":"XMLHttpRequest",Accept:"text/javascript, text/html, application/xml, text/xml, */*"},async:true,format:false,method:"post",link:"ignore",isSuccess:null,emulation:true,urlEncoded:true,encoding:"utf-8",evalScripts:false,evalResponse:false,timeout:0,noCache:false},initialize:function(e){this.xhr=new Browser.Request();
+this.setOptions(e);this.headers=this.options.headers;},onStateChange:function(){var e=this.xhr;if(e.readyState!=4||!this.running){return;}this.running=false;
+this.status=0;Function.attempt(function(){var f=e.status;this.status=(f==1223)?204:f;}.bind(this));e.onreadystatechange=d;if(a){e.onprogress=e.onloadstart=d;
+}clearTimeout(this.timer);this.response={text:this.xhr.responseText||"",xml:this.xhr.responseXML};if(this.options.isSuccess.call(this,this.status)){this.success(this.response.text,this.response.xml);
+}else{this.failure();}},isSuccess:function(){var e=this.status;return(e>=200&&e<300);},isRunning:function(){return !!this.running;},processScripts:function(e){if(this.options.evalResponse||(/(ecma|java)script/).test(this.getHeader("Content-type"))){return Browser.exec(e);
+}return e.stripScripts(this.options.evalScripts);},success:function(f,e){this.onSuccess(this.processScripts(f),e);},onSuccess:function(){this.fireEvent("complete",arguments).fireEvent("success",arguments).callChain();
+},failure:function(){this.onFailure();},onFailure:function(){this.fireEvent("complete").fireEvent("failure",this.xhr);},loadstart:function(e){this.fireEvent("loadstart",[e,this.xhr]);
+},progress:function(e){this.fireEvent("progress",[e,this.xhr]);},timeout:function(){this.fireEvent("timeout",this.xhr);},setHeader:function(e,f){this.headers[e]=f;
+return this;},getHeader:function(e){return Function.attempt(function(){return this.xhr.getResponseHeader(e);}.bind(this));},check:function(){if(!this.running){return true;
+}switch(this.options.link){case"cancel":this.cancel();return true;case"chain":this.chain(this.caller.pass(arguments,this));return false;}return false;},send:function(o){if(!this.check(o)){return this;
+}this.options.isSuccess=this.options.isSuccess||this.isSuccess;this.running=true;var l=typeOf(o);if(l=="string"||l=="element"){o={data:o};}var h=this.options;
+o=Object.append({data:h.data,url:h.url,method:h.method},o);var j=o.data,f=String(o.url),e=o.method.toLowerCase();switch(typeOf(j)){case"element":j=document.id(j).toQueryString();
+break;case"object":case"hash":j=Object.toQueryString(j);}if(this.options.format){var m="format="+this.options.format;j=(j)?m+"&"+j:m;}if(this.options.emulation&&!["get","post"].contains(e)){var k="_method="+e;
+j=(j)?k+"&"+j:k;e="post";}if(this.options.urlEncoded&&["post","put"].contains(e)){var g=(this.options.encoding)?"; charset="+this.options.encoding:"";this.headers["Content-type"]="application/x-www-form-urlencoded"+g;
+}if(!f){f=document.location.pathname;}var i=f.lastIndexOf("/");if(i>-1&&(i=f.indexOf("#"))>-1){f=f.substr(0,i);}if(this.options.noCache){f+=(f.contains("?")?"&":"?")+String.uniqueID();
+}if(j&&e=="get"){f+=(f.contains("?")?"&":"?")+j;j=null;}var n=this.xhr;if(a){n.onloadstart=this.loadstart.bind(this);n.onprogress=this.progress.bind(this);
+}n.open(e.toUpperCase(),f,this.options.async,this.options.user,this.options.password);if(this.options.user&&"withCredentials" in n){n.withCredentials=true;
+}n.onreadystatechange=this.onStateChange.bind(this);Object.each(this.headers,function(q,p){try{n.setRequestHeader(p,q);}catch(r){this.fireEvent("exception",[p,q]);
+}},this);this.fireEvent("request");n.send(j);if(!this.options.async){this.onStateChange();}else{if(this.options.timeout){this.timer=this.timeout.delay(this.options.timeout,this);
+}}return this;},cancel:function(){if(!this.running){return this;}this.running=false;var e=this.xhr;e.abort();clearTimeout(this.timer);e.onreadystatechange=d;
+if(a){e.onprogress=e.onloadstart=d;}this.xhr=new Browser.Request();this.fireEvent("cancel");return this;}});var b={};["get","post","put","delete","GET","POST","PUT","DELETE"].each(function(e){b[e]=function(g){var f={method:e};
+if(g!=null){f.data=g;}return this.send(f);};});c.implement(b);Element.Properties.send={set:function(e){var f=this.get("send").cancel();f.setOptions(e);
+return this;},get:function(){var e=this.retrieve("send");if(!e){e=new c({data:this,link:"cancel",method:this.get("method")||"post",url:this.get("action")});
+this.store("send",e);}return e;}};Element.implement({send:function(e){var f=this.get("send");f.send({data:this,url:e||f.options.url});return this;}});})();
+Request.HTML=new Class({Extends:Request,options:{update:false,append:false,evalScripts:true,filter:false,headers:{Accept:"text/html, application/xml, text/xml, */*"}},success:function(f){var e=this.options,c=this.response;
+c.html=f.stripScripts(function(h){c.javascript=h;});var d=c.html.match(/<body[^>]*>([\s\S]*?)<\/body>/i);if(d){c.html=d[1];}var b=new Element("div").set("html",c.html);
+c.tree=b.childNodes;c.elements=b.getElements(e.filter||"*");if(e.filter){c.tree=c.elements;}if(e.update){var g=document.id(e.update).empty();if(e.filter){g.adopt(c.elements);
+}else{g.set("html",c.html);}}else{if(e.append){var a=document.id(e.append);if(e.filter){c.elements.reverse().inject(a);}else{a.adopt(b.getChildren());}}}if(e.evalScripts){Browser.exec(c.javascript);
+}this.onSuccess(c.tree,c.elements,c.html,c.javascript);}});Element.Properties.load={set:function(a){var b=this.get("load").cancel();b.setOptions(a);return this;
+},get:function(){var a=this.retrieve("load");if(!a){a=new Request.HTML({data:this,link:"cancel",update:this,method:"get"});this.store("load",a);}return a;
+}};Element.implement({load:function(){this.get("load").send(Array.link(arguments,{data:Type.isObject,url:Type.isString}));return this;}});if(typeof JSON=="undefined"){this.JSON={};
+}(function(){var special={"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"};var escape=function(chr){return special[chr]||"\\u"+("0000"+chr.charCodeAt(0).toString(16)).slice(-4);
+};JSON.validate=function(string){string=string.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"");
+return(/^[\],:{}\s]*$/).test(string);};JSON.encode=JSON.stringify?function(obj){return JSON.stringify(obj);}:function(obj){if(obj&&obj.toJSON){obj=obj.toJSON();
+}switch(typeOf(obj)){case"string":return'"'+obj.replace(/[\x00-\x1f\\"]/g,escape)+'"';case"array":return"["+obj.map(JSON.encode).clean()+"]";case"object":case"hash":var string=[];
+Object.each(obj,function(value,key){var json=JSON.encode(value);if(json){string.push(JSON.encode(key)+":"+json);}});return"{"+string+"}";case"number":case"boolean":return""+obj;
+case"null":return"null";}return null;};JSON.decode=function(string,secure){if(!string||typeOf(string)!="string"){return null;}if(secure||JSON.secure){if(JSON.parse){return JSON.parse(string);
+}if(!JSON.validate(string)){throw new Error("JSON could not decode the input; security is enabled and the value is not secure.");}}return eval("("+string+")");
+};})();Request.JSON=new Class({Extends:Request,options:{secure:true},initialize:function(a){this.parent(a);Object.append(this.headers,{Accept:"application/json","X-Request":"JSON"});
+},success:function(c){var b;try{b=this.response.json=JSON.decode(c,this.options.secure);}catch(a){this.fireEvent("error",[c,a]);return;}if(b==null){this.onFailure();
+}else{this.onSuccess(b,c);}}});var Cookie=new Class({Implements:Options,options:{path:"/",domain:false,duration:false,secure:false,document:document,encode:true},initialize:function(b,a){this.key=b;
+this.setOptions(a);},write:function(b){if(this.options.encode){b=encodeURIComponent(b);}if(this.options.domain){b+="; domain="+this.options.domain;}if(this.options.path){b+="; path="+this.options.path;
+}if(this.options.duration){var a=new Date();a.setTime(a.getTime()+this.options.duration*24*60*60*1000);b+="; expires="+a.toGMTString();}if(this.options.secure){b+="; secure";
+}this.options.document.cookie=this.key+"="+b;return this;},read:function(){var a=this.options.document.cookie.match("(?:^|;)\\s*"+this.key.escapeRegExp()+"=([^;]*)");
+return(a)?decodeURIComponent(a[1]):null;},dispose:function(){new Cookie(this.key,Object.merge({},this.options,{duration:-1})).write("");return this;}});
+Cookie.write=function(b,c,a){return new Cookie(b,a).write(c);};Cookie.read=function(a){return new Cookie(a).read();};Cookie.dispose=function(b,a){return new Cookie(b,a).dispose();
+};(function(i,k){var l,f,e=[],c,b,d=k.createElement("div");var g=function(){clearTimeout(b);if(l){return;}Browser.loaded=l=true;k.removeListener("DOMContentLoaded",g).removeListener("readystatechange",a);
+k.fireEvent("domready");i.fireEvent("domready");};var a=function(){for(var m=e.length;m--;){if(e[m]()){g();return true;}}return false;};var j=function(){clearTimeout(b);
+if(!a()){b=setTimeout(j,10);}};k.addListener("DOMContentLoaded",g);var h=function(){try{d.doScroll();return true;}catch(m){}return false;};if(d.doScroll&&!h()){e.push(h);
+c=true;}if(k.readyState){e.push(function(){var m=k.readyState;return(m=="loaded"||m=="complete");});}if("onreadystatechange" in k){k.addListener("readystatechange",a);
+}else{c=true;}if(c){j();}Element.Events.domready={onAdd:function(m){if(l){m.call(this);}}};Element.Events.load={base:"load",onAdd:function(m){if(f&&this==i){m.call(this);
+}},condition:function(){if(this==i){g();delete Element.Events.load;}return true;}};i.addEvent("load",function(){f=true;});})(window,document);(function(){var Swiff=this.Swiff=new Class({Implements:Options,options:{id:null,height:1,width:1,container:null,properties:{},params:{quality:"high",allowScriptAccess:"always",wMode:"window",swLiveConnect:true},callBacks:{},vars:{}},toElement:function(){return this.object;
+},initialize:function(path,options){this.instance="Swiff_"+String.uniqueID();this.setOptions(options);options=this.options;var id=this.id=options.id||this.instance;
+var container=document.id(options.container);Swiff.CallBacks[this.instance]={};var params=options.params,vars=options.vars,callBacks=options.callBacks;
+var properties=Object.append({height:options.height,width:options.width},options.properties);var self=this;for(var callBack in callBacks){Swiff.CallBacks[this.instance][callBack]=(function(option){return function(){return option.apply(self.object,arguments);
+};})(callBacks[callBack]);vars[callBack]="Swiff.CallBacks."+this.instance+"."+callBack;}params.flashVars=Object.toQueryString(vars);if(Browser.ie){properties.classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000";
+params.movie=path;}else{properties.type="application/x-shockwave-flash";}properties.data=path;var build='<object id="'+id+'"';for(var property in properties){build+=" "+property+'="'+properties[property]+'"';
+}build+=">";for(var param in params){if(params[param]){build+='<param name="'+param+'" value="'+params[param]+'" />';}}build+="</object>";this.object=((container)?container.empty():new Element("div")).set("html",build).firstChild;
+},replaces:function(element){element=document.id(element,true);element.parentNode.replaceChild(this.toElement(),element);return this;},inject:function(element){document.id(element,true).appendChild(this.toElement());
+return this;},remote:function(){return Swiff.remote.apply(Swiff,[this.toElement()].append(arguments));}});Swiff.CallBacks={};Swiff.remote=function(obj,fn){var rs=obj.CallFunction('<invoke name="'+fn+'" returntype="javascript">'+__flash__argumentsToXML(arguments,2)+"</invoke>");
+return eval(rs);};})();
\ No newline at end of file
diff --git a/webWidgetTCT_device/doc/html/js/prettify.js b/webWidgetTCT_device/doc/html/js/prettify.js
new file mode 100755 (executable)
index 0000000..7b99049
--- /dev/null
@@ -0,0 +1,30 @@
+!function(){var q=null;window.PR_SHOULD_USE_CONTINUATION=!0;
+(function(){function S(a){function d(e){var b=e.charCodeAt(0);if(b!==92)return b;var a=e.charAt(1);return(b=r[a])?b:"0"<=a&&a<="7"?parseInt(e.substring(1),8):a==="u"||a==="x"?parseInt(e.substring(2),16):e.charCodeAt(1)}function g(e){if(e<32)return(e<16?"\\x0":"\\x")+e.toString(16);e=String.fromCharCode(e);return e==="\\"||e==="-"||e==="]"||e==="^"?"\\"+e:e}function b(e){var b=e.substring(1,e.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),e=[],a=
+b[0]==="^",c=["["];a&&c.push("^");for(var a=a?1:0,f=b.length;a<f;++a){var h=b[a];if(/\\[bdsw]/i.test(h))c.push(h);else{var h=d(h),l;a+2<f&&"-"===b[a+1]?(l=d(b[a+2]),a+=2):l=h;e.push([h,l]);l<65||h>122||(l<65||h>90||e.push([Math.max(65,h)|32,Math.min(l,90)|32]),l<97||h>122||e.push([Math.max(97,h)&-33,Math.min(l,122)&-33]))}}e.sort(function(e,a){return e[0]-a[0]||a[1]-e[1]});b=[];f=[];for(a=0;a<e.length;++a)h=e[a],h[0]<=f[1]+1?f[1]=Math.max(f[1],h[1]):b.push(f=h);for(a=0;a<b.length;++a)h=b[a],c.push(g(h[0])),
+h[1]>h[0]&&(h[1]+1>h[0]&&c.push("-"),c.push(g(h[1])));c.push("]");return c.join("")}function s(e){for(var a=e.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),c=a.length,d=[],f=0,h=0;f<c;++f){var l=a[f];l==="("?++h:"\\"===l.charAt(0)&&(l=+l.substring(1))&&(l<=h?d[l]=-1:a[f]=g(l))}for(f=1;f<d.length;++f)-1===d[f]&&(d[f]=++x);for(h=f=0;f<c;++f)l=a[f],l==="("?(++h,d[h]||(a[f]="(?:")):"\\"===l.charAt(0)&&(l=+l.substring(1))&&l<=h&&
+(a[f]="\\"+d[l]);for(f=0;f<c;++f)"^"===a[f]&&"^"!==a[f+1]&&(a[f]="");if(e.ignoreCase&&m)for(f=0;f<c;++f)l=a[f],e=l.charAt(0),l.length>=2&&e==="["?a[f]=b(l):e!=="\\"&&(a[f]=l.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return a.join("")}for(var x=0,m=!1,j=!1,k=0,c=a.length;k<c;++k){var i=a[k];if(i.ignoreCase)j=!0;else if(/[a-z]/i.test(i.source.replace(/\\u[\da-f]{4}|\\x[\da-f]{2}|\\[^UXux]/gi,""))){m=!0;j=!1;break}}for(var r={b:8,t:9,n:10,v:11,
+f:12,r:13},n=[],k=0,c=a.length;k<c;++k){i=a[k];if(i.global||i.multiline)throw Error(""+i);n.push("(?:"+s(i)+")")}return RegExp(n.join("|"),j?"gi":"g")}function T(a,d){function g(a){var c=a.nodeType;if(c==1){if(!b.test(a.className)){for(c=a.firstChild;c;c=c.nextSibling)g(c);c=a.nodeName.toLowerCase();if("br"===c||"li"===c)s[j]="\n",m[j<<1]=x++,m[j++<<1|1]=a}}else if(c==3||c==4)c=a.nodeValue,c.length&&(c=d?c.replace(/\r\n?/g,"\n"):c.replace(/[\t\n\r ]+/g," "),s[j]=c,m[j<<1]=x,x+=c.length,m[j++<<1|1]=
+a)}var b=/(?:^|\s)nocode(?:\s|$)/,s=[],x=0,m=[],j=0;g(a);return{a:s.join("").replace(/\n$/,""),d:m}}function H(a,d,g,b){d&&(a={a:d,e:a},g(a),b.push.apply(b,a.g))}function U(a){for(var d=void 0,g=a.firstChild;g;g=g.nextSibling)var b=g.nodeType,d=b===1?d?a:g:b===3?V.test(g.nodeValue)?a:d:d;return d===a?void 0:d}function C(a,d){function g(a){for(var j=a.e,k=[j,"pln"],c=0,i=a.a.match(s)||[],r={},n=0,e=i.length;n<e;++n){var z=i[n],w=r[z],t=void 0,f;if(typeof w==="string")f=!1;else{var h=b[z.charAt(0)];
+if(h)t=z.match(h[1]),w=h[0];else{for(f=0;f<x;++f)if(h=d[f],t=z.match(h[1])){w=h[0];break}t||(w="pln")}if((f=w.length>=5&&"lang-"===w.substring(0,5))&&!(t&&typeof t[1]==="string"))f=!1,w="src";f||(r[z]=w)}h=c;c+=z.length;if(f){f=t[1];var l=z.indexOf(f),B=l+f.length;t[2]&&(B=z.length-t[2].length,l=B-f.length);w=w.substring(5);H(j+h,z.substring(0,l),g,k);H(j+h+l,f,I(w,f),k);H(j+h+B,z.substring(B),g,k)}else k.push(j+h,w)}a.g=k}var b={},s;(function(){for(var g=a.concat(d),j=[],k={},c=0,i=g.length;c<i;++c){var r=
+g[c],n=r[3];if(n)for(var e=n.length;--e>=0;)b[n.charAt(e)]=r;r=r[1];n=""+r;k.hasOwnProperty(n)||(j.push(r),k[n]=q)}j.push(/[\S\s]/);s=S(j)})();var x=d.length;return g}function v(a){var d=[],g=[];a.tripleQuotedStrings?d.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?d.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/,
+q,"'\"`"]):d.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&g.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var b=a.hashComments;b&&(a.cStyleComments?(b>1?d.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):d.push(["com",/^#(?:(?:define|e(?:l|nd)if|else|error|ifn?def|include|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),g.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h(?:h|pp|\+\+)?|[a-z]\w*)>/,q])):d.push(["com",
+/^#[^\n\r]*/,q,"#"]));a.cStyleComments&&(g.push(["com",/^\/\/[^\n\r]*/,q]),g.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));if(b=a.regexLiterals){var s=(b=b>1?"":"\n\r")?".":"[\\S\\s]";g.push(["lang-regex",RegExp("^(?:^^\\.?|[+-]|[!=]=?=?|\\#|%=?|&&?=?|\\(|\\*=?|[+\\-]=|->|\\/=?|::?|<<?=?|>>?>?=?|,|;|\\?|@|\\[|~|{|\\^\\^?=?|\\|\\|?=?|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*("+("/(?=[^/*"+b+"])(?:[^/\\x5B\\x5C"+b+"]|\\x5C"+s+"|\\x5B(?:[^\\x5C\\x5D"+b+"]|\\x5C"+
+s+")*(?:\\x5D|$))+/")+")")])}(b=a.types)&&g.push(["typ",b]);b=(""+a.keywords).replace(/^ | $/g,"");b.length&&g.push(["kwd",RegExp("^(?:"+b.replace(/[\s,]+/g,"|")+")\\b"),q]);d.push(["pln",/^\s+/,q," \r\n\t\u00a0"]);b="^.[^\\s\\w.$@'\"`/\\\\]*";a.regexLiterals&&(b+="(?!s*/)");g.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/,
+q],["pun",RegExp(b),q]);return C(d,g)}function J(a,d,g){function b(a){var c=a.nodeType;if(c==1&&!x.test(a.className))if("br"===a.nodeName)s(a),a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)b(a);else if((c==3||c==4)&&g){var d=a.nodeValue,i=d.match(m);if(i)c=d.substring(0,i.index),a.nodeValue=c,(d=d.substring(i.index+i[0].length))&&a.parentNode.insertBefore(j.createTextNode(d),a.nextSibling),s(a),c||a.parentNode.removeChild(a)}}function s(a){function b(a,c){var d=
+c?a.cloneNode(!1):a,e=a.parentNode;if(e){var e=b(e,1),g=a.nextSibling;e.appendChild(d);for(var i=g;i;i=g)g=i.nextSibling,e.appendChild(i)}return d}for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),d;(d=a.parentNode)&&d.nodeType===1;)a=d;c.push(a)}for(var x=/(?:^|\s)nocode(?:\s|$)/,m=/\r\n?|\n/,j=a.ownerDocument,k=j.createElement("li");a.firstChild;)k.appendChild(a.firstChild);for(var c=[k],i=0;i<c.length;++i)b(c[i]);d===(d|0)&&c[0].setAttribute("value",d);var r=j.createElement("ol");
+r.className="linenums";for(var d=Math.max(0,d-1|0)||0,i=0,n=c.length;i<n;++i)k=c[i],k.className="L"+(i+d)%10,k.firstChild||k.appendChild(j.createTextNode("\u00a0")),r.appendChild(k);a.appendChild(r)}function p(a,d){for(var g=d.length;--g>=0;){var b=d[g];F.hasOwnProperty(b)?D.console&&console.warn("cannot override language handler %s",b):F[b]=a}}function I(a,d){if(!a||!F.hasOwnProperty(a))a=/^\s*</.test(d)?"default-markup":"default-code";return F[a]}function K(a){var d=a.h;try{var g=T(a.c,a.i),b=g.a;
+a.a=b;a.d=g.d;a.e=0;I(d,b)(a);var s=/\bMSIE\s(\d+)/.exec(navigator.userAgent),s=s&&+s[1]<=8,d=/\n/g,x=a.a,m=x.length,g=0,j=a.d,k=j.length,b=0,c=a.g,i=c.length,r=0;c[i]=m;var n,e;for(e=n=0;e<i;)c[e]!==c[e+2]?(c[n++]=c[e++],c[n++]=c[e++]):e+=2;i=n;for(e=n=0;e<i;){for(var p=c[e],w=c[e+1],t=e+2;t+2<=i&&c[t+1]===w;)t+=2;c[n++]=p;c[n++]=w;e=t}c.length=n;var f=a.c,h;if(f)h=f.style.display,f.style.display="none";try{for(;b<k;){var l=j[b+2]||m,B=c[r+2]||m,t=Math.min(l,B),A=j[b+1],G;if(A.nodeType!==1&&(G=x.substring(g,
+t))){s&&(G=G.replace(d,"\r"));A.nodeValue=G;var L=A.ownerDocument,o=L.createElement("span");o.className=c[r+1];var v=A.parentNode;v.replaceChild(o,A);o.appendChild(A);g<l&&(j[b+1]=A=L.createTextNode(x.substring(t,l)),v.insertBefore(A,o.nextSibling))}g=t;g>=l&&(b+=2);g>=B&&(r+=2)}}finally{if(f)f.style.display=h}}catch(u){D.console&&console.log(u&&u.stack||u)}}var D=window,y=["break,continue,do,else,for,if,return,while"],E=[[y,"auto,case,char,const,default,double,enum,extern,float,goto,inline,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"],
+"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],M=[E,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,delegate,dynamic_cast,explicit,export,friend,generic,late_check,mutable,namespace,nullptr,property,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],N=[E,"abstract,assert,boolean,byte,extends,final,finally,implements,import,instanceof,interface,null,native,package,strictfp,super,synchronized,throws,transient"],
+O=[N,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,internal,into,is,let,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var,virtual,where"],E=[E,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],P=[y,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"],
+Q=[y,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],W=[y,"as,assert,const,copy,drop,enum,extern,fail,false,fn,impl,let,log,loop,match,mod,move,mut,priv,pub,pure,ref,self,static,struct,true,trait,type,unsafe,use"],y=[y,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],R=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)\b/,
+V=/\S/,X=v({keywords:[M,O,E,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",P,Q,y],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),F={};p(X,["default-code"]);p(C([],[["pln",/^[^<?]+/],["dec",/^<!\w[^>]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",
+/^<xmp\b[^>]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^<script\b[^>]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^<style\b[^>]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);p(C([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/],
+["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css",/^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);p(C([],[["atv",/^[\S\s]+/]]),["uq.val"]);p(v({keywords:M,hashComments:!0,cStyleComments:!0,types:R}),["c","cc","cpp","cxx","cyc","m"]);p(v({keywords:"null,true,false"}),["json"]);p(v({keywords:O,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:R}),
+["cs"]);p(v({keywords:N,cStyleComments:!0}),["java"]);p(v({keywords:y,hashComments:!0,multiLineStrings:!0}),["bash","bsh","csh","sh"]);p(v({keywords:P,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}),["cv","py","python"]);p(v({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:2}),["perl","pl","pm"]);p(v({keywords:Q,
+hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb","ruby"]);p(v({keywords:E,cStyleComments:!0,regexLiterals:!0}),["javascript","js"]);p(v({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,throw,true,try,unless,until,when,while,yes",hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);p(v({keywords:W,cStyleComments:!0,multilineStrings:!0}),["rc","rs","rust"]);
+p(C([],[["str",/^[\S\s]+/]]),["regex"]);var Y=D.PR={createSimpleLexer:C,registerLangHandler:p,sourceDecorator:v,PR_ATTRIB_NAME:"atn",PR_ATTRIB_VALUE:"atv",PR_COMMENT:"com",PR_DECLARATION:"dec",PR_KEYWORD:"kwd",PR_LITERAL:"lit",PR_NOCODE:"nocode",PR_PLAIN:"pln",PR_PUNCTUATION:"pun",PR_SOURCE:"src",PR_STRING:"str",PR_TAG:"tag",PR_TYPE:"typ",prettyPrintOne:D.prettyPrintOne=function(a,d,g){var b=document.createElement("div");b.innerHTML="<pre>"+a+"</pre>";b=b.firstChild;g&&J(b,g,!0);K({h:d,j:g,c:b,i:1});
+return b.innerHTML},prettyPrint:D.prettyPrint=function(a,d){function g(){for(var b=D.PR_SHOULD_USE_CONTINUATION?c.now()+250:Infinity;i<p.length&&c.now()<b;i++){for(var d=p[i],j=h,k=d;k=k.previousSibling;){var m=k.nodeType,o=(m===7||m===8)&&k.nodeValue;if(o?!/^\??prettify\b/.test(o):m!==3||/\S/.test(k.nodeValue))break;if(o){j={};o.replace(/\b(\w+)=([\w%+\-.:]+)/g,function(a,b,c){j[b]=c});break}}k=d.className;if((j!==h||e.test(k))&&!v.test(k)){m=!1;for(o=d.parentNode;o;o=o.parentNode)if(f.test(o.tagName)&&
+o.className&&e.test(o.className)){m=!0;break}if(!m){d.className+=" prettyprinted";m=j.lang;if(!m){var m=k.match(n),y;if(!m&&(y=U(d))&&t.test(y.tagName))m=y.className.match(n);m&&(m=m[1])}if(w.test(d.tagName))o=1;else var o=d.currentStyle,u=s.defaultView,o=(o=o?o.whiteSpace:u&&u.getComputedStyle?u.getComputedStyle(d,q).getPropertyValue("white-space"):0)&&"pre"===o.substring(0,3);u=j.linenums;if(!(u=u==="true"||+u))u=(u=k.match(/\blinenums\b(?::(\d+))?/))?u[1]&&u[1].length?+u[1]:!0:!1;u&&J(d,u,o);r=
+{h:m,c:d,j:u,i:o};K(r)}}}i<p.length?setTimeout(g,250):"function"===typeof a&&a()}for(var b=d||document.body,s=b.ownerDocument||document,b=[b.getElementsByTagName("pre"),b.getElementsByTagName("code"),b.getElementsByTagName("xmp")],p=[],m=0;m<b.length;++m)for(var j=0,k=b[m].length;j<k;++j)p.push(b[m][j]);var b=q,c=Date;c.now||(c={now:function(){return+new Date}});var i=0,r,n=/\blang(?:uage)?-([\w.]+)(?!\S)/,e=/\bprettyprint\b/,v=/\bprettyprinted\b/,w=/pre|xmp/i,t=/^code$/i,f=/^(?:pre|code|xmp)$/i,
+h={};g()}};typeof define==="function"&&define.amd&&define("google-code-prettify",[],function(){return Y})})();}()
diff --git a/webWidgetTCT_device/doc/package.json b/webWidgetTCT_device/doc/package.json
new file mode 100755 (executable)
index 0000000..2a7a069
--- /dev/null
@@ -0,0 +1,10 @@
+{
+  "name": "WebApiGuidelines",
+  "version": "0.3.0",
+  "dependencies": {
+    "doctor-md": "git://github.com/Hagith/doctor.git#print-css"
+  },
+  "scripts": {
+    "generate": "doctor -i src/index.md -o html --title 'Tizen Avengers - WebApi Guidelines' --images src/assets/images --logo images/tizen-logo_32h.png"
+  }
+}
diff --git a/webWidgetTCT_device/doc/src/assets/images/plugin_flow.png b/webWidgetTCT_device/doc/src/assets/images/plugin_flow.png
new file mode 100755 (executable)
index 0000000..42ea946
Binary files /dev/null and b/webWidgetTCT_device/doc/src/assets/images/plugin_flow.png differ
diff --git a/webWidgetTCT_device/doc/src/assets/images/tizen-logo_32h.png b/webWidgetTCT_device/doc/src/assets/images/tizen-logo_32h.png
new file mode 100755 (executable)
index 0000000..c0c9246
Binary files /dev/null and b/webWidgetTCT_device/doc/src/assets/images/tizen-logo_32h.png differ
diff --git a/webWidgetTCT_device/doc/src/assets/webapi-plugins-devel-test.zip b/webWidgetTCT_device/doc/src/assets/webapi-plugins-devel-test.zip
new file mode 100755 (executable)
index 0000000..b940fb5
Binary files /dev/null and b/webWidgetTCT_device/doc/src/assets/webapi-plugins-devel-test.zip differ
diff --git a/webWidgetTCT_device/doc/src/devel_package.md b/webWidgetTCT_device/doc/src/devel_package.md
new file mode 100755 (executable)
index 0000000..601cb3e
--- /dev/null
@@ -0,0 +1,161 @@
+## Devel package
+
+After build process webapi-plugins-devel-xxx.rpm should be generated in gbs directory.
+Package contains required common headers files, gypi files and webapi-plugins.pc file.
+
+### Package structure
+```sh
+|-usr
+|---include
+|-----webapi-plugins
+|-------src
+|---------common
+|-------tools
+|---------gyp
+|-----------pylib
+|-------------gyp
+|---------------generator
+|---lib
+|-----pkgconfig
+```
+
+File webapi-plugins.pc source:
+```
+project_name=webapi-plugins
+dirname=tizen-extensions-crosswalk
+prefix=/usr
+exec_prefix=${prefix}
+libdir=${prefix}/lib/${dirname}
+includedir=${prefix}/include/${project_name}/src
+
+Name: ${project_name}
+Description: ${project_name}
+Version:
+Requires: dbus-1 dlog glib-2.0
+Libs: -L${libdir} -ltizen_common
+Cflags: -I${includedir}
+```
+
+### Creating custom web device plugins module
+
+To create custom web device plugins module ```webapi-plugins.spec```, ```tizen-wrt.gyp``` and ```src``` files are needed.
+Skeleton below shows the required structure of test module.
+
+```sh
+├── packaging
+│   └── webapi-plugins.spec
+└── src
+│   ├── test
+│   ├── test_api.js
+│   ├── test_extension.cc
+│   ├── test_extension.h
+│   ├── test.gyp
+│   ├── test_instance.cc
+│   └── test_instance.h
+└── tizen-wrt.gyp
+```
+
+webapi-plugins.spec source:
+```
+%define _manifestdir %{TZ_SYS_RW_PACKAGES}
+%define _desktop_icondir %{TZ_SYS_SHARE}/icons/default/small
+
+%define crosswalk_extensions tizen-extensions-crosswalk
+
+Name:       webapi-plugins-test
+Version:    0.1
+Release:    0
+License:    Apache-2.0 and BSD-2.0 and MIT
+Group:      Development/Libraries
+Summary:    Tizen Web APIs implemented
+Source0:    %{name}-%{version}.tar.gz
+
+BuildRequires: ninja
+BuildRequires: pkgconfig(webapi-plugins)
+
+%description
+Tizen Test Web APIs.
+
+%prep
+%setup -q
+
+%build
+
+export GYP_GENERATORS='ninja'
+GYP_OPTIONS="--depth=. -Dtizen=1 -Dextension_build_type=Debug -Dextension_host_os=%{tizen_profile_name} -Dprivilege_engine=%{tizen_privilege_engine}"
+GYP_OPTIONS="$GYP_OPTIONS -Ddisplay_type=x11"
+
+/usr/include/webapi-plugins/tools/gyp/gyp $GYP_OPTIONS src/tizen-wrt.gyp
+
+ninja -C out/Default %{?_smp_mflags}
+
+%install
+mkdir -p %{buildroot}%{_libdir}/%{crosswalk_extensions}
+install -p -m 644 out/Default/libtizen*.so %{buildroot}%{_libdir}/%{crosswalk_extensions}
+
+%files
+%{_libdir}/%{crosswalk_extensions}/libtizen*.so
+```
+
+tizen-wrt.gyp source:
+```
+{
+  'includes':[
+    '/usr/include/webapi-plugins/src/common/common.gypi',
+  ],
+
+  'targets': [
+    {
+      'target_name': 'extensions',
+      'type': 'none',
+      'dependencies': [
+        'test/test.gyp:*',
+      ],
+      'conditions': [],
+    },
+  ],
+}
+```
+
+test.gyp source:
+```
+{
+  'includes':[
+    '/usr/include/webapi-plugins/src/common/common.gypi',
+  ],
+  'targets': [
+    {
+      'target_name': 'tizen_test',
+      'type': 'loadable_module',
+      'sources': [
+        'test_api.js',
+        'test_extension.cc',
+        'test_extension.h',
+        'test_instance.cc',
+        'test_instance.h',
+      ],
+      'include_dirs': [
+        '../',
+        '<(SHARED_INTERMEDIATE_DIR)',
+      ],
+      'variables': {
+        'packages': [
+          'webapi-plugins',
+        ],
+      },
+    },
+  ],
+}
+```
+
+[webapi-plugins-devel-test.zip](../src/assets/webapi-plugins-devel-test.zip) contains test module which depends on webapi-plugins devel package.
+Custom web device plugins module test is placed in ```src/``` directory and contains all required files.
+Please see [Plugin structure](#plugin-structure) chapter for more details.
+
+To install custom web device plugins module ```webapi-plugins-xxx.rpm``` and ```webapi-plugins-devel-xxx.rpm``` must be installed first.
+After build and installation webapi-plugins-devel-test ```tizen.test``` namespace should be available.
+
+```javascript
+var test = tizen.test.ping();
+console.log(test); // Hello!
+```
diff --git a/webWidgetTCT_device/doc/src/guideline.md b/webWidgetTCT_device/doc/src/guideline.md
new file mode 100755 (executable)
index 0000000..a3b3183
--- /dev/null
@@ -0,0 +1,58 @@
+## Guideline
+
+### Languages
+
+C++, JavaScript
+
+### Codding style
+
+Use Google style guide,
+C++: http://google-styleguide.googlecode.com/svn/trunk/cppguide.html
+
+JavaScript: http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml
+
+### API guide
+
+Tizen Web Device API Guide Lines.pptx
+http://platform.sec.samsung.net/slp/Tizen/Tizen%20Managed%20API/Web%20Device%20API/Tizen%20Web%20Device%20API%20Guide%20Lines.pptx
+
+### Unit test criteria
+
+Tizen-Compliance-Tests-Device-API-UnitTest-Criteria.v0.11_SRPOL.xlsx
+http://platform.sec.samsung.net/slp/Tizen/Tizen%20Managed%20API/Web%20Device%20API/Tizen-Compliance-Tests-Device-API-UnitTest-Criteria.v0.11_SRPOL.xlsx
+
+### Source code
+
+For Tizen 2.4:
+```sh
+$ git clone ssh://<user.id>@168.219.209.56:29418/framework/web/webapi-plugins
+$ cd webapi-plugins
+$ git checkout origin/tizen_2.4
+```
+For Tizen 3.0
+```sh
+$ git clone ssh://<user.id>@168.219.209.56:29418/framework/web/webapi-plugins
+$ cd webapi-plugins
+$ git checkout origin/tizen_3.0
+```
+
+### License and Boilerplate
+
+Use this boilerplate in every new created source files.
+```sh
+/*
+ * Copyright (c) 2015 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.
+ */
+```
diff --git a/webWidgetTCT_device/doc/src/implementation_cc.md b/webWidgetTCT_device/doc/src/implementation_cc.md
new file mode 100755 (executable)
index 0000000..b681a0c
--- /dev/null
@@ -0,0 +1,192 @@
+## Implementation - C++
+
+### Lifecycle and plugin state
+
+All plugins instances are created by runtime on application launch.
+It's important to not initialize any database/service connections and platform
+handlers in instance constructor. All resources should be "lazy" initialized
+just before first use, to keep starting time as short as possible.
+Initialized resources can be referenced to instance and kept for further usage.
+Instance destructor is called on application termination and should release all
+used resources to prevent memory leaks.
+
+Native layer should be considered as stateless. It means that there is
+no strict reference between JavaScript and native data.<br>
+Example: If operation should change some object retrieved from platform,
+identifier should be passed again and additional check if object still exists
+should be made.
+
+### Namespace and entry points
+
+Extension namespace and other objects exported by JavaScript layer are defined
+inside ```<pluginname>_extension.cc``` file.
+
+```cpp
+SetExtensionName("tizen.notification"); //exported in JS as new NotificationManager();
+const char* entry_points[] = {"tizen.StatusNotification",
+                              "tizen.NotificationDetailInfo",
+                              NULL};
+```
+
+### Plugin structure
+
+In general ```Instance``` class (```<pluginname>_instance.cc```) should be
+treated as command dispatcher and should be as small as possible (similar to Controller in MVC).
+It's responsibility should be limited to reading/validating arguments,
+forwarding call to business logic component and passing result to JavaScript layer.
+Business logic should be implemented in additional classes with
+[SOLID][1] principles in mind.
+
+Commands callable from JavaScript layer should be registered in constructor of
+```<PluginName>Instance``` class which extends ```common::ParsedInstance```.
+
+```cpp
+// <pluginname>_instance.h
+class MediaControllerInstance : public common::ParsedInstance {}
+```
+
+Currently there is no difference in registering sync and async commands.
+But good practice is to separate them for readability and maintainability.
+Common practice is to define two macros and call ```RegisterSyncHandler```
+method from ```common::ParsedInstance```.
+
+```cpp
+// <pluginname>_instance.cc
+MediaControllerInstance::MediaControllerInstance() {
+  #define REGISTER_SYNC(c, x) \
+      RegisterSyncHandler(c, std::bind(&MediaControllerInstance::x, this, _1, _2));
+  #define REGISTER_ASYNC(c, x) \
+      RegisterSyncHandler(c, std::bind(&MediaControllerInstance::x, this, _1, _2));
+
+  REGISTER_SYNC("MediaControllerManager_getClient",
+      MediaControllerManagerGetClient);
+  REGISTER_ASYNC("MediaControllerClient_findServers",
+      MediaControllerClientFindServers);
+
+  // ... other commands
+
+  #undef REGISTER_SYNC
+  #undef REGISTER_ASYNC
+}
+```
+
+Static method registered as a handler must have proper signature:
+```cpp
+void InstanceClass::HandlerName(const picojson::value& args, picojson::object& out);
+```
+
+- ```args``` - object containing arguments passed from JavaScript layer
+- ```out``` - object containing response data returned synchronously to JavaScript
+  layer.
+
+```ReportSuccess()``` or ```ReportError()``` helpers should be used to ensure
+proper structure of ```out``` object.
+
+```cpp
+picojson::value data = picojson::value<picojson::object());
+const PlatformResult& result = model_->DoSomethingWithData(&data);
+if (!result) {
+  LOGGER(ERROR) << result.message();
+  ReportError(result, &out);
+  return;
+}
+
+ReportSuccess(data, out);
+```
+
+### Asynchronous calls
+
+To perform asynchronous request ```common::TaskQueue``` component should be used.
+You should use lambda expression which calls business logic and passes result to
+JavaScript layer by calling ```PostMessage(const char* msg)```.
+
+Asynchronous response is not matched to request automatically. You should pass
+```callbackId``` received from JavaScript layer as an argument. It allows to
+call the appropriate user callback in JS async message handler.
+
+```cpp
+auto search = [this, args]() -> void {
+
+  // business logic
+  picojson::value servers = picojson::value(picojson::array());
+  PlatformResult result = client_->FindServers(&servers.get<picojson::array>());
+
+  // response object
+  picojson::value response = picojson::value(picojson::object());
+  picojson::object& response_obj = response.get<picojson::object>();
+  response_obj["callbackId"] = args.get("callbackId");
+  if (result) {
+    ReportSuccess(servers, response_obj);
+  } else {
+    ReportError(result, &response_obj);
+  }
+
+  // post JSON string to JS layer
+  PostMessage(response.serialize().c_str());
+};
+
+TaskQueue::GetInstance().Async(search);
+```
+
+### Listeners
+
+Sending events from platform listeners is very similar to sending asynchronous
+responses. ```PostMessage(const char* msg)``` should be called with ```listenerId```
+passed from JavaScript layer.
+
+```cpp
+auto listener = [this, args](picojson::value* data) -> void {
+
+  if (!data) {
+    LOGGER(ERROR) << "No data passed to json callback";
+    return;
+  }
+
+  picojson::object& request_o = data->get<picojson::object>();
+  request_o["listenerId"] = args.get("listenerId");
+
+  PostMessage(data->serialize().c_str());
+};
+```
+
+### Logger
+
+Logger is available from ```common/logger.h``` header. There are macros:
+* ```LOGGER(priority)``` prints message with given priority
+* ```LOGGER_IF(priority, condition)``` prints message with given priority when condition is met
+
+Available log priorities are: ```DEBUG```, ```INFO```, ```WARN```, ```ERROR```
+and should be used to filter messages based on level of importance. Example:
+
+```cpp
+LOGGER(ERROR) << "Scan file failed, error: " << res;
+LOGGER_IF(DEBUG, variable < 0) << "Value is lower than zero";
+```
+
+### Error handling
+
+Regarding to [Google C++ Style Guide][2] we do not use Exceptions.
+
+To deliver error conditions to JavaScript layer, that can occur in the platform,
+```PlatformResult``` class should be used. All available error codes are defined
+in ```common/platform_result.h```
+
+PlatformResult can be returned anywhere in native layer and it should be
+converted to exception and thrown in JavaScript layer:
+
+```cpp
+// C++ layer
+return PlatformResult(ErrorCode::NOT_FOUND_ERR, "Cannot remove notification error");
+return PlatformResult(ErrorCode::UNKNOWN_ERR, "Cannot get notification id error");
+```
+
+```js
+// JavaScript layer
+var native_ = new xwalk.utils.NativeManager(extension);
+if (native_.isFailure(ret)) {
+  throw native_.getErrorObject(ret);
+}
+```
+
+  [1]: http://en.wikipedia.org/wiki/SOLID_(object-oriented_design)
+  [2]: http://google-styleguide.googlecode.com/svn/trunk/cppguide.html#Exceptions
diff --git a/webWidgetTCT_device/doc/src/implementation_js.md b/webWidgetTCT_device/doc/src/implementation_js.md
new file mode 100755 (executable)
index 0000000..533703f
--- /dev/null
@@ -0,0 +1,205 @@
+## Implementation - JavaScript
+
+Each plugin contains JavaScript files. This is the place where user input is
+being processed validated before send to C++ layer.
+
+Badge API will be used to show the creation of JavaScript file (lot of content
+of this file will be already generated via Stub Generator).
+
+### Interface creation
+
+The WIDL of BadgeManager – main entity that holds all the API methods
+looks like following:
+
+```
+[NoInterfaceObject] interface BadgeManager {
+  readonly attribute long maxBadgeCount
+  void setBadgeCount(ApplicationId appId, long count) raises(WebAPIException);
+  long getBadgeCount(ApplicationId appId) raises(WebAPIException);
+  void addChangeListener(ApplicationId[]appIdList, BadgeChangeCallback successCallback) raises(WebAPIException);
+  void removeChangeListener(ApplicationId[] appIdList) raises(WebAPIException);
+};
+```
+
+### Creating Manager entity
+
+Object that will hold attributes and methods is defined as JavaScript function:
+
+```js
+function BadgeManager() {}
+```
+
+### Properties definition
+
+Properties are defined within the created JavaScript function like this:
+
+```js
+var MAX_BADGE_COUNT = 999;
+Object.defineProperties(this, {
+  maxBadgeCount: {value: MAX_BADGE_COUNT, emumerable: true, writable: false}
+});
+```
+
+Because the property was defined as ```const```, writable is set to false.
+
+### Methods definition
+
+In accordance to WIDL BadgeManager contains setBadgeCount method.
+To define this method within JavaScript use prototype extension functionality:
+
+```js
+BadgeManager.prototype.setBadgeCount = function() {};
+```
+
+### Exporting interface
+
+Once the object is created and all the methods and attributes are set it has to
+be exported so it will be visible when making call to tizen.badge namespace.
+This is done using assigning new object instance to exports variable:
+
+```js
+exports = new BadgeManager(); //exported as tizen.badge
+exports = new CalendarManager(); //exported as tizen.calendar
+```
+
+Other namespaces within the module are exported as below:
+
+```js
+tizen.CalendarAttendee = CalendarAttendee;
+tizen.CalendarEvent = CalendarEvent;
+tizen.CalendarTask = CalendarTask;
+```
+
+### Utils
+
+In ```src/utils/utils_api.js``` file there is a lot of useful tools that allow
+automatization of certain operations. Most often used tools from utils_api.js
+are converter and validator. All tools are available under ```xwalk.utils``` namespace.
+
+#### Converter
+
+A lot of times conversion between JavaScript types will be required.
+The converter tool was created in order to make this operation easier.
+
+```js
+var converter_ = xwalk.utils.converter;
+var number = converter_.toLong(result);
+```
+
+#### Validator
+
+When API JavaScript method is called first thing that has to be done in
+JavaScript layer of api implementation is to process and validate arguments
+given by the user. The process of validation consists of ensuring that the
+proper amount of arguments was given and that they were of the expected
+type and throwing exception if necessary.
+
+Validator helps to ensure that user sent proper values. Validator is available
+at ```xwalk.utils.validator``` and predefined js types at ```xwalk.utils.validator.types```
+
+Below can be found example of using validator inside ```setBadgeCount``` method
+that requires appId in form of string and long count value:
+
+```js
+var validator_ = xwalk.utils.validator;
+var types_ = validator_.Types;
+
+var args = validator_.validateArgs(arguments, [
+  {name: 'appId', type: types_.STRING},
+  {name: 'count', type: types_.LONG}
+]);
+```
+
+#### Privileges
+
+Some of the API methods require privilege access, then it's the first step
+in JavaScript file which should be checked.
+
+Below can be found example of using Privilege in Alarm API:
+
+```js
+var Privilege = xwalk.utils.privilege;
+
+// inside add, remove, removeAll methods:
+xwalk.utils.checkPrivilegeAccess(Privilege.ALARM);
+```
+
+### Exceptions
+
+At some point whether improper data is received or given to JavaScript might
+require to throw exceptions. The example below shows how to throw properly
+predefined exceptions:
+
+```js
+throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR,
+                          'Incorrect number of arguments');
+```
+
+WebAPIException constructor takes as argument the type of error to be thrown.
+The second additional argument is error message.
+
+### Synchronous methods
+
+In order to perform synchronous operation (one that does not require callback
+and the result is given instantly) callSync() method of Native manager needs
+to be called:
+
+```js
+var native_ = new xwalk.utils.NativeManager(extension);
+var ret = native_.callSync('BadgeManager_setBadgeCount', {
+  appId: args.appId,
+  count: args.count
+});
+if (native_.isFailure(ret)) {
+  throw native_.getErrorObject(ret);
+}
+```
+
+The first argument is the command name registered in C++ layer that has to be called,
+the second is arguments object that will be passed to this method.
+Result is assigned to ret variable.
+
+### Asynchronous methods
+
+In order to work with method that requires callback instead of callSync(),
+call() method needs to be called. Apart from the first two arguments that are
+exactly the same as in call() method (c++ method binding, object) it takes
+additional argument that is a function that will be called when the native
+call is processed:
+
+```js
+var native_ = new xwalk.utils.NativeManager(extension);
+var callback = function(result) {
+  if (native_.isFailure(result)) {
+    native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+  } else {
+    var calendars = native_.getResultObject(result);
+    var c = [];
+    calendars.forEach(function(i) {
+      c.push(new Calendar(new InternalCalendar(i)));
+    });
+    args.successCallback(c);
+  }
+};
+
+native_.call('CalendarManager_getCalendars', callArgs, callback);
+```
+
+### Listeners
+
+In order to work with listeners NativeManager provides ```addListener``` and
+```removeListener``` methods. This method takes two arguments: one is unique
+```listenerId``` that will be processed when making a call from C++ to JavaScript.
+The second one is the function that is called whenever expected event occurs.
+
+```js
+var native_ = new xwalk.utils.NativeManager(extension);
+var listenerId = 'PLUGIN_LISTENER_NAME';
+native_.addListener(listenerId, function(data) {
+  // handle event data
+});
+native.callSync('Calendar_addChangeListener', {
+  type: this.type,
+  listenerId: listenerId
+});
+```
diff --git a/webWidgetTCT_device/doc/src/index.md b/webWidgetTCT_device/doc/src/index.md
new file mode 100755 (executable)
index 0000000..46e1e57
--- /dev/null
@@ -0,0 +1,26 @@
+# Tizen Avengers - WebApi Guidelines
+
+## Revision History
+| Version | Date | Description | Editor |
+|---------|------|-------------|--------|
+| 0.1.0 | 2015-05-15 | Initial Draft | Wojciech Kosowicz<br><w.kosowicz@samsung.com> |
+| 0.2.0 | 2015-05-22 | Extended version | Pawel Kaczmarek<br><p.kaczmarek3@samsung.com> |
+| 0.2.1 | 2015-06-01 | Proofreading | Rafal Galka<br><r.galka@samsung.com> |
+| 0.3.0 | 2015-06-08 | Supplemented C++ implementation guide | Rafal Galka<br><r.galka@samsung.com> |
+| 0.4.0 | 2015-06-16 | Guideline | Pawel Kaczmarek<br><p.kaczmarek3@samsung.com> |
+| 0.5.0 | 2015-06-18 | Devel package | Pawel Kaczmarek<br><p.kaczmarek3@samsung.com> |
+| 0.5.1 | 2015-06-24 | Add info about WAPIOven.py | Pawel Kaczmarek<br><p.kaczmarek3@samsung.com> |
+
+## Overview
+This document should be used as a guideline for developers who are creating web
+plugins for Tizen platform. Conventions and practices described here could be
+used to develop new web plugins for Tizen 2.4 platform and higher version.
+Each plugin should be written with great attention on JavaScript.
+
+{{>src/guideline.md}}
+{{>src/plugin_structure.md}}
+{{>src/widl.md}}
+{{>src/tools.md}}
+{{>src/implementation_js.md}}
+{{>src/implementation_cc.md}}
+{{>src/devel_package.md}}
diff --git a/webWidgetTCT_device/doc/src/plugin_structure.md b/webWidgetTCT_device/doc/src/plugin_structure.md
new file mode 100755 (executable)
index 0000000..54c1606
--- /dev/null
@@ -0,0 +1,57 @@
+## Plugin Structure
+
+### Conventions
+
+Each plugin is kept in separate directory inside src/ folder written in lowercase convention.
+
+### Structure
+
+Each plugin contains following structure:
+* ```<pluginname>.gyp```
+* ```<pluginname>_api.js```
+* ```<pluginname>_extension.h```
+* ```<pluginname>_extension.cc```
+* ```<pluginname>_instance.h```
+* ```<pluginname>_instance.cc```
+
+### Spec file
+
+Spec file (```webapi-plugins.spec```) kept inside ```packaging/``` directory
+is build specification file used by rpm packaging system where variables are defined.
+Those variables can be used to include or exclude particular modules from
+build for each profile (mobile, TV, wearable).
+
+### GYP file
+
+Each plugin has its own gyp file that contains information specific for it.
+Plugin configuration file (gyp) is the equivalent of CMake.
+It contains information what files to build what libraries to use for linking.
+There can be also found one main gyp file in ```src/``` folder (```tizen-wrt.gyp```)
+that includes others.
+
+### Implementation files
+
+Description of files required in plugin implementation.
+* **C++ files** (```<pluginname>_extension.h, <pluginname>_extension.cc```)<br>
+  Extension namespace and other objects exported by JavaScript layer are set inside these files.
+* **C++ files** (```<pluginname>_instance.h, <pluginname>_instance.cc```)<br>
+  These files are responsible for communication between JavaScript layer and Native API.
+* **JavaScript file** (```<pluginname>_api.js```)<br>
+  This file contains all methods required by each API.
+  All operation should be done by JavaScript as much as possible.
+  If JavaScript can do something, it should do it.
+  This file is responsible for checking privileges, checking arguments, calling C++ methods etc.
+
+### Plugin flow
+
+![Plugin flow](images/plugin_flow.png)
+
+Explanation of steps:
+1. From JavaScript Layer information is sent to C++ Layer.
+   This information consists of type of call (asynchronous, synchronous)
+   arguments given by user, any additional information that is required to
+   successfully acquire required data. Data is sent in form of JSON.
+2. C++ parses acquired JSON. After the data is processed. Appropriate platform
+   functions are called with the specified arguments.
+3. Platform returns specified values to C++ layer.
+4. Another JSON is formed. It consists of data that was acquired from platform.
diff --git a/webWidgetTCT_device/doc/src/tools.md b/webWidgetTCT_device/doc/src/tools.md
new file mode 100755 (executable)
index 0000000..c1e6ffa
--- /dev/null
@@ -0,0 +1,71 @@
+## Tools
+
+### Generate stub code
+
+To generate stub files from the widl you can use stub generator located in
+```tools/skeleton_generator/``` directory and run the python command:
+
+```sh
+$ python WAPIOven.py -d <stub code destination directory name> <widl directory/pluginname>.widl
+```
+
+Path to WAPIOven.py:
+```sh
+$ tools/skeleton_generator/WAPIOven.py
+```
+
+You need to install jinja2 for WAPIOven.py:
+```sh
+$ sudo apt-get install python-jinja2
+```
+
+Example:
+```sh
+$ sudo apt-get install python-jinja2
+$ cd tools/skeleton_generator/
+$ python WAPIOven.py -d ../../src/notification/ /web-device-api/web/widl/tizen/notification.widl
+```
+
+WIDL files can be found in the project repository:
+
+```sh
+$ git clone ssh://<username>@168.219.209.56:29418/doc/web-device-api
+```
+
+The widl files are placed in: ```web-device-api/web/widl/tizen/```
+
+Stub files generated by above command:
+
+```sh
+<pluginname>_api.js
+<pluginname>_extension.h
+<pluginname>_extension.cc
+<pluginname>_instance.h
+<pluginname>_instance.cc
+```
+
+What should be done when skeleton code was generated?
+- ```<pluginname>.gyp``` file should be added
+- required privileges should be added in JavaScript file
+- entry points should be checked in ```<pluginname>_extension.cc``` file
+- each method should be implemented in ```<pluginname>_instance.cc``` file
+
+### Using multiple JavaScript files
+
+To use multiple JavaScript files in one plugin create ```js/``` directory inside
+plugin directory and place JavaScript files.
+
+Inside ```<pluginname>_api.js``` required JavaScript files should be added:
+```sh
+//= require('common.js');
+//= require('calendar_item.js');
+//= require('calendar.js');
+//= require('calendar_manager.js');
+//= require('calendar_attendee.js');
+//= require('calendar_alarm.js');
+//= require('calendar_recurrence_rule.js');
+```
+
+To merge all JavaScript files ```tools/mergejs.py``` file is used.
+This script merge all files mentioned in ```<pluginname>_api.js``` file into one
+file before build process.
diff --git a/webWidgetTCT_device/doc/src/widl.md b/webWidgetTCT_device/doc/src/widl.md
new file mode 100755 (executable)
index 0000000..703958f
--- /dev/null
@@ -0,0 +1,152 @@
+## WIDL
+
+### Conventions
+
+Currently WIDL version that is used in Samsung is described here: http://www.w3.org/TR/WebIDL/.
+This is document from 19 April 2012.
+
+WIDL used for plugins creation is closer to previous drafts mainly this from
+21 October 2010. It is described here: http://www.w3.org/TR/2010/WD-WebIDL-20101021/.
+
+### Architecture
+
+Each plugin is separated from each other as a different module.
+We do this by using module key name.
+
+```
+module identifer {
+  definitions
+}
+```
+
+Each module describes space, binding many connected definitions in one namespace.
+Inside each module there are sets of **interface** defined.
+Most of the time there is one major interface defined, which is **NoInterfaceObject**.
+This is manager object which has only one property which is object that actually
+implements manager functionality.
+
+```
+interface identifier : indentifier-of-inherited-interface {
+  interface-member...
+};
+```
+
+Interface is a definition of an object, which can be realized in a system
+(an inheritance and overloading is possible).
+In interface definition you can put following members:
+* Constants.
+* Attribute : Interface member, which represents variable inside object,
+  can be changed, if it is not read only.
+* Operation: Interface member, which represents method inside object.
+  It is a function of programming language, which can be executed and returns a result.
+* Special operation: Performs a specific task. i.e. deleter, getter
+* Static operation: It is not called for a specific instance of the interface,
+  is called for static object regardless of an instance creation.
+  It is connected with the interface itself.
+
+```
+interface identifier {
+  attribute type identifier;
+  [extended-attribute] const type identifier = value;
+  [extended-attribute] attribute type identifier;
+  readonly attribute type identifier;
+  attribute type identifier inherits getter; ///Declared to change read only attribute //inherited from interface
+  attribute type identifier getraises (NoSuchValue); ///Exception declaration
+  return-type identifier(arguments…);
+  return-type identifier(argument-type argument-identifier); ///regular operation
+  return-type identifier(optional argument);
+  special-keywords return-type identifier(arguments); ///special operation
+  [extended-attribute]return-type identifier(arguments…); ///A variable number of //arguments
+  return-type identifier(arguments) raises (identifier) ///raises exception
+  caller return-type identifier(argument);
+  caller return-type (argument);
+  static return-type identifier(arguments);
+};
+```
+
+Next step is to connect manager implementation with Tizen object.
+
+```
+Tizen implements ManagerObject
+```
+
+To provide actual implementations of ManagerObject, instance of its Manager
+interface definition has to be made. Inside this Manager interface all attributes
+and functions that will be available form manager namespace, should be defined.
+There can be attributes which are other interfaces, operations and everything
+that interfaces allows.
+
+Additional interface can be available as a standalone types not connected to
+global namespace. Those are either obtained from operation of other interfaces
+or constructed with theirs constructor method. Interface which are constructible
+are described as follows:
+
+```
+[Constructor(type arg1, optional type? Arg2)]
+Interface ConstructibleInterface {
+  attributes
+  operations
+  an so on...
+};
+```
+
+As one can see list of parameters is specified for such constructor.
+Not all parameters are mandatory, some can be preceded by ```optional```
+keyword and ```?``` mark, after type to mark that this is not obligatory argument.
+Additionally some operations can be followed by ```raises``` key word to mark that,
+described exception type can be thrown during execution of such method.
+
+Because some operations can be asynchronous, it is necessary to provide callbacks
+objects that can be executed by such operation. Callback object is special type
+of ```interface``` object with ```Callback=FunctionOnly``` extended attribute.
+
+```
+[Callback=FunctionOnly, NoInterfaceObject] interface SomeCallback {
+  void someMethod(type agr1, ...)
+};
+```
+
+On the purpose of listeners which accepts dictionaries, there are callbacks that
+support more than one method. There is another definition of callback which
+lacks of keyword ```FunctionOnly```.
+
+```
+[Callback, NoInterfaceObject] interface SomeDictionaryCallback {
+  void firstmethod(type somearg1, ... );
+  void secondmethod(type somearg2, ... );
+  any additional methods...
+};
+```
+
+### Example
+
+Example of WIDL file:
+```
+module Sample {
+
+  enum SampleEnums {
+    "ENUM1",
+    "ENUM2",
+    "ENUM3",
+  };
+
+  typedef (SampleEnums) SampleType;
+
+  [NoInterfaceObject] interface SampleManagerObject {
+    readonly attribute SampleManager sample;
+  };
+
+  Tizen implements SampleManagerObject;
+
+  [NoInterfaceObject] interface SampleManager {
+    void sampleMethod(SampleType param1, Sample2 param2) raises(WebAPIException);
+    double sampleMethod2(SampleType param1) raises(WebAPIException);
+    void sampleMethod3(SampleCallback callback) raises(WebAPIException);
+  };
+
+  [Callback=FunctionOnly, NoInterfaceObject]
+  interface SampleCallback {
+    void onsuccess(Sample1 param1, Sample2 param2);
+  };
+};
+```
diff --git a/webWidgetTCT_device/install.sh b/webWidgetTCT_device/install.sh
new file mode 100755 (executable)
index 0000000..3653795
--- /dev/null
@@ -0,0 +1,4 @@
+./tools/launcher/deploy.sh
+sdb push test/ /home/owner/share/wrt-service-tct/
+sdb root off
+sdb install DeviceAPI.wgt
diff --git a/webWidgetTCT_device/packaging/webapi-plugins.pc b/webWidgetTCT_device/packaging/webapi-plugins.pc
new file mode 100755 (executable)
index 0000000..2cd06ac
--- /dev/null
@@ -0,0 +1,13 @@
+project_name=webapi-plugins
+dirname=tizen-extensions-crosswalk
+prefix=/usr
+exec_prefix=${prefix}
+libdir=${prefix}/lib/${dirname}
+includedir=${prefix}/include/${project_name}/src
+
+Name: ${project_name}
+Description: ${project_name}
+Version:
+Requires: dbus-1 dlog glib-2.0
+Libs: -L${libdir} -ltizen_common
+Cflags: -I${includedir}
diff --git a/webWidgetTCT_device/packaging/webapi-plugins.spec b/webWidgetTCT_device/packaging/webapi-plugins.spec
new file mode 100755 (executable)
index 0000000..a565153
--- /dev/null
@@ -0,0 +1,612 @@
+%define _manifestdir %{TZ_SYS_RW_PACKAGES}
+%define _desktop_icondir %{TZ_SYS_SHARE}/icons/default/small
+
+#this should be provided by gbs:
+%define model_build_feature_tv 1
+
+%if 0%{?model_build_feature_tv}
+%define tizen_tv_product 1
+%endif
+
+%define crosswalk_extensions tizen-extensions-crosswalk
+
+Name:       webapi-plugins
+Version:    0.60.12+tv
+Release:    0
+License:    Apache-2.0 and BSD-2.0 and MIT
+Group:      Development/Libraries
+Summary:    Tizen Web APIs implemented
+Source0:    %{name}-%{version}.tar.gz
+
+%ifarch %{arm}
+# ARM
+%define tizen_is_emulator           0
+%else
+# I586
+%define tizen_is_emulator           1
+%endif
+
+####################################################################
+#       Mobile Profile :  Redwood(SM-Z910F), KIRAN(Z130H)          #
+####################################################################
+%if "%{?tizen_profile_name}" == "mobile"
+
+%define tizen_privilege_engine                        ACE
+
+%define tizen_feature_account_support                 1
+%define tizen_feature_alarm_support                   1
+%define tizen_feature_app_control_settings_support    1
+%define tizen_feature_application_support             1
+%define tizen_feature_archive_support                 1
+%define tizen_feature_badge_support                   1
+%ifarch %{arm}
+# ARM
+%define tizen_feature_bluetooth_support               1
+%else
+# I586
+%define tizen_feature_bluetooth_support               0
+%endif
+%define tizen_feature_bookmark_support                1
+%define tizen_feature_calendar_support                1
+%define tizen_feature_contact_support                 1
+%define tizen_feature_content_support                 1
+%define tizen_feature_datacontrol_support             1
+%define tizen_feature_datasync_support                0
+%define tizen_feature_download_support                1
+%define tizen_feature_exif_support                    1
+%define tizen_feature_filesystem_support              1
+%define tizen_feature_fm_radio_support                1
+%ifarch %{arm}
+# ARM
+%define tizen_feature_ham_support                     0
+%else
+# I586
+%define tizen_feature_ham_support                     1
+%endif
+%define tizen_feature_location_batch                  0
+%define tizen_feature_key_manager_support             0
+%define tizen_feature_media_controller_support        1
+%ifarch %{arm}
+# ARM
+%define tizen_feature_media_key_support               1
+%else
+# I586
+%define tizen_feature_media_key_support               0
+%endif
+%define tizen_feature_message_port_support            1
+%define tizen_feature_messaging_support               1
+
+%if 0%{?model_build_feature_nfc}
+%define tizen_feature_nfc_emulation_support           0
+%define tizen_feature_nfc_support                     1
+%else
+%define tizen_feature_nfc_emulation_support           0
+%define tizen_feature_nfc_support                     0
+%endif
+%define tizen_feature_notification_support            1
+%define tizen_feature_package_support                 1
+%define tizen_feature_power_support                   1
+%define tizen_feature_push_support                    1
+%ifarch %{arm}
+# ARM
+%define tizen_feature_se_support                      1
+%else
+# I586
+%define tizen_feature_se_support                      0
+%endif
+%define tizen_feature_sensor_support                  1
+%define tizen_feature_smart_controller_support        0
+%define tizen_feature_sound_support                   1
+%define tizen_feature_system_info_support             1
+%define tizen_feature_system_setting_support          1
+%ifarch %{arm}
+# ARM
+%define tizen_feature_telephony_support               1
+%else
+# I586
+%define tizen_feature_telephony_support               0
+%endif
+%define tizen_feature_time_support                    1
+%define tizen_feature_web_setting_support             1
+%ifarch %{arm}
+# ARM
+%define tizen_feature_wi_fi_support                   1
+%else
+# I586
+%define tizen_feature_wi_fi_support                   0
+%endif
+%define tizen_feature_tvaudio_support                 0
+%define tizen_feature_tvchannel_support               0
+%define tizen_feature_tv_display_support              0
+%define tizen_feature_tvinfo_support                  0
+%define tizen_feature_tvinputdevice_support           0
+%define tizen_feature_inputdevice_support             1
+%define tizen_feature_tvwindow_support                0
+
+%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
+
+%endif # tizen_profile_mobile
+
+####################################################################
+#       Wearable Profile :  B2                          #
+####################################################################
+%if "%{?tizen_profile_name}" == "wearable"
+
+%define tizen_privilege_engine                        ACE
+
+# Account API is optional in Tizen Wearable Profile.
+%define tizen_feature_account_support                 0
+
+%define tizen_feature_alarm_support                   1
+%define tizen_feature_app_control_settings_support    1
+%define tizen_feature_application_support             1
+
+# Archive API is optional in Tizen Wearable Profile.
+%define tizen_feature_archive_support                 1
+
+# Badge API is mandatory in Tizen Wearable Profile.
+%define tizen_feature_badge_support                   1
+
+%define tizen_feature_bluetooth_support               1
+
+# Bookmark API is optional in Tizen Wearable Profile.
+%define tizen_feature_bookmark_support                0
+
+# Calendar API is mandatory in Tizen Wearable Profile.
+%define tizen_feature_calendar_support                0
+%define tizen_feature_contact_support                 0
+%define tizen_feature_content_support                 1
+%define tizen_feature_datacontrol_support             0
+%define tizen_feature_datasync_support                0
+%ifarch %{arm}
+%define tizen_feature_download_support                0
+%else
+%define tizen_feature_download_support                1
+%endif
+%define tizen_feature_exif_support                    1
+%define tizen_feature_filesystem_support              1
+%define tizen_feature_fm_radio_support                0
+%define tizen_feature_ham_support                     1
+%define tizen_feature_location_batch                  0
+%define tizen_feature_media_controller_support        1
+
+# MediayKey API is optional in Tizen Wearable Profile.
+# tizen.org/feature/network.bluetooth.audio.media is required for MediayKey API
+%ifarch %{arm}
+# ARM
+%define tizen_feature_media_key_support               1
+%else
+# I586
+%define tizen_feature_media_key_support               0
+%endif
+%define tizen_feature_key_manager_support             0
+%define tizen_feature_message_port_support            1
+%define tizen_feature_messaging_support               0
+
+%if 0%{?model_build_feature_nfc}
+%define tizen_feature_nfc_emulation_support           0
+%define tizen_feature_nfc_support                     1
+%else
+%define tizen_feature_nfc_emulation_support           0
+%define tizen_feature_nfc_support                     0
+%endif
+%define tizen_feature_notification_support            1
+%define tizen_feature_package_support                 1
+%define tizen_feature_power_support                   1
+%define tizen_feature_push_support                    1
+%if 0%{?model_build_feature_smartcard }
+%define tizen_feature_se_support                      1
+%else
+%define tizen_feature_se_support                      0
+%endif
+%define tizen_feature_sensor_support                  1
+%define tizen_feature_smart_controller_support        0
+%define tizen_feature_sound_support                   1
+%define tizen_feature_system_info_support             1
+%define tizen_feature_system_setting_support          1
+%define tizen_feature_telephony_support               0
+%define tizen_feature_time_support                    1
+%define tizen_feature_web_setting_support             0
+%define tizen_feature_wi_fi_support                   1
+%define tizen_feature_tvaudio_support                 0
+%define tizen_feature_tvchannel_support               0
+%define tizen_feature_tv_display_support              0
+%define tizen_feature_tvinfo_support                  0
+%define tizen_feature_tvinputdevice_support           0
+%define tizen_feature_inputdevice_support             1
+%define tizen_feature_tvwindow_support                0
+
+#- telephony related APIs
+# CallHistory API is optional in Tizen Wearable Profile.
+# NetworkBearerSelection API is optional in Tizen Wearable 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
+
+%endif # tizen_profile_wearable
+
+####################################################################
+#       TV Profile                                                 #
+####################################################################
+%if "%{?tizen_profile_name}" == "tv"
+
+%define tizen_privilege_engine                        ACE
+
+%define tizen_feature_account_support                 0
+%define tizen_feature_alarm_support                   1
+%define tizen_feature_app_control_settings_support    0
+%define tizen_feature_application_support             1
+%define tizen_feature_archive_support                 1
+%define tizen_feature_badge_support                   0
+%define tizen_feature_bluetooth_support               0
+%define tizen_feature_bookmark_support                0
+%define tizen_feature_calendar_support                0
+%define tizen_feature_callhistory_support             0
+%define tizen_feature_contact_support                 0
+%define tizen_feature_content_support                 1
+%define tizen_feature_datacontrol_support             1
+%define tizen_feature_datasync_support                0
+%define tizen_feature_download_support                1
+%define tizen_feature_exif_support                    1
+%define tizen_feature_filesystem_support              1
+%define tizen_feature_fm_radio_support                0
+%define tizen_feature_ham_support                     0
+%define tizen_feature_inputdevice_support             0
+%define tizen_feature_key_manager_support             1
+%define tizen_feature_media_controller_support        0
+%define tizen_feature_media_key_support               0
+%define tizen_feature_message_port_support            1
+%define tizen_feature_messaging_support               0
+%define tizen_feature_nbs_support                     0
+%define tizen_feature_nfc_emulation_support           0
+%define tizen_feature_nfc_support                     0
+%define tizen_feature_notification_support            0
+%define tizen_feature_package_support                 1
+%define tizen_feature_power_support                   0
+%define tizen_feature_push_support                    0
+%define tizen_feature_se_support                      0
+%define tizen_feature_sensor_support                  0
+%define tizen_feature_smart_controller_support        1
+%define tizen_feature_sound_support                   0
+%define tizen_feature_system_info_support             1
+%define tizen_feature_system_setting_support          0
+%define tizen_feature_telephony_support               0
+%define tizen_feature_time_support                    1
+%define tizen_feature_web_setting_support             1
+%define tizen_feature_wi_fi_support                   1
+%if 0%{?tizen_tv_product}
+%define tizen_feature_tvaudio_support                 1
+%define tizen_feature_tvchannel_support               1
+%define tizen_feature_tv_display_support              1
+%define tizen_feature_tvinfo_support                  1
+%define tizen_feature_tvinputdevice_support           1
+%define tizen_feature_tvwindow_support                1
+%define tizen_capi_system_usbdevice                   1
+%else
+%define tizen_feature_tvaudio_support                 0
+%define tizen_feature_tvchannel_support               0
+%define tizen_feature_tv_display_support              0
+%define tizen_feature_tvinputdevice_support           0
+%define tizen_feature_tvwindow_support                0
+%define tizen_capi_system_usbdevice                   0
+%endif
+
+%endif # tizen_profile_tv
+
+BuildRequires: ninja
+BuildRequires: pkgconfig(appcore-common)
+BuildRequires: pkgconfig(dlog)
+BuildRequires: pkgconfig(evas)
+BuildRequires: pkgconfig(gio-2.0)
+BuildRequires: pkgconfig(glib-2.0)
+BuildRequires: pkgconfig(libudev)
+BuildRequires: pkgconfig(minizip)
+BuildRequires: pkgconfig(zlib)
+BuildRequires: pkgconfig(pkgmgr)
+BuildRequires: pkgconfig(pkgmgr-info)
+BuildRequires: pkgconfig(vconf)
+BuildRequires: pkgconfig(x11)
+BuildRequires: pkgconfig(xrandr)
+BuildRequires: pkgconfig(ecore)
+BuildRequires: pkgconfig(icu-i18n)
+BuildRequires: pkgconfig(aul)
+BuildRequires: pkgconfig(storage)
+BuildRequires: python
+BuildRequires: pkgconfig(capi-base-common)
+BuildRequires: pkgconfig(capi-system-info)
+BuildRequires: pkgconfig(capi-system-runtime-info)
+BuildRequires: pkgconfig(capi-network-connection)
+BuildRequires: pkgconfig(capi-system-device)
+BuildRequires: pkgconfig(capi-system-system-settings)
+BuildRequires: pkgconfig(capi-network-bluetooth)
+BuildRequires: pkgconfig(capi-network-wifi)
+BuildRequires: pkgconfig(tapi)
+BuildRequires: pkgconfig(libpcrecpp)
+BuildRequires: pkgconfig(capi-appfw-application)
+BuildRequires: pkgconfig(capi-appfw-app-manager)
+BuildRequires: pkgconfig(capi-appfw-package-manager)
+BuildRequires: pkgconfig(capi-content-media-content)
+BuildRequires: pkgconfig(capi-media-metadata-extractor)
+
+%if 0%{?tizen_capi_system_usbdevice}
+BuildRequires: pkgconfig(capi-system-usbdevice)
+%endif
+
+%if "%{?tizen_privilege_engine}" == "ACE"
+BuildRequires: pkgconfig(security-privilege-checker)
+%endif
+
+%if "%{?tizen_privilege_engine}" == "CYNARA"
+BuildRequires: pkgconfig(cynara-client)
+BuildRequires: pkgconfig(libsmack)
+%endif
+
+%if 0%{?tizen_feature_account_support}
+BuildRequires: pkgconfig(accounts-svc)
+%endif
+
+%if 0%{?tizen_feature_alarm_support}
+BuildRequires: pkgconfig(capi-appfw-alarm)
+BuildRequires: pkgconfig(alarm-service)
+%endif
+
+%if 0%{?tizen_feature_bookmark_support}
+BuildRequires: pkgconfig(capi-web-bookmark)
+BuildRequires: pkgconfig(bookmark-adaptor)
+%endif
+
+%if 0%{?tizen_feature_datacontrol_support}
+BuildRequires: pkgconfig(capi-data-control)
+%endif
+
+%if 0%{?tizen_feature_download_support}
+BuildRequires: pkgconfig(capi-web-url-download)
+%endif
+
+%if 0%{?tizen_feature_ham_support}
+BuildRequires: pkgconfig(motion)
+BuildRequires: pkgconfig(capi-system-sensor)
+BuildRequires: pkgconfig(capi-location-manager)
+%endif
+
+%if 0%{?tizen_feature_power_support}
+BuildRequires: pkgconfig(deviced)
+%endif
+
+%if 0%{?tizen_feature_power_support}
+BuildRequires: pkgconfig(capi-appfw-application)
+%endif
+
+%if 0%{?tizen_feature_push_support}
+BuildRequires: pkgconfig(push)
+%endif
+
+%if 0%{?tizen_feature_key_manager_support}
+BuildRequires: pkgconfig(key-manager)
+%endif
+
+%if 0%{?tizen_feature_media_controller_support}
+BuildRequires: pkgconfig(capi-media-controller)
+%endif
+
+%if 0%{?tizen_feature_messaging_support}
+BuildRequires:  pkgconfig(ecore-file)
+BuildRequires:  pkgconfig(email-service)
+BuildRequires:  pkgconfig(msg-service)
+BuildRequires:  pkgconfig(db-util)
+%endif
+
+%if 0%{?tizen_feature_badge_support}
+BuildRequires:  pkgconfig(badge)
+%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_callhistory_support}
+BuildRequires:  pkgconfig(contacts-service2)
+%endif
+
+%if 0%{?tizen_feature_tvchannel_support}
+BuildRequires: pkgconfig(tvs-api)
+%endif
+
+%if 0%{?tizen_feature_tvwindow_support}
+BuildRequires: pkgconfig(tvs-api)
+%endif
+
+%if 0%{?tizen_feature_exif_support}
+BuildRequires:  pkgconfig(libexif)
+%endif
+
+%if 0%{?tizen_feature_nfc_support}
+BuildRequires:  pkgconfig(capi-network-nfc)
+%endif
+
+%if 0%{?tizen_feature_fm_radio_support}
+BuildRequires: pkgconfig(capi-media-radio)
+%endif
+
+%if 0%{?tizen_feature_tvaudio_support}
+BuildRequires:  pkgconfig(libavoc)
+BuildRequires:  pkgconfig(capi-media-audio-io)
+BuildRequires:  pkgconfig(capi-media-sound-manager)
+BuildRequires:  pkgconfig(capi-media-sound-manager-tv)
+%endif
+
+%if 0%{?tizen_feature_se_support}
+BuildRequires:  pkgconfig(smartcard-service)
+BuildRequires:  pkgconfig(smartcard-service-common)
+%endif
+
+%if 0%{?tizen_feature_message_port_support}
+BuildRequires: pkgconfig(capi-message-port)
+%endif
+
+%if 0%{?tizen_feature_notification_support}
+BuildRequires: pkgconfig(notification)
+%endif
+
+%if 0%{?tizen_feature_sound_support}
+BuildRequires:  pkgconfig(capi-media-sound-manager)
+%endif
+
+%if 0%{?tizen_feature_sensor_support}
+BuildRequires: pkgconfig(capi-system-sensor)
+%endif
+
+%if 0%{?tizen_feature_media_key_support}
+BuildRequires:  pkgconfig(capi-system-media-key)
+%endif
+
+%description
+Tizen Web APIs implemented.
+
+%package devel
+Summary:    webapi-plugins development headers
+Group:      Development/Libraries
+Requires:   %{name} = %{version}
+Requires:   capi-appfw-app-manager
+Requires:   capi-appfw-package-manager
+Requires:   libstorage
+Requires:   security-privilege-checker
+Requires:   tvs-api
+Requires:   capi-system-usbdevice
+
+%description devel
+webapi-plugins development headers
+
+%prep
+%setup -q
+
+%build
+
+export GYP_GENERATORS='ninja'
+GYP_OPTIONS="--depth=. -Dtizen=1 -Dextension_build_type=Debug -Dextension_host_os=%{tizen_profile_name} -Dprivilege_engine=%{tizen_privilege_engine}"
+GYP_OPTIONS="$GYP_OPTIONS -Ddisplay_type=x11"
+
+# feature flags
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_tv_product=%{?tizen_tv_product}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_is_emulator=%{?tizen_is_emulator}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_account_support=%{?tizen_feature_account_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_alarm_support=%{?tizen_feature_alarm_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_app_control_settings_support=%{?tizen_feature_app_control_settings_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_application_support=%{?tizen_feature_application_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_archive_support=%{?tizen_feature_archive_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_badge_support=%{?tizen_feature_badge_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_bluetooth_support=%{?tizen_feature_bluetooth_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_bookmark_support=%{?tizen_feature_bookmark_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_calendar_support=%{?tizen_feature_calendar_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_callhistory_support=%{?tizen_feature_callhistory_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_contact_support=%{?tizen_feature_contact_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_content_support=%{?tizen_feature_content_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_datacontrol_support=%{?tizen_feature_datacontrol_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_datasync_support=%{?tizen_feature_datasync_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_download_support=%{?tizen_feature_download_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_exif_support=%{?tizen_feature_exif_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_filesystem_support=%{?tizen_feature_filesystem_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_fm_radio_support=%{?tizen_feature_fm_radio_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_ham_support=%{?tizen_feature_ham_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_location_batch=%{?tizen_feature_location_batch}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_key_manager_support=%{?tizen_feature_key_manager_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_media_controller_support=%{?tizen_feature_media_controller_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_media_key_support=%{?tizen_feature_media_key_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_message_port_support=%{?tizen_feature_message_port_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_messaging_support=%{?tizen_feature_messaging_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_nbs_support=%{?tizen_feature_nbs_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_nfc_emulation_support=%{?tizen_feature_nfc_emulation_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_nfc_support=%{?tizen_feature_nfc_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_notification_support=%{?tizen_feature_notification_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_package_support=%{?tizen_feature_package_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_power_support=%{?tizen_feature_power_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_push_support=%{?tizen_feature_push_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_sap_support=%{?tizen_feature_sap_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_sensor_support=%{?tizen_feature_sensor_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_se_support=%{?tizen_feature_se_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_smart_controller_support=%{?tizen_feature_smart_controller_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_sound_support=%{?tizen_feature_sound_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_system_info_support=%{?tizen_feature_system_info_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_system_setting_support=%{?tizen_feature_system_setting_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_telephony_support=%{?tizen_feature_telephony_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_time_support=%{tizen_feature_time_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_tvaudio_support=%{?tizen_feature_tvaudio_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_tvchannel_support=%{?tizen_feature_tvchannel_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_tv_display_support=%{?tizen_feature_tv_display_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_tvinfo_support=%{?tizen_feature_tvinfo_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_tvinputdevice_support=%{?tizen_feature_tvinputdevice_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_inputdevice_support=%{?tizen_feature_inputdevice_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_tvwindow_support=%{?tizen_feature_tvwindow_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_web_setting_support=%{?tizen_feature_web_setting_support}"
+GYP_OPTIONS="$GYP_OPTIONS -Dtizen_feature_wi_fi_support=%{?tizen_feature_wi_fi_support}"
+
+./tools/gyp/gyp $GYP_OPTIONS src/tizen-wrt.gyp
+
+ninja -C out/Default %{?_smp_mflags}
+
+%install
+mkdir -p %{buildroot}/usr/share/license
+cp LICENSE %{buildroot}/usr/share/license/%{name}
+cat LICENSE.BSD-2.0 >> %{buildroot}/usr/share/license/%{name}
+
+# Extensions.
+mkdir -p %{buildroot}%{_libdir}/%{crosswalk_extensions}
+install -p -m 644 out/Default/libtizen*.so %{buildroot}%{_libdir}/%{crosswalk_extensions}
+
+# devel files
+mkdir -p %{buildroot}%{_libdir}/pkgconfig
+cp packaging/%{name}.pc %{buildroot}%{_libdir}/pkgconfig
+mkdir -p %{buildroot}%{_includedir}/%{name}/src/common
+install -p -m 644 src/common/*.h %{buildroot}%{_includedir}/%{name}/src/common
+install -p -m 644 src/common/*.gypi %{buildroot}%{_includedir}/%{name}/src/common
+install -p -m 644 src/common/XW_Extension.cc %{buildroot}%{_includedir}/%{name}/src/common
+mkdir -p %{buildroot}%{_includedir}/%{name}/tools
+install -p -m 644 tools/generate_api.py %{buildroot}%{_includedir}/%{name}/tools
+install -p -m 644 tools/mergejs.py %{buildroot}%{_includedir}/%{name}/tools
+install -p -m 644 tools/js_minimize.py %{buildroot}%{_includedir}/%{name}/tools
+cp -a tools/gyp %{buildroot}%{_includedir}/%{name}/tools/gyp
+cp -a tools/slimit %{buildroot}%{_includedir}/%{name}/tools/slimit
+cp -a out/Default/desc_gentool %{buildroot}%{_includedir}/%{name}/tools/desc_gentool
+
+%if 0%{?tizen_feature_tvaudio_support}
+# tv audio beep files:
+%define ringtones_directory /opt/usr/share/settings/Ringtones/
+mkdir -p %{buildroot}%{ringtones_directory}
+cp res/tvsounds/*.pcm %{buildroot}%{ringtones_directory}
+%endif
+
+# execute desc_gentool
+LD_LIBRARY_PATH=$LD_LIBRARY_PATH:%{buildroot}%{_libdir}/%{crosswalk_extensions} out/Default/desc_gentool %{buildroot}%{_libdir}/%{crosswalk_extensions} > plugins.json
+
+# temporary plugins description for lazy loading
+install -p -m 644 plugins.json %{buildroot}%{_libdir}/%{crosswalk_extensions}/plugins.json
+
+
+%files
+%{_libdir}/%{crosswalk_extensions}/libtizen*.so
+%{_libdir}/%{crosswalk_extensions}/plugins.json
+%{_datadir}/license/%{name}
+%manifest webapi-plugins.manifest
+
+%if 0%{?tizen_feature_tvaudio_support}
+# tv audio beep files:
+%{ringtones_directory}/*.pcm
+%endif
+
+%files devel
+%{_includedir}/*
+%{_libdir}/pkgconfig/*
diff --git a/webWidgetTCT_device/res/tvsounds/back.pcm b/webWidgetTCT_device/res/tvsounds/back.pcm
new file mode 100755 (executable)
index 0000000..ee41b2a
Binary files /dev/null and b/webWidgetTCT_device/res/tvsounds/back.pcm differ
diff --git a/webWidgetTCT_device/res/tvsounds/cancel.pcm b/webWidgetTCT_device/res/tvsounds/cancel.pcm
new file mode 100755 (executable)
index 0000000..1707745
Binary files /dev/null and b/webWidgetTCT_device/res/tvsounds/cancel.pcm differ
diff --git a/webWidgetTCT_device/res/tvsounds/del.pcm b/webWidgetTCT_device/res/tvsounds/del.pcm
new file mode 100755 (executable)
index 0000000..7ace3f4
Binary files /dev/null and b/webWidgetTCT_device/res/tvsounds/del.pcm differ
diff --git a/webWidgetTCT_device/res/tvsounds/enter.pcm b/webWidgetTCT_device/res/tvsounds/enter.pcm
new file mode 100755 (executable)
index 0000000..405233d
Binary files /dev/null and b/webWidgetTCT_device/res/tvsounds/enter.pcm differ
diff --git a/webWidgetTCT_device/res/tvsounds/keypad.pcm b/webWidgetTCT_device/res/tvsounds/keypad.pcm
new file mode 100755 (executable)
index 0000000..c6c7dcb
Binary files /dev/null and b/webWidgetTCT_device/res/tvsounds/keypad.pcm differ
diff --git a/webWidgetTCT_device/res/tvsounds/move.pcm b/webWidgetTCT_device/res/tvsounds/move.pcm
new file mode 100755 (executable)
index 0000000..c72792b
Binary files /dev/null and b/webWidgetTCT_device/res/tvsounds/move.pcm differ
diff --git a/webWidgetTCT_device/res/tvsounds/preparing.pcm b/webWidgetTCT_device/res/tvsounds/preparing.pcm
new file mode 100755 (executable)
index 0000000..f2f808e
Binary files /dev/null and b/webWidgetTCT_device/res/tvsounds/preparing.pcm differ
diff --git a/webWidgetTCT_device/res/tvsounds/select.pcm b/webWidgetTCT_device/res/tvsounds/select.pcm
new file mode 100755 (executable)
index 0000000..db86f0d
Binary files /dev/null and b/webWidgetTCT_device/res/tvsounds/select.pcm differ
diff --git a/webWidgetTCT_device/res/tvsounds/warning.pcm b/webWidgetTCT_device/res/tvsounds/warning.pcm
new file mode 100755 (executable)
index 0000000..d4ca5ea
Binary files /dev/null and b/webWidgetTCT_device/res/tvsounds/warning.pcm differ
diff --git a/webWidgetTCT_device/src/account/account.gyp b/webWidgetTCT_device/src/account/account.gyp
new file mode 100755 (executable)
index 0000000..272a043
--- /dev/null
@@ -0,0 +1,33 @@
+{
+  'includes':[
+    '../common/common.gypi',
+  ],
+  'targets': [
+    {
+      'target_name': 'tizen_account',
+      'type': 'loadable_module',
+      'dependencies': [
+        '../common/common.gyp:tizen_common',
+      ],
+      'sources': [
+        'account_api.js',
+        'account_extension.cc',
+        'account_extension.h',
+        'account_instance.cc',
+        'account_instance.h',
+        'account_manager.cc',
+        'account_manager.h',
+      ],
+      'conditions': [
+        ['tizen == 1', {
+          'variables': {
+            'packages': [
+              'capi-appfw-package-manager',
+              'accounts-svc',
+            ]
+          },
+        }],
+      ],
+    },
+  ],
+}
diff --git a/webWidgetTCT_device/src/account/account_api.js b/webWidgetTCT_device/src/account/account_api.js
new file mode 100755 (executable)
index 0000000..6c1c84c
--- /dev/null
@@ -0,0 +1,443 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+var validator_ = xwalk.utils.validator;
+var types_ = validator_.Types;
+var T_ = xwalk.utils.type;
+var native_ = new xwalk.utils.NativeManager(extension);
+
+
+function InternalValues_(data) {
+    if (!(this instanceof InternalValues_)) {
+        return new InternalValues_(data);
+    }
+    for(var key in data) {
+        if (data.hasOwnProperty(key)) {
+            this[key] = data[key];
+        }
+    }
+}
+
+
+function AccountProvider(data) {
+    var internal_ = [];
+    if (data) {
+        internal_ = data.capabilities;
+    }
+    Object.freeze(internal_);
+
+    Object.defineProperties(this, {
+        applicationId:              { enumerable: true, writable: false, value: data.applicationId },
+        displayName:                { enumerable: true, writable: false, value: data.displayName },
+        iconUri:                    { enumerable: true, writable: false, value: data.iconUri },
+        smallIconUri:               { enumerable: true, writable: false, value: data.smallIconUri },
+        capabilities:               { enumerable: true,
+                                      set: function() {},
+                                      get: function() { return internal_; }
+                                    },
+        isMultipleAccountSupported: { enumerable: true, writable: false, value: data.isMultipleAccountSupported },
+    });
+}
+
+
+function Account() {
+    validator_.isConstructorCall(this, tizen.Account);
+    var args = validator_.validateArgs(arguments, [
+        { name: 'provider', type: types_.PLATFORM_OBJECT, values: AccountProvider },
+        { name: 'accountInitDict', type: types_.DICTIONARY, optional: true, nullable: true }
+    ]);
+
+    var _internal = { id: null };
+
+    Object.defineProperties(this, {
+        id:         { enumerable: true,
+                      set: function (value) { if (value instanceof InternalValues_) _internal.id = value.id; },
+                      get: function () { return _internal.id; }
+        },
+        userName:   { enumerable: true, writable: true,
+                      value: (args.accountInitDict ? args.accountInitDict.userName : null) },
+        iconUri:    { enumerable: true, writable: true,
+                      value: (args.accountInitDict ? args.accountInitDict.iconUri : null) },
+        provider:   { enumerable: true, writable: false, value: args.provider }
+    });
+}
+
+
+Account.prototype.setExtendedData = function() {
+    xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.ACCOUNT_WRITE);
+
+    var args = validator_.validateArgs(arguments, [
+        { name: 'key', type: types_.STRING },
+        { name: 'value', type: types_.STRING }
+    ]);
+
+    var result = native_.callSync('Account_setExtendedData',
+                                  {
+                                      accountId: this.id,
+                                      key: args.key,
+                                      value: args.value
+                                  }
+    );
+
+    if (native_.isFailure(result)) {
+        throw native_.getErrorObject(result);
+    }
+};
+
+
+Account.prototype.getExtendedData = function() {
+    xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.ACCOUNT_READ);
+
+    if (T_.isFunction(arguments[0]) || arguments.length > 1) {
+        var args = validator_.validateArgs(arguments, [
+            {
+                name : 'successCallback',
+                type : types_.FUNCTION
+            },
+            {
+                name : 'errorCallback',
+                type : types_.FUNCTION,
+                optional : true,
+                nullable : true
+            }
+        ]);
+
+        // TODO handling exceptions
+
+        native_.call('Account_getExtendedData', { accountId: this.id },
+            function(result) {
+                if (native_.isFailure(result)) {
+                    if(!T_.isNullOrUndefined(args.errorCallback)) {
+                        args.errorCallback(native_.getErrorObject(result));
+                    }
+                } else {
+                    var data = native_.getResultObject(result);
+                    for (var i = 0; i < data.length; ++i) {
+                        Object.freeze(data[i]);
+                    }
+                    args.successCallback(native_.getResultObject(result));
+                }
+            }
+        );
+    } else {
+        var args = validator_.validateArgs(arguments, [
+            { name: 'key', type: types_.STRING }
+        ]);
+
+        var result = native_.callSync('Account_getExtendedDataSync',
+                                      {
+                                           accountId: this.id,
+                                           key: args.key
+                                      }
+        );
+        if (native_.isFailure(result)) {
+            throw native_.getErrorObject(result);
+        }
+        return native_.getResultObject(result);
+    }
+};
+
+
+function AccountFromResult(result) {
+    var provider = new AccountProvider(result.provider);
+    var account = new Account(provider, result.accountInitDict);
+    account.id = new InternalValues_({ id: result.id });
+    return account;
+}
+
+
+function AccountManager() {}
+
+
+AccountManager.prototype.add = function() {
+    xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.ACCOUNT_WRITE);
+
+    var args = validator_.validateArgs(arguments, [
+        { name: 'account', type: types_.PLATFORM_OBJECT, values: Account }
+    ]);
+
+    var result = native_.callSync('AccountManager_add',
+                                  {
+                                      userName: args.account.userName,
+                                      iconUri: args.account.iconUri,
+                                      applicationId: args.account.provider.applicationId
+                                  }
+    );
+
+    if (native_.isFailure(result)) {
+        throw native_.getErrorObject(result);
+    } else {
+        args.account.id = new InternalValues_({ id: native_.getResultObject(result) });
+    }
+}
+
+
+AccountManager.prototype.remove = function() {
+    xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.ACCOUNT_WRITE);
+
+    var args = validator_.validateArgs(arguments, [
+        { name: 'accountId', type: types_.UNSIGNED_LONG}
+    ]);
+
+    var result = native_.callSync('AccountManager_remove', { accountId: args.accountId });
+
+    if (native_.isFailure(result)) {
+        throw native_.getErrorObject(result);
+    }
+}
+
+
+AccountManager.prototype.update = function() {
+    xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.ACCOUNT_WRITE);
+
+    var args = validator_.validateArgs(arguments, [
+        { name: 'account', type: types_.PLATFORM_OBJECT, values: Account }
+    ]);
+
+    var result = native_.callSync('AccountManager_update',
+                                  {
+                                      accountId:  args.account.id,
+                                      userName:   args.account.userName,
+                                      iconUri:    args.account.iconUri
+                                  }
+    );
+
+    if (native_.isFailure(result)) {
+        throw native_.getErrorObject(result);
+    }
+}
+
+
+AccountManager.prototype.getAccount = function() {
+    xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.ACCOUNT_READ);
+
+    var args = validator_.validateArgs(arguments, [
+        { name: 'accountId', type: types_.UNSIGNED_LONG }
+    ]);
+
+    var result = native_.callSync(
+                        'AccountManager_getAccount',
+                        { accountId: args.accountId }
+    );
+
+    if (native_.isFailure(result)) {
+        throw native_.getErrorObject(result);
+    }
+
+    var account_result = native_.getResultObject(result);
+
+    if (!T_.isNull(account_result)) {
+        return AccountFromResult(account_result);
+    } else {
+        return null;
+    }
+}
+
+
+AccountManager.prototype.getAccounts = function() {
+    xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.ACCOUNT_READ);
+
+    var args = validator_.validateArgs(arguments, [
+        { name: 'successCallback', type: types_.FUNCTION, optional: false, nullable: false },
+        { name: 'errorCallback', type: types_.FUNCTION, optional: true, nullable: true },
+        { name: 'applicationId', type: types_.STRING, optional: true, nullable: true }
+    ]);
+
+    // TODO handling exceptions
+
+    native_.call('AccountManager_getAccounts',
+        {
+            applicationId: args.applicationId
+        },
+        function(result) {
+            if (native_.isFailure(result)) {
+                if(!T_.isNullOrUndefined(args.errorCallback)) {
+                    args.errorCallback(native_.getErrorObject(result));
+                }
+            } else {
+                var accounts_result = native_.getResultObject(result);
+                var accounts_table = [];
+                for (var i = 0; i < accounts_result.length; i++) {
+                    accounts_table[i] = AccountFromResult(accounts_result[i]);
+                }
+                args.successCallback(accounts_table);
+            }
+        }
+    );
+}
+
+
+AccountManager.prototype.getProvider = function() {
+    xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.ACCOUNT_READ);
+
+    var args = validator_.validateArgs(arguments, [
+        { name: 'applicationId', type: types_.STRING }
+    ]);
+
+    var result = native_.callSync(
+                        'AccountManager_getProvider',
+                        { applicationId: args.applicationId }
+    );
+
+    if (native_.isFailure(result)) {
+        throw native_.getErrorObject(result);
+    }
+
+    var provider_result = native_.getResultObject(result);
+
+    if (!T_.isNull(provider_result)) {
+        return new AccountProvider(provider_result);
+    } else {
+        return null;
+    }
+};
+
+
+AccountManager.prototype.getProviders = function() {
+    xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.ACCOUNT_READ);
+
+    var args = validator_.validateArgs(arguments, [
+        { name: 'successCallback', type: types_.FUNCTION, optional: false, nullable: false },
+        { name: 'errorCallback', type: types_.FUNCTION, optional: true, nullable: true },
+        { name: 'capability', type: types_.STRING, optional: true, nullable: true }
+    ]);
+
+    // TODO handling exceptions
+
+    native_.call( 'AccountManager_getProviders',
+        {
+            capability: args.capability
+        },
+        function(result) {
+            if (native_.isFailure(result)) {
+                if(!T_.isNullOrUndefined(args.errorCallback)) {
+                    args.errorCallback(native_.getErrorObject(result));
+                }
+            } else {
+                var providers_result = native_.getResultObject(result);
+                var providers_table = [];
+                for (var i = 0; i < providers_result.length; i++) {
+                    providers_table[i] = new AccountProvider(providers_result[i]);
+                }
+                args.successCallback(providers_table);
+            }
+        }
+    );
+}
+
+
+var ACCOUNT_LISTENER = 'ACCOUNT_CHANGED';
+
+
+function AccountListeners() {
+    var that = this;
+    this.appCallback = function (event) {
+        if (!T_.isEmptyObject(that.instances)) {
+            var param;
+            switch (event.action) {
+                case 'onadded':
+                    param = AccountFromResult(native_.getResultObject(event));
+                    break;
+
+                case 'onremoved':
+                    param = native_.getResultObject(event);
+                    break;
+
+                case 'onupdated':
+                    param = AccountFromResult(native_.getResultObject(event));
+                    break;
+
+                default:
+                    console.log('Unknown event: ' + event.action);
+                    break;
+            }
+
+            var callback;
+            for (var key in that.instances) {
+                if (that.instances.hasOwnProperty(key)) {
+                    callback = that.instances[key];
+                    if (T_.isFunction(callback[event.action])) {
+                        callback[event.action](param);
+                    }
+                }
+            }
+        }
+    };
+}
+
+
+AccountListeners.prototype.instances = {};
+AccountListeners.prototype.nextID = 0;
+
+
+AccountListeners.prototype.addListener = function(callback) {
+    var id = ++this.nextID;
+
+    if (T_.isEmptyObject(this.instances)) {
+        var result = native_.callSync('AccountManager_addAccountListener');
+        if (native_.isFailure(result)) {
+            throw native_.getErrorObject(result);
+        }
+
+        native_.addListener(ACCOUNT_LISTENER, this.appCallback);
+    }
+    this.instances[id] = callback;
+
+    return id;
+};
+
+
+AccountListeners.prototype.removeListener = function(accountListenerId) {
+    delete this.instances[accountListenerId];
+    if (T_.isEmptyObject(this.instances)) {
+        native_.removeListener(ACCOUNT_LISTENER, this.appCallback);
+
+        var result = native_.callSync('AccountManager_removeAccountListener');
+
+        if (native_.isFailure(result)) {
+            throw native_.getErrorObject(result);
+        }
+    }
+};
+
+
+var _accountListeners = new AccountListeners();
+
+
+AccountManager.prototype.addAccountListener = function() {
+    xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.ACCOUNT_READ);
+
+    var args = validator_.validateArgs(arguments, [
+        { name: 'callback', type: types_.LISTENER, values: ['onadded', 'onremoved', 'onupdated'] }
+    ]);
+
+    return _accountListeners.addListener(args.callback);
+}
+
+
+AccountManager.prototype.removeAccountListener = function() {
+    xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.ACCOUNT_READ);
+
+    var args = validator_.validateArgs(arguments, [
+        { name: 'accountListenerId', type: types_.UNSIGNED_LONG }
+    ]);
+
+    _accountListeners.removeListener(args.accountListenerId);
+}
+
+tizen.Account = Account;
+
+exports = new AccountManager();
diff --git a/webWidgetTCT_device/src/account/account_extension.cc b/webWidgetTCT_device/src/account/account_extension.cc
new file mode 100755 (executable)
index 0000000..358032c
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2015 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 "account/account_extension.h"
+
+#include "account/account_instance.h"
+
+// This will be generated from account_api.js
+extern const char kSource_account_api[];
+
+common::Extension* CreateExtension() {
+  return new AccountExtension;
+}
+
+AccountExtension::AccountExtension() {
+  SetExtensionName("tizen.account");
+  SetJavaScriptAPI(kSource_account_api);
+
+  const char* entry_points[] = {
+      "tizen.Account",
+      NULL
+    };
+  SetExtraJSEntryPoints(entry_points);
+}
+
+AccountExtension::~AccountExtension() {}
+
+common::Instance* AccountExtension::CreateInstance() {
+  return new extension::account::AccountInstance;
+}
\ No newline at end of file
diff --git a/webWidgetTCT_device/src/account/account_extension.h b/webWidgetTCT_device/src/account/account_extension.h
new file mode 100755 (executable)
index 0000000..eb87c0b
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2015 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 ACCOUNT_ACCOUNT_EXTENSION_H_
+#define ACCOUNT_ACCOUNT_EXTENSION_H_
+
+#include "common/extension.h"
+
+class AccountExtension : public common::Extension {
+ public:
+  AccountExtension();
+  virtual ~AccountExtension();
+
+ private:
+  virtual common::Instance* CreateInstance();
+};
+
+#endif // ACCOUNT_ACCOUNT_EXTENSION_H_
diff --git a/webWidgetTCT_device/src/account/account_instance.cc b/webWidgetTCT_device/src/account/account_instance.cc
new file mode 100755 (executable)
index 0000000..8e27e78
--- /dev/null
@@ -0,0 +1,328 @@
+/*
+ * Copyright (c) 2015 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 "account/account_instance.h"
+
+#include "string.h"
+
+#include <functional>
+
+#include "common/picojson.h"
+#include "common/logger.h"
+#include "common/task-queue.h"
+#include "common/platform_exception.h"
+
+namespace extension {
+namespace account {
+
+using common::TaskQueue;
+using common::TypeMismatchException;
+using common::UnknownException;
+using common::SecurityException;
+
+#define CHECK_EXIST(args, name, out) \
+    if (!args.contains(name)) {\
+      ReportError(TypeMismatchException(name" is required argument"), out);\
+      return;\
+    }
+
+AccountInstance::AccountInstance() {
+  LoggerD("Enter");
+
+  manager_ = new AccountManager;
+  subscribe_ = NULL;
+
+  using std::placeholders::_1;
+  using std::placeholders::_2;
+
+  #define REGISTER_ASYNC(c,x) \
+    RegisterSyncHandler(c, std::bind(&AccountInstance::x, this, _1, _2));
+  REGISTER_ASYNC("AccountManager_getAccounts", AccountManagerGetAccounts);
+  REGISTER_ASYNC("AccountManager_getProviders", AccountManagerGetProviders);
+  REGISTER_ASYNC("Account_getExtendedData", AccountGetExtendedData);
+  #undef REGISTER_ASYNC
+  #define REGISTER_SYNC(c,x) \
+    RegisterSyncHandler(c, std::bind(&AccountInstance::x, this, _1, _2));
+  REGISTER_SYNC("AccountManager_removeAccountListener", AccountManagerRemoveAccountListener);
+  REGISTER_SYNC("AccountManager_update", AccountManagerUpdate);
+  REGISTER_SYNC("AccountManager_remove", AccountManagerRemove);
+  REGISTER_SYNC("AccountManager_getAccount", AccountManagerGetAccount);
+  REGISTER_SYNC("AccountManager_getProvider", AccountManagerGetProvider);
+  REGISTER_SYNC("AccountManager_addAccountListener", AccountManagerAddAccountListener);
+  REGISTER_SYNC("AccountManager_add", AccountManagerAdd);
+  REGISTER_SYNC("Account_setExtendedData", AccountSetExtendedData);
+  REGISTER_SYNC("Account_getExtendedDataSync", AccountGetExtendedDataSync);
+  #undef REGISTER_SYNC
+}
+
+AccountInstance::~AccountInstance() {
+  LoggerD("Enter");
+  delete manager_;
+  if (subscribe_) {
+    account_unsubscribe_notification(subscribe_);
+  }
+}
+
+AccountManager* AccountInstance::GetAccountManager() {
+  LoggerD("Enter");
+  return manager_;
+}
+
+void AccountInstance::AccountSetExtendedData(const picojson::value& args,
+                                             picojson::object& out) {
+  LoggerD("Enter");
+
+  CHECK_EXIST(args, "key", out)
+  CHECK_EXIST(args, "value", out)
+  CHECK_EXIST(args, "accountId", out)
+
+  const std::string& key = args.get("key").get<std::string>();
+  const std::string& value = args.get("value").get<std::string>();
+  int account_id = static_cast<int>(args.get("accountId").get<double>());
+
+  this->manager_->SetExtendedData(account_id, key, value, out);
+}
+
+void AccountInstance::AccountGetExtendedData(const picojson::value& args,
+                                             picojson::object& out) {
+  LoggerD("Enter");
+
+  CHECK_EXIST(args, "accountId", out)
+  CHECK_EXIST(args, "callbackId", out)
+
+  int account_id = static_cast<int>(args.get("accountId").get<double>());
+  int callback_id = static_cast<int>(args.get("callbackId").get<double>());
+
+  auto get_extended_data = [this, account_id](const std::shared_ptr<picojson::value>& result) {
+    this->manager_->GetExtendedData(account_id, result->get<picojson::object>());
+  };
+
+  auto get_extended_data_result = [this, callback_id](const std::shared_ptr<picojson::value>& result) {
+    result->get<picojson::object>()["callbackId"] = picojson::value{static_cast<double>(callback_id)};
+    Instance::PostMessage(this, result->serialize().c_str());
+  };
+
+  auto data = std::shared_ptr<picojson::value>{new picojson::value{picojson::object()}};
+
+  TaskQueue::GetInstance().Queue<picojson::value>(
+      get_extended_data,
+      get_extended_data_result,
+      data);
+
+  ReportSuccess(out);
+}
+
+void AccountInstance::AccountGetExtendedDataSync(const picojson::value& args,
+                                                 picojson::object& out) {
+  LoggerD("Enter");
+
+  CHECK_EXIST(args, "key", out)
+  CHECK_EXIST(args, "accountId", out)
+
+  const std::string& key = args.get("key").get<std::string>();
+  int account_id = static_cast<int>(args.get("accountId").get<double>());
+
+  this->manager_->GetExtendedData(account_id, key, out);
+}
+
+void AccountInstance::AccountManagerAdd(const picojson::value& args, picojson::object& out) {
+  LoggerD("Enter");
+  manager_->AddAccount(args, out);
+}
+
+void AccountInstance::AccountManagerRemove(const picojson::value& args,
+                                           picojson::object& out) {
+  LoggerD("Enter");
+  manager_->RemoveAccount(args, out);
+}
+
+void AccountInstance::AccountManagerUpdate(const picojson::value& args,
+                                           picojson::object& out) {
+  LoggerD("Enter");
+  manager_->UpdateAccount(args, out);
+}
+
+void AccountInstance::AccountManagerGetAccount(const picojson::value& args,
+                                               picojson::object& out) {
+  LoggerD("Enter");
+
+  CHECK_EXIST(args, "accountId", out)
+
+  int account_id = static_cast<int>(args.get("accountId").get<double>());
+  LoggerD("account_id [%d]", account_id);
+  manager_->GetAccountInfo(account_id, out);
+}
+
+void AccountInstance::AccountManagerGetAccounts(const picojson::value& args,
+                                                picojson::object& out) {
+  LoggerD("Enter");
+
+  CHECK_EXIST(args, "callbackId", out)
+  int callback_id = static_cast<int>(args.get("callbackId").get<double>());
+
+  const std::string application_id = args.contains("applicationId") ? args.get("applicationId").get<std::string>() : "";
+  LoggerD("application ID: [%s]", application_id.c_str());
+
+  auto get_accounts = [this, application_id](const std::shared_ptr<picojson::value>& result) {
+    this->manager_->GetAccountsInfo(application_id, result->get<picojson::object>());
+  };
+
+  auto get_accounts_result = [this, callback_id](const std::shared_ptr<picojson::value>& result) {
+    result->get<picojson::object>()["callbackId"] = picojson::value{static_cast<double>(callback_id)};
+    Instance::PostMessage(this, result->serialize().c_str());
+  };
+
+  auto data = std::shared_ptr<picojson::value>{new picojson::value{picojson::object()}};
+
+  TaskQueue::GetInstance().Queue<picojson::value>(
+      get_accounts,
+      get_accounts_result,
+      data);
+
+  ReportSuccess(out);
+}
+
+void AccountInstance::AccountManagerGetProvider(const picojson::value& args,
+                                                picojson::object& out) {
+  LoggerD("Enter");
+
+  std::string application_id = args.get("applicationId").get<std::string>();
+  LoggerD("application_id [%s]", application_id.c_str());
+
+  manager_->GetProviderInfo(application_id, out);
+}
+
+void AccountInstance::AccountManagerGetProviders(const picojson::value& args,
+                                                 picojson::object& out) {
+  LoggerD("Enter");
+
+  CHECK_EXIST(args, "callbackId", out)
+  int callback_id = static_cast<int>(args.get("callbackId").get<double>());
+
+  const auto& cap = args.get("capability");
+  const std::string& capability = cap.is<picojson::null>() ? "" : cap.get<std::string>();
+
+  LoggerD("capability [%s]", capability.c_str());
+
+  auto get_providers = [this, capability](const std::shared_ptr<picojson::value>& result) {
+    this->manager_->GetProvidersInfo(capability, result->get<picojson::object>());
+  };
+
+  auto get_providers_result = [this, callback_id](const std::shared_ptr<picojson::value>& result) {
+    result->get<picojson::object>()["callbackId"] = picojson::value{static_cast<double>(callback_id)};
+    Instance::PostMessage(this, result->serialize().c_str());
+  };
+
+  auto data = std::shared_ptr<picojson::value>{new picojson::value{picojson::object()}};
+
+  TaskQueue::GetInstance().Queue<picojson::value>(
+      get_providers,
+      get_providers_result,
+      data);
+
+  ReportSuccess(out);
+}
+
+void AccountInstance::InvokeListener(picojson::object& param) {
+  LoggerD("Enter");
+  picojson::value result = picojson::value(param);
+  Instance::PostMessage(this, result.serialize().c_str());
+}
+
+static bool AccountEventCb(const char *event_type, int account_id,
+                           void *user_data) {
+  LoggerD("Enter");
+
+  AccountInstance* instance = static_cast<AccountInstance*>(user_data);
+  if (!instance) {
+    LoggerE("instance is NULL");
+    return false;
+  }
+
+  picojson::object result;
+  result["listenerId"] = picojson::value("ACCOUNT_CHANGED");
+  if (!strcmp(event_type, ACCOUNT_NOTI_NAME_INSERT)) {
+    LoggerD("Added");
+    result["action"] = picojson::value("onadded");
+    picojson::object info;
+    instance->GetAccountManager()->GetAccountInfo(account_id, info);
+    result["result"] = picojson::value(info["result"]);
+    instance->InvokeListener(result);
+  } else if (!strcmp(event_type, ACCOUNT_NOTI_NAME_UPDATE)) {
+    LoggerD("Updated");
+    result["action"] = picojson::value("onupdated");
+    picojson::object info;
+    instance->GetAccountManager()->GetAccountInfo(account_id, info);
+    result["result"] = picojson::value(info["result"]);
+    instance->InvokeListener(result);
+  } else if (!strcmp(event_type, ACCOUNT_NOTI_NAME_DELETE)) {
+    LoggerD("Deleted");
+    result["action"] = picojson::value("onremoved");
+    result["result"] = picojson::value(static_cast<double>(account_id));
+    instance->InvokeListener(result);
+  }
+
+  return true;
+}
+
+void AccountInstance::AccountManagerAddAccountListener(
+    const picojson::value& args, picojson::object& out) {
+  LoggerD("Enter");
+
+  if (!subscribe_) {
+    LoggerD("Creating subscription");
+    int ret = account_subscribe_create(&subscribe_);
+    if (ret != ACCOUNT_ERROR_NONE) {
+      LoggerE("Failed to create account subscribe");
+      ReportError(UnknownException(manager_->GetErrorMsg(ret)), out);
+      return;
+    }
+
+    LoggerD("Subscribing for notification");
+    ret = account_subscribe_notification(subscribe_, AccountEventCb, this);
+    if (ret != ACCOUNT_ERROR_NONE) {
+      LoggerE("Failed to subscribe notification");
+      ReportError(UnknownException(manager_->GetErrorMsg(ret)), out);
+      return;
+    }
+
+    LoggerD("Success");
+  }
+
+  ReportSuccess(out);
+}
+
+void AccountInstance::AccountManagerRemoveAccountListener(
+    const picojson::value& args, picojson::object& out) {
+  LoggerD("Enter");
+
+  if (subscribe_) {
+    LoggerD("Removing subscription");
+
+    if (account_unsubscribe_notification(subscribe_) != ACCOUNT_ERROR_NONE) {
+      LoggerE("Failed to unsubscribe notification");
+    }
+
+    subscribe_ = nullptr;
+  }
+
+  ReportSuccess(out);
+}
+
+#undef CHECK_EXIST
+
+} // namespace account
+} // namespace extension
diff --git a/webWidgetTCT_device/src/account/account_instance.h b/webWidgetTCT_device/src/account/account_instance.h
new file mode 100755 (executable)
index 0000000..9651cfb
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2015 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 ACCOUNT_ACCOUNT_INSTANCE_H_
+#define ACCOUNT_ACCOUNT_INSTANCE_H_
+
+#include <account.h>
+
+#include "account/account_manager.h"
+#include "common/extension.h"
+
+namespace extension {
+namespace account {
+
+class AccountInstance : public common::ParsedInstance {
+ public:
+  AccountInstance();
+  virtual ~AccountInstance();
+
+  AccountManager* GetAccountManager();
+  void InvokeListener(picojson::object& param);
+
+ private:
+  AccountInstance(const AccountInstance&) = delete;
+  AccountInstance(const AccountInstance&&) = delete;
+  AccountInstance& operator=(const AccountInstance&) = delete;
+  AccountInstance& operator=(const AccountInstance&&) = delete;
+
+  AccountManager* manager_;
+  account_subscribe_h subscribe_;
+
+  void AccountManagerRemoveAccountListener(
+      const picojson::value& args, picojson::object& out);
+  void AccountManagerUpdate(
+      const picojson::value& args, picojson::object& out);
+  void AccountManagerRemove(
+      const picojson::value& args, picojson::object& out);
+  void AccountConstructor(
+      const picojson::value& args, picojson::object& out);
+  void AccountManagerGetAccount(
+      const picojson::value& args, picojson::object& out);
+  void AccountManagerGetProvider(
+      const picojson::value& args, picojson::object& out);
+  void AccountSetExtendedData(
+      const picojson::value& args, picojson::object& out);
+  void AccountManagerAddAccountListener(
+      const picojson::value& args, picojson::object& out);
+  void AccountManagerAdd(
+      const picojson::value& args, picojson::object& out);
+  void AccountManagerGetAccounts(
+      const picojson::value& args, picojson::object& out);
+  void AccountGetExtendedData(
+      const picojson::value& args, picojson::object& out);
+  void AccountGetExtendedDataSync(
+      const picojson::value& args, picojson::object& out);
+  void AccountManagerGetProviders(
+      const picojson::value& args, picojson::object& out);
+};
+
+} // namespace account
+} // namespace extension
+
+#endif // ACCOUNT_ACCOUNT_INSTANCE_H_
diff --git a/webWidgetTCT_device/src/account/account_manager.cc b/webWidgetTCT_device/src/account/account_manager.cc
new file mode 100755 (executable)
index 0000000..409ac75
--- /dev/null
@@ -0,0 +1,614 @@
+/*
+ * Copyright (c) 2015 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 "account/account_manager.h"
+
+#include <functional>
+
+#include "common/logger.h"
+#include "common/scope_exit.h"
+
+namespace extension {
+namespace account {
+
+using common::ScopeExit;
+using common::UnknownException;
+using common::NotFoundException;
+
+#define REPORT_ERROR(out, exception) \
+  out["status"] = picojson::value("error"); \
+  out["error"] = exception.ToJSON();
+
+namespace {
+
+static bool ProviderCapabilitiesCb(char *app_id, char *key, void *user_data) {
+  LoggerD("Enter");
+
+  picojson::array* array_data = static_cast<picojson::array*>(user_data);
+  if (!array_data) {
+    LoggerE("user_data is NULL");
+    return false;
+  }
+
+  array_data->push_back(picojson::value(key));
+  return true;
+}
+
+static bool AccountProvidersGetCb(account_type_h provider, void *user_data) {
+  LoggerD("Enter");
+
+  picojson::array* array_data = static_cast<picojson::array*>(user_data);
+  if (!array_data) {
+    LoggerE("user_data is NULL");
+    return false;
+  }
+
+  picojson::object object_info;
+  if (AccountManager::ConvertProviderToObject(provider, object_info)) {
+    array_data->push_back(picojson::value(object_info));
+  }
+
+  return true;
+}
+
+static bool GetAccountsCallback(account_h handle, void *user_data) {
+  LoggerD("Enter");
+
+  picojson::array* array_data = static_cast<picojson::array*>(user_data);
+  if (!array_data) {
+    LoggerE("user_data is NULL");
+    return false;
+  }
+
+  picojson::object object_info;
+  if (AccountManager::ConvertAccountToObject(handle, object_info)) {
+    if (!object_info["provider"].is<picojson::null>()) {
+      array_data->push_back(picojson::value(object_info));
+    }
+  }
+
+  return true;
+}
+
+static bool GetCustomAllCallback(char* key, char* value, void* user_data) {
+  LoggerD("Enter");
+
+  picojson::array* array_data = static_cast<picojson::array*>(user_data);
+  if (!array_data) {
+    LoggerE("user_data is NULL");
+    return false;
+  }
+
+  picojson::value result{picojson::object()};
+  picojson::object& r = result.get<picojson::object>();
+
+  r.insert(std::make_pair(("key"), picojson::value(key)));
+  r.insert(std::make_pair(("value"), picojson::value(value)));
+
+  array_data->push_back(result);
+
+  return true;
+};
+
+} // namespace
+
+AccountManager::AccountManager() {
+  LoggerD("Enter");
+}
+
+AccountManager::~AccountManager() {
+  LoggerD("Enter");
+}
+
+std::string AccountManager::GetErrorMsg(int error) {
+  switch (error) {
+    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";
+  }
+}
+
+void AccountManager::GetAccountsInfo(const std::string& application_id,
+                                     picojson::object& out) {
+  LoggerD("Enter");
+
+  picojson::array array_data;
+  int ret = ACCOUNT_ERROR_NONE;
+
+  if ("" == application_id) {
+    ret = account_foreach_account_from_db(GetAccountsCallback, &array_data);
+  } else {
+    ret = account_query_account_by_package_name(GetAccountsCallback,
+                                                application_id.c_str(),
+                                                &array_data);
+  }
+
+  if (ret == ACCOUNT_ERROR_NONE || ret == ACCOUNT_ERROR_RECORD_NOT_FOUND) {
+    out["status"] = picojson::value("success");
+    out["result"] = picojson::value(array_data);
+  } else {
+    LoggerE("Failed to get accounts information");
+    REPORT_ERROR(out, UnknownException(GetErrorMsg(ret)));
+  }
+}
+
+void AccountManager::GetAccountInfo(int account_id, picojson::object& out) {
+  LoggerD("Enter");
+
+  account_h account = NULL;
+  SCOPE_EXIT {
+    account_destroy(account);
+  };
+
+  int ret = account_create(&account);
+  if (ret != ACCOUNT_ERROR_NONE) {
+    LoggerE("Failed to create account info");
+    REPORT_ERROR(out, UnknownException(GetErrorMsg(ret)));
+    return;
+  }
+
+  ret = account_query_account_by_account_id(account_id, &account);
+  if (ACCOUNT_ERROR_RECORD_NOT_FOUND == ret || ACCOUNT_ERROR_INVALID_PARAMETER == ret) {
+    out["status"] = picojson::value("success");
+    out["result"] = picojson::value();
+    return;
+  } else if (ret != ACCOUNT_ERROR_NONE) {
+    LoggerE("Failed to get account info");
+    REPORT_ERROR(out, UnknownException(GetErrorMsg(ret)));
+    return;
+  }
+
+  picojson::object info;
+  if (!ConvertAccountToObject(account, info)) {
+    LoggerE("Failed to convert account_h into object");
+    REPORT_ERROR(out, UnknownException("Unknown error occurs"));
+    return;
+  }
+
+  out["status"] = picojson::value("success");
+  out["result"] = picojson::value(info);
+
+  return;
+}
+
+bool AccountManager::GetProviderInfo(const std::string& provider_id,
+                                     picojson::object& out) {
+  LoggerD("Enter");
+
+  account_type_h provider = NULL;
+  SCOPE_EXIT {
+    account_type_destroy(provider);
+  };
+
+  int ret = account_type_create(&provider);
+  if (ret != ACCOUNT_ERROR_NONE) {
+    LoggerE("Failed to create provider info");
+    REPORT_ERROR(out, UnknownException(GetErrorMsg(ret)));
+    return false;
+  }
+
+  ret = account_type_query_by_app_id(provider_id.c_str(), &provider);
+  if (ACCOUNT_ERROR_RECORD_NOT_FOUND == ret || ACCOUNT_ERROR_INVALID_PARAMETER == ret) {
+    out["status"] = picojson::value("success");
+    out["result"] = picojson::value();
+    return true;
+  } else if (ret != ACCOUNT_ERROR_NONE) {
+    LoggerE("Failed to get provider info");
+    REPORT_ERROR(out, UnknownException(GetErrorMsg(ret)));
+    return false;
+  }
+
+  picojson::object info;
+  if (!ConvertProviderToObject(provider, info)) {
+    LoggerE("Failed to convert account_type_h into object");
+    REPORT_ERROR(out, UnknownException("Unknown error occurs"));
+    return false;
+  }
+
+  out["status"] = picojson::value("success");
+  out["result"] = picojson::value(info);
+
+  return true;
+}
+
+bool AccountManager::ConvertAccountToObject(account_h account,
+                                            picojson::object& out) {
+  LoggerD("Enter");
+
+  char* provider_id = NULL;
+  char* icon_path = NULL;
+  char* user_name = NULL;
+
+  SCOPE_EXIT {
+    free(provider_id);
+    free(icon_path);
+    free(user_name);
+  };
+
+  int account_id = -1;
+  int ret = account_get_account_id(account, &account_id);
+  if (ret != ACCOUNT_ERROR_NONE) {
+    LoggerE("Failed to get account ID");
+    REPORT_ERROR(out, UnknownException(GetErrorMsg(ret)));
+    return false;
+  }
+  out["id"] = picojson::value(static_cast<double>(account_id));
+
+  ret = account_get_package_name(account, &provider_id);
+  if (ret != ACCOUNT_ERROR_NONE) {
+    LoggerE("Failed to get provider name");
+    REPORT_ERROR(out, UnknownException(GetErrorMsg(ret)));
+    return false;
+  }
+
+  picojson::object provider_info;
+  if (!GetProviderInfo(provider_id, provider_info)) {
+    LoggerE("Failed to get provider info");
+    return false;
+  }
+  out["provider"] = provider_info["result"];
+
+  picojson::object account_init;
+  ret = account_get_icon_path(account, &icon_path);
+  if (ret != ACCOUNT_ERROR_NONE) {
+    LoggerE("Failed to get icon path");
+    REPORT_ERROR(out, UnknownException(GetErrorMsg(ret)));
+    return false;
+  }
+  account_init["iconUri"] = icon_path ? picojson::value(icon_path) : picojson::value();
+
+  ret = account_get_user_name(account, &user_name);
+  if (ret != ACCOUNT_ERROR_NONE) {
+    LoggerE("Failed to get user name");
+    REPORT_ERROR(out, UnknownException(GetErrorMsg(ret)));
+    return false;
+  }
+  account_init["userName"] = user_name ? picojson::value(user_name) : picojson::value();
+  out["accountInitDict"] = picojson::value(account_init);
+
+  return true;
+}
+
+bool AccountManager::ConvertProviderToObject(account_type_h provider,
+                                             picojson::object& out) {
+  LoggerD("Enter");
+
+  char* provider_id = NULL;
+  char* display_name = NULL;
+  char* icon_uri = NULL;
+  char* small_icon_uri = NULL;
+  bool is_multiple_account_supported = false;
+  picojson::array capabilities;
+
+  int ret = account_type_get_app_id(provider, &provider_id);
+  if (ret != ACCOUNT_ERROR_NONE) {
+    LoggerE("Failed to get application id");
+    REPORT_ERROR(out, UnknownException(GetErrorMsg(ret)));
+    return false;
+  }
+  out["applicationId"] = picojson::value(provider_id);
+  free(provider_id);
+
+  // TODO: Which label should be returned?
+  ret = account_type_get_label_by_locale(provider, "default", &display_name);
+  if (ret == ACCOUNT_ERROR_NONE) {
+    out["displayName"] = picojson::value(display_name);
+    free(display_name);
+  } else if (ret == ACCOUNT_ERROR_RECORD_NOT_FOUND) {
+    LoggerD("There is no label");
+    out["displayName"] = picojson::value("");
+  } else {
+    LoggerE("Failed to get label");
+    REPORT_ERROR(out, UnknownException(GetErrorMsg(ret)));
+    return false;
+  }
+
+  ret = account_type_get_icon_path(provider, &icon_uri);
+  if (ret != ACCOUNT_ERROR_NONE) {
+    LoggerE("Failed to get icon");
+    REPORT_ERROR(out, UnknownException(GetErrorMsg(ret)));
+    return false;
+  }
+  out["iconUri"] = picojson::value(icon_uri);
+  free(icon_uri);
+
+  ret = account_type_get_small_icon_path(provider, &small_icon_uri);
+  if (ret != ACCOUNT_ERROR_NONE) {
+    LoggerE("Failed to get small icon");
+    REPORT_ERROR(out, UnknownException(GetErrorMsg(ret)));
+    return false;
+  }
+  out["smallIconUri"] = picojson::value(small_icon_uri);
+  free(small_icon_uri);
+
+  ret = account_type_get_provider_feature_all(provider, ProviderCapabilitiesCb,
+                                              &capabilities);
+  if (ret != ACCOUNT_ERROR_NONE) {
+    LoggerE("Failed to get capabilities");
+    REPORT_ERROR(out, UnknownException(GetErrorMsg(ret)));
+    return false;
+  }
+  out["capabilities"] = picojson::value(capabilities);
+
+  int supported = 0;
+  ret = account_type_get_multiple_account_support(provider, &supported);
+  if (ret != ACCOUNT_ERROR_NONE) {
+    LoggerE("Failed to get small icon");
+    REPORT_ERROR(out, UnknownException(GetErrorMsg(ret)));
+    return false;
+  }
+  is_multiple_account_supported = (supported != 0);
+  out["isMultipleAccountSupported"] = picojson::value(
+      is_multiple_account_supported);
+
+  return true;
+}
+
+void AccountManager::GetProvidersInfo(const std::string& capability,
+                                      picojson::object& out) {
+  LoggerD("Enter");
+
+  picojson::array array_data;
+  int ret = ACCOUNT_ERROR_NONE;
+
+  if ("" == capability) {
+    ret = account_type_foreach_account_type_from_db(AccountProvidersGetCb,
+                                                    &array_data);
+  } else {
+    ret = account_type_query_by_provider_feature(AccountProvidersGetCb,
+                                                 capability.c_str(),
+                                                 &array_data);
+  }
+
+  if (ret == ACCOUNT_ERROR_NONE || ret == ACCOUNT_ERROR_RECORD_NOT_FOUND) {
+    out["status"] = picojson::value("success");
+    out["result"] = picojson::value(array_data);
+  } else {
+    LoggerE("Failed to get providers information");
+    REPORT_ERROR(out, UnknownException(GetErrorMsg(ret)));
+  }
+}
+
+void AccountManager::GetExtendedData(int account_id, const std::string& key, picojson::object& out) {
+  LoggerD("Enter");
+
+  account_h account = nullptr;
+  SCOPE_EXIT {
+    account_destroy(account);
+  };
+
+  int ret = account_create(&account);
+  if (ret != ACCOUNT_ERROR_NONE) {
+    LoggerE("Failed to create account info");
+    REPORT_ERROR(out, UnknownException(GetErrorMsg(ret)));
+    return;
+  }
+
+  ret = account_query_account_by_account_id(account_id, &account);
+  if (ret != ACCOUNT_ERROR_NONE) {
+    LoggerE("Failed to get account info");
+    REPORT_ERROR(out, UnknownException(GetErrorMsg(ret)));
+    return;
+  }
+
+  char* value = nullptr;
+  ret = account_get_custom(account, key.c_str(), &value);
+  if (ACCOUNT_ERROR_NONE != ret) {
+    if (ACCOUNT_ERROR_RECORD_NOT_FOUND == ret) {
+      LoggerE("There is no extended data value for %s", key.c_str());
+      out["status"] = picojson::value("success");
+      out["result"] = picojson::value();
+    } else {
+      LoggerE("Failed to get custom field");
+      REPORT_ERROR(out, UnknownException(GetErrorMsg(ret)));
+    }
+  } else {
+    out["status"] = picojson::value("success");
+    out["result"] = picojson::value(value);
+  }
+  free(value);
+}
+
+void AccountManager::GetExtendedData(int account_id, picojson::object& out) {
+  LoggerD("Enter");
+
+  account_h account = nullptr;
+  SCOPE_EXIT {
+    account_destroy(account);
+  };
+
+  int ret = account_create(&account);
+  if (ret != ACCOUNT_ERROR_NONE) {
+    LoggerE("Failed to create account info");
+    REPORT_ERROR(out, UnknownException(GetErrorMsg(ret)));
+    return;
+  }
+
+  ret = account_query_account_by_account_id(account_id, &account);
+  if (ret != ACCOUNT_ERROR_NONE) {
+    LoggerE("Failed to get account info");
+    REPORT_ERROR(out, UnknownException(GetErrorMsg(ret)));
+    return;
+  }
+
+  picojson::array array_data;
+  ret = account_get_custom_all(account, GetCustomAllCallback, &array_data);
+  if (ACCOUNT_ERROR_NONE != ret) {
+    LoggerE("Failed to get custom fields");
+    REPORT_ERROR(out, UnknownException(GetErrorMsg(ret)));
+  } else {
+    out["status"] = picojson::value("success");
+    out["result"] = picojson::value(array_data);
+  }
+}
+
+void AccountManager::SetExtendedData(int account_id, const std::string& key, const std::string& value, picojson::object& out) {
+  LoggerD("Enter");
+
+  account_h account = nullptr;
+  SCOPE_EXIT {
+    account_destroy(account);
+  };
+
+  int ret = account_create(&account);
+  if (ret != ACCOUNT_ERROR_NONE) {
+    LoggerE("Failed to create account info");
+    REPORT_ERROR(out, UnknownException(GetErrorMsg(ret)));
+    return;
+  }
+
+  ret = account_query_account_by_account_id(account_id, &account);
+  if (ret != ACCOUNT_ERROR_NONE) {
+    LoggerE("Failed to get account info");
+    REPORT_ERROR(out, UnknownException(GetErrorMsg(ret)));
+    return;
+  }
+
+  ret = account_set_custom(account, key.c_str(), value.c_str());
+  if (ACCOUNT_ERROR_NONE != ret) {
+    LoggerE("Failed to set custom field");
+    REPORT_ERROR(out, UnknownException(GetErrorMsg(ret)));
+    return;
+  }
+
+  ret = account_update_to_db_by_id(account, account_id);
+  if (ACCOUNT_ERROR_NONE != ret) {
+    LoggerE("Failed to update account in database");
+    REPORT_ERROR(out, UnknownException(GetErrorMsg(ret)));
+  } else {
+    out["status"] = picojson::value("success");
+  }
+}
+
+void AccountManager::AddAccount(const picojson::value& data, picojson::object& out) {
+  LoggerD("Enter");
+  account_h account_handle = NULL;
+  int account_id;
+
+  const picojson::object& obj = data.get<picojson::object>();
+
+  int ret = account_create(&account_handle);
+  if (!ret) {
+    const auto it = obj.find("userName");
+    if (obj.end() != it && !(it->second.is<picojson::null>())) {
+      ret = account_set_user_name(account_handle, it->second.get<std::string>().c_str());
+    }
+    if (!ret) {
+      const auto it = obj.find("iconUri");
+      if (obj.end() != it && !(it->second.is<picojson::null>())) {
+        ret = account_set_icon_path(account_handle, it->second.get<std::string>().c_str());
+      }
+    }
+    if (!ret) {
+      const std::string& application_id = data.get("applicationId").get<std::string>();
+      ret = account_set_package_name(account_handle, application_id.c_str());
+    }
+    if (!ret) {
+      ret = account_insert_to_db(account_handle, &account_id);
+    }
+    account_destroy(account_handle);
+  }
+  if (!ret) {
+    out["status"] = picojson::value("success");
+    out["result"] = picojson::value(static_cast<double>(account_id));
+  } else {
+    LoggerE("Failed to create account");
+    REPORT_ERROR(out, UnknownException(GetErrorMsg(ret)));
+  }
+}
+
+void AccountManager::RemoveAccount(const picojson::value& data, picojson::object& out) {
+  LoggerD("Enter");
+  int account_id = static_cast<int>(data.get("accountId").get<double>());
+
+  int ret = account_delete_from_db_by_id(account_id);
+
+  if (!ret || ret == ACCOUNT_ERROR_INVALID_PARAMETER) {
+    out["status"] = picojson::value("success");
+  } else {
+    LoggerE("Failed to create account");
+    REPORT_ERROR(out, UnknownException(GetErrorMsg(ret)));
+  }
+}
+
+void AccountManager::UpdateAccount(const picojson::value& data, picojson::object& out) {
+  LoggerD("Enter");
+  int account_id = static_cast<int>(data.get("accountId").get<double>());
+  const std::string& user_name = data.get("userName").get<std::string>();
+  const std::string& icon_uri = data.get("iconUri").get<std::string>();
+  account_h account_handle = NULL;
+
+  int ret = account_create(&account_handle);
+
+  if (!ret) {
+    ret = account_query_account_by_account_id(account_id, &account_handle);
+    if (!ret) {
+      ret = account_set_user_name(account_handle, user_name.c_str());
+    }
+    if (!ret) {
+      ret = account_set_icon_path(account_handle, icon_uri.c_str());
+    }
+    if (!ret) {
+      ret = account_update_to_db_by_id(account_handle, account_id);
+    }
+
+    account_destroy(account_handle);
+  }
+  if (!ret) {
+    out["status"] = picojson::value("success");
+  } else {
+    LoggerE("Failed to create account");
+    REPORT_ERROR(out, UnknownException(GetErrorMsg(ret)));
+  }
+}
+
+#undef REPORT_ERROR
+
+} // namespace account
+} // namespace extension
diff --git a/webWidgetTCT_device/src/account/account_manager.h b/webWidgetTCT_device/src/account/account_manager.h
new file mode 100755 (executable)
index 0000000..0e5d107
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2015 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 ACCOUNT_ACCOUNT_MANAGER_H_
+#define ACCOUNT_ACCOUNT_MANAGER_H_
+
+#include <account.h>
+
+#include "common/extension.h"
+#include "common/picojson.h"
+#include "common/platform_exception.h"
+
+namespace extension {
+namespace account {
+
+class AccountManager {
+ public:
+  AccountManager();
+  virtual ~AccountManager();
+
+  /* out["status"] = "success" or "error"
+  * If status is "success", then the result(picojson::value) will be stored in out["result"].
+  * If status is "error", then the error(picojson::value) will be stored in out["error"].
+  */
+  void GetAccountsInfo(const std::string& application_id, picojson::object& out);
+
+ /* out["status"] = "success" or "error"
+ * If status is "success", then the result(picojson::value) will be stored in out["result"].
+ * If status is "error", then the error(picojson::value) will be stored in out["error"].
+ */
+  void GetAccountInfo(int account_id, picojson::object& out);
+
+ /* out["status"] = "success" or "error"
+ * If status is "success", then the result(picojson::value) will be stored in out["result"].
+ * If status is "error", then the error(picojson::value) will be stored in out["error"].
+ */
+  void GetProvidersInfo(const std::string& capability, picojson::object& out);
+
+ /* out["status"] = "success" or "error"
+ * If status is "success", then the result(picojson::value) will be stored in out["result"].
+ * If status is "error", then the error(picojson::value) will be stored in out["error"].
+ */
+  static bool GetProviderInfo(const std::string& provider_id, picojson::object& out);
+
+  /* out["status"] = "success" or "error"
+   * If status is "success", then the result(picojson::value) will be stored in out["result"].
+   * If status is "error", then the error(picojson::value) will be stored in out["error"].
+   */
+  void GetExtendedData(int account_id, const std::string& key, picojson::object& out);
+
+  /* out["status"] = "success" or "error"
+   * If status is "success", then the result(picojson::value) will be stored in out["result"].
+   * If status is "error", then the error(picojson::value) will be stored in out["error"].
+   */
+  void GetExtendedData(int account_id, picojson::object& out);
+
+  /* out["status"] = "success" or "error"
+   * If status is "success", then the result(picojson::value) will be stored in out["result"].
+   * If status is "error", then the error(picojson::value) will be stored in out["error"].
+   */
+  void SetExtendedData(int account_id, const std::string& key, const std::string& value, picojson::object& out);
+
+  static bool ConvertAccountToObject(account_h account, picojson::object& out);
+
+  static bool ConvertProviderToObject(account_type_h provider, picojson::object& out);
+
+  static std::string GetErrorMsg(int error);
+
+  void AddAccount(const picojson::value& data, picojson::object& obj);
+  void RemoveAccount(const picojson::value& data, picojson::object& obj);
+  void UpdateAccount(const picojson::value& data, picojson::object& obj);
+  //bool IsValidPackage(const std::string& packageName);
+};
+
+} // namespace account
+} // namespace extension
+
+#endif // ACCOUNT_ACCOUNT_MANAGER_H_
diff --git a/webWidgetTCT_device/src/alarm/alarm.gyp b/webWidgetTCT_device/src/alarm/alarm.gyp
new file mode 100755 (executable)
index 0000000..dc1135a
--- /dev/null
@@ -0,0 +1,34 @@
+{
+  'includes':[
+    '../common/common.gypi',
+  ],
+  'targets': [
+    {
+      'target_name': 'tizen_alarm',
+      'type': 'loadable_module',
+      'dependencies': [
+        '../common/common.gyp:tizen_common',
+      ],
+      'sources': [
+        'alarm_api.js',
+        'alarm_extension.cc',
+        'alarm_extension.h',
+        'alarm_instance.cc',
+        'alarm_instance.h',
+        'alarm_manager.cc',
+        'alarm_manager.h',
+        'alarm_utils.cc',
+        'alarm_utils.h',
+      ],
+      'conditions': [
+        ['tizen == 1', {
+          'variables': {
+            'packages': [
+              'capi-appfw-alarm',
+            ]
+          },
+        }],
+      ],
+    },
+  ],
+}
\ No newline at end of file
diff --git a/webWidgetTCT_device/src/alarm/alarm_api.js b/webWidgetTCT_device/src/alarm/alarm_api.js
new file mode 100755 (executable)
index 0000000..db53289
--- /dev/null
@@ -0,0 +1,307 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+var T = xwalk.utils.type;
+var Converter = xwalk.utils.converter;
+var AV = xwalk.utils.validator;
+var Privilege = xwalk.utils.privilege;
+
+var native = new xwalk.utils.NativeManager(extension);
+
+var AlarmManager = function () {
+    Object.defineProperties(this, {
+        PERIOD_MINUTE:  { value: 60, writable: false, enumerable: true},
+        PERIOD_HOUR:    { value: 3600, writable: false, enumerable: true},
+        PERIOD_DAY:     { value: 86400, writable: false, enumerable: true},
+        PERIOD_WEEK:    { value: 604800, writable: false, enumerable: true},
+    });
+};
+
+function InternalData_(data) {
+    if (!(this instanceof InternalData_)) {
+        return new InternalData_(data);
+    }
+
+    for(var key in data) {
+        if (data.hasOwnProperty(key)) {
+            this[key] = data[key];
+        }
+    }
+}
+
+function UpdateInternalData_(internal, data) {
+    var values = InternalData_(data);
+
+    for(var key in data) {
+        if (values.hasOwnProperty(key) && internal.hasOwnProperty(key)) {
+            internal[key] = values;
+        }
+    }
+}
+
+//class AlarmManager ////////////////////////////////////////////////////
+AlarmManager.prototype.add = function () {
+    xwalk.utils.checkPrivilegeAccess(Privilege.ALARM);
+
+    var args = AV.validateMethod(arguments, [
+        {
+            name : 'alarm',
+            type : AV.Types.PLATFORM_OBJECT,
+            values : [tizen.AlarmRelative, tizen.AlarmAbsolute]
+        },
+        {
+            name : 'applicationId',
+            type : AV.Types.STRING,
+        },
+        {
+            name : 'appControl',
+            type : AV.Types.PLATFORM_OBJECT,
+            values : tizen.ApplicationControl,
+            optional : true,
+            nullable : true
+        },
+    ]);
+
+    var type = null, seconds = 0;
+    if (args.alarm instanceof tizen.AlarmRelative) {
+        type = 'AlarmRelative';
+    } else if (args.alarm instanceof tizen.AlarmAbsolute) {
+        type = 'AlarmAbsolute';
+        seconds = args.alarm.date.getTime();
+    }
+
+    var callArgs = {};
+    callArgs.alarm = args.alarm;
+    callArgs.applicationId = args.applicationId;
+    if (args.has.appControl) {
+        callArgs.appControl = args.appControl;
+    }
+
+    callArgs.type = type;
+    callArgs.seconds = Converter.toString(seconds);
+
+    var result = native.callSync('AlarmManager_add', callArgs);
+    if (native.isFailure(result)) {
+        throw native.getErrorObject(result);
+    } else {
+        UpdateInternalData_(args.alarm, native.getResultObject(result));
+    }
+};
+
+AlarmManager.prototype.remove = function () {
+    xwalk.utils.checkPrivilegeAccess(Privilege.ALARM);
+
+    var args = AV.validateMethod(arguments, [
+        {
+            name : 'id',
+            type : AV.Types.STRING,
+        }
+    ]);
+
+    var result = native.callSync('AlarmManager_remove', {id: Number(args.id)});
+
+    if (native.isFailure(result)) {
+        throw native.getErrorObject(result);
+    }
+};
+
+AlarmManager.prototype.removeAll = function () {
+    xwalk.utils.checkPrivilegeAccess(Privilege.ALARM);
+
+    var result = native.callSync('AlarmManager_removeAll', {});
+
+    if (native.isFailure(result)) {
+        throw native.getErrorObject(result);
+    }
+};
+
+AlarmManager.prototype.get = function () {
+    var args = AV.validateMethod(arguments, [
+        {
+            name : 'id',
+            type : AV.Types.STRING,
+        }
+    ]);
+
+    var result = native.callSync('AlarmManager_get', {id: Number(args.id)});
+
+    if (native.isFailure(result)) {
+        throw native.getErrorObject(result);
+    } else {
+        result = native.getResultObject(result);
+        if ('AlarmRelative' === result.type) {
+            return new tizen.AlarmRelative(result.delay, result.period, InternalData_(result));
+        } else {
+            var date = new Date(result.year, result.month, result.day,
+                    result.hour, result.min, result.sec);
+
+            return new tizen.AlarmAbsolute(date, result.second, InternalData_(result));
+        }
+    }
+};
+
+AlarmManager.prototype.getAll = function () {
+    var result = native.callSync('AlarmManager_getAll', {});
+
+    if (native.isFailure(result)) {
+        throw native.getErrorObject(result);
+    } else {
+        var data = native.getResultObject(result);
+        var md = [];
+        data.forEach(function (i) {
+            if ('AlarmRelative'=== i.type) {
+                md.push(new tizen.AlarmRelative(i.delay, i.period, InternalData_(i)));
+            } else {
+                var date = new Date(i.year, i.month, i.day,
+                        i.hour, i.min, i.sec);
+                md.push(new tizen.AlarmAbsolute(date, i.second, InternalData_(i)));
+            }
+        });
+        return md;
+    }
+};
+
+//class Alarm //////////////////////////////////////////////////////////
+function Alarm(id) {
+    var m_id = null;
+
+    if (!T.isNullOrUndefined(id) && id instanceof InternalData_) {
+        m_id = id.id;
+    }
+
+    var _internal = {
+        'id' : m_id
+    };
+
+    Object.defineProperties(this, {
+        id: {
+            get: function () {return _internal.id;},
+            set: function (value) {
+                if (value instanceof InternalData_) {
+                    _internal.id = value.id;
+                }
+            },
+            enumerable: true
+        }
+    });
+}
+//class AlarmRelative //////////////////////////////////////////////////
+
+tizen.AlarmRelative = function(delay, period, internal) {
+    AV.validateConstructorCall(this, tizen.AlarmRelative);
+
+    var m_period = null;
+
+    var m_delay = Converter.toLong(delay);
+
+    if (arguments.length >= 2) {
+        m_period = Converter.toLong(period, true);
+    }
+
+    Alarm.call(this, internal);
+
+    Object.defineProperties(this, {
+        delay:     { value: m_delay, writable: false, enumerable: true},
+        period:    { value: m_period, writable: false, enumerable: true}
+    });
+}
+
+tizen.AlarmRelative.prototype = new Alarm();
+
+tizen.AlarmRelative.prototype.constructor = tizen.AlarmRelative;
+
+tizen.AlarmRelative.prototype.getRemainingSeconds = function () {
+    var result = native.callSync('AlarmRelative_getRemainingSeconds', {id: Number(this.id)});
+
+    if (native.isFailure(result)) {
+        throw native.getErrorObject(result);
+    } else {
+        return Converter.toLong(native.getResultObject(result).seconds, true);
+    }
+};
+
+function makeDateConst(obj) {
+    console.log('Enter MakeConst');
+    obj.setDate = function() {};
+    obj.setFullYear = function() {};
+    obj.setHours = function() {};
+    obj.setMilliseconds = function() {};
+    obj.setMinutes = function() {};
+    obj.setMonth = function() {};
+    obj.setSeconds = function() {};
+    obj.setTime = function() {};
+    obj.setUTCDate = function() {};
+    obj.setUTCFullYear = function() {};
+    obj.setUTCHours = function() {};
+    obj.setUTCMilliseconds = function() {};
+    obj.setUTCMinutes = function() {};
+    obj.setUTCMonth = function() {};
+    obj.setUTCSeconds = function() {};
+    obj.setYear = function() {};
+    console.log('Leave MakeConst');
+}
+
+//class AlarmAbsolute //////////////////////////////////////////////////
+
+tizen.AlarmAbsolute = function(date, second, internal) {
+    AV.validateConstructorCall(this, tizen.AlarmAbsolute);
+
+    var m_period = null, m_daysOfWeek = [], m_date;
+
+    if (T.isDate(date)) {
+        m_date = date;
+        if (arguments.length >= 2) {
+            if(T.isArray(second)){
+                m_daysOfWeek = second;
+            } else {
+                m_period = Converter.toLong(second);
+            }
+        }
+
+        Alarm.call(this, internal);
+    } else {
+        m_period = undefined;
+    }
+    makeDateConst(m_date);
+    Object.defineProperties(this, {
+        date:       { value: m_date, writable: false, enumerable: true},
+        period:     { value: m_period, writable: false, enumerable: true},
+        daysOfTheWeek: { value: m_daysOfWeek, writable: false, enumerable: true}
+    });
+}
+
+tizen.AlarmAbsolute.prototype = new Alarm();
+
+tizen.AlarmAbsolute.prototype.constructor = tizen.AlarmAbsolute;
+
+tizen.AlarmAbsolute.prototype.getNextScheduledDate = function () {
+    var result = native.callSync('AlarmAbsolute_getNextScheduledDate', {id: Number(this.id)});
+
+    if (native.isFailure(result)) {
+        throw native.getErrorObject(result);
+    } else {
+        var d = native.getResultObject(result);
+        if (T.isNull(d.year)) {
+            return null;
+        } else {
+            var date = new Date(d.year, d.month, d.day, d.hour, d.min, d.sec);
+            return date;
+        }
+    }
+};
+
+//exports //////////////////////////////////////////////////////////////
+exports = new AlarmManager();
diff --git a/webWidgetTCT_device/src/alarm/alarm_extension.cc b/webWidgetTCT_device/src/alarm/alarm_extension.cc
new file mode 100755 (executable)
index 0000000..2182084
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2015 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 "alarm_extension.h"
+#include "alarm_instance.h"
+
+namespace {
+const char* kAlarm = "tizen.alarm";
+const char* kAlarmRelative = "tizen.AlarmRelative";
+const char* kAlarmAbsolute = "tizen.AlarmAbsolute";
+}
+
+// This will be generated from alarm_api.js.
+extern const char kSource_alarm_api[];
+
+common::Extension* CreateExtension() {
+  return new AlarmExtension;
+}
+
+AlarmExtension::AlarmExtension() {
+  SetExtensionName(kAlarm);
+  SetJavaScriptAPI(kSource_alarm_api);
+  const char* entry_points[] = {
+      kAlarmRelative,
+      kAlarmAbsolute,
+      NULL
+  };
+  SetExtraJSEntryPoints(entry_points);
+}
+
+AlarmExtension::~AlarmExtension() {}
+
+common::Instance* AlarmExtension::CreateInstance() {
+  return new extension::alarm::AlarmInstance();
+}
diff --git a/webWidgetTCT_device/src/alarm/alarm_extension.h b/webWidgetTCT_device/src/alarm/alarm_extension.h
new file mode 100755 (executable)
index 0000000..59606e1
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2015 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 ALARM_ALARM_EXTENSION_H_
+#define ALARM_ALARM_EXTENSION_H_
+
+#include "common/extension.h"
+
+class AlarmExtension : public common::Extension {
+ public:
+  AlarmExtension();
+  virtual ~AlarmExtension();
+
+ private:
+  virtual common::Instance* CreateInstance();
+};
+
+#endif // ALARM_ALARM_EXTENSION_H_
diff --git a/webWidgetTCT_device/src/alarm/alarm_instance.cc b/webWidgetTCT_device/src/alarm/alarm_instance.cc
new file mode 100755 (executable)
index 0000000..8f33bc3
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2015 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 "alarm_instance.h"
+
+#include "common/picojson.h"
+#include "common/logger.h"
+
+namespace extension {
+namespace alarm {
+
+using namespace common;
+
+AlarmInstance::AlarmInstance() {
+  LoggerD("Entered");
+  using namespace std::placeholders;
+
+  RegisterSyncHandler("AlarmManager_add",
+                      std::bind(&AlarmManager::Add, &manager_, _1, _2));
+  RegisterSyncHandler("AlarmManager_remove",
+                      std::bind(&AlarmManager::Remove, &manager_, _1, _2));
+  RegisterSyncHandler("AlarmManager_removeAll",
+                      std::bind(&AlarmManager::RemoveAll, &manager_, _1, _2));
+  RegisterSyncHandler("AlarmManager_get",
+                      std::bind(&AlarmManager::Get, &manager_, _1, _2));
+  RegisterSyncHandler("AlarmManager_getAll",
+                      std::bind(&AlarmManager::GetAll, &manager_, _1, _2));
+  //AlarmRelative
+  RegisterSyncHandler("AlarmRelative_getRemainingSeconds",
+                      std::bind(&AlarmManager::GetRemainingSeconds, &manager_, _1, _2));
+  //AlarmAbsolute
+  RegisterSyncHandler("AlarmAbsolute_getNextScheduledDate",
+                      std::bind(&AlarmManager::GetNextScheduledDate, &manager_, _1, _2));
+}
+
+AlarmInstance::~AlarmInstance() {
+  LoggerD("Entered");
+}
+
+} // namespace Alarm
+} // namespace extension
diff --git a/webWidgetTCT_device/src/alarm/alarm_instance.h b/webWidgetTCT_device/src/alarm/alarm_instance.h
new file mode 100755 (executable)
index 0000000..f6a7412
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2015 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 ALARM_ALARM_INSTANCE_H_
+#define ALARM_ALARM_INSTANCE_H_
+
+#include "common/extension.h"
+
+#include "alarm/alarm_manager.h"
+
+namespace extension {
+namespace alarm {
+
+class AlarmInstance: public common::ParsedInstance {
+ public:
+  AlarmInstance();
+  virtual ~AlarmInstance();
+
+ private:
+  AlarmManager manager_;
+};
+
+} // namespace alarm
+} // namespace extension
+
+#endif // ALARM_ALARM_INSTANCE_H_
diff --git a/webWidgetTCT_device/src/alarm/alarm_manager.cc b/webWidgetTCT_device/src/alarm/alarm_manager.cc
new file mode 100755 (executable)
index 0000000..3d196e9
--- /dev/null
@@ -0,0 +1,542 @@
+/*
+ * Copyright (c) 2015 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 "alarm_manager.h"
+
+#include <alarm.h>
+#include <app.h>
+#include <app_alarm.h>
+#include <app_control_internal.h>
+
+#include "common/logger.h"
+#include "common/converter.h"
+#include "common/scope_exit.h"
+
+#include "alarm_instance.h"
+#include "alarm_utils.h"
+
+using namespace common;
+using namespace common::tools;
+
+namespace extension {
+namespace alarm {
+
+namespace {
+const int kDateSize = 22; //"yyy mm dd hh mm ss dd" e.g 115 11 28 11 25 50 -1
+
+const std::string kAlarmRelative = "AlarmRelative";
+const std::string kAlarmAbsolute = "AlarmAbsolute";
+
+const char* kAlarmAbsoluteRecurrenceTypeKey = "RECURRENCE";
+const char* kAlarmAbsoluteReccurrenceTypeInterval = "INTERVAL";
+const char* kAlarmAbsoluteReccurrenceTypeByDayValue = "BYDAYVALUE";
+const char* kAlarmAbsoluteRecurrenceTypeNone = "NONE";
+const char* kAlarmAbsoluteDateKey = "DATE";
+
+const char* kAlarmKeyType = "TYPE";
+
+const char* kAlarmTypeValueAbsolute = "ABSOLUTE";
+const char* kAlarmTypeValueRelative = "RELATIVE";
+
+const char* kAlarmRelativeDelayKey = "RELATIVE_DELAY";
+
+const char* kSundayShort = "SU";
+const char* kMondayShort = "MO";
+const char* kTuesdayShort = "TU";
+const char* kWednesdayShort = "WE";
+const char* kThuesdayShort = "TH";
+const char* kFridayShort = "FR";
+const char* kSaturdayShort = "SA";
+
+}
+
+AlarmManager::AlarmManager() {
+}
+
+AlarmManager::~AlarmManager() {
+}
+
+void AlarmManager::Add(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+
+  if (!args.contains("alarm")) {
+    LoggerE("Invalid parameter passed.");
+    ReportError(PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed."), &out);
+    return;
+  }
+  const picojson::object& alarm = args.get("alarm").get<picojson::object>();
+
+  std::string alarm_type;
+  if (args.contains("type")) {
+    alarm_type = args.get("type").get<std::string>();
+  }
+
+  std::string app_id;
+  if (args.contains("applicationId")) {
+    app_id = args.get("applicationId").get<std::string>();
+  }
+
+  app_control_h app_control = nullptr;
+  SCOPE_EXIT {
+    app_control_destroy(app_control);
+  };
+
+  if (args.contains("appControl") && args.get("appControl").is<picojson::object>()) {
+    PlatformResult result = util::AppControlToService(
+        args.get("appControl").get<picojson::object>(), &app_control);
+    if (!result) {
+      LoggerE("Failed: util::AppControlToService");
+      ReportError(result, &out);
+      return;
+    }
+  } else {
+    app_control_create(&app_control);
+    app_control_set_operation(app_control, APP_CONTROL_OPERATION_DEFAULT);
+  }
+
+  app_control_set_app_id(app_control, app_id.c_str());
+
+  int alarm_id = 0;
+
+  if (kAlarmRelative == alarm_type) {
+    app_control_add_extra_data(app_control, kAlarmKeyType, kAlarmTypeValueRelative);
+
+    const auto it_delay = alarm.find("delay");
+    const auto it_period = alarm.find("period");
+
+    if (alarm.end() == it_delay || alarm.end() == it_period || !it_delay->second.is<double>()) {
+      LoggerE("Invalid parameter passed.");
+      ReportError(PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed."), &out);
+      return;
+    }
+    int delay = static_cast<int>(it_delay->second.get<double>());
+
+    int period = 0;
+    if (it_period->second.is<double>()) {
+      period = static_cast<int>(it_period->second.get<double>());
+    }
+
+    std::string delay_str = std::to_string(delay);
+    int ret = app_control_add_extra_data(app_control, kAlarmRelativeDelayKey, delay_str.c_str());
+    if (APP_CONTROL_ERROR_NONE != ret) {
+      LoggerE("Fail to add data from app_control: %d (%s)", ret, get_error_message(ret));
+      ReportError(PlatformResult(
+          ErrorCode::UNKNOWN_ERR, "Fail to add data from app_control."), &out);
+      return;
+    }
+
+    ret = alarm_schedule_after_delay(app_control, delay, period, &alarm_id);
+    if (ALARM_ERROR_NONE != ret) {
+      LoggerE("Error while add alarm to server: %d (%s)", ret, get_error_message(ret));
+      ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Error while add alarm to server."), &out);
+      return;
+    }
+  } else {
+    app_control_add_extra_data(app_control, kAlarmKeyType, kAlarmTypeValueAbsolute);
+    app_control_add_extra_data(
+        app_control, kAlarmAbsoluteRecurrenceTypeKey, kAlarmAbsoluteRecurrenceTypeNone);
+
+    const auto it_period = alarm.find("period");
+    const auto it_daysOfTheWeek = alarm.find("daysOfTheWeek");
+
+    long long int seconds = 0;
+    if (args.contains("seconds")) {
+      seconds = atoll(args.get("seconds").get<std::string>().c_str());
+    }
+
+    time_t second = seconds / 1000;
+    struct tm start_date = {0};
+
+    tzset();
+    if (nullptr == localtime_r(&second, &start_date)) {
+      LoggerE("Invalid date.");
+      ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Invalid date."), &out);
+      return;
+    }
+
+    mktime(&start_date);
+
+    char str_date[kDateSize];
+
+    snprintf(str_date, sizeof(str_date), "%d %d %d %d %d %d %d", start_date.tm_year,
+             start_date.tm_mon, start_date.tm_mday, start_date.tm_hour, start_date.tm_min,
+             start_date.tm_sec, start_date.tm_isdst);
+
+    app_control_add_extra_data(app_control, kAlarmAbsoluteDateKey, str_date);
+
+    int ret = 0;
+    if (alarm.end() != it_period && it_period->second.is<double>()) {
+      int period = static_cast<int>(it_period->second.get<double>());
+      ret = alarm_schedule_at_date(app_control, &start_date, period, &alarm_id);
+    } else if (alarm.end() != it_daysOfTheWeek && it_daysOfTheWeek->second.is<picojson::array>() && 
+        !(it_daysOfTheWeek->second.get<picojson::array>()).empty()) {
+      picojson::array days_of_the_week = it_daysOfTheWeek->second.get<picojson::array>();
+      int repeat_value = 0;
+      for (auto iter = days_of_the_week.begin(); iter != days_of_the_week.end(); ++iter) {
+        auto day = (*iter).get<std::string>();
+        if (kSundayShort == day) {
+          repeat_value |= ALARM_WEEK_FLAG_SUNDAY;
+        } else if (kMondayShort == day) {
+          repeat_value |= ALARM_WEEK_FLAG_MONDAY;
+        } else if (kTuesdayShort == day) {
+          repeat_value |= ALARM_WEEK_FLAG_TUESDAY;
+        } else if (kWednesdayShort == day) {
+          repeat_value |= ALARM_WEEK_FLAG_WEDNESDAY;
+        } else if (kThuesdayShort == day) {
+          repeat_value |= ALARM_WEEK_FLAG_THURSDAY;
+        } else if (kFridayShort == day) {
+          repeat_value |= ALARM_WEEK_FLAG_FRIDAY;
+        } else if (kSaturdayShort == day) {
+          repeat_value |= ALARM_WEEK_FLAG_SATURDAY;
+        } else {
+          LoggerE("Invalid days of the week value.");
+          ReportError(PlatformResult(
+              ErrorCode::TYPE_MISMATCH_ERR, "Invalid days of the week value."), &out);
+          return;
+        }
+        ret = alarm_schedule_with_recurrence_week_flag(
+            app_control, &start_date, repeat_value, &alarm_id);
+      }
+    } else {
+      ret = alarm_schedule_at_date(app_control, &start_date, 0, &alarm_id);
+    }
+
+    if (ALARM_ERROR_NONE != ret) {
+      LoggerE("Adding alarm to server failed: %d (%s)", ret, get_error_message(ret));
+      ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Adding alarm to server failed."), &out);
+      return;
+    }
+  }
+
+  // result object
+  picojson::value result = picojson::value(picojson::object());
+  picojson::object& result_obj = result.get<picojson::object>();
+
+  result_obj.insert(std::make_pair("id", picojson::value(std::to_string(alarm_id))));
+  ReportSuccess(result, out);
+}
+
+void AlarmManager::Remove(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+
+  int id = 0;
+
+  if (args.contains("id") && args.get("id").is<double>()) {
+    id = static_cast<int>(args.get("id").get<double>());
+  }
+
+  if (id <= 0) {
+      LoggerE("id is wrong: %d", id);
+      ReportError(PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid id."), &out);
+      return;
+  }
+
+  int ret = alarm_cancel(id);
+  if (ALARM_ERROR_NONE == ret) {
+    ReportSuccess(out);
+  } else if (ALARM_ERROR_INVALID_PARAMETER == ret) {
+    LoggerE("Alarm not found.");
+    ReportError(PlatformResult(ErrorCode::NOT_FOUND_ERR, "Alarm not found."), &out);
+  } else {
+    LoggerE("Platform unknown error: %d (%s)", ret, get_error_message(ret));
+    ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Platform unknown error."), &out);
+  }
+}
+
+void AlarmManager::RemoveAll(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+
+  int ret = alarm_cancel_all();
+  if (ALARM_ERROR_NONE != ret) {
+    LoggerE("Platform unknown error: %d (%s)", ret, get_error_message(ret));
+    ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Platform unknown error."), &out);
+    return;
+  }
+
+  ReportSuccess(out);
+}
+
+PlatformResult AlarmManager::GetAlarm(int id, picojson::object& obj) {
+  LoggerD("Entered");
+
+  if (id <= 0) {
+    LoggerE("id is wrong: %d", id);
+    return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid id.");
+  }
+
+  int ret = ALARM_ERROR_NONE;
+  app_control_h app_control = nullptr;
+  char* alarm_type = nullptr;
+  char* date_string = nullptr;
+  char* delay_string = nullptr;
+
+  SCOPE_EXIT {
+    app_control_destroy(app_control);
+    free(alarm_type);
+    free(date_string);
+    free(delay_string);
+  };
+
+  ret = alarm_get_app_control(id, &app_control);
+  if (ALARM_ERROR_NONE != ret) {
+    LoggerE("Alarm not found: %d (%s)", ret, get_error_message(ret));
+    return PlatformResult(ErrorCode::NOT_FOUND_ERR, "Alarm not found.");
+  }
+
+  ret = app_control_get_extra_data(app_control, kAlarmKeyType, &alarm_type);
+  if (APP_CONTROL_ERROR_NONE != ret) {
+    LoggerE("Getting data failed: %d (%s)", ret, get_error_message(ret));
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error occurred.");
+  }
+
+  obj.insert(std::make_pair("id", picojson::value(std::to_string(id))));
+
+  if (!strcmp(alarm_type, kAlarmTypeValueAbsolute)) {
+    struct tm date;
+    memset(&date, 0, sizeof(tm));
+
+    ret = app_control_get_extra_data(app_control, kAlarmAbsoluteDateKey, &date_string);
+
+    if (APP_CONTROL_ERROR_NONE != ret) {
+      LoggerE("Failed to get data: %d (%s)", ret, get_error_message(ret));
+      return PlatformResult(ErrorCode::NOT_FOUND_ERR, "Failed to get data.");
+    }
+
+    sscanf(date_string, "%5d %5d %5d %5d %5d %5d %5d", &date.tm_year, &date.tm_mon,
+           &date.tm_mday, &date.tm_hour, &date.tm_min, &date.tm_sec, &date.tm_isdst);
+    mktime(&date);
+
+    obj.insert(std::make_pair("year", picojson::value(std::to_string(date.tm_year + 1900))));
+    obj.insert(std::make_pair("month", picojson::value(std::to_string(date.tm_mon))));
+    obj.insert(std::make_pair("day", picojson::value(std::to_string(date.tm_mday))));
+    obj.insert(std::make_pair("hour", picojson::value(std::to_string(date.tm_hour))));
+    obj.insert(std::make_pair("min", picojson::value(std::to_string(date.tm_min))));
+    obj.insert(std::make_pair("sec", picojson::value(std::to_string(date.tm_sec))));
+
+    int interval = 0;
+
+    app_control_get_extra_data(app_control, kAlarmAbsoluteRecurrenceTypeKey, &alarm_type);
+
+    if (!strcmp(alarm_type, kAlarmAbsoluteReccurrenceTypeInterval)) {
+      ret = alarm_get_scheduled_period(id, &interval);
+      if (ALARM_ERROR_NONE != ret) {
+        LoggerE("Unknown error occurred: %d (%s)", ret, get_error_message(ret));
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error occurred.");
+      }
+
+      obj.insert(std::make_pair("second", picojson::value(std::to_string(interval))));
+    } else if (!strcmp(alarm_type, kAlarmAbsoluteReccurrenceTypeByDayValue)) {
+      int byDayValue = 0;
+
+      ret = alarm_get_scheduled_recurrence_week_flag(id, &byDayValue);
+      if (ALARM_ERROR_NONE != ret) {
+        LoggerE("Failed to get data: %d (%s)", ret, get_error_message(ret));
+        return PlatformResult(ErrorCode::NOT_FOUND_ERR, "Failed to get data.");
+      }
+
+      picojson::array& array =
+          obj.insert(std::make_pair("second", picojson::value(picojson::array())))
+          .first->second.get<picojson::array>();
+
+      if (byDayValue & ALARM_WEEK_FLAG_SUNDAY)
+        array.push_back(picojson::value(kSundayShort));
+      if (byDayValue & ALARM_WEEK_FLAG_MONDAY)
+        array.push_back(picojson::value(kMondayShort));
+      if (byDayValue & ALARM_WEEK_FLAG_TUESDAY)
+        array.push_back(picojson::value(kTuesdayShort));
+      if (byDayValue & ALARM_WEEK_FLAG_WEDNESDAY)
+        array.push_back(picojson::value(kWednesdayShort));
+      if (byDayValue & ALARM_WEEK_FLAG_THURSDAY)
+        array.push_back(picojson::value(kThuesdayShort));
+      if (byDayValue & ALARM_WEEK_FLAG_FRIDAY)
+        array.push_back(picojson::value(kFridayShort));
+      if (byDayValue & ALARM_WEEK_FLAG_SATURDAY)
+        array.push_back(picojson::value(kSaturdayShort));
+    }
+
+    obj.insert(std::make_pair("type", picojson::value(kAlarmAbsolute)));
+
+  } else if (!strcmp(alarm_type, kAlarmTypeValueRelative)) {
+    int interval = 0;
+
+    ret = alarm_get_scheduled_period(id, &interval);
+    if (ALARM_ERROR_NONE != ret) {
+      LoggerE("Unknown error occurred: %d (%s)", ret, get_error_message(ret));
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error occurred.");
+    }
+
+    ret = app_control_get_extra_data(app_control, kAlarmRelativeDelayKey, &delay_string);
+    if (APP_CONTROL_ERROR_NONE != ret) {
+      LoggerE("Failed to get data: %d (%s)", ret, get_error_message(ret));
+      return PlatformResult(ErrorCode::NOT_FOUND_ERR, "Failed to get data.");
+    }
+
+    obj.insert(std::make_pair("type", picojson::value(kAlarmRelative)));
+    obj.insert(std::make_pair("delay", picojson::value(delay_string)));
+    obj.insert(std::make_pair("period", picojson::value(std::to_string(interval))));
+  } else {
+    LoggerE("Unknown error occurred.");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error occurred.");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+void AlarmManager::Get(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+
+  int id = 0;
+
+  if (args.contains("id") && args.get("id").is<double>()) {
+    id = static_cast<int>(args.get("id").get<double>());
+  }
+
+  picojson::value result = picojson::value(picojson::object());
+  picojson::object& result_obj = result.get<picojson::object>();
+
+  PlatformResult platform_result = GetAlarm(id, result_obj);
+
+  if (!platform_result) {
+    ReportError(platform_result, &out);
+  } else {
+    ReportSuccess(result, out);
+  }
+}
+
+static bool AlarmIterateCB(int alarm_id, void *user_data) {
+  LoggerD("Enter");
+
+  std::vector<int> *alarm_ids = reinterpret_cast<std::vector<int>*>(user_data);
+
+  alarm_ids->push_back(alarm_id);
+  return true;
+}
+
+void AlarmManager::GetAll(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+
+  std::vector<int> alarm_ids;
+  int ret = alarm_foreach_registered_alarm(AlarmIterateCB, &alarm_ids);
+
+  if (ALARM_ERROR_NONE != ret) {
+    LoggerE("Platform unknown error: %d (%s)", ret, get_error_message(ret));
+    ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Platform unknown error."), &out);
+    return;
+  }
+
+  picojson::value result_array = picojson::value(picojson::array());
+  picojson::array& array_obj = result_array.get<picojson::array>();
+
+  for (size_t i = 0 ; i < alarm_ids.size(); i++) {
+    picojson::value result = picojson::value(picojson::object());
+    picojson::object& obj = result.get<picojson::object>();
+
+    PlatformResult platform_result = GetAlarm(alarm_ids.at(i), obj);
+    if (!platform_result) {
+      LoggerE("Failed GetAlarm()");
+      ReportError(platform_result, &out);
+      return;
+    }
+    array_obj.push_back(result);
+  }
+
+  ReportSuccess(result_array, out);
+}
+
+void AlarmManager::GetRemainingSeconds(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+
+  struct tm date;
+  struct tm current;
+  time_t current_time;
+  time_t next_time;
+
+  int id = 0;
+
+  if (args.contains("id") && args.get("id").is<double>()) {
+    id = static_cast<int>(args.get("id").get<double>());
+  }
+
+  picojson::value result = picojson::value(picojson::object());
+  picojson::object& result_obj = result.get<picojson::object>();
+
+  int ret = alarm_get_scheduled_date(id, &date);
+  if(ALARM_ERROR_NONE != ret) {
+    LoggerI("alarm_get_scheduled_date error: %d (%s)", ret, get_error_message(ret));
+    if (ALARM_ERROR_INVALID_PARAMETER == ret || ALARM_ERROR_CONNECTION_FAIL == ret) {
+      result_obj.insert(std::make_pair("seconds", picojson::value()));
+      ReportSuccess(result, out);
+      return;
+    } else {
+      LoggerE("Platform unknown error.");
+      ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Platform unknown error."), &out);
+      return;
+    }
+  }
+
+  alarm_get_current_time(&current);
+  next_time = mktime(&date);
+  current_time = mktime(&current);
+
+  long seconds = next_time - current_time;
+
+  result_obj.insert(std::make_pair("seconds", picojson::value(std::to_string(seconds))));
+  ReportSuccess(result, out);
+}
+
+void AlarmManager::GetNextScheduledDate(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+
+  int id = 0;
+
+  if (args.contains("id") && args.get("id").is<double>()) {
+    id = static_cast<int>(args.get("id").get<double>());
+  }
+
+  struct tm date;
+  int ret = alarm_get_scheduled_date(id, &date);
+
+  picojson::value result = picojson::value(picojson::object());
+  picojson::object& result_obj = result.get<picojson::object>();
+
+  if (ALARM_ERROR_NONE != ret) {
+    result_obj.insert(std::make_pair("year", picojson::value()));
+    ReportSuccess(result, out);
+    return;
+  }
+
+  struct tm curr_date;
+  ret = alarm_get_current_time(&curr_date);
+  if (ALARM_ERROR_NONE != ret || mktime(&date) < mktime(&curr_date)) {
+    result_obj.insert(std::make_pair("year", picojson::value()));
+    ReportSuccess(result, out);
+    return;
+  }
+
+  // tm struct contains years since 1900
+  // there is added 1900 to tm_year to return proper date
+  result_obj.insert(std::make_pair("year", picojson::value(std::to_string(date.tm_year + 1900))));
+  result_obj.insert(std::make_pair("month", picojson::value(std::to_string(date.tm_mon))));
+  result_obj.insert(std::make_pair("day", picojson::value(std::to_string(date.tm_mday))));
+  result_obj.insert(std::make_pair("hour", picojson::value(std::to_string(date.tm_hour))));
+  result_obj.insert(std::make_pair("min", picojson::value(std::to_string(date.tm_min))));
+  result_obj.insert(std::make_pair("sec", picojson::value(std::to_string(date.tm_sec))));
+
+  ReportSuccess(result, out);
+}
+
+} // namespace alarm
+} // namespace extension
diff --git a/webWidgetTCT_device/src/alarm/alarm_manager.h b/webWidgetTCT_device/src/alarm/alarm_manager.h
new file mode 100755 (executable)
index 0000000..1ad2701
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2015 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 ALARM_ALARM_MANAGER_H_
+#define ALARM_ALARM_MANAGER_H_
+
+#include "common/picojson.h"
+#include "common/platform_result.h"
+
+namespace extension {
+namespace alarm {
+
+class AlarmManager {
+ public:
+  AlarmManager();
+  virtual ~AlarmManager();
+
+  void Add(const picojson::value& args, picojson::object& out);
+  void Remove(const picojson::value& args, picojson::object& out);
+  void RemoveAll(const picojson::value& args, picojson::object& out);
+  void Get(const picojson::value& args, picojson::object& out);
+  void GetAll(const picojson::value& args, picojson::object& out);
+
+  //AlarmRelative
+  void GetRemainingSeconds(const picojson::value& args, picojson::object& out);
+  //AlarmAbsolute
+  void GetNextScheduledDate(const picojson::value& args, picojson::object& out);
+
+ private:
+  AlarmManager(const AlarmManager&) = delete;
+  AlarmManager& operator=(const AlarmManager&) = delete;
+  common::PlatformResult GetAlarm(int id, picojson::object& obj);
+
+};
+
+} // namespace alarm
+} // namespace extension
+
+#endif // ALARM_ALARM_MANAGER_H_
diff --git a/webWidgetTCT_device/src/alarm/alarm_utils.cc b/webWidgetTCT_device/src/alarm/alarm_utils.cc
new file mode 100755 (executable)
index 0000000..ede6023
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2015 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 "alarm_utils.h"
+
+#include "common/logger.h"
+
+namespace extension {
+namespace alarm {
+namespace util {
+
+using namespace common;
+
+PlatformResult AppControlToService(const picojson::object& obj, app_control_h *app_control) {
+  LoggerD("Entered");
+
+  const auto it_end = obj.end();
+
+  const auto it_operation = obj.find("operation");
+  if (it_operation == it_end || !it_operation->second.is<std::string>()) {
+    LoggerE("Invalid parameter passed.");
+    return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed.");
+  }
+
+  app_control_create(app_control);
+
+  int ret = app_control_set_operation(*app_control, it_operation->second.get<std::string>().c_str());
+  if (APP_CONTROL_ERROR_NONE != ret) {
+    LoggerE("Failed app_control_set_operation(): %d (%s)", ret, get_error_message(ret));
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Error while setting operation.");
+  }
+
+  const auto it_uri = obj.find("uri");
+  if (it_end != it_uri && it_uri->second.is<std::string>()) {
+    ret = app_control_set_uri(*app_control, it_uri->second.get<std::string>().c_str());
+    if (APP_CONTROL_ERROR_NONE != ret) {
+      LoggerE("Failed app_control_set_uri(): %d (%s)", ret, get_error_message(ret));
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, "Error while setting uri.");
+    }
+  }
+
+  const auto it_mime = obj.find("mime");
+  if (it_end != it_mime && it_mime->second.is<std::string>()) {
+    ret = app_control_set_mime(*app_control, it_mime->second.get<std::string>().c_str());
+    if (APP_CONTROL_ERROR_NONE != ret) {
+      LoggerE("Failed app_control_set_mime(): %d (%s)", ret, get_error_message(ret));
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, "Error while setting mime.");
+    }
+  }
+
+  const auto it_category = obj.find("category");
+  if (it_end != it_category && it_category->second.is<std::string>()) {
+    ret = app_control_set_category(*app_control, it_category->second.get<std::string>().c_str());
+    if (APP_CONTROL_ERROR_NONE != ret) {
+      LoggerE("Failed app_control_set_category(): %d (%s)", ret, get_error_message(ret));
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, "Error while setting category.");
+    }
+  }
+
+  const auto it_data = obj.find("data");
+  if (it_end != it_data && it_data->second.is<picojson::array>()) {
+    const picojson::array& data = it_data->second.get<picojson::array>();
+    PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
+
+    for (auto iter = data.begin(); iter != data.end(); ++iter) {
+      result = AppControlToServiceExtraData(iter->get<picojson::object>(), app_control);
+      if (!result) {
+        LoggerE("Failed AppControlToServiceExtraData()");
+        return result;
+      }
+    }
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult AppControlToServiceExtraData(const picojson::object& app_obj,
+                                            app_control_h *app_control) {
+  LoggerD("Entered");
+
+  const auto it_key = app_obj.find("key");
+  const auto it_value = app_obj.find("value");
+  const auto it_end = app_obj.end();
+
+  if (it_key == it_end ||
+      it_value == it_end ||
+      !it_key->second.is<std::string>() ||
+      !it_value->second.is<picojson::array>()) {
+    LoggerE("Problem with key or value.");
+    return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Problem with key or value.");
+  }
+
+  const std::string& key = it_key->second.get<std::string>();
+  const picojson::array& values = it_value->second.get<picojson::array>();
+
+  const size_t size = values.size();
+  const char** arr = new const char*[size];
+  size_t i = 0;
+
+  for (auto iter = values.begin(); iter != values.end(); ++iter, ++i) {
+      std::string str = iter->to_str();
+      arr[i] = str.c_str();
+  }
+
+  int ret = APP_CONTROL_ERROR_NONE;
+  if (1 == size) {
+    ret = app_control_add_extra_data(*app_control, key.c_str(), arr[0]);
+  } else {
+    ret = app_control_add_extra_data_array(*app_control, key.c_str(), arr, size);
+  }
+  delete[] arr;
+
+  if (APP_CONTROL_ERROR_NONE != ret) {
+    LoggerD("Error while setting data: %d (%s)", ret, get_error_message(ret));
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Error while setting data.");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+} // util
+} // alarm
+} // extension
diff --git a/webWidgetTCT_device/src/alarm/alarm_utils.h b/webWidgetTCT_device/src/alarm/alarm_utils.h
new file mode 100755 (executable)
index 0000000..a513f0d
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2015 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 ALARM_ALARM_UTILS_H_
+#define ALARM_ALARM_UTILS_H_
+
+#include <app_control.h>
+
+#include "common/picojson.h"
+#include "common/platform_result.h"
+
+namespace extension {
+namespace alarm {
+namespace util {
+
+common::PlatformResult AppControlToService(const picojson::object& obj, app_control_h *app_control);
+common::PlatformResult AppControlToServiceExtraData(const picojson::object& app_obj,
+                                                    app_control_h *app_control);
+} // util
+} // alarm
+} // extension
+
+#endif // ALARM_ALARM_UTILS_H_
diff --git a/webWidgetTCT_device/src/application/application.cc b/webWidgetTCT_device/src/application/application.cc
new file mode 100755 (executable)
index 0000000..d6522c5
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2015 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 "application/application.h"
+
+#include "common/extension.h"
+#include "common/logger.h"
+#include "common/platform_result.h"
+
+using namespace common;
+using namespace tools;
+
+namespace extension {
+namespace application {
+
+RequestedApplicationControl& Application::app_control() {
+    return app_control_;
+}
+
+void Application::GetRequestedAppControl(const picojson::value& args, picojson::object* out) {
+  LoggerD("Entered");
+
+  const std::string& encoded_bundle = RequestedApplicationControl::GetEncodedBundle();
+
+  picojson::value result = picojson::value(picojson::object());
+
+  if (!encoded_bundle.empty()) {
+    PlatformResult ret = app_control_.set_bundle(encoded_bundle);
+    if (ret.IsError()) {
+      ReportError(ret, out);
+      return;
+    }
+
+    app_control_.ToJson(&result.get<picojson::object>());
+  } else {
+    LoggerD("bundle string is empty.");
+    result = picojson::value();
+  }
+
+  ReportSuccess(result, *out);
+}
+
+}  // namespace application
+}  // namespace extension
diff --git a/webWidgetTCT_device/src/application/application.gyp b/webWidgetTCT_device/src/application/application.gyp
new file mode 100755 (executable)
index 0000000..24d8fbe
--- /dev/null
@@ -0,0 +1,46 @@
+{
+  'includes':[
+    '../common/common.gypi',
+  ],
+  'targets': [
+    {
+      'target_name': 'tizen_application',
+      'type': 'loadable_module',
+      'dependencies': [
+        '../common/common.gyp:tizen_common',
+      ],
+      'sources': [
+        'application_api.js',
+        'application_extension.cc',
+        'application_extension.h',
+        'application_instance.cc',
+        'application_instance.h',
+        'application.cc',
+        'application.h',
+        'application_manager.cc',
+        'application_manager.h',
+        'application_utils.cc',
+        'application_utils.h',
+        'requested_application_control.cc',
+        'requested_application_control.h',
+      ],
+      'includes': [
+        '../common/pkg-config.gypi',
+      ],
+      'conditions': [
+        ['tizen == 1', {
+         'variables': {
+            'packages': [
+              'aul',
+              'capi-appfw-app-manager',
+              'capi-appfw-application',
+              'capi-appfw-package-manager',
+              'pkgmgr',
+              'pkgmgr-info',
+            ]
+          },
+        }],
+      ],
+    },
+  ],
+}
diff --git a/webWidgetTCT_device/src/application/application.h b/webWidgetTCT_device/src/application/application.h
new file mode 100755 (executable)
index 0000000..2c6905c
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2015 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 SRC_APPLICATION_APPLICATION_H_
+#define SRC_APPLICATION_APPLICATION_H_
+
+#include <string>
+#include <memory>
+
+#include "common/picojson.h"
+#include "application/requested_application_control.h"
+
+namespace extension {
+namespace application {
+
+class Application {
+ public:
+  RequestedApplicationControl& app_control();
+  void GetRequestedAppControl(const picojson::value& args, picojson::object* out);
+
+ private:
+  RequestedApplicationControl app_control_;
+};
+
+}  // namespace application
+}  // namespace extension
+
+#endif  // SRC_APPLICATION_APPLICATION_H_
diff --git a/webWidgetTCT_device/src/application/application_api.js b/webWidgetTCT_device/src/application/application_api.js
new file mode 100755 (executable)
index 0000000..162d963
--- /dev/null
@@ -0,0 +1,1137 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+var T = xwalk.utils.type;
+var Converter = xwalk.utils.converter;
+var AV = xwalk.utils.validator;
+var Privilege = xwalk.utils.privilege;
+
+var native = new xwalk.utils.NativeManager(extension);
+
+var ApplicationControlLaunchMode = {
+  SINGLE: 'SINGLE',
+  GROUP: 'GROUP'
+};
+
+var SystemEvent = {
+  BATTERY_CHARGER_STATUS: 'BATTERY_CHARGER_STATUS',
+  BATTERY_LEVEL_STATUS: 'BATTERY_LEVEL_STATUS',
+  USB_STATUS: 'USB_STATUS',
+  USBHOST_STATUS: 'USBHOST_STATUS',
+  EARJACK_STATUS: 'EARJACK_STATUS',
+  DISPLAY_STATE: 'DISPLAY_STATE',
+  BOOT_COMPLETED: 'BOOT_COMPLETED',
+  SYSTEM_SHUTDOWN: 'SYSTEM_SHUTDOWN',
+  LOW_MEMORY: 'LOW_MEMORY',
+  WIFI_STATE: 'WIFI_STATE',
+  BT_STATE: 'BT_STATE',
+  BT_TRANSFERING_STATE: 'BT_TRANSFERING_STATE',
+  MOBILE_DATA_STATE: 'MOBILE_DATA_STATE',
+  DATA_ROAMING_STATE: 'DATA_ROAMING_STATE',
+  LOCATION_ENABLE_STATE: 'LOCATION_ENABLE_STATE',
+  GPS_ENABLE_STATE: 'GPS_ENABLE_STATE',
+  NPS_ENABLE_STATE: 'NPS_ENABLE_STATE',
+  INCOMING_MSG: 'INCOMING_MSG',
+  TIME_CHANGED: 'TIME_CHANGED',
+  TIME_ZONE: 'TIME_ZONE',
+  HOUR_FORMAT: 'HOUR_FORMAT',
+  LANGUAGE_SET: 'LANGUAGE_SET',
+  REGION_FORMAT: 'REGION_FORMAT',
+  SILENT_MODE: 'SILENT_MODE',
+  VIBRATION_STATE: 'VIBRATION_STATE',
+  SCREEN_AUTOROTATE_STATE: 'SCREEN_AUTOROTATE_STATE',
+  FONT_SET: 'FONT_SET'
+};
+
+// helper functions ////////////////////////////////////////////////////
+function _createApplicationControlData(object) {
+  var ret;
+  if (!T.isNullOrUndefined(object)) {
+    ret = new tizen.ApplicationControlData(object.key, object.value);
+  }
+  return ret;
+}
+
+function _createApplicationControlDataArray(object) {
+  var ret = [];
+  if (!T.isNullOrUndefined(object) && T.isArray(object)) {
+    object.forEach(function (o) {
+      var data = _createApplicationControlData(o);
+      if (!T.isNullOrUndefined(data)) {
+        ret.push(data);
+      }
+    });
+  }
+  return ret;
+}
+
+function _createApplicationControl(object) {
+  var ret;
+  if (!T.isNullOrUndefined(object)) {
+    ret = new tizen.ApplicationControl(object.operation,
+        object.uri,
+        object.mime,
+        object.category,
+        _createApplicationControlDataArray(object.data));
+  }
+  return ret;
+}
+
+function _createApplicationInformationArray(object) {
+  var ret = [];
+  if (!T.isNullOrUndefined(object) && T.isArray(object)) {
+    object.forEach(function (o) {
+      var data = new ApplicationInformation(o);
+      if (!T.isNullOrUndefined(data)) {
+        ret.push(data);
+      }
+    });
+  }
+  return ret;
+}
+
+// class ApplicationManager ////////////////////////////////////////////////////
+var ApplicationManager = function() {
+};
+
+ApplicationManager.prototype.getCurrentApplication = function() {
+  var result = native.callSync('ApplicationManager_getCurrentApplication', {});
+
+  if (native.isFailure(result)) {
+    throw native.getErrorObject(result);
+  } else {
+    return new Application(native.getResultObject(result));
+  }
+};
+
+ApplicationManager.prototype.kill = function() {
+  xwalk.utils.checkPrivilegeAccess(Privilege.APPMANAGER_KILL);
+
+  var args = AV.validateMethod(arguments, [
+      {
+        name : 'contextId',
+        type : AV.Types.STRING
+      },
+      {
+        name : 'successCallback',
+        type : AV.Types.FUNCTION,
+        optional : true,
+        nullable : true
+      },
+      {
+        name : 'errorCallback',
+        type : AV.Types.FUNCTION,
+        optional : true,
+        nullable : true
+      }
+  ]);
+
+  var callback = function(result) {
+    if (native.isFailure(result)) {
+      native.callIfPossible(args.errorCallback, native.getErrorObject(result));
+    } else {
+      native.callIfPossible(args.successCallback);
+    }
+  };
+
+  var result = native.call('ApplicationManager_kill', {contextId: args.contextId}, callback);
+
+  if (native.isFailure(result)) {
+    throw native.getErrorObject(result);
+  }
+};
+
+ApplicationManager.prototype.launch = function() {
+  xwalk.utils.checkPrivilegeAccess(Privilege.APPLICATION_LAUNCH);
+
+  var args = AV.validateMethod(arguments, [
+      {
+        name : 'id',
+        type : AV.Types.STRING
+      },
+      {
+        name : 'successCallback',
+        type : AV.Types.FUNCTION,
+        optional : true,
+        nullable : true
+      },
+      {
+        name : 'errorCallback',
+        type : AV.Types.FUNCTION,
+        optional : true,
+        nullable : true
+      }
+  ]);
+
+  var callback = function(result) {
+    if (native.isFailure(result)) {
+      native.callIfPossible(args.errorCallback, native.getErrorObject(result));
+    } else {
+      native.callIfPossible(args.successCallback);
+    }
+  };
+
+  var result = native.call('ApplicationManager_launch', {id: args.id}, callback);
+
+  if (native.isFailure(result)) {
+    throw native.getErrorObject(result);
+  }
+};
+
+ApplicationManager.prototype.launchAppControl = function() {
+  xwalk.utils.checkPrivilegeAccess(Privilege.APPLICATION_LAUNCH);
+
+  var args = AV.validateMethod(arguments, [
+      {
+        name : 'appControl',
+        type : AV.Types.PLATFORM_OBJECT,
+        values : tizen.ApplicationControl
+      },
+      {
+        name : 'id',
+        type : AV.Types.STRING,
+        optional : true,
+        nullable : true
+      },
+      {
+        name : 'successCallback',
+        type : AV.Types.FUNCTION,
+        optional : true,
+        nullable : true
+      },
+      {
+        name : 'errorCallback',
+        type : AV.Types.FUNCTION,
+        optional : true,
+        nullable : true
+      },
+      {
+        name : 'replyCallback',
+        type : AV.Types.LISTENER,
+        values : ['onsuccess', 'onfailure'],
+        optional : true,
+        nullable : true
+      }
+  ]);
+
+  var replyCallbackId = 'ApplicationControlDataArrayReplyCallback_' + new Date().valueOf();
+  var registeredReplyCallback = function(result) {
+    if (native.isFailure(result)) {
+      native.callIfPossible(args.replyCallback.onfailure);
+    } else {
+      native.callIfPossible(args.replyCallback.onsuccess,
+          _createApplicationControlDataArray(result.data));
+    }
+    native.removeListener(replyCallbackId, registeredReplyCallback);
+  };
+
+  var callback = function(result) {
+    if (native.isFailure(result)) {
+      native.callIfPossible(args.errorCallback, native.getErrorObject(result));
+      native.removeListener(replyCallbackId, registeredReplyCallback);
+    } else {
+      native.callIfPossible(args.successCallback);
+    }
+  };
+
+  var callArgs = {};
+  callArgs.appControl = args.appControl;
+  if (args.has.id) {
+    callArgs.id = args.id;
+  }
+  if (args.has.replyCallback && args.replyCallback) {
+    callArgs.replyCallback = replyCallbackId;
+    native.addListener(replyCallbackId, registeredReplyCallback);
+  }
+
+  var result = native.call('ApplicationManager_launchAppControl', callArgs, callback);
+
+  if (native.isFailure(result)) {
+    throw native.getErrorObject(result);
+  }
+};
+
+ApplicationManager.prototype.findAppControl = function() {
+  var args = AV.validateMethod(arguments, [
+      {
+        name : 'appControl',
+        type : AV.Types.PLATFORM_OBJECT,
+        values : tizen.ApplicationControl
+      },
+      {
+        name : 'successCallback',
+        type : AV.Types.FUNCTION
+      },
+      {
+        name : 'errorCallback',
+        type : AV.Types.FUNCTION,
+        optional : true,
+        nullable : true
+      }
+  ]);
+
+  var callback = function(result) {
+    if (native.isFailure(result)) {
+      native.callIfPossible(args.errorCallback, native.getErrorObject(result));
+    } else {
+      var r = native.getResultObject(result);
+      args.successCallback(_createApplicationInformationArray(r.informationArray),
+          _createApplicationControl(r.appControl));
+    }
+  };
+
+  var callArgs = {appControl: args.appControl};
+  var result = native.call('ApplicationManager_findAppControl', callArgs, callback);
+
+  if (native.isFailure(result)) {
+    throw native.getErrorObject(result);
+  }
+};
+
+ApplicationManager.prototype.getAppsContext = function() {
+  var args = AV.validateMethod(arguments, [
+      {
+        name : 'successCallback',
+        type : AV.Types.FUNCTION
+      },
+      {
+        name : 'errorCallback',
+        type : AV.Types.FUNCTION,
+        optional : true,
+        nullable : true
+      }
+  ]);
+
+  var callback = function(result) {
+    if (native.isFailure(result)) {
+      native.callIfPossible(args.errorCallback, native.getErrorObject(result));
+    } else {
+      var contexts = native.getResultObject(result).contexts;
+      var c = [];
+      contexts.forEach(function (i) {
+        c.push(new ApplicationContext(i));
+      });
+      args.successCallback(c);
+    }
+  };
+
+  var result = native.call('ApplicationManager_getAppsContext', {}, callback);
+
+  if (native.isFailure(result)) {
+    throw native.getErrorObject(result);
+  }
+};
+
+ApplicationManager.prototype.getAppContext = function() {
+  var args = AV.validateMethod(arguments, [
+      {
+        name : 'contextId',
+        type : AV.Types.STRING,
+        optional : true,
+        nullable : true
+      }
+  ]);
+
+  var callArgs = {};
+
+  if (args.has.contextId) {
+    callArgs.contextId = args.contextId;
+  }
+
+  var result = native.callSync('ApplicationManager_getAppContext', callArgs);
+
+  if (native.isFailure(result)) {
+    throw native.getErrorObject(result);
+  } else {
+    return new ApplicationContext(native.getResultObject(result));
+  }
+};
+
+ApplicationManager.prototype.getAppsInfo = function() {
+  var args = AV.validateMethod(arguments, [
+      {
+        name : 'successCallback',
+        type : AV.Types.FUNCTION
+      },
+      {
+        name : 'errorCallback',
+        type : AV.Types.FUNCTION,
+        optional : true,
+        nullable : true
+      }
+  ]);
+
+  var callback = function(result) {
+    if (native.isFailure(result)) {
+      native.callIfPossible(args.errorCallback, native.getErrorObject(result));
+    } else {
+      args.successCallback(_createApplicationInformationArray(
+          native.getResultObject(result).informationArray)
+      );
+    }
+  };
+
+  var result = native.call('ApplicationManager_getAppsInfo', {}, callback);
+
+  if (native.isFailure(result)) {
+    throw native.getErrorObject(result);
+  }
+};
+
+ApplicationManager.prototype.getAppInfo = function() {
+  var args = AV.validateMethod(arguments, [
+      {
+        name : 'id',
+        type : AV.Types.STRING,
+        optional : true,
+        nullable : true
+      }
+  ]);
+
+  var callArgs = {};
+
+  if (args.has.id) {
+    callArgs.id = args.id;
+  }
+
+  var result = native.callSync('ApplicationManager_getAppInfo', callArgs);
+
+  if (native.isFailure(result)) {
+    throw native.getErrorObject(result);
+  } else {
+    return new ApplicationInformation(native.getResultObject(result));
+  }
+};
+
+ApplicationManager.prototype.getAppCerts = function() {
+  xwalk.utils.checkPrivilegeAccess(Privilege.APPMANAGER_CERTIFICATE);
+
+  var args = AV.validateMethod(arguments, [
+      {
+        name : 'id',
+        type : AV.Types.STRING,
+        optional : true,
+        nullable : true
+      }
+  ]);
+
+  var callArgs = {};
+
+  if (args.has.id) {
+    callArgs.id = args.id;
+  }
+
+  var result = native.callSync('ApplicationManager_getAppCerts', callArgs);
+
+  if (native.isFailure(result)) {
+    throw native.getErrorObject(result);
+  } else {
+    var certificates = native.getResultObject(result);
+    var c = [];
+    certificates.forEach(function (i) {
+      c.push(new ApplicationCertificate(i));
+    });
+    return c;
+  }
+};
+
+ApplicationManager.prototype.getAppSharedURI = function() {
+  var args = AV.validateMethod(arguments, [
+      {
+        name : 'id',
+        type : AV.Types.STRING,
+        optional : true,
+        nullable : true
+      }
+  ]);
+
+  var callArgs = {};
+
+  if (args.has.id) {
+    callArgs.id = args.id;
+  }
+
+  var result = native.callSync('ApplicationManager_getAppSharedURI', callArgs);
+
+  if (native.isFailure(result)) {
+    throw native.getErrorObject(result);
+  } else {
+    return native.getResultObject(result);
+  }
+};
+
+ApplicationManager.prototype.getAppMetaData = function() {
+  xwalk.utils.checkPrivilegeAccess(Privilege.APPLICATION_INFO);
+
+  var args = AV.validateMethod(arguments, [
+      {
+        name : 'id',
+        type : AV.Types.STRING,
+        optional : true,
+        nullable : true
+      }
+  ]);
+
+  var callArgs = {};
+
+  if (args.has.id) {
+    callArgs.id = args.id;
+  }
+
+  var result = native.callSync('ApplicationManager_getAppMetaData', callArgs);
+
+  if (native.isFailure(result)) {
+    throw native.getErrorObject(result);
+  } else {
+    var metaData = native.getResultObject(result);
+    var md = [];
+    metaData.forEach(function (i) {
+      md.push(new ApplicationMetaData(i));
+    });
+    return md;
+  }
+};
+
+function ListenerManager(native, listenerName) {
+  this.listeners = {};
+  this.nextId = 1;
+  this.nativeSet = false;
+  this.native = native;
+  this.listenerName = listenerName;
+};
+
+ListenerManager.prototype.onListenerCalled = function(msg) {
+  var d = null;
+
+  switch (msg.action) {
+  case 'oninstalled':
+  case 'onupdated':
+    d = new ApplicationInformation(msg.data);
+    break;
+
+  case 'onuninstalled':
+    d = msg.data;
+    break;
+
+  default:
+    console.logd('Unknown mode: ' + msg.action);
+  return;
+  }
+
+  for (var watchId in this.listeners) {
+    if (this.listeners.hasOwnProperty(watchId) && this.listeners[watchId][msg.action]) {
+      this.listeners[watchId][msg.action](d);
+    }
+  }
+};
+
+ListenerManager.prototype.addListener = function(callback) {
+  console.log('ListenerManager.prototype.addListener');
+  var id = this.nextId;
+  if (!this.nativeSet) {
+    this.native.addListener(this.listenerName, this.onListenerCalled.bind(this));
+    var result = this.native.callSync('ApplicationManager_addAppInfoEventListener');
+    if (this.native.isFailure(result)) {
+      throw this.native.getErrorObject(result);
+    }
+    this.nativeSet = true;
+  }
+
+  this.listeners[id] = callback;
+  ++this.nextId;
+
+  return id;
+};
+
+ListenerManager.prototype.removeListener = function(watchId) {
+  if (this.listeners.hasOwnProperty(watchId)) {
+    delete this.listeners[watchId];
+  } else {
+    throw new WebAPIException(WebAPIException.NOT_FOUND_ERR, 'Specified listener does not exist');
+  }
+
+  if (this.nativeSet && T.isEmptyObject(this.listeners)) {
+      this.native.callSync('ApplicationManager_removeAppInfoEventListener');
+      this.native.removeListener(this.listenerName);
+      this.nativeSet = false;
+  }
+};
+
+var APPLICATION_EVENT_LISTENER = 'ApplicationEventListener';
+var applicationEventListener = new ListenerManager(native, APPLICATION_EVENT_LISTENER);
+
+ApplicationManager.prototype.addAppInfoEventListener = function() {
+  var args = AV.validateMethod(arguments, [
+      {
+        name : 'eventCallback',
+        type : AV.Types.LISTENER,
+        values : ['oninstalled', 'onupdated', 'onuninstalled']
+      }
+  ]);
+
+  return applicationEventListener.addListener(args.eventCallback);
+};
+
+ApplicationManager.prototype.removeAppInfoEventListener = function() {
+  var args = AV.validateMethod(arguments, [
+      {
+        name : 'watchId',
+        type : AV.Types.LONG
+      }
+  ]);
+
+  applicationEventListener.removeListener(args.watchId);
+};
+
+// class Application ////////////////////////////////////////////////////
+
+function Application(data) {
+  Object.defineProperties(this, {
+    appInfo : {
+      value : new ApplicationInformation(data.appInfo),
+      writable : false,
+      enumerable : true
+    },
+    contextId : {
+      value : Converter.toString(data.contextId),
+      writable : false,
+      enumerable : true
+    }
+  });
+}
+
+Application.prototype.exit = function() {
+  native.sendRuntimeMessage('tizen://exit');
+};
+
+Application.prototype.hide = function() {
+  native.sendRuntimeMessage('tizen://hide');
+};
+
+Application.prototype.getRequestedAppControl = function() {
+  var result = native.callSync('Application_getRequestedAppControl', {});
+
+  if (native.isFailure(result)) {
+    throw native.getErrorObject(result);
+  } else {
+    result = native.getResultObject(result);
+    if (result) {
+      return new RequestedApplicationControl(result);
+    } else {
+      return null;
+    }
+  }
+};
+
+function _checkEventName(name) {
+  var name = name || '';
+  if (!(/^([a-zA-Z_]){1}([a-zA-Z0-9_]){0,126}$/.test(name))) {
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+        'Invalid event name');
+  }
+}
+
+function _checkAppId(appId) {
+  if (!(/^([a-zA-Z0-9]){10}([.]){1}([a-zA-Z0-9_]){1,52}$/.test(appId))) {
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+        'Invalid appId');
+  }
+}
+
+var event_listeners_ = {};
+var watchId_ = 0;
+function nextWatchId() {
+  return ++watchId_;
+}
+
+Application.prototype.addEventListener = function(event, callback) {
+  var args = AV.validateArgs(arguments, [
+    {name: 'event', type: AV.Types.DICTIONARY},
+    {name: 'callback', type: AV.Types.FUNCTION}
+  ]);
+
+  var data = {};
+
+//TODO: Uncomment the following lines when system events are available
+//  if (!args.event.hasOwnProperty('appId')) {
+//    data.name = 'tizen.system.event.' + args.event.name.toLowerCase();
+//  } else {
+    _checkEventName(args.event.name);
+    _checkAppId(args.event.appId);
+
+    data.name = 'event.' + args.event.appId + '.' + args.event.name;
+//  }
+
+  var watchId = nextWatchId();
+  data.listenerId = data.name;
+  event_listeners_[data.name] = !T.isObject(event_listeners_[data.name])
+                                ? {} : event_listeners_[data.name];
+
+  if (!Object.keys(event_listeners_[data.name]).length) {
+    native.addListener(data.name, function(msg) {
+      var eventName = msg.name;
+      var parsedName = eventName.split('.');
+      var eventInfo = {};
+      if (parsedName.length < 3) {
+        console.logd('Invalid event name returned' + eventName);
+      }
+      for (var id in event_listeners_[eventName]) {
+        if (event_listeners_[eventName].hasOwnProperty(id)) {
+          if (msg.data) {
+            eventInfo.appId = parsedName[1];
+            eventInfo.name = parsedName[2];
+            event_listeners_[eventName][id](eventInfo, msg.data);
+          } else {
+            delete msg.name;
+            msg.type = parsedName[2]; //TODO: type should come from native site
+            eventInfo.name = parsedName[2].toUpperCase();
+            event_listeners_[eventName][id](eventInfo, msg);
+          }
+        }
+      }
+    });
+
+    var result = native.callSync('Application_addEventListener', data);
+    if (native.isFailure(result)) {
+      throw native.getErrorObject(result);
+    }
+  }
+
+  event_listeners_[data.name][watchId] = args.callback;
+  return watchId;
+};
+
+function getEventNameById(watchId) {
+  var eventName;
+  for (var event in event_listeners_) {
+    if (event_listeners_.hasOwnProperty(event)) {
+      for (var id in event_listeners_[event]) {
+        if (event_listeners_[event].hasOwnProperty(id) && Converter.toLong(id) === watchId) {
+            eventName = event;
+        }
+      }
+    }
+  }
+  return eventName;
+}
+
+Application.prototype.removeEventListener = function(watchId) {
+  var args = AV.validateArgs(arguments, [
+    {name: 'watchId', type: AV.Types.LONG}
+  ]);
+
+  var eventName = getEventNameById(args.watchId);
+
+  if (!eventName) {
+    return;
+  }
+
+  delete event_listeners_[eventName][args.watchId];
+
+  if (!Object.keys(event_listeners_[eventName]).length) {
+    native.removeListener(eventName);
+    var result = native.callSync('Application_removeEventListener', {name: eventName});
+    if (native.isFailure(result)) {
+      throw native.getErrorObject(result);
+    }
+  }
+};
+
+Application.prototype.broadcastEvent = function(event, data) {
+  var args = AV.validateMethod(arguments, [
+    {name: 'event', type: AV.Types.DICTIONARY},
+    {name: 'data', type: AV.Types.DICTIONARY}
+  ]);
+
+  _checkEventName(args.event.name);
+
+  var nativeData = {
+    name: 'event.' + this.appInfo.id + '.' + args.event.name,
+    data: args.data
+  };
+
+  var result = native.callSync('Application_broadcastEvent', nativeData);
+
+  if (native.isFailure(result)) {
+    throw native.getErrorObject(result);
+  }
+};
+
+Application.prototype.broadcastTrustedEvent = function(event, data) {
+  var args = AV.validateMethod(arguments, [
+    {name: 'event', type: AV.Types.DICTIONARY},
+    {name: 'data', type: AV.Types.DICTIONARY}
+  ]);
+
+  _checkEventName(args.event.name);
+
+  var nativeData = {
+    name: 'event.' + this.appInfo.id + '.' + args.event.name,
+    data: args.data
+  };
+
+  var result = native.callSync('Application_broadcastTrustedEvent', nativeData);
+
+  if (native.isFailure(result)) {
+    throw native.getErrorObject(result);
+  }
+};
+
+// class ApplicationInformation ////////////////////////////////////////////////////
+
+function ApplicationInformation(data) {
+  var size;
+  var sizeException;
+
+  function sizeGetter() {
+    xwalk.utils.checkPrivilegeAccess(Privilege.APPLICATION_INFO);
+    if (undefined === size) {
+      var callArgs = { packageId : this.packageId }; // jshint ignore:line
+      var result = native.callSync('ApplicationInformation_getSize', callArgs);
+
+      if (native.isFailure(result)) {
+        sizeException = native.getErrorObject(result);
+        size = 0;
+      } else {
+        size = native.getResultObject(result).size;
+      }
+    }
+
+    if (undefined !== sizeException) {
+      throw sizeException;
+    }
+
+    return size;
+  }
+
+  Object.defineProperties(this, {
+    id : {
+      value : data.id,
+      writable : false,
+      enumerable : true
+    },
+    name : {
+      value : data.name,
+      writable : false,
+      enumerable : true
+    },
+    iconPath : {
+      value : data.iconPath,
+      writable : false,
+      enumerable : true
+    },
+    version : {
+      value : data.version,
+      writable : false,
+      enumerable : true
+    },
+    show : {
+      value : data.show,
+      writable : false,
+      enumerable : true
+    },
+    categories : {
+      value : data.categories,
+      writable : false,
+      enumerable : true
+    },
+    installDate : {
+      value : new Date(data.installDate),
+      writable : false,
+      enumerable : true
+    },
+    size : {
+      enumerable : true,
+      set : function() {
+      },
+      get : sizeGetter
+    },
+    packageId : {
+      value : data.packageId,
+      writable : false,
+      enumerable : true
+    }
+  });
+}
+
+// class ApplicationContext ////////////////////////////////////////////////////
+
+function ApplicationContext(data) {
+  Object.defineProperties(this, {
+    id    : {value: data.id, writable: false, enumerable: true},
+    appId : {value: data.appId, writable: false, enumerable: true}
+  });
+}
+
+// class ApplicationControlData ////////////////////////////////////////////////////
+
+tizen.ApplicationControlData = function(k, v) {
+  AV.validateConstructorCall(this, tizen.ApplicationControlData);
+
+  var valid = (arguments.length >= 2) && T.isArray(v);
+
+  var key;
+  function keySetter(k) {
+    key = Converter.toString(k);
+  }
+  if (valid) {
+    keySetter(k);
+  }
+
+  var value;
+  function valueSetter(v) {
+    if (T.isArray(v)) {
+      value = [];
+      for (var i = 0; i < v.length; ++i) {
+        value.push(Converter.toString(v[i]));
+      }
+    }
+  }
+  if (valid) {
+    valueSetter(v);
+  }
+
+  Object.defineProperties(this, {
+    key : {
+      enumerable : true,
+      set : keySetter,
+      get : function() {
+        return key;
+      }
+    },
+    value : {
+      enumerable : true,
+      set : valueSetter,
+      get : function() {
+        return value;
+      }
+    }
+  });
+}
+
+// class ApplicationControl ////////////////////////////////////////////////////
+
+tizen.ApplicationControl = function(o, u, m, c, d, mode) {
+  AV.validateConstructorCall(this, tizen.ApplicationControl);
+
+  var valid = (arguments.length >= 1);
+
+  var operation;
+  function operationSetter(o) {
+    operation = Converter.toString(o);
+  }
+  if (valid) {
+    operationSetter(o);
+  }
+
+  var uri;
+  function uriSetter(u) {
+    if (T.isNull(u)) {
+      uri = u;
+    } else {
+      uri = Converter.toString(u);
+    }
+  }
+  if (valid) {
+    uriSetter(T.isUndefined(u) ? null : u);
+  }
+
+  var mime;
+  function mimeSetter(m) {
+    if (T.isNull(m)) {
+      mime = m;
+    } else {
+      mime = Converter.toString(m);
+    }
+  }
+  if (valid) {
+    mimeSetter(T.isUndefined(m) ? null : m);
+  }
+
+  var category;
+  function categorySetter(c) {
+    if (T.isNull(c)) {
+      category = c;
+    } else {
+      category = Converter.toString(c);
+    }
+  }
+  if (valid) {
+    categorySetter(T.isUndefined(c) ? null : c);
+  }
+
+  var data;
+  function dataSetter(d) {
+    if (T.isArray(d)) {
+      for (var i = 0; i < d.length; ++i) {
+        if (!(d[i] instanceof tizen.ApplicationControlData)) {
+          return;
+        }
+      }
+      data = d;
+    }
+  }
+  if (valid) {
+    dataSetter(T.isNullOrUndefined(d) ? [] : d);
+  }
+
+  var launchMode;
+  function launchModeSetter(mode) {
+    if (ApplicationControlLaunchMode[mode]) {
+       launchMode = ApplicationControlLaunchMode[mode];
+    }
+  }
+  if (valid) {
+    if (T.isNullOrUndefined(mode) || !ApplicationControlLaunchMode[mode]) {
+      launchMode = ApplicationControlLaunchMode['SINGLE'];
+    } else {
+      launchModeSetter(mode);
+    }
+  }
+
+  Object.defineProperties(this, {
+    operation : {
+      enumerable : true,
+      set : operationSetter,
+      get : function() {
+        return operation;
+      }
+    },
+    uri : {
+      enumerable : true,
+      set : uriSetter,
+      get : function() {
+        return uri;
+      }
+    },
+    mime : {
+      enumerable : true,
+      set : mimeSetter,
+      get : function() {
+        return mime;
+      }
+    },
+    category : {
+      enumerable : true,
+      set : categorySetter,
+      get : function() {
+        return category;
+      }
+    },
+    data : {
+      enumerable : true,
+      set : dataSetter,
+      get : function() {
+        return data;
+      }
+    },
+    launchMode : {
+      enumerable : true,
+      set : launchModeSetter,
+      get : function() {
+        return launchMode;
+      }
+    }
+  });
+}
+
+// class RequestedApplicationControl ////////////////////////////////////////////////////
+
+function RequestedApplicationControl(data) {
+  Object.defineProperties(this, {
+    appControl : {
+      value: _createApplicationControl(data.appControl),
+      writable: false,
+      enumerable: true
+    },
+    callerAppId : {
+      value: data.callerAppId,
+      writable: false,
+      enumerable: true
+    }
+  });
+}
+
+RequestedApplicationControl.prototype.replyResult = function() {
+  var args = AV.validateMethod(arguments, [
+      {
+        name : 'data',
+        type : AV.Types.ARRAY,
+        values : tizen.ApplicationControlData,
+        optional: true,
+        nullable: true
+      }
+  ]);
+
+
+  var callArgs = {};
+
+  if (args.has.data) {
+    callArgs.data = args.data;
+  } else {
+    callArgs.data = [];
+  }
+
+  var result = native.callSync('RequestedApplicationControl_replyResult', callArgs);
+
+  if (native.isFailure(result)) {
+    throw native.getErrorObject(result);
+  }
+};
+
+RequestedApplicationControl.prototype.replyFailure = function() {
+  var result = native.callSync('RequestedApplicationControl_replyFailure', {});
+
+  if (native.isFailure(result)) {
+    throw native.getErrorObject(result);
+  }
+};
+
+// class ApplicationCertificate ////////////////////////////////////////////////////
+
+function ApplicationCertificate(data) {
+  Object.defineProperties(this, {
+    type : {
+      value : data.type,
+      writable : false,
+      enumerable : true
+    },
+    value : {
+      value : data.value,
+      writable : false,
+      enumerable : true
+    }
+  });
+}
+
+// class ApplicationMetaData ////////////////////////////////////////////////////
+function ApplicationMetaData(data) {
+  Object.defineProperties(this, {
+    key : {
+      value : data.key,
+      writable : false,
+      enumerable : true
+    },
+    value : {
+      value : data.value,
+      writable : false,
+      enumerable : true
+    }
+  });
+}
+
+// exports ////////////////////////////////////////////////////
+exports = new ApplicationManager();
diff --git a/webWidgetTCT_device/src/application/application_extension.cc b/webWidgetTCT_device/src/application/application_extension.cc
new file mode 100755 (executable)
index 0000000..1379e0c
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2015 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 "application/application_extension.h"
+
+#include <iostream>
+#include <sstream>
+
+#include "application/application_instance.h"
+#include "common/logger.h"
+
+namespace {
+const char* kApplication = "tizen.application";
+const char* kApplicationControl = "tizen.ApplicationControl";
+const char* kApplicationControlData = "tizen.ApplicationControlData";
+}
+
+// This will be generated from application_api.js
+extern const char kSource_application_api[];
+
+common::Extension* CreateExtension() {
+  LoggerD("Enter");
+  ApplicationExtension* e = new ApplicationExtension();
+
+  return e;
+}
+
+ApplicationExtension::ApplicationExtension() {
+  LoggerD("Enter");
+
+  SetExtensionName(kApplication);
+  SetJavaScriptAPI(kSource_application_api);
+
+  const char* entry_points[] = {
+      kApplicationControl,
+      kApplicationControlData,
+      NULL
+  };
+  SetExtraJSEntryPoints(entry_points);
+}
+
+ApplicationExtension::~ApplicationExtension() {
+  LoggerD("Enter");
+}
+
+common::Instance* ApplicationExtension::CreateInstance() {
+  LoggerD("Enter");
+  return new extension::application::ApplicationInstance();
+}
diff --git a/webWidgetTCT_device/src/application/application_extension.h b/webWidgetTCT_device/src/application/application_extension.h
new file mode 100755 (executable)
index 0000000..c0aa74b
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2015 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 SRC_APPLICATION_APPLICATION_EXTENSION_H_
+#define SRC_APPLICATION_APPLICATION_EXTENSION_H_
+
+#include <string>
+
+#include "common/extension.h"
+
+class ApplicationExtension : public common::Extension {
+ public:
+  ApplicationExtension();
+  virtual ~ApplicationExtension();
+
+  std::string app_id() const { return app_id_; }
+
+ private:
+  std::string app_id_;
+  // common::Extension implementation.
+  virtual common::Instance* CreateInstance();
+};
+
+#endif  // SRC_APPLICATION_APPLICATION_EXTENSION_H_
diff --git a/webWidgetTCT_device/src/application/application_instance.cc b/webWidgetTCT_device/src/application/application_instance.cc
new file mode 100755 (executable)
index 0000000..e35e335
--- /dev/null
@@ -0,0 +1,267 @@
+/*
+ * Copyright (c) 2015 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 "application/application_instance.h"
+
+#include "common/logger.h"
+#include "common/picojson.h"
+#include "common/platform_exception.h"
+#include "common/task-queue.h"
+#include "common/current_application.h"
+
+namespace extension {
+namespace application {
+
+using namespace common;
+
+ApplicationInstance::ApplicationInstance() :
+  manager_(*this) {
+  LoggerD("Entered");
+
+  app_id_ = CurrentApplication::GetInstance().GetApplicationId();
+  LoggerD("app_id: %s", app_id_.c_str());
+
+  if (app_id_.empty()) {
+    LoggerE("app_id_ is empty. Application instance will not be created.");
+    //return PlatformResult(ErrorCode::NOT_FOUND_ERR, "Cannot find caller.");
+  }
+
+  using std::placeholders::_1;
+  using std::placeholders::_2;
+
+#define REGISTER_SYNC(c, x) \
+        RegisterSyncHandler(c, std::bind(&ApplicationInstance::x, this, _1, _2));
+  //ApplicationManager
+  REGISTER_SYNC("ApplicationManager_getCurrentApplication", GetCurrentApplication);
+  REGISTER_SYNC("ApplicationManager_getAppContext", GetAppContext);
+  REGISTER_SYNC("ApplicationManager_getAppInfo", GetAppInfo);
+  REGISTER_SYNC("ApplicationManager_getAppCerts", GetAppCerts);
+  REGISTER_SYNC("ApplicationManager_getAppSharedURI", GetAppSharedURI);
+  REGISTER_SYNC("ApplicationManager_getAppMetaData", GetAppMetaData);
+  REGISTER_SYNC("ApplicationManager_addAppInfoEventListener", AddAppInfoEventListener);
+  REGISTER_SYNC("ApplicationManager_removeAppInfoEventListener", RemoveAppInfoEventListener);
+
+  //Application
+  REGISTER_SYNC("Application_getRequestedAppControl", GetRequestedAppControl);
+  REGISTER_SYNC("Application_broadcastEvent", BroadcastEvent);
+  REGISTER_SYNC("Application_broadcastTrustedEvent", BroadcastTrustedEvent);
+  REGISTER_SYNC("Application_addEventListener", AddEventListener);
+  REGISTER_SYNC("Application_removeEventListener", RemoveEventListener);
+
+  //RequestedApplicationControl
+  REGISTER_SYNC("RequestedApplicationControl_replyResult", ReplyResult);
+  REGISTER_SYNC("RequestedApplicationControl_replyFailure", ReplyFailure);
+
+  //ApplicationInformation
+  REGISTER_SYNC("ApplicationInformation_getSize", GetSize);
+#undef REGISTER_SYNC
+
+#define REGISTER_ASYNC(c, x) \
+        RegisterSyncHandler(c, std::bind(&ApplicationInstance::x, this, _1, _2));
+  //ApplicationManager
+  REGISTER_ASYNC("ApplicationManager_kill", Kill);
+  REGISTER_ASYNC("ApplicationManager_launch", Launch);
+  REGISTER_ASYNC("ApplicationManager_launchAppControl", LaunchAppControl);
+  REGISTER_ASYNC("ApplicationManager_findAppControl", FindAppControl);
+  REGISTER_ASYNC("ApplicationManager_getAppsContext", GetAppsContext);
+  REGISTER_ASYNC("ApplicationManager_getAppsInfo", GetAppsInfo);
+#undef REGISTER_ASYNC
+}
+
+ApplicationInstance::~ApplicationInstance() {
+  LoggerD("Entered");
+}
+
+void ApplicationInstance::GetCurrentApplication(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+
+  manager_.GetCurrentApplication(app_id_, &out);
+}
+
+void ApplicationInstance::GetAppContext(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+
+  manager_.GetAppContext(args, &out);
+}
+
+void ApplicationInstance::GetAppInfo(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+
+  std::string app_id = app_id_;
+  const auto& id = args.get("id");
+  if (id.is<std::string>()) {
+    app_id = id.get<std::string>();
+  }
+
+  manager_.GetAppInfo(app_id, &out);
+}
+
+void ApplicationInstance::GetAppCerts(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+
+  std::string app_id = app_id_;
+  const auto& id = args.get("id");
+  if (id.is<std::string>()) {
+    app_id = id.get<std::string>();
+  }
+
+  manager_.GetAppCerts(app_id, &out);
+}
+
+void ApplicationInstance::GetAppSharedURI(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+
+  std::string app_id = app_id_;
+  const auto& id = args.get("id");
+  if (id.is<std::string>()) {
+    app_id = id.get<std::string>();
+  }
+
+  manager_.GetAppSharedUri(app_id, &out);
+}
+
+void ApplicationInstance::GetAppMetaData(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+
+  std::string app_id = app_id_;
+  const auto& id = args.get("id");
+  if (id.is<std::string>()) {
+    app_id = id.get<std::string>();
+  }
+
+  manager_.GetAppMetaData(app_id, &out);
+}
+
+void ApplicationInstance::AddAppInfoEventListener(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+
+  manager_.StartAppInfoEventListener(&out);
+ }
+
+void ApplicationInstance::RemoveAppInfoEventListener(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+
+  manager_.StopAppInfoEventListener();
+  ReportSuccess(out);
+}
+
+void ApplicationInstance::GetRequestedAppControl(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+
+  current_application_.GetRequestedAppControl(args, &out);
+}
+
+void ApplicationInstance::ReplyResult(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+
+  current_application_.app_control().ReplyResult(args, &out);
+}
+
+void ApplicationInstance::ReplyFailure(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+
+  current_application_.app_control().ReplyFailure(&out);
+}
+
+void ApplicationInstance::GetSize(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+
+  manager_.GetApplicationInformationSize(args, &out);
+}
+
+void ApplicationInstance::Kill(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+
+  manager_.Kill(args);
+}
+
+void ApplicationInstance::Launch(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+
+  manager_.Launch(args);
+}
+
+void ApplicationInstance::LaunchAppControl(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+
+  manager_.LaunchAppControl(args);
+}
+
+void ApplicationInstance::FindAppControl(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+
+  manager_.FindAppControl(args);
+}
+
+void ApplicationInstance::GetAppsContext(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+
+  manager_.GetAppsContext(args);
+}
+
+void ApplicationInstance::GetAppsInfo(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+
+  manager_.GetAppsInfo(args);
+}
+
+void ApplicationInstance::BroadcastEvent(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+
+  manager_.BroadcastEventHelper(args, out, false);
+}
+
+void ApplicationInstance::BroadcastTrustedEvent(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+
+  manager_.BroadcastEventHelper(args, out, true);
+}
+
+void ApplicationInstance::AddEventListener(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+
+  const std::string& event_name = args.get("name").get<std::string>();
+
+  LOGGER(DEBUG) << "event_name: " << event_name;
+
+  JsonCallback cb = [this, args](picojson::value* event) -> void {
+   picojson::object& event_o = event->get<picojson::object>();
+   event_o["listenerId"] = args.get("listenerId");
+   LOGGER(DEBUG) << event->serialize().c_str();
+   Instance::PostMessage(this, event->serialize().c_str());
+   LOGGER(DEBUG) << event->serialize().c_str();
+  };
+
+  PlatformResult result = manager_.StartEventListener(event_name, cb);
+  if (result) {
+    ReportSuccess(out);
+  } else {
+    ReportError(result, &out);
+  }
+}
+
+void ApplicationInstance::RemoveEventListener(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+
+  const std::string& event_name = args.get("name").get<std::string>();
+
+  LOGGER(DEBUG) << "event_name: " << event_name;
+
+  manager_.StopEventListener(event_name);
+}
+
+}  // namespace application
+}  // namespace extension
diff --git a/webWidgetTCT_device/src/application/application_instance.h b/webWidgetTCT_device/src/application/application_instance.h
new file mode 100755 (executable)
index 0000000..cb99cbb
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2015 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 SRC_APPLICATION_APPLICATION_INSTANCE_H_
+#define SRC_APPLICATION_APPLICATION_INSTANCE_H_
+
+#include <string>
+
+#include "common/extension.h"
+#include "application/application_manager.h"
+#include "application/application.h"
+#include "application/requested_application_control.h"
+
+namespace extension {
+namespace application {
+
+class ApplicationInstance: public common::ParsedInstance {
+ public:
+  ApplicationInstance();
+  virtual ~ApplicationInstance();
+ private:
+  void GetCurrentApplication(const picojson::value& args, picojson::object& out);
+  void GetAppContext(const picojson::value& args, picojson::object& out);
+  void GetAppInfo(const picojson::value& args, picojson::object& out);
+  void GetAppCerts(const picojson::value& args, picojson::object& out);
+  void GetAppSharedURI(const picojson::value& args, picojson::object& out);
+  void GetAppMetaData(const picojson::value& args, picojson::object& out);
+  void AddAppInfoEventListener(const picojson::value& args, picojson::object& out);
+  void RemoveAppInfoEventListener(const picojson::value& args, picojson::object& out);
+  void GetRequestedAppControl(const picojson::value& args, picojson::object& out);
+  void ReplyResult(const picojson::value& args, picojson::object& out);
+  void ReplyFailure(const picojson::value& args, picojson::object& out);
+  void GetSize(const picojson::value& args, picojson::object& out);
+  void Kill(const picojson::value& args, picojson::object& out);
+  void Launch(const picojson::value& args, picojson::object& out);
+  void LaunchAppControl(const picojson::value& args, picojson::object& out);
+  void FindAppControl(const picojson::value& args, picojson::object& out);
+  void GetAppsContext(const picojson::value& args, picojson::object& out);
+  void GetAppsInfo(const picojson::value& args, picojson::object& out);
+  void BroadcastEvent(const picojson::value& args, picojson::object& out);
+  void BroadcastTrustedEvent(const picojson::value& args, picojson::object& out);
+  void AddEventListener(const picojson::value& args, picojson::object& out);
+  void RemoveEventListener(const picojson::value& args, picojson::object& out);
+
+  ApplicationManager manager_;
+  Application current_application_;
+  std::string app_id_;
+};
+
+}  // namespace application
+}  // namespace extension
+
+#endif  // SRC_APPLICATION_APPLICATION_INSTANCE_H_
diff --git a/webWidgetTCT_device/src/application/application_manager.cc b/webWidgetTCT_device/src/application/application_manager.cc
new file mode 100755 (executable)
index 0000000..1537783
--- /dev/null
@@ -0,0 +1,1570 @@
+/*
+ * Copyright (c) 2015 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 "application_manager.h"
+
+#include <type_traits>
+#include <unistd.h>
+
+#include <app_info.h>
+#include <app_manager.h>
+#include <app_manager_extension.h>
+#include <aul.h>
+#include <package_manager.h>
+#include <pkgmgr-info.h>
+#include <bundle.h>
+#include <bundle_internal.h>
+
+#include "application/application_instance.h"
+#include "application/application_utils.h"
+#include "common/current_application.h"
+#include "common/logger.h"
+#include "common/platform_result.h"
+#include "common/task-queue.h"
+#include "common/scope_exit.h"
+
+using namespace common;
+using namespace tools;
+
+namespace extension {
+namespace application {
+
+namespace {
+const std::string kTizenApisFileScheme = "file://";
+const std::string kTizenApisAppSlash = "/";
+const std::string kTizenApisAppShared = "shared";
+
+const char* kStartKey = "start";
+const char* kEndKey = "end";
+const char* kAppidKey = "appid";
+const char* kOkValue = "ok";
+const char* kInstallEvent = "install";
+const char* kUpdateEvent = "update";
+const char* kUninstallEvent = "uninstall";
+
+const std::string kAction = "action";
+const std::string kCallbackId = "callbackId";
+const std::string kOnInstalled = "oninstalled";
+const std::string kOnUpdated = "onupdated";
+const std::string kOnUninstalled = "onuninstalled";
+const std::string kData = "data";
+
+const std::map<std::string, std::string> event_map_ = {
+  {SYSTEM_EVENT_BATTERY_CHARGER_STATUS, EVENT_KEY_BATTERY_CHARGER_STATUS},
+  {SYSTEM_EVENT_BATTERY_LEVEL_STATUS, EVENT_KEY_BATTERY_LEVEL_STATUS},
+  {SYSTEM_EVENT_USB_STATUS, EVENT_KEY_USB_STATUS},
+  {SYSTEM_EVENT_EARJACK_STATUS, EVENT_KEY_EARJACK_STATUS},
+  {SYSTEM_EVENT_DISPLAY_STATE, EVENT_KEY_DISPLAY_STATE},
+  {SYSTEM_EVENT_LOW_MEMORY, EVENT_KEY_LOW_MEMORY},
+  {SYSTEM_EVENT_WIFI_STATE, EVENT_KEY_WIFI_STATE},
+  {SYSTEM_EVENT_BT_STATE, EVENT_KEY_BT_STATE},
+  {SYSTEM_EVENT_LOCATION_ENABLE_STATE, EVENT_KEY_LOCATION_ENABLE_STATE},
+  {SYSTEM_EVENT_GPS_ENABLE_STATE, EVENT_KEY_GPS_ENABLE_STATE},
+  {SYSTEM_EVENT_NPS_ENABLE_STATE, EVENT_KEY_NPS_ENABLE_STATE},
+  {SYSTEM_EVENT_INCOMMING_MSG, EVENT_KEY_MSG_TYPE},
+  {SYSTEM_EVENT_TIME_ZONE, EVENT_KEY_TIME_ZONE},
+  {SYSTEM_EVENT_HOUR_FORMAT, EVENT_KEY_HOUR_FORMAT},
+  {SYSTEM_EVENT_LANGUAGE_SET, EVENT_KEY_LANGUAGE_SET},
+  {SYSTEM_EVENT_REGION_FORMAT, EVENT_KEY_REGION_FORMAT},
+  {SYSTEM_EVENT_SILENT_MODE, EVENT_KEY_SILENT_MODE},
+  {SYSTEM_EVENT_VIBRATION_STATE, EVENT_KEY_VIBRATION_STATE},
+  {SYSTEM_EVENT_SCREEN_AUTOROTATE_STATE, EVENT_KEY_SCREEN_AUTOROTATE_STATE},
+  {SYSTEM_EVENT_MOBILE_DATA_STATE, EVENT_KEY_MOBILE_DATA_STATE},
+  {SYSTEM_EVENT_DATA_ROAMING_STATE, EVENT_KEY_DATA_ROAMING_STATE},
+  {SYSTEM_EVENT_FONT_SET, EVENT_KEY_FONT_SET}
+};
+}
+
+ApplicationManager::ApplicationManager(ApplicationInstance& instance) :
+  pkgmgr_client_handle_(nullptr),
+  pkgmgrinfo_client_handle_(nullptr),
+  instance_(instance) {
+    LoggerD("Enter");
+}
+
+ApplicationManager::~ApplicationManager() {
+  LoggerD("Enter");
+  StopAppInfoEventListener();
+}
+
+void ApplicationManager::GetCurrentApplication(const std::string& app_id,
+                                                         picojson::object* out) {
+  LoggerD("Entered");
+
+  // obtain handle to application info
+  pkgmgrinfo_appinfo_h handle;
+  int ret = pkgmgrinfo_appinfo_get_appinfo(app_id.c_str(), &handle);
+  if (PMINFO_R_OK != ret) {
+    LoggerE("Failed to get app info: %d (%s)", ret, get_error_message(ret));
+    ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get app info."), out);
+    return;
+  }
+
+  picojson::value app_info = picojson::value(picojson::object());
+  picojson::object& app_info_obj = app_info.get<picojson::object>();
+
+  ApplicationUtils::CreateApplicationInformation(handle, &app_info_obj);
+  pkgmgrinfo_appinfo_destroy_appinfo(handle);
+
+  picojson::value result = picojson::value(picojson::object());
+  picojson::object& result_obj = result.get<picojson::object>();
+
+  result_obj.insert(std::make_pair(
+      "contextId", picojson::value(std::to_string(CurrentApplication::GetInstance().GetProcessId()))));
+  result_obj.insert(std::make_pair("appInfo", app_info));
+
+  ReportSuccess(result, *out);
+}
+
+class TerminateHandler {
+ public:
+  TerminateHandler(int callback_id, ApplicationInstance* app_instance) :
+    callback_handle_(callback_id),
+    pid_(-1),
+    timeout_id_(0),
+    app_instance_(app_instance) {
+  }
+
+  void set_pid(pid_t pid) {
+    pid_ = pid;
+  }
+
+  pid_t pid() const {
+    return pid_;
+  }
+
+  void Invoke(const std::shared_ptr<picojson::value>& response) {
+    LoggerD("Entered");
+
+    if (timeout_id_ > 0) {
+      // cancel terminate callback
+      g_source_remove(timeout_id_);
+      timeout_id_ = 0;
+    }
+
+    ApplicationInstance* app_instance = this->app_instance_;
+    int callback_id = this->callback_handle_;
+    TaskQueue::GetInstance().Async<picojson::value>([callback_id, app_instance](
+        const std::shared_ptr<picojson::value>& response) {
+      picojson::object& obj = response->get<picojson::object>();
+      obj.insert(std::make_pair(kCallbackId, picojson::value(static_cast<double>(callback_id))));
+      Instance::PostMessage(app_instance, response->serialize().c_str());
+    }, response);
+  }
+
+  void LaunchCheckTerminate() {
+    LoggerD("Entered");
+    timeout_id_ = g_timeout_add(3000, CheckTerminate, this);
+    LoggerD("END");
+  }
+
+ private:
+  static gboolean CheckTerminate(gpointer user_data) {
+    LoggerD("Entered");
+    TerminateHandler* that = static_cast<TerminateHandler*>(user_data);
+    LoggerD("PID: %d", that->pid_);
+
+    // we're canceling the callback by returning false, no need for Invoke() to do that again
+    that->timeout_id_ = 0;
+
+    char* app_id = nullptr;
+    std::shared_ptr<picojson::value> response{new picojson::value(picojson::object())};
+
+    LoggerD("checking if application is still alive");
+    int ret = app_manager_get_app_id(that->pid_, &app_id);
+    if (ret == APP_MANAGER_ERROR_NONE) {
+        LoggerD("application is alive - failure");
+        free(app_id);
+        // context is still alive, report error
+        ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to kill application."),
+                    &response->get<picojson::object>());
+    } else {
+        LoggerD("application is dead - success: %d (%s)", ret, get_error_message(ret));
+        ReportSuccess(response->get<picojson::object>());
+    }
+
+    that->Invoke(response);
+    delete that;
+
+    return false;
+  }
+
+  int callback_handle_;
+  pid_t pid_;
+  guint timeout_id_;
+  ApplicationInstance* app_instance_;
+};
+
+#define CHECK_RESULT(result, response, handler) \
+  if (result.IsError()) { \
+    ReportError(result, &response->get<picojson::object>()); \
+    handler->Invoke(response); \
+    delete handler; \
+    return; \
+  }
+
+void ApplicationManager::AsyncResponse(PlatformResult& result,
+                                       std::shared_ptr<picojson::value>* response) {
+
+  LoggerD("Enter");
+  ReportError(result, &(*response)->get<picojson::object>());
+
+  TaskQueue::GetInstance().Async<picojson::value>([this](
+      const std::shared_ptr<picojson::value>& response) {
+        Instance::PostMessage(&this->instance_, response->serialize().c_str());
+      }, *response);
+}
+
+void ApplicationManager::Kill(const picojson::value& args) {
+  LoggerD("Entered");
+
+  PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
+
+  int callback_id = -1;
+  const auto& callback = args.get(kCallbackId);
+  if (callback.is<double>()) {
+    callback_id = static_cast<int>(callback.get<double>());
+  }
+
+  const auto& context = args.get("contextId");
+  if (!context.is<std::string>()) {
+    LoggerE("Invalid parameter passed.");
+    result = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed.");
+  }
+
+  const std::string& context_id = context.get<std::string>();
+
+  if (context_id.empty() && result.IsSuccess()) {
+    LoggerE("Context ID is empty.");
+    result = PlatformResult(ErrorCode::NOT_FOUND_ERR, "Context ID is empty.");
+  }
+
+  std::shared_ptr<picojson::value> response(new picojson::value(picojson::object()));
+  picojson::object& obj = response->get<picojson::object>();
+  obj.insert(std::make_pair(kCallbackId, picojson::value(static_cast<double>(callback_id))));
+
+  if (result.IsError()) {
+    LoggerE("Failed args.get");
+    AsyncResponse(result, &response);
+    return;
+  }
+
+  auto kill = [this, callback_id, context_id]() -> void {
+    LoggerD("Entered Kill async");
+
+    std::shared_ptr<picojson::value> response =
+        std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+
+    TerminateHandler* handler = new TerminateHandler(callback_id, &this->instance_);
+    PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
+
+    pid_t pid = -1;
+    try {
+      pid = std::stoi(context_id);
+    } catch (...) {
+      LoggerE("Failed to convert string to int");
+      result = PlatformResult(ErrorCode::NOT_FOUND_ERR, "Failed to convert string to int.");
+      CHECK_RESULT(result, response, handler)
+    }
+
+    if (pid <= 0) {
+      LoggerE("Context ID cannot be negative value");
+      result = PlatformResult(ErrorCode::NOT_FOUND_ERR, "Context ID cannot be negative value.");
+      CHECK_RESULT(result, response, handler)
+    }
+
+    // if kill request comes for current context, throw InvalidValuesException
+    if (CurrentApplication::GetInstance().GetProcessId() == pid) {
+      LoggerE("Cannot kill current application.");
+      result = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Cannot kill current application.");
+      CHECK_RESULT(result, response, handler)
+    }
+
+    LoggerD("Kill async, pid: %d", pid);
+
+    char* app_id = nullptr;
+    int ret = app_manager_get_app_id(pid, &app_id);
+    // automatically release the memory
+    std::unique_ptr<char, void(*)(void*)> app_id_ptr(app_id, &std::free);
+
+    if (APP_MANAGER_ERROR_NONE != ret) {
+      LoggerE("Failed to get application ID, error: %d (%s)", ret,
+              get_error_message(ret));
+      result = PlatformResult(ErrorCode::NOT_FOUND_ERR, "Failed to get application ID.");
+      CHECK_RESULT(result, response, handler)
+    }
+
+    LoggerD("Kill async, app ID: %s", app_id);
+
+    // acquire application context
+    app_context_h app_context = nullptr;
+
+    ret = app_manager_get_app_context(app_id, &app_context);
+    std::unique_ptr<std::remove_pointer<app_context_h>::type, int(*)(app_context_h)>
+    app_context_ptr(app_context, &app_context_destroy); // automatically release the memory
+
+    if (APP_MANAGER_ERROR_NONE != ret) {
+      LoggerE("Failed to get application context handle: %d (%s)", ret,
+              get_error_message(ret));
+      result = PlatformResult(ErrorCode::NOT_FOUND_ERR, "Failed to get application ID.");
+      CHECK_RESULT(result, response, handler)
+    }
+
+    auto terminate_callback = [](app_context_h app_context,
+        app_context_event_e event,
+        void* user_data) {
+      LoggerD("terminate_callback: %d", event);
+
+      if (APP_CONTEXT_EVENT_TERMINATED != event) {
+        LoggerD("ignoring event");
+        return;
+      }
+
+      int pid = 0;
+      int ret = app_context_get_pid(app_context, &pid);
+
+      if (APP_MANAGER_ERROR_NONE != ret) {
+        LoggerE("Failed to get pid of terminated app: %d (%s)", ret,
+                get_error_message(ret));
+        return;
+      }
+
+      TerminateHandler* handler = static_cast<TerminateHandler*>(user_data);
+
+      LoggerD("Expected PID: %d, got: %d", handler->pid(), pid);
+
+      if (handler->pid() == pid) {
+        std::shared_ptr<picojson::value> response =
+            std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+        ReportSuccess(response->get<picojson::object>());
+        handler->Invoke(response);
+        delete handler;
+      }
+    };
+
+    LoggerD("Kill async, setting callback");
+    handler->set_pid(pid);
+    ret = app_manager_set_app_context_event_cb(terminate_callback, handler);
+
+    if (APP_MANAGER_ERROR_NONE != ret) {
+      LoggerE("Error while registering app context event: %d (%s)", ret,
+              get_error_message(ret));
+      result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to register termination callback.");
+      CHECK_RESULT(result, response, handler)
+    }
+
+    // due to platform issue, sometimes termination event is not reported to callback
+    // registered with app_manager_set_app_context_event_cb()
+    // this is a workaround, it should be removed when issue is solved
+    handler->LaunchCheckTerminate();
+
+    LoggerD("Kill async, KILL!!!!!!!!!");
+
+    // terminate application
+    ret = app_manager_terminate_app(app_context);
+
+    if (APP_MANAGER_ERROR_NONE != ret) {
+      LoggerE("Failed to terminate application: %d (%s)", ret,
+              get_error_message(ret));
+      result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to terminate application.");
+      CHECK_RESULT(result, response, handler)
+    }
+
+    LoggerD("Kill async, end, waiting for notification");
+  };
+
+  TaskQueue::GetInstance().Queue(kill);
+}
+
+void ApplicationManager::Launch(const picojson::value& args) {
+  LoggerD("Entered");
+
+  int callback_id = -1;
+  const auto& callback = args.get(kCallbackId);
+  if (callback.is<double>()) {
+    callback_id = static_cast<int>(callback.get<double>());
+  }
+
+  std::shared_ptr<picojson::value> response(new picojson::value(picojson::object()));
+  picojson::object& obj = response->get<picojson::object>();
+  obj.insert(std::make_pair(kCallbackId, picojson::value(static_cast<double>(callback_id))));
+
+  const auto& app_id = args.get("id");
+  if (!app_id.is<std::string>()) {
+    LoggerE("Invalid parameter passed.");
+    PlatformResult ret = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed.");
+    AsyncResponse(ret, &response);
+    return;
+  }
+  const std::string& id = app_id.get<std::string>();
+
+  auto launch = [id](const std::shared_ptr<picojson::value>& response) -> void {
+    PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
+    const char* app_id = id.c_str();
+    const int retry_count = 3;
+
+    int retry = 0;
+    int ret = 0;
+
+    while (retry < retry_count) {
+      ret = aul_open_app(app_id);
+
+      if (ret >= 0) {
+        break;
+      }
+
+      // delay 300ms for each retry
+      struct timespec sleep_time = { 0, 300L * 1000L * 1000L };
+      nanosleep(&sleep_time, nullptr);
+      ++retry;
+
+      LoggerD("Retry launch request: %d", retry);
+    }
+
+    if (ret < 0) {
+      result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error has occurred.");
+
+      LoggerD("Aul open return: %d (%s)", ret, get_error_message(ret));
+      switch (ret) {
+        case AUL_R_EINVAL:
+        case AUL_R_ERROR:
+        case AUL_R_ENOAPP:
+          LoggerE("aul_open_app returns Not Found error");
+          result = PlatformResult(ErrorCode::NOT_FOUND_ERR, "Launchpad returns not found error.");
+          break;
+
+        case AUL_R_ECOMM:
+          LoggerE("aul_open_app returns internal IPC error");
+          result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Internal IPC error has occurred.");
+          break;
+      }
+
+      ReportError(result, &response->get<picojson::object>());
+    } else {
+      LoggerD("Launch request success");
+      ReportSuccess(response->get<picojson::object>());
+    }
+  };
+
+  auto launch_response = [this](const std::shared_ptr<picojson::value>& response) -> void {
+    Instance::PostMessage(&this->instance_, response->serialize().c_str());
+  };
+
+  TaskQueue::GetInstance().Queue<picojson::value>(launch, launch_response, response);
+}
+
+void ApplicationManager::LaunchAppControl(const picojson::value& args) {
+  LoggerD("Entered");
+
+  int callback_id = -1;
+  const auto& callback = args.get(kCallbackId);
+  if (callback.is<double>()) {
+    callback_id = static_cast<int>(callback.get<double>());
+  }
+
+  std::shared_ptr<picojson::value> response(new picojson::value(picojson::object()));
+  picojson::object& response_obj = response->get<picojson::object>();
+  response_obj.insert(
+      std::make_pair(kCallbackId, picojson::value(static_cast<double>(callback_id))));
+
+  PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
+  const auto& control = args.get("appControl");
+  if (!control.is<picojson::object>()) {
+    LoggerE("Invalid parameter passed.");
+    result = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed.");
+    AsyncResponse(result, &response);
+    return;
+  }
+  const picojson::object& app_control_obj = control.get<picojson::object>();
+
+  std::string launch_mode_str;
+  const auto& launch_mode = control.get("launchMode");
+  if (launch_mode.is<std::string>()) {
+    launch_mode_str = launch_mode.get<std::string>();
+  }
+
+  app_control_h app_control = nullptr;
+  result = ApplicationUtils::ApplicationControlToService(app_control_obj, &app_control);
+  std::shared_ptr<std::remove_pointer<app_control_h>::type>
+  app_control_ptr(app_control, &app_control_destroy); // automatically release the memory
+
+  if (result.IsError()) {
+    LoggerE("Application control to service failed.");
+    AsyncResponse(result, &response);
+    return;
+  }
+
+  std::string app_id;
+  const auto& id = args.get("id");
+  if (id.is<std::string>()) {
+    app_id = id.get<std::string>();
+  }
+
+  std::string reply_callback;
+  const auto& reply = args.get("replyCallback");
+  if (reply.is<std::string>()) {
+    reply_callback = reply.get<std::string>();
+  }
+
+  auto launch = [this, app_control_ptr, app_id, launch_mode_str, reply_callback](
+      const std::shared_ptr<picojson::value>& response) -> void {
+    LoggerD("Entered");
+
+    if (!app_id.empty()) {
+      LoggerD("app_id: %s", app_id.c_str());
+
+      int ret = app_control_set_app_id(app_control_ptr.get(), app_id.c_str());
+
+      if (APP_CONTROL_ERROR_NONE != ret) {
+        LoggerE("Failed to set app id: %d (%s)", ret, get_error_message(ret));
+        ReportError(PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed."),
+                    &response->get<picojson::object>());
+        return;
+      }
+    }
+
+    if (!launch_mode_str.empty()) {
+      app_control_launch_mode_e launch_mode;
+
+      if ("SINGLE" == launch_mode_str) {
+        launch_mode = APP_CONTROL_LAUNCH_MODE_SINGLE;
+      } else if ("GROUP" == launch_mode_str) {
+        launch_mode = APP_CONTROL_LAUNCH_MODE_GROUP;
+      } else {
+        LoggerE("Invalid parameter passed.");
+        ReportError(PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed."),
+                    &response->get<picojson::object>());
+        return;
+      }
+
+      int ret = app_control_set_launch_mode(app_control_ptr.get(), launch_mode);
+      if (APP_CONTROL_ERROR_NONE != ret) {
+        LoggerE("Setting launch mode failed: %d (%s)", ret,
+                get_error_message(ret));
+        ReportError(PlatformResult(ErrorCode::NOT_FOUND_ERR, "Setting launch mode failed."),
+                    &response->get<picojson::object>());
+        return;
+      }
+    }
+
+    app_control_reply_cb callback = nullptr;
+    struct ReplayCallbackData {
+      ApplicationInstance* app_instance;
+      std::string reply_callback;
+    };
+
+    ReplayCallbackData* user_data = nullptr;
+
+    if (!reply_callback.empty()) {
+      user_data = new ReplayCallbackData();
+      user_data->app_instance = &this->instance_;
+      user_data->reply_callback = reply_callback;
+
+      callback = [](app_control_h request,
+          app_control_h reply, app_control_result_e result, void* user_data) {
+        LoggerD("send_launch_request callback");
+
+        picojson::value return_value = picojson::value(picojson::object());
+        picojson::object& return_value_obj = return_value.get<picojson::object>();
+        ReplayCallbackData* reply_callback = static_cast<ReplayCallbackData*>(user_data);
+
+        if (APP_CONTROL_RESULT_SUCCEEDED == result) {
+          const std::string data = "data";
+          return_value_obj.insert(std::make_pair(data, picojson::value(picojson::array())));
+          if (!ApplicationUtils::ServiceToApplicationControlDataArray(
+              reply, &return_value_obj.find(data)->second.get<picojson::array>())) {
+            return_value_obj.erase(data);
+          }
+          ReportSuccess(return_value_obj);
+        } else {
+          ReportError(return_value_obj);
+        }
+
+        return_value_obj.insert(
+            std::make_pair("listenerId", picojson::value(reply_callback->reply_callback)));
+        Instance::PostMessage(reply_callback->app_instance, return_value.serialize().c_str());
+        delete reply_callback;
+      };
+    }
+
+    const int retry_count = 3;
+
+    int retry = 0;
+    int ret = 0;
+
+    while (retry < retry_count) {
+      ret = app_control_send_launch_request(app_control_ptr.get(), callback, user_data);
+
+      if (APP_CONTROL_ERROR_NONE == ret) {
+        break;
+      }
+
+      // delay 300ms for each retry
+      struct timespec sleep_time = { 0, 300L * 1000L * 1000L };
+      nanosleep(&sleep_time, nullptr);
+      ++retry;
+
+      LoggerD("Retry launch request: %d", retry);
+    }
+
+    if (APP_CONTROL_ERROR_NONE != ret) {
+      delete user_data;
+
+      switch (ret) {
+        case APP_CONTROL_ERROR_INVALID_PARAMETER:
+          LoggerE("app_control_send_launch_request returns APP_CONTROL_ERROR_INVALID_PARAMETER");
+          ReportError(PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter returned."),
+                      &response->get<picojson::object>());
+          return;
+        case APP_CONTROL_ERROR_OUT_OF_MEMORY:
+          LoggerE("app_control_send_launch_request returns APP_CONTROL_ERROR_OUT_OF_MEMORY");
+          ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Out of memory."),
+                      &response->get<picojson::object>());
+          return;
+        case APP_CONTROL_ERROR_LAUNCH_REJECTED:
+        case APP_CONTROL_ERROR_APP_NOT_FOUND:
+          LoggerE("app_control_send_launch_request returns APP_CONTROL_ERROR_APP_NOT_FOUND");
+          ReportError(PlatformResult(ErrorCode::NOT_FOUND_ERR, "No matched application found."),
+                      &response->get<picojson::object>());
+          return;
+        default:
+          LoggerE("app_control_send_launch_request returns: %d (%s)", ret,
+                  get_error_message(ret));
+          ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error."),
+                      &response->get<picojson::object>());
+          return;
+      }
+    }
+
+    ReportSuccess(response->get<picojson::object>());
+  };
+
+  auto launch_response = [this](const std::shared_ptr<picojson::value>& response) -> void {
+    Instance::PostMessage(&this->instance_, response->serialize().c_str());
+  };
+
+  TaskQueue::GetInstance().Queue<picojson::value>(launch, launch_response, response);
+}
+
+void ApplicationManager::FindAppControl(const picojson::value& args) {
+  LoggerD("Entered");
+
+  int callback_id = -1;
+  const auto& callback = args.get(kCallbackId);
+  if (callback.is<double>()) {
+    callback_id = static_cast<int>(callback.get<double>());
+  }
+
+  std::shared_ptr<picojson::value> response(new picojson::value(picojson::object()));
+  picojson::object& response_obj = response->get<picojson::object>();
+  response_obj.insert(
+      std::make_pair(kCallbackId, picojson::value(static_cast<double>(callback_id))));
+
+  PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
+  const auto& control = args.get("appControl");
+  if (!control.is<picojson::object>()) {
+    LoggerE("Invalid parameter passed.");
+    result = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed.");
+    AsyncResponse(result, &response);
+    return;
+  }
+
+  const picojson::object& app_control_obj = control.get<picojson::object>();
+
+  app_control_h app_control = nullptr;
+  result = ApplicationUtils::ApplicationControlToService(app_control_obj, &app_control);
+  std::shared_ptr<std::remove_pointer<app_control_h>::type>
+  app_control_ptr(app_control, &app_control_destroy); // automatically release the memory
+
+  if (result.IsError()) {
+    LoggerE("Application control to service failed.");
+    AsyncResponse(result, &response);
+    return;
+  }
+
+  auto find = [app_control_ptr](const std::shared_ptr<picojson::value>& response) -> void {
+    auto app_control_matched = [](app_control_h app_control, const char* appid, void* user_data) -> bool {
+      if (nullptr == appid) {
+        LoggerD("appid is NULL");
+        return false;
+      }
+
+      pkgmgrinfo_appinfo_h handle;
+      int ret = pkgmgrinfo_appinfo_get_appinfo(appid, &handle);
+      if (PMINFO_R_OK != ret) {
+        LoggerE("Failed to get appInfo: %d (%s)", ret, get_error_message(ret));
+      } else {
+        picojson::array* array = static_cast<picojson::array*>(user_data);
+        array->push_back(picojson::value(picojson::object()));
+
+        ApplicationUtils::CreateApplicationInformation(handle, &array->back().get<picojson::object>());
+        pkgmgrinfo_appinfo_destroy_appinfo(handle);
+      }
+
+      return true;
+    };
+
+    picojson::object& response_obj = response->get<picojson::object>();
+    auto it_result = response_obj.find("result");
+    picojson::object& result_obj = it_result->second.get<picojson::object>();
+    auto array = result_obj.insert(
+        std::make_pair("informationArray", picojson::value(picojson::array())));
+
+    int ret = app_control_foreach_app_matched(
+        app_control_ptr.get(), app_control_matched, &array.first->second.get<picojson::array>());
+
+    if (APP_CONTROL_ERROR_NONE != ret) {
+      LoggerE("app_control_foreach_app_matched error: %d (%s)", ret,
+              get_error_message(ret));
+
+      ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR,"Unknown error"), &response_obj);
+      // remove copied ApplicationControl from result
+      response_obj.erase(it_result);
+    } else {
+      ReportSuccess(response_obj);
+    }
+  };
+
+  auto find_response = [this](const std::shared_ptr<picojson::value>& response) -> void {
+    Instance::PostMessage(&this->instance_, response->serialize().c_str());
+  };
+
+  // prepare result object, we need to do that here, as input parameter is passed to result callback
+  auto ret = response_obj.insert(std::make_pair("result", picojson::value(picojson::object())));
+  // reinsert application control
+  ret.first->second.get<picojson::object>().insert(std::make_pair("appControl", args.get("appControl")));
+
+  TaskQueue::GetInstance().Queue<picojson::value>(find, find_response, response);
+}
+
+void ApplicationManager::GetAppsContext(const picojson::value& args) {
+  LoggerD("Entered");
+
+  int callback_id = -1;
+  const auto& callback = args.get(kCallbackId);
+  if (callback.is<double>()) {
+    callback_id = static_cast<int>(callback.get<double>());
+  }
+
+  auto get_apps_context = [](const std::shared_ptr<picojson::value>& response) -> void {
+    picojson::object& response_obj = response->get<picojson::object>();
+    picojson::value result = picojson::value(picojson::object());
+    picojson::object& result_obj = result.get<picojson::object>();
+    picojson::array& array =
+        result_obj.insert(std::make_pair("contexts", picojson::value(
+            picojson::array()))).first->second.get<picojson::array>();
+
+    auto app_context_cb = [](app_context_h app_context, void* user_data) -> bool {
+      if (nullptr == user_data) {
+        return false;
+      }
+
+      picojson::array* array = static_cast<picojson::array*>(user_data);
+      array->push_back(picojson::value(picojson::object()));
+
+      if (!ApplicationUtils::CreateApplicationContext(
+          app_context, &array->back().get<picojson::object>())) {
+        array->pop_back();
+        return false;
+      }
+
+      return true;
+    };
+
+    int ret = app_manager_foreach_app_context(app_context_cb, &array);
+
+    if (APP_MANAGER_ERROR_NONE != ret) {
+      LoggerE("app_manager_foreach_app_context error: %d (%s)", ret, get_error_message(ret));
+      ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error."), &response_obj);
+    } else {
+      ReportSuccess(result, response_obj);
+    }
+  };
+
+  auto get_apps_context_response = [this, callback_id](
+      const std::shared_ptr<picojson::value>& response) -> void {
+    picojson::object& obj = response->get<picojson::object>();
+    obj.insert(std::make_pair(kCallbackId, picojson::value(static_cast<double>(callback_id))));
+    Instance::PostMessage(&this->instance_, response->serialize().c_str());
+  };
+
+  auto data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+
+  TaskQueue::GetInstance().Queue<picojson::value>(
+      get_apps_context,
+      get_apps_context_response,
+      data);
+}
+
+void ApplicationManager::GetAppContext(const picojson::value& args, picojson::object* out) {
+  LoggerD("Entered");
+  pid_t pid = 0;
+
+  const auto& context_id = args.get("contextId");
+  if (context_id.is<std::string>()) {
+    try {
+      pid = std::stoi(context_id.get<std::string>());
+    } catch(...) {
+      LoggerE("Failed to convert context id.");
+      ReportError(PlatformResult(ErrorCode::NOT_FOUND_ERR, "Failed to convert context id."), out);
+      return;
+    }
+  } else {
+    pid = CurrentApplication::GetInstance().GetProcessId();
+  }
+
+  char* app_id = nullptr;
+
+  int ret = app_manager_get_app_id(pid, &app_id);
+  // automatically release the memory
+  std::unique_ptr<char, void(*)(void*)> app_id_ptr(app_id, &std::free);
+
+  if (APP_MANAGER_ERROR_NONE != ret || nullptr == app_id) {
+    switch(ret) {
+      case APP_MANAGER_ERROR_NO_SUCH_APP:
+        LoggerE("app_manager_get_app_id returned: APP_MANAGER_ERROR_NO_SUCH_APP");
+        ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "No such application exist."), out);
+        return;
+
+      case APP_MANAGER_ERROR_INVALID_PARAMETER:
+        LoggerE("app_manager_get_app_id returned: APP_MANAGER_ERROR_INVALID_PARAMETER");
+        ReportError(PlatformResult(ErrorCode::NOT_FOUND_ERR, "Application not found."), out);
+        return;
+
+      default:
+        LoggerE("app_manager_get_app_id returned: %d (%s)", ret, get_error_message(ret));
+        ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error."), out);
+        return;
+    }
+  }
+
+  picojson::value result = picojson::value(picojson::object());
+  ApplicationUtils::CreateApplicationContext(pid, app_id, &result.get<picojson::object>());
+
+  ReportSuccess(result, *out);
+}
+
+void ApplicationManager::GetAppsInfo(const picojson::value& args) {
+  LoggerD("Entered");
+
+  int callback_id = -1;
+  const auto& callback = args.get(kCallbackId);
+  if (callback.is<double>()) {
+    callback_id = static_cast<int>(callback.get<double>());
+  }
+
+  auto get_apps_info = [](const std::shared_ptr<picojson::value>& response) -> void {
+    picojson::object& response_obj = response->get<picojson::object>();
+    picojson::value result = picojson::value(picojson::object());
+    picojson::object& result_obj = result.get<picojson::object>();
+    picojson::array& array =
+        result_obj.insert(std::make_pair("informationArray", picojson::value(
+            picojson::array()))).first->second.get<picojson::array>();
+
+    auto app_info_cb = [](pkgmgrinfo_appinfo_h handle, void* user_data) -> int {
+      if (nullptr == user_data) {
+        return -1;
+      }
+
+      picojson::array* array = static_cast<picojson::array*>(user_data);
+      array->push_back(picojson::value(picojson::object()));
+
+      ApplicationUtils::CreateApplicationInformation(handle, &array->back().get<picojson::object>());
+
+      return 0;
+    };
+
+    int ret = pkgmgrinfo_appinfo_get_installed_list(app_info_cb, &array);
+
+    if (APP_MANAGER_ERROR_NONE != ret) {
+      LoggerE("pkgmgrinfo_appinfo_get_installed_list error: %d (%s)", ret, get_error_message(ret));
+      ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error."), &response_obj);
+    } else {
+      ReportSuccess(result, response_obj);
+    }
+  };
+
+  auto get_apps_info_response = [this, callback_id](
+      const std::shared_ptr<picojson::value>& response) -> void {
+    picojson::object& obj = response->get<picojson::object>();
+    obj.insert(std::make_pair(kCallbackId, picojson::value(static_cast<double>(callback_id))));
+    Instance::PostMessage(&this->instance_, response->serialize().c_str());
+  };
+
+  auto data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+
+  TaskQueue::GetInstance().Queue<picojson::value>(
+      get_apps_info,
+      get_apps_info_response,
+      data);
+}
+
+void ApplicationManager::GetAppInfo(const std::string& app_id, picojson::object* out) {
+  LoggerD("Entered");
+
+  pkgmgrinfo_appinfo_h handle = nullptr;
+
+  int ret = pkgmgrinfo_appinfo_get_appinfo(app_id.c_str(), &handle);
+  if (PMINFO_R_OK != ret) {
+    LoggerE("Failed to get app info: %d (%s)", ret, get_error_message(ret));
+    ReportError(PlatformResult(ErrorCode::NOT_FOUND_ERR, "Failed to get app info."), out);
+    return;
+  }
+
+  picojson::value result = picojson::value(picojson::object());
+  ApplicationUtils::CreateApplicationInformation(handle, &result.get<picojson::object>());
+  pkgmgrinfo_appinfo_destroy_appinfo(handle);
+
+  ReportSuccess(result, *out);
+}
+
+char* ApplicationManager::GetPackageId(const std::string& app_id) {
+  LoggerD("Entered");
+  app_info_h handle;
+  char* pkg_id = nullptr;
+
+  int ret = app_manager_get_app_info(app_id.c_str(), &handle);
+  if (APP_MANAGER_ERROR_NONE != ret) {
+    LoggerE("Failed to get app info: %d (%s)", ret, get_error_message(ret));
+    return nullptr;
+  }
+
+  ret = app_info_get_package(handle, &pkg_id);
+  if (APP_MANAGER_ERROR_NONE != ret) {
+    LoggerE("Failed to get package id: %d (%s)", ret, get_error_message(ret));
+    pkg_id = nullptr;
+  }
+
+  ret = app_info_destroy(handle);
+  if (APP_MANAGER_ERROR_NONE != ret) {
+    LoggerE("Failed to destroy app info: %d (%s)", ret, get_error_message(ret));
+  }
+
+  return pkg_id;
+}
+
+void ApplicationManager::GetAppCerts(const std::string& app_id, picojson::object* out) {
+  LoggerD("Entered");
+
+  char* package_id = nullptr;
+
+  package_id = GetPackageId(app_id);
+  // automatically release the memory
+  std::unique_ptr<char, void(*)(void*)> package_id_ptr(package_id, &std::free);
+
+  if (!package_id) {
+    LoggerE("Failed to get package.");
+    ReportError(PlatformResult(ErrorCode::NOT_FOUND_ERR, "Failed to get package."), out);
+    return;
+  }
+
+  package_info_h pkg_info = nullptr;
+  int ret = package_info_create(package_id, &pkg_info);
+
+  std::unique_ptr<std::remove_pointer<package_info_h>::type, int(*)(package_info_h)>
+  pkg_info_ptr(pkg_info, &package_info_destroy); // automatically release the memory
+
+  if (PACKAGE_MANAGER_ERROR_NONE != ret) {
+    LoggerE("Failed to get package info: %d (%s)", ret, get_error_message(ret));
+    ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get package info."), out);
+    return;
+  }
+
+  auto cert_info_cb = [](package_info_h handle, package_cert_type_e cert_type,
+      const char* cert_value, void* user_data) -> bool {
+    const char* cert_name = nullptr;
+
+    switch(cert_type) {
+      case PACKAGE_INFO_AUTHOR_ROOT_CERT:
+        cert_name = "AUTHOR_ROOT";
+        break;
+      case PACKAGE_INFO_AUTHOR_INTERMEDIATE_CERT:
+        cert_name = "AUTHOR_INTERMEDIATE";
+        break;
+      case PACKAGE_INFO_AUTHOR_SIGNER_CERT:
+        cert_name = "AUTHOR_SIGNER";
+        break;
+      case PACKAGE_INFO_DISTRIBUTOR_ROOT_CERT:
+        cert_name = "DISTRIBUTOR_ROOT";
+        break;
+      case PACKAGE_INFO_DISTRIBUTOR_INTERMEDIATE_CERT:
+        cert_name = "DISTRIBUTOR_INTERMEDIATE";
+        break;
+      case PACKAGE_INFO_DISTRIBUTOR_SIGNER_CERT:
+        cert_name = "DISTRIBUTOR_SIGNER";
+        break;
+      case PACKAGE_INFO_DISTRIBUTOR2_ROOT_CERT:
+        cert_name = "DISTRIBUTOR2_ROOT";
+        break;
+      case PACKAGE_INFO_DISTRIBUTOR2_INTERMEDIATE_CERT:
+        cert_name = "DISTRIBUTOR2_INTERMEDIATE";
+        break;
+      case PACKAGE_INFO_DISTRIBUTOR2_SIGNER_CERT:
+        cert_name = "DISTRIBUTOR2_SIGNER";
+        break;
+      default:
+        LoggerD("Unknown certificate type: %d", cert_type);
+        break;
+    }
+
+    picojson::array* array = static_cast<picojson::array*>(user_data);
+    array->push_back(picojson::value(picojson::object()));
+
+    ApplicationUtils::CreateApplicationCertificate(
+        cert_name, cert_value, &array->back().get<picojson::object>());
+
+    return true;
+  };
+
+  picojson::value result = picojson::value(picojson::array());
+
+  ret = package_info_foreach_cert_info(pkg_info, cert_info_cb, &result.get<picojson::array>());
+
+  if ((PACKAGE_MANAGER_ERROR_NONE != ret) && (PACKAGE_MANAGER_ERROR_IO_ERROR != ret)) {
+    LoggerE("Failed to get certificates info: %d (%s)", ret, get_error_message(ret));
+    ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get certificates info."), out);
+    return;
+  }
+
+  ReportSuccess(result, *out);
+}
+
+void ApplicationManager::GetAppSharedUri(const std::string& app_id, picojson::object* out) {
+  LoggerD("Entered");
+
+  char* package_id = nullptr;
+
+  package_id = GetPackageId(app_id);
+  // automatically release the memory
+  std::unique_ptr<char, void(*)(void*)> package_id_ptr(package_id, &std::free);
+
+  if (!package_id) {
+    LoggerE("Failed to get package.");
+    ReportError(PlatformResult(ErrorCode::NOT_FOUND_ERR, "Failed to get package."), out);
+    return;
+  }
+
+  pkgmgrinfo_pkginfo_h pkg_info = nullptr;
+
+  int ret = pkgmgrinfo_pkginfo_get_pkginfo(package_id, &pkg_info);
+  std::unique_ptr<std::remove_pointer<pkgmgrinfo_pkginfo_h>::type, int(*)(pkgmgrinfo_pkginfo_h)>
+  pkg_info_ptr(pkg_info, &pkgmgrinfo_pkginfo_destroy_pkginfo); // automatically release the memory
+
+  if (PMINFO_R_OK != ret) {
+    LoggerE("Failed to get package info: %d (%s)", ret, get_error_message(ret));
+    ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get package info."), out);
+    return;
+  }
+
+  char* root_path = nullptr;
+  ret = pkgmgrinfo_pkginfo_get_root_path(pkg_info, &root_path);
+
+  if (PMINFO_R_OK != ret || nullptr == root_path) {
+    LoggerE("Failed to get root path: %d (%s)", ret, get_error_message(ret));
+    ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get root path."), out);
+    return;
+  }
+
+  picojson::value result = picojson::value(kTizenApisFileScheme +
+                                           root_path +
+                                           kTizenApisAppSlash +
+                                           kTizenApisAppShared +
+                                           kTizenApisAppSlash);
+  ReportSuccess(result, *out);
+}
+
+void ApplicationManager::GetAppMetaData(const std::string& app_id, picojson::object* out) {
+  LoggerD("Entered");
+
+  pkgmgrinfo_appinfo_h handle = nullptr;
+
+  int ret = pkgmgrinfo_appinfo_get_appinfo(app_id.c_str(), &handle);
+  std::unique_ptr<std::remove_pointer<pkgmgrinfo_appinfo_h>::type, int(*)(pkgmgrinfo_appinfo_h)>
+  pkg_info_ptr(handle, &pkgmgrinfo_appinfo_destroy_appinfo); // automatically release the memory
+
+  if (PMINFO_R_OK != ret) {
+    LoggerE("Failed to get app info: %d (%s)", ret, get_error_message(ret));
+    ReportError(PlatformResult(ErrorCode::NOT_FOUND_ERR, "Failed to get app info."), out);
+    return;
+  }
+
+  auto meta_data_cb = [](const char* meta_key, const char* meta_value, void* user_data) -> int {
+    if (nullptr == meta_key || nullptr == meta_value) {
+      LoggerE("meta_key or meta_value is null");
+      return 0;
+    }
+
+    picojson::array* array = static_cast<picojson::array*>(user_data);
+    array->push_back(picojson::value(picojson::object()));
+
+    ApplicationUtils::CreateApplicationMetaData(meta_key, meta_value,
+                                                &array->back().get<picojson::object>());
+    return 0;
+  };
+
+  picojson::value result = picojson::value(picojson::array());
+  ret = pkgmgrinfo_appinfo_foreach_metadata(handle, meta_data_cb, &result.get<picojson::array>());
+
+  if (PMINFO_R_OK != ret) {
+    LoggerE("Failed to get metadata: %d (%s)", ret, get_error_message(ret));
+    ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get metadata."), out);
+    return;
+  }
+
+  ReportSuccess(result, *out);
+}
+
+class ApplicationListChangedBroker {
+ public:
+    ApplicationListChangedBroker() : event_type_() {}
+  enum class Event {
+    kInstalled,
+    kUpdated,
+    kUninstalled,
+  };
+
+  static int ClientStatusListener(int id, const char* type, const char* package, const char* key,
+                                  const char* val, const void* msg, void* data) {
+    LoggerD("Entered");
+    ApplicationListChangedBroker* that = static_cast<ApplicationListChangedBroker*>(data);
+
+    if (0 == strcasecmp(key, kStartKey)) {
+      that->HandleStart(val, package);
+    } else if (0 == strcasecmp(key, kEndKey) && 0 == strcasecmp(val, kOkValue)) {
+      that->HandleEnd(package);
+    } else {
+      LoggerD("Ignored key: %s", key);
+    }
+
+    return 0;
+  }
+
+  static int AppUninstallListener(int id, const char* type, const char* package, const char* key,
+                                  const char* val, const void* msg, void* data) {
+    LoggerD("Entered");
+
+    ApplicationListChangedBroker* that = static_cast<ApplicationListChangedBroker*>(data);
+
+    if (0 == strcasecmp(key, kStartKey)) {
+      that->HandleUninstallStart();
+    } else if (0 == strcasecmp(key, kAppidKey)) {
+      that->AddUninstalledAppId(val);
+    } else if (0 == strcasecmp(key, kEndKey)) {
+      that->HandleUninstallEnd();
+    } else {
+      LoggerD("Ignored key: %s", key);
+    }
+
+    return 0;
+  }
+
+  void AddApplicationInstance(ApplicationInstance* app_instance) {
+    LoggerD("Entered");
+      app_instance_list_.push_back(app_instance);
+  }
+
+  void RemoveApplicationInstance(ApplicationInstance* app_instance) {
+    LoggerD("Entered");
+    for (auto it = app_instance_list_.begin(); it != app_instance_list_.end(); it++) {
+      if (*it == app_instance) {
+       app_instance_list_.erase(it);
+       return;
+      }
+    }
+  }
+ private:
+  void HandleStart(const char* event_type, const char* package) {
+    LoggerD("Entered");
+    app_list_.clear();
+    set_event_type(event_type);
+  }
+
+  void HandleEnd(const char* package) {
+    LoggerD("Entered");
+
+    if (Event::kUninstalled == event_type_) {
+      return;
+    }
+
+    GetApplicationIdsFromPackage(package);
+
+    for (auto& app_id : app_list_) {
+      picojson::value value = picojson::value(picojson::object());
+      picojson::object& data_obj = value.get<picojson::object>();
+
+      switch (event_type_) {
+        case Event::kInstalled:
+          data_obj.insert(std::make_pair(kAction, picojson::value(kOnInstalled)));
+          break;
+
+        case Event::kUpdated:
+          data_obj.insert(std::make_pair(kAction, picojson::value(kOnUpdated)));
+          break;
+        case Event::kUninstalled:
+          LoggerD("Uninstalled called");
+          break;
+      }
+
+      switch (event_type_) {
+        case Event::kInstalled:
+        case Event::kUpdated:
+        {
+          pkgmgrinfo_appinfo_h handle = nullptr;
+          int ret = pkgmgrinfo_appinfo_get_appinfo(app_id.c_str(), &handle);
+          if (PMINFO_R_OK != ret) {
+            LoggerE("Failed to get application information handle: %d (%s)",
+                    ret, get_error_message(ret));
+            continue;
+          }
+          auto info = data_obj.insert(std::make_pair(kData, picojson::value(picojson::object())));
+          ApplicationUtils::CreateApplicationInformation(
+              handle, &info.first->second.get<picojson::object>());
+          pkgmgrinfo_appinfo_destroy_appinfo(handle);
+        }
+        break;
+        case Event::kUninstalled:
+          LoggerD("Uninstalled called");
+          break;
+      }
+
+      data_obj["listenerId"] = picojson::value("ApplicationEventListener");
+
+      for (auto instance : app_instance_list_) {
+        Instance::PostMessage(instance, value.serialize().c_str());
+      }
+    }
+  }
+
+  void GetApplicationIdsFromPackage(const char* package) {
+    LoggerD("Entered");
+    package_info_h package_info = nullptr;
+
+    int ret = package_info_create(package, &package_info);
+    if (PACKAGE_MANAGER_ERROR_NONE != ret) {
+      LoggerE("Failed to create package info: %d (%s)", ret, get_error_message(ret));
+      return;
+    }
+
+    ret = package_info_foreach_app_from_package(package_info,
+                                                PACKAGE_INFO_ALLAPP,
+                                                ApplicationIdCallback,
+                                                this);
+    if (PACKAGE_MANAGER_ERROR_NONE != ret) {
+      LoggerE("Failed to get application IDs: %d (%s)", ret, get_error_message(ret));
+    }
+
+    ret = package_info_destroy(package_info);
+    if (PACKAGE_MANAGER_ERROR_NONE != ret) {
+      LoggerE("Failed to destroy package info: %d (%s)", ret, get_error_message(ret));
+    }
+  }
+
+  void set_event_type(const char* type) {
+    LoggerD("Entered");
+    if (0 == strcasecmp(type, kInstallEvent)) {
+      event_type_ = Event::kInstalled;
+    } else if (0 == strcasecmp(type, kUpdateEvent)) {
+      event_type_ = Event::kUpdated;
+    } else if (0 == strcasecmp(type, kUninstallEvent)) {
+      event_type_ = Event::kUninstalled;
+    }
+  }
+
+  static bool ApplicationIdCallback(package_info_app_component_type_e comp_type,
+                                    const char* app_id, void* user_data) {
+    LoggerD("Entered");
+    if (nullptr != app_id) {
+      static_cast<ApplicationListChangedBroker*>(user_data)->app_list_.push_back(app_id);
+    }
+    return true;
+  }
+
+  void HandleUninstallStart() {
+    LoggerD("Entered");
+    app_list_.clear();
+    set_event_type(kUninstallEvent);
+  }
+
+  void AddUninstalledAppId(const char* app_id) {
+    LoggerD("Entered");
+    if (nullptr != app_id) {
+      app_list_.push_back(app_id);
+    }
+  }
+
+  void HandleUninstallEnd() {
+    LoggerD("Entered");
+    for (auto& app_id : app_list_) {
+      picojson::value value = picojson::value(picojson::object());
+      picojson::object& data_obj = value.get<picojson::object>();
+
+      data_obj.insert(std::make_pair(kAction, picojson::value(kOnUninstalled)));
+      data_obj.insert(std::make_pair(kData, picojson::value(app_id)));
+
+      data_obj["listenerId"] = picojson::value("ApplicationEventListener");
+
+      for (auto instance : app_instance_list_) {
+        Instance::PostMessage(instance, value.serialize().c_str());
+      }
+    }
+  }
+
+  Event event_type_;
+  std::vector<std::string> app_list_;
+  std::vector<ApplicationInstance*> app_instance_list_;
+};
+
+static ApplicationListChangedBroker g_application_list_changed_broker;
+
+void ApplicationManager::StartAppInfoEventListener(picojson::object* out) {
+  LoggerD("Entered");
+
+  if (nullptr == pkgmgr_client_handle_ || nullptr == pkgmgrinfo_client_handle_) {
+    if (nullptr == pkgmgr_client_handle_) {
+      pkgmgr_client_handle_ = pkgmgr_client_new(PC_LISTENING);
+    }
+
+    if (nullptr == pkgmgrinfo_client_handle_) {
+      pkgmgrinfo_client_handle_ = pkgmgrinfo_client_new(PMINFO_LISTENING);
+    }
+
+    if (nullptr == pkgmgr_client_handle_ || nullptr == pkgmgrinfo_client_handle_) {
+      LoggerE("Failed to register listener.");
+      if (nullptr != pkgmgr_client_handle_) {
+        pkgmgr_client_free(pkgmgr_client_handle_);
+        pkgmgr_client_handle_ = nullptr;
+      }
+      else if (nullptr != pkgmgrinfo_client_handle_) {
+        pkgmgrinfo_client_free(pkgmgrinfo_client_handle_);
+        pkgmgrinfo_client_handle_ = nullptr;
+      }
+      ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to register listener."), out);
+      return;
+    }
+
+    g_application_list_changed_broker.AddApplicationInstance(&instance_);
+    pkgmgr_client_listen_status(pkgmgr_client_handle_,
+                                ApplicationListChangedBroker::ClientStatusListener,
+                                &g_application_list_changed_broker);
+
+    pkgmgrinfo_client_set_status_type(pkgmgrinfo_client_handle_,
+                                      PACKAGE_MANAGER_STATUS_TYPE_UNINSTALL);
+    pkgmgrinfo_client_listen_status(pkgmgrinfo_client_handle_,
+                                ApplicationListChangedBroker::AppUninstallListener,
+                                &g_application_list_changed_broker);
+  } else {
+    LoggerD("Broker callback is already registered.");
+  }
+
+  ReportSuccess(*out);
+}
+
+void ApplicationManager::StopAppInfoEventListener() {
+  LoggerD("Entered");
+
+  if (nullptr != pkgmgr_client_handle_ || nullptr != pkgmgrinfo_client_handle_) {
+    if (nullptr != pkgmgr_client_handle_) {
+      pkgmgr_client_free(pkgmgr_client_handle_);
+      pkgmgr_client_handle_ = nullptr;
+    }
+    if (nullptr != pkgmgrinfo_client_handle_) {
+      pkgmgrinfo_client_free(pkgmgrinfo_client_handle_);
+      pkgmgrinfo_client_handle_ = nullptr;
+    }
+    g_application_list_changed_broker.RemoveApplicationInstance(&instance_);
+  } else {
+    LoggerD("Broker callback is already unregistered.");
+  }
+}
+
+void ApplicationManager::GetApplicationInformationSize(const picojson::value& args,
+                                                       picojson::object* out) {
+  LoggerD("Entered");
+
+  const auto& package_id = args.get("packageId");
+  if (!package_id.is<std::string>()) {
+    LoggerE("Invalid parameter passed.");
+    ReportError(PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed."), out);
+    return;
+  }
+
+  const std::string& package_id_str = package_id.get<std::string>();
+
+  // get installed size from package server (to solve smack issue)
+  pkgmgr_client* pc = pkgmgr_client_new(PC_REQUEST);
+  int size = -1;
+
+  if (nullptr == pc) {
+    LoggerE("Failed to create pkgmgr client");
+  } else {
+    size = pkgmgr_client_request_service(PM_REQUEST_GET_SIZE, PM_GET_TOTAL_SIZE, pc, NULL,
+                                         package_id_str.c_str(), NULL, NULL, NULL);
+
+    if (size < 0) {
+      LoggerE("Failed to get installed size: %d (%s)", size, get_error_message(size));
+    }
+
+    pkgmgr_client_free(pc);
+  }
+
+  picojson::value result = picojson::value(picojson::object());
+  picojson::object& result_obj = result.get<picojson::object>();
+  result_obj.insert(std::make_pair("size", picojson::value(static_cast<double>(size))));
+
+  ReportSuccess(result, *out);
+}
+
+void ApplicationManager::BroadcastEventHelper(
+    const picojson::value& args,
+    picojson::object& out, bool trusted) {
+
+  LoggerD("Entered");
+
+  int ret;
+  std::string event_str = args.get("name").get<std::string>();
+  const char* event_name = event_str.c_str();
+
+  bundle* data = bundle_create();
+  SCOPE_EXIT {
+    bundle_free(data);
+  };
+
+  ret = bundle_add(data, "data", args.get("data").serialize().c_str());
+
+  if (ret != EVENT_ERROR_NONE) {
+    LoggerE("bundle_add failed, error: %d (%s)", ret, get_error_message(ret));
+    ReportError(out);
+    return;
+  }
+
+  if (trusted) {
+    ret = event_publish_trusted_app_event(event_name, data);
+  } else {
+    ret = event_publish_app_event(event_name, data);
+  }
+
+  if (ret == EVENT_ERROR_NONE) {
+    ReportSuccess(out);
+  } else {
+    LoggerE("event_publish_app_event failed, error: %d (%s)", ret, get_error_message(ret));
+    ReportError(out);
+  }
+}
+
+void ApplicationManager::OnEvent(const char* event_name,
+                                 bundle* event_data,
+                                 void* user_data) {
+  LoggerD("Entered");
+  LOGGER(DEBUG) << event_name;
+
+  ApplicationManager* manager = static_cast<ApplicationManager*>(user_data);
+
+  if (!manager->event_callback_) {
+    LOGGER(DEBUG) << "No event listener registered, skipping.";
+    return;
+  }
+
+  picojson::value event = picojson::value(picojson::object());
+  picojson::object& event_o = event.get<picojson::object>();
+
+  int ret;
+  char* val = nullptr;
+
+  if (event_map_.count(event_name)) { // system event
+    const std::string& key = event_map_.at(event_name);
+    std::string state = "true";
+    if (key != "") {
+      ret = bundle_get_str(event_data, key.c_str(), &val);
+      if (EVENT_ERROR_NONE != ret) {
+        LoggerE("failed to read bundle data, error: %d (%s)", ret, get_error_message(ret));
+        return;
+      }
+
+      state = std::string(val);
+    }
+
+    LOGGER(DEBUG) << "state is: " << state;
+    event_o["value"] = picojson::value(state);
+
+  } else { // user event
+    ret = bundle_get_str(event_data, "data", &val);
+    if (EVENT_ERROR_NONE != ret) {
+      LoggerE("failed to read bundle data, error: %d (%s)", ret, get_error_message(ret));
+      return;
+    }
+
+    picojson::value data;
+    std::string err;
+    picojson::parse(data, val, val + strlen(val), &err);
+    if (!err.empty()) {
+      LOGGER(ERROR) << "Failed to parse bundle data: " << err;
+      return;
+    }
+
+    event_o["data"] = data;
+  }
+
+  LOGGER(DEBUG) << "event_name is: " << event_name;
+  event_o["name"] = picojson::value(event_name);
+
+  manager->event_callback_(&event);
+}
+
+PlatformResult ApplicationManager::StartEventListener(const std::string& event_name,
+                                                      const JsonCallback& callback) {
+  LoggerD("Entered");
+
+  int ret;
+  event_handler_h event_handler;
+
+  ret = event_add_event_handler(event_name.c_str(), OnEvent, this, &event_handler);
+  LoggerD("event_add_event_handler() result: %d (%s)", ret, get_error_message(ret));
+  if (EVENT_ERROR_PERMISSION_DENIED == ret) {
+    LOGGER(ERROR) << "event_add_event_handler failed, error: " << ret;
+    return PlatformResult(ErrorCode::SECURITY_ERR, "The privilege is required");
+  } else if (EVENT_ERROR_NONE != ret) {
+    LOGGER(ERROR) << "event_add_event_handler failed, error: " << ret;
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Error setting event listener");
+  }
+
+  event_handler_map_[event_name] = event_handler;
+
+  event_callback_ = callback;
+  LOGGER(DEBUG) << "event_add_event_handler success";
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+void ApplicationManager::StopEventListener(const std::string& event_name) {
+  LoggerD("Entered");
+
+  int ret;
+  event_handler_h event_handler;
+
+  if (event_handler_map_.find(event_name) != event_handler_map_.end()) {
+    event_handler = event_handler_map_[event_name];
+
+    ret = event_remove_event_handler(event_handler);
+    if (EVENT_ERROR_NONE != ret) {
+      LoggerE("event_remove_event_handler failed, error: %d (%s)", ret, get_error_message(ret));
+      return;
+    }
+
+    event_handler_map_.erase(event_name);
+  }
+}
+
+} // namespace application
+} // namespace extension
diff --git a/webWidgetTCT_device/src/application/application_manager.h b/webWidgetTCT_device/src/application/application_manager.h
new file mode 100755 (executable)
index 0000000..892e902
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2015 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 SRC_APPLICATION_APPLICATION_MANAGER_H__
+#define SRC_APPLICATION_APPLICATION_MANAGER_H__
+
+#include <app_event.h>
+#include <bundle.h>
+#include <functional>
+#include <memory>
+#include <package-manager.h>
+#include <pkgmgr-info.h>
+#include <string>
+
+#include "common/picojson.h"
+#include "common/platform_result.h"
+
+typedef std::function<void(picojson::value*)> JsonCallback;
+
+namespace extension {
+namespace application {
+
+class ApplicationInstance;
+
+class ApplicationManager {
+ public:
+  explicit ApplicationManager(ApplicationInstance& instance);
+  ~ApplicationManager();
+
+  void GetCurrentApplication(const std::string& app_id, picojson::object* out);
+  void Kill(const picojson::value& args);
+  void Launch(const picojson::value& args);
+  void LaunchAppControl(const picojson::value& args);
+  void FindAppControl(const picojson::value& args);
+  void GetAppsContext(const picojson::value& args);
+  void GetAppContext(const picojson::value& args, picojson::object* out);
+  void GetAppsInfo(const picojson::value& args);
+  void GetAppInfo(const std::string& app_id, picojson::object* out);
+  void GetAppCerts(const std::string& app_id, picojson::object* out);
+  void GetAppSharedUri(const std::string& app_id, picojson::object* out);
+  void GetAppMetaData(const std::string& app_id, picojson::object* out);
+  void StartAppInfoEventListener(picojson::object* out);
+  void StopAppInfoEventListener();
+  void GetApplicationInformationSize(const picojson::value& args, picojson::object* out);
+  void AsyncResponse(common::PlatformResult& result, std::shared_ptr<picojson::value>* response);
+
+  void BroadcastEventHelper(const picojson::value& args, picojson::object& out, bool trusted);
+  common::PlatformResult StartEventListener(const std::string& event_name,
+                                            const JsonCallback& callback);
+  void StopEventListener(const std::string& event_name);
+
+ private:
+  char* GetPackageId(const std::string& app_id);
+
+  pkgmgr_client* pkgmgr_client_handle_;
+  pkgmgrinfo_client* pkgmgrinfo_client_handle_;
+  ApplicationInstance& instance_;
+
+  JsonCallback event_callback_;
+  std::map<std::string, event_handler_h> event_handler_map_;
+  static void OnEvent(const char* event_name,
+                      bundle* event_data,
+                      void* user_data);
+};
+
+} // namespace application
+} // namespace extension
+
+#endif // SRC_APPLICATION_APPLICATION_MANAGER_H__
diff --git a/webWidgetTCT_device/src/application/application_utils.cc b/webWidgetTCT_device/src/application/application_utils.cc
new file mode 100755 (executable)
index 0000000..4504d72
--- /dev/null
@@ -0,0 +1,404 @@
+/*
+ * Copyright (c) 2015 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 "application_utils.h"
+
+#include <memory>
+
+#include <app_manager.h>
+
+#include "common/logger.h"
+#include "common/platform_result.h"
+
+using namespace common;
+
+namespace extension {
+namespace application {
+
+void ApplicationUtils::CreateApplicationInformation(const pkgmgrinfo_appinfo_h handle,
+                                                    picojson::object* app_info) {
+  LoggerD("Enter");
+
+  char* tmp_str = nullptr;
+  int ret = 0;
+
+  // application ID
+  ret = pkgmgrinfo_appinfo_get_appid(handle, &tmp_str);
+  if ((PMINFO_R_OK != ret) || (nullptr == tmp_str)) {
+    LoggerE("Failed to get appid: %d (%s)", ret, get_error_message(ret));
+  } else {
+    app_info->insert(std::make_pair("id", picojson::value(tmp_str)));
+  }
+  tmp_str = nullptr;
+
+  // name
+  ret = pkgmgrinfo_appinfo_get_label(handle, &tmp_str);
+  if ((PMINFO_R_OK != ret) || (nullptr == tmp_str)) {
+    LoggerE("Failed to get label: %d (%s)", ret, get_error_message(ret));
+  } else {
+    app_info->insert(std::make_pair("name", picojson::value(tmp_str)));
+  }
+  tmp_str = nullptr;
+
+  // icon path
+  ret = pkgmgrinfo_appinfo_get_icon(handle, &tmp_str);
+  if ((PMINFO_R_OK != ret) || (nullptr == tmp_str)) {
+    LoggerE("Failed to get icon path: %d (%s)", ret, get_error_message(ret));
+  } else {
+    app_info->insert(std::make_pair("iconPath", picojson::value(tmp_str)));
+  }
+  tmp_str = nullptr;
+
+  // show
+  bool no_display = false;
+  ret = pkgmgrinfo_appinfo_is_nodisplay(handle, &no_display);
+  if (PMINFO_R_OK != ret) {
+    LoggerE("Failed to get nodisplay: %d (%s)", ret, get_error_message(ret));
+  } else {
+    app_info->insert(std::make_pair("show", picojson::value(!no_display)));
+  }
+
+  // categories
+  picojson::value categories = picojson::value(picojson::array());
+  picojson::array& categories_array = categories.get<picojson::array>();
+  app_info->insert(std::make_pair("categories", categories));
+
+  ret = pkgmgrinfo_appinfo_foreach_category(
+      handle,
+      [](const char* category, void* user_data) -> int {
+    picojson::array* categories_array = static_cast<picojson::array*>(user_data);
+
+    if ((nullptr != category) && (nullptr != categories_array)) {
+      categories_array->push_back(picojson::value(category));
+    }
+
+    return 0;
+  },
+  &categories_array);
+
+  if (PMINFO_R_OK != ret) {
+    LoggerE("Failed to get categories: %d (%s)", ret, get_error_message(ret));
+  }
+
+  // package ID
+  ret = pkgmgrinfo_appinfo_get_pkgid(handle, &tmp_str);
+  if ((PMINFO_R_OK != ret) || (nullptr == tmp_str)) {
+    LoggerE("Failed to get pkgid: %d (%s)", ret, get_error_message(ret));
+  } else {
+    app_info->insert(std::make_pair("packageId", picojson::value(tmp_str)));
+  }
+
+  pkgmgrinfo_pkginfo_h pkginfo;
+  ret = pkgmgrinfo_pkginfo_get_pkginfo(tmp_str, &pkginfo);
+  if (PMINFO_R_OK != ret) {
+    LoggerE("Failed to get package info: %d (%s)", ret, get_error_message(ret));
+  } else {
+    // version
+    tmp_str = nullptr;
+    ret = pkgmgrinfo_pkginfo_get_version(pkginfo, &tmp_str);
+    if ((PMINFO_R_OK != ret) || (nullptr == tmp_str)) {
+      LoggerE("Failed to get version: %d (%s)", ret, get_error_message(ret));
+    } else {
+      app_info->insert(std::make_pair("version", picojson::value(tmp_str)));
+    }
+
+    // installation date
+    int installed_time = 0;
+    ret = pkgmgrinfo_pkginfo_get_installed_time(pkginfo, &installed_time);
+    if (ret != PMINFO_R_OK) {
+      LoggerE("Fail to get installed date: %d (%s)", ret, get_error_message(ret));
+    } else {
+      app_info->insert(std::make_pair("installDate", picojson::value(1000.0 * installed_time)));
+    }
+
+    pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo);
+  }
+
+  // size is set at first attribute access (performance)
+}
+
+bool ApplicationUtils::CreateApplicationContext(const app_context_h handle,
+                                                picojson::object* app_context) {
+  char* app_id = nullptr;
+
+  int ret = app_context_get_app_id(handle, &app_id);
+  // automatically release the memory
+  std::unique_ptr<char, void(*)(void*)> app_id_ptr(app_id, &std::free);
+
+  if ((APP_MANAGER_ERROR_NONE != ret) || (nullptr == app_id)) {
+    LoggerD("Failed to get application ID from context: %d (%s)", ret, get_error_message(ret));
+    return false;
+  }
+
+  pid_t pid;
+  ret = app_context_get_pid(handle, &pid);
+
+  if(ret != APP_MANAGER_ERROR_NONE) {
+    LoggerD("Failed to get pid from context: %d (%s)", ret, get_error_message(ret));
+    return false;
+  }
+
+  CreateApplicationContext(pid, app_id, app_context);
+
+  return true;
+}
+
+void ApplicationUtils::CreateApplicationContext(pid_t pid, const std::string& app_id,
+                                                picojson::object* app_context) {
+
+  LoggerD("Enter");
+  app_context->insert(std::make_pair("id", picojson::value(std::to_string(pid))));
+  app_context->insert(std::make_pair("appId", picojson::value(app_id)));
+}
+
+void ApplicationUtils::CreateApplicationCertificate(const char* cert_type,
+                                                    const char* cert_value,
+                                                    picojson::object* app_certificate) {
+
+  LoggerD("Enter");
+  app_certificate->insert(std::make_pair("type", picojson::value(cert_type)));
+  app_certificate->insert(std::make_pair("value", picojson::value(cert_value)));
+}
+
+void ApplicationUtils::CreateApplicationMetaData(const char* key,
+                                                 const char* value,
+                                                 picojson::object* app_meta_data) {
+
+  LoggerD("Enter");
+  app_meta_data->insert(std::make_pair("key", picojson::value(key)));
+  app_meta_data->insert(std::make_pair("value", picojson::value(value)));
+}
+
+PlatformResult ApplicationUtils::ApplicationControlToService(
+    const picojson::object& app_control_obj,
+    app_control_h* app_control) {
+
+  LoggerD("Enter");
+  const auto it_operation = app_control_obj.find("operation");
+  const auto it_uri = app_control_obj.find("uri");
+  const auto it_mime = app_control_obj.find("mime");
+  const auto it_category = app_control_obj.find("category");
+  const auto it_data = app_control_obj.find("data");
+  const auto it_app_control_end = app_control_obj.end();
+
+  if (it_operation == it_app_control_end ||
+      it_uri == it_app_control_end ||
+      it_mime == it_app_control_end ||
+      it_category == it_app_control_end ||
+      it_data == it_app_control_end ||
+      !it_operation->second.is<std::string>() ||
+      !it_data->second.is<picojson::array>()) {
+    LoggerE("Invalid parameter was passed.");
+    return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter was passed.");
+  }
+
+  app_control_create(app_control);
+
+  // operation
+  app_control_set_operation(*app_control, it_operation->second.get<std::string>().c_str());
+
+  // uri
+  if (it_uri->second.is<std::string>()) {
+    app_control_set_uri(*app_control, it_uri->second.get<std::string>().c_str());
+  }
+
+  // mime
+  if (it_mime->second.is<std::string>()) {
+    app_control_set_mime(*app_control, it_mime->second.get<std::string>().c_str());
+  }
+
+  // category
+  if (it_category->second.is<std::string>()) {
+    app_control_set_category(*app_control, it_category->second.get<std::string>().c_str());
+  }
+
+  // ApplicationControlData
+  const picojson::array& data = it_data->second.get<picojson::array>();
+
+  for (auto iter = data.begin(); iter != data.end(); ++iter) {
+    if (iter->is<picojson::object>()) {
+      PlatformResult ret =
+          ApplicationControlDataToServiceExtraData(iter->get<picojson::object>(), *app_control);
+      if (ret.IsError()) {
+        LoggerE("Failed ApplicationControlDataToServiceExtraData()");
+        return ret;
+      }
+    }
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult ApplicationUtils::ApplicationControlDataToServiceExtraData(
+    const picojson::object& app_control_data,
+    app_control_h app_control) {
+
+  LoggerD("Enter");
+
+  const auto it_key = app_control_data.find("key");
+  const auto it_value = app_control_data.find("value");
+  const auto it_app_control_data_end = app_control_data.end();
+
+  if (it_key == it_app_control_data_end ||
+      it_value == it_app_control_data_end ||
+      !it_key->second.is<std::string>() ||
+      !it_value->second.is<picojson::array>()) {
+    LoggerE("Problem with key or value.");
+    return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter was passed.");
+  }
+
+  const std::string& key = it_key->second.get<std::string>();
+  const picojson::array& value = it_value->second.get<picojson::array>();
+
+  const size_t size = value.size();
+  const char** arr = new const char*[size];
+  size_t i = 0;
+
+  for (auto iter = value.begin(); iter != value.end(); ++iter, ++i) {
+    std::string str = iter->to_str();
+    arr[i] = str.c_str();
+  }
+
+  if (1 == size) {
+    app_control_add_extra_data(app_control, key.c_str(), arr[0]);
+  } else {
+    app_control_add_extra_data_array(app_control, key.c_str(), arr, size);
+  }
+
+  delete[] arr;
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+void ApplicationUtils::ServiceToApplicationControl(app_control_h app_control,
+                                                   picojson::object* app_control_obj) {
+  LoggerD("Enter");
+
+  int ret = 0;
+  char* tmp_str = nullptr;
+  auto clear = [](char*& str) {
+    free(str);
+    str = nullptr;
+  };
+
+  ret = app_control_get_operation(app_control, &tmp_str);
+  if ((APP_CONTROL_ERROR_NONE == ret) && (nullptr != tmp_str)) {
+    LoggerD("operation: %s", tmp_str);
+    app_control_obj->insert(std::make_pair("operation", picojson::value(std::string(tmp_str))));
+  } else {
+    LoggerE("Get operation failed: %d (%s)", ret, get_error_message(ret));
+  }
+  clear(tmp_str);
+
+  ret = app_control_get_uri(app_control, &tmp_str);
+  if ((APP_CONTROL_ERROR_NONE == ret) && (nullptr != tmp_str)) {
+    LoggerD("URI: %s", tmp_str);
+    app_control_obj->insert(std::make_pair("uri", picojson::value(std::string(tmp_str))));
+  }
+  clear(tmp_str);
+
+  ret = app_control_get_mime(app_control, &tmp_str);
+  if ((APP_CONTROL_ERROR_NONE == ret) && (nullptr != tmp_str)) {
+    LoggerD("MIME: %s", tmp_str);
+    app_control_obj->insert(std::make_pair("mime", picojson::value(std::string(tmp_str))));
+  } else {
+    LoggerE("Get mime failed: %d (%s)", ret, get_error_message(ret));
+  }
+  clear(tmp_str);
+
+  ret = app_control_get_category(app_control, &tmp_str);
+  if ((APP_CONTROL_ERROR_NONE == ret) && (nullptr != tmp_str)) {
+    LoggerD("category: %s", tmp_str);
+    app_control_obj->insert(std::make_pair("category", picojson::value(std::string(tmp_str))));
+  } else {
+    LoggerE("Get category failed: %d (%s)", ret, get_error_message(ret));
+  }
+  clear(tmp_str);
+
+  app_control_obj->insert(std::make_pair("data", picojson::value(picojson::array())));
+  ServiceToApplicationControlDataArray(
+      app_control, &app_control_obj->find("data")->second.get<picojson::array>());
+}
+
+void ApplicationUtils::ServiceExtraDataToApplicationControlData(app_control_h app_control,
+                                                                const std::string& key,
+                                                                picojson::object* app_control_data) {
+  LoggerD("Enter");
+
+  int ret = 0;
+  bool is_array = false;
+
+  ret = app_control_is_extra_data_array(app_control, key.c_str(), &is_array);
+
+  if (APP_CONTROL_ERROR_NONE != ret) {
+    LoggerE("Failed to check whether extra data is array or not: %d (%s)", ret, get_error_message(ret));
+    return;
+  }
+
+  app_control_data->insert(std::make_pair("key", picojson::value(key)));
+  picojson::array value_array;
+
+  if (is_array) {
+    int length = 0;
+    char** value = nullptr;
+
+    ret = app_control_get_extra_data_array(app_control, key.c_str(), &value, &length);
+
+    if ((APP_CONTROL_ERROR_NONE == ret) && (nullptr != value)) {
+      for (int i = 0; i < length; ++i) {
+        if (value[i]) {
+          value_array.push_back(picojson::value(value[i]));
+          free(value[i]);
+        }
+      }
+      free(value);
+    } else {
+      LoggerE("Failed to get extra data array, errno: %d (%s)", ret, get_error_message(ret));
+    }
+  } else {
+    char* value = nullptr;
+
+    ret = app_control_get_extra_data(app_control, key.c_str(), &value);
+
+    if ((APP_CONTROL_ERROR_NONE == ret) && (nullptr != value)) {
+      value_array.push_back(picojson::value(value));
+      free(value);
+    } else {
+      LoggerE("Failed to get extra data, errno: %d (%s)", ret, get_error_message(ret));
+    }
+  }
+
+  app_control_data->insert(std::make_pair("value", picojson::value(value_array)));
+}
+
+bool ApplicationUtils::ServiceToApplicationControlDataArray(app_control_h app_control,
+                                                            picojson::array* data) {
+  int ret = app_control_foreach_extra_data(app_control, ServiceExtraDataCallback, data);
+  return APP_CONTROL_ERROR_NONE == ret;
+}
+
+bool ApplicationUtils::ServiceExtraDataCallback(app_control_h app_control,
+                                                const char* key,
+                                                void* user_data) {
+  picojson::array* data = static_cast<picojson::array*>(user_data);
+
+  data->push_back(picojson::value(picojson::object()));
+  ServiceExtraDataToApplicationControlData(app_control, key, &data->back().get<picojson::object>());
+
+  return true;
+}
+
+} // namespace application
+} // namespace extension
diff --git a/webWidgetTCT_device/src/application/application_utils.h b/webWidgetTCT_device/src/application/application_utils.h
new file mode 100755 (executable)
index 0000000..d66af26
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2015 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 SRC_APPLICATION_APPLICATION_UTILS_H__
+#define SRC_APPLICATION_APPLICATION_UTILS_H__
+
+#include <pkgmgr-info.h>
+#include <app_context.h>
+#include <app_control.h>
+
+#include "common/picojson.h"
+#include "common/platform_result.h"
+
+namespace extension {
+namespace application {
+
+class ApplicationUtils {
+ public:
+  static void CreateApplicationInformation(const pkgmgrinfo_appinfo_h handle,
+                                           picojson::object* app_info);
+
+  static bool CreateApplicationContext(const app_context_h handle,
+                                       picojson::object* app_context);
+
+  static void CreateApplicationContext(pid_t pid,
+                                       const std::string& app_id,
+                                       picojson::object* app_context);
+
+  static void CreateApplicationCertificate(const char* cert_type,
+                                           const char* cert_value,
+                                           picojson::object* app_certificate);
+
+  static void CreateApplicationMetaData(const char* key,
+                                        const char* value,
+                                        picojson::object* app_meta_data);
+
+  static common::PlatformResult ApplicationControlToService(const picojson::object& app_control_obj,
+                                                            app_control_h* app_control);
+
+  static common::PlatformResult ApplicationControlDataToServiceExtraData(
+      const picojson::object& app_control_data,
+      app_control_h app_control);
+
+  static void ServiceToApplicationControl(app_control_h app_control,
+                                          picojson::object* app_control_obj);
+
+  static void ServiceExtraDataToApplicationControlData(app_control_h app_control,
+                                                       const std::string& key,
+                                                       picojson::object* app_control_data);
+
+  static bool ServiceToApplicationControlDataArray(app_control_h app_control,
+                                                   picojson::array* data);
+ private:
+  static bool ServiceExtraDataCallback(app_control_h app_control,
+                                       const char* key,
+                                       void* user_data);
+};
+
+} // namespace application
+} // namespace extension
+
+#endif // SRC_APPLICATION_APPLICATION_UTILS_H__
diff --git a/webWidgetTCT_device/src/application/requested_application_control.cc b/webWidgetTCT_device/src/application/requested_application_control.cc
new file mode 100755 (executable)
index 0000000..0c6d6d6
--- /dev/null
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 2015 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 "requested_application_control.h"
+
+#include <app_manager.h>
+#include <app_control_internal.h>
+#include <bundle.h>
+#include <bundle_internal.h>
+
+#include "common/logger.h"
+#include "application/application_utils.h"
+
+using namespace common;
+using namespace tools;
+
+namespace extension {
+namespace application {
+
+PlatformResult RequestedApplicationControl::set_bundle(const std::string& encoded_bundle) {
+  LoggerD("Entered");
+
+  if (encoded_bundle != bundle_) {
+    bundle_ = encoded_bundle;
+
+    bundle* bundle = bundle_decode((bundle_raw*)(encoded_bundle.c_str()),
+                                   encoded_bundle.length());
+    app_control_h app_control = nullptr;
+    int ret = app_control_create_event(bundle, &app_control);
+    bundle_free(bundle);
+
+    if (APP_CONTROL_ERROR_NONE != ret) {
+      LoggerE("Failed to create app_control: %d (%s)", ret, get_error_message(ret));
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to create app_control.");
+    }
+
+    set_app_control(app_control);
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+void RequestedApplicationControl::set_app_control(app_control_h app_control) {
+  LoggerD("Entered");
+
+  app_control_.reset(app_control, app_control_destroy);
+
+  char* tmp_str = nullptr;
+  int ret = app_control_get_caller(app_control, &tmp_str);
+
+  if ((APP_CONTROL_ERROR_NONE == ret) && (nullptr != tmp_str)) {
+    caller_app_id_ = tmp_str;
+  } else {
+    LoggerW("Failed to get callerAppId because of platform error: %d (%s)", ret, get_error_message(ret));
+    LoggerW("Please ignore if the application is launched in debug mode");
+  }
+
+  free(tmp_str);
+}
+
+void RequestedApplicationControl::ToJson(picojson::object* out) {
+  LoggerD("Entered");
+
+  if (app_control_) {
+    out->insert(std::make_pair("callerAppId", picojson::value(caller_app_id_)));
+    auto appControl = out->insert(std::make_pair(
+        "appControl", picojson::value(picojson::object())));
+    ApplicationUtils::ServiceToApplicationControl(
+        app_control_.get(), &appControl.first->second.get<picojson::object>());
+  }
+}
+
+void RequestedApplicationControl::ReplyResult(const picojson::value& args, picojson::object* out) {
+  LoggerD("Entered");
+
+  const auto& data_arr = args.get("data");
+  if (!data_arr.is<picojson::array>()) {
+    LoggerE("Invalid parameter passed.");
+    ReportError(PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid parameter passed."), out);
+    return;
+  }
+
+  // read input data
+  const picojson::array& data = data_arr.get<picojson::array>();
+
+  const std::string& encoded_bundle = GetEncodedBundle();
+
+  PlatformResult result = set_bundle(encoded_bundle);
+  if (result.IsError()) {
+    LoggerE("Failed set_bundle()");
+    ReportError(result, out);
+    return;
+  }
+
+  // code to check caller liveness
+  result = VerifyCallerPresence();
+  if (result.IsError()) {
+    LoggerE("Failed VerifyCallerPresence()");
+    ReportError(result, out);
+    return;
+  }
+
+  // create reply
+  app_control_h reply;
+  app_control_create(&reply);
+  std::unique_ptr<std::remove_pointer<app_control_h>::type, int(*)(app_control_h)>
+  reply_ptr(reply, &app_control_destroy); // automatically release the memory
+
+  if (!data.empty()) {
+    for (auto iter = data.begin(); iter != data.end(); ++iter) {
+      result = ApplicationUtils::ApplicationControlDataToServiceExtraData(
+          iter->get<picojson::object>(), reply);
+      if (result.IsError()) {
+        LoggerE("Failed ApplicationControlDataToServiceExtraData()");
+        ReportError(result, out);
+        return;
+      }
+    }
+  } else {
+    LoggerD("appControlDataArray is empty");
+  }
+
+  // send reply
+  int ret = app_control_reply_to_launch_request(reply, app_control_.get(),
+          APP_CONTROL_RESULT_SUCCEEDED);
+  if (APP_CONTROL_ERROR_NONE != ret) {
+    LoggerE("Cannot find caller: %d (%s)", ret, get_error_message(ret));
+    ReportError(PlatformResult(ErrorCode::NOT_FOUND_ERR, "Cannot find caller."), out);
+    return;
+  }
+
+  ReportSuccess(*out);
+}
+
+void RequestedApplicationControl::ReplyFailure(picojson::object* out) {
+  LoggerD("Entered");
+
+  // read input data
+  const std::string& encoded_bundle = GetEncodedBundle();
+
+  PlatformResult result = set_bundle(encoded_bundle);
+  if (result.IsError()) {
+    LoggerE("Failed set_bundle()");
+    ReportError(result, out);
+    return;
+  }
+
+  // code to check caller liveness
+  result = VerifyCallerPresence();
+  if (result.IsError()) {
+    LoggerE("Failed VerifyCallerPresence()");
+    ReportError(result, out);
+    return;
+  }
+
+  // create reply
+  app_control_h reply;
+  app_control_create(&reply);
+  std::unique_ptr<std::remove_pointer<app_control_h>::type, int(*)(app_control_h)>
+  reply_ptr(reply, &app_control_destroy); // automatically release the memory
+
+  // send reply
+  int ret = app_control_reply_to_launch_request(reply, app_control_.get(), APP_CONTROL_RESULT_FAILED);
+  if (APP_CONTROL_ERROR_NONE != ret) {
+    LoggerE("Cannot find caller: %d (%s)", ret, get_error_message(ret));
+    ReportError(PlatformResult(ErrorCode::NOT_FOUND_ERR, "Cannot find caller."), out);
+    return;
+  }
+
+  ReportSuccess(*out);
+}
+
+std::string RequestedApplicationControl::GetEncodedBundle() {
+  LoggerD("Entered");
+
+  std::string result;
+  std::size_t size = 512;
+
+  // make sure we read whole variable, if the length of read variable is equal
+  // to the size we were trying to obtain, the variable is likely to be longer
+  do {
+    size <<= 1;
+    result = GetCurrentExtension()->GetRuntimeVariable("encoded_bundle", size);
+  } while (strlen(result.c_str()) == size);
+
+  return result;
+}
+
+PlatformResult RequestedApplicationControl::VerifyCallerPresence() {
+  LoggerD("Entered");
+
+  if (caller_app_id_.empty()) {
+    LoggerE("caller_app_id_ is empty. This means caller is dead.");
+    return PlatformResult(ErrorCode::NOT_FOUND_ERR, "Cannot find caller.");
+  } else {
+    bool running = false;
+
+    int ret = app_manager_is_running(caller_app_id_.c_str(), &running);
+
+    if ((APP_MANAGER_ERROR_NONE != ret) || !running) {
+      LoggerE("Caller is not running: %d (%s)", ret, get_error_message(ret));
+      return PlatformResult(ErrorCode::NOT_FOUND_ERR, "Cannot find caller.");
+    }
+
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+}
+
+}  // namespace application
+}  // namespace extension
diff --git a/webWidgetTCT_device/src/application/requested_application_control.h b/webWidgetTCT_device/src/application/requested_application_control.h
new file mode 100755 (executable)
index 0000000..859e822
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2015 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 SRC_APPLICATION_REQUESTED_APPLICATION_CONTROL_H_
+#define SRC_APPLICATION_REQUESTED_APPLICATION_CONTROL_H_
+
+#include <string>
+#include <memory>
+#include <type_traits>
+
+#include <app_control.h>
+
+#include "common/picojson.h"
+#include "common/extension.h"
+#include "common/platform_result.h"
+#include "tizen/tizen.h"
+
+namespace extension {
+namespace application {
+
+class RequestedApplicationControl {
+ public:
+  common::PlatformResult set_bundle(const std::string& encoded_bundle);
+  void ToJson(picojson::object* out);
+  void ReplyResult(const picojson::value& args, picojson::object* out);
+  void ReplyFailure(picojson::object* out);
+
+  static std::string GetEncodedBundle();
+
+ private:
+  void set_app_control(app_control_h app_control);
+  common::PlatformResult VerifyCallerPresence();
+
+  std::string bundle_;
+  std::shared_ptr<std::remove_pointer<app_control_h>::type> app_control_;
+  std::string caller_app_id_;
+};
+
+}  // namespace application
+}  // namespace extension
+
+#endif  // SRC_APPLICATION_REQUESTED_APPLICATION_CONTROL_H_
diff --git a/webWidgetTCT_device/src/archive/archive.gyp b/webWidgetTCT_device/src/archive/archive.gyp
new file mode 100755 (executable)
index 0000000..589e477
--- /dev/null
@@ -0,0 +1,59 @@
+{
+  'includes':[
+    '../common/common.gypi',
+  ],
+  'targets': [
+    {
+      'target_name': 'tizen_archive',
+      'type': 'loadable_module',
+      'dependencies': [
+        '../common/common.gyp:tizen_common',
+      ],
+      'sources': [
+        'archive_api.js',
+        'archive_extension.cc',
+        'archive_extension.h',
+        'archive_file.cc',
+        'archive_file.h',
+        'archive_file_entry.cc',
+        'archive_file_entry.h',
+        'archive_instance.cc',
+        'archive_instance.h',
+        'archive_manager.cc',
+        'archive_manager.h',
+        'archive_utils.cc',
+        'archive_utils.h',
+        'archive_callback_data.cc',
+        'archive_callback_data.h',
+        'filesystem_file.cc',
+        'filesystem_file.h',
+        'filesystem_path.cc',
+        'filesystem_path.h',
+        'filesystem_node.cc',
+        'filesystem_node.h',
+        'defs.h',
+        'un_zip.cc',
+        'un_zip.h',
+        'un_zip_extract_request.cc',
+        'un_zip_extract_request.h',
+        'zip_add_request.cc',
+        'zip_add_request.h',
+        'zip.cc',
+        'zip.h'
+      ],
+      'includes': [
+        '../common/pkg-config.gypi'
+      ],
+      'conditions': [
+        ['tizen == 1', {
+          'variables': {
+            'packages': [
+              'minizip',
+              'zlib'
+            ]
+          },
+        }],
+      ],
+    },
+  ],
+}
diff --git a/webWidgetTCT_device/src/archive/archive_api.js b/webWidgetTCT_device/src/archive/archive_api.js
new file mode 100755 (executable)
index 0000000..f3576ce
--- /dev/null
@@ -0,0 +1,552 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+var validator_ = xwalk.utils.validator;
+var types_ = validator_.Types;
+var bridge = xwalk.utils.NativeBridge(extension, true);
+
+function CommonFS() {};
+
+CommonFS.cacheVirtualToReal = {};
+
+function _initializeCache() {
+    try {
+        var result = bridge.sync({
+            cmd: 'Archive_fetchVirtualRoots'
+        });
+        for (var i = 0; i < result.length; ++i) {
+          CommonFS.cacheVirtualToReal[result[i].name] = {
+            path: result[i].path
+          };
+        }
+    } catch(e) {
+        console.log("Exception while getting widget paths was thrown: " + e);
+    }
+}
+
+_initializeCache();
+
+CommonFS.toRealPath = function(aPath) {
+    var _fileRealPath = '', _uriPrefix = 'file://', i;
+    if (aPath.indexOf(_uriPrefix) === 0) {
+        _fileRealPath = aPath.substr(_uriPrefix.length);
+    } else if (aPath[0] != '/') {
+        // virtual path$
+        var _pathTokens = aPath.split('/');
+        if (this.cacheVirtualToReal[_pathTokens[0]]
+                && (this.cacheVirtualToReal[_pathTokens[0]].state === undefined || this.cacheVirtualToReal[_pathTokens[0]].state === 'MOUNTED')) {
+            _fileRealPath = this.cacheVirtualToReal[_pathTokens[0]].path;
+            for (i = 1; i < _pathTokens.length; ++i) {
+                _fileRealPath += '/' + _pathTokens[i];
+            }
+        } else {
+            _fileRealPath = aPath;
+        }
+    } else {
+        _fileRealPath = aPath;
+    }
+    console.log("REAL PATH:" + _fileRealPath);
+    if (_fileRealPath === "undefined" || _fileRealPath === "null") {
+        throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR);
+    }
+    return _fileRealPath;
+};
+
+CommonFS.isVirtualPath = function(aPath) {
+    var root = aPath.split("/")[0];
+
+    return this.cacheVirtualToReal[root] != undefined;
+};
+
+/**
+ * Returns new unique opId
+ */
+var getNextOpId = (function () {
+    var opId = 0,
+        incOpId = function () {
+            return opId++;
+        };
+    return incOpId;
+}());
+
+var Property = {
+    W: 1 << 0,   // WRITABLE
+    E: 1 << 1,   // ENUMERABLE
+    C: 1 << 2    // CONFIGURABLE
+}
+
+/**
+ * Example usage:
+ * function Messaging () {
+ *     propertyFactory_(this, 'ids', [2,3,4], Property.W | Property.E | Property.C);
+ *     propertyFactory_(this, 'name', 'Name', Property.E);
+ *     propertyFactory_(this, 'age', 25, Property.W);
+ *     propertyFactory_(this, 'something', 1);
+ *     propertyFactory_(this, 'getSomething', Property.E, {get: function(){return 100;}});
+ * }
+ * Will produce:
+ * var m = new Messaging();
+ * {
+ *     id: [2,3,4],
+ *     name: 'Name',
+ *     age: 25
+ * }
+ *
+ * m.name = 'A brand new name';
+ * console.log(m.name); // Name
+ */
+function propertyFactory_(that, name, value, flags, options) {
+    flags = flags || 0;
+    if (options === null || typeof options !== 'object') {
+        options = {};
+    }
+    if (!(options.get) && !(options.set)) {
+        options.value = value;
+    }
+    if ((flags & Property.W) != 0) { options.writable     = true; }
+    if ((flags & Property.E) != 0) { options.enumerable   = true; }
+    if ((flags & Property.C) != 0) { options.configurable = true; }
+    Object.defineProperty(
+        that,
+        name,
+        options
+    );
+}
+
+function checkMode(mode, access)
+{   if(access.indexOf(mode) == -1) {
+        throw new WebAPIException(WebAPIException.INVALID_ACCESS_ERR, 'Not allowed operation');
+    }
+}
+
+/**
+ * Enumeration for the compression level.
+ * @enum {string}
+ */
+var ArchiveCompressionLevel = {
+    STORE: "STORE",
+    FAST: "FAST",
+    NORMAL: "NORMAL",
+    BEST: "BEST"
+};
+
+/**
+ * The ArchiveFileEntry interface provides access to ArchiveFile member information and file data.
+ * This constructor is for internal use only.
+ * It should be prohibited to call this constructor by user.
+ */
+function ArchiveFileEntry(data, priv) {
+    if (!(this instanceof ArchiveFileEntry)) {
+        return new ArchiveFileEntry(data);
+    }
+
+    if (data === null || typeof data !== 'object') {
+        throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR);
+    }
+
+    propertyFactory_(this, 'name',           data.name                      || "",    Property.E);
+    propertyFactory_(this, 'size',           data.size                      || 0,     Property.E);
+    propertyFactory_(this, 'compressedSize', data.compressedSize            || 0,     Property.E);
+    propertyFactory_(this, 'modified',       new Date(data.modified * 1000) || null , Property.E);
+
+    function getHandle() {
+        if(priv.handle)
+            return priv.handle;
+        else throw new WebAPIException(WebAPIException.UNKNOWN_ERR, 'Archive is not opened');
+    }
+
+    /**
+     * Extracts ArchiveFileEntry to the given location.
+     */
+    this.extract = function () {
+        xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.FILESYSTEM_WRITE);
+
+        var args = validator_.validateArgs(arguments, [
+            { name: "destinationDirectory", type: types_.FILE_REFERENCE },
+            { name: "onsuccess", type: types_.FUNCTION, optional: true, nullable: true },
+            { name: "onerror", type: types_.FUNCTION, optional: true, nullable: true },
+            { name: "onprogress", type: types_.FUNCTION, optional: true, nullable: true },
+            { name: "stripName", type: types_.STRING, optional: true, nullable: true },
+            { name: "overwrite", type: types_.BOOLEAN, optional: true, nullable: true }
+        ]),
+        opId = getNextOpId();
+
+        if (!CommonFS.isVirtualPath(args.destinationDirectory))
+            throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR,
+                    "Destination directory should be virtual path or file.");
+        bridge.async({
+            cmd: 'ArchiveFileEntry_extract',
+            args: {
+                destinationDirectory: CommonFS.toRealPath(args.destinationDirectory),
+                stripName: args.stripName || null,
+                overwrite: args.overwrite || null,
+                opId: opId,
+                handle: getHandle(),
+                name: this.name
+            }
+        }).then({
+            success: function () {
+                if (args.onsuccess) {
+                    args.onsuccess.call(null);
+                }
+            },
+            error: function (e) {
+                if (args.onerror) {
+                    args.onerror.call(
+                        null,
+                        new WebAPIException(e)
+                    );
+                }
+            },
+            progress: function (data) {
+                if (args.onprogress) {
+                    args.onprogress.call(
+                        null,
+                        opId,
+                        data.value,
+                        data.filename
+                    );
+                }
+            }
+        });
+
+        return opId;
+    };
+}
+
+
+/**
+ * The ArchiveManager interface provides methods for global operations related to ArchiveFile.
+ */
+
+/**
+ * ArchiveFile interface provides access to member files of the archive file.
+ * This constructor is for internal use only.
+ * It should be prohibited to call this constructor by user.
+ */
+function ArchiveFile(data) {
+    if (!(this instanceof ArchiveFile)) {
+        return new ArchiveFile(data);
+    }
+
+    if (data === null || typeof data !== 'object') {
+        throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR);
+    }
+
+    propertyFactory_(this, 'mode'            , data.mode             || "r", Property.E);
+    propertyFactory_(this, 'decompressedSize', data.decompressedSize || 0,   Property.E);
+
+    var priv ={ handle: data.handle };
+
+    function getHandle() {
+        if(priv.handle)
+            return priv.handle;
+        else throw new WebAPIException(WebAPIException.INVALID_STATE_ERR, 'ArchiveFile closed - operation not permitted');
+    }
+
+    /**
+     * Adds a new member file to ArchiveFile.
+     */
+    this.add = function () {
+        xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.FILESYSTEM_WRITE);
+
+        var args = validator_.validateArgs(arguments, [
+            { name: "sourceFile", type: types_.FILE_REFERENCE },
+            { name: "onsuccess", type: types_.FUNCTION, optional: true, nullable: true },
+            { name: "onerror", type: types_.FUNCTION, optional: true, nullable: true },
+            { name: "onprogress", type: types_.FUNCTION, optional: true, nullable: true },
+            { name: "options", type: types_.DICTIONARY, optional: true, nullable: true }
+        ]),
+        opId = getNextOpId();
+
+        if (!CommonFS.isVirtualPath(args.sourceFile))
+            throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR,
+                    "sourceFile should be virtual path or file.");
+
+        var optionsAttributes = ["destination", "stripSourceDirectory", "compressionLevel"],
+            options = args.options || {};
+
+        for(var i in optionsAttributes) {
+            if (!options[optionsAttributes[i]]) {
+                options[optionsAttributes[i]] = null;
+            }
+        }
+
+        checkMode(this.mode, ["w","rw", "a"]);
+        bridge.async({
+            cmd: 'ArchiveFile_add',
+            args: {
+                sourceFile: CommonFS.toRealPath(args.sourceFile),
+                options: options,
+                opId: opId,
+                handle: getHandle()
+            }
+        }).then({
+            success: function () {
+                if (args.onsuccess) {
+                    args.onsuccess.call(null);
+                }
+            },
+            error: function (e) {
+                if (args.onerror) {
+                    args.onerror.call(
+                        null,
+                        new WebAPIException(e)
+                    );
+                }
+            },
+            progress: function (data) {
+                if (args.onprogress) {
+                    args.onprogress.call(
+                        null,
+                        opId,
+                        data.value,
+                        data.filename
+                    );
+                }
+            }
+        });
+
+        return opId;
+    };
+
+    /**
+     * Extracts every file from this ArchiveFile to a given directory.
+     */
+    this.extractAll = function () {
+        xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.FILESYSTEM_WRITE);
+
+        var args = validator_.validateArgs(arguments, [
+            { name: "destinationDirectory", type: types_.FILE_REFERENCE },
+            { name: "onsuccess", type: types_.FUNCTION, optional: true, nullable: true },
+            { name: "onerror", type: types_.FUNCTION, optional: true, nullable: true },
+            { name: "onprogress", type: types_.FUNCTION, optional: true, nullable: true },
+            { name: "overwrite", type: types_.BOOLEAN, optional: true, nullable: true }
+        ]),
+        opId = getNextOpId();
+
+        if (!CommonFS.isVirtualPath(args.destinationDirectory))
+            throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR,
+                    "destinationDirectory should be virtual path or file.");
+
+        checkMode(this.mode, ["r","rw"]);
+        bridge.async({
+            cmd: 'ArchiveFile_extractAll',
+            args: {
+                destinationDirectory: CommonFS.toRealPath(args.destinationDirectory),
+                overwrite: args.overwrite || null,
+                opId: opId,
+                handle: getHandle()
+            }
+        }).then({
+            success: function () {
+                if (args.onsuccess) {
+                    args.onsuccess.call(null);
+                }
+            },
+            error: function (e) {
+                if (args.onerror) {
+                    args.onerror.call(
+                        null,
+                        new WebAPIException(e)
+                    );
+                }
+            },
+            progress: function (data) {
+                if (args.onprogress) {
+                    args.onprogress.call(
+                        null,
+                        opId,
+                        data.value,
+                        data.filename
+                    );
+                }
+            }
+        });
+
+        return opId;
+    };
+
+    /**
+     * Retrieves information about the member files in ArchiveFile.
+     */
+    this.getEntries = function () {
+        xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.FILESYSTEM_READ);
+
+        var args = validator_.validateArgs(arguments, [
+            { name: "onsuccess", type: types_.FUNCTION },
+            { name: "onerror", type: types_.FUNCTION, optional: true, nullable: true }
+        ]),
+        opId = getNextOpId();
+
+        checkMode(this.mode, ["r","rw"]);
+        bridge.async({
+            cmd: 'ArchiveFile_getEntries',
+            args: {
+                opId: opId,
+                handle: getHandle()
+            }
+        }).then({
+            success: function (data) {
+                var entries = [];
+                data.forEach(function (e) {
+                    entries.push(new ArchiveFileEntry(e, priv));
+                });
+                args.onsuccess.call(null, entries);
+            },
+            error: function (e) {
+                if (args.onerror) {
+                    args.onerror.call(
+                        null,
+                        new WebAPIException(e)
+                    );
+                }
+            }
+        });
+
+        return opId;
+    };
+
+    /**
+     * Retrieves information about ArchiveFileEntry with the specified name in ArchiveFile.
+     */
+    this.getEntryByName = function () {
+        xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.FILESYSTEM_READ);
+
+        var args = validator_.validateArgs(arguments, [
+            { name: "name", type: types_.STRING },
+            { name: "onsuccess", type: types_.FUNCTION },
+            { name: "onerror", type: types_.FUNCTION, optional: true, nullable: true }
+        ]),
+        opId = getNextOpId();
+
+        checkMode(this.mode, ["r","rw"]);
+        bridge.async({
+            cmd: 'ArchiveFile_getEntryByName',
+            args: {
+                name: args.name,
+                opId: opId,
+                handle: getHandle()
+            }
+        }).then({
+            success: function (data) {
+                args.onsuccess.call(null, new ArchiveFileEntry(data, priv));
+            },
+            error: function (e) {
+                if (args.onerror) {
+                    args.onerror.call(
+                        null,
+                        new WebAPIException(e)
+                    );
+                }
+            }
+        });
+
+        return opId;
+    };
+
+    /**
+     * Closes the ArchiveFile.
+     */
+    this.close = function () {
+        var handle = priv.handle;
+        if(priv.handle) {
+            delete priv.handle;
+            bridge.sync({
+                cmd: 'ArchiveFile_close',
+                args: {
+                    handle: handle
+                }
+            });
+        }
+    };
+}
+
+
+var ArchiveManager = function () {
+};
+
+/**
+ * Opens the archive file. After this operation, it is possible to add or get files to and from the archive.
+ */
+ArchiveManager.prototype.open = function () {
+    xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.FILESYSTEM_WRITE);
+
+    var args = validator_.validateArgs(arguments, [
+        { name: "file", type: types_.FILE_REFERENCE },
+        { name: "mode", type: types_.ENUM, values: ["r", "rw", "w", "a"] },
+        { name: "onsuccess", type: types_.FUNCTION },
+        { name: "onerror", type: types_.FUNCTION, optional: true, nullable: true },
+        { name: "options", type: types_.DICTIONARY, optional: true, nullable: true }
+    ]),
+    opId = getNextOpId();
+
+    var optionsAttributes = ["overwrite"],
+        options = args.options || {};
+
+    for(var i in optionsAttributes) {
+        if (!options[optionsAttributes[i]]) {
+            options[optionsAttributes[i]] = null;
+        }
+    }
+
+    if (!CommonFS.isVirtualPath(args.file))
+        throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR,
+                "file should be virtual path or file.");
+
+    bridge.async({
+        cmd: 'ArchiveManager_open',
+        args: {
+            file: CommonFS.toRealPath(args.file),
+            mode: args.mode,
+            options: options,
+            opId: opId
+        }
+    }).then({
+        success: function (data) {
+            args.onsuccess.call(null, new ArchiveFile(data));
+        },
+        error: function (e) {
+            if (args.onerror) {
+                args.onerror.call(
+                    null,
+                    new WebAPIException(e)
+                );
+            }
+        }
+    });
+
+    return opId;
+};
+
+/**
+ * Cancels an operation with the given identifier.
+ */
+ArchiveManager.prototype.abort = function () {
+    var args = validator_.validateArgs(arguments, [
+        { name: "opId", type: types_.LONG }
+    ]);
+
+    bridge.sync({
+        cmd: 'ArchiveManager_abort',
+        args: {
+            opId: args.opId
+        }
+    });
+};
+
+//Exports
+exports = new ArchiveManager();
diff --git a/webWidgetTCT_device/src/archive/archive_callback_data.cc b/webWidgetTCT_device/src/archive/archive_callback_data.cc
new file mode 100755 (executable)
index 0000000..dcb210f
--- /dev/null
@@ -0,0 +1,832 @@
+/*
+ * Copyright (c) 2015 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 "archive_callback_data.h"
+
+#include "common/logger.h"
+
+#include "archive_file.h"
+#include "archive_utils.h"
+#include "un_zip.h"
+#include "zip.h"
+#include "archive_manager.h"
+#include "defs.h"
+#include "archive_instance.h"
+
+namespace extension {
+namespace archive {
+
+using namespace common;
+
+//----------------------------------------------------------------------------------------
+//OperationCallbackData
+//----------------------------------------------------------------------------------------
+
+OperationCallbackData::OperationCallbackData(ArchiveCallbackType callback_type, ArchiveInstance& instance) :
+    m_callback_type(callback_type),
+    m_op_id(-1),
+    m_cid(-1),
+    m_handle(-1),
+    instance_(instance),
+    m_is_error(false),
+    m_is_canceled(false),
+    m_err_code(ErrorCode::NO_ERROR)
+{
+    LoggerD("Entered");
+}
+
+OperationCallbackData::~OperationCallbackData()
+{
+    LoggerD("Entered");
+    if(m_op_id > -1){
+        ArchiveManager::getInstance().eraseElementFromArchiveFileMap(m_op_id);
+    }
+}
+
+void OperationCallbackData::setError(const ErrorCode &err_code,
+        const std::string &err_message)
+{
+    LoggerD("Entered");
+    //store only first error
+    if (!m_is_error) {
+        m_err_code = err_code;
+        m_err_message = err_message;
+        m_is_error = true;
+    }
+}
+
+bool OperationCallbackData::isError() const
+{
+    LoggerD("Entered");
+    return m_is_error;
+}
+
+bool OperationCallbackData::isCanceled() const
+{
+    LoggerD("Enter");
+    return m_is_canceled;
+}
+
+void OperationCallbackData::setOperationId(long op_id)
+{
+    LoggerD("Entered");
+    m_op_id = op_id;
+}
+
+long OperationCallbackData::getOperationId() const
+{
+    LoggerD("Entered");
+    return m_op_id;
+}
+
+void OperationCallbackData::setCallbackId(double cid)
+{
+    LoggerD("Enter");
+    m_cid = cid;
+}
+
+double OperationCallbackData::getCallbackId() const
+{
+    LoggerD("Enter");
+    return m_cid;
+}
+
+void OperationCallbackData::setHandle(long handle)
+{
+    LoggerD("Enter");
+    m_handle = handle;
+}
+
+long OperationCallbackData::getHandle() const
+{
+    LoggerD("Enter");
+    return m_handle;
+}
+
+void OperationCallbackData::setIsCanceled(bool canceled)
+{
+    LoggerD("Enter");
+    m_is_canceled = canceled;
+}
+
+void OperationCallbackData::PostMessage(const char* msg) {
+  LoggerD("Enter");
+  Instance::PostMessage(&instance_, msg);
+}
+
+const ErrorCode& OperationCallbackData::getErrorCode() const
+{
+    LoggerD("Entered");
+    return m_err_code;
+}
+
+const std::string& OperationCallbackData::getErrorMessage() const
+{
+    LoggerD("Entered");
+    return m_err_message;
+}
+
+ArchiveCallbackType OperationCallbackData::getCallbackType() const
+{
+    LoggerD("Entered");
+    return m_callback_type;
+}
+
+ArchiveFilePtr OperationCallbackData::getArchiveFile() const
+{
+    LoggerD("Enter");
+    return m_caller_instance;
+}
+
+void OperationCallbackData::setArchiveFile(ArchiveFilePtr caller)
+{
+    LoggerD("Enter");
+    m_caller_instance = caller;
+}
+
+//----------------------------------------------------------------------------------------
+//OpenCallbackData
+//----------------------------------------------------------------------------------------
+
+OpenCallbackData::OpenCallbackData(ArchiveInstance& instance):
+    OperationCallbackData(OPEN_CALLBACK_DATA, instance)
+{
+    LoggerD("Entered");
+}
+
+OpenCallbackData::~OpenCallbackData()
+{
+    LoggerD("Entered");
+}
+
+PlatformResult OpenCallbackData::executeOperation(ArchiveFilePtr archive_file_ptr)
+{
+    LoggerE("Entered");
+
+    filesystem::FilePtr file = archive_file_ptr->getFile();
+    if (!file) {
+        LoggerE("File is null");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "File is null");
+    }
+    filesystem::NodePtr node = file->getNode();
+    if(!node) {
+        LoggerE("Node is null");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Node is null");
+    }
+    const FileMode fm = archive_file_ptr->m_file_mode;
+    unsigned long long size = 0;
+    PlatformResult result = node->getSize(&size);
+    if (result.error_code() != ErrorCode::NO_ERROR) {
+        LoggerE("Fail node->getSize()");
+        return result;
+    }
+    if (0 == size) {
+        if(FileMode::READ_WRITE == fm ||
+                FileMode::WRITE == fm ||
+                FileMode::ADD == fm) {
+            LoggerD("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 {
+            LoggerE("The file is empty throwing: InvalidValuesException - Invalid ZIP archive");
+            return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid ZIP archive");
+        }
+    }
+    else {
+        archive_file_ptr->setIsOpen(true);
+        result = archive_file_ptr->updateListOfEntries();
+        if (result.error_code() != ErrorCode::NO_ERROR) {
+            LoggerE("Fail archive_file_ptr->updateListOfEntries()");
+            return result;
+        }
+    }
+
+    guint id = g_idle_add(ArchiveFile::openTaskCompleteCB, this);
+    if (!id) {
+        LoggerE("g_idle_add fails");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "g_idle_add fails");
+    }
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+//----------------------------------------------------------------------------------------
+//GetEntriesCallbackData
+//----------------------------------------------------------------------------------------
+
+GetEntriesCallbackData::GetEntriesCallbackData(ArchiveInstance& instance):
+    OperationCallbackData(GET_ENTRIES_CALLBACK_DATA, instance)
+{
+    LoggerD("Entered");
+}
+
+GetEntriesCallbackData::~GetEntriesCallbackData()
+{
+    LoggerD("Entered");
+}
+
+ArchiveFileEntryPtrMapPtr GetEntriesCallbackData::getEntries() const
+{
+    LoggerD("Entered");
+    return m_entries;
+}
+
+void GetEntriesCallbackData::setEntries(ArchiveFileEntryPtrMapPtr entries)
+{
+    LoggerD("Entered");
+    m_entries = entries;
+}
+
+PlatformResult GetEntriesCallbackData::executeOperation(ArchiveFilePtr archive_file_ptr)
+{
+    LoggerD("Entered");
+
+    setEntries(archive_file_ptr->getEntryMap());
+
+    guint id = g_idle_add(ArchiveFile::getEntriesTaskCompleteCB, this);
+    if (!id) {
+        LoggerE("g_idle_add fails");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "g_idle_add fails");
+    }
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+//----------------------------------------------------------------------------------------
+//GetEntryByNameCallbackData
+//----------------------------------------------------------------------------------------
+
+GetEntryByNameCallbackData::GetEntryByNameCallbackData(ArchiveInstance& instance):
+    OperationCallbackData(GET_ENTRY_BY_NAME_CALLBACK_DATA, instance)
+{
+    LoggerD("Entered");
+}
+
+GetEntryByNameCallbackData::~GetEntryByNameCallbackData()
+{
+    LoggerD("Entered");
+}
+
+const std::string& GetEntryByNameCallbackData::getName() const
+{
+    LoggerD("Entered");
+    return m_name;
+}
+
+void GetEntryByNameCallbackData::setName(const std::string& name)
+{
+    LoggerD("Entered");
+    m_name = name;
+}
+
+ArchiveFileEntryPtr GetEntryByNameCallbackData::getFileEntry() const
+{
+    LoggerD("Entered");
+    return m_file_entry;
+}
+
+void GetEntryByNameCallbackData::setFileEntry(ArchiveFileEntryPtr entry)
+{
+    LoggerD("Entered");
+    m_file_entry = entry;
+}
+
+PlatformResult GetEntryByNameCallbackData::executeOperation(ArchiveFilePtr archive_file_ptr)
+{
+    LoggerD("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() + "/";
+        LoggerD("GetEntryByName Trying directory: [%s]", try_directory.c_str());
+        it = entries->find(try_directory);
+    }
+
+    if (it == entries->end()) {
+        LoggerE("GetEntryByName Entry with name: [%s] not found", getName().c_str());
+        LoggerE("Throwing NotFoundException - Entry not found");
+        return PlatformResult(ErrorCode::NOT_FOUND_ERR, "Entry not found");
+    }
+
+    setFileEntry(it->second);
+
+    guint id = g_idle_add(ArchiveFile::getEntryByNameTaskCompleteCB, this);
+    if (!id) {
+        LoggerE("g_idle_add fails");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "g_idle_add fails");
+    }
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+//----------------------------------------------------------------------------------------
+//BaseProgressCallback
+//----------------------------------------------------------------------------------------
+
+BaseProgressCallback::BaseProgressCallback(ArchiveCallbackType callback_type, ArchiveInstance& instance):
+    OperationCallbackData(callback_type, instance),
+    m_overwrite(false)
+{
+    LoggerD("Entered");
+}
+
+BaseProgressCallback::~BaseProgressCallback()
+{
+    LoggerD("Entered");
+}
+
+bool BaseProgressCallback::getOverwrite() const
+{
+    LoggerD("Entered");
+    return m_overwrite;
+}
+
+void BaseProgressCallback::setOverwrite(bool overwrite)
+{
+    LoggerD("Entered");
+    m_overwrite = overwrite;
+}
+
+struct ProgressHolder
+{
+    ProgressHolder() :
+        overall_progress(0.0),
+        callback(NULL)
+    {
+    };
+
+    double overall_progress;
+    ArchiveFileEntryPtr currently_processed_entry;
+    BaseProgressCallback* callback;
+};
+
+void BaseProgressCallback::callSuccessCallbackOnMainThread()
+{
+    LoggerD("Entered");
+
+    guint id = g_idle_add(BaseProgressCallback::callSuccessCallbackCB,
+            static_cast<void*>(this));
+    if (!id) {
+        LoggerE("g_idle_add fails - success callback will not be called");
+    }
+}
+
+gboolean BaseProgressCallback::callSuccessCallbackCB(void* data)
+{
+    LoggerD("Entered");
+
+    BaseProgressCallback* callback = static_cast<BaseProgressCallback*>(data);
+    if (!callback) {
+        LoggerE("callback pointer is NULL");
+        return false;
+    }
+
+    std::unique_ptr<BaseProgressCallback> cb_ptr(callback);
+
+    picojson::value val = picojson::value(picojson::object());
+    picojson::object& obj = val.get<picojson::object>();
+    obj[JSON_CALLBACK_ID] = picojson::value(callback->getCallbackId());
+
+    if (!callback->isError()) {
+        obj[JSON_ACTION] = picojson::value(JSON_CALLBACK_SUCCCESS);
+
+        LoggerD("%s", val.serialize().c_str());
+
+        Instance::PostMessage(&callback->instance_, val.serialize().c_str());
+    } else {
+        LoggerW("Not calling error callback in such case");
+    }
+
+    callback->setArchiveFile(ArchiveFilePtr());
+    ArchiveManager::getInstance().eraseElementFromArchiveFileMap(callback->m_op_id);
+
+    return false;
+}
+
+void BaseProgressCallback::callProgressCallback(long operationId,
+        double value,
+        const std::string& filename,
+        double callbackId)
+{
+    LoggerD("Entered");
+
+    picojson::value val = picojson::value(picojson::object());
+    picojson::object& obj = val.get<picojson::object>();
+    obj[JSON_CALLBACK_ID] = picojson::value(callbackId);
+    obj[JSON_DATA] = picojson::value(picojson::object());
+    picojson::object& args = obj[JSON_DATA].get<picojson::object>();
+
+    obj[JSON_ACTION] = picojson::value(JSON_CALLBACK_PROGRESS);
+    obj[JSON_CALLBACK_KEEP] = picojson::value(true);
+
+    args[PARAM_OPERATION_ID] = picojson::value(static_cast<double>(operationId));
+    args[PARAM_VALUE] = picojson::value(value);
+    args[PARAM_FILENAME] = picojson::value(filename);
+
+    LoggerD("%s", val.serialize().c_str());
+
+    Instance::PostMessage(&instance_, val.serialize().c_str());
+}
+
+void BaseProgressCallback::callProgressCallbackOnMainThread(const double progress,
+        ArchiveFileEntryPtr current_entry)
+{
+    LoggerD("Entered");
+
+    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) {
+            LoggerE("g_idle_add fails");
+            delete ph;
+            ph = NULL;
+        }
+    } else {
+        LoggerE("Couldn't allocate ProgressHolder");
+    }
+}
+
+gboolean BaseProgressCallback::callProgressCallbackCB(void* data)
+{
+    LoggerD("Entered");
+
+    ProgressHolder* ph = static_cast<ProgressHolder*>(data);
+    if (!ph) {
+        LoggerE("ph is null");
+        return false;
+    }
+
+    std::unique_ptr<ProgressHolder> ph_ptr(ph);
+    if (!ph->callback) {
+        LoggerE("ph->callback is null");
+        return false;
+    }
+
+    LoggerW("STUB Not checking if context is still alive");
+
+    ph->callback->callProgressCallback(
+            ph->callback->m_op_id,
+            ph->overall_progress,
+            ph->currently_processed_entry->getName(),
+            ph->callback->m_cid);
+
+    return false;
+}
+
+//----------------------------------------------------------------------------------------
+//AddProgressCallback
+//----------------------------------------------------------------------------------------
+
+AddProgressCallback::AddProgressCallback(ArchiveInstance& instance):
+    BaseProgressCallback(ADD_PROGRESS_CALLBACK, instance)
+{
+    LoggerD("Entered");
+}
+
+AddProgressCallback::~AddProgressCallback()
+{
+    LoggerD("Entered");
+}
+
+ArchiveFileEntryPtr AddProgressCallback::getFileEntry() const
+{
+    LoggerD("Entered");
+    return m_file_entry;
+}
+
+void AddProgressCallback::setFileEntry(ArchiveFileEntryPtr file_entry)
+{
+    LoggerD("Entered");
+    m_file_entry = file_entry;
+}
+
+void AddProgressCallback::setBasePath(const std::string& path)
+{
+    LoggerD("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(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()
+{
+    LoggerD("Entered");
+    return m_base_path;
+}
+
+const std::string& AddProgressCallback::getBaseVirtualPath()
+{
+    LoggerD("Entered");
+    return m_base_virt_path;
+}
+
+PlatformResult AddProgressCallback::executeOperation(ArchiveFilePtr archive_file_ptr)
+{
+    LoggerD("Entered");
+
+    if(!m_file_entry) {
+        LoggerE("ArchiveFileEntry is not set in callback");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Could not add file to archive");
+    }
+
+    if(!archive_file_ptr) {
+        LoggerE("archive_file_ptr is NULL");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Could not extract archive file entry");
+    }
+
+    AddProgressCallback* callback = this;
+
+    ZipPtr zip;
+    PlatformResult result = archive_file_ptr->createZipObject(&zip);
+    if (result.error_code() != ErrorCode::NO_ERROR) {
+      LoggerE("archive_file_ptr->createZipObject()");
+      return result;
+    }
+
+    result = zip->addFile(callback);
+    if (result.error_code() != ErrorCode::NO_ERROR) {
+      LoggerE("zip->addFile()");
+      return result;
+    }
+
+    // Zip is no more needed but it locks file opening while
+    // it is needed to read entries from file
+    result = zip->close();
+    if (result.error_code() != ErrorCode::NO_ERROR) {
+      LoggerE("zip->close()");
+      return result;
+    }
+
+    //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);
+
+    LoggerD("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
+
+    return archive_file_ptr->updateListOfEntries();
+}
+
+//----------------------------------------------------------------------------------------
+//ExtractAllProgressCallback
+//----------------------------------------------------------------------------------------
+
+ExtractAllProgressCallback::ExtractAllProgressCallback(ArchiveInstance& instance):
+    BaseProgressCallback(EXTRACT_ALL_PROGRESS_CALLBACK, instance),
+    m_files_to_extract(0),
+    m_expected_decompressed_size(0),
+    m_current_file_size(0),
+    m_current_file_extracted_bytes(0),
+    m_files_extracted(0),
+    m_progress_overall(0),
+    m_overall_decompressed(0)
+{
+    LoggerD("Entered");
+}
+
+ExtractAllProgressCallback::~ExtractAllProgressCallback()
+{
+    LoggerD("Entered");
+}
+
+filesystem::FilePtr ExtractAllProgressCallback::getDirectory() const
+{
+    LoggerD("Entered");
+    return m_directory;
+}
+
+void ExtractAllProgressCallback::setDirectory(filesystem::FilePtr directory)
+{
+    LoggerD("Entered");
+    m_directory = directory;
+}
+
+void ExtractAllProgressCallback::startedExtractingFile(unsigned long current_file_size)
+{
+    LoggerD("Entered");
+
+    m_current_file_size = current_file_size;
+    m_current_file_extracted_bytes = 0;
+}
+
+void ExtractAllProgressCallback::extractedPartOfFile(unsigned long bytes_decompressed)
+{
+    LoggerD("Entered");
+
+    m_current_file_extracted_bytes += bytes_decompressed;
+    updateOverallProgress(bytes_decompressed);
+}
+
+void ExtractAllProgressCallback::finishedExtractingFile()
+{
+    LoggerD("Entered");
+
+    m_current_file_size = 0;
+    m_current_file_extracted_bytes = 0;
+    ++m_files_extracted;
+    updateOverallProgress(0);
+}
+
+void ExtractAllProgressCallback::updateOverallProgress(unsigned long bytes_decompressed)
+{
+    LoggerD("Entered");
+
+    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);
+
+    LoggerD("%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
+{
+    LoggerD("Entered");
+
+    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
+{
+    LoggerD("Entered");
+
+    return m_progress_overall;
+}
+
+PlatformResult ExtractAllProgressCallback::executeOperation(ArchiveFilePtr archive_file_ptr)
+{
+    LoggerD("Entered");
+    return archive_file_ptr->extractAllTask(this);
+}
+
+void ExtractAllProgressCallback::setExpectedDecompressedSize(unsigned long exp_dec_size)
+{
+    LoggerD("Entered");
+
+    m_expected_decompressed_size = exp_dec_size;
+}
+
+unsigned long ExtractAllProgressCallback::getExpectedDecompressedSize() const
+{
+    LoggerD("Entered");
+
+    return m_expected_decompressed_size;
+}
+
+void ExtractAllProgressCallback::setNumberOfFilesToExtract(unsigned long files_count)
+{
+    LoggerD("Entered");
+
+    m_files_to_extract = files_count;
+}
+
+unsigned long ExtractAllProgressCallback::getNumberOfFilesToExtract() const
+{
+    LoggerD("Entered");
+
+    return m_files_to_extract;
+}
+
+//----------------------------------------------------------------------------------------
+//OperationCanceledException
+//----------------------------------------------------------------------------------------
+
+const char* OPERATION_CANCELED_EXCEPTION = "OperationCanceledException";
+
+OperationCanceledException::OperationCanceledException(const char* message)
+{
+    LoggerD("Entered");
+}
+
+//----------------------------------------------------------------------------------------
+//ExtractEntryProgressCallback
+//----------------------------------------------------------------------------------------
+
+ExtractEntryProgressCallback::ExtractEntryProgressCallback(ArchiveInstance& instance):
+        ExtractAllProgressCallback(instance),
+        m_strip_name(false)
+{
+    LoggerD("Entered");
+    m_callback_type = EXTRACT_ENTRY_PROGRESS_CALLBACK;
+}
+
+ExtractEntryProgressCallback::~ExtractEntryProgressCallback()
+{
+    LoggerD("Entered");
+}
+
+ArchiveFileEntryPtr ExtractEntryProgressCallback::getArchiveFileEntry()
+{
+    LoggerD("Entered");
+    return m_archive_file_entry;
+}
+
+void ExtractEntryProgressCallback::setArchiveFileEntry(ArchiveFileEntryPtr afentry)
+{
+    LoggerD("Entered");
+    m_archive_file_entry = afentry;
+}
+
+void ExtractEntryProgressCallback::setStripName(bool strip_name)
+{
+    LoggerD("Entered");
+    m_strip_name = strip_name;
+}
+
+bool ExtractEntryProgressCallback::getStripName() const
+{
+    LoggerD("Entered");
+    return m_strip_name;
+}
+
+void ExtractEntryProgressCallback::setStripBasePath(
+        const std::string& strip_base_path)
+{
+    LoggerD("Entered");
+    m_strip_base_path = strip_base_path;
+}
+
+const std::string& ExtractEntryProgressCallback::getStripBasePath() const
+{
+    LoggerD("Entered");
+    return m_strip_base_path;
+}
+
+PlatformResult ExtractEntryProgressCallback::executeOperation(ArchiveFilePtr archive_file_ptr)
+{
+    LoggerD("Entered");
+
+    if(!m_archive_file_entry) {
+        LoggerE("ArchiveFileEntry is not set in callback");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Could not extract archive file entry");
+    }
+
+    if(!archive_file_ptr) {
+        LoggerE("archive_file_ptr is NULL");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Could not extract archive file entry");
+    }
+
+    UnZipPtr unzip;
+    PlatformResult result = archive_file_ptr->createUnZipObject(&unzip);
+    if (result.error_code() != ErrorCode::NO_ERROR) {
+      LoggerE("archive_file_ptr->createUnZipObject()");
+      return result;
+    }
+
+    return unzip->extractTo(this);
+}
+
+} //namespace archive
+} //namespace extension
diff --git a/webWidgetTCT_device/src/archive/archive_callback_data.h b/webWidgetTCT_device/src/archive/archive_callback_data.h
new file mode 100755 (executable)
index 0000000..4815e9e
--- /dev/null
@@ -0,0 +1,275 @@
+/*
+ * Copyright (c) 2015 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 __ARCHIVE_CALLBACK_DATA_H__
+#define __ARCHIVE_CALLBACK_DATA_H__
+
+#include <string>
+#include <memory>
+#include <glib.h>
+
+#include "common/platform_result.h"
+#include "filesystem_file.h"
+#include "archive_file_entry.h"
+
+namespace extension {
+namespace archive {
+
+using namespace common;
+using namespace filesystem;
+
+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 ArchiveInstance;
+
+class OperationCallbackData
+{
+public:
+    OperationCallbackData(ArchiveCallbackType callback_type, ArchiveInstance& instance);
+    virtual ~OperationCallbackData();
+
+    void setError(const ErrorCode &err_code,
+            const std::string &err_message);
+    bool isError() const;
+    const ErrorCode& getErrorCode() const;
+    const std::string& getErrorMessage() const;
+
+    void setOperationId(long op_id);
+    long getOperationId() const;
+    void setCallbackId(double cid);
+    double getCallbackId() const;
+    void setHandle(long handle);
+    long getHandle() const;
+
+    ArchiveCallbackType getCallbackType() const;
+
+    virtual PlatformResult executeOperation(ArchiveFilePtr archive_file_ptr) = 0;
+
+    ArchiveFilePtr getArchiveFile() const;
+    void setArchiveFile(ArchiveFilePtr caller);
+
+    bool isCanceled() const;
+    void setIsCanceled(bool canceled);
+
+    void PostMessage(const char* msg);
+
+protected:
+    ArchiveCallbackType m_callback_type;
+    long m_op_id;
+    double m_cid;
+    long m_handle;
+    ArchiveInstance& instance_;
+
+private:
+    bool m_is_error;
+    bool m_is_canceled;
+    ErrorCode m_err_code;
+    std::string m_err_message;
+
+    ArchiveFilePtr m_caller_instance;
+};
+
+class OpenCallbackData : public OperationCallbackData
+{
+public:
+    explicit OpenCallbackData(ArchiveInstance& instance);
+    virtual ~OpenCallbackData();
+
+    virtual PlatformResult executeOperation(ArchiveFilePtr archive_file_ptr);
+
+private:
+    std::string m_filename;
+};
+
+class GetEntriesCallbackData : public OperationCallbackData
+{
+public:
+    explicit GetEntriesCallbackData(ArchiveInstance& instance);
+    virtual ~GetEntriesCallbackData();
+
+    ArchiveFileEntryPtrMapPtr getEntries() const;
+    void setEntries(ArchiveFileEntryPtrMapPtr entries);
+
+    virtual PlatformResult executeOperation(ArchiveFilePtr archive_file_ptr);
+
+private:
+    ArchiveFileEntryPtrMapPtr m_entries;
+};
+
+class GetEntryByNameCallbackData : public OperationCallbackData
+{
+public:
+    explicit GetEntryByNameCallbackData(ArchiveInstance& instance);
+    virtual ~GetEntryByNameCallbackData();
+
+    const std::string& getName() const;
+    void setName(const std::string& name);
+
+    ArchiveFileEntryPtr getFileEntry() const;
+    void setFileEntry(ArchiveFileEntryPtr entry);
+
+    virtual PlatformResult executeOperation(ArchiveFilePtr archive_file_ptr);
+private:
+    std::string m_name;
+    ArchiveFileEntryPtr m_file_entry;
+
+};
+
+class BaseProgressCallback : public OperationCallbackData
+{
+public:
+    BaseProgressCallback(ArchiveCallbackType callback_type, ArchiveInstance& instance);
+    virtual ~BaseProgressCallback();
+
+    bool getOverwrite() const;
+    void setOverwrite(bool overwrite);
+
+    void callProgressCallbackOnMainThread(const double progress,
+            ArchiveFileEntryPtr current_entry);
+    void callSuccessCallbackOnMainThread();
+
+    virtual PlatformResult executeOperation(ArchiveFilePtr archive_file_ptr) = 0;
+
+protected:
+    void callProgressCallback(long operationId,
+            double value,
+            const std::string& filename,
+            double callbackId);
+
+private:
+    static gboolean callProgressCallbackCB(void* data);
+    static gboolean callSuccessCallbackCB(void* data);
+
+    bool m_overwrite;
+};
+
+class AddProgressCallback : public BaseProgressCallback
+{
+public:
+    explicit AddProgressCallback(ArchiveInstance& instance);
+    virtual ~AddProgressCallback();
+
+    virtual PlatformResult 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:
+    explicit ExtractAllProgressCallback(ArchiveInstance& instance);
+    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 PlatformResult 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:
+    explicit ExtractEntryProgressCallback(ArchiveInstance& instance);
+    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 PlatformResult executeOperation(ArchiveFilePtr archive_file_ptr);
+
+private:
+    ArchiveFileEntryPtr m_archive_file_entry;
+    bool m_strip_name;
+    std::string m_strip_base_path;
+};
+
+class OperationCanceledException {
+public:
+    OperationCanceledException(const char* message = "Operation Canceled");
+};
+
+}
+}
+
+#endif //__ARCHIVE_CALLBACK_DATA_H__
diff --git a/webWidgetTCT_device/src/archive/archive_extension.cc b/webWidgetTCT_device/src/archive/archive_extension.cc
new file mode 100755 (executable)
index 0000000..d0c2b9d
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2015 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 "archive_extension.h"
+#include "archive_instance.h"
+#include "common/logger.h"
+
+// This will be generated from archive_api.js
+extern const char kSource_archive_api[];
+
+common::Extension* CreateExtension()
+{
+    LoggerD("Enter");
+    return new ArchiveExtension;
+}
+
+ArchiveExtension::ArchiveExtension()
+{
+    LoggerD("Enter");
+    SetExtensionName("tizen.archive");
+    SetJavaScriptAPI(kSource_archive_api);
+}
+
+ArchiveExtension::~ArchiveExtension()
+{
+    LoggerD("Enter");
+}
+
+common::Instance* ArchiveExtension::CreateInstance()
+{
+    LoggerD("Enter");
+    return new extension::archive::ArchiveInstance();
+}
diff --git a/webWidgetTCT_device/src/archive/archive_extension.h b/webWidgetTCT_device/src/archive/archive_extension.h
new file mode 100755 (executable)
index 0000000..3514201
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015 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 ARCHIVE_ARCHIVE_EXTENSION_H_
+#define ARCHIVE_ARCHIVE_EXTENSION_H_
+
+#include "common/extension.h"
+
+class ArchiveExtension: public common::Extension {
+public:
+    ArchiveExtension();
+    virtual ~ArchiveExtension();
+
+private:
+    virtual common::Instance* CreateInstance();
+};
+
+#endif // ARCHIVE_ARCHIVE_EXTENSION_H_
diff --git a/webWidgetTCT_device/src/archive/archive_file.cc b/webWidgetTCT_device/src/archive/archive_file.cc
new file mode 100755 (executable)
index 0000000..0649d74
--- /dev/null
@@ -0,0 +1,797 @@
+/*
+ * Copyright (c) 2015 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 "archive_file.h"
+
+#include "common/picojson.h"
+#include "common/logger.h"
+
+#include "archive_manager.h"
+#include "archive_utils.h"
+#include "defs.h"
+#include "un_zip.h"
+#include "zip.h"
+#include "archive_instance.h"
+
+using namespace common;
+
+namespace extension {
+namespace archive {
+
+Permission::Permission(bool r, bool w, bool rw, bool a){
+    LoggerD("Enter");
+    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_file_mode(),
+        m_decompressed_size(0),
+        m_is_open(false),
+        m_overwrite(false),
+        m_created_as_new_empty_archive(false)
+{
+    LoggerD("Entered");
+}
+
+ArchiveFile::ArchiveFile(FileMode file_mode) :
+        enable_shared_from_this<ArchiveFile>(),
+        m_decompressed_size(0),
+        m_is_open(false),
+        m_overwrite(false),
+        m_created_as_new_empty_archive(false)
+{
+    LoggerD("Enter");
+    m_file_mode = file_mode;
+}
+
+ArchiveFile::~ArchiveFile()
+{
+    LoggerD("Entered");
+
+    if(m_entry_map) {
+        LoggerD("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)
+{
+    LoggerD("Entered");
+
+    auto callback = static_cast<OperationCallbackData*>(data);
+    if (!callback) {
+        LoggerE("callback is null");
+        return false;
+    }
+
+    auto archive_file = callback->getArchiveFile();
+
+    picojson::value val = picojson::value(picojson::object());
+    picojson::object& obj = val.get<picojson::object>();
+    obj[JSON_CALLBACK_ID] = picojson::value(callback->getCallbackId());
+    obj[JSON_DATA] = picojson::value(picojson::object());
+
+    picojson::object& args = obj[JSON_DATA].get<picojson::object>();
+
+    if (!callback->isError()) {
+        long handle = ArchiveManager::getInstance().addPrivData(archive_file);
+
+        obj[JSON_ACTION] = picojson::value(JSON_CALLBACK_SUCCCESS);
+
+        std::string fm_str;
+        PlatformResult result = fileModeToString(archive_file->getFileMode(), &fm_str);
+        if (result.error_code() != ErrorCode::NO_ERROR) {
+            LoggerE("%s (%d)", result.message().c_str(), result.error_code());
+            delete callback;
+            callback = NULL;
+            return false;
+        }
+
+        args[ARCHIVE_FILE_ATTR_MODE] = picojson::value(fm_str);
+        args[ARCHIVE_FILE_ATTR_DECOMPRESSED_SIZE] = picojson::value();
+        args[ARCHIVE_FILE_HANDLE] = picojson::value(static_cast<double>(handle));
+    } else {
+        obj[JSON_ACTION] = picojson::value(JSON_CALLBACK_ERROR);
+
+        args[ERROR_CALLBACK_CODE] = picojson::value(static_cast<double>(callback->getErrorCode()));
+        args[ERROR_CALLBACK_MESSAGE] = picojson::value(callback->getErrorMessage());
+    }
+
+    LoggerD("%s", val.serialize().c_str());
+
+    callback->PostMessage(val.serialize().c_str());
+
+    delete callback;
+    callback = NULL;
+
+    return false;
+}
+
+gboolean ArchiveFile::callErrorCallback(void* data)
+{
+    LoggerD("Entered");
+
+    auto callback = static_cast<OperationCallbackData*>(data);
+    if (!callback) {
+        LoggerE("callback is null");
+        return false;
+    }
+
+    picojson::value val = picojson::value(picojson::object());
+    picojson::object& obj = val.get<picojson::object>();
+    obj[JSON_CALLBACK_ID] = picojson::value(callback->getCallbackId());
+    obj[JSON_DATA] = picojson::value(picojson::object());
+
+    picojson::object& args = obj[JSON_DATA].get<picojson::object>();
+
+    if (!callback->isError()) {
+        LoggerW("The success callback should be not be called in this case");
+    } else {
+        obj[JSON_ACTION] = picojson::value(JSON_CALLBACK_ERROR);
+
+        args[ERROR_CALLBACK_CODE] = picojson::value(static_cast<double>(callback->getErrorCode()));
+        args[ERROR_CALLBACK_MESSAGE] = picojson::value(callback->getErrorMessage());
+    }
+
+    LoggerD("%s", val.serialize().c_str());
+
+    callback->PostMessage(val.serialize().c_str());
+
+    delete callback;
+    callback = NULL;
+
+    return false;
+}
+
+void* ArchiveFile::taskManagerThread(void *data)
+{
+    LoggerD("Entered");
+    ArchiveFileHolder* archive_file_holder = static_cast<ArchiveFileHolder*>(data);
+    if (!archive_file_holder) {
+        LoggerE("archive_file_holder is null");
+        return NULL;
+    }
+
+    if (!archive_file_holder->ptr){
+        LoggerE("archive_file is null");
+        delete archive_file_holder;
+        archive_file_holder = NULL;
+        return NULL;
+    }
+
+    PlatformResult result(ErrorCode::NO_ERROR);
+
+    while(true){
+        OperationCallbackData* callback = NULL;
+
+        result = PlatformResult(ErrorCode::NO_ERROR);
+
+        {
+            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) {
+            if (!callback->isCanceled()){
+                result = callback->executeOperation(archive_file_holder->ptr);
+            }
+
+            if (ErrorCode::OPERATION_CANCELED_ERR == result.error_code()) {
+                delete callback;
+                callback = NULL;
+            } else if (ErrorCode::NO_ERROR != result.error_code()) {
+                LoggerE("taskManagerThread fails, %d: %s", result.error_code(),
+                        result.message().c_str());
+                callback->setError(result.error_code(), result.message().c_str());
+                if (!g_idle_add(callErrorCallback, static_cast<void*>(callback))) {
+                    LoggerE("g_idle_add fails");
+                    delete callback;
+                    callback = NULL;
+                }
+            }
+        }
+
+        {
+            std::lock_guard<std::mutex> lock(archive_file_holder->ptr->m_mutex);
+            archive_file_holder->ptr->m_task_queue.pop_back();
+        }
+    }
+
+    delete archive_file_holder;
+    archive_file_holder = NULL;
+
+    return NULL;
+}
+
+PlatformResult ArchiveFile::addOperation(OperationCallbackData* callback)
+{
+    LoggerD("Entered callback type:%d", callback->getCallbackType());
+
+    const long operation_id = callback->getOperationId();
+    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) {
+            LoggerE("Memory allocation error");
+            return PlatformResult(ErrorCode::UNKNOWN_ERR, "Memory allocation error");
+        }
+        holder->ptr = shared_from_this();
+        if (pthread_create(&thread, NULL, taskManagerThread,
+                static_cast<void*>(holder))) {
+            LoggerE("Thread creation failed");
+            delete holder;
+            holder = NULL;
+            return PlatformResult(ErrorCode::UNKNOWN_ERR, "Thread creation failed");
+        }
+
+        if (pthread_detach(thread)) {
+            LoggerE("Thread detachment failed");
+        }
+    }
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult ArchiveFile::extractAllTask(ExtractAllProgressCallback* callback)
+{
+    LoggerD("Enter");
+    filesystem::FilePtr directory = callback->getDirectory();
+
+    if(!directory) {
+        LoggerE("Directory is null");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Directory is null");
+    } else {
+        if(!directory->getNode()){
+            LoggerE("Node in directory is null");
+            return PlatformResult(ErrorCode::UNKNOWN_ERR, "Node is null");
+        }
+    }
+
+    if(!m_file) {
+        LoggerE("File is null");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "File is null");
+    } else {
+        if(!m_file->getNode()){
+            LoggerE("Node in file is null");
+            return PlatformResult(ErrorCode::UNKNOWN_ERR, "Node in file is null");
+        }
+    }
+
+    // For explanation please see:
+    //    ArchiveFile.h m_created_as_new_empty_archive description
+    //
+    unsigned long long size = 0;
+    PlatformResult result = m_file->getNode()->getSize(&size);
+    if (result.error_code() != ErrorCode::NO_ERROR) {
+      LoggerE("Fail m_file->getNode()->getSize()");
+      return result;
+    }
+    if(size == 0) {
+        LoggerD("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();
+            return PlatformResult(ErrorCode::NO_ERROR);
+        }
+        else {
+            LoggerW("m_created_as_new_empty_archive is false");
+            LoggerE("Throwing InvalidStateException: File is not valid ZIP archive");
+            return PlatformResult(ErrorCode::INVALID_STATE_ERR, "File is not valid ZIP archive");
+        }
+    }
+
+    UnZipPtr unzip;
+    result = createUnZipObject(&unzip);
+    if (result.error_code() != ErrorCode::NO_ERROR) {
+      LoggerE("Fail createUnZipObject()");
+      return result;
+    }
+
+    return unzip->extractAllFilesTo(directory->getNode()->getPath()->getFullPath(), callback);
+}
+
+PlatformResult ArchiveFile::getEntries(GetEntriesCallbackData* callback)
+{
+    LoggerD("Entered");
+    if(!callback) {
+        LoggerE("callback is NULL");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Could not get list of files in archive");
+    }
+
+    if(!m_is_open){
+        LoggerE("ArchiveFile closed - operation not permitted");
+        return PlatformResult(ErrorCode::INVALID_STATE_ERR, "ArchiveFile closed - operation not permitted");
+    }
+
+    return addOperation(callback);
+}
+
+gboolean ArchiveFile::getEntriesTaskCompleteCB(void *data)
+{
+    LoggerD("Entered");
+    LoggerW("STUB Not calling success/error callback");
+
+    auto callback = static_cast<GetEntriesCallbackData*>(data);
+    if (!callback) {
+        LoggerE("callback is null");
+        return false;
+    }
+
+    picojson::value val = picojson::value(picojson::object());
+    picojson::object& obj = val.get<picojson::object>();
+    obj[JSON_CALLBACK_ID] = picojson::value(callback->getCallbackId());
+
+    if (!callback->isError()) {
+        obj[JSON_ACTION] = picojson::value(JSON_CALLBACK_SUCCCESS);
+        obj[JSON_DATA] = picojson::value(picojson::array());
+        picojson::array &arr = obj[JSON_DATA].get<picojson::array>();
+
+        ArchiveFileEntryPtrMapPtr entries = callback->getEntries();
+        for(auto it = entries->begin(); it != entries->end(); it++) {
+            picojson::value val = picojson::value(picojson::object());
+            picojson::object& obj = val.get<picojson::object>();
+
+            obj[ARCHIVE_FILE_ENTRY_ATTR_NAME] = picojson::value(
+                    it->second->getName());
+            obj[ARCHIVE_FILE_ENTRY_ATTR_SIZE] = picojson::value(
+                    static_cast<double>(it->second->getSize()));
+            obj[ARCHIVE_FILE_ENTRY_ATTR_MODIFIED] = picojson::value(
+                    static_cast<double>(it->second->getModified()));
+            obj[ARCHIVE_FILE_ENTRY_ATTR_COMPRESSED_SIZE] = picojson::value(
+                    static_cast<double>(it->second->getCompressedSize()));
+            obj[ARCHIVE_FILE_HANDLE] = picojson::value(
+                    static_cast<double>(callback->getHandle()));
+
+            arr.push_back(val);
+        }
+    } else {
+        obj[JSON_ACTION] = picojson::value(JSON_CALLBACK_ERROR);
+        obj[JSON_DATA] = picojson::value(picojson::object());
+        picojson::object& args = obj[JSON_DATA].get<picojson::object>();
+
+        args[ERROR_CALLBACK_CODE] = picojson::value(static_cast<double>(callback->getErrorCode()));
+        args[ERROR_CALLBACK_MESSAGE] = picojson::value(callback->getErrorMessage());
+    }
+
+    LoggerD("%s", val.serialize().c_str());
+
+    callback->PostMessage(val.serialize().c_str());
+
+    delete callback;
+    callback = NULL;
+
+    return false;
+}
+
+PlatformResult ArchiveFile::extractAll(ExtractAllProgressCallback *callback)
+{
+    LoggerD("Entered");
+    if(!callback) {
+        LoggerE("callback is NULL");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Could not extract all files from archive");
+    }
+
+    if(!m_is_open){
+        LoggerE("ArchiveFile closed - operation not permitted");
+        return PlatformResult(ErrorCode::INVALID_STATE_ERR, "ArchiveFile closed - operation not permitted");
+    }
+
+    return addOperation(callback);
+}
+
+PlatformResult ArchiveFile::extractEntryTo(ExtractEntryProgressCallback* callback)
+{
+    LoggerD("Entered");
+    if(!callback) {
+        LoggerE("callback is NULL");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "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
+    if(!m_is_open) {
+        LoggerE("Archive is not opened");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Archive is not opened");
+    }
+
+    return addOperation(callback);
+}
+
+
+PlatformResult ArchiveFile::add(AddProgressCallback *callback)
+{
+    LoggerD("Entered");
+    if(!callback) {
+        LoggerE("callback is NULL");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Could not add file to archive");
+    }
+    if(FileMode::READ == m_file_mode) {
+        LoggerE("Trying to add file when READ access mode selected");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Add not allowed for \"r\" access mode");
+    }
+
+    if(!m_is_open){
+        LoggerE("ArchiveFile closed - operation not permitted");
+        return PlatformResult(ErrorCode::INVALID_STATE_ERR, "ArchiveFile closed - operation not permitted");
+    }
+
+    return addOperation(callback);
+}
+
+void ArchiveFile::close()
+{
+    LoggerD("Entered");
+
+    if(!m_is_open){
+        LoggerD("Archive already closed");
+    }
+    m_is_open = false;
+
+    return;
+}
+
+PlatformResult ArchiveFile::getEntryByName(GetEntryByNameCallbackData* callback)
+{
+    LoggerD("Entered");
+    if(!callback) {
+        LoggerE("callback is NULL");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Could not get archive file entries by name");
+    }
+
+    if(!m_is_open){
+        LoggerE("ArchiveFile closed - operation not permitted");
+        return PlatformResult(ErrorCode::INVALID_STATE_ERR, "ArchiveFile closed - operation not permitted");
+    }
+
+    return addOperation(callback);
+}
+
+gboolean ArchiveFile::getEntryByNameTaskCompleteCB(void *data)
+{
+    LoggerD("Entered");
+
+    auto callback = static_cast<GetEntryByNameCallbackData*>(data);
+    if (!callback) {
+        LoggerE("callback is null");
+        return false;
+    }
+
+    picojson::value val = picojson::value(picojson::object());
+    picojson::object& obj = val.get<picojson::object>();
+    obj[JSON_CALLBACK_ID] = picojson::value(callback->getCallbackId());
+    obj[JSON_DATA] = picojson::value(picojson::object());
+    picojson::object& args = obj[JSON_DATA].get<picojson::object>();
+
+    if (!callback->isError()) {
+        obj[JSON_ACTION] = picojson::value(JSON_CALLBACK_SUCCCESS);
+
+        ArchiveFileEntryPtr ent = callback->getFileEntry();
+
+        args[ARCHIVE_FILE_ENTRY_ATTR_NAME] = picojson::value(ent->getName());
+        args[ARCHIVE_FILE_ENTRY_ATTR_SIZE] = picojson::value(
+                static_cast<double>(ent->getSize()));
+        args[ARCHIVE_FILE_ENTRY_ATTR_MODIFIED] = picojson::value(
+                static_cast<double>(ent->getModified()));
+        args[ARCHIVE_FILE_ENTRY_ATTR_COMPRESSED_SIZE] = picojson::value(
+                static_cast<double>(ent->getCompressedSize()));
+        args[ARCHIVE_FILE_HANDLE] = picojson::value(
+                static_cast<double>(callback->getHandle()));
+    } else {
+        obj[JSON_ACTION] = picojson::value(JSON_CALLBACK_ERROR);
+
+        args[ERROR_CALLBACK_CODE] = picojson::value(static_cast<double>(callback->getErrorCode()));
+        args[ERROR_CALLBACK_MESSAGE] = picojson::value(callback->getErrorMessage());
+    }
+
+    LoggerD("%s", val.serialize().c_str());
+
+    callback->PostMessage(val.serialize().c_str());
+
+    delete callback;
+    callback = NULL;
+
+    return false;
+}
+
+filesystem::FilePtr ArchiveFile::getFile() const
+{
+    LoggerD("Entered");
+    return m_file;
+}
+
+void ArchiveFile::setFile(filesystem::FilePtr file)
+{
+    LoggerD("Entered");
+    m_file = file;
+}
+
+bool ArchiveFile::isOverwrite() const
+{
+    return m_overwrite;
+}
+
+void ArchiveFile::setOverwrite(bool overwrite)
+{
+    LoggerD("Entered");
+    m_overwrite = overwrite;
+}
+
+unsigned long ArchiveFile::getDecompressedSize() const
+{
+    LoggerD("Entered");
+    return m_decompressed_size;
+}
+
+void ArchiveFile::setDecompressedSize(unsigned long decompressed_size)
+{
+    LoggerD("Entered");
+    m_decompressed_size = decompressed_size;
+}
+
+bool ArchiveFile::isOpen() const
+{
+    LoggerD("Entered");
+    return m_is_open;
+}
+
+void ArchiveFile::setIsOpen(bool is_open)
+{
+    LoggerD("Entered");
+    m_is_open = is_open;
+}
+
+ArchiveFileEntryPtrMapPtr ArchiveFile::getEntryMap() const
+{
+    LoggerD("Entered");
+    return m_entry_map;
+}
+
+void ArchiveFile::setEntryMap(ArchiveFileEntryPtrMapPtr entries)
+{
+    LoggerD("Entered");
+
+    if(m_entry_map) {
+        LoggerD("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;
+
+    LoggerD("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);
+        }
+    }
+}
+
+PlatformResult ArchiveFile::createUnZipObject(UnZipPtr* unzip)
+{
+    LoggerD("Entered");
+    if(!m_is_open) {
+        LoggerE("File is not opened");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "File is not opened");
+    }
+
+    if (!m_file) {
+        LoggerE("m_file is null");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "File is null");
+    }
+
+    filesystem::NodePtr node = m_file->getNode();
+    if(!node) {
+        LoggerE("Node is null");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "File is null");
+    }
+
+    return UnZip::open(m_file->getNode()->getPath()->getFullPath(), unzip);
+}
+
+PlatformResult ArchiveFile::createZipObject(ZipPtr* zip)
+{
+    LoggerD("Entered");
+    if(!m_is_open) {
+        LoggerE("File is not opened");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "File is not opened");
+    }
+
+    if (!m_file) {
+        LoggerE("m_file is null");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "File is null");
+    }
+
+    filesystem::NodePtr node = m_file->getNode();
+    if(!node) {
+        LoggerE("Node is null");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Node is null");
+    }
+
+    return Zip::open(m_file->getNode()->getPath()->getFullPath(), zip);
+}
+
+bool ArchiveFile::isAllowedOperation(const std::string& method_name)
+{
+    LoggerD("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
+{
+   LoggerD("Entered");
+   return m_file_mode;
+}
+
+void ArchiveFile::setFileMode(FileMode file_mode)
+{
+    LoggerD("Entered");
+    m_file_mode = file_mode;
+}
+
+void ArchiveFile::setCreatedAsNewEmptyArchive(bool new_and_empty)
+{
+    LoggerD("Entered");
+    m_created_as_new_empty_archive = new_and_empty;
+}
+
+bool ArchiveFile::isCreatedAsNewEmptyArchive() const
+{
+    LoggerD("Entered");
+    return m_created_as_new_empty_archive;
+}
+
+PlatformResult ArchiveFile::updateListOfEntries()
+{
+    LoggerD("Entered");
+    // For explanation please see:
+    //    ArchiveFile.h m_created_as_new_empty_archive description
+    //
+    unsigned long long size = 0;
+    PlatformResult result = m_file->getNode()->getSize(&size);
+    if (result.error_code() != ErrorCode::NO_ERROR) {
+      return result;
+    }
+
+    if(size == 0) {
+        LoggerD("Zip file: %s is empty",
+                m_file->getNode()->getPath()->getFullPath().c_str());
+
+        if(m_created_as_new_empty_archive) {
+            LoggerD("OK this is empty archive = nothing to do yet");
+            return PlatformResult(ErrorCode::NO_ERROR);
+        }
+        else {
+            LoggerW("m_created_as_new_empty_archive is false");
+            LoggerE("Throwing InvalidStateException: File is not valid ZIP archive");
+            return PlatformResult(ErrorCode::INVALID_STATE_ERR, "File is not valid ZIP archive");
+        }
+    }
+
+    UnZipPtr unzip;
+    result = createUnZipObject(&unzip);
+    if (result.error_code() != ErrorCode::NO_ERROR) {
+      LoggerD("Fail createUnZipObject()");
+      return result;
+    }
+
+    unsigned long decompressedSize = 0;
+    ArchiveFileEntryPtrMapPtr emap;
+    result = unzip->listEntries(&decompressedSize, &emap);
+    if (result.error_code() != ErrorCode::NO_ERROR) {
+      LoggerD("Fail unzip->listEntries()");
+      return result;
+    }
+
+    setEntryMap(emap);
+    setDecompressedSize(decompressedSize);
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+bool ArchiveFile::isEntryWithNameInArchive(const std::string& name_in_zip,
+        bool* out_is_directory,
+        std::string* out_matching_name)
+{
+    LoggerD("Enter");
+
+    if(!m_entry_map) {
+        LoggerW("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) {
+        LoggerE("Fail: name do not 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
+} // extension
diff --git a/webWidgetTCT_device/src/archive/archive_file.h b/webWidgetTCT_device/src/archive/archive_file.h
new file mode 100755 (executable)
index 0000000..61f6a6d
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2015 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_ARCHIVE_ARCHIVE_FILE_H_
+#define _TIZEN_ARCHIVE_ARCHIVE_FILE_H_
+
+#include <deque>
+#include <memory>
+#include <mutex>
+#include <string>
+#include <map>
+
+#include "archive_callback_data.h"
+#include "filesystem_file.h"
+#include "un_zip.h"
+#include "zip.h"
+#include "archive_file_entry.h"
+
+namespace extension {
+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();
+
+    common::PlatformResult getEntries(GetEntriesCallbackData* callback);
+    common::PlatformResult getEntryByName(GetEntryByNameCallbackData* callback);
+    common::PlatformResult extractAll(ExtractAllProgressCallback *callback);
+    common::PlatformResult 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
+    common::PlatformResult extractEntryTo(ExtractEntryProgressCallback* callback);
+
+    bool isAllowedOperation(const std::string& method_name);
+    FileMode getFileMode() const;
+    void setFileMode(FileMode file_mode);
+
+    void setCreatedAsNewEmptyArchive(bool new_and_empty);
+    bool isCreatedAsNewEmptyArchive() const;
+
+    PlatformResult updateListOfEntries();
+private:
+    PlatformResult createUnZipObject(UnZipPtr* unzip);
+    PlatformResult createZipObject(ZipPtr* zip);
+
+    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);
+    common::PlatformResult addOperation(OperationCallbackData* callback);
+    static gboolean callErrorCallback(void* data);
+
+    PlatformResult 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
+} // extension
+
+#endif /* _TIZEN_ARCHIVE_FILE_ENTRY_H_ */
diff --git a/webWidgetTCT_device/src/archive/archive_file_entry.cc b/webWidgetTCT_device/src/archive/archive_file_entry.cc
new file mode 100755 (executable)
index 0000000..6ccc13d
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2015 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 "archive_file_entry.h"
+
+#include "common/logger.h"
+#include "common/platform_exception.h"
+
+#include "archive_callback_data.h"
+#include "archive_file.h"
+#include "archive_utils.h"
+
+using namespace common;
+
+namespace extension {
+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;
+}
+
+PlatformResult ArchiveFileEntry::extractTo(ExtractEntryProgressCallback* callback)
+{
+    if(!m_archive) {
+        LOGE("m_archive is NULL");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "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
+} // extension
diff --git a/webWidgetTCT_device/src/archive/archive_file_entry.h b/webWidgetTCT_device/src/archive/archive_file_entry.h
new file mode 100755 (executable)
index 0000000..bbd72f8
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2015 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_ARCHIVE_ARCHIVE_FILE_ENTRY_H_
+#define _TIZEN_ARCHIVE_ARCHIVE_FILE_ENTRY_H_
+
+#include <memory>
+#include "common/platform_result.h"
+#include "filesystem_file.h"
+
+namespace extension {
+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();
+
+    common::PlatformResult 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
+} // extension
+
+#endif /* _TIZEN_ARCHIVE_FILE_ENTRY_H_ */
diff --git a/webWidgetTCT_device/src/archive/archive_instance.cc b/webWidgetTCT_device/src/archive/archive_instance.cc
new file mode 100755 (executable)
index 0000000..2178e59
--- /dev/null
@@ -0,0 +1,611 @@
+/*
+ * Copyright (c) 2015 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 "archive/archive_instance.h"
+
+//#include "archive_manager.h"
+
+#include <functional>
+#include <memory>
+#include <pkgmgr-info.h>
+#include "common/current_application.h"
+#include "common/picojson.h"
+#include "common/logger.h"
+#include "archive_callback_data.h"
+#include "archive_manager.h"
+#include "archive_utils.h"
+#include "defs.h"
+
+namespace extension {
+namespace archive {
+
+using namespace common;
+
+namespace {
+
+const std::string kArchiveFileEntryOptDest = "destination";
+const std::string kArchiveFileEntryOptStrip = "stripSourceDirectory";
+const std::string kArchiveFileEntryOptCompressionLevel = "compressionLevel";
+
+const std::string kNoCompressionStr = "STORE";
+const std::string kFastCompressionStr = "FAST";
+const std::string kNormalCompressionStr = "NORMAL";
+const std::string kBestCompressionStr = "BEST";
+
+} // namespace
+
+ArchiveInstance::ArchiveInstance(): fs_provider_(common::FilesystemProviderStorage::Create()) {
+    LoggerD("Entered");
+
+    using std::placeholders::_1;
+    using std::placeholders::_2;
+
+    #define REGISTER_SYNC(c,x) \
+        RegisterSyncHandler(c, std::bind(&ArchiveInstance::x, this, _1, _2));
+    #define REGISTER_ASYNC(c,x) \
+        RegisterHandler(c, std::bind(&ArchiveInstance::x, this, _1, _2));
+
+    REGISTER_ASYNC("ArchiveManager_open", Open);
+    REGISTER_SYNC("ArchiveManager_abort", Abort);
+
+    REGISTER_ASYNC("ArchiveFile_add", Add);
+    REGISTER_ASYNC("ArchiveFile_extractAll", ExtractAll);
+    REGISTER_ASYNC("ArchiveFile_getEntries", GetEntries);
+    REGISTER_ASYNC("ArchiveFile_getEntryByName", GetEntryByName);
+    REGISTER_SYNC("ArchiveFile_close", Close);
+
+    REGISTER_ASYNC("ArchiveFileEntry_extract", Extract);
+
+    REGISTER_SYNC("Archive_fetchVirtualRoots", FetchVirtualRoots);
+
+    #undef REGISTER_ASYNC
+    #undef REGISTER_SYNC
+}
+
+ArchiveInstance::~ArchiveInstance() {
+    LoggerD("Entered");
+}
+
+void ArchiveInstance::PostError(const PlatformResult& e, double callback_id) {
+    picojson::value val = picojson::value(picojson::object());
+    picojson::object& obj = val.get<picojson::object>();
+    obj[JSON_CALLBACK_ID] = picojson::value(callback_id);
+    obj[JSON_DATA] = picojson::value(picojson::object());
+
+    picojson::object& args = obj[JSON_DATA].get<picojson::object>();
+    obj[JSON_ACTION] = picojson::value(JSON_CALLBACK_ERROR);
+
+    args[ERROR_CALLBACK_CODE] = picojson::value(static_cast<double>(e.error_code()));
+    args[ERROR_CALLBACK_MESSAGE] = picojson::value(e.message());
+
+    Instance::PostMessage(this, val.serialize().c_str());
+}
+
+void ArchiveInstance::Open(const picojson::value& args, picojson::object& out) {
+    LoggerD("Entered");
+    LoggerD("%s", args.serialize().c_str());
+
+    picojson::object data = args.get(JSON_DATA).get<picojson::object>();
+    picojson::value v_file = data.at(PARAM_FILE);
+    picojson::value v_mode = data.at(PARAM_MODE);
+    picojson::value v_op_id = data.at(PARAM_OPERATION_ID);
+    picojson::object options = data.at(PARAM_OPTIONS).get<picojson::object>();
+    picojson::value v_overwrite = options.at(PARAM_OVERWRITE);
+    const double callbackId = args.get(JSON_CALLBACK_ID).get<double>();
+    const long operationId = static_cast<long>(v_op_id.get<double>());
+    FileMode fm;
+    PlatformResult result = stringToFileMode(v_mode.get<std::string>(), &fm);
+    if (result.error_code() != ErrorCode::NO_ERROR) {
+        LoggerE("File mode conversions error");
+        PostError(result, callbackId);
+        return;
+    }
+
+    OpenCallbackData *callback = new OpenCallbackData(*this);
+
+    FilePtr file_ptr;
+
+    callback->setOperationId(operationId);
+    callback->setCallbackId(callbackId);
+
+    bool overwrite = false;
+    if(v_overwrite.is<bool>()) {
+        overwrite = v_overwrite.get<bool>();
+    }
+
+    std::string location_full_path = v_file.get<std::string>();
+    PathPtr path = Path::create(location_full_path);
+
+    struct stat info;
+    if (lstat(path->getFullPath().c_str(), &info) == 0) {
+        NodePtr node;
+        result = Node::resolve(path, &node);
+        if (result.error_code() != ErrorCode::NO_ERROR) {
+            LoggerE("Filesystem exception - calling error callback");
+            PostError(result, callbackId);
+            delete callback;
+            callback = NULL;
+            return;
+        }
+
+        file_ptr = FilePtr(new File(node, File::PermissionList()));
+        LoggerD("open: %s mode: 0x%x overwrite: %d", location_full_path.c_str(), fm, overwrite);
+        if (FileMode::WRITE == fm || FileMode::READ_WRITE == fm) {
+            if (overwrite) {
+                LoggerD("Deleting existing file: %s", location_full_path.c_str());
+                result = file_ptr->getNode()->remove(OPT_RECURSIVE);
+                if (result.error_code() != ErrorCode::NO_ERROR) {
+                    LoggerE("Couldn't remove existing file: %s", location_full_path.c_str());
+                    PostError(result, callbackId);
+                    delete callback;
+                    callback = NULL;
+                    return;
+                }
+                file_ptr.reset();   //We need to create new empty file
+            } else if (FileMode::WRITE == fm) {
+                LoggerE("open: %s with mode: \"w\" file exists and overwrite is FALSE!"
+                        " throwing InvalidModificationException", location_full_path.c_str());
+                PostError(PlatformResult(ErrorCode::INVALID_MODIFICATION_ERR,
+                                         "Zip archive already exists"), callbackId);
+                delete callback;
+                callback = NULL;
+                return;
+            }
+        }
+    }
+
+    if (!file_ptr) {
+        NodePtr node_ptr;
+
+        if (FileMode::WRITE == fm ||
+                FileMode::READ_WRITE == fm ||
+                FileMode::ADD == fm) {
+            LoggerD("Archive file not found - trying to create new one at: "
+                    "full: %s", location_full_path.c_str());
+
+            std::string parent_path_string = path->getPath();
+            PathPtr parent_path = Path::create(parent_path_string);
+            LoggerD("Parent path: %s", parent_path_string.c_str());
+
+            NodePtr parent_node;
+            PlatformResult result = Node::resolve(parent_path, &parent_node);
+            if (result.error_code() != ErrorCode::NO_ERROR) {
+                LoggerE("Filesystem exception - calling error callback");
+                PostError(result, callbackId);
+                delete callback;
+                callback = NULL;
+                return;
+            }
+
+            parent_node->setPermissions(PERM_READ | PERM_WRITE);
+            std::string filename = path->getName();
+            LoggerD("File name: %s", filename.c_str());
+            result = parent_node->createChild(Path::create(filename), NT_FILE, &node_ptr);
+            if (result.error_code() != ErrorCode::NO_ERROR) {
+                LoggerE("Filesystem exception - calling error callback");
+                PostError(result, callbackId);
+                delete callback;
+                callback = NULL;
+                return;
+            }
+        } else {
+            LoggerE("Archive file not found");
+            LoggerE("Filesystem exception - calling error callback");
+            PostError(PlatformResult(ErrorCode::NOT_FOUND_ERR, "Archive file not found"), callbackId);
+            delete callback;
+            callback = NULL;
+            return;
+        }
+        file_ptr = FilePtr(new File(node_ptr, File::PermissionList()));
+    }
+
+    ArchiveFilePtr afp = ArchiveFilePtr(new ArchiveFile(fm));
+    afp->setFile(file_ptr);
+    afp->setOverwrite(overwrite);
+    callback->setArchiveFile(afp);
+
+    result = ArchiveManager::getInstance().open(callback);
+
+    if (result) {
+        ReportSuccess(out);
+    } else {
+        ReportError(result, &out);
+    }
+}
+
+void ArchiveInstance::Abort(const picojson::value& args, picojson::object& out)
+{
+    LoggerD("Entered");
+    LoggerD("%s", args.serialize().c_str());
+
+    picojson::object data = args.get(JSON_DATA).get<picojson::object>();
+    picojson::value v_op_id = data.at(PARAM_OPERATION_ID);
+
+    const long op_id = static_cast<long>(v_op_id.get<double>());
+
+    ArchiveManager::getInstance().abort(op_id);
+
+    ReportSuccess(out);
+}
+
+unsigned int ConvertStringToCompressionLevel(const std::string& level) {
+  LoggerD("Entered");
+
+  if (kNoCompressionStr == level) {
+      return Z_NO_COMPRESSION;
+  } else if (kFastCompressionStr == level) {
+      return Z_BEST_SPEED;
+  } else if (kBestCompressionStr == level) {
+      return Z_BEST_COMPRESSION;
+  } else {
+      return Z_DEFAULT_COMPRESSION;
+  }
+}
+
+void ArchiveInstance::Add(const picojson::value& args, picojson::object& out)
+{
+    LoggerD("Entered");
+    LoggerD("%s", args.serialize().c_str());
+
+    picojson::object data = args.get(JSON_DATA).get<picojson::object>();
+    picojson::value v_source = data.at(PARAM_SOURCE_FILE);
+    picojson::value v_options = data.at(PARAM_OPTIONS);
+    picojson::value v_op_id = data.at(PARAM_OPERATION_ID);
+    picojson::value v_handle = data.at(ARCHIVE_FILE_HANDLE);
+
+    const double callbackId = args.get(JSON_CALLBACK_ID).get<double>();
+    const long operationId = static_cast<long>(v_op_id.get<double>());
+    const long handle = static_cast<long>(v_handle.get<double>());
+
+    AddProgressCallback *callback = new AddProgressCallback(*this);
+
+    NodePtr node;
+    PlatformResult result = Node::resolve(Path::create(v_source.get<std::string>()), &node);
+    if (result.error_code() != ErrorCode::NO_ERROR) {
+        LoggerE("Filesystem exception - calling error callback");
+        PostError(result, callbackId);
+        delete callback;
+        callback = NULL;
+        return;
+    }
+
+    FilePtr file_ptr = FilePtr(new File(node, File::PermissionList()));
+    ArchiveFileEntryPtr afep = ArchiveFileEntryPtr(new ArchiveFileEntry(file_ptr));
+
+    callback->setOperationId(operationId);
+    callback->setCallbackId(callbackId);
+    callback->setFileEntry(afep);
+
+    callback->setBasePath(file_ptr->getNode()->getPath()->getPath());
+
+    // check and set options
+    LoggerD("Processing OPTIONS dictionary: %s", v_options.serialize().c_str());
+    const auto& dest = v_options.get(kArchiveFileEntryOptDest);
+    if (dest.is<std::string>()) {
+      std::string dic_destination = dest.get<std::string>();
+      LoggerD("Setting destination path to: \"%s\"",dic_destination.c_str());
+      afep->setDestination(dic_destination);
+    }
+
+    const auto& strip = v_options.get(kArchiveFileEntryOptStrip);
+    if (strip.is<bool>()) {
+      bool dic_strip = strip.get<bool>();
+      LoggerD("Setting strip option to: %d", dic_strip);
+      afep->setStriped(dic_strip);
+    }
+
+    const auto& level = v_options.get(kArchiveFileEntryOptCompressionLevel);
+    if (level.is<std::string>()) {
+      std::string dic_compression_level = level.get<std::string>();
+      LoggerD("Setting compression level to: \"%s\"", dic_compression_level.c_str());
+      afep->setCompressionLevel(ConvertStringToCompressionLevel(dic_compression_level));
+    }
+
+    LoggerD("base path:%s base virt:%s", callback->getBasePath().c_str(),
+            callback->getBaseVirtualPath().c_str());
+
+    ArchiveFilePtr priv;
+    result = ArchiveManager::getInstance().getPrivData(handle, &priv);
+    if (result.error_code() != ErrorCode::NO_ERROR) {
+        LoggerE("Exception occurred");
+        delete callback;
+        callback = NULL;
+        return;
+    }
+
+    if (!priv->isAllowedOperation(ARCHIVE_FUNCTION_API_ARCHIVE_FILE_ADD)) {
+        LoggerE("Not allowed operation");
+        delete callback;
+        callback = NULL;
+        return;
+    }
+
+    result = priv->add(callback);
+    if (result.error_code() != ErrorCode::NO_ERROR) {
+        LoggerE("Exception occurred");
+        delete callback;
+        callback = NULL;
+        return;
+    }
+}
+
+void ArchiveInstance::ExtractAll(const picojson::value& args, picojson::object& out)
+{
+    LoggerD("Entered");
+    LoggerD("%s", args.serialize().c_str());
+
+    picojson::object data = args.get(JSON_DATA).get<picojson::object>();
+    picojson::value v_dest_dir = data.at(PARAM_DESTINATION_DIR);
+    picojson::value v_overwrite = data.at(PARAM_OVERWRITE);
+    picojson::value v_op_id = data.at(PARAM_OPERATION_ID);
+    picojson::value v_handle = data.at(ARCHIVE_FILE_HANDLE);
+
+    const double callbackId = args.get(JSON_CALLBACK_ID).get<double>();
+    const long operationId = static_cast<long>(v_op_id.get<double>());
+    const long handle = static_cast<long>(v_handle.get<double>());
+
+    ExtractAllProgressCallback *callback = new ExtractAllProgressCallback(*this);
+
+    NodePtr node;
+    PlatformResult result = Node::resolve(Path::create(v_dest_dir.get<std::string>()), &node);
+    if (result.error_code() != ErrorCode::NO_ERROR) {
+        LoggerE("Filesystem exception - calling error callback");
+        PostError(result, callbackId);
+        delete callback;
+        callback = NULL;
+        return;
+    }
+
+    FilePtr file_ptr = FilePtr(new File(node, File::PermissionList()));
+
+    callback->setDirectory(file_ptr);
+    callback->setOperationId(operationId);
+    callback->setCallbackId(callbackId);
+
+    if (v_overwrite.is<bool>()) {
+        callback->setOverwrite(v_overwrite.get<bool>());
+    }
+
+    ArchiveFilePtr priv;
+    result = ArchiveManager::getInstance().getPrivData(handle, &priv);
+    if (result.error_code() != ErrorCode::NO_ERROR) {
+        LoggerE("Exception occurred");
+        delete callback;
+        callback = NULL;
+        return;
+    }
+
+    if (!priv->isAllowedOperation(ARCHIVE_FUNCTION_API_ARCHIVE_FILE_EXTRACT_ALL)) {
+        LoggerE("Not allowed operation");
+        delete callback;
+        callback = NULL;
+        return;
+    }
+
+    result = priv->extractAll(callback);
+    if (result.error_code() != ErrorCode::NO_ERROR) {
+        LoggerE("Exception occurred");
+        delete callback;
+        callback = NULL;
+        return;
+    }
+}
+
+void ArchiveInstance::GetEntries(const picojson::value& args, picojson::object& out)
+{
+    LoggerD("Entered");
+    LoggerD("%s", args.serialize().c_str());
+
+    picojson::object data = args.get(JSON_DATA).get<picojson::object>();
+    picojson::value v_op_id = data.at(PARAM_OPERATION_ID);
+    picojson::value v_handle = data.at(ARCHIVE_FILE_HANDLE);
+
+    const double callbackId = args.get(JSON_CALLBACK_ID).get<double>();
+    const long operationId = static_cast<long>(v_op_id.get<double>());
+    const long handle = static_cast<long>(v_handle.get<double>());
+
+    GetEntriesCallbackData *callback = new GetEntriesCallbackData(*this);
+
+    callback->setOperationId(operationId);
+    callback->setCallbackId(callbackId);
+    callback->setHandle(handle);
+
+    ArchiveFilePtr priv;
+    PlatformResult result = ArchiveManager::getInstance().getPrivData(handle, &priv);
+    if (result.error_code() != ErrorCode::NO_ERROR) {
+        LoggerE("Exception occurred");
+        delete callback;
+        callback = NULL;
+        return;
+    }
+
+    if (!priv->isAllowedOperation(ARCHIVE_FUNCTION_API_ARCHIVE_FILE_GET_ENTRIES)) {
+        LoggerE("Not allowed operation");
+        delete callback;
+        callback = NULL;
+        return;
+    }
+
+    result = priv->getEntries(callback);
+    if (result.error_code() != ErrorCode::NO_ERROR) {
+        LoggerE("Exception occurred");
+        delete callback;
+        callback = NULL;
+        return;
+    }
+}
+
+void ArchiveInstance::GetEntryByName(const picojson::value& args, picojson::object& out)
+{
+    LoggerD("Entered");
+    LoggerD("%s", args.serialize().c_str());
+
+    picojson::object data = args.get(JSON_DATA).get<picojson::object>();
+    picojson::value v_op_id = data.at(PARAM_OPERATION_ID);
+    picojson::value v_handle = data.at(ARCHIVE_FILE_HANDLE);
+    picojson::value v_name = data.at(PARAM_NAME);
+
+    const double callbackId = args.get(JSON_CALLBACK_ID).get<double>();
+    const long operationId = static_cast<long>(v_op_id.get<double>());
+    const long handle = static_cast<long>(v_handle.get<double>());
+
+    GetEntryByNameCallbackData *callback = new GetEntryByNameCallbackData(*this);
+
+    callback->setOperationId(operationId);
+    callback->setCallbackId(callbackId);
+    callback->setName(v_name.get<std::string>());
+    callback->setHandle(handle);
+
+    ArchiveFilePtr priv;
+    PlatformResult result = ArchiveManager::getInstance().getPrivData(handle, &priv);
+    if (result.error_code() != ErrorCode::NO_ERROR) {
+        LoggerE("Exception occurred");
+        delete callback;
+        callback = NULL;
+        return;
+    }
+
+    if (!priv->isAllowedOperation(ARCHIVE_FUNCTION_API_ARCHIVE_FILE_GET_ENTRY_BY_NAME)) {
+        LoggerE("Not allowed operation");
+        delete callback;
+        callback = NULL;
+        return;
+    }
+
+    result = priv->getEntryByName(callback);
+    if (result.error_code() != ErrorCode::NO_ERROR) {
+        LoggerE("Exception occurred");
+        delete callback;
+        callback = NULL;
+        return;
+    }
+}
+
+void ArchiveInstance::Close(const picojson::value& args, picojson::object& out)
+{
+    LoggerD("Entered");
+    LoggerD("%s", args.serialize().c_str());
+
+    picojson::object data = args.get(JSON_DATA).get<picojson::object>();
+    picojson::value v_handle = data.at(ARCHIVE_FILE_HANDLE);
+
+    const long handle = static_cast<long>(v_handle.get<double>());
+
+    ArchiveFilePtr priv;
+    PlatformResult result = ArchiveManager::getInstance().getPrivData(handle, &priv);
+    if (result.error_code() == ErrorCode::NO_ERROR) {
+      priv->close();
+      ArchiveManager::getInstance().erasePrivData(handle);
+    } else {
+      LoggerD("Close method was called on already closed archive. Just end execution");
+      LoggerD("%s", result.message().c_str());
+    }
+
+    ReportSuccess(out);
+}
+
+void ArchiveInstance::Extract(const picojson::value& args, picojson::object& out)
+{
+    LoggerD("Entered");
+    LoggerD("%s", args.serialize().c_str());
+
+    picojson::object data = args.get(JSON_DATA).get<picojson::object>();
+    picojson::value v_dest_dir = data.at(PARAM_DESTINATION_DIR);
+    picojson::value v_strip_name = data.at(PARAM_STRIP_NAME);
+    picojson::value v_overwrite = data.at(PARAM_OVERWRITE);
+    picojson::value v_op_id = data.at(PARAM_OPERATION_ID);
+    picojson::value v_handle = data.at(ARCHIVE_FILE_HANDLE);
+    picojson::value v_entry_name = data.at(PARAM_NAME);
+
+    const double callbackId = args.get(JSON_CALLBACK_ID).get<double>();
+    const long operationId = static_cast<long>(v_op_id.get<double>());
+    const long handle = static_cast<long>(v_handle.get<double>());
+
+    ExtractEntryProgressCallback *callback = new ExtractEntryProgressCallback(*this);
+
+    NodePtr node;
+    PlatformResult result = Node::resolve(Path::create(v_dest_dir.get<std::string>()), &node);
+    if (result.error_code() != ErrorCode::NO_ERROR) {
+        LoggerE("Filesystem exception - calling error callback");
+        PostError(result, callbackId);
+        delete callback;
+        callback = NULL;
+        return;
+    }
+
+    FilePtr file_ptr = FilePtr(new File(node, File::PermissionList()));
+
+    callback->setDirectory(file_ptr);
+    callback->setOperationId(operationId);
+    callback->setCallbackId(callbackId);
+
+    if (v_overwrite.is<bool>()) {
+        callback->setOverwrite(v_overwrite.get<bool>());
+    }
+    if (v_strip_name.is<bool>()) {
+        callback->setStripName(v_strip_name.get<bool>());
+    }
+
+    ArchiveFilePtr archive_file_ptr;
+    result = ArchiveManager::getInstance().getPrivData(handle, &archive_file_ptr);
+    if (result.error_code() != ErrorCode::NO_ERROR) {
+        LoggerE("Exception occurred");
+        delete callback;
+        callback = NULL;
+        return;
+    }
+
+    ArchiveFileEntryPtrMapPtr entries = archive_file_ptr->getEntryMap();
+    auto it = entries->find(v_entry_name.get<std::string>());
+
+    //Not found but if our name does not contain '/'
+    //try looking for directory with such name
+    if (entries->end() == it && !isDirectoryPath(v_entry_name.get<std::string>())) {
+        const std::string try_directory = v_entry_name.get<std::string>() + "/";
+        LoggerD("GetEntryByName Trying directory: [%s]", try_directory.c_str());
+        it = entries->find(try_directory);
+    }
+
+    if (entries->end() == it) {
+        LoggerE("Failed to find entry");
+        PostError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to find entry"), callbackId);
+        delete callback;
+        callback = NULL;
+        return;
+    }
+
+    result = it->second->extractTo(callback);
+    if (result.error_code() != ErrorCode::NO_ERROR) {
+        LoggerE("ArchiveFileEntry.extractTo error");
+        PostError(result, callbackId);
+        delete callback;
+        callback = NULL;
+        return;
+    }
+}
+
+void ArchiveInstance::FetchVirtualRoots(const picojson::value& args, picojson::object& out) {
+    LoggerD("Entered");
+
+    picojson::array roots;
+    for (const auto& root : fs_provider_.GetVirtualPaths()) {
+      roots.push_back(root.ToJson());
+    }
+    ReportSuccess(picojson::value(roots), out);
+}
+
+} // namespace archive
+} // namespace extension
diff --git a/webWidgetTCT_device/src/archive/archive_instance.h b/webWidgetTCT_device/src/archive/archive_instance.h
new file mode 100755 (executable)
index 0000000..8573ca6
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2015 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 ARCHIVE_ARCHIVE_INSTANCE_H_
+#define ARCHIVE_ARCHIVE_INSTANCE_H_
+
+#include "common/extension.h"
+#include "common/platform_exception.h"
+#include "common/platform_result.h"
+#include "common/filesystem/filesystem_provider_storage.h"
+
+namespace extension {
+namespace archive {
+
+class ArchiveInstance: public common::ParsedInstance {
+public:
+    ArchiveInstance();
+    virtual ~ArchiveInstance();
+
+private:
+    ArchiveInstance(ArchiveInstance const&);
+    void operator=(ArchiveInstance const&);
+
+    /* ArchiveManager methods */
+    void Open(const picojson::value& args, picojson::object& out);
+    void Abort(const picojson::value& args, picojson::object& out);
+
+    /* ArchiveFile methods */
+    void Add(const picojson::value& args, picojson::object& out);
+    void ExtractAll(const picojson::value& args, picojson::object& out);
+    void GetEntries(const picojson::value& args, picojson::object& out);
+    void GetEntryByName(const picojson::value& args, picojson::object& out);
+    void Close(const picojson::value& args, picojson::object& out);
+
+    /* ArchiveFileEntry methods */
+    void Extract(const picojson::value& args, picojson::object& out);
+
+    /* Filesystem related method */
+    void FetchVirtualRoots(const picojson::value& args, picojson::object& out);
+
+    void PostError(const common::PlatformException& e, double callback_id);
+    void PostError(const common::PlatformResult& e, double callback_id);
+
+    common::FilesystemProviderRef fs_provider_;
+};
+
+} // namespace archive
+} // namespace extension
+
+#endif // ARCHIVE_ARCHIVE_INSTANCE_H_
diff --git a/webWidgetTCT_device/src/archive/archive_manager.cc b/webWidgetTCT_device/src/archive/archive_manager.cc
new file mode 100755 (executable)
index 0000000..97a9998
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2015 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 "archive_manager.h"
+#include <mutex>
+#include "common/logger.h"
+#include "filesystem_file.h"
+
+namespace extension {
+namespace archive {
+
+using namespace filesystem;
+
+ArchiveManager::ArchiveManager():
+        m_next_unique_id(0)
+{
+    LoggerD("Initialize ArchiveManager");
+}
+
+ArchiveManager::~ArchiveManager()
+{
+    LoggerD("Deinitialize ArchiveManager");
+}
+
+ArchiveManager& ArchiveManager::getInstance()
+{
+    LoggerD("Entered");
+    static ArchiveManager instance;
+    return instance;
+}
+
+void ArchiveManager::abort(long operation_id)
+{
+    LoggerD("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(std::size_t 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;
+            }
+        }
+    }
+    LoggerD("The Operation Identifier not found");
+}
+
+void ArchiveManager::erasePrivData(long handle)
+{
+    LoggerD("Entered");
+
+    ArchiveFileMap::iterator it = m_priv_map.find(handle);
+    if (it != m_priv_map.end()) {
+        m_priv_map.erase(it);
+    }
+}
+
+long ArchiveManager::addPrivData(ArchiveFilePtr archive_file_ptr)
+{
+    LoggerD("Entered");
+
+    long handle = ++m_next_unique_id;
+    m_priv_map.insert(ArchiveFilePair(handle, archive_file_ptr));
+    return handle;
+}
+
+PlatformResult ArchiveManager::getPrivData(long handle, ArchiveFilePtr* archive_file)
+{
+    ArchiveFileMap::iterator it = m_priv_map.find(handle);
+    if (it != m_priv_map.end()) {
+        *archive_file = it->second;
+        return PlatformResult(ErrorCode::NO_ERROR);
+    }
+    LoggerE("Failed: Priv is null");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Priv is null");
+}
+
+PlatformResult ArchiveManager::open(OpenCallbackData* callback)
+{
+    LoggerD("Entered");
+
+    //ArchiveFilePtr a_ptr = callback->getArchiveFile();
+//    std::string filename = callback->getFile();
+//
+//    NodePtr node = Node::resolve(Path::create(filename));
+//    FilePtr file_ptr = FilePtr(new File(node, std::vector<int>(), filename));
+//    ArchiveFilePtr a_ptr = ArchiveFilePtr(new ArchiveFile(FileMode::READ));
+
+    ArchiveFilePtr a_ptr = callback->getArchiveFile();
+    return a_ptr->addOperation(callback);
+}
+
+void ArchiveManager::eraseElementFromArchiveFileMap(long operation_id)
+{
+    LoggerD("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
+} // extension
diff --git a/webWidgetTCT_device/src/archive/archive_manager.h b/webWidgetTCT_device/src/archive/archive_manager.h
new file mode 100755 (executable)
index 0000000..354edb0
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2015 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_ARCHIVE_ARCHIVE_MANAGER_H_
+#define _TIZEN_ARCHIVE_ARCHIVE_MANAGER_H_
+
+#include <map>
+#include <memory>
+#include <string>
+
+#include "archive_file.h"
+#include "archive_callback_data.h"
+
+namespace extension {
+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);
+    void eraseElementFromArchiveFileMap(long operation_id);
+    void erasePrivData(long handle);
+    long addPrivData(ArchiveFilePtr archive_file_ptr);
+    common::PlatformResult getPrivData(long handle, ArchiveFilePtr* archive_file);
+    common::PlatformResult open(OpenCallbackData* callback);
+
+private:
+    ArchiveManager();
+    ArchiveManager(ArchiveManager const&);
+    void operator=(ArchiveManager const&);
+
+    ArchiveFileMap m_archive_file_map;
+    ArchiveFileMap m_priv_map;
+
+    long m_next_unique_id;
+};
+
+} // archive
+} // extension
+
+#endif /* _TIZEN_ARCHIVE_ARCHIVE_MANAGER_H_ */
diff --git a/webWidgetTCT_device/src/archive/archive_utils.cc b/webWidgetTCT_device/src/archive/archive_utils.cc
new file mode 100755 (executable)
index 0000000..10230f0
--- /dev/null
@@ -0,0 +1,277 @@
+/*
+ * Copyright (c) 2015 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 "archive_utils.h"
+#include <sstream>
+#include <iomanip>
+#include "common/logger.h"
+
+//TODO:
+//#include <FilesystemExternalUtils.h>
+
+using namespace common;
+
+namespace extension {
+namespace archive {
+
+using namespace filesystem;
+
+std::string bytesToReadableString(const size_t num_bytes)
+{
+    LoggerD("Enter");
+    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();
+}
+
+PlatformResult fileModeToString(FileMode fm, std::string* fm_str)
+{
+    LoggerD("Enter");
+    switch(fm) {
+        case FileMode::READ:
+            *fm_str = "r";
+            break;
+        case FileMode::WRITE:
+            *fm_str = "w";
+            break;
+        case FileMode::READ_WRITE:
+            *fm_str = "rw";
+            break;
+        case FileMode::ADD:
+            *fm_str = "a";
+            break;
+        default:
+            LoggerE("Unknown file mode");
+            return PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown file mode");
+    }
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult stringToFileMode(std::string fmString, FileMode* fm)
+{
+    LoggerD("Enter");
+    if (!fmString.compare("r")) {
+        *fm = FileMode::READ;
+        return PlatformResult(ErrorCode::NO_ERROR);
+    }
+    else if (!fmString.compare("w")) {
+        *fm = FileMode::WRITE;
+        return PlatformResult(ErrorCode::NO_ERROR);
+    }
+    else if (!fmString.compare("rw")) {
+        *fm = FileMode::READ_WRITE;
+        return PlatformResult(ErrorCode::NO_ERROR);
+    }
+    else if (!fmString.compare("a")) {
+        *fm = FileMode::ADD;
+        return PlatformResult(ErrorCode::NO_ERROR);
+    }
+    // In widl it's "TypeMismatchError" so this exception used
+    // instead of InvalidValues
+    LoggerE("Invalid FileMode");
+    return PlatformResult(ErrorCode::TYPE_MISMATCH_ERR, "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)
+{
+    LoggerD("Enter");
+    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)
+{
+    LoggerD("Enter");
+    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)
+{
+    LoggerD("Enter");
+    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)
+{
+    LoggerD("Enter");
+    if (!isDirectoryPath(path)) {
+        return path;
+    }
+
+    return path.substr(0, path.length() - 1);
+}
+
+std::string stripBasePathFromPath(const std::string& fullpath)
+{
+    LoggerD("Enter");
+    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)
+{
+    LoggerD("Enter");
+    /**
+     * 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;
+    }
+}
+}
+
+std::string getBasePathFromPath(const std::string& fullpath)
+{
+    LoggerD("Enter");
+    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);
+}
+
+std::string getArchiveLogMessage(const int errorCode, const std::string &hint)
+{
+    LoggerD("Enter");
+    std::stringstream ss;
+    ss << "Failed " << hint << " : " << getArchiveErrorMessage(errorCode) << ", " << errorCode;
+    return std::string(ss.str());
+}
+
+} //namespace archive
+} //namespace extension
diff --git a/webWidgetTCT_device/src/archive/archive_utils.h b/webWidgetTCT_device/src/archive/archive_utils.h
new file mode 100755 (executable)
index 0000000..541822e
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2015 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_ARCHIVE_ARCHIVE_UTILS_H__
+#define __TIZEN_ARCHIVE_ARCHIVE_UTILS_H__
+
+#include <string>
+
+#include "common/platform_result.h"
+#include "filesystem_file.h"
+#include "archive_file.h"
+
+namespace extension {
+namespace archive {
+
+std::string bytesToReadableString(const size_t num_bytes);
+common::PlatformResult fileModeToString(FileMode fm, std::string* fm_str);
+common::PlatformResult stringToFileMode(std::string fmString, FileMode* fm);
+
+//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"
+ */
+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 \)
+ */
+std::string removeDuplicatedSlashesFromPath(const std::string& path);
+
+/**
+ * Return true if last character of string is '/' or '\'
+ */
+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"
+ */
+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)
+ */
+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/"
+ */
+std::string getBasePathFromPath(const std::string& fullpath);
+
+std::string getArchiveLogMessage(const int errorCode, const std::string &hint);
+
+} //namespace archive
+} //namespace extension
+
+#endif // __TIZEN_ARCHIVE_ARCHIVE_UTILS_H__
diff --git a/webWidgetTCT_device/src/archive/defs.h b/webWidgetTCT_device/src/archive/defs.h
new file mode 100755 (executable)
index 0000000..8f7eb74
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2015 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 _ARCHIVE_PLUGIN_DEFS_H_
+#define _ARCHIVE_PLUGIN_DEFS_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"
+
+#define JSON_CMD                                                "cmd"
+#define JSON_ACTION                                             "action"
+#define JSON_CALLBACK_ID                                        "cid"
+#define JSON_CALLBACK_SUCCCESS                                  "success"
+#define JSON_CALLBACK_ERROR                                     "error"
+#define JSON_CALLBACK_PROGRESS                                  "progress"
+#define JSON_CALLBACK_KEEP                                      "keep"
+#define JSON_DATA                                               "args"
+
+#define PARAM_FILE                                              "file"
+#define PARAM_MODE                                              "mode"
+#define PARAM_OPTIONS                                           "options"
+#define PARAM_SOURCE_FILE                                       "sourceFile"
+#define PARAM_DESTINATION_DIR                                   "destinationDirectory"
+#define PARAM_OVERWRITE                                         "overwrite"
+#define PARAM_NAME                                              "name"
+#define PARAM_STRIP_NAME                                        "stripName"
+#define PARAM_OPERATION_ID                                      "opId"
+#define PARAM_VALUE                                             "value"
+#define PARAM_FILENAME                                          "filename"
+
+#define ARCHIVE_FILE_ATTR_MODE                                  "mode"
+#define ARCHIVE_FILE_ATTR_DECOMPRESSED_SIZE                     "decompressedSize"
+#define ARCHIVE_FILE_HANDLE                                     "handle"
+
+#define ARCHIVE_FILE_ENTRY_ATTR_NAME                            "name"
+#define ARCHIVE_FILE_ENTRY_ATTR_SIZE                            "size"
+#define ARCHIVE_FILE_ENTRY_ATTR_COMPRESSED_SIZE                 "compressedSize"
+#define ARCHIVE_FILE_ENTRY_ATTR_MODIFIED                        "modified"
+
+#define ERROR_CALLBACK_CODE                                     "code"
+#define ERROR_CALLBACK_MESSAGE                                  "message"
+
+#endif // _ARCHIVE_PLUGIN_DEFS_H_
diff --git a/webWidgetTCT_device/src/archive/filesystem_file.cc b/webWidgetTCT_device/src/archive/filesystem_file.cc
new file mode 100755 (executable)
index 0000000..cbd8de7
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2015 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 "filesystem_file.h"
+#include "common/logger.h"
+
+using namespace common;
+
+namespace extension {
+namespace filesystem {
+
+File::File(NodePtr node, const File::PermissionList &parentPermissions,
+        const std::string& original_location) :
+    m_node(node),
+    m_parentPerms(parentPermissions)
+{
+    LoggerD("original_location is fullPath: %s", original_location.c_str());
+    m_original_fullpath = original_location;
+}
+
+File::~File()
+{
+    LoggerD("Enter");
+}
+
+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);
+}
+
+const std::string& File::getOriginalURI() const
+{
+    return m_original_URI;
+}
+
+const std::string& File::getOriginalFullPath() const
+{
+    return m_original_fullpath;
+}
+
+std::string External::toVirtualPath(const std::string& path)
+{
+    //TODO::implement this method
+    LoggerW("Just STUB");
+    return path;
+}
+
+} // filesystem
+} // extension
diff --git a/webWidgetTCT_device/src/archive/filesystem_file.h b/webWidgetTCT_device/src/archive/filesystem_file.h
new file mode 100755 (executable)
index 0000000..26401f2
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2015 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_FILESYSTEM_FILE_H_
+#define _TIZEN_FILESYSTEM_FILE_H_
+
+#include <string>
+#include <memory>
+#include <vector>
+
+#include "common/logger.h"
+#include "filesystem_node.h"
+#include "filesystem_path.h"
+
+namespace extension {
+namespace filesystem {
+
+class File;
+typedef std::shared_ptr<File> FilePtr;
+
+class File : public std::enable_shared_from_this<File>
+{
+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);
+
+    const std::string& getOriginalURI() const;
+    const std::string& getOriginalFullPath() const;
+private:
+    NodePtr m_node;
+    PermissionList m_parentPerms;
+
+    std::string m_original_URI;
+    std::string m_original_fullpath;
+};
+
+class External {
+public:
+    static std::string toVirtualPath(const std::string& path);
+};
+
+
+} // filesystem
+} // extension
+
+#endif /* _TIZEN_FILESYSTEM_FILE_H_ */
diff --git a/webWidgetTCT_device/src/archive/filesystem_node.cc b/webWidgetTCT_device/src/archive/filesystem_node.cc
new file mode 100755 (executable)
index 0000000..06bd56a
--- /dev/null
@@ -0,0 +1,670 @@
+/*
+ * Copyright (c) 2015 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 "filesystem_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 <fstream>
+
+#include "filesystem_path.h"
+#include "filesystem_node.h"
+#include "common/logger.h"
+
+namespace extension {
+namespace filesystem {
+
+using namespace common;
+
+#define MAX_NODE_LENGTH 256
+PlatformResult Node::checkPermission(const PathPtr &path, const std::string &mode, NodeType type, bool* granted)
+{
+    LoggerD("Enter");
+    *granted = false;
+
+    switch (type)
+    {
+        case NT_DIRECTORY:
+        {
+            DIR* dir = opendir(path->getFullPath().c_str());
+
+            if (!dir) {
+                LoggerE("throw InvalidValuesException");
+                return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Node has been deleted from platform.");
+            }
+
+            if (closedir(dir) != 0) {
+                LoggerE("throw InvalidValuesException");
+                return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Could not close platform node.");
+            }
+
+            if (mode == "r") {
+                *granted = true;
+                return PlatformResult(ErrorCode::NO_ERROR);
+            }
+
+            std::stringstream ss;
+            time_t now;
+            time(&now);
+            ss << now;
+            PathPtr tempFilePath = Path::create(path->getFullPath());
+            tempFilePath->append(ss.str());
+
+            PlatformResult result = createAsFileInternal(tempFilePath);
+            if (result.error_code() != ErrorCode::NO_ERROR) {
+                return result;
+            }
+
+            result = removeAsFile(tempFilePath);
+            if (result.error_code() != ErrorCode::NO_ERROR) {
+                return result;
+            }
+
+            if (mode == "rw" || mode == "w"  || mode == "a") {
+                *granted = true;
+                return PlatformResult(ErrorCode::NO_ERROR);
+            }
+            LoggerE("throw InvalidValuesException");
+            return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "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
+            {
+                LoggerE("throw InvalidValuesException");
+                return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "invalid mode");
+            }
+
+            stream.open(path->getFullPath().c_str(), modeBit);
+
+            if (stream.is_open())
+            {
+                stream.close();
+                *granted = true;
+            }
+            return PlatformResult(ErrorCode::NO_ERROR);
+        }
+        break;
+    }
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult Node::resolve(const PathPtr& path, NodePtr* node)
+{
+    LoggerD("Entered path:[%s]", path->getFullPath().c_str());
+
+    struct stat info;
+    struct stat syminfo;
+
+    if (lstat(path->getFullPath().c_str(), &info) != 0) {
+        LoggerE("File:[%s] error no:%d", path->getFullPath().c_str(), errno);
+
+        switch (errno)
+        {
+            case EACCES:
+                LoggerE("throw InvalidValuesException for file:[%s]", path->getFullPath().c_str());
+                return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Node access denied");
+                break;
+            case ENOENT:
+                LoggerE("throw NotFoundException for file:[%s]", path->getFullPath().c_str());
+                return PlatformResult(ErrorCode::NOT_FOUND_ERR, "NotFoundError");
+                break;
+            default:
+                LoggerE("throw IOException for file:[%s]", path->getFullPath().c_str());
+                return PlatformResult(ErrorCode::IO_ERR, "Platform exception fail");
+        }
+    }
+
+    if ((!S_ISDIR(info.st_mode)) & (!S_ISREG(info.st_mode)) && !S_ISLNK(info.st_mode)) {
+        LoggerE("throw IOException for file:[%s]", path->getFullPath().c_str());
+        return PlatformResult(ErrorCode::IO_ERR, "Platform node is of unsupported type.");
+    }
+
+    NodeType type = S_ISDIR(info.st_mode) ? NT_DIRECTORY : NT_FILE;
+
+    if (S_ISLNK(info.st_mode)) {
+        PlatformResult result = stat(path, &syminfo);
+        if (result.error_code() != ErrorCode::NO_ERROR) {
+            LoggerE("Error: %s", result.message().c_str());
+            return result;
+        }
+
+        type = S_ISDIR(syminfo.st_mode) ? NT_DIRECTORY : NT_FILE;
+        LoggerD("%x", type);
+    }
+
+    *node = std::shared_ptr<Node>(new Node(path, type));
+
+    LoggerD("Finished execution for file:[%s] type:%s", path->getFullPath().c_str(),
+            type == NT_DIRECTORY ? "directory" : "file");
+
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PathPtr Node::getPath() const
+{
+    return Path::create(m_path->getFullPath());
+}
+
+PlatformResult Node::getChild(const PathPtr& path, NodePtr* node)
+{
+    LoggerD("Enter");
+    if (m_type != NT_DIRECTORY) {
+        LoggerW("throw IOException");
+        return PlatformResult(ErrorCode::IO_ERR, "Not a directory.");
+    }
+    return Node::resolve(*m_path + *path, node);
+}
+
+NodeType Node::getType() const
+{
+    return m_type;
+}
+
+int Node::getPermissions() const
+{
+    return m_perms;
+}
+
+void Node::setPermissions(int perms)
+{
+    m_perms = perms;
+}
+
+PlatformResult Node::getChildNames(Node::NameList* out_name_list) const
+{
+    LoggerD("Enter");
+    if (m_type != NT_DIRECTORY) {
+        LoggerE("throw IOException");
+        return PlatformResult(ErrorCode::IO_ERR, "Node is not directory.");
+    }
+
+    if ((m_perms & PERM_READ) == 0) {
+        LoggerE("throw InvalidValuesException");
+        return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "No permission.");
+    }
+
+    DIR* dir = opendir(m_path->getFullPath().c_str());
+    if (!dir) {
+        LoggerE("throw IOException");
+        return PlatformResult(ErrorCode::IO_ERR, "Node has been deleted from platform.");
+    }
+
+    int err = 0;
+    struct dirent entry = {0};
+    struct dirent* result = nullptr;
+    NameList name_list;
+    while ((0 == (err = readdir_r(dir, &entry, &result))) && result) {
+        if (!strcmp(entry.d_name, ".") || !strncmp(entry.d_name, "..", 2)) {
+            continue;
+        }
+        name_list.push_back(entry.d_name);
+    }
+
+    if (closedir(dir) != 0) {
+        LoggerE("throw IOException");
+        return PlatformResult(ErrorCode::IO_ERR, "Could not close platform node.");
+    }
+
+    if (0 != err) {
+        LoggerE("throw IOException");
+        return PlatformResult(ErrorCode::IO_ERR, "Error while reading directory.");
+    }
+
+    *out_name_list = name_list;
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult Node::getChildNodes(NodeList* out_node_list) const
+{
+    LoggerD("Enter");
+
+    if (m_type != NT_DIRECTORY) {
+        LoggerE("Path %s Perm %d", m_path->getFullPath().c_str(), m_perms);
+        LoggerE("throw IOException");
+        LoggerE("Path %s Perm %d", m_path->getFullPath().c_str(), m_perms);
+        return PlatformResult(ErrorCode::IO_ERR, "Node is not directory.");
+    }
+
+    if ((m_perms & PERM_READ) == 0) {
+        LoggerE("Path %s Perm %d", m_path->getFullPath().c_str(), m_perms);
+        LoggerE("throw InvalidValuesException");
+        return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "No permission.");
+    }
+
+    DIR* dir = opendir(m_path->getFullPath().c_str());
+    if (!dir) {
+        LoggerE("Path %s Perm %d", m_path->getFullPath().c_str(), m_perms);
+        LoggerE("throw IOException");
+        return PlatformResult(ErrorCode::IO_ERR, "Node has been deleted from platform.");
+    }
+
+    int err = 0;
+    struct dirent entry = {0};
+    struct dirent* result = nullptr;
+    NodeList node_list;
+    while ((0 == (err = readdir_r(dir, &entry, &result))) && result) {
+        if (!strcmp(entry.d_name, ".") || !strncmp(entry.d_name, "..", 2)) {
+            continue;
+        }
+
+        NodePtr node;
+        Node::resolve(*m_path + entry.d_name, &node);
+        node->setPermissions(getPermissions()); // inherit access rights
+        node_list.push_back(node);
+    }
+
+    if (closedir(dir) != 0) {
+        LoggerE("Path %s Perm %d", m_path->getFullPath().c_str(), m_perms);
+        LoggerE("throw IOException");
+        return PlatformResult(ErrorCode::IO_ERR, "Could not close platform node.");
+    }
+
+    if (0 != err) {
+        LoggerE("Path %s Perm %d", m_path->getFullPath().c_str(), m_perms);
+        LoggerE("throw IOException");
+        return PlatformResult(ErrorCode::IO_ERR, "Error while reading directory.");
+    }
+
+    *out_node_list = node_list;
+
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult Node::createChild(
+        const PathPtr& path,
+        NodeType type,
+        NodePtr* node,
+        int options)
+{
+    LoggerD("Enter");
+    if (m_type != NT_DIRECTORY) {
+        LoggerE("throw IOException");
+        return PlatformResult(ErrorCode::IO_ERR, "Parent node is not a directory.");
+    }
+
+    if ((m_perms & PERM_WRITE) == 0) {
+        LoggerE("throw InvalidValuesException");
+        return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Not enough permissions.");
+    }
+
+    PathPtr childPath = *m_path + *path;
+    bool existed;
+    PlatformResult result = exists(childPath, &existed);
+    if (result.error_code() != ErrorCode::NO_ERROR) {
+        LoggerE("Fail: exists()");
+        return result;
+    }
+    if (existed) {
+        LoggerE("throw IOException");
+        return PlatformResult(ErrorCode::IO_ERR, "Node already exists.");
+    }
+
+    switch (type) {
+        case NT_FILE:
+            result = createAsFile(childPath, node, options);
+            break;
+        case NT_DIRECTORY:
+            result = createAsDirectory(childPath, node, options);
+            break;
+        default:
+            LoggerE("throw IOException");
+            return PlatformResult(ErrorCode::IO_ERR, "Unsupported node type.");
+    }
+    if (result.error_code() != ErrorCode::NO_ERROR) {
+        LoggerE("Fail CreateAs...()");
+        return result;
+    }
+
+    if (!!(*node)) {
+        (*node)->m_perms = m_perms;
+    } else {
+        LoggerE("throw IOException");
+        return PlatformResult(ErrorCode::IO_ERR, "Node creation error");
+    }
+
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult Node::remove(int options)
+{
+    LoggerD("Enter");
+    PlatformResult result(ErrorCode::NO_ERROR);
+    switch (m_type) {
+        case NT_FILE:
+            result = removeAsFile(m_path);
+            break;
+        case NT_DIRECTORY:
+            result = removeAsDirectory(m_path, (options & OPT_RECURSIVE));
+            break;
+        default:
+            LoggerE("throw UnknownError");
+            result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Not supported value of m_type");
+    }
+    return result;
+}
+
+PlatformResult Node::getSize(unsigned long long* size) const
+{
+    LoggerD("Enter");
+    if (m_type == NT_DIRECTORY) {
+        LoggerE("Getting size for directories is not supported.");
+        LoggerE("throw IOException");
+        return PlatformResult(ErrorCode::IO_ERR, "Getting size for directories is not supported.");
+    }
+
+    struct stat info;
+    PlatformResult result = stat(m_path, &info);
+    if (result.error_code() != ErrorCode::NO_ERROR) {
+        LoggerE("Fail: stat()");
+        return result;
+    }
+
+    if (!S_ISREG(info.st_mode)) {
+        LoggerE("Specified node is not a regular file.");
+        LoggerE("throw IOException");
+        return PlatformResult(ErrorCode::IO_ERR, "Specified node is not a regular file.");
+    }
+
+    *size =  (unsigned long long)info.st_size;
+
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult Node::getCreated(std::time_t* time) const
+{
+    LoggerD("Enter");
+    struct stat info;
+    PlatformResult result = stat(m_path, &info);
+    if (result.error_code() != ErrorCode::NO_ERROR) {
+        LoggerE("Fail: stat()");
+        return result;
+    }
+    *time = info.st_ctime;
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult Node::getModified(std::time_t* time) const
+{
+    LoggerD("Enter");
+    struct stat info;
+    PlatformResult result = stat(m_path, &info);
+    if (result.error_code() != ErrorCode::NO_ERROR) {
+        LoggerE("Fail: stat()");
+        return result;
+    }
+    *time = info.st_mtime;
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+// TODO Optimize it, maybe store a flag indicating that node is a root.
+PlatformResult Node::getParent(NodePtr* node) const
+{
+    LoggerD("Enter");
+
+//    LocationPaths roots = Manager::getInstance().getLocationPaths();
+//    for (LocationPaths::iterator it = roots.begin(); it != roots.end(); ++it) {
+//        if (*(*it) == *m_path) {
+//            return NodePtr();
+//        }
+//    }
+    PlatformResult result = Node::resolve(Path::create(m_path->getPath()), node);
+    if (result.error_code() == ErrorCode::NO_ERROR) {
+        (*node)->setPermissions(getPermissions());
+    }
+
+    return result;
+}
+
+PlatformResult Node::getMode(int* mode) const
+{
+    LoggerD("Enter");
+
+    struct stat info;
+    PlatformResult result = stat(m_path, &info);
+    if (result.error_code() == ErrorCode::NO_ERROR) {
+        *mode = 0;
+        if (info.st_mode & S_IRUSR) { *mode |= PM_USER_READ; }
+        if (info.st_mode & S_IWUSR) { *mode |= PM_USER_WRITE; }
+        if (info.st_mode & S_IXUSR) { *mode |= PM_USER_EXEC; }
+        if (info.st_mode & S_IRGRP) { *mode |= PM_GROUP_READ; }
+        if (info.st_mode & S_IWGRP) { *mode |= PM_GROUP_WRITE; }
+        if (info.st_mode & S_IXGRP) { *mode |= PM_GROUP_EXEC; }
+        if (info.st_mode & S_IROTH) { *mode |= PM_OTHER_READ; }
+        if (info.st_mode & S_IWOTH) { *mode |= PM_OTHER_WRITE; }
+        if (info.st_mode & S_IXOTH) { *mode |= PM_OTHER_EXEC; }
+    }
+    return result;
+}
+
+PlatformResult Node::exists(const PathPtr& path, bool* existed)
+{
+    LoggerD("Enter");
+
+    struct stat info;
+    memset(&info, 0, sizeof(struct stat));
+    int status = lstat(path->getFullPath().c_str(), &info);
+
+    *existed = false;
+
+    if (0 == status)
+    {
+        *existed = true;
+        return PlatformResult(ErrorCode::NO_ERROR);
+    }
+    else if (ENAMETOOLONG == errno)
+    {
+        LoggerE("throw IOException");
+        return PlatformResult(ErrorCode::IO_ERR, "file name is too long");
+    }
+    else if (errno != ENOENT)
+    {
+        *existed = true;
+        return PlatformResult(ErrorCode::NO_ERROR);
+    }
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult Node::stat(const PathPtr& path, struct stat* out_info)
+{
+    LoggerD("Enter");
+    struct stat info;
+    memset(&info, 0, sizeof(struct stat));
+
+    if (::stat(path->getFullPath().c_str(), &info) != 0)
+    {
+        LoggerE("File: %s", path->getFullPath().c_str());
+        LoggerE("throw IOException");
+        return PlatformResult(ErrorCode::IO_ERR, "Node does not exist or no access");
+    }
+    *out_info = info;
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+Node::Node(const PathPtr& path, NodeType type):
+            m_path(path),
+            m_type(type),
+            m_perms(PERM_NONE)
+{
+    LoggerD("Enter");
+}
+
+PlatformResult Node::createAsFile(const PathPtr& path, NodePtr* node, int /* options */)
+{
+    LoggerD("Enter");
+
+    PlatformResult result = createAsFileInternal(path);
+    if (result.error_code() == ErrorCode::NO_ERROR) {
+        node->reset(new Node(path, NT_FILE));
+    }
+    return result;
+}
+
+PlatformResult Node::createAsFileInternal(const PathPtr& path)
+{
+    LoggerD("Enter");
+
+    FILE* file = std::fopen(path->getFullPath().c_str(), "wb");
+    if (!file) {
+        LoggerE("fopen fails IOException throw for path [%s]",
+                path->getFullPath().c_str());
+        return PlatformResult(ErrorCode::IO_ERR, "Platform node could not be created.");
+    }
+    std::fclose(file);
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult Node::createAsDirectory(const PathPtr& path, NodePtr* node, int options)
+{
+    LoggerD("Enter");
+
+//    if (options & OPT_RECURSIVE) {
+//        auto parts = Utils::getParts(path);
+//        for (auto it = parts.begin(); it != parts.end(); ++it) {
+//            if (!exists(*it)) { createAsDirectoryInternal(*it); }
+//        }
+//    }
+    PlatformResult result = createAsDirectoryInternal(path);
+    if (result.error_code() == ErrorCode::NO_ERROR) {
+        node->reset(new Node(path, NT_DIRECTORY));
+    }
+    return result;
+}
+
+PlatformResult Node::createAsDirectoryInternal(const PathPtr& path)
+{
+    LoggerD("Enter");
+
+    if (mkdir(path->getFullPath().c_str(), S_IRWXU | S_IRWXG | S_IROTH |
+            S_IXOTH) != 0) {
+        LoggerE("throw IOException");
+        return PlatformResult(ErrorCode::IO_ERR, "Platform node could not be created.");
+    }
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult Node::removeAsFile(const PathPtr& path)
+{
+    LoggerD("Enter");
+
+    auto fullPath = path->getFullPath();
+    if (unlink(fullPath.c_str()) != 0) {
+        LoggerE("remove [%s]", fullPath.c_str());
+        LoggerE("throw IOException");
+        return PlatformResult(ErrorCode::IO_ERR, "Error while removing platform node.");
+    }
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult Node::removeAsDirectory(const PathPtr& path, bool recursive)
+{
+    LoggerD("Enter");
+
+    if (recursive) {
+        DIR* dir = opendir(path->getFullPath().c_str());
+        if (!dir) {
+            LoggerE("File %s", path->getFullPath().c_str());
+            LoggerE("throw IOException");
+            return PlatformResult(ErrorCode::IO_ERR, "Node does not exist or access denied.");
+        }
+        struct dirent entry = {0};
+        struct dirent* result = nullptr;
+        PlatformResult platform_result(ErrorCode::NO_ERROR);
+        while ((0 == (readdir_r(dir, &entry, &result))) && result) {
+            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) {
+                if (S_ISDIR(info.st_mode)) {
+                    platform_result = removeAsDirectory(subPath, true);
+                } else if (S_ISREG(info.st_mode)) {
+                    platform_result = removeAsFile(subPath);
+                }
+                if (platform_result.error_code() != ErrorCode::NO_ERROR) {
+                    LoggerE("Fail: getFullPath() (%d)",platform_result.error_code());
+                    closedir(dir);
+                    return platform_result;
+                }
+            }
+        }
+        closedir(dir);
+    }
+
+    errno = 0;
+    if (rmdir(path->getFullPath().c_str()) != 0) {
+        if (errno == EEXIST) {
+            LoggerE("throw IOException");
+            return PlatformResult(ErrorCode::IO_ERR, "Node has child nodes.");
+        }
+        LoggerE("throw IOException");
+        return PlatformResult(ErrorCode::IO_ERR, "Error while removing platform node.");
+    }
+
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+std::string Node::toUri(int /*widgetId*/) const
+{
+    LoggerD("Enter");
+    // 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)
+{
+    LoggerD("Enter");
+    auto myPath = aDirPath;
+    if(!myPath.empty() && myPath[myPath.length()-1] != Path::getSeparator()) {
+        myPath += Path::getSeparator();
+        LoggerD("updated aDirPath to:%s", aDirPath.c_str());
+    }
+
+    auto childPath = aFilePath->getFullPath();
+    bool isSubP = strncmp(myPath.c_str(), childPath.c_str(), myPath.size()) == 0;
+
+    LoggerD("aDirPath:%s myPath:%s aFilePath:%s isSubP:%d",
+            aDirPath.c_str(),
+            myPath.c_str(),
+            aFilePath->getFullPath().c_str(),
+            isSubP);
+
+    return isSubP;
+}
+
+}   // filesystem
+}   // extension
diff --git a/webWidgetTCT_device/src/archive/filesystem_node.h b/webWidgetTCT_device/src/archive/filesystem_node.h
new file mode 100755 (executable)
index 0000000..9cc9b52
--- /dev/null
@@ -0,0 +1,258 @@
+/*
+ * Copyright (c) 2015 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 _FILESYSTEM_NODE_H_
+#define _FILESYSTEM_NODE_H_
+
+#include <ctime>
+#include <cstddef>
+#include <sys/stat.h>
+#include <set>
+#include <memory>
+#include <mutex>
+#include <string>
+#include <vector>
+#include <ctime>
+#include <map>
+
+#include "common/platform_result.h"
+
+namespace extension {
+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;
+
+class Node;
+typedef std::shared_ptr<Node> NodePtr;
+typedef std::vector<NodePtr> NodeList;
+typedef NodeList::iterator NodeListIterator;
+
+class Path;
+typedef std::shared_ptr<Path> PathPtr;
+
+class Node : public std::enable_shared_from_this<Node>
+{
+public:
+    typedef std::vector<std::string> NameList;
+    typedef NameList::iterator NameListIterator;
+
+    //! \brief Resolves Path into Node
+    //!
+    //! This function creates Node wich represent folder or file
+    //! in file system.
+    //! @param path virtual path in filesystem
+    //! @param node output pointer
+    //! @return a platform result
+    static common::PlatformResult resolve(const PathPtr& path, NodePtr* node);
+    //! \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
+    //! @param granted true if access is granted, false if not
+    //! @return a platform result
+    common::PlatformResult checkPermission(const PathPtr& path,
+                                   const std::string& mode,
+                                   NodeType type,
+                                   bool* granted);
+    //! \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.
+    //! @param size output size of a file.
+    //! @return a platform result.
+    common::PlatformResult getSize(unsigned long long* size) const;
+    //! \brief Gets creation date of this node.
+    //! @param time output date.
+    //! @return a platform result.
+    common::PlatformResult getCreated(std::time_t* time) const;
+    //! \brief Gets last modification date of this node.
+    //! @param time output date.
+    //! @return a platform result.
+    common::PlatformResult getModified(std::time_t* time) const;
+    //! \brief Gets parent of this node.
+    //! @param node the output node pointer or NULL if no parent (e.g. in case of a root node).
+    //! @return a platform result
+    common::PlatformResult getParent(NodePtr* node) const;
+    //! \brief Gets platform permissions.
+    //! @param mode output Platform permissions (set of flags from @see Permissions enum).
+    //! @return a platform result
+    common::PlatformResult getMode(int* mode) const;
+    //! \brief Gets direct child of this node.
+    //! @param path Path to the child node.
+    //! @param output Ptr to the child node.
+    //! @return a platform result
+    //! @remarks Ownership passed to the caller.
+    common::PlatformResult getChild(const PathPtr& path, NodePtr* node);
+    //! \brief Gets list of names of direct child nodes.
+    //! @param out_name_list the pointer to the list of nodes
+    //! @return a platform result
+    common::PlatformResult getChildNames(NameList* out_name_list) const;
+    //! \brief Gets list of direct child nodes.
+    //! @param out_node_list the pointer to the list of nodes
+    //! @return a platform result
+    //! @remarks Ownership passed to the caller.
+    //! @deprecated
+    common::PlatformResult getChildNodes(NodeList* out_node_list) const;
+    //! \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 node of the created file or directory
+    //! @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
+    common::PlatformResult createChild(
+        const PathPtr& path,
+        NodeType,
+        NodePtr* node,
+        int options = OPT_NONE);
+    //! \brief Removes underlying filesystem node.
+    //! @param options Removal options (by default removal is recursive).
+    //! @return a platform result
+    //! @remarks Synchronous.
+    //! Valid options:
+    //! - OPT_RECURSIVE - remove node recursively.
+    common::PlatformResult remove(int options);
+
+    std::string toUri(int widgetId) const;
+
+    static bool isSubPath(std::string aDirPath, PathPtr aFilePath);
+
+private:
+    static common::PlatformResult exists(const PathPtr& path, bool* existed);
+    static common::PlatformResult stat(const PathPtr& path, struct stat* out_info);
+
+    Node(const PathPtr& path, NodeType type);
+
+    common::PlatformResult createAsFile(const PathPtr& path, NodePtr* node, int options);
+    common::PlatformResult createAsFileInternal(const PathPtr& path);
+
+    common::PlatformResult createAsDirectory(const PathPtr& path, NodePtr* node, int options);
+    common::PlatformResult createAsDirectoryInternal(const PathPtr& path);
+
+    common::PlatformResult removeAsFile(const PathPtr& path);
+    common::PlatformResult removeAsDirectory(const PathPtr& path, bool recursive);
+
+    PathPtr m_path;
+    NodeType m_type;
+    int m_perms;
+
+};
+
+} // extension
+} // filesystem
+
+#endif /* _FILESYSTEM_NODE_H_ */
+
diff --git a/webWidgetTCT_device/src/archive/filesystem_path.cc b/webWidgetTCT_device/src/archive/filesystem_path.cc
new file mode 100755 (executable)
index 0000000..1357a71
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2015 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 <memory>
+#include <algorithm>
+#include <iterator>
+#include <stdlib.h>
+#include <limits.h>
+
+#include "filesystem_path.h"
+#include "common/logger.h"
+
+namespace extension {
+namespace filesystem {
+
+const Path::SeparatorType Path::m_pathSeparator = '/';
+
+PathPtr Path::create(const std::string& path)
+{
+    LoggerD("Enter");
+    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)
+{
+    LoggerD("Enter");
+    if (!isValid(str)) {
+        LoggerD("Invalid string %s", str.c_str());
+        LoggerW("throw NotFoundException");
+        // The only way to remove throw statement from here is to just return, because
+        // this function is used in the operator functions and they're not able
+        // to handle a PlatformResult value;
+        return;
+    }
+//    std::string tmp = Commons::String::unique(/*Commons::String::trim*/(
+//                                                  str), m_pathSeparator);
+    std::string tmp = str;
+
+    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
+} // extension
diff --git a/webWidgetTCT_device/src/archive/filesystem_path.h b/webWidgetTCT_device/src/archive/filesystem_path.h
new file mode 100755 (executable)
index 0000000..c06b9cb
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2015 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 _FILESYSTEM_PATH_H_
+#define _FILESYSTEM_PATH_H_
+
+#include <string>
+#include <vector>
+#include <memory>
+
+namespace extension {
+namespace filesystem {
+
+class Path;
+typedef std::shared_ptr<Path> PathPtr;
+
+class 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
+} // extension
+
+#endif /* _FILESYSTEM_PATH_H_ */
diff --git a/webWidgetTCT_device/src/archive/un_zip.cc b/webWidgetTCT_device/src/archive/un_zip.cc
new file mode 100755 (executable)
index 0000000..a937c58
--- /dev/null
@@ -0,0 +1,476 @@
+/*
+ * Copyright (c) 2015 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 "un_zip.h"
+
+#include <cstdio>
+#include <errno.h>
+#include <iostream>
+#include <memory>
+#include <string>
+#include <string.h>
+#include <sys/stat.h>
+
+#include "common/logger.h"
+#include "common/platform_exception.h"
+#include "filesystem_file.h"
+
+#include "archive_file.h"
+#include "archive_utils.h"
+#include "un_zip_extract_request.h"
+
+namespace extension {
+namespace archive {
+
+using namespace common;
+
+UnZip::UnZip(const std::string& filename) :
+        m_zipfile_name(filename),
+        m_unzip(NULL),
+        m_default_buffer_size(1024 * 1024),
+        m_is_open(false)
+{
+    LoggerD("Entered");
+    m_unzip = unzOpen(filename.c_str());
+}
+
+UnZip::~UnZip()
+{
+    LoggerD("Enter");
+    close();
+}
+
+PlatformResult UnZip::close()
+{
+    LoggerD("Entered");
+    if(!m_is_open) {
+        LoggerD("Unzip already closed - exiting");
+        return PlatformResult(ErrorCode::NO_ERROR);
+    }
+
+    int errclose = unzClose(m_unzip);
+    m_unzip = NULL;
+
+    if (errclose != UNZ_OK) {
+        LoggerE("ret: %d",errclose);
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, getArchiveLogMessage(errclose, "unzClose()"));
+    }
+    m_is_open = false;
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult UnZip::open(const std::string& filename, UnZipPtr* out_unzip)
+{
+    LoggerD("Entered");
+    UnZipPtr unzip = UnZipPtr(new UnZip(filename));
+
+    if(!unzip->m_unzip) {
+        LoggerE("unzOpen returned NULL : It means the file is invalid.");
+        return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Failed to open zip file");
+    }
+    unzip->m_is_open = true;
+    *out_unzip = unzip;
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult UnZip::listEntries(unsigned long *decompressedSize, ArchiveFileEntryPtrMapPtr* out_map)
+{
+    LoggerD("Enter");
+    if(!m_is_open) {
+        LoggerE("Failed to get list of entries - UnZip closed");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get list of files in zip archive");
+    }
+    unz_global_info gi;
+    int err = unzGetGlobalInfo (m_unzip, &gi);
+    if (UNZ_OK != err) {
+        LoggerE("ret: %d",err);
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, getArchiveLogMessage(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) {
+        LoggerW("%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) {
+            LoggerE("ret: %d",err);
+            return PlatformResult(ErrorCode::UNKNOWN_ERR, getArchiveLogMessage(err, "unzGetCurrentFileInfo()"));
+        }
+
+        LoggerD("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;
+        LoggerD("%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) {
+                LoggerE("ret: %d",err);
+                return PlatformResult(ErrorCode::UNKNOWN_ERR, getArchiveLogMessage(err, "unzGoToNextFile()"));
+            }
+        }
+    }
+
+    (*decompressedSize) = totalDecompressed;
+
+    *out_map = map;
+
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult UnZip::extractAllFilesTo(const std::string& extract_path,
+                                  ExtractAllProgressCallback* callback)
+{
+    LoggerD("Enter");
+    if(!m_is_open) {
+        LoggerE("Failed to extract files - UnZip closed");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to extract zip archive");
+    }
+
+    //
+    // Calculate number of entries to extract and total number of bytes
+    //
+    unz_global_info gi;
+    PlatformResult result = updateCallbackWithArchiveStatistics(callback, gi);
+    if ( result.error_code() != ErrorCode::NO_ERROR) {
+        LoggerE("Error: %s", result.message().c_str());
+        return result;
+    }
+
+    //
+    // Begin extracting entries
+    //
+    int err = unzGoToFirstFile(m_unzip);
+    if (err != UNZ_OK) {
+        LoggerE("%s",getArchiveLogMessage(err, "unzGoToFirstFile()").c_str());
+    }
+
+    for (uLong i = 0; i < gi.number_entry; i++) {
+
+        if (callback->isCanceled()) {
+            LoggerD("Operation cancelled");
+            return PlatformResult(ErrorCode::OPERATION_CANCELED_ERR);
+        }
+
+        result = extractCurrentFile(extract_path, std::string(), callback);
+        if ( result.error_code() != ErrorCode::NO_ERROR) {
+            LoggerE("Fail: extractCurrentFile()");
+            return result;
+        }
+
+        if ((i + 1) < gi.number_entry) {
+            err = unzGoToNextFile(m_unzip);
+            if (UNZ_OK != err) {
+                LoggerE("ret: %d",err);
+                return PlatformResult(ErrorCode::UNKNOWN_ERR, getArchiveLogMessage(err, "unzGoToNextFile()"));
+            }
+        }
+    }
+
+    callback->callSuccessCallbackOnMainThread();
+
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+struct ExtractDataHolder
+{
+    UnZip* unzip;
+    ExtractEntryProgressCallback* callback;
+    std::string root_output_path;
+};
+
+PlatformResult UnZip::extractTo(ExtractEntryProgressCallback* callback)
+{
+    LoggerD("Enter");
+    if(!m_is_open) {
+        LoggerE("Extract archive file entry failed - UnZip closed");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Extract archive file entry failed");
+    }
+
+    if(!callback) {
+        LoggerE("callback is NULL");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Extract archive file entry failed");
+    }
+
+    if(!callback->getArchiveFileEntry()) {
+        LoggerE("callback->getArchiveFileEntry() is NULL");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Extract archive file entry failed");
+    }
+
+    filesystem::FilePtr out_dir = callback->getDirectory();
+    if(!out_dir) {
+        LoggerE("Output directory is not valid");
+        return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Output directory is not correct");
+    }
+
+    NodePtr out_node = out_dir->getNode();
+    if(!out_node) {
+        LoggerE("Output directory is not valid");
+        return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Output directory is not correct");
+    }
+
+    PathPtr out_path = out_node->getPath();
+    if(!out_path) {
+        LoggerE("Output directory is not valid");
+        return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Output directory is not correct");
+    }
+
+    auto entry_name_in_zip = callback->getArchiveFileEntry()->getName();
+    auto root_output_path = out_dir->getNode()->getPath()->getFullPath();
+    LoggerD("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;
+    PlatformResult result = updateCallbackWithArchiveStatistics(callback, gi, entry_name_in_zip);
+    if ( result.error_code() != ErrorCode::NO_ERROR) {
+        LoggerE("Fail: updateCallbackWithArchiveStatistics()");
+        return result;
+    }
+
+    //
+    // Begin extracting entries
+    //
+
+    ExtractDataHolder h;
+    h.unzip = this;
+    h.callback = callback;
+    h.root_output_path = root_output_path;
+
+    // this loop call internally progress callbacks
+    unsigned int matched;
+    result = IterateFilesInZip(gi, entry_name_in_zip, callback, extractItFunction, matched, &h);
+    if ( result.error_code() != ErrorCode::NO_ERROR) {
+        LoggerE("Fail: IterateFilesInZip()");
+        return result;
+    }
+
+    // after finish extracting success callback will be called
+    callback->callSuccessCallbackOnMainThread();
+
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult UnZip::extractItFunction(const std::string& file_name, unz_file_info& file_info,
+                                       void* user_data)
+{
+    LoggerD("Enter");
+    ExtractDataHolder* h = static_cast<ExtractDataHolder*>(user_data);
+    if(!h) {
+        LoggerE("ExtractDataHolder is NULL!");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Could not list content of zip archive");
+    }
+
+    PlatformResult result = h->unzip->extractCurrentFile(h->root_output_path,
+                                          h->callback->getStripBasePath(),
+                                          h->callback);
+    if ( result.error_code() != ErrorCode::NO_ERROR) {
+        LoggerE("Error: %s", result.message().c_str());
+        return result;
+    }
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult UnZip::IterateFilesInZip(unz_global_info& gi,
+        const std::string& entry_name_in_zip,
+        OperationCallbackData* callback,
+        UnZip::IterateFunction itfunc,
+        unsigned int& num_file_or_folder_matched,
+        void* user_data)
+{
+    LoggerD("Enter");
+    int err = unzGoToFirstFile(m_unzip);
+    if (UNZ_OK != err) {
+        LoggerW("%s",getArchiveLogMessage(err, "unzGoToFirstFile()").c_str());
+    }
+
+    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()) {
+            LoggerD("Operation cancelled");
+            return PlatformResult(ErrorCode::OPERATION_CANCELED_ERR);
+        }
+
+        err = unzGetCurrentFileInfo(m_unzip, &cur_file_info,
+                tmp_fname, sizeof(tmp_fname), NULL, 0, NULL, 0);
+        if (UNZ_OK != err) {
+            LoggerE("ret: %d",err);
+            return PlatformResult(ErrorCode::UNKNOWN_ERR, getArchiveLogMessage(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) {
+            PlatformResult result = itfunc(cur_filename_in_zip, cur_file_info, user_data);
+            if ( result.error_code() != ErrorCode::NO_ERROR) {
+                LoggerE("Error: %s", result.message().c_str());
+                return result;
+            }
+            ++num_file_or_folder_matched;
+        }
+
+        if ((i + 1) < gi.number_entry) {
+            err = unzGoToNextFile(m_unzip);
+            if (UNZ_OK != err) {
+                LoggerE("ret: %d",err);
+                return PlatformResult(ErrorCode::UNKNOWN_ERR, getArchiveLogMessage(err, "unzGoToNextFile()"));
+            }
+        }
+    }
+
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult UnZip::extractCurrentFile(const std::string& extract_path,
+        const std::string& base_strip_path,
+        BaseProgressCallback* callback)
+{
+    LoggerD("Entered");
+
+    if (callback->isCanceled()) {
+        LoggerD("Operation cancelled");
+        return PlatformResult(ErrorCode::OPERATION_CANCELED_ERR);
+    }
+
+    LoggerD("extract_path: [%s] base_strip_path: [%s] ", extract_path.c_str(),
+            base_strip_path.c_str());
+    return 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;
+};
+
+PlatformResult generateArchiveStatistics(const std::string& file_name, unz_file_info& file_info,
+         void* user_data)
+{
+    LoggerD("Enter");
+    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;
+        }
+    }
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult UnZip::updateCallbackWithArchiveStatistics(ExtractAllProgressCallback* callback,
+        unz_global_info& out_global_info,
+        const std::string& optional_filter)
+{
+    LoggerD("Enter");
+    int err = unzGetGlobalInfo(m_unzip, &out_global_info);
+    if (UNZ_OK != err) {
+        LoggerE("ret: %d",err);
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, getArchiveLogMessage(err, "unzGetGlobalInfo()"));
+    }
+
+    ArchiveStatistics astats;
+    unsigned int num_matched;
+
+    PlatformResult result = IterateFilesInZip(out_global_info, optional_filter,
+            callback, generateArchiveStatistics, num_matched, &astats);
+    if ( result.error_code() != ErrorCode::NO_ERROR) {
+        LoggerE("Error: %s", result.message().c_str());
+        return result;
+    }
+    if(0 == num_matched) {
+        LoggerE("No matching file/directory: [%s] has been found in zip archive",
+                optional_filter.c_str());
+        LoggerE("Throwing NotFoundException - Could not extract file from archive");
+        return PlatformResult(ErrorCode::NOT_FOUND_ERR, "Could not extract file from archive");
+    }
+
+    callback->setExpectedDecompressedSize(astats.uncompressed_size);
+    LoggerD("Expected uncompressed size: %s",
+            bytesToReadableString(astats.uncompressed_size).c_str());
+
+    callback->setNumberOfFilesToExtract(astats.number_of_files);
+    LoggerD("Number entries to extract: files: %d folders: %d", astats.number_of_files,
+            astats.number_of_folders);
+
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+} //namespace archive
+} //namespace extension
diff --git a/webWidgetTCT_device/src/archive/un_zip.h b/webWidgetTCT_device/src/archive/un_zip.h
new file mode 100755 (executable)
index 0000000..187d9c5
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2015 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_ARCHIVE_UNZIP_H__
+#define __TIZEN_ARCHIVE_UNZIP_H__
+
+#include <memory>
+#include <string>
+#include <queue>
+#include <unzip.h>
+
+#include "common/platform_result.h"
+#include "archive_callback_data.h"
+#include "archive_file_entry.h"
+
+namespace extension {
+namespace archive {
+
+class UnZipExtractRequest;
+
+typedef std::shared_ptr<std::vector<char>> CharVectorPtr;
+
+class UnZip;
+typedef std::shared_ptr<UnZip> UnZipPtr;
+
+class UnZip
+{
+public:
+    static PlatformResult open(const std::string& filename, UnZipPtr* out_unzip);
+    ~UnZip();
+
+    PlatformResult listEntries(unsigned long *decompressedSize, ArchiveFileEntryPtrMapPtr* out_map);
+
+    /**
+     * \brief Extract all files to output directory
+     * \param callback which keep pointer to ArchiveFile.
+     */
+    PlatformResult extractAllFilesTo(const std::string& extract_path,
+            ExtractAllProgressCallback* callback);
+
+    PlatformResult extractTo(ExtractEntryProgressCallback* callback);
+
+    PlatformResult close();
+
+private:
+    UnZip(const std::string& filename);
+
+    /**
+     * \brief Extract current file (iterated with minizip library)
+     * \param callback which keep pointer to ArchiveFile.
+     */
+    PlatformResult extractCurrentFile(const std::string& extract_path,
+            const std::string& base_strip_path,
+            BaseProgressCallback* callback);
+
+    static PlatformResult extractItFunction(const std::string& file_name,
+            unz_file_info& file_info,
+            void* user_data);
+
+    typedef PlatformResult (*IterateFunction) (const std::string& file_name,
+            unz_file_info& file_info,
+            void* user_data);
+
+    PlatformResult IterateFilesInZip(unz_global_info& gi,
+            const std::string& entry_name_in_zip,
+            OperationCallbackData* callback,
+            IterateFunction itfunc,
+            unsigned int& num_file_or_folder_matched,
+            void* user_data);
+
+    PlatformResult 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 extension
+
+#endif // __TIZEN_ARCHIVE_ZIP_H__
diff --git a/webWidgetTCT_device/src/archive/un_zip_extract_request.cc b/webWidgetTCT_device/src/archive/un_zip_extract_request.cc
new file mode 100755 (executable)
index 0000000..2498d6e
--- /dev/null
@@ -0,0 +1,520 @@
+/*
+ * Copyright (c) 2015 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 "un_zip_extract_request.h"
+
+#include <cstdio>
+#include <errno.h>
+#include <iostream>
+#include <memory>
+#include <string>
+#include <string.h>
+#include <sys/stat.h>
+#include <utime.h>
+
+#include "common/logger.h"
+#include "common/tools.h"
+
+#include "filesystem_file.h"
+#include "archive_file.h"
+#include "archive_utils.h"
+#include "un_zip.h"
+
+namespace extension {
+namespace archive {
+
+using namespace common;
+using common::tools::GetErrorString;
+
+FilePathStatus getPathStatus(const std::string& path)
+{
+    LoggerD("Enter");
+    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)
+{
+    LoggerD("Enter");
+    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)
+{
+    LoggerD("Enter");
+    if(check_first) {
+        const FilePathStatus path_status = getPathStatus(path);
+        //LoggerD("[%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);
+            //LoggerD("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(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == -1) {
+                    LoggerE("Couldn't create new directory: %s errno: %s",
+                            left_part.c_str(), GetErrorString(errno).c_str());
+               //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)
+{
+  LoggerD("Enter");
+  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) {
+      LoggerE("Couldn't set time for: [%s] errno: %s", filepath.c_str(), GetErrorString(errno).c_str());
+  }
+}
+
+PlatformResult UnZipExtractRequest::execute(UnZip& owner, const std::string& extract_path,
+        const std::string& base_strip_path,
+        BaseProgressCallback* callback)
+{
+    LoggerD("Enter");
+    UnZipExtractRequest req(owner, extract_path, base_strip_path, callback);
+    if(!req.m_callback){
+        LoggerE("Callback is null");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Problem with callback functionality");
+    }
+    return 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)
+{
+    LoggerD("Enter");
+    m_filename_inzip[0] = '\0';
+}
+
+PlatformResult UnZipExtractRequest::run()
+{
+    LoggerD("Entered");
+
+    PlatformResult result = getCurrentFileInfo();
+    if (result.error_code() != ErrorCode::NO_ERROR) {
+        LoggerE("Error: %s", result.message().c_str());
+        return result;
+    }
+
+    if(m_is_directory_entry) {
+        result = handleDirectoryEntry();
+    } else {
+        result = handleFileEntry();
+    }
+
+    return result;
+}
+
+UnZipExtractRequest::~UnZipExtractRequest()
+{
+    LoggerD("Enter");
+
+    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) {
+            LoggerE("Couldn't remove partial file! "
+                    "std::remove(\"%s\") failed with errno: %s",
+                    m_output_filepath.c_str(), GetErrorString(errno).c_str());
+        }
+    }
+
+    delete [] m_buffer;
+    m_buffer = NULL;
+
+    if(m_close_unz_current_file) {
+        int err = unzCloseCurrentFile (m_owner.m_unzip);
+        if(UNZ_OK != err) {
+            LoggerW("%s",getArchiveLogMessage(err, "unzCloseCurrentFile()").c_str());
+        }
+    }
+}
+
+PlatformResult UnZipExtractRequest::getCurrentFileInfo()
+{
+    LoggerD("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) {
+        LoggerE("ret: %d", err);
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, getArchiveLogMessage(err, "unzGetCurrentFileInfo()"));
+    }
+
+    LoggerD("Input from ZIP: m_filename_inzip: [%s]", m_filename_inzip);
+    LoggerD("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) {
+            LoggerW("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());
+            LoggerD("Stripped file name: [%s]", file_path.c_str());
+        }
+    }
+    else {
+        LoggerD("Not stripped file name: [%s]", file_path.c_str());
+    }
+
+    m_output_filepath = removeDuplicatedSlashesFromPath(m_extract_path + "/" + file_path);
+
+    LoggerD("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();
+
+    LoggerD("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;
+                }
+            }
+
+            LoggerD("Type: DIRECTORY checking base output directories: [%s]",
+                    base_directories.c_str());
+            createMissingDirectories(base_directories, false);
+        } else {
+            LoggerD("Type: FILE checking output dir: [%s]", m_new_dir_path.c_str());
+            createMissingDirectories(m_new_dir_path, false);
+        }
+    }
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult UnZipExtractRequest::handleDirectoryEntry()
+{
+    LoggerD("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) {
+                    LoggerE("std::remove(\"%s\") failed with errno: %s",
+                            m_new_dir_path.c_str(), GetErrorString(errno).c_str());
+                    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Could not overwrite file in output directory");
+                }
+            } else {                            //Is a file & overwrite is not set:
+                LoggerE("Failed to extract directory, "
+                        "file with the same name exists in output directory");
+                return PlatformResult(ErrorCode::UNKNOWN_ERR, "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(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == -1) {
+            LoggerE("Couldn't create new directory: %s errno: %s",
+                    m_new_dir_path.c_str(), GetErrorString(errno).c_str());
+            return PlatformResult(ErrorCode::UNKNOWN_ERR, "Could not create new directory in extract output directory");
+        }
+    }
+
+    LoggerD("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);
+
+    LoggerD("Extracted directory entry: [%s]", m_new_dir_path.c_str());
+
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult UnZipExtractRequest::prepareOutputSubdirectory()
+{
+    LoggerD("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) {
+            LoggerE("Path: %s is pointing to file not directory!",
+                    m_new_dir_path.c_str());
+            return PlatformResult(ErrorCode::UNKNOWN_ERR, "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(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == -1) {
+            LoggerW("couldn't create new directory: %s errno: %s",
+                    m_new_dir_path.c_str(), GetErrorString(errno).c_str());
+            //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()) {
+        LoggerD("Operation cancelled");
+        return PlatformResult(ErrorCode::OPERATION_CANCELED_ERR);
+    }
+
+    const FilePathStatus output_fstatus = getPathStatus(m_output_filepath);
+    if(FPS_NOT_EXIST != output_fstatus) {
+        if(!m_callback->getOverwrite()) {
+            LoggerW("%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 PlatformResult(ErrorCode::INVALID_MODIFICATION_ERR, "file already exists.");
+        } else {
+            if(FPS_DIRECTORY == output_fstatus) {
+                filesystem::PathPtr path = filesystem::Path::create(m_output_filepath);
+                filesystem::NodePtr node;
+                PlatformResult result = filesystem::Node::resolve(path, &node);
+                if (result.error_code() != ErrorCode::NO_ERROR) {
+                    LoggerE("Error: %s", result.message().c_str());
+                    return result;
+                }
+                result = node->remove(filesystem::OPT_RECURSIVE);
+                if (result.error_code() != ErrorCode::NO_ERROR) {
+                    LoggerE("Error: %s", result.message().c_str());
+                    return result;
+                }
+            }
+        }
+    }
+
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult UnZipExtractRequest::handleFileEntry()
+{
+    LoggerD("Entered");
+
+    PlatformResult result = prepareOutputSubdirectory();
+    if (result.error_code() != ErrorCode::NO_ERROR) {
+        LoggerE("File exists but overwrite is false");
+        return result;
+    }
+
+    int err = unzOpenCurrentFilePassword(m_owner.m_unzip,
+        NULL); //password is not supported yet therefore passing NULL
+    if (UNZ_OK != err) {
+        LoggerE("ret: %d", err);
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, getArchiveLogMessage(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) {
+        LoggerE("Couldn't allocate buffer with size: %s",
+                bytesToReadableString(buffer_size).c_str());
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Memory allocation failed");
+    }
+
+    m_output_file = fopen(m_output_filepath.c_str(), "wb");
+    if(!m_output_file) {
+        LoggerE("Couldn't open output file: %s", m_output_filepath.c_str());
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Could not create extracted file");
+    }
+    m_delete_output_file = true;
+
+    bool marked_as_finished = false;
+
+    LoggerD("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()) {
+        LoggerE("Entry not found");
+        return PlatformResult(ErrorCode::NOT_FOUND_ERR, "Entry not found");
+    }
+
+    while(true) {
+        if(m_callback->isCanceled()) {
+            LoggerD("Operation cancelled");
+            return PlatformResult(ErrorCode::OPERATION_CANCELED_ERR);
+        }
+
+        int read_size = unzReadCurrentFile(m_owner.m_unzip, m_buffer, buffer_size);
+        if (read_size < 0) {
+            LoggerE("unzReadCurrentFile failed with error code:%d for file:%s", read_size,
+                    m_filename_inzip);
+            return PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to extract file from zip archive");
+        }
+        else if(0 == read_size) {
+
+            if(extract_callback) {
+                if(!marked_as_finished) {
+                    LoggerD("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) {
+                        LoggerD("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) {
+            LoggerE("Couldn't write extracted data to output file:%s",
+                    m_output_filepath.c_str());
+            return PlatformResult(ErrorCode::UNKNOWN_ERR, "Could not write extract file into output file");
+        }
+
+        if(extract_callback) {
+            extract_callback->extractedPartOfFile(read_size);
+            LoggerD("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) {
+                LoggerD("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();
+            }
+
+            LoggerD("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);
+
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+} //namespace archive
+} //namespace extension
diff --git a/webWidgetTCT_device/src/archive/un_zip_extract_request.h b/webWidgetTCT_device/src/archive/un_zip_extract_request.h
new file mode 100755 (executable)
index 0000000..f5c3ce2
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2015 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_ARCHIVE_UNZIP_EXTRACT_REQUEST_H__
+#define __TIZEN_ARCHIVE_UNZIP_EXTRACT_REQUEST_H__
+
+#include <stdio.h>
+#include <string>
+#include "un_zip.h"
+
+namespace extension {
+namespace archive {
+
+enum FilePathStatus {
+    FPS_NOT_EXIST = 0,
+    FPS_FILE = 1,
+    FPS_DIRECTORY = 2
+};
+
+class UnZipExtractRequest
+{
+public:
+    static PlatformResult 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);
+
+    //Not copyable, assignable
+    UnZipExtractRequest(UnZipExtractRequest const&) = delete;
+    UnZipExtractRequest& operator=(UnZipExtractRequest const&) = delete;
+
+    PlatformResult run();
+    PlatformResult getCurrentFileInfo();
+    PlatformResult handleDirectoryEntry();
+    PlatformResult handleFileEntry();
+    PlatformResult 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 extension
+
+#endif // __TIZEN_ARCHIVE_UNZIP_EXTRACT_REQUEST_H__
diff --git a/webWidgetTCT_device/src/archive/zip.cc b/webWidgetTCT_device/src/archive/zip.cc
new file mode 100755 (executable)
index 0000000..b5d18a1
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2015 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 "zip.h"
+
+#include <iostream>
+#include <memory>
+#include <string>
+#include <string.h>
+#include <sys/stat.h>
+
+#include "common/logger.h"
+#include "common/platform_result.h"
+#include "filesystem_file.h"
+#include "archive_file.h"
+#include "archive_utils.h"
+#include "zip_add_request.h"
+
+namespace extension {
+namespace archive {
+
+using namespace common;
+
+void Zip::generateZipFileInfo(const std::string& filename, zip_fileinfo& out_zi)
+{
+    LoggerD("Enter");
+
+    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 = {0};
+    tzset();
+    if (nullptr != localtime_r(&tm_t, &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),
+        m_is_open(false)
+{
+    LoggerD("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;
+    }
+    LoggerD("append_mode: %d", append_mode);
+
+    m_zip = zipOpen(filename.c_str(), append_mode);
+}
+
+Zip::~Zip()
+{
+    LoggerD("Enter");
+
+    close();
+}
+
+PlatformResult Zip::close()
+{
+    LoggerD("Entered");
+    if(!m_is_open) {
+        LoggerD("Already closed - exiting.");
+        return PlatformResult(ErrorCode::NO_ERROR);
+    }
+
+    int errclose = zipClose(m_zip, NULL);
+    m_zip = NULL;
+
+    if (errclose != ZIP_OK) {
+        LoggerE("ret: %d", errclose);
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, getArchiveLogMessage(errclose, "zipClose()"));
+    }
+    m_is_open = false;
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult Zip::createNew(const std::string& filename, ZipPtr* out_zip)
+{
+    LoggerD("Entered");
+    ZipPtr zip = ZipPtr(new Zip(filename, ZOM_CREATE));
+    if(!zip->m_zip) {
+        LoggerE("zipOpen returned NULL!");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Opening/creating zip file failed");
+    }
+    zip->m_is_open = true;
+    *out_zip = zip;
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult Zip::open(const std::string& filename, ZipPtr* out_zip)
+{
+    LoggerD("Entered");
+    ZipPtr zip = ZipPtr(new Zip(filename, ZOM_ADDINZIP));
+    if(!zip->m_zip) {
+        LoggerE("zipOpen returned NULL!");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Opening/creating zip file failed");
+    }
+    zip->m_is_open = true;
+    *out_zip = zip;
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult Zip::addFile(AddProgressCallback*& callback)
+{
+    LoggerD("Entered");
+    if(!callback) {
+        LoggerE("callback is NULL!");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Could not add file(-s) to archive");
+    }
+    if(!m_is_open) {
+        LoggerE("Zip file not opened - exiting");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Could not add file(-s) to archive - zip file closed");
+    }
+
+    return ZipAddRequest::execute(*this, callback);
+}
+
+} //namespace archive
+} //namespace extension
diff --git a/webWidgetTCT_device/src/archive/zip.h b/webWidgetTCT_device/src/archive/zip.h
new file mode 100755 (executable)
index 0000000..47108bf
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2015 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_ARCHIVE_ZIP_H__
+#define __TIZEN_ARCHIVE_ZIP_H__
+
+#include <memory>
+#include <string>
+
+#include <zip.h>
+
+#include "archive_callback_data.h"
+
+namespace extension {
+namespace archive {
+
+
+class ZipAddRequest;
+
+class Zip;
+typedef std::shared_ptr<Zip> ZipPtr;
+
+class Zip
+{
+public:
+    static PlatformResult createNew(const std::string& filename, ZipPtr* out_zip);
+    static PlatformResult open(const std::string& filename, ZipPtr* out_zip);
+    ~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.
+     */
+    PlatformResult addFile(AddProgressCallback*& callback);
+
+    PlatformResult 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 extension
+
+#endif // __TIZEN_ARCHIVE_ZIP_H__
diff --git a/webWidgetTCT_device/src/archive/zip_add_request.cc b/webWidgetTCT_device/src/archive/zip_add_request.cc
new file mode 100755 (executable)
index 0000000..6a5e570
--- /dev/null
@@ -0,0 +1,558 @@
+/*
+ * Copyright (c) 2015 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 "zip_add_request.h"
+#include "common/logger.h"
+#include "archive_file.h"
+#include "archive_file_entry.h"
+#include "archive_utils.h"
+
+using namespace common;
+
+namespace extension {
+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)
+{
+    LoggerD("Enter");
+
+}
+
+ZipAddRequest::~ZipAddRequest()
+{
+    LoggerD("Enter");
+    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) {
+            LoggerE("%s",getArchiveLogMessage(err, "zipCloseFileInZip()").c_str());
+        }
+    }
+}
+
+PlatformResult ZipAddRequest::execute(Zip& owner, AddProgressCallback*& callback)
+{
+    LoggerD("Enter");
+    ZipAddRequest req(owner, callback);
+    return req.run();
+}
+
+PlatformResult ZipAddRequest::run()
+{
+    LoggerD("Enter");
+    if(!m_callback) {
+        LoggerE("m_callback is NULL");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Could not add file(-s) to archive");
+    }
+
+    if(!m_callback->getFileEntry()) {
+        LoggerE("m_callback->getFileEntry() is NULL");
+        return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Provided ArchiveFileEntry is not correct");
+    }
+
+    if(m_callback->isCanceled()) {
+        LoggerD("Operation cancelled");
+        return PlatformResult(ErrorCode::OPERATION_CANCELED_ERR);
+    }
+
+    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
+    LoggerW("STUB Not setting PERM_READ permissions");
+    //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;
+    LoggerD("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.
+    //
+    PlatformResult result(ErrorCode::NO_ERROR);
+    if(m_destination_path_in_zip.length() > 0) {
+        LoggerD("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);
+
+                LoggerD("Adding empty directory: [%s] to archive", new_dir.c_str());
+                result = addEmptyDirectoryToZipArchive(new_dir);
+                if (result.error_code() != ErrorCode::NO_ERROR) {
+                    return result;
+                }
+            }
+        }
+    }
+
+    // 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()) {
+        LoggerD("Operation cancelled");
+        return PlatformResult(ErrorCode::OPERATION_CANCELED_ERR);
+    }
+
+    // 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) {
+            result = (*it)->getSize(&size);
+            if (result.error_code() != ErrorCode::NO_ERROR) {
+                return result;
+            }
+            m_bytes_to_compress += size;
+            ++m_files_to_compress;
+        }
+
+        LoggerD("[%d] : [%s] --zip--> [%s] | size: %s", i, (*it)->getPath()->getFullPath().c_str(),
+                getNameInZipArchiveFor(*it, m_callback->getFileEntry()->getStriped()).c_str(),
+                bytesToReadableString(size).c_str());
+    }
+
+    LoggerD("m_files_to_compress: %d", m_files_to_compress);
+    LoggerD("m_bytes_to_compress: %llu (%s)", m_bytes_to_compress,
+            bytesToReadableString(m_bytes_to_compress).c_str());
+
+    if(m_callback->isCanceled()) {
+        LoggerD("Operation cancelled");
+        return PlatformResult(ErrorCode::OPERATION_CANCELED_ERR);
+    }
+
+    // Begin files compression
+    //
+    for(auto it = all_sub_nodes.begin(); it != all_sub_nodes.end(); ++it, ++i) {
+        result = addToZipArchive(*it);
+        if (result.error_code() != ErrorCode::NO_ERROR) {
+            return result;
+        }
+    }
+
+    m_callback->callSuccessCallbackOnMainThread();
+    m_callback = NULL;
+
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+void ZipAddRequest::addNodeAndSubdirsToList(filesystem::NodePtr src_node,
+        filesystem::NodeList& out_list_of_child_nodes)
+{
+    LoggerD("Enter");
+    out_list_of_child_nodes.push_back(src_node);
+
+    if(filesystem::NT_DIRECTORY == src_node->getType()) {
+        LoggerW("STUB Not generating recursive list of files in directory");
+        //auto child_nodes = src_node->getChildNodes();
+        //for(auto it = child_nodes.begin(); it != child_nodes.end(); ++it) {
+        //    addNodeAndSubdirsToList(*it, out_list_of_child_nodes);
+        //}
+    }
+}
+
+PlatformResult ZipAddRequest::addEmptyDirectoryToZipArchive(std::string name_in_zip)
+{
+    LoggerD("Entered name_in_zip:%s", name_in_zip.c_str());
+
+    if(name_in_zip.length() == 0) {
+        LoggerW("Trying to create directory with empty name - \"\"");
+        return PlatformResult(ErrorCode::NO_ERROR);
+    }
+
+    const char last_char = name_in_zip[name_in_zip.length()-1];
+    if(last_char != '/' && last_char != '\\') {
+        name_in_zip += "/";
+        LoggerD("Corrected name_in_zip: [%s]", name_in_zip.c_str());
+    }
+
+    if(m_new_file_in_zip_opened) {
+        LoggerE("WARNING: Previous new file in zip archive is opened!");
+        int err = zipCloseFileInZip(m_owner.m_zip);
+        if (ZIP_OK != err) {
+            LoggerE("%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) {
+            LoggerE("Entry: [%s] exists and is NOT directory!", conflicting_name.c_str());
+
+            LoggerE("Throwing InvalidValuesException - File with the same name exists");
+            return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "File with the same name exists");
+        }
+
+        LoggerD("Directory: [%s] already exists -> nothing to do", name_in_zip.c_str());
+        return PlatformResult(ErrorCode::NO_ERROR);
+    }
+
+    if(m_callback->isCanceled()) {
+        LoggerD("Operation cancelled");
+        return PlatformResult(ErrorCode::OPERATION_CANCELED_ERR);
+    }
+
+    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 = {0};
+    tzset();
+    if (nullptr != localtime_r(&current_time, &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) {
+        LoggerE("ret: %d", err);
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, getArchiveLogMessage(err, "zipOpenNewFileInZip3()"));
+    }
+
+    m_new_file_in_zip_opened = true;
+
+    err = zipCloseFileInZip(m_owner.m_zip);
+    if (ZIP_OK != err) {
+        LoggerE("%s",getArchiveLogMessage(err, "zipCloseFileInZip()").c_str());
+    }
+
+    LoggerD("Added new empty directory to archive: [%s]", name_in_zip.c_str());
+    m_new_file_in_zip_opened = false;
+
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult ZipAddRequest::addToZipArchive(filesystem::NodePtr src_file_node)
+{
+    LoggerD("Enter");
+    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();
+
+    LoggerD("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) {
+        LoggerE("WARNING: Previous new file in zip archive is opened!");
+        int err = zipCloseFileInZip(m_owner.m_zip);
+        if (ZIP_OK != err) {
+            LoggerE("zipCloseFileInZip failed with error: %d", err);
+        }
+    }
+
+    if(m_callback->isCanceled()) {
+        LoggerD("Operation cancelled");
+        return PlatformResult(ErrorCode::OPERATION_CANCELED_ERR);
+    }
+
+    std::string conflicting_name;
+    if(m_callback->getArchiveFile()->isEntryWithNameInArchive(name_in_zip,
+            NULL, &conflicting_name)) {
+
+        LoggerE("Cannot add new entry with name name: [%s] "
+                "it would conflict with existing entry: [%s]",
+                name_in_zip.c_str(), conflicting_name.c_str());
+
+        LoggerE("Throwing InvalidModificationException - Archive entry name conflicts");
+        return PlatformResult(ErrorCode::INVALID_MODIFICATION_ERR, "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) {
+        LoggerE("Error opening new file: [%s] in zipfile", name_in_zip.c_str());
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Could not add new file to zip archive");
+    }
+
+    m_new_file_in_zip_opened = true;
+
+    if(m_input_file) {
+        LoggerW("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);
+
+    std::time_t time;
+    PlatformResult result = src_file_node->getModified(&time);
+    if (result.error_code() != ErrorCode::NO_ERROR) {
+        return result;
+    }
+    cur_afentry->setModified(time);
+
+    auto entry = m_callback->getFileEntry();
+    cur_afentry->setDestination(entry->getDestination());
+    cur_afentry->setStriped(entry->getStriped());
+    cur_afentry->setSize(0);
+
+    LoggerD("m_bytes_compressed:%llu / m_bytes_to_compress: %llu",
+            m_bytes_compressed, m_bytes_to_compress);
+
+    LoggerD("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) {
+            LoggerE("Error opening source file:%s", src_file_path.c_str());
+            return PlatformResult(ErrorCode::UNKNOWN_ERR, "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);
+        LoggerD("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) {
+                LoggerE("Couldn't allocate m_buffer");
+                return PlatformResult(ErrorCode::UNKNOWN_ERR, "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) {
+                LoggerE("Error reading source file: %s\n", src_file_path.c_str());
+                return PlatformResult(ErrorCode::UNKNOWN_ERR, "New file addition failed");
+            }
+
+            LoggerD("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) {
+                    LoggerE("Error during adding file: %s into zip archive",
+                            src_file_path.c_str());
+                    return PlatformResult(ErrorCode::UNKNOWN_ERR, "New file addition failed");
+                }
+            }
+
+            if(total_bytes_read == in_file_size) {
+                LoggerD("Finished reading and compressing source file: [%s]",
+                        src_file_path.c_str());
+                ++m_files_compressed;
+            }
+
+            LoggerD("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);
+            }
+
+            LoggerD("Wrote: %s total progress: %.2f%% %d/%d files",
+                    bytesToReadableString(size_read).c_str(), progress * 100.0,
+                    m_files_compressed, m_files_to_compress);
+
+            LoggerD("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) {
+            LoggerE("in_file_size(%d) != total_bytes_read(%d)", in_file_size,
+                    total_bytes_read);
+            return PlatformResult(ErrorCode::UNKNOWN_ERR, "Could not add file to archive");
+        }
+
+        fclose(m_input_file);
+        m_input_file = NULL;
+    }
+
+    err = zipCloseFileInZip(m_owner.m_zip);
+    if (ZIP_OK != err) {
+        LoggerE("Error in closing added file:%s in zipfile", src_file_path.c_str());
+    }
+
+    m_new_file_in_zip_opened = false;
+
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+std::string removeDirCharsFromFront(const std::string& path)
+{
+    LoggerD("Enter");
+    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)
+{
+    LoggerD("Enter");
+    //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)
+{
+    LoggerD("Enter");
+    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) {
+        LoggerW("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());
+    LoggerD("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;
+        LoggerD("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 += "/";
+            LoggerD("Directory: [%s] added \\", name.c_str());
+        }
+    }
+
+    return name;
+}
+
+} //namespace archive
+} //namespace extension
diff --git a/webWidgetTCT_device/src/archive/zip_add_request.h b/webWidgetTCT_device/src/archive/zip_add_request.h
new file mode 100755 (executable)
index 0000000..49459d8
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2015 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_ARCHIVE_ZIP_ADD_REQUEST_H__
+#define __TIZEN_ARCHIVE_ZIP_ADD_REQUEST_H__
+
+#include <stdio.h>
+#include <string>
+
+#include "common/platform_result.h"
+#include "filesystem_file.h"
+#include "archive_callback_data.h"
+#include "zip.h"
+
+namespace extension {
+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 PlatformResult execute(Zip& owner, AddProgressCallback*& callback);
+    ~ZipAddRequest();
+
+private:
+    ZipAddRequest(Zip& owner, AddProgressCallback*& callback);
+    ZipAddRequest(ZipAddRequest const&) = delete;
+    ZipAddRequest& operator=(ZipAddRequest const&) = delete;
+
+    PlatformResult run();
+
+    void addNodeAndSubdirsToList(filesystem::NodePtr src_node,
+            filesystem::NodeList& out_list_of_child_nodes);
+
+    PlatformResult addEmptyDirectoryToZipArchive(std::string name_in_zip);
+    PlatformResult 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 extension
+
+#endif // __TIZEN_ARCHIVE_ZIP_ADD_REQUEST_H__
diff --git a/webWidgetTCT_device/src/badge/badge.gyp b/webWidgetTCT_device/src/badge/badge.gyp
new file mode 100755 (executable)
index 0000000..7fc986e
--- /dev/null
@@ -0,0 +1,34 @@
+{
+  'includes':[
+    '../common/common.gypi',
+  ],
+  'targets': [
+    {
+      'target_name': 'tizen_badge',
+      'type': 'loadable_module',
+      'dependencies': [
+        '../common/common.gyp:tizen_common',
+      ],
+      'sources': [
+        'badge_api.js',
+        'badge_extension.cc',
+        'badge_extension.h',
+        'badge_instance.cc',
+        'badge_instance.h',
+        'badge_manager.cc',
+        'badge_manager.h',
+      ],
+      'conditions': [
+        ['tizen == 1', {
+          'variables': {
+            'packages': [
+              'aul',
+              'badge',
+              'vconf',
+            ]
+          },
+        }],
+      ],
+    },
+  ],
+}
diff --git a/webWidgetTCT_device/src/badge/badge_api.js b/webWidgetTCT_device/src/badge/badge_api.js
new file mode 100755 (executable)
index 0000000..4a2ab7c
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+//maximum value of badge as found in old plugin implementation
+var MAX_BADGE_COUNT = 999;
+
+var validator_ = xwalk.utils.validator;
+var converter_ = xwalk.utils.converter;
+var types_ = validator_.Types;
+var Type = xwalk.utils.type;
+var native_ = new xwalk.utils.NativeManager(extension);
+
+var _badgeListenerRegistered = false;
+var _badgeCallbackMap = {};
+var _currentWatchId = 1;
+var _getNextWatchId = function() {
+  return _currentWatchId++;
+};
+
+var _badgeChangeListener = function(result) {
+  if (result.appId && result.count && _badgeCallbackMap.hasOwnProperty(result.appId)) {
+    for (var functionToCall in _badgeCallbackMap[result.appId]) {
+      native_.callIfPossible(_badgeCallbackMap[result.appId][functionToCall],
+                             result.appId, converter_.toLong(result.count));
+    }
+  }
+};
+
+
+
+/**
+ * This class provides functions to request and release badge resource.
+ * @constructor
+ */
+function BadgeManager() {
+  Object.defineProperties(this, {
+    'maxBadgeCount': { value: MAX_BADGE_COUNT, emumerable: true, writable: false}
+  });
+}
+
+
+/**
+ * Sets the badge count for the designated application.
+ */
+BadgeManager.prototype.setBadgeCount = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.NOTIFICATION);
+
+  var args = validator_.validateArgs(arguments, [
+    {name: 'appId', type: types_.STRING},
+    {name: 'count', type: types_.LONG}
+  ]);
+
+  if (args.count < 0) {
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+                              'Count parameter is negative!');
+  }
+
+  var ret = native_.callSync('BadgeManager_setBadgeCount', {
+    appId: args.appId,
+    count: args.count
+  });
+
+  if (native_.isFailure(ret)) {
+    throw native_.getErrorObject(ret);
+  }
+};
+
+
+/**
+ * Gets the badge count for the designated application.
+ * @return {number} long Count of the badge
+ */
+BadgeManager.prototype.getBadgeCount = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.NOTIFICATION);
+
+  var args = validator_.validateArgs(arguments, [
+    {name: 'appId', type: types_.STRING}
+  ]);
+
+  var ret = native_.callSync('BadgeManager_getBadgeCount', {
+    appId: args.appId
+  });
+
+  if (native_.isFailure(ret)) {
+    throw native_.getErrorObject(ret);
+  }
+
+  return parseInt(native_.getResultObject(ret));
+};
+
+
+/**
+ * Gets the badge count for the designated application.
+ */
+BadgeManager.prototype.addChangeListener = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.NOTIFICATION);
+
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'appIdList',
+      type: types_.ARRAY,
+      values: types_.STRING,
+      optional: false,
+      nullable: false
+    },
+    {
+      name: 'successCallback',
+      type: types_.FUNCTION,
+      optional: false,
+      nullable: false
+    }
+  ]);
+
+  var result = native_.callSync('BadgeManager_addChangeListener', args);
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+  if (!_badgeListenerRegistered) {
+    _badgeListenerRegistered = true;
+    native_.addListener('BadgeChangeListener', _badgeChangeListener);
+  }
+  for (var i = 0; i < args.appIdList.length; i++) {
+    if (!_badgeCallbackMap.hasOwnProperty(args.appIdList[i])) {
+      _badgeCallbackMap[args.appIdList[i]] = [];
+    }
+    _badgeCallbackMap[args.appIdList[i]].push(args.successCallback);
+  }
+  return;
+};
+
+
+/**
+ * Gets the badge count for the designated application.
+ */
+BadgeManager.prototype.removeChangeListener = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.NOTIFICATION);
+
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'appIdList',
+      type: types_.ARRAY,
+      values: types_.STRING,
+      optional: false,
+      nullable: false
+    }
+  ]);
+
+  for (var i = 0; i < args.appIdList.length; i++) {
+    if (_badgeCallbackMap.hasOwnProperty(args.appIdList[i]))
+      delete _badgeCallbackMap[args.appIdList[i]];
+  }
+
+  if (Type.isEmptyObject(_badgeCallbackMap)) {
+    native_.removeListener('BadgeChangeListener', _badgeChangeListener);
+    _badgeListenerRegistered = false;
+  }
+
+  var result = native_.callSync('BadgeManager_removeChangeListener', args);
+  if (native_.isFailure(result))
+    throw native_.getErrorObject(result);
+};
+
+exports = new BadgeManager();
diff --git a/webWidgetTCT_device/src/badge/badge_extension.cc b/webWidgetTCT_device/src/badge/badge_extension.cc
new file mode 100755 (executable)
index 0000000..07ac87f
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2015 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 "badge/badge_extension.h"
+#include "badge/badge_instance.h"
+
+// This will be generated from badge_api.js
+extern const char kSource_badge_api[];
+
+common::Extension* CreateExtension() { return new BadgeExtension; }
+
+BadgeExtension::BadgeExtension() {
+  SetExtensionName("tizen.badge");
+  SetJavaScriptAPI(kSource_badge_api);
+}
+
+BadgeExtension::~BadgeExtension() {}
+
+common::Instance* BadgeExtension::CreateInstance() {
+  return new extension::badge::BadgeInstance();
+}
diff --git a/webWidgetTCT_device/src/badge/badge_extension.h b/webWidgetTCT_device/src/badge/badge_extension.h
new file mode 100755 (executable)
index 0000000..c17c093
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2015 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 BADGE_BADGE_EXTENSION_H_
+#define BADGE_BADGE_EXTENSION_H_
+
+#include "common/extension.h"
+
+class BadgeExtension : public common::Extension {
+ public:
+  BadgeExtension();
+  virtual ~BadgeExtension();
+
+ private:
+  virtual common::Instance* CreateInstance();
+};
+
+#endif  // BADGE_BADGE_EXTENSION_H_
diff --git a/webWidgetTCT_device/src/badge/badge_instance.cc b/webWidgetTCT_device/src/badge/badge_instance.cc
new file mode 100755 (executable)
index 0000000..9984e21
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2015 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 "badge/badge_instance.h"
+
+#include "common/converter.h"
+
+namespace extension {
+namespace badge {
+
+using namespace common;
+using namespace extension::badge;
+
+BadgeInstance::BadgeInstance() : manager_(*this) {
+  LoggerD("Enter");
+  using std::placeholders::_1;
+  using std::placeholders::_2;
+
+#define REGISTER_SYNC(c, x) \
+  RegisterSyncHandler(c, std::bind(&BadgeInstance::x, this, _1, _2));
+  REGISTER_SYNC("BadgeManager_setBadgeCount", BadgeManagerSetBadgeCount);
+  REGISTER_SYNC("BadgeManager_addChangeListener",
+                BadgeManagerAddChangeListener);
+  REGISTER_SYNC("BadgeManager_removeChangeListener",
+                BadgeManagerRemoveChangeListener);
+  REGISTER_SYNC("BadgeManager_getBadgeCount", BadgeManagerGetBadgeCount);
+#undef REGISTER_SYNC
+}
+
+BadgeInstance::~BadgeInstance() {
+  LoggerD("Enter");
+}
+
+void BadgeInstance::BadgeManagerSetBadgeCount(const JsonValue& args,
+                                              JsonObject& out) {
+  LoggerD("Enter");
+  std::string app_id =
+      common::FromJson<std::string>(args.get<JsonObject>(), "appId");
+  const double count = args.get("count").get<double>();
+
+  PlatformResult status = manager_.SetBadgeCount(
+      app_id, static_cast<unsigned int>(count));
+  if (status.IsSuccess())
+    ReportSuccess(out);
+  else
+    ReportError(status, &out);
+}
+
+void BadgeInstance::BadgeManagerGetBadgeCount(const JsonValue& args,
+                                              JsonObject& out) {
+  LoggerD("Enter");
+  std::string app_id =
+      common::FromJson<std::string>(args.get<JsonObject>(), "appId");
+
+  unsigned int count = 0;
+  PlatformResult status =
+      manager_.GetBadgeCount(app_id, &count);
+  if (status.IsSuccess())
+    ReportSuccess(JsonValue(std::to_string(count)), out);
+  else
+    ReportError(status, &out);
+}
+
+void BadgeInstance::BadgeManagerAddChangeListener(const JsonValue& args,
+                                                  JsonObject& out) {
+  LoggerD("Enter");
+  PlatformResult status =
+      manager_.AddChangeListener(args.get<JsonObject>());
+
+  if (status.IsSuccess())
+    ReportSuccess(out);
+  else
+    ReportError(status, &out);
+}
+
+void BadgeInstance::BadgeManagerRemoveChangeListener(const JsonValue& args,
+                                                     JsonObject& out) {
+  LoggerD("Enter");
+  PlatformResult status =
+      manager_.RemoveChangeListener(args.get<JsonObject>());
+
+  if (status.IsSuccess())
+    ReportSuccess(out);
+  else
+    ReportError(status, &out);
+}
+
+}  // namespace badge
+}  // namespace extension
diff --git a/webWidgetTCT_device/src/badge/badge_instance.h b/webWidgetTCT_device/src/badge/badge_instance.h
new file mode 100755 (executable)
index 0000000..77fc8d1
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2015 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 BADGE_BADGE_INSTANCE_H_
+#define BADGE_BADGE_INSTANCE_H_
+
+#include "badge/badge_manager.h"
+
+#include "common/extension.h"
+
+namespace extension {
+namespace badge {
+
+class BadgeInstance : public common::ParsedInstance {
+ public:
+  BadgeInstance();
+  virtual ~BadgeInstance();
+
+ private:
+  /**
+   * Signature: @code void setBadgeCount(appId, count);
+   * @endcode
+   * JSON: @code data: {method: 'Badge_setBadgeCount',
+   *                    args: {ApplicationId: appId, long: count}} @endcode
+   * Invocation: @code native.callSync(request) @endcode
+   * Return:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success'}
+   * @endcode
+   */
+  void BadgeManagerSetBadgeCount(const JsonValue& args, JsonObject& out);
+
+  /**
+   * Signature: @code void getBadgeCount(appId);
+   * @endcode
+   * JSON: @code data: {method: 'Badge_getBadgeCount',
+   *                    args: {ApplicationId: appId}} @endcode
+   * Invocation: @code native.callSync(request) @endcode
+   * Return:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success', result: {count}}
+   * @endcode
+   */
+  void BadgeManagerGetBadgeCount(const JsonValue& args, JsonObject& out);
+  void BadgeManagerAddChangeListener(const JsonValue& args, JsonObject& out);
+  void BadgeManagerRemoveChangeListener(const JsonValue& args, JsonObject& out);
+
+  BadgeManager manager_;
+};
+}  // namespace badge
+}  // namespace extension
+
+#endif  // BADGE_BADGE_INSTANCE_H_
diff --git a/webWidgetTCT_device/src/badge/badge_manager.cc b/webWidgetTCT_device/src/badge/badge_manager.cc
new file mode 100755 (executable)
index 0000000..bcebc36
--- /dev/null
@@ -0,0 +1,248 @@
+/*
+ * Copyright (c) 2015 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 "badge/badge_manager.h"
+
+#include <aul.h>
+#include <badge.h>
+#include <badge_internal.h>
+#include <fcntl.h>
+#include <pkgmgr-info.h>
+#include <unistd.h>
+
+#include "badge/badge_instance.h"
+#include "common/assert.h"
+#include "common/logger.h"
+#include "common/converter.h"
+#include "common/platform_exception.h"
+
+using namespace common;
+
+namespace extension {
+namespace badge {
+
+BadgeManager::BadgeManager(BadgeInstance& instance)
+    : instance_(instance),
+      is_cb_registered_(false) {
+}
+
+BadgeManager::~BadgeManager() {
+  LoggerD("Enter");
+  if (is_cb_registered_) {
+    if (!watched_applications_.empty()) watched_applications_.clear();
+    int ret = badge_unregister_changed_cb(badge_changed_cb);
+    if (ret != BADGE_ERROR_NONE) {
+      LoggerE("Unknown error : %d", ret);
+    }
+    is_cb_registered_ = false;
+  }
+}
+
+PlatformResult BadgeManager::SetBadgeCount(const std::string& app_id,
+                                           unsigned int count) {
+  LoggerD("Enter");
+  SLoggerD("app_id : %s ", app_id.c_str());
+
+  if (!IsAppInstalled(app_id)) {
+    LoggerE("Application is not installed");
+    return PlatformResult(ErrorCode::INVALID_VALUES_ERR,
+                          "InvalidValues error : app_id");
+  }
+
+  bool badge_exist = false;
+  const char *app_id_str = app_id.c_str();
+  int ret = badge_is_existing(app_id_str, &badge_exist);
+
+  if (ret != BADGE_ERROR_NONE) {
+    LoggerE("Unknown error : %d", ret);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error");
+  }
+
+  LoggerD("badge exist : %d", badge_exist);
+
+  if (!badge_exist) {
+    ret = badge_create(app_id_str, app_id_str);
+    LoggerD("badge_create() ret : %d", ret);
+
+    if (ret == BADGE_ERROR_PERMISSION_DENIED) {
+      LoggerE("Security error");
+      return PlatformResult(ErrorCode::SECURITY_ERR, "Security error");
+#ifdef PROFILE_WEARABLE
+    } else if (ret == BADGE_ERROR_INVALID_DATA) {
+#else
+    } else if (ret == BADGE_ERROR_INVALID_PARAMETER) {
+#endif
+      LoggerE("Invalid values error");
+      return PlatformResult(ErrorCode::INVALID_VALUES_ERR,
+                            "Invalid values error");
+    } else if (ret != BADGE_ERROR_NONE && ret != BADGE_ERROR_ALREADY_EXIST) {
+      LoggerE("Unknown error");
+      return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Unknown error");
+    }
+  }
+
+  ret = badge_set_count(app_id_str, count);
+  LoggerE("badge_set_count() ret : %d count : %d ", ret, count);
+
+  if (ret == BADGE_ERROR_PERMISSION_DENIED) {
+    LoggerE("Security error");
+    return PlatformResult(ErrorCode::SECURITY_ERR, "Security error");
+  } else if (ret == BADGE_ERROR_NOT_EXIST) {
+    LoggerE("Application is not installed");
+    return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Application is not installed");
+#ifdef PROFILE_WEARABLE
+  } else if (ret == BADGE_ERROR_INVALID_DATA) {
+#else
+  } else if (ret == BADGE_ERROR_INVALID_PARAMETER) {
+#endif
+    LoggerE("Invalid values error");
+    return PlatformResult(ErrorCode::INVALID_VALUES_ERR,
+                          "Invalid values error");
+  } else if (ret != BADGE_ERROR_NONE) {
+    LoggerE("Unknown error : %d", ret);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult BadgeManager::GetBadgeCount(const std::string& app_id,
+                                           unsigned int *count) {
+  LoggerD("Enter");
+  SLoggerD("app_id : %s ", app_id.c_str());
+
+  Assert(count);
+
+  if (!IsAppInstalled(app_id)) {
+    LoggerE("Application is not installed");
+    return PlatformResult(ErrorCode::INVALID_VALUES_ERR,
+                          "InvalidValues error : app_id");
+  }
+
+  bool badge_exist = false;
+  int ret = badge_is_existing(app_id.c_str(), &badge_exist);
+
+  if (ret != BADGE_ERROR_NONE) {
+    LoggerE("Unknown error : %d", ret);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Platform error while checking badge.");
+  }
+
+  LoggerD("badge exist : %d", badge_exist);
+
+  if (!badge_exist) {
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "badge not exist. app_id: " + app_id);
+  }
+
+  *count = 0;
+  ret = badge_get_count(app_id.c_str(), count);
+
+  LoggerD("badge_get_count() ret : %d count : %d", ret, *count);
+
+  switch (ret) {
+    case BADGE_ERROR_NONE:
+      return PlatformResult(ErrorCode::NO_ERROR);
+    case BADGE_ERROR_PERMISSION_DENIED:
+      LoggerE("Security error");
+      return PlatformResult(ErrorCode::SECURITY_ERR, "Security error.");
+    case BADGE_ERROR_NOT_EXIST:
+      LoggerE("Application is not installed");
+      return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Application is not installed");
+#ifdef PROFILE_WEARABLE
+    case BADGE_ERROR_INVALID_DATA:
+#else
+    case BADGE_ERROR_INVALID_PARAMETER:
+#endif
+      LoggerE("Invalid values error");
+      return PlatformResult(ErrorCode::INVALID_VALUES_ERR,
+                            "InvalidValues error : app_id");
+    default:
+      LoggerE("Unknown error : %d", ret);
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error");
+  }
+}
+
+PlatformResult BadgeManager::AddChangeListener(const JsonObject &obj) {
+  LoggerD("Enter");
+  auto &items = FromJson<picojson::array>(obj, "appIdList");
+  for (auto item : items) {
+    watched_applications_.insert(common::JsonCast<std::string>(item));
+  }
+  int ret = BADGE_ERROR_SERVICE_NOT_READY;
+  if (!is_cb_registered_) {
+    ret = badge_register_changed_cb(badge_changed_cb, this);
+    if (ret != BADGE_ERROR_NONE) {
+      LoggerE("Unknown error %d:", ret);
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "Platform error while adding listener.");
+    }
+    is_cb_registered_ = true;
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult BadgeManager::RemoveChangeListener(const JsonObject &obj) {
+  LoggerD("Enter");
+  auto &items = FromJson<picojson::array>(obj, "appIdList");
+  for (auto item : items) {
+    watched_applications_.erase(common::JsonCast<std::string>(item));
+  }
+  if (watched_applications_.empty() && is_cb_registered_) {
+    int ret = badge_unregister_changed_cb(badge_changed_cb);
+    if (ret != BADGE_ERROR_NONE) {
+      LoggerE("Unknown error : %d", ret);
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "Platform error while removing listener.");
+    }
+    is_cb_registered_ = false;
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+void BadgeManager::badge_changed_cb(unsigned int action, const char *pkgname,
+                                    unsigned int count, void *user_data) {
+  LoggerD("Enter");
+  BadgeManager* that = static_cast<BadgeManager*>(user_data);
+  if (action != BADGE_ACTION_SERVICE_READY &&
+      that->watched_applications_.find(pkgname) != that->watched_applications_.end()) {
+    picojson::value response = picojson::value(picojson::object());
+    picojson::object &response_obj = response.get<picojson::object>();
+    response_obj.insert(
+        std::make_pair("listenerId", picojson::value(std::string("BadgeChangeListener"))));
+    response_obj.insert(std::make_pair("appId", picojson::value(pkgname)));
+    response_obj.insert(std::make_pair("count", picojson::value(std::to_string(count))));
+    Instance::PostMessage(&that->instance_, response.serialize().c_str());
+  }
+}
+
+bool BadgeManager::IsAppInstalled(const std::string &app_id) {
+  LoggerD("Enter");
+
+  if (app_id.empty()) {
+    return false;
+  }
+
+  pkgmgrinfo_appinfo_h pkgmgrinfo_appinfo = nullptr;
+  int ret = pkgmgrinfo_appinfo_get_appinfo(app_id.c_str(), &pkgmgrinfo_appinfo);
+
+  return (ret == PMINFO_R_OK);
+}
+
+}  // namespace badge
+}  // namespace extension
diff --git a/webWidgetTCT_device/src/badge/badge_manager.h b/webWidgetTCT_device/src/badge/badge_manager.h
new file mode 100755 (executable)
index 0000000..48e64b6
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2015 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 BADGE_BADGE_MANAGER_H_
+#define BADGE_BADGE_MANAGER_H_
+
+#include <string>
+#include <set>
+
+#include "common/logger.h"
+#include "common/picojson.h"
+#include "common/platform_result.h"
+
+namespace extension {
+namespace badge {
+
+typedef picojson::value JsonValue;
+typedef picojson::object JsonObject;
+typedef picojson::array JsonArray;
+typedef std::string JsonString;
+
+class BadgeInstance;
+
+class BadgeManager {
+ public:
+  explicit BadgeManager(BadgeInstance& instance);
+  ~BadgeManager();
+
+  common::PlatformResult SetBadgeCount(const std::string& app_id,
+                                       unsigned int count);
+  common::PlatformResult GetBadgeCount(const std::string& app_id,
+                                       unsigned int* count);
+  common::PlatformResult AddChangeListener(const JsonObject& obj);
+  common::PlatformResult RemoveChangeListener(const JsonObject& obj);
+  static void badge_changed_cb(unsigned int, const char*, unsigned int, void*);
+
+ private:
+  bool IsAppInstalled(const std::string& app_id);
+
+  BadgeInstance& instance_;
+
+  bool is_cb_registered_;
+  std::set<std::string> watched_applications_;
+};
+
+}  // namespace badge
+}  // namespace extension
+
+#endif  // BADGE_BADGE_MANAGER_H_
diff --git a/webWidgetTCT_device/src/bluetooth/bluetooth.gyp b/webWidgetTCT_device/src/bluetooth/bluetooth.gyp
new file mode 100755 (executable)
index 0000000..bc91dc4
--- /dev/null
@@ -0,0 +1,62 @@
+{
+  'includes':[
+    '../common/common.gypi',
+  ],
+  'targets': [
+    {
+      'target_name': 'tizen_bluetooth',
+      'type': 'loadable_module',
+      'dependencies': [
+        '../common/common.gyp:tizen_common',
+      ],
+      'sources': [
+        'bluetooth_api.js',
+        'bluetooth_adapter.cc',
+        'bluetooth_adapter.h',
+        'bluetooth_class.cc',
+        'bluetooth_class.h',
+        'bluetooth_device.cc',
+        'bluetooth_device.h',
+        'bluetooth_extension.cc',
+        'bluetooth_extension.h',
+        'bluetooth_health_application.cc',
+        'bluetooth_health_application.h',
+        'bluetooth_health_channel.cc',
+        'bluetooth_health_channel.h',
+        'bluetooth_health_profile_handler.cc',
+        'bluetooth_health_profile_handler.h',
+        'bluetooth_instance.cc',
+        'bluetooth_instance.h',
+        'bluetooth_le_adapter.cc',
+        'bluetooth_le_adapter.h',
+        'bluetooth_service_handler.cc',
+        'bluetooth_service_handler.h',
+        'bluetooth_gatt_service.cc',
+        'bluetooth_gatt_service.h',
+        'bluetooth_socket.cc',
+        'bluetooth_socket.h',
+        'bluetooth_util.cc',
+        'bluetooth_util.h',
+        'bluetooth_le_device.cc',
+        'bluetooth_le_device.h',
+      ],
+      'includes': [
+        '../common/pkg-config.gypi',
+      ],
+      'conditions': [
+        ['tizen == 1', {
+         'variables': {
+            'packages': [
+              'capi-network-bluetooth',
+              'capi-system-info',
+              'libpcrecpp',
+            ]
+          },
+        }],
+        ['tizen_feature_app_control_settings_support == 1', {
+          'defines': ['APP_CONTROL_SETTINGS_SUPPORT'],
+        }],
+      ],
+    },
+  ],
+}
diff --git a/webWidgetTCT_device/src/bluetooth/bluetooth_adapter.cc b/webWidgetTCT_device/src/bluetooth/bluetooth_adapter.cc
new file mode 100755 (executable)
index 0000000..de2679f
--- /dev/null
@@ -0,0 +1,1660 @@
+/*
+ * Copyright (c) 2015 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 "bluetooth_adapter.h"
+
+#include <algorithm>
+#include <memory>
+
+#include <pcrecpp.h>
+
+#ifdef APP_CONTROL_SETTINGS_SUPPORT
+#include <appfw/app_control.h>
+#endif
+
+#include <system_info.h>
+#include <bluetooth.h>
+#include "bluetooth_internal.h"
+
+#include "common/converter.h"
+#include "common/logger.h"
+#include "common/platform_result.h"
+#include "common/extension.h"
+#include "common/task-queue.h"
+
+#include "bluetooth/bluetooth_class.h"
+#include "bluetooth/bluetooth_device.h"
+#include "bluetooth/bluetooth_instance.h"
+#include "bluetooth/bluetooth_socket.h"
+#include "bluetooth/bluetooth_util.h"
+
+namespace extension {
+namespace bluetooth {
+
+using namespace common;
+using namespace common::tools;
+
+namespace {
+const std::string kAction = "action";
+const std::string kData = "data";
+const std::string kName = "name";
+//adapter
+const std::string kAdapterPowered = "powered";
+const std::string kAdapterVisible = "visible";
+//AdapterChangeCallback
+const std::string kOnStateChanged = "onstatechanged";
+const std::string kOnNameChanged = "onnamechanged";
+const std::string kOnVisibilityChanged = "onvisibilitychanged";
+const std::string kAdapterChangeCallbackEvent = "BluetoothAdapterChangeCallback";
+// BluetoothProfileHandler
+const std::string kBluetoothProfileHealth = "HEALTH";
+const std::string kFeatureBluetoothHealth = "tizen.org/feature/network.bluetooth.health";
+//DiscoverDevicesCallback
+const std::string kOnDiscoverStarted = "onstarted";
+const std::string kOnDiscoverFound = "ondevicefound";
+const std::string kOnDiscoverDisappeared = "ondevicedisappeared";
+const std::string kOnDiscoverFinished = "onfinished";
+const std::string kAdapterDiscoverSuccessEvent = "BluetoothDiscoverDevicesSuccessCallback";
+const std::string kAdapterDiscoverErrorEvent = "BluetoothDiscoverDevicesErrorCallback";
+//device
+const std::string kDeviceAddress = "address";
+const unsigned short kTimeout = 180;
+}
+
+static bool IsValidAddress(const std::string& address) {
+  static pcrecpp::RE re("(([0-9a-zA-Z]+):)+([0-9a-zA-Z]+)");
+  static  std::string compare_address = "00:12:47:08:9A:A6";
+
+  if (!re.FullMatch(address)) {
+    LoggerE("Invalid address");
+    return false;
+  }
+  if (address.size() != compare_address.size()) {
+    LoggerE("Invalid size");
+    return false;
+  }
+  return true;
+}
+
+static bool IsValidUUID(const std::string& uuid) {
+  static pcrecpp::RE re("(([0-9a-zA-Z]+)-)+([0-9a-zA-Z]+)");
+  static std::string compare_uuid = "00001101-0000-1000-8000-00805F9B34FB";
+
+  if (!re.FullMatch(uuid)) {
+    LoggerE("Invalid UUID: %s", uuid.c_str());
+    return false;
+  }
+
+  if (uuid.size() != compare_uuid.size()) {
+    LoggerE("Invalid size: %s", uuid.c_str());
+    return false;
+  }
+
+  return true;
+}
+
+void BluetoothAdapter::StateChangedCB(int result, bt_adapter_state_e state, void *user_data) {
+  LoggerD("Entered");
+
+  BluetoothAdapter* adapter = static_cast<BluetoothAdapter*>(user_data);
+  if (!adapter) {
+    LoggerD("User data is NULL");
+    return;
+  }
+
+  const bool powered = BT_ADAPTER_ENABLED == state;
+  bool previous_powered = adapter->is_powered_;
+  adapter->is_powered_ = powered;
+
+  if (powered) {
+    //update visible state if bluetooth device has been turned on
+    adapter->is_visible_ = adapter->get_visible();
+  }
+
+  if (previous_powered != powered && BT_ERROR_NONE == result) {
+    picojson::value value = picojson::value(picojson::object());
+    picojson::object* data_obj = &value.get<picojson::object>();
+
+    data_obj->insert(std::make_pair(kAction, picojson::value(kOnStateChanged)));
+    data_obj->insert(std::make_pair(kAdapterPowered, picojson::value(powered)));
+
+    adapter->instance_.FireEvent(kAdapterChangeCallbackEvent, value);
+  }
+
+  if (adapter->user_request_list_[SET_POWERED]) {
+    if (adapter->requested_powered_ != powered) {
+      return;
+    }
+
+    PlatformResult ret = PlatformResult(ErrorCode::NO_ERROR);
+    switch(result) {
+      case BT_ERROR_NONE:
+      case BT_ERROR_ALREADY_DONE:
+      case BT_ERROR_NOT_ENABLED:
+        //do nothing
+        break;
+      case BT_ERROR_NOW_IN_PROGRESS:
+        ret = PlatformResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR, "Bluetooth device is busy");
+        break;
+      default:
+        ret = PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown exception");
+    }
+
+    adapter->instance_.AsyncResponse(adapter->user_request_callback_[SET_POWERED], ret);
+    adapter->user_request_list_[SET_POWERED] = false;
+  }
+}
+
+void BluetoothAdapter::NameChangedCB(char *name, void *user_data) {
+  LoggerD("Entered");
+
+  BluetoothAdapter* adapter = static_cast<BluetoothAdapter*>(user_data);
+  if (!adapter) {
+    LoggerD("User data is NULL");
+    return;
+  }
+
+  picojson::value value = picojson::value(picojson::object());
+  picojson::object* data_obj = &value.get<picojson::object>();
+
+  data_obj->insert(std::make_pair(kAction, picojson::value(kOnNameChanged)));
+  data_obj->insert(std::make_pair(kName, picojson::value(name)));
+
+  adapter->instance_.FireEvent(kAdapterChangeCallbackEvent, value);
+
+  if (adapter->user_request_list_[SET_NAME] && name == adapter->requested_name_) {
+    std::shared_ptr<picojson::value> response =
+        std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+    adapter->instance_.AsyncResponse(adapter->user_request_callback_[SET_NAME], response);
+    adapter->user_request_list_[SET_NAME] = false;
+  }
+}
+
+void BluetoothAdapter::VisibilityChangedCB(int result, bt_adapter_visibility_mode_e mode, void *user_data) {
+  LoggerD("Entered");
+
+  BluetoothAdapter* adapter = static_cast<BluetoothAdapter*>(user_data);
+  if (!adapter) {
+    LoggerD("User data is NULL");
+    return;
+  }
+
+  bool visible = BT_ADAPTER_VISIBILITY_MODE_NON_DISCOVERABLE != mode;
+  bool previous_visible = adapter->is_visible_;
+  adapter->is_visible_ = visible;
+
+  if (previous_visible != visible) {
+    picojson::value value = picojson::value(picojson::object());
+    picojson::object* data_obj = &value.get<picojson::object>();
+
+    data_obj->insert(std::make_pair(kAction, picojson::value(kOnVisibilityChanged)));
+    data_obj->insert(std::make_pair(kAdapterVisible, picojson::value(visible)));
+
+    adapter->instance_.FireEvent(kAdapterChangeCallbackEvent, value);
+  }
+
+  if (adapter->user_request_list_[SET_VISIBLE] && adapter->requested_visibility_ == mode) {
+    PlatformResult ret = PlatformResult(ErrorCode::NO_ERROR);
+
+    if (BT_ERROR_NONE != result) {
+      ret = PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown exception");
+    }
+
+    adapter->instance_.AsyncResponse(adapter->user_request_callback_[SET_VISIBLE], ret);
+    adapter->user_request_list_[SET_VISIBLE] = false;
+  }
+}
+
+static bool ForeachBondedDevicesCB(bt_device_info_s *device_info, void *user_data)
+{
+  LoggerD("Entered");
+  if (nullptr == user_data) {
+    LoggerD("user data is NULL.");
+    return false;
+  }
+
+  if (nullptr == device_info) {
+    LoggerD("Device info is not valid.");
+    return false;
+  }
+
+  picojson::array* array = static_cast<picojson::array*>(user_data);
+  for (auto iter = array->begin(); iter != array->end(); iter++) {
+    if (!strcmp(device_info->remote_address, ((*iter).get<picojson::object>())
+                .find(kDeviceAddress)->second.get<std::string>().c_str())) {
+      BluetoothDevice::ToJson(device_info, &iter->get<picojson::object>());
+      return true;
+    }
+  }
+
+  array->push_back(picojson::value(picojson::object()));
+
+  BluetoothDevice::ToJson(device_info, &array->back().get<picojson::object>());
+  return true;
+}
+
+void BluetoothAdapter::DiscoveryStateChangedCB(
+    int result,
+    bt_adapter_device_discovery_state_e discovery_state,
+    bt_adapter_device_discovery_info_s *discovery_info,
+    void *user_data)
+{
+  LoggerD("Entered");
+
+  BluetoothAdapter* adapter = static_cast<BluetoothAdapter*>(user_data);
+  if (!adapter) {
+    LoggerD("User data is NULL");
+    return;
+  }
+
+  picojson::value value = picojson::value(picojson::object());
+  picojson::object* data_obj = &value.get<picojson::object>();
+
+  switch(discovery_state) {
+    case BT_ADAPTER_DEVICE_DISCOVERY_STARTED: {
+      if (adapter->user_request_list_[DISCOVER_DEVICES]) {
+        if (BT_ERROR_NONE == result) {
+          //store addresses of previously found devices into disappeared_addresses
+          adapter->disappeared_addresses_ = adapter->discovered_addresses_;
+          adapter->discovered_addresses_.clear();
+          adapter->discovered_devices_.clear();
+
+          data_obj->insert(std::make_pair(kAction, picojson::value(kOnDiscoverStarted)));
+          adapter->instance_.FireEvent(kAdapterDiscoverSuccessEvent, value);
+        } else {
+          ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error"), data_obj);
+          adapter->instance_.FireEvent(kAdapterDiscoverErrorEvent, value);
+          adapter->user_request_list_[DISCOVER_DEVICES] = false;
+        }
+      }
+      break;
+    }
+    case BT_ADAPTER_DEVICE_DISCOVERY_FINISHED: {
+      if (BT_ERROR_NONE == result || BT_ERROR_CANCELLED == result) {
+        if (adapter->user_request_list_[DISCOVER_DEVICES]) {
+          data_obj->insert(std::make_pair(kAction, picojson::value(kOnDiscoverFinished)));
+
+          for (auto it : adapter->disappeared_addresses_) {
+            picojson::value disapeared_val = picojson::value(picojson::object());
+            picojson::object* disapeared_obj = &disapeared_val.get<picojson::object>();
+
+            disapeared_obj->insert(std::make_pair(kAction,
+                                                  picojson::value(kOnDiscoverDisappeared)));
+            disapeared_obj->insert(std::make_pair(kData, picojson::value(it)));
+
+            adapter->instance_.FireEvent(kAdapterDiscoverSuccessEvent, disapeared_val);
+          }
+
+          data_obj->insert(std::make_pair(kData, picojson::value(adapter->discovered_devices_)));
+
+          //TODO Consider if all events during scanning shouldn't be called asynchronously
+          adapter->user_request_list_[DISCOVER_DEVICES] = false;
+          adapter->instance_.FireEvent(kAdapterDiscoverSuccessEvent, value);
+        }
+
+        if (adapter->user_request_list_[STOP_DISCOVERY]) {
+          std::shared_ptr<picojson::value> response =
+              std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+
+          ReportSuccess(response->get<picojson::object>());
+          adapter->instance_.AsyncResponse(adapter->user_request_callback_[STOP_DISCOVERY], response);
+
+          adapter->user_request_list_[STOP_DISCOVERY] = false;
+        }
+      }
+      break;
+    }
+    case BT_ADAPTER_DEVICE_DISCOVERY_FOUND: {
+      if (adapter->user_request_list_[DISCOVER_DEVICES]) {
+        if (BT_ERROR_NONE == result &&
+            adapter->discovered_addresses_.insert(
+                discovery_info->remote_address).second) {
+          adapter->disappeared_addresses_.erase(discovery_info->remote_address);
+
+          data_obj->insert(std::make_pair(kAction, picojson::value(kOnDiscoverFound)));
+          picojson::value& data = data_obj->insert(std::make_pair(kData,
+                                                                  picojson::value(picojson::object()))).first->second;
+
+          BluetoothDevice::ToJson(discovery_info, &data.get<picojson::object>());
+          adapter->discovered_devices_.push_back(data);
+
+          adapter->instance_.FireEvent(kAdapterDiscoverSuccessEvent, value);
+        }
+      }
+      break;
+    }
+    default:
+      LoggerD("Unknown state");
+      break;
+  }
+}
+
+BluetoothAdapter::BluetoothAdapter(BluetoothInstance& instance) :
+    is_visible_(false),
+    is_powered_(false),
+    is_initialized_(false),
+    user_request_list_(),
+    user_request_callback_(),
+    requested_powered_(),
+    requested_visibility_(),
+    instance_(instance)
+{
+  LoggerD("Entered");
+  if (BT_ERROR_NONE == bt_initialize()) {
+    LoggerD("Bluetooth service is initialized.");
+    is_initialized_ = true;
+
+    int ret = BT_ERROR_NONE;
+    ret |= bt_adapter_set_device_discovery_state_changed_cb(DiscoveryStateChangedCB, this);
+    ret |= bt_adapter_set_state_changed_cb(StateChangedCB, this);
+    ret |= bt_adapter_set_name_changed_cb(NameChangedCB, this);
+    ret |= bt_adapter_set_visibility_mode_changed_cb(VisibilityChangedCB, this);
+
+    if (BT_ERROR_NONE != ret) {
+      LoggerE("Setting listeners function failed.");
+    }
+  } else {
+    LoggerE("Bluetooth service initialization failed.");
+  }
+
+  bt_adapter_state_e state;
+  if (BT_ERROR_NONE == bt_adapter_get_state(&state)) {
+    is_powered_ = BT_ADAPTER_ENABLED == state;
+  }
+
+  bt_adapter_visibility_mode_e mode;
+  if (BT_ERROR_NONE == bt_adapter_get_visibility(&mode, nullptr)) {
+    is_visible_ = BT_ADAPTER_VISIBILITY_MODE_NON_DISCOVERABLE != mode;
+  }
+}
+
+BluetoothAdapter::~BluetoothAdapter() {
+  bt_socket_unset_data_received_cb();
+  bt_socket_unset_connection_state_changed_cb();
+
+  for (auto it : connected_sockets_) {
+    bt_socket_disconnect_rfcomm(it);
+  }
+
+  for (auto it : registered_uuids_) {
+    bt_socket_destroy_rfcomm(it.second.first);
+  }
+
+  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();
+
+  if (is_initialized_) {
+    if (BT_ERROR_NONE == bt_deinitialize()) {
+      LoggerD("Bluetooth service is deinitialized.");
+    } else {
+      LoggerE("Bluetooth service deinitialization failed.");
+    }
+  }
+}
+
+std::string BluetoothAdapter::get_name() const {
+  char* name = nullptr;
+  std::string str_name = "";
+  if (BT_ERROR_NONE == bt_adapter_get_name(&name)) {
+    if (name) {
+      str_name = name;
+      free(name);
+    }
+  }
+
+  return str_name;
+}
+
+bool BluetoothAdapter::get_visible() const {
+  bt_adapter_visibility_mode_e mode;
+
+  if (BT_ERROR_NONE == bt_adapter_get_visibility(&mode, NULL)) {
+    return mode != BT_ADAPTER_VISIBILITY_MODE_NON_DISCOVERABLE;
+  }
+
+  return false;
+}
+
+void BluetoothAdapter::set_visible(bool visible) {
+  is_visible_ = visible;
+}
+
+bool BluetoothAdapter::get_powered() {
+  return is_powered_;
+}
+
+void BluetoothAdapter::set_powered(bool powered) {
+  is_powered_ = powered;
+}
+
+bool BluetoothAdapter::is_initialized() const {
+  return is_initialized_;
+}
+
+void BluetoothAdapter::SetName(const picojson::value& data, picojson::object& out) {
+  LoggerD("Entered");
+
+  const auto callback_handle = util::GetAsyncCallbackHandle(data);
+  const auto& args = util::GetArguments(data);
+  const auto name = FromJson<std::string>(args, "name");
+
+  PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
+  if (!this->is_initialized()) {
+    result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Bluetooth service is not initialized.");
+    instance_.AsyncResponse(callback_handle, result);
+    return;
+  }
+
+  if (this->get_powered()) {
+    if (get_name() == name) {
+      instance_.AsyncResponse(callback_handle, result);
+      return;
+    }
+
+    if (this->user_request_list_[SET_NAME]) {
+      result = PlatformResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR, "Already requested");
+      instance_.AsyncResponse(callback_handle, result);
+      return;
+    }
+
+    this->user_request_list_[SET_NAME] = true;
+    this->user_request_callback_[SET_NAME] = callback_handle;
+
+    int ret = bt_adapter_set_name(name.c_str());
+    switch(ret) {
+      case BT_ERROR_NONE:
+        //bt_adapter_name_changed_cb() will be invoked
+        //if this function returns #BT_ERROR_NONE
+        this->requested_name_ = name;
+        break;
+      case BT_ERROR_INVALID_PARAMETER:
+        result = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid value");
+        break;
+      default:
+        result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown exception");
+    }
+  } else {
+    result = PlatformResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR, "Bluetooth device is turned off");
+  }
+
+  if (result.IsError()) {
+    this->user_request_list_[SET_NAME] = false;
+  }
+
+  instance_.AsyncResponse(callback_handle, result);
+}
+
+void BluetoothAdapter::SetPowered(const picojson::value& data, picojson::object& out) {
+  LoggerD("Entered");
+
+  const auto callback_handle = util::GetAsyncCallbackHandle(data);
+  const auto& args = util::GetArguments(data);
+  const auto new_powered = FromJson<bool>(args, "powered");
+
+  PlatformResult ret = PlatformResult(ErrorCode::NO_ERROR);
+
+  if (!this->is_initialized()) {
+    ret = PlatformResult(ErrorCode::UNKNOWN_ERR, "Bluetooth service is not initialized.");
+  }
+
+  if (ret.IsSuccess() && this->user_request_list_[SET_POWERED]) {
+    ret = PlatformResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR, "Already requested");
+  }
+
+  bool cur_powered = this->get_powered();
+
+  if (ret.IsSuccess() && new_powered != cur_powered) {
+#ifdef APP_CONTROL_SETTINGS_SUPPORT
+    app_control_h service;
+    int err = 0;
+
+    if ((err = app_control_create(&service)) != APP_CONTROL_ERROR_NONE) {
+      LoggerE("app control create failed: %d", err);
+      ret = PlatformResult(ErrorCode::UNKNOWN_ERR, "app control create failed");
+    }
+
+    if (ret.IsSuccess()) {
+      err = app_control_set_operation(service, "http://tizen.org/appcontrol/operation/edit");
+      if (err != APP_CONTROL_ERROR_NONE) {
+        LoggerE("app control set operation failed: %d", err);
+        ret = PlatformResult(ErrorCode::UNKNOWN_ERR, "app control set operation failed");
+      }
+    }
+
+    if (ret.IsSuccess()) {
+      err = app_control_set_mime(service, "application/x-bluetooth-on-off");
+      if (err != APP_CONTROL_ERROR_NONE) {
+        LoggerE("app control set mime failed: %d", err);
+        ret = PlatformResult(ErrorCode::UNKNOWN_ERR, "app control set mime failed");
+      }
+    }
+
+    if (ret.IsSuccess()) {
+      struct UserData {
+        BluetoothAdapter* adapter;
+        double callback_handle;
+      };
+
+      UserData* user_data = new UserData{ this, callback_handle };
+
+      err = app_control_send_launch_request(service, [](
+              app_control_h request, app_control_h reply,
+              app_control_result_e r, void* user_data) {
+        LoggerD("app_control_send_launch_request() callback");
+
+        UserData* data = static_cast<UserData*>(user_data);
+
+        char* result = nullptr;
+        app_control_get_extra_data(reply, "result", &result);
+
+        if (result && strcmp(result, "success") == 0) {
+          LoggerD("bt onoff: %s", result);
+          free(result);
+        } else {
+          LoggerE("app control setPowered failed");
+          data->adapter->instance_.AsyncResponse(data->callback_handle, PlatformResult(ErrorCode::UNKNOWN_ERR, "app control setPowered failed"));
+        }
+
+        delete data;
+      }, user_data);
+
+      if (err != APP_CONTROL_ERROR_NONE) {
+        LoggerE("app control set launch request failed: %d", err);
+        ret = PlatformResult(ErrorCode::UNKNOWN_ERR, "app control set launch request failed");
+      } else {
+        this->requested_powered_ = new_powered;
+        this->user_request_list_[SET_POWERED] = true;
+        this->user_request_callback_[SET_POWERED] = callback_handle;
+      }
+    }
+
+    err = app_control_destroy(service);
+    if (err != APP_CONTROL_ERROR_NONE) {
+      LoggerE("app control destroy failed: %d", err);
+      ret = PlatformResult(ErrorCode::UNKNOWN_ERR, "app control destroy failed");
+    }
+
+    if (!ret) {
+      instance_.AsyncResponse(callback_handle, ret);
+    }
+#else
+    this->requested_powered_ = new_powered;
+    this->user_request_list_[SET_POWERED] = true;
+    this->user_request_callback_[SET_POWERED] = callback_handle;
+
+    if (new_powered) {
+      bt_adapter_enable();
+    } else {
+      bt_adapter_disable();
+    }
+#endif
+  } else {
+    instance_.AsyncResponse(callback_handle, ret);
+  }
+}
+
+void BluetoothAdapter::SetVisible(const picojson::value& data, picojson::object& out) {
+  LoggerD("Entered");
+
+  const auto callback_handle = util::GetAsyncCallbackHandle(data);
+  const auto& args = util::GetArguments(data);
+  const auto visible = FromJson<bool>(args, "visible");
+
+  unsigned short new_timeout = kTimeout;
+  if (visible) {
+    new_timeout = static_cast<unsigned short>(FromJson<double>(args, "timeout"));
+  }
+
+  PlatformResult ret = PlatformResult(ErrorCode::NO_ERROR);
+
+  if (!this->is_initialized()) {
+    ret = PlatformResult(ErrorCode::UNKNOWN_ERR, "Bluetooth service is not initialized.");
+  }
+
+  if (ret.IsSuccess() && this->user_request_list_[SET_VISIBLE]) {
+    ret = PlatformResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR, "Already requested");
+  }
+
+  if (ret.IsSuccess() && this->get_powered()) {
+
+    bt_adapter_visibility_mode_e new_mode = BT_ADAPTER_VISIBILITY_MODE_NON_DISCOVERABLE;
+    if (visible) {
+      if (0 == new_timeout) {
+        new_mode = BT_ADAPTER_VISIBILITY_MODE_GENERAL_DISCOVERABLE;
+      } else {
+        new_mode = BT_ADAPTER_VISIBILITY_MODE_LIMITED_DISCOVERABLE;
+      }
+    }
+
+    bt_adapter_visibility_mode_e cur_mode = BT_ADAPTER_VISIBILITY_MODE_NON_DISCOVERABLE;
+    int cur_timeout = 0;
+    if (BT_ERROR_NONE != bt_adapter_get_visibility(&cur_mode , &cur_timeout)) {
+      ret = PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown exception");
+    }
+
+    if (ret.IsSuccess() && new_mode == cur_mode) {
+      if (BT_ADAPTER_VISIBILITY_MODE_LIMITED_DISCOVERABLE != new_mode ||
+          (unsigned int) cur_timeout == new_timeout) {
+        instance_.AsyncResponse(callback_handle, ret);
+        return;
+      }
+    }
+
+    if (ret.IsSuccess()) {
+#ifdef APP_CONTROL_SETTINGS_SUPPORT
+      app_control_h service;
+      int err = 0;
+
+      if ((err = app_control_create(&service)) != APP_CONTROL_ERROR_NONE) {
+        LoggerE("app control create failed: %d", err);
+        ret = PlatformResult(ErrorCode::UNKNOWN_ERR, "app control create failed");
+      }
+
+      if (ret.IsSuccess()) {
+        err = app_control_set_operation(service, "http://tizen.org/appcontrol/operation/edit");
+        if (err != APP_CONTROL_ERROR_NONE) {
+          LoggerE("app control set operation failed: %d", err);
+          ret = PlatformResult(ErrorCode::UNKNOWN_ERR, "app control set operation failed");
+        }
+      }
+
+      if (ret.IsSuccess()) {
+        err = app_control_set_mime(service, "application/x-bluetooth-visibility");
+        if (err != APP_CONTROL_ERROR_NONE) {
+          LoggerE("app control set mime failed: %d", err);
+          ret = PlatformResult(ErrorCode::UNKNOWN_ERR, "app control set mime failed");
+        }
+      }
+
+      if (ret.IsSuccess()) {
+        const void* t_param[] = { this, &ret, &new_mode, &callback_handle };
+
+        err = 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*>(((void**) user_data)[0]);
+          PlatformResult* p_ret = static_cast<PlatformResult*>(((void**) user_data)[1]);
+          bt_adapter_visibility_mode_e* p_new_mode = static_cast<bt_adapter_visibility_mode_e*>(((void**) user_data)[2]);
+          double* p_callback_handle = static_cast<double*>(((void**) user_data)[3]);
+
+          char* result = nullptr;
+          app_control_get_extra_data(reply, "result", &result);
+          LoggerD("bt visibility onoff: %s", result);
+
+          if (strcmp(result, "success") == 0) {
+            self->requested_visibility_ = *p_new_mode;
+            self->user_request_list_[SET_VISIBLE] = true;
+            self->user_request_callback_[SET_VISIBLE] = *p_callback_handle;
+          } else {
+            LoggerE("app control setVisible failed");
+            *p_ret = PlatformResult(ErrorCode::UNKNOWN_ERR, "app control setVisible failed");
+          }
+        }, t_param);
+
+        if (err != APP_CONTROL_ERROR_NONE) {
+          LoggerE("app control set launch request failed: %d", err);
+          ret = PlatformResult(ErrorCode::UNKNOWN_ERR, "app control set launch request failed");
+        }
+      }
+
+      err = app_control_destroy(service);
+      if (err != APP_CONTROL_ERROR_NONE) {
+        LoggerE("app control destroy failed: %d", err);
+        ret = PlatformResult(ErrorCode::UNKNOWN_ERR, "app control destroy failed");
+      }
+#else
+      this->requested_visibility_ = new_mode;
+      this->user_request_list_[SET_VISIBLE] = true;
+      this->user_request_callback_[SET_VISIBLE] = callback_handle;
+      int ret = bt_adapter_set_visibility(new_mode, new_timeout);
+
+      switch(ret) {
+        case BT_ERROR_NONE:
+          //bt_adapter_visibility_mode_changed_cb() will be invoked
+          //if this function returns #BT_ERROR_NONE
+          break;
+        case BT_ERROR_INVALID_PARAMETER:
+          ret = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid value");
+          break;
+        default:
+          ret = PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown exception");
+      }
+#endif
+    }
+  } else if (ret.IsSuccess()){
+    ret = PlatformResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR, "Bluetooth device is turned off");
+  }
+
+  instance_.AsyncResponse(callback_handle, ret);
+}
+
+void BluetoothAdapter::DiscoverDevices(const picojson::value& /* data */, picojson::object& out) {
+  LoggerD("Entered");
+
+  PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
+
+  if (!is_initialized_) {
+    result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Bluetooth service is not initialized.");
+  }
+
+  if (result.IsSuccess() && this->user_request_list_[DISCOVER_DEVICES]) {
+    result = PlatformResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR, "Already requested");
+  }
+
+  if (result.IsSuccess() && !get_powered()) {
+    result = PlatformResult(
+        ErrorCode::SERVICE_NOT_AVAILABLE_ERR, "Bluetooth device is turned off");
+  }
+
+  if (result.IsSuccess()) {
+    this->user_request_list_[DISCOVER_DEVICES] = true;
+    bt_adapter_start_device_discovery();
+  } else {
+    std::shared_ptr<picojson::value> response =
+        std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+
+    ReportError(result, &response->get<picojson::object>());
+    TaskQueue::GetInstance().Async<picojson::value>([this](const std::shared_ptr<picojson::value>& result) {
+      instance_.FireEvent(kAdapterDiscoverErrorEvent, result);
+    }, response);
+  }
+}
+
+void BluetoothAdapter::StopDiscovery(const picojson::value& data, picojson::object& out) {
+  LoggerD("Entered");
+
+  const auto callback_handle = util::GetAsyncCallbackHandle(data);
+
+  PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
+
+  if (!this->is_initialized()) {
+    result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Bluetooth service is not initialized.");
+  }
+
+  if (result.IsSuccess() && this->user_request_list_[STOP_DISCOVERY]) {
+    result = PlatformResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR, "Already requested");
+  }
+
+  if (result.IsSuccess() && this->get_powered()) {
+    bool is_discovering = false;
+    bt_adapter_is_discovering(&is_discovering);
+
+    if (!is_discovering) {
+      instance_.AsyncResponse(callback_handle, result);
+      return;
+    }
+
+    this->user_request_list_[STOP_DISCOVERY] = true;
+    this->user_request_callback_[STOP_DISCOVERY] = callback_handle;
+    int ret = bt_adapter_stop_device_discovery();
+    switch(ret) {
+      case BT_ERROR_NONE: {
+        //This function invokes bt_adapter_device_discovery_state_changed_cb().
+        break;
+      }
+      default: {
+        this->user_request_list_[STOP_DISCOVERY] = false;
+        result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown exception");
+      }
+    }
+  } else if (result.IsSuccess()) {
+    result = PlatformResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR, "Bluetooth device is turned off");
+  }
+
+  if (result.IsError()) {
+    instance_.AsyncResponse(callback_handle, result);
+  }
+}
+
+void BluetoothAdapter::GetKnownDevices(const picojson::value& data, picojson::object& out) {
+  LoggerD("Entered");
+
+  const auto callback_handle = util::GetAsyncCallbackHandle(data);
+
+  auto get_known_devices = [this](const std::shared_ptr<picojson::value>& response) -> void {
+    PlatformResult ret = PlatformResult(ErrorCode::NO_ERROR);
+
+    if (!this->is_initialized()) {
+      ret = PlatformResult(ErrorCode::UNKNOWN_ERR, "Bluetooth service is not initialized.");
+    }
+
+    if (ret.IsSuccess() && this->get_powered()) {
+      picojson::object& response_obj = response->get<picojson::object>();
+      picojson::value result = picojson::value(picojson::object());
+      picojson::object& result_obj = result.get<picojson::object>();
+      picojson::array& array = result_obj.insert(std::make_pair("devices", picojson::value(
+          picojson::array()))).first->second.get<picojson::array>();
+
+      array = discovered_devices_;
+
+      if (BT_ERROR_NONE == bt_adapter_foreach_bonded_device(ForeachBondedDevicesCB, &array)) {
+        ReportSuccess(result, response_obj);
+      } else {
+        ret = PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown exception");
+      }
+    } else if (ret.IsSuccess()) {
+      ret = PlatformResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR, "Bluetooth device is turned off");
+    }
+
+    if (ret.IsError()) {
+      ReportError(ret, &response->get<picojson::object>());
+    }
+  };
+  auto get_known_devices_response = [this, callback_handle](
+      const std::shared_ptr<picojson::value>& response) -> void {
+    instance_.SyncResponse(callback_handle, response);
+  };
+
+  auto queue_data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+
+  TaskQueue::GetInstance().Queue<picojson::value>(
+      get_known_devices,
+      get_known_devices_response,
+      queue_data);
+
+  ReportSuccess(out);
+}
+
+void BluetoothAdapter::GetDevice(const picojson::value& data, picojson::object&  out) {
+  LoggerD("Entered");
+
+  const auto callback_handle = util::GetAsyncCallbackHandle(data);
+  const auto& args = util::GetArguments(data);
+
+  const auto& address = FromJson<std::string>(args, "address");
+
+  auto get_device = [this, address](const std::shared_ptr<picojson::value>& response) -> void {
+    PlatformResult ret = PlatformResult(ErrorCode::NO_ERROR);
+    if (!IsValidAddress(address)) {
+      ret = PlatformResult(ErrorCode::NOT_FOUND_ERR, "Wrong address");
+    }
+
+    if (ret.IsSuccess() && !this->is_initialized()) {
+      ret = PlatformResult(ErrorCode::UNKNOWN_ERR, "Bluetooth service is not initialized.");
+    }
+    if (ret.IsSuccess() && this->get_powered()) {
+      picojson::object& response_obj = response->get<picojson::object>();
+      bt_device_info_s *info = nullptr;
+
+      if (bt_adapter_get_bonded_device_info(address.c_str(), &info) == BT_ERROR_NONE &&
+          info != nullptr) {
+        picojson::value result = picojson::value(picojson::object());
+        picojson::object& result_obj = result.get<picojson::object>();
+
+        BluetoothDevice::ToJson(info, &result_obj);
+        ReportSuccess(result, response_obj);
+        bt_adapter_free_device_info(info);
+        return;
+      }
+
+      auto is_address = discovered_addresses_.find(address);
+      if (is_address != discovered_addresses_.end()) {
+        for (auto iter = discovered_devices_.begin();
+            iter != discovered_devices_.end(); iter++) {
+          if (!strcmp(address.c_str(), ((*iter).get<picojson::object>())
+                      .find(kDeviceAddress)->second.get<std::string>().c_str())) {
+            ReportSuccess(*iter, response_obj);
+            return;
+          }
+        }
+      } else {
+        ret = PlatformResult(ErrorCode::NOT_FOUND_ERR, "There is no device with the given address");
+      }
+    } else if (ret.IsSuccess()) {
+      ret = PlatformResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR, "Bluetooth device is turned off");
+    }
+
+    if (ret.IsError()) {
+      ReportError(ret, &response->get<picojson::object>());
+    }
+  };
+
+  auto get_device_response = [this, callback_handle](
+      const std::shared_ptr<picojson::value>& response) -> void {
+    instance_.SyncResponse(callback_handle, response);
+  };
+
+  auto queue_data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+
+  TaskQueue::GetInstance().Queue<picojson::value>(
+      get_device,
+      get_device_response,
+      queue_data);
+
+  ReportSuccess(out);
+}
+
+class BondingHandler {
+ public:
+  BondingHandler(BluetoothInstance& instance, double callback_handle, const std::string& address) :
+    instance_(instance) ,callback_handle_(callback_handle), address_(address) {}
+
+  void set_address(const std::string& address) {
+    address_ = address;
+  }
+
+  const std::string& address() const {
+    return address_;
+  }
+
+  void Invoke(const PlatformResult& result, const std::shared_ptr<picojson::value>& response) {
+    LoggerD("Entered");
+
+    if (result.IsError()) {
+      ReportError(result, &response->get<picojson::object>());
+    } else {
+      ReportSuccess(response->get<picojson::object>());
+    }
+
+    instance_.AsyncResponse(callback_handle_, response);
+  }
+
+ private:
+  BluetoothInstance& instance_;
+  double callback_handle_;
+  std::string address_;
+};
+
+void BluetoothAdapter::CreateBonding(const picojson::value& data, picojson::object& out) {
+  LoggerD("Entered");
+
+  const auto callback_handle = util::GetAsyncCallbackHandle(data);
+  const auto& args = util::GetArguments(data);
+
+  const auto& address = FromJson<std::string>(args, "address");
+
+  auto create_bonding = [address, callback_handle, this]() -> void {
+    PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
+    if(!IsValidAddress(address)) {
+      result = PlatformResult(ErrorCode::NOT_FOUND_ERR, "Wrong address");
+    }
+
+    if (result.IsSuccess() && !this->is_initialized()) {
+      result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Bluetooth service is not initialized.");
+    }
+
+    if (result.IsSuccess() && this->get_powered()) {
+
+      auto bond_create_callback = [](int callback_result,
+          bt_device_info_s *device_info,
+          void *user_data) {
+        LoggerD("bond_create_callback");
+
+        BondingHandler* handler = static_cast<BondingHandler*>(user_data);
+        if (!handler) {
+          LoggerW("user_data is nullptr");
+          return;
+        }
+        if (!device_info) {
+          LoggerW("device_info is nullptr");
+          return;
+        }
+
+        PlatformResult ret = PlatformResult(ErrorCode::NO_ERROR);
+        std::shared_ptr<picojson::value> response =
+            std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+
+        std::string address(handler->address());
+        for(size_t i = 0; i < handler->address().length(); i++) {
+          address[i] = toupper(handler->address()[i]);
+        }
+
+        std::string remote_address(device_info->remote_address);
+        for(size_t i = 0; i < sizeof(device_info->remote_address); i++) {
+          remote_address[i] = toupper(device_info->remote_address[i]);
+        }
+
+        if (!strcmp(address.c_str(), remote_address.c_str())) {  // requested event
+          if (BT_ERROR_NONE == callback_result && nullptr != device_info ) {
+            picojson::object& response_obj = response->get<picojson::object>();
+            picojson::value result = picojson::value(picojson::object());
+            picojson::object& result_obj = result.get<picojson::object>();
+
+            BluetoothDevice::ToJson(device_info, &result_obj);
+            result_obj["address"] = picojson::value(handler->address());
+            ReportSuccess(result, response_obj);
+          } else if (BT_ERROR_REMOTE_DEVICE_NOT_FOUND == callback_result) {
+            LoggerE("Not found");
+            ret = PlatformResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR, "Not found");
+          } else {
+            LoggerE("Unknown exception");
+            ret = PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown exception");
+          }
+
+          handler->Invoke(ret, response);
+          delete handler;
+          bt_device_unset_bond_created_cb();
+        } else {  // unexpected event
+          LoggerD("An unexpected bonding detected");
+        }
+      };
+
+      BondingHandler* handler = new BondingHandler(instance_, callback_handle, address);
+      bt_device_set_bond_created_cb(bond_create_callback, handler);
+      int ret = bt_device_create_bond(address.c_str());
+
+      switch(ret) {
+        case BT_ERROR_NONE:
+        {
+          LoggerD("bt_device_create_bond() succeeded");
+          break;
+        }
+        case BT_ERROR_INVALID_PARAMETER:
+        {
+          LoggerE("Not found");
+          bt_device_unset_bond_created_cb();
+          delete handler;
+          result = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid value");
+          break;
+        }
+        default:
+        {
+          LoggerE("Unknown exception");
+          bt_device_unset_bond_created_cb();
+          delete handler;
+          result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown exception");
+        }
+      }
+    } else if (result.IsSuccess()) {
+      LoggerE("Bluetooth device is turned off");
+      result = PlatformResult(
+          ErrorCode::SERVICE_NOT_AVAILABLE_ERR, "Bluetooth device is turned off");
+    }
+
+    if (result.IsError()) {
+      instance_.AsyncResponse(callback_handle, result);
+    }
+  };
+  TaskQueue::GetInstance().Queue(create_bonding);
+  ReportSuccess(out);
+}
+
+void BluetoothAdapter::DestroyBonding(const picojson::value& data, picojson::object& out)
+{
+  LoggerD("Entered");
+
+  const auto callback_handle = util::GetAsyncCallbackHandle(data);
+  const auto& args = util::GetArguments(data);
+
+  const auto& address = FromJson<std::string>(args, "address");
+
+  auto destroy_bonding = [address, callback_handle, this]() -> void {
+    PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
+    if(!IsValidAddress(address)) {
+      result = PlatformResult(ErrorCode::NOT_FOUND_ERR, "Wrong address");
+    }
+    if (result.IsSuccess() && !this->is_initialized()) {
+      result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Bluetooth service is not initialized.");
+    }
+
+    if (result.IsSuccess() && this->get_powered()) {
+      bt_device_info_s *device_info = nullptr;
+      int ret = bt_adapter_get_bonded_device_info(address.c_str(), &device_info);
+
+      if (BT_ERROR_NONE != ret || nullptr == device_info) {
+        LoggerD("There is no bonding");
+        result = PlatformResult(ErrorCode::NOT_FOUND_ERR, "Not found");
+      } else {
+        bt_adapter_free_device_info(device_info);
+
+        auto bond_destroy_callback = [](int callback_result,
+            char *remote_address,
+            void *user_data) {
+          LoggerD("bond_destroy_callback");
+
+          BondingHandler* handler = static_cast<BondingHandler*>(user_data);
+          if (!handler) {
+            LoggerW("user_data is nullptr");
+            return;
+          }
+
+          PlatformResult ret = PlatformResult(ErrorCode::NO_ERROR);
+          std::shared_ptr<picojson::value> response =
+              std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+
+          std::string address(handler->address());
+          for(size_t i = 0; i < handler->address().length(); i++) {
+            address[i] = toupper(handler->address()[i]);
+          }
+
+          std::string r_address(remote_address);
+          for(size_t i = 0; i < sizeof(remote_address); i++) {
+            r_address[i] = toupper(remote_address[i]);
+          }
+
+          if (!strcmp(address.c_str(), r_address.c_str())) {  // requested event
+            if (BT_ERROR_NONE != callback_result) {
+              LoggerE("Unknown exception");
+              ret = PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown exception");
+            }
+
+            handler->Invoke(ret, response);
+            delete handler;
+            bt_device_unset_bond_destroyed_cb();
+          } else {  // unexpected event
+            LoggerD("An unexpected bonding detected");
+          }
+        };
+
+        BondingHandler* handler = new BondingHandler(instance_, callback_handle, address);
+        bt_device_set_bond_destroyed_cb(bond_destroy_callback, handler);
+
+        int ret = bt_device_destroy_bond(address.c_str());
+
+        switch(ret) {
+          case BT_ERROR_NONE:
+          {
+            LoggerD("bt_device_destroy_bond() succeeded");
+            break;
+          }
+          case BT_ERROR_INVALID_PARAMETER:
+          {
+            LoggerE("Not found");
+            bt_device_unset_bond_destroyed_cb();
+            delete handler;
+            result = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid value");
+            break;
+          }
+          default:
+          {
+            LoggerE("Unknown exception");
+            bt_device_unset_bond_destroyed_cb();
+            delete handler;
+            result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown exception");
+          }
+        }
+      }
+    } else  if (result.IsSuccess()) {
+      LoggerE("Bluetooth device is turned off");
+      result = PlatformResult(
+          ErrorCode::SERVICE_NOT_AVAILABLE_ERR, "Bluetooth device is turned off");
+    }
+
+    if (result.IsError()) {
+      instance_.AsyncResponse(callback_handle, result);
+    }
+  };
+  TaskQueue::GetInstance().Queue(destroy_bonding);
+  ReportSuccess(out);
+}
+
+void BluetoothAdapter::RegisterRFCOMMServiceByUUID(const picojson::value& data, picojson::object& out) {
+  LoggerD("Entered");
+
+  const auto callback_handle = util::GetAsyncCallbackHandle(data);
+  const auto& args = util::GetArguments(data);
+
+  const auto& uuid = FromJson<std::string>(args, "uuid");
+  const auto& name = FromJson<std::string>(args, "name");
+
+  auto rfcomm = [this, uuid, name](const std::shared_ptr<picojson::value>& response) -> void {
+    PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
+    if (!this->is_initialized()) {
+      result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Bluetooth service is not initialized.");
+    }
+
+    if (result.IsSuccess() && !IsValidUUID(uuid)) {
+      result = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Wrong UUID");
+    }
+
+    if (result.IsSuccess() && this->get_powered()) {
+      bool is_registered = false;
+      int ret = bt_adapter_is_service_used(uuid.c_str(), &is_registered);
+
+      if (BT_ERROR_NONE == ret && is_registered) {
+        result = PlatformResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR, "Already requested");
+      } else {
+        int socket = -1;
+        ret = bt_socket_create_rfcomm(uuid.c_str(), &socket);
+
+        switch (ret) {
+          case BT_ERROR_NONE: {
+            int ret_in = bt_socket_listen_and_accept_rfcomm(socket, 0);
+            switch(ret_in) {
+              case BT_ERROR_NONE: {
+                LoggerD("bt_socket_listen() succeeded");
+                bt_socket_set_connection_state_changed_cb(OnSocketConnected, this);
+
+                registered_uuids_.insert(std::make_pair(uuid,
+                                                        std::make_pair(socket, false)));
+
+                ReportSuccess(response->get<picojson::object>());
+                break;
+              }
+
+              case BT_ERROR_INVALID_PARAMETER: {
+                result = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid value");
+                break;
+              }
+
+              default: {
+                result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error");
+                break;
+              }
+            }
+            break;
+          }
+          case BT_ERROR_INVALID_PARAMETER:
+            result = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid value");
+            break;
+          default:
+            result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error");
+            break;
+        }
+      }
+    } else if (result.IsSuccess()) {
+      result = PlatformResult(
+          ErrorCode::SERVICE_NOT_AVAILABLE_ERR, "Bluetooth device is turned off");
+    }
+
+    if (result.IsError()) {
+      ReportError(result, &response->get<picojson::object>());
+    }
+  };
+
+  auto rfcomm_response = [this, callback_handle](const std::shared_ptr<picojson::value>& response) -> void {
+    instance_.SyncResponse(callback_handle, response);
+  };
+
+  auto queue_data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+
+  TaskQueue::GetInstance().Queue<picojson::value>(
+      rfcomm,
+      rfcomm_response,
+      queue_data);
+
+  ReportSuccess(out);
+}
+
+void BluetoothAdapter::UnregisterUUID(const std::string& uuid, int callback_handle) {
+  LoggerD("Entered");
+
+  PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
+  if (!IsValidUUID(uuid)) {
+    result = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Wrong UUID");
+  }
+
+  if (result.IsSuccess() && is_powered_) {
+    auto iter = registered_uuids_.find(uuid);
+    if (iter != registered_uuids_.end()) {
+      if (BT_ERROR_NONE == bt_socket_destroy_rfcomm(iter->second.first)) {
+        registered_uuids_.erase(iter);
+      } else {
+        result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown exception");
+      }
+    }
+
+    if (registered_uuids_.empty() &&
+        connection_requests_.empty() &&
+        connected_sockets_.empty()) {
+      bt_socket_unset_connection_state_changed_cb();
+    }
+  } else if (result.IsSuccess()){
+    result = PlatformResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR, "Bluetooth device is turned off");
+  }
+
+  instance_.AsyncResponse(callback_handle, result);
+}
+
+void BluetoothAdapter::GetBluetoothProfileHandler(const picojson::value& data,
+                                                  picojson::object& out) {
+  LoggerD("Entered");
+
+  const auto& args = util::GetArguments(data);
+  auto profile = FromJson<std::string>(args, "profileType");
+
+  PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
+
+  if (kBluetoothProfileHealth == profile) {
+    bool supported = false;
+    if (SYSTEM_INFO_ERROR_NONE !=
+        system_info_get_platform_bool(kFeatureBluetoothHealth.c_str(), &supported)) {
+      LoggerW("Can't check if BT health profile is supported or not");
+    }
+
+    if (!supported) {
+      result = PlatformResult(
+          ErrorCode::NOT_SUPPORTED_ERR, "Bluetooth health profile is not supported");
+    } else {
+      LoggerD("BT health profile is supported");
+    }
+  } else {
+    result = PlatformResult(ErrorCode::TYPE_MISMATCH_ERR, "Wrong profile type.");
+  }
+
+  if (result.IsSuccess()) {
+    ReportSuccess(out);
+  } else {
+    ReportError(result, &out);
+  }
+}
+
+void BluetoothAdapter::GetName(const picojson::value& /* data */, picojson::object& out) {
+  LoggerD("Entered");
+
+  ReportSuccess(picojson::value(get_name()), out);
+}
+
+void BluetoothAdapter::GetAddress(const picojson::value& /* data */, picojson::object& out) {
+  LoggerD("Entered");
+
+  if (!is_initialized_) {
+    ReportError(PlatformResult(
+        ErrorCode::UNKNOWN_ERR, "Bluetooth service is not initialized."), &out);
+    return;
+  }
+
+  std::string str_address = "";
+  char* address = nullptr;
+  if (BT_ERROR_NONE == bt_adapter_get_address(&address)) {
+    if (address) {
+      str_address = address;
+      free(address);
+    }
+  }
+
+  ReportSuccess(picojson::value(str_address), out);
+}
+
+void BluetoothAdapter::GetPowered(const picojson::value& /* data */, picojson::object& out) {
+  LoggerD("Entered");
+
+  ReportSuccess(picojson::value(is_powered_), out);
+}
+
+void BluetoothAdapter::GetVisible(const picojson::value& /* data */, picojson::object& out) {
+  LoggerD("Entered");
+
+  ReportSuccess(picojson::value(get_visible()), out);
+}
+
+void BluetoothAdapter::OnSocketConnected(
+    int result,
+    bt_socket_connection_state_e state,
+    bt_socket_connection_s* connection,
+    void* user_data) {
+  LoggerD("Entered");
+
+  BluetoothAdapter* object = static_cast<BluetoothAdapter*>(user_data);
+
+  if (!object) {
+    LoggerW("user_data is NULL");
+    return;
+  }
+
+  if (!connection) {
+    LoggerW("connection is NULL");
+    return;
+  }
+
+  if (BT_SOCKET_SERVER == connection->local_role) {
+    LoggerD("Server");
+
+    const auto iter = object->registered_uuids_.find(connection->service_uuid);
+    if (iter == object->registered_uuids_.end()) {
+      LoggerW("Connection state has changed unexpectedly");
+      return;
+    }
+
+    if (BT_SOCKET_CONNECTED == state) {  // connected when Server
+      if (BT_ERROR_NONE == result) {
+        // Update registered_uuids_ state
+        iter->second.second = true;
+
+        // Call BluetoothServiceHandler.onconnect
+        object->instance_.FireEvent("BLUETOOTH_SERVICE_ONCONNECT", BluetoothSocket::ToJson(connection));
+
+        // Update connected_sockets_
+        object->connected_sockets_.push_back(connection->socket_fd);
+        bt_socket_set_data_received_cb(OnSocketReceivedData, user_data);
+      } else {
+        LoggerW("Establishing a connection failed");
+      }
+      return;
+    } else {  // disconnected when Server
+      if (BT_ERROR_NONE == result) {
+        // Update registered_uuids_ state
+        iter->second.second = false;
+        object->RemoveSocket(connection->socket_fd);
+      }
+      else {
+        LoggerW("Disconnecting a connection failed");
+      }
+    }
+  } else if (BT_SOCKET_CLIENT == connection->local_role) {
+    LoggerD("Client");
+
+    if (BT_SOCKET_CONNECTED == state) {  // connected when Client
+      const auto range = object->connection_requests_.equal_range(connection->remote_address);
+      const auto end = object->connection_requests_.end();
+      auto request = end;
+
+      for (auto it = range.first; it != range.second; ++it) {
+        if (strcmp(it->second->uuid_.c_str(), connection->service_uuid) == 0) {
+          request = it;
+          break;
+        }
+      }
+
+      if (end == request) {
+        LoggerW("Connection state has changed unexpectedly");
+        return;
+      }
+
+      std::shared_ptr<picojson::value> response =
+          std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+
+      if (BT_ERROR_NONE == result) {
+        object->connected_sockets_.push_back(connection->socket_fd);
+        bt_socket_set_data_received_cb(OnSocketReceivedData, user_data);
+
+        ReportSuccess(BluetoothSocket::ToJson(connection), response->get<picojson::object>());
+      } else {
+        ReportError(PlatformResult(
+            ErrorCode::NOT_FOUND_ERR, "Not found"), &response->get<picojson::object>());
+      }
+
+      object->instance_.AsyncResponse(request->second->callback_handle_, response);
+
+      // request has been handled, can be safely removed
+      object->connection_requests_.erase(request);
+    } else {  // disconnected when Client
+      if (result == BT_ERROR_NONE) {
+        object->RemoveSocket(connection->socket_fd);
+      } else {
+        LoggerW("Disconnecting a connection failed");
+      }
+    }
+  } else {
+    LoggerW("Unknown role");
+    return;
+  }
+
+  if (object->connected_sockets_.empty()) {
+    bt_socket_unset_data_received_cb();
+  }
+
+  if (object->registered_uuids_.empty() &&
+      object->connection_requests_.empty() &&
+      object->connected_sockets_.empty()) {
+    bt_socket_unset_connection_state_changed_cb();
+  }
+}
+
+void BluetoothAdapter::OnSocketReceivedData(bt_socket_received_data_s* data, void* user_data) {
+  LoggerD("Entered");
+
+  BluetoothAdapter* object = static_cast<BluetoothAdapter*>(user_data);
+
+  if (!object) {
+    LoggerW("user_data is NULL");
+    return;
+  }
+
+  if (!data) {
+    LoggerW("data is NULL");
+    return;
+  }
+
+  const auto it = std::find(object->connected_sockets_.begin(),
+                            object->connected_sockets_.end(),
+                            data->socket_fd);
+
+  if (it == object->connected_sockets_.end()) {
+    LoggerW("Unknown connected socket: %d", data->socket_fd);
+    return;
+  }
+
+  // Store received data
+  object->StoreSocketData(data);
+
+  object->InvokeSocketOnMessageEvent(*it);
+}
+
+void BluetoothAdapter::ConnectToServiceByUUID(
+    const std::string& address,
+    const std::string& uuid,
+    double callback_handle) {
+  LoggerD("Entered");
+
+  PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
+
+  if (!IsValidUUID(uuid)) {
+    result = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Wrong UUID");
+  }
+
+  if (result.IsSuccess() && is_powered_) {
+    int ret = bt_socket_connect_rfcomm(address.c_str(), uuid.c_str());
+
+    switch (ret) {
+      case BT_ERROR_NONE: {
+        LoggerD("bt_socket_connect_rfcomm() succeeded");
+
+        ConnectionRequestPtr request{new ConnectionRequest()};
+        request->uuid_ = uuid;
+        request->callback_handle_ = callback_handle;
+
+        std::string r_address(address);
+        for(size_t i = 0; i < address.length(); i++) {
+          r_address[i] = toupper(address[i]);
+        }
+        connection_requests_.insert(std::make_pair(r_address, request));
+
+        bt_socket_set_connection_state_changed_cb(OnSocketConnected, this);
+        break;
+      }
+
+      case BT_ERROR_INVALID_PARAMETER:
+      case BT_ERROR_REMOTE_DEVICE_NOT_BONDED:
+        result = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid value");
+        break;
+      default:
+        result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error");
+        break;
+    }
+  } else if (result.IsSuccess()) {
+    result = PlatformResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR, "Bluetooth device is turned off");
+  }
+
+  if (result.IsError()) {
+    instance_.AsyncResponse(callback_handle, result);
+  }
+}
+
+
+void BluetoothAdapter::InvokeSocketEvent(int id, const char* event) {
+  picojson::value value = picojson::value(picojson::object());
+  picojson::object& value_obj = value.get<picojson::object>();
+  value_obj.insert(std::make_pair("id", picojson::value(std::to_string(id))));
+  value_obj.insert(std::make_pair("event", picojson::value(event)));
+  instance_.FireEvent("BLUETOOTH_SOCKET_STATE_CHANGED", value);
+}
+
+void BluetoothAdapter::InvokeSocketOnMessageEvent(int id) {
+  InvokeSocketEvent(id, "onmessage");
+}
+
+void BluetoothAdapter::InvokeSocketOnCloseEvent(int id) {
+  InvokeSocketEvent(id, "onclose");
+}
+
+void BluetoothAdapter::RemoveSocket(int socket) {
+  const auto data_it = socket_data_.find(socket);
+
+  if (data_it != socket_data_.end()) {
+    socket_data_.erase(data_it);
+  } else {
+    LoggerD("No stored data for socket: %d", socket);
+  }
+
+  const auto it = std::find(connected_sockets_.begin(), connected_sockets_.end(), socket);
+
+  if (it == connected_sockets_.end()) {
+    LoggerW("Unknown connected socket: %d", socket);
+    return;
+  }
+
+  connected_sockets_.erase(it);
+
+  InvokeSocketOnCloseEvent(*it);
+}
+
+void BluetoothAdapter::StoreSocketData(bt_socket_received_data_s* data) {
+  LoggerD("Entered");
+
+  auto& data_store = socket_data_[data->socket_fd];
+
+  for (int i = 0; i < data->data_size; ++i) {
+    data_store.push_back(data->data[i]);
+  }
+}
+
+const std::list<char>& BluetoothAdapter::ReadSocketData(int socket) {
+  LoggerD("Entered");
+
+  return socket_data_[socket];
+}
+
+void BluetoothAdapter::ClearSocketData(int socket) {
+  LoggerD("Entered");
+
+  const auto data_it = socket_data_.find(socket);
+
+  if (data_it != socket_data_.end()) {
+    data_it->second.clear();
+  }
+}
+
+void BluetoothAdapter::IsServiceConnected(const picojson::value& data, picojson::object& out) {
+  LoggerD("Entered");
+
+  const auto& args = util::GetArguments(data);
+  const auto& uuid = FromJson<std::string>(args, "uuid");
+
+  auto iter = registered_uuids_.find(uuid);
+  if (iter == registered_uuids_.end()) {
+    ReportError(PlatformResult(
+        ErrorCode::INVALID_VALUES_ERR, "Invalid parameter was passed."), &out);
+    return;
+  }
+
+  ReportSuccess(picojson::value(iter->second.second), out);
+}
+
+} // namespace bluetooth
+} // namespace extension
diff --git a/webWidgetTCT_device/src/bluetooth/bluetooth_adapter.h b/webWidgetTCT_device/src/bluetooth/bluetooth_adapter.h
new file mode 100755 (executable)
index 0000000..ad77af9
--- /dev/null
@@ -0,0 +1,384 @@
+/*
+ * Copyright (c) 2015 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 BLUETOOTH_BLUETOOTH_ADAPTER_H_
+#define BLUETOOTH_BLUETOOTH_ADAPTER_H_
+
+#include <set>
+#include <list>
+#include <memory>
+#include <unordered_map>
+#include <map>
+
+#include <bluetooth.h>
+#include "bluetooth_internal.h"
+
+#include "common/picojson.h"
+
+namespace extension {
+namespace bluetooth {
+
+enum AdapterAsyncEvent {
+  SET_POWERED = 0,
+  SET_NAME,
+  SET_VISIBLE,
+  DISCOVER_DEVICES,
+  STOP_DISCOVERY
+};
+
+class BluetoothInstance;
+
+class BluetoothAdapter {
+ public:
+  /**
+   * Signature: @code void setName(name, successCallback, errorCallback); @endcode
+   * JSON: @code data: {method: 'BluetoothAdapter_setName', args: {name: name}} @endcode
+   * Invocation: @code native.call(request, result_callback); @endcode
+   * Return:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success'}
+   * @endcode
+   * Result callback:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success'}
+   * @endcode
+   */
+  void SetName(const picojson::value& data, picojson::object& out);
+
+  /**
+   * Signature: @code void setPowered(state, successCallback, errorCallback); @endcode
+   * JSON: @code data: {method: 'BluetoothAdapter_setPowered', args: {state: state}} @endcode
+   * Invocation: @code native.call(request, result_callback); @endcode
+   * Return:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success'}
+   * @endcode
+   * Result callback:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success'}
+   * @endcode
+   */
+  void SetPowered(const picojson::value& data, picojson::object& out);
+
+  /**
+   * Signature: @code void setVisible(mode, successCallback, errorCallback, timeout); @endcode
+   * JSON: @code data: {method: 'BluetoothAdapter_setVisible', args: {mode: mode, timeout: timeout}} @endcode
+   * Invocation: @code native.call(request, result_callback); @endcode
+   * Return:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success'}
+   * @endcode
+   * Result callback:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success'}
+   * @endcode
+   */
+  void SetVisible(const picojson::value& data, picojson::object& out);
+
+  /**
+   * Signature: @code void discoverDevices(discoveryCallback, errorCallback); @endcode
+   * JSON: @code data: {method: 'BluetoothAdapter_discoverDevices', args: {discoveryCallbackId: id}} @endcode
+   * Invocation: @code native.callSync(request); @endcode
+   * Return:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success'}
+   * @endcode
+   * Discovery callback:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success', result: {event, eventData}}
+   * @endcode
+   */
+  void DiscoverDevices(const picojson::value& data, picojson::object& out);
+
+  /**
+   * Signature: @code void stopDiscovery(successCallback, errorCallback); @endcode
+   * JSON: @code data: {method: 'BluetoothAdapter_stopDiscovery', args: {}} @endcode
+   * Invocation: @code native.call(request, result_callback); @endcode
+   * Return:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success'}
+   * @endcode
+   * Result callback:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success'}
+   * @endcode
+   */
+  void StopDiscovery(const picojson::value& data, picojson::object& out);
+
+  /**
+   * Signature: @code void getKnownDevices(successCallback, errorCallback); @endcode
+   * JSON: @code data: {method: 'BluetoothAdapter_getKnownDevices', args: {}} @endcode
+   * Invocation: @code native.call(request, result_callback); @endcode
+   * Return:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success'}
+   * @endcode
+   * Result callback:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success', result: {devices[]}}
+   * @endcode
+   */
+  void GetKnownDevices(const picojson::value& data, picojson::object& out);
+
+  /**
+   * Signature: @code void getDevice(address, successCallback, errorCallback); @endcode
+   * JSON: @code data: {method: 'BluetoothAdapter_getDevice', args: {address: address}} @endcode
+   * Invocation: @code native.call(request, result_callback); @endcode
+   * Return:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success'}
+   * @endcode
+   * Result callback:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success', result: {device}}
+   * @endcode
+   */
+  void GetDevice(const picojson::value& data, picojson::object& out);
+
+  /**
+   * Signature: @code void createBonding(address, successCallback, errorCallback); @endcode
+   * JSON: @code data: {method: 'BluetoothAdapter_createBonding', args: {address: address}} @endcode
+   * Invocation: @code native.call(request, result_callback); @endcode
+   * Return:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success'}
+   * @endcode
+   * Result callback:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success', result: {device}}
+   * @endcode
+   */
+  void CreateBonding(const picojson::value& data, picojson::object& out);
+
+  /**
+   * Signature: @code void destroyBonding(address, successCallback, errorCallback); @endcode
+   * JSON: @code data: {method: 'BluetoothAdapter_destroyBonding', args: {address: address}} @endcode
+   * Invocation: @code native.call(request, result_callback); @endcode
+   * Return:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success'}
+   * @endcode
+   * Result callback:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success'}
+   * @endcode
+   */
+  void DestroyBonding(const picojson::value& data, picojson::object& out);
+
+  /**
+   * Signature: @code void registerRFCOMMServiceByUUID(uuid, name, successCallback, errorCallback); @endcode
+   * JSON: @code data: {method: 'BluetoothAdapter_registerRFCOMMServiceByUUID',
+   *                    args: {uuid: uuid, name: name}} @endcode
+   * Invocation: @code native.call(request, result_callback); @endcode
+   * Return:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success'}
+   * @endcode
+   * Result callback:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success', result: {handler}}
+   * @endcode
+   */
+  void RegisterRFCOMMServiceByUUID(const picojson::value& data, picojson::object& out);
+
+  /**
+   * Signature: @code BluetoothProfileHandler getBluetoothProfileHandler(profileType); @endcode
+   * JSON: @code data: {method: 'BluetoothAdapter_getBluetoothProfileHandler',
+   *                    args: {profileType: profileType}} @endcode
+   * Invocation: @code native.callSync(request); @endcode
+   * Return:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success', result: {BluetoothProfileHandler}}
+   * @endcode
+   */
+  void GetBluetoothProfileHandler(const picojson::value& data, picojson::object& out);
+
+  /**
+   * Signature: @code BluetoothAdapter.name; @endcode
+   * JSON: @code data: {method: 'BluetoothAdapter_getName', args: {}} @endcode
+   * Invocation: @code native.callSync(request); @endcode
+   * Return:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success', result: name}
+   * @endcode
+   */
+  void GetName(const picojson::value& data, picojson::object& out);
+
+  /**
+   * Signature: @code BluetoothAdapter.address; @endcode
+   * JSON: @code data: {method: 'BluetoothAdapter_getAddress', args: {}} @endcode
+   * Invocation: @code native.callSync(request); @endcode
+   * Return:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success', result: address}
+   * @endcode
+   */
+  void GetAddress(const picojson::value& data, picojson::object& out);
+
+  /**
+   * Signature: @code BluetoothAdapter.powered; @endcode
+   * JSON: @code data: {method: 'BluetoothAdapter_getPowered', args: {}} @endcode
+   * Invocation: @code native.callSync(request); @endcode
+   * Return:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success', result: powered}
+   * @endcode
+   */
+  void GetPowered(const picojson::value& data, picojson::object& out);
+
+  /**
+   * Signature: @code BluetoothAdapter.visible; @endcode
+   * JSON: @code data: {method: 'BluetoothAdapter_getVisible', args: {}} @endcode
+   * Invocation: @code native.callSync(request); @endcode
+   * Return:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success', result: visible}
+   * @endcode
+   */
+  void GetVisible(const picojson::value& data, picojson::object& out);
+
+  /**
+   * Signature: @code BluetoothServiceHandler.isConnected; @endcode
+   * JSON: @code data: {method: 'BluetoothAdapter_isConnected', args: {}} @endcode
+   * Invocation: @code native.callSync(request); @endcode
+   * Return:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success', result: isConnected}
+   * @endcode
+   */
+  void IsServiceConnected(const picojson::value& data, picojson::object& out);
+
+  explicit BluetoothAdapter(BluetoothInstance& instance);
+  virtual ~BluetoothAdapter();
+
+  std::string get_name() const;
+  bool get_visible() const;
+  void set_visible(bool visible);
+  bool get_powered();
+  void set_powered(bool powered);
+  bool is_initialized() const;
+
+  void ConnectToServiceByUUID(const std::string& address,
+                              const std::string& uuid,
+                              double callback_handle);
+
+  const std::list<char>& ReadSocketData(int socket);
+
+  void ClearSocketData(int socket);
+
+  void UnregisterUUID(const std::string& uuid, int callback_handle);
+
+ private:
+  BluetoothAdapter(const BluetoothAdapter&) = delete;
+  BluetoothAdapter& operator=(const BluetoothAdapter&) = delete;
+
+  static void StateChangedCB(int result,
+                             bt_adapter_state_e state,
+                             void *user_data);
+  static void NameChangedCB(char *name,
+                            void *user_data);
+  static void VisibilityChangedCB(int result,
+                                  bt_adapter_visibility_mode_e mode,
+                                  void *user_data);
+  static void DiscoveryStateChangedCB(int result,
+                                      bt_adapter_device_discovery_state_e discovery_state,
+                                      bt_adapter_device_discovery_info_s *discovery_info,
+                                      void *user_data);
+
+  void StoreSocketData(bt_socket_received_data_s* data);
+
+  void RemoveSocket(int socket);
+
+  static void OnSocketConnected(int result,
+                                bt_socket_connection_state_e state,
+                                bt_socket_connection_s* connection,
+                                void* user_data);
+
+  static void OnSocketReceivedData(bt_socket_received_data_s* data,
+                                   void* user_data);
+
+  void InvokeSocketEvent(int id, const char* event);
+  void InvokeSocketOnMessageEvent(int id);
+  void InvokeSocketOnCloseEvent(int id);
+
+  bool is_visible_;
+  bool is_powered_;
+  bool is_initialized_;
+  bool user_request_list_ [STOP_DISCOVERY + 1];
+  double user_request_callback_ [STOP_DISCOVERY + 1];
+
+  bool requested_powered_;
+  bt_adapter_visibility_mode_e requested_visibility_;
+  std::string requested_name_;
+
+  picojson::array discovered_devices_;
+  std::set<std::string> discovered_addresses_;
+  std::set<std::string> disappeared_addresses_;
+
+  struct ConnectionRequest {
+    std::string uuid_;
+    double callback_handle_;
+  };
+
+  typedef std::shared_ptr<ConnectionRequest> ConnectionRequestPtr;
+  typedef std::multimap<std::string, ConnectionRequestPtr> ConnectionRequestMap;
+
+  ConnectionRequestMap connection_requests_;
+
+  typedef std::list<int> ConnectedSocketList;
+
+  ConnectedSocketList connected_sockets_;
+
+  typedef std::pair<int, bool> BluetoothServicePair; //registered socket - connection state
+  typedef std::map<std::string, BluetoothServicePair> RegisteredUuidMap;
+
+  RegisteredUuidMap registered_uuids_;
+
+  std::unordered_map<int, std::list<char>> socket_data_;
+
+  BluetoothInstance& instance_;
+};
+
+} // namespace bluetooth
+} // namespace extension
+
+#endif // BLUETOOTH_BLUETOOTH_ADAPTER_H_
diff --git a/webWidgetTCT_device/src/bluetooth/bluetooth_api.js b/webWidgetTCT_device/src/bluetooth/bluetooth_api.js
new file mode 100755 (executable)
index 0000000..710c771
--- /dev/null
@@ -0,0 +1,2566 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+var T = xwalk.utils.type;
+var Converter = xwalk.utils.converter;
+var AV = xwalk.utils.validator;
+var Privilege = xwalk.utils.privilege;
+
+var native = new xwalk.utils.NativeManager(extension);
+
+// class BluetoothClassDeviceMajor /////////////////////////////////////////
+var BluetoothClassDeviceMajor = function() {
+    Object.defineProperties(this, {
+        MISC:          {value: 0x00, writable: false, enumerable: true},
+        COMPUTER:      {value: 0x01, writable: false, enumerable: true},
+        PHONE:         {value: 0x02, writable: false, enumerable: true},
+        NETWORK:       {value: 0x03, writable: false, enumerable: true},
+        AUDIO_VIDEO:   {value: 0x04, writable: false, enumerable: true},
+        PERIPHERAL:    {value: 0x05, writable: false, enumerable: true},
+        IMAGING:       {value: 0x06, writable: false, enumerable: true},
+        WEARABLE:      {value: 0x07, writable: false, enumerable: true},
+        TOY:           {value: 0x08, writable: false, enumerable: true},
+        HEALTH:        {value: 0x09, writable: false, enumerable: true},
+        UNCATEGORIZED: {value: 0x1F, writable: false, enumerable: true}
+    });
+};
+
+// class BluetoothClassDeviceMinor /////////////////////////////////////////
+var BluetoothClassDeviceMinor = function() {
+    Object.defineProperties(this, {
+        COMPUTER_UNCATEGORIZED:           {value: 0x00, writable: false, enumerable: true},
+        COMPUTER_DESKTOP:                 {value: 0x01, writable: false, enumerable: true},
+        COMPUTER_SERVER:                  {value: 0x02, writable: false, enumerable: true},
+        COMPUTER_LAPTOP:                  {value: 0x03, writable: false, enumerable: true},
+        COMPUTER_HANDHELD_PC_OR_PDA:      {value: 0x04, writable: false, enumerable: true},
+        COMPUTER_PALM_PC_OR_PDA:          {value: 0x05, writable: false, enumerable: true},
+        COMPUTER_WEARABLE:                {value: 0x06, writable: false, enumerable: true},
+
+        PHONE_UNCATEGORIZED:              {value: 0x00, writable: false, enumerable: true},
+        PHONE_CELLULAR:                   {value: 0x01, writable: false, enumerable: true},
+        PHONE_CORDLESS:                   {value: 0x02, writable: false, enumerable: true},
+        PHONE_SMARTPHONE:                 {value: 0x03, writable: false, enumerable: true},
+        PHONE_MODEM_OR_GATEWAY:           {value: 0x04, writable: false, enumerable: true},
+        PHONE_ISDN:                       {value: 0x05, writable: false, enumerable: true},
+
+        AV_UNRECOGNIZED:                  {value: 0x00, writable: false, enumerable: true},
+        AV_WEARABLE_HEADSET:              {value: 0x01, writable: false, enumerable: true},
+        AV_HANDSFREE:                     {value: 0x02, writable: false, enumerable: true},
+        AV_MICROPHONE:                    {value: 0x04, writable: false, enumerable: true},
+        AV_LOUDSPEAKER:                   {value: 0x05, writable: false, enumerable: true},
+        AV_HEADPHONES:                    {value: 0x06, writable: false, enumerable: true},
+        AV_PORTABLE_AUDIO:                {value: 0x07, writable: false, enumerable: true},
+        AV_CAR_AUDIO:                     {value: 0x08, writable: false, enumerable: true},
+        AV_SETTOP_BOX:                    {value: 0x09, writable: false, enumerable: true},
+        AV_HIFI:                          {value: 0x0A, writable: false, enumerable: true},
+        AV_VCR:                           {value: 0x0B, writable: false, enumerable: true},
+        AV_VIDEO_CAMERA:                  {value: 0x0C, writable: false, enumerable: true},
+        AV_CAMCORDER:                     {value: 0x0D, writable: false, enumerable: true},
+        AV_MONITOR:                       {value: 0x0E, writable: false, enumerable: true},
+        AV_DISPLAY_AND_LOUDSPEAKER:       {value: 0x0F, writable: false, enumerable: true},
+        AV_VIDEO_CONFERENCING:            {value: 0x10, writable: false, enumerable: true},
+        AV_GAMING_TOY:                    {value: 0x12, writable: false, enumerable: true},
+
+        PERIPHERAL_UNCATEGORIZED:         {value: 0x00, writable: false, enumerable: true},
+        PERIPHERAL_KEYBOARD:              {value: 0x10, writable: false, enumerable: true},
+        PERIPHERAL_POINTING_DEVICE:       {value: 0x20, writable: false, enumerable: true},
+        PERIPHERAL_KEYBOARD_AND_POINTING_DEVICE: {
+            value: 0x30,
+            writable: false,
+            enumerable: true
+        },
+        PERIPHERAL_JOYSTICK:              {value: 0x01, writable: false, enumerable: true},
+        PERIPHERAL_GAMEPAD:               {value: 0x02, writable: false, enumerable: true},
+        PERIPHERAL_REMOTE_CONTROL:        {value: 0x03, writable: false, enumerable: true},
+        PERIPHERAL_SENSING_DEVICE:        {value: 0x04, writable: false, enumerable: true},
+        PERIPHERAL_DEGITIZER_TABLET:      {value: 0x05, writable: false, enumerable: true},
+        PERIPHERAL_CARD_READER:           {value: 0x06, writable: false, enumerable: true},
+        PERIPHERAL_DIGITAL_PEN:           {value: 0x07, writable: false, enumerable: true},
+        PERIPHERAL_HANDHELD_SCANNER:      {value: 0x08, writable: false, enumerable: true},
+        PERIPHERAL_HANDHELD_INPUT_DEVICE: {value: 0x09, writable: false, enumerable: true},
+
+        IMAGING_UNCATEGORIZED:            {value: 0x00, writable: false, enumerable: true},
+        IMAGING_DISPLAY:                  {value: 0x04, writable: false, enumerable: true},
+        IMAGING_CAMERA:                   {value: 0x08, writable: false, enumerable: true},
+        IMAGING_SCANNER:                  {value: 0x10, writable: false, enumerable: true},
+        IMAGING_PRINTER:                  {value: 0x20, writable: false, enumerable: true},
+
+        WEARABLE_WRITST_WATCH:            {value: 0x01, writable: false, enumerable: true},
+        WEARABLE_PAGER:                   {value: 0x02, writable: false, enumerable: true},
+        WEARABLE_JACKET:                  {value: 0x03, writable: false, enumerable: true},
+        WEARABLE_HELMET:                  {value: 0x04, writable: false, enumerable: true},
+        WEARABLE_GLASSES:                 {value: 0x05, writable: false, enumerable: true},
+
+        TOY_ROBOT:                        {value: 0x01, writable: false, enumerable: true},
+        TOY_VEHICLE:                      {value: 0x02, writable: false, enumerable: true},
+        TOY_DOLL:                         {value: 0x03, writable: false, enumerable: true},
+        TOY_CONTROLLER:                   {value: 0x04, writable: false, enumerable: true},
+        TOY_GAME:                         {value: 0x05, writable: false, enumerable: true},
+
+        HEALTH_UNDEFINED:                 {value: 0x00, writable: false, enumerable: true},
+        HEALTH_BLOOD_PRESSURE_MONITOR:    {value: 0x01, writable: false, enumerable: true},
+        HEALTH_THERMOMETER:               {value: 0x02, writable: false, enumerable: true},
+        HEALTH_WEIGHING_SCALE:            {value: 0x03, writable: false, enumerable: true},
+        HEALTH_GLUCOSE_METER:             {value: 0x04, writable: false, enumerable: true},
+        HEALTH_PULSE_OXIMETER:            {value: 0x05, writable: false, enumerable: true},
+        HEALTH_PULSE_RATE_MONITOR:        {value: 0x06, writable: false, enumerable: true},
+        HEALTH_DATA_DISPLAY:              {value: 0x07, writable: false, enumerable: true},
+        HEALTH_STEP_COUNTER:              {value: 0x08, writable: false, enumerable: true},
+        HEALTH_BODY_COMPOSITION_ANALYZER: {value: 0x09, writable: false, enumerable: true},
+        HEALTH_PEAK_FLOW_MONITOR:         {value: 0x0A, writable: false, enumerable: true},
+        HEALTH_MEDICATION_MONITOR:        {value: 0x0B, writable: false, enumerable: true},
+        HEALTH_KNEE_PROSTHESIS:           {value: 0x0C, writable: false, enumerable: true},
+        HEALTH_ANKLE_PROSTHESIS:          {value: 0x0D, writable: false, enumerable: true}
+    });
+};
+
+// class BluetoothClassDeviceService ///////////////////////////////////////
+var BluetoothClassDeviceService = function() {
+    Object.defineProperties(this, {
+        LIMITED_DISCOVERABILITY: {value: 0x0001, writable: false, enumerable: true},
+        POSITIONING:             {value: 0x0008, writable: false, enumerable: true},
+        NETWORKING:              {value: 0x0010, writable: false, enumerable: true},
+        RENDERING:               {value: 0x0020, writable: false, enumerable: true},
+        CAPTURING:               {value: 0x0040, writable: false, enumerable: true},
+        OBJECT_TRANSFER:         {value: 0x0080, writable: false, enumerable: true},
+        AUDIO:                   {value: 0x0100, writable: false, enumerable: true},
+        TELEPHONY:               {value: 0x0200, writable: false, enumerable: true},
+        INFORMATION:             {value: 0x0400, writable: false, enumerable: true}
+    });
+};
+
+//class tizen.BluetoothLEServiceData ////////////////////////////////////////////////////
+tizen.BluetoothLEServiceData = function(d) {
+  AV.isConstructorCall(this, tizen.BluetoothLEServiceData);
+  var uuid_ = '';
+  var data_ = '';
+
+  Object.defineProperties(this, {
+    uuid: {
+      enumerable: true,
+      get: function() {
+        return uuid_;
+      },
+      set: function(v) {
+        uuid_ = Converter.toString(v);
+      }
+    },
+    data: {
+      enumerable: true,
+      get: function() {
+        return data_;
+      },
+      set: function(v) {
+        data_ = Converter.toString(v);
+      }
+    }
+  });
+
+  if (arguments.length >= 2) {  // public constructor
+    this.uuid = arguments[0];
+    this.data = arguments[1];
+  } else if (d && T.isObject(d)) {  // internal constructor
+    this.uuid = d.uuid;
+    this.data = d.data;
+  } else {
+    uuid_ = undefined;
+    data_ = undefined;
+  }
+};
+
+//class BluetoothLEAdvertiseData ////////////////////////////////////////////////////
+tizen.BluetoothLEAdvertiseData = function(dict) {
+  AV.isConstructorCall(this, tizen.BluetoothLEAdvertiseData);
+  var includeName_ = false;
+  var uuids_ = null;
+  var solicitationuuids_ = null;
+  var appearance_ = null;
+  var includeTxPowerLevel_ = false;
+  var serviceData_ = null;
+  var manufacturerData_ = null;
+
+  Object.defineProperties(this, {
+    includeName: {
+      enumerable: true,
+      get: function() {
+        return includeName_;
+      },
+      set: function(v) {
+        includeName_ = Converter.toBoolean(v, true);
+      }
+    },
+    uuids: {
+      enumerable: true,
+      get: function() {
+        return uuids_;
+      },
+      set: function(v) {
+        if (T.isNull(v)) {
+          uuids_ = v;
+        } else if (T.isArray(v)) {
+          for (var i = 0; i < v.length; ++i) {
+            if (!T.isString(v[i])) {
+              v[i] = Converter.toString(v[i]);
+            }
+          }
+          uuids_ = v;
+        }
+      }
+    },
+    solicitationuuids: {
+      enumerable: true,
+      get: function() {
+        return solicitationuuids_;
+      },
+      set: function(v) {
+        if (T.isNull(v)) {
+          solicitationuuids_ = v;
+        } else if (T.isArray(v)) {
+          for (var i = 0; i < v.length; ++i) {
+            if (!T.isString(v[i])) {
+              v[i] = Converter.toString(v[i]);
+            }
+          }
+          solicitationuuids_ = v;
+        }
+      }
+    },
+    appearance: {
+      enumerable: true,
+      get: function() {
+        return appearance_;
+      },
+      set: function(v) {
+        appearance_ = Converter.toUnsignedLong(v, true);
+      }
+    },
+    includeTxPowerLevel: {
+      enumerable: true,
+      get: function() {
+        return includeTxPowerLevel_;
+      },
+      set: function(v) {
+        includeTxPowerLevel_ = Converter.toBoolean(v, true);
+      }
+    },
+    serviceData: {
+      enumerable: true,
+      get: function() {
+        return serviceData_;
+      },
+      set: function(v) {
+        if (T.isNull(v) || (v instanceof tizen.BluetoothLEServiceData)) {
+          serviceData_ = v;
+        }
+      }
+    },
+    manufacturerData: {
+      enumerable: true,
+      get: function() {
+        return manufacturerData_;
+      },
+      set: function(v) {
+        if (T.isNull(v) || (v instanceof tizen.BluetoothLEManufacturerData)) {
+          manufacturerData_ = v;
+        }
+      }
+    }
+  });
+
+  if (T.isObject(dict)) {
+    var o = {};
+
+    // includeName
+    if (T.isNull(dict.includeName) || T.isBoolean(dict.includeName)) {
+      o.includeName = dict.includeName;
+    } else if (!T.isUndefined(dict.includeName)) {
+      return;
+    }
+
+    // uuids
+    if (T.isNull(dict.uuids)) {
+      o.uuids = dict.uuids;
+    } else if (T.isArray(dict.uuids)) {
+      for (var i = 0; i < dict.uuids.length; ++i) {
+        if (!T.isString(dict.uuids[i])) {
+          return;
+        }
+      }
+      o.uuids = dict.uuids;
+    } else if (!T.isUndefined(dict.uuids)) {
+      return;
+    }
+
+    // solicitationuuids
+    if (T.isNull(dict.solicitationuuids)) {
+      o.solicitationuuids = dict.solicitationuuids;
+    } else if (T.isArray(dict.solicitationuuids)) {
+      for (var i = 0; i < dict.solicitationuuids.length; ++i) {
+        if (!T.isString(dict.solicitationuuids[i])) {
+          return;
+        }
+      }
+      o.solicitationuuids = dict.solicitationuuids;
+    } else if (!T.isUndefined(dict.solicitationuuids)) {
+      return;
+    }
+
+    // appearance
+    if (T.isNull(dict.appearance) || T.isNumber(dict.appearance)) {
+      o.appearance = dict.appearance;
+    } else if (!T.isUndefined(dict.appearance)) {
+      return;
+    }
+
+    // includeTxPowerLevel
+    if (T.isNull(dict.includeTxPowerLevel) || T.isBoolean(dict.includeTxPowerLevel)) {
+      o.includeTxPowerLevel = dict.includeTxPowerLevel;
+    } else if (!T.isUndefined(dict.includeTxPowerLevel)) {
+      return;
+    }
+
+    // serviceData
+    if (T.isNull(dict.serviceData) || dict.serviceData instanceof tizen.BluetoothLEServiceData) {
+      o.serviceData = dict.serviceData;
+    } else if (!T.isUndefined(dict.serviceData)) {
+      return;
+    }
+
+    // manufacturerData
+    if (T.isNull(dict.manufacturerData) ||
+        (dict.manufacturerData instanceof tizen.BluetoothLEManufacturerData)) {
+      o.manufacturerData = dict.manufacturerData;
+    } else if (!T.isUndefined(dict.manufacturerData)) {
+      return;
+    }
+
+    for (var prop in o) {
+      if (o.hasOwnProperty(prop) && this.hasOwnProperty(prop)) {
+        this[prop] = o[prop];
+      }
+    }
+  }
+};
+
+//class tizen.BluetoothLEManufacturerData ////////////////////////////////////////////////////
+tizen.BluetoothLEManufacturerData = function(d) {
+  AV.isConstructorCall(this, tizen.BluetoothLEManufacturerData);
+  var id_ = '';
+  var data_ = '';
+
+  Object.defineProperties(this, {
+    id: {
+      enumerable: true,
+      get: function() {
+        return id_;
+      },
+      set: function(v) {
+        id_ = Converter.toString(v);
+      }
+    },
+    data: {
+      enumerable: true,
+      get: function() {
+        return data_;
+      },
+      set: function(v) {
+        data_ = Converter.toString(v);
+      }
+    }
+  });
+
+  if (arguments.length >= 2) {  // public constructor
+    this.id = arguments[0];
+    this.data = arguments[1];
+  } else if (d && T.isObject(d)) {  // internal constructor
+    this.id = d.id;
+    this.data = d.data;
+  } else {
+    id_ = undefined;
+    data_ = undefined;
+  }
+};
+
+// class BluetoothClass ////////////////////////////////////////////////////
+var BluetoothClass = function(data) {
+    var services = [];
+    if (data) {
+        services = data.services;
+    }
+
+    Object.defineProperties(this, {
+        major : {value: data.major, writable: false, enumerable: true},
+        minor : {value: data.minor, writable: false, enumerable: true},
+        services : {
+            enumerable: true,
+            set : function(){},
+            get : function(){ return services.slice(); }
+        }
+    });
+};
+
+BluetoothClass.prototype.hasService = function() {
+    console.log('Entered BluetoothClass.hasService()');
+    xwalk.utils.checkPrivilegeAccess4Ver("2.4", Privilege.BLUETOOTH, Privilege.BLUETOOTH_GAP);
+
+    var args = AV.validateMethod(arguments, [
+        {
+            name : 'service',
+            type : AV.Types.UNSIGNED_LONG
+        }
+    ]);
+
+    var size = this.services.length;
+    for (var i = 0; i < size; i++) {
+        if (this.services[i] === args.service) {
+            return true;
+        }
+    }
+    return false;
+};
+
+// class BluetoothSocket ////////////////////////////////////////////////////
+var _BLUETOOTH_SOCKET_STATE_CLOSED = 'CLOSED';
+
+function BluetoothSocketListeners() {
+    var that = this;
+    this.socketCallback = function (data) {
+        var event = data;
+        var socket = that.sockets[event.id];
+
+        if (socket) {
+            if ('onclose' === event.event) {
+                // no more events
+                that.removeListener(event.id);
+                // change state
+                Object.defineProperty(socket, 'state', {value : _BLUETOOTH_SOCKET_STATE_CLOSED});
+            }
+
+            var callback = socket[event.event];
+            if (T.isFunction(callback)) {
+                callback();
+            }
+        } else {
+            console.log('Received event for an unknown socket: ' + event.id);
+        }
+    };
+}
+
+BluetoothSocketListeners.prototype.sockets = {};
+
+BluetoothSocketListeners.prototype.addListener = function(socket) {
+    if (T.isEmptyObject(this.sockets)) {
+        native.addListener('BLUETOOTH_SOCKET_STATE_CHANGED', this.socketCallback);
+    }
+
+    this.sockets[socket._id] = socket;
+};
+
+BluetoothSocketListeners.prototype.removeListener = function(id) {
+    delete this.sockets[id];
+
+    if (T.isEmptyObject(this.sockets)) {
+        native.removeListener('BLUETOOTH_SOCKET_STATE_CHANGED', this.socketCallback);
+    }
+};
+
+var _bluetoothSocketListeners = new BluetoothSocketListeners();
+
+var BluetoothSocket = function(data) {
+    Object.defineProperties(this, {
+        uuid : {value: data.uuid, writable: false, enumerable: true},
+        state : {value: data.state, writable: false, enumerable: true, configurable: true},
+        peer : {value: new BluetoothDevice(data.peer), writable: false, enumerable: true},
+        onmessage : {value: null, writable: true, enumerable: true},
+        onclose : {value: null, writable: true, enumerable: true},
+        _id : {value: data.id, writable: false, enumerable: false}
+    });
+
+    _bluetoothSocketListeners.addListener(this);
+};
+
+BluetoothSocket.prototype.writeData = function() {
+    console.log('Entered BluetoothSocket.writeData()');
+    xwalk.utils.checkPrivilegeAccess4Ver("2.4", Privilege.BLUETOOTH, Privilege.BLUETOOTH_SPP);
+
+    var args = AV.validateMethod(arguments, [
+        {
+            name : 'data',
+            type : AV.Types.ARRAY,
+            values : AV.Types.BYTE
+        }
+    ]);
+
+    var callArgs = {
+        id : this._id,
+        data : args.data
+    };
+
+    var result = native.callSync('BluetoothSocket_writeData', callArgs);
+
+    if (native.isFailure(result)) {
+        throw native.getErrorObject(result);
+    } else {
+        return native.getResultObject(result);
+    }
+};
+
+BluetoothSocket.prototype.readData = function() {
+    console.log('Entered BluetoothSocket.readData()');
+    xwalk.utils.checkPrivilegeAccess4Ver("2.4", Privilege.BLUETOOTH, Privilege.BLUETOOTH_SPP);
+
+    var callArgs = {
+        id : this._id
+    };
+
+    var result = native.callSync('BluetoothSocket_readData', callArgs);
+
+    if (native.isFailure(result)) {
+        throw native.getErrorObject(result);
+    } else {
+        return native.getResultObject(result);
+    }
+};
+
+BluetoothSocket.prototype.close = function() {
+    console.log('Entered BluetoothSocket.close()');
+    xwalk.utils.checkPrivilegeAccess4Ver("2.4", Privilege.BLUETOOTH, Privilege.BLUETOOTH_SPP);
+
+    if (_BLUETOOTH_SOCKET_STATE_CLOSED !== this.state) {
+        var callArgs = {
+            id : this._id
+        };
+
+        var result = native.callSync('BluetoothSocket_close', callArgs);
+
+        if (native.isFailure(result)) {
+            throw native.getErrorObject(result);
+        }
+
+        // change state
+        Object.defineProperty(this, 'state', { value : _BLUETOOTH_SOCKET_STATE_CLOSED });
+    }
+};
+
+//class BluetoothLEDevice ////////////////////////////////////////////////////
+var BluetoothLEDevice = function(data) {
+    var address = "", name = null, txpowerlevel = null, appearance = null, uuids = null,
+        solicitationuuids = null, serviceData = null, manufacturerData = null;
+
+    if (data) {
+      address = data.address;
+      name = data.name || null;
+      txpowerlevel = data.txpowerlevel || null;
+      appearance = data.appearance || null;
+      uuids = data.uuids || null;
+      solicitationuuids = data.solicitationuuids || null;
+      if (data.serviceData) {
+        data.serviceData.forEach(function(d) {
+            serviceData.push(new tizen.BluetoothLEServiceData(d));
+        });
+      }
+      if (data.manufacturerData) {
+        manufacturerData = new tizen.BluetoothLEManufacturerData(data.manufacturerData);
+      }
+    }
+
+    Object.defineProperties(this, {
+        address : {value: address, writable: false, enumerable: true},
+        name : {value: name, writable: false, enumerable: true},
+        txpowerlevel : {value: txpowerlevel, writable: false, enumerable: true},
+        appearance : {value: appearance, writable: false, enumerable: true},
+        uuids : {
+            enumerable: true,
+            set : function(){},
+            get : function(){
+              var service_uuids = uuids ? uuids.slice() : null;
+              return service_uuids;
+            }
+        },
+        solicitationuuids : {
+            enumerable: true,
+            set : function(){},
+            get : function(){ return solicitationuuids ? solicitationuuids.slice() : null; }
+        },
+        serviceData : {
+            enumerable: true,
+            set : function(){},
+            get : function(){ return serviceData ? serviceData.slice() : null; }
+        },
+        manufacturerData : {
+            value: manufacturerData,
+            writable: false,
+            enumerable: true}
+    });
+};
+
+BluetoothLEDevice.prototype.connect = function() {
+    console.log('Entered BluetoothLEDevice.connect()');
+
+    xwalk.utils.checkPrivilegeAccess4Ver("2.4", Privilege.BLUETOOTH, Privilege.BLUETOOTH_ADMIN);
+    var args = AV.validateMethod(arguments, [
+    {
+        name : 'successCallback',
+        type : AV.Types.FUNCTION,
+        optional : true,
+        nullable : true
+    },
+    {
+        name : 'errorCallback',
+            type : AV.Types.FUNCTION,
+            optional : true,
+            nullable : true
+        }
+    ]);
+
+    var callback = function(result) {
+        if (native.isFailure(result)) {
+            native.callIfPossible(args.errorCallback, native.getErrorObject(result));
+        } else {
+            native.callIfPossible(args.successCallback);
+        }
+    };
+
+    native.call('BluetoothLEDevice_connect', {address : this.address}, callback);
+};
+
+BluetoothLEDevice.prototype.disconnect = function() {
+    console.log('Entered BluetoothLEDevice.disconnect()');
+
+    xwalk.utils.checkPrivilegeAccess4Ver("2.4", Privilege.BLUETOOTH, Privilege.BLUETOOTH_ADMIN);
+    var args = AV.validateMethod(arguments, [
+    {
+        name : 'successCallback',
+        type : AV.Types.FUNCTION,
+        optional : true,
+        nullable : true
+    },
+    {
+        name : 'errorCallback',
+            type : AV.Types.FUNCTION,
+            optional : true,
+            nullable : true
+        }
+    ]);
+    var callback = function(result) {
+        if (native.isFailure(result)) {
+            native.callIfPossible(args.errorCallback, native.getErrorObject(result));
+        } else {
+            native.callIfPossible(args.successCallback);
+        }
+    };
+
+    var result = native.call('BluetoothLEDevice_disconnect', {address : this.address}, callback);
+    if (native.isFailure(result)) {
+        throw native.getErrorObject(result);
+    }
+};
+
+BluetoothLEDevice.prototype.getService = function() {
+    console.log('Entered BluetoothLEDevice.getService()');
+
+    xwalk.utils.checkPrivilegeAccess4Ver("2.4", Privilege.BLUETOOTH, Privilege.BLUETOOTH_ADMIN);
+
+    var args = AV.validateMethod(arguments, [
+        {
+            name: 'uuid',
+            type: AV.Types.STRING
+        }
+    ]);
+
+    var callArgs = {
+        uuid : args.uuid,
+        address : this.address
+    };
+
+    var result = native.callSync('BluetoothLEDevice_getService', callArgs);
+
+    if (native.isFailure(result)) {
+        throw native.getErrorObject(result);
+    } else {
+        return new BluetoothGATTService(native.getResultObject(result));
+    }
+};
+
+BluetoothLEDevice.prototype.addConnectStateChangeListener = function() {
+    console.log('Entered BluetoothLEDevice.addConnectStateChangeListener()');
+
+    var args = AV.validateMethod(arguments, [
+        {
+            name: 'listener',
+            type: AV.Types.LISTENER,
+            values: ['onconnected', 'ondisconnected']
+        }
+    ]);
+
+    var that = this;
+
+    var func = function(event) {
+        if (event.address === that.address && args.listener[event.action]) {
+            args.listener[event.action](that);
+        }
+    }
+
+    var watchId = _bleConnectChangeListener.addListener(func);
+
+    return watchId;
+};
+
+BluetoothLEDevice.prototype.removeConnectStateChangeListener = function() {
+    console.log('Entered BluetoothLEDevice.removeConnectStateChangeListener()');
+
+    var args = AV.validateMethod(arguments, [
+        {
+            name: 'watchID',
+            type: AV.Types.LONG
+        }
+    ]);
+
+    _bleConnectChangeListener.removeListener(args.watchID);
+};
+
+// class BluetoothDevice ////////////////////////////////////////////////////
+var BluetoothDevice = function(data) {
+    var self = this;
+    function _getter(field) {
+        var callArgs = {};
+
+        callArgs.address = self.address;
+        callArgs.field = field;
+
+        var result = native.callSync('BluetoothDevice_getBoolValue', callArgs);
+
+        if (native.isFailure(result)) {
+            return false;
+        } else {
+            return native.getResultObject(result);
+        }
+    }
+
+    function isBondedGetter() {
+        return _getter('isBonded');
+    }
+
+    function isTrustedGetter() {
+        return _getter('isTrusted');
+    }
+
+    function isConnectedGetter() {
+        return _getter('isConnected');
+    }
+
+    var uuids = [];
+    if (data) {
+        uuids = data.uuids;
+    }
+
+    Object.defineProperties(this, {
+        name : {value: data.name, writable: false, enumerable: true},
+        address : {value: data.address, writable: false, enumerable: true},
+        deviceClass : {value: new BluetoothClass(data.deviceClass),
+            writable: false,
+            enumerable: true},
+        isBonded : {
+            enumerable: true,
+            set : function(){},
+            get : isBondedGetter
+        },
+        isTrusted : {
+            enumerable: true,
+            set : function(){},
+            get : isTrustedGetter
+        },
+        isConnected : {
+            enumerable: true,
+            set : function(){},
+            get : isConnectedGetter
+        },
+        uuids : {
+            enumerable: true,
+            set : function(){},
+            get : function(){ return uuids.slice(); }
+        }
+    });
+};
+
+BluetoothDevice.prototype.connectToServiceByUUID = function() {
+    console.log('Entered BluetoothDevice.connectToServiceByUUID()');
+    xwalk.utils.checkPrivilegeAccess4Ver("2.4", Privilege.BLUETOOTH, Privilege.BLUETOOTH_SPP);
+
+    var args = AV.validateMethod(arguments, [
+        {
+            name : 'uuid',
+            type : AV.Types.STRING
+        },
+        {
+            name : 'successCallback',
+            type : AV.Types.FUNCTION
+        },
+        {
+            name : 'errorCallback',
+            type : AV.Types.FUNCTION,
+            optional : true,
+            nullable : true
+        }
+    ]);
+
+    var callArgs = {
+        address : this.address,
+        uuid : args.uuid
+    };
+    var callback = function(result) {
+        if (native.isFailure(result)) {
+            native.callIfPossible(args.errorCallback, native.getErrorObject(result));
+        } else {
+            args.successCallback(new BluetoothSocket(native.getResultObject(result)));
+        }
+    };
+
+    // native.call does not inform if call results in failure
+    // TODO: what to do in this case?
+    native.call('BluetoothDevice_connectToServiceByUUID', callArgs, callback);
+};
+
+// class BluetoothServiceHandler ////////////////////////////////////////////////////
+function BluetoothServiceListeners() {
+    var that = this;
+    this.serviceCallback = function (data) {
+        var e = data;
+        var service = that.services[e.uuid];
+        var result = new BluetoothSocket(e);
+
+        if (service) {
+            console.log(service);
+            service.onconnect(result);
+        }
+    };
+}
+
+BluetoothServiceListeners.prototype.services = {};
+
+BluetoothServiceListeners.prototype.addListener = function(service) {
+    if (T.isEmptyObject(this.services)) {
+        native.addListener('BLUETOOTH_SERVICE_ONCONNECT', this.serviceCallback);
+    }
+
+    this.services[service.uuid] = service;
+};
+
+BluetoothServiceListeners.prototype.removeListener = function(uuid) {
+    delete this.services[uuid];
+
+    if (T.isEmptyObject(this.services)) {
+        native.removeListener('BLUETOOTH_SERVICE_ONCONNECT', this.serviceCallback);
+    }
+};
+
+var _bluetoothServiceListeners = new BluetoothServiceListeners();
+
+var BluetoothServiceHandler = function(data) {
+    function isConnectedGetter() {
+        var callArgs = {
+            uuid : this.uuid
+        };
+
+        var result = native.callSync('BluetoothAdapter_isServiceConnected', { uuid : this.uuid });
+
+        if (native.isFailure(result)) {
+            return false;
+        } else {
+            return native.getResultObject(result);
+        }
+    }
+
+    Object.defineProperties(this, {
+        uuid : {value: data.uuid, writable: false, enumerable: true},
+        name : {value: data.name, writable: false, enumerable: true},
+        isConnected : {
+            enumerable: true,
+            set : function(){},
+            get : isConnectedGetter
+        },
+        onconnect : {value: null, writable: true, enumerable: true}
+    });
+
+    _bluetoothServiceListeners.addListener(this);
+};
+
+BluetoothServiceHandler.prototype.unregister = function() {
+    console.log('Entered BluetoothServiceHandler.unregister()');
+    xwalk.utils.checkPrivilegeAccess4Ver("2.4", Privilege.BLUETOOTH, Privilege.BLUETOOTH_SPP);
+
+    var args = AV.validateMethod(arguments, [
+        {
+            name : 'successCallback',
+            type : AV.Types.FUNCTION,
+            optional : true,
+            nullable : true
+        },
+        {
+            name : 'errorCallback',
+            type : AV.Types.FUNCTION,
+            optional : true,
+            nullable : true
+        }
+    ]);
+
+    var callArgs = {
+        uuid : this.uuid
+    };
+
+    var callback = function(result) {
+        if (native.isFailure(result)) {
+            native.callIfPossible(args.errorCallback, native.getErrorObject(result));
+        } else {
+            native.callIfPossible(args.successCallback);
+        }
+    };
+
+    // native.call does not inform if call results in failure
+    // TODO: what to do in this case?
+    native.call('BluetoothServiceHandler_unregister', callArgs, callback);
+
+    _bluetoothServiceListeners.removeListener(this.uuid);
+};
+
+// class BluetoothHealthApplication ////////////////////////////////////////////////////
+function BluetoothHealthApplicationListeners() {
+    var that = this;
+    this.appCallback = function (data) {
+        var event = data;
+        var app = that.apps[event.id];
+
+        if (app) {
+            var callback = app[event.event];
+            if (T.isFunction(callback)) {
+                var param;
+                switch (event.event) {
+                case 'onconnect':
+                    param = new BluetoothHealthChannel(native.getResultObject(event));
+                    break;
+
+                default:
+                    console.log('Unknown event: ' + event.event);
+                    break;
+                }
+                callback(param);
+            }
+        } else {
+            console.log('Received event for an unknown application: ' + event.id);
+        }
+    };
+}
+
+BluetoothHealthApplicationListeners.prototype.apps = {};
+
+BluetoothHealthApplicationListeners.prototype.addListener = function(app) {
+    if (T.isEmptyObject(this.apps)) {
+        native.addListener('BLUETOOTH_HEALTH_APPLICATION_CHANGED', this.appCallback);
+    }
+
+    this.apps[app._id] = app;
+};
+
+BluetoothHealthApplicationListeners.prototype.removeListener = function(id) {
+    delete this.apps[id];
+
+    if (T.isEmptyObject(this.apps)) {
+        native.removeListener('BLUETOOTH_HEALTH_APPLICATION_CHANGED', this.appCallback);
+    }
+};
+
+var _bluetoothHealthApplicationListeners = new BluetoothHealthApplicationListeners();
+
+var BluetoothHealthApplication = function(data) {
+    Object.defineProperties(this, {
+        dataType : {value: data.dataType, writable: false, enumerable: true},
+        name : {value: data.name, writable: false, enumerable: true},
+        onconnect : {value: null, writable: true, enumerable: true},
+        _id : {value: data._id, writable: false, enumerable: false}
+    });
+
+    _bluetoothHealthApplicationListeners.addListener(this);
+};
+
+BluetoothHealthApplication.prototype.unregister = function() {
+    console.log('Entered BluetoothHealthApplication.unregister()');
+    xwalk.utils.checkPrivilegeAccess4Ver("2.4", Privilege.BLUETOOTH, Privilege.BLUETOOTH_HEALTH);
+
+    var args = AV.validateMethod(arguments, [
+        {
+            name : 'successCallback',
+            type : AV.Types.FUNCTION,
+            optional : true,
+            nullable : true
+        },
+        {
+            name : 'errorCallback',
+            type : AV.Types.FUNCTION,
+            optional : true,
+            nullable : true
+        }
+    ]);
+
+    var callArgs = {id : this._id};
+
+    var callback = function(result) {
+        if (native.isFailure(result)) {
+            native.callIfPossible(args.errorCallback, native.getErrorObject(result));
+        } else {
+            native.callIfPossible(args.successCallback);
+        }
+    };
+
+    // native.call does not inform if call results in failure
+    // TODO: what to do in this case?
+    native.call('BluetoothHealthApplication_unregister', callArgs, callback);
+
+    _bluetoothHealthApplicationListeners.removeListener(this._id);
+};
+
+// class BluetoothProfileHandler ////////////////////////////////////////////////////
+var _BluetoothProfileType = {
+    HEALTH : 'HEALTH'
+};
+
+var BluetoothProfileHandler = function(data) {
+    if (data) {
+        Object.defineProperties(this, {
+            profileType : {value: data.profileType, writable: false, enumerable: true}
+        });
+    }
+};
+
+// class BluetoothHealthProfileHandler ////////////////////////////////////////////////////
+var BluetoothHealthProfileHandler = function(data) {
+    BluetoothProfileHandler.call(this, data);
+};
+
+BluetoothHealthProfileHandler.prototype = new BluetoothProfileHandler();
+
+BluetoothHealthProfileHandler.prototype.constructor = BluetoothProfileHandler;
+
+BluetoothHealthProfileHandler.prototype.registerSinkApplication = function() {
+    console.log('Entered BluetoothHealthProfileHandler.registerSinkApplication()');
+    xwalk.utils.checkPrivilegeAccess4Ver("2.4", Privilege.BLUETOOTH, Privilege.BLUETOOTH_HEALTH);
+
+    var args = AV.validateMethod(arguments, [
+        {
+            name : 'dataType',
+            type : AV.Types.LONG // there's no short type
+        },
+        {
+            name : 'name',
+            type : AV.Types.STRING
+        },
+        {
+            name : 'successCallback',
+            type : AV.Types.FUNCTION
+        },
+        {
+            name : 'errorCallback',
+            type : AV.Types.FUNCTION,
+            optional : true,
+            nullable : true
+        }
+    ]);
+
+    var callArgs = {
+        dataType : args.dataType,
+        name : args.name
+    };
+
+    var callback = function(result) {
+        if (native.isFailure(result)) {
+            native.callIfPossible(args.errorCallback, native.getErrorObject(result));
+        } else {
+            args.successCallback(new BluetoothHealthApplication(native.getResultObject(result)));
+        }
+    };
+
+    // native.call does not inform if call results in failure
+    // TODO: what to do in this case?
+    native.call('BluetoothHealthProfileHandler_registerSinkApp', callArgs, callback);
+};
+
+BluetoothHealthProfileHandler.prototype.connectToSource = function() {
+    console.log('Entered BluetoothHealthProfileHandler.connectToSource()');
+    xwalk.utils.checkPrivilegeAccess4Ver("2.4", Privilege.BLUETOOTH, Privilege.BLUETOOTH_HEALTH);
+
+    var args = AV.validateMethod(arguments, [
+        {
+            name : 'peer',
+            type : AV.Types.PLATFORM_OBJECT,
+            values : BluetoothDevice
+        },
+        {
+            name : 'application',
+            type : AV.Types.PLATFORM_OBJECT,
+            values : BluetoothHealthApplication
+        },
+        {
+            name : 'successCallback',
+            type : AV.Types.FUNCTION
+        },
+        {
+            name : 'errorCallback',
+            type : AV.Types.FUNCTION,
+            optional : true,
+            nullable : true
+        }
+    ]);
+
+    var callArgs = {
+        address : args.peer.address,
+        appId : args.application._id
+    };
+
+    var callback = function(result) {
+        if (native.isFailure(result)) {
+            native.callIfPossible(args.errorCallback, native.getErrorObject(result));
+        } else {
+            var channel = native.getResultObject(result);
+            channel.peer = args.peer;
+            channel.appId = args.application._id;
+            args.successCallback(new BluetoothHealthChannel(channel));
+        }
+    };
+
+    // native.call does not inform if call results in failure
+    // TODO: what to do in this case?
+    native.call('BluetoothHealthProfileHandler_connectToSource', callArgs, callback);
+};
+
+// class BluetoothHealthChannel ////////////////////////////////////////////////////
+var BluetoothHealthChannel = function(data) {
+    Object.defineProperties(this, {
+        peer : {value: data.peer, writable: false, enumerable: true},
+        channelType : {value: data.channelType, writable: false, enumerable: true},
+        application : {
+            value: _bluetoothHealthApplicationListeners.apps[data.appId],
+            writable: false,
+            enumerable: true
+        },
+        isConnected : {
+            value: data.isConnected,
+            writable: false,
+            enumerable: true,
+            configurable: true},
+        _id : {value: data._id, writable: false, enumerable: false}
+    });
+};
+
+BluetoothHealthChannel.prototype.close = function() {
+    console.log('Entered BluetoothHealthChannel.close()');
+    xwalk.utils.checkPrivilegeAccess4Ver("2.4", Privilege.BLUETOOTH, Privilege.BLUETOOTH_HEALTH);
+
+    if (this.isConnected) {
+        var callArgs = {
+            channel : this._id,
+            address : this.peer.address
+        };
+
+        var result = native.callSync('BluetoothHealthChannel_close', callArgs);
+
+        if (native.isFailure(result)) {
+            throw native.getErrorObject(result);
+        }
+
+        Object.defineProperty(this, 'isConnected', { value : false });
+    }
+};
+
+BluetoothHealthChannel.prototype.sendData = function() {
+    console.log('Entered BluetoothHealthChannel.sendData()');
+    xwalk.utils.checkPrivilegeAccess4Ver("2.4", Privilege.BLUETOOTH, Privilege.BLUETOOTH_HEALTH);
+
+    var args = AV.validateMethod(arguments, [
+        {
+            name : 'data',
+            type : AV.Types.ARRAY,
+            values : AV.Types.BYTE
+        }
+    ]);
+
+    var callArgs = {
+        channel : this._id,
+        data : args.data
+    };
+
+    var result = native.callSync('BluetoothHealthChannel_sendData', callArgs);
+
+    if (native.isFailure(result)) {
+        throw native.getErrorObject(result);
+    } else {
+        return native.getResultObject(result);
+    }
+};
+
+var _healthListeners = {};
+
+function _BluetoothHealthChannelChangeCallback(event) {
+    var e = event;
+    var callback = _healthListeners[e.id];
+    var d;
+
+    switch (e.event) {
+    case 'onmessage':
+        d = e.data;
+        break;
+
+    case 'onclose':
+        break;
+
+    default:
+        console.log('Unknown mode: ' + e.event);
+        return;
+    }
+
+    if (callback[e.event]) {
+        callback[e.event](d);
+    }
+}
+
+BluetoothHealthChannel.prototype.setListener = function() {
+    console.log('Entered BluetoothHealthChannel.setListener()');
+    xwalk.utils.checkPrivilegeAccess4Ver("2.4", Privilege.BLUETOOTH, Privilege.BLUETOOTH_HEALTH);
+
+    var args = AV.validateMethod(arguments, [
+        {
+            name : 'changeCallback',
+            type : AV.Types.LISTENER,
+            values : ['onmessage', 'onclose']
+        }
+    ]);
+
+    if (T.isEmptyObject(_healthListeners)) {
+        native.addListener('BluetoothHealthChannelChangeCallback',
+                _BluetoothHealthChannelChangeCallback);
+    }
+    _healthListeners[this._id] = args.changeCallback;
+};
+
+BluetoothHealthChannel.prototype.unsetListener  = function() {
+    console.log('Entered BluetoothHealthChannel.unsetListener ()');
+    xwalk.utils.checkPrivilegeAccess4Ver("2.4", Privilege.BLUETOOTH, Privilege.BLUETOOTH_HEALTH);
+
+    delete _healthListeners[this._id];
+
+    if (T.isEmptyObject(_healthListeners)) {
+        native.removeListener('BluetoothHealthChannelChangeCallback',
+                _BluetoothHealthChannelChangeCallback);
+    }
+};
+
+
+/**
+ * Creates a manager for specified listener event.
+ *
+ * @param {string} name - name of the listener this manager handles
+ * @param {function} callback - function to be invoked when event specified by the name fires.
+ *                              This function should return false if the callback doesn't want
+ *                              to handle the event anymore, true otherwise.
+ *                              This function should have following signature:
+ *                              bool callback(event, successCallback, errorCallback);
+ *
+ * @return {object} object which allows to add or remove callbacks for specified listener
+ */
+function _singleListenerBuilder(name, callback) {
+  var listenerName = name;
+  var successCallback;
+  var errorCallback;
+  var callbackFunction = callback;
+  var listenerRegistered = false;
+
+  function innerCallback(event) {
+    if (!callbackFunction(event, successCallback, errorCallback)) {
+      removeListener();
+    }
+  }
+
+  function addListener(s, e) {
+    successCallback = s;
+    errorCallback = e;
+
+    if (!listenerRegistered) {
+      native.addListener(listenerName, innerCallback);
+      listenerRegistered = true;
+    }
+  }
+
+  function removeListener() {
+    if (listenerRegistered) {
+      native.removeListener(listenerName, innerCallback);
+      listenerRegistered = false;
+    }
+
+    successCallback = undefined;
+    errorCallback = undefined;
+  }
+
+  return {
+    addListener: addListener,
+    removeListener: removeListener
+  };
+}
+
+var _bleScanListener = _singleListenerBuilder('BluetoothLEScanCallback',
+    function(event, successCallback, errorCallback) {
+
+  var d;
+  var ret = true;
+
+  switch (event.action) {
+    case 'onsuccess':
+      d = new BluetoothLEDevice(event.data);
+      break;
+
+    case 'onerror':
+      if (errorCallback) {
+        errorCallback(native.getErrorObject(event));
+      }
+      return ret;
+
+    default:
+      console.log('Unknown mode: ' + event.action);
+      return ret;
+  }
+  if (successCallback) {
+    successCallback(d);
+  }
+
+  return ret;
+});
+
+var _bleAdvertiseListener = _singleListenerBuilder('BluetoothLEAdvertiseCallback',
+    function(event, successCallback, errorCallback) {
+  var d;
+  var ret = true;
+
+  switch (event.action) {
+    case 'onstate':
+      if (successCallback) {
+        successCallback(native.getResultObject(event));
+      }
+      return ret;
+
+    case 'onerror':
+      if (errorCallback) {
+        errorCallback(native.getErrorObject(event));
+      }
+      return ret;
+
+    default:
+      console.log('Unknown mode: ' + event.action);
+      return ret;
+  }
+});
+
+//class BluetoothLEAdapter ////////////////////////////////////////////////////
+var BluetoothLEAdapter = function() {
+};
+
+BluetoothLEAdapter.prototype.startScan = function() {
+  console.log('Entered BluetoothLEAdapter.startScan()');
+
+  xwalk.utils.checkPrivilegeAccess4Ver("2.4", Privilege.BLUETOOTH, Privilege.BLUETOOTH_ADMIN);
+
+  var args = AV.validateMethod(arguments, [{
+    name: 'successCallback',
+    type: AV.Types.FUNCTION
+  }, {
+    name: 'errorCallback',
+    type: AV.Types.FUNCTION,
+    optional: true,
+    nullable: true
+  }]);
+
+  var result = native.callSync('BluetoothLEAdapter_startScan', {});
+
+  if (native.isFailure(result)) {
+    throw native.getErrorObject(result);
+  }
+
+  _bleScanListener.addListener(args.successCallback, args.errorCallback);
+};
+
+BluetoothLEAdapter.prototype.stopScan = function() {
+  console.log('Entered BluetoothLEAdapter.stopScan()');
+
+  xwalk.utils.checkPrivilegeAccess4Ver("2.4", Privilege.BLUETOOTH, Privilege.BLUETOOTH_ADMIN);
+
+  _bleScanListener.removeListener();
+
+  var result = native.callSync('BluetoothLEAdapter_stopScan', {});
+
+  if (native.isFailure(result)) {
+    throw native.getErrorObject(result);
+  }
+};
+
+var _BluetoothAdvertisePacketType = {
+  ADVERTISE: 'ADVERTISE',
+  SCAN_RESPONSE: 'SCAN_RESPONSE'
+};
+
+var _BluetoothAdvertisingMode = {
+  BALANCED: 'BALANCED',
+  LOW_LATENCY: 'LOW_LATENCY',
+  LOW_ENERGY: 'LOW_ENERGY'
+};
+
+BluetoothLEAdapter.prototype.startAdvertise = function() {
+  console.log('Entered BluetoothLEAdapter.startAdvertise()');
+
+  xwalk.utils.checkPrivilegeAccess4Ver("2.4", Privilege.BLUETOOTH, Privilege.BLUETOOTH_ADMIN);
+
+  var args = AV.validateMethod(arguments, [{
+    name: 'advertiseData',
+    type: AV.Types.PLATFORM_OBJECT,
+    values: tizen.BluetoothLEAdvertiseData
+  }, {
+    name: 'packetType',
+    type: AV.Types.ENUM,
+    values: T.getValues(_BluetoothAdvertisePacketType)
+  }, {
+    name: 'successCallback',
+    type: AV.Types.FUNCTION
+  }, {
+    name: 'errorCallback',
+    type: AV.Types.FUNCTION,
+    optional: true,
+    nullable: true
+  }, {
+    name: 'mode',
+    type: AV.Types.ENUM,
+    values: T.getValues(_BluetoothAdvertisingMode),
+    optional: true,
+    nullable: true
+  }, {
+    name: 'connectable',
+    type: AV.Types.BOOLEAN,
+    optional: true,
+    nullable: true
+  }]);
+
+  var callArgs = {
+    advertiseData: args.advertiseData,
+    packetType: args.packetType,
+    mode: T.isNullOrUndefined(args.mode) ? _BluetoothAdvertisingMode.BALANCED : args.mode,
+    connectable: T.isNullOrUndefined(args.connectable) ? true : args.connectable
+  };
+
+  var result = native.callSync('BluetoothLEAdapter_startAdvertise', callArgs);
+
+  if (native.isFailure(result)) {
+    throw native.getErrorObject(result);
+  }
+
+  _bleAdvertiseListener.addListener(args.successCallback, args.errorCallback);
+};
+
+BluetoothLEAdapter.prototype.stopAdvertise = function() {
+  console.log('Entered BluetoothLEAdapter.stopAdvertise()');
+
+  xwalk.utils.checkPrivilegeAccess4Ver("2.4", Privilege.BLUETOOTH, Privilege.BLUETOOTH_ADMIN);
+
+  // TODO: when should we call _bleAdvertiseListener.removeListener()?
+
+  var result = native.callSync('BluetoothLEAdapter_stopAdvertise', {});
+
+  if (native.isFailure(result)) {
+    _bleAdvertiseListener.removeListener();
+    throw native.getErrorObject(result);
+  }
+};
+
+//class BluetoothGATTService ////////////////////////////////////////////////////
+var BluetoothGATTService = function(data, address) {
+    var handle_ = data.handle;
+    var uuid_ = data.uuid;
+    //address_ is needed to control if device is still connected
+    var address_ = address || data.address;
+    function servicesGetter() {
+        var services = [];
+        var result = native.callSync('BluetoothGATTService_getServices',
+                {handle: handle_, address : address_});
+        if (native.isSuccess(result)) {
+            var resultObject = native.getResultObject(result);
+            resultObject.forEach(function(s) {
+                services.push(new BluetoothGATTService(s, address_));
+            });
+        }
+        return services;
+    }
+    function characteristicsGetter() {
+        var characteristics = [];
+        var result = native.callSync('BluetoothGATTService_getCharacteristics',
+                {handle: handle_, uuid: uuid_, address : address_});
+        if (native.isSuccess(result)) {
+            var resultObject = native.getResultObject(result);
+            resultObject.forEach(function(c) {
+                characteristics.push(new BluetoothGATTCharacteristic(c, address_));
+            });
+        }
+        return characteristics;
+    }
+    Object.defineProperties(this, {
+        uuid : {value: uuid_, writable: false, enumerable: true},
+        services : {enumerable: true, set : function() {}, get : servicesGetter},
+        characteristics : {enumerable: true, set : function() {}, get : characteristicsGetter}
+    });
+};
+
+var toByteArray = function(array) {
+    var d = [];
+
+    array.forEach(function(b) {
+        d.push(Converter.toOctet(b));
+    });
+    return d;
+};
+
+//class BluetoothGATTCharacteristic ////////////////////////////////////////////////////
+var BluetoothGATTCharacteristic = function(data, address) {
+  var handle_ = data.handle;
+  var descriptors_ = [];
+  var isBroadcast_ = false;
+  var hasExtendedProperties_ = false;
+  var isNotify_ = false;
+  var isIndication_ = false;
+  var isReadable_ = false;
+  var isSignedWrite_ = false;
+  var isWritable_ = false;
+  var isWriteNoResponse_ = false;
+  //address_ is needed to control if device is still connected
+  var address_ = address;
+
+  if (T.isObject(data)) {
+    data.descriptors.forEach(function(dd) {
+      descriptors_.push(new BluetoothGATTDescriptor(dd, address_));
+    });
+    isBroadcast_ = data.isBroadcast;
+    hasExtendedProperties_ = data.hasExtendedProperties;
+    isNotify_ = data.isNotify;
+    isIndication_ = data.isIndication;
+    isReadable_ = data.isReadable;
+    isSignedWrite_ = data.isSignedWrite;
+    isWritable_ = data.isWritable;
+    isWriteNoResponse_ = data.isWriteNoResponse;
+  }
+
+  Object.defineProperties(this, {
+    descriptors: {
+      enumerable: true,
+      get: function() {
+        return descriptors_.slice();
+      },
+      set: function() {
+      }
+    },
+    isBroadcast: {
+      enumerable: true,
+      get: function() {
+        return isBroadcast_;
+      },
+      set: function() {
+      }
+    },
+    hasExtendedProperties: {
+      enumerable: true,
+      get: function() {
+        return hasExtendedProperties_;
+      },
+      set: function() {
+      }
+    },
+    isNotify: {
+      enumerable: true,
+      get: function() {
+        return isNotify_;
+      },
+      set: function() {
+      }
+    },
+    isIndication: {
+      enumerable: true,
+      get: function() {
+        return isIndication_;
+      },
+      set: function() {
+      }
+    },
+    isReadable: {
+      enumerable: true,
+      get: function() {
+        return isReadable_;
+      },
+      set: function() {
+      }
+    },
+    isSignedWrite: {
+      enumerable: true,
+      get: function() {
+        return isSignedWrite_;
+      },
+      set: function() {
+      }
+    },
+    isWritable: {
+      enumerable: true,
+      get: function() {
+        return isWritable_;
+      },
+      set: function() {
+      }
+    },
+    isWriteNoResponse: {
+      enumerable: true,
+      get: function() {
+        return isWriteNoResponse_;
+      },
+      set: function() {
+      }
+    }
+  });
+
+  BluetoothGATTCharacteristic.prototype.readValue = function() {
+      console.log('Entered BluetoothGATTCharacteristic.readValue()');
+
+      xwalk.utils.checkPrivilegeAccess4Ver("2.4", Privilege.BLUETOOTH, Privilege.BLUETOOTH_ADMIN);
+
+      var args = AV.validateMethod(arguments, [{
+        name: 'successCallback',
+        type: AV.Types.FUNCTION
+      }, {
+        name: 'errorCallback',
+        type: AV.Types.FUNCTION,
+        optional: true,
+        nullable: true
+      }]);
+
+      var callback = function(result) {
+        if (native.isFailure(result)) {
+          native.callIfPossible(args.errorCallback, native.getErrorObject(result));
+        } else {
+          var d = toByteArray(native.getResultObject(result));
+          args.successCallback(d);
+        }
+      };
+
+      var callArgs = {handle : handle_, address : address_};
+
+      var result = native.call('BluetoothGATT_readValue', callArgs, callback);
+
+      if (native.isFailure(result)) {
+        throw native.getErrorObject(result);
+      }
+    };
+
+    BluetoothGATTCharacteristic.prototype.writeValue = function() {
+      console.log('Entered BluetoothGATTCharacteristic.writeValue()');
+
+      xwalk.utils.checkPrivilegeAccess4Ver("2.4", Privilege.BLUETOOTH, Privilege.BLUETOOTH_ADMIN);
+
+      var args = AV.validateMethod(arguments, [{
+        name: 'value',
+        type: AV.Types.ARRAY,
+        values: AV.Types.BYTE
+      }, {
+        name: 'successCallback',
+        type: AV.Types.FUNCTION,
+        optional: true,
+        nullable: true
+      }, {
+        name: 'errorCallback',
+        type: AV.Types.FUNCTION,
+        optional: true,
+        nullable: true
+      }]);
+
+      var callback = function(result) {
+        if (native.isFailure(result)) {
+          native.callIfPossible(args.errorCallback, native.getErrorObject(result));
+        } else {
+          native.callIfPossible(args.successCallback);
+        }
+      };
+
+      var callArgs = { handle : handle_, value: toByteArray(args.value), address : address_ };
+
+      var result = native.call('BluetoothGATT_writeValue', callArgs, callback);
+
+      if (native.isFailure(result)) {
+        throw native.getErrorObject(result);
+      }
+    };
+
+  BluetoothGATTCharacteristic.prototype.addValueChangeListener = function() {
+    console.log('Entered BluetoothGATTCharacteristic.addValueChangeListener()');
+
+    xwalk.utils.checkPrivilegeAccess4Ver("2.4", Privilege.BLUETOOTH, Privilege.BLUETOOTH_ADMIN);
+
+    var args = AV.validateMethod(arguments, [{
+      name: 'callback',
+      type: AV.Types.FUNCTION
+    }]);
+
+    var callArgs = { handle: handle_, address : address_ };
+
+    var callback = function(event) {
+      if (event.handle === handle_) {
+        args.callback(toByteArray(native.getResultObject(event)));
+      }
+    };
+
+    return _bluetoothGATTCharacteristicListener.addListener(callback, callArgs);
+  };
+
+  BluetoothGATTCharacteristic.prototype.removeValueChangeListener = function() {
+    console.log('Entered BluetoothGATTCharacteristic.removeValueChangeListener()');
+
+    var args = AV.validateMethod(arguments, [{
+      name: 'watchID',
+      type: AV.Types.LONG
+    }]);
+
+    var callArgs = { handle: handle_, address : address_ };
+
+    return _bluetoothGATTCharacteristicListener.removeListener(args.watchID, callArgs);
+  };
+};
+
+
+/**
+ * Creates a manager for specified listener event. Manager handles multiple
+ * registered listeners
+ *
+ * @param {string} name - name of the listener this manager handles
+ * @param {function} callback - function to be invoked when event specified by the name fires.
+ *                              This function should have following signature:
+ *                              void callback(listener, event);
+ * @param {string} addListenerId - optional parameter. If specified, this native
+ *                                 method will be called synchronously when
+ *                                 listener is added.
+ * @param {string} removeListenerId - optional parameter. If specified, this native
+ *                                 method will be called synchronously when
+ *                                 listener is removed.
+ * @param {bool} repeatNativeCall - optional parameter. If specified, the addListenerId
+ *                                 and removeListenerId methods will be called synchronously
+ *                                 each time listener is added/removed. Otherwise they are
+ *                                 going to be called just once: when first listener is added
+ *                                 and last listener is removed.
+ *
+ * @return {object} object which allows to add or remove callbacks for specified listener
+ */
+function _multipleListenerBuilder(name, callback, addListenerId, removeListenerId, repeatNativeCall) {
+  var listenerName = name;
+  var addId = addListenerId;
+  var removeId = removeListenerId;
+  var callbackFunction = callback;
+  var listeners = {};
+  var nextId = 1;
+  var jsListenerRegistered = false;
+  var nativeListenerRegistered = false;
+  var repeatNativeListenerCall = repeatNativeCall;
+
+  function innerCallback(event) {
+    for (var watchId in listeners) {
+      if (listeners.hasOwnProperty(watchId)) {
+        callbackFunction(listeners[watchId], event);
+      }
+    }
+  }
+
+  function addListener(callback, args) {
+    var id = ++nextId;
+
+    if (addId && (!nativeListenerRegistered || repeatNativeListenerCall)) {
+      var result = native.callSync(addId, args || {});
+      if (native.isFailure(result)) {
+        throw native.getErrorObject(result);
+      }
+      nativeListenerRegistered = true;
+    }
+
+    if (!jsListenerRegistered) {
+      native.addListener(listenerName, innerCallback);
+      jsListenerRegistered = true;
+    }
+
+    listeners[id] = callback;
+    return id;
+  }
+
+  function removeListener(watchId, args) {
+    if (listeners.hasOwnProperty(watchId)) {
+      delete listeners[watchId];
+    }
+
+    if (removeId && ((nativeListenerRegistered && T.isEmptyObject(listeners)) || repeatNativeListenerCall)) {
+      var result = native.callSync(removeId, args || {});
+      if (native.isFailure(result)) {
+        throw native.getErrorObject(result);
+      }
+      nativeListenerRegistered = false;
+    }
+
+    if (jsListenerRegistered && T.isEmptyObject(listeners)) {
+      native.removeListener(listenerName, innerCallback);
+      jsListenerRegistered = false;
+    }
+  }
+
+  return {
+    addListener: addListener,
+    removeListener: removeListener
+  };
+}
+
+var _bluetoothGATTCharacteristicListener = _multipleListenerBuilder(
+    'BluetoothGATTCharacteristicValueChangeListener',
+    function(listener, event) {
+      listener(event);
+    },
+    'BluetoothGATTCharacteristic_addValueChangeListener',
+    'BluetoothGATTCharacteristic_removeValueChangeListener',
+    true
+);
+
+var _bleConnectChangeListener = _multipleListenerBuilder(
+    'BluetoothLEConnectChangeCallback',
+    function(listener, event) {
+        listener(event);
+    },
+    'BluetoothLEDevice_addConnectStateChangeListener',
+    'BluetoothLEDevice_removeConnectStateChangeListener'
+);
+
+//class BluetoothGATTDescriptor ////////////////////////////////////////////////////
+var BluetoothGATTDescriptor = function(data, address) {
+  var handle_ = data.handle;
+  //address_ is needed to control if device is still connected
+  var address_ = address;
+
+  BluetoothGATTDescriptor.prototype.readValue = function() {
+    console.log('Entered BluetoothGATTDescriptor.readValue()');
+
+    xwalk.utils.checkPrivilegeAccess4Ver("2.4", Privilege.BLUETOOTH, Privilege.BLUETOOTH_ADMIN);
+
+    var args = AV.validateMethod(arguments, [{
+      name: 'successCallback',
+      type: AV.Types.FUNCTION
+    }, {
+      name: 'errorCallback',
+      type: AV.Types.FUNCTION,
+      optional: true,
+      nullable: true
+    }]);
+
+    var callback = function(result) {
+      if (native.isFailure(result)) {
+        native.callIfPossible(args.errorCallback, native.getErrorObject(result));
+      } else {
+        var d = toByteArray(native.getResultObject(result));
+        args.successCallback(d);
+      }
+    };
+
+    var callArgs = {handle : handle_, address : address_};
+
+    var result = native.call('BluetoothGATT_readValue', callArgs, callback);
+
+    if (native.isFailure(result)) {
+      throw native.getErrorObject(result);
+    }
+  };
+
+  BluetoothGATTDescriptor.prototype.writeValue = function() {
+    console.log('Entered BluetoothGATTDescriptor.writeValue()');
+
+    xwalk.utils.checkPrivilegeAccess4Ver("2.4", Privilege.BLUETOOTH, Privilege.BLUETOOTH_ADMIN);
+
+    var args = AV.validateMethod(arguments, [{
+      name: 'value',
+      type: AV.Types.ARRAY,
+      values: AV.Types.BYTE
+    }, {
+      name: 'successCallback',
+      type: AV.Types.FUNCTION,
+      optional: true,
+      nullable: true
+    }, {
+      name: 'errorCallback',
+      type: AV.Types.FUNCTION,
+      optional: true,
+      nullable: true
+    }]);
+
+    var callback = function(result) {
+      if (native.isFailure(result)) {
+        native.callIfPossible(args.errorCallback, native.getErrorObject(result));
+      } else {
+        native.callIfPossible(args.successCallback);
+      }
+    };
+
+    var callArgs = { handle : handle_, value: toByteArray(args.value), address : address_ };
+
+    var result = native.call('BluetoothGATT_writeValue', callArgs, callback);
+
+    if (native.isFailure(result)) {
+      throw native.getErrorObject(result);
+    }
+  };
+};
+
+
+
+// class BluetoothAdapter ////////////////////////////////////////////////////
+var BluetoothAdapter = function() {
+    function nameGetter() {
+        var result = native.callSync('BluetoothAdapter_getName', {});
+
+        if (native.isFailure(result)) {
+            return '';
+        } else {
+            return native.getResultObject(result);
+        }
+    }
+
+    function addressGetter() {
+        var result = native.callSync('BluetoothAdapter_getAddress', {});
+
+        if (native.isFailure(result)) {
+            return '';
+        } else {
+            return native.getResultObject(result);
+        }
+    }
+
+    function poweredGetter() {
+        var result = native.callSync('BluetoothAdapter_getPowered', {});
+
+        if (native.isFailure(result)) {
+            return false;
+        } else {
+            return native.getResultObject(result);
+        }
+    }
+
+    function visibleGetter() {
+        var result = native.callSync('BluetoothAdapter_getVisible', {});
+
+        if (native.isFailure(result)) {
+            return false;
+        } else {
+            return native.getResultObject(result);
+        }
+    }
+
+    Object.defineProperties(this, {
+        name : {
+            enumerable: true,
+            set : function(){},
+            get : nameGetter
+        },
+        address : {
+            enumerable: true,
+            set : function(){},
+            get : addressGetter
+        },
+        powered : {
+            enumerable: true,
+            set : function(){},
+            get : poweredGetter
+        },
+        visible : {
+            enumerable: true,
+            set : function(){},
+            get : visibleGetter
+        }
+    });
+};
+
+BluetoothAdapter.prototype.setName = function() {
+    console.log('Entered BluetoothAdapter.setName()');
+    xwalk.utils.checkPrivilegeAccess4Ver("2.4", Privilege.BLUETOOTH, Privilege.BLUETOOTH_ADMIN);
+
+    var args = AV.validateMethod(arguments, [
+        {
+            name : 'name',
+            type : AV.Types.STRING
+        },
+        {
+            name : 'successCallback',
+            type : AV.Types.FUNCTION,
+            optional : true,
+            nullable : true
+        },
+        {
+            name : 'errorCallback',
+            type : AV.Types.FUNCTION,
+            optional : true,
+            nullable : true
+        }
+    ]);
+
+    var callArgs = {
+        name : args.name
+    };
+
+    var callback = function(result) {
+        if (native.isFailure(result)) {
+            native.callIfPossible(args.errorCallback, native.getErrorObject(result));
+        } else {
+            native.callIfPossible(args.successCallback);
+        }
+    };
+
+    // native.call does not inform if call results in failure
+    // TODO: what to do in this case?
+    native.call('BluetoothAdapter_setName', callArgs, callback);
+};
+
+BluetoothAdapter.prototype.setPowered = function() {
+    console.log('Entered BluetoothAdapter.setPowered()');
+    xwalk.utils.checkPrivilegeAccess4Ver("2.4", Privilege.BLUETOOTH, Privilege.BLUETOOTH_ADMIN);
+
+    var args = AV.validateMethod(arguments, [
+        {
+            name : 'powered',
+            type : AV.Types.BOOLEAN
+        },
+        {
+            name : 'successCallback',
+            type : AV.Types.FUNCTION,
+            optional : true,
+            nullable : true
+        },
+        {
+            name : 'errorCallback',
+            type : AV.Types.FUNCTION,
+            optional : true,
+            nullable : true
+        }
+    ]);
+
+    var callArgs = {
+        powered : args.powered
+    };
+
+    var callback = function(result) {
+        if (native.isFailure(result)) {
+            native.callIfPossible(args.errorCallback, native.getErrorObject(result));
+        } else {
+            native.callIfPossible(args.successCallback);
+        }
+    };
+
+    // native.call does not inform if call results in failure
+    // TODO: what to do in this case?
+    native.call('BluetoothAdapter_setPowered', callArgs, callback);
+};
+
+
+// This method is deprecated since Tizen 2.3 and will be removed in Tizen 3.0.
+BluetoothAdapter.prototype.setVisible = function() {
+    console.log('Entered BluetoothAdapter.setVisible()');
+    xwalk.utils.checkPrivilegeAccess4Ver("2.4", Privilege.BLUETOOTH, Privilege.BLUETOOTHMANAGER);
+
+    var args = AV.validateMethod(arguments, [
+        {
+            name : 'visible',
+            type : AV.Types.BOOLEAN
+        },
+        {
+            name : 'successCallback',
+            type : AV.Types.FUNCTION,
+            optional : true,
+            nullable : true
+        },
+        {
+            name : 'errorCallback',
+            type : AV.Types.FUNCTION,
+            optional : true,
+            nullable : true
+        },
+        {
+            name : 'timeout',
+            type : AV.Types.UNSIGNED_LONG,
+            optional : true,
+            nullable : true
+        }
+    ]);
+
+    var callArgs = {
+        visible : args.visible,
+    };
+
+    if (args.visible === true) {
+        if (T.isNullOrUndefined(args.timeout)) {
+            callArgs.timeout = 0;
+        } else {
+            callArgs.timeout = args.timeout > 65535 ? 180 : args.timeout;
+        }
+    }
+
+    var callback = function(result) {
+        if (native.isFailure(result)) {
+            native.callIfPossible(args.errorCallback, native.getErrorObject(result));
+        } else {
+            native.callIfPossible(args.successCallback);
+        }
+    };
+
+    // native.call does not inform if call results in failure
+    // TODO: what to do in this case?
+    native.call('BluetoothAdapter_setVisible', callArgs, callback);
+};
+
+var _listener;
+
+function _BluetoothAdapterChangeCallback(event) {
+    console.log('_BluetoothAdapterChangeCallback');
+
+    var e = event;
+    var d;
+
+    switch (e.action) {
+    case 'onstatechanged':
+        d = e.powered;
+        break;
+
+    case 'onnamechanged':
+        d = e.name;
+        break;
+
+    case 'onvisibilitychanged':
+        d = e.visible;
+        break;
+
+    default:
+        console.log('Unknown mode: ' + e.action);
+        return;
+    }
+
+    if (_listener[e.action]) {
+        _listener[e.action](d);
+    }
+}
+
+BluetoothAdapter.prototype.setChangeListener = function() {
+    console.log('Entered BluetoothAdapter.setChangeListener()');
+    var args = AV.validateMethod(arguments, [
+        {
+            name : 'changeCallback',
+            type : AV.Types.LISTENER,
+            values : ['onstatechanged', 'onnamechanged', 'onvisibilitychanged']
+        }
+    ]);
+
+    if (T.isNullOrUndefined(_listener)) {
+        native.addListener('BluetoothAdapterChangeCallback', _BluetoothAdapterChangeCallback);
+    }
+    _listener = args.changeCallback;
+};
+
+BluetoothAdapter.prototype.unsetChangeListener = function() {
+    console.log('Entered BluetoothAdapter.unsetChangeListener()');
+    if (!T.isNullOrUndefined(_listener)) {
+        native.removeListener('BluetoothAdapterChangeCallback', _BluetoothAdapterChangeCallback);
+        _listener = undefined;
+    }
+};
+
+var _discoverDevicesSuccessCallback;
+var _discoverDevicesErrorCallback;
+
+function _BluetoothDiscoverDevicesSuccessCallback(event) {
+    var e = event;
+    var d = null;
+
+    switch (e.action) {
+    case 'onstarted':
+        break;
+
+    case 'ondevicefound':
+        d = new BluetoothDevice(e.data);
+        break;
+
+    case 'ondevicedisappeared':
+        d = e.data;
+        break;
+
+    case 'onfinished':
+        var result = e.data;
+        d = [];
+        result.forEach(function (data) {
+            d.push(new BluetoothDevice(data));
+        });
+
+        //remove listeners after discovering
+        native.removeListener('BluetoothDiscoverDevicesSuccessCallback',
+                _BluetoothDiscoverDevicesSuccessCallback);
+        native.removeListener('BluetoothDiscoverDevicesErrorCallback',
+                _BluetoothDiscoverDevicesErrorCallback);
+        break;
+
+    default:
+        console.log('Unknown mode: ' + e.action);
+        return;
+    }
+
+    if (_discoverDevicesSuccessCallback[e.action]) {
+        _discoverDevicesSuccessCallback[e.action](d);
+    }
+}
+
+function _BluetoothDiscoverDevicesErrorCallback(event) {
+    var e = event;
+    setTimeout(function() {
+        native.callIfPossible(_discoverDevicesErrorCallback, native.getErrorObject(e));
+    }, 0);
+}
+
+BluetoothAdapter.prototype.discoverDevices = function() {
+    console.log('Entered BluetoothAdapter.discoverDevices()');
+    xwalk.utils.checkPrivilegeAccess4Ver("2.4", Privilege.BLUETOOTH, Privilege.BLUETOOTH_GAP);
+
+    var args = AV.validateMethod(arguments, [
+        {
+            name : 'successCallback',
+            type : AV.Types.LISTENER,
+            values : ['onstarted', 'ondevicefound', 'ondevicedisappeared', 'onfinished']
+        },
+        {
+            name : 'errorCallback',
+            type : AV.Types.FUNCTION,
+            optional : true,
+            nullable : true
+        }
+    ]);
+
+    _discoverDevicesSuccessCallback = args.successCallback;
+    _discoverDevicesErrorCallback = args.errorCallback;
+    native.addListener('BluetoothDiscoverDevicesSuccessCallback',
+            _BluetoothDiscoverDevicesSuccessCallback);
+    native.addListener('BluetoothDiscoverDevicesErrorCallback',
+            _BluetoothDiscoverDevicesErrorCallback);
+
+    var result = native.callSync('BluetoothAdapter_discoverDevices', {});
+
+    if (native.isFailure(result)) {
+        native.removeListener('BluetoothDiscoverDevicesSuccessCallback',
+                _BluetoothDiscoverDevicesSuccessCallback);
+        native.removeListener('BluetoothDiscoverDevicesErrorCallback',
+                _BluetoothDiscoverDevicesErrorCallback);
+        throw native.getErrorObject(result);
+    }
+};
+
+BluetoothAdapter.prototype.stopDiscovery = function() {
+    console.log('Entered BluetoothAdapter.stopDiscovery()');
+    xwalk.utils.checkPrivilegeAccess4Ver("2.4", Privilege.BLUETOOTH, Privilege.BLUETOOTH_GAP);
+
+    var args = AV.validateMethod(arguments, [
+        {
+            name : 'successCallback',
+            type : AV.Types.FUNCTION,
+            optional : true,
+            nullable : true
+        },
+        {
+            name : 'errorCallback',
+            type : AV.Types.FUNCTION,
+            optional : true,
+            nullable : true
+        }
+    ]);
+
+    var callback = function(result) {
+        if (native.isFailure(result)) {
+            native.callIfPossible(args.errorCallback, native.getErrorObject(result));
+        } else {
+            native.callIfPossible(args.successCallback);
+        }
+    };
+
+    // native.call does not inform if call results in failure
+    // TODO: what to do in this case?
+    native.call('BluetoothAdapter_stopDiscovery', {}, callback);
+};
+
+BluetoothAdapter.prototype.getKnownDevices = function() {
+    console.log('Entered BluetoothAdapter.getKnownDevices()');
+    xwalk.utils.checkPrivilegeAccess4Ver("2.4", Privilege.BLUETOOTH, Privilege.BLUETOOTH_GAP);
+
+    var args = AV.validateMethod(arguments, [
+        {
+            name : 'successCallback',
+            type : AV.Types.FUNCTION
+        },
+        {
+            name : 'errorCallback',
+            type : AV.Types.FUNCTION,
+            optional : true,
+            nullable : true
+        }
+    ]);
+
+    var callback = function(result) {
+        if (native.isFailure(result)) {
+            native.callIfPossible(args.errorCallback, native.getErrorObject(result));
+        } else {
+            var r = native.getResultObject(result).devices;
+            var devices = [];
+            r.forEach(function (data) {
+                devices.push(new BluetoothDevice(data));
+            });
+            args.successCallback(devices);
+        }
+    };
+
+    // native.call does not inform if call results in failure
+    // TODO: what to do in this case?
+    native.call('BluetoothAdapter_getKnownDevices', {}, callback);
+};
+
+BluetoothAdapter.prototype.getDevice = function() {
+    console.log('Entered BluetoothAdapter.getDevice()');
+    xwalk.utils.checkPrivilegeAccess4Ver("2.4", Privilege.BLUETOOTH, Privilege.BLUETOOTH_GAP);
+
+    var args = AV.validateMethod(arguments, [
+        {
+            name : 'address',
+            type : AV.Types.STRING
+        },
+        {
+            name : 'successCallback',
+            type : AV.Types.FUNCTION
+        },
+        {
+            name : 'errorCallback',
+            type : AV.Types.FUNCTION,
+            optional : true,
+            nullable : true
+        }
+    ]);
+
+    var callback = function(result) {
+        if (native.isFailure(result)) {
+            native.callIfPossible(args.errorCallback, native.getErrorObject(result));
+        } else {
+            args.successCallback(new BluetoothDevice(native.getResultObject(result)));
+        }
+    };
+
+    // native.call does not inform if call results in failure
+    // TODO: what to do in this case?
+    native.call('BluetoothAdapter_getDevice', {address : args.address}, callback);
+};
+
+BluetoothAdapter.prototype.createBonding = function() {
+    console.log('Entered BluetoothAdapter.createBonding()');
+    xwalk.utils.checkPrivilegeAccess4Ver("2.4", Privilege.BLUETOOTH, Privilege.BLUETOOTH_GAP);
+
+    var args = AV.validateMethod(arguments, [
+        {
+            name : 'address',
+            type : AV.Types.STRING
+        },
+        {
+            name : 'successCallback',
+            type : AV.Types.FUNCTION,
+            optional : false,
+            nullable : false
+        },
+        {
+            name : 'errorCallback',
+            type : AV.Types.FUNCTION,
+            optional : true,
+            nullable : true
+        }
+    ]);
+
+    var callArgs = {
+        address : args.address
+    };
+
+    var callback = function(result) {
+        if (native.isFailure(result)) {
+            native.callIfPossible(args.errorCallback, native.getErrorObject(result));
+        } else {
+            args.successCallback(new BluetoothDevice(native.getResultObject(result)));
+        }
+    };
+
+    // native.call does not inform if call results in failure
+    // TODO: what to do in this case?
+    native.call('BluetoothAdapter_createBonding', callArgs, callback);
+};
+
+BluetoothAdapter.prototype.destroyBonding = function() {
+    console.log('Entered BluetoothAdapter.destroyBonding()');
+    xwalk.utils.checkPrivilegeAccess4Ver("2.4", Privilege.BLUETOOTH, Privilege.BLUETOOTH_GAP);
+
+    var args = AV.validateMethod(arguments, [
+        {
+            name : 'address',
+            type : AV.Types.STRING
+        },
+        {
+            name : 'successCallback',
+            type : AV.Types.FUNCTION,
+            optional : true,
+            nullable : true
+        },
+        {
+            name : 'errorCallback',
+            type : AV.Types.FUNCTION,
+            optional : true,
+            nullable : true
+        }
+    ]);
+
+    var callArgs = {
+        address : args.address
+    };
+
+    var callback = function(result) {
+        if (native.isFailure(result)) {
+            native.callIfPossible(args.errorCallback, native.getErrorObject(result));
+        } else {
+            native.callIfPossible(args.successCallback);
+        }
+    };
+
+    // native.call does not inform if call results in failure
+    // TODO: what to do in this case?
+    native.call('BluetoothAdapter_destroyBonding', callArgs, callback);
+};
+
+BluetoothAdapter.prototype.registerRFCOMMServiceByUUID = function() {
+    console.log('Entered BluetoothAdapter.registerRFCOMMServiceByUUID()');
+    xwalk.utils.checkPrivilegeAccess4Ver("2.4", Privilege.BLUETOOTH, Privilege.BLUETOOTH_SPP);
+
+    var args = AV.validateMethod(arguments, [
+        {
+            name : 'uuid',
+            type : AV.Types.STRING
+        },
+        {
+            name : 'name',
+            type : AV.Types.STRING
+        },
+        {
+            name : 'successCallback',
+            type : AV.Types.FUNCTION,
+        },
+        {
+            name : 'errorCallback',
+            type : AV.Types.FUNCTION,
+            optional : true,
+            nullable : true
+        }
+    ]);
+
+    var callArgs = {
+        uuid : args.uuid,
+        name : args.name
+    };
+
+    var callback = function(result) {
+        if (native.isFailure(result)) {
+            native.callIfPossible(args.errorCallback, native.getErrorObject(result));
+        } else {
+            // if registration was finished with success create BluetoothServiceHandler
+            // with parameters passed to this function (uuid and name).
+            args.successCallback(new BluetoothServiceHandler(callArgs));
+        }
+    };
+
+    // native.call does not inform if call results in failure
+    // TODO: what to do in this case?
+    native.call('BluetoothAdapter_registerRFCOMMServiceByUUID', callArgs, callback);
+};
+
+BluetoothAdapter.prototype.getBluetoothProfileHandler = function() {
+    console.log('Entered BluetoothAdapter.getBluetoothProfileHandler()');
+
+    var args = AV.validateMethod(arguments, [
+        {
+            name : 'profileType',
+            type : AV.Types.ENUM,
+            values : T.getValues(_BluetoothProfileType)
+        }
+    ]);
+
+    var callArgs = {profileType : args.profileType};
+
+    var result = native.callSync('BluetoothAdapter_getBluetoothProfileHandler', callArgs);
+
+    if (native.isFailure(result)) {
+        throw native.getErrorObject(result);
+    } else {
+        switch (args.profileType) {
+        case _BluetoothProfileType.HEALTH:
+            return new BluetoothHealthProfileHandler(callArgs);
+
+        default:
+            throw new WebAPIException('NotSupportedError', 'Profile ' + args.profileType + ' is not supported.');
+        }
+    }
+};
+
+// class BluetoothManager ////////////////////////////////////////////////////
+var BluetoothManager = function() {
+    Object.defineProperties(this, {
+        deviceMajor : {
+            value: new BluetoothClassDeviceMajor(),
+            writable: false,
+            enumerable: true
+        },
+        deviceMinor : {
+            value: new BluetoothClassDeviceMinor(),
+            writable: false,
+            enumerable: true
+        },
+        deviceService : {
+            value: new BluetoothClassDeviceService(),
+            writable: false,
+            enumerable: true
+        }
+    });
+};
+
+BluetoothManager.prototype.getDefaultAdapter = function() {
+    console.log('Entered BluetoothManager.getDefaultAdapter()');
+
+    xwalk.utils.checkPrivilegeAccess4Ver("2.4", Privilege.BLUETOOTH, Privilege.BLUETOOTH_GAP);
+
+    return new BluetoothAdapter();
+};
+
+BluetoothManager.prototype.getLEAdapter = function() {
+    console.log('Entered BluetoothManager.getLEAdapter()');
+
+    xwalk.utils.checkPrivilegeAccess4Ver("2.4", Privilege.BLUETOOTH, Privilege.BLUETOOTH_ADMIN);
+
+    return new BluetoothLEAdapter();
+};
+// exports ///////////////////////////////////////////////////////////////////
+exports = new BluetoothManager();
diff --git a/webWidgetTCT_device/src/bluetooth/bluetooth_class.cc b/webWidgetTCT_device/src/bluetooth/bluetooth_class.cc
new file mode 100755 (executable)
index 0000000..4d7f62f
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2015 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 "bluetooth_class.h"
+#include "common/logger.h"
+
+#include <map>
+
+namespace extension {
+namespace bluetooth {
+
+std::map<bt_major_device_class_e, unsigned long> g_major_enum_map = {
+    {BT_MAJOR_DEVICE_CLASS_MISC, 0x00},
+    {BT_MAJOR_DEVICE_CLASS_COMPUTER, 0x01},
+    {BT_MAJOR_DEVICE_CLASS_PHONE, 0x02},
+    {BT_MAJOR_DEVICE_CLASS_LAN_NETWORK_ACCESS_POINT, 0x03},
+    {BT_MAJOR_DEVICE_CLASS_AUDIO_VIDEO, 0x04},
+    {BT_MAJOR_DEVICE_CLASS_PERIPHERAL, 0x05},
+    {BT_MAJOR_DEVICE_CLASS_IMAGING, 0x06},
+    {BT_MAJOR_DEVICE_CLASS_WEARABLE, 0x07},
+    {BT_MAJOR_DEVICE_CLASS_TOY, 0x08},
+    {BT_MAJOR_DEVICE_CLASS_HEALTH, 0x09},
+    {BT_MAJOR_DEVICE_CLASS_UNCATEGORIZED, 0x1F}
+};
+
+std::map<bt_minor_device_class_e, unsigned long> g_minor_enum_map = {
+    {BT_MINOR_DEVICE_CLASS_COMPUTER_UNCATEGORIZED, 0x00},
+    {BT_MINOR_DEVICE_CLASS_COMPUTER_DESKTOP_WORKSTATION , 0x01},
+    {BT_MINOR_DEVICE_CLASS_COMPUTER_SERVER_CLASS , 0x02},
+    {BT_MINOR_DEVICE_CLASS_COMPUTER_LAPTOP , 0x03},
+    {BT_MINOR_DEVICE_CLASS_COMPUTER_HANDHELD_PC_OR_PDA , 0x04},
+    {BT_MINOR_DEVICE_CLASS_COMPUTER_PALM_SIZED_PC_OR_PDA, 0x5},
+    {BT_MINOR_DEVICE_CLASS_COMPUTER_WEARABLE_COMPUTER , 0x06},
+    {BT_MINOR_DEVICE_CLASS_PHONE_UNCATEGORIZED , 0x00},
+    {BT_MINOR_DEVICE_CLASS_PHONE_CELLULAR , 0x01},
+    {BT_MINOR_DEVICE_CLASS_PHONE_CORDLESS , 0x02},
+    {BT_MINOR_DEVICE_CLASS_PHONE_SMART_PHONE , 0x03},
+    {BT_MINOR_DEVICE_CLASS_PHONE_WIRED_MODEM_OR_VOICE_GATEWAY , 0x04},
+    {BT_MINOR_DEVICE_CLASS_PHONE_COMMON_ISDN_ACCESS , 0x05},
+    {BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_UNCATEGORIZED , 0x00},
+    {BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_WEARABLE_HEADSET , 0x01},
+    {BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_HANDS_FREE , 0x02},
+    {BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_MICROPHONE , 0x04},
+    {BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_LOUDSPEAKER , 0x05},
+    {BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_HEADPHONES , 0x06},
+    {BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_PORTABLE_AUDIO , 0x07},
+    {BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_CAR_AUDIO , 0x08},
+    {BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_SET_TOP_BOX , 0x09},
+    {BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_HIFI_AUDIO_DEVICE , 0x0a},
+    {BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_VCR , 0x0b},
+    {BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_VIDEO_CAMERA , 0x0c},
+    {BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_CAMCORDER , 0x0d},
+    {BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_VIDEO_MONITOR , 0x0e},
+    {BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_VIDEO_DISPLAY_LOUDSPEAKER , 0x0f},
+    {BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_VIDEO_CONFERENCING , 0x10},
+    {BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_GAMING_TOY , 0x12},
+    {BT_MINOR_DEVICE_CLASS_PERIPHERA_UNCATEGORIZED , 0},
+    {BT_MINOR_DEVICE_CLASS_PERIPHERAL_KEY_BOARD , 0x10},
+    {BT_MINOR_DEVICE_CLASS_PERIPHERAL_POINTING_DEVICE , 0x20},
+    {BT_MINOR_DEVICE_CLASS_PERIPHERAL_COMBO_KEYBOARD_POINTING_DEVICE , 0x30},
+    {BT_MINOR_DEVICE_CLASS_PERIPHERAL_JOYSTICK , 0x01},
+    {BT_MINOR_DEVICE_CLASS_PERIPHERAL_GAME_PAD , 0x02},
+    {BT_MINOR_DEVICE_CLASS_PERIPHERAL_REMOTE_CONTROL , 0x03},
+    {BT_MINOR_DEVICE_CLASS_PERIPHERAL_SENSING_DEVICE , 0x04},
+    {BT_MINOR_DEVICE_CLASS_PERIPHERAL_DIGITIZER_TABLET , 0x05},
+    {BT_MINOR_DEVICE_CLASS_PERIPHERAL_CARD_READER , 0x06},
+    {BT_MINOR_DEVICE_CLASS_PERIPHERAL_DIGITAL_PEN , 0x07},
+    {BT_MINOR_DEVICE_CLASS_PERIPHERAL_HANDHELD_SCANNER , 0x08},
+    {BT_MINOR_DEVICE_CLASS_PERIPHERAL_HANDHELD_GESTURAL_INPUT_DEVICE , 0x09},
+    {BT_MINOR_DEVICE_CLASS_IMAGING_DISPLAY , 0x04},
+    {BT_MINOR_DEVICE_CLASS_IMAGING_CAMERA , 0x08},
+    {BT_MINOR_DEVICE_CLASS_IMAGING_SCANNER , 0x10},
+    {BT_MINOR_DEVICE_CLASS_IMAGING_PRINTER, 0x20},
+    {BT_MINOR_DEVICE_CLASS_WEARABLE_WRIST_WATCH , 0x01},
+    {BT_MINOR_DEVICE_CLASS_WEARABLE_PAGER , 0x02},
+    {BT_MINOR_DEVICE_CLASS_WEARABLE_JACKET , 0x03},
+    {BT_MINOR_DEVICE_CLASS_WEARABLE_HELMET , 0x04},
+    {BT_MINOR_DEVICE_CLASS_WEARABLE_GLASSES , 0x05},
+    {BT_MINOR_DEVICE_CLASS_TOY_ROBOT , 0x01},
+    {BT_MINOR_DEVICE_CLASS_TOY_VEHICLE , 0x02},
+    {BT_MINOR_DEVICE_CLASS_TOY_DOLL_ACTION , 0x03},
+    {BT_MINOR_DEVICE_CLASS_TOY_CONTROLLER , 0x04},
+    {BT_MINOR_DEVICE_CLASS_TOY_GAME , 0x05},
+    {BT_MINOR_DEVICE_CLASS_HEALTH_UNCATEGORIZED , 0x00},
+    {BT_MINOR_DEVICE_CLASS_HEALTH_BLOOD_PRESSURE_MONITOR , 0x01},
+    {BT_MINOR_DEVICE_CLASS_HEALTH_THERMOMETER , 0x02},
+    {BT_MINOR_DEVICE_CLASS_HEALTH_WEIGHING_SCALE , 0x03},
+    {BT_MINOR_DEVICE_CLASS_HEALTH_GLUCOSE_METER , 0x04},
+    {BT_MINOR_DEVICE_CLASS_HEALTH_PULSE_OXIMETER , 0x05},
+    {BT_MINOR_DEVICE_CLASS_HEALTH_HEART_PULSE_RATE_MONITOR , 0x06},
+    {BT_MINOR_DEVICE_CLASS_HEALTH_DATA_DISPLAY , 0x07},
+    {BT_MINOR_DEVICE_CLASS_HEALTH_STEP_COUNTER , 0x08},
+    {BT_MINOR_DEVICE_CLASS_HEALTH_BODY_COMPOSITION_ANALYZER , 0x09},
+    {BT_MINOR_DEVICE_CLASS_HEALTH_PEAK_FLOW_MONITOR , 0x0a},
+    {BT_MINOR_DEVICE_CLASS_HEALTH_MEDICATION_MONITOR , 0x0b},
+    {BT_MINOR_DEVICE_CLASS_HEALTH_KNEE_PROSTHESIS , 0x0c},
+    {BT_MINOR_DEVICE_CLASS_HEALTH_ANKLE_PROSTHESIS , 0x0d}
+};
+
+std::map<bt_major_service_class_e, unsigned long> g_service_enum_map = {
+    {BT_MAJOR_SERVICE_CLASS_LIMITED_DISCOVERABLE_MODE, 0x0001},
+    {BT_MAJOR_SERVICE_CLASS_POSITIONING, 0x0008},
+    {BT_MAJOR_SERVICE_CLASS_NETWORKING, 0x0010},
+    {BT_MAJOR_SERVICE_CLASS_RENDERING, 0x0020},
+    {BT_MAJOR_SERVICE_CLASS_CAPTURING, 0x0040},
+    {BT_MAJOR_SERVICE_CLASS_OBJECT_TRANSFER, 0x0080},
+    {BT_MAJOR_SERVICE_CLASS_AUDIO, 0x0100},
+    {BT_MAJOR_SERVICE_CLASS_TELEPHONY, 0x0200},
+    {BT_MAJOR_SERVICE_CLASS_INFORMATION, 0x0400}
+};
+
+unsigned long BluetoothClass::GetMajorValue(bt_major_device_class_e major)
+{
+  LoggerD("Enter");
+  auto iter = g_major_enum_map.find(major);
+  if (iter != g_major_enum_map.end()) {
+    return iter->second;
+  }
+
+  return 0;
+}
+
+unsigned long BluetoothClass::GetMinorValue(bt_minor_device_class_e minor)
+{
+  LoggerD("Enter");
+  auto iter = g_minor_enum_map.find(minor);
+  if (iter != g_minor_enum_map.end()) {
+    return iter->second;
+  }
+
+  return 0;
+}
+
+std::vector<unsigned long> BluetoothClass::getServiceValues(int serviceMask)
+{
+  LoggerD("Enter");
+  std::vector<unsigned long> ret;
+  for (auto iter = g_service_enum_map.begin(); iter != g_service_enum_map.end(); iter++) {
+    if (iter->first & serviceMask) {
+      ret.push_back(iter->second);
+    }
+  }
+
+  return ret;
+}
+
+} // namespace bluetooth
+} // namespace extension
diff --git a/webWidgetTCT_device/src/bluetooth/bluetooth_class.h b/webWidgetTCT_device/src/bluetooth/bluetooth_class.h
new file mode 100755 (executable)
index 0000000..7476369
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2015 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 BLUETOOTH_BLUETOOTH_CLASS_H_
+#define BLUETOOTH_BLUETOOTH_CLASS_H_
+
+#include <vector>
+
+#include <bluetooth.h>
+
+namespace extension {
+namespace bluetooth {
+
+class BluetoothClass {
+ public:
+  static unsigned long GetMajorValue(bt_major_device_class_e major);
+  static unsigned long GetMinorValue(bt_minor_device_class_e minor);
+  static std::vector<unsigned long> getServiceValues(int serviceMask);
+};
+
+} // namespace bluetooth
+} // namespace extension
+
+#endif // BLUETOOTH_BLUETOOTH_CLASS_H_
diff --git a/webWidgetTCT_device/src/bluetooth/bluetooth_device.cc b/webWidgetTCT_device/src/bluetooth/bluetooth_device.cc
new file mode 100755 (executable)
index 0000000..9d9a809
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2015 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 "bluetooth_device.h"
+
+#include "common/converter.h"
+#include "common/logger.h"
+#include "common/extension.h"
+
+#include "bluetooth_adapter.h"
+#include "bluetooth_class.h"
+#include "bluetooth_util.h"
+
+namespace extension {
+namespace bluetooth {
+
+using namespace common;
+using namespace common::tools;
+
+namespace {
+//device
+const std::string kDeviceName = "name";
+const std::string kDeviceAddress = "address";
+const std::string kDeviceClass = "deviceClass";
+const std::string kDeviceClassMajor = "major";
+const std::string kDeviceClassMinor = "minor";
+const std::string kDeviceClassService = "services";
+const std::string kDeviceUuids = "uuids";
+const std::string kDeviceIsBonded = "isBonded";
+const std::string kDeviceIsTrusted = "isTrusted";
+const std::string kDeviceIsConnected = "isConnected";
+}
+
+static void ToJsonFromBTClass(bt_class_s bluetooth_class, picojson::object* device) {
+  LoggerD("Entered");
+
+  picojson::object& bt = device->insert(std::make_pair(kDeviceClass, picojson::value(picojson::object())))
+                                 .first->second.get<picojson::object>();
+
+  bt.insert(std::make_pair(kDeviceClassMajor, picojson::value(static_cast<double>(
+      BluetoothClass::GetMajorValue(bluetooth_class.major_device_class)))));
+  bt.insert(std::make_pair(kDeviceClassMinor, picojson::value(static_cast<double>(
+      BluetoothClass::GetMinorValue(bluetooth_class.minor_device_class)))));
+
+  picojson::array& array = bt.insert(std::make_pair(
+      kDeviceClassService, picojson::value(picojson::array()))).first->second.get<picojson::array>();
+
+  std::vector<unsigned long> services_vector = BluetoothClass::getServiceValues(
+      bluetooth_class.major_service_class_mask);
+
+  for (auto v : services_vector) {
+    array.push_back(picojson::value(static_cast<double>(v)));
+  }
+}
+
+static void ToJsonFromUUID(char **service_uuid, int service_count, picojson::object* device) {
+  LoggerD("Entered");
+
+  picojson::array& array = device->insert(std::make_pair(kDeviceUuids, picojson::value(picojson::array())))
+                             .first->second.get<picojson::array>();
+
+  for (int i = 0; i < service_count; i++) {
+    array.push_back(picojson::value(service_uuid[i]));
+  }
+}
+
+BluetoothDevice::BluetoothDevice(BluetoothAdapter& adapter)
+    : adapter_(adapter) {
+}
+
+void BluetoothDevice::ToJson(bt_device_info_s* info, picojson::object* device) {
+  LoggerD("Entered");
+  device->insert(std::make_pair(kDeviceName, picojson::value(std::string(info->remote_name))));
+  device->insert(std::make_pair(kDeviceAddress, picojson::value(std::string(info->remote_address))));
+
+  ToJsonFromBTClass(info->bt_class, device);
+  ToJsonFromUUID(info->service_uuid, info->service_count, device);
+}
+
+void BluetoothDevice::ToJson(bt_adapter_device_discovery_info_s *info, picojson::object* device) {
+  LoggerD("Entered");
+
+  device->insert(std::make_pair(kDeviceName, picojson::value(info->remote_name)));
+  device->insert(std::make_pair(kDeviceAddress, picojson::value(info->remote_address)));
+
+  ToJsonFromBTClass(info->bt_class, device);
+  ToJsonFromUUID(info->service_uuid, info->service_count, device);
+}
+
+void BluetoothDevice::ConnectToServiceByUUID(const picojson::value& data, picojson::object& out) {
+  LoggerD("Entered");
+
+  const auto& args = util::GetArguments(data);
+
+  adapter_.ConnectToServiceByUUID(FromJson<std::string>(args, "address"),
+                                  FromJson<std::string>(args, "uuid"),
+                                  util::GetAsyncCallbackHandle(data));
+
+  ReportSuccess(out);
+}
+
+void BluetoothDevice::GetBoolValue(const picojson::value& data, picojson::object& out) {
+  LoggerD("Entered");
+
+  const auto& args = util::GetArguments(data);
+  const auto& address = FromJson<std::string>(args, "address");
+  const auto& field = FromJson<std::string>(args, "field");
+
+  PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
+  bool value = false;
+  bt_device_info_s *info = nullptr;
+  if (bt_adapter_get_bonded_device_info(address.c_str(), &info) == BT_ERROR_NONE &&
+      info != nullptr) {
+    if (kDeviceIsBonded == field) {
+      value = info->is_bonded;
+    } else if (kDeviceIsTrusted == field) {
+      value = info->is_authorized;
+    } else if (kDeviceIsConnected == field) {
+      value = info->is_connected;
+    } else {
+      result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Wrong field passed.");
+    }
+    bt_adapter_free_device_info(info);
+  } else {
+    result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error");
+  }
+
+  if (result.IsSuccess()) {
+    ReportSuccess(picojson::value(value), out);
+  } else {
+    ReportError(result, &out);
+  }
+}
+
+} // namespace bluetooth
+} // namespace extension
diff --git a/webWidgetTCT_device/src/bluetooth/bluetooth_device.h b/webWidgetTCT_device/src/bluetooth/bluetooth_device.h
new file mode 100755 (executable)
index 0000000..2df25a7
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2015 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 BLUETOOTH_BLUETOOTH_DEVICE_H_
+#define BLUETOOTH_BLUETOOTH_DEVICE_H_
+
+#include <bluetooth.h>
+
+#include "common/picojson.h"
+
+namespace extension {
+namespace bluetooth {
+
+class BluetoothAdapter;
+
+class BluetoothDevice {
+ public:
+  explicit BluetoothDevice(BluetoothAdapter& adapter);
+
+  /**
+   * Signature: @code void connectToServiceByUUID(uuid, successCallback, errorCallback); @endcode
+   * JSON: @code data: {method: 'BluetoothDevice_connectToServiceByUUID', args: {uuid: uuid}} @endcode
+   * Invocation: @code native.call(request, result_callback); @endcode
+   * Return:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success'}
+   * @endcode
+   * Result callback:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success', result: {socket}}
+   * @endcode
+   */
+  void ConnectToServiceByUUID(const picojson::value& data, picojson::object& out);
+
+  /**
+   * Signature: @code BluetoothDevice.is(Bonded, Trusted, Connected); @endcode
+   * JSON: @code data: {method: 'BluetoothDevice_GetBoolValue', args: {address: address,
+   *                    field: field}} @endcode
+   * Invocation: @code native.callSync(request); @endcode
+   * Return:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success', result: name}
+   * @endcode
+   */
+  void GetBoolValue(const picojson::value& data, picojson::object& out);
+
+  static void ToJson(bt_device_info_s* info,
+                     picojson::object* device);
+  static void ToJson(bt_adapter_device_discovery_info_s *info,
+                     picojson::object* device);
+
+ private:
+  BluetoothAdapter& adapter_;
+};
+
+} // namespace bluetooth
+} // namespace extension
+
+#endif // BLUETOOTH_BLUETOOTH_DEVICE_H_
diff --git a/webWidgetTCT_device/src/bluetooth/bluetooth_extension.cc b/webWidgetTCT_device/src/bluetooth/bluetooth_extension.cc
new file mode 100755 (executable)
index 0000000..d9efdd1
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2015 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 "bluetooth_extension.h"
+#include "bluetooth_instance.h"
+
+namespace {
+const char* kBluetooth = "tizen.bluetooth";
+const char* kBluetoothLEAdvertiseData = "tizen.BluetoothLEAdvertiseData";
+const char* kBluetoothLEServiceData = "tizen.BluetoothLEServiceData";
+const char* kBluetoothLEManufacturerData = "tizen.BluetoothLEManufacturerData";
+}
+// This will be generated from bluetooth_api.js.
+extern const char kSource_bluetooth_api[];
+
+common::Extension* CreateExtension() {
+  return new BluetoothExtension;
+}
+
+BluetoothExtension::BluetoothExtension() {
+  SetExtensionName(kBluetooth);
+  SetJavaScriptAPI(kSource_bluetooth_api);
+  const char* entry_points[] = {
+      kBluetoothLEAdvertiseData,
+      kBluetoothLEServiceData,
+      kBluetoothLEManufacturerData,
+      NULL
+  };
+  SetExtraJSEntryPoints(entry_points);
+}
+
+BluetoothExtension::~BluetoothExtension() {}
+
+common::Instance* BluetoothExtension::CreateInstance() {
+  return new extension::bluetooth::BluetoothInstance();
+}
diff --git a/webWidgetTCT_device/src/bluetooth/bluetooth_extension.h b/webWidgetTCT_device/src/bluetooth/bluetooth_extension.h
new file mode 100755 (executable)
index 0000000..32613b0
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015 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 BLUETOOTH_BLUETOOTH_EXTENSION_H_
+#define BLUETOOTH_BLUETOOTH_EXTENSION_H_
+
+#include "common/extension.h"
+
+class BluetoothExtension : public common::Extension {
+ public:
+  BluetoothExtension();
+  virtual ~BluetoothExtension();
+
+ private:
+  virtual common::Instance* CreateInstance();
+};
+
+#endif // BLUETOOTH_BLUETOOTH_EXTENSION_H_
+
diff --git a/webWidgetTCT_device/src/bluetooth/bluetooth_gatt_service.cc b/webWidgetTCT_device/src/bluetooth/bluetooth_gatt_service.cc
new file mode 100755 (executable)
index 0000000..e069c0f
--- /dev/null
@@ -0,0 +1,589 @@
+/*
+ * Copyright (c) 2015 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 "bluetooth/bluetooth_gatt_service.h"
+
+#include <sstream>
+
+#include "common/logger.h"
+#include "common/platform_result.h"
+#include "common/extension.h"
+#include "common/task-queue.h"
+
+#include "bluetooth/bluetooth_instance.h"
+#include "bluetooth/bluetooth_util.h"
+
+namespace extension {
+namespace bluetooth {
+
+using common::PlatformResult;
+using common::ErrorCode;
+using common::TaskQueue;
+using namespace common::tools;
+
+namespace {
+const std::string kUuid = "uuid";
+const std::string kHandle = "handle";
+const std::string kAddress = "address";
+
+const std::string kDescriptors = "descriptors";
+const std::string kBroadcast = "isBroadcast";
+const std::string kExtendedProperties = "hasExtendedProperties";
+const std::string kNotify = "isNotify";
+const std::string kIndication = "isIndication";
+const std::string kReadable = "isReadable";
+const std::string kSignedWrite = "isSignedWrite";
+const std::string kWritable = "isWritable";
+const std::string kWriteNoResponse = "isWriteNoResponse";
+
+const std::string kOnValueChanged = "BluetoothGATTCharacteristicValueChangeListener";
+
+bool IsProperty (int propertyBits, bt_gatt_property_e property) {
+  return (propertyBits & property) != 0;
+}
+}
+
+BluetoothGATTService::BluetoothGATTService(BluetoothInstance& instance) :
+        instance_(instance)
+{
+  LoggerD("Entered");
+}
+
+BluetoothGATTService::~BluetoothGATTService() {
+  LoggerD("Entered");
+
+  for (auto it : gatt_characteristic_) {
+    // unregister callback, ignore errors
+    bt_gatt_client_unset_characteristic_value_changed_cb(it);
+  }
+
+  for (auto it : gatt_clients_) {
+    LoggerD("destroying client for address: %s", it.first.c_str());
+    bt_gatt_client_destroy(it.second);
+  }
+}
+
+bool BluetoothGATTService::IsStillConnected(const std::string& address) {
+  auto it = gatt_clients_.find(address);
+  return gatt_clients_.end() != it;
+}
+
+bt_gatt_client_h BluetoothGATTService::GetGattClient(const std::string& address) {
+  LoggerD("Entered");
+
+  bt_gatt_client_h client = nullptr;
+
+  const auto it = gatt_clients_.find(address);
+
+  if (gatt_clients_.end() == it) {
+    int ret = bt_gatt_client_create(address.c_str(), &client);
+    if (BT_ERROR_NONE != ret) {
+      LoggerE("Failed to create GATT client, error: %d", ret);
+    } else {
+      gatt_clients_.insert(std::make_pair(address, client));
+    }
+  } else {
+    LoggerD("Client already created");
+    client = it->second;
+  }
+
+  return client;
+}
+
+// this method should be used to inform this object that some device was disconnected
+void BluetoothGATTService::TryDestroyClient(const std::string &address) {
+  auto it = gatt_clients_.find(address);
+  if (gatt_clients_.end() != it) {
+    LoggerD("destroying client for address: %s", it->first.c_str());
+    bt_gatt_client_destroy(it->second);
+    gatt_clients_.erase(it);
+  } else {
+    LoggerD("Client for address: %s does not exist, no need for deletion",
+            address.c_str());
+  }
+}
+
+PlatformResult BluetoothGATTService::GetSpecifiedGATTService(const std::string &address,
+                                                             const std::string &uuid,
+                                                             picojson::object* result) {
+  LoggerD("Entered");
+
+  bt_gatt_client_h client = GetGattClient(address);
+
+  if (nullptr == client) {
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to create the GATT client's handle");
+  }
+
+  bt_gatt_h service = nullptr;
+  int ret = bt_gatt_client_get_service(client, uuid.c_str(), &service);
+  if (BT_ERROR_NONE != ret) {
+    LoggerE("bt_gatt_client_get_service() error: %d", ret);
+    switch (ret) {
+      case BT_ERROR_NO_DATA:
+        return PlatformResult(ErrorCode::NOT_FOUND_ERR, "Service not found");
+
+      case BT_ERROR_INVALID_PARAMETER:
+        return PlatformResult(ErrorCode::NOT_FOUND_ERR, "Service UUID is invalid");
+
+      default:
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get a service's GATT handle");
+    }
+  }
+
+  //report BluetoothGattService
+  result->insert(std::make_pair(kUuid, picojson::value(uuid)));
+  //handle is passed to upper layer because there is no need to delete it
+  result->insert(std::make_pair(kHandle, picojson::value((double)(long)service)));
+  //address is necessary to later check if device is still connected
+  result->insert(std::make_pair(kAddress, picojson::value(address)));
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+void BluetoothGATTService::GetServices(const picojson::value& args,
+                                       picojson::object& out) {
+  LoggerD("Entered");
+
+  bt_gatt_h handle = (bt_gatt_h) static_cast<long>(args.get("handle").get<double>());
+  const std::string& address = args.get("address").get<std::string>();
+
+  picojson::array array;
+  PlatformResult ret = GetServicesHelper(handle, address, &array);
+  if (ret.IsError()) {
+    LoggerE("Error while getting services");
+    ReportError(ret, &out);
+  } else {
+    ReportSuccess(picojson::value(array), out);
+  }
+}
+
+PlatformResult BluetoothGATTService::GetServicesHelper(bt_gatt_h handle,
+                                                       const std::string& address,
+                                                       picojson::array* array) {
+  LoggerD("Entered");
+
+  if (!IsStillConnected(address)) {
+    LoggerE("Device with address %s is no longer connected", address.c_str());
+    return PlatformResult(ErrorCode::INVALID_STATE_ERR,
+                          "Device is not connected");
+  }
+
+  int ret = bt_gatt_service_foreach_included_services(
+      handle,
+      [](int total, int index, bt_gatt_h gatt_handle, void *data) {
+        LoggerD("Enter");
+
+        picojson::value result = picojson::value(picojson::object());
+        picojson::object& result_obj = result.get<picojson::object>();
+
+        char* uuid = nullptr;
+
+        if (BT_ERROR_NONE == bt_gatt_get_uuid(gatt_handle, &uuid) && nullptr != uuid) {
+          result_obj.insert(std::make_pair(kUuid, picojson::value(uuid)));
+          free(uuid);
+        } else {
+          result_obj.insert(std::make_pair(kUuid, picojson::value("FFFF")));
+        }
+
+        //handle is passed to upper layer because there is no need of deletion
+        result_obj.insert(std::make_pair(kHandle, picojson::value((double)(long)gatt_handle)));
+        static_cast<picojson::array*>(data)->push_back(result);
+        return true;
+      }, array);
+  if (BT_ERROR_NONE != ret) {
+    LoggerE("Failed bt_gatt_service_foreach_included_services() (%d)", ret);
+    return util::GetBluetoothError(ret, "Failed to set a service's GATT callback");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+void BluetoothGATTService::GetCharacteristics(const picojson::value& args,
+                                              picojson::object& out) {
+  LoggerD("Entered");
+
+  bt_gatt_h handle = (bt_gatt_h) static_cast<long>(args.get("handle").get<double>());
+  const std::string& uuid = args.get("uuid").get<std::string>();
+  const std::string& address = args.get("address").get<std::string>();
+
+  picojson::array array;
+  PlatformResult ret = GetCharacteristicsHelper(handle, address, uuid, &array);
+  if (ret.IsError()) {
+    LoggerE("Error while getting characteristics");
+    ReportError(ret, &out);
+  } else {
+    ReportSuccess(picojson::value(array), out);
+  }
+}
+
+PlatformResult BluetoothGATTService::GetCharacteristicsHelper(bt_gatt_h handle,
+                                                              const std::string& address,
+                                                              const std::string& uuid,
+                                                              picojson::array* array) {
+  LoggerD("Entered");
+
+  if (!IsStillConnected(address)) {
+    LoggerE("Device with address %s is no longer connected", address.c_str());
+    return PlatformResult(ErrorCode::INVALID_STATE_ERR,
+                          "Device is not connected");
+  }
+
+  struct Data {
+    picojson::array* array;
+    PlatformResult* platform_res;
+  };
+
+  PlatformResult platform_result = PlatformResult(ErrorCode::NO_ERROR);
+  Data user_data = {array, &platform_result};
+
+  int ret = bt_gatt_service_foreach_characteristics(
+      handle,
+      [](int total, int index, bt_gatt_h gatt_handle, void *data) {
+        LoggerD("Enter");
+        Data* user_data = static_cast<Data*>(data);
+        picojson::array* array = user_data->array;
+        PlatformResult* platform_result = user_data->platform_res;
+
+        picojson::value result = picojson::value(picojson::object());
+        picojson::object& result_obj = result.get<picojson::object>();
+
+        //handle is passed to upper layer because there is no need of deletion
+        result_obj.insert(std::make_pair(kHandle, picojson::value((double)(long)gatt_handle)));
+
+        //descriptors
+        picojson::array& desc_array = result_obj.insert(
+            std::make_pair("descriptors", picojson::value(picojson::array()))).
+                first->second.get<picojson::array>();
+        int ret = bt_gatt_characteristic_foreach_descriptors(
+            gatt_handle,
+            [](int total, int index, bt_gatt_h desc_handle, void *data) {
+              LoggerD("Enter");
+              picojson::array& desc_array = *(static_cast<picojson::array*>(data));
+
+              picojson::value desc = picojson::value(picojson::object());
+              picojson::object& desc_obj = desc.get<picojson::object>();
+
+              //handle is passed to upper layer because there is no need of deletion
+              desc_obj.insert(std::make_pair(kHandle, picojson::value(
+                  (double)(long)desc_handle)));
+              desc_array.push_back(desc);
+              return true;
+            }, static_cast<void*>(&desc_array));
+        if (BT_ERROR_NONE != ret) {
+          *platform_result = util::GetBluetoothError(ret, "Failed to get descriptors");
+          LoggerE("Failed bt_gatt_characteristic_foreach_descriptors() (%d)", ret);
+          return false;
+        }
+
+        //other properties
+        int property_bits = 0;
+        int err = bt_gatt_characteristic_get_properties(gatt_handle, &property_bits);
+        if(BT_ERROR_NONE != err) {
+          LoggerE("Properties of characteristic couldn't be acquired");
+        }
+        result_obj.insert(std::make_pair(kBroadcast, picojson::value(
+            IsProperty(property_bits, BT_GATT_PROPERTY_BROADCAST))));
+        result_obj.insert(std::make_pair(kReadable, picojson::value(
+            IsProperty(property_bits, BT_GATT_PROPERTY_READ))));
+        result_obj.insert(std::make_pair(kWriteNoResponse, picojson::value(
+            IsProperty(property_bits, BT_GATT_PROPERTY_WRITE_WITHOUT_RESPONSE))));
+        result_obj.insert(std::make_pair(kWritable, picojson::value(
+            IsProperty(property_bits, BT_GATT_PROPERTY_WRITE))));
+        result_obj.insert(std::make_pair(kNotify, picojson::value(
+            IsProperty(property_bits, BT_GATT_PROPERTY_NOTIFY))));
+        result_obj.insert(std::make_pair(kIndication, picojson::value(
+            IsProperty(property_bits, BT_GATT_PROPERTY_INDICATE))));
+        result_obj.insert(std::make_pair(kSignedWrite, picojson::value(
+            IsProperty(property_bits, BT_GATT_PROPERTY_AUTHENTICATED_SIGNED_WRITES))));
+        result_obj.insert(std::make_pair(kExtendedProperties, picojson::value(
+            IsProperty(property_bits, BT_GATT_PROPERTY_EXTENDED_PROPERTIES))));
+
+        array->push_back(result);
+        return true;
+      }, static_cast<void*>(&user_data));
+  if (platform_result.IsError()) {
+    return platform_result;
+  }
+  if (BT_ERROR_NONE != ret) {
+    LoggerE("Failed (%d)", ret);
+    return util::GetBluetoothError(ret, "Failed while getting characteristic");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+void BluetoothGATTService::ReadValue(const picojson::value& args,
+                                     picojson::object& out) {
+  LoggerD("Entered");
+
+  const std::string& address = args.get("address").get<std::string>();
+  if (!IsStillConnected(address)) {
+    LoggerE("Device with address %s is no longer connected", address.c_str());
+    ReportError(PlatformResult(ErrorCode::INVALID_STATE_ERR,
+                               "Device is not connected"), &out);
+    return;
+  }
+
+  const double callback_handle = util::GetAsyncCallbackHandle(args);
+  struct Data {
+    double callback_handle;
+    BluetoothGATTService* service;
+  };
+
+  Data* user_data = new Data{callback_handle, this};
+  bt_gatt_h handle = (bt_gatt_h) static_cast<long>(args.get("handle").get<double>());
+
+  auto read_value = [](int result, bt_gatt_h handle, void *user_data) -> void {
+    Data* data = static_cast<Data*>(user_data);
+    double callback_handle = data->callback_handle;
+    BluetoothGATTService* service = data->service;
+    delete data;
+
+    PlatformResult plarform_res = PlatformResult(ErrorCode::NO_ERROR);
+
+    picojson::value byte_array = picojson::value(picojson::array());
+    picojson::array& byte_array_obj = byte_array.get<picojson::array>();
+
+    if (BT_ERROR_NONE != result) {
+      plarform_res = util::GetBluetoothError(result, "Error while reading value");
+    } else {
+      char *value = nullptr;
+      int length = 0;
+      int ret = bt_gatt_get_value(handle, &value, &length);
+      if (BT_ERROR_NONE != ret) {
+        plarform_res = util::GetBluetoothError(ret, "Error while getting value");
+      } else {
+        for (int i = 0 ; i < length; i++) {
+          byte_array_obj.push_back(picojson::value(std::to_string(value[i])));
+        }
+      }
+      if (value) {
+        free(value);
+        value = nullptr;
+      }
+    }
+
+    std::shared_ptr<picojson::value> response =
+        std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+    if (plarform_res.IsSuccess()) {
+      ReportSuccess(byte_array, response->get<picojson::object>());
+    } else {
+      ReportError(plarform_res, &response->get<picojson::object>());
+    }
+    TaskQueue::GetInstance().Async<picojson::value>(
+        [service, callback_handle](const std::shared_ptr<picojson::value>& response) {
+      service->instance_.SyncResponse(callback_handle, response);
+    }, response);
+  };
+  int ret = bt_gatt_client_read_value(handle, read_value, (void*)user_data);
+  if (BT_ERROR_NONE != ret) {
+    LOGE("Couldn't register callback for read value");
+  }
+  ReportSuccess(out);
+}
+
+
+void BluetoothGATTService::WriteValue(const picojson::value& args,
+                                     picojson::object& out) {
+  LoggerD("Entered");
+
+  const std::string& address = args.get("address").get<std::string>();
+  if (!IsStillConnected(address)) {
+    LoggerE("Device with address %s is no longer connected", address.c_str());
+    ReportError(PlatformResult(ErrorCode::INVALID_STATE_ERR,
+                               "Device is not connected"), &out);
+    return;
+  }
+
+  const double callback_handle = util::GetAsyncCallbackHandle(args);
+  const picojson::array& value_array = args.get("value").get<picojson::array>();
+
+  int value_size = value_array.size();
+  std::unique_ptr<char[]> value_data(new char[value_size]);
+  for (int i = 0; i < value_size; ++i) {
+    value_data[i] = static_cast<char>(value_array[i].get<double>());
+  }
+
+  struct Data {
+    double callback_handle;
+    BluetoothGATTService* service;
+  };
+
+  bt_gatt_h handle = (bt_gatt_h) static_cast<long>(args.get("handle").get<double>());
+
+  auto write_value = [](int result, bt_gatt_h handle, void *user_data) -> void {
+    Data* data = static_cast<Data*>(user_data);
+    double callback_handle = data->callback_handle;
+    BluetoothGATTService* service = data->service;
+    delete data;
+
+    PlatformResult ret = PlatformResult(ErrorCode::NO_ERROR);
+    if (BT_ERROR_NONE != result) {
+      ret = util::GetBluetoothError(result, "Error while getting value");
+    }
+
+    std::shared_ptr<picojson::value> response =
+        std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+    if (ret.IsSuccess()) {
+      ReportSuccess(response->get<picojson::object>());
+    } else {
+      ReportError(ret, &response->get<picojson::object>());
+    }
+    TaskQueue::GetInstance().Async<picojson::value>(
+        [service, callback_handle](const std::shared_ptr<picojson::value>& response) {
+      service->instance_.SyncResponse(callback_handle, response);
+    }, response);
+  };
+
+  int ret = bt_gatt_set_value(handle, value_data.get(), value_size);
+
+  if (BT_ERROR_NONE != ret) {
+    LoggerE("Couldn't set value");
+    std::shared_ptr<picojson::value> response =
+        std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+    ReportError(util::GetBluetoothError(ret, "Failed to set value"),
+                &response->get<picojson::object>());
+    TaskQueue::GetInstance().Async<picojson::value>(
+        [this, callback_handle](const std::shared_ptr<picojson::value>& response) {
+      instance_.SyncResponse(callback_handle, response);
+    }, response);
+  } else {
+    Data* user_data = new Data{callback_handle, this};
+    ret = bt_gatt_client_write_value(handle, write_value, user_data);
+    if (BT_ERROR_NONE != ret) {
+      delete user_data;
+      LoggerE("Couldn't register callback for write value");
+    }
+  }
+  ReportSuccess(out);
+}
+
+void BluetoothGATTService::AddValueChangeListener(const picojson::value& args,
+                                                  picojson::object& out) {
+  LoggerD("Entered");
+  const auto& address = args.get("address").get<std::string>();
+  if (!IsStillConnected(address)) {
+    LoggerE("Device with address %s is no longer connected", address.c_str());
+    ReportError(PlatformResult(ErrorCode::INVALID_STATE_ERR,
+                               "Device is not connected"), &out);
+    return;
+  }
+
+  bt_gatt_h handle = (bt_gatt_h)static_cast<long>(args.get(kHandle).get<double>());
+
+  int ret = bt_gatt_client_set_characteristic_value_changed_cb(handle, OnCharacteristicValueChanged, this);
+  if (BT_ERROR_NONE != ret) {
+    LoggerE("bt_gatt_client_set_characteristic_value_changed_cb() failed with: %d", ret);
+    ReportError(util::GetBluetoothError(ret, "Failed to register listener"), &out);
+  } else {
+    gatt_characteristic_.push_back(handle);
+    ReportSuccess(out);
+  }
+}
+
+void BluetoothGATTService::RemoveValueChangeListener(
+    const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+  const auto& address = args.get("address").get<std::string>();
+  if (!IsStillConnected(address)) {
+    LoggerE("Device with address %s is no longer connected", address.c_str());
+    ReportError(PlatformResult(ErrorCode::INVALID_STATE_ERR,
+                               "Device is not connected"), &out);
+    return;
+  }
+
+  bt_gatt_h handle = (bt_gatt_h)static_cast<long>(args.get(kHandle).get<double>());
+
+  int ret = bt_gatt_client_unset_characteristic_value_changed_cb(handle);
+
+  if (BT_ERROR_NONE != ret) {
+    LoggerE("bt_gatt_client_unset_characteristic_value_changed_cb() failed with: %d", ret);
+    ReportError(util::GetBluetoothError(ret, "Failed to unregister listener"), &out);
+  } else {
+    gatt_characteristic_.erase(std::remove(gatt_characteristic_.begin(), gatt_characteristic_.end(), handle), gatt_characteristic_.end());
+    ReportSuccess(out);
+  }
+}
+
+common::PlatformResult BluetoothGATTService::GetServiceUuids(
+    const std::string& address, picojson::array* array) {
+  LoggerD("Entered");
+
+  bt_gatt_client_h client = GetGattClient(address);
+
+  if (nullptr == client) {
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Unable to create client");
+  }
+
+  auto foreach_callback = [](int total, int index, bt_gatt_h gatt_handle, void* user_data) -> bool {
+    LoggerD("Entered foreach_callback, total: %d, index: %d", total, index);
+
+    char* uuid = nullptr;
+    int ret = bt_gatt_get_uuid(gatt_handle, &uuid);
+
+    if (BT_ERROR_NONE != ret || nullptr == uuid) {
+      LoggerE("Failed to get UUID: %d", ret);
+    } else {
+      std::string u = std::string(uuid);
+      free(uuid);
+      if (u.length() > 4) {  // 128-bit UUID, needs to be converted to 16-bit
+        u = u.substr(4, 4);
+      }
+      static_cast<picojson::array*>(user_data)->push_back(picojson::value(u));
+    }
+
+    return true;
+  };
+
+  int ret = bt_gatt_client_foreach_services(client, foreach_callback, array);
+
+  if (BT_ERROR_NONE == ret) {
+    return PlatformResult(ErrorCode::NO_ERROR);
+  } else {
+    LoggerE("Failed to get UUIDS: %d", ret);
+    return util::GetBluetoothError(ret, "Failed to get UUIDS");
+  }
+}
+
+void BluetoothGATTService::OnCharacteristicValueChanged(
+    bt_gatt_h characteristic, char* value, int length, void* user_data) {
+  LoggerD("Entered, characteristic: [%p], len: [d], user_data: [%p]", characteristic, length, user_data);
+
+  auto service = static_cast<BluetoothGATTService*>(user_data);
+
+  if (!service) {
+    LoggerE("user_data is NULL");
+    return;
+  }
+
+  picojson::value result = picojson::value(picojson::object());
+  picojson::object result_obj = result.get<picojson::object>();
+
+  result_obj.insert(std::make_pair(kHandle, picojson::value((double)(long)characteristic)));
+
+  picojson::value byte_array = picojson::value(picojson::array());
+  picojson::array& byte_array_obj = byte_array.get<picojson::array>();
+
+  for (int i = 0 ; i < length; ++i) {
+    byte_array_obj.push_back(picojson::value(std::to_string(value[i])));
+  }
+
+  ReportSuccess(byte_array, result_obj);
+
+  service->instance_.FireEvent(kOnValueChanged, result);
+}
+
+} // namespace bluetooth
+} // namespace extension
diff --git a/webWidgetTCT_device/src/bluetooth/bluetooth_gatt_service.h b/webWidgetTCT_device/src/bluetooth/bluetooth_gatt_service.h
new file mode 100755 (executable)
index 0000000..7fc8f2d
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2015 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 BLUETOOTH_BLUETOOTH_GATT_SERVICE_H_
+#define BLUETOOTH_BLUETOOTH_GATT_SERVICE_H_
+
+#include <map>
+
+#include <bluetooth.h>
+
+#include "common/picojson.h"
+#include "common/platform_result.h"
+
+namespace extension {
+namespace bluetooth {
+
+class BluetoothInstance;
+
+class BluetoothGATTService {
+ public:
+  BluetoothGATTService(BluetoothInstance& instance);
+  ~BluetoothGATTService();
+
+  common::PlatformResult GetSpecifiedGATTService(const std::string &address,
+                                                 const std::string &uuid,
+                                                 picojson::object* result);
+
+  void TryDestroyClient(const std::string &address);
+  void GetServices(const picojson::value& data, picojson::object& out);
+  void GetCharacteristics(const picojson::value& data, picojson::object& out);
+  void ReadValue(const picojson::value& args, picojson::object& out);
+  void WriteValue(const picojson::value& args, picojson::object& out);
+  void AddValueChangeListener(const picojson::value& args,
+                              picojson::object& out);
+  void RemoveValueChangeListener(const picojson::value& args,
+                                 picojson::object& out);
+
+  common::PlatformResult GetServiceUuids(const std::string& address,
+                                         picojson::array* array);
+
+ private:
+  bool IsStillConnected(const std::string& address);
+
+  bt_gatt_client_h GetGattClient(const std::string& address);
+
+  common::PlatformResult GetServicesHelper(bt_gatt_h handle, const std::string& address,
+                                                  picojson::array* array);
+  common::PlatformResult GetCharacteristicsHelper(bt_gatt_h handle,
+                                                  const std::string& address,
+                                                  const std::string& uuid,
+                                                  picojson::array* array);
+
+  static void OnCharacteristicValueChanged(bt_gatt_h characteristic,
+                                           char* value, int len,
+                                           void* user_data);
+
+  std::map<std::string, bt_gatt_client_h> gatt_clients_;
+  std::vector<bt_gatt_h> gatt_characteristic_;
+
+  BluetoothInstance& instance_;
+};
+
+} // namespace bluetooth
+} // namespace extension
+
+#endif // BLUETOOTH_BLUETOOTH_GATT_SERVICE_H_
diff --git a/webWidgetTCT_device/src/bluetooth/bluetooth_health_application.cc b/webWidgetTCT_device/src/bluetooth/bluetooth_health_application.cc
new file mode 100755 (executable)
index 0000000..4670815
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2015 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 "bluetooth_health_application.h"
+
+#include "common/converter.h"
+#include "common/logger.h"
+#include "common/extension.h"
+
+#include "bluetooth_health_profile_handler.h"
+#include "bluetooth_util.h"
+
+namespace extension {
+namespace bluetooth {
+
+namespace {
+const std::string kDataType = "dataType";
+const std::string kName = "name";
+const std::string kId = "_id";
+} // namespace
+
+using namespace common;
+
+BluetoothHealthApplication::BluetoothHealthApplication(
+    BluetoothHealthProfileHandler& handler)
+    : handler_(handler) {
+}
+
+void BluetoothHealthApplication::Unregister(const picojson::value& data, picojson::object& out) {
+  LoggerD("Entered");
+
+  const auto& args = util::GetArguments(data);
+
+  handler_.UnregisterSinkAppAsync(FromJson<std::string>(args, "id"),
+                                  util::GetAsyncCallbackHandle(data));
+
+  tools::ReportSuccess(out);
+}
+
+void BluetoothHealthApplication::ToJson(short data_type,
+                                        const std::string& name,
+                                        const char* id,
+                                        picojson::object* out) {
+  out->insert(std::make_pair(kDataType, picojson::value(static_cast<double>(data_type))));
+  out->insert(std::make_pair(kName, picojson::value(name)));
+  out->insert(std::make_pair(kId, picojson::value(id)));
+}
+
+} // namespace bluetooth
+} // namespace extension
diff --git a/webWidgetTCT_device/src/bluetooth/bluetooth_health_application.h b/webWidgetTCT_device/src/bluetooth/bluetooth_health_application.h
new file mode 100755 (executable)
index 0000000..e1f773b
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2015 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 BLUETOOTH_BLUETOOTH_HEALTH_APPLICATION_H_
+#define BLUETOOTH_BLUETOOTH_HEALTH_APPLICATION_H_
+
+
+#include "common/picojson.h"
+
+namespace extension {
+namespace bluetooth {
+
+class BluetoothHealthProfileHandler;
+
+class BluetoothHealthApplication {
+ public:
+  explicit BluetoothHealthApplication(BluetoothHealthProfileHandler& handler);
+
+  /**
+   * Signature: @code void unregister(successCallback, errorCallback); @endcode
+   * JSON: @code data: {method: 'BluetoothHealthApplication_unregister', args: {}} @endcode
+   * Invocation: @code native.call(request, result_callback); @endcode
+   * Return:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success'}
+   * @endcode
+   * Result callback:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success'}
+   * @endcode
+   */
+  void Unregister(const picojson::value& data, picojson::object& out);
+
+  static void ToJson(short data_type,
+                     const std::string& name,
+                     const char* id,
+                     picojson::object* out);
+
+ private:
+  BluetoothHealthProfileHandler& handler_;
+};
+
+} // namespace bluetooth
+} // namespace extension
+
+#endif // BLUETOOTH_BLUETOOTH_HEALTH_APPLICATION_H_
diff --git a/webWidgetTCT_device/src/bluetooth/bluetooth_health_channel.cc b/webWidgetTCT_device/src/bluetooth/bluetooth_health_channel.cc
new file mode 100755 (executable)
index 0000000..3825d32
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2015 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 "bluetooth_health_channel.h"
+
+#include <memory>
+
+#include "common/converter.h"
+#include "common/logger.h"
+#include "common/extension.h"
+
+#include "bluetooth_device.h"
+#include "bluetooth_util.h"
+
+namespace extension {
+namespace bluetooth {
+
+using namespace common;
+using namespace common::tools;
+
+namespace {
+const std::string kPeer = "peer";
+const std::string kChannelType = "channelType";
+const std::string kApplication = "appId";
+const std::string kIsConnected = "isConnected";
+const std::string kId = "_id";
+} // namespace
+
+void BluetoothHealthChannel::Close(const picojson::value& data , picojson::object& out) {
+  LoggerD("Entered");
+
+  const auto& args = util::GetArguments(data);
+
+  unsigned int channel = common::stol(FromJson<std::string>(args, "channel"));
+  const auto& address = FromJson<std::string>(args, "address");
+
+  if (BT_ERROR_NONE != bt_hdp_disconnect(address.c_str(), channel)) {
+    ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error"), &out);
+    return;
+  }
+
+  ReportSuccess(out);
+}
+
+void BluetoothHealthChannel::SendData(const picojson::value& data, picojson::object& out) {
+  LoggerD("Entered");
+
+  const auto& args = util::GetArguments(data);
+
+  unsigned int channel = common::stol(FromJson<std::string>(args, "channel"));
+  const auto& binary_data = FromJson<picojson::array>(args, "data");
+  const auto data_size = binary_data.size();
+
+  std::unique_ptr<char[]> data_ptr{new char[data_size]};
+
+  for (std::size_t i = 0; i < data_size; ++i) {
+    data_ptr[i] = static_cast<char>(binary_data[i].get<double>());
+  }
+
+  if (BT_ERROR_NONE != bt_hdp_send_data(channel, data_ptr.get(), data_size)) {
+    LoggerE("bt_hdp_send_data() failed");
+    ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error"), &out);
+    return;
+  }
+
+  ReportSuccess(picojson::value(static_cast<double>(data_size)), out);
+}
+
+void BluetoothHealthChannel::ToJson(unsigned int channel,
+                                    bt_hdp_channel_type_e type,
+                                    picojson::object* out) {
+  LoggerD("Enter");
+  const char* type_str = "UNKNOWN";
+
+  switch (type) {
+    case BT_HDP_CHANNEL_TYPE_RELIABLE:
+      type_str = "RELIABLE";
+      break;
+
+    case BT_HDP_CHANNEL_TYPE_STREAMING:
+      type_str = "STREAMING";
+      break;
+
+    default:
+      LoggerE("Unknown HDP channel type: %d", type);
+      break;
+  }
+
+  out->insert(std::make_pair(kId, picojson::value(std::to_string(channel))));
+  out->insert(std::make_pair(kChannelType, picojson::value(type_str)));
+  out->insert(std::make_pair(kIsConnected, picojson::value(true)));
+}
+
+void BluetoothHealthChannel::ToJson(unsigned int channel,
+                                    bt_hdp_channel_type_e type,
+                                    bt_device_info_s* device_info,
+                                    const char* app_id,
+                                    picojson::object* out) {
+  LoggerD("Enter");
+  ToJson(channel, type, out);
+  auto& device = out->insert(
+      std::make_pair(kPeer, picojson::value(picojson::object()))) .first->second.get<picojson::object>();
+
+  BluetoothDevice::ToJson(device_info, &device);
+  out->insert(std::make_pair(kApplication, picojson::value(app_id)));
+}
+
+} // namespace bluetooth
+} // namespace extension
diff --git a/webWidgetTCT_device/src/bluetooth/bluetooth_health_channel.h b/webWidgetTCT_device/src/bluetooth/bluetooth_health_channel.h
new file mode 100755 (executable)
index 0000000..922d370
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2015 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 BLUETOOTH_BLUETOOTH_HEALTH_CHANNEL_H_
+#define BLUETOOTH_BLUETOOTH_HEALTH_CHANNEL_H_
+
+#include <bluetooth.h>
+
+#include "common/picojson.h"
+
+namespace extension {
+namespace bluetooth {
+
+class BluetoothHealthChannel {
+ public:
+  /**
+   * Signature: @code void close(); @endcode
+   * JSON: @code data: {method: 'BluetoothHealthChannel_close', args: {}} @endcode
+   * Invocation: @code native.callSync(request); @endcode
+   * Return:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success'}
+   * @endcode
+   */
+  void Close(const picojson::value& data, picojson::object& out);
+
+  /**
+   * Signature: @code unsigned long sendData(data[]); @endcode
+   * JSON: @code data: {method: 'BluetoothHealthChannel_sendData', args: {data: data}} @endcode
+   * Invocation: @code native.callSync(request); @endcode
+   * Return:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success', result: {bytes_sent}}
+   */
+  void SendData(const picojson::value& data, picojson::object& out);
+
+  static void ToJson(unsigned int channel,
+                     bt_hdp_channel_type_e type,
+                     picojson::object* out);
+
+  static void ToJson(unsigned int channel,
+                     bt_hdp_channel_type_e type,
+                     bt_device_info_s* device_info,
+                     const char* app_id,
+                     picojson::object* out);
+};
+
+} // namespace bluetooth
+} // namespace extension
+
+#endif // BLUETOOTH_BLUETOOTH_HEALTH_CHANNEL_H_
diff --git a/webWidgetTCT_device/src/bluetooth/bluetooth_health_profile_handler.cc b/webWidgetTCT_device/src/bluetooth/bluetooth_health_profile_handler.cc
new file mode 100755 (executable)
index 0000000..34dc7d4
--- /dev/null
@@ -0,0 +1,388 @@
+/*
+ * Copyright (c) 2015 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 "bluetooth_health_profile_handler.h"
+
+#include "common/converter.h"
+#include "common/logger.h"
+#include "common/extension.h"
+#include "common/task-queue.h"
+
+#include "bluetooth/bluetooth_adapter.h"
+#include "bluetooth/bluetooth_instance.h"
+#include "bluetooth/bluetooth_health_application.h"
+#include "bluetooth/bluetooth_health_channel.h"
+#include "bluetooth/bluetooth_util.h"
+
+namespace extension {
+namespace bluetooth {
+
+using namespace common;
+using namespace common::tools;
+
+namespace {
+const std::string kId = "id";
+const std::string kEvent = "event";
+const std::string kData = "data";
+const std::string kOnConnect = "onconnect";
+const std::string kOnClose = "onclose";
+const std::string kOnMessage = "onmessage";
+const std::string kChangeCallback = "BluetoothHealthChannelChangeCallback";
+} //namespace
+
+BluetoothHealthProfileHandler::BluetoothHealthProfileHandler(BluetoothInstance& instance)
+    : instance_(instance) {
+  // initialize listeners
+  LoggerD("Entered");
+  if (BT_ERROR_NONE != bt_hdp_set_connection_state_changed_cb(OnConnected, OnDisconnected, this)) {
+    LoggerE("bt_hdp_set_connection_state_changed_cb() failed");
+  }
+
+  if (BT_ERROR_NONE != bt_hdp_set_data_received_cb(OnDataReceived, this)) {
+    LoggerE("bt_hdp_set_data_received_cb() failed");
+  }
+}
+
+BluetoothHealthProfileHandler::~BluetoothHealthProfileHandler() {
+  LoggerD("Entered");
+  bt_hdp_unset_connection_state_changed_cb();
+  bt_hdp_unset_data_received_cb();
+
+  for (auto& it : registered_health_apps_) {
+    bt_hdp_unregister_sink_app(it.c_str());
+  }
+}
+
+void BluetoothHealthProfileHandler::OnConnected(int result,
+                                                const char* remote_address,
+                                                const char* app_id,
+                                                bt_hdp_channel_type_e type,
+                                                unsigned int channel,
+                                                void* user_data) {
+  LoggerD("Entered");
+
+  BluetoothHealthProfileHandler* object = static_cast<BluetoothHealthProfileHandler*>(user_data);
+
+  if (!object) {
+    LoggerW("user_data is NULL");
+    return;
+  }
+
+  if (BT_ERROR_NONE != result) {
+    LoggerD("Not BT_ERROR_NONE: %d", result);
+  }
+
+  LoggerD("Connected app: %s", app_id);
+  LoggerD("Connected channel: %u", channel);
+
+  const auto iter = object->registered_health_apps_.find(app_id);
+
+  if (iter == object->registered_health_apps_.end()) {
+    LoggerW("This app is not registered: %s", app_id);
+    return;
+  }
+
+  bool channel_added = false;
+
+  if (BT_ERROR_NONE == result) {
+    // send BluetoothHealthApplication.onconnect notification
+    bt_device_info_s* device_info = nullptr;
+
+    if (BT_ERROR_NONE == bt_adapter_get_bonded_device_info(remote_address, &device_info) &&
+        nullptr != device_info) {
+      LoggerD("invoke BluetoothHealthApplication.onconnect");
+
+      object->connected_channels_.insert(channel);
+      channel_added = true;
+
+      picojson::value response{picojson::object()};
+      picojson::object& response_obj = response.get<picojson::object>();
+      response_obj.insert(std::make_pair(kId, picojson::value(app_id)));
+      response_obj.insert(std::make_pair(kEvent, picojson::value(kOnConnect)));
+
+      picojson::value result = picojson::value(picojson::object());
+
+      BluetoothHealthChannel::ToJson(channel,
+                                     type,
+                                     device_info,
+                                     app_id,
+                                     &result.get<picojson::object>());
+
+      ReportSuccess(result, response_obj);
+      bt_adapter_free_device_info(device_info);
+
+      object->instance_.FireEvent("BLUETOOTH_HEALTH_APPLICATION_CHANGED", response);
+    } else {
+      LoggerE("Failed to get device info");
+    }
+  }
+
+  // Handle requests from  BluetoothHealthProfileHandler.connectToSource()
+  const auto request = object->connection_requests_.find(app_id);
+
+  if (request != object->connection_requests_.end()) {
+    LoggerD("Requested connection");
+
+    std::shared_ptr<picojson::value> response{new picojson::value(picojson::object())};
+
+    if (BT_ERROR_NONE == result) {
+      if (!channel_added) {
+        object->connected_channels_.insert(channel);
+      }
+
+      picojson::value result = picojson::value(picojson::object());
+
+      BluetoothHealthChannel::ToJson(channel,
+                                     type,
+                                     &result.get<picojson::object>());
+
+      ReportSuccess(result, response->get<picojson::object>());
+    } else {
+      LoggerE("Failed to establish a connection with health profile");
+      ReportError(PlatformResult(
+          ErrorCode::UNKNOWN_ERR, "Failed to establish a connection with health profile"),
+                  &response->get<picojson::object>());
+    }
+
+    object->instance_.AsyncResponse(request->second, response);
+
+    // request was handled, remove
+    object->connection_requests_.erase(request);
+  }
+  else {
+    LoggerD("This connection was not requested.");
+  }
+}
+
+void BluetoothHealthProfileHandler::OnDisconnected(int result,
+                                                   const char* /* remote_address */,
+                                                   unsigned int channel,
+                                                   void* user_data) {
+  LoggerD("Entered");
+
+  BluetoothHealthProfileHandler* object = static_cast<BluetoothHealthProfileHandler*>(user_data);
+
+  if (!object) {
+    LoggerE("user_data is NULL");
+    return;
+  }
+
+  auto it = object->connected_channels_.find(channel);
+  if (BT_ERROR_NONE == result && object->connected_channels_.end() != it) {
+    object->connected_channels_.erase(it);
+    picojson::value value = picojson::value(picojson::object());
+    picojson::object* data_obj = &value.get<picojson::object>();
+
+    data_obj->insert(std::make_pair(kEvent, picojson::value(kOnClose)));
+    data_obj->insert(std::make_pair(kId, picojson::value(std::to_string(channel))));
+    object->instance_.FireEvent(kChangeCallback, value);
+  }
+}
+
+void BluetoothHealthProfileHandler::OnDataReceived(unsigned int channel,
+                                                   const char* data,
+                                                   unsigned int size,
+                                                   void* user_data) {
+  LoggerD("Entered");
+
+  BluetoothHealthProfileHandler* object = static_cast<BluetoothHealthProfileHandler*>(user_data);
+
+  if (!object) {
+    LoggerE("user_data is NULL");
+    return;
+  }
+
+  auto it = object->connected_channels_.find(channel);
+  if (object->connected_channels_.end() != it) {
+    picojson::value value = picojson::value(picojson::object());
+    picojson::object* data_obj = &value.get<picojson::object>();
+
+    data_obj->insert(std::make_pair(kEvent, picojson::value(kOnMessage)));
+    data_obj->insert(std::make_pair(kId, picojson::value(std::to_string(channel))));
+
+    picojson::array& array = data_obj->insert(std::make_pair(kData, picojson::value(
+        picojson::array()))).first->second.get<picojson::array>();
+
+    for (unsigned int i = 0; i < size; i++) {
+      array.push_back(picojson::value(static_cast<double>(data[i])));
+    }
+
+    object->instance_.FireEvent(kChangeCallback, value);
+  }
+}
+
+void BluetoothHealthProfileHandler::RegisterSinkApp(const picojson::value& data, picojson::object& out) {
+  LoggerD("Entered");
+
+  const auto& args = util::GetArguments(data);
+  const auto data_type = static_cast<short>(FromJson<double>(args, "dataType"));
+  const auto& name = FromJson<std::string>(args, "name");
+
+  const auto callback_handle = util::GetAsyncCallbackHandle(data);
+
+  auto register_app = [data_type, name, this](const std::shared_ptr<picojson::value>& response) -> void {
+    LoggerD("Entered");
+
+    PlatformResult platform_result = PlatformResult(ErrorCode::NO_ERROR);
+    char* app_id = nullptr;
+    const int ret = bt_hdp_register_sink_app(data_type, &app_id);
+
+    switch (ret) {
+      case BT_ERROR_NONE:
+      {
+        LoggerD("Registered app: %s", app_id);
+
+        this->registered_health_apps_.insert(app_id);
+
+        picojson::value result = picojson::value(picojson::object());
+        BluetoothHealthApplication::ToJson(data_type,
+                                           name,
+                                           app_id,
+                                           &result.get<picojson::object>());
+        ReportSuccess(result, response->get<picojson::object>());
+        return;
+      }
+
+      case BT_ERROR_NOT_ENABLED:
+        LoggerE("Bluetooth device is turned off");
+        platform_result = PlatformResult(
+            ErrorCode::SERVICE_NOT_AVAILABLE_ERR, "Bluetooth device is turned off");
+        break;
+
+      default:
+        LoggerE("bt_hdp_register_sink_app() failed: %d", ret);
+        platform_result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error");
+        break;
+    }
+
+    ReportError(platform_result, &response->get<picojson::object>());
+  };
+
+  auto register_app_response = [this, callback_handle](const std::shared_ptr<picojson::value>& response) -> void {
+    instance_.SyncResponse(callback_handle, response);
+  };
+
+  auto queue_data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+
+  TaskQueue::GetInstance().Queue<picojson::value>(
+      register_app,
+      register_app_response,
+      queue_data);
+
+  ReportSuccess(out);
+}
+
+void BluetoothHealthProfileHandler::ConnectToSource(const picojson::value& data, picojson::object& out) {
+  LoggerD("Entered");
+
+  const auto& args = util::GetArguments(data);
+  const auto& address = FromJson<std::string>(args, "address");
+  const auto& app_id = FromJson<std::string>(args, "appId");
+
+  LoggerD("address: %s", address.c_str());
+  LoggerD("app ID: %s", app_id.c_str());
+
+  const auto callback_handle = util::GetAsyncCallbackHandle(data);
+
+  PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
+  const int ret = bt_hdp_connect_to_source(address.c_str(), app_id.c_str());
+
+  switch (ret) {
+    case BT_ERROR_NONE: {
+      LoggerD("bt_hdp_connect_to_source() succeeded");
+
+      connection_requests_.insert(std::make_pair(app_id, callback_handle));
+      break;
+    }
+
+    case BT_ERROR_NOT_ENABLED:
+      result = PlatformResult(
+          ErrorCode::SERVICE_NOT_AVAILABLE_ERR, "Bluetooth device is turned off");
+      break;
+
+    case BT_ERROR_INVALID_PARAMETER:
+    case BT_ERROR_REMOTE_DEVICE_NOT_BONDED:
+      result = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid value");
+      break;
+
+    default:
+      result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown exception");
+      break;
+  }
+
+  if (result.IsError()) {
+    instance_.AsyncResponse(callback_handle, result);
+  }
+
+  ReportSuccess(out);
+}
+
+void BluetoothHealthProfileHandler::UnregisterSinkAppAsync(const std::string& app_id,
+                                                           int callback_handle) {
+  LoggerD("Entered");
+
+  auto unregister_app = [app_id, this](const std::shared_ptr<picojson::value>& response) -> void {
+    LoggerD("Entered");
+
+    PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
+    auto iter = this->registered_health_apps_.find(app_id);
+
+    if (iter != this->registered_health_apps_.end()) {
+      LoggerD("Found registered Health Application: %s", app_id.c_str());
+
+      const int ret = bt_hdp_unregister_sink_app(app_id.c_str());
+
+      switch(ret) {
+        case BT_ERROR_NONE:
+          this->registered_health_apps_.erase(iter);
+          break;
+
+        case BT_ERROR_NOT_ENABLED:
+          LoggerE("Bluetooth device is turned off");
+          result = PlatformResult(
+              ErrorCode::SERVICE_NOT_AVAILABLE_ERR, "Bluetooth device is turned off");
+          break;
+
+        default:
+          LoggerE("bt_hdp_unregister_sink_app() failed: %d", ret);
+          result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown exception");
+          break;
+      }
+    } else {
+      LoggerD("Already unregistered");
+    }
+
+    if (result.IsSuccess()) {
+      ReportSuccess(response->get<picojson::object>());
+    } else {
+      ReportError(result, &response->get<picojson::object>());
+    }
+  };
+
+  auto unregister_app_response = [this, callback_handle](const std::shared_ptr<picojson::value>& response) -> void {
+    instance_.SyncResponse(callback_handle, response);
+  };
+
+  auto data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+
+  TaskQueue::GetInstance().Queue<picojson::value>(
+      unregister_app,
+      unregister_app_response,
+      data);
+}
+
+} // namespace bluetooth
+} // namespace extension
diff --git a/webWidgetTCT_device/src/bluetooth/bluetooth_health_profile_handler.h b/webWidgetTCT_device/src/bluetooth/bluetooth_health_profile_handler.h
new file mode 100755 (executable)
index 0000000..9b4bada
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2015 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 BLUETOOTH_BLUETOOTH_HEALTH_PROFILE_HANDLER_H_
+#define BLUETOOTH_BLUETOOTH_HEALTH_PROFILE_HANDLER_H_
+
+#include <set>
+
+#include <bluetooth.h>
+
+#include "common/picojson.h"
+
+namespace extension {
+namespace bluetooth {
+
+class BluetoothInstance;
+
+class BluetoothHealthProfileHandler {
+ public:
+  /**
+   * Signature: @code void registerSinkApp(dataType, name, successCallback, errorCallback); @endcode
+   * JSON: @code data: {method: 'BluetoothHealthProfileHandler_registerSinkApp',
+   *                    args: {dataType: dataType, name: name}} @endcode
+   * Invocation: @code native.call(request, result_callback); @endcode
+   * Return:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success'}
+   * @endcode
+   * Result callback:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success', result: {application}}
+   * @endcode
+   */
+  void RegisterSinkApp(const picojson::value& data, picojson::object& out);
+
+  /**
+   * Signature: @code void connectToSource(peer, application, successCallback, errorCallback); @endcode
+   * JSON: @code data: {method: 'BluetoothHealthProfileHandler_connectToSource',
+   *                    args: {peer: peer, application: application}} @endcode
+   * Invocation: @code native.call(request, result_callback); @endcode
+   * Return:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success'}
+   * @endcode
+   * Result callback:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success', result: {channel}}
+   * @endcode
+   */
+  void ConnectToSource(const picojson::value& data, picojson::object& out);
+
+  explicit BluetoothHealthProfileHandler(BluetoothInstance& instance);
+  ~BluetoothHealthProfileHandler();
+
+  void UnregisterSinkAppAsync(const std::string& app_id, int callback_handle);
+
+ private:
+  BluetoothHealthProfileHandler(const BluetoothHealthProfileHandler&) = delete;
+  BluetoothHealthProfileHandler& operator=(const BluetoothHealthProfileHandler&) = delete;
+
+  static void OnConnected(int result,
+                          const char* remote_address,
+                          const char* app_id,
+                          bt_hdp_channel_type_e type,
+                          unsigned int channel,
+                          void* user_data);
+
+  static void OnDisconnected(int result,
+                             const char* remote_address,
+                             unsigned int channel,
+                             void* user_data);
+
+  static void OnDataReceived(unsigned int channel,
+                             const char* data,
+                             unsigned int size,
+                             void* user_data);
+
+  std::set<std::string> registered_health_apps_;
+  std::map<std::string, double> connection_requests_;
+  std::set<unsigned int> connected_channels_;
+
+  BluetoothInstance& instance_;
+};
+
+} // namespace bluetooth
+} // namespace extension
+
+#endif // BLUETOOTH_BLUETOOTH_HEALTH_PROFILE_HANDLER_H_
diff --git a/webWidgetTCT_device/src/bluetooth/bluetooth_instance.cc b/webWidgetTCT_device/src/bluetooth/bluetooth_instance.cc
new file mode 100755 (executable)
index 0000000..2351162
--- /dev/null
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 2015 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 "bluetooth_instance.h"
+
+#include "common/converter.h"
+#include "common/logger.h"
+#include "common/task-queue.h"
+
+namespace extension {
+namespace bluetooth {
+
+using namespace common;
+
+BluetoothInstance::BluetoothInstance() :
+    bluetooth_adapter_(*this),
+    bluetooth_device_(bluetooth_adapter_),
+    bluetooth_health_application_(bluetooth_health_profile_handler_),
+    bluetooth_health_profile_handler_(*this),
+    bluetooth_service_handler_(bluetooth_adapter_),
+    bluetooth_socket_(bluetooth_adapter_),
+    bluetooth_le_adapter_(*this),
+    bluetooth_gatt_service_(*this),
+    bluetooth_le_device_(*this, bluetooth_gatt_service_)
+{
+  LoggerD("Entered");
+  using std::placeholders::_1;
+  using std::placeholders::_2;
+
+  #define REGISTER_ASYNC(c, func) \
+      RegisterSyncHandler(c, func);
+  #define REGISTER_SYNC(c, func) \
+      RegisterSyncHandler(c, func);
+
+  // BluetoothAdapter
+  REGISTER_ASYNC("BluetoothAdapter_setName",
+      std::bind(&BluetoothAdapter::SetName, &bluetooth_adapter_, _1, _2));
+  REGISTER_ASYNC("BluetoothAdapter_setPowered",
+      std::bind(&BluetoothAdapter::SetPowered, &bluetooth_adapter_, _1, _2));
+  REGISTER_ASYNC("BluetoothAdapter_setVisible",
+      std::bind(&BluetoothAdapter::SetVisible, &bluetooth_adapter_, _1, _2));
+  REGISTER_SYNC("BluetoothAdapter_discoverDevices",
+      std::bind(&BluetoothAdapter::DiscoverDevices, &bluetooth_adapter_, _1, _2));
+  REGISTER_ASYNC("BluetoothAdapter_stopDiscovery",
+      std::bind(&BluetoothAdapter::StopDiscovery, &bluetooth_adapter_, _1, _2));
+  REGISTER_ASYNC("BluetoothAdapter_getKnownDevices",
+      std::bind(&BluetoothAdapter::GetKnownDevices, &bluetooth_adapter_, _1, _2));
+  REGISTER_ASYNC("BluetoothAdapter_getDevice",
+      std::bind(&BluetoothAdapter::GetDevice, &bluetooth_adapter_, _1, _2));
+  REGISTER_ASYNC("BluetoothAdapter_createBonding",
+      std::bind(&BluetoothAdapter::CreateBonding, &bluetooth_adapter_, _1, _2));
+  REGISTER_ASYNC("BluetoothAdapter_destroyBonding",
+      std::bind(&BluetoothAdapter::DestroyBonding, &bluetooth_adapter_, _1, _2));
+  REGISTER_ASYNC("BluetoothAdapter_registerRFCOMMServiceByUUID",
+      std::bind(&BluetoothAdapter::RegisterRFCOMMServiceByUUID, &bluetooth_adapter_, _1, _2));
+  REGISTER_SYNC("BluetoothAdapter_getBluetoothProfileHandler",
+      std::bind(&BluetoothAdapter::GetBluetoothProfileHandler, &bluetooth_adapter_, _1, _2));
+  REGISTER_SYNC("BluetoothAdapter_getName",
+      std::bind(&BluetoothAdapter::GetName, &bluetooth_adapter_, _1, _2));
+  REGISTER_SYNC("BluetoothAdapter_getAddress",
+      std::bind(&BluetoothAdapter::GetAddress, &bluetooth_adapter_, _1, _2));
+  REGISTER_SYNC("BluetoothAdapter_getPowered",
+      std::bind(&BluetoothAdapter::GetPowered, &bluetooth_adapter_, _1, _2));
+  REGISTER_SYNC("BluetoothAdapter_getVisible",
+      std::bind(&BluetoothAdapter::GetVisible, &bluetooth_adapter_, _1, _2));
+  REGISTER_SYNC("BluetoothAdapter_isServiceConnected",
+      std::bind(&BluetoothAdapter::IsServiceConnected, &bluetooth_adapter_, _1, _2));
+
+  // BluetoothDevice
+  REGISTER_ASYNC("BluetoothDevice_connectToServiceByUUID",
+      std::bind(&BluetoothDevice::ConnectToServiceByUUID, &bluetooth_device_, _1, _2));
+  REGISTER_SYNC("BluetoothDevice_getBoolValue",
+      std::bind(&BluetoothDevice::GetBoolValue, &bluetooth_device_, _1, _2));
+
+  // BluetoothHealthApplication
+  REGISTER_ASYNC("BluetoothHealthApplication_unregister",
+      std::bind(&BluetoothHealthApplication::Unregister, &bluetooth_health_application_, _1, _2));
+
+  // BluetoothHealthChannel
+  REGISTER_SYNC("BluetoothHealthChannel_close",
+      std::bind(&BluetoothHealthChannel::Close, &bluetooth_health_channel_, _1, _2));
+  REGISTER_SYNC("BluetoothHealthChannel_sendData",
+      std::bind(&BluetoothHealthChannel::SendData, &bluetooth_health_channel_, _1, _2));
+
+  // BluetoothHealthProfileHandler
+  REGISTER_ASYNC("BluetoothHealthProfileHandler_registerSinkApp",
+      std::bind(&BluetoothHealthProfileHandler::RegisterSinkApp, &bluetooth_health_profile_handler_, _1, _2));
+  REGISTER_ASYNC("BluetoothHealthProfileHandler_connectToSource",
+      std::bind(&BluetoothHealthProfileHandler::ConnectToSource, &bluetooth_health_profile_handler_, _1, _2));
+
+  // BluetoothServiceHandler
+  REGISTER_ASYNC("BluetoothServiceHandler_unregister",
+      std::bind(&BluetoothServiceHandler::Unregister, &bluetooth_service_handler_, _1, _2));
+
+  // BluetoothSocket
+  REGISTER_SYNC("BluetoothSocket_writeData",
+      std::bind(&BluetoothSocket::WriteData, &bluetooth_socket_, _1, _2));
+  REGISTER_SYNC("BluetoothSocket_readData",
+      std::bind(&BluetoothSocket::ReadData, &bluetooth_socket_, _1, _2));
+  REGISTER_SYNC("BluetoothSocket_close",
+      std::bind(&BluetoothSocket::Close, &bluetooth_socket_, _1, _2));
+
+  // BluetoothLEAdapter
+  REGISTER_SYNC("BluetoothLEAdapter_startScan",
+      std::bind(&BluetoothLEAdapter::StartScan, &bluetooth_le_adapter_, _1, _2));
+  REGISTER_SYNC("BluetoothLEAdapter_stopScan",
+      std::bind(&BluetoothLEAdapter::StopScan, &bluetooth_le_adapter_, _1, _2));
+  REGISTER_SYNC("BluetoothLEAdapter_startAdvertise",
+      std::bind(&BluetoothLEAdapter::StartAdvertise, &bluetooth_le_adapter_, _1, _2));
+  REGISTER_SYNC("BluetoothLEAdapter_stopAdvertise",
+      std::bind(&BluetoothLEAdapter::StopAdvertise, &bluetooth_le_adapter_, _1, _2));
+
+  // BluetoothLEDevice
+  REGISTER_ASYNC(
+      "BluetoothLEDevice_connect",
+      std::bind(&BluetoothLEDevice::Connect, &bluetooth_le_device_, _1, _2));
+  REGISTER_ASYNC(
+      "BluetoothLEDevice_disconnect",
+      std::bind(&BluetoothLEDevice::Disconnect, &bluetooth_le_device_, _1, _2));
+  REGISTER_SYNC(
+      "BluetoothLEDevice_getService",
+      std::bind(&BluetoothLEDevice::GetService, &bluetooth_le_device_, _1, _2));
+  REGISTER_SYNC(
+      "BluetoothLEDevice_addConnectStateChangeListener",
+      std::bind(&BluetoothLEDevice::AddConnectStateChangeListener,
+                &bluetooth_le_device_, _1, _2));
+  REGISTER_SYNC(
+      "BluetoothLEDevice_removeConnectStateChangeListener",
+      std::bind(&BluetoothLEDevice::RemoveConnectStateChangeListener,
+                &bluetooth_le_device_, _1, _2));
+  REGISTER_SYNC(
+        "BluetoothLEDevice_getServiceUuids",
+        std::bind(&BluetoothLEDevice::GetServiceUuids,
+                  &bluetooth_le_device_, _1, _2));
+
+  // BluetoothGATTService
+  REGISTER_SYNC("BluetoothGATTService_getServices",
+      std::bind(&BluetoothGATTService::GetServices, &bluetooth_gatt_service_, _1, _2));
+  REGISTER_SYNC("BluetoothGATTService_getCharacteristics",
+      std::bind(&BluetoothGATTService::GetCharacteristics, &bluetooth_gatt_service_, _1, _2));
+  REGISTER_SYNC("BluetoothGATT_readValue",
+      std::bind(&BluetoothGATTService::ReadValue, &bluetooth_gatt_service_, _1, _2));
+  REGISTER_SYNC("BluetoothGATT_writeValue",
+      std::bind(&BluetoothGATTService::WriteValue, &bluetooth_gatt_service_, _1, _2));
+  REGISTER_SYNC(
+      "BluetoothGATTCharacteristic_addValueChangeListener",
+      std::bind(&BluetoothGATTService::AddValueChangeListener,
+                &bluetooth_gatt_service_, _1, _2));
+  REGISTER_SYNC(
+      "BluetoothGATTCharacteristic_removeValueChangeListener",
+      std::bind(&BluetoothGATTService::RemoveValueChangeListener,
+                &bluetooth_gatt_service_, _1, _2));
+
+  #undef REGISTER_ASYNC
+  #undef REGISTER_SYNC
+}
+
+BluetoothInstance::~BluetoothInstance()
+{
+  LoggerD("Entered");
+}
+
+namespace {
+const char* JSON_CALLBACK_ID = "callbackId";
+const char* JSON_LISTENER_ID = "listenerId";
+} // namespace
+
+void BluetoothInstance::AsyncResponse(double callback_handle, const std::shared_ptr<picojson::value>& response) {
+  LoggerD("Entered");
+  common::TaskQueue::GetInstance().Async<picojson::value>([this, callback_handle](const std::shared_ptr<picojson::value>& response) {
+    SyncResponse(callback_handle, response);
+  }, response);
+}
+
+void BluetoothInstance::AsyncResponse(double callback_handle, const PlatformResult& result) {
+  LoggerD("Entered");
+  std::shared_ptr<picojson::value> response =
+      std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+
+  if (result.IsError()) {
+    tools::ReportError(result, &response->get<picojson::object>());
+  } else {
+    tools::ReportSuccess(response->get<picojson::object>());
+  }
+
+  TaskQueue::GetInstance().Async<picojson::value>([this, callback_handle](const std::shared_ptr<picojson::value>& response) {
+    SyncResponse(callback_handle, response);
+  }, response);
+}
+
+void BluetoothInstance::SyncResponse(double callback_handle, const std::shared_ptr<picojson::value>& response) {
+  LoggerD("Entered");
+  auto& obj = response->get<picojson::object>();
+  obj[JSON_CALLBACK_ID] = picojson::value(callback_handle);
+  Instance::PostMessage(this, response->serialize().c_str());
+}
+
+void BluetoothInstance::FireEvent(const std::string& event, picojson::value& value) {
+  LoggerD("Entered");
+  auto& obj = value.get<picojson::object>();
+  obj[JSON_LISTENER_ID] = picojson::value(event);
+  Instance::PostMessage(this, value.serialize().c_str());
+}
+
+void BluetoothInstance::FireEvent(const std::string& event, const picojson::value& value) {
+  LoggerD("Entered");
+  picojson::value v{value};
+  FireEvent(event, v);
+}
+
+void BluetoothInstance::FireEvent(const std::string& event, const std::shared_ptr<picojson::value>& value) {
+  LoggerD("Entered");
+  FireEvent(event, *value.get());
+}
+
+
+} // namespace bluetooth
+} // namespace extension
+
diff --git a/webWidgetTCT_device/src/bluetooth/bluetooth_instance.h b/webWidgetTCT_device/src/bluetooth/bluetooth_instance.h
new file mode 100755 (executable)
index 0000000..daeabef
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2015 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 BLUETOOTH_BLUETOOTH_INSTANCE_H_
+#define BLUETOOTH_BLUETOOTH_INSTANCE_H_
+
+#include "common/extension.h"
+
+#include "bluetooth/bluetooth_adapter.h"
+#include "bluetooth/bluetooth_device.h"
+#include "bluetooth/bluetooth_health_application.h"
+#include "bluetooth/bluetooth_health_channel.h"
+#include "bluetooth/bluetooth_health_profile_handler.h"
+#include "bluetooth/bluetooth_le_adapter.h"
+#include "bluetooth/bluetooth_le_device.h"
+#include "bluetooth/bluetooth_service_handler.h"
+#include "bluetooth/bluetooth_socket.h"
+#include "bluetooth/bluetooth_gatt_service.h"
+#include "bluetooth/bluetooth_util.h"
+
+namespace extension {
+namespace bluetooth {
+
+class BluetoothInstance: public common::ParsedInstance {
+ public:
+  BluetoothInstance();
+  virtual ~BluetoothInstance();
+
+  void AsyncResponse(double callback_handle, const std::shared_ptr<picojson::value>& response);
+  void AsyncResponse(double callback_handle, const common::PlatformResult& result);
+  void SyncResponse(double callback_handle, const std::shared_ptr<picojson::value>& response);
+
+  void FireEvent(const std::string& event, picojson::value& value);
+  void FireEvent(const std::string& event, const picojson::value& value);
+  void FireEvent(const std::string& event, const std::shared_ptr<picojson::value>& value);
+
+ private:
+  BluetoothAdapter bluetooth_adapter_;
+  BluetoothDevice bluetooth_device_;
+  BluetoothHealthApplication bluetooth_health_application_;
+  BluetoothHealthChannel bluetooth_health_channel_;
+  BluetoothHealthProfileHandler bluetooth_health_profile_handler_;
+  BluetoothServiceHandler bluetooth_service_handler_;
+  BluetoothSocket bluetooth_socket_;
+  BluetoothLEAdapter bluetooth_le_adapter_;
+  BluetoothGATTService bluetooth_gatt_service_;
+  BluetoothLEDevice bluetooth_le_device_;
+};
+
+} // namespace bluetooth
+} // namespace extension
+
+#endif // BLUETOOTH_BLUETOOTH_INSTANCE_H_
diff --git a/webWidgetTCT_device/src/bluetooth/bluetooth_le_adapter.cc b/webWidgetTCT_device/src/bluetooth/bluetooth_le_adapter.cc
new file mode 100755 (executable)
index 0000000..2ee99ac
--- /dev/null
@@ -0,0 +1,757 @@
+/*
+ * Copyright (c) 2015 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 "bluetooth/bluetooth_le_adapter.h"
+
+#include "common/tools.h"
+#include "common/logger.h"
+
+#include "bluetooth/bluetooth_instance.h"
+#include "bluetooth/bluetooth_le_device.h"
+#include "bluetooth/bluetooth_util.h"
+
+namespace extension {
+namespace bluetooth {
+
+namespace {
+
+class ParsedDataHolder {
+ public:
+  ParsedDataHolder() : valid_(false) {}
+  virtual ~ParsedDataHolder() {}
+
+  bool valid() const {
+    return valid_;
+  }
+
+ protected:
+  void set_valid() {
+    valid_ = true;
+  }
+
+ private:
+  bool valid_;
+};
+
+class BluetoothLEServiceData : public ParsedDataHolder {
+ public:
+  BluetoothLEServiceData()
+      : ParsedDataHolder() {
+  }
+
+  const std::string& uuid() const {
+    return uuid_;
+  }
+
+  const std::string& data() const {
+    return data_;
+  }
+
+  static bool Construct(const picojson::value& obj,
+                        BluetoothLEServiceData* out) {
+    if (!obj.is<picojson::object>() ||
+        !ParseUUID(obj, out) ||
+        !ParseData(obj, out)) {
+      return false;
+    }
+
+    out->set_valid();
+
+    return true;
+  }
+
+ private:
+  static bool ParseUUID(const picojson::value& obj,
+                        BluetoothLEServiceData* out) {
+    LoggerD("Entered");
+    const auto& uuid = obj.get("serviceuuid");
+    if (uuid.is<std::string>()) {
+      out->uuid_ = uuid.get<std::string>();
+    } else {
+      return false;
+    }
+
+    return true;
+  }
+
+  static bool ParseData(const picojson::value& obj,
+                        BluetoothLEServiceData* out) {
+    LoggerD("Entered");
+    const auto& data = obj.get("data");
+    if (data.is<std::string>()) {
+      out->data_ = data.get<std::string>();
+    } else {
+      return false;
+    }
+
+    return true;
+  }
+
+  std::string uuid_;
+  std::string data_;
+};
+
+class BluetoothLEManufacturerData : public ParsedDataHolder {
+ public:
+  BluetoothLEManufacturerData()
+      : ParsedDataHolder(),
+        data_(nullptr),
+        data_length_(0) {
+  }
+
+  const std::string& id() const {
+    return id_;
+  }
+
+  const unsigned char* const data() const {
+    return data_;
+  }
+
+  const int data_length() const {
+    return data_length_;
+  }
+
+  static bool Construct(const picojson::value& obj,
+                        BluetoothLEManufacturerData* out) {
+    LoggerD("Entered");
+    if (!obj.is<picojson::object>() ||
+        !ParseId(obj, out) ||
+        !ParseData(obj, out)) {
+      return false;
+    }
+
+    out->set_valid();
+
+    return true;
+  }
+
+  ~BluetoothLEManufacturerData() {
+    if (data_) {
+      delete [] data_;
+      data_ = nullptr;
+      data_length_ = 0;
+    }
+  }
+
+ private:
+  static bool ParseId(const picojson::value& obj,
+                      BluetoothLEManufacturerData* out) {
+    LoggerD("Entered");
+    const auto& id = obj.get("id");
+    if (id.is<std::string>()) {
+      out->id_ = id.get<std::string>();
+    } else {
+      return false;
+    }
+
+    return true;
+  }
+
+  static bool ParseData(const picojson::value& obj,
+                        BluetoothLEManufacturerData* out) {
+    LoggerD("Entered");
+
+    const auto& val_data = obj.get("data");
+
+    if (val_data.is<std::string>()) {
+      const std::string& str_data = val_data.get<std::string>();
+      const char* p_data = str_data.c_str();
+      int size = str_data.length();
+      if (size > 2 && (str_data.find("0x", 0) == 0 || str_data.find("0X", 0) == 0)) {
+        p_data += 2;
+        size -= 2;
+      }
+      out->data_length_ = size / 2;
+      out->data_ = new unsigned char[out->data_length_];
+      common::tools::HexToBin(p_data, size, out->data_, out->data_length_);
+      return true;
+    } else {
+      return false;
+    }
+  }
+
+  std::string id_;
+  unsigned char* data_;
+  int data_length_;
+};
+
+class BluetoothLEAdvertiseData : public ParsedDataHolder {
+ public:
+  BluetoothLEAdvertiseData()
+      : ParsedDataHolder(),
+        include_name_(false),
+        appearance_(0),  // 0 means unknown
+        include_tx_power_level_(false) {
+  }
+
+  bool include_name() const {
+    return include_name_;
+  }
+
+  const std::vector<std::string>& service_uuids() const {
+    return service_uuids_;
+  }
+
+  const std::vector<std::string>& solicitation_uuids() const {
+    return solicitation_uuids_;
+  }
+
+  int appearance() const {
+    return appearance_;
+  }
+
+  bool include_tx_power_level() const {
+    return include_tx_power_level_;
+  }
+
+  const BluetoothLEServiceData& service_data() const {
+    return service_data_;
+  }
+
+  const BluetoothLEManufacturerData& manufacturer_data() const {
+    return manufacturer_data_;
+  }
+
+  static bool Construct(const picojson::value& obj,
+                        BluetoothLEAdvertiseData* out) {
+    LoggerD("Entered");
+    if (!obj.is<picojson::object>() ||
+        !ParseIncludeName(obj, out) ||
+        !ParseServiceUUIDs(obj, out) ||
+        !ParseSolicitationUUIDs(obj, out) ||
+        !ParseAppearance(obj, out) ||
+        !ParseIncludeTxPowerLevel(obj, out) ||
+        !ParseServiceData(obj, out) ||
+        !ParseManufacturerData(obj, out)) {
+      return false;
+    }
+
+    out->set_valid();
+
+    return true;
+  }
+
+ private:
+  static bool ParseIncludeName(const picojson::value& obj,
+                               BluetoothLEAdvertiseData* out) {
+    LoggerD("Entered");
+    const auto& include_name = obj.get("includeName");
+    if (include_name.is<bool>()) {
+      out->include_name_ = include_name.get<bool>();
+    } else if (!include_name.is<picojson::null>()) {
+      return false;
+    }
+
+    return true;
+  }
+
+  static bool ParseServiceUUIDs(const picojson::value& obj,
+                                BluetoothLEAdvertiseData* out) {
+    LoggerD("Entered");
+    const auto& service_uuids = obj.get("serviceuuids");
+    if (service_uuids.is<picojson::array>()) {
+      for (const auto& i : service_uuids.get<picojson::array>()) {
+        if (i.is<std::string>()) {
+          out->service_uuids_.push_back(i.get<std::string>());
+        } else {
+          return false;
+        }
+      }
+    } else if (!service_uuids.is<picojson::null>()) {
+      return false;
+    }
+
+    return true;
+  }
+
+  static bool ParseSolicitationUUIDs(const picojson::value& obj,
+                                     BluetoothLEAdvertiseData* out) {
+    LoggerD("Entered");
+    const auto& solicitation_uuids = obj.get("solicitationuuids");
+    if (solicitation_uuids.is<picojson::array>()) {
+      for (const auto& i : solicitation_uuids.get<picojson::array>()) {
+        if (i.is<std::string>()) {
+          out->solicitation_uuids_.push_back(i.get<std::string>());
+        } else {
+          return false;
+        }
+      }
+    } else if (!solicitation_uuids.is<picojson::null>()) {
+      return false;
+    }
+
+    return true;
+  }
+
+  static bool ParseAppearance(const picojson::value& obj,
+                              BluetoothLEAdvertiseData* out) {
+    LoggerD("Entered");
+    const auto& appearance = obj.get("appearance");
+    if (appearance.is<double>()) {
+      out->appearance_ = static_cast<decltype(appearance_)>(appearance.get<double>());
+    } else if (!appearance.is<picojson::null>()) {
+      return false;
+    }
+
+    return true;
+  }
+
+  static bool ParseIncludeTxPowerLevel(const picojson::value& obj,
+                                       BluetoothLEAdvertiseData* out) {
+    LoggerD("Entered");
+    const auto& include_tx_power_level = obj.get("includeTxPowerLevel");
+    if (include_tx_power_level.is<bool>()) {
+      out->include_tx_power_level_ = include_tx_power_level.get<bool>();
+    } else if (!include_tx_power_level.is<picojson::null>()) {
+      return false;
+    }
+
+    return true;
+  }
+
+  static bool ParseServiceData(const picojson::value& obj,
+                               BluetoothLEAdvertiseData* out) {
+    LoggerD("Entered");
+    const auto& service_data = obj.get("serviceData");
+    BluetoothLEServiceData data;
+    if (BluetoothLEServiceData::Construct(service_data, &data)) {
+      out->service_data_ = std::move(data);
+    } else if (!service_data.is<picojson::null>()) {
+      return false;
+    }
+
+    return true;
+  }
+
+  static bool ParseManufacturerData(const picojson::value& obj,
+                                    BluetoothLEAdvertiseData* out) {
+    LoggerD("Entered");
+    const auto& manufacturer_data = obj.get("manufacturerData");
+    BluetoothLEManufacturerData data;
+    if (BluetoothLEManufacturerData::Construct(manufacturer_data, &data)) {
+      out->manufacturer_data_ = std::move(data);
+    } else if (!manufacturer_data.is<picojson::null>()) {
+      return false;
+    }
+
+    return true;
+  }
+
+  bool include_name_;
+  std::vector<std::string> service_uuids_;
+  std::vector<std::string> solicitation_uuids_;
+  int appearance_;
+  bool include_tx_power_level_;
+  BluetoothLEServiceData service_data_;
+  BluetoothLEManufacturerData manufacturer_data_;
+};
+
+// utility functions
+
+bool ToBool(bt_adapter_le_state_e state) {
+  return (BT_ADAPTER_LE_ENABLED == state) ? true : false;
+}
+
+// constants
+
+const std::string kAction = "action";
+const std::string kData = "data";
+// scan-related
+const std::string kOnScanSuccess = "onsuccess";
+const std::string kOnScanError = "onerror";
+const std::string kScanEvent = "BluetoothLEScanCallback";
+// advertise-related
+const std::string kOnAdvertiseState = "onstate";
+const std::string kOnAdvertiseError = "onerror";
+const std::string kAdvertiseEvent = "BluetoothLEAdvertiseCallback";
+
+} // namespace
+
+using common::ErrorCode;
+using common::PlatformResult;
+using common::tools::ReportError;
+using common::tools::ReportSuccess;
+
+BluetoothLEAdapter::BluetoothLEAdapter(BluetoothInstance& instance)
+    : instance_(instance),
+      enabled_(false),
+      scanning_(false),
+      bt_advertiser_(nullptr) {
+  LoggerD("Entered");
+
+  bt_adapter_le_state_e le_state = BT_ADAPTER_LE_DISABLED;
+
+  int ret = bt_adapter_le_get_state(&le_state);
+
+  if (BT_ERROR_NONE == ret) {
+    enabled_ = ToBool(le_state);
+
+    ret = bt_adapter_le_set_state_changed_cb(OnStateChanged, this);
+    if (BT_ERROR_NONE != ret) {
+      LoggerE("Failed to register BTLE state changed listener.");
+    }
+  } else {
+    LoggerE("Failed to obtain current state of BTLE.");
+  }
+}
+
+BluetoothLEAdapter::~BluetoothLEAdapter() {
+  LoggerD("Entered");
+  bt_adapter_le_unset_state_changed_cb();
+  if (scanning_) {
+    bt_adapter_le_stop_scan();
+  }
+  if (bt_advertiser_) {
+    bt_adapter_le_stop_advertising(bt_advertiser_);
+    bt_adapter_le_destroy_advertiser(bt_advertiser_);
+  }
+}
+
+void BluetoothLEAdapter::StartScan(const picojson::value& data, picojson::object& out) {
+  LoggerD("Entered");
+
+  int ret = bt_adapter_le_start_scan(OnScanResult, this);
+
+  if (BT_ERROR_NONE != ret) {
+    if (BT_ERROR_NOW_IN_PROGRESS == ret) {
+      LoggerE("Scan in progress");
+      ReportError(PlatformResult(ErrorCode::INVALID_STATE_ERR, "Scan already in progress"), &out);
+    } else {
+      LoggerE("Failed to start scan: %d", ret);
+
+      // other errors are reported asynchronously
+      picojson::value value = picojson::value(picojson::object());
+      picojson::object* data_obj = &value.get<picojson::object>();
+      data_obj->insert(std::make_pair(kAction, picojson::value(kOnScanError)));
+      ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to start scan"), data_obj);
+      instance_.FireEvent(kScanEvent, value);
+    }
+  } else {
+    scanning_ = true;
+    ReportSuccess(out);
+  }
+}
+
+void BluetoothLEAdapter::StopScan(const picojson::value& data, picojson::object& out) {
+  LoggerD("Entered");
+
+  int ret = bt_adapter_le_stop_scan();
+
+  if (BT_ERROR_NONE != ret && BT_ERROR_NOT_IN_PROGRESS != ret) {
+    LoggerE("Failed to stop scan: %d", ret);
+    ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to stop scan"), &out);
+  } else {
+    scanning_ = false;
+    ReportSuccess(out);
+  }
+}
+
+void BluetoothLEAdapter::StartAdvertise(const picojson::value& data, picojson::object& out) {
+  LoggerD("Entered");
+
+  const auto& json_advertise_data = data.get("advertiseData");
+  const auto& json_packet_type = data.get("packetType");
+  const auto& json_mode = data.get("mode");
+  const auto& json_connectable = data.get("connectable");
+
+  if (!json_advertise_data.is<picojson::object>() ||
+      !json_packet_type.is<std::string>() ||
+      !json_mode.is<std::string>() ||
+      !json_connectable.is<bool>()) {
+    ReportError(PlatformResult(ErrorCode::TYPE_MISMATCH_ERR, "Unexpected parameter type"), &out);
+    return;
+  }
+
+  BluetoothLEAdvertiseData advertise_data;
+  if (!BluetoothLEAdvertiseData::Construct(json_advertise_data, &advertise_data)) {
+    ReportError(PlatformResult(ErrorCode::TYPE_MISMATCH_ERR, "Unexpected value of advertise data"), &out);
+    return;
+  }
+
+  bt_adapter_le_packet_type_e packet_type = BT_ADAPTER_LE_PACKET_ADVERTISING;
+  {
+    const auto& str_packet_type = json_packet_type.get<std::string>();
+    if ("ADVERTISE" == str_packet_type) {
+      packet_type = BT_ADAPTER_LE_PACKET_ADVERTISING;
+    } else if ("SCAN_RESPONSE" == str_packet_type) {
+      packet_type = BT_ADAPTER_LE_PACKET_SCAN_RESPONSE;
+    } else {
+      LoggerE("Fail: json_packet_type.get");
+      ReportError(PlatformResult(ErrorCode::TYPE_MISMATCH_ERR, "Unexpected value of packet type"), &out);
+      return;
+    }
+  }
+
+  bt_adapter_le_advertising_mode_e mode = BT_ADAPTER_LE_ADVERTISING_MODE_BALANCED;
+  {
+    const auto& str_mode = json_mode.get<std::string>();
+    if ("BALANCED" == str_mode) {
+      mode = BT_ADAPTER_LE_ADVERTISING_MODE_BALANCED;
+    } else if ("LOW_LATENCY" == str_mode) {
+      mode = BT_ADAPTER_LE_ADVERTISING_MODE_LOW_LATENCY;
+    } else if ("LOW_ENERGY" == str_mode) {
+      mode = BT_ADAPTER_LE_ADVERTISING_MODE_LOW_ENERGY;
+    } else {
+      ReportError(PlatformResult(ErrorCode::TYPE_MISMATCH_ERR, "Unexpected value of mode"), &out);
+      return;
+    }
+  }
+
+  if (nullptr != bt_advertiser_) {
+    LoggerE("Advertise in progress");
+    ReportError(PlatformResult(ErrorCode::INVALID_STATE_ERR, "Advertise already in progress"), &out);
+    return;
+  }
+
+  bt_advertiser_h advertiser = nullptr;
+
+  int ret = bt_adapter_le_create_advertiser(&advertiser);
+  if (BT_ERROR_NONE != ret) {
+    LoggerE("bt_adapter_le_create_advertiser() failed with: %d", ret);
+    ReportError(util::GetBluetoothError(ret, "Failed to create advertiser"), &out);
+    return;
+  }
+
+  std::unique_ptr<std::remove_pointer<bt_advertiser_h>::type,
+      int (*)(bt_advertiser_h)> advertiser_ptr(advertiser, &bt_adapter_le_destroy_advertiser);  // automatically release the memory
+
+  // configure advertiser
+  if (advertise_data.include_name()) {
+    ret = bt_adapter_le_set_advertising_device_name(advertiser, packet_type,
+                                                advertise_data.include_name());
+    if (BT_ERROR_NONE != ret) {
+      LoggerE("bt_adapter_le_set_advertising_device_name() failed with: %d", ret);
+      ReportError(util::GetBluetoothError(ret, "Failed to create advertiser"), &out);
+      return;
+    }
+  }
+
+  for (const auto& i : advertise_data.service_uuids()) {
+    ret = bt_adapter_le_add_advertising_service_uuid(advertiser, packet_type,
+                                                     i.c_str());
+    if (BT_ERROR_NONE != ret) {
+      LoggerE("bt_adapter_le_add_advertising_service_uuid() failed with: %d", ret);
+      ReportError(util::GetBluetoothError(ret, "Failed to create advertiser"), &out);
+      return;
+    }
+  }
+
+  for (const auto& i : advertise_data.solicitation_uuids()) {
+    ret = bt_adapter_le_add_advertising_service_solicitation_uuid(advertiser,
+                                                                  packet_type,
+                                                                  i.c_str());
+    if (BT_ERROR_NONE != ret) {
+      LoggerE("bt_adapter_le_add_advertising_service_solicitation_uuid() failed with: %d", ret);
+      ReportError(util::GetBluetoothError(ret, "Failed to create advertiser"), &out);
+      return;
+    }
+  }
+
+  ret = bt_adapter_le_set_advertising_appearance(advertiser, packet_type,
+                                                 advertise_data.appearance());
+  if (BT_ERROR_NONE != ret) {
+    LoggerE("bt_adapter_le_set_advertising_appearance() failed with: %d", ret);
+    ReportError(util::GetBluetoothError(ret, "Failed to create advertiser"), &out);
+    return;
+  }
+
+  if (advertise_data.include_tx_power_level()) {
+    ret = bt_adapter_le_set_advertising_tx_power_level(advertiser, packet_type,
+                                                       advertise_data.include_tx_power_level());
+    if (BT_ERROR_NONE != ret) {
+      LoggerE("bt_adapter_le_set_advertising_tx_power_level() failed with: %d", ret);
+      ReportError(util::GetBluetoothError(ret, "Failed to create advertiser"), &out);
+      return;
+    }
+  }
+
+  const auto& service_data = advertise_data.service_data();
+  if (service_data.uuid().empty() && service_data.data().empty()) {
+    LoggerD("service data is empty");
+  } else {
+    ret = bt_adapter_le_add_advertising_service_data(advertiser, packet_type,
+                                                     service_data.uuid().c_str(),
+                                                     service_data.data().c_str(),
+                                                     service_data.data().length());
+    if (BT_ERROR_NONE != ret) {
+      LoggerE("bt_adapter_le_add_advertising_service_data() failed with: %d", ret);
+      ReportError(util::GetBluetoothError(ret, "Failed to create advertiser"), &out);
+      return;
+    }
+  }
+
+  const auto& manufacturer_data = advertise_data.manufacturer_data();
+  if (manufacturer_data.id().empty() && manufacturer_data.data() == nullptr) {
+    LoggerD("manufacturerData is empty");
+  } else {
+    if (manufacturer_data.valid()) {
+      ret = bt_adapter_le_add_advertising_manufacturer_data(advertiser,
+                                                            packet_type,
+                                                            atoi(manufacturer_data.id().c_str()),
+                                                            (const char*)manufacturer_data.data(),
+                                                            manufacturer_data.data_length());
+      if (BT_ERROR_NONE != ret) {
+        LoggerE("bt_adapter_le_add_advertising_manufacturer_data() failed with: %d", ret);
+        ReportError(util::GetBluetoothError(ret, "Failed to create advertiser"), &out);
+        return;
+      }
+    }
+  }
+
+  ret = bt_adapter_le_set_advertising_mode(advertiser, mode);
+  if (BT_ERROR_NONE != ret) {
+    LoggerE("bt_adapter_le_set_advertising_mode() failed with: %d", ret);
+    ReportError(util::GetBluetoothError(ret, "Failed to create advertiser"), &out);
+    return;
+  }
+
+  ret = bt_adapter_le_set_advertising_connectable(advertiser, json_connectable.get<bool>());
+  if (BT_ERROR_NONE != ret) {
+    LoggerE("bt_adapter_le_set_advertising_connectable() failed with: %d", ret);
+    ReportError(util::GetBluetoothError(ret, "Failed to create advertiser"), &out);
+    return;
+  }
+
+  // advertiser is ready, let's start advertising
+  ret = bt_adapter_le_start_advertising_new(advertiser, OnAdvertiseResult, this);
+  if (BT_ERROR_NONE != ret) {
+    if (BT_ERROR_NOW_IN_PROGRESS == ret) {
+      ReportError(PlatformResult(ErrorCode::INVALID_STATE_ERR, "Advertise already in progress"), &out);
+      return;
+    }
+
+    LoggerE("bt_adapter_le_start_advertising_new() failed with: %d", ret);
+    ReportError(util::GetBluetoothError(ret, "Failed to start advertising"), &out);
+    return;
+  }
+
+  // everything went well, we want to store the pointer, so unique_ptr should no longer manage the memory
+  bt_advertiser_ = advertiser_ptr.release();
+  ReportSuccess(out);
+}
+
+void BluetoothLEAdapter::StopAdvertise(const picojson::value& data, picojson::object& out) {
+  LoggerD("Entered");
+
+  if (nullptr != bt_advertiser_) {
+    int ret = bt_adapter_le_stop_advertising(bt_advertiser_);
+    if (BT_ERROR_NONE != ret && BT_ERROR_NOT_IN_PROGRESS != ret) {
+      LoggerE("bt_adapter_le_stop_advertising() failed with: %d", ret);
+      ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to stop advertising"), &out);
+      return;
+    }
+
+    ret = bt_adapter_le_destroy_advertiser(bt_advertiser_);
+    if (BT_ERROR_NONE != ret && BT_ERROR_NOT_IN_PROGRESS != ret) {
+      LoggerE("bt_adapter_le_destroy_advertiser() failed with: %d", ret);
+      ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to destroy advertiser"), &out);
+      return;
+    }
+
+    bt_advertiser_ = nullptr;
+  } else {
+    LoggerD("Advertising is not in progress");
+  }
+
+  ReportSuccess(out);
+}
+
+void BluetoothLEAdapter::OnStateChanged(int result,
+                                        bt_adapter_le_state_e adapter_le_state,
+                                        void* user_data) {
+  LoggerD("Entered");
+
+  auto adapter = static_cast<BluetoothLEAdapter*>(user_data);
+
+  if (!adapter) {
+    LoggerE("user_data is NULL");
+    return;
+  }
+
+  adapter->enabled_ = ToBool(adapter_le_state);
+}
+
+void BluetoothLEAdapter::OnScanResult(
+    int result, bt_adapter_le_device_scan_result_info_s* info,
+    void* user_data) {
+  LoggerD("Entered, result: %d, info: %p, data: %p", result, info, user_data);
+
+  auto adapter = static_cast<BluetoothLEAdapter*>(user_data);
+
+  if (!adapter) {
+    LoggerE("user_data is NULL");
+    return;
+  }
+
+  picojson::value value = picojson::value(picojson::object());
+  picojson::object* data_obj = &value.get<picojson::object>();
+
+  if (BT_ERROR_NONE != result) {
+    LoggerE("Error during scanning: %d", result);
+    ReportError(util::GetBluetoothError(result, "Error during scanning"), data_obj);
+    data_obj->insert(std::make_pair(kAction, picojson::value(kOnScanError)));
+  } else {
+    // TODO: this is probably capi-network-bluetooth error: when scan is stopped info has 0x1 value
+    if (nullptr != info && reinterpret_cast<void*>(0x1) != info) {
+      // device found
+      LoggerD("Device found");
+      picojson::value data{picojson::object{}};
+      const auto& r = BluetoothLEDevice::ToJson(info, &data.get<picojson::object>());
+      if (r) {
+        data_obj->insert(std::make_pair(kAction, picojson::value(kOnScanSuccess)));
+        data_obj->insert(std::make_pair(kData, data));
+      } else {
+        LoggerE("Failed to parse Bluetooth LE device");
+        ReportError(r, data_obj);
+        data_obj->insert(std::make_pair(kAction, picojson::value(kOnScanError)));
+      }
+    }
+  }
+
+  adapter->instance_.FireEvent(kScanEvent, value);
+}
+
+void BluetoothLEAdapter::OnAdvertiseResult(
+    int result, bt_advertiser_h advertiser,
+    bt_adapter_le_advertising_state_e adv_state, void* user_data) {
+  LoggerD("Entered, result: %d, advertiser: %p, adv_state: %d, user_data: %p", result, advertiser, adv_state, user_data);
+
+  auto adapter = static_cast<BluetoothLEAdapter*>(user_data);
+
+  if (!adapter) {
+    LoggerE("user_data is NULL");
+    return;
+  }
+
+  picojson::value value = picojson::value(picojson::object());
+  picojson::object* data_obj = &value.get<picojson::object>();
+
+  if (BT_ERROR_NONE != result) {
+    LoggerE("Error during advertising: %d", result);
+    ReportError(util::GetBluetoothError(result, "Error during advertising"), data_obj);
+    data_obj->insert(std::make_pair(kAction, picojson::value(kOnAdvertiseError)));
+  } else {
+    const char* state = (BT_ADAPTER_LE_ADVERTISING_STARTED == adv_state) ? "STARTED" : "STOPPED";
+    LoggerD("Advertise state is: %s", state);
+    data_obj->insert(std::make_pair(kAction, picojson::value(kOnAdvertiseState)));
+    ReportSuccess(picojson::value(state), *data_obj);
+  }
+
+  adapter->instance_.FireEvent(kAdvertiseEvent, value);
+}
+
+} // namespace bluetooth
+} // namespace extension
diff --git a/webWidgetTCT_device/src/bluetooth/bluetooth_le_adapter.h b/webWidgetTCT_device/src/bluetooth/bluetooth_le_adapter.h
new file mode 100755 (executable)
index 0000000..2c3a928
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2015 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 BLUETOOTH_BLUETOOTH_LE_ADAPTER_H_
+#define BLUETOOTH_BLUETOOTH_LE_ADAPTER_H_
+
+#include <bluetooth.h>
+#include <bluetooth_internal.h>
+#include "common/picojson.h"
+
+namespace extension {
+namespace bluetooth {
+
+class BluetoothInstance;
+
+class BluetoothLEAdapter {
+ public:
+  explicit BluetoothLEAdapter(BluetoothInstance& instance);
+  ~BluetoothLEAdapter();
+
+  void StartScan(const picojson::value& data, picojson::object& out);
+  void StopScan(const picojson::value& data, picojson::object& out);
+
+  void StartAdvertise(const picojson::value& data, picojson::object& out);
+  void StopAdvertise(const picojson::value& data, picojson::object& out);
+
+ private:
+  BluetoothLEAdapter() = delete;
+  BluetoothLEAdapter(const BluetoothLEAdapter&) = delete;
+  BluetoothLEAdapter(const BluetoothLEAdapter&&) = delete;
+  BluetoothLEAdapter& operator=(const BluetoothLEAdapter&) = delete;
+  BluetoothLEAdapter& operator=(const BluetoothLEAdapter&&) = delete;
+
+  static void OnStateChanged(int result, bt_adapter_le_state_e adapter_le_state,
+                             void* user_data);
+  static void OnScanResult(int result,
+                           bt_adapter_le_device_scan_result_info_s* info,
+                           void* user_data);
+  static void OnAdvertiseResult(int result, bt_advertiser_h advertiser,
+                                bt_adapter_le_advertising_state_e adv_state,
+                                void* user_data);
+
+  BluetoothInstance& instance_;
+  bool enabled_;
+  bool scanning_;
+  bt_advertiser_h bt_advertiser_;
+};
+
+} // namespace bluetooth
+} // namespace extension
+
+#endif // BLUETOOTH_BLUETOOTH_LE_ADAPTER_H_
diff --git a/webWidgetTCT_device/src/bluetooth/bluetooth_le_device.cc b/webWidgetTCT_device/src/bluetooth/bluetooth_le_device.cc
new file mode 100755 (executable)
index 0000000..dcb429b
--- /dev/null
@@ -0,0 +1,499 @@
+/*
+ * Copyright (c) 2015 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 "bluetooth/bluetooth_le_device.h"
+#include <glib.h>
+
+#include "bluetooth/bluetooth_instance.h"
+#include "bluetooth/bluetooth_util.h"
+
+#include "common/converter.h"
+#include "common/logger.h"
+#include "common/tools.h"
+
+using common::ErrorCode;
+using common::PlatformResult;
+using common::tools::ReportError;
+using common::tools::ReportSuccess;
+using common::tools::BinToHex;
+
+namespace extension {
+namespace bluetooth {
+
+namespace {
+//le_device
+const std::string kDeviceName = "name";
+const std::string kDeviceAddress = "address";
+const std::string kTxPowerLevel = "txpowerlevel";
+const std::string kAppearance = "appearance";
+const std::string kDeviceUuids = "uuids";
+const std::string kSolicitationUuids = "solicitationuuids";
+const std::string kServiceData = "serviceData";
+const std::string kServiceUuid = "uuid";
+const std::string kManufacturerData = "manufacturerData";
+const std::string kId = "id";
+const std::string kData = "data";
+const std::string kAction = "action";
+
+const std::string kOnConnected = "onconnected";
+const std::string kOnDisconnected = "ondisconnected";
+const std::string kConnectChangeEvent = "BluetoothLEConnectChangeCallback";
+
+}
+
+BluetoothLEDevice::BluetoothLEDevice(BluetoothInstance& instance,
+                                     BluetoothGATTService& service)
+    : instance_(instance),
+      service_(service),
+      is_listener_set_(false) {
+  LoggerD("Entered");
+  int ret = bt_gatt_set_connection_state_changed_cb(GattConnectionState, this);
+  if (BT_ERROR_NONE != ret && BT_ERROR_ALREADY_DONE != ret) {
+    LoggerE("Can't add connection state listener: %d", ret);
+  }
+}
+
+BluetoothLEDevice::~BluetoothLEDevice() {
+  LoggerD("Entered");
+  int ret = bt_gatt_unset_connection_state_changed_cb();
+  if (ret != BT_ERROR_NONE) {
+    LoggerW("Failed to unset listener: %d", ret);
+  }
+}
+
+static void UUIDsToJson(char **service_uuid, int service_count,
+                        const std::string &field, picojson::object* le_device) {
+  LoggerD("Entered");
+
+  picojson::array& array = le_device->insert(
+      std::make_pair(field, picojson::value(picojson::array()))).first->second
+      .get<picojson::array>();
+
+  for (int i = 0; i < service_count; i++) {
+    array.push_back(picojson::value(service_uuid[i]));
+  }
+}
+
+static void ServiceDataToJson(bt_adapter_le_service_data_s *service_data_list,
+                              int service_data_list_count,
+                              picojson::object* le_device) {
+  LoggerD("Entered");
+
+  picojson::array& array = le_device->insert(
+      std::make_pair(kServiceData, picojson::value(picojson::array()))).first
+      ->second.get<picojson::array>();
+
+  for (int i = 0; i < service_data_list_count; i++) {
+    picojson::value response = picojson::value(picojson::object());
+    picojson::object& response_obj = response.get<picojson::object>();
+    response_obj[kServiceUuid] = picojson::value(
+        std::string(service_data_list[i].service_uuid));
+    response_obj[kData] = picojson::value(
+        std::string(service_data_list[i].service_data,
+                    service_data_list[i].service_data_len));
+
+    array.push_back(response);
+  }
+}
+
+static void ManufacturerToJson(int manufacturer_id,
+                               char *manufacturer_data,
+                               int manufacturer_count,
+                               picojson::object* le_device) {
+  LoggerD("Entered");
+
+  picojson::value response = picojson::value(picojson::object());
+  picojson::object& response_obj = response.get<picojson::object>();
+  response_obj[kId] = picojson::value(std::to_string(manufacturer_id));
+
+  const int hex_count = manufacturer_count * 2;
+  char* manuf_data_hex = new char[hex_count + 1];
+  BinToHex((const unsigned char*) manufacturer_data,
+           manufacturer_count,
+           manuf_data_hex,
+           hex_count);
+  manuf_data_hex[hex_count] = '\0';
+  response_obj[kData] = picojson::value(std::string(manuf_data_hex));
+  delete [] manuf_data_hex;
+  manuf_data_hex = nullptr;
+
+  le_device->insert(std::make_pair(kManufacturerData, response));
+}
+
+PlatformResult BluetoothLEDevice::ToJson(
+    bt_adapter_le_device_scan_result_info_s* info,
+    picojson::object* le_device) {
+
+  LoggerD("Entered");
+
+  le_device->insert(
+      std::make_pair(kDeviceAddress,
+                     picojson::value(std::string(info->remote_address))));
+
+  char *device_name = nullptr;
+
+  int ret = BT_ERROR_NONE;
+
+  std::vector<bt_adapter_le_packet_type_e> types = {
+      BT_ADAPTER_LE_PACKET_SCAN_RESPONSE, BT_ADAPTER_LE_PACKET_ADVERTISING };
+  bool found = false;
+
+  for (size_t i = 0; i < types.size() && !found; ++i) {
+    ret = bt_adapter_le_get_scan_result_device_name(info, types[i],
+                                                    &device_name);
+    if (BT_ERROR_NONE == ret) {
+      found = true;
+    } else {
+      LoggerE("Failed to get device name (%d). Packet type: %d", ret, types[i]);
+    }
+  }
+
+  if (found) {
+    le_device->insert(
+        std::make_pair(kDeviceName, picojson::value(std::string(device_name))));
+
+    g_free(device_name);
+  }
+
+  int power_level = 0;
+  found = false;
+  for (size_t i = 0; i < types.size() && !found; ++i) {
+    ret = bt_adapter_le_get_scan_result_tx_power_level(info, types[i],
+                                                       &power_level);
+    if (BT_ERROR_NONE == ret) {
+      found = true;
+    } else {
+      LoggerE("Failed to get txpower (%d). Packet type: %d", ret, types[i]);
+    }
+  }
+
+  if (found) {
+    le_device->insert(
+        std::make_pair(kTxPowerLevel,
+                       picojson::value(static_cast<double>(power_level))));
+  }
+
+  int appearance = 0;
+  found = false;
+  for (size_t i = 0; i < types.size() && !found; ++i) {
+    ret = bt_adapter_le_get_scan_result_appearance(info, types[i], &appearance);
+    if (BT_ERROR_NONE == ret) {
+      found = true;
+    } else {
+      LoggerE("Failed to get appearance (%d). Packet type: %d", ret, types[i]);
+    }
+  }
+
+  if (found) {
+    le_device->insert(
+          std::make_pair(kAppearance,
+                         picojson::value(static_cast<double>(appearance))));
+  }
+
+  char **uuids = nullptr;
+  int count = 0;
+  found = false;
+  for (size_t i = 0; i < types.size() && !found; ++i) {
+    ret = bt_adapter_le_get_scan_result_service_uuids(info, types[i], &uuids,
+                                                      &count);
+    if (BT_ERROR_NONE == ret) {
+      found = true;
+    } else {
+      LoggerE("Failed to get uuids (%d). Packet type: %d", ret, types[i]);
+    }
+  }
+
+  if (found) {
+    UUIDsToJson(uuids, count, kDeviceUuids, le_device);
+    for (int i = 0; i < count; ++i) {
+      g_free(uuids[i]);
+    }
+    g_free(uuids);
+  }
+
+  char** service_solicitation_uuids = nullptr;
+  int service_solicitation_uuids_count = 0;
+  found = false;
+
+  for (size_t i = 0; i < types.size() && !found; ++i) {
+    ret = bt_adapter_le_get_scan_result_service_solicitation_uuids(
+        info, types[i], &service_solicitation_uuids,
+        &service_solicitation_uuids_count);
+    if (BT_ERROR_NONE == ret) {
+      found = true;
+    } else {
+      LoggerE("Failed to get solicitation UUID (%d). Packet type: %d", ret,
+              types[i]);
+    }
+  }
+
+  if (found) {
+    UUIDsToJson(service_solicitation_uuids, service_solicitation_uuids_count,
+                kSolicitationUuids, le_device);
+    for (int i = 0; i < service_solicitation_uuids_count; ++i) {
+      g_free(service_solicitation_uuids[i]);
+    }
+    g_free(service_solicitation_uuids);
+  }
+
+  bt_adapter_le_service_data_s *serviceDataList = nullptr;
+  int service_data_list_count = 0;
+  found = false;
+
+  for (size_t i = 0; i < types.size() && !found; ++i) {
+    ret = bt_adapter_le_get_scan_result_service_data_list(
+        info, types[i], &serviceDataList, &service_data_list_count);
+    if (BT_ERROR_NONE == ret) {
+      found = true;
+    } else {
+      LoggerE("Failed to get device service data (%d). Packet type: %d", ret,
+              types[i]);
+    }
+  }
+
+  if (found) {
+    ServiceDataToJson(serviceDataList, service_data_list_count, le_device);
+    ret = bt_adapter_le_free_service_data_list(serviceDataList,
+                                               service_data_list_count);
+    if (BT_ERROR_NONE != ret) {
+      LoggerW("Failed to free service data list: %d", ret);
+    }
+  }
+
+  int manufacturer_id = 0;
+  char* manufacturer_data = nullptr;
+  int manufacturer_data_count = 0;
+  found = false;
+
+  for (size_t i = 0; i < types.size() && !found; ++i) {
+    ret = bt_adapter_le_get_scan_result_manufacturer_data(
+        info, types[i], &manufacturer_id, &manufacturer_data,
+        &manufacturer_data_count);
+    if (BT_ERROR_NONE == ret) {
+      found = true;
+    } else {
+      LoggerE("Failed to get device manufacturer (%d). Packet type: %d", ret,
+              types[i]);
+    }
+  }
+
+  if (found) {
+    ManufacturerToJson(manufacturer_id, manufacturer_data,
+                       manufacturer_data_count, le_device);
+    g_free(manufacturer_data);
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+void BluetoothLEDevice::Connect(const picojson::value& data,
+                                picojson::object& out) {
+  LoggerD("Entered");
+
+  const auto callback_handle = util::GetAsyncCallbackHandle(data);
+  const auto& args = util::GetArguments(data);
+
+  const auto& address = common::FromJson<std::string>(args, "address");
+
+  bool connected = false;
+  int ret = bt_device_is_profile_connected(address.c_str(), BT_PROFILE_GATT, &connected);
+  if (BT_ERROR_NONE != ret) {
+    instance_.AsyncResponse(callback_handle,
+                            PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to disconnect."));
+    return;
+  }
+
+  if (connected) {
+      instance_.AsyncResponse(callback_handle,
+                              PlatformResult(ErrorCode::NO_ERROR));
+  } else {  // not connected yet
+    ret = bt_gatt_connect(address.c_str(), false);
+    if (BT_ERROR_NONE != ret) {
+      instance_.AsyncResponse(
+          callback_handle,
+          PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to connect."));
+      return;
+    }
+    connecting_[address] = callback_handle;
+  }
+
+  ReportSuccess(out);
+}
+
+void BluetoothLEDevice::Disconnect(const picojson::value& data,
+                                   picojson::object& out) {
+  LoggerD("Entered");
+
+  const auto callback_handle = util::GetAsyncCallbackHandle(data);
+  const auto& args = util::GetArguments(data);
+  const auto& address = common::FromJson<std::string>(args, "address");
+
+  int ret = BT_ERROR_NONE;
+
+  bool connected = false;
+  ret = bt_device_is_profile_connected(address.c_str(), BT_PROFILE_GATT, &connected);
+  if (BT_ERROR_NONE != ret) {
+    instance_.AsyncResponse(
+        callback_handle,
+        PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to disconnect."));
+    return;
+  }
+  if (!connected) {
+    ReportError(PlatformResult(ErrorCode::INVALID_STATE_ERR,
+                               "Bluetooth low energy device is not connected"),
+                &out);
+    return;
+  }
+
+  ret = bt_gatt_disconnect(address.c_str());
+  if (BT_ERROR_NONE != ret) {
+    instance_.AsyncResponse(
+        callback_handle,
+        PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to disconnect."));
+    return;
+  }
+
+  connecting_[address] = callback_handle;
+
+  ReportSuccess(out);
+}
+
+void BluetoothLEDevice::GetService(const picojson::value& data,
+                                   picojson::object& out) {
+  LoggerD("Entered");
+
+  const auto& args = util::GetArguments(data);
+
+  const auto& address = common::FromJson<std::string>(args, "address");
+  const auto& uuid = common::FromJson<std::string>(args, "uuid");
+
+  auto it = is_connected_.find(address);
+  if (it == is_connected_.end()) {
+    LoggerE("Bluetooth low energy device is not connected");
+    ReportError(
+        PlatformResult(ErrorCode::INVALID_STATE_ERR,
+                       "Bluetooth low energy device is not connected"),
+        &out);
+    return;
+  }
+
+  picojson::value response = picojson::value(picojson::object());
+  picojson::object *data_obj = &response.get<picojson::object>();
+
+  PlatformResult result = service_.GetSpecifiedGATTService(address, uuid,
+                                                           data_obj);
+
+  if (result.IsError()) {
+    ReportError(result, &out);
+  } else {
+    ReportSuccess(response, out);
+  }
+}
+
+void BluetoothLEDevice::AddConnectStateChangeListener(
+    const picojson::value& data, picojson::object& out) {
+  LoggerD("Entered");
+
+  is_listener_set_ = true;
+
+  ReportSuccess(out);
+}
+
+void BluetoothLEDevice::RemoveConnectStateChangeListener(
+    const picojson::value& data, picojson::object& out) {
+  LoggerD("Entered");
+
+  is_listener_set_ = false;
+
+  ReportSuccess(out);
+}
+
+void BluetoothLEDevice::GetServiceUuids(const picojson::value& data,
+                                        picojson::object& out) {
+  LoggerD("Entered");
+
+  const auto& args = util::GetArguments(data);
+  const auto& address = common::FromJson<std::string>(args, "address");
+
+  picojson::value response = picojson::value(picojson::array());
+  picojson::array *data_obj = &response.get<picojson::array>();
+
+  PlatformResult result = service_.GetServiceUuids(address, data_obj);
+
+  if (result) {
+    ReportSuccess(response, out);
+  } else {
+    ReportError(result, &out);
+  }
+}
+
+void BluetoothLEDevice::GattConnectionState(int result, bool connected,
+                                            const char* remote_address,
+                                            void* user_data) {
+  LoggerD("Entered: %s connected: %d", remote_address, connected);
+  auto le_device = static_cast<BluetoothLEDevice *>(user_data);
+
+  if (!le_device) {
+    LoggerE("user_data is NULL");
+    return;
+  }
+
+  if (connected) {
+    le_device->is_connected_.insert(remote_address);
+  } else {
+    le_device->is_connected_.erase(remote_address);
+    // inform that this device is not connected anymore
+    le_device->service_.TryDestroyClient(remote_address);
+  }
+
+  if (le_device->is_listener_set_) {
+
+    picojson::value value = picojson::value(picojson::object());
+    picojson::object* data_obj = &value.get<picojson::object>();
+    if (connected) {
+      LoggerD("OnConnected");
+      data_obj->insert(std::make_pair(kAction, picojson::value(kOnConnected)));
+    } else {
+      LoggerD("OnDisconnected");
+      data_obj->insert(
+          std::make_pair(kAction, picojson::value(kOnDisconnected)));
+    }
+
+    data_obj->insert(
+        std::make_pair(kDeviceAddress, picojson::value(remote_address)));
+
+    le_device->instance_.FireEvent(kConnectChangeEvent, value);
+  }
+
+  auto it = le_device->connecting_.find(remote_address);
+  if (le_device->connecting_.end() == it) {
+    LoggerW("Given address is not in waiting connections list");
+    return;
+  }
+
+  PlatformResult ret = PlatformResult(ErrorCode::NO_ERROR);
+  if (BT_ERROR_NONE != result) {
+    ret = PlatformResult(ErrorCode::UNKNOWN_ERR,
+                         "Failed to get connection state");
+  }
+
+  le_device->instance_.AsyncResponse(it->second, ret);
+
+  le_device->connecting_.erase(it);
+}
+
+}  // namespace bluetooth
+}  // namespace extension
diff --git a/webWidgetTCT_device/src/bluetooth/bluetooth_le_device.h b/webWidgetTCT_device/src/bluetooth/bluetooth_le_device.h
new file mode 100755 (executable)
index 0000000..f95cab0
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2015 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 BLUETOOTH_BLUETOOTH_LE_DEVICE_H_
+#define BLUETOOTH_BLUETOOTH_LE_DEVICE_H_
+
+#include <bluetooth.h>
+
+#include <set>
+#include <unordered_map>
+
+#include "bluetooth/bluetooth_gatt_service.h"
+
+#include "common/picojson.h"
+#include "common/platform_result.h"
+
+namespace extension {
+namespace bluetooth {
+
+class BluetoothInstance;
+
+class BluetoothLEDevice {
+ public:
+  explicit BluetoothLEDevice(BluetoothInstance& instance, BluetoothGATTService& service);
+  ~BluetoothLEDevice();
+
+  void Connect(const picojson::value& data, picojson::object& out);
+  void Disconnect(const picojson::value& data, picojson::object& out);
+
+  void GetService(const picojson::value& data, picojson::object& out);
+
+  void AddConnectStateChangeListener(const picojson::value& data,
+                                     picojson::object& out);
+  void RemoveConnectStateChangeListener(const picojson::value& data,
+                                        picojson::object& out);
+
+  void GetServiceUuids(const picojson::value& data, picojson::object& out);
+
+  static common::PlatformResult ToJson(
+      bt_adapter_le_device_scan_result_info_s* info,
+      picojson::object* le_device);
+
+ private:
+  static void GattConnectionState(int result, bool connected,
+                                  const char *remote_address, void *user_data);
+
+  BluetoothInstance& instance_;
+  BluetoothGATTService& service_;
+  std::unordered_map<std::string, double> connecting_;
+  bool is_listener_set_;
+  std::set<std::string> is_connected_;
+};
+
+}  // namespace bluetooth
+}  // namespace extension
+
+#endif // BLUETOOTH_BLUETOOTH_LE_DEVICE_H_
diff --git a/webWidgetTCT_device/src/bluetooth/bluetooth_service_handler.cc b/webWidgetTCT_device/src/bluetooth/bluetooth_service_handler.cc
new file mode 100755 (executable)
index 0000000..f7b3040
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2015 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 "bluetooth_service_handler.h"
+
+#include "common/converter.h"
+#include "common/logger.h"
+#include "common/extension.h"
+
+#include "bluetooth_adapter.h"
+#include "bluetooth_util.h"
+
+namespace extension {
+namespace bluetooth {
+
+using namespace common;
+
+BluetoothServiceHandler::BluetoothServiceHandler(BluetoothAdapter& adapter)
+    : adapter_(adapter) {
+}
+
+void BluetoothServiceHandler::Unregister(const picojson::value& data, picojson::object& out) {
+  LoggerD("Entered");
+
+  const auto& args = util::GetArguments(data);
+
+  adapter_.UnregisterUUID(FromJson<std::string>(args, "uuid"),
+                          util::GetAsyncCallbackHandle(data));
+
+  tools::ReportSuccess(out);
+}
+
+} // namespace bluetooth
+} // namespace extension
diff --git a/webWidgetTCT_device/src/bluetooth/bluetooth_service_handler.h b/webWidgetTCT_device/src/bluetooth/bluetooth_service_handler.h
new file mode 100755 (executable)
index 0000000..9feca9d
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2015 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 BLUETOOTH_BLUETOOTH_SERVICE_HANDLER_H_
+#define BLUETOOTH_BLUETOOTH_SERVICE_HANDLER_H_
+
+#include "common/picojson.h"
+
+namespace extension {
+namespace bluetooth {
+
+class BluetoothAdapter;
+
+class BluetoothServiceHandler {
+ public:
+  explicit BluetoothServiceHandler(BluetoothAdapter& adapter);
+
+  /**
+   * Signature: @code void unregister(successCallback, errorCallback); @endcode
+   * JSON: @code data: {method: 'BluetoothServiceHandler_unregister', args: {}} @endcode
+   * Invocation: @code native.call(request, result_callback); @endcode
+   * Return:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success'}
+   * @endcode
+   * Result callback:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success'}
+   * @endcode
+   */
+  void Unregister(const picojson::value& data, picojson::object& out);
+
+ private:
+  BluetoothAdapter& adapter_;
+};
+
+} // namespace bluetooth
+} // namespace extension
+
+#endif // BLUETOOTH_BLUETOOTH_SERVICE_HANDLER_H_
diff --git a/webWidgetTCT_device/src/bluetooth/bluetooth_socket.cc b/webWidgetTCT_device/src/bluetooth/bluetooth_socket.cc
new file mode 100755 (executable)
index 0000000..518223f
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2015 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 "bluetooth_socket.h"
+
+#include <memory>
+
+#include "common/converter.h"
+#include "common/logger.h"
+#include "common/extension.h"
+
+#include "bluetooth_adapter.h"
+#include "bluetooth_device.h"
+#include "bluetooth_util.h"
+
+namespace extension {
+namespace bluetooth {
+
+namespace {
+const std::string kBluetoothSocketId = "id";
+const std::string kBluetoothSocketUuid = "uuid";
+const std::string kBluetoothSocketState = "state";
+const std::string kBluetoothSocketPeer = "peer";
+const std::string kBluetoothSocketStateOpen = "OPEN";
+// error
+const int kBluetoothError = -1;
+}
+
+using namespace common;
+using namespace common::tools;
+
+BluetoothSocket::BluetoothSocket(BluetoothAdapter& adapter)
+    : adapter_(adapter) {
+}
+
+void BluetoothSocket::WriteData(const picojson::value& data, picojson::object& out) {
+  LoggerD("Enter");
+
+  const auto& args = util::GetArguments(data);
+
+  int socket = common::stol(FromJson<std::string>(args, "id"));
+  const auto& binary_data = FromJson<picojson::array>(args, "data");
+  const auto data_size = binary_data.size();
+
+  std::unique_ptr<char[]> data_ptr{new char[data_size]};
+
+  for (std::size_t i = 0; i < data_size; ++i) {
+    data_ptr[i] = static_cast<char>(binary_data[i].get<double>());
+  }
+
+  if (kBluetoothError == bt_socket_send_data(socket, data_ptr.get(), data_size)) {
+    LoggerE("bt_socket_send_data() failed");
+    ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error"), &out);
+    return;
+  }
+
+  ReportSuccess(picojson::value(static_cast<double>(data_size)), out);
+}
+
+void BluetoothSocket::ReadData(const picojson::value& data, picojson::object& out) {
+  LoggerD("Enter");
+
+  const auto& args = util::GetArguments(data);
+
+  int socket = common::stol(FromJson<std::string>(args, "id"));
+
+  auto binary_data = adapter_.ReadSocketData(socket);
+  picojson::value ret = picojson::value(picojson::array());
+  picojson::array& array = ret.get<picojson::array>();
+
+  for (auto val : binary_data) {
+    array.push_back(picojson::value(static_cast<double>(val)));
+  }
+
+  adapter_.ClearSocketData(socket);
+
+  ReportSuccess(ret, out);
+}
+
+void BluetoothSocket::Close(const picojson::value& data, picojson::object& out) {
+  LoggerD("Enter");
+
+  const auto& args = util::GetArguments(data);
+
+  int socket = common::stol(FromJson<std::string>(args, "id"));
+
+  if (BT_ERROR_NONE != bt_socket_disconnect_rfcomm(socket)) {
+    LoggerE("bt_socket_disconnect_rfcomm() failed");
+    ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error"), &out);
+    return;
+  }
+
+  ReportSuccess(out);
+}
+
+picojson::value BluetoothSocket::ToJson(bt_socket_connection_s* connection) {
+  LoggerD("Enter");
+
+  picojson::value ret = picojson::value(picojson::object());
+  auto& ret_obj = ret.get<picojson::object>();
+
+  ret_obj.insert(std::make_pair(kBluetoothSocketId,
+                                picojson::value(std::to_string(connection->socket_fd))));
+  ret_obj.insert(std::make_pair(kBluetoothSocketUuid,
+                                picojson::value(connection->service_uuid)));
+  ret_obj.insert(std::make_pair(kBluetoothSocketState,
+                                picojson::value(kBluetoothSocketStateOpen)));
+
+  bt_device_info_s* device_info = nullptr;
+
+  if (BT_ERROR_NONE == bt_adapter_get_bonded_device_info(connection->remote_address, &device_info) &&
+      nullptr != device_info) {
+    picojson::value& device = ret_obj.insert(std::make_pair(
+        kBluetoothSocketPeer, picojson::value(picojson::object()))).first->second;
+
+    BluetoothDevice::ToJson(device_info, &device.get<picojson::object>());
+    bt_adapter_free_device_info(device_info);
+  } else {
+    LoggerE("Peer not found");
+  }
+
+  return ret;
+}
+
+} // namespace bluetooth
+} // namespace extension
diff --git a/webWidgetTCT_device/src/bluetooth/bluetooth_socket.h b/webWidgetTCT_device/src/bluetooth/bluetooth_socket.h
new file mode 100755 (executable)
index 0000000..64321b8
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2015 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 BLUETOOTH_BLUETOOTH_SOCKET_H__
+#define BLUETOOTH_BLUETOOTH_SOCKET_H__
+
+#include <bluetooth.h>
+
+#include "common/picojson.h"
+
+namespace extension {
+namespace bluetooth {
+
+class BluetoothAdapter;
+
+class BluetoothSocket {
+ public:
+  explicit BluetoothSocket(BluetoothAdapter& adapter);
+
+  /**
+   * Signature: @code unsigned long writeData(data[]); @endcode
+   * JSON: @code data: {method: 'BluetoothSocket_writeData', args: {data: data}} @endcode
+   * Invocation: @code native.callSync(request); @endcode
+   * Return:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success', result: {bytes_sent}}
+   * @endcode
+   */
+  void WriteData(const picojson::value& data, picojson::object& out);
+
+  /**
+   * Signature: @code byte[] readData(); @endcode
+   * JSON: @code data: {method: 'BluetoothSocket_readData', args: {}} @endcode
+   * Invocation: @code native.callSync(request); @endcode
+   * Return:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success', result: {bytes_read}}
+   * @endcode
+   */
+  void ReadData(const picojson::value& data, picojson::object& out);
+
+  /**
+   * Signature: @code void close(); @endcode
+   * JSON: @code data: {method: 'BluetoothSocket_close', args: {}} @endcode
+   * Invocation: @code native.callSync(request); @endcode
+   * Return:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success'}
+   * @endcode
+   */
+  void Close(const picojson::value& data, picojson::object& out);
+
+  static picojson::value ToJson(bt_socket_connection_s* connection);
+
+ private:
+  BluetoothAdapter& adapter_;
+};
+
+} // namespace bluetooth
+} // namespace extension
+
+#endif // BLUETOOTH_BLUETOOTH_SOCKET_H__
diff --git a/webWidgetTCT_device/src/bluetooth/bluetooth_util.cc b/webWidgetTCT_device/src/bluetooth/bluetooth_util.cc
new file mode 100755 (executable)
index 0000000..0e4ff88
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2015 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 "bluetooth/bluetooth_util.h"
+
+#include <bluetooth.h>
+
+namespace extension {
+namespace bluetooth {
+namespace util {
+
+using common::ErrorCode;
+using common::PlatformResult;
+
+namespace {
+const char* JSON_CALLBACK_ID = "callbackId";
+} // namespace
+
+double GetAsyncCallbackHandle(const picojson::value& data) {
+  return data.get(JSON_CALLBACK_ID).get<double>();
+}
+
+const picojson::object& GetArguments(const picojson::value& data) {
+  return data.get<picojson::object>();
+}
+
+PlatformResult GetBluetoothError(int error_code,
+                                         const std::string& hint) {
+  common::ErrorCode error = ErrorCode::UNKNOWN_ERR;
+
+  switch (error_code) {
+    case BT_ERROR_RESOURCE_BUSY:
+    case BT_ERROR_NOW_IN_PROGRESS:
+    case BT_ERROR_NOT_ENABLED:
+      error = ErrorCode::SERVICE_NOT_AVAILABLE_ERR;
+      break;
+
+    case BT_ERROR_REMOTE_DEVICE_NOT_FOUND:
+      error = ErrorCode::NOT_FOUND_ERR;
+      break;
+
+    case BT_ERROR_INVALID_PARAMETER:
+      error = ErrorCode::INVALID_VALUES_ERR;
+      break;
+
+    case BT_ERROR_QUOTA_EXCEEDED:
+       error = ErrorCode::QUOTA_EXCEEDED_ERR;
+       break;
+
+    default:
+      error = ErrorCode::UNKNOWN_ERR;
+      break;
+  }
+
+  return PlatformResult(error,
+                        hint + " : " + GetBluetoothErrorMessage(error_code));
+}
+
+std::string GetBluetoothErrorMessage(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";
+  }
+}
+
+} // util
+} // bluetooth
+} // extension
diff --git a/webWidgetTCT_device/src/bluetooth/bluetooth_util.h b/webWidgetTCT_device/src/bluetooth/bluetooth_util.h
new file mode 100755 (executable)
index 0000000..2673711
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2015 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 BLUETOOTH_BLUETOOTH_UTIL_H_
+#define BLUETOOTH_BLUETOOTH_UTIL_H_
+
+#include <memory>
+#include <string>
+
+#include "common/picojson.h"
+#include "common/platform_result.h"
+
+namespace extension {
+namespace bluetooth {
+namespace util {
+
+double GetAsyncCallbackHandle(const picojson::value& data);
+
+const picojson::object& GetArguments(const picojson::value& data);
+
+common::PlatformResult GetBluetoothError(int error_code, const std::string& hint);
+std::string GetBluetoothErrorMessage(int error_code);
+
+} // util
+} // bluetooth
+} // extension
+
+#endif // BLUETOOTH_BLUETOOTH_UTIL_H_
diff --git a/webWidgetTCT_device/src/bookmark/bookmark.gyp b/webWidgetTCT_device/src/bookmark/bookmark.gyp
new file mode 100755 (executable)
index 0000000..5d1af2f
--- /dev/null
@@ -0,0 +1,30 @@
+{
+  'includes':[
+    '../common/common.gypi',
+  ],
+  'targets': [
+    {
+      'target_name': 'tizen_bookmark',
+      'type': 'loadable_module',
+      'dependencies': [
+        '../common/common.gyp:tizen_common',
+      ],
+      'sources': [
+        'bookmark_api.js',
+        'bookmark_extension.cc',
+        'bookmark_extension.h',
+        'bookmark_instance.cc',
+        'bookmark_instance.h',
+      ],
+      'conditions': [
+        ['tizen == 1', {
+          'variables': {
+            'packages': [
+              'bookmark-adaptor',
+            ]
+          },
+        }],
+      ],
+    },
+  ],
+}
diff --git a/webWidgetTCT_device/src/bookmark/bookmark_api.js b/webWidgetTCT_device/src/bookmark/bookmark_api.js
new file mode 100755 (executable)
index 0000000..fc3decd
--- /dev/null
@@ -0,0 +1,376 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+var validator_ = xwalk.utils.validator;
+var privilege_ = xwalk.utils.privilege;
+var types_ = validator_.Types;
+var native_ = new xwalk.utils.NativeManager(extension);
+
+function EditManager() {
+  this.canEdit = false;
+}
+
+EditManager.prototype.allow = function() {
+  this.canEdit = true;
+};
+
+EditManager.prototype.disallow = function() {
+  this.canEdit = false;
+};
+
+var _edit = new EditManager();
+
+function BookmarkManager() {}
+
+BookmarkManager.prototype.get = function() {
+  xwalk.utils.checkPrivilegeAccess(privilege_.BOOKMARK_READ);
+
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'parentFolder',
+      type: types_.PLATFORM_OBJECT,
+      values: [tizen.BookmarkFolder, tizen.BookmarkItem],
+      optional: true,
+      nullable: true
+    },
+    {
+      name: 'recursive',
+      type: types_.BOOLEAN,
+      optional: true,
+      nullable: true
+    }
+  ]);
+  var result;
+
+  if (arguments.length === 0 || args.parentFolder === null) {
+    result = provider.getFolderItems(provider.getRootId(), args.recursive);
+    if (!result)
+      throw new WebAPIException(WebAPIException.NOT_FOUND_ERR);
+    return result;
+  }
+  if (args.parentFolder.id === null || args.parentFolder.id === 0)
+    throw new WebAPIException(WebAPIException.NOT_FOUND_ERR);
+
+  result = provider.getFolderItems(args.parentFolder.id, args.recursive);
+  if (!result)
+    throw new WebAPIException(WebAPIException.NOT_FOUND_ERR);
+  return result;
+};
+
+BookmarkManager.prototype.add = function() {
+  xwalk.utils.checkPrivilegeAccess(privilege_.BOOKMARK_WRITE);
+
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'bookmark',
+      type: types_.PLATFORM_OBJECT,
+      values: [tizen.BookmarkFolder, tizen.BookmarkItem],
+      optional: false,
+      nullable: false
+    },
+    {
+      name: 'parentFolder',
+      type: types_.PLATFORM_OBJECT,
+      values: tizen.BookmarkFolder,
+      optional: true,
+      nullable: true
+    }
+  ]);
+  if (arguments.length == 1 || args.parentFolder === null) {
+    if (args.bookmark.id) {
+      throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR);
+    }
+    if (!provider.addToFolder(args.bookmark, provider.getRootId())) {
+      throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR);
+    }
+    return;
+  }
+  if (!args.parentFolder.id) {
+    throw new WebAPIException(WebAPIException.NOT_FOUND_ERR);
+  }
+  if (!provider.addToFolder(args.bookmark, args.parentFolder.id)) {
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR);
+  }
+};
+
+BookmarkManager.prototype.remove = function() {
+  xwalk.utils.checkPrivilegeAccess(privilege_.BOOKMARK_WRITE);
+
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'bookmark',
+      type: types_.PLATFORM_OBJECT,
+      values: [tizen.BookmarkFolder, tizen.BookmarkItem],
+      optional: true,
+      nullable: true
+    }
+  ]);
+
+  if (!arguments.length || args.bookmark === null) {
+    if (native_.isFailure(native_.callSync('Bookmark_removeAll')))
+      throw new WebAPIException(WebAPIException.SECURITY_ERR);
+    return;
+  }
+  if (!args.bookmark.id)
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR);
+  if (native_.isFailure(native_.callSync('Bookmark_remove', {
+    id: args.bookmark.id})))
+    throw new WebAPIException(WebAPIException.SECURITY_ERR);
+
+  _edit.allow();
+  args.bookmark.id = null;
+  args.bookmark.parent = undefined;
+  _edit.disallow();
+};
+
+function BookmarkProvider() {}
+
+BookmarkProvider.prototype.addToFolder = function() {
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'bookmark',
+      type: types_.PLATFORM_OBJECT,
+      values: [tizen.BookmarkFolder, tizen.BookmarkItem],
+      optional: true,
+      nullable: true
+    },
+    {
+      name: 'parentId',
+      type: types_.DOUBLE,
+      optional: false,
+      nullable: false}
+  ]);
+  var ret = native_.callSync('Bookmark_add',
+    {
+      title: args.bookmark.title,
+      url: String(args.bookmark.url),
+      parentId: args.parentId,
+      type: args.bookmark instanceof tizen.BookmarkFolder ? 1 : 0
+    }
+  );
+  if (native_.isFailure(ret)) {
+    return false;
+  }
+  var ret_id = native_.getResultObject(ret);
+  _edit.allow();
+  args.bookmark.id = ret_id;
+  args.bookmark.parent = this.getFolder(args.parentId);
+  _edit.disallow();
+  return true;
+};
+
+BookmarkProvider.prototype.getFolder = function() {
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'id',
+      type: types_.DOUBLE,
+      optional: false,
+      nullable: false
+    }
+  ]);
+  if (arguments.length === 0 || args.id <= 0)
+    return null;
+  if (args.id == this.getRootId())
+    return null;
+
+  var ret = native_.callSync('Bookmark_get', {
+    id: args.id,
+    shouldGetItems: 0
+  });
+
+  if (native_.isFailure(ret)) {
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR);
+  }
+
+  var folder = native_.getResultObject(ret);
+  if (folder === undefined || folder === null)
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR);
+
+  var obj = new tizen.BookmarkFolder(folder[0].title);
+  obj.id = folder[0].id;
+  obj.parent = this.getFolder(folder[0].parentId);
+  return obj;
+};
+
+BookmarkProvider.prototype.getFolderItems = function() {
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'id',
+      type: types_.DOUBLE,
+      optional: false,
+      nullable: false
+    },
+    {
+      name: 'recursive',
+      type: types_.BOOLEAN,
+      optional: true,
+      nullable: true
+    }
+  ]);
+
+  var ret = native_.callSync('Bookmark_get', {
+    id: Number(args.id),
+    shouldGetItems: 1
+  });
+
+  if (native_.isFailure(ret)) {
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR);
+  }
+
+  var folder = native_.getResultObject(ret);
+  if (folder === undefined)
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR);
+
+  var item;
+  var obj;
+  var result = [];
+  var len = folder.length;
+
+  for (var i = 0; item = folder[i], i < len; i++) {
+    if (Number(item.type) === 0)
+      obj = new tizen.BookmarkItem(item.title, item.url);
+    else
+      obj = new tizen.BookmarkFolder(item.title);
+
+    _edit.allow();
+    obj.id = item.id;
+    obj.parent = this.getFolder(item.parentId);
+    _edit.disallow();
+    result.push(obj);
+
+    if (args.recursive && Number(item.type) !== 0)
+      result = result.concat(this.getFolderItems(item.id, true));
+  }
+  return result;
+};
+
+BookmarkProvider.prototype.getRootId = function() {
+  var ret = native_.callSync('Bookmark_getRootId');
+  if (native_.isFailure(ret)) {
+    throw native_.getErrorObject(ret);
+  }
+  var rootId = native_.getResultObject(ret);
+  return Number(rootId);
+};
+
+var provider = new BookmarkProvider();
+
+tizen.BookmarkItem = function() {
+  validator_.isConstructorCall(this, tizen.BookmarkItem);
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'title',
+      type: types_.STRING,
+      optional: false
+    },
+    {
+      name: 'url',
+      type: types_.STRING,
+      optional: false
+    }
+  ]);
+  var parent_;
+  var id_ = null;
+
+  Object.defineProperties(this, {
+    parent: {
+      get: function() {
+        return parent_;
+      },
+      set: function(new_parent) {
+        if (_edit.canEdit)
+          parent_ = new_parent;
+      },
+      enumerable: true,
+      nullable: true
+    },
+    title: {
+      get: function() {
+        return args.title;
+      },
+      enumerable: true,
+      nullable: false
+    },
+    url: {
+      get: function() {
+        if (args.url === "undefined")
+          args.url = undefined;
+        return args.url;
+      },
+      enumerable: true,
+      nullable: false
+    },
+    id: {
+      get: function() {
+        return id_;
+      },
+      set: function(new_id) {
+        if (_edit.canEdit)
+          id_ = new_id;
+      },
+      enumerable: false,
+      nullable: true
+    }
+  });
+};
+
+tizen.BookmarkFolder = function() {
+  validator_.isConstructorCall(this, tizen.BookmarkFolder);
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'title',
+      type: types_.STRING,
+      optional: false,
+      nullable: false
+    }
+  ]);
+
+  var parent_;
+  var id_ = null;
+
+  Object.defineProperties(this, {
+    parent: {
+      get: function() {
+        return parent_;
+      },
+      set: function(new_parent) {
+        if (_edit.canEdit)
+          parent_ = new_parent;
+      },
+      enumerable: true,
+      nullable: true
+    },
+    title: {
+      get: function() {
+        return args.title;
+      },
+      enumerable: true,
+      nullable: false
+    },
+    id: {
+      get: function() {
+        return id_;
+      },
+      set: function(new_id) {
+        if (_edit.canEdit)
+          id_ = new_id;
+      },
+      enumerable: false,
+      nullable: true
+    }
+  });
+};
+exports = new BookmarkManager();
diff --git a/webWidgetTCT_device/src/bookmark/bookmark_extension.cc b/webWidgetTCT_device/src/bookmark/bookmark_extension.cc
new file mode 100755 (executable)
index 0000000..8504f44
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2015 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 "bookmark/bookmark_extension.h"
+#include "bookmark/bookmark_instance.h"
+#include "common/logger.h"
+
+namespace {
+  const char kBookmark[] = "tizen.bookmark";
+  const char kBookmarkItem[] = "tizen.BookmarkItem";
+  const char kBookmarkFolder[] = "tizen.BookmarkFolder";
+}
+
+// This will be generated from bookmark_api.js.
+extern const char kSource_bookmark_api[];
+
+common::Extension* CreateExtension() {
+  return new BookmarkExtension;
+}
+
+BookmarkExtension::BookmarkExtension() {
+  SetExtensionName(kBookmark);
+  SetJavaScriptAPI(kSource_bookmark_api);
+
+  const char* entry_points[] = {
+    kBookmarkItem,
+    kBookmarkFolder,
+    NULL
+  };
+  SetExtraJSEntryPoints(entry_points);
+
+  if (bp_bookmark_adaptor_initialize()) {
+     LOGGER(ERROR) << "Fail: Bookmark not supported";
+  }
+}
+
+BookmarkExtension::~BookmarkExtension() {
+  if (bp_bookmark_adaptor_deinitialize()) {
+    LOGGER(ERROR) << "Fail: Deinitialize Bookmark";
+  }
+}
+
+common::Instance* BookmarkExtension::CreateInstance() {
+  return new extension::bookmark::BookmarkInstance;
+}
diff --git a/webWidgetTCT_device/src/bookmark/bookmark_extension.h b/webWidgetTCT_device/src/bookmark/bookmark_extension.h
new file mode 100755 (executable)
index 0000000..c2b1ffc
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2015 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 BOOKMARK_BOOKMARK_EXTENSION_H_
+#define BOOKMARK_BOOKMARK_EXTENSION_H_
+
+#include "common/extension.h"
+
+class BookmarkExtension : public common::Extension {
+ public:
+  BookmarkExtension();
+  virtual ~BookmarkExtension();
+
+ private:
+  virtual common::Instance* CreateInstance();
+};
+
+#endif  // BOOKMARK_BOOKMARK_EXTENSION_H_
diff --git a/webWidgetTCT_device/src/bookmark/bookmark_instance.cc b/webWidgetTCT_device/src/bookmark/bookmark_instance.cc
new file mode 100755 (executable)
index 0000000..adaa001
--- /dev/null
@@ -0,0 +1,313 @@
+/*
+ * Copyright (c) 2015 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 "bookmark/bookmark_instance.h"
+
+#include <web/bookmark-adaptor.h>
+#include <string>
+
+#include "common/platform_exception.h"
+#include "common/converter.h"
+#include "common/logger.h"
+
+using common::ErrorCode;
+using common::PlatformResult;
+
+namespace extension {
+namespace bookmark {
+
+namespace {
+  const char kId[] = "id";
+  const char kTitle[] = "title";
+  const char kType[] = "type";
+  const char kParentId[] = "parentId";
+  const char kUrl[] = "url";
+}  // namespace
+
+BookmarkInstance::BookmarkInstance() {
+  LoggerD("Enter");
+  using std::placeholders::_1;
+  using std::placeholders::_2;
+
+#define REGISTER_SYNC(c,x) \
+    RegisterSyncHandler(c, std::bind(&BookmarkInstance::x, this, _1, _2));
+  REGISTER_SYNC("Bookmark_get", BookmarkGet);
+  REGISTER_SYNC("Bookmark_add", BookmarkAdd);
+  REGISTER_SYNC("Bookmark_remove", BookmarkRemove);
+  REGISTER_SYNC("Bookmark_removeAll", BookmarkRemoveAll);
+  REGISTER_SYNC("Bookmark_getRootId", BookmarkGetRootId);
+#undef REGISTER_SYNC
+}
+
+BookmarkInstance::~BookmarkInstance() {
+  LoggerD("Enter");
+}
+
+bool BookmarkInstance::bookmark_foreach(
+    Context& ctx, bp_bookmark_info_fmt& info) {
+
+  LoggerD("Enter");
+  int ids_count = 0;
+  int* ids = NULL;
+  BookmarkObject item;
+  if (bp_bookmark_adaptor_get_ids_p(&ids, &ids_count, -1, 0, -1, -1, -1, -1,
+                                    BP_BOOKMARK_O_DATE_CREATED, 0) < 0)
+    return false;
+
+
+  if (ids_count > 0) {
+    for (int i = 0; i < ids_count; i++) {
+      bp_bookmark_adaptor_get_easy_all(ids[i], &info);
+      item.id = ids[i];
+      item.bookmark_info = info;
+      if ((ctx.shouldGetItems && item.bookmark_info.parent != ctx.id) ||
+        (!ctx.shouldGetItems && item.id != ctx.id))
+        continue;
+      ctx.folders.push_back(item);
+    }
+  }
+  free(ids);
+  return true;
+}
+
+PlatformResult BookmarkInstance::BookmarkUrlExists(const char* url,
+                                                   bool* exists) {
+  LoggerD("Enter");
+  int ids_count = 0;
+  int* ids = nullptr;
+  char* compare_url = nullptr;
+
+  if (bp_bookmark_adaptor_get_ids_p(&ids,  // ids
+                                    &ids_count,  // count
+                                    -1,  //limit
+                                    0,  // offset
+                                    -1,  //parent
+                                    -1,  //type
+                                    -1,  // is_operator
+                                    -1,  // is_editable
+                                    BP_BOOKMARK_O_DATE_CREATED,  // order_offset
+                                    0  // ordering ASC
+                                    ) < 0) {
+    LoggerE("Failed to obtain bookmarks");
+    return PlatformResult{ErrorCode::UNKNOWN_ERR, "Failed to obtain bookmarks"};
+  }
+
+  PlatformResult result{ErrorCode::NO_ERROR};
+  bool url_found = false;
+  for (int i = 0; (i < ids_count) && result && !url_found; ++i) {
+    if (bp_bookmark_adaptor_get_url(ids[i], &compare_url) < 0) {
+      LoggerE("Failed to obtain URL");
+      result = PlatformResult{ErrorCode::UNKNOWN_ERR, "Failed to obtain URL"};
+    } else {
+      url_found = (0 == strcmp(url, compare_url));
+      free(compare_url);
+      compare_url = nullptr;
+    }
+  }
+
+  if (result) {
+    *exists = url_found;
+  }
+
+  free(ids);
+
+  return result;
+}
+
+PlatformResult BookmarkInstance::BookmarkTitleExistsInParent(const char* title,
+                                                             int parent,
+                                                             bool* exists) {
+
+  LoggerD("Enter");
+  int ids_count = 0;
+  int compare_parent = -1;
+  int* ids = nullptr;
+  char* compare_title = nullptr;
+
+  if (bp_bookmark_adaptor_get_ids_p(&ids,  // ids
+                                    &ids_count,  // count
+                                    -1,  //limit
+                                    0,  // offset
+                                    -1,  //parent
+                                    -1,  //type
+                                    -1,  // is_operator
+                                    -1,  // is_editable
+                                    BP_BOOKMARK_O_DATE_CREATED,  // order_offset
+                                    0  // ordering ASC
+                                    ) < 0) {
+    LoggerE("Failed to obtain bookmarks");
+    return PlatformResult{ErrorCode::UNKNOWN_ERR, "Failed to obtain bookmarks"};
+  }
+
+  PlatformResult result{ErrorCode::NO_ERROR};
+  bool title_found = false;
+  for (int i = 0; (i < ids_count) && result && !title_found; ++i) {
+    if (bp_bookmark_adaptor_get_parent_id(ids[i], &compare_parent) < 0) {
+      LoggerE("Failed to obtain parent ID");
+      result = PlatformResult{ErrorCode::UNKNOWN_ERR, "Failed to obtain parent ID"};
+    } else if (bp_bookmark_adaptor_get_title(ids[i], &compare_title) < 0) {
+      LoggerE("Failed to obtain title");
+      result = PlatformResult{ErrorCode::UNKNOWN_ERR, "Failed to obtain title"};
+    } else {
+      title_found = (parent == compare_parent) && (0 == strcmp(title, compare_title));
+      free(compare_title);
+      compare_title = nullptr;
+      compare_parent = -1;
+    }
+  }
+
+  if (result) {
+    *exists = title_found;
+  }
+
+  free(ids);
+
+  return result;
+}
+
+void BookmarkInstance::BookmarkGet(
+    const picojson::value& arg, picojson::object& o) {
+
+  LoggerD("Enter");
+  Context ctx = {0};
+  bp_bookmark_info_fmt info = {0};
+  picojson::value::array arr;
+
+  ctx.shouldGetItems = arg.get("shouldGetItems").get<double>();
+  ctx.id             = arg.get(kId).get<double>();
+
+  if (!bookmark_foreach(ctx, info)) {
+    ReportError(o);
+    return;
+  }
+
+  std::vector<BookmarkObject>::iterator it;
+  for (it = ctx.folders.begin(); it!= ctx.folders.end(); ++it) {
+    picojson::object obj;
+    BookmarkObject entry = *it;
+
+    obj[kTitle] = picojson::value(entry.bookmark_info.title);
+    obj[kId] = picojson::value(std::to_string(entry.id));
+    obj[kType] = picojson::value(std::to_string(entry.bookmark_info.type));
+    obj[kParentId] = picojson::value(std::to_string(
+        entry.bookmark_info.parent));
+    if (!entry.bookmark_info.type)
+      obj[kUrl] = picojson::value(entry.bookmark_info.url);
+
+    arr.push_back(picojson::value(obj));
+  }
+  ReportSuccess(picojson::value(arr), o);
+}
+
+void BookmarkInstance::BookmarkAdd(
+    const picojson::value& arg, picojson::object& o) {
+
+  LoggerD("Enter");
+  int saved_id =-1;
+
+  const auto& title = arg.get(kTitle).get<std::string>();
+  const int parent = static_cast<int>(arg.get(kParentId).get<double>());
+  const int type = static_cast<int>(arg.get(kType).get<double>());
+  const auto& url = arg.get(kUrl).get<std::string>();
+
+  if (0 == type) {  // bookmark
+    bool exists = false;
+    auto result = BookmarkUrlExists(url.c_str(), &exists);
+    if (!result) {
+      ReportError(result, &o);
+      return;
+    } else if (exists) {
+      ReportError(PlatformResult{ErrorCode::UNKNOWN_ERR, "Bookmark already exists"}, &o);
+      return;
+    }
+  }
+
+  if (1 == type) {  // folder
+    bool exists = false;
+    auto result = BookmarkTitleExistsInParent(title.c_str(), parent, &exists);
+    if (!result) {
+      ReportError(result, &o);
+      return;
+    } else if (exists) {
+      ReportError(PlatformResult{ErrorCode::UNKNOWN_ERR, "Bookmark already exists"}, &o);
+      return;
+    }
+  }
+
+  if (bp_bookmark_adaptor_create(&saved_id) < 0) {
+    ReportError(o);
+    return;
+  }
+  if (bp_bookmark_adaptor_set_title(saved_id, title.c_str()) < 0) {
+    bp_bookmark_adaptor_delete(saved_id);
+    ReportError(o);
+    return;
+  }
+  if (bp_bookmark_adaptor_set_parent_id(saved_id, parent) < 0) {
+    bp_bookmark_adaptor_delete(saved_id);
+    ReportError(o);
+    return;
+  }
+  if (bp_bookmark_adaptor_set_type(saved_id, type) < 0) {
+    bp_bookmark_adaptor_delete(saved_id);
+    ReportError(o);
+    return;
+  }
+  if (bp_bookmark_adaptor_set_url(saved_id, url.c_str()) < 0) {
+    bp_bookmark_adaptor_delete(saved_id);
+    ReportError(o);
+    return;
+  }
+  ReportSuccess(picojson::value(std::to_string(saved_id)), o);
+}
+
+void BookmarkInstance::BookmarkRemove(
+    const picojson::value& arg, picojson::object& o) {
+
+  LoggerD("Enter");
+  int id = common::stol(
+      common::FromJson<std::string>(arg.get<picojson::object>(), kId));
+  if (bp_bookmark_adaptor_delete(id) < 0) {
+    ReportError(o);
+    return;
+  }
+  ReportSuccess(o);
+}
+
+void BookmarkInstance::BookmarkRemoveAll(
+    const picojson::value& msg, picojson::object& o) {
+
+  LoggerD("Enter");
+  if (bp_bookmark_adaptor_reset() < 0) {
+    ReportError(o);
+    return;
+  }
+  ReportSuccess(o);
+}
+
+void BookmarkInstance::BookmarkGetRootId(
+    const picojson::value& msg, picojson::object& o) {
+
+  LoggerD("Enter");
+  int rootId(0);
+  if (bp_bookmark_adaptor_get_root(&rootId) < 0) {
+    ReportError(o);
+    return;
+  }
+  ReportSuccess(picojson::value(std::to_string(rootId)), o);
+}
+}  // namespace bookmark
+}  // namespace extension
diff --git a/webWidgetTCT_device/src/bookmark/bookmark_instance.h b/webWidgetTCT_device/src/bookmark/bookmark_instance.h
new file mode 100755 (executable)
index 0000000..74de11b
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2015 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 BOOKMARK_BOOKMARK_INSTANCE_H_
+#define BOOKMARK_BOOKMARK_INSTANCE_H_
+
+#include <web/web_bookmark.h>
+#include <vector>
+
+#include "common/extension.h"
+#include "common/picojson.h"
+#include "common/platform_result.h"
+
+namespace extension {
+namespace bookmark {
+
+struct BookmarkObject {
+  int id;
+  bp_bookmark_info_fmt bookmark_info;
+};
+
+struct Context {
+  int id;
+  int shouldGetItems;
+  std::vector<BookmarkObject> folders;
+};
+
+class BookmarkInstance : public common::ParsedInstance {
+ public:
+  BookmarkInstance();
+  virtual ~BookmarkInstance();
+
+ private:
+  bool bookmark_foreach(Context& ctx, bp_bookmark_info_fmt& info);
+  common::PlatformResult BookmarkUrlExists(const char* url, bool* exists);
+  common::PlatformResult BookmarkTitleExistsInParent(const char* title,
+                                                     int parent, bool* exists);
+  void BookmarkGet(const picojson::value& arg, picojson::object& o);
+  void BookmarkAdd(const picojson::value& arg, picojson::object& o);
+  void BookmarkRemove(const picojson::value& arg, picojson::object& o);
+  void BookmarkRemoveAll(const picojson::value& msg, picojson::object& o);
+  void BookmarkGetRootId(const picojson::value& msg, picojson::object& o);
+};
+}  // namespace bookmark
+}  // namespace extension
+#endif  // BOOKMARK_BOOKMARK_INSTANCE_H_
diff --git a/webWidgetTCT_device/src/calendar/calendar.cc b/webWidgetTCT_device/src/calendar/calendar.cc
new file mode 100755 (executable)
index 0000000..bb1b9be
--- /dev/null
@@ -0,0 +1,1162 @@
+/*
+ * Copyright (c) 2015 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 "calendar.h"
+
+#include "common/platform_exception.h"
+#include "common/logger.h"
+#include "common/converter.h"
+#include "common/task-queue.h"
+#include "common/filter-utils.h"
+#include "calendar/calendar_manager.h"
+#include "calendar/calendar_privilege.h"
+#include "calendar/calendar_item.h"
+#include "calendar/calendar_instance.h"
+
+namespace extension {
+namespace calendar {
+
+typedef std::unique_ptr<std::remove_pointer<calendar_filter_h>::type,
+                        void (*)(calendar_filter_h)> CalendarFilterPtr;
+
+void CalendarFilterDeleter(calendar_filter_h calendar_filter) {
+  if (CALENDAR_ERROR_NONE != calendar_filter_destroy(calendar_filter)) {
+    LoggerE("failed to destroy contacts_filter_h");
+  }
+}
+
+using namespace common;
+
+Calendar::Calendar(CalendarInstance& instance)
+    : current_db_version_(0),
+      instance_(instance) {
+}
+
+Calendar::~Calendar() {
+  int ret;
+
+  if (listeners_registered_.find("EVENT") != listeners_registered_.end()) {
+    ret = calendar_db_remove_changed_cb(_calendar_event._uri, ChangeCallback,
+                                        this);
+    if (CALENDAR_ERROR_NONE != ret) {
+      LoggerE("Remove calendar event change callback error");
+    }
+  }
+
+  if (listeners_registered_.find("TASK") != listeners_registered_.end()) {
+    ret = calendar_db_remove_changed_cb(_calendar_todo._uri, ChangeCallback,
+                                        this);
+    if (CALENDAR_ERROR_NONE != ret) {
+      LoggerE("Remove calendar todo change callback error");
+    }
+  }
+}
+
+PlatformResult Calendar::Get(const picojson::object& args, picojson::object& out) {
+  if (!CalendarManager::GetInstance().IsConnected()) {
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "DB Connection failed.");
+  }
+
+  int calendar_id = common::stol(FromJson<std::string>(args, "calendarId"));
+
+  calendar_record_h handle = nullptr;
+  PlatformResult status =
+      CalendarRecord::GetById(calendar_id, _calendar_book._uri, &handle);
+  if (status.IsError()) return status;
+
+  CalendarRecordPtr calendar_ptr =
+      CalendarRecordPtr(handle, CalendarRecord::Deleter);
+
+  int type;
+  status = CalendarRecord::GetInt(calendar_ptr.get(), _calendar_book.store_type,
+                                  &type);
+  if (status.IsError()) return status;
+
+  int id;
+  if (type == CALENDAR_BOOK_TYPE_EVENT) {
+    id = common::stol(FromJson<std::string>(args, "id", "uid"));
+  } else {
+    id = common::stol(FromJson<std::string>(args, "id"));
+  }
+
+  std::string uri;
+  status = CalendarRecord::TypeToUri(type, &uri);
+  if (status.IsError()) return status;
+
+  calendar_record_h handle_uri = nullptr;
+  status = CalendarRecord::GetById(id, uri.c_str(), &handle_uri);
+  if (status.IsError()) return status;
+
+  CalendarRecordPtr record_ptr =
+      CalendarRecordPtr(handle_uri, CalendarRecord::Deleter);
+
+  status = CalendarItem::ToJson(type, record_ptr.get(), &out);
+  if (status.IsError()) return status;
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult Calendar::Add(const picojson::object& args,
+                             picojson::object& out) {
+  if (!CalendarManager::GetInstance().IsConnected()) {
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "DB Connection failed.");
+  }
+
+  const auto& item = FromJson<picojson::object>(args, "item");
+  int type = CalendarRecord::TypeToInt(FromJson<std::string>(args, "type"));
+
+  calendar_record_h handle = nullptr;
+  PlatformResult status = CalendarItem::Create(type, &handle);
+  if (status.IsError()) return status;
+
+  CalendarRecordPtr item_ptr =
+      CalendarRecordPtr(handle, CalendarRecord::Deleter);
+
+  status = CalendarItem::FromJson(type, item_ptr.get(), item);
+  if (status.IsError()) return status;
+
+  int record_id;
+  status = CalendarRecord::Insert(item_ptr.get(), &record_id);
+  if (status.IsError()) return status;
+
+  out.insert(std::make_pair("uid", picojson::value(std::to_string(record_id))));
+
+  if (type == CALENDAR_BOOK_TYPE_EVENT) {
+    std::string rid;
+    PlatformResult status = CalendarRecord::GetString(
+        item_ptr.get(), _calendar_event.recurrence_id, &rid);
+    if (status.IsError()) return status;
+
+    if (!rid.empty()) {
+      out["rid"] = picojson::value(rid);
+    } else {
+      out["rid"] = picojson::value();
+    }
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult Calendar::AddBatch(const picojson::object& args,
+                                  picojson::array& array) {
+  if (!CalendarManager::GetInstance().IsConnected()) {
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "DB Connection failed.");
+  }
+
+  auto& items = FromJson<picojson::array>(args, "items");
+  if (items.empty()) {
+    return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "No items");
+  }
+
+  int type = CalendarRecord::TypeToInt(FromJson<std::string>(args, "type"));
+  std::string view_uri;
+  PlatformResult status = CalendarRecord::TypeToUri(type, &view_uri);
+  if (status.IsError()) return status;
+
+  calendar_list_h list = NULL;
+  if (CALENDAR_ERROR_NONE != calendar_list_create(&list)) {
+    LoggerE("Could not create list for batch operation");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Could not create list for batch operation");
+  }
+  CalendarListPtr list_ptr = CalendarListPtr(list, CalendarRecord::ListDeleter);
+
+  int ret;
+  calendar_record_h record;
+
+  for (auto& item : items) {
+    ret = calendar_record_create(view_uri.c_str(), &record);
+    if (CALENDAR_ERROR_NONE != ret) {
+      LoggerW("Can't create platform record %d", ret);
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "Can't create platform record");
+    }
+    PlatformResult status =
+        CalendarItem::FromJson(type, record, item.get<picojson::object>());
+    if (status.IsError()) return status;
+
+    if (CALENDAR_ERROR_NONE != calendar_list_add(list_ptr.get(), record)) {
+      LoggerE("Could not add record to list events");
+      return PlatformResult(ErrorCode::INVALID_VALUES_ERR,
+                            "Could not add record to list");
+    }
+  }
+
+  int* ids;
+  int count;
+  ret = calendar_db_insert_records(list_ptr.get(), &ids, &count);
+  if (CALENDAR_ERROR_NONE != ret) {
+    LoggerE("calendar_db_insert_records failed.");
+    if (CALENDAR_ERROR_INVALID_PARAMETER == ret) {
+      LoggerE("CALENDAR_ERROR_INVALID_PARAMETER.");
+      return PlatformResult(ErrorCode::INVALID_VALUES_ERR,
+                            "Parameter is invalid");
+    } else {
+      LoggerE("CALENDAR_ERROR_DB_FAILED");
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "CALENDAR_ERROR_DB_FAILED occurred");
+    }
+  }
+
+  for (int i = 0; i < count; i++) {
+    picojson::value id = picojson::value(picojson::object());
+    picojson::object& id_obj = id.get<picojson::object>();
+
+    id_obj.insert(std::make_pair("uid", picojson::value(std::to_string(ids[i]))));
+
+    if (type == CALENDAR_BOOK_TYPE_EVENT) {
+      id_obj.insert(std::make_pair("rid", picojson::value()));
+    }
+
+    array.push_back(id);
+  }
+  free(ids);
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult Calendar::Update(const picojson::object& args,
+                                picojson::object& /*out*/) {
+  if (!CalendarManager::GetInstance().IsConnected()) {
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "DB Connection failed.");
+  }
+
+  const auto& item = FromJson<picojson::object>(args, "item");
+  int type = CalendarRecord::TypeToInt(FromJson<std::string>(args, "type"));
+
+  bool update_all = true;
+
+  int id;
+  if (type == CALENDAR_BOOK_TYPE_EVENT) {
+    id = common::stol(FromJson<std::string>(item, "id", "uid"));
+    if (!IsNull(args, "updateAllInstances")) {
+      update_all = FromJson<bool>(args, "updateAllInstances");
+    }
+  } else {
+    id = common::stol(FromJson<std::string>(item, "id"));
+  }
+
+  std::string value_str;
+  PlatformResult status = CalendarRecord::TypeToUri(type, &value_str);
+  if (status.IsError()) return status;
+
+  calendar_record_h handle = nullptr;
+  status = CalendarRecord::GetById(id, value_str.c_str(), &handle);
+  if (status.IsError()) return status;
+
+  CalendarRecordPtr record_ptr =
+      CalendarRecordPtr(handle, CalendarRecord::Deleter);
+
+  status = CalendarItem::FromJson(type, record_ptr.get(), item);
+  if (status.IsError()) return status;
+
+  if (type == CALENDAR_BOOK_TYPE_TODO || update_all ||
+      common::IsNull(item, "recurrenceRule")) {
+    if (CALENDAR_ERROR_NONE != calendar_db_update_record(record_ptr.get())) {
+      LoggerE("Can't update calendar item");
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "Can't update calendar item");
+    }
+  } else {
+    // first update the parent event
+    std::string exdate =
+        CalendarItem::ExceptionsFromJson(common::FromJson<picojson::array>(
+            item, "recurrenceRule", "exceptions"));
+    if (!common::IsNull(common::FromJson<picojson::object>(item, "id"),
+                        "rid")) {
+      exdate.append(common::FromJson<std::string>(item, "id", "rid"));
+    }
+    PlatformResult status = CalendarRecord::SetString(
+        record_ptr.get(), _calendar_event.exdate, exdate);
+    if (status.IsError()) return status;
+
+    // don't set the recurrence id for the parent event
+    status = CalendarRecord::SetString(record_ptr.get(),
+                                       _calendar_event.recurrence_id, "");
+    if (status.IsError()) return status;
+
+    if (CALENDAR_ERROR_NONE != calendar_db_update_record(record_ptr.get())) {
+      LoggerE("Can't update calendar item");
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "Can't update calendar item");
+    }
+
+    // now add the detached child event
+    calendar_record_h handle_new = nullptr;
+    status = CalendarItem::Create(type, &handle_new);
+    if (status.IsError()) return status;
+
+    CalendarRecordPtr item_ptr =
+        CalendarRecordPtr(handle_new, CalendarRecord::Deleter);
+
+    status = CalendarItem::FromJson(type, item_ptr.get(), item);
+    if (status.IsError()) return status;
+
+    int record_id;
+    status = CalendarRecord::Insert(item_ptr.get(), &record_id);
+    if (status.IsError()) return status;
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult Calendar::UpdateBatch(const picojson::object& args,
+                                     picojson::array& array) {
+  if (!CalendarManager::GetInstance().IsConnected()) {
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "DB Connection failed.");
+  }
+
+  auto& items = FromJson<picojson::array>(args, "items");
+  if (items.empty()) {
+    return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "No items");
+  }
+
+  bool update_all = true;
+  if (!IsNull(args, "updateAllInstances")) {
+    update_all = FromJson<bool>(args, "updateAllInstances");
+  }
+
+  int type = CalendarRecord::TypeToInt(FromJson<std::string>(args, "type"));
+  std::string view_uri;
+  PlatformResult status = CalendarRecord::TypeToUri(type, &view_uri);
+  if (status.IsError()) return status;
+
+  calendar_list_h list = NULL;
+  if (CALENDAR_ERROR_NONE != calendar_list_create(&list)) {
+    LoggerE("Could not create list for batch operation");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Could not create list for batch operation");
+  }
+  CalendarListPtr list_ptr = CalendarListPtr(list, CalendarRecord::ListDeleter);
+
+  int id;
+  calendar_record_h record;
+
+  for (auto& item : items) {
+    const picojson::object& item_obj = item.get<picojson::object>();
+    if (type == CALENDAR_BOOK_TYPE_EVENT) {
+      id = common::stol(FromJson<std::string>(item_obj, "id", "uid"));
+    } else {
+      id = common::stol(FromJson<std::string>(item_obj, "id"));
+    }
+
+    int ret = calendar_db_get_record(view_uri.c_str(), id, &record);
+    if (CALENDAR_ERROR_NONE != ret) {
+      LoggerW("Can't get platform record %d", ret);
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "Can't get platform record");
+    }
+    PlatformResult status =
+        CalendarItem::FromJson(type, record, item.get<picojson::object>());
+    if (status.IsError()) return status;
+
+    if (CALENDAR_ERROR_NONE != calendar_list_add(list_ptr.get(), record)) {
+      LoggerE("Could not add record to list events");
+      return PlatformResult(ErrorCode::INVALID_VALUES_ERR,
+                            "Could not add record to list");
+    }
+  }
+
+  if (type == CALENDAR_BOOK_TYPE_TODO || update_all) {
+    if (CALENDAR_ERROR_NONE != calendar_db_update_records(list_ptr.get())) {
+      LoggerE("Can't update calendar items");
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "Can't update calendar items");
+    }
+  } else {
+    // @todo update the exdate for a recurring parent event and add a new
+    // child event
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult Calendar::Remove(const picojson::object& args,
+                                picojson::object& out) {
+  if (!CalendarManager::GetInstance().IsConnected()) {
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "DB Connection failed.");
+  }
+
+  int type = CalendarRecord::TypeToInt(FromJson<std::string>(args, "type"));
+
+  int id;
+  if (type == CALENDAR_BOOK_TYPE_EVENT) {
+    id = common::stol(FromJson<std::string>(args, "id", "uid"));
+  } else {
+    id = common::stol(FromJson<std::string>(args, "id"));
+  }
+
+  return CalendarItem::Remove(type, id);
+}
+
+PlatformResult Calendar::SetDefaultFilter(calendar_query_h* calendar_query, int type, int id) {
+  LoggerD("Entered");
+
+  const long UNIFIED_CALENDAR_ID = 0;
+  int error_code = 0;
+  PlatformResult status = PlatformResult(ErrorCode::NO_ERROR);
+  calendar_filter_h calendar_filter = nullptr;
+  const char* view_uri =
+      (type == CALENDAR_BOOK_TYPE_EVENT) ? _calendar_event._uri : _calendar_todo._uri;
+  const int book_id =
+      (type == CALENDAR_BOOK_TYPE_EVENT) ? _calendar_event.calendar_book_id : _calendar_todo.calendar_book_id;
+  const int is_deleted =
+      (type == CALENDAR_BOOK_TYPE_EVENT) ? _calendar_event.is_deleted : _calendar_todo.is_deleted;
+
+  error_code = calendar_filter_create(view_uri, &calendar_filter);
+  if ((status = ErrorChecker(error_code)).IsError()) return status;
+
+  CalendarFilterPtr calendar_filter_ptr(calendar_filter, CalendarFilterDeleter);
+
+  calendar_match_int_flag_e match_int_flag = CALENDAR_MATCH_EQUAL;
+  if (CALENDAR_BOOK_FILTER_ALL == id || UNIFIED_CALENDAR_ID == id) {
+    match_int_flag = CALENDAR_MATCH_GREATER_THAN;
+  }
+
+  error_code = calendar_filter_add_int(calendar_filter, book_id, match_int_flag, id);
+  if ((status = ErrorChecker(error_code)).IsError()) return status;
+
+  error_code = calendar_filter_add_operator(calendar_filter, CALENDAR_FILTER_OPERATOR_AND);
+  if ((status = ErrorChecker(error_code)).IsError()) return status;
+
+  error_code = calendar_filter_add_int(calendar_filter, is_deleted, CALENDAR_MATCH_EQUAL, 0);
+  if ((status = ErrorChecker(error_code)).IsError()) return status;
+
+  error_code = calendar_query_set_filter(*calendar_query, calendar_filter);
+  status = ErrorChecker(error_code);
+
+  return status;
+}
+
+PlatformResult Calendar::Find(const picojson::object& args, picojson::array& array) {
+  if (!CalendarManager::GetInstance().IsConnected()) {
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "DB Connection failed.");
+  }
+  int calendar_id = common::stol(FromJson<std::string>(args, "calendarId"));
+  int error_code = 0;
+  calendar_record_h handle = nullptr;
+  PlatformResult status =
+      CalendarRecord::GetById(calendar_id, _calendar_book._uri, &handle);
+  if (status.IsError()) return status;
+
+  CalendarRecordPtr calendar_ptr =
+      CalendarRecordPtr(handle, CalendarRecord::Deleter);
+
+  int type;
+  status = CalendarRecord::GetInt(calendar_ptr.get(), _calendar_book.store_type,
+                                  &type);
+  if (status.IsError()) return status;
+  const char* view_uri = (type == CALENDAR_BOOK_TYPE_EVENT) ? _calendar_event._uri : _calendar_todo._uri;
+
+  calendar_query_h calendar_query = nullptr;
+
+  error_code = calendar_query_create(view_uri, &calendar_query);
+  if ((status = ErrorChecker(error_code)).IsError()) return status;
+
+  CalendarQueryPtr calendar_query_ptr(calendar_query,
+                                      CalendarRecord::QueryDeleter);
+
+  std::vector<std::vector<CalendarFilterPtr>> intermediate_filters(1);
+  if (!IsNull(args, "filter")) {
+    FilterVisitor visitor;
+    visitor.SetOnAttributeFilter([&](const std::string& name,
+                                     AttributeMatchFlag match_flag,
+                                     const picojson::value& match_value) {
+      int value = 0;
+      calendar_filter_h calendar_filter = nullptr;
+
+      error_code = calendar_filter_create(view_uri, &calendar_filter);
+      if ((status = ErrorChecker(error_code)).IsError()) return status;
+
+      CalendarFilterPtr calendar_filter_ptr(calendar_filter,
+                                            CalendarFilterDeleter);
+
+      unsigned int propertyId = 0;
+      if (name == "startDate" || name == "endDate" || name == "dueDate") {
+        PlatformResult status = CalendarItem::GetPlatformProperty(
+            type, name + "_time", &propertyId);
+        if (status.IsError()) return status;
+      } else {
+        PlatformResult status =
+            CalendarItem::GetPlatformProperty(type, name, &propertyId);
+        if (status.IsError()) return status;
+      }
+
+      if (name == "id" || name == "id.uid") {
+        if (type == CALENDAR_BOOK_TYPE_EVENT && name == "id") {
+          value = common::stol(
+              FromJson<std::string>(JsonCast<JsonObject>(match_value), "uid"));
+        } else {
+          value = common::stol(JsonCast<std::string>(match_value));
+        }
+        if (value < 0) {
+          return PlatformResult(ErrorCode::INVALID_VALUES_ERR,
+                                "Match value cannot be less than 0");
+        }
+        calendar_match_int_flag_e flag;
+        if (AttributeMatchFlag::kExists == match_flag) {
+          flag = CALENDAR_MATCH_GREATER_THAN_OR_EQUAL;
+          value = 0;
+        } else if (AttributeMatchFlag::kStartsWith == match_flag ||
+                   AttributeMatchFlag::kContains == match_flag) {
+          flag = CALENDAR_MATCH_GREATER_THAN_OR_EQUAL;
+        } else if (AttributeMatchFlag::kEndsWith == match_flag) {
+          flag = CALENDAR_MATCH_LESS_THAN_OR_EQUAL;
+        } else {
+          flag = CALENDAR_MATCH_EQUAL;
+        }
+        error_code =
+            calendar_filter_add_int(calendar_filter, propertyId, flag, value);
+        if ((status = ErrorChecker(error_code)).IsError()) return status;
+      } else if (name == "startDate" || name == "endDate" ||
+                 name == "dueDate") {
+        calendar_match_int_flag_e flag;
+        Date dateTofilter =
+            CalendarItem::DateFromJson(JsonCast<picojson::object>(match_value));
+        if (AttributeMatchFlag::kExists == match_flag) {
+          flag = CALENDAR_MATCH_GREATER_THAN_OR_EQUAL;
+          value = 0;
+        } else if (AttributeMatchFlag::kStartsWith == match_flag ||
+                   AttributeMatchFlag::kContains == match_flag) {
+          flag = CALENDAR_MATCH_GREATER_THAN_OR_EQUAL;
+        } else if (AttributeMatchFlag::kEndsWith == match_flag) {
+          flag = CALENDAR_MATCH_LESS_THAN_OR_EQUAL;
+        } else {
+          flag = CALENDAR_MATCH_EQUAL;
+        }
+
+        error_code = calendar_filter_add_caltime(
+            calendar_filter, propertyId, flag,
+            CalendarItem::DateToPlatform(dateTofilter, false));
+        if ((status = ErrorChecker(error_code)).IsError()) return status;
+      } else  if (name == "isAllDay" || name == "isDetached") {
+        calendar_match_int_flag_e flag = CALENDAR_MATCH_EQUAL;
+
+        if (match_value.is<bool>()) {
+          if(match_value.get<bool>()) {
+            value = 1;
+          } else {
+            value = 0;
+          }
+        } else {
+          value = 0;
+        }
+
+        error_code =
+        calendar_filter_add_int(calendar_filter, propertyId, flag, value);
+        if ((status = ErrorChecker(error_code)).IsError()) return status;
+      } else {
+        std::string value = JsonCast<std::string>(match_value);
+        calendar_match_str_flag_e flag = CALENDAR_MATCH_EXISTS;
+        if (AttributeMatchFlag::kExactly == match_flag) {
+          flag = CALENDAR_MATCH_EXACTLY;
+        } else if (AttributeMatchFlag::kFullString == match_flag) {
+          flag = CALENDAR_MATCH_FULLSTRING;
+        } else if (AttributeMatchFlag::kContains == match_flag) {
+          flag = CALENDAR_MATCH_CONTAINS;
+        } else if (AttributeMatchFlag::kStartsWith == match_flag) {
+          flag = CALENDAR_MATCH_STARTSWITH;
+        } else if (AttributeMatchFlag::kEndsWith == match_flag) {
+          flag = CALENDAR_MATCH_ENDSWITH;
+        } else if (AttributeMatchFlag::kExists == match_flag) {
+          flag = CALENDAR_MATCH_EXISTS;
+          value = "";
+        }
+        calendar_filter_add_str(calendar_filter, propertyId, flag,
+                                value.c_str());
+      }
+      intermediate_filters[intermediate_filters.size() - 1].push_back(
+          std::move(calendar_filter_ptr));
+
+      return PlatformResult(ErrorCode::NO_ERROR);
+    });
+    visitor.SetOnCompositeFilterBegin([&](CompositeFilterType type) {
+      intermediate_filters.push_back(std::vector<CalendarFilterPtr>());
+
+      return PlatformResult(ErrorCode::NO_ERROR);
+    });
+
+    visitor.SetOnCompositeFilterEnd([&](CompositeFilterType calType) {
+      if (intermediate_filters.size() == 0) {
+        return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                              "Reached stack size equal to 0!");
+      }
+      calendar_filter_h merged_filter = nullptr;
+
+      error_code = calendar_filter_create(view_uri, &merged_filter);
+      if ((status = ErrorChecker(error_code)).IsError()) return status;
+
+      CalendarFilterPtr merged_filter_ptr(merged_filter, CalendarFilterDeleter);
+      for (std::size_t i = 0; i < intermediate_filters.back().size(); ++i) {
+        error_code = calendar_filter_add_filter(
+            merged_filter, intermediate_filters.back().at(i).get());
+        if ((status = ErrorChecker(error_code)).IsError()) return status;
+        if (CompositeFilterType::kIntersection == calType) {
+          error_code = calendar_filter_add_operator(
+              merged_filter, CALENDAR_FILTER_OPERATOR_AND);
+          if ((status = ErrorChecker(error_code)).IsError()) return status;
+        } else if (CompositeFilterType::kUnion == calType) {
+          error_code = calendar_filter_add_operator(
+              merged_filter, CALENDAR_FILTER_OPERATOR_OR);
+          if ((status = ErrorChecker(error_code)).IsError()) return status;
+        } else {
+          return PlatformResult(ErrorCode::INVALID_VALUES_ERR,
+                                "Invalid union type!");
+        }
+      }
+      intermediate_filters.pop_back();
+      intermediate_filters.back().push_back(std::move(merged_filter_ptr));
+
+      return PlatformResult(ErrorCode::NO_ERROR);
+    });
+
+    visitor.SetOnAttributeRangeFilter([&](const std::string& name,
+                                          const JsonValue& initial_value,
+                                          const JsonValue& end_value) {
+      unsigned int propertyId = 0;
+      if (name == "startDate" || name == "endDate" || name == "dueDate") {
+        PlatformResult status = CalendarItem::GetPlatformProperty(
+            type, name + "_time", &propertyId);
+        if (status.IsError()) return status;
+      } else {
+        PlatformResult status =
+            CalendarItem::GetPlatformProperty(type, name, &propertyId);
+        if (status.IsError()) return status;
+      }
+
+      calendar_filter_h calendar_filter = nullptr;
+      int error_code = 0;
+
+      error_code = calendar_filter_create(view_uri, &calendar_filter);
+      if ((status = ErrorChecker(error_code)).IsError()) return status;
+
+      CalendarFilterPtr calendar_filter_ptr(calendar_filter,
+                                            CalendarFilterDeleter);
+
+      bool initial_value_exists = (!IsNull(initial_value));
+      bool end_value_exists = (!IsNull(end_value));
+      if (name == "id") {
+        int initial_value_date = 0;
+        int end_value_date = 0;
+
+        if (initial_value_exists)
+          initial_value_date =
+              common::stol(JsonCast<std::string>(initial_value));
+        if (end_value_exists)
+          end_value_date = common::stol(JsonCast<std::string>(end_value));
+
+        if (initial_value_exists && end_value_exists) {
+          calendar_filter_h sub_filter = NULL;
+
+          error_code = calendar_filter_create(view_uri, &sub_filter);
+          if ((status = ErrorChecker(error_code)).IsError()) return status;
+
+          CalendarFilterPtr sub_filter_ptr(sub_filter, CalendarFilterDeleter);
+
+          error_code = calendar_filter_add_int(
+              sub_filter, propertyId, CALENDAR_MATCH_GREATER_THAN_OR_EQUAL,
+              initial_value_date);
+          if ((status = ErrorChecker(error_code)).IsError()) return status;
+
+          error_code = calendar_filter_add_operator(
+              sub_filter, CALENDAR_FILTER_OPERATOR_AND);
+          if ((status = ErrorChecker(error_code)).IsError()) return status;
+
+          error_code = calendar_filter_add_int(
+              sub_filter, propertyId, CALENDAR_MATCH_LESS_THAN_OR_EQUAL,
+              end_value_date);
+          if ((status = ErrorChecker(error_code)).IsError()) return status;
+
+          error_code = calendar_filter_add_filter(calendar_filter, sub_filter);
+          if ((status = ErrorChecker(error_code)).IsError()) return status;
+        } else if (initial_value_exists) {
+          error_code = calendar_filter_add_int(
+              calendar_filter, propertyId, CALENDAR_MATCH_GREATER_THAN_OR_EQUAL,
+              initial_value_date);
+          if ((status = ErrorChecker(error_code)).IsError()) return status;
+        } else if (end_value_exists) {
+          error_code = calendar_filter_add_int(
+              calendar_filter, propertyId, CALENDAR_MATCH_LESS_THAN_OR_EQUAL,
+              end_value_date);
+          if ((status = ErrorChecker(error_code)).IsError()) return status;
+        }
+      } else if (name == "startDate" || name == "dueDate" ||
+                 name == "endDate") {
+        Date initial_value_date;
+        Date end_value_date;
+
+        if (initial_value_exists)
+          initial_value_date = CalendarItem::DateFromJson(
+              JsonCast<picojson::object>(initial_value));
+        if (end_value_exists)
+          end_value_date =
+              CalendarItem::DateFromJson(JsonCast<picojson::object>(end_value));
+
+        calendar_filter_h normal_filter = nullptr;
+        calendar_filter_h all_day_filter = nullptr;
+
+        error_code = calendar_filter_create(view_uri, &normal_filter);
+        if ((status = ErrorChecker(error_code)).IsError()) return status;
+        CalendarFilterPtr normal_filter_ptr(normal_filter, CalendarFilterDeleter);
+
+        error_code = calendar_filter_create(view_uri, &all_day_filter);
+        if ((status = ErrorChecker(error_code)).IsError()) return status;
+        CalendarFilterPtr all_day_filter_ptr(all_day_filter, CalendarFilterDeleter);
+
+        if (initial_value_exists) {
+          error_code = calendar_filter_add_caltime(
+              normal_filter, propertyId, CALENDAR_MATCH_GREATER_THAN_OR_EQUAL,
+              CalendarItem::DateToPlatform(initial_value_date, false));
+          if ((status = ErrorChecker(error_code)).IsError()) return status;
+          error_code = calendar_filter_add_caltime(
+              all_day_filter, propertyId, CALENDAR_MATCH_GREATER_THAN_OR_EQUAL,
+              CalendarItem::DateToPlatform(initial_value_date, true));
+          if ((status = ErrorChecker(error_code)).IsError()) return status;
+        }
+
+        if (initial_value_exists && end_value_exists) {
+          error_code = calendar_filter_add_operator(
+              normal_filter, CALENDAR_FILTER_OPERATOR_AND);
+          if ((status = ErrorChecker(error_code)).IsError()) return status;
+          error_code = calendar_filter_add_operator(
+              all_day_filter, CALENDAR_FILTER_OPERATOR_AND);
+          if ((status = ErrorChecker(error_code)).IsError()) return status;
+        }
+
+        if (end_value_exists) {
+          error_code = calendar_filter_add_caltime(
+              normal_filter, propertyId, CALENDAR_MATCH_LESS_THAN_OR_EQUAL,
+              CalendarItem::DateToPlatform(end_value_date, false));
+          if ((status = ErrorChecker(error_code)).IsError()) return status;
+          error_code = calendar_filter_add_caltime(
+              all_day_filter, propertyId, CALENDAR_MATCH_LESS_THAN_OR_EQUAL,
+              CalendarItem::DateToPlatform(end_value_date, true));
+          if ((status = ErrorChecker(error_code)).IsError()) return status;
+        }
+
+        error_code = calendar_filter_add_filter(calendar_filter, normal_filter);
+        if ((status = ErrorChecker(error_code)).IsError()) return status;
+        error_code = calendar_filter_add_operator(calendar_filter, CALENDAR_FILTER_OPERATOR_OR);
+        if ((status = ErrorChecker(error_code)).IsError()) return status;
+        error_code = calendar_filter_add_filter(calendar_filter, all_day_filter);
+        if ((status = ErrorChecker(error_code)).IsError()) return status;
+      } else {
+        std::string initial_value_str;
+        std::string end_value_str;
+
+        if (initial_value_exists) {
+          initial_value_str = JsonCast<std::string>(initial_value);
+        }
+
+        if (end_value_exists) {
+          end_value_str = JsonCast<std::string>(end_value);
+        }
+
+        if (initial_value_exists && end_value_exists) {
+          calendar_filter_h sub_filter = NULL;
+
+          error_code = calendar_filter_create(view_uri, &sub_filter);
+          if ((status = ErrorChecker(error_code)).IsError()) return status;
+
+          CalendarFilterPtr sub_filter_ptr(sub_filter, CalendarFilterDeleter);
+
+          error_code = calendar_filter_add_str(sub_filter, propertyId,
+                                               CALENDAR_MATCH_STARTSWITH,
+                                               initial_value_str.c_str());
+          if ((status = ErrorChecker(error_code)).IsError()) return status;
+          error_code = calendar_filter_add_operator(
+              sub_filter, CALENDAR_FILTER_OPERATOR_AND);
+          if ((status = ErrorChecker(error_code)).IsError()) return status;
+          error_code = calendar_filter_add_str(sub_filter, propertyId,
+                                               CALENDAR_MATCH_ENDSWITH,
+                                               end_value_str.c_str());
+          if ((status = ErrorChecker(error_code)).IsError()) return status;
+          error_code = calendar_filter_add_filter(calendar_filter, sub_filter);
+          if ((status = ErrorChecker(error_code)).IsError()) return status;
+        } else if (initial_value_exists) {
+          error_code = calendar_filter_add_str(calendar_filter, propertyId,
+                                               CALENDAR_MATCH_STARTSWITH,
+                                               initial_value_str.c_str());
+          if ((status = ErrorChecker(error_code)).IsError()) return status;
+        } else if (end_value_exists) {
+          error_code = calendar_filter_add_str(calendar_filter, propertyId,
+                                               CALENDAR_MATCH_ENDSWITH,
+                                               end_value_str.c_str());
+          if ((status = ErrorChecker(error_code)).IsError()) return status;
+        }
+      }
+      intermediate_filters[intermediate_filters.size() - 1].push_back(
+          std::move(calendar_filter_ptr));
+
+      return PlatformResult(ErrorCode::NO_ERROR);
+    });
+    visitor.Visit(FromJson<JsonObject>(args, "filter"));
+    if ((intermediate_filters.size() != 1) ||
+        (intermediate_filters[0].size() != 1)) {
+      LoggerE("Bad filter evaluation!");
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, "Bad filter evaluation!");
+    }
+    error_code = calendar_query_set_filter(calendar_query,
+                                           intermediate_filters[0][0].get());
+    if ((status = ErrorChecker(error_code)).IsError()) return status;
+  } else {
+    //filter is not provided so default filter should be set
+    status = SetDefaultFilter(&calendar_query, type, calendar_id);
+    if (status.IsError()) return status;
+  }
+
+  if (!IsNull(args, "sortMode")) {
+    picojson::object sortModeObject =
+        FromJson<picojson::object>(args, "sortMode");
+    unsigned int propertyId = 0;
+    std::string attributeName =
+        FromJson<std::string>(sortModeObject, "attributeName");
+    std::string order = FromJson<std::string>(sortModeObject, "order");
+    if (attributeName == "startDate" || attributeName == "dueDate" ||
+        attributeName == "endDate") {
+      PlatformResult status = CalendarItem::GetPlatformProperty(
+          type, attributeName + "_time", &propertyId);
+      if (status.IsError()) return status;
+    } else {
+      PlatformResult status =
+          CalendarItem::GetPlatformProperty(type, attributeName, &propertyId);
+      if (status.IsError()) return status;
+    }
+
+    if (order.empty() || order == "ASC") {
+      error_code = calendar_query_set_sort(calendar_query, propertyId, true);
+      if ((status = ErrorChecker(error_code)).IsError()) return status;
+    } else if (order == "DESC") {
+      error_code = calendar_query_set_sort(calendar_query, propertyId, false);
+      if ((status = ErrorChecker(error_code)).IsError()) return status;
+    }
+  }
+
+  calendar_list_h record_list = nullptr;
+  error_code =
+      calendar_db_get_records_with_query(calendar_query, 0, 0, &record_list);
+  if (CALENDAR_ERROR_NONE != error_code) {
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "calendar_db_get_records_with_query failed");
+  }
+  CalendarListPtr record_list_ptr(record_list, CalendarRecord::ListDeleter);
+
+  int record_count = 0;
+  error_code = calendar_list_get_count(record_list, &record_count);
+  if (CALENDAR_ERROR_NONE != error_code) {
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "calendar_list_get_count failed");
+  }
+  error_code = calendar_list_first(record_list);
+  if (CALENDAR_ERROR_NONE != error_code) {
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "calendar_list_first failed");
+  }
+
+  array.reserve(record_count);
+  LoggerD("Found %d records", record_count);
+  for (int i = 0; i < record_count; ++i) {
+    calendar_record_h current_record = NULL;
+    error_code =
+        calendar_list_get_current_record_p(record_list, &current_record);
+    if (CALENDAR_ERROR_NONE != error_code) {
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "calendar_list_get_current_record_p failed");
+    }
+    picojson::value record_obj = picojson::value(picojson::object());
+    PlatformResult status = CalendarItem::ToJson(
+        type, current_record, &record_obj.get<picojson::object>());
+    if (status.IsError()) return status;
+
+    array.push_back(record_obj);
+
+    error_code = calendar_list_next(record_list);
+    if (CALENDAR_ERROR_NONE != error_code) {
+      LoggerE("calendar_list_next failed (%i/%i)", i, record_count);
+      break;
+    }
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult Calendar::RemoveBatch(const picojson::object& args,
+                                     picojson::array& array) {
+  if (!CalendarManager::GetInstance().IsConnected()) {
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "DB Connection failed.");
+  }
+
+  auto& ids = FromJson<picojson::array>(args, "ids");
+  if (ids.empty()) {
+    return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "No items");
+  }
+
+  int type = CalendarRecord::TypeToInt(FromJson<std::string>(args, "type"));
+  std::string view_uri;
+  PlatformResult status = CalendarRecord::TypeToUri(type, &view_uri);
+  if (status.IsError()) return status;
+
+  std::vector<int> ids_to_remove;
+  int id;
+  for (int i = 0, size = ids.size(); i < size; i++) {
+    if (type == CALENDAR_BOOK_TYPE_EVENT) {
+      id = common::stol(
+          FromJson<std::string>(ids.at(i).get<picojson::object>(), "uid"));
+    } else {
+      id = common::stol(ids.at(i).get<std::string>());
+    }
+
+    calendar_record_h handle = nullptr;
+    PlatformResult status =
+        CalendarItem::GetById(id, view_uri.c_str(), &handle);
+    if (status.IsError()) return status;
+
+    CalendarRecordPtr record_ptr =
+        CalendarRecordPtr(handle, CalendarRecord::Deleter);
+
+    if (type == CALENDAR_BOOK_TYPE_EVENT) {
+      std::string rid;
+      status = CalendarRecord::GetString(record_ptr.get(),
+                                         _calendar_event.recurrence_id, &rid);
+      if (status.IsError()) return status;
+
+      if (rid.empty()) {
+        ids_to_remove.push_back(id);
+      } else {
+        // @todo handle recurrence_id
+      }
+    } else {
+      ids_to_remove.push_back(id);
+    }
+  }
+
+  if (ids_to_remove.size() > 0) {
+    int ret = calendar_db_delete_records(view_uri.c_str(), &ids_to_remove[0],
+                                     ids_to_remove.size());
+
+    if (CALENDAR_ERROR_NONE != ret) {
+      LoggerE("calendar_db_delete_records failed.");
+      if (CALENDAR_ERROR_INVALID_PARAMETER == ret) {
+        LoggerE("CALENDAR_ERROR_INVALID_PARAMETER");
+        return PlatformResult(ErrorCode::INVALID_VALUES_ERR,
+                              "Parameter is invalid");
+      } else {
+        LoggerE("CALENDAR_ERROR_DB_FAILED");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "UnknownError");
+      }
+    }
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult Calendar::AddChangeListener(const picojson::object& args,
+                                           picojson::object& out) {
+  if (!CalendarManager::GetInstance().IsConnected()) {
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "DB Connection failed.");
+  }
+
+  const std::string& type = FromJson<std::string>(args, "type");
+  const std::string& listener_id = FromJson<std::string>(args, "listenerId");
+
+  if (listeners_registered_.find(type) == listeners_registered_.end()) {
+    std::string view_uri;
+    PlatformResult status = CalendarRecord::TypeToUri(type, &view_uri);
+    if (status.IsError()) return status;
+
+    int ret = calendar_db_add_changed_cb(view_uri.c_str(), ChangeCallback, this);
+    if (CALENDAR_ERROR_NONE != ret) {
+      LoggerE("Add calendar change callback error for type %s", type.c_str());
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "Add calendar change callback error");
+    }
+
+    ret = calendar_db_get_current_version(&current_db_version_);
+    if (CALENDAR_ERROR_NONE != ret) {
+      current_db_version_ = 0;
+      LoggerE("Can't get calendar db version");
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "Can't get calendar db version");
+    }
+
+    listeners_registered_[type] = listener_id;
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult Calendar::RemoveChangeListener(const picojson::object& args,
+                                              picojson::object& out) {
+  if (!CalendarManager::GetInstance().IsConnected()) {
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "DB Connection failed.");
+  }
+
+  const std::string& type = FromJson<std::string>(args, "type");
+
+  if (listeners_registered_.find(type) != listeners_registered_.end()) {
+    std::string view_uri;
+    PlatformResult status = CalendarRecord::TypeToUri(type, &view_uri);
+    if (status.IsError()) return status;
+
+    int ret = calendar_db_remove_changed_cb(view_uri.c_str(), ChangeCallback, this);
+    if (CALENDAR_ERROR_NONE != ret) {
+      LoggerE("Remove calendar change callback error for type %s",
+              type.c_str());
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "Remove calendar change callback error");
+    }
+    listeners_registered_.erase(type);
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+void Calendar::ChangeCallback(const char* view_uri, void* user_data) {
+  LoggerD("enter");
+
+  Calendar* c = static_cast<Calendar*>(user_data);
+
+  calendar_list_h list = nullptr;
+  int ret, updated_version;
+  ret = calendar_db_get_changes_by_version(view_uri, CALENDAR_BOOK_FILTER_ALL,
+                                           c->current_db_version_, &list,
+                                           &updated_version);
+  if (CALENDAR_ERROR_NONE != ret) {
+    LoggerE("Can't get the changed item list");
+    return;
+  }
+  CalendarListPtr list_ptr = CalendarListPtr(list, CalendarRecord::ListDeleter);
+
+  int count;
+  ret = calendar_list_get_count(list_ptr.get(), &count);
+  if (CALENDAR_ERROR_NONE != ret) {
+    LoggerE("Can't get the changed item count");
+    return;
+  }
+  LoggerD("Item count: %d", count);
+
+  calendar_list_first(list_ptr.get());
+
+  int id, calendar_id, status;
+  calendar_record_h update_info = nullptr;
+
+  int type = CalendarRecord::TypeToInt(view_uri);
+
+  // prepare response object
+  picojson::value response = picojson::value(picojson::object());
+  picojson::object& response_obj = response.get<picojson::object>();
+  if (c->listeners_registered_.find("EVENT") != c->listeners_registered_.end())
+    response_obj.insert(
+        std::make_pair("listenerId", picojson::value(c->listeners_registered_["EVENT"])));
+  else
+    response_obj.insert(
+        std::make_pair("listenerId", picojson::value(c->listeners_registered_["TASK"])));
+
+  picojson::array& added =
+      response_obj.insert(std::make_pair("added", picojson::value(picojson::array())))
+          .first->second.get<picojson::array>();
+  picojson::array& updated =
+      response_obj.insert(std::make_pair("updated", picojson::value(picojson::array())))
+          .first->second.get<picojson::array>();
+  picojson::array& removed =
+      response_obj.insert(std::make_pair("removed", picojson::value(picojson::array())))
+          .first->second.get<picojson::array>();
+
+  while (count-- > 0) {
+    ret = calendar_list_get_current_record_p(list, &update_info);
+    if (CALENDAR_ERROR_NONE != ret) {
+      LoggerE("Can't get current record");
+      return;
+    }
+
+    PlatformResult result =
+        CalendarRecord::GetInt(update_info, _calendar_updated_info.id, &id);
+    if (result.IsError()) return;
+
+    result = CalendarRecord::GetInt(
+        update_info, _calendar_updated_info.modified_status, &status);
+    if (result.IsError()) return;
+
+    if (status == CALENDAR_RECORD_MODIFIED_STATUS_DELETED) {
+      result = CalendarRecord::GetInt(
+          update_info, _calendar_updated_info.calendar_book_id, &calendar_id);
+      if (result.IsError()) return;
+
+      picojson::value removed_row = picojson::value(picojson::object());
+      picojson::object& removed_obj = removed_row.get<picojson::object>();
+      removed_obj.insert(
+          std::make_pair("id", picojson::value(std::to_string(id))));
+      removed_obj.insert(std::make_pair(
+          "calendarId", picojson::value(std::to_string(calendar_id))));
+
+      removed.push_back(removed_row);
+
+      calendar_list_next(list);
+      continue;
+    }
+
+    calendar_record_h handle = nullptr;
+    result = CalendarRecord::GetById(id, view_uri, &handle);
+    if (result.IsError()) return;
+
+    CalendarRecordPtr record_ptr =
+        CalendarRecordPtr(handle, CalendarRecord::Deleter);
+
+    picojson::value record_obj = picojson::value(picojson::object());
+    result = CalendarItem::ToJson(type, record_ptr.get(),
+                                  &record_obj.get<picojson::object>());
+    if (result.IsError()) {
+      LoggerE("error occured: %s", result.message().c_str());
+      return;
+    }
+
+    if (status == CALENDAR_RECORD_MODIFIED_STATUS_INSERTED) {
+      added.push_back(record_obj);
+    } else {
+      updated.push_back(record_obj);
+    }
+
+    calendar_list_next(list);
+  }
+
+  if (added.empty()) {
+    response_obj.erase("added");
+  }
+  if (updated.empty()) {
+    response_obj.erase("updated");
+  }
+  if (removed.empty()) {
+    response_obj.erase("removed");
+  }
+
+  ret = calendar_db_get_current_version(&updated_version);
+  if (CALENDAR_ERROR_NONE != ret) {
+    LoggerE("Can't get new version");
+    return;
+  }
+  c->current_db_version_ = updated_version;
+  LoggerD("-> Calendar::ChangeCallback");
+  Instance::PostMessage(&c->instance_, response.serialize().c_str());
+}
+
+PlatformResult Calendar::ErrorChecker(int errorCode) {
+  if (errorCode != CALENDAR_ERROR_NONE)
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "exception occured");
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+}  // namespace calendar
+}  // namespace webapi
diff --git a/webWidgetTCT_device/src/calendar/calendar.gyp b/webWidgetTCT_device/src/calendar/calendar.gyp
new file mode 100755 (executable)
index 0000000..5b9798e
--- /dev/null
@@ -0,0 +1,39 @@
+{
+  'includes':[
+    '../common/common.gypi',
+  ],
+  'targets': [
+    {
+      'target_name': 'tizen_calendar',
+      'type': 'loadable_module',
+      'dependencies': [
+        '../common/common.gyp:tizen_common',
+      ],
+      'sources': [
+        'calendar_api.js',
+        'calendar_extension.cc',
+        'calendar_extension.h',
+        'calendar_instance.cc',
+        'calendar_instance.h',
+        'calendar.cc',
+        'calendar.h',
+        'calendar_item.cc',
+        'calendar_item.h',
+        'calendar_manager.cc',
+        'calendar_manager.h',
+        'calendar_privilege.h',
+        'calendar_record.cc',
+        'calendar_record.h'
+      ],
+      'conditions': [
+        ['tizen == 1', {
+          'variables': {
+            'packages': [
+              'calendar-service2',
+            ]
+          },
+        }],
+      ],
+    },
+  ],
+}
diff --git a/webWidgetTCT_device/src/calendar/calendar.h b/webWidgetTCT_device/src/calendar/calendar.h
new file mode 100755 (executable)
index 0000000..2d5db2e
--- /dev/null
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2015 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 CALENDAR_CALENDAR_H_
+#define CALENDAR_CALENDAR_H_
+
+#include <memory>
+#include <calendar-service2/calendar_types.h>
+
+#include "common/picojson.h"
+#include "common/platform_result.h"
+
+namespace extension {
+namespace calendar {
+
+typedef picojson::value JsonValue;
+typedef picojson::object JsonObject;
+typedef picojson::array JsonArray;
+typedef std::string JsonString;
+
+typedef std::shared_ptr<JsonValue> JsonValuePtr;
+
+class CalendarInstance;
+
+class Calendar {
+ public:
+  explicit Calendar(CalendarInstance& instance);
+  ~Calendar();
+
+  /**
+   * Signature: @code CalendarItem get(id); @endcode
+   * JSON: @code data: {method: 'Calendar_get', args: {id, calendarId}} @endcode
+   * Invocation: @code native.callSync(request); @endcode
+   * Return:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success', item: {}}
+   * @endcode
+   */
+  common::PlatformResult Get(const JsonObject& args, JsonObject& out);
+
+  /**
+   * Signature: @code void add(item); @endcode
+   * JSON: @code data: {method: 'Calendar_add', args: {item, type}} @endcode
+   * Invocation: @code native.callSync(request); @endcode
+   * Return:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success'}
+   * @endcode
+   */
+  common::PlatformResult Add(const JsonObject& args, JsonObject& out);
+
+  /**
+   * Signature: @code void addBatch(items, successCallback, errorCallback);
+   * @endcode
+   * JSON: @code data: {method: 'Calendar_addBatch', args: {items, type}}
+   * @endcode
+   * Invocation: @code native.call(request); @endcode
+   * Return:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success', result: items}
+   * @endcode
+   */
+  common::PlatformResult AddBatch(const JsonObject& args, JsonArray& array);
+
+  /**
+   * Signature: @code void update(item, updateAllInstances); @endcode
+   * JSON: @code data: {method: 'Calendar_update', args: {item, type,
+   * updateAllInstances}} @endcode
+   * Invocation: @code native.callSync(request); @endcode
+   * Return:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success'}
+   * @endcode
+   */
+  common::PlatformResult Update(const JsonObject& args, JsonObject& out);
+
+  /**
+   * Signature: @code void updateBatch(items, successCallback, errorCallback,
+   * updateAllInstances);
+   * @endcode
+   * JSON: @code data: {method: 'Calendar_updateBatch', args: {
+   * items, type, updateAllInstances}} @endcode
+   * Invocation: @code native.call(request); @endcode
+   * Return:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success'}
+   * @endcode
+   */
+  common::PlatformResult UpdateBatch(const JsonObject& args, JsonArray& array);
+
+  /**
+   * Signature: @code void remove(item); @endcode
+   * JSON: @code data: {method: 'Calendar_remove', args: {type, id}} @endcode
+   * Invocation: @code native.callSync(request); @endcode
+   * Return:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success'}
+   * @endcode
+   */
+  common::PlatformResult Remove(const JsonObject& args, JsonObject& out);
+
+  /**
+   * Signature: @code void removeBatch(items, successCallback, errorCallback);
+   * @endcode
+   * JSON: @code data: {method: 'Calendar_removeBatch', args: {items, type}}
+   * @endcode
+   * Invocation: @code native.call(request); @endcode
+   * Return:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success'}
+   * @endcode
+   */
+  common::PlatformResult RemoveBatch(const JsonObject& args, JsonArray& array);
+
+  /**
+   * Signature: @code void find(successCallback, errorCallback, filter,
+   * sortMode); @endcode
+   * JSON: @code data: {method: 'Calendar_find', args: {calendarId, filter,
+   * sortMode}} @endcode
+   * Invocation: @code native.call(request, result_callback); @endcode
+   * Return:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success'}
+   * @endcode
+   * Result callback:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success', result: {calendarItemsArray}}
+   * @endcode
+   */
+  common::PlatformResult Find(const JsonObject& args, JsonArray& array);
+
+  /**
+   * Signature: @code void addChangeListener(successCallback); @endcode
+   * JSON: @code data: {method: 'Calendar_addChangeListener',
+   * args: {type, listenerId}} @endcode
+   * Invocation: @code native.callSync(request); @endcode
+   * Return:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success'}
+   * @endcode
+   */
+  common::PlatformResult AddChangeListener(const JsonObject& args,
+                                           JsonObject& out);
+
+  /**
+   * Signature: @code void removeChangeListener(); @endcode
+   * JSON: @code data: {method: 'Calendar_removeChangeListener', args: {type}}
+   * @endcode
+   * Invocation: @code native.callSync(request); @endcode
+   * Return:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success'}
+   * @endcode
+   */
+  common::PlatformResult RemoveChangeListener(const JsonObject& args,
+                                              JsonObject& out);
+
+ private:
+  std::map<std::string, std::string> listeners_registered_;
+  int current_db_version_;
+  CalendarInstance& instance_;
+
+  static void ChangeCallback(const char* view_uri, void* user_data);
+  common::PlatformResult ErrorChecker(int errorCode);
+  common::PlatformResult SetDefaultFilter(calendar_query_h* calendar_query, int type, int id);
+};
+
+}  // namespace calendar
+}  // namespace webapi
+
+#endif  // CALENDAR_CALENDAR_H_
diff --git a/webWidgetTCT_device/src/calendar/calendar_api.js b/webWidgetTCT_device/src/calendar/calendar_api.js
new file mode 100755 (executable)
index 0000000..c4c6e85
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+//= require('common.js');
+//= require('calendar_item.js');
+//= require('calendar.js');
+//= require('calendar_manager.js');
+//= require('calendar_attendee.js');
+//= require('calendar_alarm.js');
+//= require('calendar_recurrence_rule.js');
diff --git a/webWidgetTCT_device/src/calendar/calendar_extension.cc b/webWidgetTCT_device/src/calendar/calendar_extension.cc
new file mode 100755 (executable)
index 0000000..bb0cf95
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2015 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 "calendar/calendar_extension.h"
+#include "calendar/calendar_instance.h"
+
+// This will be generated from calendar_api.js
+extern const char kSource_calendar_api[];
+
+common::Extension* CreateExtension() {
+  return new CalendarExtension;
+}
+
+CalendarExtension::CalendarExtension() {
+  SetExtensionName("tizen.calendar");
+  SetJavaScriptAPI(kSource_calendar_api);
+
+  const char* entry_points[] = {
+    "tizen.Calendar",
+    "tizen.CalendarEventId",
+    "tizen.CalendarEvent",
+    "tizen.CalendarTask",
+    "tizen.CalendarAlarm",
+    "tizen.CalendarAttendee",
+    "tizen.CalendarRecurrenceRule",
+    NULL
+  };
+  SetExtraJSEntryPoints(entry_points);
+}
+
+CalendarExtension::~CalendarExtension() {}
+
+common::Instance* CalendarExtension::CreateInstance() {
+  return new extension::calendar::CalendarInstance();
+}
diff --git a/webWidgetTCT_device/src/calendar/calendar_extension.h b/webWidgetTCT_device/src/calendar/calendar_extension.h
new file mode 100755 (executable)
index 0000000..d1caee4
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2015 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 CALENDAR_CALENDAR_EXTENSION_H_
+#define CALENDAR_CALENDAR_EXTENSION_H_
+
+#include "common/extension.h"
+
+class CalendarExtension : public common::Extension {
+ public:
+  CalendarExtension();
+  virtual ~CalendarExtension();
+
+ private:
+  virtual common::Instance* CreateInstance();
+};
+
+#endif // CALENDAR_CALENDAR_EXTENSION_H_
diff --git a/webWidgetTCT_device/src/calendar/calendar_instance.cc b/webWidgetTCT_device/src/calendar/calendar_instance.cc
new file mode 100755 (executable)
index 0000000..ac5f48e
--- /dev/null
@@ -0,0 +1,398 @@
+/*
+ * Copyright (c) 2015 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 "calendar/calendar_instance.h"
+
+#include "common/converter.h"
+
+#include "calendar/calendar_manager.h"
+#include "calendar/calendar.h"
+#include "common/task-queue.h"
+
+#include <memory>
+#include <map>
+#include <calendar-service2/calendar.h>
+#include "calendar_record.h"
+
+namespace extension {
+namespace calendar {
+
+using namespace common;
+using namespace extension::calendar;
+
+CalendarInstance::CalendarInstance()
+    : calendar_(*this) {
+  LoggerD("Enter");
+  using std::placeholders::_1;
+  using std::placeholders::_2;
+
+#define REGISTER_SYNC(c, x) \
+  RegisterSyncHandler(c, std::bind(&CalendarInstance::x, this, _1, _2));
+
+  // Calendar
+  REGISTER_SYNC("Calendar_get", CalendarGet);
+  REGISTER_SYNC("Calendar_add", CalendarAdd);
+  REGISTER_SYNC("Calendar_update", CalendarUpdate);
+  REGISTER_SYNC("Calendar_remove", CalendarRemove);
+  REGISTER_SYNC("Calendar_addChangeListener", CalendarAddChangeListener);
+  REGISTER_SYNC("Calendar_removeChangeListener", CalendarRemoveChangeListener);
+
+  // Calendar Manager
+  REGISTER_SYNC("CalendarManager_addCalendar", CalendarManagerAddCalendar);
+  REGISTER_SYNC("CalendarManager_getCalendar", CalendarManagerGetCalendar);
+  REGISTER_SYNC("CalendarManager_removeCalendar",
+                CalendarManagerRemoveCalendar);
+#undef REGISTER_SYNC
+
+#define REGISTER_ASYNC(c, x) \
+  RegisterSyncHandler(c, std::bind(&CalendarInstance::x, this, _1, _2));
+  REGISTER_ASYNC("Calendar_addBatch", CalendarAddBatch);
+  REGISTER_ASYNC("Calendar_updateBatch", CalendarUpdateBatch);
+  REGISTER_ASYNC("Calendar_removeBatch", CalendarRemoveBatch);
+  REGISTER_ASYNC("Calendar_updateBatch", CalendarUpdateBatch);
+  REGISTER_ASYNC("CalendarManager_getCalendars", CalendarManagerGetCalendars);
+  REGISTER_ASYNC("Calendar_find", CalendarFind);
+#undef REGISTER_ASYNC
+}
+
+CalendarInstance::~CalendarInstance() {
+  LoggerD("Enter");
+}
+
+void CalendarInstance::CalendarGet(const JsonValue& args, JsonObject& out) {
+  LoggerD("Enter");
+
+  JsonValue val{JsonObject{}};
+
+  PlatformResult status = calendar_.Get(common::JsonCast<JsonObject>(args),
+                                        val.get<JsonObject>());
+
+  if (status.IsSuccess())
+    ReportSuccess(val, out);
+  else
+  {
+    LoggerE("Failed");
+    ReportError(status, &out);
+  }
+}
+
+void CalendarInstance::CalendarAdd(const JsonValue& args, JsonObject& out) {
+  LoggerD("Enter");
+  JsonValue val{JsonObject{}};
+
+  PlatformResult status = calendar_.Add(common::JsonCast<JsonObject>(args),
+                                        val.get<JsonObject>());
+
+  if (status.IsSuccess()) {
+    ReportSuccess(val, out);
+  } else{
+    LoggerE("Failed");
+    ReportError(status, &out);
+  }
+}
+
+void CalendarInstance::CalendarAddBatch(const JsonValue& args,
+                                        JsonObject& out) {
+  LoggerD("Enter");
+
+  const double callback_id = args.get("callbackId").get<double>();
+  auto get = [=](const std::shared_ptr<JsonValue>& response) -> void {
+    LoggerD("CalendarAddBatch->get");
+    JsonValue result = JsonValue(JsonArray());
+    PlatformResult status = calendar_.AddBatch(
+        common::JsonCast<JsonObject>(args), result.get<JsonArray>());
+
+    if (status.IsSuccess())
+      ReportSuccess(result, response->get<picojson::object>());
+    else
+    {
+      LoggerE("Failed");
+      ReportError(status, &response->get<picojson::object>());
+    }
+  };
+
+  auto get_response =
+      [callback_id, this](const std::shared_ptr<JsonValue>& response) -> void {
+    LoggerD("CalendarAddBatch->get_response");
+    picojson::object& obj = response->get<picojson::object>();
+    obj.insert(std::make_pair("callbackId", picojson::value(callback_id)));
+    LoggerD("callback is %s", response->serialize().c_str());
+    Instance::PostMessage(this, response->serialize().c_str());
+  };
+
+  auto data = std::shared_ptr<JsonValue>(new JsonValue(JsonObject()));
+
+  TaskQueue::GetInstance().Queue<JsonValue>(
+      get, get_response, data);
+}
+
+void CalendarInstance::CalendarUpdate(const JsonValue& args, JsonObject& out) {
+  LoggerD("Enter");
+  JsonValue val{JsonObject{}};
+
+  PlatformResult status = calendar_.Update(common::JsonCast<JsonObject>(args),
+                                           val.get<JsonObject>());
+
+  if (status.IsSuccess())
+    ReportSuccess(val, out);
+  else
+  {
+    LoggerE("Failed");
+    ReportError(status, &out);
+  }
+}
+
+void CalendarInstance::CalendarUpdateBatch(const JsonValue& args,
+                                           JsonObject& out) {
+  LoggerD("Enter");
+
+  const double callback_id = args.get("callbackId").get<double>();
+  auto get = [=](const std::shared_ptr<JsonValue>& response) -> void {
+    LoggerD("CalendarUpdateBatch->get");
+    JsonValue result = JsonValue(JsonArray());
+    PlatformResult status = calendar_.UpdateBatch(
+        common::JsonCast<JsonObject>(args), result.get<JsonArray>());
+
+    if (status.IsSuccess())
+      ReportSuccess(result, response->get<picojson::object>());
+    else
+    {
+      LoggerE("Failed");
+      ReportError(status, &response->get<picojson::object>());
+    }
+  };
+
+  auto get_response =
+      [callback_id, this](const std::shared_ptr<JsonValue>& response) -> void {
+    LoggerD("CalendarUpdateBatch->get_response");
+    picojson::object& obj = response->get<picojson::object>();
+    obj.insert(std::make_pair("callbackId", picojson::value(callback_id)));
+    LoggerD("callback is %s", response->serialize().c_str());
+    Instance::PostMessage(this, response->serialize().c_str());
+  };
+
+  auto data = std::shared_ptr<JsonValue>(new JsonValue(JsonObject()));
+
+  TaskQueue::GetInstance().Queue<JsonValue>(
+      get, get_response, data);
+}
+
+void CalendarInstance::CalendarRemove(const JsonValue& args, JsonObject& out) {
+  LoggerD("Enter");
+  JsonValue val{JsonObject{}};
+
+  PlatformResult status = calendar_.Remove(common::JsonCast<JsonObject>(args),
+                                           val.get<JsonObject>());
+
+  if (status.IsSuccess())
+    ReportSuccess(out);
+  else
+  {
+    LoggerE("Failed");
+    ReportError(status, &val.get<JsonObject>());
+  }
+}
+
+void CalendarInstance::CalendarRemoveBatch(const JsonValue& args,
+                                           JsonObject& out) {
+  LoggerD("Enter");
+
+  const double callback_id = args.get("callbackId").get<double>();
+  auto get = [=](const std::shared_ptr<JsonValue>& response) -> void {
+    LoggerD("CalendarRemoveBatch->get");
+    JsonValue result = JsonValue(JsonArray());
+    PlatformResult status = calendar_.RemoveBatch(
+        common::JsonCast<JsonObject>(args), result.get<JsonArray>());
+
+    if (status.IsSuccess())
+      ReportSuccess(result, response->get<picojson::object>());
+    else
+    {
+      LoggerE("Failed");
+      ReportError(status, &response->get<picojson::object>());
+    }
+  };
+
+  auto get_response =
+      [callback_id, this](const std::shared_ptr<JsonValue>& response) -> void {
+    LoggerD("CalendarRemoveBatch->get_response");
+    picojson::object& obj = response->get<picojson::object>();
+    obj.insert(std::make_pair("callbackId", picojson::value(callback_id)));
+    LoggerD("callback is %s", response->serialize().c_str());
+    Instance::PostMessage(this, response->serialize().c_str());
+  };
+
+  auto data = std::shared_ptr<JsonValue>(new JsonValue(JsonObject()));
+
+  TaskQueue::GetInstance().Queue<JsonValue>(
+      get, get_response, data);
+}
+
+void CalendarInstance::CalendarFind(const JsonValue& args, JsonObject& out) {
+  LoggerD("Enter");
+
+  const double callback_id = args.get("callbackId").get<double>();
+  auto get = [=](const std::shared_ptr<JsonValue>& response) -> void {
+    LoggerD("CalendarFind->get");
+    JsonValue result = JsonValue(JsonArray());
+    PlatformResult status = calendar_.Find(
+        common::JsonCast<JsonObject>(args), result.get<JsonArray>());
+
+    if (status.IsSuccess())
+      ReportSuccess(result, response->get<picojson::object>());
+    else
+    {
+      LoggerE("Failed");
+      ReportError(status, &response->get<picojson::object>());
+    }
+  };
+
+  auto get_response =
+      [callback_id, this](const std::shared_ptr<JsonValue>& response) -> void {
+    LoggerD("CalendarFind->get_response");
+    picojson::object& obj = response->get<picojson::object>();
+    obj.insert(std::make_pair("callbackId", picojson::value(callback_id)));
+    LoggerD("callback isssssss %s", response->serialize().c_str());
+    Instance::PostMessage(this, response->serialize().c_str());
+  };
+
+  auto data = std::shared_ptr<JsonValue>(new JsonValue(JsonObject()));
+
+  TaskQueue::GetInstance().Queue<JsonValue>(
+      get, get_response, data);
+}
+
+void CalendarInstance::CalendarAddChangeListener(const JsonValue& args,
+                                                 JsonObject& out) {
+  LoggerD("Enter");
+  JsonValue val{JsonObject{}};
+
+  PlatformResult status = calendar_.AddChangeListener(
+      common::JsonCast<JsonObject>(args), val.get<JsonObject>());
+
+  if (status.IsSuccess())
+    ReportSuccess(out);
+  else
+  {
+    LoggerE("Failed");
+    ReportError(status, &val.get<JsonObject>());
+  }
+}
+
+void CalendarInstance::CalendarRemoveChangeListener(const JsonValue& args,
+                                                    JsonObject& out) {
+  LoggerD("Enter");
+  JsonValue val{JsonObject{}};
+
+  PlatformResult status = calendar_.RemoveChangeListener(
+      common::JsonCast<JsonObject>(args), val.get<JsonObject>());
+
+  if (status.IsSuccess())
+    ReportSuccess(out);
+  else
+  {
+    LoggerE("Failed");
+    ReportError(status, &val.get<JsonObject>());
+  }
+}
+
+// CalendarManager
+void CalendarInstance::CalendarManagerAddCalendar(const JsonValue& args,
+                                                  JsonObject& out) {
+  LoggerD("Enter");
+  JsonValue val{JsonObject{}};
+  PlatformResult status = CalendarManager::GetInstance().AddCalendar(
+      common::JsonCast<JsonObject>(args), val.get<JsonObject>());
+
+  if (status.IsSuccess())
+    ReportSuccess(val, out);
+  else
+  {
+    LoggerE("Failed");
+    ReportError(status, &out);
+  }
+}
+
+void CalendarInstance::CalendarManagerGetCalendar(const JsonValue& args,
+                                                  JsonObject& out) {
+  LoggerD("Enter");
+  JsonValue val{JsonObject{}};
+  PlatformResult status = CalendarManager::GetInstance().GetCalendar(common::JsonCast<JsonObject>(args),
+                                             val.get<JsonObject>());
+
+  if (status.IsSuccess())
+    ReportSuccess(val, out);
+  else
+  {
+    LoggerE("Failed");
+    ReportError(status, &out);
+  }
+}
+
+void CalendarInstance::CalendarManagerGetCalendars(const JsonValue& args,
+                                                   JsonObject& out) {
+  LoggerD("Enter");
+
+  const double callback_id = args.get("callbackId").get<double>();
+  auto get = [=](const std::shared_ptr<JsonValue>& response) -> void {
+    LoggerD("CalendarManagerGetCalendars->get");
+    JsonValue result = JsonValue(JsonArray());
+
+    PlatformResult status = CalendarManager::GetInstance().GetCalendars(
+        common::JsonCast<JsonObject>(args), result.get<JsonArray>());
+
+    if (status.IsSuccess())
+      ReportSuccess(result, response->get<picojson::object>());
+    else
+    {
+      LoggerE("Failed");
+      ReportError(status, &response->get<JsonObject>());
+    }
+  };
+
+  auto get_response = [ callback_id, this ](const std::shared_ptr<JsonValue> &
+                                            response)->void {
+    LoggerD("CalendarManagerGetCalendars->get_response");
+    picojson::object& obj = response->get<picojson::object>();
+    obj.insert(std::make_pair("callbackId", picojson::value(callback_id)));
+    LoggerD("callback is %s", response->serialize().c_str());
+    Instance::PostMessage(this, response->serialize().c_str());
+  };
+
+  auto data = std::shared_ptr<JsonValue>(new JsonValue(JsonObject()));
+
+  TaskQueue::GetInstance().Queue<JsonValue>(
+      get, get_response, data);
+}
+
+void CalendarInstance::CalendarManagerRemoveCalendar(const JsonValue& args,
+                                                     JsonObject& out) {
+  LoggerD("Enter");
+  JsonValue val{JsonObject{}};
+  PlatformResult status = CalendarManager::GetInstance().RemoveCalendar(
+      common::JsonCast<JsonObject>(args), val.get<JsonObject>());
+
+  if (status.IsSuccess())
+    ReportSuccess(val, out);
+  else
+  {
+    LoggerE("Failed");
+    ReportError(status, &out);
+  }
+}
+
+}  // namespace calendar
+}  // namespace extension
diff --git a/webWidgetTCT_device/src/calendar/calendar_instance.h b/webWidgetTCT_device/src/calendar/calendar_instance.h
new file mode 100755 (executable)
index 0000000..1537e69
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2015 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 CALENDAR_CALENDAR_INSTANCE_H_
+#define CALENDAR_CALENDAR_INSTANCE_H_
+
+#include "common/extension.h"
+#include "common/picojson.h"
+
+#include "calendar/calendar.h"
+
+namespace extension {
+namespace calendar {
+
+class CalendarInstance : public common::ParsedInstance {
+ public:
+  CalendarInstance();
+  virtual ~CalendarInstance();
+
+ private:
+  void CalendarGet(const picojson::value& args, picojson::object& out);
+  void CalendarAdd(const picojson::value& args, picojson::object& out);
+  void CalendarAddBatch(const picojson::value& args, picojson::object& out);
+  void CalendarUpdate(const picojson::value& args, picojson::object& out);
+  void CalendarUpdateBatch(const picojson::value& args, picojson::object& out);
+  void CalendarRemove(const picojson::value& args, picojson::object& out);
+  void CalendarRemoveBatch(const picojson::value& args, picojson::object& out);
+  void CalendarFind(const picojson::value& args, picojson::object& out);
+  void CalendarAddChangeListener(const picojson::value& args, picojson::object& out);
+  void CalendarRemoveChangeListener(const picojson::value& args, picojson::object& out);
+
+  void CalendarManagerAddCalendar(const picojson::value& args, picojson::object& out);
+  void CalendarManagerGetCalendar(const picojson::value& args, picojson::object& out);
+  void CalendarManagerGetCalendars(const picojson::value& args, picojson::object& out);
+  void CalendarManagerRemoveCalendar(const picojson::value& args, picojson::object& out);
+
+  Calendar calendar_;
+};
+
+} // namespace calendar
+} // namespace extension
+
+#endif // CALENDAR_CALENDAR_INSTANCE_H_
diff --git a/webWidgetTCT_device/src/calendar/calendar_item.cc b/webWidgetTCT_device/src/calendar/calendar_item.cc
new file mode 100755 (executable)
index 0000000..d221776
--- /dev/null
@@ -0,0 +1,1934 @@
+/*
+ * Copyright (c) 2015 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 "calendar_item.h"
+
+#include <calendar_view.h>
+#include <unicode/ucal.h>
+
+#include "common/logger.h"
+#include "common/converter.h"
+#include <sstream>
+using namespace common;
+namespace extension {
+namespace calendar {
+
+namespace {
+const std::string kTimeDurationUnitMilliseconds = "MSECS";
+const std::string kTimeDurationUnitSeconds = "SECS";
+const std::string kTimeDurationUnitMinutes = "MINS";
+const std::string kTimeDurationUnitHours = "HOURS";
+const std::string kTimeDurationUnitDays = "DAYS";
+
+const std::string kDefaultEnumKey = "_DEFAULT";
+const std::string kItemVisibility = "ItemVisibility";
+const std::string kEventAvailability = "EventAvailability";
+const std::string kEventPriority = "EventPriority";
+const std::string kTaskPriority = "TaskPriority";
+const std::string kEventStatus = "EventStatus";
+const std::string kTaskStatus = "TaskStatus";
+const std::string kAttendeeRole = "AttendeeRole";
+const std::string kAttendeeStatus = "AttendeeStatus";
+const std::string kAttendeeType = "AttendeeType";
+const std::string kAlarmMethod = "AlarmMethod";
+const std::string kRecurrenceRuleFrequency = "RecurrenceRuleFrequency";
+}
+
+const PlatformPropertyMap CalendarItem::platform_property_map_ = {
+    {"id", {
+        {CALENDAR_BOOK_TYPE_EVENT, _calendar_event.id},
+        {CALENDAR_BOOK_TYPE_TODO, _calendar_todo.id}}},
+    {"id.uid", {
+        {CALENDAR_BOOK_TYPE_EVENT, _calendar_event.id},
+        {CALENDAR_BOOK_TYPE_TODO, _calendar_todo.uid}}},
+    {"calendar_id", {
+        {CALENDAR_BOOK_TYPE_EVENT, _calendar_event.calendar_book_id},
+        {CALENDAR_BOOK_TYPE_TODO, _calendar_todo.calendar_book_id}}},
+    {"description", {
+        {CALENDAR_BOOK_TYPE_EVENT, _calendar_event.description},
+        {CALENDAR_BOOK_TYPE_TODO, _calendar_todo.description}}},
+    {"summary", {
+        {CALENDAR_BOOK_TYPE_EVENT, _calendar_event.summary},
+        {CALENDAR_BOOK_TYPE_TODO, _calendar_todo.summary}}},
+    {"isAllDay", {
+        {CALENDAR_BOOK_TYPE_EVENT, _calendar_event.is_allday},
+        {CALENDAR_BOOK_TYPE_TODO, _calendar_todo.is_allday}}},
+    {"startDate_time", {
+        {CALENDAR_BOOK_TYPE_EVENT, _calendar_event.start_time},
+        {CALENDAR_BOOK_TYPE_TODO, _calendar_todo.start_time}}},
+    {"startDate_tzid", {
+        {CALENDAR_BOOK_TYPE_EVENT, _calendar_event.start_tzid},
+        {CALENDAR_BOOK_TYPE_TODO, _calendar_todo.start_tzid}}},
+    {"location", {
+        {CALENDAR_BOOK_TYPE_EVENT, _calendar_event.location},
+        {CALENDAR_BOOK_TYPE_TODO, _calendar_todo.location}}},
+    {"latitude", {
+        {CALENDAR_BOOK_TYPE_EVENT, _calendar_event.latitude},
+        {CALENDAR_BOOK_TYPE_TODO, _calendar_todo.latitude}}},
+    {"longitude", {
+        {CALENDAR_BOOK_TYPE_EVENT, _calendar_event.longitude},
+        {CALENDAR_BOOK_TYPE_TODO, _calendar_todo.longitude}}},
+    {"organizer", {
+        {CALENDAR_BOOK_TYPE_EVENT, _calendar_event.organizer_name},
+        {CALENDAR_BOOK_TYPE_TODO, _calendar_todo.organizer_name}}},
+    {"visibility", {
+        {CALENDAR_BOOK_TYPE_EVENT, _calendar_event.sensitivity},
+        {CALENDAR_BOOK_TYPE_TODO, _calendar_todo.sensitivity}}},
+    {"status", {
+        {CALENDAR_BOOK_TYPE_EVENT, _calendar_event.event_status},
+        {CALENDAR_BOOK_TYPE_TODO, _calendar_todo.todo_status}}},
+    {"priority", {
+        {CALENDAR_BOOK_TYPE_EVENT, _calendar_event.priority},
+        {CALENDAR_BOOK_TYPE_TODO, _calendar_todo.priority}}},
+    {"categories", {
+        {CALENDAR_BOOK_TYPE_EVENT, _calendar_event.categories},
+        {CALENDAR_BOOK_TYPE_TODO, _calendar_todo.categories}}},
+    {"lastModificationDate", {
+        {CALENDAR_BOOK_TYPE_EVENT, _calendar_event.last_modified_time},
+        {CALENDAR_BOOK_TYPE_TODO, _calendar_todo.last_modified_time}}},
+
+    // event only
+    {"endDate_time", {{CALENDAR_BOOK_TYPE_EVENT, _calendar_event.end_time}}},
+    {"endDate_tzid", {{CALENDAR_BOOK_TYPE_EVENT, _calendar_event.end_tzid}}},
+    {"recurrence_id", {{CALENDAR_BOOK_TYPE_EVENT, _calendar_event.recurrence_id}}},
+    {"availability", {{CALENDAR_BOOK_TYPE_EVENT, _calendar_event.busy_status}}},
+
+    // task only
+    {"dueDate_time", {{CALENDAR_BOOK_TYPE_TODO, _calendar_todo.due_time}}},
+    {"dueDate_tzid", {{CALENDAR_BOOK_TYPE_TODO, _calendar_todo.due_tzid}}},
+    {"completedDate", {{CALENDAR_BOOK_TYPE_TODO, _calendar_todo.completed_time}}},
+    {"progress", {{CALENDAR_BOOK_TYPE_TODO, _calendar_todo.progress}}}};
+
+const PlatformEnumMap CalendarItem::platform_enum_map_ = {
+    {kItemVisibility, {
+        {kDefaultEnumKey, CALENDAR_SENSITIVITY_PUBLIC},
+        {"PUBLIC", CALENDAR_SENSITIVITY_PUBLIC},
+        {"PRIVATE", CALENDAR_SENSITIVITY_PRIVATE},
+        {"CONFIDENTIAL", CALENDAR_SENSITIVITY_CONFIDENTIAL}}},
+    {kEventAvailability, {
+        {kDefaultEnumKey, CALENDAR_EVENT_BUSY_STATUS_BUSY},
+        {"FREE", CALENDAR_EVENT_BUSY_STATUS_FREE},
+        {"BUSY", CALENDAR_EVENT_BUSY_STATUS_BUSY},
+        {"BUSY-UNAVAILABLE", CALENDAR_EVENT_BUSY_STATUS_UNAVAILABLE},
+        {"BUSY-TENTATIVE", CALENDAR_EVENT_BUSY_STATUS_TENTATIVE}}},
+    {kEventAvailability, {
+        {kDefaultEnumKey, CALENDAR_EVENT_BUSY_STATUS_BUSY},
+        {"FREE", CALENDAR_EVENT_BUSY_STATUS_FREE},
+        {"BUSY", CALENDAR_EVENT_BUSY_STATUS_BUSY},
+        {"BUSY-UNAVAILABLE", CALENDAR_EVENT_BUSY_STATUS_UNAVAILABLE},
+        {"BUSY-TENTATIVE", CALENDAR_EVENT_BUSY_STATUS_TENTATIVE}}},
+    {kEventPriority, {
+        {kDefaultEnumKey, CALENDAR_EVENT_PRIORITY_NONE},
+        {"NONE", CALENDAR_EVENT_PRIORITY_NONE},
+        {"LOW", CALENDAR_EVENT_PRIORITY_LOW},
+        {"MEDIUM", CALENDAR_EVENT_PRIORITY_NORMAL},
+        {"HIGH", CALENDAR_EVENT_PRIORITY_HIGH}}},
+    {kTaskPriority, {
+        {kDefaultEnumKey, CALENDAR_TODO_PRIORITY_NONE},
+        {"NONE", CALENDAR_TODO_PRIORITY_NONE},
+        {"LOW", CALENDAR_TODO_PRIORITY_LOW},
+        {"MEDIUM", CALENDAR_TODO_PRIORITY_NORMAL},
+        {"HIGH", CALENDAR_TODO_PRIORITY_HIGH}}},
+    {kEventStatus, {
+        {kDefaultEnumKey, CALENDAR_EVENT_STATUS_NONE},
+        {"NONE", CALENDAR_EVENT_STATUS_NONE},
+        {"TENTATIVE", CALENDAR_EVENT_STATUS_TENTATIVE},
+        {"CONFIRMED", CALENDAR_EVENT_STATUS_CONFIRMED},
+        {"CANCELLED", CALENDAR_EVENT_STATUS_CANCELLED}}},
+    {kTaskStatus, {
+        {kDefaultEnumKey, CALENDAR_TODO_STATUS_NONE},
+        {"NONE", CALENDAR_TODO_STATUS_NONE},
+        {"NEEDS_ACTION", CALENDAR_TODO_STATUS_NEEDS_ACTION},
+        {"COMPLETED", CALENDAR_TODO_STATUS_COMPLETED},
+        {"IN_PROCESS", CALENDAR_TODO_STATUS_IN_PROCESS},
+        {"CANCELLED", CALENDAR_TODO_STATUS_CANCELED}}},
+    {kAttendeeRole, {
+        {kDefaultEnumKey, CALENDAR_ATTENDEE_ROLE_CHAIR},
+        {"REQ_PARTICIPANT", CALENDAR_ATTENDEE_ROLE_REQ_PARTICIPANT},
+        {"OPT_PARTICIPANT", CALENDAR_ATTENDEE_ROLE_OPT_PARTICIPANT},
+        {"NON_PARTICIPANT", CALENDAR_ATTENDEE_ROLE_NON_PARTICIPANT},
+        {"CHAIR", CALENDAR_ATTENDEE_ROLE_CHAIR}}},
+    {kAttendeeStatus, {
+        {kDefaultEnumKey, CALENDAR_ATTENDEE_STATUS_PENDING},
+        {"PENDING", CALENDAR_ATTENDEE_STATUS_PENDING},
+        {"ACCEPTED", CALENDAR_ATTENDEE_STATUS_ACCEPTED},
+        {"DECLINED", CALENDAR_ATTENDEE_STATUS_DECLINED},
+        {"TENTATIVE", CALENDAR_ATTENDEE_STATUS_TENTATIVE},
+        {"DELEGATED", CALENDAR_ATTENDEE_STATUS_DELEGATED},
+        {"COMPLETED", CALENDAR_ATTENDEE_STATUS_COMPLETED},
+        {"IN_PROCESS", CALENDAR_ATTENDEE_STATUS_IN_PROCESS}, }},
+    {kAttendeeType, {
+        {kDefaultEnumKey, CALENDAR_ATTENDEE_CUTYPE_INDIVIDUAL},
+        {"INDIVIDUAL", CALENDAR_ATTENDEE_CUTYPE_INDIVIDUAL},
+        {"GROUP", CALENDAR_ATTENDEE_CUTYPE_GROUP},
+        {"RESOURCE", CALENDAR_ATTENDEE_CUTYPE_RESOURCE},
+        {"ROOM", CALENDAR_ATTENDEE_CUTYPE_ROOM},
+        {"UNKNOWN", CALENDAR_ATTENDEE_CUTYPE_UNKNOWN}}},
+    {kAlarmMethod, {
+        {kDefaultEnumKey, CALENDAR_ALARM_ACTION_AUDIO},
+        {"SOUND", CALENDAR_ALARM_ACTION_AUDIO},
+        {"DISPLAY", CALENDAR_ALARM_ACTION_DISPLAY}}},
+    {kRecurrenceRuleFrequency, {
+        {kDefaultEnumKey, CALENDAR_RECURRENCE_NONE},
+        {"", CALENDAR_RECURRENCE_NONE},
+        {"DAILY", CALENDAR_RECURRENCE_DAILY},
+        {"WEEKLY", CALENDAR_RECURRENCE_WEEKLY},
+        {"MONTHLY", CALENDAR_RECURRENCE_MONTHLY},
+        {"YEARLY", CALENDAR_RECURRENCE_YEARLY}}}};
+PlatformEnumReverseMap CalendarItem::platform_enum_reverse_map_ = {};
+
+PlatformResult CalendarItem::Create(int type, calendar_record_h* handle) {
+  LoggerD("Enter");
+  std::string value_str;
+  PlatformResult status = CalendarRecord::TypeToUri(type, &value_str);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  return CalendarRecord::Create(value_str.c_str(), handle);
+}
+
+PlatformResult CalendarItem::Remove(int type, int id) {
+  LoggerD("Enter");
+  std::string view_uri;
+  PlatformResult status = CalendarRecord::TypeToUri(type, &view_uri);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  calendar_record_h handle = nullptr;
+  status = GetById(id, view_uri.c_str(), &handle);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  CalendarRecordPtr record = CalendarRecordPtr(handle, CalendarRecord::Deleter);
+
+  if (type == CALENDAR_BOOK_TYPE_EVENT) {
+    std::string rid;
+    PlatformResult status =
+        GetString(type, record.get(), "recurrence_id", &rid);
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+
+    if (rid.length() > 0) {
+      // @todo remove all occurrences
+      LoggerE("Error: TODO: remove all occurrences");
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "TODO: remove all occurrences");
+    }
+  }
+
+  if (CALENDAR_ERROR_NONE != calendar_db_delete_record(view_uri.c_str(), id)) {
+    LOGE("Calendar record delete error");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Record deletion error");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CalendarItem::GetPlatformProperty(int type,
+                                                 const std::string& property,
+                                                 unsigned int* value) {
+  LoggerD("Enter");
+  if (platform_property_map_.find(property) == platform_property_map_.end()) {
+    std::string message = std::string("Undefined property ") + property;
+    LoggerE("Error: %s", message.c_str());
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, message);
+  }
+
+  auto prop = platform_property_map_.at(property);
+  if (prop.find(type) == prop.end()) {
+    LoggerE("Property %s not defined for type %d", property.c_str(), type);
+    return PlatformResult(
+        ErrorCode::INVALID_VALUES_ERR,
+        std::string("Property %s not defined for type ", property.c_str()) +
+        std::to_string(type));
+  }
+
+  *value = prop.at(type);
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CalendarItem::StringToPlatformEnum(const std::string& field,
+                                                  const std::string& value,
+                                                  int* platform_enum) {
+  LoggerD("Enter");
+  auto iter = platform_enum_map_.find(field);
+  if (iter == platform_enum_map_.end()) {
+    std::string message = std::string("Undefined platform enum type ") + field;
+    LoggerE("Error: %s", message.c_str());
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, message);
+  }
+
+  auto def = platform_enum_map_.at(field);
+  auto def_iter = def.find(value);
+  if (def_iter != def.end()) {
+    *platform_enum = def_iter->second;
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+
+  // default value - if any
+  def_iter = def.find("_DEFAULT");
+  if (def_iter != def.end()) {
+    *platform_enum = def_iter->second;
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+
+  std::string message =
+      "Platform enum value " + value + " not found for " + field;
+  LoggerE("Error: %s", message.c_str());
+  return PlatformResult(ErrorCode::INVALID_VALUES_ERR, message);
+}
+
+PlatformResult CalendarItem::PlatformEnumToString(const std::string& field,
+                                                  int value,
+                                                  std::string* platform_str) {
+  LoggerD("Enter");
+  // @todo can be replaced by Boost.Bimap
+  if (platform_enum_reverse_map_.empty()) {
+    for (auto& def : platform_enum_map_) {
+      platform_enum_reverse_map_[def.first] = {};
+
+      for (auto& key : def.second) {
+        if (key.first != kDefaultEnumKey) {
+          platform_enum_reverse_map_[def.first][key.second] = key.first;
+        }
+      }
+    }
+  }
+
+  auto iter = platform_enum_reverse_map_.find(field);
+  if (iter == platform_enum_reverse_map_.end()) {
+    std::string message = std::string("Undefined platform enum type ") + field;
+    LoggerE("Error: %s", message.c_str());
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, message);
+  }
+
+  auto def = platform_enum_reverse_map_.at(field);
+  auto def_iter = def.find(value);
+  if (def_iter != def.end()) {
+    *platform_str = def_iter->second;
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+
+  std::string message = "Platform enum value " + std::to_string(value) +
+      " not found for " + field;
+  LoggerE("Error: %s", message.c_str());
+  return PlatformResult(ErrorCode::INVALID_VALUES_ERR, message);
+}
+
+PlatformResult CalendarItem::SetString(int type, calendar_record_h rec,
+                                       const std::string& property,
+                                       const picojson::object& in,
+                                       bool optional) {
+  LoggerD("set: %s", property.c_str());
+
+  if (optional && IsNull(in, property.c_str())) {
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+
+  const std::string& value =
+      common::FromJson<std::string>(in, property.c_str());
+
+  return SetString(type, rec, property, value);
+}
+
+PlatformResult CalendarItem::SetString(int type, calendar_record_h rec,
+                                       const std::string& property,
+                                       const std::string& value) {
+  LoggerD("set: %s", property.c_str());
+
+  unsigned int prop;
+  PlatformResult status = GetPlatformProperty(type, property, &prop);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  if (prop != -1u) {
+    PlatformResult status = CalendarRecord::SetString(rec, prop, value);
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CalendarItem::GetString(int type, calendar_record_h rec,
+                                       const std::string& property,
+                                       std::string* value) {
+  LoggerD("get: %s", property.c_str());
+
+  unsigned int prop;
+  PlatformResult status = GetPlatformProperty(type, property, &prop);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  return CalendarRecord::GetString(rec, prop, value);
+}
+
+PlatformResult CalendarItem::SetInt(int type, calendar_record_h rec,
+                                    const std::string& property,
+                                    const picojson::object& in, bool optional) {
+  LoggerD("set: %s", property.c_str());
+
+  if (optional && IsNull(in, property.c_str())) {
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+
+  int value = common::FromJson<double>(in, property.c_str());
+
+  return SetInt(type, rec, property, value);
+}
+
+PlatformResult CalendarItem::SetInt(int type, calendar_record_h rec,
+                                    const std::string& property, int value) {
+  LoggerD("set: %s", property.c_str());
+
+  unsigned int prop;
+  PlatformResult status = GetPlatformProperty(type, property, &prop);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  return CalendarRecord::SetInt(rec, prop, value);
+}
+
+PlatformResult CalendarItem::GetInt(int type, calendar_record_h rec,
+                                    const std::string& property, int* value) {
+  LoggerD("get: %s", property.c_str());
+
+  unsigned int prop;
+  PlatformResult status = GetPlatformProperty(type, property, &prop);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  return CalendarRecord::GetInt(rec, prop, value);
+}
+
+PlatformResult CalendarItem::SetEnum(int type, calendar_record_h rec,
+                                     const std::string& property,
+                                     const picojson::object& in,
+                                     const std::string& enum_name) {
+  LoggerD("Enter");
+  std::string value = common::FromJson<std::string>(in, property.c_str());
+
+  int value_int;
+  PlatformResult status = StringToPlatformEnum(enum_name, value, &value_int);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  status = SetInt(type, rec, property, value_int);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CalendarItem::SetEnum(calendar_record_h rec,
+                                     unsigned int property,
+                                     const std::string& enum_name,
+                                     const std::string& value) {
+  LoggerD("Enter");
+  int value_int;
+  PlatformResult status = StringToPlatformEnum(enum_name, value, &value_int);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  status = CalendarRecord::SetInt(rec, property, value_int);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CalendarItem::GetEnum(int type, calendar_record_h rec,
+                                     const std::string& property,
+                                     const std::string& enum_name,
+                                     std::string* enum_str) {
+  int value;
+  PlatformResult status = GetInt(type, rec, property, &value);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  return PlatformEnumToString(enum_name, value, enum_str);
+}
+
+PlatformResult CalendarItem::GetEnum(calendar_record_h rec,
+                                     unsigned int property,
+                                     const std::string& enum_name,
+                                     std::string* enum_str) {
+  LoggerD("Enter");
+  int value;
+  PlatformResult status = CalendarRecord::GetInt(rec, property, &value);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  return PlatformEnumToString(enum_name, value, enum_str);
+}
+
+PlatformResult CalendarItem::SetDouble(int type, calendar_record_h rec,
+                                       const std::string& property, double value) {
+  LoggerD("set: %s", property.c_str());
+
+  unsigned int prop;
+  PlatformResult status = GetPlatformProperty(type, property, &prop);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  int ret = calendar_record_set_double(rec, prop, value);
+
+  if (CALENDAR_ERROR_NONE != ret) {
+    LoggerW("Can't set double value to record: %d", ret);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Set double to record failed.");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CalendarItem::GetDouble(int type, calendar_record_h rec,
+                                       const std::string& property,
+                                       double* value) {
+  LoggerD("get: %s", property.c_str());
+
+  unsigned int prop;
+  PlatformResult status = GetPlatformProperty(type, property, &prop);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  int ret = calendar_record_get_double(rec, prop, value);
+  if (CALENDAR_ERROR_NONE != ret) {
+    LoggerW("Can't get double value form record: %d", ret);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Get int from record failed.");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CalendarItem::SetCaltime(int type, calendar_record_h rec,
+                                        const std::string& property,
+                                        calendar_time_s value,
+                                        bool throw_on_error) {
+  LoggerD("Enter");
+  unsigned int prop;
+  PlatformResult status = GetPlatformProperty(type, property, &prop);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  return SetCaltime(rec, prop, value, throw_on_error);
+}
+
+PlatformResult CalendarItem::SetCaltime(calendar_record_h rec,
+                                        unsigned int property,
+                                        calendar_time_s value,
+                                        bool throw_on_error) {
+  LoggerD("Enter");
+  int ret = calendar_record_set_caltime(rec, property, value);
+
+  if (CALENDAR_ERROR_NONE != ret) {
+    LoggerW("Can't set caltime value to record: %d", ret);
+
+    if (throw_on_error) {
+      std::string message = "Set caltime to record failed.";
+      LoggerE("Error: %s", message.c_str());
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, message);
+    }
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CalendarItem::GetCaltime(int type, calendar_record_h rec,
+                                        const std::string& property,
+                                        calendar_time_s* cal_time,
+                                        bool throw_on_error) {
+  LoggerD("get: %s", property.c_str());
+
+  unsigned int prop;
+  PlatformResult status = GetPlatformProperty(type, property, &prop);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  return GetCaltime(rec, prop, cal_time, throw_on_error);
+}
+
+PlatformResult CalendarItem::GetCaltime(calendar_record_h rec,
+                                        unsigned int property,
+                                        calendar_time_s* cal_time,
+                                        bool throw_on_error) {
+  LoggerD("Enter");
+  if (property != -1u) {
+    int ret = calendar_record_get_caltime(rec, property, cal_time);
+    if (CALENDAR_ERROR_NONE != ret) {
+      LoggerW("Can't get calendar_time value form record: %d", ret);
+      if (throw_on_error) {
+        std::string message = "Can't get calendar_time value form record";
+        LoggerE("Error: %s", message.c_str());
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, message);
+      }
+    }
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CalendarItem::SetLli(calendar_record_h rec,
+                                    unsigned int property, long long int value,
+                                    bool throw_on_error) {
+  LoggerD("Enter");
+  int ret = calendar_record_set_lli(rec, property, value);
+
+  if (CALENDAR_ERROR_NONE != ret) {
+    LoggerW("Can't set long long int value to record: %d", ret);
+
+    if (throw_on_error) {
+      std::string message = "Set long long int to record failed.";
+      LoggerE("Error: %s", message.c_str());
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, message);
+    }
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CalendarItem::GetLli(int type, calendar_record_h rec,
+                                    const std::string& property,
+                                    long long int* lli) {
+  LoggerD("get: %s", property.c_str());
+
+  unsigned int prop;
+  PlatformResult status = GetPlatformProperty(type, property, &prop);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  return GetLli(rec, prop, lli);
+}
+
+PlatformResult CalendarItem::GetLli(calendar_record_h rec,
+                                    unsigned int property, long long int* value,
+                                    bool throw_on_error) {
+  LoggerD("Enter");
+  int ret = calendar_record_get_lli(rec, property, value);
+  if (CALENDAR_ERROR_NONE != ret) {
+    LoggerW("Can't get lli value form record: %d", ret);
+    if (throw_on_error) {
+      std::string message = "Get lli from record failed.";
+      LoggerE("Error: %s", message.c_str());
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, message);
+    }
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+Date CalendarItem::DateFromJson(const picojson::object& in) {
+  LoggerD("json date %s", picojson::value(in).serialize().c_str());
+
+  Date date = {(long long int)common::FromJson<double>(in, "UTCTimestamp"),
+               (int)common::FromJson<double>(in, "year"),
+               (int)common::FromJson<double>(in, "month"),
+               (int)common::FromJson<double>(in, "day"),
+               common::FromJson<std::string>(in, "timezone")};
+
+  return date;
+}
+
+Date CalendarItem::DateFromJson(const picojson::object& in, const char* obj_name) {
+  LoggerD("Enter");
+  return DateFromJson(common::FromJson<picojson::object>(in, obj_name));
+}
+
+picojson::value CalendarItem::DateToJson(Date* date) {
+  LoggerD("timestamp: %lld", date->utc_timestamp_);
+
+  picojson::value date_val = picojson::value(picojson::object());
+  picojson::object& date_obj = date_val.get<picojson::object>();
+
+  date_obj["UTCTimestamp"] =
+      picojson::value(static_cast<double>(date->utc_timestamp_));
+  date_obj["year"] = picojson::value(static_cast<double>(date->year_));
+  date_obj["month"] = picojson::value(static_cast<double>(date->month_));
+  date_obj["day"] = picojson::value(static_cast<double>(date->day_));
+  date_obj["timezone"] = picojson::value(date->time_zone_);
+
+  return date_val;
+}
+
+PlatformResult CalendarItem::CategoriesFromJson(int type, calendar_record_h rec,
+                                                const picojson::array& value) {
+  LoggerD("Enter");
+  std::string categories = "";
+  for (auto iter = value.begin(); iter != value.end(); ++iter) {
+    if (iter == value.begin()) {
+      categories.append(iter->get<std::string>().c_str());
+    } else {
+      categories.append("," + iter->get<std::string>());
+    }
+  }
+
+  PlatformResult status = SetString(type, rec, "categories", categories);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CalendarItem::CategoriesToJson(int type, calendar_record_h rec,
+                                              picojson::array* value) {
+  LoggerD("Enter");
+  std::string categories;
+  PlatformResult status = GetString(type, rec, "categories", &categories);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  *value = StringToArray(categories);
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CalendarItem::AttendeesFromJson(int type, calendar_record_h rec,
+                                               const picojson::array& value) {
+  LoggerD("Enter");
+  // Remove the preset child attendees before adding new ones.
+  unsigned int property;
+  if (type == CALENDAR_BOOK_TYPE_EVENT) {
+    property = _calendar_event.calendar_attendee;
+  } else {
+    property = _calendar_todo.calendar_attendee;
+  }
+  RemoveChildRecords(rec, property);
+
+  calendar_record_h attendee;
+  for (auto& item : value) {
+    const picojson::object& obj = JsonCast<picojson::object>(item);
+
+    int ret = calendar_record_create(_calendar_attendee._uri, &attendee);
+    if (CALENDAR_ERROR_NONE != ret) {
+      LoggerE("Fail to create attendee record, error code: %d", ret);
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, "Fail to create attendee record");
+    }
+
+    PlatformResult status =
+        CalendarRecord::SetString(attendee, _calendar_attendee.email,
+                                  common::FromJson<std::string>(obj, "uri"));
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+
+    if (!IsNull(obj, "name")) {
+      status =
+          CalendarRecord::SetString(attendee, _calendar_attendee.name,
+                                    common::FromJson<std::string>(obj, "name"));
+      if (status.IsError()) {
+        LoggerE("Error: %s", status.message().c_str());
+        return status;
+      }
+    }
+
+    status = SetEnum(attendee, _calendar_attendee.role, kAttendeeRole,
+                     common::FromJson<std::string>(obj, "role"));
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+
+    status = SetEnum(attendee, _calendar_attendee.status, kAttendeeStatus,
+                     common::FromJson<std::string>(obj, "status"));
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+
+    status = CalendarRecord::SetInt(attendee, _calendar_attendee.rsvp,
+                                    common::FromJson<bool>(obj, "RSVP"));
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+
+    status = SetEnum(attendee, _calendar_attendee.cutype, kAttendeeType,
+                     common::FromJson<std::string>(obj, "type"));
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+
+    if (!IsNull(obj, "group")) {
+      status = CalendarRecord::SetString(attendee, _calendar_attendee.group,
+                                         common::FromJson<std::string>(obj, "group"));
+      if (status.IsError()) {
+        LoggerE("Error: %s", status.message().c_str());
+        return status;
+      }
+    }
+    if (!IsNull(obj, "delegatorURI")) {
+      status = CalendarRecord::SetString(
+          attendee, _calendar_attendee.delegator_uri,
+          common::FromJson<std::string>(obj, "delegatorURI"));
+      if (status.IsError()) {
+        LoggerE("Error: %s", status.message().c_str());
+        return status;
+      }
+    }
+    if (!IsNull(obj, "delegateURI")) {
+      status = CalendarRecord::SetString(
+          attendee, _calendar_attendee.delegatee_uri,
+          common::FromJson<std::string>(obj, "delegateURI"));
+      if (status.IsError()) {
+        LoggerE("Error: %s", status.message().c_str());
+        return status;
+      }
+    }
+
+    if (!IsNull(obj, "contactRef")) {
+      status = CalendarRecord::SetString(
+          attendee, _calendar_attendee.uid,
+          common::FromJson<std::string>(obj, "contactRef", "contactId"));
+      if (status.IsError()) {
+        LoggerE("Error: %s", status.message().c_str());
+        return status;
+      }
+
+      const std::string& address_book =
+          common::FromJson<std::string>(obj, "contactRef", "addressBookId");
+
+      status = CalendarRecord::SetInt(attendee, _calendar_attendee.person_id,
+                                      common::stol(address_book));
+      if (status.IsError()) {
+        LoggerE("Error: %s", status.message().c_str());
+        return status;
+      }
+    } else {
+      LoggerD("ContactRef not set");
+    }
+
+    status = AddChildRecord(rec, property, attendee);
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CalendarItem::AttendeesToJson(int type, calendar_record_h rec,
+                                             picojson::array* out) {
+  LoggerD("Enter");
+  unsigned int property;
+  if (type == CALENDAR_BOOK_TYPE_EVENT) {
+    property = _calendar_event.calendar_attendee;
+  } else {
+    property = _calendar_todo.calendar_attendee;
+  }
+
+  unsigned int count = 0;
+  PlatformResult status = GetChildRecordCount(rec, property, true, &count);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+  if (!count) {
+    LoggerD("No attendees to set.");
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+
+  calendar_list_h list;
+  if (CALENDAR_ERROR_NONE !=
+      calendar_record_clone_child_record_list(rec, property, &list)) {
+    LoggerE("Can't get attendee list");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Can't get attendee list");
+  }
+  CalendarListPtr(list, CalendarRecord::ListDeleter);
+
+  calendar_record_h attendee;
+  for (unsigned int i = 0; i < count; ++i) {
+    LoggerD("Processing the attendee %d", i);
+
+    if (GetChildRecordAt(rec, property, &attendee, i).IsError()) {
+      LoggerW("Can't get attendee record");
+      continue;
+    }
+
+    picojson::value attendee_val = picojson::value(picojson::object());
+    picojson::object& attendee_obj = attendee_val.get<picojson::object>();
+
+    std::string value_str;
+    PlatformResult status = CalendarRecord::GetString(
+        attendee, _calendar_attendee.email, &value_str);
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+    attendee_obj["uri"] = picojson::value(value_str);
+
+    status = CalendarRecord::GetString(attendee, _calendar_attendee.name,
+                                       &value_str);
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+    attendee_obj["name"] = picojson::value(value_str);
+
+    std::string enum_str;
+    status =
+        GetEnum(attendee, _calendar_attendee.role, kAttendeeRole, &enum_str);
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+    attendee_obj["role"] = picojson::value(enum_str);
+
+    status = GetEnum(attendee, _calendar_attendee.status, kAttendeeStatus,
+                     &enum_str);
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+    attendee_obj["status"] = picojson::value(enum_str);
+
+    int value_int;
+    status =
+        CalendarRecord::GetInt(attendee, _calendar_attendee.rsvp, &value_int);
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+    attendee_obj["RSVP"] = picojson::value(static_cast<bool>(value_int));
+
+    status =
+        GetEnum(attendee, _calendar_attendee.cutype, kAttendeeType, &enum_str);
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+    attendee_obj["type"] = picojson::value(enum_str);
+
+    status = CalendarRecord::GetString(attendee, _calendar_attendee.group,
+                                       &value_str);
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+    attendee_obj["group"] = picojson::value(value_str);
+
+    status = CalendarRecord::GetString(
+        attendee, _calendar_attendee.delegator_uri, &value_str);
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+    attendee_obj["delegatorURI"] = picojson::value(value_str);
+
+    status = CalendarRecord::GetString(
+        attendee, _calendar_attendee.delegatee_uri, &value_str);
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+    attendee_obj["delegateURI"] = picojson::value(value_str);
+
+    // contactRef
+    std::string contact_id;
+    status = CalendarRecord::GetString(attendee, _calendar_attendee.uid,
+                                       &contact_id);
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+
+    int book_id;
+    status = CalendarRecord::GetInt(attendee, _calendar_attendee.person_id,
+                                    &book_id);
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+
+    attendee_obj["contactRef"] = picojson::value(
+        picojson::object{{"contactId", picojson::value(contact_id)},
+      {"addressBookId", picojson::value(std::to_string(book_id))}});
+
+    out->push_back(attendee_val);
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CalendarItem::AlarmsFromJson(int type, calendar_record_h rec,
+                                            const picojson::array& alarms) {
+  LoggerD("Enter");
+  unsigned int property;
+  if (type == CALENDAR_BOOK_TYPE_EVENT) {
+    property = _calendar_event.calendar_alarm;
+  } else {
+    property = _calendar_todo.calendar_alarm;
+  }
+  RemoveChildRecords(rec, property);
+
+  calendar_record_h alarm;
+  for (auto& item : alarms) {
+    LoggerD("alarm: %s", item.serialize().c_str());
+    const picojson::object& obj = JsonCast<picojson::object>(item);
+
+    int ret = calendar_record_create(_calendar_alarm._uri, &alarm);
+    if (CALENDAR_ERROR_NONE != ret) {
+      LoggerE("Fail to create attendee record, error code: %d", ret);
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "Fail to create attendee record");
+    }
+
+    int tick_unit = CALENDAR_ALARM_TIME_UNIT_SPECIFIC;
+    if (!common::IsNull(obj, "absoluteDate")) {
+      Date absolute = DateFromJson(obj, "absoluteDate");
+      calendar_time_s absolute_date = DateToPlatform(absolute, false);
+      PlatformResult status =
+          SetCaltime(alarm, _calendar_alarm.alarm_time, absolute_date);
+      if (status.IsError()) {
+        LoggerE("Error: %s", status.message().c_str());
+        return status;
+      }
+
+      status =
+          CalendarRecord::SetInt(alarm, _calendar_alarm.tick_unit, tick_unit);
+      if (status.IsError()) {
+        LoggerE("Error: %s", status.message().c_str());
+        return status;
+      }
+    }
+
+    if (!common::IsNull(obj, "before")) {
+      long long length = common::FromJson<double>(obj, "before", "length");
+      const std::string& unit =
+          common::FromJson<std::string>(obj, "before", "unit");
+      long long tick = 0;
+      if (kTimeDurationUnitMilliseconds == unit) {
+        tick_unit =
+            CALENDAR_ALARM_TIME_UNIT_MINUTE;  // minimum calendar time unit.
+        tick = length / 60000;
+      } else if (kTimeDurationUnitSeconds == unit) {
+        tick_unit = CALENDAR_ALARM_TIME_UNIT_MINUTE;
+        tick = length / 60;
+      } else if (kTimeDurationUnitMinutes == unit) {
+        tick_unit = CALENDAR_ALARM_TIME_UNIT_MINUTE;
+        tick = length;
+      } else if (kTimeDurationUnitHours == unit) {
+        tick_unit = CALENDAR_ALARM_TIME_UNIT_HOUR;
+        tick = length;
+      } else if (kTimeDurationUnitDays == unit) {
+        tick_unit = CALENDAR_ALARM_TIME_UNIT_DAY;
+        tick = length;
+      } else {
+        LoggerW("Wrong alarm time unit: %s", unit.c_str());
+      }
+
+      PlatformResult status =
+          CalendarRecord::SetInt(alarm, _calendar_alarm.tick, tick);
+      if (status.IsError()) {
+        LoggerE("Error: %s", status.message().c_str());
+        return status;
+      }
+
+      status =
+          CalendarRecord::SetInt(alarm, _calendar_alarm.tick_unit, tick_unit);
+      if (status.IsError()) {
+        LoggerE("Error: %s", status.message().c_str());
+        return status;
+      }
+    }
+
+    const auto it_method = obj.find("method");
+    std::string method = "unknown";
+
+    if (obj.end() != it_method && it_method->second.is<std::string>()) {
+      method = it_method->second.get<std::string>();
+    }
+
+    PlatformResult status =
+        SetEnum(alarm, _calendar_alarm.action, kAlarmMethod, method);
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+
+    status = CalendarRecord::SetString(
+        alarm, _calendar_alarm.description,
+        common::FromJson<std::string>(obj, "description"));
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+
+    status = AddChildRecord(rec, property, alarm);
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CalendarItem::AlarmsToJson(int type, calendar_record_h rec,
+                                          picojson::array* out) {
+  LoggerD("Enter");
+  unsigned int property;
+  if (type == CALENDAR_BOOK_TYPE_EVENT) {
+    property = _calendar_event.calendar_alarm;
+  } else {
+    property = _calendar_todo.calendar_alarm;
+  }
+
+  unsigned int count = 0;
+  PlatformResult status = GetChildRecordCount(rec, property, true, &count);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+  if (!count) {
+    LoggerD("No attendees to set.");
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+
+  calendar_list_h list;
+  if (CALENDAR_ERROR_NONE !=
+      calendar_record_clone_child_record_list(rec, property, &list)) {
+    LoggerW("Can't get alarms list");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Can't get alarms list");
+  }
+  CalendarListPtr(list, CalendarRecord::ListDeleter);
+
+  int tick, tick_unit;
+  calendar_record_h alarm;
+  for (unsigned int i = 0; i < count; ++i) {
+    LoggerD("Processing the alarm %d", i);
+
+    if (GetChildRecordAt(rec, property, &alarm, i).IsError()) {
+      LoggerW("Can't get alarm record");
+      continue;
+    }
+
+    picojson::value alarm_val = picojson::value(picojson::object());
+    picojson::object& alarm_obj = alarm_val.get<picojson::object>();
+
+    PlatformResult status =
+        CalendarRecord::GetInt(alarm, _calendar_alarm.tick_unit, &tick_unit);
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+
+    if (tick_unit == CALENDAR_ALARM_TIME_UNIT_SPECIFIC) {
+      calendar_time_s result;
+      status = GetCaltime(alarm, _calendar_alarm.alarm_time, &result);
+      if (status.IsError()) {
+        LoggerE("Error: %s", status.message().c_str());
+        return status;
+      }
+
+      alarm_obj["absoluteDate"] = picojson::value(static_cast<double>(result.time.utime));
+    } else {
+      status = CalendarRecord::GetInt(alarm, _calendar_alarm.tick, &tick);
+      if (status.IsError()) {
+        LoggerE("Error: %s", status.message().c_str());
+        return status;
+      }
+
+      int length = 0;
+      std::string unit = kTimeDurationUnitSeconds;
+      if (CALENDAR_ALARM_TIME_UNIT_MINUTE == tick_unit) {
+        unit = kTimeDurationUnitMinutes;
+        length = tick;
+      } else if (CALENDAR_ALARM_TIME_UNIT_HOUR == tick_unit) {
+        unit = kTimeDurationUnitHours;
+        length = tick;
+      } else if (CALENDAR_ALARM_TIME_UNIT_DAY == tick_unit) {
+        unit = kTimeDurationUnitDays;
+        length = tick;
+      } else if (CALENDAR_ALARM_TIME_UNIT_WEEK == tick_unit) {
+        unit = kTimeDurationUnitDays;
+        length = tick * 7;
+      } else {
+        LoggerW("Wrong tick unit: %d", tick_unit);
+      }
+
+      alarm_obj["before"] = picojson::value(
+          picojson::object{{"length", picojson::value(static_cast<double>(length))},
+                       {"unit", picojson::value(unit)}});
+    }
+
+    std::string enum_str;
+    status = GetEnum(alarm, _calendar_alarm.action, kAlarmMethod, &enum_str);
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+    alarm_obj["method"] = picojson::value(enum_str);
+
+    std::string value_str;
+    status = CalendarRecord::GetString(alarm, _calendar_alarm.description,
+                                       &value_str);
+    alarm_obj["description"] = picojson::value(value_str);
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+
+    out->push_back(alarm_val);
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CalendarItem::RecurrenceRuleFromJson(
+    calendar_record_h rec, const picojson::object& rrule) {
+
+  LoggerD("Enter");
+  const std::string& frequency =
+      common::FromJson<std::string>(rrule, "frequency");
+  PlatformResult status =
+      SetEnum(rec, _calendar_event.freq, kRecurrenceRuleFrequency, frequency);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  const unsigned short interval = common::FromJson<double>(rrule, "interval");
+  status = CalendarRecord::SetInt(rec, _calendar_event.interval, interval);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  const long occurrence_count =
+      common::FromJson<double>(rrule, "occurrenceCount");
+  if (-1 != occurrence_count) {
+    status =
+        CalendarRecord::SetInt(rec, _calendar_event.count, occurrence_count);
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+
+    status = CalendarRecord::SetInt(rec, _calendar_event.range_type,
+                                    CALENDAR_RANGE_COUNT);
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+  }
+
+  if (!common::IsNull(rrule, "untilDate")) {
+    Date until = DateFromJson(rrule, "untilDate");
+    status = SetCaltime(rec, _calendar_event.until_time,
+                        DateToPlatform(until, false));
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+
+    status = CalendarRecord::SetInt(rec, _calendar_event.range_type,
+                                    CALENDAR_RANGE_UNTIL);
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+  }
+
+  const picojson::array& byday_array =
+      common::FromJson<picojson::array>(rrule, "daysOfTheWeek");
+  std::string byday;
+  for (auto iter = byday_array.begin(); iter != byday_array.end(); ++iter) {
+    if (iter == byday_array.begin()) {
+      byday.append(iter->get<std::string>());
+    } else {
+      byday.append("," + iter->get<std::string>());
+    }
+  }
+  status = CalendarRecord::SetString(rec, _calendar_event.byday, byday);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  const picojson::array& bysetpos_array =
+      common::FromJson<picojson::array>(rrule, "setPositions");
+  std::string bysetpos;
+  for (auto iter = bysetpos_array.begin(); iter != bysetpos_array.end();
+      ++iter) {
+    if (iter == bysetpos_array.begin()) {
+      bysetpos.append(std::to_string((int)iter->get<double>()));
+    } else {
+      bysetpos.append("," + iter->get<std::string>());
+    }
+  }
+  status = CalendarRecord::SetString(rec, _calendar_event.bysetpos, bysetpos);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  status = CalendarRecord::SetString(
+      rec, _calendar_event.exdate,
+      ExceptionsFromJson(
+          common::FromJson<picojson::array>(rrule, "exceptions")));
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+std::string CalendarItem::ExceptionsFromJson(const picojson::array &exceptions) {
+
+  LoggerD("Enter");
+  std::string result;
+  Date date;
+  for (auto iter = exceptions.begin(); iter != exceptions.end(); ++iter) {
+    date = DateFromJson(iter->get<picojson::object>());
+    calendar_time_s exception_date = DateToPlatform(date, false);
+    std::stringstream ss;
+    ss << exception_date.time.utime;
+
+    if (iter == exceptions.begin()) {
+      result.append(ss.str());
+    } else {
+      result.append("," + ss.str());
+    }
+  }
+
+  return result;
+}
+
+PlatformResult CalendarItem::RecurrenceRuleToJson(calendar_record_h rec,
+                                                  picojson::object* out_ptr) {
+  LoggerD("Enter");
+  picojson::object& out = *out_ptr;
+
+  std::string enum_str;
+  PlatformResult status =
+      GetEnum(rec, _calendar_event.freq, kRecurrenceRuleFrequency, &enum_str);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+  out["frequency"] = picojson::value(enum_str);
+
+  int interval;
+  status =
+      CalendarRecord::GetInt(rec, _calendar_event.interval, &interval);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+  out["interval"] = picojson::value(static_cast<double>(interval));
+
+  calendar_time_s cal = {CALENDAR_TIME_UTIME, {0}};
+  calendar_record_get_caltime(rec, _calendar_event.until_time, &cal);
+  if (cal.time.utime > 0 && CALENDAR_RECORD_NO_UNTIL != cal.time.utime) {
+    Date until = {cal.time.utime, 0, 0, 0, ""};
+    out["untilDate"] = DateToJson(&until);
+  } else {
+    out["untilDate"] = picojson::value();
+  }
+
+  std::string value_str;
+  status = CalendarRecord::GetString(rec, _calendar_event.byday, &value_str);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+  out["daysOfTheWeek"] = picojson::value(StringToArray(value_str));
+
+  status = CalendarRecord::GetString(rec, _calendar_event.bysetpos, &value_str);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+  out["setPositions"] = picojson::value(StringToArray(value_str));
+
+  status = CalendarRecord::GetString(rec, _calendar_event.exdate, &value_str);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+  const picojson::array& exceptions = StringToArray(value_str);
+  picojson::array dates = picojson::array();
+  for (auto& exception : exceptions) {
+    Date date = {common::stol(exception.get<std::string>()), 0, 0, 0, ""};
+    dates.push_back(DateToJson(&date));
+  }
+  out["exceptions"] = picojson::value(dates);
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+calendar_time_s CalendarItem::DateToPlatform(const Date& date,
+                                             bool is_all_day) {
+  LoggerD("Enter");
+  calendar_time_s cal;
+
+  if (is_all_day) {
+    cal.type = CALENDAR_TIME_LOCALTIME;
+    cal.time.date = {date.year_, date.month_ + 1, date.day_};
+  } else {
+    cal.type = CALENDAR_TIME_UTIME;
+    cal.time.utime = date.utc_timestamp_;
+  }
+
+  return cal;
+}
+
+PlatformResult CalendarItem::DateFromPlatform(int type, calendar_record_h rec,
+                                              const std::string& property,
+                                              Date* date_from_platform) {
+  LoggerD("Enter");
+  calendar_time_s cal;
+  PlatformResult status = GetCaltime(type, rec, property + "_time", &cal);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  std::string tzid;
+  status = GetString(type, rec, property + "_tzid", &tzid);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  date_from_platform->utc_timestamp_ = cal.time.utime;
+  date_from_platform->year_ = cal.time.date.year;
+  date_from_platform->month_ = cal.time.date.month;
+  date_from_platform->day_ = cal.time.date.mday;
+  date_from_platform->time_zone_ = tzid;
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CalendarItem::DateFromPlatform(calendar_record_h rec,
+                                              unsigned int property,
+                                              Date* date_from_platform) {
+  LoggerD("Enter");
+  calendar_time_s cal;
+  PlatformResult status = GetCaltime(rec, property, &cal);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  date_from_platform->utc_timestamp_ = cal.time.utime;
+  date_from_platform->year_ = cal.time.date.year;
+  date_from_platform->month_ = cal.time.date.month;
+  date_from_platform->day_ = cal.time.date.mday;
+  date_from_platform->time_zone_ = "";
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CalendarItem::FromJson(int type, calendar_record_h rec,
+                                      const picojson::object& in) {
+  LoggerD("Enter");
+  if (in.empty()) {
+    LoggerE("Empty CalendarItem object.");
+    return PlatformResult(ErrorCode::INVALID_VALUES_ERR,
+                          "Empty Calendar object.");
+  }
+
+  PlatformResult status = SetString(type, rec, "description", in, true);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  status = SetString(type, rec, "summary", in, true);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  status = SetString(type, rec, "location", in, true);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  status = SetString(type, rec, "organizer", in, true);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  int is_all_day = common::FromJson<bool>(in, "isAllDay");
+  const std::string& start_property = "startDate";
+  const std::string& end_property =
+      (type == CALENDAR_BOOK_TYPE_EVENT) ? "endDate" : "dueDate";
+
+  std::string start_label = start_property;
+  if (common::IsNull(in, start_property.c_str())
+      && !common::IsNull(in, end_property.c_str())) {
+    // start date is not set, but end date is present, use it instead
+    start_label = end_property;
+  }
+
+  if (!common::IsNull(in, start_label.c_str())) {
+    Date start = DateFromJson(in, start_label.c_str());
+
+    status = SetCaltime(type, rec, "startDate_time",
+                        DateToPlatform(start, is_all_day));
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+
+    status = SetString(type, rec, "startDate_tzid", start.time_zone_);
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+  }
+
+  std::string end_label = end_property;
+  if (!common::IsNull(in, start_property.c_str())
+        && common::IsNull(in, end_property.c_str())) {
+    // end date is not set, but start date is present, use it instead
+    end_label = start_property;
+  }
+
+  if (!common::IsNull(in, end_label.c_str())) {
+    Date end = DateFromJson(in, end_label.c_str());
+
+    status = SetCaltime(type, rec, end_property + "_time",
+                        DateToPlatform(end, is_all_day));
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+
+    status = SetString(type, rec, end_property + "_tzid", end.time_zone_);
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+  }
+
+  status = SetEnum(type, rec, "visibility", in, kItemVisibility);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  if (!common::IsNull(in, "geolocation")) {
+    PlatformResult status =
+        SetDouble(type, rec, "latitude",
+                  common::FromJson<double>(in, "geolocation", "latitude"));
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+
+    status =
+        SetDouble(type, rec, "longitude",
+                  common::FromJson<double>(in, "geolocation", "longitude"));
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+  }
+
+  status = CategoriesFromJson(
+      type, rec, common::FromJson<picojson::array>(in, "categories"));
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  status = AttendeesFromJson(
+      type, rec, common::FromJson<picojson::array>(in, "attendees"));
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  status = AlarmsFromJson(type, rec,
+                          common::FromJson<picojson::array>(in, "alarms"));
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  if (type == CALENDAR_BOOK_TYPE_EVENT) {
+    status = SetEnum(type, rec, "priority", in, kEventPriority);
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+
+    status = SetEnum(type, rec, "status", in, kEventStatus);
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+
+    status = SetEnum(type, rec, "availability", in, kEventAvailability);
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+
+    if (!common::IsNull(in, "recurrenceRule")) {
+      status = RecurrenceRuleFromJson(
+          rec, common::FromJson<picojson::object>(in, "recurrenceRule"));
+      if (status.IsError()) {
+        LoggerE("Error: %s", status.message().c_str());
+        return status;
+      }
+    }
+
+  } else {
+    status = SetEnum(type, rec, "priority", in, kTaskPriority);
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+
+    status = SetEnum(type, rec, "status", in, kTaskStatus);
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+
+    if (!common::IsNull(in, "completedDate")) {
+      PlatformResult status =
+          SetLli(rec, _calendar_todo.completed_time,
+                 DateFromJson(in, "completedDate").utc_timestamp_);
+      if (status.IsError()) {
+        LoggerE("Error: %s", status.message().c_str());
+        return status;
+      }
+    }
+
+    PlatformResult status = SetInt(type, rec, "progress", in);
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CalendarItem::ToJson(int type, calendar_record_h rec,
+                                    picojson::object* out_ptr) {
+  LoggerD("Enter");
+  if (NULL == rec) {
+    LoggerE("Calendar record is null");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Calendar record is null");
+  }
+
+  picojson::object& out = *out_ptr;
+
+  int id;
+  PlatformResult status = GetInt(type, rec, "id", &id);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  picojson::value id_val;
+  if (type == CALENDAR_BOOK_TYPE_EVENT) {
+    id_val = picojson::value(picojson::object());
+    picojson::object& id_obj = id_val.get<picojson::object>();
+
+    id_obj["uid"] = picojson::value(std::to_string(id));
+    std::string rid;
+    status = GetString(type, rec, "recurrence_id", &rid);
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+
+    if (rid.length() > 0) {
+      id_obj["rid"] = picojson::value(rid);
+    } else {
+      id_obj["rid"] = picojson::value();
+    }
+  } else {
+    id_val = picojson::value(std::to_string(id));
+  }
+
+  out["id"] = id_val;
+
+  int calendar_id;
+  status = GetInt(type, rec, "calendar_id", &calendar_id);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+  out["calendarId"] = picojson::value(std::to_string(calendar_id));
+
+  std::string value_str;
+  status = GetString(type, rec, "description", &value_str);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+  out["description"] = picojson::value(value_str);
+
+  status = GetString(type, rec, "summary", &value_str);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+  out["summary"] = picojson::value(value_str);
+
+  status = GetString(type, rec, "location", &value_str);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+  out["location"] = picojson::value(value_str);
+
+  status = GetString(type, rec, "organizer", &value_str);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+  out["organizer"] = picojson::value(value_str);
+
+  int value_int;
+  status = GetInt(type, rec, "isAllDay", &value_int);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+  out["isAllDay"] = picojson::value(static_cast<bool>(value_int));
+
+  // startDate
+  Date date_from_platform;
+  status = DateFromPlatform(type, rec, "startDate", &date_from_platform);
+  if (status.IsError())return status;
+  out["startDate"] = DateToJson(&date_from_platform);
+
+  // endDate / dueDate
+  const std::string& endProperty =
+      (type == CALENDAR_BOOK_TYPE_EVENT) ? "endDate" : "dueDate";
+  status = DateFromPlatform(type, rec, endProperty, &date_from_platform);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+  out[endProperty] = DateToJson(&date_from_platform);
+
+  long long int lli;
+  status = GetLli(type, rec, "lastModificationDate", &lli);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+  out["lastModificationDate"] = picojson::value(static_cast<double>(lli));
+
+  double latitude;
+  status = GetDouble(type, rec, "latitude", &latitude);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  double longitude;
+  status = GetDouble(type, rec, "longitude", &longitude);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  out["geolocation"] = picojson::value(
+      picojson::object({{"latitude", picojson::value(latitude)},
+    {"longitude", picojson::value(longitude)}}));
+
+  std::string enum_str;
+  status = GetEnum(type, rec, "visibility", kItemVisibility, &enum_str);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+  out["visibility"] = picojson::value(enum_str);
+
+  picojson::array attendees = picojson::array();
+  status = AttendeesToJson(type, rec, &attendees);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+  out["attendees"] = picojson::value(attendees);
+
+  picojson::array categories = picojson::array();
+  status = CategoriesToJson(type, rec, &categories);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+  out["categories"] = picojson::value(categories);
+
+  picojson::array alarms = picojson::array();
+  status = AlarmsToJson(type, rec, &alarms);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+  out["alarms"] = picojson::value(alarms);
+
+  if (type == CALENDAR_BOOK_TYPE_EVENT) {
+    status = GetEnum(type, rec, "status", kEventStatus, &enum_str);
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+    out["status"] = picojson::value(enum_str);
+
+    status = GetEnum(type, rec, "priority", kEventPriority, &enum_str);
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+    out["priority"] = picojson::value(enum_str);
+
+    status = GetEnum(type, rec, "availability", kEventAvailability, &enum_str);
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+    out["availability"] = picojson::value(enum_str);
+
+    //check if reccurence count is greater than 0
+    int occurrence_count;
+    status = CalendarRecord::GetInt(rec, _calendar_event.count, &occurrence_count);
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+
+    if (occurrence_count) {
+      picojson::object rec_rule = picojson::object();
+      rec_rule["occurrenceCount"] = picojson::value(static_cast<double>(occurrence_count));
+
+      status = RecurrenceRuleToJson(rec, &rec_rule);
+      if (status.IsError()) {
+        LoggerE("Error: %s", status.message().c_str());
+        return status;
+      }
+      out["recurrenceRule"] = picojson::value(rec_rule);
+    }
+  } else {
+    status = GetEnum(type, rec, "status", kTaskStatus, &enum_str);
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+    out["status"] = picojson::value(enum_str);
+
+    status = GetEnum(type, rec, "priority", kTaskPriority, &enum_str);
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+    out["priority"] =  picojson::value(enum_str);
+
+    long long int lli;
+    status = GetLli(rec, _calendar_todo.completed_time, &lli);
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+    out["completedDate"] = picojson::value(static_cast<double>(lli));
+
+    status = GetInt(type, rec, "progress", &value_int);
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+    out["progress"] = picojson::value(static_cast<double>(value_int));
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+picojson::array CalendarItem::StringToArray(const std::string& string) {
+  LoggerD("Enter");
+  picojson::array out = picojson::array();
+
+  size_t cstr_length = string.length() + 1;
+  char* cstr = new char[cstr_length];
+  strncpy(cstr, string.c_str(), cstr_length);
+
+  char* saveptr = NULL;
+  char* pch = strtok_r(cstr, ",", &saveptr);
+
+  while (NULL != pch) {
+    out.push_back(picojson::value(std::string(pch)));
+    pch = strtok_r(NULL, ",", &saveptr);
+  }
+
+  delete[] cstr;
+
+  return out;
+}
+
+}  // namespace calendar
+}  // namespace extension
diff --git a/webWidgetTCT_device/src/calendar/calendar_item.h b/webWidgetTCT_device/src/calendar/calendar_item.h
new file mode 100755 (executable)
index 0000000..9666c11
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2015 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 CALENDAR_CALENDAR_ITEM_H_
+#define CALENDAR_CALENDAR_ITEM_H_
+
+#include <string>
+
+#include "calendar_record.h"
+#include "common/picojson.h"
+
+namespace extension {
+namespace calendar {
+struct Date {
+  long long int utc_timestamp_;
+  int year_;
+  int month_;
+  int day_;
+  std::string time_zone_;
+};
+
+typedef std::map<std::string, std::map<int, unsigned int>> PlatformPropertyMap;
+typedef std::map<std::string, std::map<std::string, int>> PlatformEnumMap;
+typedef std::map<std::string, std::map<int, std::string>>
+    PlatformEnumReverseMap;
+
+class CalendarItem : public CalendarRecord {
+ public:
+  static common::PlatformResult Create(int type, calendar_record_h *handle);
+  static common::PlatformResult Remove(int type, int id);
+
+  static common::PlatformResult GetPlatformProperty(int type,
+                                                    const std::string& property,
+                                                    unsigned int* value);
+  static common::PlatformResult StringToPlatformEnum(const std::string& type,
+                                                     const std::string& value,
+                                                     int* platform_enum);
+  static common::PlatformResult PlatformEnumToString(const std::string& field,
+                                                     int value,
+                                                     std::string* platform_str);
+
+  // string
+  static common::PlatformResult SetString(int type, calendar_record_h rec,
+                                          const std::string& property,
+                                          const picojson::object& in,
+                                          bool optional = false);
+  static common::PlatformResult SetString(int type, calendar_record_h rec,
+                                          const std::string& property,
+                                          const std::string& value);
+  static common::PlatformResult GetString(int type, calendar_record_h rec,
+                                          const std::string& property,
+                                          std::string* value);
+
+  // int
+  static common::PlatformResult SetInt(int type, calendar_record_h rec,
+                                       const std::string& property,
+                                       const picojson::object& in,
+                                       bool optional = false);
+  static common::PlatformResult SetInt(int type, calendar_record_h rec,
+                                       const std::string& property, int value);
+  static common::PlatformResult GetInt(int type, calendar_record_h rec,
+                                       const std::string& property, int* value);
+
+  // enum
+  static common::PlatformResult SetEnum(int type, calendar_record_h rec,
+                                        const std::string& property,
+                                        const picojson::object& in,
+                                        const std::string& enum_name);
+  static common::PlatformResult SetEnum(calendar_record_h rec,
+                                        unsigned int property,
+                                        const std::string& enum_name,
+                                        const std::string& value);
+  static common::PlatformResult GetEnum(int type, calendar_record_h rec,
+                                        const std::string& property,
+                                        const std::string& enum_name,
+                                        std::string* enum_str);
+  static common::PlatformResult GetEnum(calendar_record_h rec,
+                                        unsigned int property,
+                                        const std::string& enum_name,
+                                        std::string* enum_str);
+
+  // double
+  static common::PlatformResult SetDouble(int type, calendar_record_h rec,
+                                          const std::string& property,
+                                          double value);
+  static common::PlatformResult GetDouble(int type, calendar_record_h rec,
+                                          const std::string& property,
+                                          double *value);
+
+  // calendar_time_s
+  static common::PlatformResult SetCaltime(int type, calendar_record_h rec,
+                                           const std::string& property,
+                                           calendar_time_s value,
+                                           bool throw_on_error = true);
+  static common::PlatformResult SetCaltime(calendar_record_h rec,
+                                           unsigned int property,
+                                           calendar_time_s value,
+                                           bool throw_on_error = true);
+  static common::PlatformResult GetCaltime(int type, calendar_record_h rec,
+                                           const std::string& property,
+                                           calendar_time_s * cal_time,
+                                           bool throw_on_error = true);
+  static common::PlatformResult GetCaltime(calendar_record_h rec,
+                                           unsigned int property,
+                                           calendar_time_s * cal_time,
+                                           bool throw_on_error = true);
+
+  // long long int
+  static common::PlatformResult SetLli(calendar_record_h rec,
+                                       unsigned int property,
+                                       long long int value,
+                                       bool throw_on_error = true);
+  static common::PlatformResult GetLli(int type, calendar_record_h rec,
+                                       const std::string& property,
+                                       long long int* lli);
+  static common::PlatformResult GetLli(calendar_record_h rec,
+                                       unsigned int property,
+                                       long long int* value,
+                                       bool throw_on_error = true);
+
+  // conversions
+  static common::PlatformResult FromJson(int type, calendar_record_h record,
+                                         const picojson::object& in);
+  static common::PlatformResult ToJson(int type, calendar_record_h record,
+                                       picojson::object* out_ptr);
+
+  static std::string ExceptionsFromJson(const picojson::array& exceptions);
+  static Date DateFromJson(const  picojson::object& in);
+  static Date DateFromJson(const  picojson::object& in,
+                           const char* obj_name);
+   static calendar_time_s DateToPlatform(const Date& date, bool is_all_day);
+
+ private:
+  // from JSON to platform
+
+  static common::PlatformResult CategoriesFromJson(
+      int type, calendar_record_h rec, const picojson::array& value);
+  static common::PlatformResult AttendeesFromJson(int type,
+                                                  calendar_record_h rec,
+                                                  const picojson::array& value);
+  static common::PlatformResult AlarmsFromJson(int type, calendar_record_h rec,
+                                               const picojson::array& alarms);
+  static common::PlatformResult RecurrenceRuleFromJson(
+      calendar_record_h rec, const picojson::object& rrule);
+
+  // from platform to JSON
+  static picojson::value DateToJson(Date *date);
+  static common::PlatformResult CategoriesToJson(int type,
+                                                 calendar_record_h rec,
+                                                 picojson::array* value);
+  static common::PlatformResult AttendeesToJson(int type, calendar_record_h rec,
+                                                picojson::array* out);
+  static common::PlatformResult AlarmsToJson(int type, calendar_record_h rec,
+                                             picojson::array* out);
+  static common::PlatformResult RecurrenceRuleToJson(calendar_record_h rec,
+                                                     picojson::object* out_ptr);
+
+  static common::PlatformResult DateFromPlatform(int type,
+                                                 calendar_record_h rec,
+                                                 const std::string& property,
+                                                 Date* date_from_platform);
+  static common::PlatformResult DateFromPlatform(calendar_record_h rec,
+                                                 unsigned int property,
+                                                 Date* date_from_platform);
+
+  static picojson::array StringToArray(const std::string& string);
+
+  static const PlatformPropertyMap platform_property_map_;
+  static const PlatformEnumMap platform_enum_map_;
+  // @todo can be replaced by Boost.Bimap
+  static PlatformEnumReverseMap platform_enum_reverse_map_;
+};
+
+}  // namespace calendar
+}  // namespace webapi
+
+#endif  // CALENDAR_CALENDAR_ITEM_H_
diff --git a/webWidgetTCT_device/src/calendar/calendar_manager.cc b/webWidgetTCT_device/src/calendar/calendar_manager.cc
new file mode 100755 (executable)
index 0000000..ba34b8a
--- /dev/null
@@ -0,0 +1,263 @@
+/*
+ * Copyright (c) 2015 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 "calendar_manager.h"
+#include "calendar_record.h"
+#include "calendar_privilege.h"
+
+#include <memory>
+#include <map>
+#include <calendar-service2/calendar.h>
+#include "calendar_record.h"
+
+#include "common/task-queue.h"
+#include "common/converter.h"
+#include "common/logger.h"
+
+namespace extension {
+namespace calendar {
+
+namespace {
+const int kUnifiedCalendardId = 0;
+}
+
+using namespace common;
+
+CalendarManager::CalendarManager() {
+  LoggerD("Enter");
+  if (CALENDAR_ERROR_NONE == calendar_connect()) {
+    LoggerD("Calendar DB connected");
+    is_connected_ = true;
+  } else {
+    LoggerE("Calendar DB connection failed");
+  }
+}
+
+CalendarManager::~CalendarManager() {
+  LoggerD("Enter");
+  if (is_connected_) {
+    if (CALENDAR_ERROR_NONE == calendar_disconnect()) {
+      LoggerD("Calendar DB disconnected");
+    } else {
+      LoggerE("Calendar DB disconnect failed");
+    }
+  }
+}
+
+CalendarManager& CalendarManager::GetInstance() {
+  LoggerD("Enter");
+  static CalendarManager instance;
+  return instance;
+}
+
+bool CalendarManager::IsConnected() { return is_connected_; }
+
+PlatformResult CalendarManager::GetCalendars(const JsonObject& args,
+                                             JsonArray& array) {
+  LoggerD("Enter");
+  if (!is_connected_) {
+    LoggerE("DB Connection failed.");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "DB Connection failed.");
+  }
+
+  const std::string& type = FromJson<std::string>(args, "type");
+
+  LoggerD("calendar type: %s", type.c_str());
+
+  calendar_list_h list = NULL;
+  CalendarListPtr list_ptr = CalendarListPtr(list, CalendarRecord::ListDeleter);
+  int ret = calendar_db_get_all_records(_calendar_book._uri, 0, 0, &list);
+  PlatformResult status =
+      CalendarRecord::CheckReturn(ret, "Failed to get list");
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  int count = 0;
+  ret = calendar_list_get_count(list, &count);
+  status = CalendarRecord::CheckReturn(ret, "Failed to get list size");
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  LoggerD("Calendar list count: %d", count);
+
+  ret = calendar_list_first(list);
+  status = CalendarRecord::CheckReturn(
+      ret, "Failed to move list to the first position");
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  int current_calendar_type = CalendarRecord::TypeToInt(type);
+  calendar_record_h calendar = NULL;
+  int store_type;
+
+  while (count-- > 0) {
+    ret = calendar_list_get_current_record_p(list, &calendar);
+    status = CalendarRecord::CheckReturn(ret, "Failed to get current record");
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+
+    PlatformResult status = CalendarRecord::GetInt(
+        calendar, _calendar_book.store_type, &store_type);
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+
+    if (current_calendar_type != store_type) {
+      LoggerD("Different store type %d, requested: %d. Skipping...",
+              store_type, current_calendar_type);
+      calendar_list_next(list);
+      continue;
+    }
+
+    array.push_back(JsonValue(JsonObject()));
+
+    status = CalendarRecord::CalendarToJson(calendar,
+                                            &array.back().get<JsonObject>());
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+
+    calendar_list_next(list);
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CalendarManager::GetCalendar(const JsonObject& args,
+                                            JsonObject& out) {
+  LoggerD("Enter");
+  if (!is_connected_) {
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "DB Connection failed.");
+  }
+
+  int id = common::stol(FromJson<std::string>(args, "id"));
+
+  calendar_record_h handle = nullptr;
+  PlatformResult status =
+      CalendarRecord::GetById(id, _calendar_book._uri, &handle);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  CalendarRecordPtr record_ptr =
+      CalendarRecordPtr(handle, CalendarRecord::Deleter);
+
+  int type = CalendarRecord::TypeToInt(FromJson<std::string>(args, "type"));
+  int calendar_type;
+  status = CalendarRecord::GetInt(record_ptr.get(), _calendar_book.store_type,
+                                  &calendar_type);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  if (type != calendar_type) {
+    LoggerD("Calendar type doesn't match requested type");
+    return PlatformResult(ErrorCode::NOT_FOUND_ERR, "Calendar not found");
+  }
+
+  status = CalendarRecord::CalendarToJson(record_ptr.get(), &out);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CalendarManager::AddCalendar(const JsonObject& args,
+                                            JsonObject& out) {
+  LoggerD("Enter");
+  if (!is_connected_) {
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "DB Connection failed.");
+  }
+
+  const JsonObject& calendar = FromJson<JsonObject>(args, "calendar");
+
+  calendar_record_h handle = nullptr;
+  PlatformResult status = CalendarRecord::CreateCalendar(&handle);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  CalendarRecordPtr record_ptr =
+      CalendarRecordPtr(handle, CalendarRecord::Deleter);
+
+  status = CalendarRecord::CalendarFromJson(record_ptr.get(), calendar);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  int ret, record_id;
+  ret = calendar_db_insert_record(record_ptr.get(), &record_id);
+  status = CalendarRecord::CheckReturn(
+      ret, "Failed to insert calendar record into db");
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+}
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CalendarManager::RemoveCalendar(const JsonObject& args,
+                                               JsonObject& out) {
+  LoggerD("Enter");
+  if (!is_connected_) {
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "DB Connection failed.");
+  }
+
+  int id = common::stol(FromJson<std::string>(args, "id"));
+
+  if (id == kUnifiedCalendardId) {
+    LoggerE("Unified calendar can not be deleted");
+    return PlatformResult(ErrorCode::INVALID_VALUES_ERR,
+                          "Unified calendar can not be deleted");
+  } else if (id == DEFAULT_EVENT_CALENDAR_BOOK_ID) {
+    LoggerE("Default event calendar can not be deleted");
+    return PlatformResult(ErrorCode::INVALID_VALUES_ERR,
+                          "Default event calendar can not be deleted");
+  } else if (id == DEFAULT_TODO_CALENDAR_BOOK_ID) {
+    LoggerE("Default todo calendar can not be deleted");
+    return PlatformResult(ErrorCode::INVALID_VALUES_ERR,
+                          "Default todo calendar can not be deleted");
+  }
+
+  int ret = calendar_db_delete_record(_calendar_book._uri, id);
+  PlatformResult status =
+      CalendarRecord::CheckReturn(ret, "Failed to delete record from db");
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+}
+}
diff --git a/webWidgetTCT_device/src/calendar/calendar_manager.h b/webWidgetTCT_device/src/calendar/calendar_manager.h
new file mode 100755 (executable)
index 0000000..5e8e250
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2015 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 CALENDAR_CALENDAR_MANAGER_H_
+#define CALENDAR_CALENDAR_MANAGER_H_
+
+#include "common/picojson.h"
+#include "common/platform_result.h"
+
+namespace extension {
+namespace calendar {
+
+typedef picojson::value JsonValue;
+typedef picojson::object JsonObject;
+typedef picojson::array JsonArray;
+typedef std::string JsonString;
+
+class CalendarManager {
+ public:
+  /**
+   * Signature: @code void getCalendars(type, successCallback, errorCallback);
+   * @endcode
+   * JSON: @code data: {method: 'CalendarManager_getCalendars',
+   *                    args: {type: type}} @endcode
+   * Invocation: @code native.call(request, result_callback); @endcode
+   * Return:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success'}
+   * @endcode
+   * Result callback:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success', result: {calendarsArray}}
+   * @endcode
+   */
+  common::PlatformResult GetCalendars(const JsonObject& args, JsonArray& array);
+  common::PlatformResult GetCalendar(const JsonObject& args, JsonObject& out);
+  common::PlatformResult AddCalendar(const JsonObject& args, JsonObject& out);
+  common::PlatformResult RemoveCalendar(const JsonObject& args,
+                                        JsonObject& out);
+
+  static CalendarManager& GetInstance();
+  virtual ~CalendarManager();
+  bool IsConnected();
+
+ private:
+  CalendarManager();
+  bool is_connected_;
+};
+
+}  // namespace calendar
+}  // namespace webapi
+
+#endif /* CALENDAR_CALENDAR_MANAGER_H_ */
diff --git a/webWidgetTCT_device/src/calendar/calendar_plugin.cc b/webWidgetTCT_device/src/calendar/calendar_plugin.cc
new file mode 100755 (executable)
index 0000000..dbe8ec6
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2015 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 "native-plugin.h"
+#include "calendar_manager.h"
+#include "calendar.h"
+
+namespace webapi {
+namespace calendar {
+
+using namespace webapi::common;
+
+class CalendarPlugin : public NativePlugin {
+ public:
+  CalendarPlugin();
+  ~CalendarPlugin();
+  virtual void OnLoad();
+
+ private:
+  CalendarManager* manager_;
+  Calendar* calendar_;
+};
+
+EXPORT_NATIVE_PLUGIN(webapi::calendar::CalendarPlugin);
+
+CalendarPlugin::CalendarPlugin() {
+  manager_ = &CalendarManager::GetInstance();
+  calendar_ = &Calendar::GetInstance();
+}
+
+CalendarPlugin::~CalendarPlugin() { manager_ = nullptr; }
+
+void CalendarPlugin::OnLoad() {
+  using std::placeholders::_1;
+  using std::placeholders::_2;
+
+  dispatcher_.AddFunction(
+      "CalendarManager_getCalendars",
+      std::bind(&CalendarManager::GetCalendars, manager_, _1, _2));
+
+  dispatcher_.AddFunction(
+      "CalendarManager_getCalendar",
+      std::bind(&CalendarManager::GetCalendar, manager_, _1, _2));
+
+  dispatcher_.AddFunction(
+      "CalendarManager_addCalendar",
+      std::bind(&CalendarManager::AddCalendar, manager_, _1, _2));
+
+  dispatcher_.AddFunction(
+      "CalendarManager_removeCalendar",
+      std::bind(&CalendarManager::RemoveCalendar, manager_, _1, _2));
+
+  dispatcher_.AddFunction("Calendar_get",
+                          std::bind(&Calendar::Get, calendar_, _1, _2));
+
+  dispatcher_.AddFunction("Calendar_add",
+                          std::bind(&Calendar::Add, calendar_, _1, _2));
+
+  dispatcher_.AddFunction("Calendar_addBatch",
+                          std::bind(&Calendar::AddBatch, calendar_, _1, _2));
+
+  dispatcher_.AddFunction("Calendar_update",
+                          std::bind(&Calendar::Update, calendar_, _1, _2));
+
+  dispatcher_.AddFunction("Calendar_updateBatch",
+                          std::bind(&Calendar::UpdateBatch, calendar_, _1, _2));
+
+  dispatcher_.AddFunction("Calendar_remove",
+                          std::bind(&Calendar::Remove, calendar_, _1, _2));
+
+  dispatcher_.AddFunction("Calendar_removeBatch",
+                          std::bind(&Calendar::RemoveBatch, calendar_, _1, _2));
+
+  dispatcher_.AddFunction("Calendar_find",
+                          std::bind(&Calendar::Find, calendar_, _1, _2));
+
+  dispatcher_.AddFunction(
+      "Calendar_addChangeListener",
+      std::bind(&Calendar::AddChangeListener, calendar_, _1, _2));
+
+  dispatcher_.AddFunction(
+      "Calendar_removeChangeListener",
+      std::bind(&Calendar::RemoveChangeListener, calendar_, _1, _2));
+}
+
+}  // namespace calendar
+}  // namespace webapi
diff --git a/webWidgetTCT_device/src/calendar/calendar_privilege.h b/webWidgetTCT_device/src/calendar/calendar_privilege.h
new file mode 100755 (executable)
index 0000000..47cfae7
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2015 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 CALENDAR_CALENDAR_PRIVILEGE_H__
+#define CALENDAR_CALENDAR_PRIVILEGE_H__
+
+#include <string>
+
+namespace webapi {
+namespace calendar {
+
+namespace Privilege {
+const std::string kCalendarRead = "http://tizen.org/privilege/calendar.read";
+const std::string kCalendarWrite = "http://tizen.org/privilege/calendar.write";
+}  // namespace Privilege
+
+}  // namespace calendar
+}  // namespace webapi
+
+#endif  // CALENDAR_CALENDAR_PRIVILEGE_H__
diff --git a/webWidgetTCT_device/src/calendar/calendar_record.cc b/webWidgetTCT_device/src/calendar/calendar_record.cc
new file mode 100755 (executable)
index 0000000..81c1795
--- /dev/null
@@ -0,0 +1,428 @@
+/*
+ * Copyright (c) 2015 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 "calendar_record.h"
+
+#include <calendar-service2/calendar.h>
+
+#include "common/logger.h"
+#include "common/converter.h"
+
+namespace extension {
+namespace calendar {
+
+namespace {
+const std::string kCalendarTypeEvent = "EVENT";
+const std::string kCalendarTypeTask = "TASK";
+}
+
+using namespace common;
+
+PlatformResult CalendarRecord::CheckReturn(int ret,
+                                           const std::string& error_name) {
+  LoggerD("Enter");
+  if (CALENDAR_ERROR_NONE != ret) {
+    LoggerE("%s : %d", error_name.c_str(), ret);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, error_name);
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+void CalendarRecord::QueryDeleter(calendar_query_h handle) {
+  LoggerD("Enter");
+  if (handle) {
+    if (CALENDAR_ERROR_NONE != calendar_query_destroy(handle)) {
+      LoggerW("calendar_query_destroy failed");
+    }
+  }
+}
+
+void CalendarRecord::Deleter(calendar_record_h handle) {
+  LoggerD("Enter");
+  if (handle) {
+    if (CALENDAR_ERROR_NONE != calendar_record_destroy(handle, true)) {
+      LoggerW("calendar_record_destroy failed");
+    }
+  }
+}
+
+void CalendarRecord::ListDeleter(calendar_list_h handle) {
+  LoggerD("Enter");
+  if (handle) {
+    if (CALENDAR_ERROR_NONE != calendar_list_destroy(handle, true)) {
+      LoggerW("calendar_list_destroy failed");
+    }
+  }
+}
+
+PlatformResult CalendarRecord::GetString(calendar_record_h rec,
+                                         unsigned int property,
+                                         std::string* str,
+                                         bool throw_on_error) {
+  LoggerD("Enter");
+  char* value = NULL;
+  int ret = calendar_record_get_str(rec, property, &value);
+  if (CALENDAR_ERROR_NONE != ret) {
+    LoggerE("Can't get string value form record: %d", ret);
+    if (throw_on_error) {
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "Get string from record failed.");
+    }
+  }
+
+  *str = "";
+  if (value) {
+    *str = std::string(value);
+    free(value);
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CalendarRecord::SetString(calendar_record_h record,
+                                         unsigned int property,
+                                         const std::string& value,
+                                         bool throw_on_error) {
+  LoggerD("Enter");
+  int ret = calendar_record_set_str(record, property,
+                                    value.empty() ? NULL : value.c_str());
+
+  if (CALENDAR_ERROR_NONE != ret) {
+    LoggerE("Can't set string value to record: %d", ret);
+    if (throw_on_error) {
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "Set string to record failed.");
+    }
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CalendarRecord::GetInt(calendar_record_h rec,
+                                      unsigned int property, int* value,
+                                      bool throw_on_error) {
+  LoggerD("Enter");
+  int ret = calendar_record_get_int(rec, property, value);
+  if (CALENDAR_ERROR_NONE != ret) {
+    LoggerE("Can't get int value form record: %d", ret);
+    if (throw_on_error) {
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "Get int from record failed.");
+    }
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CalendarRecord::SetInt(calendar_record_h record,
+                                      unsigned int property, int value,
+                                      bool throw_on_error) {
+  LoggerD("Enter");
+  int ret = calendar_record_set_int(record, property, value);
+
+  if (CALENDAR_ERROR_NONE != ret) {
+    LoggerE("Can't set int value to record: %d", ret);
+    if (throw_on_error) {
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "Set int to record failed.");
+    }
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+std::string CalendarRecord::TypeToString(int type) {
+  LoggerD("Enter");
+  if (CALENDAR_BOOK_TYPE_EVENT == type) {
+    return kCalendarTypeEvent;
+  }
+
+  if (CALENDAR_BOOK_TYPE_TODO == type) {
+    return kCalendarTypeTask;
+  }
+
+  return "";
+}
+
+std::string CalendarRecord::TypeToString(const char* view_uri) {
+  LoggerD("Enter");
+  if (0 == strcmp(view_uri, _calendar_event._uri)) {
+    return kCalendarTypeEvent;
+  }
+  if (0 == strcmp(view_uri, _calendar_todo._uri)) {
+    return kCalendarTypeTask;
+  }
+
+  return "";
+}
+
+int CalendarRecord::TypeToInt(const std::string& type) {
+  LoggerD("Enter");
+  if (kCalendarTypeEvent == type) {
+    return CALENDAR_BOOK_TYPE_EVENT;
+  }
+  if (kCalendarTypeTask == type) {
+    return CALENDAR_BOOK_TYPE_TODO;
+  }
+
+  return CALENDAR_BOOK_TYPE_NONE;
+}
+
+int CalendarRecord::TypeToInt(const char* view_uri) {
+  LoggerD("Enter");
+  if (0 == strcmp(view_uri, _calendar_event._uri)) {
+    return CALENDAR_BOOK_TYPE_EVENT;
+  }
+  if (0 == strcmp(view_uri, _calendar_todo._uri)) {
+    return CALENDAR_BOOK_TYPE_TODO;
+  }
+
+  return CALENDAR_BOOK_TYPE_NONE;
+}
+
+PlatformResult CalendarRecord::TypeToUri(const std::string& type,
+                                         std::string* uri) {
+  LoggerD("Enter");
+  if (kCalendarTypeEvent == type) {
+    *uri = _calendar_event._uri;
+  } else if (kCalendarTypeTask == type) {
+    *uri = _calendar_todo._uri;
+  } else {
+    LoggerE("Undefined record type: %s", type.c_str());
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Undefined record type");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CalendarRecord::TypeToUri(int type, std::string* uri) {
+  LoggerD("Enter");
+  if (CALENDAR_BOOK_TYPE_EVENT == type) {
+    *uri = _calendar_event._uri;
+  } else if (CALENDAR_BOOK_TYPE_TODO == type) {
+    *uri = _calendar_todo._uri;
+  } else {
+    LoggerE("Undefined record type: %d", type);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Undefined record type");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CalendarRecord::Create(const char* view_uri,
+                                      calendar_record_h* handle) {
+  LoggerD("Enter");
+  int ret = calendar_record_create(view_uri, handle);
+  if (CALENDAR_ERROR_NONE != ret || nullptr == handle) {
+    LoggerE("Fail to create calendar record, error code: %d", ret);
+    return PlatformResult(ErrorCode::NOT_FOUND_ERR,
+                          "Fail to create calendar record");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CalendarRecord::CreateCalendar(calendar_record_h* handle) {
+  LoggerD("Enter");
+  return Create(_calendar_book._uri, handle);
+}
+
+PlatformResult CalendarRecord::GetById(int id, const char* view_uri,
+                                       calendar_record_h* handle) {
+  LoggerD("Enter");
+  int ret = calendar_db_get_record(view_uri, id, handle);
+  if (CALENDAR_ERROR_NONE != ret || nullptr == handle) {
+    LoggerE("Fail to get calendar record %d for view %s, error code: %d", id,
+            view_uri, ret);
+    return PlatformResult(ErrorCode::NOT_FOUND_ERR,
+                          "Fail to get record with given id");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CalendarRecord::Insert(calendar_record_h rec, int* record_id) {
+  LoggerD("Enter");
+  int ret = calendar_db_insert_record(rec, record_id);
+
+  if (CALENDAR_ERROR_NONE != ret) {
+    LoggerE("Cannot insert record, error code: %d", ret);
+    return PlatformResult(ErrorCode::NOT_FOUND_ERR, "Cannot insert record");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CalendarRecord::AddChildRecord(calendar_record_h rec,
+                                              unsigned int property,
+                                              calendar_record_h child) {
+  LoggerD("Enter");
+  int ret = calendar_record_add_child_record(rec, property, child);
+  if (CALENDAR_ERROR_NONE != ret) {
+    if (child) {
+      calendar_record_destroy(child, true);
+    }
+    LoggerE("Cannot add child record, error code: %d", ret);
+    return PlatformResult(ErrorCode::NOT_FOUND_ERR, "Cannot add child record");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+void CalendarRecord::RemoveChildRecords(calendar_record_h rec,
+                                        unsigned int property_id) {
+  LoggerD("Enter");
+  unsigned int count = 0;
+
+  if (CALENDAR_ERROR_NONE !=
+      calendar_record_get_child_record_count(rec, property_id, &count)) {
+    LoggerW("Can't get attendees count");
+  }
+
+  calendar_record_h attendee;
+  for (unsigned int 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(rec, property_id, 0, &attendee)) {
+      LoggerW("Can't get the attendee");
+      continue;
+    }
+
+    if (CALENDAR_ERROR_NONE !=
+        calendar_record_remove_child_record(rec, property_id, attendee)) {
+      LoggerW("Can't remove the attendee");
+      continue;
+    }
+  }
+}
+
+PlatformResult CalendarRecord::GetChildRecordCount(calendar_record_h rec,
+                                                   unsigned int property,
+                                                   bool throw_on_error,
+                                                   unsigned int* value) {
+  LoggerD("Enter");
+  int ret = calendar_record_get_child_record_count(rec, property, value);
+  if (CALENDAR_ERROR_NONE != ret) {
+    LoggerE("Can't get child record count: %d", ret);
+    if (throw_on_error) {
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "Get child record count failed.");
+    }
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CalendarRecord::GetChildRecordAt(calendar_record_h rec,
+                                                unsigned int property,
+                                                calendar_record_h* result,
+                                                int index) {
+  LoggerD("Enter");
+  int ret = calendar_record_get_child_record_at_p(rec, property, index, result);
+  if (CALENDAR_ERROR_NONE != ret) {
+    LoggerE("Can't get child record at: %d", ret);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Get child record at failed.");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CalendarRecord::CalendarToJson(calendar_record_h rec,
+                                              picojson::object* out_ptr) {
+  LoggerD("Enter");
+  picojson::object& out = *out_ptr;
+
+  if (NULL == rec) {
+    LoggerE("Calendar record is null");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Calendar record is null");
+  }
+
+  int id = 0;
+  PlatformResult status = GetInt(rec, _calendar_book.id, &id);
+  int account_id;
+  GetInt(rec, _calendar_book.account_id, &account_id);
+
+  std::string name;
+  status = GetString(rec, _calendar_book.name, &name);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  int value;
+  status = GetInt(rec, _calendar_book.store_type, &value);
+  std::string type = TypeToString(value);
+
+  out.insert(std::make_pair("id", picojson::value(std::to_string(id))));
+  out.insert(
+      std::make_pair("accountId", picojson::value(std::to_string(account_id))));
+  out.insert(std::make_pair("name", picojson::value(name)));
+  out.insert(std::make_pair("type", picojson::value(type)));
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CalendarRecord::CalendarFromJson(calendar_record_h rec,
+                                                const picojson::object& in) {
+  LoggerD("Enter");
+  if (in.empty()) {
+    LoggerE("Empty Calendar object.");
+    return PlatformResult(ErrorCode::INVALID_VALUES_ERR,
+                          "Empty Calendar object.");
+  }
+
+  const std::string& name = FromJson<std::string>(in, "name");
+  int account_id = static_cast<int>(FromJson<double>(in, "accountId"));
+  const std::string& type = FromJson<std::string>(in, "type");
+
+  int store_type = 0;
+  if (kCalendarTypeEvent == type) {
+    store_type = CALENDAR_BOOK_TYPE_EVENT;
+  } else if (kCalendarTypeTask == type) {
+    store_type = CALENDAR_BOOK_TYPE_TODO;
+  }
+
+  int ret = calendar_record_set_str(rec, _calendar_book.name, name.c_str());
+  PlatformResult status = CheckReturn(ret, "Failed to set name");
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  ret = calendar_record_set_int(rec, _calendar_book.account_id, account_id);
+  status = CheckReturn(ret, "Failed to set account_id");
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  ret = calendar_record_set_int(rec, _calendar_book.store_type, store_type);
+  status = CheckReturn(ret, "Failed to set store_type");
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+}  // namespace calendar
+}  // namespace webapi
diff --git a/webWidgetTCT_device/src/calendar/calendar_record.h b/webWidgetTCT_device/src/calendar/calendar_record.h
new file mode 100755 (executable)
index 0000000..8228b67
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2015 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 WEBAPI_PLUGINS_CALENDAR_RECORD_H_
+#define WEBAPI_PLUGINS_CALENDAR_RECORD_H_
+
+#include <type_traits>
+#include <string>
+#include <memory>
+#include <calendar-service2/calendar.h>
+
+#include "common/platform_result.h"
+#include "common/picojson.h"
+
+namespace extension {
+namespace calendar {
+
+typedef std::unique_ptr<std::remove_pointer<calendar_query_h>::type,
+                        void (*)(calendar_query_h)> CalendarQueryPtr;
+typedef std::unique_ptr<std::remove_pointer<calendar_record_h>::type,
+                        void (*)(calendar_record_h)> CalendarRecordPtr;
+typedef std::unique_ptr<std::remove_pointer<calendar_list_h>::type,
+                        void (*)(calendar_list_h)> CalendarListPtr;
+
+class CalendarRecord {
+ public:
+  static void QueryDeleter(calendar_query_h handle);
+  static void Deleter(calendar_record_h handle);
+  static void ListDeleter(calendar_list_h handle);
+
+  static common::PlatformResult GetString(calendar_record_h rec,
+                                          unsigned int property,
+                                          std::string* str,
+                                          bool throw_on_error = true);
+  static common::PlatformResult SetString(calendar_record_h rec,
+                                          unsigned int property,
+                                          const std::string& value,
+                                          bool throw_on_error = true);
+
+  static common::PlatformResult GetInt(calendar_record_h rec,
+                                       unsigned int property,
+                                       int* value,
+                                       bool throw_on_error = true);
+  static common::PlatformResult SetInt(calendar_record_h rec,
+                                       unsigned int property, int value,
+                                       bool throw_on_error = true);
+
+  static std::string TypeToString(int type);
+  static std::string TypeToString(const char* view_uri);
+  static int TypeToInt(const std::string& type);
+  static int TypeToInt(const char* view_uri);
+  static common::PlatformResult TypeToUri(const std::string& type,
+                                          std::string* uri);
+  static common::PlatformResult TypeToUri(int type, std::string* uri);
+
+  static common::PlatformResult Insert(calendar_record_h rec, int* record_id);
+
+  static common::PlatformResult AddChildRecord(calendar_record_h rec,
+                                               unsigned int property,
+                                               calendar_record_h child);
+  static void RemoveChildRecords(calendar_record_h rec,
+                                 unsigned int property_id);
+  static common::PlatformResult GetChildRecordCount(calendar_record_h rec,
+                                                    unsigned int property,
+                                                    bool throw_on_error,
+                                                    unsigned int* value);
+  static common::PlatformResult GetChildRecordAt(calendar_record_h rec,
+                                                 unsigned int property,
+                                                 calendar_record_h* result,
+                                                 int index);
+
+  static common::PlatformResult GetById(int id, const char* view_uri,
+                                        calendar_record_h *handle);
+  static common::PlatformResult Create(const char* view_uri,
+                                       calendar_record_h *calendar);
+  static common::PlatformResult CreateCalendar(calendar_record_h* handle);
+
+  static common::PlatformResult CalendarToJson(calendar_record_h rec,
+                                               picojson::object* out_ptr);
+  static common::PlatformResult CalendarFromJson(calendar_record_h rec,
+                                                 const picojson::object& in);
+
+  static common::PlatformResult CheckReturn(int ret,
+                                            const std::string& error_name);
+};
+
+}  // namespace calendar
+}  // namespace webapi
+
+#endif  // WEBAPI_PLUGINS_CALENDAR_RECORD_H_
diff --git a/webWidgetTCT_device/src/calendar/js/calendar.js b/webWidgetTCT_device/src/calendar/js/calendar.js
new file mode 100755 (executable)
index 0000000..cd4195f
--- /dev/null
@@ -0,0 +1,691 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+var _global = window || global || {};
+var CalendarType = {
+  EVENT: 'EVENT',
+  TASK: 'TASK'
+};
+
+/**
+ * For internal use only.
+ */
+var InternalCalendar = function(data) {
+  Object.defineProperties(this, {
+    accountId: {
+      value: -1,
+      writable: true,
+      enumerable: true
+    },
+    id: {
+      value: null,
+      writable: true,
+      enumerable: true
+    },
+    name: {
+      value: null,
+      writable: true,
+      enumerable: true
+    },
+    type: {
+      value: '',
+      writable: true,
+      enumerable: true
+    },
+    isUnified: {
+      value: false,
+      writable: true,
+      enumerable: true
+    }
+  });
+
+  if (data instanceof _global.Object) {
+    for (var prop in data) {
+      if (this.hasOwnProperty(prop)) {
+        this[prop] = data[prop];
+      }
+    }
+  }
+};
+
+
+// class Calendar
+var Calendar = function(accountId, name, type) {
+  var _data;
+
+  validator_.isConstructorCall(this, Calendar);
+
+  if (arguments[0] instanceof InternalCalendar) {
+    _data = arguments[0];
+  } else {
+    var _accountId = converter_.toLong(accountId);
+    var _name = converter_.toString(name);
+    var _type = converter_.toString(type);
+
+    if (arguments.length < 3) {
+      _data = new InternalCalendar();
+    } else {
+      _data = new InternalCalendar({
+                accountId: _accountId,
+                name: _name,
+                type: _type
+      });
+    }
+  }
+
+  Object.defineProperties(this, {
+    accountId: {
+      value: converter_.toLong(_data.accountId),
+      writable: false,
+      enumerable: true
+    },
+    id: {
+      get: function() {
+        return converter_.toString(_data.id, true);
+      },
+      set: function(v) {
+        if (v instanceof InternalCalendar) {
+          _data.id = v.id;
+        }
+      },
+      enumerable: true
+    },
+    name: {
+      value: _data.name,
+      writable: false,
+      enumerable: true
+    },
+    type: {
+      value: _data.type,
+      writable: false,
+      enumerable: false
+    },
+    isUnified: {
+      value: _data.isUnified,
+      writable: false,
+      enumerable: false
+    }
+  });
+};
+
+Calendar.prototype.get = function(id) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.CALENDAR_READ);
+
+  var args;
+  if (this.type === CalendarType.TASK) {
+    if (!parseInt(id) || parseInt(id) <= 0) {
+      throw new WebAPIException(WebAPIException.NOT_FOUND_ERR);
+    }
+    args = validator_.validateArgs(arguments, [{
+      name: 'id',
+      type: types_.STRING
+    }]);
+  } else {
+    args = validator_.validateArgs(arguments, [{
+      name: 'id',
+      type: types_.PLATFORM_OBJECT,
+      values: tizen.CalendarEventId
+    }]);
+  }
+
+  var result = native_.callSync('Calendar_get', {
+    calendarId: this.id,
+    id: args.id
+  });
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+
+  _edit.allow();
+  var item;
+  var _item = native_.getResultObject(result);
+
+  if (this.type === CalendarType.TASK) {
+    item = new CalendarTask(_itemConverter.toTizenObject(_item, _item.isAllDay));
+  } else {
+    item = new CalendarEvent(_itemConverter.toTizenObject(_item, _item.isAllDay));
+  }
+  _edit.disallow();
+
+  return item;
+};
+
+Calendar.prototype.add = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.CALENDAR_WRITE);
+
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'item',
+      type: types_.PLATFORM_OBJECT,
+      values: [CalendarEvent, CalendarTask]
+    }
+  ]);
+
+  if ((this.type === CalendarType.EVENT && !(args.item instanceof CalendarEvent)) ||
+      (this.type === CalendarType.TASK && !(args.item instanceof CalendarTask))) {
+    throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR,
+        'Invalid item type.');
+  }
+
+  var tmp = _itemConverter.fromTizenObject(args.item);
+  tmp.calendarId = this.id;
+
+  var result = native_.callSync('Calendar_add', {
+    item: tmp,
+    type: this.type
+  });
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+
+  var _id = native_.getResultObject(result);
+
+  _edit.allow();
+  args.item.calendarId = this.id;
+
+  switch (this.type) {
+    case CalendarType.EVENT:
+      args.item.id = new CalendarEventId(_id.uid, _id.rid);
+      break;
+    case CalendarType.TASK:
+      args.item.id = _id.uid;
+      break;
+  }
+  _edit.disallow();
+};
+
+Calendar.prototype.addBatch = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.CALENDAR_WRITE);
+
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'items',
+      type: types_.ARRAY,
+      values: (this.type === CalendarType.EVENT)
+                ? tizen.CalendarEvent : tizen.CalendarTask
+    }, {
+      name: 'successCallback',
+      type: types_.FUNCTION,
+      optional: true,
+      nullable: true
+    }, {
+      name: 'errorCallback',
+      type: types_.FUNCTION,
+      optional: true,
+      nullable: true
+    }
+  ]);
+
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+    } else {
+      _edit.allow();
+      var _ids = native_.getResultObject(result);
+      for (var i = 0; i < args.items.length; i++) {
+        args.items[i].calendarId = this.id;
+        switch (this.type) {
+          case CalendarType.EVENT:
+            args.items[i].id = new CalendarEventId(_ids[i].uid, _ids[i].rid);
+            break;
+          case CalendarType.TASK:
+            args.items[i].id = _ids[i].uid;
+            break;
+        }
+      }
+      _edit.disallow();
+      native_.callIfPossible(args.successCallback, args.items);
+    }
+  }.bind(this);
+
+  var tmp = [];
+  var tmpItem;
+  for (var i = 0; i < args.items.length; i++) {
+    if ((this.type === CalendarType.EVENT && !(args.items[i] instanceof CalendarEvent)) ||
+            (this.type === CalendarType.TASK && !(args.items[i] instanceof CalendarTask))) {
+      throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR,
+        'Invalid item type.');
+    }
+    tmpItem = _itemConverter.fromTizenObject(args.items[i]);
+    tmpItem.calendarId = this.id;
+    tmp.push(tmpItem);
+  }
+
+  native_.call('Calendar_addBatch', {
+    type: this.type,
+    items: tmp
+  }, callback);
+
+};
+
+Calendar.prototype.update = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.CALENDAR_WRITE);
+
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'item',
+      type: types_.PLATFORM_OBJECT,
+      values: [tizen.CalendarEvent, tizen.CalendarTask]
+    },
+    {
+      name: 'updateAllInstances',
+      type: types_.BOOLEAN,
+      optional: true,
+      nullable: true
+    }
+  ]);
+
+  if ((this.type === CalendarType.EVENT && !(args.item instanceof CalendarEvent)) ||
+      (this.type === CalendarType.TASK && !(args.item instanceof CalendarTask))) {
+    throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR,
+      'Invalid item type.');
+  }
+
+  var tmp = _itemConverter.fromTizenObject(args.item);
+  tmp.calendarId = this.id;
+
+  var result = native_.callSync('Calendar_update', {
+    item: tmp,
+    type: this.type,
+    updateAllInstances: (args.has.updateAllInstances)
+            ? converter_.toBoolean(args.updateAllInstances, true)
+            : true
+  });
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+
+  var _item = native_.getResultObject(result);
+  _edit.allow();
+  for (var prop in _item) {
+    if (args.item.hasOwnProperty(prop)) {
+      args.item[prop] = _item[prop];
+    }
+  }
+  _edit.disallow();
+
+};
+
+Calendar.prototype.updateBatch = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.CALENDAR_WRITE);
+
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'items',
+      type: types_.ARRAY,
+      values: (this.type === CalendarType.EVENT)
+                ? tizen.CalendarEvent : tizen.CalendarTask
+    },
+    {
+      name: 'successCallback',
+      type: types_.FUNCTION,
+      optional: true,
+      nullable: true
+    },
+    {
+      name: 'errorCallback',
+      type: types_.FUNCTION,
+      optional: true,
+      nullable: true
+    },
+    {
+      name: 'updateAllInstances',
+      type: types_.BOOLEAN,
+      optional: true,
+      nullable: true
+    }
+  ]);
+
+  var calendarType = this.type;
+
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+      return;
+    }
+
+    native_.callIfPossible(args.successCallback);
+  }.bind(this);
+
+  var tmp = [];
+  var tmpItem;
+  for (var i = 0; i < args.items.length; i++) {
+    if ((calendarType === CalendarType.EVENT && !(args.items[i] instanceof CalendarEvent)) ||
+            (calendarType === CalendarType.TASK && !(args.items[i] instanceof CalendarTask))) {
+      throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR,
+        'Invalid item type.');
+    }
+    tmpItem = _itemConverter.fromTizenObject(args.items[i]);
+    tmp.push(tmpItem);
+  }
+
+  native_.call('Calendar_updateBatch', {
+    type: this.type,
+    items: tmp,
+    updateAllInstances: (args.has.updateAllInstances)
+            ? converter_.toBoolean(args.updateAllInstances, true)
+            : true
+  }, callback);
+
+};
+
+Calendar.prototype.remove = function(id) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.CALENDAR_WRITE);
+
+  var args;
+  if (this.type === CalendarType.TASK) {
+    if (!parseInt(id) || parseInt(id) <= 0) {
+      throw new WebAPIException(WebAPIException.NOT_FOUND_ERR);
+    }
+    args = validator_.validateArgs(arguments, [{
+      name: 'id',
+      type: types_.STRING
+    }]);
+  } else {
+    args = validator_.validateArgs(arguments, [{
+      name: 'id',
+      type: types_.PLATFORM_OBJECT,
+      values: tizen.CalendarEventId
+    }]);
+  }
+
+  var result = native_.callSync('Calendar_remove', {
+    type: this.type,
+    id: args.id
+  });
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+};
+
+Calendar.prototype.removeBatch = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.CALENDAR_WRITE);
+
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'ids',
+      type: types_.ARRAY,
+      values: (this.type === CalendarType.EVENT)
+                ? tizen.CalendarEventId : undefined
+    },
+    {
+      name: 'successCallback',
+      type: types_.FUNCTION,
+      optional: true,
+      nullable: true
+    },
+    {
+      name: 'errorCallback',
+      type: types_.FUNCTION,
+      optional: true,
+      nullable: true
+    }
+  ]);
+
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+    } else {
+      native_.callIfPossible(args.successCallback);
+    }
+  };
+
+  native_.call('Calendar_removeBatch', {
+    type: this.type,
+    ids: args.ids
+  }, callback);
+
+};
+
+Calendar.prototype.find = function(successCallback, errorCallback, filter, sortMode) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.CALENDAR_READ);
+
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'successCallback',
+      type: types_.FUNCTION
+    },
+    {
+      name: 'errorCallback',
+      type: types_.FUNCTION,
+      optional: true,
+      nullable: true
+    },
+    {
+      name: 'filter',
+      type: types_.PLATFORM_OBJECT,
+      values: [tizen.AttributeFilter, tizen.AttributeRangeFilter, tizen.CompositeFilter],
+      optional: true,
+      nullable: true
+    },
+    {
+      name: 'sortMode',
+      type: types_.PLATFORM_OBJECT,
+      values: tizen.SortMode,
+      optional: true,
+      nullable: true
+    }
+  ]);
+  args.filter = utils_.repackFilter(args.filter);
+  var calendarType = this.type;
+
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+    } else {
+      var _items = native_.getResultObject(result);
+      var c = [];
+      _edit.allow();
+      _items.forEach(function(i) {
+        if (calendarType === CalendarType.TASK) {
+          c.push(new CalendarTask(_itemConverter.toTizenObject(i, i.isAllDay)));
+        } else {
+          c.push(new CalendarEvent(_itemConverter.toTizenObject(i, i.isAllDay)));
+        }
+      });
+      _edit.disallow();
+      args.successCallback(c);
+
+    }
+  };
+  native_.call('Calendar_find', {
+    calendarId: this.id,
+    filter: args.filter,
+    sortMode: args.sortMode || null
+  }, callback);
+
+};
+
+var _listeners = {};
+// @todo this could be replaced by _taskListeners & _eventListeners
+var _nativeListeners = {};
+var _nextId = 0;
+
+function _CalendarEventChangeCallback(event) {
+  _CalendarChangeCallback('EVENT', event);
+}
+function _CalendarTaskChangeCallback(event) {
+  _CalendarChangeCallback('TASK', event);
+}
+function _CalendarChangeCallback(type, event) {
+  var invokeListeners = function(listeners, callbackName, items) {
+    var result = [];
+    _edit.allow();
+    for (var i = 0, length = items.length; i < length; i++) {
+      var item;
+
+      if (callbackName === 'onitemsremoved') {
+        if (type === 'EVENT') {
+          item = new CalendarEventId(items[i].id, null);
+        } else {
+          item = converter_.toString(items[i].id);
+        }
+      } else {
+        item = _itemConverter.toTizenObject(items[i], items[i].isAllDay);
+        if (type === 'EVENT') {
+          item = new CalendarEvent(item);
+        } else {
+          item = new CalendarTask(item);
+        }
+      }
+
+      result.push(item);
+    }
+    _edit.disallow();
+
+    for (var watchId in listeners) {
+      if (listeners.hasOwnProperty(watchId)) {
+        native_.callIfPossible(listeners[watchId][callbackName], result);
+      }
+    }
+  }.bind(this);
+
+  var groupItemsByCalendar = function(items) {
+    var grouped = {};
+
+    for (var i = 0, length = items.length; i < length; i++) {
+      var item = items[i];
+
+      // skip item if we are not listening on this calendarId
+      if (!_listeners.hasOwnProperty(item.calendarId)) {
+        continue;
+      }
+
+      if (!grouped.hasOwnProperty(item.calendarId)) {
+        grouped[item.calendarId] = [];
+      }
+      grouped[item.calendarId].push(item);
+    }
+
+    return grouped;
+  }.bind(this);
+
+  var actions = ['added', 'updated', 'removed'];
+  for (var i = 0; i < actions.length; i++) {
+    var action = actions[i];
+    var callback = 'onitems' + action;
+
+    if (event.hasOwnProperty(action) && type_.isArray(event[action]) && event[action].length) {
+
+      // invoke listeners for unified calendars
+      if (_listeners.hasOwnProperty(type)) {
+        invokeListeners(_listeners[type], callback, event[action]);
+      }
+
+      var groupedItems = groupItemsByCalendar(event[action]);
+      for (var calendarId in groupedItems) {
+        if (groupedItems.hasOwnProperty(calendarId)) {
+          invokeListeners(_listeners[calendarId], callback, groupedItems[calendarId]);
+        }
+      }
+    }
+  }
+}
+
+Calendar.prototype.addChangeListener = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.CALENDAR_READ);
+
+  var args = validator_.validateArgs(arguments, [{
+    name: 'successCallback',
+    type: types_.LISTENER,
+    values: ['onitemsadded', 'onitemsupdated', 'onitemsremoved']
+  }]);
+
+  var listenerId = 'CalendarChangeCallback_' + this.type;
+
+  if (!_nativeListeners.hasOwnProperty(listenerId)) {
+    var result = native_.callSync('Calendar_addChangeListener', {
+      type: this.type,
+      listenerId: listenerId
+    });
+    if (native_.isFailure(result)) {
+      throw native_.getErrorObject(result);
+    }
+
+    native_.addListener(listenerId, (this.type === 'EVENT')
+            ? _CalendarEventChangeCallback
+            : _CalendarTaskChangeCallback);
+    _nativeListeners[listenerId] = this.type;
+  }
+
+  // we can't use id in case of unified calendar - which is null for both calendar types
+  var calendarId = (this.isUnified) ? this.type : this.id;
+  if (!_listeners.hasOwnProperty(calendarId)) {
+    _listeners[calendarId] = {};
+  }
+
+  var watchId = ++_nextId;
+  _listeners[calendarId][watchId] = args.successCallback;
+
+  return watchId;
+};
+
+Calendar.prototype.removeChangeListener = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.CALENDAR_READ);
+
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'watchId',
+      type: types_.LONG
+    }
+  ]);
+
+  var watchId = converter_.toString(args.watchId);
+  var calendarId = (this.isUnified) ? this.type : this.id;
+
+  if (!_listeners[calendarId] || !_listeners[calendarId][watchId]) {
+    return;
+  }
+
+  delete _listeners[calendarId][watchId];
+
+  if (type_.isEmptyObject(_listeners[calendarId])) {
+    delete _listeners[calendarId];
+  }
+
+  if (type_.isEmptyObject(_listeners)) {
+
+    var result;
+    // @todo consider listener unregister when we are not listening on this.type of calendar
+    var fail = false;
+    for (var listenerId in _nativeListeners) {
+      if (_nativeListeners.hasOwnProperty(listenerId)) {
+        result = native_.callSync('Calendar_removeChangeListener', {
+          type: _nativeListeners[listenerId]
+        });
+        if (native_.isFailure(result)) {
+          fail = native_.getErrorObject(result);
+        }
+        native_.removeListener(listenerId, (this.type === 'EVENT')
+                    ? _CalendarEventChangeCallback
+                    : _CalendarTaskChangeCallback);
+
+        delete _nativeListeners[listenerId];
+      }
+    }
+
+    if (fail) {
+      throw fail;
+    }
+  }
+};
+
+tizen.Calendar = Calendar;
diff --git a/webWidgetTCT_device/src/calendar/js/calendar_alarm.js b/webWidgetTCT_device/src/calendar/js/calendar_alarm.js
new file mode 100755 (executable)
index 0000000..08c2638
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+var AlarmMethod = {
+  SOUND: 'SOUND',
+  DISPLAY: 'DISPLAY'
+};
+
+var CalendarAlarm = function(time, method, description) {
+  validator_.isConstructorCall(this, CalendarAlarm);
+
+  var _absoluteDate = time instanceof tizen.TZDate && !this.before ? time : null;
+  var _before = time instanceof tizen.TimeDuration && !this.absoluteDate ? time : null;
+  var _description = (description) ? converter_.toString(description, true) : '';
+  var _method;
+
+  try {
+    _method = converter_.toEnum(method, Object.keys(AlarmMethod), false);
+  } catch (e) {
+    console.warn('Failed to convert method: "' + method + '" to enum AlarmMethod.');
+    _method = method;
+  }
+
+  Object.defineProperties(this, {
+    absoluteDate: {
+      get: function() {
+        return _absoluteDate;
+      },
+      set: function(v) {
+        _absoluteDate = v instanceof tizen.TZDate && !_before ? v : null;
+      },
+      enumerable: true
+    },
+    before: {
+      get: function() {
+        return _before;
+      },
+      set: function(v) {
+        _before = v instanceof tizen.TimeDuration && !_absoluteDate ? v : null;
+      },
+      enumerable: true
+    },
+    method: {
+      get: function() {
+        return _method;
+      },
+      set: function(v) {
+        if (v === null) {
+          return;
+        }
+        _method = converter_.toEnum(v, Object.keys(AlarmMethod), false);
+      },
+      enumerable: true
+    },
+    description: {
+      get: function() {
+        return _description;
+      },
+      set: function(v) {
+        _description = converter_.toString(v, true);
+      },
+      enumerable: true
+    }
+  });
+};
+
+tizen.CalendarAlarm = CalendarAlarm;
diff --git a/webWidgetTCT_device/src/calendar/js/calendar_attendee.js b/webWidgetTCT_device/src/calendar/js/calendar_attendee.js
new file mode 100755 (executable)
index 0000000..0db4f55
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+var _global = window || global || {};
+var AttendeeType = {
+  INDIVIDUAL: 'INDIVIDUAL',
+  GROUP: 'GROUP',
+  RESOURCE: 'RESOURCE',
+  ROOM: 'ROOM',
+  UNKNOWN: 'UNKNOWN'
+};
+
+var AttendeeStatus = {
+  PENDING: 'PENDING',
+  ACCEPTED: 'ACCEPTED',
+  DECLINED: 'DECLINED',
+  TENTATIVE: 'TENTATIVE',
+  DELEGATED: 'DELEGATED',
+  COMPLETED: 'COMPLETED',
+  IN_PROCESS: 'IN_PROCESS'
+};
+
+var AttendeeRole = {
+  REQ_PARTICIPANT: 'REQ_PARTICIPANT',
+  OPT_PARTICIPANT: 'OPT_PARTICIPANT',
+  NON_PARTICIPANT: 'NON_PARTICIPANT',
+  CHAIR: 'CHAIR'
+};
+
+var CalendarAttendeeInit = function(data) {
+  var _name = null;
+  var _role = 'REQ_PARTICIPANT';
+  var _status = 'PENDING';
+  var _RSVP = false;
+  var _type = 'INDIVIDUAL';
+  var _group = null;
+  var _delegatorURI = null;
+  var _delegateURI = null;
+  var _contactRef = null;
+
+  Object.defineProperties(this, {
+    name: {
+      get: function() {
+        return _name;
+      },
+      set: function(v) {
+        _name = converter_.toString(v, true);
+      },
+      enumerable: true
+    },
+    role: {
+      get: function() {
+        return _role;
+      },
+      set: function(v) {
+        if (v === null) {
+          return;
+        }
+        _role = converter_.toEnum(v, Object.keys(AttendeeRole), false);
+      },
+      enumerable: true
+    },
+    status: {
+      get: function() {
+        return _status;
+      },
+      set: function(v) {
+        if (v === null) {
+          return;
+        }
+        _status = converter_.toEnum(v, Object.keys(AttendeeStatus), false);
+      },
+      enumerable: true
+    },
+    RSVP: {
+      get: function() {
+        return _RSVP;
+      },
+      set: function(v) {
+        _RSVP = converter_.toBoolean(v);
+      },
+      enumerable: true
+    },
+    type: {
+      get: function() {
+        return _type;
+      },
+      set: function(v) {
+        if (v === null) {
+          return;
+        }
+        _type = converter_.toEnum(v, Object.keys(AttendeeType), false);
+      },
+      enumerable: true
+    },
+    group: {
+      get: function() {
+        return _group;
+      },
+      set: function(v) {
+        _group = converter_.toString(v, true);
+      },
+      enumerable: true
+    },
+    delegatorURI: {
+      get: function() {
+        return _delegatorURI;
+      },
+      set: function(v) {
+        _delegatorURI = converter_.toString(v, true);
+      },
+      enumerable: true
+    },
+    delegateURI: {
+      get: function() {
+        return _delegateURI;
+      },
+      set: function(v) {
+        _delegateURI = converter_.toString(v, true);
+      },
+      enumerable: true
+    },
+    contactRef: {
+      get: function() {
+        return _contactRef;
+      },
+      set: function(v) {
+        _contactRef = v instanceof tizen.ContactRef ? v : _contactRef;
+      },
+      enumerable: true
+    }
+  });
+
+  if (data instanceof _global.Object) {
+    for (var prop in data) {
+      if (this.hasOwnProperty(prop)) {
+        this[prop] = data[prop];
+      }
+    }
+  }
+};
+
+var CalendarAttendee = function(uri, attendeeInitDict) {
+  validator_.isConstructorCall(this, CalendarAttendee);
+
+  CalendarAttendeeInit.call(this, attendeeInitDict);
+
+  var _uri = null;
+
+  Object.defineProperties(this, {
+    uri: {
+      get: function() {
+        return _uri;
+      },
+      set: function(v) {
+        if (v === null) {
+          return;
+        }
+        _uri = converter_.toString(v, true);
+      },
+      enumerable: true
+    }
+  });
+
+  this.uri = uri;
+};
+
+CalendarAttendee.prototype = new CalendarAttendeeInit();
+CalendarAttendee.prototype.constructor = CalendarAttendee;
+
+tizen.CalendarAttendee = CalendarAttendee;
diff --git a/webWidgetTCT_device/src/calendar/js/calendar_item.js b/webWidgetTCT_device/src/calendar/js/calendar_item.js
new file mode 100755 (executable)
index 0000000..c4d5402
--- /dev/null
@@ -0,0 +1,753 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+var _global = window || global || {};
+
+var CalendarTextFormat = {
+  ICALENDAR_20: 'ICALENDAR_20',
+  VCALENDAR_10: 'VCALENDAR_10'
+};
+
+var CalendarItemVisibility = {
+  PUBLIC: 'PUBLIC', //default
+  PRIVATE: 'PRIVATE',
+  CONFIDENTIAL: 'CONFIDENTIAL'
+};
+
+var CalendarItemPriority = {
+  HIGH: 'HIGH',
+  MEDIUM: 'MEDIUM',
+  LOW: 'LOW',
+  NONE: 'NONE' //default
+};
+
+var CalendarItemStatus = {
+  TENTATIVE: 'TENTATIVE',
+  CONFIRMED: 'CONFIRMED',
+  CANCELLED: 'CANCELLED',
+  NONE: 'NONE', //default for both CalendarEvent and CalendarTask
+  NEEDS_ACTION: 'NEEDS_ACTION',
+  IN_PROCESS: 'IN_PROCESS',
+  COMPLETED: 'COMPLETED'
+};
+
+var EventAvailability = {
+  BUSY: 'BUSY', //default for CalendarEvent
+  FREE: 'FREE'
+};
+
+var CalendarEventId = function(uid, rid) {
+  validator_.isConstructorCall(this, CalendarEventId);
+
+  var _uid = null;
+
+  Object.defineProperties(this, {
+    uid: {
+      get: function() {
+        return _uid;
+      },
+      set: function(v) {
+        if (v === null) {
+          return;
+        }
+        _uid = converter_.toString(v, true);
+      },
+      enumerable: true
+    },
+    rid: {
+      value: (rid) ? converter_.toString(rid, true) : null,
+      writable: true,
+      enumerable: true
+    }
+  });
+
+  this.uid = uid;
+};
+
+// class CalendarItem
+var CalendarItem = function(data) {
+  var _id = null;
+  var _calendarId = null;
+  var _lastModificationDate = null;
+  var _description = '';
+  var _summary = '';
+  var _isAllDay = false;
+  var _startDate = null;
+  var _duration = null;
+  var _location = '';
+  var _geolocation = null;
+  var _organizer = '';
+  var _visibility = CalendarItemVisibility.PUBLIC;
+  var _status = CalendarItemStatus.NONE;
+  var _priority = CalendarItemPriority.NONE;
+  var _alarms = [];
+  var _categories = [];
+  var _attendees = [];
+
+  function _validateAlarms(v) {
+    var valid = false;
+
+    if (type_.isArray(v)) {
+      for (var i = 0; i < v.length; i++) {
+        if (!(v[i] instanceof tizen.CalendarAlarm)) {
+          return false;
+        }
+      }
+      valid = true;
+    }
+    return valid;
+  }
+
+  function _validateAttendees(v) {
+    var valid = false;
+
+    if (type_.isArray(v)) {
+      for (var i = 0; i < v.length; i++) {
+        if (!(v[i] instanceof tizen.CalendarAttendee)) {
+          return false;
+        }
+      }
+      valid = true;
+    }
+    return valid;
+  }
+
+  function _validateCategories(v) {
+    var valid = false;
+
+    if (type_.isArray(v)) {
+      for (var i = 0; i < v.length; i++) {
+        if (!(type_.isString(v[i]))) {
+          return false;
+        }
+      }
+      valid = true;
+    }
+    return valid;
+  }
+
+  Object.defineProperties(this, {
+    id: {
+      get: function() {
+        return _id;
+      },
+      set: function(v) {
+        if (_edit.canEdit) {
+          if (v instanceof _global.Object) {
+            _id = new CalendarEventId(v.uid, v.rid);
+          } else {
+            _id = converter_.toString(v, true);
+          }
+        }
+      },
+      enumerable: true
+    },
+    calendarId: {
+      get: function() {
+        return _calendarId;
+      },
+      set: function(v) {
+        if (_edit.canEdit) {
+          _calendarId = v;
+        }
+      },
+      enumerable: true
+    },
+    lastModificationDate: {
+      get: function() {
+        return _lastModificationDate;
+      },
+      set: function(v) {
+        if (_edit.canEdit) {
+          _lastModificationDate = v instanceof tizen.TZDate ? v :
+              tizen.time.getCurrentDateTime();
+        }
+      },
+      enumerable: true
+    },
+    description: {
+      get: function() {
+        return _description;
+      },
+      set: function(v) {
+        _description = v ? converter_.toString(v, true) : _description;
+      },
+      enumerable: true
+    },
+    summary: {
+      get: function() {
+        return _summary;
+      },
+      set: function(v) {
+        _summary = v ? converter_.toString(v, true) : _summary;
+      },
+      enumerable: true
+    },
+    isAllDay: {
+      get: function() {
+        return _isAllDay;
+      },
+      set: function(v) {
+        _isAllDay = v ? converter_.toBoolean(v) : _isAllDay;
+      },
+      enumerable: true
+    },
+    startDate: {
+      get: function() {
+        return _startDate;
+      },
+      set: function(v) {
+        _startDate = v instanceof tizen.TZDate ? v : _startDate;
+        this.duration = _duration;
+      },
+      enumerable: true
+    },
+    duration: {
+      get: function() {
+        return _duration;
+      },
+      set: function(v) {
+        // set duration as dueDate or endDate
+        var _startDate = this.startDate ?
+            this.startDate : tizen.time.getCurrentDateTime();
+        if (this instanceof tizen.CalendarEvent) {
+          this.endDate = v instanceof tizen.TimeDuration ?
+              _startDate.addDuration(v) : this.endDate;
+        } else {
+          this.dueDate = v instanceof tizen.TimeDuration ?
+              _startDate.addDuration(v) : this.dueDate;
+        }
+        _duration = v instanceof tizen.TimeDuration ? v : null;
+        //@todo Fix UTC, UTC expect duration value but according to documentation:
+        // ... the implementation may not save the duration itself,
+        // rather convert it to the corresponding endDate/dueDate attribute and save it.
+        // For example, if you set the startDate and the duration attributes and save the item,
+        // you may see that the duration is null while endDate/dueDate is non-null
+        // after retrieving it because the implementation has calculated the endDate/dueDate
+        // based on the duration and the startDate then saved it, not the duration.
+      },
+      enumerable: true
+    },
+    location: {
+      get: function() {
+        return _location;
+      },
+      set: function(v) {
+        _location = v ? converter_.toString(v) : _location;
+      },
+      enumerable: true
+    },
+    geolocation: {
+      get: function() {
+        return _geolocation;
+      },
+      set: function(v) {
+        _geolocation = v instanceof tizen.SimpleCoordinates ? v : _geolocation;
+      },
+      enumerable: true
+    },
+    organizer: {
+      get: function() {
+        return _organizer;
+      },
+      set: function(v) {
+        _organizer = v ? converter_.toString(v) : _organizer;
+      },
+      enumerable: true
+    },
+    visibility: {
+      get: function() {
+        return _visibility;
+      },
+      set: function(v) {
+        _visibility = v ? converter_.toEnum(v, Object.keys(CalendarItemVisibility), false) :
+                _visibility;
+      },
+      enumerable: true
+    },
+    status: {
+      get: function() {
+        return _status;
+      },
+      set: function(v) {
+        if (v === null) {
+          return;
+        }
+        if (this instanceof tizen.CalendarEvent) {
+          _status = v ? converter_.toEnum(v, Object.keys(CalendarItemStatus).slice(0, 4), false) :
+                        CalendarItemStatus.NONE;
+        } else {
+          _status = v ? converter_.toEnum(v, Object.keys(CalendarItemStatus).slice(2), false) :
+                        CalendarItemStatus.NONE;
+        }
+      },
+      enumerable: true
+    },
+    priority: {
+      get: function() {
+        return _priority;
+      },
+      set: function(v) {
+        if (v === null) {
+          return;
+        }
+        _priority = v ? converter_.toEnum(v, Object.keys(CalendarItemPriority), false) :
+                    _status;
+      },
+      enumerable: true
+    },
+    alarms: {
+      get: function() {
+        return _alarms;
+      },
+      set: function(v) {
+        _alarms = _validateAlarms(v) ? v : _alarms;
+      },
+      enumerable: true
+    },
+    categories: {
+      get: function() {
+        return _categories;
+      },
+      set: function(v) {
+        _categories = _validateCategories(v) ? v : _categories;
+      },
+      enumerable: true
+    },
+    attendees: {
+      get: function() {
+        return _attendees;
+      },
+      set: function(v) {
+        _attendees = _validateAttendees(v) ? v : _attendees;
+      },
+      enumerable: true
+    }
+  });
+
+  if (data instanceof _global.Object) {
+    for (var prop in data) {
+      if (this.hasOwnProperty(prop)) {
+        this[prop] = data[prop];
+      }
+    }
+  }
+
+};
+
+CalendarItem.prototype.convertToString = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.CALENDAR_READ);
+
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'format',
+      type: types_.ENUM,
+      values: Object.keys(CalendarTextFormat)
+    }
+  ]);
+
+  var _checkNumber = function(n) {
+    return n < 10 ? '0' + n : n;
+  };
+
+  var _timeFormat = function(d) {
+    return ';TZID=' + d.getTimezone() +
+        ':' + d.getFullYear() + _checkNumber(d.getMonth()) + _checkNumber(d.getDate()) +
+            'T' + _checkNumber(d.getHours()) + _checkNumber(d.getMinutes()) +
+            _checkNumber(d.getSeconds() + 'Z');
+  };
+
+  var _this = this;
+  var _dtStart = '';
+
+  if (_this.startDate) {
+    _dtStart = _timeFormat(_this.startDate);
+  } else {
+    _dtStart = _timeFormat(tizen.time.getCurrentDateTime());
+  }
+
+  var _dtEnd = _dtStart;
+
+  if (_this.endDate) {
+    _dtEnd = _timeFormat(_this.endDate);
+  } else if (_this.dueDate) {
+    _dtEnd = _timeFormat(_this.dueDate);
+  }
+
+  var _description = _this.description.length ? ':' + _this.description : '';
+  var _location = _this.location.length ? ':' + _this.location : '';
+  var _organizer = _this.organizer.length ? ';CN=' + _this.organizer : '';
+  var _priority = _this.priority.length ? ':' + _this.priority : '';
+  var _summary = _this.summary.length ? ':' + _this.summary : '';
+  var _categories = _this.categories.length ? ':' + _this.categories.join(', ') : '';
+  var _visibility = _this.visibility;
+  var _status = _this.status;
+  var _version = args.format === CalendarTextFormat.ICALENDAR_20 ? ':2.0' : ':1.0';
+
+  var vEven = [
+    'BEGIN:VCALENDAR',
+    'VERSION' + _version,
+    'BEGIN:VEVENT',
+    'CLASS:' + _visibility,
+    'TRANSP:OPAQUE',
+    'DTSTART' + _dtStart,
+    'DESCRIPTION' + _description,
+    'LOCATION' + _location,
+    'ORGANIZER' + _organizer,
+    'PRIORITY' + _priority,
+    'SUMMARY' + _summary,
+    'DTEND' + _dtEnd,
+    'CATEGORIES' + _categories,
+    'END:VEVENT',
+    'END:VCALENDAR'
+  ].join('\n');
+
+  var vTodo = [
+    'BEGIN:VCALENDAR',
+    'VERSION' + _version,
+    'BEGIN:VTODO',
+    'SUMMARY' + _summary,
+    'DUE' + _dtEnd,
+    'STATUS' + _status,
+    'END:VTODO',
+    'END:VCALENDAR'
+  ].join('\n');
+
+  if (this instanceof tizen.CalendarTask) {
+    return vTodo;
+  } else {
+    return vEven;
+  }
+
+};
+
+CalendarItem.prototype.clone = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.CALENDAR_READ);
+
+  var tmp = _itemConverter.toTizenObject(_itemConverter.fromTizenObject(this));
+
+  tmp.id = null;
+
+  return this instanceof tizen.CalendarEvent ? new tizen.CalendarEvent(tmp) :
+      new tizen.CalendarTask(tmp);
+};
+
+function _convertFromStringToItem(str) {
+  if (str.indexOf('VCALENDAR') === -1) {
+    return;
+  }
+
+  var _startDate = null;
+  var _description = '';
+  var _location = null;
+  var _organizer = null;
+  var _priority = null;
+  var _summary = null;
+  var _categories = [];
+  var _visibility = null;
+  var _status = null;
+  var _endDate = null;
+  var _dueDate = null;
+  var sep;
+
+  if (str.indexOf('\r\n') > -1) {
+    sep = '\r\n';
+  } else if (str.indexOf('\n') > -1) {
+    sep = '\n';
+  } else {
+    return;
+  }
+
+  function _convertTime(v) {
+    var y = parseInt(v.substring(0, 4) , 10);
+    var m = parseInt(v.substring(4, 6) , 10);
+    var d = parseInt(v.substring(6, 8) , 10);
+    var h = parseInt(v.substring(9, 11) , 10);
+    var n = parseInt(v.substring(11, 13) , 10);
+    var s = parseInt(v.substring(13, 15) , 10);
+
+    return new tizen.TZDate(y, m, d, h, n, s);
+  }
+
+  var arr = str.split(sep);
+
+  for (var i = 0; i < arr.length; i++) {
+    if (arr[i].indexOf('SUMMARY') > -1) {
+      _summary = arr[i].split(':')[1];
+    } else if (arr[i].indexOf('CATEGORIES') > -1) {
+      var c = arr[i].split(':')[1];
+      _categories = c.split(',');
+    } else if (arr[i].indexOf('ORGANIZER') > -1) {
+      _organizer = arr[i].split('=')[1];
+    } else if (arr[i].indexOf('DESCRIPTION') > -1) {
+      _description = arr[i].split(':')[1];
+    } else if (arr[i].indexOf('CLASS') > -1) {
+      _visibility = arr[i].split(':')[1];
+    } else if (arr[i].indexOf('LOCATION') > -1) {
+      _location = arr[i].split(':')[1];
+    } else if (arr[i].indexOf('PRIORITY') > -1) {
+      _priority = arr[i].split(':')[1];
+    } else if (arr[i].indexOf('STATUS') > -1) {
+      _status = arr[i].split(':')[1];
+    } else if (arr[i].indexOf('DTSTART') > -1) {
+      _startDate = _convertTime(arr[i].split(':')[1]);
+    } else if (arr[i].indexOf('DTEND') > -1) {
+      _endDate = _convertTime(arr[i].split(':')[1]);
+    } else if (arr[i].indexOf('DUE') > -1) {
+      _dueDate = _convertTime(arr[i].split(':')[1]);
+    }
+  }
+
+  return {
+    visibility: _visibility,
+    startDate: _startDate,
+    description: _description,
+    location: _location,
+    organizer: _organizer,
+    priority: _priority,
+    summary: _summary,
+    status: _status,
+    categories: _categories,
+    endDate: _endDate,
+    dueDate: _dueDate
+  };
+
+}
+
+var CalendarTaskInit = function(data) {
+  CalendarItem.call(this, {
+    status: CalendarItemStatus.NONE
+  });
+
+  var _dueDate = null;
+  var _completedDate = null;
+  var _progress = 0;
+
+  Object.defineProperties(this, {
+    dueDate: {
+      get: function() {
+        return _dueDate;
+      },
+      set: function(v) {
+        if (!v instanceof tizen.TZDate && this.startDate) {
+          v = this.startDate;
+        }
+
+        _dueDate = v instanceof tizen.TZDate ? v : _dueDate;
+      },
+      enumerable: true
+    },
+    completedDate: {
+      get: function() {
+        return _completedDate;
+      },
+      set: function(v) {
+        _completedDate = v instanceof tizen.TZDate ? v : _completedDate;
+      },
+      enumerable: true
+    },
+    progress: {
+      get: function() {
+        return _progress;
+      },
+      set: function(v) {
+        if (v === null) {
+          return;
+        }
+        _progress = (type_.isNumber(v) && (v >= 0 || v <= 100)) ? v : _progress;
+      },
+      enumerable: true
+    }
+  });
+
+  if (data instanceof _global.Object) {
+    for (var prop in data) {
+      if (this.hasOwnProperty(prop)) {
+        this[prop] = data[prop];
+      }
+    }
+  }
+};
+
+var CalendarTask = function(taskInitDict, format) {
+  validator_.isConstructorCall(this, CalendarTask);
+
+  if (type_.isString(taskInitDict) && Object.keys(CalendarTextFormat).indexOf(format) > -1) {
+    CalendarTaskInit.call(this, _convertFromStringToItem(taskInitDict));
+  } else {
+    CalendarTaskInit.call(this, taskInitDict);
+  }
+};
+
+CalendarTask.prototype = new CalendarItem();
+CalendarTask.prototype.constructor = CalendarTask;
+
+
+var CalendarEventInit = function(data) {
+  CalendarItem.call(this, {
+    status: CalendarItemStatus.NONE
+  });
+
+  var _isDetached = false;
+  var _endDate = null;
+  var _availability = EventAvailability.BUSY;
+  var _recurrenceRule = null;
+
+  var _validateReccurence = function(v) {
+    if (_isDetached && v !== null) {
+      throw new WebAPIException(WebAPIException.NOT_SUPPORTED_ERR,
+        'Recurrence can\'t be set because event is detached');
+    }
+
+    if (v === null || v instanceof tizen.CalendarRecurrenceRule) {
+      return v;
+    } else {
+      return _recurrenceRule;
+    }
+  };
+
+  Object.defineProperties(this, {
+    isDetached: {
+      get: function() {
+        return _isDetached;
+      },
+      set: function(v) {
+        if (_edit.canEdit) {
+          _isDetached = v;
+        }
+      },
+      enumerable: true
+    },
+    endDate: {
+      get: function() {
+        return _endDate;
+      },
+      set: function(v) {
+        if (!v instanceof tizen.TZDate && this.startDate) {
+          v = this.startDate;
+        }
+
+        _endDate = v instanceof tizen.TZDate ? v : _endDate;
+      },
+      enumerable: true
+    },
+    availability: {
+      get: function() {
+        return _availability;
+      },
+      set: function(v) {
+        _availability = Object.keys(EventAvailability).indexOf(v) > -1 ? v :
+                _availability;
+      },
+      enumerable: true
+    },
+    recurrenceRule: {
+      get: function() {
+        return _recurrenceRule;
+      },
+      set: function(v) {
+        _recurrenceRule = _validateReccurence(v);
+      },
+      enumerable: true
+    }
+  });
+
+  if (data instanceof _global.Object) {
+    for (var prop in data) {
+      if (this.hasOwnProperty(prop)) {
+        this[prop] = data[prop];
+      }
+    }
+  }
+};
+
+var CalendarEvent = function(eventInitDict, format) {
+  validator_.isConstructorCall(this, CalendarEvent);
+
+  if (type_.isString(eventInitDict) && Object.keys(CalendarTextFormat).indexOf(format) > -1) {
+    CalendarEventInit.call(this, _convertFromStringToItem(eventInitDict));
+  } else {
+    CalendarEventInit.call(this, eventInitDict);
+  }
+};
+
+CalendarEvent.prototype = new CalendarItem();
+CalendarEvent.prototype.constructor = CalendarEvent;
+
+CalendarEvent.prototype.expandRecurrence = function(startDate, endDate, successCallback, errorCallback) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.CALENDAR_READ);
+
+  if (arguments.length < 3) {
+    throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR);
+  }
+  if (!(startDate instanceof tizen.TZDate)) {
+    throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR);
+  }
+  if (!(endDate instanceof tizen.TZDate)) {
+    throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR);
+  }
+  if (typeof successCallback !== 'function') {
+    throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR);
+  }
+  if (errorCallback) {
+    if (typeof errorCallback !== 'function') {
+      throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR);
+    }
+  }
+  if (!(this.recurrenceRule instanceof tizen.CalendarRecurrenceRule)) {
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+      'The event is not recurring.');
+  }
+
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'startDate',
+      type: types_.PLATFORM_OBJECT,
+      values: tizen.TZDate
+    },
+    {
+      name: 'endDate',
+      type: types_.PLATFORM_OBJECT,
+      values: tizen.TZDate
+    },
+    {
+      name: 'successCallback',
+      type: types_.FUNCTION,
+      nullable: true
+    },
+    {
+      name: 'errorCallback',
+      type: types_.FUNCTION,
+      optional: true,
+      nullable: true
+    }
+  ]);
+
+  // invoke callbacks in "next tick"
+  setTimeout(function() {
+    var result = _recurrenceManager.get(this, startDate, endDate);
+
+    if (result instanceof Array) {
+      args.successCallback(result);
+    } else if (args.errorCallback) {
+      args.errorCallback(result);
+    }
+  }.bind(this), 1);
+};
+
+tizen.CalendarEventId = CalendarEventId;
+tizen.CalendarEvent = CalendarEvent;
+tizen.CalendarTask = CalendarTask;
diff --git a/webWidgetTCT_device/src/calendar/js/calendar_manager.js b/webWidgetTCT_device/src/calendar/js/calendar_manager.js
new file mode 100755 (executable)
index 0000000..c63619b
--- /dev/null
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+// class CalendarManager
+var CalendarManager = function() {};
+
+var _PRIVILEGE_CALENDAR_READ = "http://tizen.org/privilege/calendar.read";
+// IDs defined in C-API calendar_types2.h
+var DefaultCalendarId = {
+  EVENT: 1, // DEFAULT_EVENT_CALENDAR_BOOK_ID
+  TASK: 2 // DEFAULT_TODO_CALENDAR_BOOK_ID
+};
+
+CalendarManager.prototype.getCalendars = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.CALENDAR_READ);
+
+  var args = validator_.validateArgs(arguments, [{
+    name: 'type',
+    type: types_.ENUM,
+    values: Object.keys(CalendarType)
+  },
+  {
+    name: 'successCallback',
+    type: types_.FUNCTION
+  },
+  {
+    name: 'errorCallback',
+    type: types_.FUNCTION,
+    optional: true,
+    nullable: true
+  }]);
+
+  var callArgs = {
+    type: args.type
+  };
+
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+    } else {
+      var calendars = native_.getResultObject(result);
+      var c = [];
+      calendars.forEach(function(i) {
+        c.push(new Calendar(new InternalCalendar(i)));
+      });
+      args.successCallback(c);
+    }
+  };
+
+  native_.call('CalendarManager_getCalendars', callArgs, callback);
+};
+
+CalendarManager.prototype.getUnifiedCalendar = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.CALENDAR_READ);
+
+  var args = validator_.validateArgs(arguments, [{
+    name: 'type',
+    type: types_.ENUM,
+    values: Object.keys(CalendarType)
+  }]);
+
+  return new Calendar(new InternalCalendar({
+    type: args.type,
+    isUnified: true
+  }));
+};
+
+CalendarManager.prototype.getDefaultCalendar = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.CALENDAR_READ);
+
+  var args = validator_.validateArgs(arguments, [{
+    name: 'type',
+    type: types_.ENUM,
+    values: Object.keys(CalendarType)
+  }
+  ]);
+
+  return this.getCalendar(args.type, DefaultCalendarId[args.type]);
+};
+
+CalendarManager.prototype.getCalendar = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.CALENDAR_READ);
+
+  var args = validator_.validateArgs(arguments, [{
+    name: 'type',
+    type: types_.ENUM,
+    values: Object.keys(CalendarType)
+  },
+  {
+    name: 'id',
+    type: types_.STRING
+  }
+  ]);
+
+  if (isNaN(Number(args.id))) {
+      throw new WebAPIException(WebAPIException.NOT_FOUND_ERR,
+          'Calendar not found');
+  }
+
+  var callArgs = {
+    type: args.type,
+    id: args.id
+  };
+
+  var result = native_.callSync('CalendarManager_getCalendar', callArgs);
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+
+  return new Calendar(new InternalCalendar(native_.getResultObject(result)));
+};
+
+CalendarManager.prototype.addCalendar = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.CALENDAR_WRITE);
+
+  var args = validator_.validateArgs(arguments, [{
+    name: 'calendar',
+    type: types_.PLATFORM_OBJECT,
+    values: Calendar
+  }]);
+
+  var callArgs = {
+    calendar: args.calendar
+  };
+
+  var result = native_.callSync('CalendarManager_addCalendar', callArgs);
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+
+  args.calendar.id = new InternalCalendar({
+    id: native_.getResultObject(result)
+  });
+};
+
+CalendarManager.prototype.removeCalendar = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.CALENDAR_WRITE);
+
+  var args = validator_.validateArgs(arguments, [{
+    name: 'type',
+    type: types_.ENUM,
+    values: Object.keys(CalendarType)
+  },
+  {
+    name: 'id',
+    type: types_.STRING
+  }
+  ]);
+
+  var callArgs = {
+    type: args.type,
+    id: args.id
+  };
+
+  var result = native_.callSync('CalendarManager_removeCalendar', callArgs);
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+};
+
+exports = new CalendarManager();
diff --git a/webWidgetTCT_device/src/calendar/js/calendar_recurrence_rule.js b/webWidgetTCT_device/src/calendar/js/calendar_recurrence_rule.js
new file mode 100755 (executable)
index 0000000..b13ebff
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+var _global = window || global || {};
+
+var RecurrenceRuleFrequency = {
+  DAILY: 'DAILY',
+  WEEKLY: 'WEEKLY',
+  MONTHLY: 'MONTHLY',
+  YEARLY: 'YEARLY'
+};
+
+var ByDayValue = {
+  MO: 'MO',
+  TU: 'TU',
+  WE: 'WE',
+  TH: 'TH',
+  FR: 'FR',
+  SA: 'SA',
+  SU: 'SU'
+};
+
+var CalendarRecurrenceRuleInit = function(data) {
+  var _interval = 1;
+  var _untilDate = null;
+  var _daysOfTheWeek = [];
+  var _occurrenceCount = -1;
+  var _setPositions = [];
+  var _exceptions = [];
+
+  function _validateDaysOfTheWeek(v) {
+    if (type_.isArray(v)) {
+      var allowedValues = Object.keys(ByDayValue);
+      for (var i = 0; i < v.length; ++i) {
+        if (allowedValues.indexOf(v[i]) < 0) {
+          return false;
+        }
+      }
+      return true;
+    }
+
+    return false;
+  }
+
+  function _validateSetPositions(v) {
+    var valid = false;
+
+    if (type_.isArray(v)) {
+      for (var i = 0; i < v.length; i++) {
+        v[i] = parseInt(v[i]);
+        if (isNaN(v[i]) || (v[i] < -366 || v[i] > 366 || v[i] === 0)) {
+          return false;
+        }
+      }
+      valid = true;
+    }
+    return valid;
+  }
+
+  function _validateExceptions(v) {
+    var valid = false;
+
+    if (type_.isArray(v)) {
+      for (var i = 0; i < v.length; i++) {
+        if (!(v[i] instanceof tizen.TZDate)) {
+          return false;
+        }
+      }
+      valid = true;
+    }
+    return valid;
+  }
+
+  Object.defineProperties(this, {
+    interval: {
+      get: function() {
+        return _interval;
+      },
+      set: function(v) {
+        _interval = (type_.isNumber(v) && v > 0) ? v : _interval;
+      },
+      enumerable: true
+    },
+    untilDate: {
+      get: function() {
+        return _untilDate;
+      },
+      set: function(v) {
+        if (v instanceof tizen.TZDate) {
+          _untilDate = v;
+        }
+      },
+      enumerable: true
+    },
+    occurrenceCount: {
+      get: function() {
+        return _occurrenceCount;
+      },
+      set: function(v) {
+        if (type_.isNumber(v) && v >= -1) {
+          _occurrenceCount = v;
+        }
+      },
+      enumerable: true
+    },
+    daysOfTheWeek: {
+      get: function() {
+        return _daysOfTheWeek;
+      },
+      set: function(v) {
+        _daysOfTheWeek = _validateDaysOfTheWeek(v) ? v : _daysOfTheWeek;
+      },
+      enumerable: true
+    },
+    setPositions: {
+      get: function() {
+        return _setPositions;
+      },
+      set: function(v) {
+        _setPositions = _validateSetPositions(v) ? v : _setPositions;
+      },
+      enumerable: true
+    },
+    exceptions: {
+      get: function() {
+        return _exceptions;
+      },
+      set: function(v) {
+        _exceptions = _validateExceptions(v) ? v : _exceptions;
+      },
+      enumerable: true
+    }
+  });
+
+  if (data instanceof _global.Object) {
+    for (var prop in data) {
+      if (this.hasOwnProperty(prop)) {
+        this[prop] = data[prop];
+      }
+    }
+  }
+};
+
+var CalendarRecurrenceRule = function(frequency, ruleInitDict) {
+  validator_.isConstructorCall(this, CalendarRecurrenceRule);
+
+  CalendarRecurrenceRuleInit.call(this, ruleInitDict);
+
+  var _frequency = null;
+
+  Object.defineProperties(this, {
+    frequency: {
+      get: function() {
+        return _frequency;
+      },
+      set: function(v) {
+        if (v === null) {
+          return;
+        }
+        _frequency = converter_.toEnum(v, Object.keys(RecurrenceRuleFrequency), false);
+      },
+      enumerable: true
+    }
+  });
+
+  // @todo fix UTC, according to documentation frequency is not optional
+  this.frequency = (!frequency) ? 'DAILY' : frequency;
+};
+
+CalendarRecurrenceRule.prototype = new CalendarRecurrenceRuleInit();
+CalendarRecurrenceRule.prototype.constructor = CalendarRecurrenceRule;
+
+tizen.CalendarRecurrenceRule = CalendarRecurrenceRule;
diff --git a/webWidgetTCT_device/src/calendar/js/common.js b/webWidgetTCT_device/src/calendar/js/common.js
new file mode 100755 (executable)
index 0000000..192f7fb
--- /dev/null
@@ -0,0 +1,265 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+var _global = window || global || {};
+
+var utils_ = xwalk.utils;
+var dateConverter_ = utils_.dateConverter;
+var type_ = utils_.type;
+var converter_ = utils_.converter;
+var validator_ = utils_.validator;
+var types_ = validator_.Types;
+var native_ = new xwalk.utils.NativeManager(extension);
+
+
+var EditManager = function() {
+  this.canEdit = false;
+};
+
+EditManager.prototype.allow = function() {
+  this.canEdit = true;
+};
+
+EditManager.prototype.disallow = function() {
+  this.canEdit = false;
+};
+
+var _edit = new EditManager();
+
+var ItemConverter = function() {};
+
+ItemConverter.prototype.toTizenObject = function(item) {
+  var tmp = {};
+  for (var prop in item) {
+    if (prop === 'startDate' ||
+            prop === 'endDate' ||
+            prop === 'dueDate' ||
+            prop === 'completedDate' ||
+            prop === 'lastModificationDate') {
+      tmp[prop] = dateConverter_.toTZDate(item[prop], item.isAllDay);
+    } else {
+      tmp[prop] = item[prop];
+    }
+  }
+
+  var alarms = [];
+  var alarm, time;
+  for (var i = 0; i < tmp.alarms.length; i++) {
+    alarm = tmp.alarms[i];
+    if (alarm.absoluteDate) {
+      time = dateConverter_.toTZDate(alarm.absoluteDate, tmp.isAllDay);
+    } else if (alarm.before) {
+      time = new tizen.TimeDuration(alarm.before.length, alarm.before.unit);
+    }
+    alarms.push(new tizen.CalendarAlarm(time, alarm.method, alarm.description));
+  }
+  tmp.alarms = alarms;
+
+  var attendees = [];
+  for (var i = 0; i < tmp.attendees.length; i++) {
+    if (tmp.attendees[i].contactRef) {
+      var contactRef = new tizen.ContactRef(tmp.attendees[i].contactRef.addressBookId,
+                                                  tmp.attendees[i].contactRef.contactId);
+      tmp.attendees[i].contactRef = contactRef;
+    }
+    if (tmp.attendees[i].uri) {
+      attendees.push(new tizen.CalendarAttendee(tmp.attendees[i].uri, tmp.attendees[i]));
+    }
+  }
+  tmp.attendees = attendees;
+
+  var untilDate;
+  var exceptions = [];
+  if (tmp.recurrenceRule) {
+    untilDate = dateConverter_.toTZDate(tmp.recurrenceRule.untilDate, tmp.isAllDay);
+    tmp.recurrenceRule.untilDate = untilDate;
+
+    for (var i = 0; i < tmp.recurrenceRule.exceptions.length; i++) {
+      exceptions.push(dateConverter_.toTZDate(tmp.recurrenceRule.exceptions[i], tmp.isAllDay));
+    }
+    tmp.recurrenceRule.exceptions = exceptions;
+
+    var recurrenceRule = new tizen.CalendarRecurrenceRule(tmp.recurrenceRule.frequency, tmp.recurrenceRule);
+    tmp.recurrenceRule = recurrenceRule;
+  }
+
+  if (tmp.duration) {
+    var duration = new tizen.TimeDuration(tmp.duration.length, tmp.duration.unit);
+    tmp.duration = duration;
+  }
+
+  if (tmp.geolocation) {
+    var geolocation = new tizen.SimpleCoordinates(tmp.geolocation.latitude, tmp.geolocation.longitude);
+    tmp.geolocation = geolocation;
+  }
+
+  return tmp;
+};
+
+ItemConverter.prototype.fromTizenObject = function(item) {
+  var tmp = {};
+  for (var prop in item) {
+    if (item[prop] instanceof tizen.TZDate) {
+      tmp[prop] = dateConverter_.fromTZDate(item[prop]);
+    } else if (item[prop] instanceof Array) {
+      tmp[prop] = [];
+      for (var i = 0, length = item[prop].length; i < length; i++) {
+        if (item[prop][i] instanceof _global.Object) {
+          tmp[prop][i] = {};
+          for (var p in item[prop][i]) {
+            if (item[prop][i][p] instanceof tizen.TZDate) {
+              tmp[prop][i][p] = dateConverter_.fromTZDate(item[prop][i][p]);
+            } else {
+              tmp[prop][i][p] = item[prop][i][p];
+            }
+          }
+        } else {
+          tmp[prop] = item[prop];
+        }
+      }
+    } else if (item[prop] instanceof _global.Object) {
+      tmp[prop] = {};
+      for (var p in item[prop]) {
+        if (item[prop][p] instanceof tizen.TZDate) {
+          tmp[prop][p] = dateConverter_.fromTZDate(item[prop][p]);
+        } else if (item[prop][p] instanceof Array) {
+          tmp[prop][p] = [];
+          for (var j = 0, l = item[prop][p].length; j < l; j++) {
+            tmp[prop][p].push(dateConverter_.fromTZDate(item[prop][p][j]));
+          }
+        } else {
+          tmp[prop][p] = item[prop][p];
+        }
+      }
+    } else {
+      tmp[prop] = item[prop];
+    }
+  }
+
+  return tmp;
+};
+
+var _itemConverter = new ItemConverter();
+
+function _daysInYear(y) {
+  if ((y % 4 === 0 && y % 100) || y % 400 === 0) {
+    return 366;
+  }
+  return 365;
+}
+
+function _daysInMonth(m, y) {
+  switch (m) {
+    case 1 :
+      return _daysInYear(y) === 366 ? 29 : 28;
+    case 3 :
+    case 5 :
+    case 8 :
+    case 10 :
+      return 30;
+    default :
+      return 31;
+  }
+}
+
+var RecurrenceManager = function() {};
+
+RecurrenceManager.prototype.get = function(event, startDate, endDate) {
+  var events = [];
+  var frequency = event.recurrenceRule.frequency;
+  var interval = event.recurrenceRule.interval;
+  var untilDate = event.recurrenceRule.untilDate;
+  var occurrenceCount = event.recurrenceRule.occurrenceCount;
+  var exceptions = event.recurrenceRule.exceptions;
+  var isDetached = event.isDetached;
+  var startEvent = event.startDate;
+  var startDate = startDate;
+  var endDate = endDate;
+
+  if (isDetached) {
+    return 'The event is detached.';
+  }
+
+  if (startEvent.laterThan(startDate)) {
+    startDate = startEvent;
+  }
+
+  if (untilDate) {
+    endDate = untilDate.laterThan(endDate) ? endDate : untilDate;
+  }
+
+  var timeDifference = endDate.difference(startDate);
+  var daysDifference = timeDifference.length;
+
+  function checkDays(date) {
+    switch (frequency) {
+      case 'DAILY' :
+        return 1;
+      case 'WEEKLY' :
+        return 7;
+      case 'MONTHLY' :
+        return _daysInMonth(date.getMonth(), date.getFullYear());
+      case 'YEARLY' :
+        return _daysInYear(date.getFullYear());
+    }
+  }
+
+  function checkException(date) {
+    for (var j = 0; j < exceptions.length; j++) {
+      if (exceptions[j].equalsTo(date)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  var dates = [];
+  var date = startDate;
+  var push = true;
+  var _interval = occurrenceCount >= 0 ? occurrenceCount :
+      (daysDifference + 1) / checkDays(startDate);
+
+  for (var i = 0; i < _interval; ++i) {
+    if (exceptions) {
+      checkException(date) ? push = false : null;
+    }
+
+    if (push) {
+      if (endDate.laterThan(date) || endDate.equalsTo(date)) {
+        dates.push(date);
+      }
+    }
+    date = date.addDuration(new tizen.TimeDuration((checkDays(date) * interval), 'DAYS'));
+  }
+
+  var tmp;
+  for (var i = 0; i < dates.length; i++) {
+    tmp = event.clone();
+    _edit.allow();
+    tmp.startDate = dates[i];
+    if (event.id instanceof tizen.CalendarEventId) {
+      tmp.id = new tizen.CalendarEventId(event.id.uid, +new Date());
+      tmp.isDetached = true;
+    }
+    _edit.disallow();
+
+    events.push(tmp);
+  }
+
+  return events;
+};
+
+var _recurrenceManager = new RecurrenceManager();
diff --git a/webWidgetTCT_device/src/callhistory/callhistory.cc b/webWidgetTCT_device/src/callhistory/callhistory.cc
new file mode 100755 (executable)
index 0000000..5591b56
--- /dev/null
@@ -0,0 +1,700 @@
+/*
+ * Copyright (c) 2015 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 "callhistory.h"
+
+#include <thread>
+
+#include <tapi_common.h>
+#include <ITapiSim.h>
+#include <contacts_db_extension.h>
+
+#include "common/logger.h"
+#include "common/platform_exception.h"
+#include "common/task-queue.h"
+#include "common/scope_exit.h"
+#include "callhistory_instance.h"
+#include "callhistory_types.h"
+
+using namespace common;
+using namespace tools;
+
+namespace extension {
+namespace callhistory {
+
+namespace {
+static void get_sim_msisdn_cb(TapiHandle *handle, int result, void *data, void *user_data)
+{
+  LoggerD("Entered");
+
+  TelSimMsisdnList_t *list;
+  std::promise<std::string> *prom = reinterpret_cast<std::promise<std::string> *>(user_data);
+  char *number = NULL;
+
+  if (TAPI_SIM_ACCESS_SUCCESS == result) {
+    list = static_cast<TelSimMsisdnList_t *>(data);
+    if (list->count) {
+      number = list->list[0].num;
+    }
+    LoggerD("Phone number: %s", number);
+  } else {
+    LoggerE("Failed to access sim: %d", result);
+  }
+
+  std::string n = number ? std::string(number) : "";
+  prom->set_value(n);
+}
+}
+
+CallHistory::CallHistory(CallHistoryInstance& instance)
+    : m_is_listener_set(false),
+      instance_(instance),
+      utils_(*this) {
+  LoggerD("Entered");
+  if (CONTACTS_ERROR_NONE == contacts_connect()) {
+    LoggerD("Successful to connect Call history DB");
+  } else {
+    LoggerD("Failed to connect Call history DB");
+  }
+}
+
+CallHistory::~CallHistory()
+{
+  LoggerD("Entered");
+
+  if (m_is_listener_set) {
+    int ret = contacts_db_remove_changed_cb_with_info(_contacts_phone_log._uri,
+                                                      changeListenerCB, NULL);
+
+    if (CONTACTS_ERROR_NONE != ret) {
+      LoggerW("Failed to remove ChangeListener");
+    }
+  }
+
+  if (CONTACTS_ERROR_NONE == contacts_disconnect()) {
+    LoggerD("Successful to disconnect Call history DB");
+  } else {
+    LoggerD("Failed to disconnect Call history DB");
+  }
+}
+
+void CallHistory::FindThread(const picojson::object& args, CallHistory* call_history)
+{
+  LoggerD("Entered");
+
+  std::shared_ptr<picojson::value> response{new picojson::value(picojson::object())};
+  int phone_numbers = call_history->getPhoneNumbers().size();
+  const double callback_id = args.find("callbackId")->second.get<double>();
+
+  if (phone_numbers == 0) {
+    LoggerE("Phone numbers list is empty.");
+    ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Phone numbers list is empty."),
+                &response->get<picojson::object>());
+  } else {
+    const auto it_args_end = args.end();
+    const auto it_filter = args.find("filter");
+    picojson::object filter_obj;
+    if (it_filter != it_args_end &&
+        it_filter->second.is<picojson::object>()) {
+      filter_obj = it_filter->second.get<picojson::object>();
+    }
+
+    const auto it_sort_mode = args.find("sortMode");
+    picojson::object sort_mode;
+    if (it_sort_mode != it_args_end &&
+        it_sort_mode->second.is<picojson::object>()) {
+      sort_mode = it_sort_mode->second.get<picojson::object>();
+    }
+
+    std::string sort_attr_name;
+    std::string sort_order;
+    if (!sort_mode.empty()) {
+      const auto it_sort_end = sort_mode.end();
+      const auto it_sort_attr_name = sort_mode.find("attributeName");
+      if (it_sort_attr_name != it_sort_end &&
+          it_sort_attr_name->second.is<std::string>()) {
+        sort_attr_name = it_sort_attr_name->second.get<std::string>();
+      }
+
+      const auto it_sort_order = sort_mode.find("order");
+      if (it_sort_order != it_sort_end &&
+          it_sort_order->second.is<std::string>()) {
+        sort_order = it_sort_order->second.get<std::string>();
+      }
+    }
+
+    const auto it_limit = args.find("limit");
+    int limit = 0;
+    if (it_limit != it_args_end &&
+        it_limit->second.is<double>()) {
+      limit = static_cast<int>(it_limit->second.get<double>());
+    }
+
+    const auto it_offset = args.find("offset");
+    int offset = 0;
+    if (it_offset != it_args_end &&
+        it_offset->second.is<double>()) {
+      offset = static_cast<int>(it_offset->second.get<double>());
+    }
+
+    contacts_query_h query = nullptr;
+    contacts_filter_h filter = nullptr;
+    contacts_list_h record_list = nullptr;
+
+    SCOPE_EXIT {
+      contacts_query_destroy(query);
+      contacts_filter_destroy(filter);
+      contacts_list_destroy(record_list, true);
+    };
+
+    int ret = contacts_connect_on_thread();
+    if (CONTACTS_ERROR_NONE != ret) {
+      LoggerW("contacts_connect_on_thread failed");
+    }
+
+    ret = contacts_query_create(_contacts_phone_log._uri, &query);
+    if (CONTACTS_ERROR_NONE != ret) {
+      LoggerW("contacts_query_create failed");
+    }
+
+    ret = contacts_filter_create(_contacts_phone_log._uri, &filter);
+    if (CONTACTS_ERROR_NONE != ret) {
+      LoggerW("contacts_filter_create failed");
+    }
+
+    //filter
+    CallHistoryUtils& utils = call_history->getUtils();
+    if (!filter_obj.empty()) {
+      LoggerD("Filter is set");
+      utils.createFilter(filter, filter_obj);
+      ret = contacts_filter_add_operator(filter, CONTACTS_FILTER_OPERATOR_AND);
+      if (CONTACTS_ERROR_NONE != ret) {
+        LoggerW("contacts_filter_add_operator failed");
+      }
+    }
+
+    ret = contacts_filter_add_int(filter, _contacts_phone_log.log_type,
+                                  CONTACTS_MATCH_LESS_THAN_OR_EQUAL, CONTACTS_PLOG_TYPE_VIDEO_BLOCKED);
+    if (CONTACTS_ERROR_NONE != ret) {
+      LoggerW("contacts_filter_add_int failed");
+    }
+
+    ret = contacts_query_set_filter(query, filter);
+    if (CONTACTS_ERROR_NONE != ret) {
+      LoggerW("contacts_query_set_filter failed");
+    }
+
+    //sort mode
+    bool is_asc = false;
+    if (!sort_order.empty()) {
+      if (STR_ORDER_ASC == sort_order) {
+        is_asc = true;
+      }
+      unsigned int attribute = utils.convertAttributeName(sort_attr_name);
+      ret = contacts_query_set_sort(query, attribute, is_asc);
+    } else {
+      ret = contacts_query_set_sort(query, _contacts_phone_log.id, is_asc);
+    }
+
+    if (CONTACTS_ERROR_NONE != ret) {
+      LoggerW("contacts_query_set_sort failed");
+    }
+
+    //get records with limit and offset
+    ret = contacts_db_get_records_with_query(query, offset, limit, &record_list);
+    if (CONTACTS_ERROR_NONE != ret) {
+      LoggerW("contacts_db_get_records_with_query failed");
+    }
+
+    picojson::object& obj = response->get<picojson::object>();
+    picojson::array& array = obj.insert(std::make_pair(STR_DATA, picojson::value(
+        picojson::array()))).first->second.get<picojson::array>();
+    if (record_list) {
+      utils.parseRecordList(&record_list, array);
+    }
+
+    ret = contacts_disconnect_on_thread();
+    if (CONTACTS_ERROR_NONE != ret) {
+      LoggerW("contacts_disconnect_on_thread failed");
+    }
+
+    ReportSuccess(response->get<picojson::object>());
+  }
+
+  auto find_response = [call_history, callback_id](const std::shared_ptr<picojson::value>& response) -> void {
+    picojson::object& obj = response->get<picojson::object>();
+    obj.insert(std::make_pair("callbackId", picojson::value(callback_id)));
+    Instance::PostMessage(&call_history->instance_, response->serialize().c_str());
+  };
+
+  TaskQueue::GetInstance().Async<picojson::value>(find_response, response);
+}
+
+void CallHistory::LoadPhoneNumbers(const picojson::object& args, CallHistory* call_history)
+{
+  LoggerD("Entered");
+
+  char** cp_list =  tel_get_cp_name_list();
+
+  if (cp_list) {
+    unsigned int modem_num = 0;
+    std::vector<std::string>& phone_numbers = call_history->getPhoneNumbers();
+
+    while (cp_list[modem_num]) {
+      std::string n = "";
+      TapiHandle* handle = nullptr;
+      do {
+        std::promise<std::string> prom;
+        handle = tel_init(cp_list[modem_num]);
+        if (!handle) {
+          LoggerE("Failed to init tapi handle.");
+          break;
+        }
+
+        int card_changed;
+        TelSimCardStatus_t card_status = TAPI_SIM_STATUS_UNKNOWN;
+        int ret = tel_get_sim_init_info(handle, &card_status, &card_changed);
+        if (TAPI_API_SUCCESS != ret) {
+          LoggerE("Failed to get sim init info: %d", ret);
+          break;
+        }
+        LoggerD("Card status: %d Card Changed: %d", card_status, card_changed);
+        if (TAPI_SIM_STATUS_SIM_INIT_COMPLETED != card_status) {
+          LoggerW("SIM is not ready, we can't get other properties");
+          break;
+        }
+
+        ret = tel_get_sim_msisdn(handle, get_sim_msisdn_cb, &prom);
+        if (TAPI_API_SUCCESS != ret) {
+          LoggerE("Failed to get msisdn : %d", ret);
+          break;
+        }
+
+        auto fut = prom.get_future();
+        LoggerD("wait...");
+        fut.wait();
+        n = fut.get();
+        LoggerD("Phone number [%d] : %s", modem_num, n.c_str());
+      } while(false);
+
+      phone_numbers.push_back(n);
+      tel_deinit(handle);
+      modem_num++;
+    }
+
+    g_strfreev(cp_list);
+  }
+
+  FindThread(args, call_history);
+}
+
+void CallHistory::find(const picojson::object& args) {
+  LoggerD("Entered");
+
+  if (m_phone_numbers.size() == 0) {
+    std::thread(LoadPhoneNumbers, args, this).detach();
+  } else {
+    std::thread(FindThread, args, this).detach();
+  }
+}
+
+PlatformResult CallHistory::remove(const picojson::object& args)
+{
+  LoggerD("Entered");
+
+  const auto it_uid = args.find("uid");
+  const auto it_args_end = args.end();
+
+  if (it_uid == it_args_end ||
+      !it_uid->second.is<std::string>()) {
+    LoggerE("Invalid parameter was passed.");
+    return PlatformResult(ErrorCode::INVALID_VALUES_ERR,
+                          "Invalid parameter was passed.");
+  }
+
+  int uid = atoi((it_uid->second.get<std::string>()).c_str());
+  int ret = contacts_db_delete_record(_contacts_phone_log._uri, (int)uid);
+  if (CONTACTS_ERROR_NONE != ret) {
+    LoggerE("Failed to delete log record [%d] with error: %d", uid, ret);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Failed to delete log record.");
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+common::PlatformResult CallHistory::removeBatch(const picojson::object& args)
+{
+  LoggerD("Entered");
+
+  const auto it_uid = args.find("uid");
+  const auto it_args_end = args.end();
+
+  if (it_uid == it_args_end ||
+      !it_uid->second.is<picojson::array>()) {
+    LoggerE("Invalid parameter was passed.");
+    return PlatformResult(ErrorCode::INVALID_VALUES_ERR,
+                          "Invalid parameter was passed.");
+  }
+  const picojson::array& uids = it_uid->second.get<picojson::array>();
+  const double callback_id = args.find("callbackId")->second.get<double>();
+
+  auto remove_batch = [uids](const std::shared_ptr<picojson::value>& response) -> void {
+    if (uids.size() == 0) {
+      ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR,
+                                 "Object is null."),
+                  &response->get<picojson::object>());
+      return;
+    }
+
+    int ret = CONTACTS_ERROR_NONE;
+    for (unsigned int i = 0; i < uids.size(); ++i) {
+      int uid = atoi(uids[i].get<std::string>().c_str());
+      ret = contacts_db_delete_record(_contacts_phone_log._uri, (int)uid);
+      if (CONTACTS_ERROR_NONE != ret) {
+        LoggerE("Failed to delete log [%d] with code %d", uid, ret);
+        ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR,
+                                   "Remove record failed."),
+                    &response->get<picojson::object>());
+        return;
+      }
+    }
+    ReportSuccess(response->get<picojson::object>());
+  };
+
+  auto remove_batch_response = [this, callback_id](const std::shared_ptr<picojson::value>& response) -> void {
+    picojson::object& obj = response->get<picojson::object>();
+    obj.insert(std::make_pair("callbackId", picojson::value(callback_id)));
+    Instance::PostMessage(&this->instance_, response->serialize().c_str());
+  };
+
+  auto data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+
+  TaskQueue::GetInstance().Queue<picojson::value>(
+      remove_batch,
+      remove_batch_response,
+      data);
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+void CallHistory::removeAll(const picojson::object& args)
+{
+  LoggerD("Entered");
+
+  const double callback_id = args.find("callbackId")->second.get<double>();
+
+  auto remove_all = [](const std::shared_ptr<picojson::value>& response) -> void {
+
+    contacts_list_h record_list = nullptr;
+    int* list = NULL;
+    SCOPE_EXIT {
+      contacts_list_destroy(record_list, true);
+      delete[] list;
+    };
+
+    contacts_record_h record = NULL;
+    int total = 0;
+    int value;
+    unsigned int cnt = 0;
+
+    int ret = contacts_connect_on_thread();
+    if (CONTACTS_ERROR_NONE != ret) {
+      LoggerW("contacts_connect_on_thread failed");
+    }
+
+    ret = contacts_db_get_all_records(_contacts_phone_log._uri, 0, 0, &record_list);
+    if (CONTACTS_ERROR_NONE != ret || !record_list) {
+      LoggerE("Failed to get all records list");
+      ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR,
+                                 "Failed to get all records list."),
+                  &response->get<picojson::object>());
+      return;
+    }
+
+    ret = contacts_list_get_count(record_list, &total);
+    if (CONTACTS_ERROR_NONE != ret) {
+      LoggerW("Failed to get count");
+    }
+
+    list = new int[total];
+    for (int i = 0; i < total; i++) {
+      LoggerD("Record number: %d", i);
+      ret = contacts_list_get_current_record_p(record_list, &record);
+      if (CONTACTS_ERROR_NONE != ret) {
+        LoggerW("contacts_list_get_current_record_p function failed");
+      }
+
+      if (!record) {
+        ret = contacts_list_next(record_list);
+        if (CONTACTS_ERROR_NONE != ret && CONTACTS_ERROR_NO_DATA != ret) {
+          LoggerE("contacts_list_next function failed");
+          ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR,
+                                     "Get next record from list failed."),
+                      &response->get<picojson::object>());
+          return;
+        }
+        continue;
+      }
+
+      if (CONTACTS_ERROR_NONE == ret) {
+        ret = contacts_record_get_int(record, _contacts_phone_log.id , &value);
+        if (CONTACTS_ERROR_NONE == ret) {
+          list[cnt++] = value;
+        }
+      }
+
+      value = 0;
+      ret = contacts_list_next(record_list);
+      if (CONTACTS_ERROR_NONE != ret && CONTACTS_ERROR_NO_DATA != ret) {
+        LoggerE("contacts_list_next function failed");
+        ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR,
+                                   "Get next record from list failed."),
+                    &response->get<picojson::object>());
+        return;
+      }
+    }
+
+    if (cnt > 0) {
+      ret = contacts_db_delete_records(_contacts_phone_log._uri, list, cnt);
+      if (CONTACTS_ERROR_NONE != ret) {
+        LoggerE("contacts_db_delete_records function failed");
+        ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR,
+                                   "Delete records function failed."),
+                    &response->get<picojson::object>());
+        return;
+      }
+    }
+
+    if (CONTACTS_ERROR_NONE != ret) {
+      LoggerW("contacts_list_destroy failed");
+    }
+
+    ret = contacts_disconnect_on_thread();
+    if (CONTACTS_ERROR_NONE != ret) {
+      LoggerW("contacts_disconnect_on_thread failed");
+    }
+
+    ReportSuccess(response->get<picojson::object>());
+  };
+
+  auto remove_all_response = [this, callback_id](const std::shared_ptr<picojson::value>& response) -> void {
+    picojson::object& obj = response->get<picojson::object>();
+    obj.insert(std::make_pair("callbackId", picojson::value(callback_id)));
+    Instance::PostMessage(&this->instance_, response->serialize().c_str());
+  };
+
+  auto data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+
+  TaskQueue::GetInstance().Queue<picojson::value>(
+      remove_all,
+      remove_all_response,
+      data);
+}
+
+std::vector<std::string>& CallHistory::getPhoneNumbers()
+{
+  return m_phone_numbers;
+}
+
+CallHistoryUtils& CallHistory::getUtils()
+{
+  return utils_;
+}
+
+void CallHistory::changeListenerCB(const char* view_uri, char *changes, void* user_data)
+{
+  LoggerD("Entered");
+
+  CallHistory* h = static_cast<CallHistory*>(user_data);
+
+  if (NULL == changes) {
+    LoggerW("changes is NULL");
+    return;
+  }
+  if (0 == strlen(changes)) {
+    LoggerW("changes is empty");
+    return;
+  }
+
+  char seps[] = ",:";
+  char* token_type = NULL;
+  int change_id = 0;
+
+  picojson::value added = picojson::value(picojson::object());
+  picojson::object& added_obj = added.get<picojson::object>();
+  picojson::array& added_array = added_obj.insert(std::make_pair(STR_DATA, picojson::value(
+      picojson::array()))).first->second.get<picojson::array>();
+
+  picojson::value changed = picojson::value(picojson::object());
+  picojson::object& changed_obj = changed.get<picojson::object>();
+  picojson::array& changed_array = changed_obj.insert(std::make_pair(STR_DATA, picojson::value(
+      picojson::array()))).first->second.get<picojson::array>();
+
+  picojson::value removed = picojson::value(picojson::object());
+  picojson::object& removed_obj = removed.get<picojson::object>();
+  picojson::array& removed_array = removed_obj.insert(std::make_pair(STR_DATA, picojson::value(
+      picojson::array()))).first->second.get<picojson::array>();
+
+  char* saveptr = nullptr;
+
+  token_type = strtok_r(changes, seps, &saveptr);
+  while (NULL != token_type) {
+    char* token_id = strtok_r(NULL, seps, &saveptr);
+    int change_type = atoi((const char*)token_type);
+
+    if (NULL != token_id) {
+      change_id = atoi((const char*)token_id);
+    } else {
+      LoggerD("There is no (more) changed Item : %s", token_id);
+      break;
+    }
+
+    contacts_query_h query = NULL;
+    contacts_filter_h filter = NULL;
+    contacts_list_h record_list = NULL;
+
+    contacts_query_create(_contacts_phone_log._uri, &query);
+    contacts_filter_create(_contacts_phone_log._uri, &filter);
+    contacts_filter_add_int(filter, _contacts_phone_log.id, CONTACTS_MATCH_EQUAL, change_id);
+
+    contacts_query_set_filter(query, filter);
+    int ret = contacts_query_set_sort(query, _contacts_phone_log.id, false);
+    if (CONTACTS_ERROR_NONE != ret) {
+      LoggerD("Callhistory query error: %d", ret);
+    }
+
+    ret = contacts_db_get_records_with_query(query, 0, 1, &record_list);
+    if (CONTACTS_ERROR_NONE != ret) {
+      contacts_list_destroy(record_list, true);
+      contacts_query_destroy(query);
+      contacts_filter_destroy(filter);
+      LoggerD("Callhistory query error: %d", ret);
+      return;
+    }
+
+    if (CONTACTS_CHANGE_INSERTED == change_type) {
+      h->utils_.parseRecordList(&record_list, added_array);
+    } else if (CONTACTS_CHANGE_UPDATED == change_type) {
+      h->utils_.parseRecordList(&record_list, changed_array);
+    } else if (CONTACTS_CHANGE_DELETED == change_type) {
+      removed_array.push_back(picojson::value(token_id));
+    }
+
+    contacts_list_destroy(record_list, true);
+    contacts_query_destroy(query);
+    contacts_filter_destroy(filter);
+
+    token_type = strtok_r( NULL, seps, &saveptr);
+  }
+
+  if (added_array.size() > 0) {
+    added_obj[STR_ACTION] = picojson::value("onadded");
+    h->instance_.CallHistoryChange(added_obj);
+  }
+  if (changed_array.size() > 0) {
+    changed_obj[STR_ACTION] = picojson::value("onchanged");
+    h->instance_.CallHistoryChange(changed_obj);
+  }
+  if (removed_array.size() > 0) {
+    removed_obj[STR_ACTION] = picojson::value("onremoved");
+    h->instance_.CallHistoryChange(removed_obj);
+  }
+}
+
+PlatformResult CallHistory::startCallHistoryChangeListener()
+{
+  LoggerD("Entered");
+
+  if (!m_is_listener_set) {
+    int ret = contacts_db_add_changed_cb_with_info(_contacts_phone_log._uri,
+                                                   changeListenerCB, this);
+
+    if (CONTACTS_ERROR_NONE != ret) {
+      LoggerE("Failed to add ChangeListener");
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "Failed to add ChangeListener");
+    }
+  }
+
+  m_is_listener_set = true;
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CallHistory::stopCallHistoryChangeListener()
+{
+  LoggerD("Entered");
+  if (m_is_listener_set) {
+    int ret = contacts_db_remove_changed_cb_with_info(_contacts_phone_log._uri,
+                                                      changeListenerCB, this);
+
+    if (CONTACTS_ERROR_NONE != ret) {
+      LoggerE("Failed to remove ChangeListener");
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "Failed to remove ChangeListener");
+    }
+  }
+  m_is_listener_set = false;
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CallHistory::setMissedDirection(int uid)
+{
+  LoggerD("Entered");
+
+  contacts_record_h record = nullptr;
+  SCOPE_EXIT {
+    contacts_record_destroy(record, true);
+  };
+
+  int log_type = CONTACTS_PLOG_TYPE_NONE;
+
+  int ret = contacts_db_get_record(_contacts_phone_log._uri, uid, &record);
+  if (CONTACTS_ERROR_NONE != ret) {
+    LoggerE("Failed to get record [%d]", ret);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get record");
+  }
+
+  ret = contacts_record_get_int(record, _contacts_phone_log.log_type, &log_type);
+  if (CONTACTS_ERROR_NONE != ret) {
+    LoggerE("Failed to get log type [%d]", ret);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get log type");
+  }
+
+  if (CONTACTS_PLOG_TYPE_VOICE_INCOMMING_UNSEEN == log_type) {
+    ret = contacts_record_set_int(
+        record, _contacts_phone_log.log_type, CONTACTS_PLOG_TYPE_VOICE_INCOMMING_SEEN);
+  } else if (CONTACTS_PLOG_TYPE_VIDEO_INCOMMING_UNSEEN == log_type) {
+    ret = contacts_record_set_int(
+        record, _contacts_phone_log.log_type, CONTACTS_PLOG_TYPE_VIDEO_INCOMMING_SEEN);
+  } else {
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+
+  if (CONTACTS_ERROR_NONE != ret) {
+    LoggerE("Failed to set direction [%d]", ret);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to set direction");
+  }
+
+  ret = contacts_db_update_record(record);
+  if (CONTACTS_ERROR_NONE != ret) {
+    LoggerE("Failed to update record [%d]", ret);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to update record");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+} // namespace callhistory
+} // namespace extension
diff --git a/webWidgetTCT_device/src/callhistory/callhistory.gyp b/webWidgetTCT_device/src/callhistory/callhistory.gyp
new file mode 100755 (executable)
index 0000000..3e88ecc
--- /dev/null
@@ -0,0 +1,40 @@
+{
+  'includes':[
+    '../common/common.gypi',
+  ],
+  'targets': [
+    {
+      'target_name': 'tizen_callhistory',
+      'type': 'loadable_module',
+      'dependencies': [
+        '../common/common.gyp:tizen_common',
+      ],
+      'sources': [
+        'callhistory_api.js',
+        'callhistory.cc',
+        'callhistory.h',
+        'callhistory_extension.cc',
+        'callhistory_extension.h',
+        'callhistory_instance.cc',
+        'callhistory_instance.h',
+        'callhistory_utils.cc',
+        'callhistory_utils.h',
+      ],
+      'includes': [
+        '../common/pkg-config.gypi',
+      ],
+      'conditions': [
+        ['tizen == 1', {
+          'variables': {
+            'packages': [
+              'glib-2.0',
+              'contacts-service2',
+              'libpcrecpp',
+              'tapi',
+            ]
+          },
+        }],
+      ],
+    },
+  ],
+}
\ No newline at end of file
diff --git a/webWidgetTCT_device/src/callhistory/callhistory.h b/webWidgetTCT_device/src/callhistory/callhistory.h
new file mode 100755 (executable)
index 0000000..a366237
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2015 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 CALLHISTORY_CALLHISTORY_H_
+#define CALLHISTORY_CALLHISTORY_H_
+
+#include <string>
+#include <vector>
+#include <future>
+
+#include <contacts.h>
+#include <contacts_internal.h>
+
+#include "common/picojson.h"
+#include "common/platform_result.h"
+
+#include "callhistory/callhistory_utils.h"
+
+namespace extension {
+namespace callhistory {
+
+class CallHistoryInstance;
+
+class CallHistory
+{
+ public:
+  explicit CallHistory(CallHistoryInstance& instance);
+  ~CallHistory();
+
+  std::vector<std::string>& getPhoneNumbers();
+  CallHistoryUtils& getUtils();
+
+  void find(const picojson::object& args);
+  common::PlatformResult remove(const picojson::object& args);
+  common::PlatformResult removeBatch(const picojson::object& args);
+  void removeAll(const picojson::object& args);
+  common::PlatformResult startCallHistoryChangeListener();
+  common::PlatformResult stopCallHistoryChangeListener();
+  common::PlatformResult setMissedDirection(int uid);
+
+ private:
+  static void changeListenerCB(const char* view_uri, char *changes, void* user_data);
+  static void FindThread(const picojson::object& args, CallHistory* call_history);
+  static void LoadPhoneNumbers(const picojson::object& args, CallHistory* call_history);
+
+  bool m_is_listener_set;
+  std::vector<std::string> m_phone_numbers;
+  CallHistoryInstance& instance_;
+  CallHistoryUtils utils_;
+};
+
+} // namespace callhistory
+} // namespace extension
+
+#endif // CALLHISTORY_CALLHISTORY_H_
diff --git a/webWidgetTCT_device/src/callhistory/callhistory_api.js b/webWidgetTCT_device/src/callhistory/callhistory_api.js
new file mode 100755 (executable)
index 0000000..d12b5ab
--- /dev/null
@@ -0,0 +1,360 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+var validator_ = xwalk.utils.validator;
+var converter_ = xwalk.utils.converter;
+var types_ = validator_.Types;
+var T_ = xwalk.utils.type;
+var native_ = new xwalk.utils.NativeManager(extension);
+
+function _createCallHistoryEntries(e) {
+    var entries_array = [];
+    var entries = e.data;
+
+    entries.forEach(function (data) {
+        entries_array.push(new CallHistoryEntry(data));
+    });
+
+    return entries_array;
+};
+
+function _getUidFromCallHistoryEntry(entries) {
+    var uid = [];
+
+    entries.forEach(function (data) {
+        uid.push(data.uid);
+    });
+
+    return uid;
+};
+
+function ListenerManager(native, listenerName) {
+    this.listeners = {};
+    this.nextId = 1;
+    this.nativeSet = false;
+    this.native = native;
+    this.listenerName = listenerName;
+};
+
+ListenerManager.prototype.onListenerCalled = function(msg) {
+    var d = undefined;
+    switch (msg.action) {
+    case 'onadded':
+    case 'onchanged':
+        d = _createCallHistoryEntries(msg);
+        break;
+
+    case 'onremoved':
+        d = msg.data;
+        break;
+
+    default:
+        console.log('Unknown mode: ' + msg.action);
+        return;
+    }
+
+    for (var watchId in this.listeners) {
+        if (this.listeners.hasOwnProperty(watchId) && this.listeners[watchId][msg.action]) {
+            this.listeners[watchId][msg.action](d);
+        }
+    }
+};
+
+ListenerManager.prototype.addListener = function(callback) {
+    var id = this.nextId;
+    if (!this.nativeSet) {
+      this.native.addListener(this.listenerName, this.onListenerCalled.bind(this));
+      this.nativeSet = true;
+    }
+    this.listeners[id] = callback;
+    ++this.nextId;
+    return id;
+};
+
+ListenerManager.prototype.removeListener = function(watchId) {
+    if (this.listeners[watchId] === null || this.listeners[watchId] === undefined) {
+        throw new WebAPIException(0, 'Watch id not found.', 'InvalidValuesError');
+    }
+
+    if (this.listeners.hasOwnProperty(watchId)) {
+        delete this.listeners[watchId];
+    }
+};
+
+var CALL_HISTORY_CHANGE_LISTENER = 'CallHistoryChangeCallback';
+var callHistoryChangeListener = new ListenerManager(native_, CALL_HISTORY_CHANGE_LISTENER);
+
+function CallHistory() {
+};
+
+CallHistory.prototype.find = function() {
+    xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.CALLHISTORY_READ);
+
+    var args = validator_.validateArgs(arguments, [
+        {
+            name : 'successCallback',
+            type : types_.FUNCTION,
+        },
+        {
+            name : 'errorCallback',
+            type : types_.FUNCTION,
+            optional : true,
+            nullable : true
+        },
+        {
+            name : 'filter',
+            type : types_.PLATFORM_OBJECT,
+            optional : true,
+            nullable : true,
+            values : [tizen.AttributeFilter,
+                      tizen.AttributeRangeFilter,
+                      tizen.CompositeFilter]
+        },
+        {
+            name : 'sortMode',
+            type : types_.PLATFORM_OBJECT,
+            optional : true,
+            nullable : true,
+            values : tizen.SortMode
+        },
+        {
+            name : 'limit',
+            type : types_.UNSIGNED_LONG,
+            optional : true,
+            nullable : true
+        },
+        {
+            name : 'offset',
+            type : types_.UNSIGNED_LONG,
+            optional : true,
+            nullable : true
+        }
+    ]);
+
+    var callback = function(result) {
+        if (native_.isFailure(result)) {
+            native_.callIfPossible(args.errorCallback, native.getErrorObject(result));
+        } else {
+            var entries = _createCallHistoryEntries(result);
+            args.successCallback(entries);
+        }
+    };
+
+    var callArgs = {};
+    callArgs.filter = args.filter;
+    callArgs.sortMode = args.sortMode;
+    callArgs.limit = args.limit;
+    callArgs.offset = args.offset;
+
+    native_.call('CallHistory_find', callArgs, callback);
+};
+
+CallHistory.prototype.remove = function() {
+    xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.CALLHISTORY_WRITE);
+
+    var args = validator_.validateArgs(arguments, [
+        {
+            name : 'entry',
+            type : types_.PLATFORM_OBJECT,
+            values : CallHistoryEntry
+        }
+    ]);
+
+    var callArgs = {};
+    callArgs.uid = args.entry.uid;
+
+    var result = native_.callSync('CallHistory_remove', callArgs);
+    if (native_.isFailure(result)) {
+        throw new WebAPIException(
+                WebAPIException.INVALID_VALUES_ERR, 'Watch id not found.');
+    }
+
+    return;
+};
+
+CallHistory.prototype.removeBatch = function() {
+    xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.CALLHISTORY_WRITE);
+
+    var args = validator_.validateArgs(arguments, [
+        {
+            name : 'entries',
+            type : types_.ARRAY,
+            values : CallHistoryEntry
+        },
+        {
+            name : 'successCallback',
+            type : types_.FUNCTION,
+            optional : true,
+            nullable : true
+        },
+        {
+            name : 'errorCallback',
+            type : types_.FUNCTION,
+            optional : true,
+            nullable : true
+        }
+    ]);
+
+    var callback = function(result) {
+        if (native_.isFailure(result)) {
+            native_.callIfPossible(args.errorCallback, native.getErrorObject(result));
+        } else {
+            native_.callIfPossible(args.successCallback);
+        }
+    };
+
+    var uid = _getUidFromCallHistoryEntry(args.entries);
+    var callArgs = {};
+    callArgs.uid = uid;
+
+    native_.call('CallHistory_removeBatch', callArgs, callback);
+};
+
+CallHistory.prototype.removeAll = function() {
+    xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.CALLHISTORY_WRITE);
+
+    var args = validator_.validateArgs(arguments, [
+        {
+            name : 'successCallback',
+            type : types_.FUNCTION,
+            optional : true,
+            nullable : true
+        },
+        {
+            name : 'errorCallback',
+            type : types_.FUNCTION,
+            optional : true,
+            nullable : true
+        }
+    ]);
+
+    var callback = function(result) {
+        if (native_.isFailure(result)) {
+            native_.callIfPossible(args.errorCallback, native.getErrorObject(result));
+        } else {
+            native_.callIfPossible(args.successCallback);
+        }
+    };
+
+    native_.call('CallHistory_removeAll', {}, callback);
+};
+
+CallHistory.prototype.addChangeListener = function() {
+    xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.CALLHISTORY_READ);
+
+    var args = validator_.validateArgs(arguments, [
+        {
+            name : 'eventCallback',
+            type : types_.LISTENER,
+            values : ['onadded', 'onchanged', 'onremoved']
+        }
+    ]);
+
+    if (T_.isEmptyObject(callHistoryChangeListener.listeners)) {
+        native_.callSync('CallHistory_addChangeListener');
+    }
+
+    return callHistoryChangeListener.addListener(args.eventCallback);
+};
+
+CallHistory.prototype.removeChangeListener = function() {
+    xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.CALLHISTORY_READ);
+
+    var args = validator_.validateArgs(arguments, [
+        {
+            name : 'watchId',
+            type : types_.LONG
+        }
+    ]);
+
+    callHistoryChangeListener.removeListener(args.watchId);
+
+    if (T_.isEmptyObject(callHistoryChangeListener.listeners)) {
+        native_.callSync('CallHistory_removeChangeListener');
+    }
+};
+
+function RemoteParty(data) {
+    Object.defineProperties(this, {
+        remoteParty: {
+            value: data.remoteParty ? data.remoteParty : null,
+            writable: false,
+            enumerable: true
+        },
+        personId: {
+            value: data.personId ? converter_.toString(data.personId) : null,
+            writable: false,
+            enumerable: true
+        }
+    });
+};
+
+function CallHistoryEntry(data) {
+    function directionSetter(val) {
+        if (direction === 'MISSEDNEW' && val === 'MISSED') {
+            var result = native_.callSync('CallHistory_setMissedDirection', {uid : this.uid});
+            if (native_.isSuccess(result)) {
+                direction = 'MISSED';
+            }
+        }
+    }
+
+    function createRemoteParties(parties) {
+        var parties_array = [];
+        parties.forEach(function (data) {
+            parties_array.push(new RemoteParty(data));
+        });
+        return parties_array;
+    }
+
+    var direction;
+    if (data) {
+        direction = converter_.toString(data.direction, false);
+    }
+
+    Object.defineProperties(this, {
+        uid: {value: converter_.toString(data.uid), writable: false, enumerable: true},
+        type: {value: data.type, writable: false, enumerable: true},
+        features : {
+            value: data.features ? data.features : null,
+            writable: false,
+            enumerable: true
+        },
+        remoteParties : {
+            value : createRemoteParties(data.remoteParties),
+            writable: false,
+            enumerable: true
+        },
+        startTime: {value: new Date(Number(data.startTime) * 1000),
+            writable: false,
+            enumerable: true
+        },
+        duration: {value: data.duration, writable: false, enumerable: true},
+        direction: {
+            enumerable: true,
+            set : directionSetter,
+            get : function() { return direction; }
+        },
+        callingParty: {
+            value: data.callingParty ? data.callingParty : null,
+            writable: false,
+            enumerable: true
+        },
+    });
+};
+
+// Exports
+exports = new CallHistory();
diff --git a/webWidgetTCT_device/src/callhistory/callhistory_extension.cc b/webWidgetTCT_device/src/callhistory/callhistory_extension.cc
new file mode 100755 (executable)
index 0000000..2d37fd6
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2015 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 "callhistory/callhistory_extension.h"
+#include "callhistory/callhistory_instance.h"
+
+// This will be generated from power_api.js
+extern const char kSource_callhistory_api[];
+
+common::Extension* CreateExtension() {
+  return new CallHistoryExtension;
+}
+
+CallHistoryExtension::CallHistoryExtension() {
+  SetExtensionName("tizen.callhistory");
+  SetJavaScriptAPI(kSource_callhistory_api);
+}
+
+CallHistoryExtension::~CallHistoryExtension() {}
+
+common::Instance* CallHistoryExtension::CreateInstance() {
+  return new extension::callhistory::CallHistoryInstance();
+}
diff --git a/webWidgetTCT_device/src/callhistory/callhistory_extension.h b/webWidgetTCT_device/src/callhistory/callhistory_extension.h
new file mode 100755 (executable)
index 0000000..12abb6d
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2015 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 CALLHISTORY_CALLHISTORY_EXTENSION_H_
+#define CALLHISTORY_CALLHISTORY_EXTENSION_H_
+
+#include "common/extension.h"
+
+class CallHistoryExtension : public common::Extension {
+ public:
+  CallHistoryExtension();
+  virtual ~CallHistoryExtension();
+
+ private:
+  virtual common::Instance* CreateInstance();
+};
+
+#endif // CALLHISTORY_CALLHISTORY_EXTENSION_H_
diff --git a/webWidgetTCT_device/src/callhistory/callhistory_instance.cc b/webWidgetTCT_device/src/callhistory/callhistory_instance.cc
new file mode 100755 (executable)
index 0000000..7b74910
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2015 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 "callhistory/callhistory_instance.h"
+
+#include "common/picojson.h"
+#include "common/logger.h"
+#include "common/platform_exception.h"
+
+namespace extension {
+namespace callhistory {
+
+using namespace common;
+
+CallHistoryInstance::CallHistoryInstance() : history_(*this) {
+  using std::placeholders::_1;
+  using std::placeholders::_2;
+
+#define REGISTER_SYNC(c,x) \
+    RegisterSyncHandler(c, std::bind(&CallHistoryInstance::x, this, _1, _2));
+  REGISTER_SYNC("CallHistory_remove", Remove);
+  REGISTER_SYNC("CallHistory_addChangeListener", AddChangeListener);
+  REGISTER_SYNC("CallHistory_removeChangeListener", RemoveChangeListener);
+  REGISTER_SYNC("CallHistory_setMissedDirection", SetMissedDirection);
+#undef REGISTER_SYNC
+#define REGISTER_ASYNC(c,x) \
+    RegisterSyncHandler(c, std::bind(&CallHistoryInstance::x, this, _1, _2));
+  REGISTER_ASYNC("CallHistory_find", Find);
+  REGISTER_ASYNC("CallHistory_removeBatch", RemoveBatch);
+  REGISTER_ASYNC("CallHistory_removeAll", RemoveAll);
+#undef REGISTER_ASYNC
+}
+
+CallHistoryInstance::~CallHistoryInstance() {
+}
+
+void CallHistoryInstance::Find(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+  history_.find(args.get<picojson::object>());
+  ReportSuccess(out);
+}
+
+void CallHistoryInstance::Remove(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+  PlatformResult result = history_.remove(args.get<picojson::object>());
+  if (result.IsSuccess()) {
+    ReportSuccess(out);
+  } else {
+    ReportError(result, &out);
+  }
+}
+
+void CallHistoryInstance::RemoveBatch(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+  PlatformResult result = history_.removeBatch(args.get<picojson::object>());
+  if (result.IsSuccess()) {
+    ReportSuccess(out);
+  } else {
+    ReportError(result, &out);
+  }
+}
+
+void CallHistoryInstance::RemoveAll(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+  history_.removeAll(args.get<picojson::object>());
+  ReportSuccess(out);
+}
+
+void CallHistoryInstance::AddChangeListener(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+  PlatformResult result = history_.startCallHistoryChangeListener();
+  if (result.IsSuccess()) {
+    ReportSuccess(out);
+  } else {
+    ReportError(result, &out);
+  }
+}
+
+void CallHistoryInstance::RemoveChangeListener(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+  PlatformResult result = history_.stopCallHistoryChangeListener();
+  if (result.IsSuccess()) {
+    ReportSuccess(out);
+  } else {
+    ReportError(result, &out);
+  }
+}
+
+void CallHistoryInstance::SetMissedDirection(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+
+  if (!args.contains("uid")) {
+    LoggerD("args doesn't contain attribute 'uid'");
+    ReportError(out);
+    return;
+  }
+
+  int uid = std::atoi(args.get("uid").get<std::string>().c_str());
+
+  PlatformResult result = history_.setMissedDirection(uid);
+  if (result.IsSuccess()) {
+    ReportSuccess(out);
+  } else {
+    ReportError(out);
+  }
+}
+
+void CallHistoryInstance::CallHistoryChange(picojson::object& data) {
+  LoggerD("Entered");
+  picojson::value event = picojson::value(data);
+  picojson::object& obj = event.get<picojson::object>();
+  obj["listenerId"] = picojson::value("CallHistoryChangeCallback");
+
+  Instance::PostMessage(this, event.serialize().c_str());
+}
+
+} // namespace callhistory
+} // namespace extension
diff --git a/webWidgetTCT_device/src/callhistory/callhistory_instance.h b/webWidgetTCT_device/src/callhistory/callhistory_instance.h
new file mode 100755 (executable)
index 0000000..a7e9f30
--- /dev/null
@@ -0,0 +1,35 @@
+// Copyright 2014 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CALLHISTORY_CALLHISTORY_INSTANCE_H_
+#define CALLHISTORY_CALLHISTORY_INSTANCE_H_
+
+#include "common/extension.h"
+#include "callhistory.h"
+
+namespace extension {
+namespace callhistory {
+
+class CallHistoryInstance : public common::ParsedInstance {
+ public:
+  CallHistoryInstance();
+  virtual ~CallHistoryInstance();
+
+  void CallHistoryChange(picojson::object& data);
+ private:
+  void Find(const picojson::value& args, picojson::object& out);
+  void Remove(const picojson::value& args, picojson::object& out);
+  void RemoveBatch(const picojson::value& args, picojson::object& out);
+  void RemoveAll(const picojson::value& args, picojson::object& out);
+  void AddChangeListener (const picojson::value& args, picojson::object& out);
+  void RemoveChangeListener(const picojson::value& args, picojson::object& out);
+  void SetMissedDirection(const picojson::value& args, picojson::object& out);
+
+  CallHistory history_;
+};
+
+} // namespace callhistory
+} // namespace extension
+
+#endif // CALLHISTORY_CALLHISTORY_INSTANCE_H_
diff --git a/webWidgetTCT_device/src/callhistory/callhistory_types.h b/webWidgetTCT_device/src/callhistory/callhistory_types.h
new file mode 100755 (executable)
index 0000000..b2a6d7a
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2015 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 CALLHISTORY_CALLHISTORY_TYPES_H_
+#define CALLHISTORY_CALLHISTORY_TYPES_H_
+
+namespace extension {
+namespace callhistory {
+
+#define STR_CALLTYPE_TEL "TEL"
+#define STR_CALLTYPE_XMPP "XMPP"
+#define STR_CALLTYPE_SIP "SIP"
+
+#define STR_CALL "CALL"
+#define STR_CALL_VOICE "VOICECALL"
+#define STR_CALL_VIDEO "VIDEOCALL"
+#define STR_CALL_EMERGENCY "EMERGENCYCALL"
+
+#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_DATA "data"
+#define STR_ACTION "action"
+#define STR_ENTRY_ID "uid"
+#define STR_CALL_TYPE "type"
+#define STR_TAGS "features"
+#define STR_REMOTE_PARTIES "remoteParties"
+#define STR_START_TIME "startTime"
+#define STR_DURATION "duration"
+#define STR_DIRECTION "direction"
+#define STR_CALLING_PARTY "callingParty"
+
+#define STR_REMOTE_PARTY "remoteParty"
+#define STR_PERSON_ID "personId"
+
+#define STR_RP_REMOTEPARTY "remoteParties.remoteParty"
+#define STR_RP_PERSONID "remoteParties.personId"
+
+#define STR_ORDER_ASC "ASC"
+
+#define STR_FILTER_EXACTLY "EXACTLY"
+#define STR_FILTER_FULLSTRING "FULLSTRING"
+#define STR_FILTER_CONTAINS "CONTAINS"
+#define STR_FILTER_STARTSWITH "STARTSWITH"
+#define STR_FILTER_ENDSWITH "ENDSWITH"
+#define STR_FILTER_EXISTS "EXISTS"
+
+} // namespace callhistory
+} // namespace extension
+
+#endif // CALLHISTORY_CALLHISTORY_TYPES_H_
diff --git a/webWidgetTCT_device/src/callhistory/callhistory_utils.cc b/webWidgetTCT_device/src/callhistory/callhistory_utils.cc
new file mode 100755 (executable)
index 0000000..70dcb50
--- /dev/null
@@ -0,0 +1,670 @@
+/*
+ * Copyright (c) 2015 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 "callhistory_utils.h"
+
+#include <stack>
+#include <ctime>
+
+#include "callhistory_types.h"
+#include "callhistory.h"
+#include "common/logger.h"
+
+namespace extension {
+namespace callhistory {
+
+namespace {
+enum FilterTypeEnum {
+  FILTER_ATTRIBUTE = 0,
+  FILTER_ATTRIBUTE_RANGE = 1,
+  FILTER_COMPOSITE = 2,
+  FILTER_UNKNOWN = 3
+};
+
+enum CompositeTypeEnum {
+  UNION = 0,
+  INTERSECTION = 1,
+  NONE = 2
+};
+}
+
+CallHistoryUtils::CallHistoryUtils(CallHistory& history)
+    : history_(history) {
+}
+
+void CallHistoryUtils::parseRecordList(contacts_list_h *record_list, picojson::array& array)
+{
+  LoggerD("Entered");
+
+  contacts_record_h record = NULL;
+  int total = 0;
+
+  int ret = contacts_list_get_count(*record_list, &total);
+  if (CONTACTS_ERROR_NONE != ret) {
+    LoggerW("Failed to get contacts list: %d", ret);
+    return;
+  }
+
+  for (int i = 0; i < total; i++) {
+    ret = contacts_list_get_current_record_p(*record_list, &record);
+    if (NULL != record) {
+      array.push_back(picojson::value(picojson::object()));
+      picojson::object& obj = array.back().get<picojson::object>();
+      parseRecord(&record, obj);
+    } else {
+      ret = contacts_list_next(*record_list);
+      if (CONTACTS_ERROR_NONE != ret && CONTACTS_ERROR_NO_DATA != ret) {
+        LoggerW("Callhistory list parse error: %d", ret);
+        return;
+      }
+    }
+    ret = contacts_list_next(*record_list);
+    if (CONTACTS_ERROR_NONE != ret && CONTACTS_ERROR_NO_DATA != ret) {
+      LoggerW("Callhistory list parse error: %d", ret);
+      return;
+    }
+  }
+}
+
+void CallHistoryUtils::parseRecord(contacts_record_h *record, picojson::object& obj)
+{
+  LoggerD("Entered");
+
+  int int_data;
+
+  int ret = contacts_record_get_int(*record, _contacts_phone_log.id, &int_data);
+  if (CONTACTS_ERROR_NONE != ret) {
+    LoggerD("Failed to get contacts phone log id: %d", ret);
+  } else {
+    obj[STR_ENTRY_ID] = picojson::value(static_cast<double>(int_data));
+  }
+
+  ret = contacts_record_get_int(*record, _contacts_phone_log.log_type, &int_data);
+  if (CONTACTS_ERROR_NONE != ret) {
+    LoggerD("Failed to get contacts phone log type: %d", ret);
+  } else {
+    parseLogType(static_cast<contacts_phone_log_type_e>(int_data), obj);
+  }
+
+  ret = contacts_record_get_int(*record, _contacts_phone_log.log_time, &int_data);
+  if (CONTACTS_ERROR_NONE != ret) {
+    LoggerD("Failed to get contacts phone log time: %d", ret);
+  } else {
+    obj[STR_START_TIME] = picojson::value(static_cast<double>(int_data));
+  }
+
+  ret = contacts_record_get_int(*record, _contacts_phone_log.extra_data1, &int_data);
+  if (CONTACTS_ERROR_NONE != ret) {
+    LoggerD("Failed to get contacts phone log extra data: %d", ret);
+  } else {
+    obj[STR_DURATION] = picojson::value(static_cast<double>(int_data));
+  }
+
+  parseRemoteParties(record, obj);
+  parseCallingParty(record, obj);
+}
+
+void CallHistoryUtils::parseLogType(contacts_phone_log_type_e log_type, picojson::object& obj)
+{
+  LoggerD("Entered");
+
+  picojson::value val = picojson::value(picojson::array());
+  picojson::array& features = val.get<picojson::array>();
+
+  switch(log_type) {
+    case CONTACTS_PLOG_TYPE_VOICE_INCOMMING:
+      obj[STR_CALL_TYPE] = picojson::value(STR_CALLTYPE_TEL);
+      obj[STR_DIRECTION] = picojson::value(STR_RECEIVED);
+      features.push_back(picojson::value(STR_CALL_VOICE));
+      break;
+    case CONTACTS_PLOG_TYPE_VOICE_OUTGOING:
+      obj[STR_CALL_TYPE] = picojson::value(STR_CALLTYPE_TEL);
+      obj[STR_DIRECTION] = picojson::value(STR_DIALED);
+      features.push_back(picojson::value(STR_CALL_VOICE));
+      break;
+    case CONTACTS_PLOG_TYPE_VOICE_INCOMMING_SEEN:
+      obj[STR_CALL_TYPE] = picojson::value(STR_CALLTYPE_TEL);
+      obj[STR_DIRECTION] = picojson::value(STR_MISSED);
+      features.push_back(picojson::value(STR_CALL_VOICE));
+      break;
+    case CONTACTS_PLOG_TYPE_VOICE_INCOMMING_UNSEEN:
+      obj[STR_CALL_TYPE] = picojson::value(STR_CALLTYPE_TEL);
+      obj[STR_DIRECTION] = picojson::value(STR_MISSED_NEW);
+      features.push_back(picojson::value(STR_CALL_VOICE));
+      break;
+    case CONTACTS_PLOG_TYPE_VOICE_REJECT:
+      obj[STR_CALL_TYPE] = picojson::value(STR_CALLTYPE_TEL);
+      obj[STR_DIRECTION] = picojson::value(STR_REJECTED);
+      features.push_back(picojson::value(STR_CALL_VOICE));
+      break;
+    case CONTACTS_PLOG_TYPE_VOICE_BLOCKED:
+      obj[STR_CALL_TYPE] = picojson::value(STR_CALLTYPE_TEL);
+      obj[STR_DIRECTION] = picojson::value(STR_BLOCKED);
+      features.push_back(picojson::value(STR_CALL_VOICE));
+      break;
+    case CONTACTS_PLOG_TYPE_VIDEO_INCOMMING:
+      obj[STR_CALL_TYPE] = picojson::value(STR_CALLTYPE_TEL);
+      obj[STR_DIRECTION] = picojson::value(STR_RECEIVED);
+      features.push_back(picojson::value(STR_CALL_VIDEO));
+      break;
+    case CONTACTS_PLOG_TYPE_VIDEO_OUTGOING:
+      obj[STR_CALL_TYPE] = picojson::value(STR_CALLTYPE_TEL);
+      obj[STR_DIRECTION] = picojson::value(STR_DIALED);
+      features.push_back(picojson::value(STR_CALL_VIDEO));
+      break;
+    case CONTACTS_PLOG_TYPE_VIDEO_INCOMMING_SEEN:
+      obj[STR_CALL_TYPE] = picojson::value(STR_CALLTYPE_TEL);
+      obj[STR_DIRECTION] = picojson::value(STR_MISSED);
+      features.push_back(picojson::value(STR_CALL_VIDEO));
+      break;
+    case CONTACTS_PLOG_TYPE_VIDEO_INCOMMING_UNSEEN:
+      obj[STR_CALL_TYPE] = picojson::value(STR_CALLTYPE_TEL);
+      obj[STR_DIRECTION] = picojson::value(STR_MISSED_NEW);
+      features.push_back(picojson::value(STR_CALL_VIDEO));
+      break;
+    case CONTACTS_PLOG_TYPE_VIDEO_REJECT:
+      obj[STR_CALL_TYPE] = picojson::value(STR_CALLTYPE_TEL);
+      obj[STR_DIRECTION] = picojson::value(STR_REJECTED);
+      features.push_back(picojson::value(STR_CALL_VIDEO));
+      break;
+    case CONTACTS_PLOG_TYPE_VIDEO_BLOCKED:
+      obj[STR_CALL_TYPE] = picojson::value(STR_CALLTYPE_TEL);
+      obj[STR_DIRECTION] = picojson::value(STR_BLOCKED);
+      features.push_back(picojson::value(STR_CALL_VIDEO));
+      break;
+    default:
+      LoggerW("Wrong phone log type: %d", log_type);
+      return;
+  }
+
+  if (features.size() > 0) {
+    obj.insert(std::make_pair(STR_TAGS, picojson::value(features)));
+  }
+}
+
+void CallHistoryUtils::parseRemoteParties(contacts_record_h *record, picojson::object& obj)
+{
+  LoggerD("Entered");
+
+  char * char_data = NULL;
+  int int_data;
+
+  picojson::array& remote_parties = obj.insert(std::make_pair(STR_REMOTE_PARTIES, picojson::value(
+      picojson::array()))).first->second.get<picojson::array>();
+  remote_parties.push_back(picojson::value(picojson::object()));
+  picojson::object& parties_obj = remote_parties.back().get<picojson::object>();
+
+  int ret = contacts_record_get_int(*record, _contacts_phone_log.person_id, &int_data);
+  if (CONTACTS_ERROR_NONE != ret) {
+    LoggerD("Failed to get contacts phone log person id: %d", ret);
+  } else {
+    parties_obj[STR_PERSON_ID] = picojson::value(static_cast<double>(int_data));
+  }
+
+  ret = contacts_record_get_str_p(*record, _contacts_phone_log.address, &char_data);
+  if (CONTACTS_ERROR_NONE != ret) {
+    LoggerD("Failed to get contacts phone log address: %d", ret);
+  } else if (NULL != char_data) {
+    parties_obj[STR_REMOTE_PARTY] = picojson::value(char_data);
+  }
+}
+
+void CallHistoryUtils::parseCallingParty(contacts_record_h *record, picojson::object& obj)
+{
+  LoggerD("Entered");
+
+  const std::vector<std::string>& phone_numbers = history_.getPhoneNumbers();
+  int sim_count = phone_numbers.size();
+  int sim_index;
+
+  int ret = contacts_record_get_int(*record, _contacts_phone_log.sim_slot_no, &sim_index);
+  if (CONTACTS_ERROR_NONE != ret) {
+    LoggerW("Failed to get sim slot no. %d", ret);
+  }
+
+  if (sim_index >= sim_count) {
+    LoggerE("sim slot no. [%d] is out of count %d", sim_index, sim_count);
+  } else if (sim_index > 0) {
+    obj[STR_CALLING_PARTY] = picojson::value(phone_numbers.at(sim_index));
+  }
+}
+
+unsigned int CallHistoryUtils::convertAttributeName(const std::string& attribute_name)
+{
+  LoggerD("Entered");
+
+  if (STR_RP_REMOTEPARTY == attribute_name) {
+    return _contacts_phone_log.address;
+  } else if (STR_START_TIME == attribute_name) {
+    return _contacts_phone_log.log_time;
+  } else if (STR_DURATION == attribute_name) {
+    return _contacts_phone_log.extra_data1;
+  } else if (STR_DIRECTION == attribute_name) {
+    return _contacts_phone_log.log_type;
+  } else if (STR_ENTRY_ID == attribute_name) {
+    return _contacts_phone_log.id;
+  } else {
+    return 0;
+  }
+}
+
+static FilterTypeEnum getFilterType(const picojson::object &filter)
+{
+  LoggerD("Entered");
+
+  const auto it_end = filter.end();
+
+  FilterTypeEnum type = FILTER_UNKNOWN;
+
+  const auto it_match_flag = filter.find("matchFlag");
+  if (it_match_flag != it_end) {
+    type = FILTER_ATTRIBUTE;
+  }
+
+  const auto it_initial_value = filter.find("initialValue");
+  const auto it_end_value = filter.find("endValue");
+  if (it_initial_value != it_end && it_end_value != it_end) {
+    type = FILTER_ATTRIBUTE_RANGE;
+  }
+
+  const auto it_type = filter.find("type");
+  if (it_type != it_end) {
+    type = FILTER_COMPOSITE;
+  }
+  return type;
+}
+
+static CompositeTypeEnum getCompositeType(const picojson::object &filter)
+{
+  LoggerD("Entered");
+  CompositeTypeEnum type = NONE;
+  const std::string& str_type = filter.find("type")->second.get<std::string>();
+
+  if ("UNION" == str_type) {
+    type = UNION;
+  } else if ("INTERSECTION" == str_type) {
+    type = INTERSECTION;
+  }
+  return type;
+}
+
+static contacts_match_str_flag_e getMatchFlag(const std::string& match_flag)
+{
+  LoggerD("Entered");
+  if (STR_FILTER_FULLSTRING == match_flag) {
+    return CONTACTS_MATCH_FULLSTRING;
+  } else if (STR_FILTER_CONTAINS == match_flag) {
+    return CONTACTS_MATCH_CONTAINS;
+  } else if (STR_FILTER_STARTSWITH == match_flag) {
+    return CONTACTS_MATCH_STARTSWITH;
+  } else if (STR_FILTER_ENDSWITH == match_flag) {
+    return CONTACTS_MATCH_ENDSWITH;
+  } else if (STR_FILTER_EXISTS == match_flag) {
+    return CONTACTS_MATCH_EXISTS;
+  } else {
+    return CONTACTS_MATCH_EXACTLY;
+  }
+}
+
+static std::time_t toTimeT(const std::string &value)
+{
+  LoggerD("Entered");
+  struct tm date;
+  if (nullptr == strptime(value.c_str(), "%Y-%m-%dT%H:%M:%S", &date)) {
+    LOGW("Couldn't convert supplied date.");
+  }
+  return mktime(&date);
+}
+
+static void visitAttribute(std::stack<contacts_filter_h>& stack, const picojson::object filter)
+{
+  LoggerD("Entered");
+
+  contacts_filter_h filter_top = stack.top();
+  contacts_filter_h sub_filter = NULL;
+  contacts_filter_create(_contacts_phone_log._uri, &sub_filter);
+
+  const auto it_attr_name = filter.find("attributeName");
+  const std::string &attr_name = it_attr_name->second.get<std::string>();
+
+  const auto it_match_flag = filter.find("matchFlag");
+  const std::string &match_flag = it_match_flag->second.get<std::string>();
+  contacts_match_str_flag_e c_match_flag = getMatchFlag(match_flag);
+
+  const auto it_match_value = filter.find("matchValue");
+  std::string match_value_str;
+  if (!it_match_value->second.is<picojson::null>()) {
+    if (it_match_value->second.is<double>()) {
+      match_value_str = std::to_string(it_match_value->second.get<double>());
+    } else {
+      match_value_str = it_match_value->second.get<std::string>();
+    }
+  }
+
+  if (STR_DIRECTION == attr_name) {
+    if (STR_RECEIVED == match_value_str) {
+      contacts_filter_add_int(sub_filter, _contacts_phone_log.log_type,
+                              CONTACTS_MATCH_EQUAL, CONTACTS_PLOG_TYPE_VOICE_INCOMMING);
+      contacts_filter_add_operator(sub_filter, CONTACTS_FILTER_OPERATOR_OR);
+      contacts_filter_add_int(sub_filter, _contacts_phone_log.log_type,
+                              CONTACTS_MATCH_EQUAL, CONTACTS_PLOG_TYPE_VIDEO_INCOMMING);
+      contacts_filter_add_filter(filter_top, sub_filter);
+    }
+    else if (STR_DIALED == match_value_str) {
+      contacts_filter_add_int(sub_filter, _contacts_phone_log.log_type,
+                              CONTACTS_MATCH_EQUAL, CONTACTS_PLOG_TYPE_VOICE_OUTGOING);
+      contacts_filter_add_operator(sub_filter, CONTACTS_FILTER_OPERATOR_OR);
+      contacts_filter_add_int(sub_filter, _contacts_phone_log.log_type,
+                              CONTACTS_MATCH_EQUAL, CONTACTS_PLOG_TYPE_VIDEO_OUTGOING);
+      contacts_filter_add_filter(filter_top, sub_filter);
+    }
+    else if (STR_MISSED == match_value_str) {
+      contacts_filter_add_int(sub_filter, _contacts_phone_log.log_type,
+                              CONTACTS_MATCH_EQUAL, CONTACTS_PLOG_TYPE_VOICE_INCOMMING_SEEN);
+      contacts_filter_add_operator(sub_filter, CONTACTS_FILTER_OPERATOR_OR);
+      contacts_filter_add_int(sub_filter, _contacts_phone_log.log_type,
+                              CONTACTS_MATCH_EQUAL, CONTACTS_PLOG_TYPE_VIDEO_INCOMMING_SEEN);
+      contacts_filter_add_filter(filter_top, sub_filter);
+    }
+    else if (STR_MISSED_NEW == match_value_str) {
+      contacts_filter_add_int(sub_filter, _contacts_phone_log.log_type,
+                              CONTACTS_MATCH_EQUAL, CONTACTS_PLOG_TYPE_VOICE_INCOMMING_UNSEEN);
+      contacts_filter_add_operator(sub_filter, CONTACTS_FILTER_OPERATOR_OR);
+      contacts_filter_add_int(sub_filter, _contacts_phone_log.log_type,
+                              CONTACTS_MATCH_EQUAL, CONTACTS_PLOG_TYPE_VIDEO_INCOMMING_UNSEEN);
+      contacts_filter_add_filter(filter_top, sub_filter);
+    }
+    else if (STR_REJECTED == match_value_str) {
+      contacts_filter_add_int(sub_filter, _contacts_phone_log.log_type,
+                              CONTACTS_MATCH_EQUAL, CONTACTS_PLOG_TYPE_VOICE_REJECT);
+      contacts_filter_add_operator(sub_filter, CONTACTS_FILTER_OPERATOR_OR);
+      contacts_filter_add_int(sub_filter, _contacts_phone_log.log_type,
+                              CONTACTS_MATCH_EQUAL, CONTACTS_PLOG_TYPE_VIDEO_REJECT);
+      contacts_filter_add_filter(filter_top, sub_filter);
+    }
+    else if (STR_BLOCKED == match_value_str) {
+      contacts_filter_add_int(sub_filter, _contacts_phone_log.log_type,
+                              CONTACTS_MATCH_EQUAL, CONTACTS_PLOG_TYPE_VOICE_BLOCKED);
+      contacts_filter_add_operator(sub_filter, CONTACTS_FILTER_OPERATOR_OR);
+      contacts_filter_add_int(sub_filter, _contacts_phone_log.log_type,
+                              CONTACTS_MATCH_EQUAL, CONTACTS_PLOG_TYPE_VIDEO_BLOCKED);
+      contacts_filter_add_filter(filter_top, sub_filter);
+    }
+    else {
+      contacts_filter_add_int(filter_top, _contacts_phone_log.log_type,
+                              CONTACTS_MATCH_EQUAL, CONTACTS_PLOG_TYPE_NONE);
+    }
+  }
+  else if (STR_TAGS == attr_name) {
+    if (STR_CALL == match_value_str) {
+      contacts_filter_add_int(sub_filter, _contacts_phone_log.log_type,
+                              CONTACTS_MATCH_GREATER_THAN_OR_EQUAL,
+                              CONTACTS_PLOG_TYPE_VOICE_INCOMMING);
+      contacts_filter_add_operator(sub_filter, CONTACTS_FILTER_OPERATOR_AND);
+      contacts_filter_add_int(sub_filter, _contacts_phone_log.log_type,
+                              CONTACTS_MATCH_LESS_THAN_OR_EQUAL, CONTACTS_PLOG_TYPE_VIDEO_BLOCKED);
+      contacts_filter_add_filter(filter_top, sub_filter);
+    }
+    else if (STR_CALL_VOICE == match_value_str) {
+      contacts_filter_add_int(sub_filter, _contacts_phone_log.log_type,
+                              CONTACTS_MATCH_EQUAL, CONTACTS_PLOG_TYPE_VOICE_INCOMMING);
+      contacts_filter_add_operator(sub_filter, CONTACTS_FILTER_OPERATOR_OR);
+      contacts_filter_add_int(sub_filter, _contacts_phone_log.log_type,
+                              CONTACTS_MATCH_EQUAL, CONTACTS_PLOG_TYPE_VOICE_OUTGOING);
+      contacts_filter_add_operator(sub_filter, CONTACTS_FILTER_OPERATOR_OR);
+      contacts_filter_add_int(sub_filter, _contacts_phone_log.log_type,
+                              CONTACTS_MATCH_EQUAL, CONTACTS_PLOG_TYPE_VOICE_INCOMMING_UNSEEN);
+      contacts_filter_add_operator(sub_filter, CONTACTS_FILTER_OPERATOR_OR);
+      contacts_filter_add_int(sub_filter, _contacts_phone_log.log_type,
+                              CONTACTS_MATCH_EQUAL, CONTACTS_PLOG_TYPE_VOICE_INCOMMING_SEEN);
+      contacts_filter_add_operator(sub_filter, CONTACTS_FILTER_OPERATOR_OR);
+      contacts_filter_add_int(sub_filter, _contacts_phone_log.log_type,
+                              CONTACTS_MATCH_EQUAL, CONTACTS_PLOG_TYPE_VOICE_REJECT);
+      contacts_filter_add_operator(sub_filter, CONTACTS_FILTER_OPERATOR_OR);
+      contacts_filter_add_int(sub_filter, _contacts_phone_log.log_type,
+                              CONTACTS_MATCH_EQUAL, CONTACTS_PLOG_TYPE_VOICE_BLOCKED);
+      contacts_filter_add_filter(filter_top, sub_filter);
+    }
+    else if (STR_CALL_VIDEO == match_value_str) {
+      contacts_filter_add_int(sub_filter, _contacts_phone_log.log_type,
+                              CONTACTS_MATCH_EQUAL, CONTACTS_PLOG_TYPE_VIDEO_INCOMMING);
+      contacts_filter_add_operator(sub_filter, CONTACTS_FILTER_OPERATOR_OR);
+      contacts_filter_add_int(sub_filter, _contacts_phone_log.log_type,
+                              CONTACTS_MATCH_EQUAL, CONTACTS_PLOG_TYPE_VIDEO_OUTGOING);
+      contacts_filter_add_operator(sub_filter, CONTACTS_FILTER_OPERATOR_OR);
+      contacts_filter_add_int(sub_filter, _contacts_phone_log.log_type,
+                              CONTACTS_MATCH_EQUAL, CONTACTS_PLOG_TYPE_VIDEO_INCOMMING_UNSEEN);
+      contacts_filter_add_operator(sub_filter, CONTACTS_FILTER_OPERATOR_OR);
+      contacts_filter_add_int(sub_filter, _contacts_phone_log.log_type,
+                              CONTACTS_MATCH_EQUAL, CONTACTS_PLOG_TYPE_VIDEO_INCOMMING_SEEN);
+      contacts_filter_add_operator(sub_filter, CONTACTS_FILTER_OPERATOR_OR);
+      contacts_filter_add_int(sub_filter, _contacts_phone_log.log_type,
+                              CONTACTS_MATCH_EQUAL, CONTACTS_PLOG_TYPE_VIDEO_REJECT);
+      contacts_filter_add_operator(sub_filter, CONTACTS_FILTER_OPERATOR_OR);
+      contacts_filter_add_int(sub_filter, _contacts_phone_log.log_type,
+                              CONTACTS_MATCH_EQUAL, CONTACTS_PLOG_TYPE_VIDEO_BLOCKED);
+      contacts_filter_add_filter(filter_top, sub_filter);
+    }
+    else if (STR_CALL_EMERGENCY == match_value_str) {
+      contacts_filter_add_str(filter_top, _contacts_phone_log.extra_data2,
+                              CONTACTS_MATCH_EXACTLY, "001");
+    }
+    else {
+      contacts_filter_add_int(filter_top, _contacts_phone_log.log_type,
+                              CONTACTS_MATCH_EQUAL, CONTACTS_PLOG_TYPE_NONE);
+    }
+  }
+  else if (STR_RP_REMOTEPARTY == attr_name) {
+    contacts_filter_add_str(filter_top, _contacts_phone_log.address, c_match_flag,
+                            match_value_str.c_str());
+  }
+  else if (STR_RP_PERSONID == attr_name) {
+    contacts_filter_add_str(filter_top, _contacts_phone_log.person_id, c_match_flag,
+                            match_value_str.c_str());
+  }
+  else if (STR_START_TIME == attr_name) {
+    LoggerD("DATE _____>>>>>>>>> %s", match_value_str.c_str());
+    contacts_filter_add_int(filter_top, _contacts_phone_log.log_time,
+                            CONTACTS_MATCH_EQUAL, static_cast<int>(toTimeT(match_value_str)));
+  }
+  else if (STR_DURATION == attr_name) {
+    contacts_filter_add_str(filter_top, _contacts_phone_log.extra_data1, c_match_flag,
+                            match_value_str.c_str());
+  }
+  else if (STR_CALL_TYPE == attr_name) {
+    if (STR_CALLTYPE_TEL == match_value_str) {
+      contacts_filter_add_int(sub_filter, _contacts_phone_log.log_type,
+                              CONTACTS_MATCH_GREATER_THAN_OR_EQUAL,
+                              CONTACTS_PLOG_TYPE_VOICE_INCOMMING);
+      contacts_filter_add_operator(sub_filter, CONTACTS_FILTER_OPERATOR_AND);
+      contacts_filter_add_int(sub_filter, _contacts_phone_log.log_type,
+                              CONTACTS_MATCH_LESS_THAN_OR_EQUAL, CONTACTS_PLOG_TYPE_VIDEO_BLOCKED);
+      contacts_filter_add_filter(filter_top, sub_filter);
+    }
+    else {
+      contacts_filter_add_int(filter_top, _contacts_phone_log.log_type,
+                              CONTACTS_MATCH_EQUAL, CONTACTS_PLOG_TYPE_NONE);
+    }
+  }
+  else if (STR_ENTRY_ID == attr_name) {
+    contacts_filter_add_str(filter_top, _contacts_phone_log.id, c_match_flag,
+                            match_value_str.c_str());
+  }
+  else {
+    contacts_filter_add_int(filter_top, _contacts_phone_log.log_type,
+                            CONTACTS_MATCH_EQUAL, CONTACTS_PLOG_TYPE_NONE);
+  }
+
+  contacts_filter_destroy(sub_filter);
+}
+
+static void visitAttributeRange(std::stack<contacts_filter_h>& stack, const picojson::object filter)
+{
+  LoggerD("Entered");
+
+  unsigned int prop_id = 0;
+  const auto it_attr_name = filter.find("attributeName");
+  const std::string &attr_name = it_attr_name->second.get<std::string>();
+
+  if (STR_RP_REMOTEPARTY == attr_name) {
+    prop_id = _contacts_phone_log.address;
+  } else if (STR_RP_PERSONID == attr_name) {
+    prop_id = _contacts_phone_log.person_id;
+  } else if (STR_START_TIME == attr_name) {
+    prop_id = _contacts_phone_log.log_time;
+  } else if (STR_DURATION == attr_name) {
+    prop_id = _contacts_phone_log.extra_data1;
+  } else if (STR_ENTRY_ID == attr_name) {
+    prop_id = _contacts_phone_log.id;
+  } else {
+    LoggerW("attribute: %s is not supported", attr_name.c_str());
+    return;
+  }
+
+  std::string i_val;
+  std::string e_val;
+  contacts_filter_h filter_top = stack.top();
+  contacts_filter_h sub_filter = NULL;
+
+  const auto it_initial_value = filter.find("initialValue");
+  const auto it_end_value = filter.find("endValue");
+  bool is_i_val_null = it_initial_value->second.is<picojson::null>();
+  bool is_e_val_null = it_end_value->second.is<picojson::null>();
+
+  if (!is_i_val_null) {
+    if (it_initial_value->second.is<double>()) {
+      i_val = std::to_string(it_initial_value->second.is<double>());
+    } else {
+      i_val = it_initial_value->second.get<std::string>();
+    }
+  }
+
+  if (!is_e_val_null) {
+    if (it_end_value->second.is<double>()) {
+      e_val = std::to_string(it_end_value->second.is<double>());
+    } else {
+      e_val = it_end_value->second.get<std::string>();
+    }
+  }
+
+  contacts_filter_create(_contacts_phone_log._uri, &sub_filter);
+
+  if (_contacts_phone_log.address == prop_id) {
+    if (!is_i_val_null && is_e_val_null) {
+      contacts_filter_add_str(filter_top, prop_id, CONTACTS_MATCH_STARTSWITH,i_val.c_str());
+    }
+    else if (is_i_val_null && !is_e_val_null) {
+      contacts_filter_add_str(filter_top, prop_id, CONTACTS_MATCH_ENDSWITH, e_val.c_str());
+    }
+    else if (!is_i_val_null && !is_e_val_null) {
+      contacts_filter_add_str(sub_filter, prop_id, CONTACTS_MATCH_STARTSWITH, i_val.c_str());
+      contacts_filter_add_operator(sub_filter, CONTACTS_FILTER_OPERATOR_AND);
+      contacts_filter_add_str(sub_filter, prop_id, CONTACTS_MATCH_ENDSWITH, e_val.c_str());
+      contacts_filter_add_filter(filter_top, sub_filter);
+    }
+  }
+  else {
+    int i_val_int = atoi(i_val.c_str());
+    int e_val_int = atoi(e_val.c_str());
+
+    if (!is_i_val_null && is_e_val_null) {
+      contacts_filter_add_int(filter_top, prop_id,
+                              CONTACTS_MATCH_GREATER_THAN_OR_EQUAL, i_val_int);
+    }
+    else if (is_i_val_null && !is_e_val_null) {
+      contacts_filter_add_int(filter_top, prop_id, CONTACTS_MATCH_LESS_THAN, e_val_int);
+    }
+    else if (!is_i_val_null && !is_e_val_null) {
+      contacts_filter_add_int(sub_filter, prop_id,
+                              CONTACTS_MATCH_GREATER_THAN_OR_EQUAL, i_val_int);
+      contacts_filter_add_operator(sub_filter, CONTACTS_FILTER_OPERATOR_AND);
+      contacts_filter_add_int(sub_filter, prop_id, CONTACTS_MATCH_LESS_THAN, e_val_int);
+      contacts_filter_add_filter(filter_top, sub_filter);
+    }
+  }
+  contacts_filter_destroy(sub_filter);
+}
+
+static void generateFilter(std::stack<contacts_filter_h>& stack,
+                           const picojson::object filter,
+                           CompositeTypeEnum type)
+{
+  LoggerD("Entered");
+  switch (getFilterType(filter)) {
+    case FILTER_ATTRIBUTE: {
+      visitAttribute(stack, filter);
+      if (type != NONE) {
+        contacts_filter_h top_filter = stack.top();
+        if (type == UNION) {
+          contacts_filter_add_operator(top_filter, CONTACTS_FILTER_OPERATOR_OR);
+        } else {
+          contacts_filter_add_operator(top_filter, CONTACTS_FILTER_OPERATOR_AND);
+        }
+      }
+    }
+    break;
+    case FILTER_ATTRIBUTE_RANGE: {
+      visitAttributeRange(stack, filter);
+      if (type != NONE) {
+        contacts_filter_h top_filter = stack.top();
+        if (type == UNION) {
+          contacts_filter_add_operator(top_filter, CONTACTS_FILTER_OPERATOR_OR);
+        } else {
+          contacts_filter_add_operator(top_filter, CONTACTS_FILTER_OPERATOR_AND);
+        }
+      }
+    }
+    break;
+    case FILTER_COMPOSITE: {
+      contacts_filter_h contact_filter = NULL;
+      contacts_filter_create(_contacts_phone_log._uri, &contact_filter);
+      if (contact_filter != NULL) {
+        stack.push(contact_filter);
+      }
+
+      CompositeTypeEnum composite_type = getCompositeType(filter);
+      const picojson::array& filters =
+          filter.find("filters")->second.get<picojson::array>();
+
+      for (auto it = filters.begin(); it != filters.end(); ++it) {
+        generateFilter(stack, it->get<picojson::object>(), composite_type);
+      }
+
+      contacts_filter_h top_filter = stack.top();
+      if (stack.size() > 1) {
+        stack.pop();
+        contacts_filter_h parent_filter = stack.top();
+        contacts_filter_add_filter(parent_filter, top_filter);
+        contacts_filter_destroy(top_filter);
+      }
+    }
+    break;
+    case FILTER_UNKNOWN:
+      return;
+      break;
+  }
+}
+
+void CallHistoryUtils::createFilter(contacts_filter_h filter, const picojson::object filter_obj)
+{
+  LoggerD("Entered");
+  std::stack<contacts_filter_h> filter_stack;
+  filter_stack.push(filter);
+  generateFilter(filter_stack, filter_obj, CompositeTypeEnum::NONE);
+}
+
+} // namespace callhistory
+} // namespace extension
diff --git a/webWidgetTCT_device/src/callhistory/callhistory_utils.h b/webWidgetTCT_device/src/callhistory/callhistory_utils.h
new file mode 100755 (executable)
index 0000000..9c9699c
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2015 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 CALLHISTORY_CALLHISTORY_UTILS_H_
+#define CALLHISTORY_CALLHISTORY_UTILS_H_
+
+#include <contacts.h>
+#include <contacts_internal.h>
+
+#include "common/picojson.h"
+
+namespace extension {
+namespace callhistory {
+
+class CallHistory;
+
+class CallHistoryUtils {
+ public:
+  explicit CallHistoryUtils(CallHistory& history);
+
+  void parseRecordList(contacts_list_h *record_list, picojson::array& array);
+  void parseRecord(contacts_record_h *record, picojson::object& obj);
+  void parseLogType(contacts_phone_log_type_e log_type, picojson::object& obj);
+  void parseRemoteParties(contacts_record_h *record, picojson::object& obj);
+  void parseCallingParty(contacts_record_h *record, picojson::object& obj);
+  unsigned int convertAttributeName(const std::string& attribute_name);
+  void createFilter(contacts_filter_h filter, const picojson::object filter_obj);
+
+ private:
+  CallHistory& history_;
+};
+
+} // namespace callhistory
+} // namespace extension
+
+#endif // CALLHISTORY_CALLHISTORY_UTILS_H_
diff --git a/webWidgetTCT_device/src/common/GDBus/connection.cpp b/webWidgetTCT_device/src/common/GDBus/connection.cpp
new file mode 100755 (executable)
index 0000000..c5a115d
--- /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.
+//
+
+#include "common/GDBus/connection.h"
+#include "common/logger.h"
+#include <cstring>
+
+namespace common {
+namespace dbus {
+
+Connection& Connection::getInstance()
+{
+    LoggerD("Entered");
+    static Connection instance;
+    return instance;
+}
+
+GDBusConnection* Connection::getDBus()
+{
+    return m_dbus;
+}
+
+Connection::Connection()
+{
+    m_dbus = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &m_error);
+    if (!m_dbus || m_error) {
+        LoggerE("Could not get connection");
+    }
+    LoggerD("Connection set");
+}
+
+Connection::~Connection()
+{
+    g_object_unref(m_dbus);
+}
+
+} //namespace dbus
+} //namespace common
diff --git a/webWidgetTCT_device/src/common/GDBus/connection.h b/webWidgetTCT_device/src/common/GDBus/connection.h
new file mode 100755 (executable)
index 0000000..29475fb
--- /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_DBUS_CONNECTION_H__
+#define __TIZEN_DBUS_CONNECTION_H__
+
+#include <gio/gio.h>
+
+namespace common {
+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 common
+
+#endif
diff --git a/webWidgetTCT_device/src/common/GDBus/proxy.cpp b/webWidgetTCT_device/src/common/GDBus/proxy.cpp
new file mode 100755 (executable)
index 0000000..4f6eedd
--- /dev/null
@@ -0,0 +1,142 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT 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 "common/GDBus/proxy.h"
+#include "common/logger.h"
+#include "common/platform_result.h"
+#include <cstring>
+
+namespace common {
+namespace dbus {
+
+using namespace common;
+
+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)
+{
+    LoggerD("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());
+    LoggerD("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);
+}
+
+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) {
+        LoggerW("Proxy is null, nothing to do");
+        return;
+    }
+
+    //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
+    //LoggerD("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);
+}
+
+void Proxy::signalSubscribe()
+{
+    if(m_dbus_signal_subscribed) {
+        LoggerW("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);
+    LoggerD("g_dbus_connection_signal_subscribe returned id: %d", m_sub_id);
+
+    m_dbus_signal_subscribed = true;
+}
+
+void Proxy::signalUnsubscribe()
+{
+    if (!m_dbus_signal_subscribed) {
+        LoggerW("Proxy hasn't subscribed for listening DBus signal");
+        return;
+    }
+
+    g_dbus_connection_signal_unsubscribe(m_conn.getDBus(), m_sub_id);
+    LoggerD("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 common
diff --git a/webWidgetTCT_device/src/common/GDBus/proxy.h b/webWidgetTCT_device/src/common/GDBus/proxy.h
new file mode 100755 (executable)
index 0000000..ed00283
--- /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        Proxy.h
+ */
+
+#ifndef __TIZEN_DBUS_PROXY_H__
+#define __TIZEN_DBUS_PROXY_H__
+
+#include "common/GDBus/connection.h"
+#include <memory>
+#include <string>
+#include <mutex>
+#include <map>
+#include "common/callback_user_data.h"
+#include "common/picojson.h"
+#include "common/platform_result.h"
+
+namespace common {
+namespace dbus {
+
+
+class Proxy;
+typedef std::shared_ptr<Proxy> ProxyPtr;
+
+/**
+ * This is generic dbus signal listener proxy.
+ */
+class Proxy {
+public:
+
+    virtual ~Proxy();
+    bool isNotProxyGot() { return !m_proxy || m_error; };
+
+    void signalSubscribe();
+    void signalUnsubscribe();
+
+    const std::string& getSignalName() const;
+    const std::string& getSignalPath() const;
+    const std::string& getSignalInterfaceName() const;
+
+protected:
+    /**
+     * @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);
+    /**
+     * 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 common
+
+#endif // __TIZEN_DBUS_PROXY_H__
diff --git a/webWidgetTCT_device/src/common/XW_Extension.cc b/webWidgetTCT_device/src/common/XW_Extension.cc
new file mode 100755 (executable)
index 0000000..7517791
--- /dev/null
@@ -0,0 +1,73 @@
+// Copyright (c) 2013 Intel Corporation. All rights reserved.
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file is compiled into each plugin, hence its size should be minimized.
+
+#include "common/extension.h"
+#include "common/assert.h"
+#include "common/logger.h"
+
+namespace {
+
+common::Extension* g_extension = nullptr;
+
+} // namespace
+
+namespace common {
+
+Extension* GetCurrentExtension() {
+  Assert(g_extension);
+  return g_extension;
+}
+
+class Extension::Detail {
+ private:
+  friend int32_t (::XW_Initialize)(XW_Extension extension,
+                                   XW_GetInterface get_interface);
+
+  static int32_t XW_Initialize(XW_Extension extension, XW_GetInterface get_interface);
+
+  // XW_Extension callbacks.
+  static void OnInstanceCreated(XW_Instance xw_instance);
+  static void OnShutdown(XW_Extension);
+};
+
+int32_t Extension::Detail::XW_Initialize(XW_Extension extension, XW_GetInterface get_interface) {
+  LoggerD("Enter");
+  g_extension = CreateExtension();
+  if (!g_extension) {
+    LoggerE("Can't initialize extension: CreateExtension() returned NULL.");
+    return XW_ERROR;
+  }
+  return XW_OK;
+}
+
+void Extension::Detail::OnInstanceCreated(XW_Instance xw_instance) {
+  LoggerD("Enter");
+  if (!g_extension) {
+    return;
+  }
+  Instance* instance = g_extension->CreateInstance();
+  if (!instance) {
+    return;
+  }
+  Extension::OnInstanceCreated(xw_instance, instance);
+}
+
+void Extension::Detail::OnShutdown(XW_Extension) {
+  LoggerD("Enter");
+  delete g_extension;
+  g_extension = nullptr;
+}
+
+} // namespace common
+
+// Entry point for CrossWalk plugin
+extern "C" int32_t XW_Initialize(XW_Extension extension, XW_GetInterface get_interface) {
+  return common::Extension::XW_Initialize(extension, get_interface,
+                                          common::Extension::Detail::XW_Initialize,
+                                          common::Extension::Detail::OnInstanceCreated,
+                                          common::Extension::Detail::OnShutdown);
+}
diff --git a/webWidgetTCT_device/src/common/XW_Extension.h b/webWidgetTCT_device/src/common/XW_Extension.h
new file mode 100755 (executable)
index 0000000..4543b92
--- /dev/null
@@ -0,0 +1,186 @@
+// Copyright (c) 2013 Intel Corporation. All rights reserved.
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_H_
+#define XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_H_
+
+// Crosswalk Extensions are modules of code loaded by Crosswalk runtime that
+// allow extending its capabilities. The extension is expected to define a
+// XW_Initialize() function as declared below, get the interfaces it need to
+// use and register to whatever callbacks it needs, then return XW_OK.
+//
+// The Extension is represented by the type XW_Extension. Each extension
+// loaded may be used multiple times for different pages, so to each execution
+// there will be an associated XW_Instance. A reasonable analogy is that the
+// XW_Extension represent a "class", and have concrete instances running.
+//
+// An interface is a struct with a set of functions, provided by Crosswalk,
+// that allow the extension code to interact with the web content. Certain
+// functions in an interface are used to register callbacks, so that Crosswalk
+// can call the extension at specific situations.
+//
+// Crosswalk won't call an extension's XW_Initialize() multiple times in the
+// same process.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if __GNUC__ >= 4
+#define XW_EXPORT __attribute__ ((visibility("default")))
+#elif defined(_MSC_VER)
+#define XW_EXPORT __declspec(dllexport)
+#endif
+
+#include <stdint.h>
+
+
+// XW_Extension is used to identify your extension when calling functions from
+// the API. You should always use the XW_Extension received at XW_Initialize().
+//
+// XW_Instance is used to identify different web contents using your
+// extension. Each time a new web content is created you can be notified
+// registering the XW_CreatedInstanceCallback, that receives the new
+// XW_Instance. When interacting with an Instance (for example to post a
+// message), you should pass the corresponding XW_Instance.
+//
+// In both types the zero value is never used by Crosswalk, so can be used to
+// initialize variables.
+typedef int32_t XW_Extension;
+typedef int32_t XW_Instance;
+
+enum {
+  XW_OK = 0,
+  XW_ERROR = -1
+};
+
+// Returns a struct containing functions to be used by the extension. Those
+// structs can be stored statically and used until the extension is unloaded.
+// Extensions should use definitions like XW_CORE_INTERFACE, instead of using
+// the versioned definition or the literal string. Returns NULL if the
+// interface is not supported.
+typedef const void* (*XW_GetInterface)(const char* interface_name);
+
+
+typedef int32_t (*XW_Initialize_Func)(XW_Extension extension,
+                                      XW_GetInterface get_interface);
+
+// XW_Initialize is called after the extension code is loaded. The 'extension'
+// value should be used in further calls that expect XW_Extension argument.
+//
+// The 'get_interface' function should be used to get access to functions that
+// interact with the web content. It is only valid during the execution of the
+// XW_Initialize() function.
+//
+// This function should return XW_OK when the extension was succesfully
+// loaded, otherwise XW_ERROR.
+XW_EXPORT int32_t XW_Initialize(XW_Extension extension,
+                                XW_GetInterface get_interface);
+
+
+//
+// XW_CORE_INTERFACE: Basic functionality for Crosswalk Extensions. All
+// extensions should use this interface to set at least their name.
+//
+
+#define XW_CORE_INTERFACE_1 "XW_CoreInterface_1"
+#define XW_CORE_INTERFACE XW_CORE_INTERFACE_1
+
+typedef void (*XW_CreatedInstanceCallback)(XW_Instance instance);
+typedef void (*XW_DestroyedInstanceCallback)(XW_Instance instance);
+typedef void (*XW_ShutdownCallback)(XW_Extension extension);
+
+struct XW_CoreInterface_1 {
+  // Set the name of the extension. It is used as the namespace for the
+  // JavaScript code exposed by the extension. So extension named
+  // 'my_extension', will expose its JavaScript functionality inside
+  // the 'my_extension' namespace.
+  //
+  // This function should be called only during XW_Initialize().
+  void (*SetExtensionName)(XW_Extension extension, const char* name);
+
+  // Set the JavaScript code loaded in the web content when the extension is
+  // used. This can be used together with the messaging mechanism to implement
+  // a higher-level API that posts messages to extensions, see
+  // XW_MESSAGING_INTERFACE below.
+  //
+  // The code will be executed inside a JS function context with the following
+  // objects available:
+  //
+  // - exports: this object should be filled with properties and functions
+  //            that will be exposed in the namespace associated with this
+  //            extension.
+  //
+  // - extension.postMessage(): post a string message to the extension native
+  //                            code. See below for details.
+  // - extension.setMessageListener(): allow setting a callback that is called
+  //                                   when the native code sends a message
+  //                                   to JavaScript. Callback takes a string.
+  //
+  // This function should be called only during XW_Initialize().
+  void (*SetJavaScriptAPI)(XW_Extension extension, const char* api);
+
+  // Register callbacks that are called when an instance of this extension
+  // is created or destroyed. Everytime a new web content is loaded, it will
+  // get a new associated instance.
+  //
+  // This function should be called only during XW_Initialize().
+  void (*RegisterInstanceCallbacks)(XW_Extension extension,
+                                    XW_CreatedInstanceCallback created,
+                                    XW_DestroyedInstanceCallback destroyed);
+
+  // Register a callback to be executed when the extension will be unloaded.
+  //
+  // This function should be called only during XW_Initialize().
+  void (*RegisterShutdownCallback)(XW_Extension extension,
+                                   XW_ShutdownCallback shutdown_callback);
+
+  // These two functions are conveniences used to associated arbitrary data
+  // with a given XW_Instance. They can be used only with instances that were
+  // created but not yet completely destroyed. GetInstanceData() can be used
+  // during the destroyed instance callback. If not instance data was set,
+  // getting it returns NULL.
+  void (*SetInstanceData)(XW_Instance instance, void* data);
+  void* (*GetInstanceData)(XW_Instance instance);
+};
+
+typedef struct XW_CoreInterface_1 XW_CoreInterface;
+
+
+//
+// XW_MESSAGING_INTERFACE: Exchange asynchronous messages with JavaScript
+// code provided by extension.
+//
+
+#define XW_MESSAGING_INTERFACE_1 "XW_MessagingInterface_1"
+#define XW_MESSAGING_INTERFACE XW_MESSAGING_INTERFACE_1
+
+typedef void (*XW_HandleMessageCallback)(XW_Instance instance,
+                                         const char* message);
+
+struct XW_MessagingInterface_1 {
+  // Register a callback to be called when the JavaScript code associated
+  // with the extension posts a message. Note that the callback will be called
+  // with the XW_Instance that posted the message as well as the message
+  // contents.
+  void (*Register)(XW_Extension extension,
+                   XW_HandleMessageCallback handle_message);
+
+  // Post a message to the web content associated with the instance. To
+  // receive this message the extension's JavaScript code should set a
+  // listener using extension.setMessageListener() function.
+  //
+  // This function is thread-safe and can be called until the instance is
+  // destroyed.
+  void (*PostMessage)(XW_Instance instance, const char* message);
+};
+
+typedef struct XW_MessagingInterface_1 XW_MessagingInterface;
+
+#ifdef __cplusplus
+}  // extern "C"
+#endif
+
+#endif  // XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_H_
diff --git a/webWidgetTCT_device/src/common/XW_Extension_Data.h b/webWidgetTCT_device/src/common/XW_Extension_Data.h
new file mode 100755 (executable)
index 0000000..c1b55de
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2015 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 XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_DATA_H_
+#define XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_DATA_H_
+
+#ifndef XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_H_
+#error "You should include XW_Extension.h before this file"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//
+// XW_INTERNAL_DATA_INTERFACE: allow extensions to exchange binary chunk data
+// between extension and loader.
+//
+
+#define XW_INTERNAL_DATA_INTERFACE_1 \
+  "XW_InternalDataInterface_1"
+#define XW_INTERNAL_DATA_INTERFACE \
+  XW_INTERNAL_DATA_INTERFACE_1
+
+// Synchronous / Asynchronous data exchanging interface
+typedef void (*XW_HandleDataCallback)(XW_Instance instance,
+                                      const char* message,
+                                      uint8_t* buffer, size_t len);
+
+struct XW_Internal_DataInterface_1 {
+  void (*RegisterSync)(XW_Extension extension,
+                       XW_HandleDataCallback handle_data);
+
+  void (*RegisterAsync)(XW_Extension extension,
+                        XW_HandleDataCallback handle_data);
+
+  void (*SetSyncReply)(XW_Instance instance, const char* reply,
+                       uint8_t* buffer, size_t len);
+
+  void (*PostData)(XW_Instance instance, const char* message,
+                   uint8_t* buffer, size_t len);
+};
+
+typedef struct XW_Internal_DataInterface_1
+    XW_Internal_DataInterface;
+
+#ifdef __cplusplus
+}  // extern "C"
+#endif
+
+#endif  // XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_DATA_H_
diff --git a/webWidgetTCT_device/src/common/XW_Extension_EntryPoints.h b/webWidgetTCT_device/src/common/XW_Extension_EntryPoints.h
new file mode 100755 (executable)
index 0000000..b8a3ef4
--- /dev/null
@@ -0,0 +1,50 @@
+// Copyright (c) 2013 Intel Corporation. All rights reserved.
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_ENTRYPOINTS_H_
+#define XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_ENTRYPOINTS_H_
+
+// NOTE: This file and interfaces marked as internal are not considered stable
+// and can be modified in incompatible ways between Crosswalk versions.
+
+#ifndef XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_H_
+#error "You should include XW_Extension.h before this file"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define XW_INTERNAL_ENTRY_POINTS_INTERFACE_1 \
+  "XW_Internal_EntryPointsInterface_1"
+#define XW_INTERNAL_ENTRY_POINTS_INTERFACE \
+  XW_INTERNAL_ENTRY_POINTS_INTERFACE_1
+
+//
+// XW_INTERNAL_ENTRY_POINTS_INTERFACE: provides a way for extensions to add
+// more information about its implementation. For now, allow extensions to
+// specify more objects that the access should cause the extension to be
+// loaded.
+//
+
+struct XW_Internal_EntryPointsInterface_1 {
+  // Register extra entry points for this extension. An "extra" entry points
+  // are objects outside the implicit namespace for which the extension should
+  // be loaded when they are touched.
+  //
+  // This function should be called only during XW_Initialize().
+  void (*SetExtraJSEntryPoints)(XW_Extension extension,
+                                const char** entry_points);
+};
+
+typedef struct XW_Internal_EntryPointsInterface_1
+    XW_Internal_EntryPointsInterface;
+
+#ifdef __cplusplus
+}  // extern "C"
+#endif
+
+#endif  // XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_ENTRYPOINTS_H_
+
diff --git a/webWidgetTCT_device/src/common/XW_Extension_Permissions.h b/webWidgetTCT_device/src/common/XW_Extension_Permissions.h
new file mode 100755 (executable)
index 0000000..781e3a9
--- /dev/null
@@ -0,0 +1,42 @@
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_PERMISSIONS_H_
+#define XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_PERMISSIONS_H_
+
+// NOTE: This file and interfaces marked as internal are not considered stable
+// and can be modified in incompatible ways between Crosswalk versions.
+
+#ifndef XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_H_
+#error "You should include XW_Extension.h before this file"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define XW_INTERNAL_PERMISSIONS_INTERFACE_1 \
+    "XW_Internal_PermissionsInterface_1"
+#define XW_INTERNAL_PERMISSIONS_INTERFACE \
+    XW_INTERNAL_PERMISSIONS_INTERFACE_1
+
+//
+// XW_INTERNAL_PERMISSIONS_INTERFACE: provides a way for extensions
+// check if they have the proper permissions for certain APIs.
+//
+
+struct XW_Internal_PermissionsInterface_1 {
+  int (*CheckAPIAccessControl)(XW_Extension extension, const char* api_name);
+  int (*RegisterPermissions)(XW_Extension extension, const char* perm_table);
+};
+
+typedef struct XW_Internal_PermissionsInterface_1
+    XW_Internal_PermissionsInterface;
+
+#ifdef __cplusplus
+}  // extern "C"
+#endif
+
+#endif  // XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_PERMISSIONS_H_
diff --git a/webWidgetTCT_device/src/common/XW_Extension_Runtime.h b/webWidgetTCT_device/src/common/XW_Extension_Runtime.h
new file mode 100755 (executable)
index 0000000..1c33557
--- /dev/null
@@ -0,0 +1,45 @@
+// Copyright (c) 2013 Intel Corporation. All rights reserved.
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_RUNTIME_H_
+#define XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_RUNTIME_H_
+
+// NOTE: This file and interfaces marked as internal are not considered stable
+// and can be modified in incompatible ways between Crosswalk versions.
+
+#ifndef XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_H_
+#error "You should include XW_Extension.h before this file"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define XW_INTERNAL_RUNTIME_INTERFACE_1 \
+  "XW_Internal_RuntimeInterface_1"
+#define XW_INTERNAL_RUNTIME_INTERFACE \
+  XW_INTERNAL_RUNTIME_INTERFACE_1
+
+//
+// XW_INTERNAL_RUNTIME_INTERFACE: allow extensions to gather information
+// from the runtime.
+//
+
+struct XW_Internal_RuntimeInterface_1 {
+  void (*GetRuntimeVariableString)(XW_Extension extension,
+                                   const char* key,
+                                   char* value,
+                                   size_t value_len);
+};
+
+typedef struct XW_Internal_RuntimeInterface_1
+    XW_Internal_RuntimeInterface;
+
+#ifdef __cplusplus
+}  // extern "C"
+#endif
+
+#endif  // XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_RUNTIME_H_
+
diff --git a/webWidgetTCT_device/src/common/XW_Extension_SyncMessage.h b/webWidgetTCT_device/src/common/XW_Extension_SyncMessage.h
new file mode 100755 (executable)
index 0000000..caa46df
--- /dev/null
@@ -0,0 +1,49 @@
+// Copyright (c) 2013 Intel Corporation. All rights reserved.
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_SYNCMESSAGE_H_
+#define XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_SYNCMESSAGE_H_
+
+// NOTE: This file and interfaces marked as internal are not considered stable
+// and can be modified in incompatible ways between Crosswalk versions.
+
+#ifndef XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_H_
+#error "You should include XW_Extension.h before this file"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//
+// XW_INTERNAL_SYNC_MESSAGING_INTERFACE: allow JavaScript code to send a
+// synchronous message to extension code and block until response is
+// available. The response is made available by calling the SetSyncReply
+// function, that can be done from outside the context of the SyncMessage
+// handler.
+//
+
+#define XW_INTERNAL_SYNC_MESSAGING_INTERFACE_1 \
+  "XW_InternalSyncMessagingInterface_1"
+#define XW_INTERNAL_SYNC_MESSAGING_INTERFACE \
+  XW_INTERNAL_SYNC_MESSAGING_INTERFACE_1
+
+typedef void (*XW_HandleSyncMessageCallback)(XW_Instance instance,
+                                             const char* message);
+
+struct XW_Internal_SyncMessagingInterface_1 {
+  void (*Register)(XW_Extension extension,
+                   XW_HandleSyncMessageCallback handle_sync_message);
+  void (*SetSyncReply)(XW_Instance instance, const char* reply);
+};
+
+typedef struct XW_Internal_SyncMessagingInterface_1
+    XW_Internal_SyncMessagingInterface;
+
+#ifdef __cplusplus
+}  // extern "C"
+#endif
+
+#endif  // XWALK_EXTENSIONS_PUBLIC_XW_EXTENSION_SYNCMESSAGE_H_
diff --git a/webWidgetTCT_device/src/common/assert.h b/webWidgetTCT_device/src/common/assert.h
new file mode 100755 (executable)
index 0000000..1e0fd39
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015 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 COMMON_ASSERT_H_
+#define COMMON_ASSERT_H_
+
+#include <cassert>
+
+#include "common/logger.h"
+
+#define AssertMsg(condition, message)                                          \
+  do {                                                                         \
+    std::string msg(message);                                                  \
+    if (!(condition))                                                          \
+      LoggerE("assert(%s)%s", #condition,                                      \
+            !msg.empty() ? std::string(", message: " + msg).c_str() : "");     \
+    assert(!!(condition) && message);                                          \
+  } while(0)
+
+#define Assert(condition) AssertMsg(condition, "")
+
+#endif  // COMMON_ASSERT_H_
diff --git a/webWidgetTCT_device/src/common/callback_user_data.cc b/webWidgetTCT_device/src/common/callback_user_data.cc
new file mode 100755 (executable)
index 0000000..266cbee
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2015 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 "common/callback_user_data.h"
+
+namespace common {
+
+CallbackUserData::CallbackUserData() :
+    m_is_act(true) {
+}
+
+CallbackUserData::~CallbackUserData() {
+}
+
+void CallbackUserData::setActive(bool act) {
+  m_is_act = act;
+}
+
+bool CallbackUserData::isActive() const {
+  return m_is_act;
+}
+
+void CallbackUserData::setJson(std::shared_ptr<picojson::value> json) {
+  m_json = json;
+}
+
+std::shared_ptr<picojson::value> CallbackUserData::getJson() const {
+  return m_json;
+}
+
+}  // common
diff --git a/webWidgetTCT_device/src/common/callback_user_data.h b/webWidgetTCT_device/src/common/callback_user_data.h
new file mode 100755 (executable)
index 0000000..26bed79
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+// Class added for backward compatibility with WRT plugins.
+// TODO To be cleaned/replaced in the future.
+
+#ifndef COMMON_CALLBACK_USER_DATA_H_
+#define COMMON_CALLBACK_USER_DATA_H_
+
+#include "common/picojson.h"
+
+#include <memory>
+
+namespace common {
+
+class CallbackUserData {
+public:
+  CallbackUserData();
+
+  virtual ~CallbackUserData();
+
+  void setActive(bool act);
+  bool isActive() const;
+
+  void setJson(std::shared_ptr<picojson::value> json);
+  std::shared_ptr<picojson::value> getJson() const;
+
+  virtual void setError(const std::string& err_name,
+                        const std::string& err_message) = 0;
+
+protected:
+  std::shared_ptr<picojson::value> m_json;
+
+private:
+  bool m_is_act;
+};
+
+} // common
+
+#endif  // COMMON_CALLBACK_USER_DATA_H_
diff --git a/webWidgetTCT_device/src/common/common.gyp b/webWidgetTCT_device/src/common/common.gyp
new file mode 100755 (executable)
index 0000000..18edfda
--- /dev/null
@@ -0,0 +1,132 @@
+{
+  'includes':[
+    '../common/common.gypi',
+  ],
+  'targets': [
+    {
+      'target_name': 'tizen_common',
+      'type': 'loadable_module',
+      'sources': [
+        'converter.cc',
+        'converter.h',
+        'current_application.cc',
+        'current_application.h',
+        'extension.cc',
+        'extension.h',
+        'filter-utils.cc',
+        'filter-utils.h',
+        'picojson.h',
+        'utils.h',
+        'logger.cc',
+        'logger.h',
+        'platform_exception.cc',
+        'platform_exception.h',
+        'dbus_operation.cc',
+        'dbus_operation.h',
+        'XW_Extension.h',
+        'XW_Extension_EntryPoints.h',
+        'XW_Extension_Permissions.h',
+        'XW_Extension_Runtime.h',
+        'XW_Extension_SyncMessage.h',
+        'scope_exit.h',
+        'task-queue.cpp',
+        'task-queue.h',
+        'tools.cc',
+        'tools.h',
+        'callback_user_data.cc',
+        'callback_user_data.h',
+        'optional.h',
+        'platform_result.cc',
+        'platform_result.h',
+        'assert.h',
+        'video_source_types.cc',
+        'video_source_types.h',
+        'tvsapi_subscribe_helper.h',
+        'tvsapi_subscribe_helper.cc',
+        'GDBus/connection.cpp',
+        'GDBus/connection.h',
+        'GDBus/proxy.cpp',
+        'GDBus/proxy.h',
+        'filesystem/storage.h',
+        'filesystem/storage.cc',
+        'filesystem/filesystem_provider.h',
+        'filesystem/filesystem_provider.cc',
+        'filesystem/deviced.h',
+        'filesystem/deviced.cc',
+        'filesystem/filesystem_provider_capiusb.cc',
+        'filesystem/filesystem_provider_capiusb.h',
+        'filesystem/filesystem_provider_storage.h',
+        'filesystem/filesystem_provider_storage.cc',
+      ],
+      'cflags': [
+        '-fvisibility=default',
+      ],
+      'conditions': [
+        ['tizen == 1', {
+          'variables': {
+            'packages': [
+              'capi-appfw-app-manager',
+              'capi-appfw-package-manager',
+              'storage',
+            ]
+          },
+          'conditions': [
+            ['privilege_engine == "DB"', {
+              'defines': ['PRIVILEGE_USE_DB'],
+              'variables': {
+                'packages': [
+                  'sqlite3',
+                ],
+              },
+            }],
+            ['privilege_engine == "ACE"', {
+              'defines': ['PRIVILEGE_USE_ACE'],
+              'variables': {
+                'packages': [
+                  'security-privilege-checker',
+                ],
+              },
+            }],
+            ['privilege_engine == "CYNARA"', {
+              'defines': ['PRIVILEGE_USE_CYNARA'],
+              'variables': {
+                'packages': [
+                  'cynara-client',
+                  'libsmack',
+                ],
+              },
+            }],
+            ['tizen_tv_product == 1', {
+              'variables': {
+                'packages': [
+                  'tvs-api',
+                  'capi-system-usbdevice'
+                ],
+              },
+            }],
+          ],
+        }],
+        ['tizen_tv_product != 1', {
+            'sources!' : [
+            'filesystem/filesystem_provider_capiusb.cc',
+            'filesystem/filesystem_provider_capiusb.h',
+            'video_source_types.h',
+            'video_source_types.cc',
+            'tvsapi_subscribe_helper.h',
+            'tvsapi_subscribe_helper.cc',
+            ],
+        }],
+      ],
+      'direct_dependent_settings': {
+        'libraries' : [
+          '-ltizen_common',
+        ],
+        'variables': {
+          'packages': [
+            'storage',
+          ],
+        },
+      },
+    },
+  ],
+}
diff --git a/webWidgetTCT_device/src/common/common.gypi b/webWidgetTCT_device/src/common/common.gypi
new file mode 100755 (executable)
index 0000000..2d6b8eb
--- /dev/null
@@ -0,0 +1,92 @@
+{
+  'variables': {
+    'extension_host_os%': 'desktop',
+    'tizen%': '0',
+    'extension_build_type%': '<(extension_build_type)',
+    'extension_build_type%': 'Debug',
+    'display_type%': 'x11',
+    'tizen_tv_product%': '1',
+  },
+  'target_defaults': {
+    'conditions': [
+      ['extension_host_os != "mobile"', {
+        'sources/': [['exclude', '_mobile\\.cc$|mobile/']],
+        'includes/': [['exclude', '_mobile\\.gypi$|mobile/']],
+      }],
+      ['extension_host_os != "wearable"', {
+        'sources/': [['exclude', '_wearable\\.cc$|wearable/']],
+        'includes/': [['exclude', '_wearable\\.gypi$|wearable/']],
+      }],
+      ['extension_host_os != "tv"', {
+        'sources/': [['exclude', '_tv\\.cc$|tv/']],
+        'includes/': [['exclude', '_tv\\.gypi$|tv/']],
+      }],
+      ['extension_host_os != "desktop"', {
+        'sources/': [['exclude', '_desktop\\.cc$|desktop/']],
+        'includes/': [['exclude', '_desktop\\.gypi$|desktop/']],
+      }],
+      ['tizen == 1', {
+        'defines': ['TIZEN'],
+        'variables': {
+          'packages': [
+            'dlog',
+            'glib-2.0',
+          ]
+        },
+      }, {
+        'sources/': [['exclude', '_tizen\\.cc$|tizen/']],
+        'includes/': [['exclude', '_tizen\\.gypi$|tizen/']],
+      }],
+      ['extension_host_os == "tv"', { 'defines': ['TIZEN_TV'] } ],
+      ['tizen_tv_product == 1', { 'defines': ['TIZEN_TV_PRODUCT'] } ],
+      ['extension_host_os == "wearable"', { 'defines': ['TIZEN_WEARABLE'] } ],
+      ['extension_host_os == "mobile"', { 'defines': ['TIZEN_MOBILE'] } ],
+      ['extension_host_os == "ivi"', { 'defines': ['TIZEN_IVI'] } ],
+      ['extension_host_os == "desktop"', { 'defines': ['GENERIC_DESKTOP'] } ],
+      ['extension_build_type== "Debug"', {
+        'defines': ['_DEBUG', 'TIZEN_DEBUG_ENABLE', ],
+        'cflags': [ '-O0', '-g', ],
+      }],
+      ['extension_build_type == "Release"', {
+        'defines': ['NDEBUG', ],
+        'cflags': [
+          '-O2',
+          # Don't emit the GCC version ident directives, they just end up
+          # in the .comment section taking up binary size.
+          '-fno-ident',
+          # Put data and code in their own sections, so that unused symbols
+          # can be removed at link time with --gc-sections.
+          '-fdata-sections',
+          '-ffunction-sections',
+        ],
+      }],
+      [ 'display_type != "wayland"', {
+        'sources/': [['exclude', '_wayland\\.cc$|wayland/']],
+      }],
+      [ 'display_type != "x11"', {
+        'sources/': [['exclude', '_x11\\.cc$|x11/']],
+      }],
+    ],
+    'includes': [
+      'xwalk_js2c.gypi',
+      'pkg-config.gypi',
+    ],
+    'include_dirs': [
+      '../',
+      '<(SHARED_INTERMEDIATE_DIR)',
+    ],
+    'sources': [
+      'XW_Extension.cc',
+    ],
+    'cflags': [
+      '-std=c++0x',
+      '-fPIC',
+      '-fvisibility=hidden',
+      '-Wall',
+    ],
+    'libraries' : [
+      '-L .',
+      '-Wl,-rpath=/usr/lib/tizen-extensions-crosswalk',
+    ],
+  },
+}
diff --git a/webWidgetTCT_device/src/common/converter.cc b/webWidgetTCT_device/src/common/converter.cc
new file mode 100755 (executable)
index 0000000..edb62bf
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2015 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 "common/converter.h"
+#include "common/logger.h"
+#include <stdexcept>
+#include <string>
+
+namespace common {
+
+const picojson::value& FindValue(const picojson::object& in,
+                                     const char* name) {
+  LoggerD("Enter");
+  auto it = in.find(name);
+  if (it == in.end()) {
+    throw common::UnknownException(
+        std::string("Failed to find required JSON property: ") + name + ".");
+  }
+  return it->second;
+}
+
+long stol(const std::string& str, std::size_t* pos, int base) {
+  try {
+    return std::stol(str, pos, base);
+  }
+  catch (const std::invalid_argument& e) {
+    LoggerE("invalid_argument");
+    throw common::InvalidValuesException(e.what());
+  }
+  catch (const std::out_of_range& e) {
+    LoggerE("InvalidValuesException");
+    throw common::InvalidValuesException(e.what());
+  }
+}
+
+}  // webapi
diff --git a/webWidgetTCT_device/src/common/converter.h b/webWidgetTCT_device/src/common/converter.h
new file mode 100755 (executable)
index 0000000..1b9a30d
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2015 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 COMMON_CONVERTER_H_
+#define COMMON_CONVERTER_H_
+
+#include "common/picojson.h"
+#include "common/platform_exception.h"
+
+namespace common {
+
+// This is a wrapper around std::stol which throws exceptions from common rather
+// than std
+long stol(const std::string &str, std::size_t *pos = 0, int base = 10);
+
+const picojson::value &FindValue(const picojson::object &in, const char *name);
+
+inline bool IsNull(const picojson::value &in) {
+  return in.is<picojson::null>();
+}
+
+inline bool IsNull(const picojson::object &in, const char *name) {
+  return IsNull(FindValue(in, name));
+}
+
+template <typename T>
+const T &JsonCast(const picojson::value &in) {
+  if (!in.is<T>()) {
+    throw common::UnknownException(std::string("Invalid JSON type"));
+  }
+  return in.get<T>();
+}
+
+template <typename T>
+const T &FromJson(const picojson::object &in, const char *name) {
+  const picojson::value &v = FindValue(in, name);
+  return JsonCast<T>(v);
+}
+
+template <typename T, typename... Names>
+const T &FromJson(const picojson::object &in, const char *name,
+                  Names... names) {
+  const picojson::value &v = FindValue(in, name);
+  if (!v.is<picojson::object>()) {
+    throw common::UnknownException(
+        std::string("Invalid JSON type for property: ") + name + ".");
+  }
+  return FromJson<T>(v.get<picojson::object>(), names...);
+}
+
+}  // common
+
+#endif  // COMMON_CONVERTER_H_
diff --git a/webWidgetTCT_device/src/common/current_application.cc b/webWidgetTCT_device/src/common/current_application.cc
new file mode 100755 (executable)
index 0000000..85b60a7
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2015 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 "common/current_application.h"
+
+#include <app_manager.h>
+#include <package_manager.h>
+#include <unistd.h>
+
+#include "common/logger.h"
+#include "common/scope_exit.h"
+
+namespace common {
+
+CurrentApplication& CurrentApplication::GetInstance() {
+  LoggerD("Enter");
+  static CurrentApplication current_application;
+  return current_application;
+}
+
+pid_t CurrentApplication::GetProcessId() const {
+  LoggerD("Enter");
+  return pid_;
+}
+
+std::string CurrentApplication::GetApplicationId() const {
+  LoggerD("Enter");
+  return app_id_;
+}
+
+std::string CurrentApplication::GetPackageId() const {
+  LoggerD("Enter");
+  return package_id_;
+}
+
+std::string CurrentApplication::GetRoot() const {
+  return root_;
+}
+
+CurrentApplication::CurrentApplication() :
+    pid_(getpid()),
+    app_id_(FetchApplicationId()),
+    package_id_(FetchPackageId()),
+    root_(FetchRoot()) {
+  LoggerD("Enter");
+}
+
+std::string CurrentApplication::FetchApplicationId() const {
+  LoggerD("Enter");
+  std::string app_id;
+  char* tmp_str = nullptr;
+
+  const int ret = app_manager_get_app_id(pid_, &tmp_str);
+
+  if ((APP_MANAGER_ERROR_NONE == ret) && (nullptr != tmp_str)) {
+    app_id = tmp_str;
+  } else {
+    LoggerE("Failed to get application ID: %d (%s)", ret, get_error_message(ret));
+    app_id = "";
+  }
+
+  free(tmp_str);
+
+  return app_id;
+}
+
+std::string CurrentApplication::FetchPackageId() const {
+  LoggerD("Enter");
+  std::string package_id;
+  app_info_h app_info;
+  int err = app_info_create(app_id_.c_str(), &app_info);
+  if (APP_MANAGER_ERROR_NONE != err) {
+    LoggerE("Can't create app info handle from appId %s: %d (%s)",
+            app_id_.c_str(), err, get_error_message(err));
+    return "";
+  }
+  SCOPE_EXIT {
+    app_info_destroy(app_info);
+  };
+
+  char* package = nullptr;
+  err = app_info_get_package(app_info, &package);
+  if (APP_MANAGER_ERROR_NONE != err) {
+    LoggerE("Can't get package name from app info: %d (%s)",
+            err, get_error_message(err));
+    package_id = "";
+  } else {
+    package_id = package;
+  }
+
+  free(package);
+
+  return package_id;
+}
+
+std::string CurrentApplication::FetchRoot() const {
+  LoggerD("Enter");
+  package_info_h pkg_info;
+  int err = package_info_create(package_id_.c_str(), &pkg_info);
+  if (PACKAGE_MANAGER_ERROR_NONE != err) {
+    LoggerE("Can't create package info handle from pkg (%s)", get_error_message(err));
+    return nullptr;
+  }
+  SCOPE_EXIT {
+    package_info_destroy(pkg_info);
+  };
+
+  char* root_ = nullptr;
+  err = package_info_get_root_path(pkg_info, &root_);
+  if (PACKAGE_MANAGER_ERROR_NONE != err || nullptr == root_) {
+    LoggerE("Can't get root_ path from package info (%s)", get_error_message(err));
+    return nullptr;
+  }
+
+  std::string ret(root_);
+  free(root_);
+
+  LoggerD("Exit");
+  return ret;
+}
+
+}  // namespace common
diff --git a/webWidgetTCT_device/src/common/current_application.h b/webWidgetTCT_device/src/common/current_application.h
new file mode 100755 (executable)
index 0000000..9665881
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2015 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 COMMON_CURRENT_APPLICATION_H_
+#define COMMON_CURRENT_APPLICATION_H_
+
+#include <string>
+
+namespace common {
+
+class CurrentApplication {
+ public:
+  CurrentApplication(const CurrentApplication&) = delete;
+  CurrentApplication& operator=(const CurrentApplication&) = delete;
+
+  static CurrentApplication& GetInstance();
+  pid_t GetProcessId() const;
+  std::string GetApplicationId() const;
+  std::string GetPackageId() const;
+  std::string GetRoot() const;
+
+ private:
+  CurrentApplication();
+  std::string FetchApplicationId() const;
+  std::string FetchPackageId() const;
+  std::string FetchRoot() const;
+
+ private:
+  pid_t pid_;
+  std::string app_id_;
+  std::string package_id_;
+  std::string root_;
+};
+
+}  // namespace common
+
+#endif  // COMMON_CURRENT_APPLICATION_H_
diff --git a/webWidgetTCT_device/src/common/dbus_operation.cc b/webWidgetTCT_device/src/common/dbus_operation.cc
new file mode 100755 (executable)
index 0000000..3e027e6
--- /dev/null
@@ -0,0 +1,440 @@
+/*
+ * Copyright (c) 2015 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 "dbus_operation.h"
+
+#include <string>
+#include <sstream>
+#include <vector>
+#include <set>
+
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#include "logger.h"
+#include "platform_exception.h"
+
+#define DBUS_REPLY_TIMEOUT (-1)
+
+namespace common {
+
+DBusOperationArguments::DBusOperationArguments() {
+  LoggerD("Enter");
+}
+
+DBusOperationArguments::~DBusOperationArguments() {
+    LoggerD("Enter");
+    for (auto iter = arguments_.begin(); iter != arguments_.end(); ++iter) {
+        ArgType type = iter->first;
+        void* p_val = iter->second;
+
+        switch (type) {
+        case ArgType::kTypeBool:
+        case ArgType::kTypeInt32:
+            delete static_cast<int32_t *>(p_val);
+            break;
+
+        case ArgType::kTypeUInt32:
+            delete static_cast<uint32_t *>(p_val);
+            break;
+
+        case ArgType::kTypeUInt64:
+            delete static_cast<uint64_t *>(p_val);
+            break;
+
+        case ArgType::kTypeString:
+            delete[] static_cast<char *>(p_val);
+            break;
+
+        default:
+            LoggerE("invalid type");
+            break;
+        }
+    }
+
+    arguments_.clear();
+}
+
+void DBusOperationArguments::AddArgumentBool(bool val) {
+    LoggerD("Enter");
+    int32_t* p_val = new int32_t;
+    *p_val = val;
+
+    arguments_.push_back(ArgumentElement(ArgType::kTypeBool, p_val));
+}
+
+void DBusOperationArguments::AddArgumentInt32(int val) {
+    LoggerD("Enter");
+    int32_t* p_val = new int32_t;
+    *p_val = val;
+
+    arguments_.push_back(ArgumentElement(ArgType::kTypeInt32, p_val));
+}
+
+void DBusOperationArguments::AddArgumentUInt32(unsigned int val) {
+    LoggerD("Enter");
+    uint32_t* p_val = new uint32_t;
+    *p_val = val;
+
+    arguments_.push_back(ArgumentElement(ArgType::kTypeUInt32, p_val));
+}
+
+void DBusOperationArguments::AddArgumentUInt64(uint64_t val) {
+    LoggerD("Enter");
+    uint64_t* p_val = new uint64_t;
+    *p_val = val;
+
+    arguments_.push_back(ArgumentElement(ArgType::kTypeUInt64, p_val));
+}
+
+void DBusOperationArguments::AddArgumentString(const std::string& val) {
+    LoggerD("Enter");
+    const int length = val.length();
+
+    char* p_val = new char[length+1];
+    strncpy(p_val, val.c_str(), length+1); // TODO: is it safe?
+
+    arguments_.push_back(ArgumentElement(ArgType::kTypeString, p_val));
+}
+
+PlatformResult DBusOperationArguments::AppendVariant(DBusMessageIter* bus_msg_iter) {
+    LoggerD("Enter");
+    for (auto iter = arguments_.begin(); iter != arguments_.end(); ++iter) {
+        ArgType type = iter->first;
+        void *p_val = iter->second;
+
+        switch (type) {
+        case ArgType::kTypeBool:
+            dbus_message_iter_append_basic(bus_msg_iter, DBUS_TYPE_BOOLEAN, p_val);
+            break;
+
+        case ArgType::kTypeInt32:
+            dbus_message_iter_append_basic(bus_msg_iter, DBUS_TYPE_INT32, p_val);
+            break;
+
+        case ArgType::kTypeUInt32:
+            dbus_message_iter_append_basic(bus_msg_iter, DBUS_TYPE_UINT32, p_val);
+            break;
+
+        case ArgType::kTypeUInt64:
+            dbus_message_iter_append_basic(bus_msg_iter, DBUS_TYPE_UINT64, p_val);
+            break;
+
+        case ArgType::kTypeString:
+            dbus_message_iter_append_basic(bus_msg_iter, DBUS_TYPE_STRING, &p_val);
+            break;
+
+        default:
+            return PlatformResult(ErrorCode::UNKNOWN_ERR, "Wrong debug parameter type");
+        }
+    }
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+DBusOperationListener::DBusOperationListener() {
+}
+
+DBusOperationListener::~DBusOperationListener() {
+}
+
+std::set<DBusOperation*> DBusOperation::s_objects_;
+
+DBusOperation::DBusOperation(const std::string& destination,
+                             const std::string& path,
+                             const std::string& interface) :
+                             destination_(destination),
+                             path_(path),
+                             interface_(interface),
+                             connection_(nullptr) {
+    LoggerD("Enter");
+    s_objects_.insert(this);
+}
+
+DBusOperation::~DBusOperation() {
+    LoggerD("Enter");
+    if (connection_) {
+        dbus_connection_close(connection_);
+        dbus_connection_unref(connection_);
+    }
+
+    const auto iter = s_objects_.find(this);
+
+    if (s_objects_.end() != iter){
+        s_objects_.erase(iter);
+    } else {
+        LoggerE("Object is not existing in the static pool");
+    }
+}
+
+int DBusOperation::InvokeSyncGetInt(const std::string& method,
+                                    DBusOperationArguments* args) {
+
+    LoggerD("Enter");
+    if (!connection_) {
+        connection_ = dbus_bus_get_private(DBUS_BUS_SYSTEM, nullptr);
+    }
+
+    if (!connection_) {
+        LoggerE("dbus_bus_get_private error");
+        throw UnknownException("Failed to get dbus connection");
+    }
+
+    DBusMessage* msg = dbus_message_new_method_call(destination_.c_str(),
+                                                    path_.c_str(),
+                                                    interface_.c_str(),
+                                                    method.c_str());
+
+    if (!msg) {
+        LoggerE("dbus_message_new_method_call error");
+        throw UnknownException("Failed to create dbus message");
+    }
+
+    DBusMessageIter iter;
+    dbus_message_iter_init_append(msg, &iter);
+
+    if (nullptr != args) {
+        try {
+            args->AppendVariant(&iter);
+        } catch (const UnknownException& ex) {
+            LoggerE("append_variant error");
+            dbus_message_unref(msg);
+            throw UnknownException("Failed to append dbus variable");
+        }
+    }
+
+    DBusError err;
+    dbus_error_init(&err);
+    DBusMessage* reply = dbus_connection_send_with_reply_and_block(connection_,
+                                                                   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 UnknownException("Failed to send request via dbus");
+    }
+
+    int result = 0;
+    dbus_bool_t 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 UnknownException("Failed to get reply from dbus");
+    }
+
+    return result;
+}
+
+PlatformResult DBusOperation::InvokeSyncGetInt(const std::string& method,
+                                    DBusOperationArguments* args, int* result) {
+
+    LoggerD("Enter");
+    if (!connection_) {
+        connection_ = dbus_bus_get_private(DBUS_BUS_SYSTEM, nullptr);
+    }
+
+    if (!connection_) {
+        LoggerE("dbus_bus_get_private error");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get dbus connection");
+    }
+
+    DBusMessage* msg = dbus_message_new_method_call(destination_.c_str(),
+                                                    path_.c_str(),
+                                                    interface_.c_str(),
+                                                    method.c_str());
+
+    if (!msg) {
+        LoggerE("dbus_message_new_method_call error");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to create dbus message");
+    }
+
+    DBusMessageIter iter;
+    dbus_message_iter_init_append(msg, &iter);
+
+    if (nullptr != args) {
+        PlatformResult ret = args->AppendVariant(&iter);
+        if (ret.IsError()) {
+            LoggerE("append_variant error");
+            dbus_message_unref(msg);
+            return PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to append dbus variable");
+        }
+    }
+
+    DBusError err;
+    dbus_error_init(&err);
+    DBusMessage* reply = dbus_connection_send_with_reply_and_block(connection_,
+                                                                   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);
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to send request via dbus");
+    }
+
+    *result = 0;
+    dbus_bool_t 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);
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get reply from dbus");
+    }
+
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult DBusOperation::RegisterSignalListener(const std::string& signal_name,
+                                           DBusOperationListener* listener) {
+    LoggerD("Enter");
+    PlatformResult ret = AddDBusSignalFilter();
+    if (ret.IsError()) return ret;
+
+    listeners_.insert(std::make_pair(signal_name, listener));
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult DBusOperation::UnregisterSignalListener(const std::string& signal_name,
+                                             DBusOperationListener* listener) {
+    LoggerD("Enter");
+    bool signal_found = false;
+
+    for (auto iter = listeners_.begin(); iter != listeners_.end(); ++iter) {
+        if (iter->first == signal_name && iter->second == listener) {
+            LoggerD("Found and remove");
+            listeners_.erase(iter);
+
+            signal_found = true;
+            break;
+        }
+    }
+
+    if (false == signal_found) {
+        LoggerE("Failed to find signal handler");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to find signal handler");
+    }
+
+    if (listeners_.empty()) {
+        return RemoveDBusSignalFilter();
+    }
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult DBusOperation::AddDBusSignalFilter() {
+    LoggerD("Enter");
+    if (!connection_) {
+        connection_ = dbus_bus_get_private(DBUS_BUS_SYSTEM, nullptr);
+    }
+
+    if (!connection_) {
+        LoggerE("dbus_bus_get_private error");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get dbus connection");
+    }
+
+    dbus_connection_setup_with_g_main(connection_, nullptr);
+
+    std::stringstream rule;
+    rule << "type='signal',sender='" << destination_
+            << "',path='" << path_
+            << "',interface='" << interface_ << "'";
+
+    rule_ = rule.str();
+
+    DBusError err;
+    dbus_error_init(&err);
+
+    dbus_bus_add_match(connection_, 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);
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to set rule for dbus signal");
+    }
+
+    if (dbus_connection_add_filter(connection_, DBusSignalFilterHandler, this, nullptr) == FALSE) {
+        LoggerE("dbus_connection_add_filter error %s: %s", err.name, err.message);
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to set handler for dbus signal");
+    }
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult DBusOperation::RemoveDBusSignalFilter() {
+    LoggerD("Enter");
+    DBusError err;
+    dbus_error_init(&err);
+    dbus_bus_remove_match(connection_, 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);
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to remove rule for dbus signal");
+    }
+
+    dbus_connection_remove_filter(connection_, DBusSignalFilterHandler, this);
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+DBusHandlerResult DBusOperation::DBusSignalFilter(DBusConnection* /* conn */,
+                                                  DBusMessage* message) {
+    LoggerD("Enter");
+    DBusError err;
+    dbus_error_init(&err);
+
+    int val = 0;
+    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;
+    }
+
+    for (auto iter = listeners_.begin(); iter != listeners_.end(); ++iter) {
+        if (dbus_message_is_signal(message, interface_.c_str(), iter->first.c_str())) {
+            iter->second->OnDBusSignal(val);
+        }
+    }
+
+    return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+DBusHandlerResult DBusOperation::DBusSignalFilterHandler(DBusConnection* conn,
+                                                         DBusMessage* message,
+                                                         void* user_data) {
+    LoggerD("Enter");
+    DBusOperation* that = static_cast<DBusOperation *>(user_data);
+
+    if (s_objects_.end() == s_objects_.find(that)) {
+        LoggerE("Object does not exist in the static pool");
+        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+    }
+
+    return that->DBusSignalFilter(conn, message);
+}
+
+} // namespace common
diff --git a/webWidgetTCT_device/src/common/dbus_operation.h b/webWidgetTCT_device/src/common/dbus_operation.h
new file mode 100755 (executable)
index 0000000..7a0d6ab
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2015 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 COMMON_DBUS_OPERATION_H_
+#define COMMON_DBUS_OPERATION_H_
+
+#include <string>
+#include <vector>
+#include <set>
+
+#include <dbus/dbus.h>
+#include "platform_result.h"
+
+namespace common {
+
+class DBusOperation;
+
+class DBusOperationArguments {
+ public:
+  DBusOperationArguments();
+  ~DBusOperationArguments();
+
+  void AddArgumentBool(bool val);
+  void AddArgumentInt32(int val);
+  void AddArgumentUInt32(unsigned int val);
+  void AddArgumentUInt64(uint64_t val);
+  void AddArgumentString(const std::string& val);
+
+ private:
+  enum class ArgType {
+    kTypeBool,
+    kTypeInt32,
+    kTypeUInt32,
+    kTypeUInt64,
+    kTypeString
+  };
+
+  typedef std::pair<ArgType, void*> ArgumentElement;
+  typedef std::vector<ArgumentElement> Arguments;
+
+  Arguments arguments_;
+
+  friend class DBusOperation;
+
+  common::PlatformResult AppendVariant(DBusMessageIter* bus_msg_iter);
+};
+
+class DBusOperationListener {
+ public:
+  DBusOperationListener();
+  virtual ~DBusOperationListener();
+
+  virtual void OnDBusSignal(int value) = 0;
+};
+
+class DBusOperation {
+ public:
+  DBusOperation(const std::string& destination,
+          const std::string& path,
+          const std::string& interface);
+  virtual ~DBusOperation();
+
+  int InvokeSyncGetInt(const std::string& method,
+             DBusOperationArguments* args);
+  //TODO remove throwing methods when they would be not needed any more.
+  common::PlatformResult InvokeSyncGetInt(const std::string& method,
+             DBusOperationArguments* args, int* result);
+
+  common::PlatformResult RegisterSignalListener(const std::string& signal_name,
+                DBusOperationListener* listener);
+  common::PlatformResult UnregisterSignalListener(const std::string& signal_name,
+                  DBusOperationListener* listener);
+
+ private:
+  std::string destination_;
+  std::string path_;
+  std::string interface_;
+
+  typedef std::pair<std::string, DBusOperationListener*> SignalListenerPair;
+  typedef std::set<SignalListenerPair> SignalListenerSet;
+  SignalListenerSet listeners_;
+
+  DBusConnection* connection_;
+  std::string rule_;
+
+  common::PlatformResult AddDBusSignalFilter();
+  common::PlatformResult RemoveDBusSignalFilter();
+
+  DBusHandlerResult DBusSignalFilter(DBusConnection* conn,
+                     DBusMessage* message);
+
+  static DBusHandlerResult DBusSignalFilterHandler(DBusConnection* conn,
+                           DBusMessage* message,
+                           void* user_data);
+
+  static std::set<DBusOperation*> s_objects_;
+};
+
+} // namespace common
+
+#endif // COMMON_DBUS_OPERATION_H_
diff --git a/webWidgetTCT_device/src/common/deleter.h b/webWidgetTCT_device/src/common/deleter.h
new file mode 100755 (executable)
index 0000000..ce20f79
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2015 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 COMMON_DELETER_H_
+#define COMMON_DELETER_H_
+
+#include <cstdio>
+
+namespace common {
+
+template<typename T>
+struct Deleter
+{
+  typedef std::function<void(T*)> Function;
+
+  Deleter() : function_(NoDelete) {}
+  explicit Deleter(Function const& function) : function_(function) {}
+
+  void operator()(T* ptr) const {
+    function_(ptr);
+  }
+
+  static void CallArrayDelete(T *ptr) { delete[] ptr; };
+  static void CallDelete(T *ptr) { delete ptr; }
+  static void CallFree(T *ptr) { free(ptr); }
+  static void NoDelete(T *) {}
+
+private:
+  Function function_;
+};
+
+struct FileDeleter : public Deleter<FILE>
+{
+  FileDeleter() : Deleter(CloseFile) {}
+  explicit FileDeleter(Function const& function) : Deleter(function) {};
+
+  static void CloseFile(FILE *file) { fclose(file); }
+};
+
+}  // namespace common
+
+#endif  // COMMON_DELETER_H_
\ No newline at end of file
diff --git a/webWidgetTCT_device/src/common/extension.cc b/webWidgetTCT_device/src/common/extension.cc
new file mode 100755 (executable)
index 0000000..f343205
--- /dev/null
@@ -0,0 +1,565 @@
+// Copyright (c) 2013 Intel Corporation. All rights reserved.
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "common/extension.h"
+
+#include <iostream>
+#include <vector>
+#include <string>
+#include <map>
+#include "common/logger.h"
+#include "common/assert.h"
+
+// This function is hidden, because each plugin needs to have own implementation.
+__attribute__ ((visibility ("hidden"))) common::Extension* CreateExtension() {
+  common::Extension* e = new common::Extension();
+  e->SetExtensionName("common");
+  return e;
+}
+
+namespace {
+
+// this variable is valid only during Extension::XW_Initialize() call
+// do not use !!!
+// it's here, so we don't have to modify the interface of CreateExtension(), Extension(), etc.
+XW_Extension g_xw_extension_ = 0;
+
+const XW_CoreInterface* g_core = NULL;
+const XW_MessagingInterface* g_messaging = NULL;
+const XW_Internal_SyncMessagingInterface* g_sync_messaging = NULL;
+const XW_Internal_EntryPointsInterface* g_entry_points = NULL;
+const XW_Internal_RuntimeInterface* g_runtime = NULL;
+const XW_Internal_PermissionsInterface* g_permission = NULL;
+const XW_Internal_DataInterface* g_data = NULL;
+
+bool InitializeInterfaces(XW_GetInterface get_interface) {
+  LoggerD("Enter");
+  static bool initialized = false;
+
+  if (!initialized) {
+    g_core = reinterpret_cast<const XW_CoreInterface*>(
+        get_interface(XW_CORE_INTERFACE));
+    if (!g_core) {
+      LoggerE("Can't initialize extension: error getting Core interface.");
+      return false;
+    }
+
+    g_messaging = reinterpret_cast<const XW_MessagingInterface*>(
+        get_interface(XW_MESSAGING_INTERFACE));
+    if (!g_messaging) {
+      LoggerE("Can't initialize extension: error getting Messaging interface.");
+      return false;
+    }
+
+    g_sync_messaging =
+        reinterpret_cast<const XW_Internal_SyncMessagingInterface*>(
+            get_interface(XW_INTERNAL_SYNC_MESSAGING_INTERFACE));
+    if (!g_sync_messaging) {
+      LoggerE("Can't initialize extension: error getting SyncMessaging interface.");
+      return false;
+    }
+
+    g_entry_points = reinterpret_cast<const XW_Internal_EntryPointsInterface*>(
+        get_interface(XW_INTERNAL_ENTRY_POINTS_INTERFACE));
+    if (!g_entry_points) {
+      LoggerE("NOTE: Entry points interface not available in this version "
+              "of runtime, ignoring entry point data for extensions.");
+    }
+
+    g_runtime = reinterpret_cast<const XW_Internal_RuntimeInterface*>(
+        get_interface(XW_INTERNAL_RUNTIME_INTERFACE));
+    if (!g_runtime) {
+      LoggerE("NOTE: runtime interface not available in this version "
+              "of runtime, ignoring runtime variables for extensions.");
+    }
+
+    g_permission = reinterpret_cast<const XW_Internal_PermissionsInterface*>(
+        get_interface(XW_INTERNAL_PERMISSIONS_INTERFACE));
+    if (!g_permission) {
+      LoggerE("NOTE: permission interface not available in this version "
+              "of runtime, ignoring permission for extensions.");
+    }
+
+    g_data = reinterpret_cast<const XW_Internal_DataInterface*>(
+        get_interface(XW_INTERNAL_DATA_INTERFACE));
+    if (!g_data) {
+      std::cerr << "NOTE: data interface not available in this version of "
+        << "runtime, ignoring data for extensions.\n";
+    }
+
+    initialized = true;
+  }
+
+  return true;
+}
+
+}  // namespace
+
+namespace common {
+
+Extension::Extension() : xw_extension_(g_xw_extension_) {
+  LoggerD("Enter");
+}
+
+Extension::~Extension() {
+  LoggerD("Enter");
+}
+
+void Extension::SetExtensionName(const char* name) {
+  LoggerD("Enter");
+  g_core->SetExtensionName(xw_extension_, name);
+}
+
+void Extension::SetJavaScriptAPI(const char* api) {
+  LoggerD("Enter");
+  g_core->SetJavaScriptAPI(xw_extension_, api);
+}
+
+void Extension::SetExtraJSEntryPoints(const char** entry_points) {
+  LoggerD("Enter");
+  if (g_entry_points)
+    g_entry_points->SetExtraJSEntryPoints(xw_extension_, entry_points);
+}
+
+bool Extension::RegisterPermissions(const char* perm_table) {
+  LoggerD("Enter");
+  if (g_permission)
+    return g_permission->RegisterPermissions(xw_extension_, perm_table);
+  return false;
+}
+
+bool Extension::CheckAPIAccessControl(const char* api_name) {
+  LoggerD("Enter");
+  if (g_permission)
+    return g_permission->CheckAPIAccessControl(xw_extension_, api_name);
+  return false;
+}
+
+Instance* Extension::CreateInstance() {
+  LoggerD("Enter");
+  return NULL;
+}
+
+std::string Extension::GetRuntimeVariable(const char* var_name, unsigned len) {
+  LoggerD("Enter");
+  if (!g_runtime)
+    return "";
+
+  std::vector<char> res(len + 1, 0);
+  g_runtime->GetRuntimeVariableString(xw_extension_, var_name, &res[0], len);
+  return std::string(res.begin(), res.end());
+}
+
+// static
+void Extension::OnInstanceCreated(XW_Instance xw_instance, Instance* instance) {
+  LoggerD("Enter");
+  Assert(!g_core->GetInstanceData(xw_instance));
+  if (!instance)
+    return;
+  instance->xw_instance_ = xw_instance;
+  g_core->SetInstanceData(xw_instance, instance);
+  instance->Initialize();
+}
+
+// static
+void Extension::OnInstanceDestroyed(XW_Instance xw_instance) {
+  LoggerD("Enter");
+  Instance* instance =
+      reinterpret_cast<Instance*>(g_core->GetInstanceData(xw_instance));
+  if (!instance)
+    return;
+  instance->xw_instance_ = 0;
+  delete instance;
+}
+
+// static
+void Extension::HandleMessage(XW_Instance xw_instance, const char* msg) {
+  LoggerD("Enter");
+  Instance* instance =
+      reinterpret_cast<Instance*>(g_core->GetInstanceData(xw_instance));
+  if (!instance)
+    return;
+  instance->HandleMessage(msg);
+}
+
+// static
+void Extension::HandleSyncMessage(XW_Instance xw_instance, const char* msg) {
+  LoggerD("Enter");
+  Instance* instance =
+      reinterpret_cast<Instance*>(g_core->GetInstanceData(xw_instance));
+  if (!instance)
+    return;
+  instance->HandleSyncMessage(msg);
+}
+
+// static
+void Extension::HandleData(XW_Instance xw_instance, const char* msg,
+                           uint8_t* buffer, size_t len) {
+  LoggerD("Enter");
+  Instance* instance =
+      reinterpret_cast<Instance*>(g_core->GetInstanceData(xw_instance));
+  if (!instance)
+    return;
+  instance->HandleData(msg, buffer, len);
+}
+
+// static
+void Extension::HandleSyncData(XW_Instance xw_instance, const char* msg,
+                               uint8_t* buffer, size_t len) {
+  LoggerD("Enter");
+  Instance* instance =
+      reinterpret_cast<Instance*>(g_core->GetInstanceData(xw_instance));
+  if (!instance)
+    return;
+  instance->HandleSyncData(msg, buffer, len);
+}
+
+//static
+int32_t Extension::XW_Initialize(XW_Extension extension,
+                                 XW_GetInterface get_interface,
+                                 XW_Initialize_Func initialize,
+                                 XW_CreatedInstanceCallback created_instance,
+                                 XW_ShutdownCallback shutdown) {
+  LoggerD("Enter");
+  Assert(extension);
+
+  if (!InitializeInterfaces(get_interface)) {
+    return XW_ERROR;
+  }
+
+  g_xw_extension_ = extension;
+
+  if (XW_ERROR == initialize(extension, get_interface)) {
+    return XW_ERROR;
+  }
+
+  g_xw_extension_ = 0;
+
+  using common::Extension;
+  g_core->RegisterShutdownCallback(extension, shutdown);
+  g_core->RegisterInstanceCallbacks(extension, created_instance,
+                                    Extension::OnInstanceDestroyed);
+  g_messaging->Register(extension, Extension::HandleMessage);
+  g_sync_messaging->Register(extension, Extension::HandleSyncMessage);
+
+  if (g_data) {
+    g_data->RegisterSync(extension, Extension::HandleSyncData);
+    g_data->RegisterAsync(extension, Extension::HandleData);
+  }
+
+  return XW_OK;
+}
+
+std::unordered_set<Instance*> Instance::all_instances_;
+
+Instance::Instance() :
+    xw_instance_(0)
+{
+  LoggerD("Enter");
+  {
+    all_instances_.insert(this);
+  }
+}
+
+Instance::~Instance() {
+  LoggerD("Enter");
+  {
+    all_instances_.erase(this);
+  }
+  Assert(xw_instance_ == 0);
+}
+
+void Instance::PostMessage(Instance* that, const char* msg) {
+  LoggerD("Enter");
+  if (that && all_instances_.end() != all_instances_.find(that)) {
+    that->PostMessage(msg);
+  } else {
+    LoggerE("Trying to post message to non-existing instance: [%p], ignoring",
+            that);
+  }
+}
+
+void Instance::PostMessage(const char* msg) {
+  LoggerD("Enter");
+  if (!xw_instance_) {
+    LoggerE("Ignoring PostMessage() in the constructor or after the "
+            "instance was destroyed.");
+    return;
+  }
+  g_messaging->PostMessage(xw_instance_, msg);
+}
+
+
+void Instance::PostData(const char* msg, uint8_t* buffer, size_t len) {
+  LoggerD("Enter");
+  if (!xw_instance_) {
+    std::cerr << "Ignoring PostData() in the constructor or after the "
+              << "instance was destroyed.";
+    return;
+  }
+  g_data->PostData(xw_instance_, msg, buffer, len);
+}
+
+
+void Instance::SendSyncReply(const char* reply) {
+  LoggerD("Enter");
+  if (!xw_instance_) {
+    LoggerE("Ignoring SendSyncReply() in the constructor or after the "
+            "instance was destroyed.");
+    return;
+  }
+  g_sync_messaging->SetSyncReply(xw_instance_, reply);
+}
+
+// ParsedInstance //////////////////////////////////////////////////////////////
+void Instance::SendSyncReply(const char* reply, uint8_t* buffer, size_t len) {
+  LoggerD("Enter");
+  if (!xw_instance_) {
+    std::cerr << "Ignoring SendSyncReply() in the constructor or after the "
+              << "instance was destroyed.";
+    return;
+  }
+  g_data->SetSyncReply(xw_instance_, reply, buffer, len);
+}
+
+ParsedInstance::ParsedInstance() {
+  LoggerD("Enter");
+}
+
+ParsedInstance::~ParsedInstance() {
+  LoggerD("Enter");
+}
+
+void ParsedInstance::RegisterHandler(const std::string& name, const NativeHandler& func) {
+  LoggerD("Enter");
+  handler_map_.insert(std::make_pair(name, func));
+}
+
+void ParsedInstance::RegisterSyncHandler(const std::string& name, const NativeHandler& func) {
+  LoggerD("Enter");
+  handler_map_.insert(std::make_pair("#SYNC#" + name, func));
+}
+
+void ParsedInstance::ReportSuccess(picojson::object& out) {
+  LoggerD("Enter");
+  tools::ReportSuccess(out);
+}
+
+void ParsedInstance::ReportSuccess(const picojson::value& result, picojson::object& out) {
+  LoggerD("Enter");
+  tools::ReportSuccess(result, out);
+}
+
+void ParsedInstance::ReportError(picojson::object& out) {
+  LoggerD("Enter");
+  tools::ReportError(out);
+}
+
+void ParsedInstance::ReportError(const PlatformException& ex, picojson::object& out) {
+  LoggerD("Enter");
+  tools::ReportError(ex, out);
+}
+
+void ParsedInstance::ReportError(const PlatformResult& error, picojson::object* out) {
+  LoggerD("Enter");
+  tools::ReportError(error, out);
+}
+
+void ParsedInstance::HandleMessage(const char* msg) {
+  LoggerD("Enter");
+  HandleMessage(msg, false);
+}
+
+void ParsedInstance::HandleSyncMessage(const char* msg) {
+  LoggerD("Enter");
+  HandleMessage(msg, true);
+}
+
+void ParsedInstance::HandleMessage(const char* msg, bool is_sync) {
+  LoggerD("Enter");
+  try {
+    picojson::value value;
+    std::string err;
+    picojson::parse(value, msg, msg + strlen(msg), &err);
+    if (!err.empty()) {
+      LoggerE("Ignoring message, error: %s", err.c_str());
+      return;
+    }
+
+    if (!value.is<picojson::object>()) {
+      LoggerE("Ignoring message. It is not an object.");
+      return;
+    }
+
+    std::string cmd = (is_sync ? "#SYNC#" : "") + value.get("cmd").to_str();
+
+    auto it = handler_map_.find(cmd);
+    if (handler_map_.end() == it) {
+      throw UnknownException("Unknown command.");
+    }
+
+    NativeHandler func = it->second;
+
+    // check for args in JSON message
+    const picojson::value& args = value.get("args");
+    if (!args.is<picojson::object>()) {
+      throw InvalidValuesException("No \"args\" field in message");
+    }
+
+    picojson::value result = picojson::value(picojson::object());
+    func(args, result.get<picojson::object>());
+
+    if (is_sync)
+      SendSyncReply(result.serialize().c_str());
+
+  } catch (const PlatformException& e) {
+    return HandleException(e);
+  } catch (const PlatformException* e) {
+    return HandleException(*e);
+  } catch (const std::exception& e) {
+    return HandleException(UnknownException(e.what()));
+  } catch (const std::exception* e) {
+    return HandleException(UnknownException(e->what()));
+  } catch (...) {
+    return HandleException(UnknownException("Unknown exception"));
+  }
+}
+
+void ParsedInstance::HandleException(const PlatformException& ex) {
+  LoggerD("Enter");
+  LoggerE("Exception: %s", ex.message().c_str());
+  picojson::value result = picojson::value(picojson::object());
+  ReportError(ex, result.get<picojson::object>());
+  SendSyncReply(result.serialize().c_str());
+}
+
+void ParsedInstance::HandleError(const PlatformResult& e) {
+  LoggerE("Error: %s", static_cast<int>(e.error_code()));
+  picojson::value result = picojson::value(picojson::object());
+  ReportError(e, &result.get<picojson::object>());
+  SendSyncReply(result.serialize().c_str());
+}
+
+// ParsedDataStruct ////////////////////////////////////////////////////////////
+
+ParsedDataStruct::ParsedDataStruct()
+    : buffer_(NULL), buffer_len_(0) {
+}
+
+ParsedDataStruct::ParsedDataStruct(uint8_t* buffer, size_t len)
+    : buffer_(buffer), buffer_len_(len) {
+}
+
+void ParsedDataStruct::SetBuffer(uint8_t* buffer, size_t len) {
+  buffer_ = buffer;
+  buffer_len_ = len;
+}
+
+ParsedDataRequest::ParsedDataRequest(uint8_t* buffer, size_t len)
+    : ParsedDataStruct(buffer, len) {
+}
+
+bool ParsedDataRequest::Parse(const char* msg) {
+  std::string err;
+  picojson::parse(value_, msg, msg + strlen(msg), &err);
+  if (!err.empty()) {
+    std::cerr << "Ignoring message. " << err;
+    return false;
+  }
+
+  if (!value_.is<picojson::object>()) {
+    std::cerr << "Ignoring message. It is not an object.";
+    return false;
+  }
+
+  return true;
+}
+
+std::string ParsedDataRequest::cmd() const {
+  return value_.get("cmd").to_str();
+}
+
+const picojson::value& ParsedDataRequest::args() const {
+  return value_.get("args");
+}
+
+ParsedDataResponse::ParsedDataResponse()
+    : value_(picojson::value(picojson::object())) {
+}
+
+picojson::object& ParsedDataResponse::object() {
+  return value_.get<picojson::object>();
+}
+
+// ParsedDataInstance //////////////////////////////////////////////////////////
+
+void ParsedDataInstance::RegisterHandler(const std::string& name,
+                                         const NativeDataHandler& func) {
+  LoggerD("Enter");
+  data_handler_map_.insert(std::make_pair(name, func));
+}
+
+void ParsedDataInstance::RegisterSyncHandler(const std::string& name,
+                                             const NativeDataHandler& func) {
+  LoggerD("Enter");
+  data_handler_map_.insert(std::make_pair("#SYNC#" + name, func));
+}
+
+void ParsedDataInstance::HandleData(const char* msg,
+                                    uint8_t* buffer, size_t len) {
+  LoggerD("Enter");
+  HandleData(msg, buffer, len, false);
+}
+
+void ParsedDataInstance::HandleSyncData(const char* msg,
+                                        uint8_t* buffer, size_t len) {
+  LoggerD("Enter");
+  HandleData(msg, buffer, len, true);
+}
+
+void ParsedDataInstance::HandleData(const char* msg,
+                                    uint8_t* buffer, size_t len, bool is_sync) {
+  LoggerD("Enter");
+  try {
+    ParsedDataRequest request(buffer, len);
+    if (!request.Parse(msg)) {
+      return;
+    }
+
+    // check for args in JSON message
+    const picojson::value& args = request.args();
+    if (!args.is<picojson::object>()) {
+      throw InvalidValuesException("No \"args\" field in message");
+    }
+
+    std::string cmd = (is_sync ? "#SYNC#" : "") + request.cmd();
+    auto it = data_handler_map_.find(cmd);
+    if (data_handler_map_.end() == it) {
+      throw UnknownException("Unknown command.");
+    }
+    NativeDataHandler func = it->second;
+
+    ParsedDataResponse response;
+    func(request, response);
+    if (is_sync) {
+      SendSyncReply(response.value().serialize().c_str(),
+                    response.buffer(), response.buffer_length());
+    }
+  } catch (const PlatformException& e) {
+    return HandleException(e);
+  } catch (const PlatformException* e) {
+    return HandleException(*e);
+  } catch (const std::exception& e) {
+    return HandleException(UnknownException(e.what()));
+  } catch (const std::exception* e) {
+    return HandleException(UnknownException(e->what()));
+  } catch (...) {
+    return HandleException(UnknownException("Unknown exception"));
+  }
+}
+
+
+
+}  // namespace common
diff --git a/webWidgetTCT_device/src/common/extension.h b/webWidgetTCT_device/src/common/extension.h
new file mode 100755 (executable)
index 0000000..65b7160
--- /dev/null
@@ -0,0 +1,213 @@
+// Copyright (c) 2013 Intel Corporation. All rights reserved.
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMMON_EXTENSION_H_
+#define COMMON_EXTENSION_H_
+
+// This is a C++ wrapper over Crosswalk Extension C API. It implements once the
+// boilerplate for the common case of mapping XW_Extension and XW_Instance to
+// objects of their own. The wrapper deals automatically with creating and
+// destroying the objects.
+//
+// Extension object lives during the lifetime of the extension, and when the
+// extension process is properly shutdown, it's destructor will be
+// called. Instance objects (there can be many) live during the lifetime of a
+// script context associated with a frame in the page. These objects serves as
+// storage points for extension specific objects, use them for that.
+
+#include <sys/types.h>
+
+#include <string>
+#include <map>
+#include <functional>
+#include <unordered_set>
+
+#include "common/platform_exception.h"
+#include "common/platform_result.h"
+// TODO: this include should be moved to source file
+//       it's here, so we don't break other modules using it implicitly
+#include "common/tools.h"
+#include "common/XW_Extension.h"
+#include "common/XW_Extension_EntryPoints.h"
+#include "common/XW_Extension_Permissions.h"
+#include "common/XW_Extension_Runtime.h"
+#include "common/XW_Extension_SyncMessage.h"
+#include "common/XW_Extension_Data.h"
+
+namespace common {
+
+class Instance;
+class Extension;
+
+}  // namespace common
+
+
+// This function should be implemented by each extension and should return
+// an appropriate Extension subclass.
+common::Extension* CreateExtension();
+
+namespace common {
+
+// implemented in XW_Extension.cc
+// can be called only after the extension is fully created
+//    (CreateExtension() has been called)
+Extension* GetCurrentExtension();
+
+class Extension {
+ public:
+  Extension();
+  virtual ~Extension();
+
+  // These should be called in the subclass constructor.
+  void SetExtensionName(const char* name);
+  void SetJavaScriptAPI(const char* api);
+  void SetExtraJSEntryPoints(const char** entry_points);
+  bool RegisterPermissions(const char* perm_table);
+
+  // This API should be called in the message handler of extension
+  bool CheckAPIAccessControl(const char* api_name);
+
+  virtual Instance* CreateInstance();
+
+  std::string GetRuntimeVariable(const char* var_name, unsigned len);
+
+ private:
+  friend int32_t (::XW_Initialize)(XW_Extension extension,
+                                   XW_GetInterface get_interface);
+
+  static int32_t XW_Initialize(XW_Extension extension,
+                               XW_GetInterface get_interface,
+                               XW_Initialize_Func initialize,
+                               XW_CreatedInstanceCallback created_instance,
+                               XW_ShutdownCallback shutdown);
+
+  // XW_Extension callbacks.
+  static void OnInstanceCreated(XW_Instance xw_instance, Instance* instance); // modified
+  static void OnInstanceDestroyed(XW_Instance xw_instance);
+  static void HandleMessage(XW_Instance xw_instance, const char* msg);
+  static void HandleSyncMessage(XW_Instance xw_instance, const char* msg);
+  static void HandleData(XW_Instance xw_instance, const char* msg,
+                         uint8_t* buffer, size_t len);
+  static void HandleSyncData(XW_Instance xw_instance, const char* msg,
+                             uint8_t* buffer, size_t len);
+
+  XW_Extension xw_extension_;
+
+  class Detail;
+};
+
+class Instance {
+ public:
+  Instance();
+  virtual ~Instance();
+
+  static void PostMessage(Instance* that, const char* msg);
+  void PostData(const char* msg, uint8_t* buffer, size_t len);
+  void SendSyncReply(const char* reply);
+  void SendSyncReply(const char* reply, uint8_t* buffer, size_t len);
+
+  virtual void Initialize() {}
+
+  virtual void HandleMessage(const char* msg) = 0;
+  virtual void HandleSyncMessage(const char* msg) {}
+
+  virtual void HandleData(const char* msg, uint8_t* buffer, size_t len) {}
+  virtual void HandleSyncData(const char* msg, uint8_t* buffer, size_t len) {}
+
+  XW_Instance xw_instance() const { return xw_instance_; }
+
+ private:
+  void PostMessage(const char* msg);
+
+  friend class Extension;
+
+  static std::unordered_set<Instance*> all_instances_;
+
+  XW_Instance xw_instance_;
+};
+
+typedef std::function<void(const picojson::value&, picojson::object&)>
+    NativeHandler;
+
+class ParsedInstance : public Instance {
+ public:
+  ParsedInstance();
+  virtual ~ParsedInstance();
+ protected:
+  void RegisterHandler(const std::string& name, const NativeHandler& func);
+  void RegisterSyncHandler(const std::string& name, const NativeHandler& func);
+
+  void ReportSuccess(picojson::object& out);
+  void ReportSuccess(const picojson::value& result, picojson::object& out);
+  void ReportError(picojson::object& out);
+  void ReportError(const PlatformException& ex, picojson::object& out);
+  void ReportError(const PlatformResult& error, picojson::object* out);
+
+  void HandleException(const PlatformException& ex);
+  void HandleError(const PlatformResult& error);
+
+ private:
+  void HandleMessage(const char* msg);
+  void HandleSyncMessage(const char* msg);
+  void HandleMessage(const char* msg, bool is_sync);
+
+  std::map<std::string, NativeHandler> handler_map_;
+};
+
+class ParsedDataStruct {
+ public:
+  ParsedDataStruct();
+  ParsedDataStruct(uint8_t* buffer, size_t len);
+
+  void SetBuffer(uint8_t* buffer, size_t len);
+
+  uint8_t* buffer() const { return buffer_; }
+  size_t buffer_length() const { return buffer_len_; }
+ private:
+  uint8_t* buffer_;
+  size_t buffer_len_;
+};
+
+class ParsedDataRequest : public ParsedDataStruct {
+ public:
+  ParsedDataRequest(uint8_t* buffer, size_t len);
+
+  bool Parse(const char* msg);
+  std::string cmd() const;
+  const picojson::value& args() const;
+  const picojson::value& value() const { return value_; }
+ private:
+  picojson::value value_;
+};
+
+class ParsedDataResponse : public ParsedDataStruct {
+ public:
+  ParsedDataResponse();
+
+  const picojson::value& value() const { return value_; }
+  picojson::object& object();
+ private:
+  picojson::value value_;
+};
+
+typedef std::function<void(const ParsedDataRequest&, ParsedDataResponse&)>
+    NativeDataHandler;
+
+class ParsedDataInstance : public ParsedInstance {
+ public:
+  using ParsedInstance::RegisterSyncHandler;
+  void RegisterHandler(const std::string& name, const NativeDataHandler& func);
+  void RegisterSyncHandler(const std::string& name, const NativeDataHandler& func);
+ private:
+  void HandleData(const char* msg, uint8_t* buffer, size_t len);
+  void HandleSyncData(const char* msg, uint8_t* buffer, size_t len);
+  void HandleData(const char* msg, uint8_t* buffer, size_t len, bool is_sync);
+
+  std::map<std::string, NativeDataHandler> data_handler_map_;
+};
+
+}  // namespace common
+
+#endif  // COMMON_EXTENSION_H_
diff --git a/webWidgetTCT_device/src/common/filesystem/deviced.cc b/webWidgetTCT_device/src/common/filesystem/deviced.cc
new file mode 100755 (executable)
index 0000000..1a58b94
--- /dev/null
@@ -0,0 +1,349 @@
+/*
+ * Copyright (c) 2015 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 "common/filesystem/deviced.h"
+
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib.h>
+#include <gio/gio.h>
+#include <functional>
+#include <list>
+#include <map>
+#include <algorithm>
+#include <memory>
+#include <utility>
+
+#include "common/filesystem/storage.h"
+#include "common/logger.h"
+
+namespace {
+static const char* kIface = "org.tizen.system.deviced.BlockManager";
+static const char* kPath = "/Org/Tizen/System/DeviceD/Block/Manager";
+}  // namespace
+
+namespace common {
+
+struct DeviceListElem {
+    DeviceListElem()
+        : block_type(0),
+          devnode(nullptr),
+          syspath(nullptr),
+          fs_usage(nullptr),
+          fs_type(nullptr),
+          fs_version(nullptr),
+          fs_uuid_enc(nullptr),
+          readonly(0),
+          mount_point(nullptr),
+          state(0),
+          primary(false) {}
+
+    int block_type;
+    char* devnode;
+    char* syspath;
+    char* fs_usage;
+    char* fs_type;
+    char* fs_version;
+    char* fs_uuid_enc;
+    int readonly;
+    char* mount_point;
+    int state;
+    bool primary;
+};
+
+FilesystemProviderDeviced::~FilesystemProviderDeviced() {
+  LoggerD("Entered");
+}
+
+FilesystemProviderDeviced::FilesystemProviderDeviced() :
+  dbus_(nullptr),
+  proxy_(nullptr),
+  device_changed_callback_(nullptr),
+  signal_device_removed_id_(0),
+  signal_device_added_id_(0),
+  virtual_roots_provider_(FilesystemProviderStorage::Create()),
+  is_initialized_(false) {
+
+  GError* error = nullptr;
+
+  dbus_ = g_bus_get_sync(G_BUS_TYPE_SYSTEM, nullptr, &error);
+  if (!dbus_ || (error == NULL)) {
+    LoggerE("Could not get dbus connection. %s", error->message);
+  }
+  else {
+    LoggerD("Dbus connection set");
+    const gchar* unique_name = g_dbus_connection_get_unique_name(dbus_);
+    proxy_ = g_dbus_proxy_new_sync(dbus_, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
+                                   nullptr, unique_name, kPath, kIface, nullptr,
+                                   &error);
+    if (!proxy_ || error) {
+      LoggerE("Could not get dbus proxy. %s", error->message);
+    } else {
+      is_initialized_ = true;
+    }
+  }
+}
+
+FilesystemProviderDeviced& FilesystemProviderDeviced::Create() {
+
+  static FilesystemProviderDeviced instance;
+
+  return instance;
+}
+
+void FilesystemProviderDeviced::RegisterDeviceChangeState(
+    DeviceChangeStateFun _callback) {
+  LoggerD("Entered");
+
+  if(!is_initialized_) {
+    LoggerE("DeviceD Core api not initialized");
+    return;
+  }
+
+  if (device_changed_callback_ != nullptr) {
+    LoggerW("Overwriting device changed state callback");
+  }
+  device_changed_callback_ = _callback;
+}
+
+void FilesystemProviderDeviced::UnregisterDeviceChangeState() {
+  LoggerD("Entered");
+
+  if(!is_initialized_) {
+    LoggerE("DeviceD Core api not initialized");
+    return;
+  }
+
+  std::for_each(signal_device_changed_ids_map_.begin(),
+                signal_device_changed_ids_map_.end(),
+                [this](const std::pair<std::string, guint>& path_and_id) {
+                  g_dbus_connection_signal_unsubscribe(this->dbus_,
+                                                       path_and_id.second);
+                });
+  device_changed_callback_ = nullptr;
+}
+
+void FilesystemProviderDeviced::SignalCallbackRemovedProxy(
+    GDBusConnection* connection, const gchar* sender_name,
+    const gchar* object_path, const gchar* interface_name,
+    const gchar* signal_name, GVariant* parameters, gpointer user_data) {
+  LoggerD("Entered");
+  FilesystemProviderDeviced* instance =
+    static_cast<FilesystemProviderDeviced*>(user_data);
+  instance->SignalCallbackRemoved(connection, sender_name, object_path,
+                                  interface_name, signal_name, parameters,
+                                  nullptr);
+}
+
+void FilesystemProviderDeviced::SignalCallbackAddedProxy(
+    GDBusConnection* connection, const gchar* sender_name,
+    const gchar* object_path, const gchar* interface_name,
+    const gchar* signal_name, GVariant* parameters, gpointer user_data) {
+  LoggerD("Entered");
+  FilesystemProviderDeviced* instance =
+    static_cast<FilesystemProviderDeviced*>(user_data);
+  instance->SignalCallbackAdded(connection, sender_name, object_path,
+                                interface_name, signal_name, parameters,
+                                nullptr);
+}
+
+void FilesystemProviderDeviced::SignalCallbackChangedProxy(
+    GDBusConnection* connection, const gchar* sender_name,
+    const gchar* object_path, const gchar* interface_name,
+    const gchar* signal_name, GVariant* parameters, gpointer user_data) {
+  LoggerD("Entered");
+  FilesystemProviderDeviced* instance =
+    static_cast<FilesystemProviderDeviced*>(user_data);
+  instance->SignalCallbackChanged(connection, sender_name, object_path,
+                                  interface_name, signal_name, parameters,
+                                  nullptr);
+}
+
+void FilesystemProviderDeviced::SignalCallbackRemoved(
+    GDBusConnection* connection, const gchar* sender_name,
+    const gchar* object_path, const gchar* interface_name,
+    const gchar* signal_name, GVariant* parameters, gpointer user_data) {
+  LoggerD("Entered");
+  LoggerD("callback Removed called");
+  char* path = nullptr;
+  g_variant_get(parameters, "(s)", &path);
+  LoggerD("removed device path: %s", path);
+  UnsubscribeOneDeviceChangedSignal(path);
+  auto it = previous_device_state_map_.find(path);
+  if (it != previous_device_state_map_.end()) {
+    previous_device_state_map_.erase(path);
+  }
+}
+
+void FilesystemProviderDeviced::SignalCallbackAdded(
+    GDBusConnection* connection, const gchar* sender_name,
+    const gchar* object_path, const gchar* interface_name,
+    const gchar* signal_name, GVariant* parameters, gpointer user_data) {
+  LoggerD("Entered");
+  LoggerD("callback device added called");
+  char* path = nullptr;
+  g_variant_get(parameters, "(s)", &path);
+  LoggerD("added device path: %s", path);
+  const char* sender = nullptr;
+  UnsubscribeOneDeviceChangedSignal(path);
+  guint id = g_dbus_connection_signal_subscribe(
+      connection, sender, "org.tizen.system.deviced.Block", "DeviceChanged",
+      path, nullptr, G_DBUS_SIGNAL_FLAGS_NONE, SignalCallbackChangedProxy, this,
+      nullptr);
+  signal_device_changed_ids_map_[path] = id;
+}
+
+void FilesystemProviderDeviced::SignalCallbackChanged(
+    GDBusConnection* connection, const gchar* sender_name,
+    const gchar* object_path, const gchar* interface_name,
+    const gchar* signal_name, GVariant* parameters, gpointer user_data) {
+  LoggerD("Entered");
+  LoggerD("callback device changed");
+  DeviceListElem elem;
+  g_variant_get(parameters, "(issssssisib)", &elem.block_type, &elem.devnode,
+                &elem.syspath, &elem.fs_usage, &elem.fs_type, &elem.fs_version,
+                &elem.fs_uuid_enc, &elem.readonly, &elem.mount_point,
+                &elem.state, &elem.primary);
+
+  StorageState previous_state = StorageState::kUnmounted;
+  auto it = previous_device_state_map_.find(elem.syspath);
+  if (it == previous_device_state_map_.end()) {
+    previous_device_state_map_[elem.syspath] = previous_state =
+        (elem.state ? StorageState::kMounted : StorageState::kUnmounted);
+  } else {
+    previous_state = it->second;
+  }
+  if (device_changed_callback_ != nullptr) {
+    std::shared_ptr<Storage> storage = GetStorage(elem);
+    device_changed_callback_(*storage, previous_state, storage->state_);
+  }
+}
+
+std::shared_ptr<Storage> FilesystemProviderDeviced::GetInternalStorage() {
+
+  return virtual_roots_provider_.GetInternalStorage();
+}
+
+std::shared_ptr<Storage> FilesystemProviderDeviced::GetStorage(const DeviceListElem& elem) {
+  LoggerD("Entered");
+  return std::make_shared<Storage>(Storage(GetIdFromUUID(elem.fs_uuid_enc), StorageType::kExternal,
+                 (elem.state ? StorageState::kMounted : StorageState::kUnmounted),
+                 elem.syspath, GetNameFromPath(elem.devnode)));
+}
+
+std::string FilesystemProviderDeviced::GetNameFromPath(
+    const char* const char_path) {
+  LoggerD("Entered");
+  std::string path = char_path;
+  std::string name = "removable_";
+  std::size_t last_slash_pos = path.find_last_of("/");
+  if (last_slash_pos + 1 >= path.size()) {
+    name += path;
+    LoggerW("Failed to get device name from device syspath");
+  } else {
+    name += path.substr(last_slash_pos + 1);
+  }
+  return name;
+}
+
+int FilesystemProviderDeviced::GetIdFromUUID(const char* const char_uuid) {
+  LoggerD("Entered");
+  std::string uuid = char_uuid;
+  size_t hyphen = uuid.find("-");
+  std::string clear_uuid = uuid.substr(0, hyphen) + uuid.substr(hyphen + 1);
+  return static_cast<int>(std::stoul(clear_uuid, 0, 16));
+}
+
+void FilesystemProviderDeviced::UnsubscribeOneDeviceChangedSignal(
+    const char* path) {
+  LoggerD("Entered");
+  auto it = signal_device_changed_ids_map_.find(path);
+  if (it != signal_device_changed_ids_map_.end()) {
+    g_dbus_connection_signal_unsubscribe(dbus_, it->second);
+    signal_device_changed_ids_map_.erase(it);
+  }
+}
+
+Storages FilesystemProviderDeviced::GetStorages() {
+  LoggerD("Entered");
+
+  if(!is_initialized_) {
+    LoggerE("DeviceD Core api not initialized");
+    return Storages();
+  }
+
+  GError* error = nullptr;
+  GVariant* variant = g_dbus_proxy_call_sync(
+      proxy_, "GetDeviceList", g_variant_new("(s)", "all"),
+      G_DBUS_CALL_FLAGS_NONE, -1, nullptr, &error);
+  if (!variant || error) {
+    LoggerE("Failed to call GetDeviceList method - %s", error->message);
+    return Storages();
+  }
+  LoggerD("GetDeviceList called");
+  return GetStoragesFromGVariant(variant);
+}
+
+Storages FilesystemProviderDeviced::GetStoragesFromGVariant(GVariant* variant) {
+  LoggerD("Entered");
+  Storages storages;
+  GVariantIter iter;
+  GVariant* tuple = nullptr;
+  g_variant_iter_init(&iter, variant);
+  while ((tuple = g_variant_iter_next_value(&iter))) {
+    DeviceListElem elem;
+    g_variant_get(tuple, "(issssssisib)", &elem.block_type, &elem.devnode,
+                  &elem.syspath, &elem.fs_usage, &elem.fs_type,
+                  &elem.fs_version, &elem.fs_uuid_enc, &elem.readonly,
+                  &elem.mount_point, &elem.state, &elem.primary);
+    storages.push_back(GetStorage(elem));
+    g_variant_unref(tuple);
+  }
+  return storages;
+}
+
+VirtualRoots FilesystemProviderDeviced::GetVirtualPaths() {
+  LoggerD("Entered");
+
+  if(!is_initialized_) {
+    LoggerE("DeviceD Core api not initialized");
+    return VirtualRoots();
+  }
+
+  return virtual_roots_provider_.GetVirtualPaths();
+}
+
+VirtualStorages FilesystemProviderDeviced::GetAllStorages() {
+  LoggerD("Entered");
+
+  if(!is_initialized_) {
+    LoggerE("DeviceD Core api not initialized");
+    return VirtualStorages();
+  }
+
+  std::lock_guard<std::mutex> lock(mutex_);
+  VirtualStorages vs;
+  for (auto storage : GetStorages()) {
+    vs.push_back(storage);
+  }
+
+  for (auto virtual_root : virtual_roots_provider_.GetVirtualPaths()) {
+    vs.push_back(std::make_shared<VirtualRoot>(virtual_root));
+  }
+
+  return vs;
+}
+
+}  // namespace common
diff --git a/webWidgetTCT_device/src/common/filesystem/deviced.h b/webWidgetTCT_device/src/common/filesystem/deviced.h
new file mode 100755 (executable)
index 0000000..9b6f913
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2015 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 COMMON_FILESYSTEM_DEVICED_H
+#define COMMON_FILESYSTEM_DEVICED_H
+
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib.h>
+#include <gio/gio.h>
+
+#include <functional>
+#include <list>
+#include <string>
+#include <map>
+#include <memory>
+#include <mutex>
+
+#include "common/filesystem/storage.h"
+#include "common/filesystem/filesystem_provider.h"
+#include "common/filesystem/filesystem_provider_storage.h"
+
+namespace common {
+
+struct DeviceListElem;
+
+class FilesystemProviderDeviced : public FilesystemProvider {
+ public:
+  virtual ~FilesystemProviderDeviced();
+  virtual void RegisterDeviceChangeState(DeviceChangeStateFun _callback);
+  virtual void UnregisterDeviceChangeState();
+  virtual VirtualRoots GetVirtualPaths();
+  virtual Storages GetStorages();
+  virtual VirtualStorages GetAllStorages();
+  virtual std::shared_ptr< Storage > GetInternalStorage();
+  static FilesystemProviderDeviced& Create();
+
+ private:
+  FilesystemProviderDeviced();
+  FilesystemProviderDeviced(GDBusConnection* dbus, GDBusProxy* proxy);
+
+  static void SignalCallbackRemovedProxy(GDBusConnection* connection,
+                             const gchar* sender_name, const gchar* object_path,
+                             const gchar* interface_name,
+                             const gchar* signal_name, GVariant* parameters,
+                             gpointer user_data);
+  static void SignalCallbackAddedProxy(GDBusConnection* connection,
+                           const gchar* sender_name, const gchar* object_path,
+                           const gchar* interface_name,
+                           const gchar* signal_name, GVariant* parameters,
+                           gpointer user_data);
+  static void SignalCallbackChangedProxy(GDBusConnection* connection,
+                             const gchar* sender_name, const gchar* object_path,
+                             const gchar* interface_name,
+                             const gchar* signal_name, GVariant* parameters,
+                             gpointer user_data);
+
+  void SignalCallbackRemoved(GDBusConnection* connection,
+                             const gchar* sender_name, const gchar* object_path,
+                             const gchar* interface_name,
+                             const gchar* signal_name, GVariant* parameters,
+                             gpointer user_data);
+  void SignalCallbackAdded(GDBusConnection* connection,
+                           const gchar* sender_name, const gchar* object_path,
+                           const gchar* interface_name,
+                           const gchar* signal_name, GVariant* parameters,
+                           gpointer user_data);
+  void SignalCallbackChanged(GDBusConnection* connection,
+                             const gchar* sender_name, const gchar* object_path,
+                             const gchar* interface_name,
+                             const gchar* signal_name, GVariant* parameters,
+                             gpointer user_data);
+  void UnsubscribeOneDeviceChangedSignal(const char* path);
+
+  static std::string GetNameFromPath(const char* const char_path);
+  static int GetIdFromUUID(const char* const char_uuid);
+  static std::shared_ptr<Storage> GetStorage(const DeviceListElem& elem);
+  static Storages GetStoragesFromGVariant(GVariant* variant);
+  GDBusConnection* dbus_;
+  GDBusProxy* proxy_;
+
+  DeviceChangeStateFun device_changed_callback_;
+  guint signal_device_removed_id_;
+  guint signal_device_added_id_;
+  std::map<std::string, guint> signal_device_changed_ids_map_;
+  std::map<std::string, StorageState> previous_device_state_map_;
+  FilesystemProviderRef virtual_roots_provider_;
+  std::mutex mutex_;
+
+  bool is_initialized_;
+};
+
+}  // namespace common
+
+#endif /* DEVICED_H */
diff --git a/webWidgetTCT_device/src/common/filesystem/filesystem_provider.cc b/webWidgetTCT_device/src/common/filesystem/filesystem_provider.cc
new file mode 100755 (executable)
index 0000000..feeeb6d
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2015 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 "common/filesystem/filesystem_provider.h"
+
+namespace common {
+
+FilesystemProvider::FilesystemProvider() {
+}
+
+FilesystemProvider::~FilesystemProvider() {
+}
+
+}  // namespace common
diff --git a/webWidgetTCT_device/src/common/filesystem/filesystem_provider.h b/webWidgetTCT_device/src/common/filesystem/filesystem_provider.h
new file mode 100755 (executable)
index 0000000..1eeb642
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2015 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 COMMON_FILESYSTEM_FILESYSTEM_PROVIDER_H_
+#define COMMON_FILESYSTEM_FILESYSTEM_PROVIDER_H_
+
+#include <functional>
+#include <vector>
+#include <memory>
+#include "common/filesystem/storage.h"
+
+namespace common {
+
+typedef std::function<
+    void(common::Storage, common::StorageState,
+         common::StorageState)> DeviceChangeStateFun;
+typedef std::vector<std::shared_ptr<common::Storage> > Storages;
+typedef std::vector<common::VirtualRoot> VirtualRoots;
+typedef std::vector<std::shared_ptr<common::VirtualStorage> > VirtualStorages;
+
+class FilesystemProvider {
+ public:
+  FilesystemProvider();
+  virtual ~FilesystemProvider();
+
+  virtual void RegisterDeviceChangeState(DeviceChangeStateFun _callback) = 0;
+  virtual void UnregisterDeviceChangeState() = 0;
+
+  virtual Storages GetStorages() = 0;
+  virtual VirtualRoots GetVirtualPaths() = 0;
+  virtual VirtualStorages GetAllStorages() = 0;
+  virtual std::shared_ptr<Storage> GetInternalStorage() = 0;
+};
+
+typedef FilesystemProvider& FilesystemProviderRef;
+
+}  // namespace common
+
+#endif  // COMMON_FILESYSTEM_FILESYSTEM_PROVIDER_H_
diff --git a/webWidgetTCT_device/src/common/filesystem/filesystem_provider_capiusb.cc b/webWidgetTCT_device/src/common/filesystem/filesystem_provider_capiusb.cc
new file mode 100755 (executable)
index 0000000..ece2af8
--- /dev/null
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2015 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 "filesystem_provider_capiusb.h"
+
+#include <string>
+#include "common/logger.h"
+#include "common/filesystem/storage.h"
+
+namespace {
+const char* kUsbDeviceMounted = "mounted";
+const char* kUsbDeviceRemoved = "removed";
+}
+
+namespace common {
+
+void FilesystemProviderCAPIUSB::OnUsbDeviceConnectionChange(
+    usb_device_h usb_device, char *action, void *user_data) {
+  LoggerD("Enter. Device: %x, action: %s", usb_device, action);
+  StorageState current_state = StorageState::kUnknown;
+  if (strcmp(action, kUsbDeviceMounted) == 0) {
+    LoggerD("Device mounted %s", usb_device_get_devname(usb_device));
+    current_state = StorageState::kMounted;
+  } else if (strcmp(action, kUsbDeviceRemoved) == 0) {
+    LoggerD("Device unmounted %s", usb_device_get_devname(usb_device));
+    current_state = StorageState::kUnmounted;
+  } else {
+    LoggerW("Ignoring since other actions. Action %s", action);
+    return;
+  }
+
+  FilesystemProviderCAPIUSB* provider =
+      static_cast<FilesystemProviderCAPIUSB*>(user_data);
+  StorageState previous_state = StorageState::kUnknown;
+  if( provider ) {
+    std::string label(
+        "removable_" + std::string(usb_device_get_devname(usb_device)));
+    for (auto &storage : provider->storages_) {
+      if (storage->name_ == label) {
+        previous_state = storage->state_;
+        storage->state_ = current_state;
+        if (provider->listener_) {
+          provider->listener_(*storage, previous_state, current_state);
+        }
+        return;
+      }
+    }
+    provider->AddDevice(usb_device);
+    if (provider->listener_) {
+      provider->listener_(*provider->storages_.back(), previous_state, current_state);
+    }
+  }
+  else {
+    LoggerW("Provider is dead");
+  }
+}
+
+FilesystemProviderCAPIUSB::FilesystemProviderCAPIUSB()
+    : virtual_roots_provider_( FilesystemProviderStorage::Create() ),
+      is_initialized_(false){
+  LoggerD("Entered");
+
+  storages_.push_back(GetInternalStorage());
+
+  LoggerD("Initializing usb device");
+  int err = usb_device_init();
+  if(err) {
+    LOGW("usb_device_init() failed");
+  }
+  else {
+    is_initialized_ = true;
+    usb_set_connected_cb(OnUsbDeviceConnectionChange, this);
+  }
+}
+
+FilesystemProviderCAPIUSB::~FilesystemProviderCAPIUSB() {
+  LoggerD("Entered");
+  usb_device_fini();
+}
+
+void FilesystemProviderCAPIUSB::RegisterDeviceChangeState(
+    DeviceChangeStateFun callback) {
+  LoggerD("Entered");
+
+  if(!is_initialized_) {
+    LoggerE("Capi Usb Core api not initialized");
+    return;
+  }
+
+  if(!listener_) {
+    LoggerD("Registering Callback function");
+    listener_ = callback;
+  }
+}
+
+void FilesystemProviderCAPIUSB::UnregisterDeviceChangeState() {
+  LoggerD("Entered");
+
+  if(!is_initialized_) {
+    LoggerE("Capi Usb Core api not initialized");
+    return;
+  }
+
+  listener_ = nullptr;
+}
+
+VirtualRoots FilesystemProviderCAPIUSB::GetVirtualPaths() {
+  LoggerD("Entered");
+
+  if(!is_initialized_) {
+    LoggerE("Capi Usb Core api not initialized");
+    return VirtualRoots();
+  }
+
+  return virtual_roots_provider_.GetVirtualPaths();
+}
+
+std::shared_ptr< Storage > FilesystemProviderCAPIUSB::GetInternalStorage() {
+  LoggerD("Entered");
+
+  return virtual_roots_provider_.GetInternalStorage();
+}
+
+Storages FilesystemProviderCAPIUSB::GetStorages() {
+  LoggerD("Entered");
+
+  if(!is_initialized_) {
+    LoggerE("Capi Usb Core api not initialized");
+    return storages_;
+  }
+
+  int no_ext_devices = usb_get_connected_device_number(USB_MASS_STORAGE);
+  LoggerD("Number of usb storages %d", no_ext_devices);
+  if (no_ext_devices > 0) {
+    usb_device_list_h device_list = nullptr;
+    int error = 0;
+    error = usb_device_get_device_list(USB_MASS_STORAGE, &device_list);
+    if (0 > error) {
+      LoggerE("Couldn't iterate over mass storages");
+    }
+    usb_device_h device = nullptr;
+    error = usb_device_list_get_first(device_list, &device);
+    if (0 > error) {
+      LoggerE("Couldn't get first element");
+      return storages_;
+    }
+    AddDevice(device);
+    int is_end = 0;
+    free_usb_device_h(device);
+    device = NULL;
+    do {
+      is_end = usb_device_list_get_next(device_list, &device);
+      if (0 > is_end)
+        break;
+      AddDevice(device);
+      free_usb_device_h(device);
+    } while (0 <= is_end);
+  }
+
+  LoggerD("After iteration over storages %d", storages_.size());
+  return storages_;
+}
+
+void FilesystemProviderCAPIUSB::AddDevice(usb_device_h usb_device) {
+  LoggerD("Device %s", usb_device_get_devname(usb_device));
+
+  StorageState state = StorageState::kMounted;
+  std::string label(
+      "removable_" + std::string(usb_device_get_devname(usb_device)));
+  for (auto &storage : storages_) {
+    if (storage->name_ == label) {
+      LoggerD("Device already added");
+      return;
+    }
+  }
+
+  LoggerD("Device %s has id %d", label.c_str(),
+          usb_device_get_address(usb_device));
+
+  storages_.push_back(std::make_shared<Storage>( Storage(usb_device_get_address(usb_device), StorageType::kExternal, state,
+                                                         usb_device_get_mountpath(usb_device), label) ));
+}
+
+FilesystemProviderCAPIUSB& FilesystemProviderCAPIUSB::Create() {
+  LoggerD("Entered");
+
+  static FilesystemProviderCAPIUSB fs;
+  return fs;
+}
+
+VirtualStorages FilesystemProviderCAPIUSB::GetAllStorages() {
+
+  if(!is_initialized_) {
+    LoggerE("Capi Usb Core api not initialized");
+    return VirtualStorages();
+  }
+
+  //This function has to be thread safe since it is available for diferent threads.
+  std::lock_guard<std::mutex> lock(mutex_);
+  VirtualStorages vs;
+  for (auto storage : GetStorages()) {
+    vs.push_back(storage);
+  }
+
+  for (auto virtualRoot : virtual_roots_provider_.GetVirtualPaths()) {
+    vs.push_back(std::make_shared < VirtualRoot > (virtualRoot));
+  }
+
+  return vs;
+}
+
+}  // namespace common
diff --git a/webWidgetTCT_device/src/common/filesystem/filesystem_provider_capiusb.h b/webWidgetTCT_device/src/common/filesystem/filesystem_provider_capiusb.h
new file mode 100755 (executable)
index 0000000..e730d27
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2015 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 COMMON_FILESYSTEM_FILESYSTEM_PROVIDER_CAPIUSB_H_
+#define COMMON_FILESYSTEM_FILESYSTEM_PROVIDER_CAPIUSB_H_
+
+#include <system/usb-device.h>
+#include <memory>
+#include <vector>
+#include <mutex>
+#include "common/filesystem/filesystem_provider.h"
+#include "common/filesystem/filesystem_provider_storage.h"
+
+namespace common {
+
+class FilesystemProviderCAPIUSB : public FilesystemProvider {
+ public:
+  virtual ~FilesystemProviderCAPIUSB();
+
+  virtual void RegisterDeviceChangeState(DeviceChangeStateFun callback);
+  virtual void UnregisterDeviceChangeState();
+
+  virtual Storages GetStorages();
+
+  static FilesystemProviderCAPIUSB& Create();
+
+  virtual VirtualRoots GetVirtualPaths();
+  virtual VirtualStorages GetAllStorages();
+  virtual std::shared_ptr<Storage> GetInternalStorage();
+
+ private:
+  FilesystemProviderCAPIUSB();
+  void AddDevice(usb_device_h usb_device);
+  static void OnUsbDeviceConnectionChange(usb_device_h usb_device, char *action,
+                                          void *user_data);
+
+  Storages storages_;
+  DeviceChangeStateFun listener_;
+  FilesystemProviderRef virtual_roots_provider_;
+
+  std::mutex mutex_;
+
+  bool is_initialized_;
+};
+
+}  // namespace common
+
+#endif  // COMMON_FILESYSTEM_FILESYSTEM_PROVIDER_CAPIUSB_H_
diff --git a/webWidgetTCT_device/src/common/filesystem/filesystem_provider_storage.cc b/webWidgetTCT_device/src/common/filesystem/filesystem_provider_storage.cc
new file mode 100755 (executable)
index 0000000..f8f623f
--- /dev/null
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 2015 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 "common/filesystem/filesystem_provider_storage.h"
+#include <algorithm>
+#include <map>
+#include "common/logger.h"
+#include "common/current_application.h"
+
+namespace {
+
+const std::string kVirtualRootCamera = "camera";
+const std::string kVirtualRootDocuments = "documents";
+const std::string kVirtualRootDownloads = "downloads";
+const std::string kVirtualRootImages = "images";
+const std::string kVirtualRootMusic = "music";
+const std::string kVirtualRootRingtones = "ringtones";
+const std::string kVirtualRootVideos = "videos";
+const std::string kVirtualRootWgtPackage = "wgt-package";
+const std::string kVirtualRootWgtPrivate = "wgt-private";
+const std::string kVirtualRootWgtPrivateTmp = "wgt-private-tmp";
+const std::string kVirtualRootMedia = "internal0";
+
+const std::map<storage_directory_e, const std::string*> kStorageDirectories = {
+    { STORAGE_DIRECTORY_CAMERA, &kVirtualRootCamera }, {
+        STORAGE_DIRECTORY_DOCUMENTS, &kVirtualRootDocuments }, {
+        STORAGE_DIRECTORY_DOWNLOADS, &kVirtualRootDownloads }, {
+        STORAGE_DIRECTORY_IMAGES, &kVirtualRootImages }, {
+        STORAGE_DIRECTORY_MUSIC, &kVirtualRootMusic }, {
+        STORAGE_DIRECTORY_SYSTEM_RINGTONES, &kVirtualRootRingtones }, {
+        STORAGE_DIRECTORY_VIDEOS, &kVirtualRootVideos } };
+
+const std::string kFileUriPrefix = "file://";
+
+}  // namespace
+
+namespace common {
+
+FilesystemProviderStorage::FilesystemProviderStorage(): internal_storage_(nullptr) {
+  LoggerD("Entered");
+  int err = storage_foreach_device_supported(OnForeachStorage, this);
+  if (err != STORAGE_ERROR_NONE) {
+    LoggerE("Unknown Error on getting storage paths");
+  }
+}
+
+FilesystemProviderStorage& FilesystemProviderStorage::Create() {
+  static FilesystemProviderStorage fs;
+  return fs;
+}
+
+FilesystemProviderStorage::~FilesystemProviderStorage() {
+}
+
+bool FilesystemProviderStorage::OnForeachStorage(int storage_id,
+                                                 storage_type_e type,
+                                                 storage_state_e state,
+                                                 const char* path,
+                                                 void* user_data) {
+  LoggerD("Entered, id: %d", storage_id);
+  FilesystemProviderStorage* provider =
+      static_cast<FilesystemProviderStorage*>(user_data);
+
+#ifndef TIZEN_TV
+  int err = storage_set_state_changed_cb(storage_id, OnStorageChange, provider);
+  if (STORAGE_ERROR_NONE != err) {
+    LoggerW("Failed to add listener");
+  }
+#endif
+
+  StorageType type_ = type == STORAGE_TYPE_INTERNAL ? StorageType::kInternal : StorageType::kExternal;
+  StorageState state_ = StorageState::kUnknown;
+  if( state == STORAGE_STATE_REMOVED) {
+    state_ = StorageState::kUnmounted;
+  }
+  else if( state == STORAGE_STATE_MOUNTED || state == STORAGE_STATE_MOUNTED_READ_ONLY ) {
+    state_ = StorageState::kMounted;
+  }
+  else {
+    state_ = StorageState::kUnmountable;
+  }
+
+#ifndef TIZEN_TV
+  provider->storages_.push_back( std::make_shared<Storage>( Storage(storage_id, type_, state_, path) ) );
+#endif
+  if (type_ == StorageType::kInternal) {
+    provider->internal_storage_ = std::make_shared<Storage>(Storage(storage_id, type_, state_, path, kVirtualRootMedia));
+    // if internal storage is supported, we can add also virtual paths:
+    // downloads, documents etc
+    provider->FillVirtualPaths(storage_id);
+  }
+  return true;
+}
+
+void FilesystemProviderStorage::FillVirtualPaths(int storage_id) {
+  LoggerD("Creating virtual paths for storage: %d", storage_id);
+  for (auto& item : kStorageDirectories) {
+    char* dir_path = nullptr;
+    storage_directory_e dir_enum = item.first;
+    int err = storage_get_directory(storage_id, dir_enum, &dir_path);
+    if (STORAGE_ERROR_NONE == err && nullptr != dir_path) {
+      virtual_paths_.push_back(VirtualRoot(*(item.second), dir_path));
+      free(dir_path);
+    }
+  }
+
+  // fill also virtual paths based on current application install dir
+  std::string root = common::CurrentApplication::GetInstance().GetRoot();
+  if (!root.empty()) {
+    virtual_paths_.push_back(
+        VirtualRoot(kVirtualRootWgtPackage, root + "/res/wgt"));
+    virtual_paths_.push_back(VirtualRoot(kVirtualRootWgtPrivate, root + "/data"));
+    virtual_paths_.push_back(
+        VirtualRoot(kVirtualRootWgtPrivateTmp, root + "/tmp"));
+  }
+}
+
+void FilesystemProviderStorage::OnStorageChange(int storage_id,
+                                                storage_state_e state,
+                                                void* user_data) {
+  LoggerD("Entered, id: %d", storage_id);
+
+  FilesystemProviderStorage* provider =
+      static_cast<FilesystemProviderStorage*>(user_data);
+  for (auto &storage : provider->storages_) {
+    if (storage->id_ == storage_id) {
+      StorageState current_state = StorageState::kUnknown;
+      if( state == STORAGE_STATE_REMOVED)
+        current_state = StorageState::kUnmounted;
+      else if( state == STORAGE_STATE_MOUNTED || state == STORAGE_STATE_MOUNTED_READ_ONLY ) {
+        current_state = StorageState::kMounted;
+      }
+      else {
+        current_state = StorageState::kUnmountable;
+      }
+      StorageState previous_state = storage->state_;
+      storage->state_ = current_state;
+      if (provider->listener_) {
+        provider->listener_(*storage, previous_state, current_state);
+      }
+      break;
+    }
+  }
+}
+
+void FilesystemProviderStorage::RegisterDeviceChangeState(
+    DeviceChangeStateFun callback) {
+  LoggerD("Entered");
+  listener_ = callback;
+}
+
+void FilesystemProviderStorage::UnregisterDeviceChangeState() {
+  LoggerD("Entered");
+  listener_ = nullptr;
+}
+
+Storages FilesystemProviderStorage::GetStorages() {
+  return storages_;
+}
+
+VirtualRoots FilesystemProviderStorage::GetVirtualPaths() {
+  return virtual_paths_;
+}
+
+std::string FilesystemProviderStorage::GetRealPath(
+    const std::string& path_or_uri) {
+  LoggerD("Enter");
+  std::string realpath;
+  std::size_t pos = path_or_uri.find(kFileUriPrefix);
+  if (pos != std::string::npos) {
+    realpath = path_or_uri.substr(pos + kFileUriPrefix.size());
+  } else {
+    realpath = path_or_uri;
+  }
+  pos = realpath.find('/');
+  if (pos != 0) {
+    const std::string prefix = realpath.substr(0, pos);
+    const auto it = std::find_if(virtual_paths_.begin(), virtual_paths_.end(),
+                                 [prefix](const common::VirtualRoot & vr) {
+                                   return vr.name_ == prefix;
+                                 });
+    if (it != virtual_paths_.end()) {
+      realpath.replace(0, prefix.size(), it->path_);
+    } else {
+      LoggerE("Unknown virtual root");
+    }
+  }
+  return realpath;
+}
+
+std::shared_ptr< Storage > FilesystemProviderStorage::GetInternalStorage(){
+  return internal_storage_;
+}
+
+VirtualStorages FilesystemProviderStorage::GetAllStorages() {
+  VirtualStorages vs;
+  for (auto storage : storages_) {
+    vs.push_back(storage);
+  }
+
+  for (auto virtualRoot : virtual_paths_) {
+    vs.push_back(std::make_shared < VirtualRoot > (virtualRoot));
+  }
+
+  return vs;
+}
+
+}  // namespace common
diff --git a/webWidgetTCT_device/src/common/filesystem/filesystem_provider_storage.h b/webWidgetTCT_device/src/common/filesystem/filesystem_provider_storage.h
new file mode 100755 (executable)
index 0000000..e530c1d
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2015 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 COMMON_FILESYSTEM_FILESYSTEM_PROVIDER_STORAGE_H_
+#define COMMON_FILESYSTEM_FILESYSTEM_PROVIDER_STORAGE_H_
+
+#include "common/filesystem/filesystem_provider.h"
+#include <storage.h>
+#include <string>
+#include <memory>
+
+namespace common {
+
+class FilesystemProviderStorage : public FilesystemProvider {
+ public:
+  static FilesystemProviderStorage& Create();
+  virtual ~FilesystemProviderStorage();
+
+  virtual void RegisterDeviceChangeState(DeviceChangeStateFun callback);
+  virtual void UnregisterDeviceChangeState();
+
+  virtual Storages GetStorages();
+  virtual VirtualRoots GetVirtualPaths();
+  virtual VirtualStorages GetAllStorages();
+  virtual std::shared_ptr< Storage > GetInternalStorage();
+
+  std::string GetRealPath(const std::string& path_or_uri);
+
+ private:
+  FilesystemProviderStorage();
+
+  static bool OnForeachStorage(int storage_id, storage_type_e type,
+                               storage_state_e state, const char *path,
+                               void *user_data);
+  static void OnStorageChange(int storage_id, storage_state_e state,
+                              void *user_data);
+  /**
+   * For given storage_id try to get paths for virtual paths.
+   * For example for storage_id (which has type INTERNAL) it will
+   * add to storages virtual paths: downloads with real path /opt/usr/media/Downloads
+   */
+  void FillVirtualPaths(int storage_id);
+  DeviceChangeStateFun listener_;
+  Storages storages_;
+  VirtualRoots virtual_paths_;
+  std::shared_ptr<Storage> internal_storage_;
+};
+
+}  // namespace common
+
+#endif  // COMMON_FILESYSTEM_FILESYSTEM_PROVIDER_STORAGE_H_
diff --git a/webWidgetTCT_device/src/common/filesystem/storage.cc b/webWidgetTCT_device/src/common/filesystem/storage.cc
new file mode 100755 (executable)
index 0000000..4cf7aef
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2015 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 "common/filesystem/storage.h"
+#include <string>
+#include "common/logger.h"
+
+namespace common {
+
+VirtualRoot::VirtualRoot(std::string const& name, std::string const& path,
+                         StorageType type, StorageState state)
+    : name_(name),
+      path_(path),
+      type_(type),
+      state_(state) {
+}
+
+Storage::Storage(int id, StorageType type, StorageState state,
+                 std::string const& path, std::string const& name)
+    : VirtualRoot(name, path, type, state),
+      id_(id) {
+  LoggerD("Enter");
+  if (name_ == "") {
+    switch (type) {
+      case StorageType::kInternal:
+        name_ = "internal";
+        break;
+
+      case StorageType::kExternal:
+        name_ = "removable";
+        break;
+
+      default:
+        name_ = "unknown";
+        LoggerE("Unknown storage type: %d", type);
+        break;
+    }
+    name_ += std::to_string(id);
+  }
+}
+
+picojson::value VirtualRoot::ToJson() const {
+  picojson::value v { picojson::object { } };
+  picojson::object& obj = v.get<picojson::object>();
+
+  obj["type"] = picojson::value(ToString(type_));
+  obj["state"] = picojson::value(ToString(state_));
+  obj["path"] = picojson::value(path_);
+  obj["name"] = picojson::value(name_);
+
+  return v;
+}
+
+picojson::value Storage::ToJson() const {
+  picojson::value value = VirtualRoot::ToJson();
+  picojson::object& obj = value.get<picojson::object>();
+  obj["storage_id"] = picojson::value(static_cast<double>(id_));
+  return value;
+}
+
+Storage::Storage(Storage const& other)
+    : VirtualRoot(other) {
+  this->id_ = other.id_;
+}
+
+Storage& Storage::operator=(Storage const& other) {
+  this->path_ = other.path_;
+  this->name_ = other.name_;
+  this->state_ = other.state_;
+  this->type_ = other.type_;
+  this->id_ = other.id_;
+  return *this;
+}
+
+VirtualRoot::VirtualRoot(VirtualRoot const& other) {
+  this->path_ = other.path_;
+  this->name_ = other.name_;
+  this->state_ = other.state_;
+  this->type_ = other.type_;
+}
+
+VirtualRoot& VirtualRoot::operator=(VirtualRoot const& other) {
+  this->path_ = other.path_;
+  this->name_ = other.name_;
+  this->state_ = other.state_;
+  this->type_ = other.type_;
+  return *this;
+}
+
+std::string VirtualRoot::ToString(StorageType type) {
+  switch (type) {
+    case StorageType::kInternal:
+      return "INTERNAL";
+
+    case StorageType::kExternal:
+      return "EXTERNAL";
+
+    default:
+      LoggerE("Unknown storage type: %d", type);
+      return "UNKNOWN";
+  }
+}
+
+std::string VirtualRoot::ToString(StorageState state) {
+  switch (state) {
+    case StorageState::kUnmounted:
+      return "REMOVED";
+    case StorageState::kUnmountable:
+      return "UNMOUNTABLE";
+    case StorageState::kMounted:
+      return "MOUNTED";
+    default:
+      LoggerE("Unknown storage state: %d", state);
+      return "UNKNOWN";
+  }
+}
+
+}  // namespace common
diff --git a/webWidgetTCT_device/src/common/filesystem/storage.h b/webWidgetTCT_device/src/common/filesystem/storage.h
new file mode 100755 (executable)
index 0000000..53081ff
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2015 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 COMMON_FILESYSTEM_STORAGE_H_
+#define COMMON_FILESYSTEM_STORAGE_H_
+
+#include <string>
+#include "common/picojson.h"
+
+namespace common {
+
+enum class StorageState {
+  kMounted,
+  kUnmounted,
+  kUnmountable,
+  kUnknown
+};
+
+enum class StorageType {
+  kInternal,
+  kExternal,
+  kUnknown
+};
+
+class VirtualStorage {
+ public:
+  virtual picojson::value ToJson() const = 0;
+  virtual ~VirtualStorage() {
+  }
+
+  virtual std::string path() const = 0;
+  virtual std::string name() const = 0;
+  virtual StorageType type() const = 0;
+  virtual StorageState state() const = 0;
+};
+
+class VirtualRoot : public VirtualStorage {
+ public:
+  VirtualRoot(std::string const& name, std::string const & path,
+              StorageType type = StorageType::kInternal, StorageState state = StorageState::kMounted);
+  VirtualRoot(VirtualRoot const& other);
+  VirtualRoot& operator=(VirtualRoot const& other);
+
+  std::string name_;
+  std::string path_;
+  StorageType type_;
+  StorageState state_;
+  virtual picojson::value ToJson() const;
+  virtual std::string path() const{
+    return path_;
+  }
+  virtual std::string name() const {
+    return name_;
+  }
+  virtual StorageType type() const{
+    return type_;
+  }
+  virtual StorageState state() const{
+    return state_;
+  }
+
+  static std::string ToString(StorageType type);
+  static std::string ToString(StorageState state);
+};
+
+class Storage : public VirtualRoot {
+ public:
+  virtual ~Storage() {
+  }
+
+  Storage() : VirtualRoot("","", StorageType::kUnknown, StorageState::kUnknown ), id_(-1) {}
+
+  Storage(int id, StorageType type, StorageState state,
+          std::string const& path = "", std::string const& name = "");
+  Storage(Storage const& other);
+  Storage& operator=(Storage const& other);
+
+  int id_;
+  virtual picojson::value ToJson() const;
+};
+
+}  // namespace common
+
+#endif  // COMMON_FILESYSTEM_STORAGE_H_
diff --git a/webWidgetTCT_device/src/common/filter-utils.cc b/webWidgetTCT_device/src/common/filter-utils.cc
new file mode 100755 (executable)
index 0000000..9859d90
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2015 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 "common/filter-utils.h"
+
+#include "common/logger.h"
+#include "common/converter.h"
+
+namespace common {
+
+PlatformResult AttributeMatchFlagFromString(
+    const std::string &str, AttributeMatchFlag *filter_match_flag) {
+  LoggerD("Enter");
+  if (str == "EXACTLY") {
+    *filter_match_flag = AttributeMatchFlag::kExactly;
+  } else if (str == "FULLSTRING") {
+    *filter_match_flag = AttributeMatchFlag::kFullString;
+  } else if (str == "CONTAINS") {
+    *filter_match_flag = AttributeMatchFlag::kContains;
+  } else if (str == "STARTSWITH") {
+    *filter_match_flag = AttributeMatchFlag::kStartsWith;
+  } else if (str == "ENDSWITH") {
+    *filter_match_flag = AttributeMatchFlag::kEndsWith;
+  } else if (str == "EXISTS") {
+    *filter_match_flag = AttributeMatchFlag::kExists;
+  } else {
+    LoggerE("Invalid attribute match string: %i", str.c_str());
+    return PlatformResult(ErrorCode::INVALID_VALUES_ERR,
+                          "Invalid attribute match string!");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CompositeFilterTypeFromString(
+    const std::string &str, CompositeFilterType *comp_filter_type) {
+  LoggerD("Enter");
+  if (str == "UNION") {
+    *comp_filter_type = CompositeFilterType::kUnion;
+  } else if (str == "INTERSECTION") {
+    *comp_filter_type = CompositeFilterType::kIntersection;
+  } else {
+    LoggerE("Invalid composite type string: %i", str.c_str());
+
+    return PlatformResult(ErrorCode::INVALID_VALUES_ERR,
+                          "Invalid composite type string!");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+void FilterVisitor::SetOnAttributeFilter(const AttributeFilterOnVisit &func) {
+  LoggerD("Enter");
+  m_attributeFilterOnVisit = func;
+}
+
+void FilterVisitor::SetOnAttributeRangeFilter(const AttributeRangeFilterOnVisit &func) {
+  LoggerD("Enter");
+  m_attributeRangeFilterOnVisit = func;
+}
+
+void FilterVisitor::SetOnCompositeFilterBegin(const CompositeFilterOnBegin &func) {
+  LoggerD("Enter");
+  m_compositeFilterOnBegin = func;
+}
+
+void FilterVisitor::SetOnCompositeFilterEnd(const CompositeFilterOnEnd &func) {
+  LoggerD("Enter");
+  m_compositeFilterOnEnd = func;
+}
+
+PlatformResult FilterVisitor::Visit(const picojson::object &filter) {
+  LoggerD("Enter");
+  const std::string &filterType = FromJson<std::string>(filter, "filterType");
+  if (filterType == "AttributeFilter") {
+    PlatformResult status = VisitAttributeFilter(filter);
+    if (status.IsError()) return status;
+  } else if (filterType == "AttributeRangeFilter") {
+    PlatformResult status = VisitAttributeRangeFilter(filter);
+    if (status.IsError()) return status;
+  } else if (filterType == "CompositeFilter") {
+    PlatformResult status = VisitCompositeFilter(filter);
+    if (status.IsError()) return status;
+  } else {
+    LoggerE("Invalid filter type!");
+    return PlatformResult(ErrorCode::INVALID_VALUES_ERR,
+                          "Invalid filter type!");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult FilterVisitor::VisitAttributeFilter(
+    const picojson::object &filter) {
+  LoggerD("Enter");
+  const std::string &attribute_name =
+      FromJson<std::string>(filter, "attributeName");
+
+  AttributeMatchFlag match_flag;
+  PlatformResult status = AttributeMatchFlagFromString(
+      FromJson<std::string>(filter, "matchFlag"), &match_flag);
+  if (status.IsError()) return status;
+
+  const picojson::value &match_value = FindValue(filter, "matchValue");
+
+  if (m_attributeFilterOnVisit) {
+    status = m_attributeFilterOnVisit(attribute_name, match_flag, match_value);
+    if (status.IsError()) return status;
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult FilterVisitor::VisitAttributeRangeFilter(
+    const picojson::object &filter) {
+  LoggerD("Enter");
+  const std::string &attributeName =
+      FromJson<std::string>(filter, "attributeName");
+  const picojson::value &initialValue = FindValue(filter, "initialValue");
+  const picojson::value &endValue = FindValue(filter, "endValue");
+
+  if (m_attributeRangeFilterOnVisit) {
+    PlatformResult status =
+        m_attributeRangeFilterOnVisit(attributeName, initialValue, endValue);
+    if (status.IsError()) return status;
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult FilterVisitor::VisitCompositeFilter(
+    const picojson::object &filter) {
+  LoggerD("Enter");
+  CompositeFilterType filter_type;
+  PlatformResult status = CompositeFilterTypeFromString(
+      FromJson<std::string>(filter, "type"), &filter_type);
+  if (status.IsError()) return status;
+
+  const picojson::array &filters = FromJson<picojson::array>(filter, "filters");
+
+  if (m_compositeFilterOnBegin) {
+    status = m_compositeFilterOnBegin(filter_type);
+    if (status.IsError()) return status;
+  }
+
+  for (std::size_t i = 0; i < filters.size(); ++i) {
+    PlatformResult status = Visit(JsonCast<picojson::object>(filters[i]));
+    if (status.IsError()) return status;
+  }
+
+  if (m_compositeFilterOnEnd) {
+    status = m_compositeFilterOnEnd(filter_type);
+    if (status.IsError()) return status;
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+}
diff --git a/webWidgetTCT_device/src/common/filter-utils.h b/webWidgetTCT_device/src/common/filter-utils.h
new file mode 100755 (executable)
index 0000000..daa7cc4
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2015 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 WEBAPI_PLUGINS_COMMON_FILTER_UTILS_H_
+#define WEBAPI_PLUGINS_COMMON_FILTER_UTILS_H_
+
+#include <functional>
+#include <memory>
+
+#include "picojson.h"
+#include "platform_result.h"
+
+namespace common {
+
+enum PrimitiveType {
+    kPrimitiveTypeBoolean,
+    kPrimitiveTypeString,
+    kPrimitiveTypeLong,
+    kPrimitiveTypeId
+};
+
+enum class AttributeMatchFlag {
+    kExactly,
+    kFullString,
+    kContains,
+    kStartsWith,
+    kEndsWith,
+    kExists
+};
+
+PlatformResult AttributeMatchFlagFromString(
+    const std::string& str, AttributeMatchFlag* filter_match_flag);
+
+enum class CompositeFilterType {
+    kUnion,
+    kIntersection
+};
+
+PlatformResult CompositeFilterTypeFromString(
+    const std::string& str, CompositeFilterType* comp_filter_type);
+
+typedef std::function<PlatformResult(const std::string&, AttributeMatchFlag,
+                                     const picojson::value&)>
+    AttributeFilterOnVisit;
+
+typedef std::function<PlatformResult(const std::string&, const picojson::value&,
+                                     const picojson::value&)>
+    AttributeRangeFilterOnVisit;
+
+typedef std::function<PlatformResult(CompositeFilterType)>
+    CompositeFilterOnBegin;
+
+typedef std::function<PlatformResult(CompositeFilterType)> CompositeFilterOnEnd;
+
+/**
+ * @brief The FilterVisitor class
+ * A helper class to convert Tizen filters stored as JSON data to native object.
+ * User should set callbacks to react on each of Tizen filters detected.
+ */
+class FilterVisitor {
+  public:
+    /**
+     * @brief Sets callback to be invoked on AttributeFilter.
+     *
+     * @param[in] func - callback with arguments:
+     *  - std::string AttributeName
+     *  - AttributeMatchFlag flag
+     *  - picojson::value matchValue
+     */
+    void SetOnAttributeFilter(const AttributeFilterOnVisit& func);
+
+    /**
+     * @brief Sets callback to be invoked on AttributeRangeFilter.
+     *
+     * @param[in] func - callback with arguments:
+     *  - std::string AttributeName
+     *  - picojson::value initialValue
+     *  - picojson::value endValue
+     */
+    void SetOnAttributeRangeFilter(const AttributeRangeFilterOnVisit& func);
+
+    /**
+     * @brief Sets callback to be invoked on begin of CompositeFilter.
+     *
+     * @param[in] func - callback with arguments:
+     *  - CompositeFilterType type
+     */
+    void SetOnCompositeFilterBegin(const CompositeFilterOnBegin& func);
+
+    /**
+     * @brief Sets callback to be invoked on end of CompositeFilter.
+     *
+     * @param[in] func - callback with no arguments
+     */
+    void SetOnCompositeFilterEnd(const CompositeFilterOnEnd& func);
+
+    /**
+     * @brief Parses a json object as Tizen filter.
+     * @param filter Object to be visited
+     */
+    PlatformResult Visit(const picojson::object& filter);
+
+private:
+    PlatformResult VisitAttributeFilter(const picojson::object& filter);
+    PlatformResult VisitAttributeRangeFilter(const picojson::object& filter);
+    PlatformResult VisitCompositeFilter(const picojson::object& filter);
+
+    AttributeFilterOnVisit m_attributeFilterOnVisit;
+    AttributeRangeFilterOnVisit m_attributeRangeFilterOnVisit;
+    CompositeFilterOnBegin m_compositeFilterOnBegin;
+    CompositeFilterOnEnd m_compositeFilterOnEnd;
+};
+
+}  // namespace common
+
+#endif  // WEBAPI_PLUGINS_COMMON_FILTER_UTILS_H_
diff --git a/webWidgetTCT_device/src/common/logger.cc b/webWidgetTCT_device/src/common/logger.cc
new file mode 100755 (executable)
index 0000000..bd3db74
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2014 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "common/logger.h"
+
+LogMessage::LogMessage(const char* file, const char* function, int line,
+    log_priority priority)
+    : file_(file),
+      function_(function),
+      line_(line),
+      priority_(priority) {}
+
+LogMessage::~LogMessage() {
+  __dlog_print(LOG_ID_MAIN, priority_, LOGGER_TAG, "%s: %s(%d) > %s",
+      file_, function_, line_, stream_.str().c_str());
+}
diff --git a/webWidgetTCT_device/src/common/logger.h b/webWidgetTCT_device/src/common/logger.h
new file mode 100755 (executable)
index 0000000..5240724
--- /dev/null
@@ -0,0 +1,94 @@
+// Copyright 2014 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMMON_LOGGER_H_
+#define COMMON_LOGGER_H_
+
+#include <dlog.h>
+#include <string>
+#include <cstring>
+#include <sstream>
+
+#include "common/utils.h"
+
+#undef LOGGER_TAG
+#define LOGGER_TAG "WEBAPI_PLUGINS"
+
+#define _LOGGER_LOG(prio, fmt, args...) \
+  LOG_(LOG_ID_MAIN, prio, LOGGER_TAG, fmt, ##args)
+
+#define _LOGGER_SLOG(prio, fmt, args...) \
+  SECURE_LOG_(LOG_ID_MAIN, prio, LOGGER_TAG, fmt, ##args)
+
+#define LoggerD(fmt, args...) _LOGGER_LOG(DLOG_DEBUG, fmt, ##args)
+#define LoggerI(fmt, args...) _LOGGER_LOG(DLOG_INFO, fmt, ##args)
+#define LoggerW(fmt, args...) _LOGGER_LOG(DLOG_WARN, fmt, ##args)
+#define LoggerE(fmt, args...) _LOGGER_LOG(DLOG_ERROR, fmt, ##args)
+
+#define SLoggerD(fmt, args...) _LOGGER_SLOG(DLOG_DEBUG, fmt, ##args)
+#define SLoggerI(fmt, args...) _LOGGER_SLOG(DLOG_INFO, fmt, ##args)
+#define SLoggerW(fmt, args...) _LOGGER_SLOG(DLOG_WARN, fmt, ##args)
+#define SLoggerE(fmt, args...) _LOGGER_SLOG(DLOG_ERROR, fmt, ##args)
+
+// A few definitions of macros that don't generate much code. These are used
+// by LOGGER() and LOGGER_IF, etc. Since these are used all over our code, it's
+// better to have compact code for these operations.
+#ifdef TIZEN_DEBUG_ENABLE
+#define COMPACT_LOG_DEBUG \
+  LogMessage(__MODULE__, __func__, __LINE__, DLOG_DEBUG).stream()
+#else
+#define COMPACT_LOG_DEBUG \
+  true ? (void) 0 : LogMessageVoidify() & (std::ostringstream())
+#endif
+
+#define COMPACT_LOG_INFO \
+  LogMessage(__MODULE__, __func__, __LINE__, DLOG_INFO).stream()
+#define COMPACT_LOG_WARN \
+  LogMessage(__MODULE__, __func__, __LINE__, DLOG_WARN).stream()
+#define COMPACT_LOG_ERROR \
+  LogMessage(__MODULE__, __func__, __LINE__, DLOG_ERROR).stream()
+
+#define LOGGER(priority) COMPACT_LOG_ ## priority
+#define LOGGER_IF(priority, condition) \
+  !(condition) ? (void) 0 : LogMessageVoidify() & (LOGGER(priority))
+
+// This class more or less represents a particular log message.
+// You create an instance of LogMessage and then stream stuff to it.
+// When you finish streaming to it, ~LogMessage is called and the
+// full message gets streamed to dlog.
+//
+// You shouldn't actually use LogMessage's constructor to log things,
+// though. You should use the LOGGER() macro (and variants thereof) above.
+class LogMessage {
+ public:
+  LogMessage(const char* file, const char* function, int line,
+      log_priority priority);
+  ~LogMessage();
+
+  std::ostream& stream() { return stream_; }
+
+ private:
+  const char* file_;
+  const char* function_;
+  const int line_;
+  log_priority priority_;
+
+  std::ostringstream stream_;
+
+  DISALLOW_COPY_AND_ASSIGN(LogMessage);
+};
+
+// This class is used to explicitly ignore values in the conditional
+// logging macros. This avoids compiler warnings like "value computed
+// is not used" and "statement has no effect".
+class LogMessageVoidify {
+public:
+  LogMessageVoidify() {}
+
+  // This has to be an operator with a precedence lower than << but
+  // higher than ?:
+  void operator&(std::ostream &) {}
+};
+
+#endif // COMMON_LOGGER_H_
diff --git a/webWidgetTCT_device/src/common/optional.h b/webWidgetTCT_device/src/common/optional.h
new file mode 100755 (executable)
index 0000000..232a745
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2015 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 COMMON_OPTIONAL_H_
+#define COMMON_OPTIONAL_H_
+
+#if __GNUC__ >= 4 && __GNUC_MINOR__ >= 8
+  #define ALIGNAS_TYPE(x) alignas(x)
+  #define ALIGNAS(x) alignas(x)
+#else
+  #define ALIGNAS_TYPE(x) __attribute__((__aligned__(__alignof(x))))
+  #define ALIGNAS(x) __attribute__((aligned(x)))
+#endif
+
+
+#include <new>
+#include <utility>
+#include <type_traits>
+#include "common/assert.h"
+
+namespace common {
+
+template<typename T>
+class optional {
+  static_assert(!std::is_reference<T>::value, "reference is not supported");
+
+ public:
+  optional() : exist_(false) {}
+  optional(std::nullptr_t) : exist_(false) {}
+  optional(const optional& rhs): exist_(rhs.exist_) { create(rhs); }
+  optional(optional&& rhs): exist_(rhs.exist_) { create(std::move(rhs)); }
+  optional(const T& v): exist_(true) { create(v); }
+  ~optional() { if (exist_) destroy(); }
+
+  bool operator !() const { return !exist_; }
+  explicit operator bool() const { return exist_; }
+
+  optional& operator = (const optional& rhs) { return assign(rhs); }
+  optional& operator = (optional&& rhs) { return assign(std::move(rhs)); }
+  optional& operator = (std::nullptr_t) {if (exist_) cleanup(); return *this; }
+  optional& operator = (const T& v) { return assign(v); }
+
+  const T& operator * () const { return *get(); }
+  T& operator * () { return *get(); }
+  const T* operator -> () const { return get(); }
+  T* operator -> () { return get(); }
+
+ private:
+  void create(const T& v) {
+    new(value_) T(v);
+  }
+  void create(T&& v) {
+    new(value_) T(std::move(v));
+  }
+  void create(const optional& rhs) {
+    if (exist_) create(*rhs.get());
+  }
+  void create(optional&& rhs) {
+    if (exist_) create(std::move(*rhs.get()));
+  }
+  void destroy() {
+    get()->~T();
+  }
+  const T* get() const {
+    Assert(exist_);
+    return reinterpret_cast<const T*>(value_);
+  }
+
+  T* get() {
+    Assert(exist_);
+    return reinterpret_cast<T*>(value_);
+  }
+
+  void cleanup() {
+    destroy();
+    exist_ = false;
+  }
+
+  optional& assign(const T& v) {
+    if (exist_) {
+      *get() = v;
+    } else {
+      create(v);
+      exist_ = true;
+    }
+    return *this;
+  }
+
+  optional& assign(const optional& rhs) {
+    if (rhs.exist_) return assign(*rhs.get());
+    if (!exist_) return *this;
+    cleanup();
+    return *this;
+  }
+
+  optional& assign(optional&& rhs) {
+    if (rhs.exist_) return assign(std::move(*rhs.get()));
+    if (!exist_) return *this;
+    cleanup();
+    return *this;
+  }
+
+  bool exist_;
+  ALIGNAS_TYPE(T) char value_[sizeof(T)];
+};
+
+}  // namespace common
+
+#undef ALIGNAS_TYPE
+#undef ALIGNAS
+
+#endif  // COMMON_OPTIONAL_H_
diff --git a/webWidgetTCT_device/src/common/picojson.h b/webWidgetTCT_device/src/common/picojson.h
new file mode 100755 (executable)
index 0000000..6921b1f
--- /dev/null
@@ -0,0 +1,1037 @@
+/*
+ * Copyright 2009-2010 Cybozu Labs, Inc.
+ * Copyright 2011 Kazuho Oku
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY CYBOZU LABS, INC. ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL CYBOZU LABS, INC. OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * The views and conclusions contained in the software and documentation are
+ * those of the authors and should not be interpreted as representing official
+ * policies, either expressed or implied, of Cybozu Labs, Inc.
+ *
+ */
+#ifndef picojson_h
+#define picojson_h
+
+#include <algorithm>
+#include <cmath>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <iostream>
+#include <iterator>
+#include <map>
+#include <string>
+#include <vector>
+#include "common/assert.h"
+
+#ifdef _MSC_VER
+    #define SNPRINTF _snprintf_s
+    #pragma warning(push)
+    #pragma warning(disable : 4244) // conversion from int to char
+#else
+    #define SNPRINTF snprintf
+#endif
+
+namespace picojson {
+  
+  enum {
+    null_type,
+    boolean_type,
+    number_type,
+    string_type,
+    array_type,
+    object_type
+  };
+  
+  struct null {};
+  
+  class value {
+  public:
+    typedef std::vector<value> array;
+    typedef std::map<std::string, value> object;
+    union _storage {
+      bool boolean_;
+      double number_;
+      std::string* string_;
+      array* array_;
+      object* object_;
+    };
+  protected:
+    int type_;
+    _storage u_;
+  public:
+    value();
+    value(int type, bool);
+    explicit value(bool b);
+    explicit value(double n);
+    explicit value(const std::string& s);
+    explicit value(const array& a);
+    explicit value(const object& o);
+    explicit value(const char* s);
+    value(const char* s, size_t len);
+    ~value();
+    value(const value& x);
+    value& operator=(const value& x);
+    void swap(value& x);
+    template <typename T> bool is() const;
+    template <typename T> const T& get() const;
+    template <typename T> T& get();
+    bool evaluate_as_boolean() const;
+    const value& get(size_t idx) const;
+    const value& get(const std::string& key) const;
+    bool contains(size_t idx) const;
+    bool contains(const std::string& key) const;
+    std::string to_str() const;
+    template <typename Iter> void serialize(Iter os) const;
+    std::string serialize() const;
+  private:
+    template <typename T> value(const T*); // intentionally defined to block implicit conversion of pointer to bool
+  };
+  
+  typedef value::array array;
+  typedef value::object object;
+  
+  inline value::value() : type_(null_type) {}
+  
+  inline value::value(int type, bool) : type_(type) {
+    switch (type) {
+#define INIT(p, v) case p##type: u_.p = v; break
+      INIT(boolean_, false);
+      INIT(number_, 0.0);
+      INIT(string_, new std::string());
+      INIT(array_, new array());
+      INIT(object_, new object());
+#undef INIT
+    default: break;
+    }
+  }
+  
+  inline value::value(bool b) : type_(boolean_type) {
+    u_.boolean_ = b;
+  }
+  
+  inline value::value(double n) : type_(number_type) {
+    u_.number_ = n;
+  }
+  
+  inline value::value(const std::string& s) : type_(string_type) {
+    u_.string_ = new std::string(s);
+  }
+  
+  inline value::value(const array& a) : type_(array_type) {
+    u_.array_ = new array(a);
+  }
+  
+  inline value::value(const object& o) : type_(object_type) {
+    u_.object_ = new object(o);
+  }
+  
+  inline value::value(const char* s) : type_(string_type) {
+    u_.string_ = new std::string(s);
+  }
+  
+  inline value::value(const char* s, size_t len) : type_(string_type) {
+    u_.string_ = new std::string(s, len);
+  }
+  
+  inline value::~value() {
+    switch (type_) {
+#define DEINIT(p) case p##type: delete u_.p; break
+      DEINIT(string_);
+      DEINIT(array_);
+      DEINIT(object_);
+#undef DEINIT
+    default: break;
+    }
+  }
+  
+  inline value::value(const value& x) : type_(x.type_) {
+    switch (type_) {
+#define INIT(p, v) case p##type: u_.p = v; break
+      INIT(string_, new std::string(*x.u_.string_));
+      INIT(array_, new array(*x.u_.array_));
+      INIT(object_, new object(*x.u_.object_));
+#undef INIT
+    default:
+      u_ = x.u_;
+      break;
+    }
+  }
+  
+  inline value& value::operator=(const value& x) {
+    if (this != &x) {
+      this->~value();
+      new (this) value(x);
+    }
+    return *this;
+  }
+  
+  inline void value::swap(value& x) {
+    std::swap(type_, x.type_);
+    std::swap(u_, x.u_);
+  }
+  
+#define IS(ctype, jtype)                            \
+  template <> inline bool value::is<ctype>() const { \
+    return type_ == jtype##_type;                   \
+  }
+  IS(null, null)
+  IS(bool, boolean)
+  IS(int, number)
+  IS(double, number)
+  IS(std::string, string)
+  IS(array, array)
+  IS(object, object)
+#undef IS
+  
+#define GET(ctype, var)                                                \
+  template <> inline const ctype& value::get<ctype>() const {  \
+    Assert("type mismatch! call vis<type>() before get<type>()" \
+          && is<ctype>());                                     \
+    return var;                                                        \
+  }                                                            \
+  template <> inline ctype& value::get<ctype>() {              \
+    Assert("type mismatch! call is<type>() before get<type>()" \
+          && is<ctype>());                                     \
+    return var;                                                        \
+  }
+  GET(bool, u_.boolean_)
+  GET(double, u_.number_)
+  GET(std::string, *u_.string_)
+  GET(array, *u_.array_)
+  GET(object, *u_.object_)
+#undef GET
+  
+  inline bool value::evaluate_as_boolean() const {
+    switch (type_) {
+    case null_type:
+      return false;
+    case boolean_type:
+      return u_.boolean_;
+    case number_type:
+      return u_.number_ != 0;
+    case string_type:
+      return ! u_.string_->empty();
+    default:
+      return true;
+    }
+  }
+  
+  inline const value& value::get(size_t idx) const {
+    static value s_null;
+    Assert(is<array>());
+    return idx < u_.array_->size() ? (*u_.array_)[idx] : s_null;
+  }
+
+  inline const value& value::get(const std::string& key) const {
+    static value s_null;
+    Assert(is<object>());
+    object::const_iterator i = u_.object_->find(key);
+    return i != u_.object_->end() ? i->second : s_null;
+  }
+
+  inline bool value::contains(size_t idx) const {
+    Assert(is<array>());
+    return idx < u_.array_->size();
+  }
+
+  inline bool value::contains(const std::string& key) const {
+    Assert(is<object>());
+    object::const_iterator i = u_.object_->find(key);
+    return i != u_.object_->end();
+  }
+  
+  inline std::string value::to_str() const {
+    switch (type_) {
+    case null_type:      return "null";
+    case boolean_type:   return u_.boolean_ ? "true" : "false";
+    case number_type:    {
+      char buf[256];
+      double tmp;
+      SNPRINTF(buf, sizeof(buf), fabs(u_.number_) < (1ULL << 53) && modf(u_.number_, &tmp) == 0 ? "%.f" : "%.17g", u_.number_);
+      return buf;
+    }
+    case string_type:    return *u_.string_;
+    case array_type:     return "array";
+    case object_type:    return "object";
+    default:             Assert(0);
+#ifdef _MSC_VER
+      __assume(0);
+#endif
+    }
+    return std::string();
+  }
+  
+  template <typename Iter> void copy(const std::string& s, Iter oi) {
+    std::copy(s.begin(), s.end(), oi);
+  }
+  
+  template <typename Iter> void serialize_str(const std::string& s, Iter oi) {
+    *oi++ = '"';
+    for (std::string::const_iterator i = s.begin(); i != s.end(); ++i) {
+      switch (*i) {
+#define MAP(val, sym) case val: copy(sym, oi); break
+       MAP('"', "\\\"");
+       MAP('\\', "\\\\");
+       MAP('/', "\\/");
+       MAP('\b', "\\b");
+       MAP('\f', "\\f");
+       MAP('\n', "\\n");
+       MAP('\r', "\\r");
+       MAP('\t', "\\t");
+#undef MAP
+      default:
+       if ((unsigned char)*i < 0x20 || *i == 0x7f) {
+         char buf[7];
+         SNPRINTF(buf, sizeof(buf), "\\u%04x", *i & 0xff);
+         copy(buf, buf + 6, oi);
+         } else {
+         *oi++ = *i;
+       }
+       break;
+      }
+    }
+    *oi++ = '"';
+  }
+  
+  template <typename Iter> void value::serialize(Iter oi) const {
+    switch (type_) {
+    case string_type:
+      serialize_str(*u_.string_, oi);
+      break;
+    case array_type: {
+      *oi++ = '[';
+      for (array::const_iterator i = u_.array_->begin();
+           i != u_.array_->end();
+           ++i) {
+       if (i != u_.array_->begin()) {
+         *oi++ = ',';
+       }
+       i->serialize(oi);
+      }
+      *oi++ = ']';
+      break;
+    }
+    case object_type: {
+      *oi++ = '{';
+      for (object::const_iterator i = u_.object_->begin();
+          i != u_.object_->end();
+          ++i) {
+       if (i != u_.object_->begin()) {
+         *oi++ = ',';
+       }
+       serialize_str(i->first, oi);
+       *oi++ = ':';
+       i->second.serialize(oi);
+      }
+      *oi++ = '}';
+      break;
+    }
+    default:
+      copy(to_str(), oi);
+      break;
+    }
+  }
+  
+  inline std::string value::serialize() const {
+    std::string s;
+    serialize(std::back_inserter(s));
+    return s;
+  }
+  
+  template <typename Iter> class input {
+  protected:
+    Iter cur_, end_;
+    int last_ch_;
+    bool ungot_;
+    int line_;
+  public:
+    input(const Iter& first, const Iter& last) : cur_(first), end_(last), last_ch_(-1), ungot_(false), line_(1) {}
+    int getc() {
+      if (ungot_) {
+       ungot_ = false;
+       return last_ch_;
+      }
+      if (cur_ == end_) {
+       last_ch_ = -1;
+       return -1;
+      }
+      if (last_ch_ == '\n') {
+       line_++;
+      }
+      last_ch_ = *cur_++ & 0xff;
+      return last_ch_;
+    }
+    void ungetc() {
+      if (last_ch_ != -1) {
+       Assert(! ungot_);
+       ungot_ = true;
+      }
+    }
+    Iter cur() const { return cur_; }
+    int line() const { return line_; }
+    void skip_ws() {
+      while (1) {
+       int ch = getc();
+       if (! (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r')) {
+         ungetc();
+         break;
+       }
+      }
+    }
+    bool expect(int expect) {
+      skip_ws();
+      if (getc() != expect) {
+       ungetc();
+       return false;
+      }
+      return true;
+    }
+    bool match(const std::string& pattern) {
+      for (std::string::const_iterator pi(pattern.begin());
+          pi != pattern.end();
+          ++pi) {
+       if (getc() != *pi) {
+         ungetc();
+         return false;
+       }
+      }
+      return true;
+    }
+  };
+  
+  template<typename Iter> inline int _parse_quadhex(input<Iter> &in) {
+    int uni_ch = 0, hex;
+    for (int i = 0; i < 4; i++) {
+      if ((hex = in.getc()) == -1) {
+       return -1;
+      }
+      if ('0' <= hex && hex <= '9') {
+       hex -= '0';
+      } else if ('A' <= hex && hex <= 'F') {
+       hex -= 'A' - 0xa;
+      } else if ('a' <= hex && hex <= 'f') {
+       hex -= 'a' - 0xa;
+      } else {
+       in.ungetc();
+       return -1;
+      }
+      uni_ch = uni_ch * 16 + hex;
+    }
+    return uni_ch;
+  }
+  
+  template<typename String, typename Iter> inline bool _parse_codepoint(String& out, input<Iter>& in) {
+    int uni_ch;
+    if ((uni_ch = _parse_quadhex(in)) == -1) {
+      return false;
+    }
+    if (0xd800 <= uni_ch && uni_ch <= 0xdfff) {
+      if (0xdc00 <= uni_ch) {
+       // a second 16-bit of a surrogate pair appeared
+       return false;
+      }
+      // first 16-bit of surrogate pair, get the next one
+      if (in.getc() != '\\' || in.getc() != 'u') {
+       in.ungetc();
+       return false;
+      }
+      int second = _parse_quadhex(in);
+      if (! (0xdc00 <= second && second <= 0xdfff)) {
+       return false;
+      }
+      uni_ch = ((uni_ch - 0xd800) << 10) | ((second - 0xdc00) & 0x3ff);
+      uni_ch += 0x10000;
+    }
+    if (uni_ch < 0x80) {
+      out.push_back(uni_ch);
+    } else {
+      if (uni_ch < 0x800) {
+       out.push_back(0xc0 | (uni_ch >> 6));
+      } else {
+       if (uni_ch < 0x10000) {
+         out.push_back(0xe0 | (uni_ch >> 12));
+       } else {
+         out.push_back(0xf0 | (uni_ch >> 18));
+         out.push_back(0x80 | ((uni_ch >> 12) & 0x3f));
+       }
+       out.push_back(0x80 | ((uni_ch >> 6) & 0x3f));
+      }
+      out.push_back(0x80 | (uni_ch & 0x3f));
+    }
+    return true;
+  }
+  
+  template<typename String, typename Iter> inline bool _parse_string(String& out, input<Iter>& in) {
+    while (1) {
+      int ch = in.getc();
+      if (ch < ' ') {
+       in.ungetc();
+       return false;
+      } else if (ch == '"') {
+       return true;
+      } else if (ch == '\\') {
+       if ((ch = in.getc()) == -1) {
+         return false;
+       }
+       switch (ch) {
+#define MAP(sym, val) case sym: out.push_back(val); break
+         MAP('"', '\"');
+         MAP('\\', '\\');
+         MAP('/', '/');
+         MAP('b', '\b');
+         MAP('f', '\f');
+         MAP('n', '\n');
+         MAP('r', '\r');
+         MAP('t', '\t');
+#undef MAP
+       case 'u':
+         if (! _parse_codepoint(out, in)) {
+           return false;
+         }
+         break;
+       default:
+         return false;
+       }
+      } else {
+       out.push_back(ch);
+      }
+    }
+    return false;
+  }
+  
+  template <typename Context, typename Iter> inline bool _parse_array(Context& ctx, input<Iter>& in) {
+    if (! ctx.parse_array_start()) {
+      return false;
+    }
+    if (in.expect(']')) {
+      return true;
+    }
+    size_t idx = 0;
+    do {
+      if (! ctx.parse_array_item(in, idx)) {
+       return false;
+      }
+      idx++;
+    } while (in.expect(','));
+    return in.expect(']');
+  }
+  
+  template <typename Context, typename Iter> inline bool _parse_object(Context& ctx, input<Iter>& in) {
+    if (! ctx.parse_object_start()) {
+      return false;
+    }
+    if (in.expect('}')) {
+      return true;
+    }
+    do {
+      std::string key;
+      if (! in.expect('"')
+         || ! _parse_string(key, in)
+         || ! in.expect(':')) {
+       return false;
+      }
+      if (! ctx.parse_object_item(in, key)) {
+       return false;
+      }
+    } while (in.expect(','));
+    return in.expect('}');
+  }
+  
+  template <typename Iter> inline bool _parse_number(double& out, input<Iter>& in) {
+    std::string num_str;
+    while (1) {
+      int ch = in.getc();
+      if (('0' <= ch && ch <= '9') || ch == '+' || ch == '-' || ch == '.'
+         || ch == 'e' || ch == 'E') {
+       num_str.push_back(ch);
+      } else {
+       in.ungetc();
+       break;
+      }
+    }
+    char* endp;
+    out = strtod(num_str.c_str(), &endp);
+    return endp == num_str.c_str() + num_str.size();
+  }
+  
+  template <typename Context, typename Iter> inline bool _parse(Context& ctx, input<Iter>& in) {
+    in.skip_ws();
+    int ch = in.getc();
+    switch (ch) {
+#define IS(ch, text, op) case ch: \
+      if (in.match(text) && op) { \
+       return true; \
+      } else { \
+       return false; \
+      }
+      IS('n', "ull", ctx.set_null());
+      IS('f', "alse", ctx.set_bool(false));
+      IS('t', "rue", ctx.set_bool(true));
+#undef IS
+    case '"':
+      return ctx.parse_string(in);
+    case '[':
+      return _parse_array(ctx, in);
+    case '{':
+      return _parse_object(ctx, in);
+    default:
+      if (('0' <= ch && ch <= '9') || ch == '-') {
+       in.ungetc();
+       double f;
+       if (_parse_number(f, in)) {
+         ctx.set_number(f);
+         return true;
+       } else {
+         return false;
+       }
+      }
+      break;
+    }
+    in.ungetc();
+    return false;
+  }
+  
+  class deny_parse_context {
+  public:
+    bool set_null() { return false; }
+    bool set_bool(bool) { return false; }
+    bool set_number(double) { return false; }
+    template <typename Iter> bool parse_string(input<Iter>&) { return false; }
+    bool parse_array_start() { return false; }
+    template <typename Iter> bool parse_array_item(input<Iter>&, size_t) {
+      return false;
+    }
+    bool parse_object_start() { return false; }
+    template <typename Iter> bool parse_object_item(input<Iter>&, const std::string&) {
+      return false;
+    }
+  };
+  
+  class default_parse_context {
+  protected:
+    value* out_;
+  public:
+    default_parse_context(value* out) : out_(out) {}
+    bool set_null() {
+      *out_ = value();
+      return true;
+    }
+    bool set_bool(bool b) {
+      *out_ = value(b);
+      return true;
+    }
+    bool set_number(double f) {
+      *out_ = value(f);
+      return true;
+    }
+    template<typename Iter> bool parse_string(input<Iter>& in) {
+      *out_ = value(string_type, false);
+      return _parse_string(out_->get<std::string>(), in);
+    }
+    bool parse_array_start() {
+      *out_ = value(array_type, false);
+      return true;
+    }
+    template <typename Iter> bool parse_array_item(input<Iter>& in, size_t) {
+      array& a = out_->get<array>();
+      a.push_back(value());
+      default_parse_context ctx(&a.back());
+      return _parse(ctx, in);
+    }
+    bool parse_object_start() {
+      *out_ = value(object_type, false);
+      return true;
+    }
+    template <typename Iter> bool parse_object_item(input<Iter>& in, const std::string& key) {
+      object& o = out_->get<object>();
+      default_parse_context ctx(&o[key]);
+      return _parse(ctx, in);
+    }
+  private:
+    default_parse_context(const default_parse_context&);
+    default_parse_context& operator=(const default_parse_context&);
+  };
+
+  class null_parse_context {
+  public:
+    struct dummy_str {
+      void push_back(int) {}
+    };
+  public:
+    null_parse_context() {}
+    bool set_null() { return true; }
+    bool set_bool(bool) { return true; }
+    bool set_number(double) { return true; }
+    template <typename Iter> bool parse_string(input<Iter>& in) {
+      dummy_str s;
+      return _parse_string(s, in);
+    }
+    bool parse_array_start() { return true; }
+    template <typename Iter> bool parse_array_item(input<Iter>& in, size_t) {
+      return _parse(*this, in);
+    }
+    bool parse_object_start() { return true; }
+    template <typename Iter> bool parse_object_item(input<Iter>& in, const std::string&) {
+      return _parse(*this, in);
+    }
+  private:
+    null_parse_context(const null_parse_context&);
+    null_parse_context& operator=(const null_parse_context&);
+  };
+  
+  // obsolete, use the version below
+  template <typename Iter> inline std::string parse(value& out, Iter& pos, const Iter& last) {
+    std::string err;
+    pos = parse(out, pos, last, &err);
+    return err;
+  }
+  
+  template <typename Context, typename Iter> inline Iter _parse(Context& ctx, const Iter& first, const Iter& last, std::string* err) {
+    input<Iter> in(first, last);
+    if (! _parse(ctx, in) && err != NULL) {
+      char buf[64];
+      SNPRINTF(buf, sizeof(buf), "syntax error at line %d near: ", in.line());
+      *err = buf;
+      while (1) {
+       int ch = in.getc();
+       if (ch == -1 || ch == '\n') {
+         break;
+       } else if (ch >= ' ') {
+         err->push_back(ch);
+       }
+      }
+    }
+    return in.cur();
+  }
+  
+  template <typename Iter> inline Iter parse(value& out, const Iter& first, const Iter& last, std::string* err) {
+    default_parse_context ctx(&out);
+    return _parse(ctx, first, last, err);
+  }
+  
+  inline std::string parse(value& out, std::istream& is) {
+    std::string err;
+    parse(out, std::istreambuf_iterator<char>(is.rdbuf()),
+         std::istreambuf_iterator<char>(), &err);
+    return err;
+  }
+  
+  template <typename T> struct last_error_t {
+    static std::string s;
+  };
+  template <typename T> std::string last_error_t<T>::s;
+  
+  inline void set_last_error(const std::string& s) {
+    last_error_t<bool>::s = s;
+  }
+  
+  inline const std::string& get_last_error() {
+    return last_error_t<bool>::s;
+  }
+
+  inline bool operator==(const value& x, const value& y) {
+    if (x.is<null>())
+      return y.is<null>();
+#define PICOJSON_CMP(type)                                     \
+    if (x.is<type>())                                          \
+      return y.is<type>() && x.get<type>() == y.get<type>()
+    PICOJSON_CMP(bool);
+    PICOJSON_CMP(double);
+    PICOJSON_CMP(std::string);
+    PICOJSON_CMP(array);
+    PICOJSON_CMP(object);
+#undef PICOJSON_CMP
+    Assert(0);
+#ifdef _MSC_VER
+    __assume(0);
+#endif
+    return false;
+  }
+  
+  inline bool operator!=(const value& x, const value& y) {
+    return ! (x == y);
+  }
+}
+
+namespace std {
+  template<> inline void swap(picojson::value& x, picojson::value& y)
+    {
+      x.swap(y);
+    }
+}
+
+inline std::istream& operator>>(std::istream& is, picojson::value& x)
+{
+  picojson::set_last_error(std::string());
+  std::string err = picojson::parse(x, is);
+  if (! err.empty()) {
+    picojson::set_last_error(err);
+    is.setstate(std::ios::failbit);
+  }
+  return is;
+}
+
+inline std::ostream& operator<<(std::ostream& os, const picojson::value& x)
+{
+  x.serialize(std::ostream_iterator<char>(os));
+  return os;
+}
+#ifdef _MSC_VER
+    #pragma warning(pop)
+#endif
+
+#endif
+#ifdef TEST_PICOJSON
+#ifdef _MSC_VER
+    #pragma warning(disable : 4127) // conditional expression is constant
+#endif
+
+using namespace std;
+  
+static void plan(int num)
+{
+  printf("1..%d\n", num);
+}
+
+static bool success = true;
+
+static void ok(bool b, const char* name = "")
+{
+  static int n = 1;
+  if (! b)
+    success = false;
+  printf("%s %d - %s\n", b ? "ok" : "ng", n++, name);
+}
+
+template <typename T> void is(const T& x, const T& y, const char* name = "")
+{
+  if (x == y) {
+    ok(true, name);
+  } else {
+    ok(false, name);
+  }
+}
+
+#include <algorithm>
+#include <sstream>
+#include <float.h>
+#include <limits.h>
+
+int main(void)
+{
+  plan(85);
+
+  // constructors
+#define TEST(expr, expected) \
+    is(picojson::value expr .serialize(), string(expected), "picojson::value" #expr)
+  
+  TEST( (true),  "true");
+  TEST( (false), "false");
+  TEST( (42.0),   "42");
+  TEST( (string("hello")), "\"hello\"");
+  TEST( ("hello"), "\"hello\"");
+  TEST( ("hello", 4), "\"hell\"");
+
+  {
+    double a = 1;
+    for (int i = 0; i < 1024; i++) {
+      picojson::value vi(a);
+      std::stringstream ss;
+      ss << vi;
+      picojson::value vo;
+      ss >> vo;
+      double b = vo.get<double>();
+      if ((i < 53 && a != b) || fabs(a - b) / b > 1e-8) {
+        printf("ng i=%d a=%.18e b=%.18e\n", i, a, b);
+      }
+      a *= 2;
+    }
+  }
+  
+#undef TEST
+  
+#define TEST(in, type, cmp, serialize_test) {                          \
+    picojson::value v;                                                 \
+    const char* s = in;                                                        \
+    string err = picojson::parse(v, s, s + strlen(s));                 \
+    ok(err.empty(), in " no error");                                   \
+    ok(v.is<type>(), in " check type");                                        \
+    is<type>(v.get<type>(), cmp, in " correct output");                        \
+    is(*s, '\0', in " read to eof");                                   \
+    if (serialize_test) {                                              \
+      is(v.serialize(), string(in), in " serialize");                  \
+    }                                                                  \
+  }
+  TEST("false", bool, false, true);
+  TEST("true", bool, true, true);
+  TEST("90.5", double, 90.5, false);
+  TEST("1.7976931348623157e+308", double, DBL_MAX, false);
+  TEST("\"hello\"", string, string("hello"), true);
+  TEST("\"\\\"\\\\\\/\\b\\f\\n\\r\\t\"", string, string("\"\\/\b\f\n\r\t"),
+       true);
+  TEST("\"\\u0061\\u30af\\u30ea\\u30b9\"", string,
+       string("a\xe3\x82\xaf\xe3\x83\xaa\xe3\x82\xb9"), false);
+  TEST("\"\\ud840\\udc0b\"", string, string("\xf0\xa0\x80\x8b"), false);
+#undef TEST
+
+#define TEST(type, expr) {                                            \
+    picojson::value v;                                                \
+    const char *s = expr;                                             \
+    string err = picojson::parse(v, s, s + strlen(s));                \
+    ok(err.empty(), "empty " #type " no error");                      \
+    ok(v.is<picojson::type>(), "empty " #type " check type");         \
+    ok(v.get<picojson::type>().empty(), "check " #type " array size"); \
+  }
+  TEST(array, "[]");
+  TEST(object, "{}");
+#undef TEST
+  
+  {
+    picojson::value v;
+    const char *s = "[1,true,\"hello\"]";
+    string err = picojson::parse(v, s, s + strlen(s));
+    ok(err.empty(), "array no error");
+    ok(v.is<picojson::array>(), "array check type");
+    is(v.get<picojson::array>().size(), size_t(3), "check array size");
+    ok(v.contains(0), "check contains array[0]");
+    ok(v.get(0).is<double>(), "check array[0] type");
+    is(v.get(0).get<double>(), 1.0, "check array[0] value");
+    ok(v.contains(1), "check contains array[1]");
+    ok(v.get(1).is<bool>(), "check array[1] type");
+    ok(v.get(1).get<bool>(), "check array[1] value");
+    ok(v.contains(2), "check contains array[2]");
+    ok(v.get(2).is<string>(), "check array[2] type");
+    is(v.get(2).get<string>(), string("hello"), "check array[2] value");
+    ok(!v.contains(3), "check not contains array[3]");
+  }
+  
+  {
+    picojson::value v;
+    const char *s = "{ \"a\": true }";
+    string err = picojson::parse(v, s, s + strlen(s));
+    ok(err.empty(), "object no error");
+    ok(v.is<picojson::object>(), "object check type");
+    is(v.get<picojson::object>().size(), size_t(1), "check object size");
+    ok(v.contains("a"), "check contains property");
+    ok(v.get("a").is<bool>(), "check bool property exists");
+    is(v.get("a").get<bool>(), true, "check bool property value");
+    is(v.serialize(), string("{\"a\":true}"), "serialize object");
+    ok(!v.contains("z"), "check not contains property");
+  }
+
+#define TEST(json, msg) do {                           \
+    picojson::value v;                                 \
+    const char *s = json;                              \
+    string err = picojson::parse(v, s, s + strlen(s)); \
+    is(err, string("syntax error at line " msg), msg); \
+  } while (0)
+  TEST("falsoa", "1 near: oa");
+  TEST("{]", "1 near: ]");
+  TEST("\n\bbell", "2 near: bell");
+  TEST("\"abc\nd\"", "1 near: ");
+#undef TEST
+  
+  {
+    picojson::value v1, v2;
+    const char *s;
+    string err;
+    s = "{ \"b\": true, \"a\": [1,2,\"three\"], \"d\": 2 }";
+    err = picojson::parse(v1, s, s + strlen(s));
+    s = "{ \"d\": 2.0, \"b\": true, \"a\": [1,2,\"three\"] }";
+    err = picojson::parse(v2, s, s + strlen(s));
+    ok((v1 == v2), "check == operator in deep comparison");
+  }
+
+  {
+    picojson::value v1, v2;
+    const char *s;
+    string err;
+    s = "{ \"b\": true, \"a\": [1,2,\"three\"], \"d\": 2 }";
+    err = picojson::parse(v1, s, s + strlen(s));
+    s = "{ \"d\": 2.0, \"a\": [1,\"three\"], \"b\": true }";
+    err = picojson::parse(v2, s, s + strlen(s));
+    ok((v1 != v2), "check != operator for array in deep comparison");
+  }
+
+  {
+    picojson::value v1, v2;
+    const char *s;
+    string err;
+    s = "{ \"b\": true, \"a\": [1,2,\"three\"], \"d\": 2 }";
+    err = picojson::parse(v1, s, s + strlen(s));
+    s = "{ \"d\": 2.0, \"a\": [1,2,\"three\"], \"b\": false }";
+    err = picojson::parse(v2, s, s + strlen(s));
+    ok((v1 != v2), "check != operator for object in deep comparison");
+  }
+
+  {
+    picojson::value v1, v2;
+    const char *s;
+    string err;
+    s = "{ \"b\": true, \"a\": [1,2,\"three\"], \"d\": 2 }";
+    err = picojson::parse(v1, s, s + strlen(s));
+    picojson::object& o = v1.get<picojson::object>();
+    o.erase("b");
+    picojson::array& a = o["a"].get<picojson::array>();
+    picojson::array::iterator i;
+    i = std::remove(a.begin(), a.end(), picojson::value(std::string("three")));
+    a.erase(i, a.end());
+    s = "{ \"a\": [1,2], \"d\": 2 }";
+    err = picojson::parse(v2, s, s + strlen(s));
+    ok((v1 == v2), "check erase()");
+  }
+
+  ok(picojson::value(3.0).serialize() == "3",
+     "integral number should be serialized as a integer");
+  
+  {
+    const char* s = "{ \"a\": [1,2], \"d\": 2 }";
+    picojson::null_parse_context ctx;
+    string err;
+    picojson::_parse(ctx, s, s + strlen(s), &err);
+    ok(err.empty(), "null_parse_context");
+  }
+  
+  {
+    picojson::value v1, v2;
+    v1 = picojson::value(true);
+    swap(v1, v2);
+    ok(v1.is<picojson::null>(), "swap (null)");
+    ok(v2.get<bool>() == true, "swap (bool)");
+
+    v1 = picojson::value("a");
+    v2 = picojson::value(1.0);
+    swap(v1, v2);
+    ok(v1.get<double>() == 1.0, "swap (dobule)");
+    ok(v2.get<string>() == "a", "swap (string)");
+
+    v1 = picojson::value(picojson::object());
+    v2 = picojson::value(picojson::array());
+    swap(v1, v2);
+    ok(v1.is<picojson::array>(), "swap (array)");
+    ok(v2.is<picojson::object>(), "swap (object)");
+  }
+  
+  return success ? 0 : 1;
+}
+
+#endif
diff --git a/webWidgetTCT_device/src/common/pkg-config.gypi b/webWidgetTCT_device/src/common/pkg-config.gypi
new file mode 100755 (executable)
index 0000000..47410ef
--- /dev/null
@@ -0,0 +1,18 @@
+{
+  'variables': {
+    'packages%': [],
+  },
+
+  'cflags': [
+    '>!@(if [ -n ">@(packages)" ]; then pkg-config --cflags >@(packages); fi)'
+  ],
+
+  'link_settings': {
+    'ldflags': [
+      '>!@(if [ -n ">@(packages)" ]; then pkg-config --libs-only-L --libs-only-other >@(packages); fi)',
+    ],
+    'libraries': [
+      '>!@(if [ -n ">@(packages)" ]; then pkg-config --libs-only-l >@(packages); fi)',
+    ],
+  },
+}
diff --git a/webWidgetTCT_device/src/common/platform_exception.cc b/webWidgetTCT_device/src/common/platform_exception.cc
new file mode 100755 (executable)
index 0000000..20d6892
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2015 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 "common/platform_exception.h"
+
+namespace common {
+
+PlatformException::PlatformException(
+    const std::string& name,
+    const std::string& message)
+    : name_(name),
+    message_(message) {
+}
+
+PlatformException::~PlatformException() {
+}
+
+std::string PlatformException::name() const {
+  return name_;
+}
+
+std::string PlatformException::message() const {
+  return message_;
+}
+
+picojson::value PlatformException::ToJSON() const {
+  picojson::value::object obj;
+  obj["name"] = picojson::value(name_);
+  obj["message"] = picojson::value(message_);
+  picojson::value ret(obj);
+  return ret;
+}
+
+} // namespace common
diff --git a/webWidgetTCT_device/src/common/platform_exception.h b/webWidgetTCT_device/src/common/platform_exception.h
new file mode 100755 (executable)
index 0000000..3054187
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2015 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 COMMON_PLATFORM_EXCEPTION_H_
+#define COMMON_PLATFORM_EXCEPTION_H_
+
+#include <string>
+
+#include "common/picojson.h"
+
+namespace common {
+
+class PlatformException {
+ public:
+  PlatformException(const std::string& name, const std::string& message);
+  virtual ~PlatformException();
+
+  std::string name() const;
+  std::string message() const;
+  picojson::value ToJSON() const;
+
+ protected:
+  std::string name_;
+  std::string message_;
+};
+
+#define DEFINE_EXCEPTION(NAME) \
+class NAME##Exception: public PlatformException { \
+ public: \
+  NAME##Exception(const std::string& msg) \
+      : PlatformException(#NAME "Error", msg) { \
+  } \
+};
+DEFINE_EXCEPTION(Unknown)
+DEFINE_EXCEPTION(TypeMismatch)
+DEFINE_EXCEPTION(InvalidValues)
+DEFINE_EXCEPTION(IO)
+DEFINE_EXCEPTION(ServiceNotAvailable)
+DEFINE_EXCEPTION(Security)
+DEFINE_EXCEPTION(Network)
+DEFINE_EXCEPTION(NotSupported)
+DEFINE_EXCEPTION(NotFound)
+DEFINE_EXCEPTION(InvalidAccess)
+DEFINE_EXCEPTION(Abort)
+DEFINE_EXCEPTION(QuotaExceeded)
+DEFINE_EXCEPTION(InvalidState)
+DEFINE_EXCEPTION(InvalidModification)
+#undef DEFINE_EXCEPTION
+
+} // namespace common
+
+#endif // COMMON_PLATFORM_EXCEPTION_H_
diff --git a/webWidgetTCT_device/src/common/platform_result.cc b/webWidgetTCT_device/src/common/platform_result.cc
new file mode 100755 (executable)
index 0000000..cf091b3
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2015 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 "common/platform_result.h"
+#include "common/logger.h"
+
+namespace common {
+
+PlatformResult::PlatformResult(const ErrorCode& error_code, const std::string& message) :
+    error_code_(error_code),
+    message_(message)
+{
+  LoggerD("Enter");
+}
+
+picojson::value PlatformResult::ToJSON() const {
+  LoggerD("Enter");
+  picojson::value::object obj;
+  obj["code"] = picojson::value(static_cast<double>(error_code_));
+  if (!message_.empty())
+    obj["message"] = picojson::value(message_);
+  picojson::value ret(obj);
+  return ret;
+}
+
+}  // namespace common
+
+
diff --git a/webWidgetTCT_device/src/common/platform_result.h b/webWidgetTCT_device/src/common/platform_result.h
new file mode 100755 (executable)
index 0000000..c323175
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2015 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 SRC_COMMON_PLATFORM_RESULT_H_
+#define SRC_COMMON_PLATFORM_RESULT_H_
+
+#include <string>
+
+#include "common/picojson.h"
+
+namespace common {
+
+// WARNING! This list should be in sync with the equivalent list
+// located at tizen/tizen_api.js. Remember to update tizen/tizen_api.js if you
+// change something here.
+enum class ErrorCode : int {
+  // NO_ERROR is not really a valid error, but can be used
+  // to indicate that no error occoured instead of having an
+  // extra field in the message protocol just for that.
+  NO_ERROR = 0,
+
+  INDEX_SIZE_ERR = 1,
+  DOMSTRING_SIZE_ERR = 2,
+  HIERARCHY_REQUEST_ERR = 3,
+  WRONG_DOCUMENT_ERR = 4,
+  INVALID_CHARACTER_ERR = 5,
+  NO_DATA_ALLOWED_ERR = 6,
+  NO_MODIFICATION_ALLOWED_ERR = 7,
+  NOT_FOUND_ERR = 8,
+  NOT_SUPPORTED_ERR = 9,
+  INUSE_ATTRIBUTE_ERR = 10,
+  INVALID_STATE_ERR = 11,
+  SYNTAX_ERR = 12,
+  INVALID_MODIFICATION_ERR = 13,
+  NAMESPACE_ERR = 14,
+  INVALID_ACCESS_ERR = 15,
+  VALIDATION_ERR = 16,
+  TYPE_MISMATCH_ERR = 17,
+  SECURITY_ERR = 18,
+  NETWORK_ERR = 19,
+  ABORT_ERR = 20,
+  URL_MISMATCH_ERR = 21,
+  QUOTA_EXCEEDED_ERR = 22,
+  TIMEOUT_ERR = 23,
+  INVALID_NODE_TYPE_ERR = 24,
+  DATA_CLONE_ERR = 25,
+
+  // Error codes for these errors are not really defined anywhere.
+  INVALID_VALUES_ERR = 100,
+  IO_ERR = 101,
+  PERMISSION_DENIED_ERR = 102,
+  SERVICE_NOT_AVAILABLE_ERR = 103,
+  DATABASE_ERR = 104,
+  VERIFICATION_ERR = 105,
+
+  // Error codes specific for plugins
+  OPERATION_CANCELED_ERR = 200,
+
+  UNKNOWN_ERR = -1
+};
+
+class PlatformResult {
+ public:
+  explicit PlatformResult(const ErrorCode& error_code,
+                          const std::string& message = "");
+
+  ErrorCode error_code() const { return error_code_; }
+  std::string message() const { return message_; }
+
+  bool IsSuccess() const { return error_code() == ErrorCode::NO_ERROR; }
+  bool IsError() const { return !IsSuccess(); }
+  explicit operator bool() const { return IsSuccess(); }
+
+  picojson::value ToJSON() const;
+
+ protected:
+  ErrorCode error_code_;
+  std::string message_;
+};
+
+}  // namespace common
+
+#endif  // SRC_COMMON_PLATFORM_RESULT_H_
diff --git a/webWidgetTCT_device/src/common/scope_exit.h b/webWidgetTCT_device/src/common/scope_exit.h
new file mode 100755 (executable)
index 0000000..fda1b45
--- /dev/null
@@ -0,0 +1,116 @@
+// Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+
+// Header file coppied from crosswalk extensions repository. Difference is to miss final keyword
+// in class ScopeExit
+
+
+
+#ifndef COMMON_SCOPE_EXIT_H_
+#define COMMON_SCOPE_EXIT_H_
+
+namespace common {
+
+/**
+ * The Scope Exit idiom
+ *
+ * Func - callable type (function, standard functor, lambda function...)
+ *
+ * This idiom provides way to release resources when execution exits lexical
+ * scope exit.
+ *
+ * Template class encapsulate callable object. This object is being called
+ * automatically upon exiting function, block scope. This guarantees resource
+ * cleanup at any way of exit from scope - normal function return or exception.
+ *
+ * Example:
+ *
+ *   struct unit;
+ *   struct unit* unit_new();
+ *   void unit_free(unit*);
+ *
+ *   void ExampleFunctionScope() {
+ *     struct unit* u = unit_new();
+ *
+ *     // automatic cleanup for all cases
+ *     auto scope_exit = MakeScopeExit([=]() {
+ *       unit_free(u);
+ *     });
+ *
+ *     // do 1st operation with unit and possibly quit function
+ *     // do 2nd operation with unit and possibly quit function
+ *     // do 3rd operation with unit and possibly quit function
+ *   }
+ */
+template<typename Func>
+class ScopeExit {
+ public:
+  ScopeExit(Func func) : func_(func), released_(false) { }  // NOLINT
+  ~ScopeExit() noexcept(false) {
+    if (!released_)
+      func_();
+  }
+
+  ScopeExit(const ScopeExit&) = delete;
+  ScopeExit& operator=(const ScopeExit&) = delete;
+  ScopeExit(ScopeExit&& other)  // NOLINT
+      : func_(std::move(other.func_)),
+        released_(other.released_) {
+    other.released_ = true;
+  }
+
+ private:
+  Func func_;
+  bool released_;
+};
+
+template <typename F>
+ScopeExit<F> MakeScopeExit(F f) {
+  return ScopeExit<F>(f);
+}
+
+// Internal use for macro SCOPE_EXIT
+
+struct __dummy{};
+
+template <typename F>
+ScopeExit<typename std::decay<F>::type>
+operator+(__dummy, F&& f)
+{
+  return ScopeExit<typename std::decay<F>::type>
+  {std::forward<F>(f)};
+}
+
+/*
+ * This macro is for simple way to using ScopeExit
+ *
+ * Example:
+ *
+ *   struct unit;
+ *   struct unit* unit_new();
+ *   void unit_free(unit*);
+ *
+ *   void ExampleFunctionScope() {
+ *     struct unit* u = unit_new();
+ *
+ *     // automatic cleanup for all cases
+ *     SCOPE_EXIT {
+ *       unit_free(u);
+ *     };
+ *
+ *     // do 1st operation with unit and possibly quit function
+ *     // do 2nd operation with unit and possibly quit function
+ *     // do 3rd operation with unit and possibly quit function
+ *   }
+ */
+#define _SYNTAX_CONCAT(A, B) A ## B
+#define SYNTAX_CONCAT(A, B) _SYNTAX_CONCAT(A, B)
+#define SCOPE_EXIT \
+    auto SYNTAX_CONCAT(SCOPE_EXIT_, __LINE__) = ::common::__dummy{} + [&]()
+
+}  // namespace common
+
+#endif  // COMMON_SCOPE_EXIT_H_
diff --git a/webWidgetTCT_device/src/common/task-queue.cpp b/webWidgetTCT_device/src/common/task-queue.cpp
new file mode 100755 (executable)
index 0000000..2fc305c
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2015 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 "task-queue.h"
+
+namespace common {
+
+TaskQueue& TaskQueue::GetInstance() {
+    static TaskQueue task_queue;
+    return task_queue;
+}
+
+template <>
+gboolean TaskQueue::AfterWorkCallback<void>(gpointer data) {
+    QueueData<void>* d = static_cast<QueueData<void>*>(data);
+    if (nullptr != d) {
+        d->after_work_callback_();
+        delete d;
+    }
+    return FALSE;
+}
+
+template <>
+void* TaskQueue::WorkCallback<void>(void* data) {
+    QueueData<void>* d = static_cast<QueueData<void>*>(data);
+    if (nullptr != d) {
+        d->work_callback_();
+        if (d->after_work_callback_) {
+            g_idle_add(AfterWorkCallback<void>, d);
+        }
+    }
+    return nullptr;
+}
+
+void TaskQueue::Queue(const std::function<void()>& work, const std::function<void()>& after_work) {
+    QueueData<void>* d = new QueueData<void>();
+    d->work_callback_ = work;
+    d->after_work_callback_ = after_work;
+
+    if (pthread_create(&d->thread_, nullptr, WorkCallback<void>, d) != 0) {
+        LoggerE("Failed to create a background thread.");
+        delete d;
+    } else {
+        pthread_detach(d->thread_);
+    }
+}
+
+void TaskQueue::Async(const std::function<void()>& work) {
+    QueueData<void>* d = new QueueData<void>();
+    d->after_work_callback_ = work;
+    g_idle_add(AfterWorkCallback<void>, d);
+}
+
+} // namespace common
diff --git a/webWidgetTCT_device/src/common/task-queue.h b/webWidgetTCT_device/src/common/task-queue.h
new file mode 100755 (executable)
index 0000000..94df211
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2015 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 WEBAPI_PLUGINS_COMMON_THREAD_SCHEDULER_H_
+#define WEBAPI_PLUGINS_COMMON_THREAD_SCHEDULER_H_
+
+#include <glib.h>
+#include <functional>
+#include <memory>
+#include <pthread.h>
+
+#include "logger.h"
+
+namespace common {
+
+class TaskQueue {
+public:
+    TaskQueue(const TaskQueue&) = delete;
+    TaskQueue& operator=(const TaskQueue&) = delete;
+
+    static TaskQueue& GetInstance();
+
+    /**
+     * @brief Schedules work to be executed in a separate thread, after_work is going
+     *        to be called in main glib loop.
+     *
+     * @param[in] work - callback is going to be called in a separate thread
+     * @param[in] after_work - callback is going to be called in main glib loop
+     * @param[in] data - data passed to both callbacks
+     */
+    template <class T>
+    void Queue(const std::function<void(const std::shared_ptr<T>&)>& work,
+               const std::function<void(const std::shared_ptr<T>&)>& after_work,
+               const std::shared_ptr<T>& data);
+
+    /**
+     * @brief Schedules work to be executed in a separate thread, after_work is going
+     *        to be called in main glib loop.
+     *
+     * @param[in] work - callback is going to be called in a separate thread
+     * @param[in] after_work - callback is going to be called in main glib loop
+     */
+    void Queue(const std::function<void()>& work,
+               const std::function<void()>& after_work = std::function<void()>());
+
+    /**
+     * @brief Schedules work to be executed in main glib loop.
+     *
+     * @param[in] work - callback is going to be called in main glib loop
+     * @param[in] data - data passed to callback
+     */
+    template <class T>
+    void Async(const std::function<void(const std::shared_ptr<T>&)>& work,
+               const std::shared_ptr<T>& data);
+
+    /**
+     * @brief Schedules work to be executed in main glib loop.
+     *
+     * @param[in] work - callback is going to be called in main glib loop
+     */
+    void Async(const std::function<void()>& work);
+
+private:
+    TaskQueue() {}
+
+    template <class T>
+    struct QueueData {
+        pthread_t thread_;
+        std::function<void(const std::shared_ptr<T>&)> work_callback_;
+        std::function<void(const std::shared_ptr<T>&)> after_work_callback_;
+        std::shared_ptr<T> data_;
+    };
+
+    template <class T>
+    static void* WorkCallback(void* data);
+
+    template <class T>
+    static gboolean AfterWorkCallback(gpointer data);
+};
+
+template <>
+struct TaskQueue::QueueData<void> {
+    pthread_t thread_;
+    std::function<void()> work_callback_;
+    std::function<void()> after_work_callback_;
+};
+
+template <class T>
+gboolean TaskQueue::AfterWorkCallback(gpointer data) {
+    QueueData<T>* d = static_cast<QueueData<T>*>(data);
+    if (nullptr != d) {
+        d->after_work_callback_(d->data_);
+        delete d;
+    }
+    return FALSE;
+}
+
+template <class T>
+void* TaskQueue::WorkCallback(void* data) {
+    QueueData<T>* d = static_cast<QueueData<T>*>(data);
+    if (nullptr != d) {
+        d->work_callback_(d->data_);
+        g_idle_add(AfterWorkCallback<T>, d);
+    }
+    return nullptr;
+}
+
+template <class T>
+void TaskQueue::Queue(const std::function<void(const std::shared_ptr<T>&)>& work,
+                      const std::function<void(const std::shared_ptr<T>&)>& after_work,
+                      const std::shared_ptr<T>& data) {
+    QueueData<T>* d = new QueueData<T>();
+    d->work_callback_ = work;
+    d->after_work_callback_ = after_work;
+    d->data_ = data;
+
+    if (pthread_create(&d->thread_, nullptr, WorkCallback<T>, d) != 0) {
+        LoggerE("Failed to create a background thread.");
+        delete d;
+    } else {
+        pthread_detach(d->thread_);
+    }
+}
+
+template <class T>
+void TaskQueue::Async(const std::function<void(const std::shared_ptr<T>&)>& work,
+                      const std::shared_ptr<T>& data) {
+    QueueData<T>* d = new QueueData<T>();
+    d->after_work_callback_ = work;
+    d->data_ = data;
+    g_idle_add(AfterWorkCallback<T>, d);
+}
+
+} // namespace common
+
+#endif // WEBAPI_PLUGINS_COMMON_THREAD_SCHEDULER_H_
diff --git a/webWidgetTCT_device/src/common/tools.cc b/webWidgetTCT_device/src/common/tools.cc
new file mode 100755 (executable)
index 0000000..252bcd5
--- /dev/null
@@ -0,0 +1,313 @@
+/*
+ * Copyright (c) 2015 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 "common/tools.h"
+
+#ifdef PRIVILEGE_USE_DB
+#include <sqlite3.h>
+#include "common/current_application.h"
+#elif PRIVILEGE_USE_ACE
+#include <privilege_checker.h>
+#elif PRIVILEGE_USE_CYNARA
+#include <unistd.h>
+
+#include <cynara/cynara-client.h>
+#include <sys/smack.h>
+#endif
+
+#include "common/logger.h"
+#include "common/scope_exit.h"
+
+namespace common {
+namespace tools {
+
+void ReportSuccess(picojson::object& out) {
+  LoggerD("Enter");
+  out.insert(std::make_pair("status", picojson::value("success")));
+}
+
+void ReportSuccess(const picojson::value& result, picojson::object& out) {
+  LoggerD("Enter");
+  out.insert(std::make_pair("status", picojson::value("success")));
+  out.insert(std::make_pair("result", result));
+}
+
+void ReportError(picojson::object& out) {
+  LoggerD("Enter");
+  out.insert(std::make_pair("status", picojson::value("error")));
+}
+
+void ReportError(const PlatformException& ex, picojson::object& out) {
+  LoggerD("Enter");
+  out.insert(std::make_pair("status", picojson::value("error")));
+  out.insert(std::make_pair("error", ex.ToJSON()));
+}
+
+void ReportError(const PlatformResult& error, picojson::object* out) {
+  LoggerD("Enter");
+  out->insert(std::make_pair("status", picojson::value("error")));
+  out->insert(std::make_pair("error", error.ToJSON()));
+}
+
+namespace {
+
+#ifdef PRIVILEGE_USE_DB
+
+class AccessControlImpl {
+ public:
+  AccessControlImpl()
+      : initialized_(false) {
+    LoggerD("Privilege access checked using DB.");
+
+    const char* kWrtDBPath = "/opt/dbspace/.wrt.db";
+    sqlite3* db = nullptr;
+
+    int ret = sqlite3_open(kWrtDBPath, &db);
+    if (SQLITE_OK != ret) {
+      LoggerE("Failed to access WRT database");
+      return;
+    }
+
+    const char* kQuery = "select name from WidgetFeature where app_id = "
+                         "(select app_id from WidgetInfo where tizen_appid = ?)"
+                         " and rejected = 0";
+    const std::string app_id = common::CurrentApplication::GetInstance().GetApplicationId();
+    sqlite3_stmt* stmt = nullptr;
+
+    ret = sqlite3_prepare_v2(db, kQuery, -1, &stmt, nullptr);
+    ret |= sqlite3_bind_text(stmt, 1, app_id.c_str(), -1, SQLITE_TRANSIENT);
+
+    SCOPE_EXIT {
+      sqlite3_finalize(stmt);
+      sqlite3_close(db);
+    };
+
+    if (SQLITE_OK != ret) {
+      LoggerE("Failed to query WRT database");
+      return;
+    }
+
+    while (sqlite3_step(stmt) == SQLITE_ROW) {
+      const char* privilege = reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0));
+      SLoggerD("Granted: %s", privilege);
+      granted_privileges_.push_back(privilege);
+    }
+
+    initialized_ = true;
+  }
+
+  ~AccessControlImpl() {}
+
+  bool CheckAccess(const std::vector<std::string>& privileges) {
+    LoggerD("Enter");
+    if (!initialized_) {
+      return false;
+    }
+
+    for (const auto& privilege : privileges) {
+      if (std::find(granted_privileges_.begin(), granted_privileges_.end(), privilege) == granted_privileges_.end()) {
+        return false;
+      }
+    }
+
+    return true;
+  }
+
+ private:
+  bool initialized_;
+  std::vector<std::string> granted_privileges_;
+};
+
+#elif PRIVILEGE_USE_ACE
+
+class AccessControlImpl {
+ public:
+  AccessControlImpl() {
+    LoggerD("Privilege access checked using ACE.");
+  }
+
+  ~AccessControlImpl() {
+  }
+
+  bool CheckAccess(const std::vector<std::string>& privileges) {
+    LoggerD("Enter");
+    for (size_t i = 0; i < privileges.size(); ++i) {
+      int ret = privilege_checker_check_privilege(privileges[i].c_str());
+      if (PRIVILEGE_CHECKER_ERR_NONE != ret) {
+        return false;
+      }
+    }
+    return true;
+  }
+};
+
+#elif PRIVILEGE_USE_CYNARA
+
+class AccessControlImpl {
+ public:
+  AccessControlImpl() : cynara_(nullptr) {
+    LoggerD("Privilege access checked using Cynara.");
+
+    char* smack_label = nullptr;
+    int ret = smack_new_label_from_self(&smack_label);
+
+    if (0 == ret && nullptr != smack_label) {
+      auto uid = getuid();
+
+      SLoggerD("uid: [%u]", uid);
+      SLoggerD("smack label: [%s]", smack_label);
+
+      uid_ = std::to_string(uid);
+      smack_label_ = smack_label;
+
+      free(smack_label);
+    } else {
+      LoggerE("Failed to get smack label");
+      return;
+    }
+
+    ret = cynara_initialize(&cynara_, nullptr);
+    if (CYNARA_API_SUCCESS != ret) {
+      LoggerE("Failed to initialize Cynara");
+      cynara_ = nullptr;
+    }
+  }
+
+  ~AccessControlImpl() {
+    if (cynara_) {
+      auto ret = cynara_finish(cynara_);
+      if (CYNARA_API_SUCCESS != ret) {
+        LoggerE("Failed to finalize Cynara");
+      }
+      cynara_ = nullptr;
+    }
+  }
+
+  bool CheckAccess(const std::vector<std::string>& privileges) {
+    if (cynara_) {
+      for (const auto& privilege : privileges) {
+        if (CYNARA_API_ACCESS_ALLOWED != cynara_simple_check(cynara_,  // p_cynara
+                                                             smack_label_.c_str(),  // client
+                                                             "", // client_session
+                                                             uid_.c_str(),  // user
+                                                             privilege.c_str()  // privilege
+                                                             )) {
+          return false;
+        }
+      }
+      return true;
+    } else {
+      return false;
+    }
+  }
+
+ private:
+  cynara* cynara_;
+  std::string uid_;
+  std::string smack_label_;
+};
+
+#else
+
+class AccessControlImpl {
+ public:
+  AccessControlImpl() {
+    LoggerD("Privilege access - deny all.");
+  }
+
+  bool CheckAccess(const std::vector<std::string>& privileges) {
+    return false;
+  }
+};
+
+#endif
+
+class AccessControl {
+ public:
+  static AccessControl& GetInstance() {
+    static AccessControl instance;
+    return instance;
+  }
+
+  bool CheckAccess(const std::string& privilege) {
+    return CheckAccess(std::vector<std::string>{privilege});
+  }
+
+  bool CheckAccess(const std::vector<std::string>& privileges) {
+    return impl_.CheckAccess(privileges);
+  }
+
+ private:
+  AccessControl() {}
+  ~AccessControl() {}
+  AccessControlImpl impl_;
+};
+
+} // namespace
+
+PlatformResult CheckAccess(const std::string& privilege) {
+  return CheckAccess(std::vector<std::string>{privilege});
+}
+
+PlatformResult CheckAccess(const std::vector<std::string>& privileges) {
+  LoggerD("Enter");
+  if (AccessControl::GetInstance().CheckAccess(privileges)) {
+    return PlatformResult(ErrorCode::NO_ERROR);
+  } else {
+    for (const auto& privilege : privileges) {
+      LoggerD("Access to privilege: %s has been denied.", privilege.c_str());
+    }
+    return PlatformResult(ErrorCode::SECURITY_ERR, "Permission denied");
+  }
+}
+
+std::string GetErrorString(int error_code) {
+  static const size_t kSize = 1024;
+  char msg[kSize] = {0};
+  strerror_r(error_code, msg, kSize);
+  return msg;
+}
+
+
+int HexToInt(char c) {
+  if (c >= '0' && c <= '9') {
+    return c - '0';
+  } else if (c >= 'A' && c <= 'Z') {
+    return c - 'A';
+  } else {
+    return c - 'a';
+  }
+}
+
+unsigned char* HexToBin(const char* hex, int size, unsigned char* bin, int bin_size) {
+  for (int i = 0; i < size - 1 && i / 2 < bin_size; i += 2) {
+    bin[i * 2] = HexToInt(hex[i]) << 4;
+    bin[i * 2] += HexToInt(hex[i + 1]);
+  }
+  return bin;
+}
+
+char* BinToHex(const unsigned char* bin, int size, char* hex, int hex_size) {
+  static const char * const digits = "0123456789ABCDEF";
+  for (int i = 0; i < size && i < hex_size / 2; i++) {
+    hex[i * 2] = digits[bin[i] >> 4];
+    hex[i * 2 + 1] = digits[bin[i] & 15];
+  }
+  return hex;
+}
+
+}  // namespace tools
+}  // namespace common
diff --git a/webWidgetTCT_device/src/common/tools.h b/webWidgetTCT_device/src/common/tools.h
new file mode 100755 (executable)
index 0000000..fcd9868
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2015 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 COMMON_TOOLS_H_
+#define COMMON_TOOLS_H_
+
+#include <string>
+#include <vector>
+
+#include "common/picojson.h"
+#include "common/platform_exception.h"
+#include "common/platform_result.h"
+
+namespace common {
+namespace tools {
+
+void ReportSuccess(picojson::object& out);
+void ReportSuccess(const picojson::value& result, picojson::object& out);
+void ReportError(picojson::object& out);
+void ReportError(const PlatformException& ex, picojson::object& out);
+void ReportError(const PlatformResult& error, picojson::object* out);
+
+common::PlatformResult CheckAccess(const std::string& privilege);
+common::PlatformResult CheckAccess(const std::vector<std::string>& privileges);
+
+#define CHECK_PRIVILEGE_ACCESS(privilege, out) \
+do { \
+  auto r = common::tools::CheckAccess(privilege); \
+  if (!r) { \
+    common::tools::ReportError(r, out); \
+    return; \
+  } \
+} while (0)
+
+#define CHECK_BACKWARD_COMPABILITY_PRIVILEGE_ACCESS(current_priv, prev_priv, out) \
+do { \
+  auto ret = common::tools::CheckAccess(current_priv); \
+  auto ret2 = common::tools::CheckAccess(prev_priv); \
+\
+  if (!ret && ret2) { \
+    ret = ret2; \
+  } \
+\
+  if (!ret) { \
+    common::tools::ReportError(ret, out); \
+    return; \
+  } \
+} while (0)
+
+/**
+ * @brief Safe wrapper of strerror() function.
+ *
+ * @param[in] error_code - error code to be passed to strerror()
+ *
+ * @return string representation of error_code
+ */
+std::string GetErrorString(int error_code);
+
+int HexToInt(char c);
+unsigned char* HexToBin(const char* hex, int size, unsigned char* bin, int bin_size);
+char* BinToHex(const unsigned char* bin, int size, char* hex, int hex_size);
+
+}  // namespace tools
+}  // namespace common
+
+#endif  // COMMON_TOOLS_H_
diff --git a/webWidgetTCT_device/src/common/tvsapi_subscribe_helper.cc b/webWidgetTCT_device/src/common/tvsapi_subscribe_helper.cc
new file mode 100755 (executable)
index 0000000..3ee0a38
--- /dev/null
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2015 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 "tvsapi_subscribe_helper.h"
+#include "common/logger.h"
+#include "common/platform_exception.h"
+
+namespace common
+{
+
+TvsSubscribeHelper::TvsSubscribeHelper():
+    m_Service(nullptr),
+    m_tvsSubscriber(nullptr)
+{
+    LoggerD("Entered");
+
+    int ret = TVServiceAPI::CreateService(&m_Service);
+    if (TVS_API_SUCCESS != ret) {
+        LoggerE("Failed to create tvs-api service: %d", ret);
+        return;
+    }
+    // only create subscriber - do not register on any signal here
+    ret = TVServiceAPI::CreateSignalSubscriber(
+            TvsSubscribeHelper::signalHandler, &m_tvsSubscriber);
+
+    if (TVS_API_SUCCESS != ret) {
+        LoggerE("Failed to create tvs-api SignalSubscriber");
+    }
+}
+
+IService* TvsSubscribeHelper::getService() {
+    return m_Service;
+}
+
+TvsSubscribeHelper::~TvsSubscribeHelper()
+{
+    LoggerD("Entered");
+    if(!m_tvsSubscriber)
+    {
+        LoggerE("No SignalSubscriber created!");
+        return;
+    }
+
+    // unregister signal handler in TVS-API subscriber
+    for(auto type:m_registeredSignals)
+    {
+        LoggerD("Unsubscribing listener for signal: %d", type);
+        m_tvsSubscriber->Unsubscribe((ESignalType)type);
+    }
+    TVServiceAPI::Destroy();
+}
+
+
+int TvsSubscribeHelper::signalHandler(ESignalType type, EProfile _profile,
+        u_int16_t _screenID, TSSignalData data, void* user_data)
+{
+    LoggerD("Entered: %d", type);
+
+    switch (type) {
+        case SIGNAL_EPG_COMPLETED:
+            LoggerD("SIGNAL_EPG_COMPLETED for channel number: %d", data.data.l[0]);
+            break;
+        case SIGNAL_LOCK_SUCCESS:
+            LoggerD("SIGNAL_LOCK_SUCCESS for ServiceId: %lld", data.data.ll);
+            break;
+    }
+
+    TvsSubscribeHelper* helper = static_cast<TvsSubscribeHelper*>(user_data);
+
+    auto range = helper->m_listeners.equal_range((int)type);
+    for(auto iter = range.first; iter != range.second; ++iter)
+    {
+        iter->second->OnSignal(type, data);
+    }
+
+    return 0;
+}
+
+std::multimap<int, TvsSignalListener*>::iterator TvsSubscribeHelper::findMatch(
+        int type, TvsSignalListener* listener)
+{
+    auto range = m_listeners.equal_range(type);
+
+    // if empty range returned then loop not executer and map::end returned
+    for(auto iter = range.first; iter != range.second; ++iter)
+    {
+        if(iter->second == listener)
+        {
+            return iter;
+        }
+    }
+
+    return m_listeners.end();
+}
+
+TvsSubscribeHelper& TvsSubscribeHelper::getInstance()
+{
+    LoggerD("Entered");
+
+    static TvsSubscribeHelper tsh;
+    return tsh;
+}
+
+PlatformResult TvsSubscribeHelper::registerListener(ESignalType type, TvsSignalListener* listener)
+{
+    LoggerD("Entered");
+    if(!m_tvsSubscriber)
+    {
+        LoggerE("No SignalSubscriber created!");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR);
+    }
+
+    if(!listener)
+    {
+        LoggerW("NULL-listener given - ignoring registration");
+        return PlatformResult(ErrorCode::INVALID_VALUES_ERR);
+    }
+
+    if(findMatch(type, listener) != m_listeners.end())
+    {
+        LoggerD("Given listener already registered for signal %d", type);
+        return PlatformResult(ErrorCode::NO_ERROR);
+    }
+
+    // add new listener for specific signal type
+    m_listeners.emplace((int)type, listener);
+
+    // if signal type not used yet then subscribe in TVS subcriber
+    if(m_registeredSignals.find((int)type) == m_registeredSignals.end())
+    {
+
+        int ret = m_tvsSubscriber->Subscribe(type, this);
+        if (TVS_API_METHOD_SUCCESS == ret) {
+            m_registeredSignals.insert((int)type);
+        }
+        else
+        {
+            LoggerW("Failed to add listener for: %d", type);
+            return PlatformResult(ErrorCode::UNKNOWN_ERR);
+        }
+    }
+
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+void TvsSubscribeHelper::unregisterListener(ESignalType type, TvsSignalListener* listener)
+{
+    LoggerD("Entered");
+    if(!m_tvsSubscriber)
+    {
+        LoggerE("No SignalSubscriber created!");
+        return;
+    }
+
+    // remove listener from list (if registered - otherwise exit)
+    auto exactMatch = findMatch(type, listener);
+    if(exactMatch == m_listeners.end())
+    {
+        LoggerW("Trying to remove not subscribed pair");
+        return;
+    }
+    else
+    {
+        m_listeners.erase(exactMatch);
+    }
+
+    // if there's no more listeners for specifed signal type
+    // unsubscribe in TVS subscriber
+    if(m_listeners.find((int)type) == m_listeners.end())
+    {
+        int ret = m_tvsSubscriber->Unsubscribe(type);
+        if (TVS_API_METHOD_SUCCESS == ret) {
+            m_registeredSignals.erase((int)type);
+        }
+        else
+        {
+            LoggerW("Failed to unsubscribe listener for: %d", type);
+        }
+    }
+
+    return;
+}
+
+} // namespace: common
diff --git a/webWidgetTCT_device/src/common/tvsapi_subscribe_helper.h b/webWidgetTCT_device/src/common/tvsapi_subscribe_helper.h
new file mode 100755 (executable)
index 0000000..74ddd4f
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2015 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 TVSAPI_SUBSCRIBE_HELPER_H
+#define TVSAPI_SUBSCRIBE_HELPER_H
+
+#include <TVServiceAPI.h>
+#include <map>
+#include <memory>
+#include <unordered_set>
+#include "common/platform_result.h"
+
+namespace common
+{
+
+static const int TVS_API_SUCCESS = 0;
+//  TVServiceAPI object methods return 1 on success
+static const int TVS_API_METHOD_SUCCESS = 1;
+//  TVServiceAPI object methods return -1 on failure
+static const int TVS_API_METHOD_FAILURE = -1;
+
+class TvsSignalListener
+{
+public:
+    virtual void OnSignal(ESignalType, TSSignalData) = 0;
+    virtual ~TvsSignalListener() {}
+};
+
+class TvsSubscribeHelper
+{
+private:
+    IService* m_Service;
+    ISignalSubscriber* m_tvsSubscriber;
+    std::multimap<int, TvsSignalListener*> m_listeners;
+    std::unordered_set<int> m_registeredSignals;
+
+    TvsSubscribeHelper();
+    TvsSubscribeHelper(TvsSubscribeHelper const&) = delete;
+    void operator=(TvsSubscribeHelper const&) = delete;
+    TvsSubscribeHelper(TvsSubscribeHelper &&) = delete;
+
+    static int signalHandler(ESignalType type, EProfile _profile,
+                        u_int16_t _screenID, TSSignalData data, void*);
+
+    std::multimap<int, TvsSignalListener*>::iterator findMatch(
+                                int type, TvsSignalListener* listener);
+
+public:
+    static TvsSubscribeHelper& getInstance();
+    ~TvsSubscribeHelper();
+
+// WARNING: register and unregister function are not thread-safe
+    PlatformResult registerListener(ESignalType type, TvsSignalListener* listener);
+    void unregisterListener(ESignalType type, TvsSignalListener* listener);
+    IService* getService();
+
+};
+
+
+} // namespace: common
+
+#endif // TVSAPI_SUBSCRIBE_HELPER_H
diff --git a/webWidgetTCT_device/src/common/typeutil.h b/webWidgetTCT_device/src/common/typeutil.h
new file mode 100755 (executable)
index 0000000..c20c398
--- /dev/null
@@ -0,0 +1,283 @@
+/*
+ * Copyright (c) 2015 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 COMMON_TYPEUTIL_H_
+#define COMMON_TYPEUTIL_H_
+
+#include <set>
+#include <string>
+
+#include "common/picojson.h"
+
+namespace common {
+
+namespace WIDLTypeValidator {
+
+enum WIDLType {
+  StringType,
+  ArrayType,
+  ObjectType,
+  BooleanType,
+  DoubleType,
+  FloatType,
+  ByteType,
+  OctetType,
+  ShortType,
+  UnsignedShortType,
+  LongType,
+  UnsignedLongType,
+  LongLongType,
+  UnsignedLongLongType,
+};
+
+using picojson::object;
+using picojson::value;
+using picojson::array;
+
+template <WIDLType E>
+bool IsType(const value& arg, const char* name);
+
+#define IS_TYPE_NORANGE(wtype, ctype) \
+    template <> bool IsType<wtype>(const value& arg, const char* name) { \
+      return arg.get(name).is<ctype>(); \
+    }
+IS_TYPE_NORANGE(StringType, std::string)
+IS_TYPE_NORANGE(ArrayType, array)
+IS_TYPE_NORANGE(ObjectType, object)
+IS_TYPE_NORANGE(BooleanType, bool)
+IS_TYPE_NORANGE(DoubleType, double)
+IS_TYPE_NORANGE(FloatType, double)
+#undef IS_TYPE_NORANGE
+
+#define IS_TYPE_RANGE(wtype, min, max) \
+      template <> bool IsType<wtype>(const value& arg, const char* name) { \
+        const value& v = arg.get(name); \
+        if (!v.is<double>()) return false; \
+        double n = v.get<double>(); \
+        if (n < min || n > max) return false; \
+        return true; \
+      }
+IS_TYPE_RANGE(ByteType, -128, 127)
+IS_TYPE_RANGE(OctetType, 0, 255)
+IS_TYPE_RANGE(ShortType, -32768, 32767)
+IS_TYPE_RANGE(UnsignedShortType, 0, 65535)
+IS_TYPE_RANGE(LongType, -2147483648L, 2147483647LL)
+IS_TYPE_RANGE(UnsignedLongType, 0, 4294967295ULL)
+IS_TYPE_RANGE(LongLongType, -9223372036854775807LL, 9223372036854775807LL)
+IS_TYPE_RANGE(UnsignedLongLongType, 0, 18446744073709551615ULL)
+#undef IS_TYPE_RANGE
+
+bool IsEnum(const value& arg, const std::string& name,
+            const std::set<std::string>& values) {
+  const value& v = arg.get(name);
+  return v.is<std::string>() &&
+      values.find(v.get<std::string>()) != values.end();
+}
+
+}  // namespace WIDLTypeValidator
+
+namespace CTypeConveter {
+
+enum CType {
+  StringType,
+  ArrayType
+};
+
+}  // namespace CTypeConveter
+
+}  // namespace common
+
+#ifdef TEST_TYPEUTIL
+#include <cstdlib>
+#include <cstdio>
+//using namespace common::WIDLTypeValidator;
+int main(void) {
+  const char *tc = 
+      "{"
+        "\"string\": \"string value\","
+        "\"object\": {\"first\":1, \"second\":2},"
+        "\"array\": [1,2,3,4],"
+        "\"array2\": [1,\"two\",3,{\"obj\":\"obj!!\"}],"
+        "\"boolean\": true,"
+        "\"double\": 12345678.9999,"
+        "\"float\": 12345.678,"
+        "\"byte1\": -128,"
+        "\"byte2\": 127,"
+        "\"octet\": 255,"
+        "\"short1\": -32768,"
+        "\"short2\": 32767,"
+        "\"ushort\": 65535,"
+        "\"long1\": -2147483648,"
+        "\"long2\": 2147483647,"
+        "\"ulong\": 4294967295,"
+        "\"longlong1\": -9223372036854775808,"
+        "\"longlong2\": 9223372036854775807,"
+        "\"ulonglong\": 18446744073709551615,"
+        "\"zero\": 0,"
+        "\"enum\": \"enum\""
+      "}";
+  picojson::value v;
+  std::string err = picojson::parse(v, tc, tc + strlen(tc));
+  printf("parse err : %s\n", err.c_str());
+
+
+  using common::WIDLTypeValidator::WIDLType;
+  using common::WIDLTypeValidator::IsType;
+  using common::WIDLTypeValidator::IsEnum;
+
+#define TC_POSITIVE(name, wtype) \
+  printf("%s positive %s : %s\n", #wtype, \
+         IsType<wtype>(v, name) ? "pass" : "fail", \
+         v.get(name).to_str().c_str());
+#define TC_NEGATIVE(name, wtype) \
+  printf("%s negative %s : %s\n", #wtype, \
+         !IsType<wtype>(v, name) ? "pass" : "fail", \
+         v.get(name).to_str().c_str());
+
+  TC_POSITIVE("string", WIDLType::StringType);
+  TC_NEGATIVE("object", WIDLType::StringType);
+  TC_NEGATIVE("array", WIDLType::StringType);
+  TC_NEGATIVE("array2", WIDLType::StringType);
+  TC_NEGATIVE("boolean", WIDLType::StringType);
+  TC_NEGATIVE("double", WIDLType::StringType);
+  TC_NEGATIVE("longlong", WIDLType::StringType);
+  TC_NEGATIVE("ulonglong", WIDLType::StringType);
+
+  TC_POSITIVE("object", WIDLType::ObjectType);
+  TC_NEGATIVE("string", WIDLType::ObjectType);
+  TC_NEGATIVE("array", WIDLType::ObjectType);
+  TC_NEGATIVE("array2", WIDLType::ObjectType);
+  TC_NEGATIVE("boolean", WIDLType::ObjectType);
+  TC_NEGATIVE("double", WIDLType::ObjectType);
+  TC_NEGATIVE("longlong", WIDLType::ObjectType);
+  TC_NEGATIVE("ulonglong", WIDLType::ObjectType);
+
+  TC_POSITIVE("array", WIDLType::ArrayType);
+  TC_POSITIVE("array2", WIDLType::ArrayType);
+  TC_NEGATIVE("string", WIDLType::ArrayType);
+  TC_NEGATIVE("boolean", WIDLType::ArrayType);
+  TC_NEGATIVE("double", WIDLType::ArrayType);
+  TC_NEGATIVE("longlong", WIDLType::ArrayType);
+  TC_NEGATIVE("ulonglong", WIDLType::ArrayType);
+
+  TC_POSITIVE("boolean", WIDLType::BooleanType);
+  TC_NEGATIVE("object", WIDLType::BooleanType);
+  TC_NEGATIVE("string", WIDLType::BooleanType);
+  TC_NEGATIVE("array", WIDLType::BooleanType);
+  TC_NEGATIVE("array2", WIDLType::BooleanType);
+  TC_NEGATIVE("double", WIDLType::BooleanType);
+  TC_NEGATIVE("longlong", WIDLType::BooleanType);
+  TC_NEGATIVE("ulonglong", WIDLType::BooleanType);
+
+  TC_POSITIVE("byte1", WIDLType::ByteType);
+  TC_POSITIVE("byte2", WIDLType::ByteType);
+  TC_NEGATIVE("object", WIDLType::ByteType);
+  TC_NEGATIVE("string", WIDLType::ByteType);
+  TC_NEGATIVE("array", WIDLType::ByteType);
+  TC_NEGATIVE("array2", WIDLType::ByteType);
+  TC_NEGATIVE("boolean", WIDLType::ByteType);
+  TC_NEGATIVE("double", WIDLType::ByteType);
+  TC_NEGATIVE("longlong", WIDLType::ByteType);
+  TC_NEGATIVE("ulonglong", WIDLType::ByteType);
+
+  TC_POSITIVE("octet", WIDLType::OctetType);
+  TC_POSITIVE("zero", WIDLType::OctetType);
+  TC_NEGATIVE("byte1", WIDLType::OctetType);
+  TC_NEGATIVE("object", WIDLType::OctetType);
+  TC_NEGATIVE("string", WIDLType::OctetType);
+  TC_NEGATIVE("array", WIDLType::OctetType);
+  TC_NEGATIVE("array2", WIDLType::OctetType);
+  TC_NEGATIVE("boolean", WIDLType::OctetType);
+  TC_NEGATIVE("double", WIDLType::OctetType);
+  TC_NEGATIVE("longlong", WIDLType::OctetType);
+  TC_NEGATIVE("ulonglong", WIDLType::OctetType);
+
+  TC_POSITIVE("short1", WIDLType::ShortType);
+  TC_POSITIVE("short2", WIDLType::ShortType);
+  TC_NEGATIVE("object", WIDLType::ShortType);
+  TC_NEGATIVE("string", WIDLType::ShortType);
+  TC_NEGATIVE("array", WIDLType::ShortType);
+  TC_NEGATIVE("array2", WIDLType::ShortType);
+  TC_NEGATIVE("boolean", WIDLType::ShortType);
+  TC_NEGATIVE("double", WIDLType::ShortType);
+  TC_NEGATIVE("longlong", WIDLType::ShortType);
+  TC_NEGATIVE("ulonglong", WIDLType::ShortType);
+
+  TC_POSITIVE("ushort", WIDLType::UnsignedShortType);
+  TC_POSITIVE("zero", WIDLType::UnsignedShortType);
+  TC_NEGATIVE("object", WIDLType::UnsignedShortType);
+  TC_NEGATIVE("string", WIDLType::UnsignedShortType);
+  TC_NEGATIVE("array", WIDLType::UnsignedShortType);
+  TC_NEGATIVE("array2", WIDLType::UnsignedShortType);
+  TC_NEGATIVE("boolean", WIDLType::UnsignedShortType);
+  TC_NEGATIVE("double", WIDLType::UnsignedShortType);
+  TC_NEGATIVE("longlong", WIDLType::UnsignedShortType);
+  TC_NEGATIVE("ulonglong", WIDLType::UnsignedShortType);
+
+  TC_POSITIVE("long1", WIDLType::LongType);
+  TC_POSITIVE("long2", WIDLType::LongType);
+  TC_NEGATIVE("object", WIDLType::LongType);
+  TC_NEGATIVE("string", WIDLType::LongType);
+  TC_NEGATIVE("array", WIDLType::LongType);
+  TC_NEGATIVE("array2", WIDLType::LongType);
+  TC_NEGATIVE("boolean", WIDLType::LongType);
+  TC_NEGATIVE("longlong", WIDLType::LongType);
+  TC_NEGATIVE("ulonglong", WIDLType::LongType);
+
+  TC_POSITIVE("ulong", WIDLType::UnsignedLongType);
+  TC_POSITIVE("zero", WIDLType::UnsignedLongType);
+  TC_NEGATIVE("object", WIDLType::UnsignedLongType);
+  TC_NEGATIVE("string", WIDLType::UnsignedLongType);
+  TC_NEGATIVE("array", WIDLType::UnsignedLongType);
+  TC_NEGATIVE("array2", WIDLType::UnsignedLongType);
+  TC_NEGATIVE("boolean", WIDLType::UnsignedLongType);
+  TC_NEGATIVE("longlong", WIDLType::UnsignedLongType);
+  TC_NEGATIVE("ulonglong", WIDLType::UnsignedLongType);
+
+  TC_POSITIVE("longlong1", WIDLType::LongLongType);
+  TC_POSITIVE("longlong2", WIDLType::LongLongType);
+  TC_NEGATIVE("object", WIDLType::LongLongType);
+  TC_NEGATIVE("string", WIDLType::LongLongType);
+  TC_NEGATIVE("array", WIDLType::LongLongType);
+  TC_NEGATIVE("array2", WIDLType::LongLongType);
+  TC_NEGATIVE("boolean", WIDLType::LongLongType);
+  TC_NEGATIVE("ulonglong", WIDLType::LongLongType);
+
+  TC_POSITIVE("ulonglong", WIDLType::UnsignedLongLongType);
+  TC_POSITIVE("zero", WIDLType::UnsignedLongLongType);
+  TC_NEGATIVE("object", WIDLType::UnsignedLongLongType);
+  TC_NEGATIVE("string", WIDLType::UnsignedLongLongType);
+  TC_NEGATIVE("array", WIDLType::UnsignedLongLongType);
+  TC_NEGATIVE("array2", WIDLType::UnsignedLongLongType);
+  TC_NEGATIVE("boolean", WIDLType::UnsignedLongLongType);
+
+  std::string values[] = {
+    "enum", "foo", "bar"
+  };
+  std::set<std::string> enums(values, values+3);
+  bool enum_p = IsEnum(v, "enum", enums);
+  printf("%s positive %s : %s\n", "enum", enum_p ? "pass" : "fail",
+         v.get("enum").to_str().c_str());
+  bool enum_n = IsEnum(v, "xxx", enums);
+  printf("%s negative %s : %s\n", "enum", !enum_n ? "pass" : "fail",
+         v.get("enum").to_str().c_str());
+
+#undef TC_POSITIVE
+#undef TC_NEGATIVE
+}
+#endif  // TEST_TYPEUTIL
+
+#endif  // COMMON_TYPEUTIL_H_
diff --git a/webWidgetTCT_device/src/common/utils.h b/webWidgetTCT_device/src/common/utils.h
new file mode 100755 (executable)
index 0000000..c118025
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright (c) 2013 Intel Corporation. All rights reserved.
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMMON_UTILS_H_
+#define COMMON_UTILS_H_
+
+// Put this in the private: declarations for a class to be uncopyable.
+#define DISALLOW_COPY(TypeName) \
+  TypeName(const TypeName&)
+
+// Put this in the private: declarations for a class to be unassignable.
+#define DISALLOW_ASSIGN(TypeName) \
+  void operator=(const TypeName&)
+
+// A macro to disallow the copy constructor and operator= functions
+// This should be used in the private: declarations for a class
+#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
+  TypeName(const TypeName&);               \
+  void operator=(const TypeName&)
+
+#endif  // COMMON_UTILS_H_
diff --git a/webWidgetTCT_device/src/common/video_source_types.cc b/webWidgetTCT_device/src/common/video_source_types.cc
new file mode 100755 (executable)
index 0000000..ab1a271
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2015 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 "video_source_types.h"
+#include "common/logger.h"
+#include <map>
+#include <algorithm>
+
+namespace VideoSourceTypes {
+
+namespace{
+
+
+sourceMapType sourceMap = {
+        { SOURCE_TYPE_TV, SourceDesc( SourceType::SOURCETYPE_TV, 1 ) },
+        { SOURCE_TYPE_AV1, SourceDesc( SourceType::SOURCETYPE_AV, 1 ) },
+        { SOURCE_TYPE_AV2, SourceDesc( SourceType::SOURCETYPE_AV, 2 ) },
+        { SOURCE_TYPE_AV3, SourceDesc( SourceType::SOURCETYPE_AV, 3 ) },
+        { SOURCE_TYPE_SVIDEO1, SourceDesc( SourceType::SOURCETYPE_SVIDEO, 1 ) },
+        { SOURCE_TYPE_SVIDEO2, SourceDesc( SourceType::SOURCETYPE_SVIDEO, 2 ) },
+        { SOURCE_TYPE_SVIDEO3, SourceDesc( SourceType::SOURCETYPE_SVIDEO, 3 ) },
+        { SOURCE_TYPE_COMP1, SourceDesc( SourceType::SOURCETYPE_COMP, 1 ) },
+        { SOURCE_TYPE_COMP2, SourceDesc( SourceType::SOURCETYPE_COMP, 2 ) },
+        { SOURCE_TYPE_COMP3, SourceDesc( SourceType::SOURCETYPE_COMP, 3 ) },
+        { SOURCE_TYPE_PC1, SourceDesc( SourceType::SOURCETYPE_PC, 1 ) },
+        { SOURCE_TYPE_PC2, SourceDesc( SourceType::SOURCETYPE_PC, 2 ) },
+        { SOURCE_TYPE_PC3, SourceDesc( SourceType::SOURCETYPE_PC, 3 ) },
+        { SOURCE_TYPE_HDMI1, SourceDesc( SourceType::SOURCETYPE_HDMI, 1 ) },
+        { SOURCE_TYPE_HDMI2, SourceDesc( SourceType::SOURCETYPE_HDMI, 2 ) },
+        { SOURCE_TYPE_HDMI3, SourceDesc( SourceType::SOURCETYPE_HDMI, 3 ) },
+        { SOURCE_TYPE_HDMI4, SourceDesc( SourceType::SOURCETYPE_HDMI, 4 ) },
+        { SOURCE_TYPE_SCART1, SourceDesc( SourceType::SOURCETYPE_SCART, 1 ) },
+        { SOURCE_TYPE_SCART2, SourceDesc( SourceType::SOURCETYPE_SCART, 2 ) },
+        { SOURCE_TYPE_SCART3, SourceDesc( SourceType::SOURCETYPE_SCART, 3 ) },
+        { SOURCE_TYPE_DVI1, SourceDesc( SourceType::SOURCETYPE_DVI, 1 ) },
+        { SOURCE_TYPE_DVI2, SourceDesc( SourceType::SOURCETYPE_DVI, 2 ) },
+        { SOURCE_TYPE_DVI3, SourceDesc( SourceType::SOURCETYPE_DVI, 3 ) }
+};
+
+sourceNameType sourceName = {
+    {SOURCETYPE_TV,"TV"},
+    {SOURCETYPE_AV,"AV"},
+    {SOURCETYPE_SVIDEO,"SVIDEO"},
+    {SOURCETYPE_COMP,"COMP"},
+    {SOURCETYPE_PC,"PC"},
+    {SOURCETYPE_HDMI,"HDMI"},
+    {SOURCETYPE_SCART,"SCART"},
+    {SOURCETYPE_DVI,"DVI"},
+    {SOURCETYPE_MEDIA,"MEDIA"}
+};
+}
+
+sourceMapType::const_iterator getSourceMapTypeBeginIterator()
+{
+    return sourceMap.cbegin();
+}
+
+sourceMapType::const_iterator getSourceMapTypeEndIterator()
+{
+    return sourceMap.cend();
+}
+
+bool SourceDescFromESource(ESource src,SourceDesc& desc)
+{
+    sourceMapType::iterator it = sourceMap.find(src);
+    if (it == sourceMap.end() ) {
+        LoggerE("Unknown source type: %d", src);
+        return true;
+    }
+    desc = it->second;
+    return false;
+}
+
+bool ESourceFromSourceDesc(SourceDesc desc,ESource& src )
+{
+    auto it = std::find_if(sourceMap.begin(), sourceMap.end(),
+        [&desc](std::pair<ESource, VideoSourceTypes::SourceDesc>_record)->bool{
+            return (_record.second.type == desc.type &&_record.second.number == desc.number);
+        });
+
+    if(it != sourceMap.end()) {
+        src = it->first;
+        return false;
+    }
+    return true;
+}
+
+bool SourceTypeToName(SourceType type,std::string&name)
+{
+    sourceNameType::iterator it = sourceName.find(type);
+    if (it == sourceName.end() ) {
+        LoggerE("Unknown source type: %d", type);
+        return true;
+    }
+    name=it->second;
+    return false;
+}
+bool NameToSourceType(std::string name,SourceType& type )
+{
+    auto it = std::find_if(sourceName.begin(), sourceName.end(),
+        [&name]( std::pair<VideoSourceTypes::SourceType, std::string>_record )->bool{
+            return (!_record.second.compare(name));
+        });
+    if(it != sourceName.end()) {
+        type=it->first;
+        return false;
+    }
+    return true;
+}
+
+}
diff --git a/webWidgetTCT_device/src/common/video_source_types.h b/webWidgetTCT_device/src/common/video_source_types.h
new file mode 100755 (executable)
index 0000000..40cd40c
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2015 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 _VIDEO_SOURCE_TYPES_H_
+#define _VIDEO_SOURCE_TYPES_H_
+
+
+#include <TVServiceAPI.h>
+#include <map>
+
+namespace VideoSourceTypes
+{
+
+struct SourceDesc;
+
+enum SourceType
+{
+    SOURCETYPE_TV,
+    SOURCETYPE_AV,
+    SOURCETYPE_SVIDEO,
+    SOURCETYPE_COMP,
+    SOURCETYPE_PC,
+    SOURCETYPE_HDMI,
+    SOURCETYPE_SCART,
+    SOURCETYPE_DVI,
+    SOURCETYPE_MEDIA
+
+};
+
+typedef std::map<ESource, SourceDesc> sourceMapType;
+typedef std::map<SourceType, std::string> sourceNameType;
+
+struct SourceDesc
+{
+    SourceDesc() :
+        type(SOURCETYPE_TV), number(0) {};
+    SourceDesc(SourceType _type, unsigned long _number):
+        type( _type ), number( _number ){}
+    SourceType type;
+    unsigned long number;
+};
+
+sourceMapType::const_iterator getSourceMapTypeBeginIterator();
+sourceMapType::const_iterator getSourceMapTypeEndIterator();
+
+bool SourceDescFromESource(ESource src,SourceDesc& desc);
+bool ESourceFromSourceDesc(SourceDesc,ESource&);
+
+bool SourceTypeToName(SourceType,std::string&);
+bool NameToSourceType(std::string,SourceType&);
+
+}
+#endif
diff --git a/webWidgetTCT_device/src/common/xwalk_js2c.gypi b/webWidgetTCT_device/src/common/xwalk_js2c.gypi
new file mode 100755 (executable)
index 0000000..38d5710
--- /dev/null
@@ -0,0 +1,23 @@
+{
+  'rules': [
+    {
+      'rule_name': 'xwalk_js2c',
+      'extension': 'js',
+      'inputs': [
+        '../../tools/generate_api.py',
+      ],
+      'outputs': [
+        '<(SHARED_INTERMEDIATE_DIR)/<(RULE_INPUT_ROOT).cc'
+      ],
+      'process_outputs_as_sources': 1,
+      'action': [
+        'python',
+        '<@(_inputs)',
+        '<(RULE_INPUT_PATH)',
+        'kSource_<(RULE_INPUT_ROOT)',
+        '<@(_outputs)',
+      ],
+      'message': 'Generating code from <(RULE_INPUT_PATH)',
+    },
+  ],
+}
diff --git a/webWidgetTCT_device/src/contact/addressbook.cc b/webWidgetTCT_device/src/contact/addressbook.cc
new file mode 100755 (executable)
index 0000000..461b527
--- /dev/null
@@ -0,0 +1,911 @@
+/*
+ * Copyright (c) 2015 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 "contact/addressbook.h"
+
+#include "common/converter.h"
+#include "common/extension.h"
+#include "common/logger.h"
+#include "common/platform_exception.h"
+#include "common/scope_exit.h"
+
+#include <contacts.h>
+#include "contact/contact_instance.h"
+
+namespace extension {
+namespace contact {
+namespace AddressBook {
+
+using namespace common;
+
+typedef std::shared_ptr<JsonValue> shared_json_value;
+
+namespace {
+static const long kUnifiedAddressBookId = -1;
+const char* kContactListenerId = "ContactChangeListener";
+
+inline long AddressBookId(const JsonObject& obj) {
+  return common::stol(FromJson<JsonString>(obj, "addressBook", "id"));
+}
+
+inline bool IsUnified(const JsonObject& args) {
+  return AddressBookId(args) == kUnifiedAddressBookId;
+}
+
+inline bool IsUnified(long id) { return id == kUnifiedAddressBookId; }
+
+}  // anonymous namespace
+
+PlatformResult AddressBookGet(const JsonObject& args, JsonObject& out) {
+  LoggerD("Enter");
+  PlatformResult status = ContactUtil::CheckDBConnection();
+  if (status.IsError()) return status;
+
+  int contact_id = common::stol(FromJson<JsonString>(args, "id"));
+
+  contacts_record_h contacts_record = nullptr;
+  int err = contacts_db_get_record(_contacts_contact._uri, contact_id,
+                                   &contacts_record);
+  if (CONTACTS_ERROR_NONE != err) {
+    LoggerW("Contacts record get error, error code: %d", err);
+    return PlatformResult(ErrorCode::NOT_FOUND_ERR,
+                          "Contacts record get error");
+  }
+  ContactUtil::ContactsRecordHPtr contacts_record_ptr(
+      &contacts_record, ContactUtil::ContactsDeleter);
+
+  out["id"] = picojson::value(std::to_string(contact_id));
+  status =
+      ContactUtil::ImportContactFromContactsRecord(*contacts_record_ptr, &out);
+  if (status.IsError()) return status;
+
+  status = ContactUtil::UpdateAdditionalInformation(contacts_record_ptr, &out);
+  if (status.IsError()) return status;
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult AddressBookAdd(const JsonObject& args, JsonObject& out) {
+  LoggerD("Enter");
+  PlatformResult status = ContactUtil::CheckDBConnection();
+  if (status.IsError()) return status;
+
+  const JsonObject& contact = FromJson<JsonObject>(args, "contact");
+
+  if (!IsNull(contact, "id")) {
+    LoggerW("Contact already exists");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Contact already exists");
+  }
+
+  contacts_record_h contacts_record = nullptr;
+  int err = 0;
+  err = contacts_record_create(_contacts_contact._uri, &contacts_record);
+  if (CONTACTS_ERROR_NONE != err) {
+    LoggerW("Contacts record create error, error code: %d", err);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Contacts record create error");
+  }
+
+  // contacts_record starts to be protected by unique_ptr
+  ContactUtil::ContactsRecordHPtr contacts_record_ptr(
+      &contacts_record, ContactUtil::ContactsDeleter);
+  status =
+      ContactUtil::ExportContactToContactsRecord(*contacts_record_ptr, contact);
+  if (status.IsError()) return status;
+
+  int id = -1;
+  err = contacts_db_insert_record(*contacts_record_ptr, &id);
+  if (CONTACTS_ERROR_NONE != err) {
+    LoggerW("Contacts db insert error, error code: %d", err);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Contacts db insert error");
+  }
+
+  contacts_record_h reset_record;
+  err = contacts_db_get_record(_contacts_contact._uri, id, &reset_record);
+  if (CONTACTS_ERROR_NONE != err) {
+    LoggerW("Contacts record get error, error code: %d", err);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Contacts record get error");
+  }
+  if (nullptr != reset_record) {
+    LoggerE("reset");
+    contacts_record_ptr.reset(&reset_record);
+  }
+
+  out.insert(std::make_pair("id", JsonValue{std::to_string(id)}));
+
+  status = ContactUtil::UpdateAdditionalInformation(contacts_record_ptr, &out);
+  if (status.IsError()) return status;
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult AddressBookUpdate(const JsonObject& args, JsonObject& out) {
+  LoggerD("Enter");
+  PlatformResult status = ContactUtil::CheckDBConnection();
+  if (status.IsError()) return status;
+
+  const JsonObject& contact = FromJson<JsonObject>(args, "contact");
+  const JsonObject& addressbook = FromJson<JsonObject>(args, "addressBook");
+  long contactId = common::stol(FromJson<JsonString>(contact, "id"));
+
+  if (IsNull(contact, "id")) {
+    LoggerW("Contact doesn't exist");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Contact doesn't exist");
+  }
+
+  if (IsNull(addressbook, "id")) {
+    LoggerE("Contact is not saved in database");
+    return PlatformResult(ErrorCode::INVALID_VALUES_ERR,
+                          "Contact is not saved in database");
+  }
+
+  contacts_record_h to_update = nullptr;
+  int err = contacts_db_get_record(_contacts_contact._uri, contactId, &to_update);
+  if (CONTACTS_ERROR_NONE != err) {
+    LoggerW("Problem with getting contact. Error: %d", err);
+    return PlatformResult(ErrorCode::NOT_FOUND_ERR,
+                          "Problem with getting contact");
+  }
+  ContactUtil::ContactsRecordHPtr contacts_record_ptr(
+      &to_update, ContactUtil::ContactsDeleter);
+  status =
+      ContactUtil::ExportContactToContactsRecord(*contacts_record_ptr, contact);
+  if (status.IsError()) return status;
+
+  err = contacts_db_update_record(*contacts_record_ptr);
+  if (CONTACTS_ERROR_NONE != err) {
+    if (CONTACTS_ERROR_INVALID_PARAMETER == err) {
+      LoggerE("Error during executing contacts_db_update_record(). Error: %d",
+              err);
+      return PlatformResult(
+          ErrorCode::NOT_FOUND_ERR,
+          "Error during executing contacts_db_update_record().");
+    }
+    if (CONTACTS_ERROR_DB == err) {
+      LoggerE("Error during executing contacts_db_update_record(). Error: %d",
+              err);
+      return PlatformResult(
+          ErrorCode::UNKNOWN_ERR,
+          "Error during executing contacts_db_update_record().");
+    }
+  }
+
+  status = ContactUtil::UpdateAdditionalInformation(contacts_record_ptr, &out);
+  if (status.IsError()) return status;
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult AddressBookRemove(const JsonObject& args, JsonObject&) {
+  LoggerE("entered");
+  PlatformResult status = ContactUtil::CheckDBConnection();
+  if (status.IsError()) return status;
+
+  int contact_id = common::stol(FromJson<JsonString>(args, "id"));
+
+  if (contact_id < 0) {
+    return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Nagative contact id");
+  }
+
+  int err = contacts_db_delete_record(_contacts_contact._uri, contact_id);
+  if (CONTACTS_ERROR_NO_DATA == err) {
+    return PlatformResult(ErrorCode::NOT_FOUND_ERR,
+                          "Remove failed: contact not found");
+  } else if (CONTACTS_ERROR_NONE != err) {
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Contacts record delete error");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult AddressBookAddBatch(const JsonObject& args, JsonArray& out) {
+  LoggerD("Enter");
+
+  PlatformResult status = ContactUtil::CheckDBConnection();
+  if (status.IsError()) return status;
+
+  const JsonArray& batch_args = FromJson<JsonArray>(args, "batchArgs");
+  long addressBookId =
+      common::stol(FromJson<JsonString>(args, "addressBookId"));
+  addressBookId = addressBookId == -1 ? 0 : addressBookId;
+
+  int length = static_cast<int>(batch_args.size());
+  contacts_list_h contacts_list = NULL;
+  int error_code = contacts_list_create(&contacts_list);
+  if (CONTACTS_ERROR_NONE != error_code) {
+    LoggerE("list creation failed, code: %d", error_code);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "list creation failed");
+  }
+  ContactUtil::ContactsListHPtr contacts_list_ptr(
+      &contacts_list, ContactUtil::ContactsListDeleter);
+
+  for (auto& item : batch_args) {
+    contacts_record_h contacts_record = nullptr;
+    int err = 0;
+    err = contacts_record_create(_contacts_contact._uri, &contacts_record);
+    if (CONTACTS_ERROR_NONE != err) {
+      LoggerW("Contacts record create error, error code: %d", err);
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "Contacts record create error");
+    }
+    ContactUtil::ContactsRecordHPtr x(&contacts_record,
+                                      ContactUtil::ContactsDeleter);
+    PlatformResult status = ContactUtil::ExportContactToContactsRecord(
+        contacts_record, JsonCast<JsonObject>(item));
+    if (status.IsError()) return status;
+
+    status = ContactUtil::SetIntInRecord(
+        contacts_record, _contacts_contact.address_book_id, addressBookId);
+    if (status.IsError()) return status;
+
+    error_code = contacts_list_add(*contacts_list_ptr, *(x.release()));
+    if (CONTACTS_ERROR_NONE != error_code) {
+      LoggerE("error during add record to list, code: %d", error_code);
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "error during add record to list");
+    }
+  }
+
+  int* ids = nullptr;
+  int count = 0;
+
+  SCOPE_EXIT {
+    free(ids);
+  };
+
+  error_code = contacts_db_insert_records(*contacts_list_ptr, &ids, &count);
+  if (CONTACTS_ERROR_NONE != error_code || nullptr == ids) {
+    LoggerE("inserting contacts to db fails, code: %d", error_code);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "inserting contacts to db fails");
+  }
+
+  if (length != count) {
+    LoggerW("Added different number of contacts");
+  }
+
+  for (int i = 0; i < count; i++) {
+    JsonObject out_object;
+    contacts_record_h contact_record = nullptr;
+    error_code =
+        contacts_db_get_record(_contacts_contact._uri, ids[i], &contact_record);
+    if (CONTACTS_ERROR_NONE != error_code) {
+      LoggerW("Contacts record get error, error code: %d", error_code);
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "Contacts record get error");
+    }
+    PlatformResult status = ContactUtil::ImportContactFromContactsRecord(
+        contact_record, &out_object);
+    if (status.IsError()) return status;
+
+    out.push_back(JsonValue{out_object});
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+// TODO all batch operations should be implemented using CAPI batch functions
+PlatformResult AddressBookBatchFunc(NativeFunction impl,
+                                    const char* single_arg_name,
+                                    const JsonObject& args, JsonArray& out) {
+  LoggerD("Enter");
+  const JsonArray& batch_args = FromJson<JsonArray>(args, "batchArgs");
+  const JsonObject& address_book = FromJson<JsonObject>(args, "addressBook");
+
+  int i = 0;
+  for (auto& item : batch_args) {
+    ++i;
+    JsonObject single_args{};
+
+    single_args["addressBook"] = picojson::value(address_book);
+    single_args[single_arg_name] = picojson::value(item);
+
+    JsonObject single_out;
+    PlatformResult status = impl(single_args, single_out);
+    if (status.IsError()) return status;
+
+    if (!single_out.empty()) {
+      out.push_back(JsonValue{single_out});
+    }
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult AddressBookFind(const JsonObject& args, JsonArray& array) {
+  LoggerD("Entered");
+  PlatformResult status = ContactUtil::CheckDBConnection();
+  if (status.IsError()) return status;
+
+  // TODO implement contact filter and sorting.
+  const JsonObject& address_book = FromJson<JsonObject>(args, "addressBook");
+  long addressbook_id = common::stol(FromJson<std::string>(address_book, "id"));
+  int error_code;
+
+  contacts_list_h list = nullptr;
+
+  if (IsUnified(addressbook_id)) {
+    LoggerD("calling contacts_db_get_all_records");
+    error_code = contacts_db_get_all_records(_contacts_contact._uri, 0, 0, &list);
+    status =
+        ContactUtil::ErrorChecker(error_code, "Failed contacts_db_get_all_records");
+    if (status.IsError())  {
+      LoggerD("contacts_db_get_all_records - exit with error");
+      return status;
+    }
+  } else {
+    contacts_query_h query = nullptr;
+    contacts_filter_h filter = nullptr;
+
+    error_code = contacts_query_create(_contacts_contact._uri, &query);
+    status =
+        ContactUtil::ErrorChecker(error_code, "Failed contacts_query_create");
+    if (status.IsError()) return status;
+    ContactUtil::ContactsQueryHPtr query_ptr(&query,
+                                             ContactUtil::ContactsQueryDeleter);
+    error_code = contacts_filter_create(_contacts_contact._uri, &filter);
+    status =
+        ContactUtil::ErrorChecker(error_code, "Failed contacts_filter_create");
+    if (status.IsError()) return status;
+    ContactUtil::ContactsFilterPtr filter_ptr(filter,
+                                              ContactUtil::ContactsFilterDeleter);
+    error_code =
+        contacts_filter_add_int(filter, _contacts_contact.address_book_id,
+                                CONTACTS_MATCH_EQUAL, addressbook_id);
+    status =
+        ContactUtil::ErrorChecker(error_code, "Failed contacts_filter_add_int");
+    if (status.IsError()) return status;
+    error_code = contacts_query_set_filter(query, filter);
+    status =
+        ContactUtil::ErrorChecker(error_code, "Failed contacts_query_set_filter");
+    if (status.IsError()) return status;
+    error_code = contacts_db_get_records_with_query(query, 0, 0, &list);
+    status = ContactUtil::ErrorChecker(
+        error_code, "Failed contacts_db_get_records_with_query");
+    if (status.IsError()) return status;
+  }
+  ContactUtil::ContactsListHPtr list_ptr(&list,
+                                         ContactUtil::ContactsListDeleter);
+
+  int record_count = 0;
+  error_code = contacts_list_get_count(list, &record_count);
+  status =
+      ContactUtil::ErrorChecker(error_code, "Failed contacts_list_get_count");
+  if (status.IsError()) return status;
+
+  contacts_list_first(list);
+  for (int i = 0; i < record_count; i++) {
+    contacts_record_h record;
+    error_code = contacts_list_get_current_record_p(list, &record);
+    status = ContactUtil::ErrorChecker(
+        error_code, "Failed contacts_list_get_current_record_p");
+    if (status.IsError()) return status;
+
+    int id_value = 0;
+    error_code =
+        contacts_record_get_int(record, _contacts_contact.id, &id_value);
+    status =
+        ContactUtil::ErrorChecker(error_code, "Failed contacts_record_get_int");
+    if (status.IsError()) return status;
+
+    array.push_back(JsonValue(static_cast<double>(id_value)));
+    contacts_list_next(list);
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult AddressBookAddGroup(const JsonObject& args, JsonObject& out) {
+  LoggerD("Enter");
+  PlatformResult status = ContactUtil::CheckDBConnection();
+  if (status.IsError()) return status;
+
+  const JsonObject& group = FromJson<JsonObject>(args, "group");
+  if (!IsNull(group, "id") || !IsNull(group, "addressBookId")) {
+    LoggerE("Group object is previously added");
+    return PlatformResult(ErrorCode::INVALID_VALUES_ERR,
+                          "Group object is previously added");
+  }
+
+  contacts_record_h contacts_record = nullptr;
+  int err = contacts_record_create(_contacts_group._uri, &contacts_record);
+  status = ContactUtil::ErrorChecker(
+      err, "Error during executing contacts_record_create()");
+  if (status.IsError()) return status;
+
+  ContactUtil::ContactsRecordHPtr record(&contacts_record,
+                                         ContactUtil::ContactsDeleter);
+
+  long addressbook_id =
+      common::stol(FromJson<JsonString>(args, "addressBookId"));
+  addressbook_id = (IsUnified(addressbook_id)) ? 0 : addressbook_id;
+  status = ContactUtil::SetIntInRecord(
+      contacts_record, _contacts_group.address_book_id, addressbook_id);
+  if (status.IsError()) return status;
+
+  status =
+      ContactUtil::ExportContactGroupToContactsRecord(contacts_record, group);
+  if (status.IsError()) return status;
+
+  int groupId = 0;
+  err = contacts_db_insert_record(contacts_record, &groupId);
+  status = ContactUtil::ErrorChecker(err, "Error during insert group record");
+  if (status.IsError()) return status;
+
+  out["id"] = picojson::value(std::to_string(groupId));
+  out["addressBookId"] = picojson::value(std::to_string(addressbook_id));
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult AddressBookGetGroup(const JsonObject& args, JsonObject& out) {
+  LoggerD("Enter");
+  PlatformResult status = ContactUtil::CheckDBConnection();
+  if (status.IsError()) return status;
+
+  long id = common::stol(FromJson<JsonString>(args, "id"));
+
+  if (id < 0) {
+    return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Incorrect group id");
+  }
+
+  contacts_record_h contacts_record = nullptr;
+  int err = contacts_db_get_record(_contacts_group._uri, id, &contacts_record);
+  if (CONTACTS_ERROR_NONE != err || nullptr == contacts_record) {
+    LoggerE("Group not exist");
+    return PlatformResult(ErrorCode::NOT_FOUND_ERR, "Group not exist");
+  }
+
+  ContactUtil::ContactsRecordHPtr record(&contacts_record,
+                                         ContactUtil::ContactsDeleter);
+
+  long addressbook_id =
+      common::stol(FromJson<JsonString>(args, "addressBook", "id"));
+  if (IsUnified(addressbook_id)) {
+    int address_book_id = 0;
+    status = ContactUtil::GetIntFromRecord(
+        contacts_record, _contacts_group.address_book_id, &address_book_id);
+    if (status.IsError()) return status;
+
+    if (address_book_id != addressbook_id) {
+      return PlatformResult(ErrorCode::NOT_FOUND_ERR,
+                            "No group in this address book.");
+    }
+  }
+
+  status =
+      ContactUtil::ImportContactGroupFromContactsRecord(contacts_record, &out);
+  if (status.IsError()) return status;
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult AddressBookUpdateGroup(const JsonObject& args, JsonObject&) {
+  LoggerD("Enter");
+  PlatformResult status = ContactUtil::CheckDBConnection();
+  if (status.IsError()) return status;
+
+  const JsonObject& group = FromJson<JsonObject>(args, "group");
+
+  if (IsNull(group, "id") || IsNull(group, "addressBookId")) {
+    LoggerE("Group object is not added");
+    return PlatformResult(ErrorCode::INVALID_VALUES_ERR,
+                          "Group object is not added");
+  }
+
+  long addressbook_id =
+      common::stol(FromJson<JsonString>(args, "addressBookId"));
+  long group_addressbook_id =
+      common::stol(FromJson<JsonString>(group, "addressBookId"));
+  if (IsUnified(addressbook_id) && (addressbook_id != group_addressbook_id)) {
+    LoggerE("Wrong address book");
+    return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Wrong address book");
+  }
+
+  if (FromJson<bool>(group, "readOnly")) {
+    LoggerW("Group is readonly - cancel update");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Group is readonly - cancel update");
+  }
+
+  long group_id = common::stol(FromJson<JsonString>(group, "id"));
+  if (group_id < 0) {
+    return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Incorrect group id");
+  }
+
+  contacts_record_h contacts_record = nullptr;
+  int err =
+      contacts_db_get_record(_contacts_group._uri, group_id, &contacts_record);
+  if (CONTACTS_ERROR_NONE != err || nullptr == contacts_record) {
+    LoggerE("Group not exist");
+    return PlatformResult(ErrorCode::NOT_FOUND_ERR, "Group not exist");
+  }
+
+  status = ContactUtil::ErrorChecker(
+      err, "Error during executing contacts_db_get_record()");
+  if (status.IsError()) return status;
+
+  ContactUtil::ContactsRecordHPtr record(&contacts_record,
+                                         ContactUtil::ContactsDeleter);
+  status =
+      ContactUtil::ExportContactGroupToContactsRecord(contacts_record, group);
+  if (status.IsError()) return status;
+
+  err = contacts_db_update_record(contacts_record);
+  if (CONTACTS_ERROR_INVALID_PARAMETER == err) {
+    LoggerE("Problem during db_update_record");
+    return PlatformResult(ErrorCode::NOT_FOUND_ERR,
+                          "Problem during db_update_record");
+  }
+  status = ContactUtil::ErrorChecker(err, "Problem during db_update_record");
+  if (status.IsError()) return status;
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult AddressBookRemoveGroup(const JsonObject& args, JsonObject&) {
+  LoggerD("Enter");
+  PlatformResult status = ContactUtil::CheckDBConnection();
+  if (status.IsError()) return status;
+
+  long id = common::stol(FromJson<JsonString>(args, "id"));
+  if (id < 0) {
+    return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Incorrect group id");
+  }
+
+  int err;
+  long addressbook_id = AddressBookId(args);
+  if (!IsUnified(addressbook_id)) {
+    contacts_record_h contacts_record = nullptr;
+    err = contacts_db_get_record(_contacts_group._uri, id, &contacts_record);
+    if (CONTACTS_ERROR_NONE != err || contacts_record == nullptr) {
+      return PlatformResult(ErrorCode::NOT_FOUND_ERR, "Group not exist");
+    }
+
+    int group_addressbook_id = 0;
+    status = ContactUtil::GetIntFromRecord(contacts_record,
+                                           _contacts_group.address_book_id,
+                                           &group_addressbook_id);
+    if (status.IsError()) return status;
+
+    if (group_addressbook_id != addressbook_id) {
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "Contact is not a member of this address book");
+    }
+  }
+
+  err = contacts_db_delete_record(_contacts_group._uri, id);
+  if (CONTACTS_ERROR_INVALID_PARAMETER == err) {
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Problem during db_delete_record");
+  }
+  status = ContactUtil::ErrorChecker(err, "Problem during db_delete_record");
+  if (status.IsError()) return status;
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult AddressBookGetGroups(const JsonObject& args, JsonArray& out) {
+  LoggerD("Enter");
+  PlatformResult status = ContactUtil::CheckDBConnection();
+  if (status.IsError()) return status;
+
+  int err = CONTACTS_ERROR_NONE;
+  contacts_list_h groups_list = nullptr;
+  long addressbook_id = AddressBookId(args);
+
+  if (IsUnified(addressbook_id)) {
+    err = contacts_db_get_all_records(_contacts_group._uri, 0, 0, &groups_list);
+    status = ContactUtil::ErrorChecker(err, "Fail to get group list");
+    if (status.IsError()) return status;
+  } else {
+    contacts_query_h query = nullptr;
+    contacts_filter_h filter = nullptr;
+
+    err = contacts_query_create(_contacts_group._uri, &query);
+    status =
+        ContactUtil::ErrorChecker(err, "Fail to get contacts_query_create ");
+    if (status.IsError()) return status;
+
+    err = contacts_filter_create(_contacts_group._uri, &filter);
+    status =
+        ContactUtil::ErrorChecker(err, "Fail to get contacts_filter_create ");
+    if (status.IsError()) return status;
+
+    err = contacts_filter_add_int(filter, _contacts_group.address_book_id,
+                                  CONTACTS_MATCH_EQUAL, addressbook_id);
+    status =
+        ContactUtil::ErrorChecker(err, "Fail to get contacts_filter_add_int ");
+    if (status.IsError()) return status;
+
+    err = contacts_query_set_filter(query, filter);
+    status = ContactUtil::ErrorChecker(
+        err, "Fail to get contacts_query_set_filter ");
+    if (status.IsError()) return status;
+
+    err = contacts_db_get_records_with_query(query, 0, 0, &groups_list);
+    status = ContactUtil::ErrorChecker(
+        err, "Fail to get contacts_db_get_records_with_query ");
+    if (status.IsError()) return status;
+
+    // deleter to release the memory in case of an error
+    ContactUtil::ContactsListHPtr group_list_ptr(
+        &groups_list, ContactUtil::ContactsListDeleter);
+
+    err = contacts_filter_destroy(filter);
+    status =
+        ContactUtil::ErrorChecker(err, "Fail to get contacts_filter_destroy ");
+    if (status.IsError()) return status;
+
+    err = contacts_query_destroy(query);
+    status =
+        ContactUtil::ErrorChecker(err, "Fail to get contacts_query_destroy ");
+    if (status.IsError()) return status;
+
+    // release the ownership, pass it back to the outer scope
+    group_list_ptr.release();
+  }
+
+  // groups_list has been initialized, take the ownership
+  ContactUtil::ContactsListHPtr group_list_ptr(
+      &groups_list, ContactUtil::ContactsListDeleter);
+
+  int record_count = 0;
+  err = contacts_list_get_count(groups_list, &record_count);
+  status =
+      ContactUtil::ErrorChecker(err, "Fail to get contacts_list_get_count ");
+  if (status.IsError()) return status;
+
+  contacts_list_first(groups_list);
+
+  for (int i = 0; i < record_count; i++) {
+    contacts_record_h contacts_record;
+    err = contacts_list_get_current_record_p(groups_list, &contacts_record);
+    if (CONTACTS_ERROR_NONE != err || nullptr == contacts_record) {
+      LoggerE("Fail to get group record");
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, "Fail to get group record");
+    }
+
+    JsonValue group{JsonObject{}};
+    status = ContactUtil::ImportContactGroupFromContactsRecord(
+        contacts_record, &group.get<JsonObject>());
+    if (status.IsError()) return status;
+
+    out.push_back(group);
+
+    if (i < record_count - 1) {
+      err = contacts_list_next(groups_list);
+      if (CONTACTS_ERROR_NONE != err) {
+        LoggerE("Fail to get next address book, error %d", err);
+        break;
+      }
+    }
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+namespace {
+
+void AddressBookListenerCallback(const char* view_uri, void* user_data) {
+  LoggerD("entered");
+  (void)view_uri;
+
+  PlatformResult status = ContactUtil::CheckDBConnection();
+  if (status.IsError()) {
+    LoggerE("Fail to check db connection: %s", status.message().c_str());
+    return;
+  }
+
+  contacts_list_h contacts_list = nullptr;
+
+  int error_code;
+  int current_version = 0;
+  error_code = contacts_db_get_current_version(&current_version);
+  if (CONTACTS_ERROR_NONE != error_code) {
+    LoggerW("get current version returns error, code: %d", error_code);
+  }
+
+  ContactInstance* instance = static_cast<ContactInstance*>(user_data);
+  if (!instance) {
+    LoggerE("instance is NULL");
+    return;
+  }
+
+  for (int version = instance->current_state(); version < current_version; ++version) {
+    int latest_version = 0;
+    error_code = contacts_db_get_changes_by_version(
+        _contacts_contact_updated_info._uri, kUnifiedAddressBookId, version,
+        &contacts_list, &latest_version);
+    if (CONTACTS_ERROR_NONE != error_code) {
+      LoggerE("cannot get changes by version, code: %d", error_code);
+      continue;
+    }
+
+    ContactUtil::ContactsListHPtr contacts_list_ptr(
+        &contacts_list, ContactUtil::ContactsListDeleter);
+
+    int count = 0;
+    error_code = contacts_list_get_count(contacts_list, &count);
+    if (CONTACTS_ERROR_NONE != error_code) {
+      LoggerW("Cannot get updated contact count, code: %d", error_code);
+      continue;
+    }
+
+    if (!count) {
+      LoggerW("No updated contacts");
+      continue;
+    }
+
+    contacts_list_first(contacts_list);
+
+    JsonValue result{JsonObject{}};
+    JsonObject& result_obj = result.get<JsonObject>();
+    result_obj.insert(
+        std::make_pair(std::string("listenerId"),
+            picojson::value(std::string(kContactListenerId))));
+    JsonArray& added =
+        result_obj.insert(std::make_pair(std::string("added"),
+            picojson::value(JsonArray{}))).first->second.get<JsonArray>();
+    JsonArray& updated =
+        result_obj.insert(std::make_pair(std::string("updated"),
+            picojson::value(JsonArray{}))).first->second.get<JsonArray>();
+    JsonArray& removed =
+        result_obj.insert(std::make_pair(std::string("removed"),
+            picojson::value(JsonArray{}))).first->second.get<JsonArray>();
+
+    for (int i = 0; i < count; i++) {
+      contacts_record_h contact_updated_record = nullptr;
+
+      error_code = contacts_list_get_current_record_p(contacts_list,
+                                                      &contact_updated_record);
+      if (CONTACTS_ERROR_NONE != error_code) {
+        LoggerW("fail to get contact from list, code: %d", error_code);
+        break;
+      }
+
+      int changed_id = 0;
+      int changed_ab_id = 0;
+      int changed_type = 0;
+
+      PlatformResult status = ContactUtil::GetIntFromRecord(
+          contact_updated_record, _contacts_contact_updated_info.contact_id,
+          &changed_id);
+      if (status.IsError()) {
+        LoggerE("Fail to get int from record: %s", status.message().c_str());
+        break;
+      }
+
+      status = ContactUtil::GetIntFromRecord(
+          contact_updated_record,
+          _contacts_contact_updated_info.address_book_id, &changed_ab_id);
+      if (status.IsError()) {
+        LoggerE("Fail to get int from record: %s", status.message().c_str());
+        break;
+      }
+
+      status = ContactUtil::GetIntFromRecord(
+          contact_updated_record, _contacts_contact_updated_info.type,
+          &changed_type);
+      if (status.IsError()) {
+        LoggerE("Fail to get int from record: %s", status.message().c_str());
+        break;
+      }
+
+      if (CONTACTS_CHANGE_INSERTED == changed_type ||
+          CONTACTS_CHANGE_UPDATED == changed_type) {
+        contacts_record_h contacts_record = nullptr;
+
+        error_code = contacts_db_get_record(_contacts_contact._uri, changed_id,
+                                            &contacts_record);
+
+        if (CONTACTS_ERROR_NONE != error_code) {
+          LoggerW("fail to get contact from record");
+          break;
+        }
+
+        ContactUtil::ContactsRecordHPtr contact_record_ptr(
+            &contacts_record, ContactUtil::ContactsDeleter);
+
+        JsonValue contact{JsonObject{}};
+        status = ContactUtil::ImportContactFromContactsRecord(
+            contacts_record, &contact.get<JsonObject>());
+        if (status.IsError()) {
+          LoggerE("Fail to get contact from record: %s",
+                  status.message().c_str());
+          break;
+        }
+
+        if (CONTACTS_CHANGE_INSERTED == changed_type) {
+          added.push_back(std::move(contact));
+        } else {
+          updated.push_back(std::move(contact));
+        }
+      } else if (CONTACTS_CHANGE_DELETED == changed_type) {
+        // Need to send the addressbook id with the removed id
+        JsonValue removed_data{JsonObject{}};
+        JsonObject& removed_data_obj = removed_data.get<JsonObject>();
+
+        removed_data_obj.insert(
+            std::make_pair(std::string("id"),
+                picojson::value(std::to_string(changed_id))));
+        removed_data_obj.insert(
+            std::make_pair(std::string("addressBookId"),
+                picojson::value(std::to_string(changed_ab_id))));
+        removed.push_back(std::move(removed_data));
+      }
+    }
+
+    Instance::PostMessage(instance, result.serialize().c_str());
+  }
+
+  instance->set_current_state(current_version);
+}
+}
+
+PlatformResult AddressBookStartListening(ContactInstance& instance, const JsonObject&, JsonObject& out) {
+  LoggerD("Enter");
+  PlatformResult status = ContactUtil::CheckDBConnection();
+  if (status.IsError()) return status;
+  int current_state = 0;
+
+  // Set the initial latest version before registering the callback.
+  // The callback should only be registered once so no race can occur.
+  int error_code = contacts_db_get_current_version(&current_state);
+  if (CONTACTS_ERROR_NONE != error_code) {
+    LoggerW("get current version returns error, code: %d", error_code);
+  }
+
+  instance.set_current_state(current_state);
+
+  error_code = contacts_db_add_changed_cb(_contacts_contact._uri,
+                                          AddressBookListenerCallback, &instance);
+
+  if (CONTACTS_ERROR_NONE != error_code) {
+    LoggerE("Error while registering listener to contacts db, code: %d",
+            error_code);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Error while registering listener to contacts db");
+  }
+
+  instance.set_is_listening(true);
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult AddressBookStopListening(ContactInstance& instance) {
+  LoggerD("Enter");
+  PlatformResult status = ContactUtil::CheckDBConnection();
+  if (status.IsError()) return status;
+
+  int error_code = contacts_db_remove_changed_cb(
+      _contacts_contact._uri, AddressBookListenerCallback, &instance);
+
+  if (CONTACTS_ERROR_NONE != error_code) {
+    LoggerE("Error while removing listener");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Error while removing listener");
+  }
+
+  instance.set_is_listening(false);
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+}  // AddressBook
+}  // contact
+}  // extension
diff --git a/webWidgetTCT_device/src/contact/addressbook.h b/webWidgetTCT_device/src/contact/addressbook.h
new file mode 100755 (executable)
index 0000000..f1aaea4
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2015 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 CONTACT_ADDRESSBOOK_H_
+#define CONTACT_ADDRESSBOOK_H_
+
+#include "common/picojson.h"
+#include "contact/contact_util.h"
+#include "functional"
+#include "common/platform_result.h"
+
+namespace extension {
+namespace contact {
+
+class ContactInstance;
+
+namespace AddressBook {
+
+typedef std::function<common::PlatformResult(const JsonObject&, JsonObject&)>
+    NativeFunction;
+
+common::PlatformResult AddressBookGet(const JsonObject& args, JsonObject& out);
+common::PlatformResult AddressBookAdd(const JsonObject& args, JsonObject& out);
+common::PlatformResult AddressBookUpdate(const JsonObject& args,
+                                         JsonObject& out);
+common::PlatformResult AddressBookRemove(const JsonObject& args, JsonObject&);
+common::PlatformResult AddressBookFind(const JsonObject& args,
+                                       JsonArray& array);
+common::PlatformResult AddressBookAddGroup(const JsonObject& args,
+                                           JsonObject& out);
+common::PlatformResult AddressBookGetGroup(const JsonObject& args,
+                                           JsonObject& out);
+common::PlatformResult AddressBookUpdateGroup(const JsonObject& args,
+                                              JsonObject&);
+common::PlatformResult AddressBookRemoveGroup(const JsonObject& args,
+                                              JsonObject&);
+common::PlatformResult AddressBookGetGroups(const JsonObject& args,
+                                            JsonArray& out);
+common::PlatformResult AddressBookStartListening(ContactInstance& instance, const JsonObject& args,
+                                                 JsonObject& out);
+common::PlatformResult AddressBookStopListening(ContactInstance& instance);
+
+common::PlatformResult AddressBookBatchFunc(NativeFunction impl,
+                                            const char* single_arg_name,
+                                            const JsonObject& args,
+                                            JsonArray& out);
+
+// TODO all batch operations should be implemented using CAPI batch functions
+common::PlatformResult AddressBookAddBatch(const JsonObject& args,
+                                           JsonArray& out);
+
+}  // AddressBook
+}  // contact
+}  // extension
+
+#endif  // CONTACT_ADDRESSBOOK_H_
diff --git a/webWidgetTCT_device/src/contact/contact.gyp b/webWidgetTCT_device/src/contact/contact.gyp
new file mode 100755 (executable)
index 0000000..1d0f5f9
--- /dev/null
@@ -0,0 +1,41 @@
+{
+  'includes':[
+    '../common/common.gypi',
+  ],
+  'targets': [
+    {
+      'target_name': 'tizen_contact',
+      'type': 'loadable_module',
+      'dependencies': [
+        '../common/common.gyp:tizen_common',
+      ],
+      'sources': [
+        'contact_api.js',
+        'contact_extension.cc',
+        'contact_extension.h',
+        'contact_instance.cc',
+        'contact_instance.h',
+        'addressbook.cc',
+        'addressbook.h',
+        'contact_manager.cc',
+        'contact_manager.h',
+        'contact_util.cc',
+        'contact_util.h',
+        'person.cc',
+        'person.h',
+      ],
+      'includes': [
+        '../common/pkg-config.gypi',
+      ],
+      'conditions': [
+        ['tizen == 1', {
+          'variables': {
+            'packages': [
+              'contacts-service2',
+            ]
+          },
+        }],
+      ],
+    },
+  ],
+}
diff --git a/webWidgetTCT_device/src/contact/contact_api.js b/webWidgetTCT_device/src/contact/contact_api.js
new file mode 100755 (executable)
index 0000000..261b5d3
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+//= require('common.js');
+//= require('contact_data_structures.js');
+//= require('contact.js');
+//= require('address_book.js');
+//= require('person.js');
+//= require('contact_manager.js');
diff --git a/webWidgetTCT_device/src/contact/contact_extension.cc b/webWidgetTCT_device/src/contact/contact_extension.cc
new file mode 100755 (executable)
index 0000000..3746a00
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2015 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 "contact/contact_extension.h"
+#include "contact/contact_instance.h"
+
+extern const char kSource_contact_api[];
+
+common::Extension* CreateExtension() { return new ContactExtension; }
+
+ContactExtension::ContactExtension() {
+  SetExtensionName("tizen.contact");
+  SetJavaScriptAPI(kSource_contact_api);
+
+  const char* entry_points[] = {
+      "tizen.ContactRef",              "tizen.ContactName",
+      "tizen.ContactOrganization",     "tizen.ContactWebSite",
+      "tizen.ContactAnniversary",      "tizen.ContactAddress",
+      "tizen.ContactPhoneNumber",      "tizen.ContactEmailAddress",
+      "tizen.ContactGroup",            "tizen.ContactRelationship",
+      "tizen.ContactInstantMessenger", "tizen.Contact",
+      "tizen.AddressBook",             NULL};
+  SetExtraJSEntryPoints(entry_points);
+}
+
+ContactExtension::~ContactExtension() {}
+
+common::Instance* ContactExtension::CreateInstance() {
+  return new extension::contact::ContactInstance();
+}
diff --git a/webWidgetTCT_device/src/contact/contact_extension.h b/webWidgetTCT_device/src/contact/contact_extension.h
new file mode 100755 (executable)
index 0000000..b4a2355
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2015 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 CONTACT_CONTACT_EXTENSION_H
+#define CONTACT_CONTACT_EXTENSION_H
+
+#include "common/extension.h"
+
+class ContactExtension : public common::Extension {
+ public:
+  ContactExtension();
+  virtual ~ContactExtension();
+
+ private:
+  virtual common::Instance* CreateInstance();
+};
+
+#endif  // CONTACT_CONTACT_EXTENSION_H
diff --git a/webWidgetTCT_device/src/contact/contact_instance.cc b/webWidgetTCT_device/src/contact/contact_instance.cc
new file mode 100755 (executable)
index 0000000..78dd443
--- /dev/null
@@ -0,0 +1,578 @@
+/*
+ * Copyright (c) 2015 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 "contact/contact_instance.h"
+
+#include "common/converter.h"
+#include "common/task-queue.h"
+#include "common/logger.h"
+#include "common/platform_exception.h"
+
+#include "contact/addressbook.h"
+#include "contact/contact_manager.h"
+#include "contact/person.h"
+
+namespace extension {
+namespace contact {
+
+using namespace common;
+
+ContactInstance::ContactInstance()
+    : current_state_(0),
+      is_listening_(false) {
+  using std::placeholders::_1;
+  using std::placeholders::_2;
+
+#define REGISTER_SYNC(c, x) \
+  RegisterSyncHandler(c, std::bind(&ContactInstance::x, this, _1, _2));
+#define REGISTER_ASYNC(c, x) \
+  RegisterSyncHandler(c, std::bind(&ContactInstance::x, this, _1, _2));
+
+  // Contact Manager
+  REGISTER_ASYNC("ContactManager_getAddressBooks",
+                 ContactManagerGetAddressBooks);
+  REGISTER_SYNC("ContactManager_getAddressBook", ContactManagerGetAddressBook);
+  REGISTER_SYNC("ContactManager_addAddressBook", ContactManagerAddAddressBook);
+  REGISTER_SYNC("ContactManager_removeAddressBook",
+                ContactManagerRemoveAddressBook);
+  REGISTER_SYNC("ContactManager_get", ContactManagerGet);
+  REGISTER_SYNC("ContactManager_update", ContactManagerUpdate);
+  REGISTER_ASYNC("ContactManager_updateBatch", ContactManagerUpdateBatch);
+  REGISTER_SYNC("ContactManager_remove", ContactManagerRemove);
+  REGISTER_ASYNC("ContactManager_removeBatch", ContactManagerRemoveBatch);
+  REGISTER_ASYNC("ContactManager_find", ContactManagerFind);
+  REGISTER_SYNC("ContactManager_importFromVCard",
+                ContactManagerImportFromVCard);
+  REGISTER_SYNC("ContactManager_startListening", ContactManagerStartListening);
+  REGISTER_SYNC("ContactManager_stopListening", ContactManagerStopListening);
+
+  // AddressBook
+  REGISTER_ASYNC("AddressBook_addBatch", AddressBookAddBatch);
+  REGISTER_ASYNC("AddressBook_updateBatch", AddressBookUpdateBatch);
+  REGISTER_ASYNC("AddressBook_removeBatch", AddressBookRemoveBatch);
+  REGISTER_SYNC("AddressBook_get", AddressBookGet);
+  REGISTER_SYNC("AddressBook_add", AddressBookAdd);
+  REGISTER_SYNC("AddressBook_update", AddressBookUpdate);
+  REGISTER_SYNC("AddressBook_remove", AddressBookRemove);
+  REGISTER_ASYNC("AddressBook_find", AddressBookFind);
+  REGISTER_SYNC("AddressBook_addGroup", AddressBookAddGroup);
+  REGISTER_SYNC("AddressBook_getGroup", AddressBookGetGroup);
+  REGISTER_SYNC("AddressBook_updateGroup", AddressBookUpdateGroup);
+  REGISTER_SYNC("AddressBook_removeGroup", AddressBookRemoveGroup);
+  REGISTER_SYNC("AddressBook_getGroups", AddressBookGetGroups);
+  REGISTER_SYNC("AddressBook_startListening", AddressBookStartListening);
+  REGISTER_SYNC("AddressBook_stopListening", AddressBookStopListening);
+
+  // Person
+  REGISTER_SYNC("Person_link", PersonLink);
+  REGISTER_SYNC("Person_unlink", PersonUnlink);
+
+#undef REGISTER_SYNC
+#undef REGISTER_ASYNC
+}
+
+ContactInstance::~ContactInstance() {
+  if (is_listening_) {
+    AddressBook::AddressBookStopListening(*this);
+    set_is_listening(false);
+  }
+}
+
+void ContactInstance::AddressBookGet(const JsonValue& args, JsonObject& out) {
+  JsonValue val{JsonObject{}};
+  PlatformResult status = AddressBook::AddressBookGet(
+      common::JsonCast<JsonObject>(args), val.get<JsonObject>());
+  if (status.IsSuccess())
+    ReportSuccess(val, out);
+  else
+    ReportError(status, &out);
+}
+
+void ContactInstance::AddressBookAdd(const JsonValue& args, JsonObject& out) {
+  JsonValue val{JsonObject{}};
+  PlatformResult status = AddressBook::AddressBookAdd(
+      common::JsonCast<JsonObject>(args), val.get<JsonObject>());
+  if (status.IsSuccess())
+    ReportSuccess(val, out);
+  else
+    ReportError(status, &out);
+}
+
+void ContactInstance::AddressBookAddBatch(const JsonValue& args,
+                                          JsonObject& out) {
+  LoggerD("entered");
+
+  const double callback_id = args.get("callbackId").get<double>();
+
+  auto get = [=](const std::shared_ptr<JsonValue>& response) -> void {
+    JsonValue result = JsonValue(JsonArray());
+    PlatformResult status = AddressBook::AddressBookAddBatch(
+        common::JsonCast<JsonObject>(args), result.get<JsonArray>());
+    if (status.IsSuccess())
+      ReportSuccess(result, response->get<JsonObject>());
+    else
+      ReportError(status, &response->get<JsonObject>());
+  };
+
+  auto get_response =
+      [this, callback_id](const std::shared_ptr<JsonValue>& response) {
+    JsonObject& obj = response->get<JsonObject>();
+    obj["callbackId"] = picojson::value(static_cast<double>(callback_id));
+    Instance::PostMessage(this, response->serialize().c_str());
+  };
+
+  auto data = std::shared_ptr<JsonValue>(new JsonValue(JsonObject()));
+
+  TaskQueue::GetInstance().Queue<JsonValue>(
+      get, get_response, data);
+}
+
+void ContactInstance::AddressBookRemoveBatch(const JsonValue& args,
+                                             JsonObject& out) {
+  LoggerD("entered");
+
+  const double callback_id = args.get("callbackId").get<double>();
+
+  auto get = [=](const std::shared_ptr<JsonValue>& response) -> void {
+    JsonValue result = JsonValue(JsonArray());
+    // TODO all batch operations should be implemented using CAPI batch
+    // functions
+    PlatformResult status = AddressBook::AddressBookBatchFunc(
+        AddressBook::AddressBookRemove, "id",
+        common::JsonCast<JsonObject>(args), result.get<JsonArray>());
+
+    if (status.IsSuccess())
+      ReportSuccess(result, response->get<JsonObject>());
+    else
+      ReportError(status, &response->get<JsonObject>());
+  };
+
+  auto get_response =
+      [this, callback_id](const std::shared_ptr<JsonValue>& response) {
+    JsonObject& obj = response->get<JsonObject>();
+    obj["callbackId"] = picojson::value(static_cast<double>(callback_id));
+    Instance::PostMessage(this, response->serialize().c_str());
+  };
+
+  auto data = std::shared_ptr<JsonValue>(new JsonValue(JsonObject()));
+
+  TaskQueue::GetInstance().Queue<JsonValue>(
+      get, get_response, data);
+}
+
+void ContactInstance::AddressBookUpdateBatch(const JsonValue& args,
+                                             JsonObject& out) {
+  LoggerD("entered");
+
+  const double callback_id = args.get("callbackId").get<double>();
+
+  auto get = [=](const std::shared_ptr<JsonValue>& response) -> void {
+    JsonValue result = JsonValue(JsonArray());
+    // TODO all batch operations should be implemented using CAPI batch
+    // functions
+    PlatformResult status = AddressBook::AddressBookBatchFunc(
+        AddressBook::AddressBookUpdate, "contact",
+        common::JsonCast<JsonObject>(args), result.get<JsonArray>());
+
+    if (status.IsSuccess())
+      ReportSuccess(result, response->get<JsonObject>());
+    else
+      ReportError(status, &response->get<JsonObject>());
+  };
+
+  auto get_response =
+      [this, callback_id](const std::shared_ptr<JsonValue>& response) {
+    JsonObject& obj = response->get<JsonObject>();
+    obj["callbackId"] = picojson::value(static_cast<double>(callback_id));
+    Instance::PostMessage(this, response->serialize().c_str());
+  };
+
+  auto data = std::shared_ptr<JsonValue>(new JsonValue(JsonObject()));
+
+  TaskQueue::GetInstance().Queue<JsonValue>(
+      get, get_response, data);
+}
+
+void ContactInstance::AddressBookUpdate(const JsonValue& args,
+                                        JsonObject& out) {
+  JsonValue val{JsonObject{}};
+  PlatformResult status = AddressBook::AddressBookUpdate(
+      common::JsonCast<JsonObject>(args), val.get<JsonObject>());
+  if (status.IsSuccess())
+    ReportSuccess(val, out);
+  else
+    ReportError(status, &out);
+}
+
+void ContactInstance::AddressBookRemove(const JsonValue& args,
+                                        JsonObject& out) {
+  JsonValue val{JsonObject{}};
+  PlatformResult status = AddressBook::AddressBookRemove(
+      common::JsonCast<JsonObject>(args), val.get<JsonObject>());
+  if (status.IsSuccess())
+    ReportSuccess(out);
+  else
+    ReportError(status, &out);
+}
+
+void ContactInstance::AddressBookFind(const JsonValue& args, JsonObject& out) {
+  LoggerD("entered");
+
+  const double callback_id = args.get("callbackId").get<double>();
+
+  auto get = [=](const std::shared_ptr<JsonValue>& response) -> void {
+    JsonValue result = JsonValue(JsonArray());
+    PlatformResult status = AddressBook::AddressBookFind(
+        JsonCast<JsonObject>(args), result.get<JsonArray>());
+    if (status.IsSuccess())
+      ReportSuccess(result, response->get<JsonObject>());
+    else
+      ReportError(status, &response->get<JsonObject>());
+  };
+
+  auto get_response =
+      [this, callback_id](const std::shared_ptr<JsonValue>& response) {
+    JsonObject& obj = response->get<JsonObject>();
+    obj["callbackId"] = picojson::value(static_cast<double>(callback_id));
+    Instance::PostMessage(this, response->serialize().c_str());
+  };
+
+  auto data = std::shared_ptr<JsonValue>(new JsonValue(JsonObject()));
+
+  TaskQueue::GetInstance().Queue<JsonValue>(
+      get, get_response, data);
+}
+
+void ContactInstance::AddressBookAddGroup(const JsonValue& args,
+                                          JsonObject& out) {
+  JsonValue val{JsonObject{}};
+  PlatformResult status = AddressBook::AddressBookAddGroup(
+      common::JsonCast<JsonObject>(args), val.get<JsonObject>());
+  if (status.IsSuccess())
+    ReportSuccess(val, out);
+  else
+    ReportError(status, &out);
+}
+
+void ContactInstance::AddressBookGetGroup(const JsonValue& args,
+                                          JsonObject& out) {
+  JsonValue val{JsonObject{}};
+  PlatformResult status = AddressBook::AddressBookGetGroup(
+      common::JsonCast<JsonObject>(args), val.get<JsonObject>());
+  if (status.IsSuccess())
+    ReportSuccess(val, out);
+  else
+    ReportError(status, &out);
+}
+
+void ContactInstance::AddressBookUpdateGroup(const JsonValue& args,
+                                             JsonObject& out) {
+  JsonValue val{JsonObject{}};
+  PlatformResult status = AddressBook::AddressBookUpdateGroup(
+      common::JsonCast<JsonObject>(args), val.get<JsonObject>());
+  if (status.IsSuccess())
+    ReportSuccess(out);
+  else
+    ReportError(status, &out);
+}
+
+void ContactInstance::AddressBookRemoveGroup(const JsonValue& args,
+                                             JsonObject& out) {
+  JsonValue val{JsonObject{}};
+  PlatformResult status = AddressBook::AddressBookRemoveGroup(
+      common::JsonCast<JsonObject>(args), val.get<JsonObject>());
+  if (status.IsSuccess())
+    ReportSuccess(out);
+  else
+    ReportError(status, &out);
+}
+
+void ContactInstance::AddressBookGetGroups(const JsonValue& args,
+                                           JsonObject& out) {
+  JsonValue val{JsonArray{}};
+  PlatformResult status = AddressBook::AddressBookGetGroups(
+      common::JsonCast<JsonObject>(args), val.get<JsonArray>());
+  if (status.IsSuccess())
+    ReportSuccess(val, out);
+  else
+    ReportError(status, &out);
+}
+
+void ContactInstance::ContactManagerGetAddressBooks(const JsonValue& args,
+                                                    JsonObject& out) {
+  const double callback_id = args.get("callbackId").get<double>();
+
+  auto get = [=](const std::shared_ptr<JsonValue>& response) -> void {
+    JsonValue result = JsonValue(JsonArray());
+    PlatformResult status = ContactManager::ContactManagerGetAddressBooks(
+        common::JsonCast<JsonObject>(args), result.get<JsonArray>());
+
+    if (status.IsSuccess())
+      ReportSuccess(result, response->get<JsonObject>());
+    else
+      ReportError(status, &response->get<JsonObject>());
+  };
+
+  auto get_response =
+      [this, callback_id](const std::shared_ptr<JsonValue>& response) {
+    JsonObject& obj = response->get<JsonObject>();
+    obj["callbackId"] = picojson::value(static_cast<double>(callback_id));
+    Instance::PostMessage(this, response->serialize().c_str());
+  };
+
+  auto data = std::shared_ptr<JsonValue>(new JsonValue(JsonObject()));
+
+  TaskQueue::GetInstance().Queue<JsonValue>(
+      get, get_response, data);
+}
+
+void ContactInstance::ContactManagerGetAddressBook(const JsonValue& args,
+                                                   JsonObject& out) {
+  JsonValue val{JsonObject{}};
+  PlatformResult status = ContactManager::ContactManagerGetAddressBook(
+      common::JsonCast<JsonObject>(args), val.get<JsonObject>());
+  if (status.IsSuccess())
+    ReportSuccess(val, out);
+  else
+    ReportError(status, &out);
+}
+
+void ContactInstance::ContactManagerAddAddressBook(const JsonValue& args,
+                                                   JsonObject& out) {
+  JsonValue val{JsonObject{}};
+  PlatformResult status = ContactManager::ContactManagerAddAddressBook(
+      common::JsonCast<JsonObject>(args), val.get<JsonObject>());
+  if (status.IsSuccess())
+    ReportSuccess(val, out);
+  else
+    ReportError(status, &out);
+}
+
+void ContactInstance::ContactManagerRemoveAddressBook(const JsonValue& args,
+                                                      JsonObject& out) {
+  JsonValue val{JsonObject{}};
+  PlatformResult status = ContactManager::ContactManagerRemoveAddressBook(
+      common::JsonCast<JsonObject>(args), val.get<JsonObject>());
+  if (status.IsSuccess())
+    ReportSuccess(val, out);
+  else
+    ReportError(status, &out);
+}
+
+void ContactInstance::AddressBookStartListening(const JsonValue& args,
+                                                JsonObject& out) {
+  JsonValue val{JsonObject{}};
+  PlatformResult status = AddressBook::AddressBookStartListening(
+      *this, common::JsonCast<JsonObject>(args), val.get<JsonObject>());
+  if (status.IsSuccess())
+    ReportSuccess(val, out);
+  else
+    ReportError(status, &out);
+}
+
+void ContactInstance::AddressBookStopListening(const JsonValue& args,
+                                               JsonObject& out) {
+  JsonValue val{JsonObject{}};
+  PlatformResult status = AddressBook::AddressBookStopListening(*this);
+  if (status.IsSuccess())
+    ReportSuccess(val, out);
+  else
+    ReportError(status, &out);
+}
+
+void ContactInstance::ContactManagerGet(const JsonValue& args,
+                                        JsonObject& out) {
+  JsonValue val{JsonObject{}};
+  PlatformResult status = ContactManager::ContactManagerGet(
+      common::JsonCast<JsonObject>(args), val.get<JsonObject>());
+  if (status.IsSuccess())
+    ReportSuccess(val, out);
+  else
+    ReportError(status, &out);
+}
+
+void ContactInstance::ContactManagerUpdate(const JsonValue& args,
+                                           JsonObject& out) {
+  JsonValue val{JsonObject{}};
+  PlatformResult status = ContactManager::ContactManagerUpdate(
+      common::JsonCast<JsonObject>(args), val.get<JsonObject>());
+  if (status.IsSuccess())
+    ReportSuccess(out);
+  else
+    ReportError(status, &out);
+}
+
+void ContactInstance::ContactManagerUpdateBatch(const JsonValue& args,
+                                                JsonObject& out) {
+  LoggerD("entered");
+
+  const double callback_id = args.get("callbackId").get<double>();
+
+  auto get = [=](const std::shared_ptr<JsonValue>& response) -> void {
+    JsonValue result = JsonValue(JsonArray());
+    // TODO all batch operations should be implemented using CAPI batch
+    // functions
+    PlatformResult status = AddressBook::AddressBookBatchFunc(
+        ContactManager::ContactManagerUpdate, "person",
+        common::JsonCast<JsonObject>(args), result.get<JsonArray>());
+
+    if (status.IsSuccess())
+      ReportSuccess(result, response->get<JsonObject>());
+    else
+      ReportError(status, &response->get<JsonObject>());
+  };
+
+  auto get_response =
+      [this, callback_id](const std::shared_ptr<JsonValue>& response) {
+    JsonObject& obj = response->get<JsonObject>();
+    obj["callbackId"] = picojson::value(static_cast<double>(callback_id));
+    Instance::PostMessage(this, response->serialize().c_str());
+  };
+
+  auto data = std::shared_ptr<JsonValue>(new JsonValue(JsonObject()));
+
+  TaskQueue::GetInstance().Queue<JsonValue>(
+      get, get_response, data);
+}
+
+void ContactInstance::ContactManagerRemove(const JsonValue& args,
+                                           JsonObject& out) {
+  JsonValue val{JsonObject{}};
+  PlatformResult status = ContactManager::ContactManagerRemove(
+      common::JsonCast<JsonObject>(args), val.get<JsonObject>());
+  if (status.IsSuccess())
+    ReportSuccess(out);
+  else
+    ReportError(status, &out);
+}
+
+void ContactInstance::ContactManagerRemoveBatch(const JsonValue& args,
+                                                JsonObject& out) {
+  LoggerD("entered");
+
+  const double callback_id = args.get("callbackId").get<double>();
+
+  auto get = [=](const std::shared_ptr<JsonValue>& response) -> void {
+    JsonValue result = JsonValue(JsonArray());
+    // TODO all batch operations should be implemented using CAPI batch
+    // functions
+    PlatformResult status = AddressBook::AddressBookBatchFunc(
+        ContactManager::ContactManagerRemove, "personId",
+        common::JsonCast<JsonObject>(args), result.get<JsonArray>());
+
+    if (status.IsSuccess())
+      ReportSuccess(result, response->get<JsonObject>());
+    else
+      ReportError(status, &response->get<JsonObject>());
+  };
+
+  auto get_response =
+      [this, callback_id](const std::shared_ptr<JsonValue>& response) {
+    JsonObject& obj = response->get<JsonObject>();
+    obj["callbackId"] = picojson::value(static_cast<double>(callback_id));
+    Instance::PostMessage(this, response->serialize().c_str());
+  };
+
+  auto data = std::shared_ptr<JsonValue>(new JsonValue(JsonObject()));
+
+  TaskQueue::GetInstance().Queue<JsonValue>(
+      get, get_response, data);
+}
+
+void ContactInstance::ContactManagerFind(const JsonValue& args,
+                                         JsonObject& out) {
+  const double callback_id = args.get("callbackId").get<double>();
+
+  auto get = [this, args](const std::shared_ptr<JsonValue>& response) -> void {
+    JsonValue result = JsonValue(JsonArray());
+
+    PlatformResult status = ContactManager::ContactManagerFind(
+        common::JsonCast<JsonObject>(args), result.get<JsonArray>());
+    if (status.IsSuccess()) {
+      ReportSuccess(result, response->get<JsonObject>());
+    } else {
+      ReportError(status, &response->get<JsonObject>());
+    }
+  };
+
+  auto get_response =
+      [this, callback_id](const std::shared_ptr<JsonValue>& response) {
+    JsonObject& obj = response->get<JsonObject>();
+    obj["callbackId"] = picojson::value(static_cast<double>(callback_id));
+    Instance::PostMessage(this, response->serialize().c_str());
+  };
+
+  auto data = std::shared_ptr<JsonValue>(new JsonValue(JsonObject()));
+
+  TaskQueue::GetInstance().Queue<JsonValue>(
+      get, get_response, data);
+}
+
+void ContactInstance::ContactManagerImportFromVCard(const JsonValue& args,
+                                                    JsonObject& out) {
+  JsonValue val{JsonObject{}};
+  PlatformResult status = ContactManager::ContactManagerImportFromVCard(
+      common::JsonCast<JsonObject>(args), val.get<JsonObject>());
+  if (status.IsSuccess())
+    ReportSuccess(val, out);
+  else
+    ReportError(status, &out);
+}
+
+void ContactInstance::ContactManagerStartListening(const JsonValue& args,
+                                                   JsonObject& out) {
+  JsonValue val{JsonObject{}};
+  PlatformResult status = ContactManager::ContactManagerStartListening(
+      *this, common::JsonCast<JsonObject>(args), val.get<JsonObject>());
+  if (status.IsSuccess())
+    ReportSuccess(val, out);
+  else
+    ReportError(status, &out);
+}
+
+void ContactInstance::ContactManagerStopListening(const JsonValue& args,
+                                                  JsonObject& out) {
+  JsonValue val{JsonObject{}};
+  PlatformResult status = ContactManager::ContactManagerStopListening(
+      *this, common::JsonCast<JsonObject>(args), val.get<JsonObject>());
+  if (status.IsSuccess())
+    ReportSuccess(val, out);
+  else
+    ReportError(status, &out);
+}
+
+void ContactInstance::PersonLink(const JsonValue& args, JsonObject& out) {
+  JsonValue val{JsonObject{}};
+  PlatformResult status = Person::PersonLink(common::JsonCast<JsonObject>(args),
+                                             val.get<JsonObject>());
+  if (status.IsSuccess())
+    ReportSuccess(out);
+  else
+    ReportError(status, &out);
+}
+
+void ContactInstance::PersonUnlink(const JsonValue& args, JsonObject& out) {
+  JsonValue val{JsonObject{}};
+  PlatformResult status = Person::PersonUnlink(
+      common::JsonCast<JsonObject>(args), val.get<JsonObject>());
+  if (status.IsSuccess())
+    ReportSuccess(val, out);
+  else
+    ReportError(status, &out);
+}
+
+}  // namespace contact
+}  // namespace extension
diff --git a/webWidgetTCT_device/src/contact/contact_instance.h b/webWidgetTCT_device/src/contact/contact_instance.h
new file mode 100755 (executable)
index 0000000..4e58d6c
--- /dev/null
@@ -0,0 +1,237 @@
+/*
+ * Copyright (c) 2015 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 CONTACT_CONTACT_INSTANCE_H
+#define CONTACT_CONTACT_INSTANCE_H
+
+#include "common/extension.h"
+#include "common/picojson.h"
+
+#include "contact/contact_util.h"
+
+namespace extension {
+namespace contact {
+
+class ContactInstance : public common::ParsedInstance {
+ public:
+  ContactInstance();
+  virtual ~ContactInstance();
+
+  int current_state() const { return current_state_; }
+  void set_current_state(int state) { current_state_ = state; }
+  void set_is_listening(bool listening) { is_listening_ = listening; }
+
+ private:
+  void AddressBookGet(const JsonValue& args, JsonObject& out);
+  void AddressBookAdd(const JsonValue& args, JsonObject& out);
+  void AddressBookAddBatch(const JsonValue& args, JsonObject& out);
+  void AddressBookUpdate(const JsonValue& args, JsonObject& out);
+  void AddressBookUpdateBatch(const JsonValue& args, JsonObject& out);
+  void AddressBookRemove(const JsonValue& args, JsonObject& out);
+  void AddressBookRemoveBatch(const JsonValue& args, JsonObject& out);
+  void AddressBookFind(const JsonValue& args, JsonObject& out);
+
+  void AddressBookGetGroup(const JsonValue& args, JsonObject& out);
+  void AddressBookGetGroups(const JsonValue& args, JsonObject& out);
+  void AddressBookAddGroup(const JsonValue& args, JsonObject& out);
+  void AddressBookUpdateGroup(const JsonValue& args, JsonObject& out);
+  void AddressBookRemoveGroup(const JsonValue& args, JsonObject& out);
+
+  void AddressBookStartListening(const JsonValue& args, JsonObject& out);
+  void AddressBookStopListening(const JsonValue& args, JsonObject& out);
+
+  /**
+   * Signature: @code void getAddressBooks(successCallback, errorCallback);
+   * @endcode
+   * JSON: @code data: {method: 'ContactManager_getAddressBook', args: {}}
+   * @endcode
+   * Invocation: @code native.call(request, result_callback) @endcode
+   * Return:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success'}
+   * @endcode
+   * Result callback:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success', result: {addressbooks}}
+   * @endcode
+   */
+  void ContactManagerGetAddressBooks(const JsonValue& args, JsonObject& out);
+
+  /**
+   * Signature: @code AddressBook getAddressBook(addressBookId); @endcode
+   * JSON: @code data: {method: 'ContactManager_getAddressBook',
+   *                    args: {addressBookID: addressBookId}} @endcode
+   * Invocation: @code native.callSync(request) @endcode
+   * Return:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success'}
+   * @endcode
+   */
+  void ContactManagerGetAddressBook(const JsonValue& args, JsonObject& out);
+
+  void ContactManagerAddAddressBook(const JsonValue& args, JsonObject& out);
+  void ContactManagerRemoveAddressBook(const JsonValue& args, JsonObject& out);
+
+  /**
+   * Signature: @code Person get(personId); @endcode
+   * JSON: @code data: {method: 'ContactManager_get',
+   *                    args: {personID: personId}} @endcode
+   * Invocation: @code native.callSync(request); @endcode
+   * Return:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success'}
+   * @endcode
+   */
+  void ContactManagerGet(const JsonValue& args, JsonObject& out);
+
+  /**
+   * Signature: @code void update(person); @endcode
+   * JSON: @code data: {method: 'ContactManager_update',
+   *                    args: {person: person}} @endcode
+   * Invocation: @code native.callSync(request); @endcode
+   * Return:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success'}
+   * @endcode
+   */
+  void ContactManagerUpdate(const JsonValue& args, JsonObject& out);
+
+  /**
+   * Signature: @code void updateBatch(persons, successCallback, errorCallback);
+   * @endcode
+   * JSON: @code data: {method: 'ContactManager_updateBatch',
+   *                    args: {persons: persons}} @endcode
+   * Invocation: @code native.call(request, result_callback); @endcode
+   * Return:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success'}
+   * @endcode
+   * Result callback:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success', result: {persons}}
+   * @endcode
+   */
+  void ContactManagerUpdateBatch(const JsonValue& args, JsonObject& out);
+
+  /**
+   * Signature: @code void remove(personId); @endcode
+   * JSON: @code data: {method: 'ContactManager_remove',
+   *                    args: {personID: personId}} @endcode
+   * Invocation: @code native.callSync(request); @endcode
+   * Return:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success'}
+   * @endcode
+   */
+  void ContactManagerRemove(const JsonValue& args, JsonObject& out);
+
+  /**
+   * Signature: @code void removeBatch(personIds, successCallback,
+   * errorCallback);
+   * @endcode
+   * JSON: @code data: {method: 'ContactManager_removeBatch',
+   *                    args: {personsIDs: personIds}} @endcode
+   * Invocation: @code native.call(request, result_callback); @endcode
+   * Return:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success'}
+   * @endcode
+   * Result callback:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success'}
+   * @endcode
+   */
+  void ContactManagerRemoveBatch(const JsonValue& args, JsonObject& out);
+
+  /**
+   * Signature: @code void find(successCallback, errorCallback, filter,
+   * sortMode);
+   * @endcode
+   * JSON: @code data: {method: 'ContactManager_find',
+   *                    args: {filter: filter, sortMode: sortMode}} @endcode
+   * Invocation: @code native.call(request, result_callback); @endcode
+   * Return:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success'}
+   * @endcode
+   * Result callback:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success', result: {persons}}
+   * @endcode
+   */
+  void ContactManagerFind(const JsonValue& args, JsonObject& out);
+
+  /**
+   * Signature: @code void getAddressBook(contactString); @endcode
+   * JSON: @code data: {method: 'ContactManager_importFromVCard',
+   *                    args: {contact: contactString}} @endcode
+   * Invocation: @code native.callSync(request); @endcode
+   * Return:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success', result: {contact}}
+   * @endcode
+   */
+  void ContactManagerImportFromVCard(const JsonValue& args, JsonObject& out);
+
+  /**
+   * Signature: @code void getAddressBook(contactString); @endcode
+   * JSON: @code data: {method: 'ContactManager_startListening',
+   *                    args: {}} @endcode
+   * Invocation: @code native.callSync(request); @endcode
+   * Return:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success'}
+   * @endcode
+   */
+  void ContactManagerStartListening(const JsonValue& args, JsonObject& out);
+
+  /**
+   * Signature: @code void getAddressBook(contactString); @endcode
+   * JSON: @code data: {method: 'ContactManager_stopListening',
+   *                    args: {}} @endcode
+   * Invocation: @code native.callSync(request); @endcode
+   * Return:
+   * @code
+   * {status: 'error', error: {name, message}}
+   * {status: 'success'}
+   * @endcode
+   */
+  void ContactManagerStopListening(const JsonValue& args, JsonObject& out);
+
+  void PersonLink(const JsonValue& args, JsonObject& out);
+  void PersonUnlink(const JsonValue& args, JsonObject& out);
+
+  int current_state_;
+  bool is_listening_;
+};
+}  // namespace contact
+}  // namespace extension
+
+#endif  // CONTACT_CONTACT_INSTANCE_H
diff --git a/webWidgetTCT_device/src/contact/contact_manager.cc b/webWidgetTCT_device/src/contact/contact_manager.cc
new file mode 100755 (executable)
index 0000000..569395c
--- /dev/null
@@ -0,0 +1,964 @@
+/*
+ * Copyright (c) 2015 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 "contact/contact_manager.h"
+#include <memory>
+#include <set>
+
+#include "common/converter.h"
+#include "common/filter-utils.h"
+#include "common/logger.h"
+#include "common/picojson.h"
+#include "common/scope_exit.h"
+
+#include <contacts.h>
+#include <contacts_db_extension.h>
+#include "contact/contact_instance.h"
+#include "contact/person.h"
+
+namespace extension {
+namespace contact {
+namespace ContactManager {
+
+namespace {
+const char* kContactPersonListenerId = "ContactPersonChangeListener";
+const char* kTokenDelimiter = " ,:";
+}
+
+using namespace common;
+
+PlatformResult ContactManagerGetAddressBooks(const JsonObject& args,
+                                             JsonArray& out) {
+  LoggerD("Enter");
+  PlatformResult status = ContactUtil::CheckDBConnection();
+  if (status.IsError()) return status;
+
+  contacts_list_h address_book_list = nullptr;
+
+  int error_code = contacts_db_get_all_records(_contacts_address_book._uri, 0,
+                                               0, &address_book_list);
+  if (CONTACTS_ERROR_NONE != error_code) {
+    LoggerE("Fail to get address book list, error: %d", error_code);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Fail to get address book list");
+  }
+
+  ContactUtil::ContactsListHPtr contacts_list_ptr(
+      &address_book_list, ContactUtil::ContactsListDeleter);
+
+  int record_count = 0;
+  error_code = contacts_list_get_count(*contacts_list_ptr, &record_count);
+  if (CONTACTS_ERROR_NONE != error_code) {
+    LoggerE("Fail to get address book list count, error: %d", error_code);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Fail to get address book list count");
+  }
+
+  error_code = contacts_list_first(*contacts_list_ptr);
+  if (CONTACTS_ERROR_NONE != error_code) {
+    LoggerE("Fail to get address book from list, error: %d", error_code);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Fail to get address book from list");
+  }
+
+  for (int i = 0; i < record_count; i++) {
+    contacts_record_h contacts_record = nullptr;
+    error_code = contacts_list_get_current_record_p(*contacts_list_ptr,
+                                                    &contacts_record);
+
+    if (CONTACTS_ERROR_NONE != error_code) {
+      LoggerW("Fail to get address book record");
+      continue;
+    }
+
+    int id = 0;
+    int account_id = 0;
+    int mode = 0;
+    char* name = nullptr;
+    status = ContactUtil::GetIntFromRecord(contacts_record,
+                                           _contacts_address_book.id, &id);
+    if (status.IsError()) return status;
+
+    status = ContactUtil::GetIntFromRecord(
+        contacts_record, _contacts_address_book.account_id, &account_id);
+    if (status.IsError()) return status;
+
+    status = ContactUtil::GetIntFromRecord(contacts_record,
+                                           _contacts_address_book.mode, &mode);
+    if (status.IsError()) return status;
+
+    status = ContactUtil::GetStrFromRecord(contacts_record,
+                                           _contacts_address_book.name, &name);
+    if (status.IsError()) return status;
+
+    JsonValue single = JsonValue(JsonObject());
+    JsonObject& single_obj = single.get<JsonObject>();
+
+    single_obj["id"] = JsonValue(std::to_string(id));
+    single_obj["accountId"] = JsonValue(static_cast<double>(account_id));
+    single_obj["name"] = JsonValue(name);
+    single_obj["readOnly"] =
+        JsonValue(CONTACTS_ADDRESS_BOOK_MODE_READONLY == mode);
+    out.push_back(single);
+
+    contacts_list_next(*contacts_list_ptr);
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult ContactManagerGetAddressBook(const JsonObject& args,
+                                            JsonObject& out) {
+  LoggerD("Enter");
+  PlatformResult status = ContactUtil::CheckDBConnection();
+  if (status.IsError()) return status;
+
+  long address_book_id =
+      common::stol(FromJson<JsonString>(args, "addressBookId"));
+
+  contacts_record_h contacts_record;
+  int error_code = contacts_db_get_record(_contacts_address_book._uri,
+                                          static_cast<int>(address_book_id),
+                                          &contacts_record);
+  if (CONTACTS_ERROR_NONE != error_code || nullptr == contacts_record) {
+    LoggerE("Fail to get addressbook record, error code: %d", error_code);
+    return PlatformResult(ErrorCode::NOT_FOUND_ERR,
+                          "Fail to get address book with given id");
+  }
+
+  ContactUtil::ContactsRecordHPtr contacts_record_ptr(
+      &contacts_record, ContactUtil::ContactsDeleter);
+
+  int account_id;
+  status = ContactUtil::GetIntFromRecord(
+      contacts_record, _contacts_address_book.account_id, &account_id);
+  if (status.IsError()) return status;
+
+  int mode;
+  status = ContactUtil::GetIntFromRecord(contacts_record,
+                                         _contacts_address_book.mode, &mode);
+  if (status.IsError()) return status;
+
+  char* name;
+  status = ContactUtil::GetStrFromRecord(contacts_record,
+                                         _contacts_address_book.name, &name);
+  if (status.IsError()) return status;
+
+  out["accountId"] = picojson::value(static_cast<double>(account_id));
+  out["name"] = picojson::value(name);
+  out["readOnly"] =
+      picojson::value(CONTACTS_ADDRESS_BOOK_MODE_READONLY == mode);
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+namespace {
+PlatformResult ContactManagerGetInternal(int person_id, JsonObject* out) {
+  LoggerD("Enter");
+  contacts_record_h contacts_record = nullptr;
+
+  int error_code = contacts_db_get_record(_contacts_person._uri, person_id,
+                                          &contacts_record);
+  if (CONTACTS_ERROR_NONE != error_code) {
+    LoggerE("Person with id: %d, not found, error: %d", person_id, error_code);
+    return PlatformResult(ErrorCode::NOT_FOUND_ERR, "Person not found");
+  }
+
+  ContactUtil::ContactsRecordHPtr contacts_record_ptr(
+      &contacts_record, ContactUtil::ContactsDeleter);
+
+  PlatformResult status =
+      ContactUtil::ImportPersonFromContactsRecord(contacts_record, out);
+  if (status.IsError()) return status;
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+}
+
+PlatformResult ContactManagerAddAddressBook(const JsonObject& args,
+                                            JsonObject& out) {
+  LoggerD("Enter");
+  PlatformResult status = ContactUtil::CheckDBConnection();
+  if (status.IsError()) return status;
+
+  const JsonObject& addressBook = FromJson<JsonObject>(args, "addressBook");
+
+  if (!IsNull(addressBook, "id")) {
+    LoggerW("AddressBook already exists");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "AddressBook already exists");
+  }
+
+  contacts_record_h contacts_record;
+  int ret =
+      contacts_record_create(_contacts_address_book._uri, &contacts_record);
+  if (CONTACTS_ERROR_NONE != ret) {
+    LoggerE("Failed to create address book record, error code : %d", ret);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Failed to create address book record");
+  }
+  ContactUtil::ContactsRecordHPtr contacts_record_ptr(
+      &contacts_record, ContactUtil::ContactsDeleter);
+
+  status = ContactUtil::SetStrInRecord(
+      contacts_record, _contacts_address_book.name,
+      FromJson<JsonString>(addressBook, "name").c_str());
+  if (status.IsError()) return status;
+
+  contacts_address_book_mode_e mode = FromJson<bool>(addressBook, "readOnly")
+                                          ? CONTACTS_ADDRESS_BOOK_MODE_READONLY
+                                          : CONTACTS_ADDRESS_BOOK_MODE_NONE;
+  status = ContactUtil::SetIntInRecord(
+      contacts_record, _contacts_address_book.mode, static_cast<int>(mode));
+  if (status.IsError()) return status;
+
+  double account_id = FromJson<double>(addressBook, "accountId");
+  status = ContactUtil::SetIntInRecord(contacts_record,
+                                       _contacts_address_book.account_id,
+                                       static_cast<int>(account_id));
+  if (status.IsError()) return status;
+
+  int address_book_id;
+  ret = contacts_db_insert_record(*contacts_record_ptr, &address_book_id);
+  if (CONTACTS_ERROR_NONE != ret) {
+    LoggerE("Failed to insert address book record, error code: %d", ret);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Failed to insert address book record");
+  }
+
+  out["id"] = picojson::value(std::to_string(address_book_id));
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult ContactManagerRemoveAddressBook(const JsonObject& args,
+                                               JsonObject& out) {
+  LoggerD("Enter");
+  PlatformResult status = ContactUtil::CheckDBConnection();
+  if (status.IsError()) return status;
+
+  long address_book_id =
+      common::stol(FromJson<JsonString>(args, "addressBookId"));
+
+  contacts_record_h contacts_record;
+  int error_code = contacts_db_get_record(_contacts_address_book._uri,
+                                          static_cast<int>(address_book_id),
+                                          &contacts_record);
+  if (CONTACTS_ERROR_NONE != error_code || nullptr == contacts_record) {
+    LoggerE("Fail to get addressbook record, error code: %d", error_code);
+    return PlatformResult(ErrorCode::NOT_FOUND_ERR,
+                          "Fail to get address book with given id");
+  }
+
+  int ret = contacts_db_delete_record(_contacts_address_book._uri,
+                                      static_cast<int>(address_book_id));
+  if (CONTACTS_ERROR_NONE != ret) {
+    LOGE("Failed to delete address book record, error code : %d", ret);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Failed to delete address book record");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult ContactManagerGet(const JsonObject& args, JsonObject& out) {
+  LoggerD("Enter");
+  PlatformResult status = ContactUtil::CheckDBConnection();
+  if (status.IsError()) return status;
+
+  long person_id = common::stol(FromJson<JsonString>(args, "personId"));
+
+  return ContactManagerGetInternal(person_id, &out);
+}
+
+PlatformResult ContactManagerUpdate(const JsonObject& args, JsonObject&) {
+  LoggerD("Enter");
+  PlatformResult status = ContactUtil::CheckDBConnection();
+  if (status.IsError()) return status;
+
+  const JsonObject& person = FromJson<JsonObject>(args, "person");
+  long person_id = common::stol(FromJson<JsonString>(person, "id"));
+  contacts_record_h contacts_record = nullptr;
+  int error_code = contacts_db_get_record(_contacts_person._uri, person_id,
+                                          &contacts_record);
+
+  if (CONTACTS_ERROR_NONE != error_code) {
+    return PlatformResult(ErrorCode::NOT_FOUND_ERR, "Person not found");
+  }
+
+  status = ContactUtil::ExportPersonToContactsRecord(contacts_record, person);
+  if (status.IsError()) return status;
+
+  ContactUtil::ContactsRecordHPtr contacts_record_ptr(
+      &contacts_record, ContactUtil::ContactsDeleter);
+
+  error_code = contacts_db_update_record(*contacts_record_ptr);
+  if (CONTACTS_ERROR_NONE != error_code) {
+    LoggerE("error code: %d", error_code);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Error during executing contacts_db_update_record()");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult ContactManagerRemove(const JsonObject& args, JsonObject&) {
+  LoggerD("Enter");
+  PlatformResult status = ContactUtil::CheckDBConnection();
+  if (status.IsError()) return status;
+
+  long person_id = common::stol(FromJson<JsonString>(args, "personId"));
+
+  if (person_id < 0) {
+    return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Negative person id");
+  }
+
+  int error_code = contacts_db_delete_record(_contacts_person._uri, person_id);
+  if (CONTACTS_ERROR_NONE != error_code) {
+    LoggerE("Error during removing contact, error: %d", error_code);
+    return PlatformResult(ErrorCode::NOT_FOUND_ERR,
+                          "Error during removing contact");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult ContactManagerFind(const JsonObject& args, JsonArray& out) {
+  LoggerD("Enter");
+  PlatformResult status = ContactUtil::CheckDBConnection();
+  if (status.IsError()) return status;
+
+  contacts_query_h contacts_query = nullptr;
+  int error_code =
+      contacts_query_create(_contacts_person._uri, &contacts_query);
+  status =
+      ContactUtil::ErrorChecker(error_code, "Failed contacts_query_create");
+  if (status.IsError()) return status;
+
+  ContactUtil::ContactsQueryHPtr contacts_query_ptr(
+      &contacts_query, ContactUtil::ContactsQueryDeleter);
+
+  // Add filter to query
+  std::vector<std::vector<ContactUtil::ContactsFilterPtr>> intermediate_filters(
+      1);
+
+  if (!IsNull(args, "filter")) {
+    FilterVisitor visitor;
+    visitor.SetOnAttributeFilter([&](const std::string& name,
+                                     AttributeMatchFlag match_flag,
+                                     const JsonValue& match_value) {
+      Person::PersonProperty property;
+      status = Person::PersonPropertyFromString(name, &property);
+      if (status.IsError()) return status;
+
+      contacts_filter_h contacts_filter = nullptr;
+      int error_code =
+          contacts_filter_create(_contacts_person._uri, &contacts_filter);
+      status = ContactUtil::ErrorChecker(error_code,
+                                         "Failed contacts_query_set_filter");
+      if (status.IsError()) return status;
+
+      ContactUtil::ContactsFilterPtr contacts_filter_ptr(
+          contacts_filter, ContactUtil::ContactsFilterDeleter);
+
+      if (property.type == kPrimitiveTypeBoolean) {
+        bool value = true;
+        if (AttributeMatchFlag::kExists != match_flag) {
+          value = JsonCast<bool>(match_value);
+        }
+        error_code = contacts_filter_add_bool(contacts_filter,
+                                              property.propertyId, value);
+        status = ContactUtil::ErrorChecker(error_code,
+                                           "Failed contacts_filter_add_bool");
+        if (status.IsError()) return status;
+      } else if (property.type == kPrimitiveTypeString) {
+        std::string value = JsonCast<std::string>(match_value);
+
+        contacts_match_str_flag_e flag = CONTACTS_MATCH_EXISTS;
+        if (AttributeMatchFlag::kExactly == match_flag) {
+          flag = CONTACTS_MATCH_EXACTLY;
+        } else if (AttributeMatchFlag::kFullString == match_flag) {
+          flag = CONTACTS_MATCH_FULLSTRING;
+        } else if (AttributeMatchFlag::kContains == match_flag) {
+          flag = CONTACTS_MATCH_CONTAINS;
+        } else if (AttributeMatchFlag::kStartsWith == match_flag) {
+          flag = CONTACTS_MATCH_STARTSWITH;
+        } else if (AttributeMatchFlag::kEndsWith == match_flag) {
+          flag = CONTACTS_MATCH_ENDSWITH;
+        } else if (AttributeMatchFlag::kExists == match_flag) {
+          flag = CONTACTS_MATCH_EXISTS;
+          value = "";
+        }
+        error_code = contacts_filter_add_str(
+            contacts_filter, property.propertyId, flag, value.c_str());
+        status = ContactUtil::ErrorChecker(error_code,
+                                           "Failed contacts_filter_add_str");
+        if (status.IsError()) return status;
+      } else if (property.type == kPrimitiveTypeLong ||
+                 property.type == kPrimitiveTypeId) {
+        int value;
+        if (property.type == kPrimitiveTypeLong) {
+          value = static_cast<int>(JsonCast<double>(match_value));
+        } else {
+          value = common::stol(JsonCast<std::string>(match_value));
+        }
+        if (value < 0) {
+          return PlatformResult(ErrorCode::INVALID_VALUES_ERR,
+                                "Match value cannot be less than 0");
+        }
+        contacts_match_int_flag_e flag;
+        if (AttributeMatchFlag::kExists == match_flag) {
+          flag = CONTACTS_MATCH_GREATER_THAN_OR_EQUAL;
+          value = 0;
+        } else if (AttributeMatchFlag::kStartsWith == match_flag ||
+                   AttributeMatchFlag::kContains == match_flag) {
+          flag = CONTACTS_MATCH_GREATER_THAN_OR_EQUAL;
+        } else if (AttributeMatchFlag::kEndsWith == match_flag) {
+          flag = CONTACTS_MATCH_LESS_THAN_OR_EQUAL;
+        } else {
+          flag = CONTACTS_MATCH_EQUAL;
+        }
+
+        error_code = contacts_filter_add_int(contacts_filter,
+                                             property.propertyId, flag, value);
+        status = ContactUtil::ErrorChecker(error_code,
+                                           "Failed contacts_filter_add_str");
+        if (status.IsError()) return status;
+      } else {
+        LoggerE("Invalid primitive type!");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                              "Invalid primitive type!");
+      }
+      intermediate_filters[intermediate_filters.size() - 1].push_back(
+          std::move(contacts_filter_ptr));
+
+      return PlatformResult(ErrorCode::NO_ERROR);
+    });
+
+    visitor.SetOnAttributeRangeFilter([&](const std::string& name,
+                                          const JsonValue& initial_value,
+                                          const JsonValue& end_value) {
+      Person::PersonProperty property;
+      status = Person::PersonPropertyFromString(name, &property);
+      if (status.IsError()) return status;
+
+      contacts_filter_h contacts_filter = nullptr;
+      int error_code =
+          contacts_filter_create(_contacts_person._uri, &contacts_filter);
+      status = ContactUtil::ErrorChecker(error_code,
+                                         "Failed contacts_query_set_filter");
+      if (status.IsError()) return status;
+
+      ContactUtil::ContactsFilterPtr contacts_filter_ptr(
+          contacts_filter, ContactUtil::ContactsFilterDeleter);
+
+      bool initial_value_exists = (!IsNull(initial_value));
+      bool end_value_exists = (!IsNull(end_value));
+
+      if (property.type == kPrimitiveTypeBoolean) {
+        bool initial_value_bool = false;
+        bool end_value_bool = false;
+
+        if (initial_value_exists) {
+          initial_value_bool = JsonCast<bool>(initial_value);
+        }
+        if (end_value_exists) {
+          end_value_bool = JsonCast<bool>(end_value);
+        }
+
+        if (initial_value_exists && end_value_exists) {
+          if (initial_value_bool == end_value_bool) {
+            error_code = contacts_filter_add_bool(
+                contacts_filter, property.propertyId, initial_value_bool);
+            status = ContactUtil::ErrorChecker(
+                error_code, "Failed contacts_filter_add_bool");
+            if (status.IsError()) return status;
+          }
+        } else if (initial_value_exists) {
+          if (initial_value_bool) {
+            error_code = contacts_filter_add_bool(contacts_filter,
+                                                  property.propertyId, true);
+            status = ContactUtil::ErrorChecker(
+                error_code, "Failed contacts_filter_add_bool");
+            if (status.IsError()) return status;
+          }
+        } else if (end_value_exists) {
+          if (!end_value_bool) {
+            error_code = contacts_filter_add_bool(contacts_filter,
+                                                  property.propertyId, false);
+            status = ContactUtil::ErrorChecker(
+                error_code, "Failed contacts_filter_add_bool");
+            if (status.IsError()) return status;
+          }
+        }
+      } else if (property.type == kPrimitiveTypeString) {
+        std::string initial_value_str;
+        std::string end_value_str;
+
+        if (initial_value_exists) {
+          initial_value_str = JsonCast<std::string>(initial_value);
+        }
+
+        if (end_value_exists) {
+          end_value_str = JsonCast<std::string>(end_value);
+        }
+
+        if (initial_value_exists && end_value_exists) {
+          contacts_filter_h sub_filter = NULL;
+
+          error_code =
+              contacts_filter_create(_contacts_person._uri, &sub_filter);
+          status = ContactUtil::ErrorChecker(error_code,
+                                             "Failed contacts_filter_add_str");
+          if (status.IsError()) return status;
+
+          ContactUtil::ContactsFilterPtr sub_filter_ptr(
+              sub_filter, ContactUtil::ContactsFilterDeleter);
+
+          error_code = contacts_filter_add_str(sub_filter, property.propertyId,
+                                               CONTACTS_MATCH_STARTSWITH,
+                                               initial_value_str.c_str());
+          status = ContactUtil::ErrorChecker(error_code,
+                                             "Failed contacts_filter_add_str");
+          if (status.IsError()) return status;
+
+          error_code = contacts_filter_add_operator(
+              sub_filter, CONTACTS_FILTER_OPERATOR_AND);
+          status = ContactUtil::ErrorChecker(error_code,
+                                             "Failed contacts_filter_add_str");
+          if (status.IsError()) return status;
+
+          error_code = contacts_filter_add_str(sub_filter, property.propertyId,
+                                               CONTACTS_MATCH_ENDSWITH,
+                                               end_value_str.c_str());
+          status = ContactUtil::ErrorChecker(error_code,
+                                             "Failed contacts_filter_add_str");
+          if (status.IsError()) return status;
+
+          error_code = contacts_filter_add_filter(contacts_filter, sub_filter);
+          status = ContactUtil::ErrorChecker(error_code,
+                                             "Failed contacts_filter_add_str");
+          if (status.IsError()) return status;
+        } else if (initial_value_exists) {
+          error_code = contacts_filter_add_str(
+              contacts_filter, property.propertyId, CONTACTS_MATCH_STARTSWITH,
+              initial_value_str.c_str());
+          status = ContactUtil::ErrorChecker(error_code,
+                                             "Failed contacts_filter_add_str");
+          if (status.IsError()) return status;
+        } else if (end_value_exists) {
+          error_code = contacts_filter_add_str(
+              contacts_filter, property.propertyId, CONTACTS_MATCH_ENDSWITH,
+              end_value_str.c_str());
+          status = ContactUtil::ErrorChecker(error_code,
+                                             "Failed contacts_filter_add_str");
+          if (status.IsError()) return status;
+        }
+      } else if (property.type == kPrimitiveTypeLong ||
+                 property.type == kPrimitiveTypeId) {
+        int initial_value_int = 0;
+        int end_value_int = 0;
+
+        if (initial_value_exists) {
+          if (property.type == kPrimitiveTypeLong) {
+            initial_value_int =
+                static_cast<int>(JsonCast<double>(initial_value));
+          } else {
+            initial_value_int =
+                common::stol(JsonCast<std::string>(initial_value));
+          }
+        }
+
+        if (end_value_exists) {
+          if (property.type == kPrimitiveTypeLong) {
+            end_value_int = static_cast<int>(JsonCast<double>(end_value));
+          } else {
+            end_value_int = common::stol(JsonCast<std::string>(end_value));
+          }
+        }
+
+        if (initial_value_exists && end_value_exists) {
+          contacts_filter_h sub_filter = NULL;
+
+          error_code =
+              contacts_filter_create(_contacts_person._uri, &sub_filter);
+          status = ContactUtil::ErrorChecker(error_code,
+                                             "Failed contacts_filter_add_bool");
+          if (status.IsError()) return status;
+
+          ContactUtil::ContactsFilterPtr sub_filter_ptr(
+              sub_filter, ContactUtil::ContactsFilterDeleter);
+
+          error_code = contacts_filter_add_int(
+              sub_filter, property.propertyId,
+              CONTACTS_MATCH_GREATER_THAN_OR_EQUAL, initial_value_int);
+          status = ContactUtil::ErrorChecker(error_code,
+                                             "Failed contacts_filter_add_int");
+          if (status.IsError()) return status;
+
+          error_code = contacts_filter_add_operator(
+              sub_filter, CONTACTS_FILTER_OPERATOR_AND);
+          status = ContactUtil::ErrorChecker(
+              error_code, "Failed contacts_filter_add_operator");
+          if (status.IsError()) return status;
+
+          error_code = contacts_filter_add_int(
+              sub_filter, property.propertyId,
+              CONTACTS_MATCH_LESS_THAN_OR_EQUAL, end_value_int);
+          status = ContactUtil::ErrorChecker(error_code,
+                                             "Failed contacts_filter_add_int");
+          if (status.IsError()) return status;
+
+          error_code = contacts_filter_add_filter(contacts_filter, sub_filter);
+          status = ContactUtil::ErrorChecker(
+              error_code, "Failed contacts_filter_add_filter");
+          if (status.IsError()) return status;
+        } else if (initial_value_exists) {
+          error_code = contacts_filter_add_int(
+              contacts_filter, property.propertyId,
+              CONTACTS_MATCH_GREATER_THAN_OR_EQUAL, initial_value_int);
+          status = ContactUtil::ErrorChecker(error_code,
+                                             "Failed contacts_filter_add_int");
+          if (status.IsError()) return status;
+        } else if (end_value_exists) {
+          error_code = contacts_filter_add_int(
+              contacts_filter, property.propertyId,
+              CONTACTS_MATCH_LESS_THAN_OR_EQUAL, end_value_int);
+          status = ContactUtil::ErrorChecker(error_code,
+                                             "Failed contacts_filter_add_int");
+          if (status.IsError()) return status;
+        }
+      } else {
+        return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                              "Invalid primitive type!");
+      }
+      intermediate_filters[intermediate_filters.size() - 1].push_back(
+          std::move(contacts_filter_ptr));
+
+      return PlatformResult(ErrorCode::NO_ERROR);
+    });
+
+    visitor.SetOnCompositeFilterBegin([&](CompositeFilterType type) {
+      intermediate_filters.push_back(
+          std::vector<ContactUtil::ContactsFilterPtr>());
+
+      return PlatformResult(ErrorCode::NO_ERROR);
+    });
+
+    visitor.SetOnCompositeFilterEnd([&](CompositeFilterType type) {
+      if (intermediate_filters.size() == 0) {
+        return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                              "Reached stack size equal to 0!");
+      }
+
+      contacts_filter_h merged_filter = nullptr;
+      int error_code =
+          contacts_filter_create(_contacts_person._uri, &merged_filter);
+      status = ContactUtil::ErrorChecker(error_code,
+                                         "Failed contacts_query_set_filter");
+      if (status.IsError()) return status;
+
+      ContactUtil::ContactsFilterPtr merged_filter_ptr(
+          merged_filter, ContactUtil::ContactsFilterDeleter);
+
+      for (std::size_t i = 0; i < intermediate_filters.back().size(); ++i) {
+        error_code = contacts_filter_add_filter(
+            merged_filter, intermediate_filters.back().at(i).get());
+        status = ContactUtil::ErrorChecker(error_code,
+                                           "Failed contacts_query_set_filter");
+        if (status.IsError()) return status;
+
+        if (CompositeFilterType::kIntersection == type) {
+          error_code = contacts_filter_add_operator(
+              merged_filter, CONTACTS_FILTER_OPERATOR_AND);
+          status = ContactUtil::ErrorChecker(
+              error_code, "Failed contacts_query_set_filter");
+          if (status.IsError()) return status;
+        } else if (CompositeFilterType::kUnion == type) {
+          error_code = contacts_filter_add_operator(
+              merged_filter, CONTACTS_FILTER_OPERATOR_OR);
+          status = ContactUtil::ErrorChecker(
+              error_code, "Failed contacts_query_set_filter");
+          if (status.IsError()) return status;
+        } else {
+          return PlatformResult(ErrorCode::INVALID_VALUES_ERR,
+                                "Invalid union type!");
+        }
+      }
+
+      intermediate_filters.pop_back();
+      intermediate_filters.back().push_back(std::move(merged_filter_ptr));
+
+      return PlatformResult(ErrorCode::NO_ERROR);
+    });
+
+    status = visitor.Visit(FromJson<JsonObject>(args, "filter"));
+    if (status.IsError()) return status;
+
+    // Should compute only one filter always.
+    if ((intermediate_filters.size() != 1) ||
+        (intermediate_filters[0].size() != 1)) {
+      LoggerE("Bad filter evaluation!");
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, "Bad filter evaluation!");
+    }
+    // Filter is generated
+    error_code = contacts_query_set_filter(contacts_query,
+                                           intermediate_filters[0][0].get());
+    status = ContactUtil::ErrorChecker(error_code,
+                                       "Failed contacts_query_set_filter");
+    if (status.IsError()) return status;
+  }
+
+  contacts_list_h person_list = nullptr;
+  error_code =
+      contacts_db_get_records_with_query(contacts_query, 0, 0, &person_list);
+
+  status = ContactUtil::ErrorChecker(
+      error_code, "Failed contacts_db_get_records_with_query");
+  if (status.IsError()) return status;
+
+  ContactUtil::ContactsListHPtr person_list_ptr(
+      &person_list, ContactUtil::ContactsListDeleter);
+
+  int record_count = 0;
+  error_code = contacts_list_get_count(person_list, &record_count);
+  status =
+      ContactUtil::ErrorChecker(error_code, "Failed contacts_list_get_count");
+  if (status.IsError()) return status;
+
+  contacts_list_first(person_list);
+
+  for (int i = 0; i < record_count; i++) {
+    contacts_record_h contacts_record;
+    error_code =
+        contacts_list_get_current_record_p(person_list, &contacts_record);
+    if (error_code != CONTACTS_ERROR_NONE || contacts_record == NULL) {
+      LoggerW("Failed group record (ret:%d)", error_code);
+      continue;
+    }
+
+    int id_value = 0;
+    error_code = contacts_record_get_int(contacts_record, _contacts_person.id,
+                                         &id_value);
+
+    status =
+        ContactUtil::ErrorChecker(error_code, "Failed contacts_record_get_int");
+    if (status.IsError()) return status;
+
+    out.push_back(JsonValue(static_cast<double>(id_value)));
+
+    contacts_list_next(person_list);
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult ContactManagerImportFromVCard(const JsonObject& args,
+                                             JsonObject& out) {
+  LoggerD("Enter");
+  // I'm not sure how to call it. Should it be 'Contact', 'vCard' or what?
+  PlatformResult status = ContactUtil::CheckDBConnection();
+  if (status.IsError()) return status;
+
+  const char* vcard_char_ptr = FromJson<JsonString>(args, "contact").c_str();
+
+  contacts_list_h contacts_list = nullptr;
+
+  int err = contacts_vcard_parse_to_contacts(vcard_char_ptr, &contacts_list);
+  if (CONTACTS_ERROR_INVALID_PARAMETER == err) {
+    LoggerE("Invalid vCard string");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Invalid vCard string");
+  } else if (CONTACTS_ERROR_NONE != err) {
+    LoggerE("Fail to convert vCard from string");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Fail to convert vCard from string");
+  }
+
+  SCOPE_EXIT {
+    contacts_list_destroy(contacts_list, true);
+  };
+
+  int record_count = 0;
+  err = contacts_list_get_count(contacts_list, &record_count);
+  if (CONTACTS_ERROR_NONE != err || 0 == record_count) {
+    LoggerE("Invalid vCard string.");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Invalid vCard string.");
+  }
+
+  contacts_record_h contacts_record;
+  contacts_list_first(contacts_list);
+  err = contacts_list_get_current_record_p(contacts_list, &contacts_record);
+  if (CONTACTS_ERROR_NONE != err || nullptr == contacts_record) {
+    LoggerE("Invalid vCard string.");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Invalid vCard string.");
+  }
+
+  status = ContactUtil::ImportContactFromContactsRecord(contacts_record, &out);
+  if (status.IsError()) return status;
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+namespace {
+bool IsNumeric(const char* s) {
+  for (; *s; s++) {
+    if (!isdigit(*s)) {
+      return false;
+    }
+  }
+  return true;
+}
+
+void ContactManagerListenerCallback(const char* view_uri, char* changes,
+                                    void* user_data) {
+  LoggerD("ContactManagerListenerCallback");
+
+  (void)view_uri;
+
+  if (nullptr == changes) {
+    LoggerW("changes is NULL");
+    return;
+  }
+  if (strlen(changes) == 0) {
+    LoggerW("changes is empty");
+    return;
+  }
+
+  SLoggerD("view_uri: %s", view_uri);
+  SLoggerD("changes: %s", changes);
+
+  JsonValue result{JsonObject{}};
+  JsonObject& result_obj = result.get<JsonObject>();
+  result_obj.insert(std::make_pair(std::string("listenerId"),
+      picojson::value(kContactPersonListenerId)));
+  JsonArray& added = result_obj.insert(std::make_pair(std::string("added"),
+      picojson::value(JsonArray{}))).first->second.get<JsonArray>();
+  JsonArray& updated = result_obj.insert(std::make_pair(std::string("updated"),
+      picojson::value(JsonArray{}))).first->second.get<JsonArray>();
+  JsonArray& removed = result_obj.insert(std::make_pair(std::string("removed"),
+      picojson::value(JsonArray{}))).first->second.get<JsonArray>();
+
+  std::unique_ptr<char, void (*)(char*)> tmp(strdup(changes),
+                                             [](char* p) { free(p); });
+
+  // 'changes' may contain repeated values, we need to filter it
+  std::set<int> added_ids;
+  std::set<int> updated_ids;
+  std::set<int> removed_ids;
+
+  char* tmpptr = nullptr;
+
+  char* token = strtok_r(tmp.get(), kTokenDelimiter, &tmpptr);
+  while (token) {
+    if (IsNumeric(token)) {
+      int type = atoi(token);
+      token = strtok_r(nullptr, kTokenDelimiter, &tmpptr);
+      if (!token) {
+        break;
+      }
+      if (IsNumeric(token)) {
+        int person_id = atoi(token);
+        switch (type) {
+          case CONTACTS_CHANGE_INSERTED: {
+            if (added_ids.find(person_id) == added_ids.end()) {
+              added.push_back(JsonValue{JsonObject{}});
+              PlatformResult status = ContactManagerGetInternal(
+                  person_id, &added.back().get<JsonObject>());
+              if (status.IsError()) {
+                LoggerE("Caught exception in listener callback: %s",
+                        status.message().c_str());
+                return;
+              }
+              added_ids.insert(person_id);
+            }
+
+            break;
+          }
+          case CONTACTS_CHANGE_UPDATED: {
+            if (updated_ids.find(person_id) == updated_ids.end()) {
+              updated.push_back(JsonValue{JsonObject{}});
+              PlatformResult status = ContactManagerGetInternal(
+                  person_id, &updated.back().get<JsonObject>());
+              if (status.IsError()) {
+                LoggerE("Caught exception in listener callback: %s",
+                        status.message().c_str());
+                return;
+              }
+              updated_ids.insert(person_id);
+            }
+
+            break;
+          }
+          case CONTACTS_CHANGE_DELETED: {
+            if (removed_ids.find(person_id) == removed_ids.end()) {
+              removed.push_back(JsonValue{std::to_string(person_id)});
+              removed_ids.insert(person_id);
+            }
+            break;
+          }
+          default: {
+            break;
+          }
+        }
+      }
+    }
+
+    token = strtok_r(nullptr, kTokenDelimiter, &tmpptr);
+  }
+
+  ContactInstance* instance = static_cast<ContactInstance*>(user_data);
+  Instance::PostMessage(instance, result.serialize().c_str());
+}
+}
+
+PlatformResult ContactManagerStartListening(ContactInstance& instance, const JsonObject& /*args*/,
+                                            JsonObject& /*out*/) {
+  LoggerD("Enter");
+  PlatformResult status = ContactUtil::CheckDBConnection();
+  if (status.IsError()) return status;
+
+  int error_code = contacts_db_add_changed_cb_with_info(
+      _contacts_person._uri, ContactManagerListenerCallback, &instance);
+
+  if (CONTACTS_ERROR_NONE != error_code) {
+    LoggerE("contacts_db_add_changed_cb(_contacts_person._uri) error: %d",
+            error_code);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to start listening");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult ContactManagerStopListening(ContactInstance& instance, const JsonObject& /*args*/,
+                                           JsonObject& /*out*/) {
+  LoggerD("Enter");
+  PlatformResult status = ContactUtil::CheckDBConnection();
+  if (status.IsError()) return status;
+
+  int error_code = contacts_db_remove_changed_cb_with_info(
+      _contacts_person._uri, ContactManagerListenerCallback, &instance);
+
+  if (CONTACTS_ERROR_NONE != error_code) {
+    LoggerE("contacts_db_remove_changed_cb(_contacts_person._uri) error: %d",
+            error_code);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to stop listening");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+}  // namespace ContactManager
+}  // namespace contact
+}  // namespace extension
diff --git a/webWidgetTCT_device/src/contact/contact_manager.h b/webWidgetTCT_device/src/contact/contact_manager.h
new file mode 100755 (executable)
index 0000000..9c72b62
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2015 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 CONTACT_CONTACT_MANAGER_H__
+#define CONTACT_CONTACT_MANAGER_H__
+
+#include "common/picojson.h"
+#include "contact/contact_util.h"
+
+namespace extension {
+namespace contact {
+
+class ContactInstance;
+
+namespace ContactManager {
+
+common::PlatformResult ContactManagerGetAddressBooks(const JsonObject& args,
+                                                     JsonArray& out);
+
+common::PlatformResult ContactManagerGetAddressBook(const JsonObject& args,
+                                                    JsonObject& out);
+
+common::PlatformResult ContactManagerAddAddressBook(const JsonObject& args,
+                                                    JsonObject& out);
+
+common::PlatformResult ContactManagerRemoveAddressBook(const JsonObject& args,
+                                                       JsonObject& out);
+
+common::PlatformResult ContactManagerGet(const JsonObject& args,
+                                         JsonObject& out);
+
+common::PlatformResult ContactManagerUpdate(const JsonObject& args,
+                                            JsonObject&);
+
+common::PlatformResult ContactManagerRemove(const JsonObject& args,
+                                            JsonObject&);
+
+common::PlatformResult ContactManagerFind(const JsonObject& args,
+                                          JsonArray& out);
+
+common::PlatformResult ContactManagerImportFromVCard(const JsonObject& args,
+                                                     JsonObject& out);
+
+/**
+ * Signature: @code void getAddressBook(contactString); @endcode
+ * JSON: @code data: {method: 'ContactManager_startListening',
+ *                    args: {}} @endcode
+ * Invocation: @code native.callSync(request); @endcode
+ * Return:
+ * @code
+ * {status: 'error', error: {name, message}}
+ * {status: 'success'}
+ * @endcode
+ */
+common::PlatformResult ContactManagerStartListening(ContactInstance& instance, const JsonObject& args,
+                                                    JsonObject& out);
+
+/**
+ * Signature: @code void getAddressBook(contactString); @endcode
+ * JSON: @code data: {method: 'ContactManager_stopListening',
+ *                    args: {}} @endcode
+ * Invocation: @code native.callSync(request); @endcode
+ * Return:
+ * @code
+ * {status: 'error', error: {name, message}}
+ * {status: 'success'}
+ * @endcode
+ */
+common::PlatformResult ContactManagerStopListening(ContactInstance& instance, const JsonObject& args,
+                                                   JsonObject& out);
+
+}  // namespace ContactManager
+}  // namespace contact
+}  // namespace extension
+
+#endif  // CONTACT_CONTACT_MANAGER_H__
diff --git a/webWidgetTCT_device/src/contact/contact_util.cc b/webWidgetTCT_device/src/contact/contact_util.cc
new file mode 100755 (executable)
index 0000000..3bbcd81
--- /dev/null
@@ -0,0 +1,2981 @@
+/*
+ * Copyright (c) 2015 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 "contact/contact_util.h"
+#include <algorithm>
+#include <iomanip>
+#include <string>
+#include <unistd.h>
+#include "common/converter.h"
+#include "common/assert.h"
+#include "common/logger.h"
+
+namespace extension {
+namespace contact {
+namespace ContactUtil {
+
+using common::ErrorCode;
+using common::FromJson;
+using common::IsNull;
+using common::JsonCast;
+using common::PlatformResult;
+
+namespace {
+
+static const std::string kSchema("file://");
+
+std::string ConvertUriToPath(const std::string& str) {
+  if (str.substr(0, kSchema.size()) == kSchema) {
+    return str.substr(kSchema.size());
+  }
+
+  return str;
+}
+
+std::string ConvertPathToUri(const std::string& str) {
+  if (str.substr(0, kSchema.size()) == kSchema) {
+    return str;
+  }
+
+  return kSchema + str;
+}
+
+PlatformResult VerifyLocalPath(const std::string& path) {
+  // path should be either empty or point to existing local path
+  bool result = path.length() == 0
+      || (path.length() > 0 && path[0] == '/'
+          && (access(path.c_str(), F_OK) == 0));
+  return PlatformResult(
+      result ? ErrorCode::NO_ERROR : ErrorCode::INVALID_VALUES_ERR);
+}
+
+}  // namespace
+
+void ContactsDeleter(contacts_record_h* contacts_record) {
+  if (CONTACTS_ERROR_NONE != contacts_record_destroy(*contacts_record, true)) {
+    LoggerE("failed to destroy contacts_record_h");
+  }
+}
+
+void ContactsListDeleter(contacts_list_h* contacts_list) {
+  if (CONTACTS_ERROR_NONE != contacts_list_destroy(*contacts_list, true)) {
+    LoggerE("failed to destroy contacts_list_h");
+  }
+}
+
+void ContactsFilterDeleter(contacts_filter_h contacts_filter) {
+  if (CONTACTS_ERROR_NONE != contacts_filter_destroy(contacts_filter)) {
+    LoggerE("failed to destroy contacts_filter_h");
+  }
+}
+
+void ContactsQueryDeleter(contacts_query_h* contacts_query) {
+  if (CONTACTS_ERROR_NONE != contacts_query_destroy(*contacts_query)) {
+    LoggerE("failed to destroy contacts_query_h");
+  }
+}
+
+namespace {
+static const char kContactPhoneTypeHome[] = "HOME";
+static const char kContactPhoneTypeWork[] = "WORK";
+static const char kContactPhoneTypeVoice[] = "VOICE";
+static const char kContactPhoneTypeFax[] = "FAX";
+static const char kContactPhoneTypeMsg[] = "MSG";
+static const char kContactPhoneTypeCell[] = "CELL";
+static const char kContactPhoneTypePager[] = "PAGER";
+static const char kContactPhoneTypeBbs[] = "BBS";
+static const char kContactPhoneTypeModem[] = "MODEM";
+static const char kContactPhoneTypeCar[] = "CAR";
+static const char kContactPhoneTypeIsdn[] = "ISDN";
+static const char kContactPhoneTypeVideo[] = "VIDEO";
+static const char kContactPhoneTypePcs[] = "PCS";
+static const char kContactPhoneTypeAssistant[] = "ASSISTANT";
+static const char kContactPhoneTypeOther[] = "OTHER";
+static const char kContactPhoneTypeCustom[] = "Custom";
+
+static const char kContactEmailAddressTypeHome[] = "HOME";
+static const char kContactEmailAddressTypeWork[] = "WORK";
+static const char kContactEmailAddressTypeOther[] = "OTHER";
+static const char kContactEmailAddressTypeCustom[] = "CUSTOM";
+
+static const char kContactAddressTypeHome[] = "HOME";
+static const char kContactAddressTypeWork[] = "WORK";
+static const char kContactAddressTypeOther[] = "OTHER";
+static const char kContactAddressTypeCustom[] = "CUSTOM";
+
+static const char kContactWebSiteTypeHomePage[] = "HOMEPAGE";
+static const char kContactWebSiteTypeBlog[] = "BLOG";
+
+static const char kContactRelationshipTypeCustom[] = "CUSTOM";
+static const char kContactRelationshipTypeAssistant[] = "ASSISTANT";
+static const char kContactRelationshipTypeBrother[] = "BROTHER";
+static const char kContactRelationshipTypeChild[] = "CHILD";
+static const char kContactRelationshipTypeDomesticPartner[] =
+    "DOMESTIC_PARTNER";
+static const char kContactRelationshipTypeFather[] = "FATHER";
+static const char kContactRelationshipTypeFriend[] = "FRIEND";
+static const char kContactRelationshipTypeManager[] = "MANAGER";
+static const char kContactRelationshipTypeMother[] = "MOTHER";
+static const char kContactRelationshipTypeParent[] = "PARENT";
+static const char kContactRelationshipTypePartner[] = "PARTNER";
+static const char kContactRelationshipTypeReferredBy[] = "REFERRED_BY";
+static const char kContactRelationshipTypeRelative[] = "RELATIVE";
+static const char kContactRelationshipTypeSister[] = "SISTER";
+static const char kContactRelationshipTypeSpouse[] = "SPOUSE";
+static const char kContactRelationshipTypeOther[] = "OTHER";
+
+static const char kContactInstantMessageTypeOther[] = "OTHER";
+static const char kContactInstantMessageTypeGoogle[] = "GOOGLE";
+static const char kContactInstantMessageTypeWlm[] = "WLM";
+static const char kContactInstantMessageTypeYahoo[] = "YAHOO";
+static const char kContactInstantMessageTypeFacebook[] = "FACEBOOK";
+static const char kContactInstantMessageTypeIcq[] = "ICQ";
+static const char kContactInstantMessageTypeAim[] = "AIM";
+static const char kContactInstantMessageTypeQq[] = "QQ";
+static const char kContactInstantMessageTypeJabber[] = "JABBER";
+static const char kContactInstantMessageTypeSkype[] = "SKYPE";
+static const char kContactInstantMessageTypeIrc[] = "IRC";
+static const char kContactInstantMessageTypeCustom[] = "CUSTOM";
+}
+
+PlatformResult ErrorChecker(int err, const char* message) {
+  LoggerD("Enter");
+  if (CONTACTS_ERROR_NONE != err) {
+    LoggerE("%s, error code: %i", message, err);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, message);
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult GetStrFromRecord(contacts_record_h record,
+                                unsigned int property_id, char** value) {
+  LoggerD("Enter");
+  int err = contacts_record_get_str_p(record, property_id, value);
+  if (CONTACTS_ERROR_NONE != err) {
+    LoggerE("Error during getting contact record, error code: %i", err);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Error during getting contact record");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult GetIntFromRecord(contacts_record_h record,
+                                unsigned int property_id, int* value) {
+  LoggerD("Enter");
+  int err = contacts_record_get_int(record, property_id, value);
+  if (CONTACTS_ERROR_NONE != err) {
+    LoggerE("Error during getting contact record, error code: %i", err);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Error during getting contact record");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult GetBoolFromRecord(contacts_record_h record,
+                                 unsigned int property_id, bool* value) {
+  LoggerD("Enter");
+  int err = contacts_record_get_bool(record, property_id, value);
+  if (CONTACTS_ERROR_NONE != err) {
+    LoggerE("Error during getting contact record, error code: %i", err);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Error during getting contact record");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SetStrInRecord(contacts_record_h record,
+                              unsigned int property_id, const char* value) {
+  LoggerD("Enter");
+  int err = contacts_record_set_str(record, property_id, value);
+  if (CONTACTS_ERROR_NONE != err) {
+    LoggerE("Error during setting str contact record property, error code: %i",
+            err);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Error during setting contact record");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SetIntInRecord(contacts_record_h record,
+                              unsigned int property_id, int value) {
+  LoggerD("Enter");
+  int err = contacts_record_set_int(record, property_id, value);
+  if (CONTACTS_ERROR_NONE != err) {
+    LoggerE("Error during getting contact record, error code: %i", err);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Error during setting contact record");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SetBoolInRecord(contacts_record_h record,
+                               unsigned int property_id, bool value) {
+  LoggerD("Enter");
+  int err = contacts_record_set_bool(record, property_id, value);
+  if (CONTACTS_ERROR_NONE != err) {
+    LoggerE("Error during getting contact record, error code: %i", err);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Error during setting contact record");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult ClearAllContactRecord(contacts_record_h contacts_record,
+                                     unsigned int property_id) {
+  LoggerD("Enter");
+  // contacts_record is protected by unique_ptr and its ownership is not passed
+  // here
+  if (!contacts_record) {
+    LoggerE("Contacts record is null");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Contacts record is null");
+  }
+
+  int record_count;
+  PlatformResult status =
+      GetNumberOfChildRecord(contacts_record, property_id, &record_count);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  for (int i = 0; i < record_count; ++i) {
+    unsigned int actual_index = record_count - 1 - i;
+    contacts_record_h phone_record = nullptr;
+    int err = contacts_record_get_child_record_at_p(
+        contacts_record, property_id, actual_index, &phone_record);
+    PlatformResult status =
+        ContactUtil::ErrorChecker(err, "Error during getting phone record");
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+
+    err = contacts_record_remove_child_record(contacts_record, property_id,
+                                              phone_record);
+    status =
+        ContactUtil::ErrorChecker(err, "Error during getting phone record");
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult GetNumberOfChildRecord(contacts_record_h contacts_record,
+                                      unsigned int property_id,
+                                      int* child_count) {
+  LoggerD("Enter");
+  Assert(child_count);
+
+  int err = contacts_record_get_child_record_count(contacts_record, property_id,
+                                                   child_count);
+  if (CONTACTS_ERROR_NONE != err && CONTACTS_ERROR_NO_DATA != err) {
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Problem during getting child count");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult ImportContactNameFromContactsRecord(
+    contacts_record_h contacts_record, JsonObject* out_ptr,
+    bool* is_contact_name) {
+  LoggerD("Enter");
+  JsonObject& out = *out_ptr;
+  if (!contacts_record) {
+    LoggerW("Contacts record is null");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Contacts record is null");
+  }
+  int count = 0;
+  int err = contacts_record_get_child_record_count(contacts_record,
+                                                   _contacts_contact.name, &count);
+  PlatformResult status =
+      ContactUtil::ErrorChecker(err, "Contacts child record get count error");
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  if (count > 1) {
+    LoggerE("More than one ContactName for one Contact");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "More than one ContactName for one Contact");
+  }
+  LoggerD("Contact name record count: %i", count);
+
+  if (count == 0) {
+    *is_contact_name = false;
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+
+  contacts_record_h contact_name = nullptr;
+  err = contacts_record_get_child_record_at_p(
+      contacts_record, _contacts_contact.name, 0, &contact_name);
+  status =
+      ContactUtil::ErrorChecker(err, "Contacts name record get childerror");
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  // 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 = nullptr;
+  status = ContactUtil::GetStrFromRecord(contact_name, _contacts_name.prefix,
+                                         &char_value);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  out.insert(std::make_pair("prefix",
+                            char_value ? JsonValue{char_value} : JsonValue{}));
+
+  status = ContactUtil::GetStrFromRecord(contact_name, _contacts_name.suffix,
+                                         &char_value);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  out.insert(std::make_pair("suffix",
+                            char_value ? JsonValue{char_value} : JsonValue{}));
+
+  status = ContactUtil::GetStrFromRecord(contact_name, _contacts_name.first,
+                                         &char_value);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  out.insert(std::make_pair("firstName",
+                            char_value ? JsonValue{char_value} : JsonValue{}));
+
+  status = ContactUtil::GetStrFromRecord(contact_name, _contacts_name.addition,
+                                         &char_value);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  out.insert(std::make_pair("middleName",
+                            char_value ? JsonValue{char_value} : JsonValue{}));
+
+  status = ContactUtil::GetStrFromRecord(contact_name, _contacts_name.last,
+                                         &char_value);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  out.insert(std::make_pair("lastName",
+                            char_value ? JsonValue{char_value} : JsonValue{}));
+
+  status = ContactUtil::GetStrFromRecord(
+      contact_name, _contacts_name.phonetic_first, &char_value);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  out.insert(std::make_pair("phoneticFirstName",
+                            char_value ? JsonValue{char_value} : JsonValue{}));
+
+  status = ContactUtil::GetStrFromRecord(
+      contact_name, _contacts_name.phonetic_middle, &char_value);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  out.insert(std::make_pair("phoneticMiddleName",
+                            char_value ? JsonValue{char_value} : JsonValue{}));
+
+  status = ContactUtil::GetStrFromRecord(
+      contact_name, _contacts_name.phonetic_last, &char_value);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  out.insert(std::make_pair("phoneticLastName",
+                            char_value ? JsonValue{char_value} : JsonValue{}));
+
+  err = contacts_record_get_child_record_count(
+      contacts_record, _contacts_contact.nickname, &count);
+  status =
+      ContactUtil::ErrorChecker(err, "Contacts child record get count error");
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  JsonArray nicknames;
+  for (int i = 0; i < count; ++i) {
+    contacts_record_h nickname = nullptr;
+    err = contacts_record_get_child_record_at_p(
+        contacts_record, _contacts_contact.nickname, i, &nickname);
+    status = ContactUtil::ErrorChecker(
+        err, "Contacts nicknames record get child error");
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+
+    status = ContactUtil::GetStrFromRecord(nickname, _contacts_nickname.name,
+                                           &char_value);
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+
+    if (char_value) {
+      nicknames.push_back(JsonValue{char_value});
+    }
+  }
+  out["nicknames"] = picojson::value(nicknames);
+
+  *is_contact_name = true;
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult ExportContactNameToContactsRecord(
+    contacts_record_h contacts_record, const JsonObject& in) {
+
+  LoggerD("Enter");
+  // contacts_record is protected by unique_ptr and its ownership is not passed
+  // here
+  if (!contacts_record) {
+    LoggerW("Contacts record is null");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Contacts record is null");
+  }
+
+  contacts_record_h contact_name = nullptr;
+  int err = contacts_record_get_child_record_at_p(
+      contacts_record, _contacts_contact.name, 0, &contact_name);
+  bool update = true;
+  if (CONTACTS_ERROR_NONE != err && nullptr == contact_name) {
+    err = contacts_record_create(_contacts_name._uri, &contact_name);
+    PlatformResult status =
+        ContactUtil::ErrorChecker(err, "Contacts record create error");
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+
+    update = false;
+  }
+  // contact_name starts to be protected by unique_ptr
+  ContactsRecordHPtr contacts_name_ptr(&contact_name, ContactsDeleter);
+
+  if (!IsNull(in, "prefix")) {
+    PlatformResult status =
+        ContactUtil::SetStrInRecord(*contacts_name_ptr, _contacts_name.prefix,
+                                    FromJson<JsonString>(in, "prefix").c_str());
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+  }
+  if (!IsNull(in, "suffix")) {
+    PlatformResult status =
+        ContactUtil::SetStrInRecord(*contacts_name_ptr, _contacts_name.suffix,
+                                    FromJson<JsonString>(in, "suffix").c_str());
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+  }
+  if (!IsNull(in, "firstName")) {
+    PlatformResult status = ContactUtil::SetStrInRecord(
+        *contacts_name_ptr, _contacts_name.first,
+        FromJson<JsonString>(in, "firstName").c_str());
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+  }
+  if (!IsNull(in, "middleName")) {
+    PlatformResult status = ContactUtil::SetStrInRecord(
+        *contacts_name_ptr, _contacts_name.addition,
+        FromJson<JsonString>(in, "middleName").c_str());
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+  }
+  if (!IsNull(in, "lastName")) {
+    PlatformResult status = ContactUtil::SetStrInRecord(
+        *contacts_name_ptr, _contacts_name.last,
+        FromJson<JsonString>(in, "lastName").c_str());
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+  }
+  if (!IsNull(in, "phoneticFirstName")) {
+    PlatformResult status = ContactUtil::SetStrInRecord(
+        *contacts_name_ptr, _contacts_name.phonetic_first,
+        FromJson<JsonString>(in, "phoneticFirstName").c_str());
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+  }
+  if (!IsNull(in, "phoneticMiddleName")) {
+    PlatformResult status = ContactUtil::SetStrInRecord(
+        *contacts_name_ptr, _contacts_name.phonetic_middle,
+        FromJson<JsonString>(in, "phoneticMiddleName").c_str());
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+  }
+  if (!IsNull(in, "phoneticLastName")) {
+    PlatformResult status = ContactUtil::SetStrInRecord(
+        *contacts_name_ptr, _contacts_name.phonetic_last,
+        FromJson<JsonString>(in, "phoneticLastName").c_str());
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+  }
+
+  // contact_name is being added as a child to contacts_record
+  // and in future will be destroyed by contacts_record's contactsDeleter
+  if (!update) {
+    err = contacts_record_add_child_record(
+        contacts_record, _contacts_contact.name, *contacts_name_ptr);
+    PlatformResult status =
+        ContactUtil::ErrorChecker(err, "Contacts record add child error");
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+  }
+  // and now unique_ptr can be released - contacts_name is protected
+  // by its parent (contacts_record)
+  contacts_name_ptr.release();
+
+  const JsonArray& nicknames = FromJson<JsonArray>(in, "nicknames");
+
+  for (auto& nickname : nicknames) {
+    contacts_record_h nickname_record = nullptr;
+    err = contacts_record_get_child_record_at_p(
+        contacts_record, _contacts_contact.nickname, 0, &nickname_record);
+    if (CONTACTS_ERROR_NONE != err && nullptr == nickname_record) {
+      err = contacts_record_create(_contacts_nickname._uri, &nickname_record);
+      PlatformResult status =
+          ContactUtil::ErrorChecker(err, "Contacts record create error");
+      if (status.IsError()) {
+        LoggerE("Error: %s", status.message().c_str());
+        return status;
+      }
+
+      update = false;
+    }
+    ContactsRecordHPtr nickname_ptr(&nickname_record, ContactsDeleter);
+
+    PlatformResult status =
+        ContactUtil::SetStrInRecord(*nickname_ptr, _contacts_nickname.name,
+                                    JsonCast<JsonString>(nickname).c_str());
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+
+    if (!update) {
+      err = contacts_record_add_child_record(
+          contacts_record, _contacts_contact.nickname, *nickname_ptr);
+      PlatformResult status =
+          ContactUtil::ErrorChecker(err, "Contacts record add child error");
+      if (status.IsError()) {
+        LoggerE("Error: %s", status.message().c_str());
+        return status;
+      }
+    }
+    // Do not delete record, it is passed to the platform
+    nickname_ptr.release();
+  }
+
+  // TODO update displayName in JS!
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult ImportContactEmailAddressFromContactsRecord(
+    contacts_record_h contacts_record, unsigned int index,
+    JsonObject* out_ptr) {
+
+  LoggerD("Enter");
+  JsonObject& out = *out_ptr;
+  // contacts_record is protected by unique_ptr and its ownership is not passed
+  // here
+  if (!contacts_record) {
+    LoggerE("Contacts record is null");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Contacts record is null");
+  }
+
+  contacts_record_h child_record = nullptr;
+  int 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) {
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+
+  char* email = nullptr;
+  PlatformResult status = ContactUtil::GetStrFromRecord(
+      child_record, _contacts_email.email, &email);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  if (!email) {
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+  out.insert(std::make_pair("email", JsonValue{email}));
+
+  bool is_default = false;
+  status = ContactUtil::GetBoolFromRecord(
+      child_record, _contacts_email.is_default, &is_default);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  out.insert(std::make_pair("isDefault", JsonValue{is_default}));
+
+  char* label = nullptr;
+  status = ContactUtil::GetStrFromRecord(child_record, _contacts_email.label,
+                                         &label);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  out.insert(std::make_pair("label", label ? JsonValue{label} : JsonValue{}));
+
+  int type = 0;
+  status =
+      ContactUtil::GetIntFromRecord(child_record, _contacts_email.type, &type);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  JsonArray types;
+  if (type & CONTACTS_EMAIL_TYPE_HOME) {
+    types.push_back(JsonValue{kContactEmailAddressTypeHome});
+  }
+  if (type & CONTACTS_EMAIL_TYPE_WORK) {
+    types.push_back(JsonValue{kContactEmailAddressTypeWork});
+  }
+  if (CONTACTS_EMAIL_TYPE_OTHER == type) {
+    types.push_back(JsonValue{kContactEmailAddressTypeOther});
+  }
+  if (type & CONTACTS_EMAIL_TYPE_CUSTOM) {
+    types.push_back(JsonValue{kContactEmailAddressTypeCustom});
+  }
+
+  if (0 == types.size()) {
+    types.push_back(JsonValue{kContactEmailAddressTypeHome});
+  }
+
+  out.insert(std::make_pair("types", JsonValue{types}));
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult ExportContactEmailAddressToContactsRecord(
+    contacts_record_h contacts_record, const JsonObject& in) {
+
+  LoggerD("Enter");
+  contacts_record_h c_email_record_h = nullptr;
+  // contacts_record is protected by unique_ptr and its ownership is not passed
+  // here
+  if (!contacts_record) {
+    LoggerE("Contacts record is null");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Contacts record is null");
+  }
+
+  int err = contacts_record_create(_contacts_email._uri, &c_email_record_h);
+  PlatformResult status = ContactUtil::ErrorChecker(
+      err, "Failed to create email record in database");
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  ContactsRecordHPtr record(&c_email_record_h, ContactsDeleter);
+
+  status =
+      ContactUtil::SetStrInRecord(c_email_record_h, _contacts_email.email,
+                                  FromJson<JsonString>(in, "email").c_str());
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  status =
+      ContactUtil::SetBoolInRecord(c_email_record_h, _contacts_email.is_default,
+                                   FromJson<bool>(in, "isDefault"));
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  if (!IsNull(in, "label")) {
+    status =
+        ContactUtil::SetStrInRecord(c_email_record_h, _contacts_email.label,
+                                    FromJson<JsonString>(in, "label").c_str());
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+  }
+
+  int type_to_set = 0;
+
+  auto& types = FromJson<JsonArray>(in, "types");
+  for (auto& type : types) {
+    auto type_str = JsonCast<JsonString>(type);
+    if (type_str == kContactEmailAddressTypeWork) {
+      type_to_set |= CONTACTS_EMAIL_TYPE_WORK;
+    } else if (type_str == kContactEmailAddressTypeOther) {
+      type_to_set |= CONTACTS_EMAIL_TYPE_OTHER;
+    } else if (type_str == kContactEmailAddressTypeCustom) {
+      type_to_set |= CONTACTS_EMAIL_TYPE_CUSTOM;
+    } else {
+      type_to_set |= CONTACTS_EMAIL_TYPE_HOME;
+    }
+  }
+  status = ContactUtil::SetIntInRecord(c_email_record_h, _contacts_email.type,
+                                       type_to_set);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  err = contacts_record_add_child_record(
+      contacts_record, _contacts_contact.email, c_email_record_h);
+  status =
+      ContactUtil::ErrorChecker(err, "Fail to save email record into database");
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  // Do not delete record, it is passed to the platform
+  record.release();
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult ImportContactPhoneNumberFromContactsRecord(
+    contacts_record_h contacts_record, unsigned int index,
+    JsonObject* out_ptr) {
+
+  LoggerD("Enter");
+  JsonObject& out = *out_ptr;
+  contacts_record_h child_record = nullptr;
+  // contacts_record is protected by unique_ptr and its ownership is not passed
+  // here
+  if (!contacts_record) {
+    LoggerE("Contacts record is null");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Contacts record is null");
+  }
+
+  int 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) {
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+
+  char* phone = nullptr;
+  PlatformResult status = ContactUtil::GetStrFromRecord(
+      child_record, _contacts_number.number, &phone);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  out.insert(std::make_pair("number", JsonValue{phone}));
+
+  bool is_default = false;
+  status = ContactUtil::GetBoolFromRecord(
+      child_record, _contacts_number.is_default, &is_default);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  out.insert(std::make_pair("isDefault", JsonValue{is_default}));
+  int type = 0;
+  status =
+      ContactUtil::GetIntFromRecord(child_record, _contacts_number.type, &type);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  JsonArray types;
+  if (type & CONTACTS_NUMBER_TYPE_HOME) {
+    types.push_back(JsonValue{kContactPhoneTypeHome});
+  }
+  if (type & CONTACTS_NUMBER_TYPE_WORK) {
+    types.push_back(JsonValue{kContactPhoneTypeWork});
+  }
+  if (type & CONTACTS_NUMBER_TYPE_VOICE) {
+    types.push_back(JsonValue{kContactPhoneTypeVoice});
+  }
+  if (type & CONTACTS_NUMBER_TYPE_FAX) {
+    types.push_back(JsonValue{kContactPhoneTypeFax});
+  }
+  if (type & CONTACTS_NUMBER_TYPE_MSG) {
+    types.push_back(JsonValue{kContactPhoneTypeMsg});
+  }
+  if (type & CONTACTS_NUMBER_TYPE_CELL) {
+    types.push_back(JsonValue{kContactPhoneTypeCell});
+  }
+  if (type & CONTACTS_NUMBER_TYPE_PAGER) {
+    types.push_back(JsonValue{kContactPhoneTypePager});
+  }
+  if (type & CONTACTS_NUMBER_TYPE_BBS) {
+    types.push_back(JsonValue{kContactPhoneTypeBbs});
+  }
+  if (type & CONTACTS_NUMBER_TYPE_MODEM) {
+    types.push_back(JsonValue{kContactPhoneTypeModem});
+  }
+  if (type & CONTACTS_NUMBER_TYPE_CAR) {
+    types.push_back(JsonValue{kContactPhoneTypeCar});
+  }
+  if (type & CONTACTS_NUMBER_TYPE_ISDN) {
+    types.push_back(JsonValue{kContactPhoneTypeIsdn});
+  }
+  if (type & CONTACTS_NUMBER_TYPE_VIDEO) {
+    types.push_back(JsonValue{kContactPhoneTypeVideo});
+  }
+  if (type & CONTACTS_NUMBER_TYPE_PCS) {
+    types.push_back(JsonValue{kContactPhoneTypePcs});
+  }
+  if (type & CONTACTS_NUMBER_TYPE_ASSISTANT) {
+    types.push_back(JsonValue{kContactPhoneTypeAssistant});
+  }
+  if (CONTACTS_NUMBER_TYPE_OTHER == type) {
+    types.push_back(JsonValue{kContactPhoneTypeOther});
+  }
+  if (type & CONTACTS_NUMBER_TYPE_CUSTOM) {
+    types.push_back(JsonValue{kContactPhoneTypeCustom});
+  }
+  if (0 == types.size()) {
+    types.push_back(JsonValue{kContactPhoneTypeVoice});
+  }
+  out["types"] = picojson::value(types);
+
+  char* label = nullptr;
+  status = ContactUtil::GetStrFromRecord(child_record, _contacts_number.label,
+                                         &label);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  out["label"] = label ? JsonValue{label} : JsonValue{};
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult ExportContactPhoneNumberToContactsRecord(
+    contacts_record_h contacts_record, const JsonObject& in) {
+
+  LoggerD("Enter");
+  contacts_record_h phone_record = nullptr;
+  // contacts_record is protected by unique_ptr and its ownership is not passed
+  // here
+  if (!contacts_record) {
+    LoggerE("Contacts record is null");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Contacts record is null");
+  }
+
+  int err = contacts_record_create(_contacts_number._uri, &phone_record);
+  PlatformResult status =
+      ContactUtil::ErrorChecker(err, "Fail to create phone_record in database");
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  ContactsRecordHPtr record(&phone_record, ContactsDeleter);
+
+  status =
+      ContactUtil::SetStrInRecord(phone_record, _contacts_number.number,
+                                  FromJson<JsonString>(in, "number").c_str());
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  status =
+      ContactUtil::SetBoolInRecord(phone_record, _contacts_number.is_default,
+                                   FromJson<bool>(in, "isDefault"));
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  if (!IsNull(in, "label")) {
+    status =
+        ContactUtil::SetStrInRecord(phone_record, _contacts_address.label,
+                                    FromJson<JsonString>(in, "label").c_str());
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+  }
+
+  int type_to_set = 0;
+  const JsonArray& types = FromJson<JsonArray>(in, "types");
+  for (auto& type : types) {
+    auto& type_str = JsonCast<JsonString>(type);
+    if (type_str == kContactPhoneTypeHome) {
+      type_to_set |= CONTACTS_NUMBER_TYPE_HOME;
+    } else if (type_str == kContactPhoneTypeWork) {
+      type_to_set |= CONTACTS_NUMBER_TYPE_WORK;
+    } else if (type_str == kContactPhoneTypeVoice) {
+      type_to_set |= CONTACTS_NUMBER_TYPE_VOICE;
+    } else if (type_str == kContactPhoneTypeFax) {
+      type_to_set |= CONTACTS_NUMBER_TYPE_FAX;
+    } else if (type_str == kContactPhoneTypeMsg) {
+      type_to_set |= CONTACTS_NUMBER_TYPE_MSG;
+    } else if (type_str == kContactPhoneTypeCell) {
+      type_to_set |= CONTACTS_NUMBER_TYPE_CELL;
+    } else if (type_str == kContactPhoneTypePager) {
+      type_to_set |= CONTACTS_NUMBER_TYPE_PAGER;
+    } else if (type_str == kContactPhoneTypeBbs) {
+      type_to_set |= CONTACTS_NUMBER_TYPE_BBS;
+    } else if (type_str == kContactPhoneTypeModem) {
+      type_to_set |= CONTACTS_NUMBER_TYPE_MODEM;
+    } else if (type_str == kContactPhoneTypeCar) {
+      type_to_set |= CONTACTS_NUMBER_TYPE_CAR;
+    } else if (type_str == kContactPhoneTypeIsdn) {
+      type_to_set |= CONTACTS_NUMBER_TYPE_ISDN;
+    } else if (type_str == kContactPhoneTypeVideo) {
+      type_to_set |= CONTACTS_NUMBER_TYPE_VIDEO;
+    } else if (type_str == kContactPhoneTypePcs) {
+      type_to_set |= CONTACTS_NUMBER_TYPE_PCS;
+    } else if (type_str == kContactPhoneTypeAssistant) {
+      type_to_set |= CONTACTS_NUMBER_TYPE_ASSISTANT;
+    } else if (type_str == kContactPhoneTypeOther) {
+      type_to_set |= CONTACTS_NUMBER_TYPE_OTHER;
+    } else if (type_str == kContactPhoneTypeCustom) {
+      type_to_set |= CONTACTS_NUMBER_TYPE_CUSTOM;
+    } else {
+      type_to_set |= CONTACTS_NUMBER_TYPE_VOICE;
+    }
+  }
+
+  status = ContactUtil::SetIntInRecord(phone_record, _contacts_number.type,
+                                       type_to_set);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  err = contacts_record_add_child_record(
+      contacts_record, _contacts_contact.number, phone_record);
+  status = ContactUtil::ErrorChecker(
+      err, "Fail to set number value to phone_record");
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  // Do not delete record, it is passed to the platform
+  record.release();
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult ImportContactOrganizationFromContactsRecord(
+    contacts_record_h contacts_record, unsigned int index,
+    JsonObject* out_ptr) {
+
+  LoggerD("Enter");
+  JsonObject& out = *out_ptr;
+  // contacts_record is protected by unique_ptr and its ownership is not passed
+  // here
+  if (!contacts_record) {
+    LoggerE("Contacts record is null");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Contacts record is null");
+  }
+
+  contacts_record_h child_record = nullptr;
+  int 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) {
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+
+  char* char_value = nullptr;
+  PlatformResult status = ContactUtil::GetStrFromRecord(
+      child_record, _contacts_company.name, &char_value);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  out.insert(
+      std::make_pair("name", char_value ? JsonValue{char_value} : JsonValue{}));
+
+  status = ContactUtil::GetStrFromRecord(
+      child_record, _contacts_company.department, &char_value);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  out.insert(std::make_pair("department",
+                            char_value ? JsonValue{char_value} : JsonValue{}));
+
+  status = ContactUtil::GetStrFromRecord(
+      child_record, _contacts_company.job_title, &char_value);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  out.insert(std::make_pair("title",
+                            char_value ? JsonValue{char_value} : JsonValue{}));
+
+  status = ContactUtil::GetStrFromRecord(child_record, _contacts_company.role,
+                                         &char_value);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  out.insert(
+      std::make_pair("role", char_value ? JsonValue{char_value} : JsonValue{}));
+
+  status = ContactUtil::GetStrFromRecord(child_record, _contacts_company.logo,
+                                         &char_value);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  out.insert(
+      std::make_pair(
+          "logoURI",
+          char_value ? JsonValue{ConvertPathToUri(char_value)} : JsonValue{}));
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult ExportContactOrganizationToContactsRecord(
+    contacts_record_h contacts_record, const JsonObject& in) {
+
+  LoggerD("Enter");
+  // contacts_record is protected by unique_ptr and its ownership is not passed
+  // here
+  if (!contacts_record) {
+    LoggerE("Contacts record is null");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Contacts record is null");
+  }
+
+  contacts_record_h organization_record = nullptr;
+  int err = contacts_record_create(_contacts_company._uri, &organization_record);
+  PlatformResult status = ContactUtil::ErrorChecker(
+      err, "Failed to create organization record in database");
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  ContactsRecordHPtr record(&organization_record, ContactsDeleter);
+
+  if (!IsNull(in, "name")) {
+    status =
+        ContactUtil::SetStrInRecord(organization_record, _contacts_company.name,
+                                    FromJson<JsonString>(in, "name").c_str());
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+  }
+  if (!IsNull(in, "department")) {
+    status = ContactUtil::SetStrInRecord(
+        organization_record, _contacts_company.department,
+        FromJson<JsonString>(in, "department").c_str());
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+  }
+  if (!IsNull(in, "title")) {
+    status = ContactUtil::SetStrInRecord(
+        organization_record, _contacts_company.job_title,
+        FromJson<JsonString>(in, "title").c_str());
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+  }
+  if (!IsNull(in, "role")) {
+    status =
+        ContactUtil::SetStrInRecord(organization_record, _contacts_company.role,
+                                    FromJson<JsonString>(in, "role").c_str());
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+  }
+  if (!IsNull(in, "logoURI")) {
+    std::string path =
+        ContactUtil::ConvertUriToPath(FromJson<JsonString>(in, "logoURI"));
+    status = ContactUtil::SetStrInRecord(organization_record,
+                                         _contacts_company.logo, path.c_str());
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+  }
+
+  err = contacts_record_add_child_record(
+      contacts_record, _contacts_contact.company, organization_record);
+  status = ContactUtil::ErrorChecker(
+      err, "Fail to set company value to child_record");
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  // Do not delete record, it is passed to the platform
+  record.release();
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult ImportContactWebSiteFromContactsRecord(
+    contacts_record_h contacts_record, unsigned int index,
+    JsonObject* out_ptr) {
+
+  LoggerD("Enter");
+  JsonObject& out = *out_ptr;
+  // contacts_record is protected by unique_ptr and its ownership is not passed
+  // here
+  if (!contacts_record) {
+    LoggerE("Contacts record is null");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Contacts record is null");
+  }
+
+  contacts_record_h child_record = nullptr;
+  int 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) {
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+
+  char* char_value = nullptr;
+  PlatformResult status = ContactUtil::GetStrFromRecord(
+      child_record, _contacts_url.url, &char_value);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  out.insert(
+      std::make_pair(std::string("url"),
+                     picojson::value(char_value ? char_value : "")));
+
+  int type = 0;
+  status =
+      ContactUtil::GetIntFromRecord(child_record, _contacts_url.type, &type);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  out.insert(std::make_pair(std::string("type"),
+                            picojson::value((CONTACTS_URL_TYPE_HOME == type)
+                                            ? kContactWebSiteTypeHomePage
+                                                : kContactWebSiteTypeBlog)));
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult ExportContactWebSiteToContactsRecord(
+    contacts_record_h contacts_record, const JsonObject& in) {
+
+  LoggerD("Enter");
+  // contacts_record is protected by unique_ptr and its ownership is not passed
+  // here
+  if (!contacts_record) {
+    LoggerE("Contacts record is null");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Contacts record is null");
+  }
+
+  if (IsNull(in, "url")) {
+    LoggerD("WebSite urls are not set");
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+
+  const std::string& url = FromJson<JsonString>(in, "url");
+  if (url.empty()) {
+    LoggerD("WebSite urls are not set");
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+
+  contacts_record_h website_record_h = nullptr;
+  int err = contacts_record_create(_contacts_url._uri, &website_record_h);
+  PlatformResult status = ContactUtil::ErrorChecker(
+      err, "Fail to create website record in database.");
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  ContactsRecordHPtr record(&website_record_h, ContactsDeleter);
+
+  status = ContactUtil::SetStrInRecord(website_record_h, _contacts_url.url,
+                                       url.c_str());
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  int type_to_set =
+      (FromJson<JsonString>(in, "type") == kContactWebSiteTypeHomePage)
+          ? CONTACTS_URL_TYPE_HOME
+          : CONTACTS_URL_TYPE_WORK;
+
+  status = ContactUtil::SetIntInRecord(website_record_h, _contacts_url.type,
+                                       type_to_set);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  err = contacts_record_add_child_record(contacts_record, _contacts_contact.url,
+                                         website_record_h);
+  status = ContactUtil::ErrorChecker(
+      err, "Problem during saving WebSite urls into database.");
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  // Do not delete record, it is passed to the platform
+  record.release();
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult ImportContactAnniversariesFromContactsRecord(
+    contacts_record_h contacts_record, unsigned int index, JsonObject* out_ptr,
+    bool* ret) {
+
+  LoggerD("Enter");
+  JsonObject& out = *out_ptr;
+  // contacts_record is protected by unique_ptr and its ownership is not passed
+  // here
+  if (!contacts_record) {
+    LoggerE("Contacts record is null");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Contacts record is null");
+  }
+
+  contacts_record_h child_record = nullptr;
+  int 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) {
+    *ret = false;
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+
+  int value = 0;
+  PlatformResult status =
+      ContactUtil::GetIntFromRecord(child_record, _contacts_event.type, &value);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  if (CONTACTS_EVENT_TYPE_BIRTH == value) {
+    *ret = false;
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+
+  if (CONTACTS_EVENT_TYPE_ANNIVERSARY == value) {
+    status = ContactUtil::GetIntFromRecord(child_record, _contacts_event.date,
+                                           &value);
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+
+    out.insert(std::make_pair("date", JsonValue{static_cast<double>(value)}));
+
+    char* label = nullptr;
+    status = ContactUtil::GetStrFromRecord(child_record, _contacts_event.label,
+                                           &label);
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+
+    out.insert(std::make_pair("label", label ? JsonValue{label} : JsonValue{}));
+  }
+
+  *ret = true;
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult ExportContactAnniversariesToContactsRecord(
+    contacts_record_h contacts_record, const JsonObject& in) {
+
+  LoggerD("Enter");
+  // contacts_record is protected by unique_ptr and its ownership is not passed
+  // here
+  if (!contacts_record) {
+    LoggerE("Contacts record is null");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Contacts record is null");
+  }
+
+  int date = static_cast<int>(FromJson<double>(in, "date"));
+  if (date == 0) {
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+
+  contacts_record_h anniversary_record = nullptr;
+  int err = contacts_record_create(_contacts_event._uri, &anniversary_record);
+  PlatformResult status = ContactUtil::ErrorChecker(
+      err, "Failed to create anniversary record in database");
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  ContactsRecordHPtr record(&anniversary_record, ContactsDeleter);
+
+  status = ContactUtil::SetIntInRecord(anniversary_record, _contacts_event.type,
+                                       CONTACTS_EVENT_TYPE_ANNIVERSARY);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  status = ContactUtil::SetIntInRecord(anniversary_record, _contacts_event.date,
+                                       date);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  if (!IsNull(in, "label")) {
+    status =
+        ContactUtil::SetStrInRecord(anniversary_record, _contacts_event.label,
+                                    FromJson<JsonString>(in, "label").c_str());
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+  }
+
+  err = contacts_record_add_child_record(
+      contacts_record, _contacts_contact.event, anniversary_record);
+  status = ContactUtil::ErrorChecker(
+      err, "Fail to save anniversary record in database");
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  // Do not delete record, it is passed to the platform
+  record.release();
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult ImportContactRelationshipFromContactsRecord(
+    contacts_record_h contacts_record, unsigned int index,
+    JsonObject* out_ptr) {
+
+  LoggerD("Enter");
+  JsonObject& out = *out_ptr;
+  // contacts_record is protected by unique_ptr and its ownership is not passed
+  // here
+  if (!contacts_record) {
+    LoggerE("Contacts record is null");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Contacts record is null");
+  }
+
+  contacts_record_h child_record = nullptr;
+  int 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) {
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+
+  char* relative = nullptr;
+  PlatformResult status = ContactUtil::GetStrFromRecord(
+      child_record, _contacts_relationship.name, &relative);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  if (!relative) {
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+
+  out.insert(std::make_pair(std::string("relativeName"),
+                            picojson::value(JsonString{relative})));
+
+  int type = 0;
+  status = ContactUtil::GetIntFromRecord(child_record,
+                                         _contacts_relationship.type, &type);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  // TODO Move out.insert outside of switch statement.
+  switch (type) {
+    case CONTACTS_RELATIONSHIP_TYPE_CUSTOM:
+      out.insert(
+          std::make_pair(std::string("type"),
+                         picojson::value(JsonString{kContactRelationshipTypeCustom})));
+      break;
+    case CONTACTS_RELATIONSHIP_TYPE_ASSISTANT:
+      out.insert(std::make_pair(std::string("type"),
+                                picojson::value(JsonString{kContactRelationshipTypeAssistant})));
+      break;
+    case CONTACTS_RELATIONSHIP_TYPE_BROTHER:
+      out.insert(
+          std::make_pair(std::string("type"),
+                         picojson::value(JsonString{kContactRelationshipTypeBrother})));
+      break;
+    case CONTACTS_RELATIONSHIP_TYPE_CHILD:
+      out.insert(
+          std::make_pair(std::string("type"),
+                         picojson::value(JsonString{kContactRelationshipTypeChild})));
+      break;
+    case CONTACTS_RELATIONSHIP_TYPE_DOMESTIC_PARTNER:
+      out.insert(std::make_pair(
+          std::string("type"),
+          picojson::value(
+              JsonString{kContactRelationshipTypeDomesticPartner})));
+      break;
+    case CONTACTS_RELATIONSHIP_TYPE_FATHER:
+      out.insert(
+          std::make_pair(std::string("type"),
+                         picojson::value(JsonString{kContactRelationshipTypeFather})));
+      break;
+    case CONTACTS_RELATIONSHIP_TYPE_FRIEND:
+      out.insert(
+          std::make_pair(std::string("type"),
+                         picojson::value(JsonString{kContactRelationshipTypeFriend})));
+      break;
+    case CONTACTS_RELATIONSHIP_TYPE_MANAGER:
+      out.insert(
+          std::make_pair(std::string("type"),
+                         picojson::value(JsonString{kContactRelationshipTypeManager})));
+      break;
+    case CONTACTS_RELATIONSHIP_TYPE_MOTHER:
+      out.insert(
+          std::make_pair(std::string("type"),
+                         picojson::value(JsonString{kContactRelationshipTypeMother})));
+      break;
+    case CONTACTS_RELATIONSHIP_TYPE_PARENT:
+      out.insert(
+          std::make_pair(std::string("type"),
+                         picojson::value(JsonString{kContactRelationshipTypeParent})));
+      break;
+    case CONTACTS_RELATIONSHIP_TYPE_PARTNER:
+      out.insert(
+          std::make_pair(std::string("type"),
+                         picojson::value(JsonString{kContactRelationshipTypePartner})));
+      break;
+    case CONTACTS_RELATIONSHIP_TYPE_REFERRED_BY:
+      out.insert(std::make_pair(
+          std::string("type"),
+          picojson::value(JsonString{kContactRelationshipTypeReferredBy})));
+      break;
+    case CONTACTS_RELATIONSHIP_TYPE_RELATIVE:
+      out.insert(
+          std::make_pair(std::string("type"),
+                         picojson::value(JsonString{kContactRelationshipTypeRelative})));
+      break;
+    case CONTACTS_RELATIONSHIP_TYPE_SISTER:
+      out.insert(
+          std::make_pair(std::string("type"),
+                         picojson::value(JsonString{kContactRelationshipTypeSister})));
+      break;
+    case CONTACTS_RELATIONSHIP_TYPE_SPOUSE:
+      out.insert(
+          std::make_pair(std::string("type"),
+                         picojson::value(JsonString{kContactRelationshipTypeSpouse})));
+      break;
+    case CONTACTS_RELATIONSHIP_TYPE_OTHER:
+    default:
+      out.insert(
+          std::make_pair(std::string("type"),
+                         picojson::value(JsonString{kContactRelationshipTypeOther})));
+      break;
+  }
+
+  char* label = nullptr;
+  status = ContactUtil::GetStrFromRecord(child_record,
+                                         _contacts_relationship.label, &label);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  out.insert(
+      std::make_pair(std::string("label"),
+                     picojson::value(label ? JsonValue{label} : JsonValue{})));
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult ExportContactRelationshipToContactsRecord(
+    contacts_record_h contacts_record, const JsonObject& in) {
+
+  LoggerD("Enter");
+  // contacts_record is protected by unique_ptr and its ownership is not passed
+  // here
+  if (!contacts_record) {
+    LoggerE("Contacts record is null");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Contacts record is null");
+  }
+
+  contacts_record_h child_record = nullptr;
+  int err = contacts_record_create(_contacts_relationship._uri, &child_record);
+  PlatformResult status =
+      ContactUtil::ErrorChecker(err, "Fail to create child_record in database");
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  ContactsRecordHPtr record(&child_record, ContactsDeleter);
+
+  status = ContactUtil::SetStrInRecord(
+      child_record, _contacts_relationship.name,
+      FromJson<JsonString>(in, "relativeName").c_str());
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  const JsonString& type = FromJson<JsonString>(in, "type");
+  int type_to_set;
+  if (type == kContactRelationshipTypeAssistant) {
+    type_to_set = CONTACTS_RELATIONSHIP_TYPE_ASSISTANT;
+  } else if (type == kContactRelationshipTypeBrother) {
+    type_to_set = CONTACTS_RELATIONSHIP_TYPE_BROTHER;
+  } else if (type == kContactRelationshipTypeChild) {
+    type_to_set = CONTACTS_RELATIONSHIP_TYPE_CHILD;
+  } else if (type == kContactRelationshipTypeDomesticPartner) {
+    type_to_set = CONTACTS_RELATIONSHIP_TYPE_DOMESTIC_PARTNER;
+  } else if (type == kContactRelationshipTypeFather) {
+    type_to_set = CONTACTS_RELATIONSHIP_TYPE_FATHER;
+  } else if (type == kContactRelationshipTypeFriend) {
+    type_to_set = CONTACTS_RELATIONSHIP_TYPE_FRIEND;
+  } else if (type == kContactRelationshipTypeManager) {
+    type_to_set = CONTACTS_RELATIONSHIP_TYPE_MANAGER;
+  } else if (type == kContactRelationshipTypeMother) {
+    type_to_set = CONTACTS_RELATIONSHIP_TYPE_MOTHER;
+  } else if (type == kContactRelationshipTypeParent) {
+    type_to_set = CONTACTS_RELATIONSHIP_TYPE_PARENT;
+  } else if (type == kContactRelationshipTypePartner) {
+    type_to_set = CONTACTS_RELATIONSHIP_TYPE_PARTNER;
+  } else if (type == kContactRelationshipTypeReferredBy) {
+    type_to_set = CONTACTS_RELATIONSHIP_TYPE_REFERRED_BY;
+  } else if (type == kContactRelationshipTypeRelative) {
+    type_to_set = CONTACTS_RELATIONSHIP_TYPE_RELATIVE;
+  } else if (type == kContactRelationshipTypeSister) {
+    type_to_set = CONTACTS_RELATIONSHIP_TYPE_SISTER;
+  } else if (type == kContactRelationshipTypeSpouse) {
+    type_to_set = CONTACTS_RELATIONSHIP_TYPE_SPOUSE;
+  } else if (type == kContactRelationshipTypeCustom) {
+    type_to_set = CONTACTS_RELATIONSHIP_TYPE_CUSTOM;
+  } else {
+    type_to_set = CONTACTS_MESSENGER_TYPE_OTHER;
+  }
+
+  status = ContactUtil::SetIntInRecord(
+      child_record, _contacts_relationship.type, type_to_set);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  if (!IsNull(in, "label")) {
+    status =
+        ContactUtil::SetStrInRecord(child_record, _contacts_relationship.label,
+                                    FromJson<JsonString>(in, "label").c_str());
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+  }
+
+  err = contacts_record_add_child_record(
+      contacts_record, _contacts_contact.relationship, child_record);
+  status = ContactUtil::ErrorChecker(
+      err, "Fail to set number value to child_record");
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  record.release();
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult ImportContactInstantMessengerFromContactsRecord(
+    contacts_record_h contacts_record, unsigned int index,
+    JsonObject* out_ptr) {
+
+  LoggerD("Enter");
+  JsonObject& out = *out_ptr;
+  // contacts_record is protected by unique_ptr and its ownership is not passed
+  // here
+  if (!contacts_record) {
+    LoggerE("Contacts record is null");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Contacts record is null");
+  }
+
+  contacts_record_h child_record = nullptr;
+  int 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) {
+    LoggerW("Skipping message with index %i. error code: %i", index, err);
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+
+  char* im_address = nullptr;
+  PlatformResult status = ContactUtil::GetStrFromRecord(
+      child_record, _contacts_messenger.im_id, &im_address);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  if (!im_address) {
+    LoggerW("Skipping message with index %i. missing im address", index);
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+
+  out.insert(std::make_pair("imAddress", JsonValue{im_address}));
+
+  int type = 0;
+  status = ContactUtil::GetIntFromRecord(child_record, _contacts_messenger.type,
+                                         &type);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  // TODO Move out.insert outside of switch statement.
+  switch (type) {
+    case CONTACTS_MESSENGER_TYPE_CUSTOM:
+      out.insert(
+          std::make_pair("type", JsonValue{kContactInstantMessageTypeCustom}));
+      break;
+    case CONTACTS_MESSENGER_TYPE_GOOGLE:
+      out.insert(
+          std::make_pair("type", JsonValue{kContactInstantMessageTypeGoogle}));
+      break;
+    case CONTACTS_MESSENGER_TYPE_WLM:
+      out.insert(
+          std::make_pair("type", JsonValue{kContactInstantMessageTypeWlm}));
+      break;
+    case CONTACTS_MESSENGER_TYPE_YAHOO:
+      out.insert(
+          std::make_pair("type", JsonValue{kContactInstantMessageTypeYahoo}));
+      break;
+    case CONTACTS_MESSENGER_TYPE_FACEBOOK:
+      out.insert(std::make_pair("type",
+                                JsonValue{kContactInstantMessageTypeFacebook}));
+      break;
+    case CONTACTS_MESSENGER_TYPE_ICQ:
+      out.insert(
+          std::make_pair("type", JsonValue{kContactInstantMessageTypeIcq}));
+      break;
+    case CONTACTS_MESSENGER_TYPE_AIM:
+      out.insert(
+          std::make_pair("type", JsonValue{kContactInstantMessageTypeAim}));
+      break;
+    case CONTACTS_MESSENGER_TYPE_QQ:
+      out.insert(
+          std::make_pair("type", JsonValue{kContactInstantMessageTypeQq}));
+      break;
+    case CONTACTS_MESSENGER_TYPE_JABBER:
+      out.insert(
+          std::make_pair("type", JsonValue{kContactInstantMessageTypeJabber}));
+      break;
+    case CONTACTS_MESSENGER_TYPE_SKYPE:
+      out.insert(
+          std::make_pair("type", JsonValue{kContactInstantMessageTypeSkype}));
+      break;
+    case CONTACTS_MESSENGER_TYPE_IRC:
+      out.insert(
+          std::make_pair("type", JsonValue{kContactInstantMessageTypeIrc}));
+      break;
+    case CONTACTS_MESSENGER_TYPE_OTHER:
+    default:
+      out.insert(
+          std::make_pair("type", JsonValue{kContactInstantMessageTypeOther}));
+      break;
+  }
+
+  char* label = nullptr;
+  status = ContactUtil::GetStrFromRecord(child_record,
+                                         _contacts_messenger.label, &label);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  out.insert(std::make_pair("label", label ? JsonValue{label} : JsonValue{}));
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult ExportContactInstantMessengerToContactsRecord(
+    contacts_record_h contacts_record, const JsonObject& in) {
+
+  LoggerD("Enter");
+  // contacts_record is protected by unique_ptr and its ownership is not passed
+  // here
+  if (!contacts_record) {
+    LoggerE("Contacts record is null");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Contacts record is null");
+  }
+
+  contacts_record_h child_record = nullptr;
+  int err = contacts_record_create(_contacts_messenger._uri, &child_record);
+  PlatformResult status =
+      ContactUtil::ErrorChecker(err, "Fail to create child_record in database");
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  ContactsRecordHPtr record(&child_record, ContactsDeleter);
+
+  status = ContactUtil::SetStrInRecord(
+      child_record, _contacts_messenger.im_id,
+      FromJson<JsonString>(in, "imAddress").c_str());
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  int type_to_set = 0;
+  const JsonString& type = FromJson<JsonString>(in, "type");
+  if (type == kContactInstantMessageTypeGoogle) {
+    type_to_set = CONTACTS_MESSENGER_TYPE_GOOGLE;
+  } else if (type == kContactInstantMessageTypeWlm) {
+    type_to_set = CONTACTS_MESSENGER_TYPE_WLM;
+  } else if (type == kContactInstantMessageTypeYahoo) {
+    type_to_set = CONTACTS_MESSENGER_TYPE_YAHOO;
+  } else if (type == kContactInstantMessageTypeFacebook) {
+    type_to_set = CONTACTS_MESSENGER_TYPE_FACEBOOK;
+  } else if (type == kContactInstantMessageTypeIcq) {
+    type_to_set = CONTACTS_MESSENGER_TYPE_ICQ;
+  } else if (type == kContactInstantMessageTypeAim) {
+    type_to_set = CONTACTS_MESSENGER_TYPE_AIM;
+  } else if (type == kContactInstantMessageTypeQq) {
+    type_to_set = CONTACTS_MESSENGER_TYPE_QQ;
+  } else if (type == kContactInstantMessageTypeJabber) {
+    type_to_set = CONTACTS_MESSENGER_TYPE_JABBER;
+  } else if (type == kContactInstantMessageTypeSkype) {
+    type_to_set = CONTACTS_MESSENGER_TYPE_SKYPE;
+  } else if (type == kContactInstantMessageTypeIrc) {
+    type_to_set = CONTACTS_MESSENGER_TYPE_IRC;
+  } else if (type == kContactInstantMessageTypeCustom) {
+    type_to_set = CONTACTS_MESSENGER_TYPE_CUSTOM;
+  } else {
+    type_to_set = CONTACTS_MESSENGER_TYPE_OTHER;
+  }
+
+  status = ContactUtil::SetIntInRecord(child_record, _contacts_messenger.type,
+                                       type_to_set);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  if (!IsNull(in, "label")) {
+    status =
+        ContactUtil::SetStrInRecord(child_record, _contacts_messenger.label,
+                                    FromJson<JsonString>(in, "label").c_str());
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+  }
+
+  err = contacts_record_add_child_record(
+      contacts_record, _contacts_contact.messenger, child_record);
+  status = ContactUtil::ErrorChecker(
+      err, "Fail to set number value to child_record");
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  record.release();
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult ImportContactAddressFromContactsRecord(
+    contacts_record_h contacts_record, unsigned int index,
+    JsonObject* out_ptr) {
+
+  LoggerD("Enter");
+  JsonObject& out = *out_ptr;
+  // contacts_record is protected by unique_ptr and its ownership is not passed
+  // here
+  if (!contacts_record) {
+    LoggerE("Contacts record is null");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Contacts record is null");
+  }
+
+  contacts_record_h child_record = nullptr;
+  int 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) {
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+
+  char* value = nullptr;
+  PlatformResult status = ContactUtil::GetStrFromRecord(
+      child_record, _contacts_address.country, &value);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  out.insert(std::make_pair("country", value ? JsonValue{value} : JsonValue{}));
+  status = ContactUtil::GetStrFromRecord(child_record, _contacts_address.region,
+                                         &value);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  out.insert(std::make_pair("region", value ? JsonValue{value} : JsonValue{}));
+  status = ContactUtil::GetStrFromRecord(child_record,
+                                         _contacts_address.locality, &value);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  out.insert(std::make_pair("city", value ? JsonValue{value} : JsonValue{}));
+  status = ContactUtil::GetStrFromRecord(child_record, _contacts_address.street,
+                                         &value);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  out.insert(
+      std::make_pair("streetAddress", value ? JsonValue{value} : JsonValue{}));
+  status = ContactUtil::GetStrFromRecord(child_record,
+                                         _contacts_address.extended, &value);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  out.insert(std::make_pair("additionalInformation",
+                            value ? JsonValue{value} : JsonValue{}));
+  status = ContactUtil::GetStrFromRecord(child_record,
+                                         _contacts_address.postal_code, &value);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  out.insert(
+      std::make_pair("postalCode", value ? JsonValue{value} : JsonValue{}));
+  status = ContactUtil::GetStrFromRecord(child_record, _contacts_address.label,
+                                         &value);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  out.insert(std::make_pair("label", value ? JsonValue{value} : JsonValue{}));
+
+  bool bool_value = false;
+  status = ContactUtil::GetBoolFromRecord(
+      child_record, _contacts_address.is_default, &bool_value);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  out.insert(std::make_pair("isDefault", JsonValue{bool_value}));
+
+  int int_value = 0;
+  status = ContactUtil::GetIntFromRecord(child_record, _contacts_address.type,
+                                         &int_value);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  JsonArray types;
+  if (int_value & CONTACTS_ADDRESS_TYPE_HOME) {
+    types.push_back(JsonValue{kContactAddressTypeHome});
+  }
+  if (int_value & CONTACTS_ADDRESS_TYPE_WORK) {
+    types.push_back(JsonValue{kContactAddressTypeWork});
+  }
+  if (CONTACTS_ADDRESS_TYPE_OTHER == int_value) {
+    types.push_back(JsonValue{kContactAddressTypeOther});
+  }
+  if (int_value & CONTACTS_ADDRESS_TYPE_CUSTOM) {
+    types.push_back(JsonValue{kContactAddressTypeCustom});
+  }
+
+  if (types.empty()) {
+    types.push_back(JsonValue{kContactAddressTypeHome});
+  }
+  out.insert(std::make_pair("types", picojson::value(types)));
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult ExportContactAddressToContactsRecord(
+    contacts_record_h contacts_record, const JsonObject& in) {
+
+  LoggerD("Enter");
+  // contacts_record is protected by unique_ptr and its ownership is not passed
+  // here
+  if (!contacts_record) {
+    LoggerE("Contacts record is null");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Contacts record is null");
+  }
+
+  contacts_record_h address_record = nullptr;
+  int err = contacts_record_create(_contacts_address._uri, &address_record);
+  PlatformResult status = ContactUtil::ErrorChecker(
+      err, "Failed to create address record in database");
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  ContactsRecordHPtr record(&address_record, ContactsDeleter);
+
+  if (!IsNull(in, "country")) {
+    status = ContactUtil::SetStrInRecord(
+        address_record, _contacts_address.country,
+        FromJson<JsonString>(in, "country").c_str());
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+  }
+  if (!IsNull(in, "region")) {
+    status =
+        ContactUtil::SetStrInRecord(address_record, _contacts_address.region,
+                                    FromJson<JsonString>(in, "region").c_str());
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+  }
+  if (!IsNull(in, "city")) {
+    status =
+        ContactUtil::SetStrInRecord(address_record, _contacts_address.locality,
+                                    FromJson<JsonString>(in, "city").c_str());
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+  }
+  if (!IsNull(in, "streetAddress")) {
+    status = ContactUtil::SetStrInRecord(
+        address_record, _contacts_address.street,
+        FromJson<JsonString>(in, "streetAddress").c_str());
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+  }
+  if (!IsNull(in, "additionalInformation")) {
+    status = ContactUtil::SetStrInRecord(
+        address_record, _contacts_address.extended,
+        FromJson<JsonString>(in, "additionalInformation").c_str());
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+  }
+  if (!IsNull(in, "postalCode")) {
+    status = ContactUtil::SetStrInRecord(
+        address_record, _contacts_address.postal_code,
+        FromJson<JsonString>(in, "postalCode").c_str());
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+  }
+  if (!IsNull(in, "label")) {
+    status =
+        ContactUtil::SetStrInRecord(address_record, _contacts_address.label,
+                                    FromJson<JsonString>(in, "label").c_str());
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+  }
+
+  status =
+      ContactUtil::SetBoolInRecord(address_record, _contacts_address.is_default,
+                                   FromJson<bool>(in, "isDefault"));
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  int type_to_set = 0;
+  const JsonArray& types = FromJson<JsonArray>(in, "types");
+  for (auto& type : types) {
+    auto& type_str = JsonCast<JsonString>(type);
+    if (type_str == kContactAddressTypeWork) {
+      type_to_set |= CONTACTS_ADDRESS_TYPE_WORK;
+    } else if (type_str == kContactAddressTypeOther) {
+      type_to_set |= CONTACTS_ADDRESS_TYPE_OTHER;
+    } else if (type_str == kContactAddressTypeCustom) {
+      type_to_set |= CONTACTS_ADDRESS_TYPE_CUSTOM;
+    } else {
+      type_to_set |= CONTACTS_ADDRESS_TYPE_HOME;
+    }
+  }
+
+  status = ContactUtil::SetIntInRecord(address_record, _contacts_address.type,
+                                       type_to_set);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  err = contacts_record_add_child_record(
+      contacts_record, _contacts_contact.address, address_record);
+  status =
+      ContactUtil::ErrorChecker(err, "Fail to save address record in database");
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  // Do not delete record, it is passed to the platform
+  record.release();
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult ImportContactNotesFromContactsRecord(
+    contacts_record_h contacts_record, unsigned int index, JsonValue* val) {
+
+  LoggerD("Enter");
+  // contacts_record is protected by unique_ptr and its ownership is not passed
+  // here
+  if (!contacts_record) {
+    LoggerE("Contacts record is null");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Contacts record is null");
+  }
+
+  contacts_record_h notes_record = nullptr;
+  int 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) {
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+
+  char* note = nullptr;
+  PlatformResult status =
+      ContactUtil::GetStrFromRecord(notes_record, _contacts_note.note, &note);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  if (note) {
+    *val = JsonValue{note};
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult ExportNotesToContactsRecord(contacts_record_h contacts_record,
+                                           const std::string& value) {
+
+  LoggerD("Enter");
+  contacts_record_h notes_record = nullptr;
+  // contacts_record is protected by unique_ptr and its ownership is not passed
+  // here
+  if (!contacts_record) {
+    LoggerE("Contacts record is null");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Contacts record is null");
+  }
+
+  int err = contacts_record_create(_contacts_note._uri, &notes_record);
+  PlatformResult status =
+      ContactUtil::ErrorChecker(err, "Fail to create note record in database");
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  ContactsRecordHPtr record(&notes_record, ContactsDeleter);
+
+  status = ContactUtil::SetStrInRecord(notes_record, _contacts_note.note,
+                                       value.c_str());
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  err = contacts_record_add_child_record(contacts_record,
+                                         _contacts_contact.note, notes_record);
+  status =
+      ContactUtil::ErrorChecker(err, "Fail to save note record in database");
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  // Do not delete record, it is passed to the platform
+  record.release();
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult ImportContactFromContactsRecord(
+    contacts_record_h contacts_record, JsonObject* out_ptr) {
+
+  LoggerD("Enter");
+  JsonObject& out = *out_ptr;
+  // contacts_record is protected by unique_ptr and its ownership is not passed
+  // here
+  if (!contacts_record) {
+    LoggerE("Contacts record is null");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Contacts record is null");
+  }
+
+  int id = 0;
+  PlatformResult status =
+      ContactUtil::GetIntFromRecord(contacts_record, _contacts_contact.id, &id);
+  if (status.IsError())
+  {
+    LoggerE("Fail: GetIntFromRecord");
+    return status;
+  }
+  out.insert(std::make_pair("id", JsonValue{std::to_string(id)}));
+  status = ContactUtil::GetIntFromRecord(
+      contacts_record, _contacts_contact.address_book_id, &id);
+  if (status.IsError())
+  {
+    LoggerE("Fail: GetIntFromRecord");
+    return status;
+  }
+  out.insert(std::make_pair("addressBookId", JsonValue{std::to_string(id)}));
+  status = ContactUtil::GetIntFromRecord(contacts_record,
+                                         _contacts_contact.person_id, &id);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  out.insert(std::make_pair("personId", JsonValue{std::to_string(id)}));
+
+  bool is_favorite = false;
+  status = ContactUtil::GetBoolFromRecord(
+      contacts_record, _contacts_contact.is_favorite, &is_favorite);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  out.insert(std::make_pair("isFavorite", JsonValue{is_favorite}));
+
+  int last_update = 0;
+  status = ContactUtil::GetIntFromRecord(
+      contacts_record, _contacts_contact.changed_time, &last_update);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  out.insert(std::make_pair("lastUpdated",
+                            JsonValue{static_cast<double>(last_update)}));
+
+  //### ContactName: ###
+  JsonObject name;
+  bool is_contact_name;
+  status = ImportContactNameFromContactsRecord(contacts_record, &name,
+                                               &is_contact_name);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  if (is_contact_name) {
+    out.insert(std::make_pair(std::string("name"), picojson::value(name)));
+  } else {
+    out.insert(std::make_pair(std::string("name"),
+                              picojson::value(JsonValue{})));
+  }
+
+  typedef PlatformResult (*ImportFunc)(contacts_record_h, unsigned int,
+      JsonObject*);
+  struct ImportData {
+    const char* name;
+    unsigned int property_id;
+    ImportFunc import_func;
+  };
+  ImportData imports[] = {
+      {"emails", _contacts_contact.email,
+          ImportContactEmailAddressFromContactsRecord},
+      {"phoneNumbers", _contacts_contact.number,
+          ImportContactPhoneNumberFromContactsRecord},
+      {"organizations", _contacts_contact.company,
+          ImportContactOrganizationFromContactsRecord},
+      {"urls", _contacts_contact.url, ImportContactWebSiteFromContactsRecord},
+      {"addresses", _contacts_contact.address,
+          ImportContactAddressFromContactsRecord},
+      {"messengers", _contacts_contact.messenger,
+          ImportContactInstantMessengerFromContactsRecord},
+      {"relationships", _contacts_contact.relationship,
+          ImportContactRelationshipFromContactsRecord},
+  };
+
+  for (auto& data : imports) {
+    JsonArray& array = out.insert(std::make_pair(data.name,
+        picojson::value(JsonArray()))).first->second.get<JsonArray>();
+
+    int child_rec_count;
+    status = ContactUtil::GetNumberOfChildRecord(
+        contacts_record, data.property_id, &child_rec_count);
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+
+    for (int i = 0; i < child_rec_count; ++i) {
+      JsonValue val{JsonObject{}};
+      data.import_func(contacts_record, static_cast<unsigned int>(i), &val.get<JsonObject>());
+      array.push_back(val);
+    }
+  }
+
+  //### ContactAnniversary: ###
+  JsonArray& anniversaries =
+      out.insert(std::make_pair(std::string("anniversaries"),
+                                picojson::value(JsonArray()))).first->second.get<JsonArray>();
+
+  int child_rec_count;
+  status = ContactUtil::GetNumberOfChildRecord(
+      contacts_record, _contacts_contact.event, &child_rec_count);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  bool is_contact_anniv;
+  for (int i = 0; i < child_rec_count; ++i) {
+    JsonValue anniversary{JsonObject{}};
+
+    PlatformResult status = ImportContactAnniversariesFromContactsRecord(
+        contacts_record, static_cast<unsigned int>(i), &anniversary.get<JsonObject>(), &is_contact_anniv);
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+
+    if (is_contact_anniv) {
+      anniversaries.push_back(anniversary);
+    } else {
+      out.insert(std::make_pair(std::string("birthday"),
+                                picojson::value(anniversaries)));
+    }
+  }
+
+  //### m_notes: ###
+  JsonArray& notes = out.insert(std::make_pair(std::string("notes"),
+      picojson::value(JsonArray()))).first->second.get<JsonArray>();
+
+  status = ContactUtil::GetNumberOfChildRecord(
+      contacts_record, _contacts_contact.note, &child_rec_count);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  for (int i = 0; i < child_rec_count; ++i) {
+    JsonValue val{JsonObject{}};
+
+    status = ImportContactNotesFromContactsRecord(contacts_record, static_cast<unsigned int>(i), &val);
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+
+    notes.push_back(val);
+  }
+
+  //### m_photo_uri ###
+  //### m_ringtone_uri ###
+  {
+    char* value = nullptr;
+
+    status = ContactUtil::GetStrFromRecord(
+        contacts_record, _contacts_contact.image_thumbnail_path, &value);
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+    out.insert(
+        std::make_pair(
+            "photoURI",
+            value ? JsonValue{ConvertPathToUri(value)} : JsonValue{}));
+    value = nullptr;
+
+    status = ContactUtil::GetStrFromRecord(
+        contacts_record, _contacts_contact.ringtone_path, &value);
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+    out.insert(
+        std::make_pair(
+            "ringtoneURI",
+            value ? JsonValue{ConvertPathToUri(value)} : JsonValue{}));
+    value = nullptr;
+
+    status = ContactUtil::GetStrFromRecord(
+        contacts_record, _contacts_contact.message_alert, &value);
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+    out.insert(
+        std::make_pair(
+            "messageAlertURI",
+            value ? JsonValue{ConvertPathToUri(value)} : JsonValue{}));
+    value = nullptr;
+
+    status = ContactUtil::GetStrFromRecord(contacts_record,
+                                           _contacts_contact.vibration, &value);
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+    out.insert(
+        std::make_pair(
+            "vibrationURI",
+            value ? JsonValue{ConvertPathToUri(value)} : JsonValue{}));
+    value = nullptr;
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult ExportContactToContactsRecord(contacts_record_h contacts_record,
+                                             const JsonObject& in) {
+  // contacts_record is protected by unique_ptr and its ownership is not passed
+  // here
+  if (!contacts_record) {
+    LoggerW("Contacts record is null");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Contacts record is null");
+  }
+
+  //### ContactName: ###
+  if (!IsNull(in, "name")) {
+    PlatformResult status = ExportContactNameToContactsRecord(
+        contacts_record, FromJson<JsonObject>(in, "name"));
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+  }
+
+  typedef PlatformResult (*ExportFunc)(contacts_record_h, const JsonObject&);
+  struct ExportDataHelper {
+    unsigned int property_id;
+    const char* name;
+    ExportFunc export_func;
+  };
+  const ExportDataHelper exports[] = {
+      {_contacts_contact.email, "emails",
+          ExportContactEmailAddressToContactsRecord},
+      {_contacts_contact.number, "phoneNumbers",
+          ExportContactPhoneNumberToContactsRecord},
+      {_contacts_contact.company, "organizations",
+          ExportContactOrganizationToContactsRecord},
+      {_contacts_contact.url, "urls", ExportContactWebSiteToContactsRecord},
+      {_contacts_contact.event, "anniversaries",
+          ExportContactAnniversariesToContactsRecord},
+      {_contacts_contact.address, "addresses",
+          ExportContactAddressToContactsRecord},
+      {_contacts_contact.messenger, "messengers",
+          ExportContactInstantMessengerToContactsRecord},
+      {_contacts_contact.relationship, "relationships",
+          ExportContactRelationshipToContactsRecord},
+  };
+
+  for (auto& data : exports) {
+    PlatformResult status =
+        ContactUtil::ClearAllContactRecord(contacts_record, data.property_id);
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+
+    const JsonArray& elements = FromJson<JsonArray>(in, data.name);
+    for (auto& element : elements) {
+      data.export_func(contacts_record, JsonCast<JsonObject>(element));
+    }
+  }
+
+  {
+    //### m_notes: ###
+    PlatformResult status = ContactUtil::ClearAllContactRecord(
+        contacts_record, _contacts_contact.note);
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+
+    const JsonArray& elements = FromJson<JsonArray>(in, "notes");
+    for (auto& element : elements) {
+      auto& str = JsonCast<JsonString>(element);
+      if (str.empty()) {
+        continue;
+      }
+      ExportNotesToContactsRecord(contacts_record, str);
+    }
+  }
+
+  // Contact.photoURI
+  if (IsNull(in, "photoURI")) {
+    contacts_record_h child_record = nullptr;
+    int err = contacts_record_create(_contacts_image._uri, &child_record);
+    PlatformResult status = ContactUtil::ErrorChecker(
+        err, "Fail to create image uri record in database.");
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+
+    ContactsRecordHPtr record(&child_record, ContactsDeleter);
+    err = contacts_record_add_child_record(
+        contacts_record, _contacts_contact.image, child_record);
+    status = ContactUtil::ErrorChecker(err, "Fail to add child to image uri.");
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+
+    // Do not delete record, it is passed to the platform
+    record.release();
+  } else {
+    bool is_first = false;
+    contacts_record_h child_record = nullptr;
+    int err = contacts_record_get_child_record_at_p(
+        contacts_record, _contacts_contact.image, 0, &child_record);
+    if (CONTACTS_ERROR_NONE != err || nullptr == child_record) {
+      err = contacts_record_create(_contacts_image._uri, &child_record);
+      PlatformResult status = ContactUtil::ErrorChecker(
+          err, "Fail to create image uri record in database.");
+      if (status.IsError()) {
+        LoggerE("Error: %s", status.message().c_str());
+        return status;
+      }
+
+      is_first = true;
+    }
+    ContactsRecordHPtr record(&child_record, ContactsDeleter);
+    // TODO this was never used anywhere in the old module. Can this be removed?
+    // char *old_value_str = nullptr;
+    // ContactUtil::getStrFromRecord(child_record, _contacts_image.path,
+    // &old_value_str);
+
+    std::string real_path;
+    if (!IsNull(in, "photoURI")) {
+      real_path =
+          ContactUtil::ConvertUriToPath(FromJson<JsonString>(in, "photoURI"));
+      PlatformResult status = ContactUtil::SetStrInRecord(
+          child_record, _contacts_image.path, real_path.c_str());
+      if (status.IsError()) {
+        LoggerE("Error: %s", status.message().c_str());
+        return status;
+      }
+    }
+
+    if (is_first) {
+      err = contacts_record_add_child_record(
+          contacts_record, _contacts_contact.image, child_record);
+      PlatformResult status =
+          ContactUtil::ErrorChecker(err, "Fail to add child to image uri.");
+      if (status.IsError()) {
+        LoggerE("Error: %s", status.message().c_str());
+        return status;
+      }
+    }
+    // Do not delete record, it is passed to the platform
+    record.release();
+  }
+
+  std::string real_path;
+  // Contact.ringtoneURI
+  if (!IsNull(in, "ringtoneURI")) {
+    real_path =
+        ContactUtil::ConvertUriToPath(FromJson<JsonString>(in, "ringtoneURI"));
+    PlatformResult status = VerifyLocalPath(real_path);
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+    status = ContactUtil::SetStrInRecord(
+        contacts_record, _contacts_contact.ringtone_path, real_path.c_str());
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+  }
+  // Contact.messageAlertURI
+  if (!IsNull(in, "messageAlertURI")) {
+    real_path = ContactUtil::ConvertUriToPath(
+        FromJson<JsonString>(in, "messageAlertURI"));
+    PlatformResult status = ContactUtil::SetStrInRecord(
+        contacts_record, _contacts_contact.message_alert, real_path.c_str());
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+  }
+
+  // Contact.vibrationURI
+  if (!IsNull(in, "vibrationURI")) {
+    real_path =
+        ContactUtil::ConvertUriToPath(FromJson<JsonString>(in, "vibrationURI"));
+    PlatformResult status = ContactUtil::SetStrInRecord(
+        contacts_record, _contacts_contact.vibration, real_path.c_str());
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult ImportContactGroupFromContactsRecord(
+    contacts_record_h contacts_record, JsonObject* out_ptr) {
+  JsonObject& out = *out_ptr;
+  // contacts_record is protected by unique_ptr and its ownership is not passed
+  // here
+  if (!contacts_record) {
+    LoggerE("Contacts record is null");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Contacts record is null");
+  }
+
+  // id
+  int int_val = 0;
+  PlatformResult status = ContactUtil::GetIntFromRecord(
+      contacts_record, _contacts_group.id, &int_val);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  out.insert(std::make_pair("id", JsonValue{std::to_string(int_val)}));
+
+  // addressBookId
+  status = ContactUtil::GetIntFromRecord(
+      contacts_record, _contacts_group.address_book_id, &int_val);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  out.insert(
+      std::make_pair("addressBookId", JsonValue{std::to_string(int_val)}));
+
+  // name
+  char* value = nullptr;
+  status = ContactUtil::GetStrFromRecord(contacts_record, _contacts_group.name,
+                                         &value);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  out.insert(std::make_pair("name", value ? JsonValue{value} : JsonValue{}));
+
+  // photoURI
+  value = nullptr;
+  status = ContactUtil::GetStrFromRecord(contacts_record,
+                                         _contacts_group.image_path, &value);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  out.insert(
+      std::make_pair(
+          "photoURI",
+          value ? JsonValue{ConvertPathToUri(value)} : JsonValue{}));
+
+  // ringtoneURI
+  value = nullptr;
+  status = ContactUtil::GetStrFromRecord(contacts_record,
+                                         _contacts_group.ringtone_path, &value);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  out.insert(
+      std::make_pair(
+          "ringtoneURI",
+          value ? JsonValue{ConvertPathToUri(value)} : JsonValue{}));
+
+  // is_read_only
+  bool bool_value = false;
+  status = ContactUtil::GetBoolFromRecord(
+      contacts_record, _contacts_group.is_read_only, &bool_value);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  out.insert(std::make_pair("readOnly", JsonValue{bool_value}));
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult ExportContactGroupToContactsRecord(
+    contacts_record_h contacts_record, const JsonObject& in) {
+  // name
+  PlatformResult status =
+      ContactUtil::SetStrInRecord(contacts_record, _contacts_group.name,
+                                  FromJson<JsonString>(in, "name").c_str());
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  std::string real_path;
+  // photoURI
+  if (!IsNull(in, "photoURI")) {
+    real_path = ConvertUriToPath(FromJson<JsonString>(in, "photoURI"));
+    PlatformResult status = ContactUtil::SetStrInRecord(
+        contacts_record, _contacts_group.image_path, real_path.c_str());
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+  }
+  // ringtoneURI
+  if (!IsNull(in, "ringtoneURI")) {
+    real_path =
+        ContactUtil::ConvertUriToPath(FromJson<JsonString>(in, "ringtoneURI"));
+    // NOTE in the original code real path was not read
+    PlatformResult status = ContactUtil::SetStrInRecord(
+        contacts_record, _contacts_group.ringtone_path, real_path.c_str());
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+/**
+ * @brief   Fills Person object with values from record
+ * @param[in]   contacts_record_h  Record which is used to fill Person
+ */
+PlatformResult ImportPersonFromContactsRecord(contacts_record_h record,
+                                              JsonObject* out_ptr) {
+  if (nullptr == record) {
+    LoggerW("Platform person record did not set");
+    return PlatformResult(ErrorCode::INVALID_VALUES_ERR,
+                          "Platform person record did not set");
+  }
+
+  JsonObject& arguments_obj = *out_ptr;
+
+  int int_value = 0;
+  // id
+  PlatformResult status =
+      ContactUtil::GetIntFromRecord(record, _contacts_person.id, &int_value);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  arguments_obj.insert(
+      std::make_pair("id", JsonValue(std::to_string(int_value))));
+
+  char* char_value = nullptr;
+  // displayName
+  status = ContactUtil::GetStrFromRecord(record, _contacts_person.display_name,
+                                         &char_value);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  arguments_obj.insert(std::make_pair(
+      "displayName", char_value ? JsonValue(char_value) : JsonValue{}));
+
+  // contactCount
+  status = ContactUtil::GetIntFromRecord(record, _contacts_person.link_count,
+                                         &int_value);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  arguments_obj.insert(std::make_pair(
+      "contactCount", JsonValue(static_cast<double>(int_value))));
+
+  bool bool_value = false;
+  // hasPhoneNumber
+  status = ContactUtil::GetBoolFromRecord(
+      record, _contacts_person.has_phonenumber, &bool_value);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  arguments_obj.insert(std::make_pair("hasPhoneNumber", JsonValue(bool_value)));
+
+  // hasEmail
+  status = ContactUtil::GetBoolFromRecord(record, _contacts_person.has_email,
+                                          &bool_value);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  arguments_obj.insert(std::make_pair("hasEmail", JsonValue(bool_value)));
+
+  // isFavorite
+  status = ContactUtil::GetBoolFromRecord(record, _contacts_person.is_favorite,
+                                          &bool_value);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  arguments_obj.insert(std::make_pair("isFavorite", JsonValue(bool_value)));
+
+  // photoURI
+  status = ContactUtil::GetStrFromRecord(
+      record, _contacts_person.image_thumbnail_path, &char_value);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  arguments_obj.insert(
+      std::make_pair(
+          "photoURI",
+          char_value ? JsonValue(ConvertPathToUri(char_value)) : JsonValue{}));
+
+  // ringtoneURI
+  status = ContactUtil::GetStrFromRecord(record, _contacts_person.ringtone_path,
+                                         &char_value);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  arguments_obj.insert(
+      std::make_pair(
+          "ringtoneURI",
+          char_value ? JsonValue(ConvertPathToUri(char_value)) : JsonValue{}));
+
+  // displayContactId
+  status = ContactUtil::GetIntFromRecord(
+      record, _contacts_person.display_contact_id, &int_value);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  arguments_obj.insert(
+      std::make_pair("displayContactId",
+                     picojson::value(std::to_string(int_value))));
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+/**
+ * @brief   Updates contacts_record_h with values from Person object
+ * @param[out]   contacts_record_h  Record which is updated
+ */
+PlatformResult ExportPersonToContactsRecord(contacts_record_h record,
+                                            const JsonObject& args) {
+  if (nullptr == record) {
+    LoggerE("Platform person object did not set");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Platform person object did not set");
+  }
+
+  PlatformResult status = ContactUtil::SetBoolInRecord(
+      record, _contacts_person.is_favorite, FromJson<bool>(args, "isFavorite"));
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  if (!IsNull(args, "photoURI") &&
+      !FromJson<JsonString>(args, "photoURI").empty()) {
+    PlatformResult status = ContactUtil::SetStrInRecord(
+        record, _contacts_person.image_thumbnail_path,
+        ConvertUriToPath(FromJson<JsonString>(args, "photoURI")).c_str());
+    if (status.IsError()) {
+      LoggerE("Try updating read only attribute photoURI");
+      return status;
+    }
+  } else {
+    // TO DO: fix when photoURI attribute changed from read only to write mode
+  }
+
+  if (!IsNull(args, "ringtoneURI")) {
+    PlatformResult status = ContactUtil::SetStrInRecord(
+        record, _contacts_person.ringtone_path,
+        ConvertUriToPath(FromJson<JsonString>(args, "ringtoneURI")).c_str());
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+  } else {
+    PlatformResult status =
+        ContactUtil::SetStrInRecord(record, _contacts_person.ringtone_path, "");
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+  }
+  if (!IsNull(args, "displayContactId")) {
+    PlatformResult status = ContactUtil::SetIntInRecord(
+        record, _contacts_person.display_contact_id,
+        common::stol(FromJson<JsonString>(args, "displayContactId")));
+    if (status.IsError()) {
+      LoggerE("Error: %s", status.message().c_str());
+      return status;
+    }
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult UpdateAdditionalInformation(
+    const ContactsRecordHPtr& contacts_record_ptr, JsonObject* out_ptr) {
+  JsonObject& out = *out_ptr;
+  int int_value = -1;
+  PlatformResult status = ContactUtil::GetIntFromRecord(
+      *contacts_record_ptr, _contacts_contact.person_id, &int_value);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  out.insert(std::make_pair("personId", JsonValue{std::to_string(int_value)}));
+  status = ContactUtil::GetIntFromRecord(
+      *contacts_record_ptr, _contacts_contact.address_book_id, &int_value);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  out.insert(
+      std::make_pair("addressBookId", JsonValue{std::to_string(int_value)}));
+  status = ContactUtil::GetIntFromRecord(
+      *contacts_record_ptr, _contacts_contact.changed_time, &int_value);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  out.insert(
+      std::make_pair("lastUpdated", JsonValue{static_cast<double>(int_value)}));
+  bool bool_value = false;
+  status = ContactUtil::GetBoolFromRecord(
+      *contacts_record_ptr, _contacts_contact.is_favorite, &bool_value);
+  if (status.IsError()) {
+    LoggerE("Error: %s", status.message().c_str());
+    return status;
+  }
+
+  out.insert(std::make_pair("isFavorite", JsonValue{bool_value}));
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult CheckDBConnection() {
+  static bool _connected = false;
+  if (_connected) return PlatformResult(ErrorCode::NO_ERROR);
+
+  int err = contacts_connect();
+  if (CONTACTS_ERROR_NONE == err) {
+    LoggerI("Connection established!");
+    _connected = true;
+  } else {
+    LoggerE("DB connection error occured: %s", std::to_string(err).c_str());
+    return PlatformResult(
+        ErrorCode::UNKNOWN_ERR,
+        "DB connection error occured: " + std::to_string(err));
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+}  // ContactUtil
+}  // contact
+}  // extension
diff --git a/webWidgetTCT_device/src/contact/contact_util.h b/webWidgetTCT_device/src/contact/contact_util.h
new file mode 100755 (executable)
index 0000000..2652d1a
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2015 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 CONTACT_CONTACT_UTIL_H_
+#define CONTACT_CONTACT_UTIL_H_
+
+#include <ctime>
+#include <memory>
+#include <string>
+#include <contacts.h>
+#include "common/picojson.h"
+#include "common/platform_exception.h"
+#include "common/platform_result.h"
+
+namespace extension {
+namespace contact {
+
+typedef picojson::value JsonValue;
+typedef picojson::object JsonObject;
+typedef picojson::array JsonArray;
+typedef std::string JsonString;
+
+namespace ContactUtil {
+
+void ContactsDeleter(contacts_record_h *contacts_record);
+typedef std::unique_ptr<contacts_record_h, void (*)(contacts_record_h *)>
+    ContactsRecordHPtr;
+
+void ContactsListDeleter(contacts_list_h *contacts_list);
+typedef std::unique_ptr<contacts_list_h, void (*)(contacts_list_h *)>
+    ContactsListHPtr;
+
+void ContactsFilterDeleter(contacts_filter_h contacts_filter);
+typedef std::unique_ptr<std::remove_pointer<contacts_filter_h>::type,
+                        void (*)(contacts_filter_h)> ContactsFilterPtr;
+
+void ContactsQueryDeleter(contacts_query_h *contacts_query);
+typedef std::unique_ptr<contacts_query_h, void (*)(contacts_query_h *)>
+    ContactsQueryHPtr;
+
+common::PlatformResult ErrorChecker(int err, const char *message);
+
+common::PlatformResult GetStrFromRecord(contacts_record_h record,
+                                        unsigned int property_id, char **value);
+
+common::PlatformResult GetIntFromRecord(contacts_record_h record,
+                                        unsigned int property_id, int *value);
+
+common::PlatformResult GetBoolFromRecord(contacts_record_h record,
+                                         unsigned int property_id, bool *value);
+
+common::PlatformResult SetStrInRecord(contacts_record_h record,
+                                      unsigned int property_id,
+                                      const char *value);
+
+common::PlatformResult SetIntInRecord(contacts_record_h record,
+                                      unsigned int property_id, int value);
+
+common::PlatformResult SetBoolInRecord(contacts_record_h record,
+                                       unsigned int property_id, bool value);
+
+common::PlatformResult ClearAllContactRecord(contacts_record_h contacts_record,
+                                             unsigned int property_id);
+
+common::PlatformResult GetNumberOfChildRecord(contacts_record_h contacts_record,
+                                              unsigned int property_id,
+                                              int *child_count);
+
+common::PlatformResult UpdateAdditionalInformation(
+    const ContactsRecordHPtr &contacts_record_ptr, JsonObject *out);
+
+common::PlatformResult ImportContactNameFromContactsRecord(
+    contacts_record_h contacts_record, JsonObject *out, bool *is_contact_name);
+common::PlatformResult ExportContactNameToContactsRecord(
+    contacts_record_h contacts_record, const JsonObject &in);
+common::PlatformResult ImportContactEmailAddressFromContactsRecord(
+    contacts_record_h contacts_record, unsigned int index, JsonObject *out);
+common::PlatformResult ExportContactEmailAddressToContactsRecord(
+    contacts_record_h contacts_record, const JsonObject &in);
+
+common::PlatformResult ImportContactAddressFromContactsRecord(
+    contacts_record_h contacts_record, unsigned int index, JsonObject *out);
+common::PlatformResult ExportContactAddressToContactsRecord(
+    contacts_record_h contacts_record, const JsonObject &in);
+common::PlatformResult ImportContactPhoneNumberFromContactsRecord(
+    contacts_record_h contacts_record, unsigned int index, JsonObject *out);
+common::PlatformResult ExportContactPhoneNumberToContactsRecord(
+    contacts_record_h contacts_record, const JsonObject &in);
+common::PlatformResult ImportContactOrganizationFromContactsRecord(
+    contacts_record_h contacts_record, unsigned int index, JsonObject *out);
+common::PlatformResult ExportContactOrganizationToContactsRecord(
+    contacts_record_h contacts_record, const JsonObject &in);
+common::PlatformResult ImportContactWebSiteFromContactsRecord(
+    contacts_record_h contacts_record, unsigned int index, JsonObject *out);
+common::PlatformResult ExportContactWebSiteToContactsRecord(
+    contacts_record_h contacts_record, const JsonObject &in);
+common::PlatformResult ImportContactAnniversariesFromContactsRecord(
+    contacts_record_h contacts_record, unsigned int index, JsonObject *out,
+    bool *ret);
+common::PlatformResult ExportContactAnniversariesToContactsRecord(
+    contacts_record_h contacts_record, const JsonObject &in);
+common::PlatformResult ImportContactRelationshipFromContactsRecord(
+    contacts_record_h contacts_record, unsigned int index, JsonObject *out);
+common::PlatformResult ExportContactRelationshipToContactsRecord(
+    contacts_record_h contacts_record, const JsonObject &in);
+common::PlatformResult ImportContactInstantMessengerFromContactsRecord(
+    contacts_record_h contacts_record, unsigned int index, JsonObject *out);
+common::PlatformResult ExportContactInstantMessengerToContactsRecord(
+    contacts_record_h contacts_record, const JsonObject &in);
+
+common::PlatformResult ImportContactNotesFromContactsRecord(
+    contacts_record_h contacts_record, unsigned int index, JsonValue *val);
+common::PlatformResult ExportNotesToContactsRecord(
+    contacts_record_h contacts_record, const std::string &value);
+common::PlatformResult ImportContactFromContactsRecord(
+    contacts_record_h contacts_record, JsonObject *out);
+common::PlatformResult ExportPersonToContactsRecord(contacts_record_h record,
+                                                    const JsonObject &args);
+
+common::PlatformResult ExportContactToContactsRecord(
+    contacts_record_h contacts_record, const JsonObject &in);
+common::PlatformResult ImportContactGroupFromContactsRecord(
+    contacts_record_h contacts_record, JsonObject *out);
+common::PlatformResult ExportContactGroupToContactsRecord(
+    contacts_record_h contacts_record, const JsonObject &in);
+common::PlatformResult ImportPersonFromContactsRecord(
+    contacts_record_h contacts_record, JsonObject *out);
+
+common::PlatformResult CheckDBConnection();
+
+}  // ContactUtil
+}  // contact
+}  // extension
+
+#endif  // CONTACT_CONTACT_UTIL_H_
diff --git a/webWidgetTCT_device/src/contact/js/address_book.js b/webWidgetTCT_device/src/contact/js/address_book.js
new file mode 100755 (executable)
index 0000000..52de121
--- /dev/null
@@ -0,0 +1,731 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+var DEFAULT_ADDRESSBOOK_ID = '0';
+var UNIFIED_ADDRESSBOOK_ID = '-1';
+
+var _contactListenerRegistered = false;
+var _contactCallbackMap = {};
+
+var _filterById = function(array, id) {
+  var ret = [];
+  for (var i = 0; i < array.length; ++i) {
+    if (array[i].addressBookId === id) {
+      ret.push(_promote(array[i], Contact));
+    }
+  }
+  return ret;
+};
+
+var _contactChangeListener = function(result) {
+  var unifiedId = UNIFIED_ADDRESSBOOK_ID;
+  var watchId;
+  var callback, i;
+
+  // Unified address book case
+  if (_contactCallbackMap.hasOwnProperty(unifiedId)) {
+    for (watchId in _contactCallbackMap[unifiedId]) {
+      if (_contactCallbackMap[unifiedId].hasOwnProperty(watchId)) {
+        callback = _contactCallbackMap[unifiedId][watchId].successCallback;
+        if (result.added.length) {
+          native_.callIfPossible(callback.oncontactsadded, _promote(result.added, Contact));
+        }
+        if (result.updated.length) {
+          native_.callIfPossible(callback.oncontactsupdated, _promote(result.updated, Contact));
+        }
+        if (result.removed.length) {
+          var allRemoved = [];
+          for (i = 0; i < result.removed.length; ++i) {
+            allRemoved.push(result.removed[i].id);
+          }
+          native_.callIfPossible(callback.oncontactsremoved, result.allRemoved);
+        }
+      }
+    }
+  }
+
+  for (var callbackAddressbookId in _contactCallbackMap) {
+    if (callbackAddressbookId !== UNIFIED_ADDRESSBOOK_ID &&
+        _contactCallbackMap.hasOwnProperty(callbackAddressbookId)) {
+
+      var filteredAdded = [];
+      var filteredUpdated = [];
+      var filteredRemoved = [];
+
+      if (result.added.length) {
+        filteredAdded = _filterById(result.added, callbackAddressbookId);
+      }
+      if (result.updated.length) {
+        filteredUpdated = _filterById(result.updated, callbackAddressbookId);
+      }
+      if (result.removed.length) {
+        for (i = 0; i < result.removed.length; ++i) {
+          if (result.removed[i].addressBookId === callbackAddressbookId) {
+            filteredRemoved.push(result.removed[i].id);
+          }
+        }
+      }
+
+      for (watchId in _contactCallbackMap[callbackAddressbookId]) {
+        if (_contactCallbackMap[callbackAddressbookId].hasOwnProperty(watchId)) {
+          callback = _contactCallbackMap[callbackAddressbookId][watchId].successCallback;
+          if (filteredAdded.length) {
+            native_.callIfPossible(callback.oncontactsadded, filteredAdded);
+          }
+          if (filteredUpdated.length) {
+            native_.callIfPossible(callback.oncontactsupdated, filteredUpdated);
+          }
+          if (filteredRemoved.length) {
+            native_.callIfPossible(callback.oncontactsremoved, filteredRemoved);
+          }
+        }
+      }
+    }
+  }
+};
+
+
+var AddressBook = function(accountId, name) {
+  validator_.isConstructorCall(this, AddressBook);
+
+  var id_ = null;
+  var name_ = '';
+  var readOnly_ = false;
+  var accountId_ = null;
+
+  if (type_.isNumber(accountId)) {
+    accountId_ = accountId;
+  }
+  if (type_.isString(name)) {
+    name_ = name;
+  }
+
+  Object.defineProperties(this, {
+    id: {
+      get: function() {
+        return id_;
+      },
+      set: function(v) {
+        if (_editGuard.isEditEnabled()) {
+          id_ = converter_.toString(v, false);
+        }
+      },
+      enumerable: true
+    },
+    accountId: {
+      get: function() {
+        return accountId_;
+      },
+      set: function(v) {
+        if (_editGuard.isEditEnabled()) {
+          accountId_ = converter_.toLong(v, true);
+        }
+      },
+      enumerable: true
+    },
+    name: {
+      get: function() {
+        return name_;
+      },
+      set: function(v) {
+        if (_editGuard.isEditEnabled()) {
+          name_ = converter_.toString(v, false);
+        }
+      },
+      enumerable: true
+    },
+    readOnly: {
+      get: function() {
+        return readOnly_;
+      },
+      set: function(v) {
+        if (_editGuard.isEditEnabled()) {
+          readOnly_ = converter_.toBoolean(v, false);
+        }
+      },
+      enumerable: true
+    }
+  });
+};
+
+AddressBook.prototype.get = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.CONTACT_READ);
+
+  var args = validator_.validateArgs(arguments, [{
+    name: 'id',
+    type: types_.STRING,
+    optional: false,
+    nullable: false
+  }]);
+
+  if (String(converter_.toLong(args.id)) !== args.id) {
+    // TCT: AddressBook_get_id_invalid
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR);
+  }
+
+  var result = native_.callSync('AddressBook_get', {
+    // TODO move to only sending the address book id (in all functions)
+    addressBook: this,
+    id: args.id
+  });
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+
+  return _editGuard.run(function() {
+    var contact = new Contact(native_.getResultObject(result));
+
+    if (contact.name instanceof ContactName) {
+      contact.name.displayName = '';
+      if (type_.isString(contact.name.firstName)) {
+        contact.name.displayName = contact.name.firstName;
+        if (type_.isString(contact.name.lastName)) {
+          contact.name.displayName += ' ' + contact.name.lastName;
+        }
+      } else if (type_.isArray(contact.name.nicknames) &&
+          type_.isString(contact.name.nicknames[0])) {
+        contact.name.displayName = contact.name.nicknames[0];
+      } else if (type_.isString(contact.name.nicknames)) {
+        contact.name.displayName = contact.name.nicknames;
+      }
+    }
+
+
+
+    return contact;
+  });
+};
+
+AddressBook.prototype.add = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.CONTACT_WRITE);
+
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'contact',
+      type: types_.PLATFORM_OBJECT,
+      values: Contact,
+      optional: false,
+      nullable: false
+    }
+  ]);
+
+  var result = native_.callSync('AddressBook_add', {
+    // TODO move to only sending the address book id (in all functions)
+    addressBook: this,
+    contact: _toJsonObject(args.contact)
+  });
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+
+  var _updatedContact = native_.getResultObject(result);
+  _editGuard.run(function() {
+    for (var prop in _updatedContact) {
+      if (args.contact.hasOwnProperty(prop)) {
+        args.contact[prop] = _updatedContact[prop];
+      }
+    }
+
+    if (args.contact.name instanceof ContactName) {
+      args.contact.name.displayName = '';
+      if (type_.isString(args.contact.name.firstName)) {
+        args.contact.name.displayName = args.contact.name.firstName;
+        if (type_.isString(args.contact.name.lastName)) {
+          args.contact.name.displayName += ' ' + args.contact.name.lastName;
+        }
+      } else if (type_.isArray(args.contact.name.nicknames) &&
+          type_.isString(args.contact.name.nicknames[0])) {
+        args.contact.name.displayName = args.contact.name.nicknames[0];
+      } else if (type_.isString(args.contact.name.nicknames)) {
+        args.contact.name.displayName = args.contact.name.nicknames;
+      }
+    }
+  });
+};
+
+AddressBook.prototype.addBatch = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.CONTACT_WRITE);
+
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'contacts',
+      type: types_.ARRAY,
+      value: Contact,
+      optional: false,
+      nullable: false
+    },
+    {
+      name: 'successCallback',
+      type: types_.FUNCTION,
+      optional: true,
+      nullable: true
+    },
+    {
+      name: 'errorCallback',
+      type: types_.FUNCTION,
+      optional: true,
+      nullable: true
+    }
+
+  ]);
+
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+      return;
+    }
+
+    _editGuard.run(function() {
+      var _result = native_.getResultObject(result);
+      for (var i = 0; i < _result.length; ++i) {
+        for (var prop in _result[i]) {
+          if (args.contacts[i].hasOwnProperty(prop)) {
+            args.contacts[i][prop] = _result[i][prop];
+          }
+        }
+      }
+    });
+
+    native_.callIfPossible(args.successCallback, args.contacts);
+  };
+
+  native_.call('AddressBook_addBatch', {
+    addressBookId: this.id,
+    batchArgs: _toJsonObject(args.contacts)
+  }, callback);
+};
+
+AddressBook.prototype.update = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.CONTACT_WRITE);
+
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'contact',
+      type: types_.PLATFORM_OBJECT,
+      values: Contact,
+      optional: false,
+      nullable: false
+    }
+  ]);
+
+  var result = native_.callSync('AddressBook_update', {
+    addressBook: this,
+    contact: _toJsonObject(args.contact)
+  });
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+
+  var _updatedContact = native_.getResultObject(result);
+  _editGuard.run(function() {
+    for (var prop in _updatedContact) {
+      if (args.contact.hasOwnProperty(prop)) {
+        args.contact[prop] = _updatedContact[prop];
+      }
+    }
+  });
+};
+
+AddressBook.prototype.updateBatch = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.CONTACT_WRITE);
+
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'contacts',
+      type: types_.ARRAY,
+      values: Contact,
+      optional: false,
+      nullable: false
+    },
+    {
+      name: 'successCallback',
+      type: types_.FUNCTION,
+      optional: true,
+      nullable: true
+    },
+    {
+      name: 'errorCallback',
+      type: types_.FUNCTION,
+      optional: true,
+      nullable: true
+    }
+  ]);
+
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+      return;
+    }
+
+    _editGuard.run(function() {
+      var _result = native_.getResultObject(result);
+      for (var i = 0; i < _result.length; ++i) {
+        for (var prop in _result[i].result) {
+          if (args.contacts[i].hasOwnProperty(prop)) {
+            args.contacts[i][prop] = _result[i].result[prop];
+          }
+        }
+      }
+    });
+
+    native_.callIfPossible(args.successCallback);
+  };
+
+  native_.call('AddressBook_updateBatch', {
+    addressBook: this,
+    batchArgs: _toJsonObject(args.contacts)
+  }, callback);
+};
+
+AddressBook.prototype.remove = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.CONTACT_WRITE);
+
+  var args = validator_.validateArgs(arguments, [{
+    name: 'id',
+    type: types_.STRING,
+    optional: false,
+    nullable: false
+  }]);
+
+  if (String(converter_.toLong(args.id)) !== args.id) {
+    // TCT: AddressBook_remove_id_invalid
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR);
+  }
+
+  var result = native_.callSync('AddressBook_remove', {
+    addressBook: this,
+    id: args.id
+  });
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+};
+
+AddressBook.prototype.removeBatch = function(ids, successCallback, errorCallback) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.CONTACT_WRITE);
+
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'ids',
+      type: types_.ARRAY,
+      values: types_.STRING,
+      optional: false,
+      nullable: false
+    },
+    {
+      name: 'successCallback',
+      type: types_.FUNCTION,
+      optional: true,
+      nullable: true
+    },
+    {
+      name: 'errorCallback',
+      type: types_.FUNCTION,
+      optional: true,
+      nullable: true
+    }
+  ]);
+
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+      return;
+    }
+
+    native_.callIfPossible(args.successCallback);
+  };
+
+  native_.call('AddressBook_removeBatch', {
+    addressBook: this,
+    batchArgs: args.ids
+  }, callback);
+};
+
+AddressBook.prototype.find = function(successCallback, errorCallback, filter, sortMode) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.CONTACT_READ);
+
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'successCallback',
+      type: types_.FUNCTION,
+      optional: false,
+      nullable: false
+    },
+    {
+      name: 'errorCallback',
+      type: types_.FUNCTION,
+      optional: true,
+      nullable: true
+    },
+    {
+      name: 'filter',
+      type: types_.PLATFORM_OBJECT,
+      values: [
+        tizen.AttributeFilter,
+        tizen.AttributeRangeFilter,
+        tizen.CompositeFilter
+      ],
+      optional: true,
+      nullable: true
+    },
+    {
+      name: 'sortMode',
+      type: types_.PLATFORM_OBJECT,
+      values: tizen.SortMode,
+      optional: true,
+      nullable: true
+    }
+  ]);
+
+  var self = this;
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(errorCallback, native_.getErrorObject(result));
+      return;
+    }
+
+    var _contacts = [];
+    var _result = native_.getResultObject(result);
+    _result.forEach(function(data) {
+      try {
+        _contacts.push(self.get(String(data)));
+      } catch (e) {}
+    });
+
+    //TODO: Move filtering to native code
+    try {
+      _contacts = C.filter(_contacts, args.filter);
+    } catch (e) {
+      native_.callIfPossible(errorCallback, e);
+      return;
+    }
+
+    //TODO: Move sorting to native code
+    _contacts = C.sort(_contacts, args.sortMode);
+
+    native_.callIfPossible(successCallback, _contacts);
+  };
+
+  native_.call('AddressBook_find', {
+    addressBook: this,
+    filter: filter,
+    sortMode: sortMode
+  }, callback);
+};
+
+AddressBook.prototype.addChangeListener = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.CONTACT_READ);
+
+  var args = validator_.validateArgs(arguments, [{
+    name: 'successCallback',
+    type: types_.LISTENER,
+    values: ['oncontactsadded', 'oncontactsupdated', 'oncontactsremoved'],
+    optional: false,
+    nullable: false
+  }, {
+    name: 'errorCallback',
+    type: types_.FUNCTION,
+    optional: true,
+    nullable: true
+  }]);
+
+  if (type_.isEmptyObject(_contactCallbackMap)) {
+    var result = native_.callSync('AddressBook_startListening', {});
+
+    if (native_.isFailure(result)) {
+      throw native_.getErrorObject(result);
+    }
+  }
+
+  if (!_contactListenerRegistered) {
+    native_.addListener('ContactChangeListener', _contactChangeListener);
+    _contactListenerRegistered = true;
+  }
+
+  if (!_contactCallbackMap.hasOwnProperty(this.id)) {
+    _contactCallbackMap[this.id] = {};
+  }
+
+  var currentWatchId = _getNextWatchId();
+
+  _contactCallbackMap[this.id][currentWatchId] = {
+    successCallback: args.successCallback,
+    errorCallback: args.errorCallback
+  };
+
+  return currentWatchId;
+};
+
+AddressBook.prototype.removeChangeListener = function(watchId) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.CONTACT_READ);
+
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'watchId',
+      type: types_.LONG,
+      optional: false,
+      nullable: false
+    }
+  ]);
+
+  if (args.watchId <= 0) {
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+        'Wrong watch id');
+  }
+
+  if (!_contactCallbackMap.hasOwnProperty(this.id) ||
+      !_contactCallbackMap[this.id].hasOwnProperty(args.watchId)) {
+    throw new WebAPIException(WebAPIException.NOT_FOUND_ERR,
+        'watch id not found for this address book');
+  }
+
+  delete _contactCallbackMap[this.id][args.watchId];
+
+  if (type_.isEmptyObject(_contactCallbackMap[this.id])) {
+    delete _contactCallbackMap[this.id];
+  }
+
+  if (type_.isEmptyObject(_contactCallbackMap)) {
+    native_.removeListener('ContactChangeListener', _contactChangeListener);
+    _contactListenerRegistered = false;
+
+    var result = native_.callSync('AddressBook_stopListening', {});
+
+    if (native_.isFailure(result)) {
+      throw native_.getErrorObject(result);
+    }
+  }
+};
+
+AddressBook.prototype.getGroup = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.CONTACT_READ);
+
+  var args = validator_.validateArgs(arguments, [{
+    name: 'groupId',
+    type: types_.STRING,
+    optional: false,
+    nullable: false
+  }]);
+
+  if (String(converter_.toLong(args.groupId)) !== args.groupId) {
+    // TCT: AddressBook_getGroup_groupId_invalid
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR);
+  }
+
+  var result = native_.callSync('AddressBook_getGroup', {
+    addressBook: this,
+    id: args.groupId
+  });
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+
+  return _editGuard.run(function() {
+    return new ContactGroup(native_.getResultObject(result));
+  });
+};
+
+AddressBook.prototype.addGroup = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.CONTACT_WRITE);
+
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'group',
+      type: types_.PLATFORM_OBJECT,
+      values: ContactGroup,
+      optional: false,
+      nullable: false
+    }
+  ]);
+
+  var result = native_.callSync('AddressBook_addGroup',
+      {addressBookId: this.id, group: args.group});
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+
+  _editGuard.run(function() {
+    result = native_.getResultObject(result);
+    args.group.id = result.id;
+    args.group.addressBookId = result.addressBookId;
+  });
+};
+
+AddressBook.prototype.updateGroup = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.CONTACT_WRITE);
+
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'group',
+      type: types_.PLATFORM_OBJECT,
+      values: ContactGroup,
+      optional: false,
+      nullable: false
+    }
+  ]);
+
+  var result = native_.callSync('AddressBook_updateGroup',
+      {addressBookId: this.id, group: args.group});
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+};
+
+AddressBook.prototype.removeGroup = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.CONTACT_WRITE);
+
+  var args = validator_.validateArgs(arguments, [{
+    name: 'groupId',
+    type: types_.STRING,
+    optional: false,
+    nullable: false
+  }]);
+
+  if (String(converter_.toLong(args.groupId)) !== args.groupId) {
+    // TCT: AddressBook_removeGroup_groupId_invalid
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR);
+  }
+
+  var result = native_.callSync('AddressBook_removeGroup',
+      {addressBook: this, id: args.groupId});
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+};
+
+AddressBook.prototype.getGroups = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.CONTACT_READ);
+
+  var result = native_.callSync('AddressBook_getGroups', {addressBook: this});
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+  result = native_.getResultObject(result);
+  var _tab = [];
+  _editGuard.run(function() {
+    result.forEach(function(data) {
+      _tab.push(new ContactGroup(data));
+    });
+  });
+  return _tab;
+};
+
+// exports /////////////////////////////////////////////////////////////////
+tizen.AddressBook = AddressBook;
diff --git a/webWidgetTCT_device/src/contact/js/common.js b/webWidgetTCT_device/src/contact/js/common.js
new file mode 100755 (executable)
index 0000000..5f25a91
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+var _global = window || global || {};
+var utils_ = xwalk.utils;
+var type_ = utils_.type;
+var converter_ = utils_.converter;
+var validator_ = utils_.validator;
+var types_ = validator_.Types;
+var native_ = new xwalk.utils.NativeManager(extension);
+
+var _currentWatchId = 1;
+
+var _getNextWatchId = function() {
+  return _currentWatchId++;
+};
+
+// Adjusts properties to have the correct format expected by the native side.
+// Currently only translates JS Date
+var _toJsonObject = function(obj) {
+  var ret;
+  if (type_.isDate(obj)) {
+    var year = ('0000' + obj.getFullYear()).slice(-4);
+    var month = ('00' + (obj.getMonth() + 1)).slice(-2);
+    var day = ('00' + obj.getDate()).slice(-2);
+    return Number(year + month + day);
+  }
+  if (type_.isArray(obj)) {
+    ret = [];
+    for (var i = 0; i < obj.length; ++i) {
+      ret[i] = _toJsonObject(obj[i]);
+    }
+    return ret;
+  }
+  if (obj instanceof _global.Object) {
+    ret = {};
+    for (var prop in obj) {
+      if (obj.hasOwnProperty(prop)) {
+        ret[prop] = _toJsonObject(obj[prop]);
+      }
+    }
+    return ret;
+  }
+  return obj;
+};
+
+var _fromJsonDate = function(date) {
+  date = date + '';
+  var year = date.substr(0, 4);
+  var month = date.substr(4, 2);
+  var day = date.substr(6, 2);
+  return new Date(year, month - 1, day);
+};
+
+var _promote = function(val, type) {
+  return _editGuard.run(function() {
+    if (type_.isArray(val)) {
+      var ret = [];
+      for (var i = 0; i < val.length; ++i) {
+        ret.push(new type(val[i]));
+      }
+      return ret;
+    }
+    return new type(val);
+  });
+};
+
+function _checkError(result) {
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+}
+
+var TypeEnum = ['VCARD_30'];
+
+// Edit Guard //////////////////////////////////////////////////////////////
+// This flag is workaround. It is caused by specification
+// which tell to edit readonly fields.
+var _canEdit = 0;
+
+var EditGuard = function() {
+};
+
+EditGuard.prototype.run = function(callback) {
+  try {
+    this.enable();
+    var result = callback();
+    this.disable();
+    return result;
+  } catch (ex) {
+    this.disable();
+    throw ex;
+  }
+};
+
+EditGuard.prototype.enable = function() {
+  _canEdit++;
+};
+
+EditGuard.prototype.disable = function() {
+  _canEdit--;
+};
+
+EditGuard.prototype.isEditEnabled = function() {
+  return _canEdit > 0;
+};
+
+var _editGuard = new EditGuard();
+
+//TODO: Move sorting and filtering to native code
+var Common = function() {};
+Common.prototype.sort = function(arr, sortMode) {
+  var _getSortProperty = function(obj, props) {
+    for (var i = 0; i < props.length; ++i) {
+      if (!obj.hasOwnProperty(props[i])) {
+        return null;
+      }
+      obj = obj[props[i]];
+    }
+    return obj;
+  };
+
+  if (sortMode instanceof tizen.SortMode) {
+    var props = sortMode.attributeName.split('.');
+    arr.sort(function(a, b) {
+      var aValue = _getSortProperty(a, props);
+      var bValue = _getSortProperty(b, props);
+
+      if (sortMode.order === 'DESC') {
+        return aValue < bValue;
+      }
+      return bValue < aValue;
+    });
+  }
+  return arr;
+};
+
+Common.prototype.filter = function(arr, filter) {
+  if (type_.isNullOrUndefined(arr))
+    return arr;
+  if (filter instanceof tizen.AttributeFilter ||
+      filter instanceof tizen.AttributeRangeFilter ||
+      filter instanceof tizen.CompositeFilter) {
+    arr = arr.filter(function(element) {
+      return filter._filter(element);
+    });
+  }
+  return arr;
+};
+
+var C = new Common();
diff --git a/webWidgetTCT_device/src/contact/js/contact.js b/webWidgetTCT_device/src/contact/js/contact.js
new file mode 100755 (executable)
index 0000000..edf09d3
--- /dev/null
@@ -0,0 +1,597 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+var Contact = function(data) {
+  validator_.isConstructorCall(this, Contact);
+
+  var _forceEditMode = false;
+  if (type_.isString(data)) {
+    var result = native_.callSync('ContactManager_importFromVCard', {
+      'contact': data
+    });
+    _checkError(result);
+
+    data = native_.getResultObject(result);
+    // These need to be forced to null as a contact created from a vcard is not added
+    // to any address book
+    data.id = null;
+    data.personId = null;
+    data.addressBookId = null;
+    data.lastUpdate = null;
+
+    // Force edit mode so that anonymous objects can be promoted to their correct types.
+    _forceEditMode = true;
+  } else if (type_.isObject(data) || type_.isFunction(data)) {
+    // It's a dictionary
+  } else {
+    // null or invalid types.
+    data = {};
+  }
+
+  var _id = null;
+  var _personId = null;
+  var _addressBookId = null;
+  var _lastUpdate = null;
+  var _isFavorite = false;
+  var _name = null;
+  var _addresses = [];
+  var _photoURI = null;
+  var _phoneNumbers = [];
+  var _emails = [];
+  var _messengers = [];
+  var _relationships = [];
+  var _birthday = null;
+  var _anniversaries = [];
+  var _organizations = [];
+  var _notes = [];
+  var _urls = [];
+  var _ringtoneURI = null;
+  var _messageAlertURI = null;
+  var _vibrationURI = null;
+  var _groupIds = [];
+
+  var _sanitizeArray = function(arr, type, previousValue) {
+    if (!type_.isArray(arr)) {
+      return previousValue;
+    }
+    for (var i = 0; i < arr.length; ++i) {
+      if (type_.isString(type)) {
+        if (!type_.isString(arr[i])) {
+          return previousValue;
+        }
+      } else if (_editGuard.isEditEnabled()) {
+        arr[i] = new type(arr[i]);
+      } else if (!(arr[i] instanceof type)) {
+        return previousValue;
+      }
+    }
+    return arr;
+  };
+
+  Object.defineProperties(this, {
+    id: {
+      get: function() {
+        return _id;
+      },
+      set: function(v) {
+        if (_editGuard.isEditEnabled()) {
+          _id = converter_.toString(v, false);
+        }
+      },
+      enumerable: true
+    },
+    personId: {
+      get: function() {
+        return _personId;
+      },
+      set: function(v) {
+        if (_editGuard.isEditEnabled()) {
+          _personId = converter_.toString(v, false);
+        }
+      },
+      enumerable: true
+    },
+    addressBookId: {
+      get: function() {
+        return _addressBookId;
+      },
+      set: function(v) {
+        if (_editGuard.isEditEnabled()) {
+          _addressBookId = converter_.toString(v, false);
+        }
+      },
+      enumerable: true
+    },
+    lastUpdated: {
+      get: function() {
+        return _lastUpdate;
+      },
+      set: function(v) {
+        if (_editGuard.isEditEnabled()) {
+          if (v instanceof Date || v === null) {
+            _lastUpdate = v;
+          } else if (type_.isString(v)) {
+            _lastUpdate = new Date(v);
+          } else {
+            _lastUpdate = _fromJsonDate(v);
+          }
+        }
+      },
+      enumerable: true
+    },
+    isFavorite: {
+      get: function() {
+        return _isFavorite;
+      },
+      set: function(v) {
+        if (_editGuard.isEditEnabled()) {
+          _isFavorite = converter_.toBoolean(v, false);
+        }
+      },
+      enumerable: true
+    },
+    name: {
+      get: function() {
+        return _name;
+      },
+      set: function(v) {
+        if (_editGuard.isEditEnabled()) {
+          _name = new ContactName(v);
+        } else {
+          _name = (v instanceof ContactName || v === null) ? v : _name;
+        }
+      },
+      enumerable: true
+    },
+    addresses: {
+      get: function() {
+        return _addresses;
+      },
+      set: function(v) {
+        _addresses = _sanitizeArray(v, ContactAddress, _addresses);
+      },
+      enumerable: true
+    },
+    photoURI: {
+      get: function() {
+        return _photoURI;
+      },
+      set: function(v) {
+        _photoURI = converter_.toString(v, true);
+      },
+      enumerable: true
+    },
+    phoneNumbers: {
+      get: function() {
+        return _phoneNumbers;
+      },
+      set: function(v) {
+        _phoneNumbers = _sanitizeArray(v, ContactPhoneNumber, _phoneNumbers);
+      },
+      enumerable: true
+    },
+    emails: {
+      get: function() {
+        return _emails;
+      },
+      set: function(v) {
+        _emails = _sanitizeArray(v, ContactEmailAddress, _emails);
+      },
+      enumerable: true
+    },
+    messengers: {
+      get: function() {
+        return _messengers;
+      },
+      set: function(v) {
+        _messengers = _sanitizeArray(v, ContactInstantMessenger, _messengers);
+      },
+      enumerable: true
+    },
+    relationships: {
+      get: function() {
+        return _relationships;
+      },
+      set: function(v) {
+        _relationships = _sanitizeArray(v, ContactRelationship, _relationships);
+      },
+      enumerable: true
+    },
+    birthday: {
+      get: function() {
+        return _birthday;
+      },
+      set: function(v) {
+        if (v instanceof Date || v === null) {
+          _birthday = v;
+        } else if (type_.isString(v)) {
+          _birthday = new Date(v);
+        } else if (_editGuard.isEditEnabled()) {
+          _birthday = _fromJsonDate(v);
+        }
+      },
+      enumerable: true
+    },
+    anniversaries: {
+      get: function() {
+        return _anniversaries;
+      },
+      set: function(v) {
+        _anniversaries = _sanitizeArray(v, ContactAnniversary, _anniversaries);
+      },
+      enumerable: true
+    },
+    organizations: {
+      get: function() {
+        return _organizations;
+      },
+      set: function(v) {
+        _organizations = _sanitizeArray(v, ContactOrganization, _organizations);
+      },
+      enumerable: true
+    },
+    notes: {
+      get: function() {
+        return _notes;
+      },
+      set: function(v) {
+        _notes = _sanitizeArray(v, '', _notes);
+      },
+      enumerable: true
+    },
+    urls: {
+      get: function() {
+        return _urls;
+      },
+      set: function(v) {
+        _urls = _sanitizeArray(v, ContactWebSite, _urls);
+      },
+      enumerable: true
+    },
+    ringtoneURI: {
+      get: function() {
+        return _ringtoneURI;
+      },
+      set: function(v) {
+        _ringtoneURI = converter_.toString(v, true);
+      },
+      enumerable: true
+    },
+    messageAlertURI: {
+      get: function() {
+        return _messageAlertURI;
+      },
+      set: function(v) {
+        _messageAlertURI = converter_.toString(v, true);
+      },
+      enumerable: true
+    },
+    vibrationURI: {
+      get: function() {
+        return _vibrationURI;
+      },
+      set: function(v) {
+        _vibrationURI = converter_.toString(v, true);
+      },
+      enumerable: true
+    },
+    groupIds: {
+      get: function() {
+        return _groupIds;
+      },
+      set: function(v) {
+        _groupIds = _sanitizeArray(v, '', _groupIds);
+      },
+      enumerable: true
+    }
+  });
+
+  var _this = this;
+  var _setProperties = function() {
+    for (var p in _this) {
+      if (data.hasOwnProperty(p)) {
+        _this[p] = data[p];
+      }
+    }
+  };
+
+  if (_forceEditMode) {
+    _editGuard.run(_setProperties);
+  } else {
+    _setProperties();
+  }
+
+};
+
+// Auxiliary functions /////////////////////////////////////////////////////
+
+// Convert address from Contact object to string
+var _contactAddressToString = function(obj) {
+  var str = '';
+  if (obj.addresses.length === 0) {
+    return '';
+  }
+  // Sorry for so many if statements, but the IDE makes me do it
+  for (var it in obj.addresses) {
+    if (!it instanceof ContactAddress) {
+      continue;
+    }
+    str += 'ADR;';
+    for (var addType in it.types) {
+      if (type_.isString(addType)) {
+        str += addType + ',';
+      }
+    }
+    if (str.charAt(str.length - 1) === ',') {
+      str[str.length - 1] = ':';
+    }
+    str += ';'; // because of we don't keep Post office addres
+    // which is part of vCard 3.0 standard
+    str += it.additionalInformation + ';';
+    str += it.streetAddress + ';';
+    str += it.city + ';';
+    str += it.region + ';';
+    str += it.postalCode + ';';
+    str += it.country + ';';
+    str += '\n';
+  }
+  return str;
+};
+
+// Convert email address from Contact object to string
+var _contactEmailToString = function(obj) {
+  if (!type_.isArray(obj.emails) || obj.emails.length === 0) {
+    console.log('Empty email list');
+    return '';
+  }
+  var str = '';
+  for (var mail in obj.emails) {
+    if (!mail instanceof ContactEmailAddress || !type_.isArray(mail.types) ||
+      mail.types.length === 0) {
+      console.log('Incorrect email type');
+      continue;
+    }
+    str += 'EMAIL;';
+    // set types
+    for (var type in mail.types) {
+      if (type_.isString(type)) {
+        str += type + ',';
+      }
+    }
+    if (str.charAt(str.length - 1) === ',') {
+      str[str.length - 1] = ':';
+    }
+    str += '=' + converter_.toString(mail.email) + '\n';
+  }
+  return str;
+};
+
+// Convert organizations info from Contact object to string
+var _contactOrganizationToString = function(obj) {
+  if (obj.organizations.length === 0 ||
+    !obj.organizations[0] instanceof ContactOrganization) {
+    return '';
+  }
+  var str = '';
+  for (var org in obj.organizations) {
+    if (!org instanceof ContactOrganization) {
+      continue;
+    }
+    str += 'ORG:';
+    str += org.name + ';' + org.department + ';' + org.title + '\n';
+  }
+  return str;
+};
+
+// Convert organizations roles from Contact object to string
+var _contactRoleToString = function(obj) {
+  if (obj.organizations.length === 0 ||
+    !obj.organizations[0] instanceof ContactOrganization) {
+    return '';
+  }
+  var str = '';
+  for (var org in obj.organizations) {
+    if (!org instanceof ContactOrganization) {
+      continue;
+    }
+    str += 'ROLE:';
+    str += org.name + ';' + org.role + '\n';
+  }
+  return str;
+};
+
+// Convert phone numbers from Contact object to string
+var _contactPhoneNumbersToString = function(obj) {
+  if (obj.phoneNumbers.length === 0 || !obj.phoneNumbers[0] instanceof ContactPhoneNumber) {
+    return '';
+  }
+  var str = '';
+  for (var phone in obj.phoneNumbers) {
+    if (!phone instanceof ContactPhoneNumber) {
+      continue;
+    }
+    str += 'TEL';
+    for (var type in phone.types) {
+      if (type_.isString(type)) {
+        str += ';' + type;
+      }
+    }
+    str += ':';
+    str += phone.number + '\n';
+  }
+  return str;
+};
+
+// Convert urls from Contact object to string
+var _contactURLToString = function(obj) {
+  if (obj.urls.length === 0 || !obj.urls[0] instanceof ContactWebSite) {
+    return '';
+  }
+  var str = '';
+  for (var url in obj.urls) {
+    if (url instanceof ContactWebSite) {
+      str += 'URL:' + url.url + '\n';
+    }
+  }
+  return str;
+};
+
+// Convert anniversaries to string
+var _contactAnniversaryToString = function(obj) {
+  if (obj.anniversaries.length === 0 || !obj.anniversaries[0] instanceof ContactAnniversary) {
+    return '';
+  }
+  var str = '';
+  for (var ann in obj.anniversaries) {
+    if (ann instanceof ContactAnniversary) {
+      str += 'X-ANNIVERSARY;' + ann.label + ':' + ann.date + ';' + '\n';
+    }
+  }
+  return str;
+};
+
+// Convert relationships to string
+var _contactRelationshipsToString = function(obj) {
+  if (obj.relationships.length === 0 ||
+    !obj.relationships[0] instanceof ContactRelationship) {
+    return '';
+  }
+  var str = '';
+  for (var rel in obj.relationships) {
+    if (rel instanceof ContactRelationship) {
+      str += 'X-RELATIONSHIP;' + rel.relativeName + ':' + rel.type +
+      ':' + rel.label + ';\n';
+    }
+  }
+  return str;
+};
+
+// Convert messengers to string
+var _contactInstantMessengeToString = function(obj) {
+  if (obj.messengers.length === 0 || !obj.messengers[0] instanceof ContactInstantMessenger) {
+    return '';
+  }
+  var str = '';
+  for (var messenger in obj.messengers) {
+    if (messenger instanceof ContactInstantMessenger) {
+      str += 'X-MESSANGER;' + messenger.imAddress + ':' + messenger.type +
+      ':' + messenger.label + ';\n';
+    }
+  }
+  return str;
+};
+
+// Auxiliary function, allows to parse JSON to Contact
+var _JSONToContactType = function(type, obj) {
+  var contact = new type();
+
+  for (var prop in obj) {
+    if (contact.hasOwnProperty(prop)) {
+      if (contact[prop] instanceof Date && type_.isNumber(obj[prop])) {
+        contact[prop] = new Date(1000 * obj[prop]);
+      } else {
+        contact[prop] = obj[prop];
+      }
+    }
+  }
+
+  return contact;
+};
+
+// Converts the Contact item to a string format.
+Contact.prototype.convertToString = function(format) {
+  format = format || TypeEnum[0];
+
+  if (!type_.isString(format)) {
+    throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR, 'Invalid format');
+  }
+
+  if (TypeEnum.indexOf(format) < 0) {
+    throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR, 'Invalid format');
+  }
+
+  if (this.id === '') {
+    throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR,
+      'Contact ID is empty.');
+  }
+
+  var str = 'BEGIN:VCARD\nVERSION:3.0\n';
+
+  // set contact name
+  str += 'N:' + this.name.lastName + ';' + this.name.firstName + ';' +
+  this.name.middleName + ';' + this.name.prefix + ';' + this.name.suffix + '\n';
+  str += 'FN' + this.name.displayName + '\n';
+
+  // set phonetic names
+  str += 'X-PHONETIC-FIRST-NAME' + this.name.phoneticFirstName + '\n' +
+  'X-PHONETIC-LAST-NAME' + this.name.phoneticLastName + '\n';
+
+  // set contact address
+  str += _contactAddressToString(this);
+
+  // set Birthday
+  if (this.birthday) {
+    str += 'BDAY:' + this.birthday.getYear() + '-' + this.birthday.getMonth() +
+    '-' + this.birthday.getDay() + '\n';
+  }
+
+  // set anniversary
+  str += _contactAnniversaryToString(this);
+
+  // set relationship
+  str += _contactRelationshipsToString(this);
+
+  // set emails
+  str += _contactEmailToString(this);
+
+  // set organization data
+  str += _contactOrganizationToString(this);
+
+  // set role
+  str += _contactRoleToString(this);
+
+  // set phone numbers
+  str += _contactPhoneNumbersToString(this);
+
+  // set user ID
+  str += 'UID:' + this.id + '\n';
+
+  // set isFavorite
+  str += 'X-IS-FAVORITE' + this.isFavorite + '\n';
+
+  // set URLs
+  str += _contactURLToString(this);
+
+  // set messengers
+  str += _contactInstantMessengeToString(this);
+
+  // set last revision
+  str += 'REV:' + this.lastUpdated.getYear() + '-' + this.lastUpdated.getMonth() +
+  '-' + this.lastUpdated.getDay() + 'T' + this.lastUpdated.getHours() + ':' +
+  this.lastUpdated.getMinutes() + ':' + this.lastUpdated.getSeconds() + 'Z\n';
+
+  str += 'END:VCARD\n';
+
+  return str;
+};
+
+// Creates a clone of the Contact object, detached from any address book
+Contact.prototype.clone = function() {
+  return new Contact(this);
+};
+
+// exports /////////////////////////////////////////////////////////////////
+tizen.Contact = Contact;
diff --git a/webWidgetTCT_device/src/contact/js/contact_data_structures.js b/webWidgetTCT_device/src/contact/js/contact_data_structures.js
new file mode 100755 (executable)
index 0000000..433f2e5
--- /dev/null
@@ -0,0 +1,755 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+// An enumerator that indicates the types for the relationships.
+var ContactRelationshipType = {
+  ASSISTANT: 'ASSISTANT',
+  BROTHER: 'BROTHER',
+  CHILD: 'CHILD',
+  DOMESTIC_PARTNER: 'DOMESTIC_PARTNER',
+  FATHER: 'FATHER',
+  FRIEND: 'FRIEND',
+  MANAGER: 'MANAGER',
+  MOTHER: 'MOTHER',
+  PARENT: 'PARENT',
+  PARTNER: 'PARTNER',
+  REFERRED_BY: 'REFERRED_BY',
+  RELATIVE: 'RELATIVE',
+  SISTER: 'SISTER',
+  SPOUSE: 'SPOUSE',
+  OTHER: 'OTHER',
+  CUSTOM: 'CUSTOM'
+};
+
+// An enumerator that indicates the types for instant messenger.
+var ContactInstantMessengerType = {
+  GOOGLE: 'GOOGLE',
+  WLM: 'WLM',
+  YAHOO: 'YAHOO',
+  FACEBOOK: 'FACEBOOK',
+  ICQ: 'ICQ',
+  AIM: 'AIM',
+  QQ: 'QQ',
+  JABBER: 'JABBER',
+  SKYPE: 'SKYPE',
+  IRC: 'IRC',
+  OTHER: 'OTHER',
+  CUSTOM: 'CUSTOM'
+};
+
+// class ContactRef ////////////////////////////////////////////////////////
+
+var ContactRef = function(data) {
+  validator_.isConstructorCall(this, ContactRef);
+  var _contactId = '';
+  var _addressBookId = '';
+  Object.defineProperties(this, {
+    addressBookId: {
+      get: function() {
+        return _addressBookId;
+      },
+      set: function(v) {
+        _addressBookId = converter_.toString(v, false);
+      },
+      enumerable: true
+    },
+    contactId: {
+      get: function() {
+        return _contactId;
+      },
+      set: function(v) {
+        _contactId = converter_.toString(v, false);
+      },
+      enumerable: true
+    }
+  });
+
+  if (type_.isObject(data)) {
+    this.addressBookId = data.addressBookId;
+    this.contactId = data.contactId;
+  } else {
+    try {
+      var args = validator_.validateArgs(arguments, [
+        {
+          name: 'addressBookId',
+          type: types_.STRING,
+          optional: false,
+          nullable: false
+        },
+        {
+          name: 'contactId',
+          type: types_.STRING,
+          optional: false,
+          nullable: false
+        }
+      ]);
+      _addressBookId = args.addressBookId;
+      _contactId = args.contactId;
+    } catch (x) {
+      // Constructors shouldn't throw
+    }
+  }
+};
+
+// class ContactGroup //////////////////////////////////////////////////
+
+var ContactGroup = function(name, ringtone, photo) {
+  validator_.isConstructorCall(this, ContactGroup);
+
+  var _id = null;
+  var _address = null;
+  var _readOnly = false;
+  var _name = '';
+  var _ringtoneURI = null;
+  var _photoURI = null;
+
+  if (name && type_.isString(name)) {
+    _name = name.length ? name : '';
+  }
+
+  if (ringtone && type_.isString(ringtone)) {
+    _ringtoneURI = ringtone.length ? ringtone : null;
+  }
+
+  if (photo && type_.isString(photo)) {
+    _photoURI = photo.length ? photo : null;
+  }
+
+  Object.defineProperties(this, {
+    id: {
+      get: function() {
+        return _id;
+      },
+      set: function(v) {
+        if (_editGuard.isEditEnabled()) {
+          _id = converter_.toString(v, true);
+        }
+      },
+      enumerable: true
+    },
+    addressBookId: {
+      get: function() {
+        return _address;
+      },
+      set: function(v) {
+        if (_editGuard.isEditEnabled()) {
+          _address = converter_.toString(v, true);
+        }
+      },
+      enumerable: true
+    },
+    name: {
+      get: function() {
+        return _name;
+      },
+      set: function(v) {
+        _name = converter_.toString(v, false);
+      },
+      enumerable: true
+    },
+    ringtoneURI: {
+      get: function() {
+        return _ringtoneURI;
+      },
+      set: function(v) {
+        _ringtoneURI = converter_.toString(v, true);
+      },
+      enumerable: true
+    },
+    photoURI: {
+      get: function() {
+        return _photoURI;
+      },
+      set: function(v) {
+        _photoURI = converter_.toString(v, true);
+      },
+      enumerable: true
+    },
+    readOnly: {
+      get: function() {
+        return _readOnly;
+      },
+      set: function(v) {
+        if (_editGuard.isEditEnabled()) {
+          _readOnly = converter_.toBoolean(v, false);
+        }
+      },
+      enumerable: true
+    }
+  });
+
+  if (_editGuard.isEditEnabled()) {
+    var data = arguments[0];
+    if (type_.isObject(data)) {
+      for (var prop in data) {
+        if (this.hasOwnProperty(prop)) {
+          this[prop] = data[prop];
+        }
+      }
+    }
+  }
+};
+
+// class ContactEmailAddress ///////////////////////////////////////////
+
+var ContactEmailAddress = function(address, types, isDefault) {
+  validator_.isConstructorCall(this, ContactEmailAddress);
+
+  var _email = '';
+  var _label = null;
+  var _isDefault = false;
+  var _types = ['WORK'];
+
+  if (type_.isString(address) && address.indexOf('@') > 0 &&
+      address.indexOf('@') !== (address.length - 1)) {
+    _email = address;
+  }
+
+  if (type_.isBoolean(isDefault)) {
+    _isDefault = isDefault;
+  }
+
+  if (type_.isArray(types)) {
+    _types = [];
+    for (var i = 0; i < types.length; ++i) {
+      if (type_.isString(types[i])) {
+        _types.push(types[i]);
+      }
+    }
+  } else if (type_.isString(types)) {
+    _types = [];
+    _types.push(types);
+  }
+
+  Object.defineProperties(this, {
+    email: {
+      get: function() {
+        return _email;
+      },
+      set: function(v) {
+        if (type_.isString(v) && v.indexOf('@') > 0 &&
+            v.indexOf('@') !== (v.length - 1)) {
+          _email = v;
+        }
+      },
+      enumerable: true
+    },
+    isDefault: {
+      get: function() {
+        return _isDefault;
+      },
+      set: function(v) {
+        _isDefault = converter_.toBoolean(v, false);
+      },
+      enumerable: true
+    },
+    types: {
+      get: function() {
+        return _types;
+      },
+      set: function(v) {
+        if (type_.isArray(v)) {
+          _types = [];
+          for (var i = 0; i < v.length; ++i) {
+            if (type_.isString(v[i])) {
+              _types.push(v[i]);
+            }
+          }
+        } else if (type_.isString(v)) {
+          _types = [];
+          _types.push(v);
+        }
+      },
+      enumerable: true
+    },
+    label: {
+      get: function() {
+        return _label;
+      },
+      set: function(v) {
+        _label = converter_.toString(v, true);
+      },
+      enumerable: true
+    }
+  });
+
+  if (_editGuard.isEditEnabled()) {
+    for (var prop in arguments[0]) {
+      if (this.hasOwnProperty(prop)) {
+        this[prop] = arguments[0][prop];
+      }
+    }
+  }
+};
+
+// class ContactPhoneNumber ////////////////////////////////////////////
+
+var ContactPhoneNumber = function(number, type, isDefault) {
+  validator_.isConstructorCall(this, ContactPhoneNumber);
+
+  var _isDefault = false;
+  var _number = '';
+  var _types = ['VOICE'];
+
+  if (type_.isString(number)) {
+    _number = number;
+  }
+
+  if (type_.isArray(type)) {
+    _types = [];
+    for (var i = 0; i < type.length; ++i) {
+      _types.push(converter_.toString(type[i], false));
+    }
+  } else if (type_.isString(type)) {
+    _types = [];
+    _types.push(type, false);
+  }
+
+  if (type_.isBoolean(isDefault)) {
+    _isDefault = isDefault;
+  }
+
+  Object.defineProperties(this, {
+    number: {
+      get: function() {
+        return _number;
+      },
+      set: function(v) {
+        _number = converter_.toString(v, false);
+      },
+      enumerable: true
+    },
+    isDefault: {
+      get: function() {
+        return _isDefault;
+      },
+      set: function(v) {
+        _isDefault = converter_.toBoolean(v, false);
+      },
+      enumerable: true
+    },
+    types: {
+      get: function() {
+        return _types;
+      },
+      set: function(v) {
+        if (type_.isArray(v)) {
+          _types = [];
+          for (var i = 0; i < v.length; ++i) {
+            _types.push(converter_.toString(v[i], false));
+          }
+        } else if (type_.isString(v)) {
+          _types = [];
+          _types.push(v, false);
+        }
+      },
+      enumerable: true
+    },
+    label: {
+      value: null,
+      writable: true,
+      enumerable: true
+    }
+  });
+
+  if (_editGuard.isEditEnabled()) {
+    for (var prop in arguments[0]) {
+      if (this.hasOwnProperty(prop)) {
+        this[prop] = arguments[0][prop];
+      }
+    }
+  }
+};
+
+// class ContactAddress ////////////////////////////////////////////////
+
+var ContactAddress = function(data) {
+  validator_.isConstructorCall(this, ContactAddress);
+
+  var _isDefault = false;
+  var _types = ['HOME'];
+
+  Object.defineProperties(this, {
+    country: {
+      value: null,
+      writable: true,
+      enumerable: true
+    },
+    region: {
+      value: null,
+      writable: true,
+      enumerable: true
+    },
+    city: {
+      value: null,
+      writable: true,
+      enumerable: true
+    },
+    streetAddress: {
+      value: null,
+      writable: true,
+      enumerable: true
+    },
+    additionalInformation: {
+      value: null,
+      writable: true,
+      enumerable: true
+    },
+    postalCode: {
+      value: null,
+      writable: true,
+      enumerable: true
+    },
+    isDefault: {
+      get: function() {
+        return _isDefault;
+      },
+      set: function(v) {
+        _isDefault = converter_.toBoolean(v, false);
+      },
+      enumerable: true
+    },
+    types: {
+      get: function() {
+        return _types;
+      },
+      set: function(v) {
+        if (type_.isString(v)) {
+          _types = [];
+          _types.push(v);
+        } else if (type_.isArray(v)) {
+          _types = [];
+          for (var i = 0; i < v.length; ++i) {
+            if (type_.isString(v[i])) {
+              _types.push(v[i]);
+            }
+          }
+        }
+      },
+      enumerable: true
+    },
+    label: {
+      value: null,
+      writable: true,
+      enumerable: true
+    }
+  });
+
+  if (type_.isObject(data)) {
+    for (var prop in data) {
+      if (this.hasOwnProperty(prop)) {
+        this[prop] = data[prop];
+      }
+    }
+  }
+};
+
+// class ContactAnniversary ////////////////////////////////////////////////
+
+var ContactAnniversary = function(anniversary_date, anniversary_label) {
+  validator_.isConstructorCall(this, ContactAnniversary);
+
+  var _anniversary_date = new Date();
+  var _anniversary_label = null;
+
+  Object.defineProperties(this, {
+    date: {
+      get: function() {
+        return _anniversary_date;
+      },
+      set: function(v) {
+        _anniversary_date = v instanceof Date ? v : new Date();
+      },
+      enumerable: true
+    },
+    label: {
+      get: function() {
+        return _anniversary_label;
+      },
+      set: function(v) {
+        _anniversary_label = converter_.toString(v, true);
+      },
+      enumerable: true
+    }
+  });
+
+  if (_editGuard.isEditEnabled()) {
+    _anniversary_date = _fromJsonDate(arguments[0].date);
+    _anniversary_label = arguments[0].label;
+  } else {
+    if (type_.isDate(anniversary_date)) {
+      _anniversary_date = anniversary_date;
+    }
+    if (type_.isString(anniversary_label)) {
+      _anniversary_label = anniversary_label;
+    }
+  }
+};
+
+// class ContactWebSite ////////////////////////////////////////////////////
+
+var ContactWebSite = function(contact_url, contact_type) {
+  validator_.isConstructorCall(this, ContactWebSite);
+
+  var _url = '';
+  var _type = 'HOMEPAGE';
+
+  if (type_.isString(contact_url)) {
+    _url = contact_url;
+  }
+  if (type_.isString(contact_type)) {
+    _type = contact_type;
+  }
+
+  Object.defineProperties(this, {
+    url: {
+      get: function() {
+        return _url;
+      },
+      set: function(v) {
+        _url = converter_.toString(v, false);
+      },
+      enumerable: true
+    },
+    type: {
+      get: function() {
+        return _type;
+      },
+      set: function(v) {
+        _type = converter_.toString(v, false);
+      },
+      enumerable: true
+    }
+  });
+};
+
+// class ContactOrganization ///////////////////////////////////////////////
+
+var ContactOrganization = function(data) {
+  validator_.isConstructorCall(this, ContactOrganization);
+  Object.defineProperties(this, {
+    name: {
+      value: null,
+      writable: true,
+      enumerable: true
+    },
+    department: {
+      value: null,
+      writable: true,
+      enumerable: true
+    },
+    title: {
+      value: null,
+      writable: true,
+      enumerable: true
+    },
+    role: {
+      value: null,
+      writable: true,
+      enumerable: true
+    },
+    logoURI: {
+      value: null,
+      writable: true,
+      enumerable: true
+    }
+  });
+
+  if (type_.isObject(data)) {
+    for (var prop in data) {
+      if (this.hasOwnProperty(prop)) {
+        this[prop] = data[prop];
+      }
+    }
+  }
+};
+
+// class ContactName ///////////////////////////////////////////////////////
+
+var ContactName = function(data) {
+  validator_.isConstructorCall(this, ContactName);
+
+  var _displayName = null;
+  var _nicknames = [];
+
+  Object.defineProperties(this, {
+    prefix: {
+      value: null,
+      writable: true,
+      enumerable: true
+    },
+    suffix: {
+      value: null,
+      writable: true,
+      enumerable: true
+    },
+    firstName: {
+      value: null,
+      writable: true,
+      enumerable: true
+    },
+    middleName: {
+      value: null,
+      writable: true,
+      enumerable: true
+    },
+    lastName: {
+      value: null,
+      writable: true,
+      enumerable: true
+    },
+    nicknames: {
+      get: function() {
+        return _nicknames;
+      },
+      set: function(nicknames) {
+        if (type_.isArray(nicknames)) {
+          _nicknames = nicknames;
+        }
+      },
+      enumerable: true
+    },
+    phoneticFirstName: {
+      value: null,
+      writable: true,
+      enumerable: true
+    },
+    phoneticMiddleName: {
+      value: null,
+      writable: true,
+      enumerable: true
+    },
+    phoneticLastName: {
+      value: null,
+      writable: true,
+      enumerable: true
+    },
+    displayName: {
+      get: function() {
+        return _displayName;
+      },
+      set: function(v) {
+        if (_editGuard.isEditEnabled()) {
+          _displayName = converter_.toString(v, true);
+        }
+      },
+      enumerable: true
+    }
+  });
+
+  if (type_.isObject(data)) {
+    for (var prop in data) {
+      if (this.hasOwnProperty(prop)) {
+        this[prop] = data[prop];
+      }
+    }
+  }
+};
+
+var ContactRelationship = function(relativeName, type) {
+  validator_.isConstructorCall(this, ContactRelationship);
+
+  var _relativeName = converter_.toString(relativeName, false);
+  var _type = type ? converter_.toEnum(type, Object.keys(ContactRelationshipType), false)
+            : ContactRelationshipType.OTHER;
+  var _label = null;
+
+  Object.defineProperties(this, {
+    relativeName: {
+      get: function () {
+        return _relativeName;
+      },
+      set: function (v) {
+        _relativeName = converter_.toString(v, false);
+      },
+      enumerable: true
+    },
+    type: {
+      get: function () {
+        return _type;
+      },
+      set: function (v) {
+        _type = v ? converter_.toEnum(v, Object.keys(ContactRelationshipType), false)
+                  : _type;
+      },
+      enumerable: true
+    },
+    label: {
+      get: function () {
+        return _label;
+      },
+      set: function (v) {
+        _label = converter_.toString(v, true);
+      },
+      enumerable: true
+    }
+  });
+};
+
+var ContactInstantMessenger = function(imAddress, type) {
+  validator_.isConstructorCall(this, ContactInstantMessenger);
+
+  var _imAddress = '';
+  var _type = 'OTHER';
+
+  Object.defineProperties(this, {
+    imAddress: {
+      get: function() {
+        return _imAddress;
+      },
+      set: function(v) {
+        if (type_.isNullOrUndefined(v)) {
+          return;
+        }
+        _imAddress = converter_.toString(v, false);
+      },
+      enumerable: true
+    },
+    type: {
+      get: function() {
+        return _type;
+      },
+      set: function(v) {
+        if (type_.isNullOrUndefined(v)) {
+          return;
+        }
+        _type = converter_.toEnum(v, Object.keys(ContactInstantMessengerType), false);
+      },
+      enumerable: true
+    },
+    label: {
+      value: null,
+      writable: true,
+      enumerable: true
+    }
+  });
+
+  this.imAddress = imAddress;
+  this.type = type;
+};
+
+// exports /////////////////////////////////////////////////////////////////
+tizen.ContactRef = ContactRef;
+tizen.ContactName = ContactName;
+tizen.ContactOrganization = ContactOrganization;
+tizen.ContactWebSite = ContactWebSite;
+tizen.ContactAnniversary = ContactAnniversary;
+tizen.ContactAddress = ContactAddress;
+tizen.ContactPhoneNumber = ContactPhoneNumber;
+tizen.ContactEmailAddress = ContactEmailAddress;
+tizen.ContactGroup = ContactGroup;
+tizen.ContactRelationship = ContactRelationship;
+tizen.ContactInstantMessenger = ContactInstantMessenger;
diff --git a/webWidgetTCT_device/src/contact/js/contact_manager.js b/webWidgetTCT_device/src/contact/js/contact_manager.js
new file mode 100755 (executable)
index 0000000..11ea6fd
--- /dev/null
@@ -0,0 +1,506 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+var _personListenerRegistered = false;
+var _personCallbackMap = {};
+var _personChangeListener = function(result) {
+  for (var key in _personCallbackMap) {
+    if (_personCallbackMap.hasOwnProperty(key)) {
+      if (result.added.length) {
+        native_.callIfPossible(_personCallbackMap[key].onpersonsadded,
+            _promote(result.added, Person));
+      }
+      if (result.updated.length) {
+        native_.callIfPossible(_personCallbackMap[key].onpersonsupdated,
+            _promote(result.updated, Person));
+      }
+      if (result.removed.length) {
+        native_.callIfPossible(_personCallbackMap[key].onpersonsremoved,
+            result.removed);
+      }
+    }
+  }
+};
+
+
+var ContactManager = function() {};
+
+// Gets the available address books
+ContactManager.prototype.getAddressBooks = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.CONTACT_READ);
+
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'successCallback',
+      type: types_.FUNCTION,
+      optional: false,
+      nullable: false
+    },
+    {
+      name: 'errorCallback',
+      type: types_.FUNCTION,
+      optional: true,
+      nullable: true
+    }
+  ]);
+
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+    } else {
+      var books = native_.getResultObject(result);
+      var tmp = [];
+
+      books.forEach(function(data) {
+        return _editGuard.run(function() {
+          var addressBook = new AddressBook(result.accountId, result.name);
+          addressBook.id = data.id;
+          addressBook.name = data.name;
+          addressBook.readOnly = result.readOnly;
+
+          tmp.push(addressBook);
+        });
+      });
+
+      native_.callIfPossible(args.successCallback, tmp);
+    }
+  };
+
+  var result = native_.call('ContactManager_getAddressBooks', {}, callback);
+
+  _checkError(result);
+};
+
+// Gets the aggregation of all address books.
+ContactManager.prototype.getUnifiedAddressBook = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.CONTACT_READ);
+
+  return _editGuard.run(function() {
+    var addressBook = new AddressBook(0, 'Unified address book');
+    addressBook.id = UNIFIED_ADDRESSBOOK_ID;
+    addressBook.readOnly = false;
+
+    return addressBook;
+  });
+};
+
+// Gets the default address book.
+ContactManager.prototype.getDefaultAddressBook = function() {
+  //privileges are checked in getAddressBook function
+  return this.getAddressBook(DEFAULT_ADDRESSBOOK_ID);
+};
+
+// Gets the address book with the specified identifier.
+ContactManager.prototype.getAddressBook = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.CONTACT_READ);
+
+  var args = validator_.validateArgs(arguments, [{
+    name: 'addressBookId',
+    type: types_.STRING,
+    optional: false,
+    nullable: false
+  }]);
+
+  if (String(converter_.toLong(args.addressBookId)) !== args.addressBookId) {
+    // TCT: ContactManager_getAddressBook_addressBookId_invalid
+    throw new WebAPIException(WebAPIException.NOT_FOUND_ERR);
+  }
+
+  var result = native_.callSync('ContactManager_getAddressBook', {
+    addressBookId: args.addressBookId
+  });
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+
+  result = native_.getResultObject(result);
+
+  return _editGuard.run(function() {
+    var addressBook = new AddressBook(result.accountId, result.name);
+    addressBook.id = args.addressBookId;
+    addressBook.readOnly = result.readOnly;
+
+    return addressBook;
+  });
+};
+
+ContactManager.prototype.addAddressBook = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.CONTACT_WRITE);
+
+  var args = validator_.validateArgs(arguments, [{
+    name: 'addressBook',
+    type: types_.PLATFORM_OBJECT,
+    values: tizen.AddressBook,
+    optional: false,
+    nullable: false
+  }]);
+
+  var result = native_.callSync('ContactManager_addAddressBook', {
+    addressBook: args.addressBook
+  });
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+
+  var data = native_.getResultObject(result);
+  _editGuard.run(function() {
+    for (var prop in data) {
+      if (args.addressBook.hasOwnProperty(prop)) {
+        args.addressBook[prop] = data[prop];
+      }
+    }
+  });
+};
+
+ContactManager.prototype.removeAddressBook = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.CONTACT_WRITE);
+
+  // TCT: ContactManager_removeAddressBook_misarg
+  if (type_.isNullOrUndefined(arguments[0])) {
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR);
+  }
+
+  var args = validator_.validateArgs(arguments, [{
+    name: 'addressBookId',
+    type: types_.STRING,
+    optional: false,
+    nullable: false
+  }]);
+
+  if (args.addressBookId === UNIFIED_ADDRESSBOOK_ID) {
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+        'Unified address book can not be deleted');
+  }
+
+  if (args.addressBookId === DEFAULT_ADDRESSBOOK_ID) {
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+        'Default address book can not be deleted');
+  }
+
+  var result = native_.callSync('ContactManager_removeAddressBook', {
+    addressBookId: args.addressBookId
+  });
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+};
+
+// Gets the person with the specified identifier.
+ContactManager.prototype.get = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.CONTACT_READ);
+
+  // validation
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'personId',
+      type: types_.STRING,
+      optional: false,
+      nullable: false
+    }
+  ]);
+
+  if (String(converter_.toLong(args.personId)) !== args.personId) {
+    // TCT: ContactManager_get_personId_invalid
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR);
+  }
+
+  var result = native_.callSync('ContactManager_get', {
+    personId: args.personId
+  });
+  _checkError(result);
+
+  return _editGuard.run(function() {
+    return new Person(native_.getResultObject(result));
+  });
+};
+
+// Updates a person in the address book synchronously.
+ContactManager.prototype.update = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.CONTACT_WRITE);
+
+  // validation
+  var args = validator_.validateArgs(arguments, [{
+    name: 'person',
+    type: types_.PLATFORM_OBJECT,
+    values: Person,
+    optional: false,
+    nullable: false
+  }]);
+  var result = native_.callSync('ContactManager_update', { person: args.person });
+  _checkError(result);
+
+  result = native_.getResultObject(result);
+  for (var prop in result) {
+    if (args.person.hasOwnProperty(prop)) {
+      args.person[prop] = result[prop];
+    }
+  }
+};
+
+// Updates several existing persons in the contact DB asynchronously.
+ContactManager.prototype.updateBatch = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.CONTACT_WRITE);
+
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'persons',
+      type: types_.ARRAY,
+      values: Person,
+      optional: false,
+      nullable: false
+    },
+    {
+      name: 'successCallback',
+      type: types_.FUNCTION,
+      optional: true,
+      nullable: true
+    },
+    {
+      name: 'errorCallback',
+      type: types_.FUNCTION,
+      optional: true,
+      nullable: true
+    }
+  ]);
+
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+      return;
+    }
+
+    native_.callIfPossible(args.successCallback);
+  };
+
+  var result = native_.call('ContactManager_updateBatch', {
+    addressBook: {},
+    batchArgs: _toJsonObject(args.persons)
+  }, callback);
+
+  _checkError(result);
+};
+
+// Removes a person from the contact DB synchronously.
+ContactManager.prototype.remove = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.CONTACT_WRITE);
+
+  // validation
+  var args = validator_.validateArgs(arguments, [{
+    name: 'personId',
+    type: types_.STRING,
+    optional: false,
+    nullable: false
+  }]);
+
+  if (String(converter_.toLong(args.personId)) !== args.personId) {
+    // TCT: ContactManager_remove_personId_invalid
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR);
+  }
+
+  var result = native_.callSync('ContactManager_remove', {personId: args.personId});
+  _checkError(result);
+};
+
+// Removes persons from contact DB asynchronously.
+ContactManager.prototype.removeBatch = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.CONTACT_WRITE);
+
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'personIds',
+      type: types_.ARRAY,
+      values: types_.STRING,
+      optional: false,
+      nullable: false
+    },
+    {
+      name: 'successCallback',
+      type: types_.FUNCTION,
+      optional: true,
+      nullable: true
+    },
+    {
+      name: 'errorCallback',
+      type: types_.FUNCTION,
+      optional: true,
+      nullable: true
+    }
+  ]);
+
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+      return;
+    }
+
+    native_.callIfPossible(args.successCallback);
+  };
+
+  var result = native_.call('ContactManager_removeBatch', {
+    addressBook: {},
+    batchArgs: _toJsonObject(args.personIds)
+  }, callback);
+
+  _checkError(result);
+};
+
+// Gets an array of all Person objects from the contact DB or the ones that match the
+// optionally supplied filter.
+ContactManager.prototype.find = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.CONTACT_READ);
+
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'successCallback',
+      type: types_.FUNCTION,
+      optional: false,
+      nullable: false
+    },
+    {
+      name: 'errorCallback',
+      type: types_.FUNCTION,
+      optional: true,
+      nullable: true
+    },
+    {
+      name: 'filter',
+      type: types_.PLATFORM_OBJECT,
+      values: [tizen.AttributeFilter,
+        tizen.AttributeRangeFilter,
+        tizen.CompositeFilter],
+      optional: true,
+      nullable: true
+    },
+    {
+      name: 'sortMode',
+      type: types_.PLATFORM_OBJECT,
+      values: tizen.SortMode,
+      optional: true,
+      nullable: true
+    }
+  ]);
+
+  // TODO implement contact filtering/sorting.
+  var data = {
+    filter: utils_.repackFilter(args.filter),
+    sortMode: args.sortMode
+  };
+
+  var self = this;
+
+  var callback = function(result) {
+    if (native_.isSuccess(result)) {
+      var _result = native_.getResultObject(result);
+      var retval = [];
+      for (var i = 0; i < _result.length; ++i) {
+        retval.push(self.get(String(_result[i])));
+      }
+      //TODO: Move sorting to native code
+      retval = C.sort(retval, args.sortMode);
+      args.successCallback(retval);
+    } else {
+      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+    }
+  };
+
+  var result = native_.call('ContactManager_find', data, callback);
+
+  _checkError(result);
+};
+
+// Subscribes to receive notifications about persons' changes.
+ContactManager.prototype.addChangeListener = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.CONTACT_READ);
+
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'successCallback',
+      type: types_.LISTENER,
+      values: ['onpersonsadded', 'onpersonsupdated', 'onpersonsremoved'],
+      optional: false,
+      nullable: false
+    }
+  ]);
+
+  if (type_.isEmptyObject(_personCallbackMap)) {
+    var result = native_.callSync('ContactManager_startListening', {});
+
+    if (native_.isFailure(result)) {
+      throw native_.getErrorObject(result);
+    }
+  }
+
+  if (!_personListenerRegistered) {
+    native_.addListener('ContactPersonChangeListener', _personChangeListener);
+    _personListenerRegistered = true;
+  }
+
+  var currentWatchId = _getNextWatchId();
+
+  _personCallbackMap[currentWatchId] = args.successCallback;
+
+  return currentWatchId;
+};
+
+// Unsubscribes a persons' changes watch operation.
+ContactManager.prototype.removeChangeListener = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.CONTACT_READ);
+
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'watchId',
+      type: types_.LONG,
+      optional: false,
+      nullable: false
+    }
+  ]);
+
+  // This makes UTC_contact_removeChangeListenerPerson_N_001 pass.
+  // watch id's start at 1
+  if (args.watchId === 0) {
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+      'id is null or undefined');
+  }
+
+  if (args.watchId < 0) {
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+        'Negative watch id');
+  }
+
+  if (!_personCallbackMap.hasOwnProperty(args.watchId)) {
+    throw new WebAPIException(WebAPIException.NOT_FOUND_ERR,
+        'watch id not found');
+  }
+
+  delete _personCallbackMap[args.watchId];
+
+  if (type_.isEmptyObject(_personCallbackMap)) {
+    native_.removeListener('ContactPersonChangeListener', _personChangeListener);
+    _personListenerRegistered = false;
+
+    var result = native_.callSync('ContactManager_stopListening', {});
+
+    if (native_.isFailure(result)) {
+      throw native_.getErrorObject(result);
+    }
+  }
+};
+
+// exports /////////////////////////////////////////////////////////////////
+exports = new ContactManager();
diff --git a/webWidgetTCT_device/src/contact/js/person.js b/webWidgetTCT_device/src/contact/js/person.js
new file mode 100755 (executable)
index 0000000..6161f7b
--- /dev/null
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+var Person = function(data) {
+  validator_.isConstructorCall(this, Person);
+
+  var _id = '';
+  var _displayName = '';
+  var _contactCount = 0;
+  var _hasPhoneNumber = false;
+  var _hasEmail = false;
+  var _isFavorite = false;
+  var _displayContactId = '';
+
+  if (data.hasOwnProperty('id') && type_.isString(data.id)) {
+    _id = data.id;
+  }
+  if (data.hasOwnProperty('displayName') && type_.isString(data.displayName)) {
+    _displayName = data.displayName;
+  }
+  if (data.hasOwnProperty('contactCount') && type_.isNumber(data.contactCount)) {
+    _contactCount = data.contactCount;
+  }
+  if (data.hasOwnProperty('hasPhoneNumber') && type_.isBoolean(data.hasPhoneNumber)) {
+    _hasPhoneNumber = data.hasPhoneNumber;
+  }
+  if (data.hasOwnProperty('hasEmail') && type_.isBoolean(data.hasEmail)) {
+    _hasEmail = data.hasEmail;
+  }
+  if (data.hasOwnProperty('displayContactId') && type_.isString(data.displayContactId)) {
+    _displayContactId = data.displayContactId;
+  }
+  if (data.hasOwnProperty('isFavorite') && type_.isBoolean(data.isFavorite)) {
+    _isFavorite = data.isFavorite;
+  }
+
+  Object.defineProperties(this, {
+    id: {
+      get: function() {
+        return _id;
+      },
+      set: function(v) {
+        if (_editGuard.isEditEnabled()) {
+          _id = converter_.toString(v, false);
+        }
+      },
+      enumerable: true
+    },
+    displayName: {
+      get: function() {
+        return _displayName;
+      },
+      set: function(v) {
+        if (_editGuard.isEditEnabled()) {
+          _displayName = converter_.toString(v, false);
+        }
+      },
+      enumerable: true
+    },
+    contactCount: {
+      get: function() {
+        return _contactCount;
+      },
+      set: function(v) {
+        if (_editGuard.isEditEnabled()) {
+          _contactCount = converter_.toLong(v, false);
+        }
+      },
+      enumerable: true
+    },
+    hasPhoneNumber: {
+      get: function() {
+        return _hasPhoneNumber;
+      },
+      set: function(v) {
+        if (_editGuard.isEditEnabled()) {
+          _hasPhoneNumber = converter_.toBoolean(v, false);
+        }
+      },
+      enumerable: true
+    },
+    hasEmail: {
+      get: function() {
+        return _hasEmail;
+      },
+      set: function(v) {
+        if (_editGuard.isEditEnabled()) {
+          _hasEmail = converter_.toBoolean(v, false);
+        }
+      },
+      enumerable: true
+    },
+
+    isFavorite: {
+      get: function() {
+        return _isFavorite;
+      },
+      set: function(v) {
+        _isFavorite = converter_.toBoolean(v, false);
+      },
+      enumerable: true
+    },
+    photoURI: {
+      value: data.hasOwnProperty('photoURI') ? data.photoURI : null,
+      writable: true,
+      enumerable: true
+    },
+    ringtoneURI: {
+      value: data.hasOwnProperty('ringtoneURI') ? data.ringtoneURI : null,
+      writable: true,
+      enumerable: true
+    },
+    displayContactId: {
+      get: function() {
+        return _displayContactId;
+      },
+      set: function(v) {
+        _displayContactId = converter_.toString(v, false);
+      },
+      enumerable: true
+    }
+  });
+};
+
+// Aggregates another person to this person.
+Person.prototype.link = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.CONTACT_WRITE);
+
+  var args = validator_.validateArgs(arguments, [{
+    name: 'personId',
+    type: types_.STRING,
+    optional: false,
+    nullable: false
+  }]);
+
+  if (String(converter_.toLong(args.personId)) !== args.personId) {
+    // TCT: Person_link_personId_invalid
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR);
+  }
+
+  var result = native_.callSync('Person_link', {
+    // TODO move to only sending the person id (in all functions)
+    person: this,
+    id: args.personId
+  });
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+  var _this = this;
+  _editGuard.run(function() {
+    _this.contactCount = _this.contactCount + 1;
+  });
+};
+
+// Separates a contact from this person.
+Person.prototype.unlink = function(contactId) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.CONTACT_WRITE);
+
+  var args = validator_.validateArgs(arguments, [{
+    name: 'contactId',
+    type: types_.STRING,
+    optional: false,
+    nullable: false
+  }]);
+
+  if (String(converter_.toLong(args.contactId)) !== args.contactId) {
+    // TCT: Person_unlink_contactId_invalid
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR);
+  }
+
+  var result = native_.callSync('Person_unlink', {
+    // TODO move to only sending the person id (in all functions)
+    person: this,
+    id: args.contactId
+  });
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+  var _this = this;
+  return _editGuard.run(function() {
+    _this.contactCount = _this.contactCount - 1;
+    return new Person(native_.getResultObject(result));
+  });
+};
diff --git a/webWidgetTCT_device/src/contact/person.cc b/webWidgetTCT_device/src/contact/person.cc
new file mode 100755 (executable)
index 0000000..1490c2c
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2015 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 "contact/person.h"
+#include "common/converter.h"
+#include "common/platform_exception.h"
+#include "common/logger.h"
+
+namespace extension {
+namespace contact {
+namespace Person {
+
+using namespace common;
+
+static const PersonPropertyMap personPropertyMap = {
+    {"id", {_contacts_person.id, kPrimitiveTypeId}},
+    {"displayName", {_contacts_person.display_name, kPrimitiveTypeString}},
+    {"contactCount", {_contacts_person.link_count, kPrimitiveTypeLong}},
+    {"hasPhoneNumber",
+     {_contacts_person.has_phonenumber, kPrimitiveTypeBoolean}},
+    {"hasEmail", {_contacts_person.has_email, kPrimitiveTypeBoolean}},
+    {"isFavorite", {_contacts_person.is_favorite, kPrimitiveTypeBoolean}},
+    {"photoURI", {_contacts_person.image_thumbnail_path, kPrimitiveTypeString}},
+    {"ringtoneURI", {_contacts_person.ringtone_path, kPrimitiveTypeString}},
+    {"displayContactId",
+     {_contacts_person.display_contact_id, kPrimitiveTypeId}},
+};
+
+PlatformResult PersonLink(const JsonObject& args, JsonObject&) {
+  LoggerD("Enter");
+  PlatformResult status = ContactUtil::CheckDBConnection();
+  if (status.IsError()) return status;
+
+  long id = common::stol(FromJson<JsonString>(args, "id"));
+  long person_id = common::stol(FromJson<JsonString>(args, "person", "id"));
+
+  contacts_record_h contacts_record = nullptr;
+
+  int err = contacts_db_get_record(_contacts_person._uri, id, &contacts_record);
+  contacts_record_destroy(contacts_record, true);
+  contacts_record = nullptr;
+
+  if (CONTACTS_ERROR_NONE != err) {
+    LoggerW("Person was not found, error code: %d", err);
+    return PlatformResult(ErrorCode::NOT_FOUND_ERR, "Person not found");
+  }
+
+  err = contacts_person_link_person(person_id, id);
+
+  status =
+      ContactUtil::ErrorChecker(err, "Error during executing person link()");
+  if (status.IsError()) return status;
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult PersonUnlink(const JsonObject& args, JsonObject& out) {
+  LoggerD("Enter");
+  PlatformResult status = ContactUtil::CheckDBConnection();
+  if (status.IsError()) return status;
+
+  long contact_id = common::stol(FromJson<JsonString>(args, "id"));
+
+  contacts_record_h contacts_record = nullptr;
+  int error_code = contacts_db_get_record(_contacts_simple_contact._uri,
+                                          contact_id, &contacts_record);
+
+  if (CONTACTS_ERROR_NONE != error_code) {
+    contacts_record_destroy(contacts_record, true);
+    contacts_record = nullptr;
+    LoggerW("Contact not found, error code: %d", error_code);
+    return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Contact not found");
+  }
+
+  int contacts_person_id = 0;
+  error_code = contacts_record_get_int(
+      contacts_record, _contacts_simple_contact.person_id, &contacts_person_id);
+  contacts_record_destroy(contacts_record, true);
+  contacts_record = nullptr;
+
+  status = ContactUtil::ErrorChecker(error_code,
+                                     "Contact is not a member of person");
+  if (status.IsError()) return status;
+
+  long person_id = common::stol(FromJson<JsonString>(args, "person", "id"));
+  if (contacts_person_id != person_id) {
+    LoggerW("Contact is not a member of person (wrong id's)");
+    return PlatformResult(ErrorCode::INVALID_VALUES_ERR,
+                          "Contact is not a member of person");
+  }
+
+  int new_person_id = 0;
+
+  error_code =
+      contacts_person_unlink_contact(person_id, contact_id, &new_person_id);
+
+  status =
+      ContactUtil::ErrorChecker(error_code, "Error during executing unlink()");
+  if (status.IsError()) return status;
+
+  error_code = contacts_db_get_record(_contacts_person._uri, new_person_id,
+                                      &contacts_record);
+  if (CONTACTS_ERROR_NONE != error_code) {
+    contacts_record_destroy(contacts_record, true);
+    contacts_record = nullptr;
+    LoggerW("Person not found, error code: %d", error_code);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Person not found");
+  }
+
+  status = ContactUtil::ImportPersonFromContactsRecord(contacts_record, &out);
+  if (status.IsError()) return status;
+
+  contacts_record_destroy(contacts_record, true);
+  contacts_record = nullptr;
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult PersonPropertyFromString(const std::string& name,
+                                        PersonProperty* person_prop) {
+  LoggerD("Enter");
+  auto iter = personPropertyMap.find(name);
+  if (iter == personPropertyMap.end()) {
+    LoggerE("Invalid property name (not in map): %s", name.c_str());
+    return PlatformResult(ErrorCode::INVALID_VALUES_ERR,
+                          "Invalid property name");
+  }
+  (*person_prop).propertyId = iter->second.propertyId;
+  (*person_prop).type = iter->second.type;
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+}  // Person
+}  // contact
+}  // extension
diff --git a/webWidgetTCT_device/src/contact/person.h b/webWidgetTCT_device/src/contact/person.h
new file mode 100755 (executable)
index 0000000..d71b2ed
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2015 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 CONTACT_PERSON_H_
+#define CONTACT_PERSON_H_
+
+#include "common/picojson.h"
+#include "contact/contact_util.h"
+
+namespace extension {
+namespace contact {
+
+enum PrimitiveType {
+  kPrimitiveTypeBoolean,
+  kPrimitiveTypeString,
+  kPrimitiveTypeLong,
+  kPrimitiveTypeId
+};
+
+namespace Person {
+
+struct PersonProperty {
+  unsigned int propertyId;
+  PrimitiveType type;
+};
+
+typedef std::map<std::string, PersonProperty> PersonPropertyMap;
+
+common::PlatformResult PersonPropertyFromString(const std::string& name,
+                                                PersonProperty* person_prop);
+
+common::PlatformResult PersonLink(const JsonObject& args, JsonObject&);
+common::PlatformResult PersonUnlink(const JsonObject& args, JsonObject&);
+
+}  // Person
+}  // contact
+}  // extension
+
+#endif  // CONTACT_PERSON_H
diff --git a/webWidgetTCT_device/src/content/content.gyp b/webWidgetTCT_device/src/content/content.gyp
new file mode 100755 (executable)
index 0000000..9cc2f8c
--- /dev/null
@@ -0,0 +1,37 @@
+{
+  'includes':[
+    '../common/common.gypi',
+  ],
+  'targets': [
+    {
+      'target_name': 'tizen_content',
+      'type': 'loadable_module',
+      'dependencies': [
+        '../common/common.gyp:tizen_common',
+      ],
+      'sources': [
+        'content_api.js',
+        'content_extension.cc',
+        'content_extension.h',
+        'content_filter.cc',
+        'content_filter.h',
+        'content_instance.cc',
+        'content_instance.h',
+        'content_manager.h',
+        'content_manager.cc',
+      ],
+      'conditions': [
+        ['tizen == 1', {
+          'variables': {
+            'packages': [
+              'capi-content-media-content',
+              'capi-media-metadata-extractor',
+              'capi-base-common',
+              'dlog',
+            ]
+          },
+        }],
+      ],
+    },
+  ],
+}
diff --git a/webWidgetTCT_device/src/content/content_api.js b/webWidgetTCT_device/src/content/content_api.js
new file mode 100755 (executable)
index 0000000..688c929
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+//= require('common.js');
+//= require('datatypes.js');
+//= require('manager.js');
+//= require('playlist.js');
diff --git a/webWidgetTCT_device/src/content/content_extension.cc b/webWidgetTCT_device/src/content/content_extension.cc
new file mode 100755 (executable)
index 0000000..ae072b7
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2015 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 "content/content_extension.h"
+
+#include "content/content_instance.h"
+
+// This will be generated from content_api.js
+extern const char kSource_content_api[];
+
+common::Extension* CreateExtension() {
+  return new ContentExtension;
+}
+
+ContentExtension::ContentExtension() {
+  SetExtensionName("tizen.content");
+  SetJavaScriptAPI(kSource_content_api);
+}
+
+ContentExtension::~ContentExtension() {}
+
+common::Instance* ContentExtension::CreateInstance() {
+  return new extension::content::ContentInstance;
+}
\ No newline at end of file
diff --git a/webWidgetTCT_device/src/content/content_extension.h b/webWidgetTCT_device/src/content/content_extension.h
new file mode 100755 (executable)
index 0000000..9e58cef
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2015 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 CONTENT_CONTENT_EXTENSION_H_
+#define CONTENT_CONTENT_EXTENSION_H_
+
+#include "common/extension.h"
+
+class ContentExtension : public common::Extension {
+ public:
+  ContentExtension();
+  virtual ~ContentExtension();
+
+ private:
+  virtual common::Instance* CreateInstance();
+};
+
+#endif // CONTENT_CONTENT_EXTENSION_H_
diff --git a/webWidgetTCT_device/src/content/content_filter.cc b/webWidgetTCT_device/src/content/content_filter.cc
new file mode 100755 (executable)
index 0000000..bb0f558
--- /dev/null
@@ -0,0 +1,255 @@
+/*
+ * Copyright (c) 2015 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 "content/content_filter.h"
+
+#include <vector>
+
+#include "common/converter.h"
+#include "common/logger.h"
+
+using common::AttributeMatchFlag;
+using common::CompositeFilterType;
+using common::ErrorCode;
+using common::JsonCast;
+using common::PlatformResult;
+
+namespace extension {
+namespace content {
+
+namespace {
+
+std::map<std::string, std::string> const attributeNameMap = {
+    {"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"},
+    {"geolocation.latitude", "MEDIA_LATITUDE"},
+    {"geolocation.longitude", "MEDIA_LONGITUDE"},
+    {"duration", "MEDIA_DURATION"},
+    {"album", "MEDIA_ALBUM"},
+    {"artists", "MEDIA_ARTIST"},
+    {"width", "MEDIA_WIDTH"},
+    {"height", "MEDIA_HEIGHT"},
+    {"genres", "MEDIA_GENRE"},
+    {"size", "MEDIA_SIZE"},
+};
+
+std::string escapeValueString(const std::string& data) {
+  LoggerD("Enter");
+  std::string out;
+  // If string won't be resized, then it will be faster
+  out.reserve(data.size());
+  for (auto c : data) {
+    if (c == '\\')
+      out += "\\\\";
+    else if (c == '\"')
+      out += "\\\"";
+    else if (c == '\'')
+      out += "\\\'";
+    else if (c == '\n')
+      out += "\\\n";
+    else if (c == '\r')
+      out += "\\\r";
+    else
+      out += c;
+  }
+  return out;
+}
+
+}  // namespace
+
+PlatformResult ContentFilter::MapField(const std::string& name,
+                                       std::string* result) {
+  LoggerD("Enter");
+  auto it = attributeNameMap.find(name);
+  if (it != attributeNameMap.end())
+    *result = it->second;
+  else
+  {
+    LoggerE("INVALID_VALUES_ERR");
+    return PlatformResult(ErrorCode::INVALID_VALUES_ERR);
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult ContentFilter::BuildQuery(const picojson::object& jsFilter,
+                                         std::string* queryToCall) {
+  LoggerD("Enter");
+  std::vector<std::vector<std::string> > partialqueries;
+  partialqueries.push_back(std::vector<std::string>());
+
+  visitor.SetOnAttributeFilter([&](const std::string& name,
+                                   AttributeMatchFlag match_flag,
+                                   const picojson::value& match_value) {
+    LoggerD("entered OnAttributeFilter");
+
+
+    std::string query;
+    std::string matchValue;
+
+    PlatformResult result = MapField(name, &query);
+    if (!result)
+      return result;
+
+    if (AttributeMatchFlag::kExactly == match_flag ||
+        AttributeMatchFlag::kFullString == match_flag) {
+      query += " = ";
+    } else if (AttributeMatchFlag::kContains == match_flag ||
+               AttributeMatchFlag::kStartsWith == match_flag ||
+               AttributeMatchFlag::kEndsWith == match_flag) {
+      query += " LIKE ";
+    } else if (AttributeMatchFlag::kExists == match_flag) {
+      query += " IS NOT NULL ";
+    } else {
+      LoggerE("INVALID_VALUES_ERR");
+      return PlatformResult(ErrorCode::INVALID_VALUES_ERR);
+    }
+    if (AttributeMatchFlag::kExists != match_flag) {
+      query.append("\"");
+      matchValue = escapeValueString(JsonCast<std::string>(match_value));
+      if (name == "type") {
+        if (matchValue == "IMAGE") {
+          matchValue = "0";
+        } else if (matchValue == "VIDEO") {
+          matchValue = "1";
+        } else if (matchValue == "AUDIO") {
+          matchValue = "3";
+        } else {  // OTHER
+          matchValue = "4";
+        }
+      } else if (name == "contentURI") {
+        const char* uri_prefix = "file://";
+        size_t found = matchValue.find(uri_prefix);
+        if (found != std::string::npos) {
+          //simple convertion of URI to globalpath
+          matchValue = matchValue.substr(found + strlen(uri_prefix));
+        }
+      }
+      switch (match_flag) {
+        case AttributeMatchFlag::kStartsWith :
+          query += matchValue + "%";
+          break;
+        case AttributeMatchFlag::kEndsWith :
+          query += "%" + matchValue;
+          break;
+        case AttributeMatchFlag::kContains :
+          query += "%" + matchValue + "%";
+          break;
+        default :
+          query += matchValue;
+      }
+      query.append("\"");
+    }
+
+    partialqueries.back().push_back(query);
+
+    return result;
+  });
+
+  visitor.SetOnCompositeFilterBegin([&](CompositeFilterType type) {
+    LoggerD("entered OnCompositeFilterBegin");
+    partialqueries.push_back(std::vector<std::string>());
+    return PlatformResult(ErrorCode::NO_ERROR);
+  });
+
+  visitor.SetOnCompositeFilterEnd([&](CompositeFilterType calType) {
+    LoggerD("entered OnCompositeFilterEnd");
+    std::string finalQuery;
+    std::string separator;
+
+    if (CompositeFilterType::kUnion == calType)
+      separator = " OR ";
+    else
+      separator = " AND ";
+
+    if (partialqueries.back().empty()) {
+      partialqueries.pop_back();
+      return PlatformResult(ErrorCode::NO_ERROR);
+    }
+    if (partialqueries.back().size() != 1)
+      finalQuery.append("(");
+
+    for (unsigned long i = 0; i < partialqueries.back().size(); i++) {
+      finalQuery += partialqueries.back().at(i);
+      if (i != partialqueries.back().size() - 1) {
+        finalQuery += separator;
+      }
+    }
+
+    if (partialqueries.back().size() != 1)
+      finalQuery.append(")");
+    partialqueries.pop_back();
+    partialqueries.back().push_back(finalQuery);
+
+    return PlatformResult(ErrorCode::NO_ERROR);
+  });
+
+  visitor.SetOnAttributeRangeFilter([&](const std::string& name,
+                                        const picojson::value& initial_value,
+                                        const picojson::value& end_value) {
+    LoggerD("entered OnAttributeFilter");
+
+    std::string query = "";
+    std::string paramName;
+    PlatformResult result = MapField(name, &paramName);
+    if (!result)
+      return result;
+
+    std::string initialValue = escapeValueString(JsonCast<std::string>(initial_value));
+    std::string endValue = escapeValueString(JsonCast<std::string>(end_value));
+    query += paramName;
+    query += " >= \"";
+    query += initialValue;
+    query += "\" AND ";
+    query += paramName;
+    query += " <= \"";
+    query += endValue;
+    query += "\"";
+    partialqueries.back().push_back(query);
+
+    return result;
+  });
+
+  if (!visitor.Visit(jsFilter)) {
+    LoggerE("INVALID_VALUES_ERR");
+    return PlatformResult(ErrorCode::INVALID_VALUES_ERR);
+  }
+
+  if (partialqueries.empty()) {
+    LoggerE("Filter parsing error!");
+    return PlatformResult(ErrorCode::SYNTAX_ERR);
+  }
+  if (partialqueries.back().empty()) {
+    LoggerD("Resolved to empty string!");
+    *queryToCall = "";
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+
+  *queryToCall = partialqueries.back().front();
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+}  // namespace content
+}  // namespace extension
diff --git a/webWidgetTCT_device/src/content/content_filter.h b/webWidgetTCT_device/src/content/content_filter.h
new file mode 100755 (executable)
index 0000000..c68c151
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2015 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 CONTENT_FILTER_H_
+#define CONTENT_FILTER_H_
+
+#include <media_content.h>
+#include <string>
+
+#include "common/filter-utils.h"
+#include "common/picojson.h"
+#include "common/platform_result.h"
+
+namespace extension {
+namespace content {
+
+class ContentFilter {
+ public:
+  static common::PlatformResult MapField(const std::string& name,
+                                         std::string* result);
+  common::PlatformResult BuildQuery(const picojson::object& jsFilter,
+                                    std::string* query);
+
+ private:
+  common::FilterVisitor visitor;
+};
+}
+}
+
+#endif
diff --git a/webWidgetTCT_device/src/content/content_instance.cc b/webWidgetTCT_device/src/content/content_instance.cc
new file mode 100755 (executable)
index 0000000..f50e5d2
--- /dev/null
@@ -0,0 +1,774 @@
+/*
+ * Copyright (c) 2015 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 "content/content_instance.h"
+
+#include <functional>
+#include <string>
+#include <dlog.h>
+#include <glib.h>
+#include <memory>
+#include <media_content.h>
+
+#include "common/logger.h"
+#include "common/picojson.h"
+#include "common/platform_result.h"
+#include "common/task-queue.h"
+#include "content/content_manager.h"
+
+namespace extension {
+namespace content {
+
+using common::tools::ReportSuccess;
+using common::tools::ReportError;
+
+ContentInstance::ContentInstance() :
+    noti_handle_(nullptr),
+    listener_data_(nullptr) {
+  using std::placeholders::_1;
+  using std::placeholders::_2;
+
+  #define REGISTER_SYNC(c,x) \
+    RegisterSyncHandler(c, std::bind(&ContentInstance::x, this, _1, _2));
+
+  REGISTER_SYNC("ContentManager_find", ContentManagerFind);
+  REGISTER_SYNC("ContentManager_update", ContentManagerUpdate);
+  REGISTER_SYNC("ContentManager_scanFile", ContentManagerScanfile);
+  REGISTER_SYNC("ContentManager_scanDirectory", ContentManagerScanDirectory);
+  REGISTER_SYNC("ContentManager_cancelScanDirectory", ContentManagerCancelScanDirectory);
+  REGISTER_SYNC("ContentManager_unsetChangeListener", ContentManagerUnsetchangelistener);
+  REGISTER_SYNC("ContentManager_setChangeListener", ContentManagerSetchangelistener);
+  REGISTER_SYNC("ContentManager_getDirectories", ContentManagerGetdirectories);
+  REGISTER_SYNC("ContentManager_updateBatch", ContentManagerUpdatebatch);
+  REGISTER_SYNC("ContentManager_removePlaylist", ContentManagerRemoveplaylist);
+  REGISTER_SYNC("ContentManager_createPlaylist", ContentManagerCreateplaylist);
+  REGISTER_SYNC("ContentManager_getPlaylists", ContentManagerGetplaylists);
+  REGISTER_SYNC("ContentPlaylist_add", ContentManagerPlaylistAdd);
+  REGISTER_SYNC("ContentPlaylist_addBatch", ContentManagerPlaylistAddbatch);
+  REGISTER_SYNC("ContentPlaylist_get", ContentManagerPlaylistGet);
+  REGISTER_SYNC("ContentPlaylist_remove", ContentManagerPlaylistRemove);
+  REGISTER_SYNC("ContentPlaylist_removeBatch", ContentManagerPlaylistRemovebatch);
+  REGISTER_SYNC("ContentPlaylist_setOrder", ContentManagerPlaylistSetorder);
+  REGISTER_SYNC("ContentPlaylist_move", ContentManagerPlaylistMove);
+  REGISTER_SYNC("ContentManager_getLyrics", ContentManagerAudioGetLyrics);
+
+  REGISTER_SYNC("ContentPlaylist_getName", PlaylistGetName);
+  REGISTER_SYNC("ContentPlaylist_setName", PlaylistSetName);
+  REGISTER_SYNC("ContentPlaylist_getThumbnailUri", PlaylistGetThumbnailUri);
+  REGISTER_SYNC("ContentPlaylist_setThumbnailUri", PlaylistSetThumbnailUri);
+  REGISTER_SYNC("ContentPlaylist_getNumberOfTracks", PlaylistGetNumberOfTracks);
+  #undef REGISTER_SYNC
+}
+
+ContentInstance::~ContentInstance() {
+  LoggerD("entered");
+  if (noti_handle_) {
+    media_content_unset_db_updated_cb_v2(noti_handle_);
+    noti_handle_ = nullptr;
+  }
+  if (listener_data_) {
+    delete listener_data_;
+    listener_data_ = nullptr;
+  }
+}
+
+static gboolean CompletedCallback(const std::shared_ptr<ReplyCallbackData>& user_data) {
+  LoggerD("entered");
+
+  picojson::object out;
+  out["callbackId"] = picojson::value(user_data->callbackId);
+
+  if (user_data->isSuccess) {
+    ReportSuccess(user_data->result, out);
+  } else {
+    LoggerE("Failed: user_data->isSuccess");
+    ReportError(user_data->isSuccess, &out);
+  }
+
+  common::Instance::PostMessage(user_data->instance, picojson::value(out).serialize().c_str());
+
+  return false;
+}
+
+static void* WorkThread(const std::shared_ptr<ReplyCallbackData>& user_data) {
+  LoggerD("entered");
+
+  int ret = MEDIA_CONTENT_ERROR_NONE;
+  ContentCallbacks cbType = user_data->cbType;
+  switch(cbType) {
+    case ContentManagerUpdatebatchCallback: {
+      ret = ContentManager::getInstance()->updateBatch(user_data->args);
+      if(ret != MEDIA_CONTENT_ERROR_NONE){
+          LoggerD("UpdateBatch Failed");
+          user_data->isSuccess = ContentManager::getInstance()->convertError(ret);
+      }
+      break;
+    }
+    case ContentManagerGetdirectoriesCallback: {
+      ContentManager::getInstance()->getDirectories(user_data);
+      break;
+    }
+    case ContentManagerFindCallback: {
+      ContentManager::getInstance()->find(user_data);
+      break;
+    }
+    case ContentManagerScanfileCallback: {
+      std::string contentURI = user_data->args.get("contentURI").get<std::string>();
+      std::string real_path = ContentManager::getInstance()->fs_provider_.GetRealPath(contentURI);
+      int res = ContentManager::getInstance()->scanFile(real_path);
+      if (res != MEDIA_CONTENT_ERROR_NONE) {
+        LOGGER(ERROR) << "Scan file failed, error: " << res;
+        common::PlatformResult err(common::ErrorCode::UNKNOWN_ERR, "Scan file failed.");
+        user_data->isSuccess = err;
+      }
+      break;
+    }
+    case ContentManagerGetplaylistsCallback: {
+      ContentManager::getInstance()->getPlaylists(user_data);
+      break;
+    }
+    case ContentManagerCreateplaylistCallback: {
+      if (user_data->args.contains("sourcePlaylist")) {
+        picojson::object playlist = user_data->args.get("sourcePlaylist").get<picojson::object>();
+        user_data->result = picojson::value(playlist);
+      }
+      else{
+        std::string name = user_data->args.get("name").get<std::string>();
+        ContentManager::getInstance()->createPlaylist(name, user_data);
+      }
+      break;
+    }
+    case ContentManagerRemoveplaylistCallback: {
+      std::string id = user_data->args.get("id").get<std::string>();
+      ContentManager::getInstance()->removePlaylist(id, user_data);
+      // do something...
+      break;
+    }
+    case ContentManagerPlaylistAddbatchCallback: {
+      ContentManager::getInstance()->playlistAddbatch(user_data);
+      break;
+    }
+    case ContentManagerPlaylistGetCallback: {
+      ContentManager::getInstance()->playlistGet(user_data);
+      break;
+    }
+    case ContentManagerPlaylistRemovebatchCallback: {
+      ContentManager::getInstance()->playlistRemovebatch(user_data);
+      break;
+    }
+    case ContentManagerPlaylistSetOrderCallback: {
+      ContentManager::getInstance()->playlistSetOrder(user_data);
+      break;
+      //ContentManagerPlaylistSetOrderCallback
+    }
+    case ContentManagerPlaylistMoveCallback: {
+      ContentManager::getInstance()->playlistMove(user_data);
+      break;
+    }
+    case ContentManagerErrorCallback: {
+      common::PlatformResult err(common::ErrorCode::UNKNOWN_ERR, "DB Connection is failed.");
+      user_data->isSuccess = err;
+      break;
+    }
+    default: {
+      LoggerE("Invalid Callback Type");
+      return NULL;
+    }
+  }
+  return NULL;
+}
+
+
+static void ScanDirectoryCallback(media_content_error_e error, void* user_data) {
+  LoggerD("Enter");
+
+  ReplyCallbackData* cbData = (ReplyCallbackData*) user_data;
+
+  picojson::object out;
+  out["callbackId"] = picojson::value(cbData->callbackId);
+
+  if (error == MEDIA_CONTENT_ERROR_NONE) {
+    ReportSuccess(out);
+  } else {
+    LoggerE("Scanning directory failed (error = %d)", error);
+    ReportError(out);
+  }
+
+  common::Instance::PostMessage(cbData->instance, picojson::value(out).serialize().c_str());
+}
+
+
+static void changedContentCallback(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) {
+  LoggerD("Entered file change callback");
+
+  if (error != MEDIA_CONTENT_ERROR_NONE) {
+    LOGGER(ERROR) << "Media content changed callback error: " << error;
+    return;
+  }
+
+  if (update_item == MEDIA_ITEM_FILE) {
+    if (!uuid) {
+      LOGGER(ERROR) << "Provided uuid is NULL, ignoring";
+      return;
+    }
+
+    ReplyCallbackData* cbData = static_cast<ReplyCallbackData*>(user_data);
+
+    int ret;
+    picojson::value result = picojson::value(picojson::object());
+    picojson::object& obj = result.get<picojson::object>();
+
+    if (update_type == MEDIA_CONTENT_INSERT || update_type == MEDIA_CONTENT_UPDATE) {
+      media_info_h media = NULL;
+      ret = media_info_get_media_from_db(uuid, &media);
+      if (ret == MEDIA_CONTENT_ERROR_NONE && media != NULL) {
+        picojson::object o;
+
+        ContentToJson(media, o);
+        ReportSuccess(picojson::value(o), obj);
+
+        if (update_type == MEDIA_CONTENT_INSERT) {
+          obj["state"] = picojson::value("oncontentadded");
+        } else {
+          obj["state"] = picojson::value("oncontentupdated");
+        }
+
+        media_info_destroy(media);
+      }
+    } else {
+      ReportSuccess(picojson::value(std::string(uuid)), obj);
+      obj["state"] = picojson::value("oncontentremoved");
+    }
+
+    obj["listenerId"] = cbData->args.get("listenerId");
+    common::Instance::PostMessage(cbData->instance, result.serialize().c_str());
+  } else {
+    LOGGER(DEBUG) << "Media item is not a file, skipping.";
+    return;
+  }
+}
+
+static void changedContentV2Callback(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) {
+  LoggerD("Entered directory change callback");
+
+  if (error != MEDIA_CONTENT_ERROR_NONE) {
+    LOGGER(ERROR) << "Media content changed v2 callback error: " << error;
+    return;
+  }
+
+  if (update_item == MEDIA_ITEM_DIRECTORY) {
+    if (!uuid) {
+      LOGGER(ERROR) << "Provided uuid is NULL, ignoring";
+      return;
+    }
+
+    ReplyCallbackData* cbData = static_cast<ReplyCallbackData*>(user_data);
+
+    int ret;
+    picojson::value result = picojson::value(picojson::object());
+    picojson::object& obj = result.get<picojson::object>();
+
+    if (update_type == MEDIA_CONTENT_INSERT || update_type == MEDIA_CONTENT_UPDATE) {
+      media_folder_h folder = NULL;
+      ret = media_folder_get_folder_from_db(uuid, &folder);
+      if (ret == MEDIA_CONTENT_ERROR_NONE && folder != NULL) {
+        picojson::object o;
+
+        ContentDirToJson(folder, o);
+        ReportSuccess(picojson::value(o), obj);
+
+        if (update_type == MEDIA_CONTENT_INSERT) {
+          obj["state"] = picojson::value("oncontentdiradded");
+        } else {
+          obj["state"] = picojson::value("oncontentdirupdated");
+        }
+
+        media_folder_destroy(folder);
+      }
+    } else {
+      ReportSuccess(picojson::value(std::string(uuid)), obj);
+      obj["state"] = picojson::value("oncontentdirremoved");
+    }
+
+    obj["listenerId"] = cbData->args.get("listenerId");
+    common::Instance::PostMessage(cbData->instance, result.serialize().c_str());
+  } else {
+    LOGGER(DEBUG) << "Media item is not directory, skipping.";
+    return;
+  }
+}
+
+#define CHECK_EXIST(args, name, out) \
+  if (!args.contains(name)) {\
+    ReportError(common::PlatformResult(common::ErrorCode::TYPE_MISMATCH_ERR, (name" is required argument")), &out);\
+    return;\
+  }
+
+
+void ContentInstance::ContentManagerUpdate(const picojson::value& args, picojson::object& out) {
+  LoggerD("entered");
+  if (ContentManager::getInstance()->isConnected()) {
+    int ret = ContentManager::getInstance()->update(args);
+    if (ret != 0) {
+      LoggerE("Failed: ContentManager::getInstance()");
+      ReportError(ContentManager::getInstance()->convertError(ret), &out);
+    }
+  } else {
+    LoggerE("Failed: DB connection is failed");
+    ReportError(common::PlatformResult(common::ErrorCode::UNKNOWN_ERR, "DB connection is failed."), &out);
+  }
+}
+
+void ContentInstance::ContentManagerUpdatebatch(const picojson::value& args, picojson::object& out) {
+  LoggerD("entered");
+  double callbackId = args.get("callbackId").get<double>();
+
+  auto cbData = std::shared_ptr<ReplyCallbackData>(new ReplyCallbackData);
+  cbData->callbackId = callbackId;
+  cbData->instance = this;
+  cbData->args = args;
+
+  if(ContentManager::getInstance()->isConnected()) {
+    cbData->cbType = ContentManagerUpdatebatchCallback;
+  }
+  else {
+    cbData->cbType = ContentManagerErrorCallback;
+  }
+  common::TaskQueue::GetInstance().Queue<ReplyCallbackData>(WorkThread, CompletedCallback, cbData);
+}
+void ContentInstance::ContentManagerGetdirectories(const picojson::value& args, picojson::object& out) {
+  LoggerD("entered");
+  CHECK_EXIST(args, "callbackId", out)
+
+  double callbackId = args.get("callbackId").get<double>();
+  // implement it
+
+  auto cbData = std::shared_ptr<ReplyCallbackData>(new ReplyCallbackData);
+  cbData->callbackId = callbackId;
+  cbData->instance = this;
+
+  if(ContentManager::getInstance()->isConnected()) {
+    cbData->cbType = ContentManagerGetdirectoriesCallback;
+  }
+  else {
+    cbData->cbType = ContentManagerErrorCallback;
+  }
+  common::TaskQueue::GetInstance().Queue<ReplyCallbackData>(WorkThread, CompletedCallback, cbData);
+
+}
+void ContentInstance::ContentManagerFind(const picojson::value& args, picojson::object& out) {
+  LoggerD("entered");
+  CHECK_EXIST(args, "callbackId", out)
+
+  double callbackId = args.get("callbackId").get<double>();
+
+  auto cbData = std::shared_ptr<ReplyCallbackData>(new ReplyCallbackData);
+  cbData->callbackId = callbackId;
+  cbData->instance = this;
+  cbData->args = args;
+  if(ContentManager::getInstance()->isConnected()) {
+    cbData->cbType = ContentManagerFindCallback;
+  } else {
+    cbData->cbType = ContentManagerErrorCallback;
+  }
+
+  common::TaskQueue::GetInstance().Queue<ReplyCallbackData>(WorkThread, CompletedCallback, cbData);
+
+}
+
+void ContentInstance::ContentManagerScanfile(const picojson::value& args, picojson::object& out) {
+  LoggerD("entered");
+  CHECK_EXIST(args, "callbackId", out)
+  CHECK_EXIST(args, "contentURI", out)
+
+  double callbackId = args.get("callbackId").get<double>();
+  auto cbData = std::shared_ptr<ReplyCallbackData>(new ReplyCallbackData);
+  cbData->callbackId = callbackId;
+  cbData->instance = this;
+  cbData->args = args;
+  if(ContentManager::getInstance()->isConnected()) {
+    cbData->cbType = ContentManagerScanfileCallback;
+  }
+  else {
+    cbData->cbType = ContentManagerErrorCallback;
+  }
+  common::TaskQueue::GetInstance().Queue<ReplyCallbackData>(WorkThread, CompletedCallback, cbData);
+}
+
+
+void ContentInstance::ContentManagerScanDirectory(const picojson::value& args, picojson::object& out) {
+  LoggerD("Enter");
+  CHECK_EXIST(args, "callbackId", out)
+  CHECK_EXIST(args, "contentDirURI", out)
+  CHECK_EXIST(args, "recursive", out)
+
+  ReplyCallbackData* cbData = new ReplyCallbackData;
+  cbData->callbackId = args.get("callbackId").get<double>();
+  cbData->instance = this;
+  cbData->args = args;
+
+  common::PlatformResult result = ContentManager::getInstance()->scanDirectory(ScanDirectoryCallback, cbData);
+  if (result.IsError()) {
+    ReportError(result, &out);
+  }
+}
+
+
+void ContentInstance::ContentManagerCancelScanDirectory(const picojson::value& args, picojson::object& out) {
+  LoggerD("Enter");
+  CHECK_EXIST(args, "contentDirURI", out)
+  const std::string& content_dir_uri = args.get("contentDirURI").get<std::string>();
+
+  if (ContentManager::getInstance()->cancelScanDirectory(content_dir_uri).IsError()) {
+    ReportError(common::PlatformResult(common::ErrorCode::UNKNOWN_ERR, "Cancel scan directory failed"), &out);
+  }
+}
+
+
+void ContentInstance::ContentManagerSetchangelistener(const picojson::value& args,
+                                                      picojson::object& out) {
+  LoggerD("entered");
+  CHECK_EXIST(args, "listenerId", out)
+
+  if (!listener_data_) {
+    listener_data_ = new ReplyCallbackData();
+  }
+
+  listener_data_->instance = this;
+  listener_data_->args = args;
+  if (ContentManager::getInstance()->isConnected()) {
+    listener_data_->cbType = ContentManagerSetchangelistenerCallback;
+  } else {
+    listener_data_->cbType = ContentManagerErrorCallback;
+  }
+
+  if (ContentManager::getInstance()->setChangeListener(changedContentCallback,
+                                                       static_cast<void*>(listener_data_)).IsError()) {
+    ReportError(common::PlatformResult(common::ErrorCode::UNKNOWN_ERR, "The callback did not register properly"), &out);
+  }
+  if (ContentManager::getInstance()->setV2ChangeListener(&noti_handle_,
+                                                       changedContentV2Callback,
+                                                       static_cast<void*>(listener_data_)).IsError()) {
+    ReportError(common::PlatformResult(common::ErrorCode::UNKNOWN_ERR, "The callback did not register properly"), &out);
+  }
+}
+
+void ContentInstance::ContentManagerUnsetchangelistener(const picojson::value& args, picojson::object& out) {
+  LoggerD("entered");
+  if (ContentManager::getInstance()->unSetChangeListener().IsError()) {
+    LoggerD("unsuccesfull deregistering of callback");
+  }
+  if (ContentManager::getInstance()->unSetV2ChangeListener(&noti_handle_).IsError()) {
+    LoggerD("unsuccesfull deregistering of callback");
+  }
+}
+
+void ContentInstance::ContentManagerGetplaylists(const picojson::value& args, picojson::object& out) {
+  LoggerD("entered");
+  CHECK_EXIST(args, "callbackId", out)
+
+  double callbackId = args.get("callbackId").get<double>();
+
+  // implement it
+  std::shared_ptr<ReplyCallbackData>cbData(new ReplyCallbackData);
+
+  cbData->callbackId = callbackId;
+  cbData->instance = this;
+  cbData->args = args;
+  if(ContentManager::getInstance()->isConnected()) {
+    cbData->cbType = ContentManagerGetplaylistsCallback;
+  }
+  else {
+    cbData->cbType = ContentManagerErrorCallback;
+  }
+
+  common::TaskQueue::GetInstance().Queue<ReplyCallbackData>(WorkThread, CompletedCallback, cbData);
+
+}
+void ContentInstance::ContentManagerCreateplaylist(const picojson::value& args, picojson::object& out) {
+  LoggerD("entered");
+  CHECK_EXIST(args, "callbackId", out)
+  CHECK_EXIST(args, "name", out)
+
+  double callbackId = args.get("callbackId").get<double>();
+
+  auto cbData = std::shared_ptr<ReplyCallbackData>(new ReplyCallbackData);
+  cbData->callbackId = callbackId;
+  cbData->instance = this;
+  cbData->args = args;
+
+  if(ContentManager::getInstance()->isConnected()) {
+    cbData->cbType = ContentManagerCreateplaylistCallback;
+  }
+  else {
+    cbData->cbType = ContentManagerErrorCallback;
+  }
+
+  common::TaskQueue::GetInstance().Queue<ReplyCallbackData>(WorkThread, CompletedCallback, cbData);
+}
+void ContentInstance::ContentManagerRemoveplaylist(const picojson::value& args, picojson::object& out) {
+  LoggerD("entered");
+  double callbackId = args.get("callbackId").get<double>();
+
+  auto cbData = std::shared_ptr<ReplyCallbackData>(new ReplyCallbackData);
+  cbData->callbackId = callbackId;
+  cbData->instance = this;
+  cbData->args = args;
+
+  if(ContentManager::getInstance()->isConnected()) {
+    cbData->cbType = ContentManagerRemoveplaylistCallback;
+  }
+  else {
+    cbData->cbType = ContentManagerErrorCallback;
+  }
+
+  // implement it
+  common::TaskQueue::GetInstance().Queue<ReplyCallbackData>(WorkThread, CompletedCallback, cbData);
+
+}
+
+void ContentInstance::ContentManagerPlaylistAdd(const picojson::value& args, picojson::object& out) {
+  LoggerD("entered");
+  if(ContentManager::getInstance()->isConnected()) {
+    std::string playlist_id = args.get("playlistId").get<std::string>();
+    std::string content_id = args.get("contentId").get<std::string>();
+    int ret = ContentManager::getInstance()->playlistAdd(playlist_id, content_id);
+    if(ret != MEDIA_CONTENT_ERROR_NONE) {
+      ReportError(ContentManager::getInstance()->convertError(ret),&out);
+    }
+  }
+  else {
+    ReportError(common::PlatformResult(common::ErrorCode::UNKNOWN_ERR, "DB connection is failed."), &out);
+  }
+}
+
+void ContentInstance::ContentManagerPlaylistAddbatch(const picojson::value& args, picojson::object& out) {
+  LoggerD("entered");
+  double callbackId = args.get("callbackId").get<double>();
+
+  auto cbData = std::shared_ptr<ReplyCallbackData>(new ReplyCallbackData);
+  cbData->callbackId = callbackId;
+  cbData->instance = this;
+  cbData->args = args;
+
+  if(ContentManager::getInstance()->isConnected()) {
+    cbData->cbType = ContentManagerPlaylistAddbatchCallback;
+  }
+  else {
+    cbData->cbType = ContentManagerErrorCallback;
+  }
+  common::TaskQueue::GetInstance().Queue<ReplyCallbackData>(WorkThread, CompletedCallback, cbData);
+}
+
+
+void ContentInstance::ContentManagerPlaylistGet(const picojson::value& args, picojson::object& out) {
+  LoggerD("entered");
+  double callbackId = args.get("callbackId").get<double>();
+
+  auto cbData = std::shared_ptr<ReplyCallbackData>(new ReplyCallbackData);
+  cbData->callbackId = callbackId;
+  cbData->instance = this;
+  cbData->args = args;
+
+  if(ContentManager::getInstance()->isConnected()) {
+    cbData->cbType = ContentManagerPlaylistGetCallback;
+  }
+  else {
+    cbData->cbType = ContentManagerErrorCallback;
+  }
+  common::TaskQueue::GetInstance().Queue<ReplyCallbackData>(WorkThread, CompletedCallback, cbData);
+}
+
+void ContentInstance::ContentManagerPlaylistRemove(const picojson::value& args, picojson::object& out) {
+  LoggerD("entered");
+  if(ContentManager::getInstance()->isConnected()) {
+    std::string playlist_id = args.get("playlistId").get<std::string>();
+    int member_id = args.get("memberId").get<double>();
+    int ret = ContentManager::getInstance()->playlistRemove(playlist_id, member_id);
+    if(ret != MEDIA_CONTENT_ERROR_NONE) {
+      ReportError(ContentManager::getInstance()->convertError(ret),&out);
+    }
+  }
+  else {
+    ReportError(common::PlatformResult(common::ErrorCode::UNKNOWN_ERR, "DB connection is failed."), &out);
+  }
+}
+
+void ContentInstance::ContentManagerPlaylistRemovebatch(const picojson::value& args, picojson::object& out) {
+  LoggerD("entered");
+  double callbackId = args.get("callbackId").get<double>();
+
+  auto cbData = std::shared_ptr<ReplyCallbackData>(new ReplyCallbackData);
+  cbData->callbackId = callbackId;
+  cbData->instance = this;
+  cbData->args = args;
+
+  if(ContentManager::getInstance()->isConnected()) {
+    cbData->cbType = ContentManagerPlaylistRemovebatchCallback;
+  }
+  else {
+    cbData->cbType = ContentManagerErrorCallback;
+  }
+  common::TaskQueue::GetInstance().Queue<ReplyCallbackData>(WorkThread, CompletedCallback, cbData);
+}
+
+
+void ContentInstance::ContentManagerPlaylistSetorder(const picojson::value& args, picojson::object& out) {
+  LoggerD("entered");
+  double callbackId = args.get("callbackId").get<double>();
+
+  auto cbData = std::shared_ptr<ReplyCallbackData>(new ReplyCallbackData);
+  cbData->callbackId = callbackId;
+  cbData->instance = this;
+  cbData->args = args;
+
+  if(ContentManager::getInstance()->isConnected()) {
+    cbData->cbType = ContentManagerPlaylistSetOrderCallback;
+  }
+  else {
+    cbData->cbType = ContentManagerErrorCallback;
+  }
+  common::TaskQueue::GetInstance().Queue<ReplyCallbackData>(WorkThread, CompletedCallback, cbData);
+}
+
+void ContentInstance::ContentManagerPlaylistMove(const picojson::value& args, picojson::object& out) {
+  LoggerD("entered");
+  double callbackId = args.get("callbackId").get<double>();
+
+  auto cbData = std::shared_ptr<ReplyCallbackData>(new ReplyCallbackData);
+  cbData->callbackId = callbackId;
+  cbData->instance = this;
+  cbData->args = args;
+
+  if(ContentManager::getInstance()->isConnected()) {
+    cbData->cbType = ContentManagerPlaylistMoveCallback;
+  }
+  else {
+    cbData->cbType = ContentManagerErrorCallback;
+  }
+  common::TaskQueue::GetInstance().Queue<ReplyCallbackData>(WorkThread, CompletedCallback, cbData);
+}
+
+void ContentInstance::ContentManagerAudioGetLyrics(const picojson::value& args,
+                                                   picojson::object& out) {
+  LoggerD("entered");
+  LOGGER(DEBUG) << "entered";
+
+  picojson::object lyrics;
+  if (ContentManager::getInstance()->isConnected()) {
+    int ret = ContentManager::getInstance()->getLyrics(args, lyrics);
+    if (ret != MEDIA_CONTENT_ERROR_NONE) {
+      ReportError(ContentManager::getInstance()->convertError(ret), &out);
+    } else {
+      ReportSuccess(picojson::value(lyrics), out);
+    }
+  } else {
+    ReportError(common::PlatformResult(common::ErrorCode::UNKNOWN_ERR, "DB connection is failed."), &out);
+  }
+}
+
+void ContentInstance::PlaylistGetName(const picojson::value& args, picojson::object& out) {
+  LoggerD("entered");
+  int ret;
+  CHECK_EXIST(args, "id", out)
+  int id = static_cast<int>(args.get("id").get<double>());
+  std::string name;
+  ret = ContentManager::getInstance()->getPlaylistName(id, &name);
+  if(ret != MEDIA_CONTENT_ERROR_NONE) {
+    ReportError(ContentManager::getInstance()->convertError(ret), &out);
+  } else {
+    ReportSuccess(picojson::value(name),out);
+  }
+}
+
+void ContentInstance::PlaylistSetName(const picojson::value& args, picojson::object& out) {
+  LoggerD("entered");
+  int ret;
+  CHECK_EXIST(args, "id", out)
+  CHECK_EXIST(args, "name", out)
+  int id = static_cast<int>(args.get("id").get<double>());
+  std::string name = args.get("name").get<std::string>();
+  ret = ContentManager::getInstance()->setPlaylistName(id, name);
+  if(ret != MEDIA_CONTENT_ERROR_NONE) {
+    ReportError(ContentManager::getInstance()->convertError(ret), &out);
+  } else {
+    ReportSuccess(out);
+  }
+}
+
+void ContentInstance::PlaylistGetThumbnailUri(const picojson::value& args, picojson::object& out) {
+  LoggerD("entered");
+  int ret;
+  CHECK_EXIST(args, "id", out)
+  int id = static_cast<int>(args.get("id").get<double>());
+  std::string uri;
+  ret = ContentManager::getInstance()->getThumbnailUri(id, &uri);
+  if(ret != MEDIA_CONTENT_ERROR_NONE) {
+    ReportError(ContentManager::getInstance()->convertError(ret), &out);
+  } else {
+    ReportSuccess(picojson::value(uri),out);
+  }
+}
+
+void ContentInstance::PlaylistSetThumbnailUri(const picojson::value& args, picojson::object& out) {
+  LoggerD("entered");
+  int ret;
+  CHECK_EXIST(args, "id", out)
+  CHECK_EXIST(args, "uri", out)
+  int id = static_cast<int>(args.get("id").get<double>());
+  std::string uri = args.get("uri").get<std::string>();
+  ret = ContentManager::getInstance()->setThumbnailUri(id, uri);
+  if(ret != MEDIA_CONTENT_ERROR_NONE) {
+    ReportError(ContentManager::getInstance()->convertError(ret), &out);
+  } else {
+    ReportSuccess(out);
+  }
+}
+
+void ContentInstance::PlaylistGetNumberOfTracks(const picojson::value& args,
+                                                picojson::object& out) {
+  LoggerD("entered");
+  CHECK_EXIST(args, "id", out)
+  int id = static_cast<int>(args.get("id").get<double>());
+  int count = 0;
+  int ret = ContentManager::getInstance()->getNumberOfTracks(id, &count);
+  if (ret != MEDIA_CONTENT_ERROR_NONE) {
+    ReportError(ContentManager::getInstance()->convertError(ret), &out);
+  } else {
+    ReportSuccess(picojson::value(static_cast<double>(count)), out);
+  }
+}
+
+#undef CHECK_EXIST
+
+} // namespace content
+} // namespace extension
diff --git a/webWidgetTCT_device/src/content/content_instance.h b/webWidgetTCT_device/src/content/content_instance.h
new file mode 100755 (executable)
index 0000000..0025d2b
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2015 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 CONTENT_CONTENT_INSTANCE_H_
+#define CONTENT_CONTENT_INSTANCE_H_
+
+#include <media_content_internal.h>
+#include "common/extension.h"
+
+namespace extension {
+namespace content {
+
+enum ContentCallbacks {
+  ContentManagerFindCallback,
+  ContentManagerScanfileCallback,
+  ContentManagerUnsetchangelistenerCallback,
+  ContentManagerSetchangelistenerCallback,
+  ContentManagerGetdirectoriesCallback,
+  ContentManagerUpdatebatchCallback,
+  ContentManagerRemoveplaylistCallback,
+  ContentManagerCreateplaylistCallback,
+  ContentManagerGetplaylistsCallback,
+  ContentManagerPlaylistAddbatchCallback,
+  ContentManagerPlaylistGetCallback,
+  ContentManagerPlaylistRemovebatchCallback,
+  ContentManagerPlaylistSetOrderCallback,
+  ContentManagerPlaylistMoveCallback,
+  ContentManagerErrorCallback
+};
+
+class ContentInstance;
+
+typedef struct _ReplyCallbackData {
+  _ReplyCallbackData()
+      : instance(nullptr),
+        cbType(ContentManagerFindCallback),
+        callbackId(-1.0),
+        isSuccess(common::ErrorCode::NO_ERROR) {
+  }
+  ContentInstance* instance;
+  ContentCallbacks cbType;
+  double callbackId;
+  picojson::value args;
+  picojson::value result;
+  common::PlatformResult isSuccess;
+} ReplyCallbackData;
+
+class ContentInstance : public common::ParsedInstance {
+ public:
+  ContentInstance();
+  virtual ~ContentInstance();
+
+ private:
+  void ContentManagerUpdate(const picojson::value& args, picojson::object& out);
+  void ContentManagerUpdatebatch(const picojson::value& args, picojson::object& out);
+  void ContentManagerGetdirectories(const picojson::value& args, picojson::object& out);
+  void ContentManagerFind(const picojson::value& args, picojson::object& out);
+  void ContentManagerScanfile(const picojson::value& args, picojson::object& out);
+  void ContentManagerScanDirectory(const picojson::value& args, picojson::object& out);
+  void ContentManagerCancelScanDirectory(const picojson::value& args, picojson::object& out);
+  void ContentManagerSetchangelistener(const picojson::value& args, picojson::object& out);
+  void ContentManagerUnsetchangelistener(const picojson::value& args, picojson::object& out);
+  void ContentManagerGetplaylists(const picojson::value& args, picojson::object& out);
+  void ContentManagerCreateplaylist(const picojson::value& args, picojson::object& out);
+  void ContentManagerRemoveplaylist(const picojson::value& args, picojson::object& out);
+  void ContentManagerPlaylistAdd(const picojson::value& args, picojson::object& out);
+  void ContentManagerPlaylistAddbatch(const picojson::value& args, picojson::object& out);
+  void ContentManagerPlaylistGet(const picojson::value& args, picojson::object& out);
+  void ContentManagerPlaylistRemove(const picojson::value& args, picojson::object& out);
+  void ContentManagerPlaylistRemovebatch(const picojson::value& args, picojson::object& out);
+  void ContentManagerPlaylistSetorder(const picojson::value& args, picojson::object& out);
+  void ContentManagerPlaylistMove(const picojson::value& args, picojson::object& out);
+  void ContentManagerAudioGetLyrics(const picojson::value& args, picojson::object& out);
+
+  void PlaylistGetName(const picojson::value& args, picojson::object& out);
+  void PlaylistSetName(const picojson::value& args, picojson::object& out);
+  void PlaylistGetThumbnailUri(const picojson::value& args, picojson::object& out);
+  void PlaylistSetThumbnailUri(const picojson::value& args, picojson::object& out);
+  void PlaylistGetNumberOfTracks(const picojson::value& args, picojson::object& out);
+
+  media_content_noti_h noti_handle_;
+  ReplyCallbackData* listener_data_;
+};
+
+
+} // namespace content
+} // namespace extension
+
+#endif // CONTENT_CONTENT_INSTANCE_H_
diff --git a/webWidgetTCT_device/src/content/content_manager.cc b/webWidgetTCT_device/src/content/content_manager.cc
new file mode 100755 (executable)
index 0000000..e151b78
--- /dev/null
@@ -0,0 +1,1624 @@
+/*
+ * Copyright (c) 2015 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 "content/content_manager.h"
+
+#include <algorithm>
+#include <cstring>
+#include <map>
+#include <metadata_extractor.h>
+#include <sstream>
+#include <string>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "common/converter.h"
+#include "common/logger.h"
+#include "common/scope_exit.h"
+#include "content/content_filter.h"
+
+using namespace std;
+using namespace common;
+
+namespace extension {
+namespace content {
+
+namespace {
+static const std::string uri_prefix = "file://";
+static const std::string uri_absolute_prefix = "file:///";
+}
+
+const std::map<std::string, media_content_orientation_e> orientationMap = {
+    {"NORMAL", MEDIA_CONTENT_ORIENTATION_NORMAL},
+    {"FLIP_HORIZONTAL", MEDIA_CONTENT_ORIENTATION_HFLIP},
+    {"ROTATE_180", MEDIA_CONTENT_ORIENTATION_ROT_180},
+    {"FLIP_VERTICAL", MEDIA_CONTENT_ORIENTATION_VFLIP},
+    {"TRANSPOSE", MEDIA_CONTENT_ORIENTATION_TRANSPOSE},
+    {"ROTATE_90", MEDIA_CONTENT_ORIENTATION_ROT_90},
+    {"TRANSVERSE", MEDIA_CONTENT_ORIENTATION_TRANSVERSE},
+    {"ROTATE_270", MEDIA_CONTENT_ORIENTATION_ROT_270},
+};
+
+std::string get_date(char* tmpStr) {
+  LoggerD("Enter");
+  if (tmpStr) {
+    struct tm* result = (struct tm*) calloc(1, sizeof(struct tm));
+    if (nullptr != result) {
+      if (strptime(tmpStr, "%Y:%m:%d %H:%M:%S", result) == NULL) {
+        free(result);
+        return std::string();
+      } else {
+        time_t t = mktime(result);// + get_utc_offset() * 3600;
+        std::stringstream str_date;
+        str_date << t;
+        free(result);
+        return str_date.str();
+      }
+    }
+  }
+  return std::string();
+}
+
+void ContentToJson(media_info_h info, picojson::object& o) {
+  LoggerD("Enter");
+  int ret;
+  int tmpInt = 0;
+  bool tmpBool = false;
+  char* tmpStr = NULL;
+  time_t tmpDate;
+  double tmpDouble;
+  long long unsigned int tmpLong;
+  media_content_type_e type;
+
+  ret = media_info_get_media_type(info, &type);
+
+  if (ret != MEDIA_CONTENT_ERROR_NONE) {
+    LOGGER(ERROR) << "Get media type failed: " << ret;
+    type = MEDIA_CONTENT_TYPE_OTHERS;
+  }
+
+  if (type == MEDIA_CONTENT_TYPE_IMAGE) {
+    o["type"] = picojson::value(std::string("IMAGE"));
+    image_meta_h img;
+    if (MEDIA_CONTENT_ERROR_NONE == media_info_get_image(info, &img)) {
+      std::unique_ptr<std::remove_pointer<image_meta_h>::type, int(*)(image_meta_h)>
+          img_ptr(img, &image_meta_destroy); // automatically release the memory
+      if (MEDIA_CONTENT_ERROR_NONE == image_meta_get_date_taken(img, &tmpStr)) {
+        if (tmpStr) {
+          o["releaseDate"] = picojson::value(get_date(tmpStr));
+          free(tmpStr);
+          tmpStr = NULL;
+        }
+      }
+      if (MEDIA_CONTENT_ERROR_NONE == image_meta_get_width(img, &tmpInt)) {
+        o["width"] = picojson::value(static_cast<double>(tmpInt));
+      }
+      if (MEDIA_CONTENT_ERROR_NONE == image_meta_get_height(img, &tmpInt)) {
+        o["height"] = picojson::value(static_cast<double>(tmpInt));
+      }
+      picojson::object geo;
+      if (MEDIA_CONTENT_ERROR_NONE == media_info_get_latitude(info, &tmpDouble)) {
+        geo["latitude"] = picojson::value(tmpDouble);
+      }
+      if (MEDIA_CONTENT_ERROR_NONE == media_info_get_longitude(info, &tmpDouble)) {
+        geo["longitude"] = picojson::value(tmpDouble);
+      }
+      o["geolocation"] = picojson::value(geo);
+      std::string ori;
+      media_content_orientation_e orientation;
+      if (MEDIA_CONTENT_ERROR_NONE == image_meta_get_orientation(img, &orientation)) {
+        switch (orientation) {
+          case MEDIA_CONTENT_ORIENTATION_NOT_AVAILABLE:
+          case MEDIA_CONTENT_ORIENTATION_NORMAL:
+            ori = "NORMAL";
+            break;
+          case MEDIA_CONTENT_ORIENTATION_HFLIP:
+            ori = "FLIP_HORIZONTAL";
+            break;
+          case MEDIA_CONTENT_ORIENTATION_ROT_180:
+            ori = "ROTATE_180";
+            break;
+          case MEDIA_CONTENT_ORIENTATION_VFLIP:
+            ori = "FLIP_VERTICAL";
+            break;
+          case MEDIA_CONTENT_ORIENTATION_TRANSPOSE:
+            ori = "TRANSPOSE";
+            break;
+          case MEDIA_CONTENT_ORIENTATION_ROT_90:
+            ori = "ROTATE_90";
+            break;
+          case MEDIA_CONTENT_ORIENTATION_TRANSVERSE:
+            ori = "TRANSVERSE";
+            break;
+          case MEDIA_CONTENT_ORIENTATION_ROT_270:
+            ori = "ROTATE_270";
+            break;
+        }
+        o["orientation"] = picojson::value(ori);
+      }
+    }
+  } else if (type == MEDIA_CONTENT_TYPE_VIDEO) {
+    o["type"] = picojson::value(std::string("VIDEO"));
+    video_meta_h video;
+    if (MEDIA_CONTENT_ERROR_NONE == media_info_get_video(info, &video)) {
+      std::unique_ptr<std::remove_pointer<video_meta_h>::type, int(*)(video_meta_h)>
+          video_ptr(video, &video_meta_destroy); // automatically release the memory
+      if (MEDIA_CONTENT_ERROR_NONE == video_meta_get_width(video, &tmpInt)) {
+        o["width"] = picojson::value(static_cast<double>(tmpInt));
+      }
+
+      if (MEDIA_CONTENT_ERROR_NONE == video_meta_get_height(video, &tmpInt)) {
+        o["height"] = picojson::value(static_cast<double>(tmpInt));
+      }
+      if (MEDIA_CONTENT_ERROR_NONE == video_meta_get_artist(video, &tmpStr)) {
+        picojson::array artists;
+        if (tmpStr) {
+          artists.push_back(picojson::value(std::string(tmpStr)));
+          free(tmpStr);
+          tmpStr = NULL;
+        }
+        o["artists"] = picojson::value(artists);
+      }
+      if (MEDIA_CONTENT_ERROR_NONE == video_meta_get_album(video, &tmpStr)) {
+        if (tmpStr) {
+          o["album"] = picojson::value(tmpStr);
+          free(tmpStr);
+          tmpStr = NULL;
+        }
+      }
+      if (MEDIA_CONTENT_ERROR_NONE == video_meta_get_duration(video, &tmpInt)) {
+        o["duration"] = picojson::value(static_cast<double>(tmpInt));
+      }
+      if (MEDIA_CONTENT_ERROR_NONE == video_meta_get_recorded_date(video, &tmpStr)) {
+        if (tmpStr) {
+          o["releaseDate"] = picojson::value(get_date(tmpStr));
+          free(tmpStr);
+          tmpStr = NULL;
+        }
+      }
+    }
+    picojson::object geo;
+    if (MEDIA_CONTENT_ERROR_NONE == media_info_get_latitude(info, &tmpDouble)) {
+      geo["latitude"] = picojson::value(tmpDouble);
+    }
+    if (MEDIA_CONTENT_ERROR_NONE == media_info_get_longitude(info, &tmpDouble)) {
+      geo["longitude"] = picojson::value(tmpDouble);
+    }
+    o["geolocation"] = picojson::value(geo);
+  } else if (type == MEDIA_CONTENT_TYPE_SOUND || type == MEDIA_CONTENT_TYPE_MUSIC) {
+    o["type"] = picojson::value(std::string("AUDIO"));
+    audio_meta_h audio;
+    if (MEDIA_CONTENT_ERROR_NONE == media_info_get_audio(info, &audio)) {
+      std::unique_ptr<std::remove_pointer<audio_meta_h>::type, int(*)(audio_meta_h)>
+          audio_ptr(audio, &audio_meta_destroy); // automatically release the memory
+      if (MEDIA_CONTENT_ERROR_NONE == audio_meta_get_recorded_date(audio, &tmpStr)) {
+        if(tmpStr) {
+          o["releaseDate"] = picojson::value(get_date(tmpStr));
+          free(tmpStr);
+          tmpStr = NULL;
+        }
+      }
+      if (MEDIA_CONTENT_ERROR_NONE == audio_meta_get_album(audio, &tmpStr)) {
+        if (tmpStr) {
+          o["album"] = picojson::value(std::string(tmpStr));
+          free(tmpStr);
+          tmpStr = NULL;
+        }
+      }
+      if (MEDIA_CONTENT_ERROR_NONE == audio_meta_get_artist(audio, &tmpStr)) {
+        if (tmpStr) {
+          picojson::array artists;
+          artists.push_back(picojson::value(std::string(tmpStr)));
+          o["artists"] = picojson::value(artists);
+          free(tmpStr);
+          tmpStr = NULL;
+        }
+      }
+      if (MEDIA_CONTENT_ERROR_NONE == audio_meta_get_genre(audio, &tmpStr)) {
+        if (tmpStr) {
+          picojson::array genres;
+          genres.push_back(picojson::value(std::string(tmpStr)));
+          o["genres"] = picojson::value(genres);
+          free(tmpStr);
+          tmpStr = NULL;
+        }
+      }
+      if (MEDIA_CONTENT_ERROR_NONE == audio_meta_get_composer(audio, &tmpStr)) {
+        if (tmpStr) {
+          picojson::array composers;
+          composers.push_back(picojson::value(std::string(tmpStr)));
+          o["composers"] = picojson::value(composers);
+          free(tmpStr);
+          tmpStr = NULL;
+        }
+      }
+      if (MEDIA_CONTENT_ERROR_NONE == audio_meta_get_copyright(audio, &tmpStr)) {
+        if (tmpStr) {
+          o["copyright"] = picojson::value(std::string(tmpStr));
+          free(tmpStr);
+          tmpStr = NULL;
+        }
+      }
+      if (MEDIA_CONTENT_ERROR_NONE == audio_meta_get_bit_rate(audio, &tmpInt)) {
+        o["bitrate"] = picojson::value(static_cast<double>(tmpInt));
+      }
+      if (MEDIA_CONTENT_ERROR_NONE == audio_meta_get_track_num(audio, &tmpStr)) {
+        if (tmpStr) {
+          o["trackNumber"] = picojson::value(static_cast<double>(std::atoi(tmpStr)));
+          free(tmpStr);
+          tmpStr = NULL;
+        }
+        else {
+          o["trackNumber"] = picojson::value();
+        }
+      }
+      if (MEDIA_CONTENT_ERROR_NONE == audio_meta_get_duration(audio, &tmpInt)) {
+        o["duration"] = picojson::value(static_cast<double>(tmpInt));
+      }
+    }
+  } else {
+    o["type"] = picojson::value(std::string("OTHER"));
+  }
+
+  ret = media_info_get_media_id(info, &tmpStr);
+  if(ret == MEDIA_CONTENT_ERROR_NONE) {
+    if(tmpStr) {
+      o["id"] = picojson::value(std::string(tmpStr));
+      free(tmpStr);
+      tmpStr = NULL;
+    }
+  }
+  ret = media_info_get_display_name(info, &tmpStr);
+  if(ret == MEDIA_CONTENT_ERROR_NONE) {
+    if(tmpStr) {
+      o["name"] = picojson::value(std::string(tmpStr));
+      free(tmpStr);
+      tmpStr = NULL;
+    }
+  }
+
+  ret = media_info_get_mime_type(info, &tmpStr);
+  if(ret == MEDIA_CONTENT_ERROR_NONE) {
+    if(tmpStr) {
+      o["mimeType"] = picojson::value(std::string(tmpStr));
+      free(tmpStr);
+      tmpStr = NULL;
+    }
+  }
+  ret = media_info_get_title(info, &tmpStr);
+  if(ret == MEDIA_CONTENT_ERROR_NONE) {
+    if(tmpStr) {
+      o["title"] = picojson::value(std::string(tmpStr));
+      free(tmpStr);
+      tmpStr = NULL;
+    }
+  }
+  ret = media_info_get_file_path(info, &tmpStr);
+  if(ret == MEDIA_CONTENT_ERROR_NONE) {
+    if(tmpStr) {
+      o["contentURI"] = picojson::value(std::string(tmpStr));
+      free(tmpStr);
+      tmpStr = NULL;
+    }
+  }
+  ret = media_info_get_thumbnail_path(info, &tmpStr);
+  if(ret == MEDIA_CONTENT_ERROR_NONE) {
+    if(tmpStr) {
+      picojson::array thumbnails;
+      thumbnails.push_back(picojson::value(std::string(tmpStr)));
+      o["thumbnailURIs"] = picojson::value(thumbnails);
+      free(tmpStr);
+      tmpStr = NULL;
+    }
+  }
+  ret = media_info_get_description(info, &tmpStr);
+  if(ret == MEDIA_CONTENT_ERROR_NONE) {
+    if(tmpStr) {
+      o["description"] = picojson::value(std::string(tmpStr));
+      free(tmpStr);
+      tmpStr = NULL;
+    }
+  }
+  ret = media_info_get_rating(info, &tmpInt);
+  if(ret == MEDIA_CONTENT_ERROR_NONE) {
+    o["rating"] = picojson::value(static_cast<double>(tmpInt));
+  }
+  ret = media_info_get_size(info, &tmpLong);
+  if(ret == MEDIA_CONTENT_ERROR_NONE) {
+    o["size"] = picojson::value(static_cast<double>(tmpLong));
+  }
+  ret = media_info_get_favorite(info, &tmpBool);
+  if(ret == MEDIA_CONTENT_ERROR_NONE) {
+    o["isFavorite"] = picojson::value(tmpBool);
+  }
+  ret = media_info_get_modified_time(info, &tmpDate);
+  if(ret == MEDIA_CONTENT_ERROR_NONE) {
+    o["modifiedDate"] = picojson::value(static_cast<double>(tmpDate));
+  }
+}
+
+void ContentDirToJson(media_folder_h folder, picojson::object& o) {
+  LoggerD("Enter");
+  int ret;
+  char* tmpStr = NULL;
+  media_content_storage_e storage_type;
+  time_t tmpDate;
+
+  // id
+  ret = media_folder_get_folder_id(folder, &tmpStr);
+  if(ret == MEDIA_CONTENT_ERROR_NONE) {
+    if(tmpStr) {
+      o["id"] = picojson::value(std::string(tmpStr));
+      free(tmpStr);
+      tmpStr = NULL;
+    }
+  }
+
+  // directoryURI
+  ret = media_folder_get_path(folder, &tmpStr);
+  if(ret == MEDIA_CONTENT_ERROR_NONE) {
+    if(tmpStr) {
+      o["directoryURI"] = picojson::value(std::string(tmpStr));
+      free(tmpStr);
+      tmpStr = NULL;
+    }
+  }
+
+  // title
+  ret = media_folder_get_name(folder, &tmpStr);
+  if(ret == MEDIA_CONTENT_ERROR_NONE) {
+    if(tmpStr) {
+      o["title"] = picojson::value(std::string(tmpStr));
+      free(tmpStr);
+      tmpStr = NULL;
+    }
+  }
+
+  // storageType
+  ret = media_folder_get_storage_type(folder, &storage_type);
+  if(ret == MEDIA_CONTENT_ERROR_NONE) {
+    if (storage_type == MEDIA_CONTENT_STORAGE_INTERNAL) {
+      o["storageType"] = picojson::value(std::string("INTERNAL"));
+    } else if (storage_type == MEDIA_CONTENT_STORAGE_EXTERNAL) {
+      o["storageType"] = picojson::value(std::string("EXTERNAL"));
+    } else if (storage_type == MEDIA_CONTENT_STORAGE_CLOUD) {
+      o["storageType"] = picojson::value(std::string("CLOUD"));
+    }
+  }
+
+  // modifiedData
+  ret = media_folder_get_modified_time(folder, &tmpDate);
+  if(ret == MEDIA_CONTENT_ERROR_NONE) {
+    o["modifiedDate"] = picojson::value(static_cast<double>(tmpDate));
+  }
+}
+
+static int setContent(media_info_h media, const picojson::value& content) {
+  LoggerD("Enter");
+
+  int ret;
+  std::string name = content.get("name").to_str();
+  std::string description = content.get("description").to_str();
+  int rating = std::stoi(content.get("rating").to_str());
+  bool is_fav = content.get("isFavorite").get<bool>();
+
+  if (NULL == media) {
+    LoggerE("MEDIA_CONTENT_ERROR_DB_FAILED");
+    return MEDIA_CONTENT_ERROR_DB_FAILED;
+  }
+
+  media_content_type_e type;
+  ret = media_info_get_media_type(media, &type);
+  if (ret != MEDIA_CONTENT_ERROR_NONE) {
+    LoggerE("Failed: media_info_get_media_type()");
+    return ret;
+  }
+
+  ret = media_info_set_display_name(media, name.c_str());
+  if (ret != MEDIA_CONTENT_ERROR_NONE) {
+    LoggerE("Updating name failed.");
+  }
+
+  ret = media_info_set_description(media, description.c_str());
+  if (ret != MEDIA_CONTENT_ERROR_NONE) {
+    LoggerE("Updating description failed.");
+  }
+
+  ret = media_info_set_rating(media, rating);
+  if (ret != MEDIA_CONTENT_ERROR_NONE) {
+    LoggerE("Updating rating failed.");
+  }
+
+  ret = media_info_set_favorite(media, is_fav);
+  if (ret != MEDIA_CONTENT_ERROR_NONE) {
+    LoggerE("Updating isFavorite failed.");
+  }
+
+  if (ret != MEDIA_CONTENT_ERROR_NONE) {
+    LoggerE("Updating favorite failed.");
+  }
+
+  if (type == MEDIA_CONTENT_TYPE_IMAGE) {
+    std::string orientation = content.get("orientation").to_str();
+    auto orientationToSet = orientationMap.find(orientation);
+
+    if (orientationToSet != orientationMap.end()) {
+      image_meta_h img;
+      if (MEDIA_CONTENT_ERROR_NONE == media_info_get_image(media, &img) &&
+          MEDIA_CONTENT_ERROR_NONE == image_meta_set_orientation(img, orientationToSet->second) &&
+          MEDIA_CONTENT_ERROR_NONE == image_meta_update_to_db(img)) {
+        LoggerD("orientation update was successful");
+      } else {
+        LoggerE("orientation update failed");
+      }
+      image_meta_destroy(img);
+    }
+  }
+
+  if (type == MEDIA_CONTENT_TYPE_IMAGE || type == MEDIA_CONTENT_TYPE_VIDEO) {
+    picojson::value geo = content.get("geolocation");
+    if (geo.evaluate_as_boolean()) {
+      LoggerD("geolocation is not null");
+      double latitude = atof(geo.get("latitude").to_str().c_str());
+      double longitude = atof(geo.get("longitude").to_str().c_str());
+      ret = media_info_set_latitude(media, latitude);
+      if (ret != MEDIA_CONTENT_ERROR_NONE) {
+        LoggerE("Updating geolocation is failed.");
+      }
+      ret = media_info_set_longitude(media, longitude);
+      if (ret != MEDIA_CONTENT_ERROR_NONE) {
+        LoggerD("Updating geolocation is failed.");
+      }
+    } else {
+      LoggerD("geolocation is null");
+    }
+  }
+
+  return MEDIA_CONTENT_ERROR_NONE;
+}
+
+static void FolderToJson(media_folder_h folder, picojson::object* out) {
+  LoggerD("Enter");
+
+  char* name = NULL;
+  char* id = NULL;
+  char* path = NULL;
+  time_t date;
+  media_content_storage_e storageType;
+
+  int ret;
+
+  ret = media_folder_get_folder_id(folder, &id);
+  if(ret!=MEDIA_CONTENT_ERROR_NONE)
+  {
+    LoggerE("Failed: media_folder_get_folder_id");
+    common::tools::ReportError(ContentManager::convertError(ret), out);
+    return;
+  }
+
+  ret = media_folder_get_name(folder, &name);
+  if(ret!=MEDIA_CONTENT_ERROR_NONE)
+  {
+    LoggerE("Failed: media_folder_get_name");
+    common::tools::ReportError(ContentManager::convertError(ret), out);
+    free(id);
+    return;
+  }
+
+  ret = media_folder_get_path(folder, &path);
+  if(ret!=MEDIA_CONTENT_ERROR_NONE)
+  {
+    LoggerE("Failed: media_folder_get_path");
+    common::tools::ReportError(ContentManager::convertError(ret), out);
+    free(id);
+    free(name);
+    return;
+  }
+
+  ret = media_folder_get_modified_time(folder, &date);
+  if(ret!=MEDIA_CONTENT_ERROR_NONE)
+  {
+    LoggerE("Failed: media_folder_get_path");
+    common::tools::ReportError(ContentManager::convertError(ret), out);
+    free(id);
+    free(name);
+    free(path);
+    return;
+  }
+
+  ret = media_folder_get_storage_type(folder, &storageType);
+  if(ret!=MEDIA_CONTENT_ERROR_NONE)
+  {
+    free(id);
+    free(name);
+    free(path);
+    LoggerE("Failed: media_folder_get_storage_type");
+    common::tools::ReportError(ContentManager::convertError(ret), out);
+    return;
+  }
+
+
+  (*out)["id"] = picojson::value(std::string(id));
+  (*out)["directoryURI"] = picojson::value(std::string(path));
+  (*out)["title"] = picojson::value(std::string(name));
+
+  if (storageType == MEDIA_CONTENT_STORAGE_INTERNAL) {
+    (*out)["storageType"] = picojson::value(std::string("INTERNAL"));
+  } else if (storageType == MEDIA_CONTENT_STORAGE_EXTERNAL) {
+    (*out)["storageType"] = picojson::value(std::string("EXTERNAL"));
+  }
+
+  (*out)["modifiedDate"] = picojson::value(static_cast<double>(date));
+
+  free(name);
+  free(id);
+  free(path);
+}
+
+static bool media_foreach_directory_cb(media_folder_h folder, void *user_data) {
+  LoggerD("Enter");
+  picojson::array *array = static_cast<picojson::array*>(user_data);
+  picojson::object json;
+  FolderToJson(folder, &json);
+  array->push_back(picojson::value(json));
+  return true;
+}
+
+static bool media_foreach_content_cb(media_info_h media, void *user_data) {
+  LoggerD("Enter");
+  picojson::value::array *contents = static_cast<picojson::value::array*>(user_data);
+  picojson::value::object o;
+  ContentToJson(media, o);
+  contents->push_back(picojson::value(o));
+  return true;
+}
+
+static bool playlist_foreach_cb(media_playlist_h playlist, void *user_data) {
+
+  LoggerD("Enter");
+  picojson::value::array *playlists = static_cast<picojson::value::array*>(user_data);
+  picojson::value::object o;
+  if (playlist != NULL) {
+    int id,cnt;
+    char* thumb_path = NULL;
+    char* name = NULL;
+    filter_h filter = NULL;
+    if( media_playlist_get_playlist_id(playlist, &id) == MEDIA_CONTENT_ERROR_NONE) {
+      std::stringstream str_id;
+      str_id << id;
+      o["id"] = picojson::value(std::to_string(id));
+    }
+    else {
+      LoggerD("Invalid ID for playlist.");
+    }
+    if( media_playlist_get_thumbnail_path(playlist, &thumb_path) == MEDIA_CONTENT_ERROR_NONE) {
+      if (thumb_path != NULL) {
+        std::string thumbnail_uri (thumb_path);
+        if (thumbnail_uri != " ") {
+          thumbnail_uri = uri_prefix + thumbnail_uri;
+        }
+        o["thumbnailURI"] = picojson::value(thumbnail_uri);
+        free(thumb_path);
+      }
+      else {
+       o["thumbnailURI"] = picojson::value();//picojson::value(std::string(""));
+      }
+    }
+    else {
+      LoggerD("Invalid thumbnail path for playlist.");
+    }
+    if( media_playlist_get_name(playlist, &name) == MEDIA_CONTENT_ERROR_NONE) {
+      o["name"] = picojson::value(std::string(name));
+      free(name);
+    }
+    else {
+      LoggerD("Invalid name for playlist.");
+    }
+
+    media_filter_create(&filter);
+    std::unique_ptr<std::remove_pointer<filter_h>::type, int(*)(filter_h)>
+        filter_ptr(filter, &media_filter_destroy); // automatically release the memory
+    if( media_playlist_get_media_count_from_db(id, filter, &cnt) == MEDIA_CONTENT_ERROR_NONE) {
+      o["numberOfTracks"] = picojson::value(static_cast<double>(cnt));
+    }
+    else {
+      LoggerE("Invalid count for playlist.");
+    }
+    playlists->push_back(picojson::value(o));
+
+  }
+  return true;
+}
+
+static bool playlist_content_member_cb(int playlist_member_id, media_info_h media, void *user_data) {
+
+  LoggerD("Enter");
+  picojson::value::array *contents = static_cast<picojson::value::array*>(user_data);
+  picojson::value::object o;
+
+  o["playlist_member_id"] = picojson::value(static_cast<double>(playlist_member_id));
+  ContentToJson(media, o);
+  contents->push_back(picojson::value(o));
+  return true;
+}
+
+
+ContentManager::ContentManager() : fs_provider_(common::FilesystemProviderStorage::Create()) {
+  LoggerD("ContentManager called");
+  m_contentChangeListenerRegistered = false;
+  if(media_content_connect() == MEDIA_CONTENT_ERROR_NONE) {
+      m_dbConnected = true;
+  }
+  else
+      m_dbConnected = false;
+}
+
+ContentManager::~ContentManager() {
+  LoggerD("Enter");
+  if(m_dbConnected) {
+    if(media_content_disconnect() == MEDIA_CONTENT_ERROR_NONE) {
+      m_dbConnected = false;
+    }
+  }
+}
+
+ContentManager* ContentManager::getInstance() {
+  LoggerD("Enter");
+  static ContentManager instance;
+  return &instance;
+}
+
+bool ContentManager::isConnected() {
+  LoggerD("Enter");
+  return m_dbConnected;
+}
+
+void ContentManager::getDirectories(const std::shared_ptr<ReplyCallbackData>& user_data) {
+
+  LoggerD("Enter");
+  int ret;
+  filter_h filter = NULL;
+  ret = media_filter_create(&filter);
+  if (ret != MEDIA_CONTENT_ERROR_NONE) {
+    LoggerE("Failed: media_filter_create failed");
+    return;
+  }
+
+  SCOPE_EXIT {
+    media_filter_destroy(filter);
+  };
+
+  std::string condition = "(FOLDER_STORAGE_TYPE = 0 OR FOLDER_STORAGE_TYPE = 1)";
+  media_filter_set_condition(filter, condition.c_str(), MEDIA_CONTENT_COLLATE_DEFAULT);
+
+  picojson::array pico_dirs;
+  ret = media_folder_foreach_folder_from_db(filter, media_foreach_directory_cb, &pico_dirs);
+  if (ret != MEDIA_CONTENT_ERROR_NONE) {
+    LoggerE("Failed: Getting the directories failed");
+    PlatformResult err(ErrorCode::UNKNOWN_ERR, "Getting the directories failed.");
+    user_data->isSuccess = err;
+    return;
+  }
+
+  user_data->result = picojson::value(pico_dirs);
+}
+
+void ContentManager::find(const std::shared_ptr<ReplyCallbackData>& user_data) {
+  LoggerD("Enter");
+
+  int ret;
+  int count, offset;
+  std::string dirId;
+
+  picojson::value::array arrayContent;
+  filter_h filter = nullptr;
+  media_filter_create(&filter);
+  SCOPE_EXIT {
+    if (filter) {
+      media_filter_destroy(filter);
+    }
+  };
+
+  if (!IsNull(user_data->args.get("filter"))) {
+    ContentFilter filterMechanism;
+    std::string query;
+    picojson::object argsObject = JsonCast<picojson::object>(user_data->args);
+    if (filterMechanism.BuildQuery(
+        FromJson<picojson::object>(argsObject, "filter"), &query)) {
+      LOGGER(DEBUG) << "Filter query: " << query;
+      ret = media_filter_set_condition(filter, query.c_str(),
+          MEDIA_CONTENT_COLLATE_DEFAULT);
+      if (MEDIA_CONTENT_ERROR_NONE != ret) {
+        LoggerE("Platform filter setting failed, error %d", ret);
+      }
+    }
+  }
+
+  if (user_data->args.contains("sortMode")) {
+    picojson::value vSortMode = user_data->args.get("sortMode");
+
+    if (vSortMode.is<picojson::object>()) {
+      std::string sortModeName, sortModeOrder;
+
+      ContentFilter::MapField(vSortMode.get("attributeName").to_str(), &sortModeName);
+
+      sortModeOrder = vSortMode.get("order").to_str();
+      if (!sortModeOrder.empty()) {
+        media_content_order_e order = MEDIA_CONTENT_ORDER_ASC;
+
+        if (sortModeOrder == "ASC") {
+          order = MEDIA_CONTENT_ORDER_ASC;
+        } else if (sortModeOrder == "DESC") {
+          order = MEDIA_CONTENT_ORDER_DESC;
+        }
+
+        ret = media_filter_set_order(filter, order, sortModeName.c_str(),
+            MEDIA_CONTENT_COLLATE_DEFAULT);
+        if (MEDIA_CONTENT_ERROR_NONE != ret) {
+          LoggerE("Platform SortMode setting failed, error: %d", ret);
+        }
+      }
+    }
+  }
+
+  if (!IsNull(user_data->args.get("count"))) {
+    count = static_cast<int>(user_data->args.get("count").get<double>());
+  } else {
+    count = -1;
+  }
+  if (!IsNull(user_data->args.get("offset"))) {
+    offset = static_cast<int>(user_data->args.get("offset").get<double>());
+  } else {
+    offset = -1;
+  }
+  ret = media_filter_set_offset(filter, offset, count);
+  if (MEDIA_CONTENT_ERROR_NONE != ret) {
+    LoggerE("A platform error occurs in media_filter_set_offset: %d", ret);
+  }
+  if (!IsNull(user_data->args.get("directoryId"))) {
+    dirId = user_data->args.get("directoryId").get<std::string>();
+    ret = media_folder_foreach_media_from_db(dirId.c_str(), filter, media_foreach_content_cb, static_cast<void*>(&arrayContent));
+  } else {
+    ret = media_info_foreach_media_from_db(filter, media_foreach_content_cb, static_cast<void*>(&arrayContent));
+  }
+
+  if (ret == MEDIA_CONTENT_ERROR_NONE) {
+    user_data->result = picojson::value(arrayContent);
+  } else {
+    LoggerE("The iteration failed in platform: %d", ret);
+    PlatformResult err(ErrorCode::UNKNOWN_ERR, "The iteration failed in platform");
+    user_data->isSuccess = err;
+  }
+}
+
+int ContentManager::scanFile(std::string& uri) {
+  LoggerD("Enter");
+  return media_content_scan_file(uri.c_str());
+}
+
+PlatformResult ContentManager::scanDirectory(media_scan_completed_cb callback, ReplyCallbackData* cbData) {
+  LoggerD("Enter");
+  const std::string& contentDirURI = cbData->args.get("contentDirURI").get<std::string>();
+  std::string real_path = ContentManager::getInstance()->fs_provider_.GetRealPath(contentDirURI);
+  const bool recursive = cbData->args.get("recursive").get<bool>();
+
+  int ret = media_content_scan_folder(real_path.c_str(), recursive, callback, (void*) cbData);
+  if (ret != MEDIA_CONTENT_ERROR_NONE) {
+    LoggerE("Scan folder failed in platform: %d", ret);
+    if (MEDIA_CONTENT_ERROR_INVALID_PARAMETER == ret) {
+      return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Scanning content directory failed");
+    } else {
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, "Scanning content directory failed");
+    }
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult ContentManager::cancelScanDirectory(const std::string& content_dir_uri) {
+  LoggerD("Enter");
+
+  int ret = media_content_cancel_scan_folder(content_dir_uri.c_str());
+  if (ret != MEDIA_CONTENT_ERROR_NONE) {
+    LoggerE("Cancel scan folder failed in platform: %d", ret);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Cancel scan content directory failed");
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult ContentManager::setChangeListener(media_content_db_update_cb callback,
+                                                 void *user_data) {
+  LoggerD("Enter");
+
+  if(!m_contentChangeListenerRegistered) {
+    int ret = media_content_set_db_updated_cb(callback, user_data);
+    if(ret != MEDIA_CONTENT_ERROR_NONE) {
+      LoggerE("Failed: registering the listener is failed");
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, ("registering the listener is failed."));
+    } else {
+      m_contentChangeListenerRegistered = true;
+    }
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult ContentManager::unSetChangeListener() {
+  LoggerD("Enter");
+
+  if(m_contentChangeListenerRegistered) {
+    int ret = media_content_unset_db_updated_cb();
+    if(ret != MEDIA_CONTENT_ERROR_NONE) {
+      LoggerE("Failed: unregistering the listener is failed");
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, ("unregistering the listener is failed."));
+    } else {
+      m_contentChangeListenerRegistered = false;
+    }
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult ContentManager::setV2ChangeListener(media_content_noti_h* noti_handle,
+                                                 media_content_db_update_cb callback,
+                                                 void *user_data) {
+  LoggerD("Enter");
+  if (nullptr == *noti_handle) {
+    int ret = media_content_set_db_updated_cb_v2(noti_handle, callback, user_data);
+    if(ret != MEDIA_CONTENT_ERROR_NONE) {
+      LoggerE("Failed: registering the listener of cb_v2 is failed");
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, ("registering the listener is failed."));
+    }
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult ContentManager::unSetV2ChangeListener(media_content_noti_h* noti_handle) {
+  LoggerD("Enter");
+
+  int ret = media_content_unset_db_updated_cb_v2(*noti_handle);
+  if(ret != MEDIA_CONTENT_ERROR_NONE) {
+    LoggerE("Failed: unregistering the listener of cb_v2 is failed");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, ("unregistering the listener is failed."));
+  }
+  *noti_handle = nullptr;
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+
+void ContentManager::createPlaylist(std::string name,
+  const std::shared_ptr<ReplyCallbackData>& user_data) {
+  LoggerD("Enter");
+  media_playlist_h    playlist = NULL;
+
+  int ret = media_playlist_insert_to_db(name.c_str(),&playlist);
+  std::unique_ptr<std::remove_pointer<media_playlist_h>::type, int(*)(media_playlist_h)>
+      playlist_ptr(playlist, &media_playlist_destroy); // automatically release the memory
+  if(ret != MEDIA_CONTENT_ERROR_NONE) {
+    LoggerE("Failed: creation of playlist is failed: %d", ret);
+    // MEDIA_CONTENT_ERROR_DB_FAILED means that playlist probably already exists
+    PlatformResult err(MEDIA_CONTENT_ERROR_DB_FAILED == ret ? ErrorCode::INVALID_VALUES_ERR : ErrorCode::UNKNOWN_ERR, "Creation of playlist has failed.");
+    user_data->isSuccess = err;
+    return;
+  }
+  picojson::value::object o;
+
+  if( playlist != NULL) {
+    int id,cnt;
+    char* thumb_path = NULL;
+    char* name = NULL;
+    filter_h filter = NULL;
+    if( media_playlist_get_playlist_id(playlist, &id) == MEDIA_CONTENT_ERROR_NONE) {
+      o["id"] = picojson::value(std::to_string(id));
+    }
+    else {
+      LoggerE("Failed: loading of playlist is failed");
+      PlatformResult err(ErrorCode::UNKNOWN_ERR, "loading of playlist is failed.");
+      user_data->isSuccess = err;
+      return;
+    }
+    if( media_playlist_get_thumbnail_path(playlist, &thumb_path) == MEDIA_CONTENT_ERROR_NONE) {
+      if (thumb_path != NULL) {
+        o["thumbnailURI"] = picojson::value(std::string(thumb_path));
+        free(thumb_path);
+      }
+      else {
+        o["thumbnailURI"] = picojson::value();
+      }
+    }
+    else {
+      LoggerE("Invalid thumbnail path for playlist.");
+    }
+    if( media_playlist_get_name(playlist, &name) == MEDIA_CONTENT_ERROR_NONE) {
+      o["name"] = picojson::value(std::string(name));
+      free(name);
+    }
+    else {
+      LoggerE("Invalid name for playlist.");
+    }
+    media_filter_create(&filter);
+    std::unique_ptr<std::remove_pointer<filter_h>::type, int(*)(filter_h)>
+        filter_ptr(filter, &media_filter_destroy); // automatically release the memory
+
+    if( media_playlist_get_media_count_from_db(id, filter, &cnt) == MEDIA_CONTENT_ERROR_NONE) {
+      o["numberOfTracks"] = picojson::value(static_cast<double>(cnt));
+    }
+    else {
+      LoggerE("Invalid count for playlist.");
+    }
+  }
+
+  user_data->result = picojson::value(o);
+}
+
+void ContentManager::getPlaylists(const std::shared_ptr<ReplyCallbackData>& user_data) {
+
+  LoggerD("Enter");
+  int ret;
+  filter_h     filter = nullptr;
+  media_filter_create(&filter);
+  std::unique_ptr<std::remove_pointer<filter_h>::type, int(*)(filter_h)>
+      filter_ptr(filter, &media_filter_destroy); // automatically release the memory
+  picojson::value::array playlists;
+
+  ret = media_playlist_foreach_playlist_from_db(filter, playlist_foreach_cb, static_cast<void*>(&playlists));
+
+  if(ret != MEDIA_CONTENT_ERROR_NONE) {
+    LoggerE("Failed: Getting playlist is failed");
+    PlatformResult err(ErrorCode::UNKNOWN_ERR, "Getting playlist is failed.");
+    user_data->isSuccess = err;
+  }
+
+  user_data->result = picojson::value(playlists);
+}
+
+void ContentManager::removePlaylist(std::string playlistId,
+  const std::shared_ptr<ReplyCallbackData>& user_data) {
+
+  LoggerD("Enter");
+  int id = std::atoi(playlistId.c_str());
+  if(id == 0) {
+    LoggerE("Failed: PlaylistId is wrong");
+    PlatformResult err(ErrorCode::UNKNOWN_ERR, "PlaylistId is wrong.");
+    user_data->isSuccess = err;
+    return;
+  }
+
+  int ret = media_playlist_delete_from_db(id);
+  if(ret != MEDIA_CONTENT_ERROR_NONE) {
+    LoggerE("Failed: Removal of playlist is failed");
+    PlatformResult err(ErrorCode::UNKNOWN_ERR, "Removal of playlist is failed.");
+    user_data->isSuccess = err;
+  }
+}
+
+int ContentManager::update(picojson::value args) {
+  LoggerD("Enter");
+
+  int ret;
+  picojson::value content = args.get("content");
+  std::string id = content.get("id").to_str();
+
+  media_info_h media = NULL;
+  ret = media_info_get_media_from_db(id.c_str(), &media);
+  if (ret == MEDIA_CONTENT_ERROR_NONE) {
+    setContent(media, content);
+    ret = media_info_update_to_db(media);
+    media_info_destroy(media);
+  }
+
+  return ret;
+}
+
+int ContentManager::updateBatch(picojson::value args) {
+  LoggerD("Enter");
+  int ret = 0;
+  std::vector<picojson::value> contents = args.get("contents").get<picojson::array>();
+
+  for (picojson::value::array::iterator it = contents.begin(); it != contents.end(); ++it) {
+    picojson::value content = *it;
+    std::string id = content.get("id").to_str();
+    media_info_h media = NULL;
+    ret = media_info_get_media_from_db(id.c_str(), &media);
+    if (media != NULL && ret == MEDIA_CONTENT_ERROR_NONE) {
+      ret = setContent(media, content);
+      if(ret != MEDIA_CONTENT_ERROR_NONE){
+          LoggerE("setContent failed");
+
+          if(media != NULL){
+              media_info_destroy(media);
+          }
+          return ret;
+      }
+
+      ret = media_info_update_to_db(media);
+      if(ret != MEDIA_CONTENT_ERROR_NONE){
+          LoggerE("update to db failed");
+          if(media != NULL){
+              media_info_destroy(media);
+          }
+          return ret;
+      }
+
+      if(media != NULL){
+          media_info_destroy(media);
+      }
+
+
+    } else {
+      if(media != NULL){
+          media_info_destroy(media);
+      }
+      return ret;
+    }
+  }
+
+  return ret;
+}
+
+int ContentManager::playlistAdd(std::string playlist_id, std::string content_id) {
+  LoggerD("Enter");
+
+  media_playlist_h playlist = NULL;
+  int ret = media_playlist_get_playlist_from_db(std::stoi(playlist_id), &playlist);
+
+  if (playlist != NULL && ret == MEDIA_CONTENT_ERROR_NONE) {
+    ret = media_playlist_add_media(playlist, content_id.c_str());
+    if (ret != MEDIA_CONTENT_ERROR_NONE) {
+      LoggerE("The content(id:%s) can't add to playlist",content_id.c_str());
+    }
+
+    ret = media_playlist_update_to_db(playlist);
+    if (ret != MEDIA_CONTENT_ERROR_NONE) {
+      LoggerE("The content(id:%s) can't add to playlist",content_id.c_str());
+    }
+  }
+  else {
+    LoggerE("Playlist(id:%s) is not exist",playlist_id.c_str());
+  }
+
+  media_playlist_destroy(playlist);
+  return ret;
+}
+
+int ContentManager::playlistRemove(std::string playlist_id, int member_id) {
+  LoggerD("Enter");
+
+  media_playlist_h playlist = NULL;
+  int ret = media_playlist_get_playlist_from_db(std::stoi(playlist_id), &playlist);
+  if (playlist != NULL && ret == MEDIA_CONTENT_ERROR_NONE) {
+    ret = media_playlist_remove_media(playlist, member_id);
+    if (ret != MEDIA_CONTENT_ERROR_NONE) {
+      LoggerE("The content can't remove to playlist");
+    }
+
+    ret = media_playlist_update_to_db(playlist);
+    if (ret != MEDIA_CONTENT_ERROR_NONE) {
+      LoggerE("The content can't remove to playlist");
+    }
+  }
+  else {
+    LoggerE("Playlist(id:%s) is not exist",playlist_id.c_str());
+  }
+  media_playlist_destroy(playlist);
+
+  return ret;
+}
+
+
+void ContentManager::playlistAddbatch(const std::shared_ptr<ReplyCallbackData>& user_data) {
+
+  LoggerD("Enter");
+  std::string playlist_id = user_data->args.get("playlistId").get<std::string>();
+
+  media_playlist_h playlist = NULL;
+  int ret = media_playlist_get_playlist_from_db(std::stoi(playlist_id), &playlist);
+
+  if(ret != MEDIA_CONTENT_ERROR_NONE && playlist == NULL) {
+    PlatformResult err(ErrorCode::UNKNOWN_ERR, "Getting playlist is failed.");
+    user_data->isSuccess = err;
+    return;
+  }
+
+  std::vector<picojson::value> contents = user_data->args.get("contents").get<picojson::array>();
+  for (picojson::value::array::iterator it = contents.begin(); it != contents.end(); ++it) {
+    picojson::value content = *it;
+    std::string id = content.get("id").to_str();
+    ret = media_playlist_add_media(playlist, id.c_str());
+    if (ret != MEDIA_CONTENT_ERROR_NONE) {
+      LoggerE("Adding Content(id:%s) is failed.", id.c_str());
+    }
+  }
+
+  ret = media_playlist_update_to_db(playlist);
+  if(ret != MEDIA_CONTENT_ERROR_NONE ) {
+    PlatformResult err(ErrorCode::UNKNOWN_ERR, "Adding playlist is failed.");
+    user_data->isSuccess = err;
+  }
+  media_playlist_destroy(playlist);
+}
+
+void ContentManager::playlistGet(const std::shared_ptr<ReplyCallbackData>& user_data) {
+
+  LoggerD("Enter");
+  media_playlist_h playlist = NULL;
+  media_content_order_e order = MEDIA_CONTENT_ORDER_ASC;
+  const std::string playOrder("play_order");
+
+  std::string playlist_id = user_data->args.get("playlistId").get<std::string>();
+  int ret = media_playlist_get_playlist_from_db(std::stoi(playlist_id), &playlist);
+  if(ret != MEDIA_CONTENT_ERROR_NONE && playlist == NULL) {
+    LoggerE("Failed: Getting playlist is failed");
+    PlatformResult err(ErrorCode::UNKNOWN_ERR, "Getting playlist is failed.");
+    user_data->isSuccess = err;
+    return;
+  }
+
+  filter_h filter = NULL;
+  ret = media_filter_create(&filter);
+  if (ret != MEDIA_CONTENT_ERROR_NONE) {
+    LoggerE("Failed: Creating a filter is failed");
+    PlatformResult err(ErrorCode::UNKNOWN_ERR, "Creating a filter is failed.");
+    user_data->isSuccess = err;
+
+    if(playlist != NULL){
+      media_playlist_destroy(playlist);
+    }
+    return;
+  }
+
+  int count = user_data->args.get("count").get<double>();
+  int offset = user_data->args.get("offset").get<double>();
+  ret = media_filter_set_offset(filter, offset, count);
+  if (ret != MEDIA_CONTENT_ERROR_NONE) {
+    LoggerD("Setting a offset/count is failed.");
+  }
+  ret = media_filter_set_order(filter, order, playOrder.c_str(), MEDIA_CONTENT_COLLATE_DEFAULT);
+  if (ret != MEDIA_CONTENT_ERROR_NONE) {
+    LoggerD("Setting a offset/count is failed.");
+  }
+
+  picojson::value::array arrayContent;
+  ret = media_playlist_foreach_media_from_db(std::stoi(playlist_id),
+    filter, playlist_content_member_cb, static_cast<void*>(&arrayContent));
+
+  media_filter_destroy(filter);
+  if (ret == MEDIA_CONTENT_ERROR_NONE) {
+    user_data->result = picojson::value(arrayContent);
+  }
+  else {
+    LoggerE("Failed: Creating a filter is failed");
+    PlatformResult err(ErrorCode::UNKNOWN_ERR, "Creating a filter is failed.");
+    user_data->isSuccess = err;
+  }
+
+  if(playlist != NULL){
+    media_playlist_destroy(playlist);
+  }
+
+}
+
+void ContentManager::playlistRemovebatch(const std::shared_ptr<ReplyCallbackData>& user_data) {
+
+  LoggerD("Enter");
+  media_playlist_h playlist = NULL;
+
+  std::string playlist_id = user_data->args.get("playlistId").get<std::string>();
+  int ret = media_playlist_get_playlist_from_db(std::stoi(playlist_id), &playlist);
+  if(ret != MEDIA_CONTENT_ERROR_NONE && playlist == NULL) {
+    PlatformResult err(ErrorCode::UNKNOWN_ERR, "Getting playlist is failed.");
+    user_data->isSuccess = err;
+    return;
+  }
+
+  std::vector<picojson::value> members = user_data->args.get("members").get<picojson::array>();
+  std::size_t members_size = members.size();
+  for (std::size_t i = 0; i < members_size; i++) {
+    int member_id = static_cast<int>(members.at(i).get<double>());
+    ret = media_playlist_remove_media(playlist, member_id);
+
+    if (ret != MEDIA_CONTENT_ERROR_NONE) {
+      LoggerD("Removing a content is failed.");
+    }
+  }
+
+  ret = media_playlist_update_to_db(playlist);
+  if (ret != MEDIA_CONTENT_ERROR_NONE) {
+    LoggerE("Failed: Removing the contents is failed");
+    PlatformResult err(ErrorCode::UNKNOWN_ERR, "Removing the contents is failed.");
+    user_data->isSuccess = err;
+  }
+
+  if(playlist != NULL){
+    media_playlist_destroy(playlist);
+  }
+
+}
+
+void ContentManager::playlistSetOrder(const std::shared_ptr<ReplyCallbackData>& user_data) {
+
+  LoggerD("Enter");
+  media_playlist_h playlist = NULL;
+
+  std::string playlist_id = user_data->args.get("playlistId").get<std::string>();
+  int ret = media_playlist_get_playlist_from_db(std::stoi(playlist_id), &playlist);
+  if(ret != MEDIA_CONTENT_ERROR_NONE && playlist == NULL) {
+    PlatformResult err(ErrorCode::UNKNOWN_ERR, "Getting playlist is failed.");
+    user_data->isSuccess = err;
+    return;
+  }
+
+  int cnt;
+  std::vector<picojson::value> members = user_data->args.get("members").get<picojson::array>();
+
+  ret = media_playlist_get_media_count_from_db(std::stoi(playlist_id), NULL, &cnt);
+  if(ret != MEDIA_CONTENT_ERROR_NONE)
+  {
+    LoggerE("Failed: media_playlist_get_media_count_from_db");
+    PlatformResult err = convertError(ret);
+    user_data->isSuccess = err;
+
+    if(playlist != NULL){
+      media_playlist_destroy(playlist);
+    }
+    return;
+  }
+  std::size_t members_size = members.size();
+  if (cnt < 0 || static_cast<size_t>(cnt) != members_size ) {
+    LoggerE("Failed: The items array does not contain all items from the playlist");
+    PlatformResult err(ErrorCode::INVALID_VALUES_ERR, "The items array does not contain all items from the playlist.");
+    user_data->isSuccess = err;
+    if(playlist != NULL){
+      media_playlist_destroy(playlist);
+    }
+    return;
+  }
+
+  for (std::size_t i = 0; i < members_size; i++) {
+    int member_id = static_cast<int>(members.at(i).get<double>());
+    ret = media_playlist_set_play_order(playlist, member_id, i);
+    if (ret != MEDIA_CONTENT_ERROR_NONE) {
+      LoggerD("Removing a content is failed.");
+    }
+  }
+
+  ret = media_playlist_update_to_db(playlist);
+  if (ret != MEDIA_CONTENT_ERROR_NONE) {
+    LoggerE("Failed: Removing the contents is failed");
+    PlatformResult err(ErrorCode::UNKNOWN_ERR, "Removing the contents is failed.");
+    user_data->isSuccess = err;
+  }
+
+  if(playlist != NULL){
+    media_playlist_destroy(playlist);
+  }
+}
+
+void ContentManager::playlistMove(const std::shared_ptr<ReplyCallbackData>& user_data) {
+  LoggerD("Enter");
+  media_playlist_h playlist = NULL;
+  std::string playlist_id = user_data->args.get("playlistId").get<std::string>();
+  int ret = media_playlist_get_playlist_from_db(std::stoi(playlist_id), &playlist);
+  if(ret != MEDIA_CONTENT_ERROR_NONE && playlist == NULL) {
+    LoggerE("Failed: Getting playlist is failed");
+    PlatformResult err(ErrorCode::UNKNOWN_ERR, "Getting playlist is failed.");
+    user_data->isSuccess = err;
+    return;
+  }
+  int old_order;
+  double member_id = user_data->args.get("memberId").get<double>();
+  double delta = user_data->args.get("delta").get<double>();
+  ret = media_playlist_get_play_order(playlist, static_cast<int>(member_id), &old_order);
+  if (ret != MEDIA_CONTENT_ERROR_NONE) {
+    LoggerE("Failed: The content can't find form playlist");
+    PlatformResult err(ErrorCode::UNKNOWN_ERR, "The content can't find form playlist.");
+    user_data->isSuccess = err;
+    if(playlist != NULL){
+        media_playlist_destroy(playlist);
+    }
+    return;
+  }
+  int new_order = static_cast<int>(old_order) + static_cast<int>(delta);
+  ret = media_playlist_set_play_order(playlist, static_cast<int>(member_id), new_order);
+  if (ret != MEDIA_CONTENT_ERROR_NONE) {
+    LoggerE("Failed: The content can't update play_order");
+    PlatformResult err(ErrorCode::UNKNOWN_ERR, "The content can't update play_order.");
+    user_data->isSuccess = err;
+    if(playlist != NULL){
+        media_playlist_destroy(playlist);
+    }
+    return;
+  }
+  ret = media_playlist_update_to_db(playlist);
+  if (ret != MEDIA_CONTENT_ERROR_NONE) {
+    LoggerE("Failed: Updateing play_order is failed");
+    PlatformResult err(ErrorCode::UNKNOWN_ERR, "Updateing play_order is failed.");
+    user_data->isSuccess = err;
+    if(playlist != NULL){
+        media_playlist_destroy(playlist);
+    }
+  }
+
+  if(playlist != NULL){
+    media_playlist_destroy(playlist);
+  }
+
+}
+
+int ContentManager::getLyrics(const picojson::value& args, picojson::object& result) {
+  LoggerD("Enter");
+
+  int ret = METADATA_EXTRACTOR_ERROR_NONE;
+  const std::string& contentURI = args.get("contentURI").to_str();
+  if (contentURI.empty()) {
+    LOGGER(ERROR) << "contentURI empty - skipping media extractor";
+    return -1;
+  }
+
+  metadata_extractor_h extractor;
+  metadata_extractor_create(&extractor);
+  std::unique_ptr<std::remove_pointer<metadata_extractor_h>::type, int(*)(metadata_extractor_h)>
+      extractor_ptr(extractor, &metadata_extractor_destroy); // automatically release the memory
+
+  ret = metadata_extractor_set_path(extractor, contentURI.c_str());
+  if (ret != METADATA_EXTRACTOR_ERROR_NONE) {
+    LOGGER(ERROR) << "metadata_extractor_set_path failed, error: " << ret;
+    return ret;
+  }
+  picojson::array timestamps;
+  picojson::array texts = picojson::array();
+  char* strSyncTextNum = NULL;
+
+  ret = metadata_extractor_get_metadata(extractor,
+      METADATA_SYNCLYRICS_NUM, &strSyncTextNum);
+  if (ret != METADATA_EXTRACTOR_ERROR_NONE) {
+    LOGGER(ERROR) << "Media extractor error " << ret;
+    return ret;
+  }
+
+  int nSyncTextNum = 0;
+  if (strSyncTextNum) {
+    nSyncTextNum = atoi(strSyncTextNum);
+    free(strSyncTextNum);
+    strSyncTextNum = NULL;
+  }
+  if (nSyncTextNum > 0 && nSyncTextNum < std::numeric_limits<int>::max()) {
+    result["type"] = picojson::value(std::string("SYNCHRONIZED"));
+    for (int i = 0; i < nSyncTextNum; i++) {
+      unsigned long time_info = 0;
+      char* lyrics = NULL;
+      ret = metadata_extractor_get_synclyrics(extractor, i, &time_info, &lyrics);
+      if (ret == METADATA_EXTRACTOR_ERROR_NONE) {
+        timestamps.push_back(picojson::value(static_cast<double>(time_info)));
+        texts.push_back(picojson::value(std::string(lyrics)));
+        free(lyrics);
+      }
+    }
+    result["texts"] = picojson::value(texts);
+    result["timestamps"] = picojson::value(timestamps);
+    ret = METADATA_EXTRACTOR_ERROR_NONE;
+  } else {
+    char* unSyncText = nullptr;
+    ret = metadata_extractor_get_metadata(extractor, METADATA_UNSYNCLYRICS,
+                                          &unSyncText);
+    if (ret == METADATA_EXTRACTOR_ERROR_NONE) {
+      result["type"] = picojson::value(std::string("UNSYNCHRONIZED"));
+      if (nullptr == unSyncText) {
+        LOGGER(ERROR) << "Unsynchronized lyrics text is NULL";
+      }
+      texts.push_back(picojson::value(unSyncText ? unSyncText : ""));
+      result["texts"] = picojson::value(texts);
+      free(unSyncText);
+    }
+  }
+
+  return ret;
+}
+
+media_playlist_h getPlaylistHandle(int id)
+{
+  LoggerD("Entered");
+  media_playlist_h playlist_handle = nullptr;
+  int ret_code = media_playlist_get_playlist_from_db(id, &playlist_handle);
+  if(MEDIA_CONTENT_ERROR_NONE != ret_code ||
+      playlist_handle == nullptr) {
+    LoggerE("could not get playlist handle for id: %d", id);
+    return nullptr;
+  }
+
+  return playlist_handle;
+}
+
+void destroyMediaPlaylistHandle(media_playlist_h& playlist_handle)
+{
+  LoggerD("Entered");
+  if(playlist_handle) {
+    int ret_code = media_playlist_destroy(playlist_handle);
+    playlist_handle = nullptr;
+
+    if(MEDIA_CONTENT_ERROR_NONE != ret_code) {
+      LoggerE("media_playlist_destroy failed");
+    }
+  }
+}
+
+int ContentManager::getPlaylistName(int id, std::string* result) {
+  LoggerD("Entered");
+  media_playlist_h playlist_handle = getPlaylistHandle(id);
+  PlaylistUniquePtr playlist_ptr(playlist_handle, destroyMediaPlaylistHandle);
+
+  char* tmp_playlist_name = nullptr;
+  const int ret_code = media_playlist_get_name(playlist_handle, &tmp_playlist_name);
+
+  if(MEDIA_CONTENT_ERROR_NONE != ret_code) {
+    LoggerE("media_playlist_get_name failed");
+    return TIZEN_ERROR_UNKNOWN;
+  }
+
+  std::string playlist_name;
+  if(tmp_playlist_name) {
+    playlist_name = tmp_playlist_name;
+    free(tmp_playlist_name);
+    tmp_playlist_name = nullptr;
+  }
+
+  *result = playlist_name;
+  return MEDIA_CONTENT_ERROR_NONE;
+}
+
+int updatePlaylistInDB(media_playlist_h playlist_handle)
+{
+  LoggerD("Entered");
+  int ret_code = media_playlist_update_to_db(playlist_handle);
+  if(MEDIA_CONTENT_ERROR_NONE != ret_code) {
+    LoggerE("media_playlist_update_to_db failed");
+    return ret_code;
+  }
+  return MEDIA_CONTENT_ERROR_NONE;
+}
+
+int ContentManager::setPlaylistName(int id, const std::string& name)
+{
+  LoggerD("Entered");
+  if(name.empty()) {
+    LoggerE("Cannot set empty playlist name!");
+    return MEDIA_CONTENT_ERROR_INVALID_PARAMETER;
+  }
+
+  media_playlist_h playlist_handle = getPlaylistHandle(id);
+  PlaylistUniquePtr playlist_ptr(playlist_handle, destroyMediaPlaylistHandle);
+
+  const int ret_code = media_playlist_set_name(playlist_handle, name.c_str());
+  if(MEDIA_CONTENT_ERROR_NONE != ret_code) {
+    LoggerE("media_playlist_set_name failed");
+    //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
+    return TIZEN_ERROR_UNKNOWN;
+  }
+
+  int ret = updatePlaylistInDB(playlist_handle);
+  if (MEDIA_CONTENT_ERROR_NONE != ret) {
+    LoggerE("Error while updating playlist: %d", ret);
+    if (MEDIA_CONTENT_ERROR_DB_FAILED == ret) {
+      //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
+      LoggerE("Playlist name: %s is probably already used", name.c_str());
+      return MEDIA_CONTENT_ERROR_INVALID_PARAMETER;
+    }
+    return ret;
+  }
+  return MEDIA_CONTENT_ERROR_NONE;
+}
+
+int ContentManager::getThumbnailUri(int id, std::string* result)
+{
+  LoggerD("Entered");
+  media_playlist_h playlist_handle = getPlaylistHandle(id);
+  PlaylistUniquePtr playlist_ptr(playlist_handle, destroyMediaPlaylistHandle);
+
+  char* tmp_playlist_thb_path = nullptr;
+  const int ret_code = media_playlist_get_thumbnail_path(playlist_handle, &tmp_playlist_thb_path);
+
+  if(MEDIA_CONTENT_ERROR_NONE != ret_code) {
+    LoggerE("media_playlist_get_name failed");
+    return TIZEN_ERROR_UNKNOWN;
+  }
+
+  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 = nullptr;
+  }
+
+  if (playlist_thb_path != " ") {
+    playlist_thb_path = uri_prefix + playlist_thb_path;
+  }
+
+  *result = playlist_thb_path;
+  return MEDIA_CONTENT_ERROR_NONE;
+}
+
+int ContentManager::setThumbnailUri(int id, const std::string& thb_uri)
+{
+  LoggerD("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.
+  if(!thb_uri.empty() && " " != thb_uri) {
+    if(thb_uri.find(uri_absolute_prefix) != 0) {
+      LoggerE("thumbnail URI is not valid: [%s]", thb_uri.c_str());
+      return MEDIA_CONTENT_ERROR_INVALID_PARAMETER;
+    }
+  }
+
+  media_playlist_h playlist_handle = getPlaylistHandle(id);
+  PlaylistUniquePtr playlist_ptr(playlist_handle, destroyMediaPlaylistHandle);
+
+  std::string real_path = fs_provider_.GetRealPath(thb_uri);
+  const int ret_code = media_playlist_set_thumbnail_path(playlist_handle,
+                                                         real_path.c_str());
+  if(MEDIA_CONTENT_ERROR_NONE != ret_code) {
+    LoggerE("media_playlist_set_thumbnail_path failed");
+    return TIZEN_ERROR_UNKNOWN;
+  }
+
+  int ret = updatePlaylistInDB(playlist_handle);
+  return ret;
+}
+
+int ContentManager::getNumberOfTracks(int id, int* result) {
+  LoggerD("Entered");
+
+  int count = 0;
+  const int ret_code = media_playlist_get_media_count_from_db(id, nullptr,
+                                                              &count);
+
+  if (MEDIA_CONTENT_ERROR_NONE != ret_code) {
+    LoggerE("media_playlist_get_media_count_from_db failed");
+    return TIZEN_ERROR_UNKNOWN;
+  }
+
+  *result = count;
+  return MEDIA_CONTENT_ERROR_NONE;
+}
+
+PlatformResult ContentManager::convertError(int err) {
+  char* error_msg = get_error_message(err);
+  switch (err) {
+    case MEDIA_CONTENT_ERROR_INVALID_PARAMETER :
+      return PlatformResult(ErrorCode::INVALID_VALUES_ERR, error_msg);
+    case MEDIA_CONTENT_ERROR_OUT_OF_MEMORY :
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, error_msg);
+    case MEDIA_CONTENT_ERROR_INVALID_OPERATION :
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, error_msg);
+    case MEDIA_CONTENT_FILE_NO_SPACE_ON_DEVICE :
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, error_msg);
+    case MEDIA_CONTENT_ERROR_PERMISSION_DENIED :
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, error_msg);
+    case MEDIA_CONTENT_ERROR_DB_FAILED :
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, error_msg);
+    case MEDIA_CONTENT_ERROR_DB_BUSY :
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, error_msg);
+    case MEDIA_CONTENT_ERROR_NETWORK :
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, error_msg);
+    case MEDIA_CONTENT_ERROR_UNSUPPORTED_CONTENT :
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, error_msg);
+    default:
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error.");
+  }
+}
+
+} // namespace content
+} // namespace extension
diff --git a/webWidgetTCT_device/src/content/content_manager.h b/webWidgetTCT_device/src/content/content_manager.h
new file mode 100755 (executable)
index 0000000..c86b3e0
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2015 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 CONTENT_MANAGER_H_
+#define CONTENT_MANAGER_H_
+
+#include <glib.h>
+#include <list>
+#include <media_content.h>
+#include <media_folder.h>
+#include <memory>
+#include <string>
+
+#include "common/extension.h"
+#include "common/picojson.h"
+#include "common/platform_result.h"
+#include "common/filesystem/filesystem_provider_storage.h"
+#include "content/content_instance.h"
+
+namespace extension {
+namespace content {
+
+typedef std::unique_ptr<std::remove_pointer<media_playlist_h>::type,
+    void (*)(media_playlist_h&)> PlaylistUniquePtr;
+
+void ContentToJson(media_info_h info, picojson::object& o);
+void ContentDirToJson(media_folder_h folder, picojson::object& o);
+
+class ContentManager {
+ public:
+  virtual ~ContentManager();
+  bool isConnected();
+  static ContentManager* getInstance();
+
+  void getDirectories(const std::shared_ptr<ReplyCallbackData>& user_data);
+  void find(const std::shared_ptr<ReplyCallbackData>& user_data);
+  int update(picojson::value args);
+  int updateBatch(picojson::value args);
+
+  int scanFile(std::string& uri);
+  common::PlatformResult scanDirectory(media_scan_completed_cb callback, ReplyCallbackData* cbData);
+  common::PlatformResult cancelScanDirectory(const std::string& content_dir_uri);
+  common::PlatformResult setChangeListener(media_content_db_update_cb callback,
+                                           void *user_data);
+  common::PlatformResult unSetChangeListener();
+  common::PlatformResult setV2ChangeListener(media_content_noti_h* noti_handler,
+                                           media_content_db_update_cb callback,
+                                           void *user_data);
+  common::PlatformResult unSetV2ChangeListener(media_content_noti_h* noti_handler);
+
+//Lyrics
+  int getLyrics(const picojson::value& args,picojson::object& result);
+
+//playlist
+  void createPlaylist(std::string name, const std::shared_ptr<ReplyCallbackData>& user_data);
+  void getPlaylists(const std::shared_ptr<ReplyCallbackData>& user_data);
+  void removePlaylist(std::string playlistId, const std::shared_ptr<ReplyCallbackData>& user_data);
+  int playlistAdd(std::string playlist_id, std::string content_id);
+  int playlistRemove(std::string playlist_id, int member_id);
+  void playlistAddbatch(const std::shared_ptr<ReplyCallbackData>& user_data);
+  void playlistGet(const std::shared_ptr<ReplyCallbackData>& user_data);
+  void playlistRemovebatch(const std::shared_ptr<ReplyCallbackData>& user_data);
+  void playlistSetOrder(const std::shared_ptr<ReplyCallbackData>& user_data);
+  void playlistMove(const std::shared_ptr<ReplyCallbackData>& user_data);
+
+  int getPlaylistName(int id, std::string* result);
+  int setPlaylistName(int id, const std::string& name);
+
+  int getThumbnailUri(int id, std::string* result);
+  int setThumbnailUri(int id, const std::string& thb_uri);
+
+  int getNumberOfTracks(int id, int* result);
+
+//playlistSetOrder
+  static common::PlatformResult convertError(int err);
+
+  common::FilesystemProviderStorage& fs_provider_;
+ private:
+  //int setContent(media_info_h media, picojson::value content);
+  ContentManager();
+
+ private:
+  bool m_dbConnected;
+  bool m_contentChangeListenerRegistered;
+
+};
+
+} // namespace power
+} // namespace extension
+
+#endif
+
diff --git a/webWidgetTCT_device/src/content/js/common.js b/webWidgetTCT_device/src/content/js/common.js
new file mode 100755 (executable)
index 0000000..b3ddffc
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+var utils_ = xwalk.utils;
+var type_ = utils_.type;
+var converter_ = utils_.converter;
+var validator_ = utils_.validator;
+var types_ = validator_.Types;
+var native_ = new xwalk.utils.NativeManager(extension);
+var privilege_ = xwalk.utils.privilege;
+
+var EditManager = function() {
+  this.isAllowed = false;
+};
+
+EditManager.prototype.allow = function() {
+  this.isAllowed = true;
+};
+
+EditManager.prototype.disallow = function() {
+  this.isAllowed = false;
+};
+
+var edit_ = new EditManager();
+
+var SCHEMA = 'file://';
+
+function createContentObject_(data) {
+  var content;
+  switch (data.type) {
+    case ContentType.IMAGE:
+      content = new ImageContent(data);
+      break;
+    case ContentType.AUDIO:
+        content = new AudioContent(data);
+      break;
+    case ContentType.VIDEO:
+      content = new VideoContent(data);
+      break;
+    case ContentType.OTHER:
+      content = new Content(data);
+      break;
+    default:
+      throw new WebAPIException(WebAPIException.UNKNOWN_ERR, 'Undefined content type');
+  }
+  // below constructor overwriting is needed because of backward compatibility
+  var object = {};
+  content.constructor = object.constructor;
+  return content;
+}
+
+function createContentDirObject_(data) {
+  return new ContentDirectory(data);
+}
+
+function convertUriToPath_(uri) {
+  if (0 === uri.indexOf(SCHEMA)) {
+    return uri.substring(SCHEMA.length);
+  }
+
+  return uri;
+}
+
+function convertPathToUri_(path) {
+  if (0 === path.indexOf(SCHEMA)) {
+    return path;
+  }
+
+  return SCHEMA + path;
+}
diff --git a/webWidgetTCT_device/src/content/js/datatypes.js b/webWidgetTCT_device/src/content/js/datatypes.js
new file mode 100755 (executable)
index 0000000..0768f9f
--- /dev/null
@@ -0,0 +1,707 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+var ContentDirectoryStorageType = {
+  INTERNAL: 'INTERNAL',
+  EXTERNAL: 'EXTERNAL'
+};
+
+var ContentType = {
+  IMAGE: 'IMAGE',
+  VIDEO: 'VIDEO',
+  AUDIO: 'AUDIO',
+  OTHER: 'OTHER'
+};
+
+var AudioContentLyricsType = {
+  SYNCHRONIZED: 'SYNCHRONIZED',
+  UNSYNCHRONIZED: 'UNSYNCHRONIZED'
+};
+
+var ImageContentOrientation = {
+  NORMAL: 'NORMAL',
+  FLIP_HORIZONTAL: 'FLIP_HORIZONTAL',
+  ROTATE_180: 'ROTATE_180',
+  FLIP_VERTICAL: 'FLIP_VERTICAL',
+  TRANSPOSE: 'TRANSPOSE',
+  ROTATE_90: 'ROTATE_90',
+  TRANSVERSE: 'TRANSVERSE',
+  ROTATE_270: 'ROTATE_270'
+};
+
+function ContentDirectory(data) {
+  var id;
+  var directoryURI;
+  var title;
+  var storageType;
+  var modifiedDate = null;
+
+  Object.defineProperties(this, {
+    id: {
+      get: function() {
+        return id;
+      },
+      set: function(v) {
+        if (edit_.isAllowed) {
+          id = converter_.toString(v, false);
+        }
+      },
+      enumerable: true
+    },
+    directoryURI: {
+      get: function() {
+        return directoryURI;
+      },
+      set: function(v) {
+        if (edit_.isAllowed) {
+          directoryURI = convertPathToUri_(converter_.toString(v, false));
+        }
+      },
+      enumerable: true
+    },
+    title: {
+      get: function() {
+        return title;
+      },
+      set: function(v) {
+        if (edit_.isAllowed) {
+          title = converter_.toString(v, false);
+        }
+      },
+      enumerable: true
+    },
+    storageType: {
+      get: function() {
+        return storageType;
+      },
+      set: function(v) {
+        if (edit_.isAllowed) {
+          storageType = converter_.toEnum(v, Object.keys(ContentDirectoryStorageType), false);
+        }
+      },
+      enumerable: true
+    },
+    modifiedDate: {
+      get: function() {
+        return modifiedDate;
+      },
+      set: function(v) {
+        if (edit_.isAllowed) {
+          modifiedDate = v > 0 ? new Date(v * 1000) : null;
+        }
+      },
+      enumerable: true
+    }
+  });
+
+  if (type_.isObject(data)) {
+    // fill object with data
+    edit_.allow();
+    for (var key in data) {
+      if (data.hasOwnProperty(key) && this.hasOwnProperty(key)) {
+        this[key] = data[key];
+      }
+    }
+    edit_.disallow();
+  }
+}
+
+
+function Content(data) {
+  var editableAttributes = ['name', 'rating', 'description'];
+  var id;
+  var name;
+  var type;
+  var mimeType;
+  var title;
+  var contentURI;
+  var thumbnailURIs = null;
+  var releaseDate = null;
+  var modifiedDate = null;
+  var size;
+  var description = null;
+  var rating;
+  var isFavorite;
+
+  Object.defineProperties(this, {
+    editableAttributes: {
+      value: editableAttributes,
+      writable: false,
+      enumerable: true
+    },
+    id: {
+      get: function() {
+        return id;
+      },
+      set: function(v) {
+        if (edit_.isAllowed) {
+          id = converter_.toString(v, false);
+        }
+      },
+      enumerable: true
+    },
+    name: {
+      get: function() {
+        return name;
+      },
+      set: function(v) {
+        if (!type_.isNull(v)) {
+          name = converter_.toString(v, false);
+        }
+      },
+      enumerable: true
+    },
+    type: {
+      get: function() {
+        return type;
+      },
+      set: function(v) {
+        if (edit_.isAllowed) {
+          type = converter_.toEnum(v, Object.keys(ContentType), false);
+        }
+      },
+      enumerable: true
+    },
+    mimeType: {
+      get: function() {
+        return mimeType;
+      },
+      set: function(v) {
+        if (edit_.isAllowed) {
+          mimeType = converter_.toString(v, false);
+        }
+      },
+      enumerable: true
+    },
+    title: {
+      get: function() {
+        return title;
+      },
+      set: function(v) {
+        if (edit_.isAllowed) {
+          title = converter_.toString(v, false);
+        }
+      },
+      enumerable: true
+    },
+    contentURI: {
+      get: function() {
+        return contentURI;
+      },
+      set: function(v) {
+        if (edit_.isAllowed) {
+          contentURI = convertPathToUri_(v);
+        }
+      },
+      enumerable: true
+    },
+    thumbnailURIs: {
+      get: function() {
+        return thumbnailURIs;
+      },
+      set: function(v) {
+        if (edit_.isAllowed) {
+          thumbnailURIs = converter_.toArray(v, true);
+        }
+      },
+      enumerable: true
+    },
+    releaseDate: {
+      get: function() {
+        return releaseDate;
+      },
+      set: function(v) {
+        if (edit_.isAllowed) {
+          releaseDate = v > 0 ? new Date(v * 1000) : null;
+        }
+      },
+      enumerable: true
+    },
+    modifiedDate: {
+      get: function() {
+        return modifiedDate;
+      },
+      set: function(v) {
+        if (edit_.isAllowed) {
+          modifiedDate = v > 0 ? new Date(v * 1000) : null;
+        }
+      },
+      enumerable: true
+    },
+    size: {
+      get: function() {
+        return size;
+      },
+      set: function(v) {
+        if (edit_.isAllowed) {
+          size = converter_.toUnsignedLong(v, false);
+        }
+      },
+      enumerable: true
+    },
+    description: {
+      get: function() {
+        return description;
+      },
+      set: function(v) {
+        description = converter_.toString(v, true);
+      },
+      enumerable: true
+    },
+    rating: {
+      get: function() {
+        return rating;
+      },
+      set: function(v) {
+        if (!type_.isNull(v) && v >= 0 && v <= 10) {
+          rating = converter_.toUnsignedLong(v, false);
+        }
+      },
+      enumerable: true
+    },
+    isFavorite: {
+      get: function() {
+        return isFavorite;
+      },
+      set: function(v) {
+        if (!type_.isNull(v)) {
+          isFavorite = converter_.toBoolean(v, false);
+        }
+      },
+      enumerable: true
+    }
+  });
+
+  if (type_.isObject(data)) {
+    // fill object with data
+    edit_.allow();
+    for (var key in data) {
+      if (data.hasOwnProperty(key) && this.hasOwnProperty(key)) {
+        this[key] = data[key];
+      }
+    }
+    edit_.disallow();
+  }
+}
+
+
+function VideoContent(data) {
+  Content.call(this, data);
+
+  var editableAttributes = this.editableAttributes;
+  editableAttributes.push('geolocation');
+
+  var geolocation;
+  var album;
+  var artists;
+  var duration;
+  var width;
+  var height;
+
+    Object.defineProperties(this, {
+    editableAttributes: {
+      value: editableAttributes,
+      writable: false,
+      enumerable: true
+    },
+    geolocation: {
+      get: function() {
+        return geolocation;
+      },
+      set: function(v) {
+        if (!type_.isNull(v)) {
+          var latitude = converter_.toDouble(v.latitude, false);
+          var longitude = converter_.toDouble(v.longitude, false);
+          geolocation = new tizen.SimpleCoordinates(latitude, longitude);
+        }
+      },
+      enumerable: true
+    },
+    album: {
+      get: function() {
+        return album;
+      },
+      set: function(v) {
+        if (edit_.isAllowed) {
+          album = converter_.toString(v, false);
+        }
+      },
+      enumerable: true
+    },
+    artists: {
+      get: function() {
+        return artists;
+      },
+      set: function(v) {
+        if (edit_.isAllowed) {
+          artists = converter_.toArray(v, true);
+        }
+      },
+      enumerable: true
+    },
+    duration: {
+      get: function() {
+        return duration;
+      },
+      set: function(v) {
+        if (edit_.isAllowed) {
+          duration = converter_.toUnsignedLong(v, false);
+        }
+      },
+      enumerable: true
+    },
+    width: {
+      get: function() {
+        return width;
+      },
+      set: function(v) {
+        if (edit_.isAllowed) {
+          width = converter_.toUnsignedLong(v, false);
+        }
+      },
+      enumerable: true
+    },
+    height: {
+      get: function() {
+        return height;
+      },
+      set: function(v) {
+        if (edit_.isAllowed) {
+          height = converter_.toUnsignedLong(v, false);
+        }
+      },
+      enumerable: true
+    }
+  });
+
+  if (type_.isObject(data)) {
+    // fill object with data
+    edit_.allow();
+    for (var key in data) {
+      if (data.hasOwnProperty(key) && this.hasOwnProperty(key)) {
+        this[key] = data[key];
+      }
+    }
+    edit_.disallow();
+  }
+}
+
+VideoContent.prototype = new Content();
+VideoContent.prototype.constructor = VideoContent;
+
+
+function AudioContentLyrics(data) {
+  var type;
+  var timestamps;
+  var texts;
+
+  Object.defineProperties(this, {
+    type: {
+      get: function() {
+        return type;
+      },
+      set: function(v) {
+        if (edit_.isAllowed) {
+          type = converter_.toEnum(v, Object.keys(AudioContentLyricsType), false);
+        }
+      },
+      enumerable: true
+    },
+    timestamps: {
+      get: function() {
+        return timestamps;
+      },
+      set: function(v) {
+        if (edit_.isAllowed) {
+          timestamps = converter_.toArray(v, true);
+        }
+      },
+      enumerable: true
+    },
+    texts: {
+      get: function() {
+        return texts;
+      },
+      set: function(v) {
+        if (edit_.isAllowed) {
+          texts = converter_.toArray(v, false);
+        }
+      },
+      enumerable: true
+    }
+  });
+
+  if (type_.isObject(data)) {
+    // fill object with data
+    edit_.allow();
+    for (var key in data) {
+      if (data.hasOwnProperty(key) && this.hasOwnProperty(key)) {
+        this[key] = data[key];
+      }
+    }
+    edit_.disallow();
+  }
+}
+
+
+function AudioContent(data) {
+  Content.call(this, data);
+
+  var album;
+  var genres;
+  var artists;
+  var composers;
+  var lyrics;
+  var copyright;
+  var bitrate;
+  var trackNumber;
+  var duration;
+
+  var getLyrics = function() {
+    var data = {
+      contentURI: convertUriToPath_(this.contentURI)
+    };
+
+    var result = native_.callSync('ContentManager_getLyrics', data);
+
+    if (native_.isFailure(result)) {
+      console.log('Getting lyrics failed for ' + data.contentURI);
+      return;
+    }
+
+    return new AudioContentLyrics(native_.getResultObject(result));
+  }.bind(this);
+
+  Object.defineProperties(this, {
+    album: {
+      get: function() {
+        return album;
+      },
+      set: function(v) {
+        if (edit_.isAllowed) {
+          album = converter_.toString(v, false);
+        }
+      },
+      enumerable: true
+    },
+    genres: {
+      get: function() {
+        return genres;
+      },
+      set: function(v) {
+        if (edit_.isAllowed) {
+          genres = converter_.toArray(v, true);
+        }
+      },
+      enumerable: true
+    },
+    artists: {
+      get: function() {
+        return artists;
+      },
+      set: function(v) {
+        if (edit_.isAllowed) {
+          artists = converter_.toArray(v, true);
+        }
+      },
+      enumerable: true
+    },
+    composers: {
+      get: function() {
+        return composers;
+      },
+      set: function(v) {
+        if (edit_.isAllowed) {
+          composers = converter_.toArray(v, true);
+        }
+      },
+      enumerable: true
+    },
+    lyrics: {
+      get: function() {
+        if (lyrics === undefined) {
+          lyrics = getLyrics();
+        }
+        return lyrics;
+      },
+      set: function(v) {
+        if (edit_.isAllowed && type_.isObject(v)) {
+          lyrics = new AudioContentLyrics(v);
+        }
+      },
+      enumerable: true
+    },
+    copyright: {
+      get: function() {
+        return copyright;
+      },
+      set: function(v) {
+        if (edit_.isAllowed) {
+          copyright = converter_.toString(v, false);
+        }
+      },
+      enumerable: true
+    },
+    bitrate: {
+      get: function() {
+        return bitrate;
+      },
+      set: function(v) {
+        if (edit_.isAllowed) {
+          bitrate = converter_.toUnsignedLong(v, false);
+        }
+      },
+      enumerable: true
+    },
+    trackNumber: {
+      get: function() {
+        return trackNumber;
+      },
+      set: function(v) {
+        if (edit_.isAllowed) {
+          trackNumber = converter_.toUnsignedLong(v, false);
+        }
+      },
+      enumerable: true
+    },
+    duration: {
+      get: function() {
+        return duration;
+      },
+      set: function(v) {
+        if (edit_.isAllowed) {
+          duration = converter_.toUnsignedLong(v, false);
+        }
+      },
+      enumerable: true
+    }
+  });
+
+  if (type_.isObject(data)) {
+    // fill object with data
+    edit_.allow();
+    for (var key in data) {
+      if (data.hasOwnProperty(key) && this.hasOwnProperty(key)) {
+        this[key] = data[key];
+      }
+    }
+    edit_.disallow();
+  }
+}
+
+AudioContent.prototype = new Content();
+AudioContent.prototype.constructor = AudioContent;
+
+
+function ImageContent(data) {
+  Content.call(this, data);
+
+  var editableAttributes = this.editableAttributes;
+  editableAttributes.push('geolocation');
+  editableAttributes.push('orientation');
+
+  var geolocation;
+  var width;
+  var height;
+  var orientation;
+
+  Object.defineProperties(this, {
+    editableAttributes: {
+      value: editableAttributes,
+      writable: false,
+      enumerable: true
+    },
+    geolocation: {
+      get: function() {
+        return geolocation;
+      },
+      set: function(v) {
+        if (!type_.isNull(v)) {
+          var latitude = converter_.toDouble(v.latitude, false);
+          var longitude = converter_.toDouble(v.longitude, false);
+          geolocation = new tizen.SimpleCoordinates(latitude, longitude);
+        }
+      },
+      enumerable: true
+    },
+    width: {
+      get: function() {
+        return width;
+      },
+      set: function(v) {
+        if (edit_.isAllowed) {
+          width = converter_.toUnsignedLong(v, false);
+        }
+      },
+      enumerable: true
+    },
+    height: {
+      get: function() {
+        return height;
+      },
+      set: function(v) {
+        if (edit_.isAllowed) {
+          height = converter_.toUnsignedLong(v, false);
+        }
+      },
+      enumerable: true
+    },
+    orientation: {
+      get: function() {
+        return orientation;
+      },
+      set: function(v) {
+        if (!type_.isNull(v)) {
+          orientation = converter_.toEnum(v, Object.keys(ImageContentOrientation), false);
+        }
+      },
+      enumerable: true
+    }
+  });
+
+  if (type_.isObject(data)) {
+    // fill object with data
+    edit_.allow();
+    for (var key in data) {
+      if (data.hasOwnProperty(key) && this.hasOwnProperty(key)) {
+        this[key] = data[key];
+      }
+    }
+    edit_.disallow();
+  }
+}
+
+ImageContent.prototype = new Content();
+ImageContent.prototype.constructor = ImageContent;
+
+
+function PlaylistItem(data) {
+  var content = data;
+
+  Object.defineProperties(this, {
+    content: {
+      get: function() {
+        return content;
+      },
+      set: function(v) {
+        if (edit_.isAllowed && v instanceof Content) {
+          content = v;
+        }
+      },
+      enumerable: true
+    }
+  });
+}
diff --git a/webWidgetTCT_device/src/content/js/manager.js b/webWidgetTCT_device/src/content/js/manager.js
new file mode 100755 (executable)
index 0000000..32643c4
--- /dev/null
@@ -0,0 +1,376 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+function _ContentManagerChangeCallback(result) {
+  if (result.state === 'oncontentadded' || result.state === 'oncontentupdated') {
+    var content = native_.getResultObject(result);
+    native_.callIfPossible(this[result.state], createContentObject_(content));
+  } else if (result.state === 'oncontentdiradded' || result.state === 'oncontentdirupdated') {
+    var contentDir = native_.getResultObject(result);
+    native_.callIfPossible(this[result.state], createContentDirObject_(contentDir));
+  } else if (result.state === 'oncontentremoved' || result.state === 'oncontentdirremoved') {
+    native_.callIfPossible(this[result.state], native_.getResultObject(result));
+  }
+}
+
+function ContentManager() {
+}
+
+ContentManager.prototype.update = function(content) {
+  xwalk.utils.checkPrivilegeAccess(privilege_.CONTENT_WRITE);
+
+  var args = validator_.validateArgs(arguments, [
+    {name: 'content', type: types_.PLATFORM_OBJECT, values: Content}
+  ]);
+
+  var data = {
+    content: args.content
+  };
+
+  var result = native_.callSync('ContentManager_update', data);
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+};
+
+ContentManager.prototype.updateBatch = function(contents, successCallback, errorCallback) {
+  xwalk.utils.checkPrivilegeAccess(privilege_.CONTENT_WRITE);
+
+  var args = validator_.validateArgs(arguments, [
+    {name: 'contents', type: types_.ARRAY, values: Content},
+    {name: 'successCallback', type: types_.FUNCTION, optional: true, nullable: true},
+    {name: 'errorCallback', type: types_.FUNCTION, optional: true, nullable: true}
+  ]);
+
+  var data = {
+    contents: args.contents
+  };
+
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+      return;
+    }
+    native_.callIfPossible(args.successCallback);
+  };
+
+  var result = native_.call('ContentManager_updateBatch', data, callback);
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+};
+
+ContentManager.prototype.getDirectories = function(successCallback, errorCallback) {
+  var args = validator_.validateArgs(arguments, [
+    {name: 'successCallback', type: types_.FUNCTION},
+    {name: 'errorCallback', type: types_.FUNCTION, optional: true, nullable: true}
+  ]);
+
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+      return;
+    }
+
+    var out = [];
+    result = native_.getResultObject(result);
+    for (var i = 0, max = result.length; i < max; i++) {
+      out.push(new ContentDirectory(result[i]));
+    }
+    native_.callIfPossible(args.successCallback, out);
+  };
+
+  native_.call('ContentManager_getDirectories', null, callback);
+};
+
+ContentManager.prototype.find = function(successCallback, errorCallback, directoryId, filter, sortMode, count, offset) {
+  xwalk.utils.checkPrivilegeAccess(privilege_.CONTENT_READ);
+
+  var args = validator_.validateArgs(arguments, [
+    {name: 'successCallback', type: types_.FUNCTION},
+    {name: 'errorCallback', type: types_.FUNCTION, optional: true, nullable: true},
+    {name: 'directoryId', type: types_.STRING, optional: true, nullable: true},
+    {
+      name: 'filter',
+      type: types_.PLATFORM_OBJECT,
+      values: [tizen.AttributeFilter, tizen.AttributeRangeFilter, tizen.CompositeFilter],
+      optional: true,
+      nullable: true
+    },
+    {name: 'sortMode', type: types_.PLATFORM_OBJECT, values: tizen.SortMode, optional: true, nullable: true},
+    {name: 'count', type: types_.UNSIGNED_LONG, optional: true, nullable: true},
+    {name: 'offset', type: types_.UNSIGNED_LONG, optional: true, nullable: true}
+  ]);
+
+  var data = {
+    directoryId: args.directoryId,
+    filter: utils_.repackFilter(args.filter),
+    sortMode: args.sortMode,
+    count: args.count,
+    offset: args.offset
+  };
+
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+      return;
+    }
+
+    var out = [];
+    result = native_.getResultObject(result);
+    try {
+      for (var i = 0, max = result.length; i < max; i++) {
+        out.push(createContentObject_(result[i]));
+      }
+    } catch(e) {
+      native_.callIfPossible(args.errorCallback, e);
+      return;
+    }
+
+    native_.callIfPossible(args.successCallback, out);
+  };
+
+  var result = native_.call('ContentManager_find', data, callback);
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+};
+
+ContentManager.prototype.scanFile = function(contentURI, successCallback, errorCallback) {
+  xwalk.utils.checkPrivilegeAccess(privilege_.CONTENT_WRITE);
+
+  var args = validator_.validateArgs(arguments, [
+    {name: 'contentURI', type: types_.STRING},
+    {name: 'successCallback', type: types_.FUNCTION, optional: true, nullable: true},
+    {name: 'errorCallback', type: types_.FUNCTION, optional: true, nullable: true}
+  ]);
+
+  var path = args.contentURI.trim();
+  if (!path.length) {
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR, 'File path is not valid.');
+  }
+
+  var data = {
+    contentURI: convertUriToPath_(path)
+  };
+
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+      return;
+    }
+    native_.callIfPossible(args.successCallback, args.contentURI);
+  };
+
+  var result = native_.call('ContentManager_scanFile', data, callback);
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+};
+
+ContentManager.prototype.scanDirectory = function(contentDirURI, recursive, successCallback, errorCallback) {
+  xwalk.utils.checkPrivilegeAccess(privilege_.CONTENT_WRITE);
+
+  var args = validator_.validateArgs(arguments, [
+    {name: 'contentDirURI', type: types_.STRING},
+    {name: 'recursive', type: types_.BOOLEAN},
+    {name: 'successCallback', type: types_.FUNCTION, optional: true, nullable: true},
+    {name: 'errorCallback', type: types_.FUNCTION, optional: true, nullable: true}
+  ]);
+
+  var path = args.contentDirURI.trim();
+  if (!path.length) {
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR, 'Directory path is not valid.');
+  }
+
+  var data = {
+    contentDirURI: convertUriToPath_(path),
+    recursive: args.recursive
+  };
+
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+      return;
+    }
+    native_.callIfPossible(args.successCallback, args.contentDirURI);
+  };
+
+  var result = native_.call('ContentManager_scanDirectory', data, callback);
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+};
+
+ContentManager.prototype.cancelScanDirectory = function(contentDirURI) {
+  xwalk.utils.checkPrivilegeAccess(privilege_.CONTENT_WRITE);
+
+  var args = validator_.validateArgs(arguments, [
+    {name: 'contentDirURI', type: types_.STRING}
+  ]);
+
+  var path = args.contentDirURI.trim();
+  if (!path.length) {
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR, 'Directory path is not valid.');
+  }
+
+  var data = {
+    contentDirURI: convertUriToPath_(path)
+  };
+
+  var result = native_.callSync('ContentManager_cancelScanDirectory', data);
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+};
+
+ContentManager.prototype.setChangeListener = function(changeCallback) {
+  xwalk.utils.checkPrivilegeAccess(privilege_.CONTENT_READ);
+
+  var args = validator_.validateArgs(arguments, [{
+    name: 'changeCallback',
+    type: types_.LISTENER,
+    values: ['oncontentadded', 'oncontentupdated', 'oncontentremoved', 'oncontentdiradded', 'oncontentdirupdated', 'oncontentdirremoved']
+  }]);
+
+  var listenerId = 'ContentManagerChangeCallback';
+
+  var data = {
+    listenerId: listenerId
+  };
+
+  var callbacks = {
+    oncontentadded: args.changeCallback.oncontentadded,
+    oncontentupdated: args.changeCallback.oncontentupdated,
+    oncontentremoved: args.changeCallback.oncontentremoved,
+    oncontentdiradded: args.changeCallback.oncontentdiradded,
+    oncontentdirupdated: args.changeCallback.oncontentdirupdated,
+    oncontentdirremoved: args.changeCallback.oncontentdirremoved
+  };
+
+  native_.addListener('ContentManagerChangeCallback',
+      _ContentManagerChangeCallback.bind(callbacks));
+
+  var result = native_.callSync('ContentManager_setChangeListener', data);
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+};
+
+ContentManager.prototype.unsetChangeListener = function() {
+  xwalk.utils.checkPrivilegeAccess(privilege_.CONTENT_READ);
+
+  var data = {};
+
+  var result = native_.callSync('ContentManager_unsetChangeListener', data);
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+};
+
+ContentManager.prototype.getPlaylists = function(successCallback, errorCallback) {
+  xwalk.utils.checkPrivilegeAccess(privilege_.CONTENT_READ);
+
+  var args = validator_.validateArgs(arguments, [
+    {name: 'successCallback', type: types_.FUNCTION},
+    {name: 'errorCallback', type: types_.FUNCTION, optional: true, nullable: true}
+  ]);
+
+  var data = {};
+
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+      return;
+    }
+    var out = [];
+    result = native_.getResultObject(result);
+    for (var i = 0, max = result.length; i < max; i++) {
+      out.push(new Playlist(result[i]));
+    }
+    native_.callIfPossible(args.successCallback, out);
+  };
+
+  native_.call('ContentManager_getPlaylists', data, callback);
+};
+
+ContentManager.prototype.createPlaylist = function(name, successCallback, errorCallback, sourcePlaylist) {
+  xwalk.utils.checkPrivilegeAccess(privilege_.CONTENT_WRITE);
+
+  var args = validator_.validateArgs(arguments, [
+    {name: 'name', type: types_.STRING},
+    {name: 'successCallback', type: types_.FUNCTION},
+    {name: 'errorCallback', type: types_.FUNCTION, optional: true, nullable: true},
+    {name: 'sourcePlaylist', type: types_.PLATFORM_OBJECT, values: Playlist, optional: true, nullable: true}
+  ]);
+
+  if (!arguments.length || !type_.isString(arguments[0]) ||
+    (type_.isString(arguments[0]) && !arguments[0].length)) {
+    setTimeout(function() {
+      args.errorCallback(new WebAPIException(WebAPIException.INVALID_VALUES_ERR));
+    }, 0);
+    return;
+  }
+
+  var data = {
+    name: args.name,
+    sourcePlaylist: args.sourcePlaylist
+  };
+
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+      return;
+    }
+    native_.callIfPossible(args.successCallback, new Playlist(native_.getResultObject(result)));
+  };
+
+  native_.call('ContentManager_createPlaylist', data, callback);
+};
+
+ContentManager.prototype.removePlaylist = function(id, successCallback, errorCallback) {
+  xwalk.utils.checkPrivilegeAccess(privilege_.CONTENT_WRITE);
+
+  var args = validator_.validateArgs(arguments, [
+    {name: 'id', type: types_.STRING},
+    {name: 'successCallback', type: types_.FUNCTION, optional: true, nullable: true},
+    {name: 'errorCallback', type: types_.FUNCTION, optional: true, nullable: true}
+  ]);
+
+  var data = {
+    id: args.id
+  };
+
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+      return;
+    }
+    native_.callIfPossible(args.successCallback);
+  };
+
+  native_.call('ContentManager_removePlaylist', data, callback);
+};
+
+exports = new ContentManager();
diff --git a/webWidgetTCT_device/src/content/js/playlist.js b/webWidgetTCT_device/src/content/js/playlist.js
new file mode 100755 (executable)
index 0000000..1dd6a4f
--- /dev/null
@@ -0,0 +1,297 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+function Playlist(data) {
+  var id;
+  var numberOfTracks;
+
+  Object.defineProperties(this, {
+    id: {
+      get: function() {
+        return id;
+      },
+      set: function(v) {
+        if (edit_.isAllowed) {
+          id = converter_.toString(v, false);
+        }
+      },
+      enumerable: true
+    },
+    name: {
+      get: function() {
+        var result = native_.callSync('ContentPlaylist_getName', {'id' : Number(id)});
+        if (native_.isFailure(result)) {
+          throw native_.getErrorObject(result);
+        }
+        return native_.getResultObject(result);
+      },
+      set: function(v) {
+        xwalk.utils.checkPrivilegeAccess(privilege_.CONTENT_WRITE);
+        if (!type_.isNull(v)) {
+          var name = converter_.toString(v, false);
+          var result = native_.callSync('ContentPlaylist_setName',
+                  {'id' : Number(id), 'name' : name});
+          if (native_.isFailure(result)) {
+            throw native_.getErrorObject(result);
+          }
+        }
+      },
+      enumerable: true
+    },
+    numberOfTracks: {
+      get: function() {
+        var result = native_.callSync('ContentPlaylist_getNumberOfTracks', {'id' : Number(id)});
+        if (native_.isFailure(result)) {
+          throw native_.getErrorObject(result);
+        }
+        return native_.getResultObject(result);
+      },
+      set: function() {},
+      enumerable: true
+    },
+    thumbnailURI: {
+      get: function() {
+        var result = native_.callSync('ContentPlaylist_getThumbnailUri', {'id' : Number(id)});
+        if (native_.isFailure(result)) {
+          throw native_.getErrorObject(result);
+        }
+        var res = native_.getResultObject(result);
+        //CoreAPI not support empty thumbnail, so one space must be used instead null thumbnail
+        return res === " " ? null : res;
+      },
+      set: function(v) {
+        xwalk.utils.checkPrivilegeAccess(privilege_.CONTENT_WRITE);
+        var thumbnailURI = converter_.toString(v, true);
+        if (type_.isNullOrUndefined(thumbnailURI)) {
+          //CoreAPI not support empty thumbnail, so one space must be used instead null thumbnail
+          thumbnailURI = " ";
+        }
+        //TODO probably thumbnailURI should be converted here to absolute uri in case of virtual
+        var result = native_.callSync('ContentPlaylist_setThumbnailUri',
+                {'id' : Number(id), 'uri' : thumbnailURI});
+        if (native_.isFailure(result)) {
+          throw native_.getErrorObject(result);
+        }
+      },
+      enumerable: true
+    },
+  });
+
+  if (type_.isObject(data)) {
+    // fill object with data
+    edit_.allow();
+    for (var key in data) {
+      if (data.hasOwnProperty(key) && this.hasOwnProperty(key)) {
+        this[key] = data[key];
+      }
+    }
+    edit_.disallow();
+  }
+}
+
+Playlist.prototype.add = function (item) {
+  xwalk.utils.checkPrivilegeAccess(privilege_.CONTENT_WRITE);
+
+  var args = validator_.validateArgs(arguments, [
+    {name: 'item', type: types_.PLATFORM_OBJECT, values: Content}
+  ]);
+
+  var data = {
+    contentId: args.item.id,
+    playlistId: this.id,
+  };
+
+  var result = native_.callSync('ContentPlaylist_add', data);
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+};
+
+Playlist.prototype.addBatch = function (items, successCallback, errorCallback) {
+  xwalk.utils.checkPrivilegeAccess(privilege_.CONTENT_WRITE);
+
+  var args = validator_.validateArgs(arguments, [
+    {name: 'items', type: types_.ARRAY, values: Content},
+    {name: 'successCallback', type: types_.FUNCTION, optional: true, nullable: true},
+    {name: 'errorCallback', type: types_.FUNCTION, optional: true, nullable: true}
+  ]);
+
+  var data = {
+    playlistId: this.id,
+    contents: args.items
+  };
+
+  var callback = function (result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+      return;
+    }
+    native_.callIfPossible(args.successCallback);
+  };
+
+  native_.call('ContentPlaylist_addBatch', data, callback);
+};
+
+Playlist.prototype.remove = function (item) {
+  xwalk.utils.checkPrivilegeAccess(privilege_.CONTENT_WRITE);
+
+  var args = validator_.validateArgs(arguments, [
+    {name: 'item', type: types_.PLATFORM_OBJECT, values: PlaylistItem}
+  ]);
+
+  var data = {
+    playlistId: this.id,
+    memberId: args.item.content.memberId
+  };
+  var result = native_.callSync('ContentPlaylist_remove', data);
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+};
+
+Playlist.prototype.removeBatch = function (items, successCallback, errorCallback) {
+  xwalk.utils.checkPrivilegeAccess(privilege_.CONTENT_WRITE);
+
+  var args = validator_.validateArgs(arguments, [
+    {name: 'items', type: types_.ARRAY, values: PlaylistItem},
+    {name: 'successCallback', type: types_.FUNCTION, optional: true, nullable: true},
+    {name: 'errorCallback', type: types_.FUNCTION, optional: true, nullable: true}
+  ]);
+
+  var members = [];
+  for (var i = 0; i < args.items.length; i++) {
+    members.push(args.items[i].content.memberId);
+  }
+
+  var data = {
+    playlistId: this.id,
+    members: members
+  };
+
+  var callback = function (result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+      return;
+    }
+    native_.callIfPossible(args.successCallback);
+  };
+
+  native_.call('ContentPlaylist_removeBatch', data, callback);
+};
+
+Playlist.prototype.get = function (successCallback, errorCallback, count, offset) {
+  xwalk.utils.checkPrivilegeAccess(privilege_.CONTENT_READ);
+
+  var args = validator_.validateArgs(arguments, [
+    {name: 'successCallback', type: types_.FUNCTION},
+    {name: 'errorCallback', type: types_.FUNCTION, optional: true, nullable: true},
+    {name: 'count', type: types_.LONG, optional: true},
+    {name: 'offset', type: types_.LONG, optional: true}
+  ]);
+
+  if (args.offset < 0 || args.count < 0) {
+    setTimeout(function() {
+      args.errorCallback(new WebAPIException(WebAPIException.INVALID_VALUES_ERR));
+    }, 0);
+    return;
+  }
+
+  var data = {
+    playlistId: this.id,
+    count: type_.isNullOrUndefined(args.count) ? -1 : args.count,
+    offset: type_.isNullOrUndefined(args.offset) ? -1 : args.offset
+  };
+
+  var callback = function (result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+      return;
+    }
+    result = native_.getResultObject(result);
+    var out = [];
+    for (var i = 0, max = result.length; i < max; i++) {
+      var itemToPush = createContentObject_(result[i]);
+      itemToPush['memberId'] = result[i]['playlist_member_id'];
+      out.push(new PlaylistItem(itemToPush));
+    }
+    native_.callIfPossible(args.successCallback, out);
+  };
+
+  native_.call('ContentPlaylist_get', data, callback);
+};
+
+Playlist.prototype.setOrder = function (items, successCallback, errorCallback) {
+  xwalk.utils.checkPrivilegeAccess(privilege_.CONTENT_WRITE);
+
+  var args = validator_.validateArgs(arguments, [
+    {name: 'items', type: types_.ARRAY, values: PlaylistItem},
+    {name: 'successCallback', type: types_.FUNCTION, optional: true, nullable: true},
+    {name: 'errorCallback', type: types_.FUNCTION, optional: true, nullable: true}
+  ]);
+
+  if (!args.items.length) {
+    setTimeout(function() {
+      args.errorCallback(new WebAPIException(WebAPIException.INVALID_VALUES_ERR));
+    }, 0);
+    return;
+  }
+
+  var members = [];
+  for (var i = 0; i < args.items.length; i++) {
+    members.push(args.items[i].content.memberId);
+  }
+
+  var data = {
+    playlistId: this.id,
+    members: members,
+  };
+
+  var callback = function (result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+      return;
+    }
+    native_.callIfPossible(args.successCallback);
+  };
+
+  native_.call('ContentPlaylist_setOrder', data, callback);
+};
+
+Playlist.prototype.move = function (item, delta, successCallback, errorCallback) {
+  xwalk.utils.checkPrivilegeAccess(privilege_.CONTENT_WRITE);
+
+  var args = validator_.validateArgs(arguments, [
+    {name: 'item', type: types_.PLATFORM_OBJECT, values: PlaylistItem},
+    {name: 'delta', type: types_.LONG},
+    {name: 'successCallback', type: types_.FUNCTION, optional: true, nullable: true},
+    {name: 'errorCallback', type: types_.FUNCTION, optional: true, nullable: true}
+  ]);
+
+  var data = {
+    playlistId: this.id,
+    memberId: args.item.content.memberId,
+    delta: args.delta
+  };
+
+  var callback = function (result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+      return;
+    }
+    native_.callIfPossible(args.successCallback);
+  };
+  native_.call('ContentPlaylist_move', data, callback);
+};
diff --git a/webWidgetTCT_device/src/datacontrol/datacontrol.gyp b/webWidgetTCT_device/src/datacontrol/datacontrol.gyp
new file mode 100755 (executable)
index 0000000..83d8f57
--- /dev/null
@@ -0,0 +1,31 @@
+{
+  'includes':[
+    '../common/common.gypi',
+  ],
+  'targets': [
+    {
+      'target_name': 'tizen_datacontrol',
+      'type': 'loadable_module',
+      'dependencies': [
+        '../common/common.gyp:tizen_common',
+      ],
+      'sources': [
+        'datacontrol_api.js',
+        'datacontrol_extension.cc',
+        'datacontrol_extension.h',
+        'datacontrol_instance.cc',
+        'datacontrol_instance.h'
+      ],
+      'conditions': [
+        ['tizen == 1', {
+          'variables': {
+            'packages': [
+              'capi-data-control',
+              'capi-base-common'
+            ]
+          },
+        }],
+      ],
+    },
+  ],
+}
diff --git a/webWidgetTCT_device/src/datacontrol/datacontrol_api.js b/webWidgetTCT_device/src/datacontrol/datacontrol_api.js
new file mode 100755 (executable)
index 0000000..b1af8c2
--- /dev/null
@@ -0,0 +1,449 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+tizen.debug = extension;
+
+var validator_ = xwalk.utils.validator;
+var types_ = validator_.Types;
+
+
+var callbackId = 0;
+var callbacks = {};
+
+extension.setMessageListener(function(json) {
+  var result = JSON.parse(json);
+  var callback = callbacks[result['callbackId']];
+  callback(result);
+  delete callbacks[result['callbackId']];
+});
+
+function nextCallbackId() {
+  return callbackId++;
+}
+
+function callNative(cmd, args) {
+  var json = {'cmd': cmd, 'args': args};
+  var argjson = JSON.stringify(json);
+  var resultString = extension.internal.sendSyncMessage(argjson);
+  var result = JSON.parse(resultString);
+
+  if (typeof result !== 'object') {
+    throw new WebAPIException(WebAPIException.UNKNOWN_ERR);
+  }
+
+  if (result['status'] == 'success') {
+    if (result['result']) {
+      return result['result'];
+    }
+    return true;
+  } else if (result['status'] == 'error') {
+    var err = result['error'];
+    if (err) {
+      throw new WebAPIException(err.name, err.message);
+    }
+    return false;
+  }
+}
+
+
+function callNativeWithCallback(cmd, args, callback) {
+  if (callback) {
+    var id = nextCallbackId();
+    args['callbackId'] = id;
+    callbacks[id] = callback;
+  }
+
+  return callNative(cmd, args);
+}
+
+function SetReadOnlyProperty(obj, n, v) {
+  Object.defineProperty(obj, n, {value: v, writable: false});
+}
+
+var DataType = {
+  'MAP': 'MAP',
+  'SQL': 'SQL'
+};
+
+function DataControlManager() {
+  // constructor of DataControlManager
+}
+
+
+DataControlManager.prototype.getDataControlConsumer = function(providerId, dataId, type) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.DATACONTROL_CONSUMER);
+
+  var args = validator_.validateArgs(arguments, [
+    {'name': 'providerId', 'type': types_.STRING},
+    {'name': 'dataId', 'type': types_.STRING},
+    {'name': 'type', 'type': types_.ENUM, 'values': ['MAP', 'SQL']}
+  ]);
+
+  var returnObject = null;
+  if (type === 'SQL') {
+    returnObject = new SQLDataControlConsumer();
+  } else if (type === 'MAP') {
+    returnObject = new MappedDataControlConsumer();
+  }
+  SetReadOnlyProperty(returnObject, 'type', type); // read only property
+  SetReadOnlyProperty(returnObject, 'providerId', providerId); // read only property
+  SetReadOnlyProperty(returnObject, 'dataId', dataId); // read only property
+
+  return returnObject;
+};
+
+
+function DataControlConsumerObject() {
+  // constructor of DataControlConsumerObject
+}
+
+
+
+function SQLDataControlConsumer() {
+  // constructor of SQLDataControlConsumer
+}
+
+SQLDataControlConsumer.prototype = new DataControlConsumerObject();
+SQLDataControlConsumer.prototype.constructor = SQLDataControlConsumer;
+
+SQLDataControlConsumer.prototype.insert = function(reqId, insertionData) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.DATACONTROL_CONSUMER);
+
+  var args = validator_.validateArgs(arguments, [
+    {'name': 'reqId', 'type': types_.LONG},
+    {'name': 'insertionData', 'type': types_.DICTIONARY},
+    {'name': 'successCallback', 'type': types_.FUNCTION, optional: true, nullable: true},
+    {'name': 'errorCallback', 'type': types_.FUNCTION, optional: true, nullable: true}
+  ]);
+
+  var nativeParam = {
+    'providerId': this.providerId,
+    'dataId': this.dataId,
+    'reqId': args.reqId,
+    'insertionData': insertionData
+  };
+  try {
+    var syncResult =
+        callNativeWithCallback('SQLDataControlConsumer_insert', nativeParam, function(result) {
+      if (result.status == 'success') {
+        if (args.successCallback) {
+          args.successCallback(result['requestId'], result['result']);
+        }
+      }
+      if (result.status == 'error') {
+        if (args.errorCallback) {
+          var err = result['result'];
+          var e = new WebAPIException(err.name, err.message);
+          args.errorCallback(result['requestId'], e);
+        }
+      }
+    });
+  } catch (e) {
+    throw e;
+  }
+};
+
+SQLDataControlConsumer.prototype.update = function(reqId, updateData, where) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.DATACONTROL_CONSUMER);
+
+  var args = validator_.validateArgs(arguments, [
+    {'name': 'reqId', 'type': types_.LONG},
+    {'name': 'updateData', 'type': types_.DICTIONARY},
+    {'name': 'where', 'type': types_.STRING},
+    {'name': 'successCallback', 'type': types_.FUNCTION, optional: true, nullable: true},
+    {'name': 'errorCallback', 'type': types_.FUNCTION, optional: true, nullable: true}
+  ]);
+
+  var nativeParam = {
+    'providerId': this.providerId,
+    'dataId': this.dataId,
+    'reqId': args.reqId,
+    'where': args.where,
+    'updateData': args.updateData
+  };
+  try {
+    var syncResult =
+        callNativeWithCallback('SQLDataControlConsumer_update', nativeParam, function(result) {
+      if (result.status == 'success') {
+        if (args.successCallback) {
+          args.successCallback(result['requestId']);
+        }
+      }
+      if (result.status == 'error') {
+        if (args.errorCallback) {
+          var err = result['result'];
+          var e = new WebAPIException(err.name, err.message);
+          args.errorCallback(result['requestId'], e);
+        }
+      }
+    });
+  } catch (e) {
+    throw e;
+  }
+
+};
+
+SQLDataControlConsumer.prototype.remove = function(reqId, where) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.DATACONTROL_CONSUMER);
+
+  var args = validator_.validateArgs(arguments, [
+    {'name': 'reqId', 'type': types_.LONG},
+    {'name': 'where', 'type': types_.STRING},
+    {'name': 'successCallback', 'type': types_.FUNCTION, optional: true, nullable: true},
+    {'name': 'errorCallback', 'type': types_.FUNCTION, optional: true, nullable: true}
+  ]);
+
+  var nativeParam = {
+    'providerId': this.providerId,
+    'dataId': this.dataId,
+    'reqId': args.reqId,
+    'where': args.where
+  };
+  try {
+    var syncResult =
+        callNativeWithCallback('SQLDataControlConsumer_remove', nativeParam, function(result) {
+      if (result.status == 'success') {
+        if (args.successCallback) {
+          args.successCallback(result['requestId']);
+        }
+      }
+      if (result.status == 'error') {
+        if (args.errorCallback) {
+          var err = result['result'];
+          var e = new WebAPIException(err.name, err.message);
+          args.errorCallback(result['requestId'], e);
+        }
+      }
+    });
+  } catch (e) {
+    throw e;
+  }
+
+};
+
+SQLDataControlConsumer.prototype.select = function(reqId, columns, where, successCallback) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.DATACONTROL_CONSUMER);
+
+  var args = validator_.validateArgs(arguments, [
+    {'name': 'reqId', 'type': types_.LONG},
+    {'name': 'columns', 'type': types_.ARRAY},
+    {'name': 'where', 'type': types_.STRING},
+    {'name': 'successCallback', 'type': types_.FUNCTION},
+    {'name': 'errorCallback', 'type': types_.FUNCTION, optional: true, nullable: true},
+    {'name': 'page', 'type': types_.LONG, optional: true},
+    {'name': 'maxNumberPerPage', 'type': types_.LONG, optional: true}
+  ]);
+
+  var nativeParam = {
+    'providerId': this.providerId,
+    'dataId': this.dataId,
+    'reqId': args.reqId,
+    'columns': args.columns,
+    'where': args.where
+  };
+  if (args['page']) {
+    nativeParam['page'] = args.page;
+  }
+  if (args['maxNumberPerPage']) {
+    nativeParam['maxNumberPerPage'] = args.maxNumberPerPage;
+  }
+  try {
+    var syncResult =
+        callNativeWithCallback('SQLDataControlConsumer_select', nativeParam, function(result) {
+      if (result.status == 'success') {
+        args.successCallback(result['result'], result['requestId']);
+      }
+      if (result.status == 'error') {
+        if (args.errorCallback) {
+          var err = result['result'];
+          var e = new WebAPIException(err.name, err.message);
+          args.errorCallback(result['requestId'], e);
+        }
+      }
+    });
+    // if you need synchronous result from native function using 'syncResult'.
+  } catch (e) {
+    throw e;
+  }
+
+};
+
+
+function MappedDataControlConsumer() {
+  // constructor of MappedDataControlConsumer
+}
+
+MappedDataControlConsumer.prototype = new DataControlConsumerObject();
+MappedDataControlConsumer.prototype.constructor = MappedDataControlConsumer;
+
+MappedDataControlConsumer.prototype.addValue = function(reqId, key, value) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.DATACONTROL_CONSUMER);
+
+  var args = validator_.validateArgs(arguments, [
+    {'name': 'reqId', 'type': types_.LONG},
+    {'name': 'key', 'type': types_.STRING},
+    {'name': 'value', 'type': types_.STRING},
+    {'name': 'successCallback', 'type': types_.FUNCTION, optional: true, nullable: true},
+    {'name': 'errorCallback', 'type': types_.FUNCTION, optional: true, nullable: true}
+  ]);
+
+  var nativeParam = {
+    'providerId': this.providerId,
+    'dataId': this.dataId,
+    'reqId': args.reqId,
+    'key': args.key,
+    'value': args.value
+  };
+  try {
+    var syncResult =
+        callNativeWithCallback('MappedDataControlConsumer_addValue', nativeParam, function(result) {
+      if (result.status == 'success') {
+        if (args.successCallback) {
+          args.successCallback(result['requestId']);
+        }
+      }
+      if (result.status == 'error') {
+        if (args.errorCallback) {
+          var err = result['result'];
+          var e = new WebAPIException(err.name, err.message);
+          args.errorCallback(result['requestId'], e);
+        }
+      }
+    });
+  } catch (e) {
+    throw e;
+  }
+
+};
+
+MappedDataControlConsumer.prototype.removeValue = function(reqId, key, value, successCallback) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.DATACONTROL_CONSUMER);
+
+  var args = validator_.validateArgs(arguments, [
+    {'name': 'reqId', 'type': types_.LONG},
+    {'name': 'key', 'type': types_.STRING},
+    {'name': 'value', 'type': types_.STRING},
+    {'name': 'successCallback', 'type': types_.FUNCTION},
+    {'name': 'errorCallback', 'type': types_.FUNCTION, optional: true, nullable: true}
+  ]);
+
+  var nativeParam = {
+    'providerId': this.providerId,
+    'dataId': this.dataId,
+    'reqId': args.reqId,
+    'key': args.key,
+    'value': args.value
+  };
+  try {
+    var syncResult =
+        callNativeWithCallback('MappedDataControlConsumer_removeValue', nativeParam, function(result) {
+      if (result.status == 'success') {
+        args.successCallback(result['requestId']);
+      }
+      if (result.status == 'error') {
+        if (args.errorCallback) {
+          var err = result['result'];
+          var e = new WebAPIException(err.name, err.message);
+          args.errorCallback(result['requestId'], e);
+        }
+      }
+    });
+  } catch (e) {
+    throw e;
+  }
+
+};
+
+MappedDataControlConsumer.prototype.getValue = function(reqId, key, successCallback) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.DATACONTROL_CONSUMER);
+
+  var args = validator_.validateArgs(arguments, [
+    {'name': 'reqId', 'type': types_.LONG},
+    {'name': 'key', 'type': types_.STRING},
+    {'name': 'successCallback', 'type': types_.FUNCTION},
+    {'name': 'errorCallback', 'type': types_.FUNCTION, optional: true, nullable: true}
+  ]);
+
+  var nativeParam = {
+    'providerId': this.providerId,
+    'dataId': this.dataId,
+    'reqId': args.reqId,
+    'key': args.key
+  };
+  try {
+    var syncResult = callNativeWithCallback('MappedDataControlConsumer_getValue', nativeParam, function(result) {
+      if (result.status == 'success') {
+        args.successCallback(result['result'], result['requestId']);
+      }
+      if (result.status == 'error') {
+        if (args.errorCallback) {
+          var err = result['result'];
+          var e = new WebAPIException(err.name, err.message);
+          args.errorCallback(result['requestId'], e);
+        }
+      }
+    });
+  } catch (e) {
+    throw e;
+  }
+
+};
+
+MappedDataControlConsumer.prototype.updateValue = function(
+        reqId, key, oldValue, newValue, successCallback) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.DATACONTROL_CONSUMER);
+
+  var args = validator_.validateArgs(arguments, [
+    {'name': 'reqId', 'type': types_.LONG},
+    {'name': 'key', 'type': types_.STRING},
+    {'name': 'oldValue', 'type': types_.STRING},
+    {'name': 'newValue', 'type': types_.STRING},
+    {'name': 'successCallback', 'type': types_.FUNCTION},
+    {'name': 'errorCallback', 'type': types_.FUNCTION, optional: true, nullable: true}
+  ]);
+
+  var nativeParam = {
+    'providerId': this.providerId,
+    'dataId': this.dataId,
+    'reqId': args.reqId,
+    'key': args.key,
+    'oldValue': args.oldValue,
+    'newValue': args.newValue
+  };
+  try {
+    var syncResult =
+        callNativeWithCallback('MappedDataControlConsumer_updateValue', nativeParam, function(result) {
+      if (result.status == 'success') {
+        args.successCallback(result['requestId']);
+      }
+      if (result.status == 'error') {
+        if (args.errorCallback) {
+          var err = result['result'];
+          var e = new WebAPIException(err.name, err.message);
+          args.errorCallback(result['requestId'], e);
+        }
+      }
+    });
+  } catch (e) {
+    throw e;
+  }
+
+};
+
+
+
+exports = new DataControlManager();
+
diff --git a/webWidgetTCT_device/src/datacontrol/datacontrol_extension.cc b/webWidgetTCT_device/src/datacontrol/datacontrol_extension.cc
new file mode 100755 (executable)
index 0000000..b1f4a3e
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2015 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 "datacontrol/datacontrol_extension.h"
+
+#include "datacontrol/datacontrol_instance.h"
+
+// This will be generated from datacontrol_api.js
+extern const char kSource_datacontrol_api[];
+
+common::Extension* CreateExtension() {
+  return new DatacontrolExtension;
+}
+
+DatacontrolExtension::DatacontrolExtension() {
+  SetExtensionName("tizen.datacontrol");
+  SetJavaScriptAPI(kSource_datacontrol_api);
+}
+
+DatacontrolExtension::~DatacontrolExtension() {}
+
+common::Instance* DatacontrolExtension::CreateInstance() {
+  return new extension::datacontrol::DatacontrolInstance;
+}
+
diff --git a/webWidgetTCT_device/src/datacontrol/datacontrol_extension.h b/webWidgetTCT_device/src/datacontrol/datacontrol_extension.h
new file mode 100755 (executable)
index 0000000..e595dd5
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2015 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 DATACONTROL_DATACONTROL_EXTENSION_H_
+#define DATACONTROL_DATACONTROL_EXTENSION_H_
+
+#include "common/extension.h"
+
+class DatacontrolExtension : public common::Extension {
+ public:
+  DatacontrolExtension();
+  virtual ~DatacontrolExtension();
+
+ private:
+  virtual common::Instance* CreateInstance();
+};
+
+#endif  // DATACONTROL_DATACONTROL_EXTENSION_H_
diff --git a/webWidgetTCT_device/src/datacontrol/datacontrol_instance.cc b/webWidgetTCT_device/src/datacontrol/datacontrol_instance.cc
new file mode 100755 (executable)
index 0000000..24958d5
--- /dev/null
@@ -0,0 +1,901 @@
+/*
+ * Copyright (c) 2015 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 "datacontrol/datacontrol_instance.h"
+
+#include <glib.h>
+
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+#include <algorithm>
+#include <functional>
+
+#include "common/picojson.h"
+#include "common/logger.h"
+#include "common/platform_exception.h"
+
+#include "common/scope_exit.h"
+
+namespace extension {
+namespace datacontrol {
+
+using common::InvalidValuesException;
+using common::TypeMismatchException;
+using common::IOException;
+using common::SecurityException;
+using common::UnknownException;
+using common::NotFoundException;
+
+using common::ScopeExit;
+using common::operator+;
+
+struct DatacontrolInformation {
+  int callbackId;
+  int requestId;
+  int userDefinedRequestId;
+};
+
+static std::map<int, DatacontrolInformation*> IdMap;
+
+DatacontrolInstance::DatacontrolInstance() {
+  using std::placeholders::_1;
+  using std::placeholders::_2;
+  #define REGISTER_SYNC(c, x) \
+    RegisterSyncHandler(c, std::bind(&DatacontrolInstance::x, this, _1, _2));
+  REGISTER_SYNC("SQLDataControlConsumer_update", SQLDataControlConsumerUpdate);
+  REGISTER_SYNC("MappedDataControlConsumer_addValue",
+                MappedDataControlConsumerAddvalue);
+  REGISTER_SYNC("SQLDataControlConsumer_select",
+                SQLDataControlConsumerSelect);
+  REGISTER_SYNC("SQLDataControlConsumer_remove", SQLDataControlConsumerRemove);
+  REGISTER_SYNC("MappedDataControlConsumer_removeValue",
+                MappedDataControlConsumerRemovevalue);
+  REGISTER_SYNC("MappedDataControlConsumer_updateValue",
+                MappedDataControlConsumerUpdatevalue);
+  REGISTER_SYNC("DataControlManager_getDataControlConsumer",
+                DataControlManagerGetdatacontrolconsumer);
+  REGISTER_SYNC("SQLDataControlConsumer_insert", SQLDataControlConsumerInsert);
+  REGISTER_SYNC("MappedDataControlConsumer_getValue",
+                MappedDataControlConsumerGetvalue);
+  #undef REGISTER_SYNC
+}
+
+DatacontrolInstance::~DatacontrolInstance() {
+}
+
+static void ReplyAsync(DatacontrolInstance* instance, int callbackId,
+                       bool isSuccess, picojson::object* param) {
+  LoggerD("Enter");
+  (*param)["callbackId"] = picojson::value(static_cast<double>(callbackId));
+  (*param)["status"] = picojson::value(isSuccess ? "success" : "error");
+
+  picojson::value result = picojson::value(*param);
+
+  common::Instance::PostMessage(instance, result.serialize().c_str());
+}
+
+static bool SQLColumnName(result_set_cursor cursor, int columnIndex,
+                          picojson::value& name) {
+  LoggerD("Enter");
+  char buffer[4096];
+  int result = data_control_sql_get_column_name(cursor, columnIndex, buffer);
+  if (result != DATA_CONTROL_ERROR_NONE) {
+    LoggerE("Getting column item type is failed with error : %d", result);
+    return false;
+  }
+  name = picojson::value(buffer);
+  return true;
+}
+
+static bool SQLColumnValue(result_set_cursor cursor, int columnIndex,
+                           picojson::value& val) {
+  LoggerD("Enter");
+  data_control_sql_column_type_e type = DATA_CONTROL_SQL_COLUMN_TYPE_UNDEFINED;
+  int result =
+      data_control_sql_get_column_item_type(cursor, columnIndex, &type);
+  if (result != DATA_CONTROL_ERROR_NONE) {
+    LoggerE("Getting column item type is failed with error : %d", result);
+    return false;
+  }
+  switch (type) {
+    case DATA_CONTROL_SQL_COLUMN_TYPE_INT64: {
+      int64_t data = 0;
+      result = data_control_sql_get_int64_data(cursor, columnIndex, &data);
+      if (result != DATA_CONTROL_ERROR_NONE) break;
+      val = picojson::value(static_cast<double>(data));
+      break;
+    }
+    case DATA_CONTROL_SQL_COLUMN_TYPE_DOUBLE: {
+      double data = 0;
+      result = data_control_sql_get_double_data(cursor, columnIndex, &data);
+      if (result != DATA_CONTROL_ERROR_NONE) break;
+      val = picojson::value(data);
+      break;
+    }
+    case DATA_CONTROL_SQL_COLUMN_TYPE_TEXT: {
+      int size = data_control_sql_get_column_item_size(cursor, columnIndex);
+      char *buffer = new char[size + 1];
+      result = data_control_sql_get_text_data(cursor, columnIndex, buffer);
+      if (result != DATA_CONTROL_ERROR_NONE) {
+        LoggerE("Getting Text value failed : %s", get_error_message(result));
+        delete[] buffer;
+        break;
+      }
+      val = picojson::value(buffer);
+      delete[] buffer;
+      break;
+    }
+    case DATA_CONTROL_SQL_COLUMN_TYPE_BLOB: {
+      int size = data_control_sql_get_column_item_size(cursor, columnIndex);
+      char *buffer = new char[size + 1];
+      result =
+          data_control_sql_get_blob_data(cursor, columnIndex, buffer, size);
+      if (result != DATA_CONTROL_ERROR_NONE) {
+        delete[] buffer;
+        break;
+      }
+      val = picojson::value(buffer);
+      delete[] buffer;
+      break;
+    }
+    case DATA_CONTROL_SQL_COLUMN_TYPE_NULL: {
+      val = picojson::value();
+      break;
+    }
+    default: {
+      LoggerE("%th column is undefined column type", columnIndex);
+      return false;
+    }
+  }
+  if (result != DATA_CONTROL_ERROR_NONE) {
+    LoggerE("Getting column item value is failed with error : %s",
+            ::get_error_message(result));
+    return false;
+  } else {
+    return true;
+  }
+}
+
+static void MAPAddResponseCallback(int requestId, data_control_h handle,
+                                   bool providerResult,
+                                   const char *error, void *user_data) {
+  LoggerD("Enter");
+  DatacontrolInformation *info = IdMap[requestId];
+  if (info == NULL) {
+    LoggerE("Invalid context");
+    return;
+  }
+
+  picojson::object obj;
+  obj["requestId"] =
+      picojson::value(static_cast<double>(info->userDefinedRequestId));
+  if (!providerResult) {
+    obj["result"] = InvalidValuesException(error).ToJSON();
+  }
+
+  ReplyAsync(static_cast<DatacontrolInstance*>(user_data), info->callbackId,
+             providerResult, &obj);
+  delete info;
+  IdMap.erase(requestId);
+}
+
+static void MAPSetResponseCallback(int requestId, data_control_h handle,
+                                   bool providerResult,
+                                   const char *error, void *user_data) {
+  LoggerD("Enter");
+  DatacontrolInformation *info = IdMap[requestId];
+  if (info == NULL) {
+    LoggerE("Invalid context");
+    return;
+  }
+
+  picojson::object obj;
+  obj["requestId"] =
+      picojson::value(static_cast<double>(info->userDefinedRequestId));
+  if (!providerResult) {
+    obj["result"] = NotFoundException(error).ToJSON();
+  }
+
+  ReplyAsync(static_cast<DatacontrolInstance*>(user_data), info->callbackId, providerResult, &obj);
+  delete info;
+  IdMap.erase(requestId);
+}
+
+static void MAPGetResponseCallback(int requestId, data_control_h handle,
+                                   char **result_value_list,
+                                   int result_value_count,
+                                   bool providerResult,
+                                   const char *error, void *user_data) {
+  LoggerD("Enter");
+  DatacontrolInformation *info = IdMap[requestId];
+  if (info == NULL) {
+    LoggerE("Invalid context");
+    return;
+  }
+
+  picojson::object obj;
+  obj["requestId"] =
+      picojson::value(static_cast<double>(info->userDefinedRequestId));
+  if (!providerResult) {
+    obj["result"] = NotFoundException(error).ToJSON();
+  } else {
+    picojson::array result;
+    for (int i=0; i < result_value_count; i++) {
+      result.push_back(picojson::value(result_value_list[i]));
+    }
+    obj["result"] = picojson::value(result);
+  }
+
+  ReplyAsync(static_cast<DatacontrolInstance*>(user_data), info->callbackId,
+             providerResult, &obj);
+  delete info;
+  IdMap.erase(requestId);
+}
+
+static void MAPRemoveReponseCallback(int requestId, data_control_h handle,
+                                     bool providerResult,
+                                     const char *error, void *user_data) {
+  LoggerD("Enter");
+  DatacontrolInformation *info = IdMap[requestId];
+  if (info == NULL) {
+    LoggerE("Invalid context");
+    return;
+  }
+
+  picojson::object obj;
+  obj["requestId"] =
+      picojson::value(static_cast<double>(info->userDefinedRequestId));
+  if (!providerResult) {
+    obj["result"] = NotFoundException(error).ToJSON();
+  }
+
+  ReplyAsync(static_cast<DatacontrolInstance*>(user_data), info->callbackId,
+             providerResult, &obj);
+  delete info;
+  IdMap.erase(requestId);
+}
+
+
+static void SQLSelectResponseCallback(int requestId, data_control_h handle,
+                                      result_set_cursor cursor,
+                                      bool providerResult,
+                                      const char *error, void *user_data) {
+  LoggerD("Enter");
+  DatacontrolInformation *info = IdMap[requestId];
+  if (info == NULL) {
+    LoggerE("Invalid context");
+    return;
+  }
+
+  picojson::object obj;
+  obj["requestId"] =
+      picojson::value(static_cast<double>(info->userDefinedRequestId));
+  if (!providerResult) {
+    obj["result"] = InvalidValuesException(error).ToJSON();
+  } else {
+    picojson::array result;
+
+    while (data_control_sql_step_next(cursor) == DATA_CONTROL_ERROR_NONE) {
+      picojson::object rowData;
+      picojson::array columns;
+      picojson::array values;
+      int columnCount = data_control_sql_get_column_count(cursor);
+      for (int i=0; i < columnCount; i++) {
+        picojson::value column;
+        picojson::value value;
+        if (SQLColumnName(cursor, i, column) &&
+            SQLColumnValue(cursor, i, value)) {
+          columns.push_back(column);
+          values.push_back(value);
+        }
+      }
+      rowData["columns"] = picojson::value(columns);
+      rowData["values"] = picojson::value(values);
+      result.push_back(picojson::value(rowData));
+    }
+    obj["result"] = picojson::value(result);
+  }
+  ReplyAsync(static_cast<DatacontrolInstance*>(user_data), info->callbackId,
+             providerResult, &obj);
+  delete info;
+  IdMap.erase(requestId);
+}
+
+static void SQLInsertResponseCallback(int requestId, data_control_h handle,
+                                      int64_t inserted_row_id,
+                                      bool providerResult,
+                                      const char *error, void *user_data) {
+  LoggerD("Enter");
+  DatacontrolInformation *info = IdMap[requestId];
+  if (info == NULL) {
+    LoggerE("Invalid context");
+    return;
+  }
+
+  picojson::object obj;
+  obj["requestId"] =
+      picojson::value(static_cast<double>(info->userDefinedRequestId));
+  if (!providerResult) {
+    obj["result"] = InvalidValuesException(error).ToJSON();
+  } else {
+    obj["result"] = picojson::value(static_cast<double>(inserted_row_id));
+  }
+
+  ReplyAsync(static_cast<DatacontrolInstance*>(user_data), info->callbackId,
+             providerResult, &obj);
+  delete info;
+  IdMap.erase(requestId);
+}
+
+static void SQLUpdateResponseCallback(int requestId, data_control_h handle,
+                                      bool providerResult,
+                                      const char *error, void *user_data) {
+  LoggerD("Enter");
+  DatacontrolInformation *info = IdMap[requestId];
+  if (info == NULL) {
+    LoggerE("Invalid context");
+    return;
+  }
+
+  picojson::object obj;
+  obj["requestId"] =
+      picojson::value(static_cast<double>(info->userDefinedRequestId));
+  if (!providerResult) {
+    obj["result"] = InvalidValuesException(error).ToJSON();
+  }
+
+  ReplyAsync(static_cast<DatacontrolInstance*>(user_data), info->callbackId,
+             providerResult, &obj);
+  delete info;
+  IdMap.erase(requestId);
+}
+
+static void SQLDeleteResponseCallback(int requestId, data_control_h handle,
+                                      bool providerResult,
+                                      const char *error, void *user_data) {
+  LoggerD("Enter");
+  DatacontrolInformation *info = IdMap[requestId];
+  if (info == NULL) {
+    LoggerE("Invalid context");
+    return;
+  }
+
+  picojson::object obj;
+  obj["requestId"] =
+      picojson::value(static_cast<double>(info->userDefinedRequestId));
+  if (!providerResult) {
+    obj["result"] = InvalidValuesException(error).ToJSON();
+  }
+
+  ReplyAsync(static_cast<DatacontrolInstance*>(user_data), info->callbackId,
+             providerResult, &obj);
+  delete info;
+  IdMap.erase(requestId);
+}
+
+static data_control_sql_response_cb sqlResponseCallback = {
+  SQLSelectResponseCallback,
+  SQLInsertResponseCallback,
+  SQLUpdateResponseCallback,
+  SQLDeleteResponseCallback
+};
+static data_control_map_response_cb mapResponseCallback = {
+  MAPGetResponseCallback,
+  MAPSetResponseCallback,
+  MAPAddResponseCallback,
+  MAPRemoveReponseCallback
+};
+
+#define RETURN_IF_FAIL(result, msg) \
+    do {\
+      if (result != DATA_CONTROL_ERROR_NONE) {\
+        LoggerE(msg" : %s", ::get_error_message(result));\
+        return result;\
+      }\
+    } while (0)\
+
+int DatacontrolInstance::RunMAPDataControlJob(const std::string& providerId,
+                                              const std::string& dataId,
+                                              int callbackId,
+                                              int userRequestId,
+                                              DataControlJob job) {
+  LoggerD("Enter");
+  int result = DATA_CONTROL_ERROR_NONE;
+  std::unique_ptr<DatacontrolInformation> info {new DatacontrolInformation()};
+  info->callbackId = callbackId;
+  info->userDefinedRequestId = userRequestId;
+  data_control_h handle;
+
+  SCOPE_EXIT {
+    ::data_control_map_destroy(handle);
+  };
+
+  result = ::data_control_map_create(&handle);
+  RETURN_IF_FAIL(result,
+                 "Creating map data control handle is failed with error");
+
+  result = ::data_control_map_set_provider_id(handle, providerId.c_str());
+  RETURN_IF_FAIL(result,
+                 "Setting provider id is failed with error");
+
+  result = ::data_control_map_set_data_id(handle, dataId.c_str());
+  RETURN_IF_FAIL(result,
+                 "Setting data id is failed th error");
+
+  result =
+      ::data_control_map_register_response_cb(handle, &mapResponseCallback,
+                                              this);
+  RETURN_IF_FAIL(result, "Setting result Callback failed with error");
+
+  result = job(handle, &info->requestId);
+  RETURN_IF_FAIL(result, "Doing job failed with error");
+
+  IdMap[info->requestId] = info.get();
+
+  info.release();
+
+  return result;
+}
+int DatacontrolInstance::RunSQLDataControlJob(const std::string& providerId,
+                                              const std::string& dataId,
+                                              int callbackId,
+                                              int userRequestId,
+                                              DataControlJob job) {
+  LoggerD("Enter");
+  int result = DATA_CONTROL_ERROR_NONE;
+  std::unique_ptr<DatacontrolInformation> info {new DatacontrolInformation()};
+  info->callbackId = callbackId;
+  info->userDefinedRequestId = userRequestId;
+  data_control_h handle;
+
+  SCOPE_EXIT {
+    ::data_control_sql_destroy(handle);
+  };
+
+  result = ::data_control_sql_create(&handle);
+  RETURN_IF_FAIL(result,
+                 "Creating sql data control handle is failed with error");
+
+  result = ::data_control_sql_set_provider_id(handle, providerId.c_str());
+  RETURN_IF_FAIL(result, "Setting provider id is failed with error");
+
+  result = ::data_control_sql_set_data_id(handle, dataId.c_str());
+  RETURN_IF_FAIL(result, "Setting data id is failed th error");
+
+  result =
+      ::data_control_sql_register_response_cb(handle, &sqlResponseCallback,
+                                              this);
+  RETURN_IF_FAIL(result, "Setting result Callback failed with error");
+
+  result = job(handle, &info->requestId);
+  RETURN_IF_FAIL(result, "Doing job failed with error");
+
+  IdMap[info->requestId] = info.get();
+
+  info.release();
+
+  return result;
+}
+
+#define CHECK_EXIST(args, name, out) \
+    if (!args.contains(name)) {\
+      ReportError(TypeMismatchException(name" is required argument"), out);\
+      return;\
+    }
+
+void DatacontrolInstance::DataControlManagerGetdatacontrolconsumer(
+    const picojson::value& args, picojson::object& out) {
+  LoggerD("Enter");
+  CHECK_EXIST(args, "providerId", out)
+  CHECK_EXIST(args, "dataId", out)
+}
+void DatacontrolInstance::SQLDataControlConsumerInsert(
+    const picojson::value& args, picojson::object& out) {
+  LoggerD("Enter");
+  CHECK_EXIST(args, "callbackId", out)
+  CHECK_EXIST(args, "reqId", out)
+  CHECK_EXIST(args, "providerId", out)
+  CHECK_EXIST(args, "dataId", out)
+  CHECK_EXIST(args, "insertionData", out)
+
+  const std::string& providerId = args.get("providerId").get<std::string>();
+  const std::string& dataId = args.get("dataId").get<std::string>();
+  int callbackId = static_cast<int>(args.get("callbackId").get<double>());
+  int reqId = static_cast<int>(args.get("reqId").get<double>());
+  picojson::object insertionData =
+      args.get("insertionData").get<picojson::object>();
+
+  if (!insertionData.count("columns") || !insertionData.count("values")) {
+    ReportError(TypeMismatchException(
+            "columns and values is required insertionData argument"), out);
+    return;
+  }
+  if (!insertionData["columns"].is<picojson::array>() ||
+      !insertionData["values"].is<picojson::array>()) {
+    ReportError(TypeMismatchException("columns and values type must be array"),
+                out);
+    return;
+  }
+
+  int result = RunSQLDataControlJob(providerId, dataId, callbackId, reqId,
+                                    [&insertionData](data_control_h& handle,
+                                        int *requestId) -> int {
+    picojson::array columns = insertionData["columns"].get<picojson::array>();
+    picojson::array values = insertionData["values"].get<picojson::array>();
+
+    picojson::array::size_type columnsLength = columns.size();
+    picojson::array::size_type valuesLength = values.size();
+
+    picojson::array::size_type size = std::min(columnsLength, valuesLength);
+
+    bundle * b = ::bundle_create();
+    SCOPE_EXIT {
+      bundle_free(b);
+    };
+    for (unsigned i=0; i < size; i++) {
+      picojson::value& column = columns[i];
+      picojson::value& value = values[i];
+
+      if (!column.is<std::string>() || !value.is<std::string>()) {
+        break;
+      }
+
+      std::string& columnName = column.get<std::string>();
+      std::string valueString = value.get<std::string>();
+
+      bundle_add_str(b, columnName.c_str(), valueString.c_str());
+    }
+
+    return ::data_control_sql_insert(handle, b, requestId);
+  });
+
+  if (result == DATA_CONTROL_ERROR_NONE) {
+    ReportSuccess(out);
+  } else {
+    if (result == DATA_CONTROL_ERROR_IO_ERROR) {
+      ReportError(IOException(get_error_message(result)), out);
+    } else if (result == DATA_CONTROL_ERROR_PERMISSION_DENIED) {
+      ReportError(SecurityException(get_error_message(result)), out);
+    } else {
+      ReportError(UnknownException(get_error_message(result)), out);
+    }
+  }
+}
+void DatacontrolInstance::SQLDataControlConsumerUpdate(
+    const picojson::value& args, picojson::object& out) {
+  LoggerD("Enter");
+  CHECK_EXIST(args, "callbackId", out)
+  CHECK_EXIST(args, "reqId", out)
+  CHECK_EXIST(args, "where", out)
+  CHECK_EXIST(args, "providerId", out)
+  CHECK_EXIST(args, "dataId", out)
+  CHECK_EXIST(args, "updateData", out)
+
+  const std::string& providerId = args.get("providerId").get<std::string>();
+  const std::string& dataId = args.get("dataId").get<std::string>();
+  int callbackId = static_cast<int>(args.get("callbackId").get<double>());
+  int reqId = static_cast<int>(args.get("reqId").get<double>());
+  const std::string& where = args.get("where").get<std::string>();
+  picojson::object updateData = args.get("updateData").get<picojson::object>();
+
+  if (!updateData.count("columns") || !updateData.count("values")) {
+    ReportError(TypeMismatchException(
+            "columns and values is required updateData argument"), out);
+    return;
+  }
+
+  if (!updateData["columns"].is<picojson::array>() ||
+      !updateData["values"].is<picojson::array>()) {
+    ReportError(TypeMismatchException(
+            "columns and values type must be array"), out);
+    return;
+  }
+
+  int result = RunSQLDataControlJob(providerId, dataId, callbackId, reqId,
+                                    [&updateData, &where](
+                                        data_control_h& handle,
+                                        int *requestId) -> int {
+    LoggerD("Enter");
+    picojson::array columns = updateData["columns"].get<picojson::array>();
+    picojson::array values = updateData["values"].get<picojson::array>();
+
+    picojson::array::size_type columnsLength = columns.size();
+    picojson::array::size_type valuesLength = values.size();
+
+    picojson::array::size_type size = std::min(columnsLength, valuesLength);
+
+    bundle * b = ::bundle_create();
+    SCOPE_EXIT {
+      bundle_free(b);
+    };
+    for (unsigned i=0; i < size; i++) {
+      picojson::value& column = columns[i];
+      picojson::value& value = values[i];
+
+      if (!column.is<std::string>() || !value.is<std::string>()) {
+        break;
+      }
+
+      std::string& columnName = column.get<std::string>();
+      std::string valueString = value.get<std::string>();
+
+      bundle_add_str(b, columnName.c_str(), valueString.c_str());
+    }
+
+    return ::data_control_sql_update(handle, b, where.c_str(), requestId);
+  });
+
+  if (result == DATA_CONTROL_ERROR_NONE) {
+    ReportSuccess(out);
+  } else {
+    if (result == DATA_CONTROL_ERROR_IO_ERROR) {
+      ReportError(IOException(get_error_message(result)), out);
+    } else if (result == DATA_CONTROL_ERROR_PERMISSION_DENIED) {
+      ReportError(SecurityException(get_error_message(result)), out);
+    } else {
+      ReportError(UnknownException(get_error_message(result)), out);
+    }
+  }
+}
+
+void DatacontrolInstance::SQLDataControlConsumerRemove(
+    const picojson::value& args, picojson::object& out) {
+  LoggerD("Enter");
+  CHECK_EXIST(args, "callbackId", out)
+  CHECK_EXIST(args, "reqId", out)
+  CHECK_EXIST(args, "where", out)
+  CHECK_EXIST(args, "providerId", out)
+  CHECK_EXIST(args, "dataId", out)
+
+  const std::string& providerId = args.get("providerId").get<std::string>();
+  const std::string& dataId = args.get("dataId").get<std::string>();
+  int callbackId = static_cast<int>(args.get("callbackId").get<double>());
+  int reqId = static_cast<int>(args.get("reqId").get<double>());
+  const std::string& where = args.get("where").get<std::string>();
+
+  int result = RunSQLDataControlJob(providerId, dataId, callbackId, reqId,
+                                    [&where](data_control_h& handle,
+                                        int *requestId) -> int {
+    return ::data_control_sql_delete(handle, where.c_str(), requestId);
+  });
+  if (result == DATA_CONTROL_ERROR_NONE) {
+    ReportSuccess(out);
+  } else {
+    if (result == DATA_CONTROL_ERROR_IO_ERROR) {
+      ReportError(IOException(get_error_message(result)), out);
+    } else if (result == DATA_CONTROL_ERROR_PERMISSION_DENIED) {
+      ReportError(SecurityException(get_error_message(result)), out);
+    } else {
+      ReportError(UnknownException(get_error_message(result)), out);
+    }
+  }
+}
+
+void DatacontrolInstance::SQLDataControlConsumerSelect(
+    const picojson::value& args, picojson::object& out) {
+  LoggerD("Enter");
+  CHECK_EXIST(args, "callbackId", out)
+  CHECK_EXIST(args, "reqId", out)
+  CHECK_EXIST(args, "columns", out)
+  CHECK_EXIST(args, "where", out)
+
+  CHECK_EXIST(args, "providerId", out)
+  CHECK_EXIST(args, "dataId", out)
+
+  const std::string& providerId = args.get("providerId").get<std::string>();
+  const std::string& dataId = args.get("dataId").get<std::string>();
+  const picojson::array columns = args.get("columns").get<picojson::array>();
+  const std::string& where = args.get("where").get<std::string>();
+
+  int callbackId = static_cast<int>(args.get("callbackId").get<double>());
+  int reqId = static_cast<int>(args.get("reqId").get<double>());
+
+  int page = 0, maxNumberPerPage = 0;
+  if (args.contains("page")) {
+    page = static_cast<int>(args.get("page").get<double>());
+  }
+  if (args.contains("maxNumberPerPage")) {
+    maxNumberPerPage =
+        static_cast<int>(args.get("maxNumberPerPage").get<double>());
+  }
+
+  int result = RunSQLDataControlJob(providerId, dataId, callbackId, reqId,
+                                    [&columns, &where, page, maxNumberPerPage](
+                                        data_control_h& handle,
+                                        int *requestId) -> int {
+    LoggerD("Enter");
+    std::vector<const char*> temp;
+    for (auto& s : columns) temp.push_back(s.get<std::string>().c_str());
+    int columnCount = static_cast<int>(temp.size());
+    char** cColumns = const_cast<char**>(&*temp.begin());
+
+    if (page > 0 && maxNumberPerPage > 0) {
+      return ::data_control_sql_select_with_page(handle, cColumns,
+                                                 columnCount, where.c_str(),
+                                                 "1 ASC", page,
+                                                 maxNumberPerPage, requestId);
+    } else {
+      return ::data_control_sql_select(handle, cColumns, columnCount,
+                                       where.c_str(), "1 ASC", requestId);
+    }
+  });
+
+  if (result == DATA_CONTROL_ERROR_NONE) {
+    ReportSuccess(out);
+  } else {
+    if (result == DATA_CONTROL_ERROR_IO_ERROR) {
+      ReportError(IOException(get_error_message(result)), out);
+    } else if (result == DATA_CONTROL_ERROR_PERMISSION_DENIED) {
+      ReportError(SecurityException(get_error_message(result)), out);
+    } else {
+      ReportError(UnknownException(get_error_message(result)), out);
+    }
+  }
+}
+void DatacontrolInstance::MappedDataControlConsumerAddvalue(
+    const picojson::value& args,
+    picojson::object& out) {
+  LoggerD("Enter");
+  CHECK_EXIST(args, "callbackId", out)
+  CHECK_EXIST(args, "reqId", out)
+  CHECK_EXIST(args, "key", out)
+  CHECK_EXIST(args, "value", out)
+  CHECK_EXIST(args, "providerId", out)
+  CHECK_EXIST(args, "dataId", out)
+
+  const std::string& providerId = args.get("providerId").get<std::string>();
+  const std::string& dataId = args.get("dataId").get<std::string>();
+  int callbackId = static_cast<int>(args.get("callbackId").get<double>());
+  int reqId = static_cast<int>(args.get("reqId").get<double>());
+  const std::string& key = args.get("key").get<std::string>();
+  const std::string& value = args.get("value").get<std::string>();
+
+  int result = RunMAPDataControlJob(providerId, dataId, callbackId, reqId,
+                                    [&key, &value](data_control_h& handle,
+                                                   int *requestId) -> int {
+    return ::data_control_map_add(handle, key.c_str(), value.c_str(),
+                                  requestId);
+  });
+
+  if (result == DATA_CONTROL_ERROR_NONE) {
+    ReportSuccess(out);
+  } else {
+    if (result == DATA_CONTROL_ERROR_IO_ERROR) {
+      ReportError(IOException(get_error_message(result)), out);
+    } else if (result == DATA_CONTROL_ERROR_PERMISSION_DENIED) {
+      ReportError(SecurityException(get_error_message(result)), out);
+    } else {
+      ReportError(UnknownException(get_error_message(result)), out);
+    }
+  }
+}
+void DatacontrolInstance::MappedDataControlConsumerRemovevalue(
+    const picojson::value& args, picojson::object& out) {
+  LoggerD("Enter");
+  CHECK_EXIST(args, "callbackId", out)
+  CHECK_EXIST(args, "reqId", out)
+  CHECK_EXIST(args, "key", out)
+  CHECK_EXIST(args, "value", out)
+  CHECK_EXIST(args, "providerId", out)
+  CHECK_EXIST(args, "dataId", out)
+
+  const std::string& providerId = args.get("providerId").get<std::string>();
+  const std::string& dataId = args.get("dataId").get<std::string>();
+  int callbackId = static_cast<int>(args.get("callbackId").get<double>());
+  int reqId = static_cast<int>(args.get("reqId").get<double>());
+  const std::string& key = args.get("key").get<std::string>();
+  const std::string& value = args.get("value").get<std::string>();
+
+  int result = RunMAPDataControlJob(providerId, dataId, callbackId, reqId,
+                                    [&key, &value](data_control_h& handle,
+                                                   int *requestId) -> int {
+    return ::data_control_map_remove(handle, key.c_str(), value.c_str(),
+                                     requestId);
+  });
+
+  if (result == DATA_CONTROL_ERROR_NONE) {
+    ReportSuccess(out);
+  } else {
+    if (result == DATA_CONTROL_ERROR_IO_ERROR) {
+      ReportError(IOException(get_error_message(result)), out);
+    } else if (result == DATA_CONTROL_ERROR_PERMISSION_DENIED) {
+      ReportError(SecurityException(get_error_message(result)), out);
+    } else {
+      ReportError(UnknownException(get_error_message(result)), out);
+    }
+  }
+}
+void DatacontrolInstance::MappedDataControlConsumerGetvalue(
+    const picojson::value& args, picojson::object& out) {
+  LoggerD("Enter");
+  CHECK_EXIST(args, "callbackId", out)
+  CHECK_EXIST(args, "reqId", out)
+  CHECK_EXIST(args, "key", out)
+  CHECK_EXIST(args, "providerId", out)
+  CHECK_EXIST(args, "dataId", out)
+
+  const std::string& providerId = args.get("providerId").get<std::string>();
+  const std::string& dataId = args.get("dataId").get<std::string>();
+  int callbackId = static_cast<int>(args.get("callbackId").get<double>());
+  int reqId = static_cast<int>(args.get("reqId").get<double>());
+  const std::string& key = args.get("key").get<std::string>();
+
+  int result = RunMAPDataControlJob(providerId, dataId, callbackId, reqId,
+                                    [&key](data_control_h& handle,
+                                           int *requestId) -> int {
+    return ::data_control_map_get(handle, key.c_str(), requestId);
+  });
+
+  if (result == DATA_CONTROL_ERROR_NONE) {
+    ReportSuccess(out);
+  } else {
+    if (result == DATA_CONTROL_ERROR_IO_ERROR) {
+      ReportError(IOException(get_error_message(result)), out);
+    } else if (result == DATA_CONTROL_ERROR_PERMISSION_DENIED) {
+      ReportError(SecurityException(get_error_message(result)), out);
+    } else {
+      ReportError(UnknownException(get_error_message(result)), out);
+    }
+  }
+}
+void DatacontrolInstance::MappedDataControlConsumerUpdatevalue(
+    const picojson::value& args, picojson::object& out) {
+  LoggerD("Enter");
+  CHECK_EXIST(args, "callbackId", out)
+  CHECK_EXIST(args, "reqId", out)
+  CHECK_EXIST(args, "key", out)
+  CHECK_EXIST(args, "oldValue", out)
+  CHECK_EXIST(args, "newValue", out)
+  CHECK_EXIST(args, "providerId", out)
+  CHECK_EXIST(args, "dataId", out)
+
+  const std::string& providerId = args.get("providerId").get<std::string>();
+  const std::string& dataId = args.get("dataId").get<std::string>();
+  int callbackId = static_cast<int>(args.get("callbackId").get<double>());
+  int reqId = static_cast<int>(args.get("reqId").get<double>());
+  const std::string& key = args.get("key").get<std::string>();
+  const std::string& oldValue = args.get("oldValue").get<std::string>();
+  const std::string& newValue = args.get("newValue").get<std::string>();
+
+  int result = RunMAPDataControlJob(providerId, dataId, callbackId, reqId,
+                                    [&key, &oldValue, &newValue](
+                                        data_control_h& handle,
+                                        int *requestId) -> int {
+    return ::data_control_map_set(handle, key.c_str(),
+                                  oldValue.c_str(), newValue.c_str(),
+                                  requestId);
+  });
+
+  if (result == DATA_CONTROL_ERROR_NONE) {
+    ReportSuccess(out);
+  } else {
+    if (result == DATA_CONTROL_ERROR_IO_ERROR) {
+      ReportError(IOException(get_error_message(result)), out);
+    } else if (result == DATA_CONTROL_ERROR_PERMISSION_DENIED) {
+      ReportError(SecurityException(get_error_message(result)), out);
+    } else {
+      ReportError(UnknownException(get_error_message(result)), out);
+    }
+  }
+}
+
+
+#undef CHECK_EXIST
+
+}  // namespace datacontrol
+}  // namespace extension
diff --git a/webWidgetTCT_device/src/datacontrol/datacontrol_instance.h b/webWidgetTCT_device/src/datacontrol/datacontrol_instance.h
new file mode 100755 (executable)
index 0000000..e2f2ee3
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2015 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 DATACONTROL_DATACONTROL_INSTANCE_H_
+#define DATACONTROL_DATACONTROL_INSTANCE_H_
+
+#include <data_control.h>
+#include <string>
+
+#include "common/extension.h"
+
+namespace extension {
+namespace datacontrol {
+
+class DatacontrolInstance : public common::ParsedInstance {
+ public:
+  DatacontrolInstance();
+  virtual ~DatacontrolInstance();
+
+  typedef std::function< int (data_control_h& handle, int *requestId) >
+      DataControlJob;
+  int RunMAPDataControlJob(const std::string& providerId,
+                           const std::string& dataId,
+                           int callbackId, int userRequestId,
+                           DataControlJob job);
+  int RunSQLDataControlJob(const std::string& providerId,
+                           const std::string& dataId,
+                           int callbackId, int userRequestId,
+                           DataControlJob job);
+
+ private:
+  void DataControlManagerGetdatacontrolconsumer(const picojson::value& args,
+                                                picojson::object& out);
+  void SQLDataControlConsumerInsert(const picojson::value& args,
+                                    picojson::object& out);
+  void SQLDataControlConsumerUpdate(const picojson::value& args,
+                                    picojson::object& out);
+  void SQLDataControlConsumerRemove(const picojson::value& args,
+                                    picojson::object& out);
+  void SQLDataControlConsumerSelect(const picojson::value& args,
+                                    picojson::object& out);
+  void MappedDataControlConsumerAddvalue(const picojson::value& args,
+                                         picojson::object& out);
+  void MappedDataControlConsumerRemovevalue(const picojson::value& args,
+                                            picojson::object& out);
+  void MappedDataControlConsumerGetvalue(const picojson::value& args,
+                                         picojson::object& out);
+  void MappedDataControlConsumerUpdatevalue(const picojson::value& args,
+                                            picojson::object& out);
+};
+
+}  // namespace datacontrol
+}  // namespace extension
+
+#endif  // DATACONTROL_DATACONTROL_INSTANCE_H_
diff --git a/webWidgetTCT_device/src/download/download.gyp b/webWidgetTCT_device/src/download/download.gyp
new file mode 100755 (executable)
index 0000000..3d8bf23
--- /dev/null
@@ -0,0 +1,32 @@
+{
+  'includes':[
+    '../common/common.gypi',
+  ],
+  'targets': [
+    {
+      'target_name': 'tizen_download',
+      'type': 'loadable_module',
+      'dependencies': [
+        '../common/common.gyp:tizen_common',
+      ],
+      'sources': [
+        'download_api.js',
+        'download_extension.cc',
+        'download_extension.h',
+        'download_instance.cc',
+        'download_instance.h',
+      ],
+      'conditions': [
+        ['tizen == 1', {
+          'variables': {
+            'packages': [
+              'capi-web-url-download',
+              'capi-system-info',
+              'capi-network-connection',
+            ]
+          },
+        }],
+      ],
+    },
+  ],
+}
diff --git a/webWidgetTCT_device/src/download/download_api.js b/webWidgetTCT_device/src/download/download_api.js
new file mode 100755 (executable)
index 0000000..8b6c0c4
--- /dev/null
@@ -0,0 +1,347 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+var validator_ = xwalk.utils.validator;
+var types_ = validator_.Types;
+var check_ = xwalk.utils.type;
+
+
+var callbackId = 0;
+var callbacks = {};
+var requests = {};
+
+
+extension.setMessageListener(function(json) {
+
+  var result = JSON.parse(json);
+  var callback = callbacks[result.callbackId];
+  //console.log("PostMessage received: " + result.status);
+
+  if (!callback) {
+    console.logd('Ignoring unknown callback: ' + result.callbackId);
+    return;
+  }
+
+  if (result.status == 'progress') {
+    if (callback.onprogress) {
+      var receivedSize = result.receivedSize;
+      var totalSize = result.totalSize;
+      callback.onprogress(result.callbackId, receivedSize, totalSize);
+    }
+  }
+  else if (result.status == 'paused') {
+    if (callback.onpaused) {
+      callback.onpaused(result.callbackId);
+    }
+  }
+  else if (result.status == 'canceled') {
+    if (callback.oncanceled) {
+      callback.oncanceled(result.callbackId);
+    }
+  }
+  else if (result.status == 'completed') {
+    if (callback.oncompleted) {
+      var fullPath = result.fullPath;
+      callback.oncompleted(result.callbackId, fullPath);
+    }
+  }
+  else if (result.status == 'error') {
+    if (callback.onfailed) {
+      callback.onfailed(result.callbackId,
+              new WebAPIException(result.error));
+    }
+  }
+});
+
+function nextCallbackId() {
+  return ++callbackId;
+}
+
+function callNative(cmd, args) {
+  var json = {'cmd': cmd, 'args': args};
+  var argjson = JSON.stringify(json);
+  var resultString = extension.internal.sendSyncMessage(argjson);
+  var result = JSON.parse(resultString);
+
+  if (typeof result !== 'object') {
+    throw new WebAPIException(WebAPIException.UNKNOWN_ERR);
+  }
+
+  if (result.status == 'success') {
+    if (result.result) {
+      return result.result;
+    }
+    return true;
+  } else if (result.status == 'error') {
+    var err = result.error;
+    if (err) {
+      throw new WebAPIException(err);
+    }
+    return false;
+  }
+}
+
+
+function callNativeWithCallback(cmd, args, callback) {
+  if (callback) {
+    var id = nextCallbackId();
+    args.callbackId = id;
+    callbacks[id] = callback;
+  }
+
+  return callNative(cmd, args);
+}
+
+function SetReadOnlyProperty(obj, n, v) {
+  Object.defineProperty(obj, n, {value: v, writable: false});
+}
+
+var DownloadState = {
+  'QUEUED': 'QUEUED',
+  'DOWNLOADING': 'DOWNLOADING',
+  'PAUSED': 'PAUSED',
+  'CANCELED': 'CANCELED',
+  'COMPLETED': 'COMPLETED',
+  'FAILED': 'FAILED'
+};
+
+var DownloadNetworkType = {
+  'CELLULAR': 'CELLULAR',
+  'WIFI': 'WIFI',
+  'ALL': 'ALL'
+};
+
+tizen.DownloadRequest = function(url, destination, fileName, networkType, httpHeader) {
+  validator_.isConstructorCall(this, tizen.DownloadRequest);
+
+  var url_ = url;
+  var networkType_;
+
+  if (networkType === undefined || !(networkType in DownloadNetworkType)) {
+    networkType_ = 'ALL';
+  } else {
+    networkType_ = networkType;
+  }
+
+  Object.defineProperties(this, {
+    'url': {
+      enumerable: true,
+      get: function() {
+        return url_;
+      },
+      set: function(value) {
+        if (value !== null) {
+          url_ = value;
+        }
+      },
+    },
+    'destination': {
+      writable: true,
+      enumerable: true,
+      value: destination === undefined ? '' : destination,
+    },
+    'fileName': {
+      writable: true,
+      enumerable: true,
+      value: fileName === undefined ? '' : fileName,
+    },
+    'networkType': {
+      enumerable: true,
+      get: function() {
+        return networkType_;
+      },
+      set: function(value) {
+        if (value === null || value in DownloadNetworkType) {
+          networkType_ = value;
+        }
+      },
+    },
+    'httpHeader': {
+      writable: true,
+      enumerable: true,
+      value: httpHeader === undefined ? {} : httpHeader,
+    }
+  });
+};
+
+
+function DownloadManager() {
+  // constructor of DownloadManager
+}
+
+DownloadManager.prototype.start = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.DOWNLOAD);
+
+  var args = validator_.validateArgs(arguments, [
+    {'name' : 'downloadRequest', 'type': types_.PLATFORM_OBJECT, 'values': tizen.DownloadRequest},
+    {'name' : 'downloadCallback', 'type': types_.LISTENER,
+      'values' : ['onprogress', 'onpaused', 'oncanceled', 'oncompleted', 'onfailed'],
+      optional: true, nullable: true}
+  ]);
+
+  var nativeParam = {
+    'url': args.downloadRequest.url,
+    'destination': args.downloadRequest.destination,
+    'fileName': args.downloadRequest.fileName,
+    'networkType': args.downloadRequest.networkType,
+    'httpHeader': args.downloadRequest.httpHeader,
+    'callbackId': nextCallbackId()
+  };
+
+  if (args.downloadCallback) {
+    this.setListener(nativeParam.callbackId, args.downloadCallback);
+  }
+
+  try {
+    callNative('DownloadManager_start', nativeParam);
+  } catch (e) {
+    if ('NetworkError' === e.name) {
+      return -1;
+    }
+    throw e;
+  }
+
+  requests[nativeParam.callbackId] = args.downloadRequest;
+
+  return nativeParam.callbackId;
+};
+
+DownloadManager.prototype.cancel = function() {
+  var args = validator_.validateArgs(arguments, [
+    {name: 'downloadId', type: types_.LONG, 'nullable': false, 'optional': false}
+  ]);
+
+  var nativeParam = {
+    'downloadId': args.downloadId
+  };
+
+  if (typeof requests[args.downloadId] === 'undefined')
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+        'the identifier does not match any download operation in progress');
+
+  try {
+    callNative('DownloadManager_cancel', nativeParam);
+  } catch (e) {
+    throw e;
+  }
+};
+
+DownloadManager.prototype.pause = function() {
+  var args = validator_.validateArgs(arguments, [
+    {'name': 'downloadId', 'type': types_.LONG, 'nullable': false, 'optional': false}
+  ]);
+
+  var nativeParam = {
+    'downloadId': args.downloadId
+  };
+
+  if (typeof requests[args.downloadId] === 'undefined')
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+        'the identifier does not match any download operation in progress');
+
+  try {
+    callNative('DownloadManager_pause', nativeParam);
+  } catch (e) {
+    throw e;
+  }
+};
+
+DownloadManager.prototype.resume = function() {
+  var args = validator_.validateArgs(arguments, [
+    {'name' : 'downloadId', 'type': types_.LONG, 'nullable': false, 'optional': false}
+  ]);
+
+  var nativeParam = {
+    'downloadId': args.downloadId
+  };
+
+  if (typeof requests[args.downloadId] === 'undefined')
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+        'the identifier does not match any download operation in progress');
+
+  try {
+    callNative('DownloadManager_resume', nativeParam);
+  } catch (e) {
+    throw e;
+  }
+};
+
+DownloadManager.prototype.getState = function() {
+  var args = validator_.validateArgs(arguments, [
+    {'name' : 'downloadId', 'type': types_.LONG, 'nullable': false, 'optional': false}
+  ]);
+
+  var nativeParam = {
+    'downloadId': args.downloadId
+  };
+
+  if (typeof requests[args.downloadId] === 'undefined')
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+        'the identifier does not match any download operation in progress');
+
+  try {
+    return callNative('DownloadManager_getState', nativeParam);
+  } catch (e) {
+    throw e;
+  }
+};
+
+DownloadManager.prototype.getDownloadRequest = function() {
+  var args = validator_.validateArgs(arguments, [
+    {'name': 'downloadId', 'type': types_.LONG, 'nullable': false, 'optional': false}
+  ]);
+
+  if (typeof requests[args.downloadId] === 'undefined')
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+        'the identifier does not match any download operation in progress');
+
+  return requests[args.downloadId];
+};
+
+DownloadManager.prototype.getMIMEType = function() {
+  var args = validator_.validateArgs(arguments, [
+    {'name' : 'downloadId', 'type': types_.LONG, 'nullable': false, 'optional': false}
+  ]);
+
+  var nativeParam = {
+    'downloadId': args.downloadId
+  };
+
+  if (typeof requests[args.downloadId] === 'undefined')
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+        'the identifier does not match any download operation in progress');
+
+  try {
+    return callNative('DownloadManager_getMIMEType', nativeParam);
+  } catch (e) {
+    throw e;
+  }
+};
+
+DownloadManager.prototype.setListener = function() {
+  var args = validator_.validateArgs(arguments, [
+    {'name' : 'downloadId', 'type': types_.LONG},
+    {'name' : 'downloadCallback', 'type': types_.LISTENER,
+      'values' : ['onprogress', 'onpaused', 'oncanceled', 'oncompleted', 'onfailed']}
+  ]);
+
+  callbacks[args.downloadId] = args.downloadCallback;
+};
+
+
+
+exports = new DownloadManager();
+
diff --git a/webWidgetTCT_device/src/download/download_extension.cc b/webWidgetTCT_device/src/download/download_extension.cc
new file mode 100755 (executable)
index 0000000..1968ca1
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2015 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 "download/download_extension.h"
+
+#include "download/download_instance.h"
+
+// This will be generated from download_api.js
+extern const char kSource_download_api[];
+
+common::Extension* CreateExtension() {
+  return new DownloadExtension;
+}
+
+DownloadExtension::DownloadExtension() {
+  SetExtensionName("tizen.download");
+  SetJavaScriptAPI(kSource_download_api);
+
+  const char* entry_points[] = {
+    "tizen.DownloadRequest",
+    NULL
+  };
+  SetExtraJSEntryPoints(entry_points);
+}
+
+DownloadExtension::~DownloadExtension() {}
+
+common::Instance* DownloadExtension::CreateInstance() {
+  return new extension::download::DownloadInstance;
+}
diff --git a/webWidgetTCT_device/src/download/download_extension.h b/webWidgetTCT_device/src/download/download_extension.h
new file mode 100755 (executable)
index 0000000..b5fb009
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2015 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 DOWNLOAD_DOWNLOAD_EXTENSION_H_
+#define DOWNLOAD_DOWNLOAD_EXTENSION_H_
+
+#include "common/extension.h"
+
+class DownloadExtension : public common::Extension {
+ public:
+  DownloadExtension();
+  virtual ~DownloadExtension();
+
+ private:
+  virtual common::Instance* CreateInstance();
+};
+
+#endif  // DOWNLOAD_DOWNLOAD_EXTENSION_H_
diff --git a/webWidgetTCT_device/src/download/download_instance.cc b/webWidgetTCT_device/src/download/download_instance.cc
new file mode 100755 (executable)
index 0000000..7fcc88e
--- /dev/null
@@ -0,0 +1,807 @@
+/*
+ * Copyright (c) 2015 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 "download/download_instance.h"
+
+#include <functional>
+
+#include <net_connection.h>
+
+#include "common/picojson.h"
+#include "common/logger.h"
+#include "common/typeutil.h"
+#include "common/tools.h"
+
+namespace extension {
+namespace download {
+
+std::vector<DownloadInstance*> DownloadInstance::instances_;
+std::mutex DownloadInstance::instances_mutex_;
+
+using common::NotFoundException;
+using common::UnknownException;
+using common::NetworkException;
+using common::SecurityException;
+using common::QuotaExceededException;
+using common::NotSupportedException;
+using common::InvalidStateException;
+using common::IOException;
+using common::InvalidValuesException;
+using common::ServiceNotAvailableException;
+using common::TypeMismatchException;
+
+DownloadInstance::DownloadInstance() : fs_provider_(common::FilesystemProviderStorage::Create()) {
+  LoggerD("Entered");
+  using std::placeholders::_1;
+  using std::placeholders::_2;
+  #define REGISTER_SYNC(c, x) \
+    RegisterSyncHandler(c, std::bind(&DownloadInstance::x, this, _1, _2));
+  REGISTER_SYNC("DownloadManager_pause", DownloadManagerPause);
+  REGISTER_SYNC
+    ("DownloadManager_getDownloadRequest", DownloadManagerGetdownloadrequest);
+  REGISTER_SYNC("DownloadManager_setListener", DownloadManagerSetlistener);
+  REGISTER_SYNC("DownloadManager_getMIMEType", DownloadManagerGetmimetype);
+  REGISTER_SYNC("DownloadManager_start", DownloadManagerStart);
+  REGISTER_SYNC("DownloadManager_cancel", DownloadManagerCancel);
+  REGISTER_SYNC("DownloadManager_resume", DownloadManagerResume);
+  REGISTER_SYNC("DownloadManager_getState", DownloadManagerGetstate);
+  #undef REGISTER_SYNC
+
+  std::lock_guard<std::mutex> lock(instances_mutex_);
+  instances_.push_back(this);
+}
+
+DownloadInstance::~DownloadInstance() {
+  LoggerD("Entered");
+  int ret;
+  for (DownloadCallbackMap::iterator it = download_callbacks.begin();
+    it != download_callbacks.end(); ++it) {
+    DownloadInfoPtr diPtr = it->second->instance->diMap[it->second->callbackId];
+    LoggerD("~DownloadInstance() for callbackID %d Called", it->second->callbackId);
+
+    ret = download_unset_state_changed_cb(diPtr->download_id);
+    if (ret != DOWNLOAD_ERROR_NONE)
+      LoggerE("download_unset_state_changed_cb() is failed. (%s)", get_error_message (ret));
+
+    ret = download_unset_progress_cb(diPtr->download_id);
+    if (ret != DOWNLOAD_ERROR_NONE)
+      LoggerE("download_unset_progress_cb() is failed. (%s)", get_error_message (ret));
+
+    ret = download_cancel(diPtr->download_id);
+    if (ret != DOWNLOAD_ERROR_NONE)
+      LoggerE("download_cancel() is failed. (%s)", get_error_message (ret));
+
+    ret = download_destroy(diPtr->download_id);
+    if (ret != DOWNLOAD_ERROR_NONE)
+      LoggerE("download_destroy() is failed. (%s)", get_error_message (ret));
+
+    delete (it->second);
+  }
+
+  std::lock_guard<std::mutex> lock(instances_mutex_);
+  for (auto it = instances_.begin(); it != instances_.end(); it++) {
+    if (*it == this) {
+      instances_.erase(it);
+      break;
+    }
+  }
+}
+
+bool DownloadInstance::CheckInstance(DownloadInstance* instance) {
+  LoggerD("Entered");
+  for (auto vec_instance : instances_) {
+    if (vec_instance == instance) {
+      return true;
+    }
+  }
+
+  return false;
+}
+
+common::PlatformResult DownloadInstance::convertError(int err) {
+  char* error = get_error_message(err);
+  LoggerE("%s",error);
+  switch (err) {
+    case DOWNLOAD_ERROR_INVALID_PARAMETER:
+      return common::PlatformResult(common::ErrorCode::INVALID_VALUES_ERR,
+                                    error);
+    case DOWNLOAD_ERROR_OUT_OF_MEMORY:
+      return common::PlatformResult(common::ErrorCode::UNKNOWN_ERR,
+                                    error);
+    case DOWNLOAD_ERROR_NETWORK_UNREACHABLE:
+      return common::PlatformResult(common::ErrorCode::UNKNOWN_ERR,
+                                    error);
+    case DOWNLOAD_ERROR_CONNECTION_TIMED_OUT:
+      return common::PlatformResult(common::ErrorCode::UNKNOWN_ERR,
+                                    error);
+    case DOWNLOAD_ERROR_NO_SPACE:
+      return common::PlatformResult(common::ErrorCode::UNKNOWN_ERR,
+                                    error);
+    case DOWNLOAD_ERROR_PERMISSION_DENIED:
+      return common::PlatformResult(common::ErrorCode::UNKNOWN_ERR,
+                                    error);
+    case DOWNLOAD_ERROR_NOT_SUPPORTED:
+      return common::PlatformResult(common::ErrorCode::UNKNOWN_ERR,
+                                    error);
+    case DOWNLOAD_ERROR_INVALID_STATE:
+      return common::PlatformResult(common::ErrorCode::INVALID_VALUES_ERR,
+                                    error);
+    case DOWNLOAD_ERROR_CONNECTION_FAILED:
+      return common::PlatformResult(common::ErrorCode::UNKNOWN_ERR,
+                                    error);
+    case DOWNLOAD_ERROR_INVALID_URL:
+      return common::PlatformResult(common::ErrorCode::UNKNOWN_ERR,
+                                    error);
+    case DOWNLOAD_ERROR_INVALID_DESTINATION:
+      return common::PlatformResult(common::ErrorCode::UNKNOWN_ERR,
+                                    error);
+    case DOWNLOAD_ERROR_TOO_MANY_DOWNLOADS:
+      return common::PlatformResult(common::ErrorCode::UNKNOWN_ERR,
+                                    error);
+    case DOWNLOAD_ERROR_QUEUE_FULL:
+      return common::PlatformResult(common::ErrorCode::UNKNOWN_ERR,
+                                    error);
+    case DOWNLOAD_ERROR_ALREADY_COMPLETED:
+      return common::PlatformResult(common::ErrorCode::UNKNOWN_ERR,
+                                    error);
+    case DOWNLOAD_ERROR_FILE_ALREADY_EXISTS:
+      return common::PlatformResult(common::ErrorCode::UNKNOWN_ERR,
+                                    error);
+    case DOWNLOAD_ERROR_CANNOT_RESUME:
+      return common::PlatformResult(common::ErrorCode::UNKNOWN_ERR,
+                                    error);
+    case DOWNLOAD_ERROR_FIELD_NOT_FOUND:
+      return common::PlatformResult(common::ErrorCode::UNKNOWN_ERR,
+                                    error);
+    case DOWNLOAD_ERROR_TOO_MANY_REDIRECTS:
+      return common::PlatformResult(
+          common::ErrorCode::UNKNOWN_ERR,
+          error);
+    case DOWNLOAD_ERROR_UNHANDLED_HTTP_CODE:
+      return common::PlatformResult(
+          common::ErrorCode::UNKNOWN_ERR,
+          error);
+    case DOWNLOAD_ERROR_REQUEST_TIMEOUT:
+      return common::PlatformResult(
+          common::ErrorCode::UNKNOWN_ERR,
+          error);
+    case DOWNLOAD_ERROR_RESPONSE_TIMEOUT:
+      return common::PlatformResult(common::ErrorCode::UNKNOWN_ERR,
+                                    error);
+    case DOWNLOAD_ERROR_SYSTEM_DOWN:
+      return common::PlatformResult(
+          common::ErrorCode::UNKNOWN_ERR,
+          error);
+    case DOWNLOAD_ERROR_ID_NOT_FOUND:
+      return common::PlatformResult(
+          common::ErrorCode::UNKNOWN_ERR,
+          error);
+    case DOWNLOAD_ERROR_INVALID_NETWORK_TYPE:
+      return common::PlatformResult(common::ErrorCode::UNKNOWN_ERR,
+                                    error);
+    case DOWNLOAD_ERROR_NO_DATA:
+      return common::PlatformResult(
+          common::ErrorCode::UNKNOWN_ERR,
+          error);
+    case DOWNLOAD_ERROR_IO_ERROR:
+      return common::PlatformResult(common::ErrorCode::UNKNOWN_ERR,
+                                    error);
+    default:
+      return common::PlatformResult(common::ErrorCode::UNKNOWN_ERR,
+                                    "Unknown error.");
+  }
+}
+
+#define CHECK_EXIST(args, name, out) \
+    if (!args.contains(name)) {\
+      ReportError(common::PlatformResult(common::ErrorCode::TYPE_MISMATCH_ERR, name" is required argument"), &out);\
+      return;\
+    }
+
+void DownloadInstance::OnStateChanged(int download_id,
+  download_state_e state, void* user_data) {
+  LoggerD("Entered");
+  CallbackPtr downCbPtr = static_cast<CallbackPtr>(user_data);
+
+  downCbPtr->state = state;
+  downCbPtr->downloadId = download_id;
+
+  LoggerD("State for callbackId %d changed to %d",
+    downCbPtr->callbackId, static_cast<int>(state));
+
+  switch (state) {
+    case DOWNLOAD_STATE_NONE:
+      break;
+    case DOWNLOAD_STATE_DOWNLOADING:
+      OnStart(download_id, user_data);
+      break;
+    case DOWNLOAD_STATE_PAUSED:
+      g_idle_add(OnPaused, downCbPtr);
+      break;
+    case DOWNLOAD_STATE_COMPLETED:
+      g_idle_add(OnFinished, downCbPtr);
+      break;
+    case DOWNLOAD_STATE_CANCELED:
+      g_idle_add(OnCanceled, downCbPtr);
+      break;
+    case DOWNLOAD_STATE_FAILED:
+      g_idle_add(OnFailed, downCbPtr);
+      break;
+    default:
+      LoggerW("Unsupported download state: %d", state);
+      break;
+  }
+}
+
+gboolean DownloadInstance::OnProgressChanged(void* user_data) {
+  LoggerD("Entered");
+  CallbackPtr downCbPtr = static_cast<CallbackPtr>(user_data);
+  std::lock_guard<std::mutex> lock(instances_mutex_);
+  if (!CheckInstance(downCbPtr->instance)) {
+    return FALSE;
+  }
+
+  DownloadInfoPtr diPtr = downCbPtr->instance->diMap[downCbPtr->callbackId];
+
+  picojson::value::object out;
+  out["status"] = picojson::value("progress");
+  out["callbackId"] =
+    picojson::value(static_cast<double>(downCbPtr->callbackId));
+  out["receivedSize"] =
+    picojson::value(static_cast<double>(downCbPtr->received));
+  out["totalSize"] = picojson::value(static_cast<double>(diPtr->file_size));
+
+  LoggerD("OnProgressChanged for callbackId %d Called: Received: %ld",
+  downCbPtr->callbackId, downCbPtr->received);
+
+  picojson::value v = picojson::value(out);
+  Instance::PostMessage(downCbPtr->instance, v.serialize().c_str());
+
+  return FALSE;
+}
+
+void DownloadInstance::OnStart(int download_id, void* user_data) {
+  LoggerD("Entered");
+  unsigned long long totalSize=0;
+
+  CallbackPtr downCbPtr = static_cast<CallbackPtr>(user_data);
+  std::lock_guard<std::mutex> lock(instances_mutex_);
+  if (!CheckInstance(downCbPtr->instance)) {
+    return;
+  }
+
+  LoggerD("OnStart for callbackId %d Called", downCbPtr->callbackId);
+
+  DownloadInfoPtr diPtr = downCbPtr->instance->diMap[downCbPtr->callbackId];
+
+  int ret = download_get_content_size(download_id, &totalSize);
+  if (ret != DOWNLOAD_ERROR_NONE) {
+    LoggerE("Failed: download_get_content_size");
+    // it might be resonable to cancel download here
+  }
+  diPtr->file_size = totalSize;
+}
+
+gboolean DownloadInstance::OnFinished(void* user_data) {
+  LoggerD("Entered");
+  char* fullPath = NULL;
+
+  CallbackPtr downCbPtr = static_cast<CallbackPtr>(user_data);
+  std::lock_guard<std::mutex> lock(instances_mutex_);
+  if (!CheckInstance(downCbPtr->instance)) {
+    return FALSE;
+  }
+
+  int callback_id = downCbPtr->callbackId;
+  DownloadInfoPtr diPtr = downCbPtr->instance->diMap[callback_id];
+
+  LoggerD("OnFinished for callbackID %d Called", callback_id);
+
+  picojson::value::object out;
+
+  int ret = download_get_downloaded_file_path(downCbPtr->downloadId, &fullPath);
+  if (ret != DOWNLOAD_ERROR_NONE) {
+    common::tools::ReportError(convertError(ret), &out);
+  } else {
+    ret = download_unset_state_changed_cb(diPtr->download_id);
+    if (ret != DOWNLOAD_ERROR_NONE) {
+      LoggerW("%s",get_error_message(ret));
+    }
+    ret = download_unset_progress_cb(diPtr->download_id);
+    if (ret != DOWNLOAD_ERROR_NONE) {
+      LoggerW("%s",get_error_message(ret));
+    }
+    ret = download_destroy(diPtr->download_id);
+    if (ret != DOWNLOAD_ERROR_NONE) {
+      LoggerW("%s",get_error_message(ret));
+    }
+    out["status"] = picojson::value("completed");
+    out["fullPath"] = picojson::value(fullPath);
+  }
+
+  out["callbackId"] =
+    picojson::value(static_cast<double>(callback_id));
+  out["fullPath"] = picojson::value(fullPath);
+
+  Instance::PostMessage(downCbPtr->instance, picojson::value(out).serialize().c_str());
+  downCbPtr->instance->download_callbacks.erase(callback_id);
+  delete (downCbPtr);
+  free(fullPath);
+
+  return FALSE;
+}
+
+gboolean DownloadInstance::OnPaused(void* user_data) {
+  LoggerD("Entered");
+  CallbackPtr downCbPtr = static_cast<CallbackPtr>(user_data);
+  std::lock_guard<std::mutex> lock(instances_mutex_);
+  if (!CheckInstance(downCbPtr->instance)) {
+    return FALSE;
+  }
+
+  int callback_id = downCbPtr->callbackId;
+  DownloadInfoPtr diPtr = downCbPtr->instance->diMap[callback_id];
+
+  LoggerD("OnPaused for callbackID %d Called", callback_id);
+
+  picojson::value::object out;
+  out["status"] = picojson::value("paused");
+  out["callbackId"] =
+    picojson::value(static_cast<double>(callback_id));
+
+  Instance::PostMessage(downCbPtr->instance, picojson::value(out).serialize().c_str());
+  return FALSE;
+}
+
+gboolean DownloadInstance::OnCanceled(void* user_data) {
+  LoggerD("Entered");
+  CallbackPtr downCbPtr = static_cast<CallbackPtr>(user_data);
+  std::lock_guard<std::mutex> lock(instances_mutex_);
+  if (!CheckInstance(downCbPtr->instance)) {
+    return FALSE;
+  }
+
+  int callback_id = downCbPtr->callbackId;
+  DownloadInfoPtr diPtr = downCbPtr->instance->diMap[callback_id];
+
+  LoggerD("OnCanceled for callbackID %d Called", callback_id);
+
+  int ret = download_unset_state_changed_cb(diPtr->download_id);
+  if (ret != DOWNLOAD_ERROR_NONE) {
+    LoggerE("%s",get_error_message(ret));
+  }
+  ret = download_unset_progress_cb(diPtr->download_id);
+  if (ret != DOWNLOAD_ERROR_NONE) {
+    LoggerW("%s",get_error_message(ret));
+  }
+  ret = download_destroy(diPtr->download_id);
+  if (ret != DOWNLOAD_ERROR_NONE) {
+    LoggerW("%s",get_error_message(ret));
+  }
+  picojson::value::object out;
+  out["status"] = picojson::value("canceled");
+  out["callbackId"] =
+    picojson::value(static_cast<double>(callback_id));
+
+  Instance::PostMessage(downCbPtr->instance, picojson::value(out).serialize().c_str());
+  downCbPtr->instance->download_callbacks.erase(callback_id);
+  delete (downCbPtr);
+  return FALSE;
+}
+
+gboolean DownloadInstance::OnFailed(void* user_data) {
+  LoggerD("Entered");
+  download_error_e error;
+  picojson::object out;
+
+  CallbackPtr downCbPtr = static_cast<CallbackPtr>(user_data);
+  std::lock_guard<std::mutex> lock(instances_mutex_);
+  if (!CheckInstance(downCbPtr->instance)) {
+    return FALSE;
+  }
+
+  DownloadInstance* instance = downCbPtr->instance;
+
+  LoggerD("OnFailed for callbackID %d Called", downCbPtr->callbackId);
+
+  download_get_error(downCbPtr->downloadId, &error);
+
+  if(DOWNLOAD_ERROR_NONE != error) {
+    common::tools::ReportError(convertError(error), &out);
+  }
+
+  out["callbackId"] =
+    picojson::value(static_cast<double>(downCbPtr->callbackId));
+
+  Instance::PostMessage(downCbPtr->instance, picojson::value(out).serialize().c_str());
+  return FALSE;
+}
+
+void DownloadInstance::progress_changed_cb
+  (int download_id, long long unsigned received, void* user_data) {
+  LoggerD("Entered");
+  CallbackPtr downCbPtr = static_cast<CallbackPtr>(user_data);
+  downCbPtr->received = received;
+  downCbPtr->downloadId = download_id;
+
+  g_idle_add(OnProgressChanged, downCbPtr);
+}
+
+void DownloadInstance::DownloadManagerStart
+  (const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+  CHECK_EXIST(args, "callbackId", out)
+
+  int ret;
+  std::string networkType;
+
+  DownloadInfoPtr diPtr(new DownloadInfo);
+
+  diPtr->callbackId = static_cast<int>(args.get("callbackId").get<double>());
+  diPtr->url = args.get("url").get<std::string>();
+
+  if (!args.get("destination").is<picojson::null>()) {
+    if (args.get("destination").get<std::string>() != "") {
+      diPtr->destination = args.get("destination").get<std::string>();
+      // TODO: move conversion to JS
+      diPtr->destination = fs_provider_.GetRealPath(diPtr->destination);
+    }
+  }
+
+  if (!args.get("fileName").is<picojson::null>()) {
+    if (args.get("fileName").get<std::string>() != "") {
+      diPtr->file_name = args.get("fileName").get<std::string>();
+    }
+  }
+
+  if (!args.get("networkType").is<picojson::null>()) {
+    networkType = args.get("networkType").get<std::string>();
+  }
+
+  bool network_support = false;
+  bool cell_support = false;
+  bool wifi_support = false;
+  bool ethernet_support = false;
+
+  system_info_get_platform_bool("http://tizen.org/feature/network.telephony",
+                                &cell_support);
+  system_info_get_platform_bool("http://tizen.org/feature/network.wifi",
+                                &wifi_support);
+  system_info_get_platform_bool("http://tizen.org/feature/network.ethernet",
+                                &ethernet_support);
+
+  connection_h connection = nullptr;
+  connection_create(&connection);
+
+  connection_cellular_state_e cell_state = CONNECTION_CELLULAR_STATE_OUT_OF_SERVICE;
+  connection_wifi_state_e wifi_state = CONNECTION_WIFI_STATE_DEACTIVATED;
+  connection_ethernet_state_e ethernet_state = CONNECTION_ETHERNET_STATE_DEACTIVATED;
+
+  connection_get_cellular_state(connection, &cell_state);
+  connection_get_wifi_state(connection, &wifi_state);
+  connection_get_ethernet_state(connection, &ethernet_state);
+  connection_destroy(connection);
+
+  bool network_available = false;
+  bool cell_available = (CONNECTION_CELLULAR_STATE_CONNECTED == cell_state);
+  bool wifi_available = (CONNECTION_WIFI_STATE_CONNECTED == wifi_state);
+  bool ethernet_available = CONNECTION_ETHERNET_STATE_CONNECTED == ethernet_state;
+
+  if (networkType == "CELLULAR") {
+    network_support = cell_support;
+    network_available = cell_available;
+    diPtr->network_type = DOWNLOAD_NETWORK_DATA_NETWORK;
+  } else if (networkType == "WIFI") {
+    network_support = wifi_support;
+    network_available = wifi_available;
+    diPtr->network_type = DOWNLOAD_NETWORK_WIFI;
+  } else if (networkType == "ALL") {
+    network_support = cell_support || wifi_support || ethernet_support;
+    network_available = cell_available || wifi_available || ethernet_available;
+    diPtr->network_type = DOWNLOAD_NETWORK_ALL;
+  } else {
+    LoggerE("The input parameter contains an invalid network type");
+    ReportError(
+        common::PlatformResult(common::ErrorCode::INVALID_VALUES_ERR,
+                               "The input parameter contains an invalid network type."),
+        &out);
+    return;
+  }
+
+  if (!network_support) {
+    LoggerE("Requested network type (%s) is not supported", networkType.c_str());
+    ReportError(
+        common::PlatformResult(common::ErrorCode::NOT_SUPPORTED_ERR,
+                               "The networkType of the given DownloadRequest "
+                               "is not supported on this device."),
+        &out);
+    return;
+  }
+
+  if (!network_available) {
+    LoggerE("Requested network type (%s) is not available", networkType.c_str());
+    ReportError(
+        common::PlatformResult(common::ErrorCode::NETWORK_ERR,
+                               "The networkType of the given DownloadRequest "
+                               "is currently not available on this device."),
+        &out);
+    return;
+  }
+
+  CallbackPtr downCbPtr(new DownloadCallback);
+
+  downCbPtr->callbackId = diPtr->callbackId;
+  downCbPtr->instance = this;
+
+  download_callbacks[downCbPtr->callbackId] = downCbPtr;
+
+  ret = download_create(&diPtr->download_id);
+  if (ret != DOWNLOAD_ERROR_NONE) {
+    LoggerE("%s",get_error_message(ret));
+    common::tools::ReportError(convertError(ret), &out);
+    return;
+  }
+
+  ret = download_set_state_changed_cb(diPtr->download_id, OnStateChanged,
+                                      static_cast<void*>(downCbPtr));
+  if (ret != DOWNLOAD_ERROR_NONE) {
+    LoggerE("%s",get_error_message(ret));
+    common::tools::ReportError(convertError(ret), &out);
+    return;
+  }
+
+  ret = download_set_progress_cb(diPtr->download_id, progress_changed_cb,
+                                 static_cast<void*>(downCbPtr));
+  if (ret != DOWNLOAD_ERROR_NONE) {
+    LoggerE("%s",get_error_message(ret));
+    common::tools::ReportError(convertError(ret), &out);
+    return;
+  }
+
+  ret = download_set_url(diPtr->download_id, diPtr->url.c_str());
+  if (ret != DOWNLOAD_ERROR_NONE) {
+    LoggerE("%s",get_error_message(ret));
+    common::tools::ReportError(convertError(ret), &out);
+    return;
+  }
+
+  if (diPtr->destination.size() != 0) {
+    ret = download_set_destination(diPtr->download_id,
+                                   diPtr->destination.c_str());
+    if (ret != DOWNLOAD_ERROR_NONE) {
+      LoggerE("%s",get_error_message(ret));
+      common::tools::ReportError(convertError(ret), &out);
+      return;
+    }
+  }
+
+  if (!diPtr->file_name.empty()) {
+    ret = download_set_file_name(diPtr->download_id, diPtr->file_name.c_str());
+    if (ret != DOWNLOAD_ERROR_NONE) {
+      LoggerE("%s",get_error_message(ret));
+      common::tools::ReportError(convertError(ret), &out);
+      return;
+    }
+  }
+
+  ret = download_set_network_type(diPtr->download_id, diPtr->network_type);
+  if (ret != DOWNLOAD_ERROR_NONE) {
+    LoggerE("%s",get_error_message(ret));
+    common::tools::ReportError(convertError(ret), &out);
+    return;
+  }
+  if (args.get("httpHeader").is<picojson::object>()) {
+    picojson::object obj = args.get("httpHeader").get<picojson::object>();
+    for (picojson::object::const_iterator it = obj.begin();
+    it != obj.end(); ++it) {
+      download_add_http_header_field
+        (diPtr->download_id, it->first.c_str(), it->second.to_str().c_str());
+    }
+  }
+
+  diMap[downCbPtr->callbackId] = diPtr;
+
+  ret = download_start(diPtr->download_id);
+
+  if (ret == DOWNLOAD_ERROR_NONE)
+    ReportSuccess(out);
+  else {
+    LoggerE("%s",get_error_message(ret));
+    common::tools::ReportError(convertError(ret), &out);
+  }
+}
+
+void DownloadInstance::DownloadManagerCancel
+  (const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+  CHECK_EXIST(args, "downloadId", out)
+  int downloadId, ret;
+
+  int callbackId = static_cast<int>(args.get("downloadId").get<double>());
+
+  if (!GetDownloadID(callbackId, downloadId)) {
+    LoggerE("The identifier does not match any download operation in progress");
+    ReportError(common::PlatformResult(common::ErrorCode::NOT_FOUND_ERR,
+      "The identifier does not match any download operation in progress"),
+      &out);
+    return;
+  }
+
+  ret = download_cancel(downloadId);
+
+  if (ret == DOWNLOAD_ERROR_NONE)
+    ReportSuccess(out);
+  else {
+    common::tools::ReportError(convertError(ret), &out);
+  }
+}
+
+void DownloadInstance::DownloadManagerPause
+  (const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+  CHECK_EXIST(args, "downloadId", out)
+  int downloadId, ret;
+
+  int callbackId = static_cast<int>(args.get("downloadId").get<double>());
+
+  if (!GetDownloadID(callbackId, downloadId)) {
+    LoggerE("The identifier does not match any download operation in progress");
+    ReportError(common::PlatformResult(common::ErrorCode::NOT_FOUND_ERR,
+      "The identifier does not match any download operation in progress"),
+      &out);
+    return;
+  }
+
+  ret = download_pause(downloadId);
+
+  if (ret == DOWNLOAD_ERROR_NONE)
+    ReportSuccess(out);
+  else {
+    common::tools::ReportError(convertError(ret), &out);
+  }
+}
+
+void DownloadInstance::DownloadManagerResume
+  (const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+  CHECK_EXIST(args, "downloadId", out)
+  int downloadId, ret;
+
+  int callbackId = static_cast<int>(args.get("downloadId").get<double>());
+
+  if (!GetDownloadID(callbackId, downloadId)) {
+    ReportError(common::PlatformResult(common::ErrorCode::NOT_FOUND_ERR,
+      "The identifier does not match any download operation in progress"),
+      &out);
+    return;
+  }
+
+  ret = download_start(downloadId);
+
+  if (ret == DOWNLOAD_ERROR_NONE)
+    ReportSuccess(out);
+  else {
+    common::tools::ReportError(convertError(ret), &out);
+  }
+}
+void DownloadInstance::DownloadManagerGetstate
+  (const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+  CHECK_EXIST(args, "downloadId", out)
+  int downloadId, ret;
+  std::string stateValue;
+  download_state_e state;
+
+  int callbackId = static_cast<int>(args.get("downloadId").get<double>());
+
+  if (!GetDownloadID(callbackId, downloadId)) {
+    LoggerE("The identifier does not match any download operation in progress");
+    ReportError(common::PlatformResult(common::ErrorCode::NOT_FOUND_ERR,
+      "The identifier does not match any download operation in progress"),
+      &out);
+    return;
+  }
+
+  ret = download_get_state(downloadId, &state);
+
+  if (ret == DOWNLOAD_ERROR_NONE) {
+    switch (state) {
+     case DOWNLOAD_STATE_NONE:
+      break;
+     case DOWNLOAD_STATE_QUEUED:
+       stateValue = "QUEUED";
+       break;
+     case DOWNLOAD_STATE_DOWNLOADING:
+       stateValue = "DOWNLOADING";
+       break;
+     case DOWNLOAD_STATE_PAUSED:
+       stateValue = "PAUSED";
+       break;
+     case DOWNLOAD_STATE_COMPLETED:
+       stateValue = "COMPLETED";
+       break;
+     case DOWNLOAD_STATE_FAILED:
+       stateValue = "FAILED";
+       break;
+     case DOWNLOAD_STATE_CANCELED:
+       stateValue = "CANCELED";
+       break;
+     default:
+       LoggerW("Unsupported download state: %d", state);
+       break;
+    }
+
+    ReportSuccess(picojson::value(stateValue), out);
+  } else {
+    common::tools::ReportError(convertError(ret), &out);
+  }
+}
+
+void DownloadInstance::DownloadManagerGetmimetype
+  (const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+  CHECK_EXIST(args, "downloadId", out)
+
+  int downloadId, ret;
+  char* mimetype = NULL;
+
+  int callbackId = static_cast<int>(args.get("downloadId").get<double>());
+
+  if (!GetDownloadID(callbackId, downloadId)) {
+    ReportError(common::PlatformResult(common::ErrorCode::NOT_FOUND_ERR,
+      "The identifier does not match any download operation in progress"),
+      &out);
+    return;
+  }
+
+  ret = download_get_mime_type(downloadId, &mimetype);
+
+  if (ret == DOWNLOAD_ERROR_NONE) {
+    ReportSuccess(picojson::value(mimetype), out);
+  } else {
+    common::tools::ReportError(convertError(ret), &out);
+  }
+  free(mimetype);
+}
+
+bool DownloadInstance::GetDownloadID
+  (const int callback_id, int& download_id) {
+  LoggerD("Entered");
+  if (diMap.find(callback_id) != diMap.end()) {
+    download_id = diMap.find(callback_id)->second->download_id;
+  } else {
+    return false;
+  }
+  return true;
+}
+
+void DownloadInstance::DownloadManagerGetdownloadrequest
+  (const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+  // Nothing to do
+}
+
+void DownloadInstance::DownloadManagerSetlistener
+  (const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+  // Nothing to do
+}
+
+
+#undef CHECK_EXIST
+
+}  // namespace download
+}  // namespace extension
diff --git a/webWidgetTCT_device/src/download/download_instance.h b/webWidgetTCT_device/src/download/download_instance.h
new file mode 100755 (executable)
index 0000000..31fecb5
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2015 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 DOWNLOAD_DOWNLOAD_INSTANCE_H_
+#define DOWNLOAD_DOWNLOAD_INSTANCE_H_
+
+#include <glib.h>
+#include <download.h>
+#include <system_info.h>
+
+#include <memory>
+#include <sstream>
+#include <map>
+#include <string>
+#include <vector>
+#include <mutex>
+#include "common/extension.h"
+#include "common/filesystem/filesystem_provider_storage.h"
+
+#include "common/platform_result.h"
+
+template <class T>
+  inline std::string to_string(const T& t) {
+      std::stringstream ss;
+      ss << t;
+      return ss.str();
+  }
+
+namespace extension {
+namespace download {
+
+class DownloadInstance : public common::ParsedInstance {
+ public:
+  DownloadInstance();
+  virtual ~DownloadInstance();
+
+ private:
+  void DownloadManagerStart
+    (const picojson::value& args, picojson::object& out);
+  void DownloadManagerCancel
+    (const picojson::value& args, picojson::object& out);
+  void DownloadManagerPause
+    (const picojson::value& args, picojson::object& out);
+  void DownloadManagerResume
+    (const picojson::value& args, picojson::object& out);
+  void DownloadManagerGetstate
+    (const picojson::value& args, picojson::object& out);
+  void DownloadManagerGetdownloadrequest
+    (const picojson::value& args, picojson::object& out);
+  void DownloadManagerGetmimetype
+    (const picojson::value& args, picojson::object& out);
+  void DownloadManagerSetlistener
+    (const picojson::value& args, picojson::object& out);
+
+  bool GetDownloadID(const int callback_id, int& download_id);
+
+  static void OnStateChanged
+    (int download_id, download_state_e state, void* user_data);
+  static void progress_changed_cb
+    (int download_id, long long unsigned received, void* user_data);
+  static void OnStart(int download_id, void* user_data);
+
+  static gboolean OnProgressChanged(void* user_data);
+  static gboolean OnFinished(void* user_data);
+  static gboolean OnPaused(void* user_data);
+  static gboolean OnCanceled(void* user_data);
+  static gboolean OnFailed(void* user_data);
+  static bool CheckInstance(DownloadInstance* instance);
+  static common::PlatformResult convertError(int err);
+
+  struct DownloadInfo {
+    int callbackId;
+    std::string url;
+    std::string destination;
+    std::string file_name;
+    std::string http_header;
+    download_network_type_e network_type;
+
+    int download_id;
+    long long unsigned file_size;
+  };
+
+  struct DownloadCallback {
+    int callbackId;
+    int downloadId;
+    DownloadInstance* instance;
+    unsigned long long received;
+    download_state_e state;
+  };
+
+  typedef DownloadCallback* CallbackPtr;
+  typedef std::map<int, CallbackPtr > DownloadCallbackMap;
+  typedef std::shared_ptr<DownloadInfo> DownloadInfoPtr;
+  typedef std::map<int, DownloadInfoPtr> DownloadInfoMap;
+
+  static std::mutex instances_mutex_;
+  static std::vector<DownloadInstance*> instances_;
+
+  DownloadCallbackMap download_callbacks;
+  DownloadInfoMap diMap;
+  common::FilesystemProviderStorage& fs_provider_;
+};
+
+}  // namespace download
+}  // namespace extension
+
+#endif  // DOWNLOAD_DOWNLOAD_INSTANCE_H_
diff --git a/webWidgetTCT_device/src/exif/exif.gyp b/webWidgetTCT_device/src/exif/exif.gyp
new file mode 100755 (executable)
index 0000000..1be32d0
--- /dev/null
@@ -0,0 +1,48 @@
+{
+  'includes':[
+    '../common/common.gypi',
+  ],
+  'targets': [
+    {
+      'target_name': 'tizen_exif',
+      'type': 'loadable_module',
+      'includes': [
+        '../common/pkg-config.gypi',
+      ],
+      'dependencies': [
+        '../common/common.gyp:tizen_common',
+      ],
+      'sources': [
+        'exif_api.js',
+        'exif_extension.cc',
+        'exif_extension.h',
+        'exif_instance.cc',
+        'exif_instance.h',
+
+        'exif_information.cc',
+        'exif_information.h',
+        'exif_util.cc',
+        'exif_util.h',
+        'exif_tag_saver.cc',
+        'exif_tag_saver.h',
+        'jpeg_file.cc',
+        'jpeg_file.h',
+        'rational.cc',
+        'rational.h',
+        'exif_gps_location.cc',
+        'exif_gps_location.h',
+        'get_exif_info.cc',
+        'get_exif_info.h',
+      ],
+      'conditions': [
+        [ 'tizen == 1', {
+            'variables': {
+              'packages': [
+                'libexif',
+              ]
+            },
+        }],
+      ],
+    },
+  ],
+}
diff --git a/webWidgetTCT_device/src/exif/exif_api.js b/webWidgetTCT_device/src/exif/exif_api.js
new file mode 100755 (executable)
index 0000000..40face0
--- /dev/null
@@ -0,0 +1,588 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+var _global = window || global || {};
+var validator_ = xwalk.utils.validator;
+var type_ = xwalk.utils.type;
+var native_ = new xwalk.utils.NativeManager(extension);
+var converter_ = xwalk.utils.converter;
+
+function ExifManager() {}
+
+var ImageContentOrientation = {
+  NORMAL: 'NORMAL',
+  FLIP_HORIZONTAL: 'FLIP_HORIZONTAL',
+  ROTATE_180: 'ROTATE_180',
+  FLIP_VERTICAL: 'FLIP_VERTICAL',
+  TRANSPOSE: 'TRANSPOSE',
+  ROTATE_90: 'ROTATE_90',
+  TRANSVERSE: 'TRANSVERSE',
+  ROTATE_270: 'ROTATE_270'
+};
+
+var ExposureProgram = {
+  NOT_DEFINED: 'NOT_DEFINED',
+  MANUAL: 'MANUAL',
+  NORMAL: 'NORMAL',
+  APERTURE_PRIORITY: 'APERTURE_PRIORITY',
+  SHUTTER_PRIORITY: 'SHUTTER_PRIORITY',
+  CREATIVE_PROGRAM: 'CREATIVE_PROGRAM',
+  ACTION_PROGRAM: 'ACTION_PROGRAM',
+  PORTRAIT_MODE: 'PORTRAIT_MODE',
+  LANDSCAPE_MODE: 'LANDSCAPE_MODE'
+};
+
+var WhiteBalanceMode = {
+  AUTO: 'AUTO',
+  MANUAL: 'MANUAL'
+};
+
+var propertiesList = {
+  URI: 'uri',
+  WIDTH: 'width',
+  HEIGHT: 'height',
+  DEVICE_MAKER: 'deviceMaker',
+  DEVICE_MODEL: 'deviceModel',
+  ORIGINAL_TIME: 'originalTime',
+  ORIENTATION: 'orientation',
+  FNUMBER: 'fNumber',
+  ISO_SPEED_RATINGS: 'isoSpeedRatings',
+  EXPOSURE_TIME: 'exposureTime',
+  EXPOSURE_PROGRAM: 'exposureProgram',
+  FLASH: 'flash',
+  FOCAL_LENGTH: 'focalLength',
+  WHITE_BALANCE: 'whiteBalance',
+  GPS_LOCATION: 'gpsLocation',
+  GPS_ALTITUDE: 'gpsAltitude',
+  GPS_PROCESSING_METHOD: 'gpsProcessingMethod',
+  GPS_TIME: 'gpsTime',
+  USER_COMMENT: 'userComment'
+};
+
+var URI_ABSOLUTE_PREFIX = "file:///";
+
+function _isValidAbsoluteURI(uri) {
+  return 0 === uri.indexOf(URI_ABSOLUTE_PREFIX);
+}
+
+function _getJsonFromExifInformation(exifInfo) {
+  var json = {};
+
+  for (var prop in propertiesList) {
+    var propName = propertiesList[prop];
+
+    if (exifInfo[propName] !== null) {
+      if (propName === 'originalTime') {
+        json[propName] = Math.floor(exifInfo[propName].getTime() / 1000);
+      } else if (propName === 'gpsTime') {
+        var str = exifInfo[propName].toLocaleString().split(', ');
+        var res = str[1] + ', ' + str[2] + ', ' + str[3];
+
+        json[propName] = Math.floor(Date.parse(res) / 1000);
+      } else {
+        json[propName] = exifInfo[propName];
+      }
+    }
+  }
+
+  return json;
+}
+
+function _calculateDegDecimal(degrees, minutes, seconds) {
+  return parseInt(degrees) + parseInt(minutes) / 60.0 + parseInt(seconds) / 3600.0;
+}
+
+function _calculateExifInfo(exifInfoNative) {
+  // copy all properties that share name from
+  // exifInfoNative to exifInfo
+  var exifInfo = new tizen.ExifInformation(exifInfoNative);
+
+  // copy all remaining properties that do not share name or need extra calculations
+  if (exifInfoNative.originalTimeSeconds) {
+    exifInfo.originalTime = new Date(exifInfoNative.originalTimeSeconds * 1000);
+  }
+
+  if (parseInt(exifInfoNative.whiteBalanceValue) === 0) {  // 0=AUTO
+    exifInfo.whiteBalance = WhiteBalanceMode.AUTO;
+  } else if (parseInt(exifInfoNative.whiteBalanceValue) === 1) {  // 1=MANUAL
+    exifInfo.whiteBalance = WhiteBalanceMode.MANUAL;
+  }
+
+  // gpsLocation
+  if (exifInfoNative.gpsLatitudeDegrees &&
+      exifInfoNative.gpsLongitudeDegrees &&
+      exifInfoNative.gpsLatitudeRef &&
+      exifInfoNative.gpsLongitudeRef) {
+    exifInfo.gpsLocation = new tizen.SimpleCoordinates();
+    exifInfo.gpsLocation.latitude = _calculateDegDecimal(exifInfoNative.gpsLatitudeDegrees,
+        exifInfoNative.gpsLatitudeMinutes, exifInfoNative.gpsLatitudeSeconds);
+    exifInfo.gpsLocation.longitude = _calculateDegDecimal(exifInfoNative.gpsLongitudeDegrees,
+        exifInfoNative.gpsLongitudeMinutes, exifInfoNative.gpsLongitudeSeconds);
+
+    if (exifInfoNative.gpsLatitudeRef === 'SOUTH') {
+      exifInfo.gpsLocation.latitude = -exifInfo.gpsLocation.latitude;
+    } else if (exifInfoNative.gpsLatitudeRef !== 'NORTH') {
+      exifInfo.gpsLocation.latitude = null;  // invalid gpsLatitudeRef
+    }
+
+    if (exifInfoNative.gpsLongitudeRef === 'WEST') {
+      exifInfo.gpsLocation.longitude = -exifInfo.gpsLocation.longitude;
+    } else if (exifInfoNative.gpsLongitudeRef !== 'EAST') {
+      exifInfo.gpsLocation.longitude = null;  // invalid gpsLongitudeRef
+    }
+  }
+
+  // gpsAltitude
+  if (exifInfoNative.gpsAltitude && exifInfoNative.gpsAltitudeRef) {
+    if (parseInt(exifInfoNative.gpsAltitudeRef) === 0) {  // 0=ABOVE SEA LEVEL
+      exifInfo.gpsAltitude = exifInfoNative.gpsAltitude;
+    } else if (parseInt(exifInfoNative.gpsAltitudeRef) === 1) {  // 1=BELOW SEA LEVEL
+      exifInfo.gpsAltitude = -exifInfoNative.gpsAltitude;
+    }
+  }
+
+  // gpsTime
+  if (exifInfoNative.gpsExifDate) {
+    var dateSplit = exifInfoNative.gpsExifDate.split(':');
+    exifInfo.gpsTime = new Date(
+        dateSplit[0],  // year
+        dateSplit[1],  // month
+        dateSplit[2],  // day
+        exifInfoNative.gpsExifTimeHours,
+        exifInfoNative.gpsExifTimeMinutes,
+        exifInfoNative.gpsExifTimeSeconds);
+  }
+
+  return exifInfo;
+}
+
+ExifManager.prototype.getExifInfo = function() {
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'uri',
+      type: validator_.Types.STRING,
+      optional: false,
+      nullable: false
+    },
+    {
+      name: 'successCallback',
+      type: validator_.Types.FUNCTION,
+      optional: false,
+      nullable: false
+    },
+    {
+      name: 'errorCallback',
+      type: validator_.Types.FUNCTION,
+      optional: true,
+      nullable: true
+    }
+  ]);
+
+  if (!_isValidAbsoluteURI(args.uri)) {
+    setTimeout(function() {
+      native_.callIfPossible(args.errorCallback, new WebAPIException(
+          WebAPIException.INVALID_VALUES_ERR,
+          'Invalid URI.'));
+    }, 0);
+    return;
+  }
+
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+    } else {
+
+      // call to c++ code. Fields that do not exist are undefined.
+      var exifInfoNative = native_.getResultObject(result);
+
+      // calculate ExifInformation struct. All fields are initially null.
+      // Fields that do not exist in jpg EXIF must remain null.
+      var exifInfo = _calculateExifInfo(exifInfoNative);
+
+      // make successCalback and pass exifInfo
+      args.successCallback(exifInfo);
+    }
+  };
+
+  tizen.filesystem.resolve(args.uri,
+      function() {
+        native_.call('ExifManager_getExifInfo', {'uri': args.uri}, callback);
+      },
+      function() {
+        native_.callIfPossible(args.errorCallback, new WebAPIException(
+            WebAPIException.NOT_FOUND_ERR,
+            'File can not be found.'));
+      });
+};
+
+ExifManager.prototype.saveExifInfo = function() {
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'exifInfo',
+      type: validator_.Types.PLATFORM_OBJECT,
+      values: tizen.ExifInformation,
+      optional: false,
+      nullable: false
+    },
+    {
+      name: 'successCallback',
+      type: validator_.Types.FUNCTION,
+      optional: true,
+      nullable: true
+    },
+    {
+      name: 'errorCallback',
+      type: validator_.Types.FUNCTION,
+      optional: true,
+      nullable: true
+    }
+  ]);
+
+  if (!_isValidAbsoluteURI(args.exifInfo.uri)) {
+    setTimeout(function() {
+      native_.callIfPossible(args.errorCallback, new WebAPIException(
+          WebAPIException.INVALID_VALUES_ERR,
+          'Invalid URI.'));
+    }, 0);
+    return;
+  }
+
+  var json = _getJsonFromExifInformation(args.exifInfo);
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.errorCallback,
+          native_.getErrorObject(result));
+    } else {
+      var exifInfo = native_.getResultObject(result);
+      args.successCallback(exifInfo);
+    }
+  };
+
+  native_.call('ExifManager_saveExifInfo', json, callback);
+};
+
+ExifManager.prototype.getThumbnail = function() {
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'uri',
+      type: validator_.Types.STRING,
+      optional: false,
+      nullable: false
+    },
+    {
+      name: 'successCallback',
+      type: validator_.Types.FUNCTION,
+      optional: false,
+      nullable: false
+    },
+    {
+      name: 'errorCallback',
+      type: validator_.Types.FUNCTION,
+      optional: true,
+      nullable: true
+    }
+  ]);
+
+  if (!_isValidAbsoluteURI(args.uri)) {
+    setTimeout(function() {
+      native_.callIfPossible(args.errorCallback, new WebAPIException(
+          WebAPIException.INVALID_VALUES_ERR,
+          'Invalid URI.'));
+    }, 0);
+    return;
+  }
+
+  var _callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.errorCallback,
+          native_.getErrorObject(result));
+    } else {
+      var thumb = native_.getResultObject(result);
+      args.successCallback(thumb.src);
+    }
+  };
+
+  tizen.filesystem.resolve(args.uri,
+      function() {
+        native_.call('ExifManager_getThumbnail', {'uri': args.uri}, _callback);
+      },
+      function() {
+        native_.callIfPossible(args.errorCallback, new WebAPIException(
+            WebAPIException.NOT_FOUND_ERR,
+            'File can not be found.'));
+      });
+};
+
+tizen.ExifInformation = function() {
+  validator_.isConstructorCall(this, tizen.ExifInformation);
+
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'ExifInitDict',
+      type: validator_.Types.DICTIONARY,
+      optional: true,
+      nullable: false
+    }
+  ]);
+
+  var uri_ = null,
+      width_ = null,
+      height_ = null,
+      deviceMaker_ = null,
+      deviceModel_ = null,
+      originalTime_ = null,
+      orientation_ = null,
+      fNumber_ = null,
+      isoSpeedRatings_ = null,
+      exposureTime_ = null,
+      exposureProgram_ = null,
+      flash_ = null,
+      focalLength_ = null,
+      whiteBalance_ = null,
+      gpsLocation_ = null,
+      gpsAltitude_ = null,
+      gpsProcessingMethod_ = null,
+      gpsTime_ = null,
+      userComment_ = null;
+
+  function _validateISOSpeedRatings(v) {
+    var valid = false;
+    if (type_.isArray(v)) {
+      for (var i = 0; i < v.length; i++) {
+        var data = v[i]; // todo: uncomment when array conversion is implemented.
+        //if (!type_.isNumber(data)) {
+        //  return false;
+        //}
+      }
+      valid = true;
+    }
+    return valid;
+  }
+
+
+  var exifInitDict = args.ExifInitDict;
+  if (exifInitDict) {
+    if (exifInitDict.uri === null) {
+      throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+          'Parameter "uri" is required.');
+    }
+  }
+
+  Object.defineProperties(this, {
+    uri: {
+      get: function() {
+        return uri_;
+      },
+      set: function(v) {
+        uri_ = v ? converter_.toString(v) : uri_;
+      },
+      enumerable: true
+    },
+    width: {
+      get: function() {
+        return width_;
+      },
+      set: function(v) {
+        width_ = (!type_.isUndefined(v)) ? converter_.toLong(v, true) : width_;
+      },
+      enumerable: true
+    },
+    height: {
+      get: function() {
+        return height_;
+      },
+      set: function(v) {
+        height_ = (!type_.isUndefined(v)) ? converter_.toLong(v, true) : height_;
+      },
+      enumerable: true
+    },
+    deviceMaker: {
+      get: function() {
+        return deviceMaker_;
+      },
+      set: function(v) {
+        deviceMaker_ = (!type_.isUndefined(v)) ?
+            converter_.toString(v, true) : deviceMaker_;
+      },
+      enumerable: true
+    },
+    deviceModel: {
+      get: function() {
+        return deviceModel_;
+      },
+      set: function(v) {
+        deviceModel_ = (!type_.isUndefined(v)) ?
+            converter_.toString(v, true) : deviceModel_;
+      },
+      enumerable: true
+    },
+    originalTime: {
+      get: function() {
+        return originalTime_;
+      },
+      set: function(v) {
+        if (!type_.isUndefined(v)) {
+          if (v === null || v instanceof Date) originalTime_ = v;
+        }
+      },
+      enumerable: true
+    },
+    orientation: {
+      get: function() {
+        return orientation_;
+      },
+      set: function(v) {
+        orientation_ = (!type_.isUndefined(v)) ?
+            converter_.toEnum(v, Object.keys(ImageContentOrientation), true) : orientation_;
+      },
+      enumerable: true
+    },
+    fNumber: {
+      get: function() {
+        return fNumber_;
+      },
+      set: function(v) {
+        fNumber_ = (!type_.isUndefined(v)) ? converter_.toDouble(v, true) : fNumber_;
+      },
+      enumerable: true
+    },
+    isoSpeedRatings: {
+      get: function() {
+        return isoSpeedRatings_;
+      },
+      set: function(v) {
+        // todo: convert string array into unsigned short array
+        if (!type_.isUndefined(v)) {
+          if (v === null || _validateISOSpeedRatings(v)) isoSpeedRatings_ = v;
+        }
+      },
+      enumerable: true
+    },
+    exposureTime: {
+      get: function() {
+        return exposureTime_;
+      },
+      set: function(v) {
+        exposureTime_ = (!type_.isUndefined(v)) ?
+            converter_.toString(v, true) : exposureTime_;
+      },
+      enumerable: true
+    },
+    exposureProgram: {
+      get: function() {
+        return exposureProgram_;
+      },
+      set: function(v) {
+        exposureProgram_ = (!type_.isUndefined(v)) ?
+            converter_.toEnum(v, Object.keys(ExposureProgram), true) : exposureProgram_;
+      },
+      enumerable: true
+    },
+    flash: {
+      get: function() {
+        return flash_;
+      },
+      set: function(v) {
+        flash_ = (!type_.isUndefined(v)) ? converter_.toBoolean(v, true) : flash_;
+      },
+      enumerable: true
+    },
+    focalLength: {
+      get: function() {
+        return focalLength_;
+      },
+      set: function(v) {
+        focalLength_ = (!type_.isUndefined(v)) ?
+            converter_.toDouble(v, true) : focalLength_;
+      },
+      enumerable: true
+    },
+    whiteBalance: {
+      get: function() {
+        return whiteBalance_;
+      },
+      set: function(v) {
+        whiteBalance_ = (!type_.isUndefined(v)) ?
+            converter_.toEnum(v, Object.keys(WhiteBalanceMode), true) : whiteBalance_;
+      },
+      enumerable: true
+    },
+    gpsLocation: {
+      get: function() {
+        return gpsLocation_;
+      },
+      set: function(v) {
+        if (!type_.isUndefined(v)) {
+          if (v === null || v instanceof tizen.SimpleCoordinates) gpsLocation_ = v;
+        }
+      },
+      enumerable: true
+    },
+    gpsAltitude: {
+      get: function() {
+        return gpsAltitude_;
+      },
+      set: function(v) {
+        gpsAltitude_ = (!type_.isUndefined(v)) ?
+            converter_.toDouble(v, true) : gpsAltitude_;
+      },
+      enumerable: true
+    },
+    gpsProcessingMethod: {
+      get: function() {
+        return gpsProcessingMethod_;
+      },
+      set: function(v) {
+        gpsProcessingMethod_ = (!type_.isUndefined(v)) ?
+            converter_.toString(v, true) : gpsProcessingMethod_;
+      },
+      enumerable: true
+    },
+    gpsTime: {
+      enumerable: true,
+      get: function() {
+        return gpsTime_;
+      },
+      set: function(v) {
+        if (!type_.isUndefined(v)) {
+          if (v === null || v instanceof Date || v instanceof tizen.TZDate) gpsTime_ = v;
+        }
+      }
+    },
+    userComment: {
+      enumerable: true,
+      get: function() {
+        return userComment_;
+      },
+      set: function(v) {
+        userComment_ = (!type_.isUndefined(v)) ?
+            converter_.toString(v, true) : userComment_;
+      }
+    }
+  });
+
+  //--- copy values from exifInitDict using setters above.
+  if (exifInitDict instanceof _global.Object) {
+    for (var prop in exifInitDict) {
+      if (this.hasOwnProperty(prop)) {
+        this[prop] = exifInitDict[prop];
+      }
+    }
+  }
+};
+
+exports = new ExifManager();
diff --git a/webWidgetTCT_device/src/exif/exif_extension.cc b/webWidgetTCT_device/src/exif/exif_extension.cc
new file mode 100755 (executable)
index 0000000..b6bfdc6
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015 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 "exif/exif_extension.h"
+#include "exif/exif_instance.h"
+
+common::Extension* CreateExtension() { return new ExifExtension; }
+
+// This will be generated from exif_api.js.
+extern const char kSource_exif_api[];
+
+ExifExtension::ExifExtension() {
+  SetExtensionName("tizen.exif");
+  SetJavaScriptAPI(kSource_exif_api);
+
+  const char* entry_points[] = {"tizen.ExifInformation", NULL};
+  SetExtraJSEntryPoints(entry_points);
+}
+
+ExifExtension::~ExifExtension() {}
+
+common::Instance* ExifExtension::CreateInstance() { return new extension::exif::ExifInstance; }
diff --git a/webWidgetTCT_device/src/exif/exif_extension.h b/webWidgetTCT_device/src/exif/exif_extension.h
new file mode 100755 (executable)
index 0000000..0b87b84
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015 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 EXIF_EXIF_EXTENSION_H_
+#define EXIF_EXIF_EXTENSION_H_
+
+#include "common/extension.h"
+
+class ExifExtension : public common::Extension {
+ public:
+  ExifExtension();
+  virtual ~ExifExtension();
+
+ private:
+  // common::Extension implementation.
+  virtual common::Instance* CreateInstance();
+};
+
+#endif  // EXIF_EXIF_EXTENSION_H_
diff --git a/webWidgetTCT_device/src/exif/exif_gps_location.cc b/webWidgetTCT_device/src/exif/exif_gps_location.cc
new file mode 100755 (executable)
index 0000000..806d7b1
--- /dev/null
@@ -0,0 +1,262 @@
+/*
+ * Copyright (c) 2015 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 "exif/exif_gps_location.h"
+
+#include <string>
+#include <sstream>
+#include <cmath>
+
+#include "common/assert.h"
+#include "common/logger.h"
+
+namespace extension {
+namespace exif {
+
+GCSPosition::GCSPosition() {
+  LoggerD("Enter");
+}
+
+GCSPosition::GCSPosition(Rational _degrees, Rational _minutes,
+                         Rational _seconds) :
+    degrees(_degrees),
+    minutes(_minutes),
+    seconds(_seconds) {
+      LoggerD("Enter");
+}
+
+bool GCSPosition::isValid() const {
+  LoggerD("Enter");
+  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 {
+  LoggerD("Enter");
+  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 {
+  LoggerD("Enter");
+  Rationals vec;
+  vec.push_back(degrees);
+  vec.push_back(minutes);
+  vec.push_back(seconds);
+  return vec;
+}
+
+std::string GCSPosition::toDebugString() const {
+  LoggerD("Enter");
+  std::stringstream ss;
+  ss << degrees.toString() << "d ";
+  ss << minutes.toString() << "m ";
+  ss << seconds.toString() << "s";
+  return ss.str();
+}
+
+GCSPosition GCSPosition::createFromDouble(double value) {
+  LoggerD("Entered value:%f");
+  if (value < 0) {
+    LoggerW("Trying to create GCSPosition with double < 0: %f", value);
+    return GCSPosition();
+  }
+
+  if (value > 180.0) {
+    LoggerW("Trying to create GCSPosition with double > 180.0: %f", value);
+    return GCSPosition();
+  }
+
+  double d_degrees = floor(value);
+  double left = value - d_degrees;
+
+  double d_minutes = floor(left * 60.0);
+  left -= d_minutes / 60.0;
+
+  double d_seconds = round(left * 3600.0);
+
+  if (d_seconds >= 60.0) {
+    d_seconds -= 60.0;
+    d_minutes++;
+  }
+
+  if (d_minutes >= 60.0) {
+    d_minutes -= 60.0;
+    d_degrees++;
+  }
+
+  Assert(d_degrees <= 180.0);
+
+  LoggerD("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) {
+    LoggerD("Enter");
+    m_is_set[i] = false;
+  }
+  LoggerE("ExifGPSLocation::ExifGPSLocation()");
+}
+
+ExifGPSLocation::ExifGPSLocation(double longitude, double latitude) {
+  LoggerD("Enter");
+  for (int i = 0; i < EXIF_GPS_LOCATION_ATTRIBUTE_NUMBER_OF_ATTRIBUTES; ++i) {
+    m_is_set[i] = false;
+  }
+
+  setLongitude(GCSPosition::createFromDouble(longitude));
+  setLatitude(GCSPosition::createFromDouble(latitude));
+
+  if (longitude < 0) {
+    setLongitudeRef(GPS_LOCATION_WEST);
+  } else {
+    setLongitudeRef(GPS_LOCATION_EAST);
+  }
+
+  if (latitude < 0) {
+    setLatitudeRef(GPS_LOCATION_SOUTH);
+  } else {
+    setLatitudeRef(GPS_LOCATION_NORTH);
+  }
+}
+
+void ExifGPSLocation::setLongitude(const GCSPosition& longitude) {
+  LoggerD("Enter");
+  if (!longitude.isValid()) {
+    LoggerW("longitude is not valid!");
+    return;
+  }
+
+  m_is_set[EXIF_GPS_LOCATION_ATTRIBUTE_LONGITUDE] = true;
+  m_longitude = longitude;
+}
+
+const GCSPosition& ExifGPSLocation::getLongitude() const {
+  LoggerD("Enter");
+  return m_longitude;
+}
+
+void ExifGPSLocation::setLongitudeRef(GPSLocationDirectionLongitude ref) {
+  LoggerD("Enter");
+  m_is_set[EXIF_GPS_LOCATION_ATTRIBUTE_LONGITUDE_REF] = true;
+  m_longitude_ref = ref;
+}
+
+GPSLocationDirectionLongitude ExifGPSLocation::getLongitudeRef() const {
+  LoggerD("Enter");
+  return m_longitude_ref;
+}
+
+void ExifGPSLocation::setLatitude(const GCSPosition& latitude) {
+  LoggerD("Enter");
+  if (!latitude.isValid()) {
+    LoggerW("latitude is not valid!");
+    return;
+  }
+
+  m_is_set[EXIF_GPS_LOCATION_ATTRIBUTE_LATITUDE] = true;
+  m_latitude = latitude;
+}
+
+const GCSPosition& ExifGPSLocation::getLatitude() const {
+  LoggerD("Enter");
+  return m_latitude;
+}
+
+void ExifGPSLocation::setLatitudeRef(GPSLocationDirectionLatitude ref) {
+  LoggerD("Enter");
+  m_is_set[EXIF_GPS_LOCATION_ATTRIBUTE_LATITUDE_REF] = true;
+  m_latitude_ref = ref;
+}
+
+GPSLocationDirectionLatitude ExifGPSLocation::getLatitudeRef() const {
+  LoggerD("Enter");
+  return m_latitude_ref;
+}
+
+bool ExifGPSLocation::isSet(ExifGPSLocationAttributes attribute) const {
+  LoggerD("Enter");
+  return m_is_set[attribute];
+}
+
+void ExifGPSLocation::unset(ExifGPSLocationAttributes attribute) {
+  LoggerD("Enter");
+  m_is_set[attribute] = false;
+}
+
+void ExifGPSLocation::unsetAll() {
+  LoggerD("Enter");
+  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 {
+  LoggerD("Enter");
+  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 {
+  LoggerD("Enter");
+  return isComplete() && m_latitude.isValid() && m_longitude.isValid();
+}
+
+double ExifGPSLocation::getLongitudeValue() const {
+  LoggerD("Enter");
+  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 {
+  LoggerD("Enter");
+  const double latitude_dir =
+      (m_latitude_ref == GPS_LOCATION_SOUTH) ? -1.0f : 1.0f;
+  const double latitude = m_latitude.toDouble() * latitude_dir;
+  return latitude;
+}
+}  // namespace exif
+}  // namespace extension
diff --git a/webWidgetTCT_device/src/exif/exif_gps_location.h b/webWidgetTCT_device/src/exif/exif_gps_location.h
new file mode 100755 (executable)
index 0000000..2bafcb5
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2015 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 EXIF_EXIF_GPS_LOCATION_H_
+#define EXIF_EXIF_GPS_LOCATION_H_
+
+#include <string>
+#include <vector>
+
+#include "exif/exif_util.h"
+#include "exif/rational.h"
+
+namespace extension {
+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: degrees, minutes, seconds
+   */
+  Rationals toRationalsVector() const;
+
+  /**
+   * Return string for debugging purposes
+   */
+  std::string toDebugString() const;
+
+  Rational degrees;
+  Rational minutes;
+  Rational seconds;
+};
+
+class ExifGPSLocation {
+ public:
+  ExifGPSLocation();
+  ExifGPSLocation(double longitude, double latitude);
+
+  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;
+
+ 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];
+};
+
+}  // namespace exif
+}  // namespace extension
+
+#endif  // EXIF_EXIF_GPS_LOCATION_H_
diff --git a/webWidgetTCT_device/src/exif/exif_information.cc b/webWidgetTCT_device/src/exif/exif_information.cc
new file mode 100755 (executable)
index 0000000..dce7ff3
--- /dev/null
@@ -0,0 +1,917 @@
+/*
+ * Copyright (c) 2015 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 "exif/exif_information.h"
+
+#include <memory>
+#include <cmath>
+
+#include "common/assert.h"
+#include "common/converter.h"
+#include "common/logger.h"
+#include "common/platform_result.h"
+
+#include "exif/exif_tag_saver.h"
+#include "exif/exif_util.h"
+#include "exif/jpeg_file.h"
+
+namespace extension {
+namespace exif {
+
+using common::ErrorCode;
+using common::PlatformResult;
+
+const std::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);
+
+namespace {
+constexpr unsigned int str2int(const char* str, int h = 0) {
+  return !str[h] ? 5381 : (str2int(str, h+1)*33) ^ str[h];
+}
+
+IsoSpeedRatingsVector jsonArray2vector(const picojson::value& a) {
+  LoggerD("Enter");
+  if (!a.is<picojson::array>()) {
+    return IsoSpeedRatingsVector();
+  }
+
+  IsoSpeedRatingsVector result;
+
+  picojson::array v = a.get<picojson::array>();
+
+  for (picojson::array::iterator it = v.begin(); it != v.end(); ++it) {
+    if ((*it).is<double>())
+      result.push_back(static_cast<long long int>((*it).get<double>()));
+  }
+
+  return result;
+}
+}  // namespace
+
+ExifInformation::ExifInformation() {
+  LoggerD("Enter");
+  for (int attr = 0;
+      attr < EXIF_INFORMATION_ATTRIBUTE_NUMBER_OF_ATTRIBUTES; attr++) {
+    unset(static_cast<ExifInformationAttribute>(attr));
+  }
+}
+
+ExifInformation::ExifInformation(const picojson::value& args) {
+  LoggerD("Enter");
+  for (int attr = 0;
+      attr < EXIF_INFORMATION_ATTRIBUTE_NUMBER_OF_ATTRIBUTES; attr++) {
+    unset(static_cast<ExifInformationAttribute>(attr));
+  }
+
+  for (AttributeMap::const_iterator it = ExifInformationAttributeMap.begin();
+      it != ExifInformationAttributeMap.end(); ++it) {
+    std::string attributeName = it->second;
+    picojson::value v = args.get(attributeName);
+    if (!common::IsNull(v)) {
+      set(attributeName, v);
+    }
+  }
+}
+
+ExifInformation::~ExifInformation() {
+  LoggerD("Enter");
+ }
+
+const std::string& ExifInformation::getUri() {
+  LoggerD("Entered");
+  return m_uri;
+}
+
+void ExifInformation::setUri(const std::string& uri) {
+  LoggerD("Entered");
+  LoggerD("URI: %s", uri.c_str());
+  m_is_set[EXIF_INFORMATION_ATTRIBUTE_URI] = true;
+  m_uri = uri;
+}
+
+unsigned long ExifInformation::getWidth() const {
+  LoggerD("Entered");
+  return m_width;
+}
+
+void ExifInformation::setWidth(unsigned long width) {
+  LoggerD("Entered");
+  m_is_set[EXIF_INFORMATION_ATTRIBUTE_WIDTH] = true;
+  m_width = width;
+}
+
+unsigned long ExifInformation::getHeight() const {
+  LoggerD("Entered");
+  return m_height;
+}
+
+void ExifInformation::setHeight(unsigned long height) {
+  LoggerD("Entered");
+  m_is_set[EXIF_INFORMATION_ATTRIBUTE_HEIGHT] = true;
+  m_height = height;
+}
+
+const std::string& ExifInformation::getDeviceMaker() {
+  LoggerD("Entered");
+  return m_device_maker;
+}
+
+void ExifInformation::setDeviceMaker(const std::string& device_maker) {
+  LoggerD("Entered");
+  m_is_set[EXIF_INFORMATION_ATTRIBUTE_DEVICE_MAKER] = true;
+  m_device_maker = device_maker;
+}
+
+const std::string& ExifInformation::getDeviceModel() {
+  LoggerD("Entered");
+  return m_device_model;
+}
+
+void ExifInformation::setDeviceModel(const std::string& device_model) {
+  LoggerD("Entered");
+  m_is_set[EXIF_INFORMATION_ATTRIBUTE_DEVICE_MODEL] = true;
+  m_device_model = device_model;
+}
+
+time_t ExifInformation::getOriginalTime() const {
+  LoggerD("Entered");
+  return m_original_time;
+}
+
+void ExifInformation::setOriginalTime(time_t original_time) {
+  LoggerD("Entered");
+  m_is_set[EXIF_INFORMATION_ATTRIBUTE_ORIGINAL_TIME] = true;
+  m_original_time = original_time;
+}
+
+const std::string& ExifInformation::getOrientationString() {
+  LoggerD("Entered");
+  return ExifUtil::orientationToString(m_orientation);
+}
+
+ImageOrientation ExifInformation::getOrientation() {
+  LoggerD("Entered");
+  return m_orientation;
+}
+
+void ExifInformation::setOrientation(const std::string& orientation) {
+  LoggerD("Entered");
+  setOrientation(ExifUtil::stringToOrientation(orientation));
+}
+
+void ExifInformation::setOrientation(ImageOrientation orientation) {
+  LoggerD("Entered");
+  m_is_set[EXIF_INFORMATION_ATTRIBUTE_ORIENTATION] = true;
+  m_orientation = orientation;
+}
+
+const Rational& ExifInformation::getFNumber() const {
+  LoggerD("Entered");
+  return m_f_number;
+}
+
+void ExifInformation::setFNumber(Rational f_number) {
+  LoggerD("Entered");
+  if (!f_number.isValid()) {
+    LoggerW("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;
+}
+
+const std::vector<long long int>& ExifInformation::getIsoSpeedRatings() {
+  LoggerD("Entered");
+  return m_iso_speed_ratings;
+}
+
+void ExifInformation::setIsoSpeedRatings(
+const std::vector<long long int>& iso_speed_ratings) {
+  LoggerD("Entered");
+  m_is_set[EXIF_INFORMATION_ATTRIBUTE_ISO_SPEED_RATINGS] = true;
+  m_iso_speed_ratings = iso_speed_ratings;
+}
+
+const Rational& ExifInformation::getExposureTime() {
+  LoggerD("Entered");
+  return m_exposure_time;
+}
+
+void ExifInformation::setExposureTime(const Rational& exposure_time) {
+  LoggerD("Entered");
+  if (!exposure_time.isValid() || 0 == exposure_time.nominator) {
+    LoggerW("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;
+}
+
+const std::string& ExifInformation::getExposureProgramString() {
+  LoggerD("Entered");
+  return ExifUtil::exposureProgramToString(m_exposure_program);;
+}
+
+ExposureProgram ExifInformation::getExposureProgram() {
+  LoggerD("Entered");
+  return m_exposure_program;
+}
+
+void ExifInformation::setExposureProgram(const std::string& exposure_program) {
+  LoggerD("Entered");
+  setExposureProgram(ExifUtil::stringToExposureProgram(exposure_program));
+}
+
+void ExifInformation::setExposureProgram(ExposureProgram exposure_program) {
+  LoggerD("Entered");
+  m_is_set[EXIF_INFORMATION_ATTRIBUTE_EXPOSURE_PROGRAM] = true;
+  m_exposure_program = exposure_program;
+}
+
+bool ExifInformation::getFlash() const {
+  LoggerD("Entered");
+  return m_flash;
+}
+
+void ExifInformation::setFlash(bool flash) {
+  LoggerD("Entered");
+  m_is_set[EXIF_INFORMATION_ATTRIBUTE_FLASH] = true;
+  m_flash = flash;
+}
+
+const Rational& ExifInformation::getFocalLength() const {
+  LoggerD("Entered");
+  return m_focal_length;
+}
+
+void ExifInformation::setFocalLength(Rational focal_length) {
+  LoggerD("Entered");
+  if (!focal_length.isValid()) {
+    LoggerW("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;
+}
+
+const std::string& ExifInformation::getWhiteBalanceModeString() {
+  LoggerD("Entered");
+  return ExifUtil::whiteBalanceToString(m_white_balance);
+}
+
+WhiteBalanceMode ExifInformation::getWhiteBalanceMode() {
+  LoggerD("Entered");
+  return m_white_balance;
+}
+
+void ExifInformation::setWhiteBalanceMode(const std::string& white_balance) {
+  LoggerD("Entered");
+  setWhiteBalanceMode(ExifUtil::stringToWhiteBalance(white_balance));
+}
+
+void ExifInformation::setWhiteBalanceMode(WhiteBalanceMode white_balance) {
+  LoggerD("Entered");
+  m_is_set[EXIF_INFORMATION_ATTRIBUTE_WHITE_BALANCE] = true;
+  m_white_balance = white_balance;
+}
+
+ExifGPSLocation& ExifInformation::getGPSExifLocation() {
+  LoggerD("Entered");
+  return m_gps_location;
+}
+
+void ExifInformation::setGPSLocation(ExifGPSLocation gps_location) {
+  LoggerD("Entered");
+  m_is_set[EXIF_INFORMATION_ATTRIBUTE_GPS_LOCATION] = true;
+  m_gps_location = gps_location;
+}
+
+void ExifInformation::unsetGPSLocation() {
+  LoggerD("Entered");
+  m_is_set[EXIF_INFORMATION_ATTRIBUTE_GPS_LOCATION] = false;
+  m_gps_location.unsetAll();
+}
+
+const Rational& ExifInformation::getGpsAltitude() const {
+  LoggerD("Entered");
+  return m_gps_altitude;
+}
+
+void ExifInformation::setGpsAltitude(Rational gps_altitude) {
+  LoggerD("Entered");
+  if (!gps_altitude.isValid()) {
+    LoggerW("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 {
+  LoggerD("Entered");
+  return m_gps_altitude_ref;
+}
+
+void ExifInformation::setGpsAltitudeRef(const GpsAltitudeRef ref) {
+  LoggerD("Entered");
+  m_is_set[EXIF_INFORMATION_ATTRIBUTE_GPS_ALTITUDE_REF] = true;
+  m_gps_altitude_ref = ref;
+}
+
+void ExifInformation::setGpsAltitudeWithRef(double gps_altitude) {
+  LoggerD("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 {
+  LoggerD("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 {
+  LoggerD("Entered");
+  return m_gps_processing_method;
+}
+
+const std::string& ExifInformation::getGpsProcessingMethodType() const {
+  LoggerD("Entered");
+  return m_gps_processing_method_type;
+}
+
+void ExifInformation::setGpsProcessingMethod(const std::string& type,
+    const std::string& processing_method) {
+  LoggerD("Entered");
+  if (type != EXIF_UNDEFINED_TYPE_ASCII &&
+      type != EXIF_UNDEFINED_TYPE_JIS &&
+      type != EXIF_UNDEFINED_TYPE_UNICODE &&
+      type != EXIF_UNDEFINED_TYPE_UNDEFINED) {
+    LoggerW("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;
+}
+
+void ExifInformation::setGpsTime(time_t time) {
+  LoggerD("Entered");
+  m_is_set[EXIF_INFORMATION_ATTRIBUTE_GPS_TIME] = true;
+  m_gps_time = time;
+}
+
+time_t ExifInformation::getGpsTime() {
+  LoggerD("Entered");
+  return m_gps_time;
+}
+
+void ExifInformation::unsetGPStime() {
+  LoggerD("Entered");
+  m_is_set[EXIF_INFORMATION_ATTRIBUTE_GPS_TIME] = false;
+  m_gps_time = 0;
+}
+
+const std::string& ExifInformation::getUserComment() {
+  LoggerD("Entered");
+  return m_user_comment;
+}
+
+const std::string& ExifInformation::getUserCommentType() {
+  LoggerD("Entered");
+  return m_user_comment_type;
+}
+
+void ExifInformation::setUserComment(const std::string& type,
+    const std::string& user_comment) {
+  LoggerD("Entered");
+  if (type != EXIF_UNDEFINED_TYPE_ASCII &&
+      type != EXIF_UNDEFINED_TYPE_JIS &&
+      type != EXIF_UNDEFINED_TYPE_UNICODE &&
+      type != EXIF_UNDEFINED_TYPE_UNDEFINED) {
+    LoggerW("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 {
+  LoggerD("Entered");
+  return m_is_set[attribute];
+}
+
+void ExifInformation::unset(ExifInformationAttribute attribute) {
+  LoggerD("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_LOCATION:
+      unsetGPSLocation();
+      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_GPS_TIME:
+      unsetGPStime();
+      break;
+    case EXIF_INFORMATION_ATTRIBUTE_USER_COMMENT:
+      m_user_comment = std::string();
+      m_user_comment_type = EXIF_UNDEFINED_TYPE_ASCII;
+      break;
+    default:
+      break;
+  }
+}
+
+void ExifInformation::set(std::string attributeName, const picojson::value& v) {
+  LoggerD("Entered | name: %s", attributeName.c_str());
+
+  switch (str2int(attributeName.c_str())) {
+    case str2int(EI_URI): {
+      setUri(v.get<std::string>());
+      break;
+    }
+    case str2int(EI_WIDTH): {
+      setWidth(static_cast<int>(v.get<double>()));
+      break;
+    }
+    case str2int(EI_HEIGHT): {
+      setHeight(static_cast<int>(v.get<double>()));
+      break;
+    }
+    case str2int(EI_DEVICE_MAKER): {
+      setDeviceMaker(v.get<std::string>());
+      break;
+    }
+    case str2int(EI_DEVICE_MODEL): {
+      setDeviceModel(v.get<std::string>());
+      break;
+    }
+    case str2int(EI_ORIGINAL_TIME): {
+      setOriginalTime(static_cast<unsigned long long>(v.get<double>()));
+    break;
+    }
+    case str2int(EI_ORIENTATION): {
+      setOrientation(v.get<std::string>());
+      break;
+    }
+    case str2int(EI_FNUMBER): {
+      setFNumber(Rational::createFromDouble(v.get<double>()));
+      break;
+    }
+    case str2int(EI_ISO_SPEED_RATINGS): {
+      setIsoSpeedRatings(jsonArray2vector(v));
+      break;
+    }
+    case str2int(EI_EXPOSURE_TIME): {
+      setExposureTime(
+        Rational::createFromExposureTimeString(v.get<std::string>()));
+      break;
+    }
+    case str2int(EI_EXPOSURE_PROGRAM): {
+      setExposureProgram(v.get<std::string>());
+      break;
+    }
+    case str2int(EI_FLASH): {
+      setFlash(v.get<bool>());
+      break;
+    }
+    case str2int(EI_FOCAL_LENGTH): {
+      setFocalLength(Rational::createFromDouble(v.get<double>()));
+      break;
+    }
+    case str2int(EI_WHITE_BALANCE): {
+      setWhiteBalanceMode(v.get<std::string>());
+      break;
+    }
+    case str2int(EI_GPS_LOCATION): {
+      setGPSLocation(ExifGPSLocation(v.get("longitude").get<double>(),
+       v.get("latitude").get<double>()));
+      break;
+    }
+    case str2int(EI_GPS_ALTITUDE): {
+      setGpsAltitudeWithRef(v.get<double>());
+      break;
+    }
+    case str2int(EI_GPS_PROCESSING_METHOD): {
+      setGpsProcessingMethod(EXIF_UNDEFINED_TYPE_ASCII, v.get<std::string>());
+      break;
+    }
+    case str2int(EI_GPS_TIME): {
+      setGpsTime(static_cast<unsigned long long>(v.get<double>()));
+      break;
+    }
+    case str2int(EI_USER_COMMENT): {
+      setUserComment(EXIF_UNDEFINED_TYPE_ASCII, v.get<std::string>());
+      break;
+    }
+    default:
+      break;
+  }
+}
+
+void ExifInformation::removeNulledAttributesFromExifData(ExifData* exif_data) {
+  LoggerD("Entered");
+  AssertMsg(exif_data, "exif_data is NULL");
+
+  if (!isSet(EXIF_INFORMATION_ATTRIBUTE_WIDTH)) {
+    LoggerD("Removing width");
+    ExifTagSaver::removeExifEntryWithTag(EXIF_TAG_IMAGE_WIDTH, exif_data);
+  }
+  if (!isSet(EXIF_INFORMATION_ATTRIBUTE_HEIGHT)) {
+    LoggerD("Removing height");
+    ExifTagSaver::removeExifEntryWithTag(EXIF_TAG_IMAGE_LENGTH, exif_data);
+  }
+  if (!isSet(EXIF_INFORMATION_ATTRIBUTE_DEVICE_MAKER)) {
+    LoggerD("Removing device maker");
+    ExifTagSaver::removeExifEntryWithTag(EXIF_TAG_MAKE, exif_data);
+  }
+  if (!isSet(EXIF_INFORMATION_ATTRIBUTE_ORIENTATION)) {
+    LoggerD("Removing orientation");
+    ExifTagSaver::removeExifEntryWithTag(EXIF_TAG_ORIENTATION, exif_data);
+  }
+  if (!isSet(EXIF_INFORMATION_ATTRIBUTE_EXPOSURE_PROGRAM)) {
+    LoggerD("Removing exposure program");
+    ExifTagSaver::removeExifEntryWithTag(EXIF_TAG_EXPOSURE_PROGRAM, exif_data);
+  }
+  if (!isSet(EXIF_INFORMATION_ATTRIBUTE_ISO_SPEED_RATINGS)) {
+    LoggerD("Removing iso speed ratings");
+    ExifTagSaver::removeExifEntryWithTag(EXIF_TAG_ISO_SPEED_RATINGS, exif_data);
+  }
+  if (!isSet(EXIF_INFORMATION_ATTRIBUTE_WHITE_BALANCE)) {
+    LoggerD("Removing white balance");
+    ExifTagSaver::removeExifEntryWithTag(EXIF_TAG_WHITE_BALANCE, exif_data);
+  }
+  if (!isSet(EXIF_INFORMATION_ATTRIBUTE_DEVICE_MODEL)) {
+    LoggerD("Removing device model");
+    ExifTagSaver::removeExifEntryWithTag(EXIF_TAG_MODEL, exif_data);
+  }
+  if (!isSet(EXIF_INFORMATION_ATTRIBUTE_ORIGINAL_TIME)) {
+    LoggerD("Removing original time");
+    ExifTagSaver::removeExifEntryWithTag(
+        EXIF_TAG_DATE_TIME_ORIGINAL, exif_data);
+  }
+  if (!isSet(EXIF_INFORMATION_ATTRIBUTE_EXPOSURE_TIME)) {
+    LoggerD("Removing exposure time");
+    ExifTagSaver::removeExifEntryWithTag(EXIF_TAG_EXPOSURE_TIME, exif_data);
+  }
+  if (!isSet(EXIF_INFORMATION_ATTRIBUTE_FNUMBER)) {
+    LoggerD("Removing f-number");
+    ExifTagSaver::removeExifEntryWithTag(EXIF_TAG_FNUMBER, exif_data);
+  }
+  if (!isSet(EXIF_INFORMATION_ATTRIBUTE_FLASH)) {
+    LoggerD("Removing flash");
+    ExifTagSaver::removeExifEntryWithTag(EXIF_TAG_FLASH, exif_data);
+  }
+  if (!isSet(EXIF_INFORMATION_ATTRIBUTE_FOCAL_LENGTH)) {
+    LoggerD("Removing focal length");
+    ExifTagSaver::removeExifEntryWithTag(EXIF_TAG_FOCAL_LENGTH, exif_data);
+  }
+  if (!isSet(EXIF_INFORMATION_ATTRIBUTE_GPS_TIME)) {
+    LoggerD("Removing gps altitude");
+    ExifTagSaver::removeExifEntryWithTag(
+    static_cast<ExifTag>(EXIF_TAG_GPS_TIME_STAMP), exif_data);
+  }
+  if (!isSet(EXIF_INFORMATION_ATTRIBUTE_GPS_ALTITUDE)) {
+    LoggerD("Removing gps altitude");
+    ExifTagSaver::removeExifEntryWithTag(
+        static_cast<ExifTag>(EXIF_TAG_GPS_ALTITUDE), exif_data);
+  }
+  if (!isSet(EXIF_INFORMATION_ATTRIBUTE_GPS_ALTITUDE_REF)) {
+    LoggerD("Removing gps altitude ref");
+    ExifTagSaver::removeExifEntryWithTag(
+        static_cast<ExifTag>(EXIF_TAG_GPS_ALTITUDE_REF), exif_data);
+  }
+  if (!isSet(EXIF_INFORMATION_ATTRIBUTE_GPS_PROCESSING_METHOD)) {
+    LoggerD("Removing gps processing method");
+    ExifTagSaver::removeExifEntryWithTag(
+        static_cast<ExifTag>(EXIF_TAG_GPS_PROCESSING_METHOD), exif_data);
+  }
+  if (!isSet(EXIF_INFORMATION_ATTRIBUTE_USER_COMMENT)) {
+    LoggerD("Removing user comment");
+    ExifTagSaver::removeExifEntryWithTag(EXIF_TAG_USER_COMMENT, exif_data);
+  }
+  if (!m_gps_location.isSet(EXIF_GPS_LOCATION_ATTRIBUTE_LATITUDE)) {
+    LoggerD("Removing latitude");
+    ExifTagSaver::removeExifEntryWithTag(
+        static_cast<ExifTag>(EXIF_TAG_GPS_LATITUDE), exif_data);
+  }
+  if (!m_gps_location.isSet(EXIF_GPS_LOCATION_ATTRIBUTE_LATITUDE_REF)) {
+    LoggerD("Removing latitude ref");
+    ExifTagSaver::removeExifEntryWithTag(
+        static_cast<ExifTag>(EXIF_TAG_GPS_LATITUDE_REF), exif_data);
+  }
+  if (!m_gps_location.isSet(EXIF_GPS_LOCATION_ATTRIBUTE_LONGITUDE)) {
+    LoggerD("Removing longitude");
+    ExifTagSaver::removeExifEntryWithTag(
+        static_cast<ExifTag>(EXIF_TAG_GPS_LONGITUDE), exif_data);
+  }
+  if (!m_gps_location.isSet(EXIF_GPS_LOCATION_ATTRIBUTE_LONGITUDE_REF)) {
+    LoggerD("Removing longitude ref");
+    ExifTagSaver::removeExifEntryWithTag(
+        static_cast<ExifTag>(EXIF_TAG_GPS_LONGITUDE_REF), exif_data);
+  }
+}
+
+void ExifInformation::updateAttributesInExifData(ExifData* exif_data) {
+  LoggerD("Entered");
+  AssertMsg(exif_data, "exif_data is NULL");
+
+  if (isSet(EXIF_INFORMATION_ATTRIBUTE_WIDTH)) {
+    LoggerD("Saving width: %d", getWidth());
+    ExifTagSaver::saveToExif(getWidth(),
+        EXIF_TAG_IMAGE_WIDTH, exif_data);
+  }
+  if (isSet(EXIF_INFORMATION_ATTRIBUTE_HEIGHT)) {
+    LoggerD("Saving height: %d", getHeight());
+    ExifTagSaver::saveToExif(getHeight(),
+        EXIF_TAG_IMAGE_LENGTH, exif_data);
+  }
+  if (isSet(EXIF_INFORMATION_ATTRIBUTE_DEVICE_MAKER)) {
+    LoggerD("Saving device maker: %s", getDeviceMaker().c_str());
+    ExifTagSaver::saveToExif(getDeviceMaker(),
+        EXIF_TAG_MAKE, exif_data);
+  }
+  if (isSet(EXIF_INFORMATION_ATTRIBUTE_ORIENTATION)) {
+    LoggerD("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)) {
+    LoggerD("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();
+    LoggerD("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)) {
+    LoggerD("Saving white balance: %d",
+        static_cast<int>(getWhiteBalanceMode()));
+    ExifTagSaver::saveToExif(getWhiteBalanceMode(),
+        EXIF_TAG_WHITE_BALANCE, exif_data);
+  }
+  if (isSet(EXIF_INFORMATION_ATTRIBUTE_DEVICE_MODEL)) {
+    LoggerD("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);
+    LoggerD("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()) {
+      LoggerD("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();
+    LoggerD("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)) {
+    LoggerD("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();
+    LoggerD("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_LOCATION)) {
+    LoggerD("Saving gps location");
+    ExifTagSaver::saveGpsLocationToExif(m_gps_location, exif_data);
+  }
+  if (isSet(EXIF_INFORMATION_ATTRIBUTE_GPS_ALTITUDE)) {
+    LoggerD("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)
+    LoggerD("Saving gps altitude ref:%d (%s)",
+        static_cast<int>(m_gps_altitude_ref),
+        (static_cast<int>(m_gps_altitude_ref) > 0) ? "below sea" : "above sea");
+    std::vector<long long int> value = {
+      static_cast<long long int>(m_gps_altitude_ref)
+    };
+    ExifTagSaver::saveToExif(value, EXIF_FORMAT_BYTE,
+        static_cast<ExifTag>(EXIF_TAG_GPS_ALTITUDE_REF), exif_data);
+  }
+  if (isSet(EXIF_INFORMATION_ATTRIBUTE_GPS_PROCESSING_METHOD)) {
+    LoggerD("Saving gps processing method: [%s] type:%s",
+        getGpsProcessingMethod().c_str(), getGpsProcessingMethodType().c_str());
+
+    const std::string& joined = getGpsProcessingMethodType() +
+        getGpsProcessingMethod();
+    LoggerD("joined: [%s]", joined.c_str());
+
+    ExifTagSaver::saveToExif(joined,
+        static_cast<ExifTag>(EXIF_TAG_GPS_PROCESSING_METHOD), exif_data,
+        EXIF_FORMAT_UNDEFINED, false);
+  }
+  if (isSet(EXIF_INFORMATION_ATTRIBUTE_GPS_TIME)) {
+    const time_t gps_time = getGpsTime();
+    const Rationals gps_time_vec = ExifUtil::timeTToExifGpsTimeStamp(gps_time);
+    const std::string& gps_date_str =
+        ExifUtil::timeTToExifGpsDateStamp(gps_time);
+    LoggerD("Saving gps time stamp time_t: %d", static_cast<int>(gps_time));
+
+    ExifTagSaver::saveToExif(gps_time_vec,
+        static_cast<ExifTag>(EXIF_TAG_GPS_TIME_STAMP), exif_data);
+
+    LoggerD("Saving gps date stamp: %s", gps_date_str.c_str());
+
+    ExifTagSaver::saveToExif(gps_date_str,
+        static_cast<ExifTag>(EXIF_TAG_GPS_DATE_STAMP), exif_data,
+        EXIF_FORMAT_ASCII, false);
+  }
+  if (isSet(EXIF_INFORMATION_ATTRIBUTE_USER_COMMENT)) {
+    LoggerD("Saving user comment: %s (type:%s)", getUserComment().c_str(),
+        getUserCommentType().c_str());
+
+    const std::string& joined = getUserCommentType() + getUserComment();
+    LoggerD("joined: [%s]", joined.c_str());
+
+    ExifTagSaver::saveToExif(joined,
+        EXIF_TAG_USER_COMMENT, exif_data, EXIF_FORMAT_UNDEFINED, false);
+  }
+}
+
+PlatformResult ExifInformation::saveToFile(const std::string& file_path) {
+  LoggerD("Entered");
+  LoggerD("Using JpegFile to read: [%s] and Exif if present",
+      file_path.c_str());
+
+  JpegFilePtr jpg_file;
+  PlatformResult result = JpegFile::loadFile(file_path, &jpg_file);
+  if (!result)
+    return result;
+
+  ExifData* exif_data = jpg_file->getExifData();
+  bool exif_data_is_new = false;
+
+  // Exif is not present in file - create new ExifData
+  if (!exif_data) {
+    LoggerD("Exif is not present in file: [%s] creating new",
+        file_path.c_str());
+
+    exif_data = exif_data_new();
+    if (!exif_data) {
+      LoggerE("Couldn't allocate new ExifData");
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, "Memory allocation failed");
+    }
+
+    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;
+  }
+
+  LoggerD("Exif data type: %d", exif_data_get_data_type(exif_data));
+  LoggerD("Exif byte order: %d", exif_data_get_byte_order(exif_data));
+  exif_data_set_option(exif_data, EXIF_DATA_OPTION_FOLLOW_SPECIFICATION);
+
+  // 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);
+
+  LoggerD("Using JpegFile to save new Exif in: [%s]", file_path.c_str());
+  if (exif_data_is_new) {
+    result = jpg_file->setNewExifData(exif_data);
+  }
+
+  exif_data_unref(exif_data);
+
+  if (!result) {
+    return result;
+  }
+
+  return jpg_file->saveToFile(file_path);
+}
+
+}  // namespace exif
+}  // namespace extension
diff --git a/webWidgetTCT_device/src/exif/exif_information.h b/webWidgetTCT_device/src/exif/exif_information.h
new file mode 100755 (executable)
index 0000000..237c37a
--- /dev/null
@@ -0,0 +1,252 @@
+/*
+ * Copyright (c) 2015 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 EXIF_EXIF_INFORMATION_H_
+#define EXIF_EXIF_INFORMATION_H_
+
+#include <libexif/exif-loader.h>
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "common/picojson.h"
+#include "common/platform_result.h"
+
+#include "exif/exif_gps_location.h"
+
+namespace extension {
+namespace exif {
+
+#define EI_URI "uri"
+#define EI_WIDTH "width"
+#define EI_HEIGHT "height"
+#define EI_DEVICE_MAKER "deviceMaker"
+#define EI_DEVICE_MODEL "deviceModel"
+#define EI_ORIGINAL_TIME "originalTime"
+#define EI_ORIENTATION "orientation"
+#define EI_FNUMBER "fNumber"
+#define EI_ISO_SPEED_RATINGS "isoSpeedRatings"
+#define EI_EXPOSURE_TIME "exposureTime"
+#define EI_EXPOSURE_PROGRAM "exposureProgram"
+#define EI_FLASH "flash"
+#define EI_FOCAL_LENGTH "focalLength"
+#define EI_WHITE_BALANCE "whiteBalance"
+#define EI_GPS_LOCATION "gpsLocation"
+#define EI_GPS_ALTITUDE "gpsAltitude"
+#define EI_GPS_PROCESSING_METHOD "gpsProcessingMethod"
+#define EI_GPS_TIME "gpsTime"
+#define EI_USER_COMMENT "userComment"
+
+class ExifInformation;
+typedef std::shared_ptr<ExifInformation> ExifInformationPtr;
+typedef std::map<std::string, std::string> AttributeMap;
+typedef std::vector<long long int> IsoSpeedRatingsVector;
+
+extern const std::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_LOCATION,
+  EXIF_INFORMATION_ATTRIBUTE_GPS_PROCESSING_METHOD,
+  EXIF_INFORMATION_ATTRIBUTE_GPS_TIME,
+  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
+};
+
+const AttributeMap ExifInformationAttributeMap = {
+  {"uri", "uri"},
+  {"width", "width"},
+  {"height", "height"},
+  {"deviceMaker", "deviceMaker"},
+  {"deviceModel", "deviceModel"},
+  {"originalTime", "originalTime"},
+  {"orientation", "orientation"},
+  {"fNumber", "fNumber"},
+  {"isoSpeedRatings", "isoSpeedRatings"},
+  {"exposureTime", "exposureTime"},
+  {"exposureProgram", "exposureProgram"},
+  {"flash", "flash"},
+  {"focalLength", "focalLength"},
+  {"whiteBalance", "whiteBalance"},
+  {"gpsLocation", "gpsLocation"},
+  {"gpsAltitude", "gpsAltitude"},
+  {"gpsProcessingMethod", "gpsProcessingMethod"},
+  {"gpsTime", "gpsTime"},
+  {"userComment", "userComment"}
+};
+
+class ExifInformation {
+ public:
+  ExifInformation();
+  explicit ExifInformation(const picojson::value& args);
+  ~ExifInformation();
+
+  common::PlatformResult 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);
+
+  const std::string& getOrientationString();
+  ImageOrientation getOrientation();
+  void setOrientation(const std::string& orientation);
+  void setOrientation(ImageOrientation orientation);
+
+  const Rational& getFNumber() const;
+  void setFNumber(Rational f_number);
+
+  const std::vector<long long int>& getIsoSpeedRatings();
+  void setIsoSpeedRatings(const std::vector<long long int>& iso_speed_ratings);
+
+  const Rational& getExposureTime();
+  void setExposureTime(const Rational& exposure_time);
+
+  const std::string& getExposureProgramString();
+  ExposureProgram getExposureProgram();
+  void setExposureProgram(const std::string& exposure_program);
+  void setExposureProgram(ExposureProgram exposure_program);
+
+  bool getFlash() const;
+  void setFlash(bool flash);
+
+  const Rational& getFocalLength() const;
+  void setFocalLength(Rational focal_length);
+
+  const std::string& getWhiteBalanceModeString();
+  WhiteBalanceMode getWhiteBalanceMode();
+  void setWhiteBalanceMode(const std::string& white_balance);
+  void setWhiteBalanceMode(WhiteBalanceMode white_balance);
+
+  ExifGPSLocation& getGPSExifLocation();
+  void setGPSLocation(ExifGPSLocation 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);
+
+  void setGpsTime(time_t time);
+  time_t getGpsTime();
+  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);
+  void set(std::string attributeName, const picojson::value& args);
+
+ private:
+  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;
+  std::vector<long long int> 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_gps_location;
+
+  Rational m_gps_altitude;
+  GpsAltitudeRef m_gps_altitude_ref;
+
+  std::string m_gps_processing_method;
+  std::string m_gps_processing_method_type;
+
+  time_t m_gps_time;
+
+  std::string m_user_comment;
+  std::string m_user_comment_type;
+
+  bool m_is_set[EXIF_INFORMATION_ATTRIBUTE_NUMBER_OF_ATTRIBUTES];
+};
+
+}  // namespace exif
+}  // namespace extension
+
+#endif  // EXIF_EXIF_INFORMATION_H_
diff --git a/webWidgetTCT_device/src/exif/exif_instance.cc b/webWidgetTCT_device/src/exif/exif_instance.cc
new file mode 100755 (executable)
index 0000000..b4d6446
--- /dev/null
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 2015 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 "exif/exif_instance.h"
+
+#include <libexif/exif-data.h>
+#include <libexif/exif-entry.h>
+#include <libexif/exif-loader.h>
+#include <libexif/exif-utils.h>
+
+#include <string>
+#include <sstream>
+
+#include "common/logger.h"
+#include "common/platform_result.h"
+#include "common/task-queue.h"
+
+#include "exif/exif_information.h"
+#include "exif/exif_util.h"
+#include "exif/get_exif_info.h"
+#include "exif/jpeg_file.h"
+
+namespace extension {
+namespace exif {
+
+using common::PlatformResult;
+using common::ErrorCode;
+
+ExifInstance::ExifInstance() {
+  using std::placeholders::_1;
+  using std::placeholders::_2;
+
+#define REGISTER_ASYNC(c, x) RegisterSyncHandler(c, std::bind(&ExifInstance::x, this, _1, _2));
+  REGISTER_ASYNC("ExifManager_getExifInfo", ExifManagerGetExifInfo);
+  REGISTER_ASYNC("ExifManager_saveExifInfo", ExifManagerSaveExifInfo);
+  REGISTER_ASYNC("ExifManager_getThumbnail", ExifManagerGetThumbnail);
+#undef REGISTER_ASYNC
+}
+
+ExifInstance::~ExifInstance() {}
+
+void ExifInstance::ExifManagerGetExifInfo(const picojson::value& args, picojson::object& out) {
+  LoggerD("enter");
+
+  const std::string& uri = args.get("uri").get<std::string>();
+
+  const double callback_id = args.get("callbackId").get<double>();
+  auto get = [=](const std::shared_ptr<JsonValue>& response)->void {
+      JsonValue result = JsonValue(JsonObject());
+      PlatformResult status(ErrorCode::NO_ERROR);
+
+      // TODO(r.galka) it can be done on JS side
+      const std::string &file_path = ExifUtil::convertUriToPath(uri);
+      LoggerD("file_path = %s", file_path.c_str());
+
+      status = GetExifInfo::LoadFromURI(uri, &result);
+      if (status)
+        ReportSuccess(result, response->get<picojson::object>());
+      else
+        ReportError(status, &response->get<picojson::object>());
+  };
+
+  auto get_response = [callback_id, this](const std::shared_ptr<JsonValue>& response)->void {
+      picojson::object& obj = response->get<picojson::object>();
+      obj.insert(std::make_pair("callbackId", picojson::value(callback_id)));
+      Instance::PostMessage(this, response->serialize().c_str());
+  };
+
+  auto data = std::shared_ptr<JsonValue>(new JsonValue(JsonObject()));
+
+  common::TaskQueue::GetInstance().Queue<JsonValue>(get, get_response, data);
+
+  LoggerD("exit");
+}
+
+void ExifInstance::ExifManagerSaveExifInfo(const picojson::value& args,
+                                           picojson::object& out) {
+  LoggerD("Entered");
+
+  const double callback_id = args.get("callbackId").get<double>();
+  auto get = [=](const std::shared_ptr<JsonValue>& response) -> void {
+      JsonValue result = JsonValue(JsonObject());
+      PlatformResult status(ErrorCode::NO_ERROR);
+
+      ExifInformationPtr exifInfo(new ExifInformation(args));
+      const std::string& uri = exifInfo->getUri();
+      // TODO(r.galka) it can be done on JS side
+      const std::string& path = ExifUtil::convertUriToPath(uri);
+      status = exifInfo->saveToFile(path);
+
+      if (status)
+        ReportSuccess(result, response->get<picojson::object>());
+      else
+        ReportError(status, &response->get<picojson::object>());
+  };
+
+  auto get_response = [callback_id, this](const std::shared_ptr<JsonValue>& response) -> void {
+      picojson::object& obj = response->get<picojson::object>();
+      obj.insert(std::make_pair("callbackId", picojson::value(callback_id)));
+      Instance::PostMessage(this, response->serialize().c_str());
+  };
+
+  auto data = std::shared_ptr<JsonValue>(new JsonValue(JsonObject()));
+
+  common::TaskQueue::GetInstance().Queue<JsonValue>(get, get_response, data);
+}
+
+void ExifInstance::ExifManagerGetThumbnail(const picojson::value& args,
+                                           picojson::object& out) {
+  LoggerD("Entered");
+  const std::string& uri = args.get("uri").get<std::string>();
+
+  const double callback_id = args.get("callbackId").get<double>();
+  auto get = [=](const std::shared_ptr<JsonValue> &response) -> void {
+      PlatformResult status(ErrorCode::NO_ERROR);
+
+      // TODO(r.galka) it can be done on JS side
+      const std::string &file_path = ExifUtil::convertUriToPath(uri);
+      JsonValue result = JsonValue(JsonObject());
+      JsonObject &result_obj = result.get<JsonObject>();
+
+      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) {
+        LoggerE("extension: %s is not valid (jpeg/jpg/png/gif is supported)",
+            ext.c_str());
+        status = PlatformResult(ErrorCode::INVALID_VALUES_ERR,
+            "getThumbnail support only jpeg/jpg/png/gif");
+        ReportError(status, &response->get<picojson::object>());
+        return;
+      }
+
+      LoggerD("Get thumbnail from Exif in file: [%s]", file_path.c_str());
+      ExifData *exif_data = exif_data_new_from_file(file_path.c_str());
+      if (!exif_data) {
+        LoggerE("Error reading from file [%s]", file_path.c_str());
+        status = PlatformResult(ErrorCode::UNKNOWN_ERR,
+            "Error reading from file");
+        ReportError(status, &response->get<picojson::object>());
+        return;
+      }
+
+      if (!exif_data->data || !exif_data->size) {
+        exif_data_unref(exif_data);
+        LoggerE("File [%s] doesn't contain thumbnail", file_path.c_str());
+        status = PlatformResult(ErrorCode::UNKNOWN_ERR,
+            "File doesn't contain thumbnail");
+        ReportError(status, &response->get<picojson::object>());
+        return;
+      }
+
+      gchar *ch_uri = g_base64_encode(exif_data->data, exif_data->size);
+      exif_data_unref(exif_data);
+      std::string base64 = "data:image/" + ext + ";base64," + ch_uri;
+
+      std::pair<std::string, picojson::value> pair;
+      pair = std::make_pair("src", picojson::value(base64));
+      result_obj.insert(pair);
+
+      ReportSuccess(result, response->get<picojson::object>());
+  };
+
+  auto get_response = [callback_id, this](const std::shared_ptr<JsonValue>& response)->void {
+      picojson::object& obj = response->get<picojson::object>();
+      obj.insert(std::make_pair("callbackId", picojson::value(callback_id)));
+      Instance::PostMessage(this, response->serialize().c_str());
+  };
+
+  auto data = std::shared_ptr<JsonValue>(new JsonValue(JsonObject()));
+
+  common::TaskQueue::GetInstance().Queue<JsonValue>(get, get_response, data);
+}
+
+}  // namespace exif
+}  // namespace extension
diff --git a/webWidgetTCT_device/src/exif/exif_instance.h b/webWidgetTCT_device/src/exif/exif_instance.h
new file mode 100755 (executable)
index 0000000..50915ed
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2015 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 EXIF_EXIF_INSTANCE_H_
+#define EXIF_EXIF_INSTANCE_H_
+
+#include "common/extension.h"
+#include "common/picojson.h"
+
+typedef picojson::value JsonValue;
+typedef picojson::object JsonObject;
+typedef picojson::array JsonArray;
+typedef std::string JsonString;
+
+namespace extension {
+namespace exif {
+
+class ExifInstance : public common::ParsedInstance {
+ public:
+  ExifInstance();
+  virtual ~ExifInstance();
+
+ private:
+  void ExifManagerGetExifInfo(const picojson::value& args, picojson::object& out);
+  void ExifManagerSaveExifInfo(const picojson::value& args, picojson::object& out);
+  void ExifManagerGetThumbnail(const picojson::value& args, picojson::object& out);
+};
+
+}  // namespace exif
+}  // namespace extension
+
+#endif  // EXIF_EXIF_INSTANCE_H_
diff --git a/webWidgetTCT_device/src/exif/exif_tag_saver.cc b/webWidgetTCT_device/src/exif/exif_tag_saver.cc
new file mode 100755 (executable)
index 0000000..cbb6e02
--- /dev/null
@@ -0,0 +1,471 @@
+/*
+ * Copyright (c) 2015 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 "exif/exif_tag_saver.h"
+
+#include <libexif/exif-format.h>
+#include <sstream>
+#include <cstring>
+
+#include "common/platform_result.h"
+#include "common/logger.h"
+
+#include "exif/exif_util.h"
+
+namespace extension {
+namespace exif {
+
+void ExifTagSaver::removeExifEntryWithTag(const ExifTag tag,
+                                          ExifData* exif_data) {
+  LoggerD("Entered tag:%d (0x%x)", tag, tag);
+  ExifEntry* exif_entry = exif_data_get_entry(exif_data, tag);
+  if (!exif_entry) {
+    LoggerE("Exif entry with tag:%d (0x%x) is not present", tag, tag);
+    return;
+  }
+
+  exif_content_remove_entry(exif_entry->parent, exif_entry);
+}
+
+void ExifTagSaver::saveToExif(long int value, ExifTag tag,
+                              ExifData* exif_data) {
+  LoggerD("Entered");
+  ExifEntry* entry = prepareEntry(exif_data, tag);
+  if (!entry) {
+    // TODO return PlatformResult and handle error
+    LoggerE("Exif entry is null");
+    return;
+  }
+
+  ExifByteOrder order = exif_data_get_byte_order(exif_data);
+
+  LoggerD("entry->format: %d", entry->format);
+  LoggerD("EXIF_FORMAT_BYTE: %d", EXIF_FORMAT_BYTE);
+
+  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: {
+      LoggerE("Error: wrong format: %d \n", entry->format);
+    }
+  }
+}
+
+void ExifTagSaver::saveToExif(const std::string& value, ExifTag tag,
+                              ExifData* exif_data, ExifFormat format,
+                              bool add_zero_character) {
+  LoggerD("Entered");
+  ExifEntry* entry = prepareEntry(exif_data, tag);
+  if (!entry) {
+    // TODO return PlatformResult and handle error
+    LoggerE("Exif entry is null");
+    return;
+  }
+
+  if (!value.empty()) {
+    if (entry->data) {
+      free(entry->data);
+      entry->data = NULL;
+    }
+
+    std::size_t new_len = value.length();
+    if (add_zero_character) {
+      ++new_len;
+    }
+
+    entry->format = format;
+    entry->size = new_len;
+    entry->components = new_len;
+
+    entry->data = static_cast<unsigned char*>(malloc(entry->size));
+    if (entry->data == nullptr) {
+      LoggerE("Function malloc returned nullptr");
+      return;
+    }
+
+    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) {
+  LoggerD("Entered");
+  ExifEntry* entry = prepareEntry(exif_data, tag);
+  if (!entry) {
+    // TODO return PlatformResult and handle error
+    LoggerE("Exif entry is null");
+    return;
+  }
+  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));
+    if (entry->data == nullptr) {
+      LoggerE("Function malloc returned nullptr");
+      return;
+    }
+    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) {
+  LoggerD("Entered");
+  ExifEntry* entry = prepareEntry(exif_data, tag);
+  if (!entry) {
+    // TODO return PlatformResult and handle error
+    LoggerE("Exif entry is null");
+    return;
+  }
+  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));
+    if (entry->data == nullptr) {
+      LoggerE("Function malloc returned nullptr");
+      return;
+    }
+    memset(entry->data, 0, entry->size);
+  }
+
+  entry->components = value.size();
+  for (std::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) {
+  LoggerD("Entered");
+  ExifEntry* entry = prepareEntry(exif_data, tag);
+  if (!entry) {
+    // TODO return PlatformResult and handle error
+    LoggerE("Exif entry is null");
+    return;
+  }
+  const ExifByteOrder order = exif_data_get_byte_order(exif_data);
+
+  const std::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:
+      LoggerE("output ExifFormat: %d is not supported!", store_as);
+      return;
+  }
+  entry->format = store_as;
+
+  const std::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));
+    if (entry->data == nullptr) {
+      LoggerE("Function malloc returned nullptr");
+      return;
+    }
+    memset(entry->data, 0, entry->size);
+  }
+  entry->components = num_elements;
+
+
+  switch (store_as) {
+    case EXIF_FORMAT_BYTE: {
+      for (std::size_t i = 0; i < num_elements; ++i) {
+        entry->data[i] = static_cast<ExifByte>(value[i]);
+      }
+      break;
+    }
+    case EXIF_FORMAT_SHORT: {
+      for (std::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 (std::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 (std::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 (std::size_t i = 0; i < num_elements; ++i) {
+        exif_set_slong(entry->data + i * size_per_member, order,
+            static_cast<ExifSLong>(value[i]));
+      }
+      break;
+    }
+  }
+
+  LoggerD("entry after save:");
+  ExifUtil::printExifEntryInfo(entry, exif_data);
+}
+
+void ExifTagSaver::saveGpsLocationToExif(const ExifGPSLocation& gps_info,
+                                         ExifData* exif_data) {
+  LoggerD("Entered");
+  if (gps_info.isSet(EXIF_GPS_LOCATION_ATTRIBUTE_LATITUDE)) {
+    auto latitude = gps_info.getLatitude();
+    LoggerD("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";
+    LoggerD("Saving latitude ref: %s", lat_ref.c_str());
+    saveToExif(lat_ref, static_cast<ExifTag>(EXIF_TAG_GPS_LATITUDE_REF),
+        exif_data, EXIF_FORMAT_ASCII, false);
+  }
+
+  if (gps_info.isSet(EXIF_GPS_LOCATION_ATTRIBUTE_LONGITUDE)) {
+    auto longitude = gps_info.getLongitude();
+    LoggerD("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";
+    LoggerD("Saving longitude ref: %s", long_ref.c_str());
+    saveToExif(long_ref, static_cast<ExifTag>(EXIF_TAG_GPS_LONGITUDE_REF),
+        exif_data, EXIF_FORMAT_ASCII, false);
+  }
+}
+
+ExifEntry* ExifTagSaver::prepareEntry(ExifData* exif_data, ExifTag tag) {
+  LoggerD("Entered m_tag:%d", tag);
+
+  ExifEntry* exif_entry = exif_data_get_entry(exif_data, tag);
+  if (!exif_entry) {
+    ExifIfd exif_ifd;
+    common::PlatformResult ret = deduceIfdSection(tag, &exif_ifd);
+    if (!ret) {
+      LoggerE("Couldn't deduce ifd section: %s", ret.message().c_str());
+      return nullptr;
+    }
+
+    ExifFormat exif_format;
+    ret = deduceDataFormat(tag, &exif_format);
+    if (!ret) {
+      LoggerE("Couldn't deduce data format: %s", ret.message().c_str());
+      return nullptr;
+    }
+    exif_entry = createNewTag(exif_data, exif_ifd, exif_format, tag);
+  }
+
+  if (!exif_entry) {
+    LoggerE("Couldn't create new Exif tag");
+    return nullptr;
+  }
+
+  exif_entry_initialize(exif_entry, tag);
+
+  return exif_entry;
+}
+
+ExifEntry* ExifTagSaver::createNewTag(ExifData* exif_data, ExifIfd ifd,
+                                      ExifFormat format, ExifTag tag) {
+  LoggerD("Creating new tag: %d", tag);
+
+  ExifEntry* new_entry = exif_entry_new();
+  if (new_entry == nullptr) {
+    LoggerE("Function exif_entry_new returned nullptr");
+  } else {
+    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;
+}
+
+common::PlatformResult ExifTagSaver::deduceIfdSection(ExifTag tag, ExifIfd* exif_ifd) {
+  LoggerD("Entered");
+  // TODO EXIF_TAG_* and EXIF_TAG_GPS_* are sharing same values,
+  // they shouldn't be used in one switch statement.
+
+  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:
+      *exif_ifd = EXIF_IFD_0;
+      break;
+
+    // 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:
+      *exif_ifd = EXIF_IFD_EXIF;
+      break;
+
+    // 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:
+      *exif_ifd = EXIF_IFD_GPS;
+      break;
+
+    // Tags in other sections
+    default:
+      LoggerE("Unsupported tag: %d", tag);
+      return common::PlatformResult(common::ErrorCode::UNKNOWN_ERR, "Unsupported tag");
+  }
+
+  return common::PlatformResult(common::ErrorCode::NO_ERROR);
+}
+
+common::PlatformResult ExifTagSaver::deduceDataFormat(ExifTag tag, ExifFormat* exif_format) {
+  LoggerD("Entered");
+  // TODO EXIF_TAG_* and EXIF_TAG_GPS_* are sharing same values,
+  // they shouldn't be used in one switch statement.
+
+  switch (static_cast<unsigned int>(tag)) {
+    // Tags with byte type:
+    case EXIF_TAG_GPS_ALTITUDE_REF:
+      *exif_format = EXIF_FORMAT_BYTE;
+      break;
+
+    // Tags with long type:
+    case EXIF_TAG_IMAGE_WIDTH:
+    case EXIF_TAG_IMAGE_LENGTH:
+      *exif_format = EXIF_FORMAT_LONG;
+      break;
+
+    // Tags with short type:
+    case EXIF_TAG_ORIENTATION:
+    case EXIF_TAG_EXPOSURE_PROGRAM:
+    case EXIF_TAG_WHITE_BALANCE:
+    case EXIF_TAG_FLASH:
+      *exif_format = EXIF_FORMAT_SHORT;
+      break;
+
+    // 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:
+      *exif_format = EXIF_FORMAT_ASCII;
+      break;
+
+    // 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:
+      *exif_format = EXIF_FORMAT_RATIONAL;
+      break;
+
+    // Tags with undefined type:
+    case EXIF_TAG_USER_COMMENT:
+    case EXIF_TAG_GPS_PROCESSING_METHOD:
+      *exif_format = EXIF_FORMAT_UNDEFINED;
+      break;
+
+    // Unsupported tags:
+    default:
+      LoggerE("Unsupported tag: %d", tag);
+      return common::PlatformResult(common::ErrorCode::UNKNOWN_ERR, "Unsupported tag");
+  }
+
+  return common::PlatformResult(common::ErrorCode::NO_ERROR);
+}
+
+}  // namespace exif
+}  // namespace extension
diff --git a/webWidgetTCT_device/src/exif/exif_tag_saver.h b/webWidgetTCT_device/src/exif/exif_tag_saver.h
new file mode 100755 (executable)
index 0000000..1120fd5
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2015 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 EXIF_EXIF_TAG_SAVER_H_
+#define EXIF_EXIF_TAG_SAVER_H_
+
+#include <libexif/exif-data.h>
+
+#include <string>
+#include <vector>
+
+#include "common/platform_result.h"
+#include "exif_gps_location.h"
+
+namespace extension {
+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, ExifFormat format = EXIF_FORMAT_ASCII,
+      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);
+
+ private:
+  static ExifEntry* prepareEntry(ExifData* exif_data, ExifTag tag);
+  static common::PlatformResult deduceIfdSection(ExifTag tag, ExifIfd* exif_ifd);
+  static common::PlatformResult deduceDataFormat(ExifTag tag, ExifFormat* exif_format);
+  static ExifEntry* createNewTag(ExifData* exif_data, ExifIfd ifd,
+      ExifFormat format, ExifTag tag);
+};
+
+}  // namespace exif
+}  // namespace extension
+
+#endif  // EXIF_EXIF_TAG_SAVER_H_
diff --git a/webWidgetTCT_device/src/exif/exif_util.cc b/webWidgetTCT_device/src/exif/exif_util.cc
new file mode 100755 (executable)
index 0000000..6a703d6
--- /dev/null
@@ -0,0 +1,414 @@
+/*
+ * Copyright (c) 2015 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 "exif/exif_util.h"
+
+#include <iomanip>
+#include <sstream>
+
+#include "common/platform_result.h"
+#include "common/logger.h"
+
+namespace extension {
+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://";
+}  // namespace
+
+const std::size_t ExifTypeInfo::ByteSize = 1;
+const std::size_t ExifTypeInfo::ASCIISize = 1;
+const std::size_t ExifTypeInfo::ShortSize = 2;
+const std::size_t ExifTypeInfo::LongSize = 4;
+const std::size_t ExifTypeInfo::RationalSize = 8;
+const std::size_t ExifTypeInfo::UndefinedSize = 1;
+const std::size_t ExifTypeInfo::SLongSize = 4;
+const std::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) {
+  LoggerD("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) {
+  LoggerD("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) {
+  LoggerD("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) {
+  LoggerD("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) {
+  LoggerD("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) {
+  LoggerD("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;
+  }
+}
+
+// Example:
+// in: uri = file:///opt/usr/media/Images/exif.jpg
+// out: path = /opt/usr/media/Images/exif.jpg
+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, "%5d:%5d:%5d %5d:%5d:%5d",
+      &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();
+}
+
+const Rationals ExifUtil::timeTToExifGpsTimeStamp(time_t time) {
+  int year, month, day, hour, min, sec;
+  extractFromTimeT(time, year, month, day, hour, min, sec);
+
+  Rational hourRational = Rational::createFromDouble(static_cast<double>(hour));
+  Rational minRational = Rational::createFromDouble(static_cast<double>(min));
+  Rational secRational = Rational::createFromDouble(static_cast<double>(sec));
+
+  Rationals result;
+  result.push_back(hourRational);
+  result.push_back(minRational);
+  result.push_back(secRational);
+
+  return result;
+}
+
+std::string ExifUtil::timeTToExifGpsDateStamp(time_t time) {
+  int year, month, day, hour, min, sec;
+  extractFromTimeT(time, year, month, day, hour, min, sec);
+
+  LoggerD("year: %d", year);
+  LoggerD("month: %d", month);
+  LoggerD("day: %d", day);
+
+  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;
+
+  LoggerD("SS: %s", ss.str().c_str());
+
+  return ss.str();
+}
+
+size_t  ExifUtil::getSizeOfExifFormatType(ExifFormat format) {
+  std::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:
+      LoggerE("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) {
+    LoggerE("entry is null");
+    return;
+  }
+
+  if (!entry->data) {
+    LoggerE("entry data is null");
+    return;
+  }
+
+  unsigned char* read_buf_ptr = entry->data;
+
+  std::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;
+  }
+
+  LoggerD("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),
+      static_cast<int>(entry->size),
+      static_cast<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_r(&time, &utc);
+
+  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) {
+  struct tm timeinfo = { 0 };
+  time_t tmp_time = 0;
+  tzset();
+  localtime_r(&tmp_time, &timeinfo);
+
+  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);
+}
+
+}  // namespace exif
+}  // namespace extension
diff --git a/webWidgetTCT_device/src/exif/exif_util.h b/webWidgetTCT_device/src/exif/exif_util.h
new file mode 100755 (executable)
index 0000000..3b35f62
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2015 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 EXIF_EXIF_UTIL_H_
+#define EXIF_EXIF_UTIL_H_
+
+#include <libexif/exif-data.h>
+#include <libexif/exif-entry.h>
+#include <libexif/exif-utils.h>
+#include <string>
+#include <vector>
+
+#include "rational.h"
+
+namespace extension {
+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 std::size_t ByteSize;       // 1 byte
+  static const std::size_t ASCIISize;      // 1 byte (*N)
+  static const std::size_t ShortSize;      // 2 bytes
+  static const std::size_t LongSize;       // 4 bytes
+  static const std::size_t RationalSize;   // 8 bytes
+  static const std::size_t UndefinedSize;  // 1 byte (*N)
+  static const std::size_t SLongSize;      // 4 bytes
+  static const std::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 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 const Rationals timeTToExifGpsTimeStamp(time_t time);
+  static std::string timeTToExifGpsDateStamp(time_t time);
+
+  static std::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);
+};
+
+}  // namespace exif
+}  // namespace extension
+
+#endif  // EXIF_EXIF_UTIL_H_
diff --git a/webWidgetTCT_device/src/exif/get_exif_info.cc b/webWidgetTCT_device/src/exif/get_exif_info.cc
new file mode 100755 (executable)
index 0000000..d710e40
--- /dev/null
@@ -0,0 +1,532 @@
+/*
+ * Copyright (c) 2015 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 "exif/get_exif_info.h"
+
+#include <math.h>
+#include <memory>
+#include <string>
+#include <utility>
+
+#include "common/platform_result.h"
+#include "common/logger.h"
+
+#include "exif/exif_util.h"
+
+namespace extension {
+namespace exif {
+
+using common::PlatformResult;
+using common::ErrorCode;
+
+struct ExifDataHolder {
+  ExifData* exif_data;
+  JsonObject* result_obj_ptr;
+};
+
+Rational GetRationalFromEntry(ExifEntry *entry, ExifData* exif_data) {
+  LoggerD("Entered");
+  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 GetRationalsFromEntry(ExifEntry* entry, ExifData* exif_data,
+                           unsigned long required_count,
+                           Rationals& out_rationals) {
+  LoggerD("Entered");
+  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;
+  }
+}
+
+bool GetGCSPositionFromEntry(ExifEntry* entry, ExifData* exif_data,
+                             GCSPosition& out_pos) {
+  // RATIONAL - 3
+  LoggerD("Entered");
+  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 DecomposeExifUndefined(ExifEntry* entry, std::string& type, std::string& value) {
+  LoggerD("Entered");
+  if (!entry || !entry->data) {
+    LoggerW("exif entry is NULL/empty");
+    return false;
+  }
+
+  if (entry->size < EXIF_UNDEFINED_TYPE_LENGTH) {
+    LoggerW("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;
+}
+
+PlatformResult GetExifInfo::ProcessEntry(ExifEntry* entry,
+                               ExifData* exif_data,
+                               JsonObject* result_obj) {
+  LoggerD("Entered");
+  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 PlatformResult(ErrorCode::NO_ERROR);
+  }
+
+  std::pair<std::string, JsonValue> pair;
+  switch (static_cast<unsigned int>(entry->tag)) {
+    case EXIF_TAG_IMAGE_WIDTH: {
+      exif_entry_get_value(entry, buf, sizeof(buf));
+      LoggerD("Setting ExifInformation width to: [%s]", buf);
+      pair = std::make_pair("width", JsonValue(std::string(buf)));
+      result_obj->insert(pair);
+      break;
+    }
+    case EXIF_TAG_IMAGE_LENGTH: {
+      exif_entry_get_value(entry, buf, sizeof(buf));
+      LoggerD("Setting ExifInformation height to: [%s]", buf);
+      pair = std::make_pair("height", JsonValue(std::string(buf)));
+      result_obj->insert(pair);
+      break;
+    }
+    case EXIF_TAG_MAKE: {
+      exif_entry_get_value(entry, buf, sizeof(buf));
+      LoggerD("Setting ExifInformation maker to: [%s]", buf);
+      pair = std::make_pair("deviceMaker", JsonValue(std::string(buf)));
+      result_obj->insert(pair);
+      break;
+    }
+    case EXIF_TAG_MODEL: {
+      exif_entry_get_value(entry, buf, sizeof(buf));
+      LoggerD("Setting ExifInformation model to: [%s]", buf);
+      pair = std::make_pair("deviceModel", JsonValue(std::string(buf)));
+      result_obj->insert(pair);
+      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));
+      LoggerD("Setting ExifInformation time original to: [%s] time_t:%d", buf,
+          static_cast<int>(time));
+      // convert time_t (number of seconds) to string
+      pair = std::make_pair("originalTimeSeconds",
+          JsonValue(static_cast<double>(time)));
+      result_obj->insert(pair);
+      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));
+
+      const std::string& orientation = ExifUtil::orientationToString(
+          static_cast<ImageOrientation>(orient));
+      pair = std::make_pair("orientation", JsonValue(orientation));
+      result_obj->insert(pair);
+
+      if (orient < EXIF_ORIENTATION_NORMAL || orient >= EXIF_ORIENTATION_NOT_VALID) {
+        LoggerW("Couldn't set ExifInformation - orientation is not valid: %d (%s)",
+            orient, buf);
+      } else {
+        LoggerD("Setting ExifInformation orientation to: %d [%s]", orient, buf);
+      }
+      break;
+    }
+    case EXIF_TAG_FNUMBER:
+    {
+      // RATIONAL - 1
+      Rational fnumber = GetRationalFromEntry(entry, exif_data);
+      if (fnumber.isValid()) {
+        LoggerD("Setting ExifInformation fnumber to: %f (%s)", fnumber.toDouble(),
+          fnumber.toString().c_str());
+        pair = std::make_pair("fNumber", JsonValue(fnumber.toDouble()));
+        result_obj->insert(pair);
+      } else {
+        LoggerW("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 std::size_t size_per_member =
+            ExifUtil::getSizeOfExifFormatType(entry->format);
+
+        JsonArray array = JsonArray();
+        for (unsigned long i = 0; i < entry->components; ++i) {
+          ExifShort iso_rating = exif_get_short(read_ptr, order);
+          array.push_back(JsonValue(std::to_string(iso_rating)));
+
+          LoggerD("Appending ExifInformation speed ratings with: %d",
+              static_cast<int>(iso_rating));
+
+          read_ptr += size_per_member;
+        }
+        pair = std::make_pair("isoSpeedRatings", JsonValue(array));
+        result_obj->insert(pair);
+      } else {
+        LoggerE("iso speed ratings: format or components count is invalid!");
+        return PlatformResult(ErrorCode::TYPE_MISMATCH_ERR,
+            "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()) {
+          LoggerD("Setting ExifInformation exposure time to: %s (%s)",
+              exp_time.toString().c_str(),
+              exp_time.toExposureTimeString().c_str());
+          pair = std::make_pair("exposureTime", JsonValue(exp_time.toDouble()));
+          result_obj->insert(pair);
+        } else {
+          LoggerD("Couldn't set ExifInformation - exposure time is not valid: %s",
+              exp_time.toString().c_str());
+        }
+      } else {
+        LoggerE("exposure time: format or components count is invalid!");
+        return PlatformResult(ErrorCode::TYPE_MISMATCH_ERR,
+            "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) {
+        LoggerW("ExposureProgram: %d (%s) is not valid!", exp_program, buf);
+      } else {
+        LoggerD("Setting ExifInformation exposure program to: %d [%s]",
+            exp_program, buf);
+        std::string exp_program_string =
+            ExifUtil::exposureProgramToString(static_cast<ExposureProgram>(exp_program));
+        pair = std::make_pair("exposureProgram", JsonValue(exp_program_string));
+        result_obj->insert(pair);
+      }
+      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);
+
+      LoggerD("Setting ExifInformation flash to: [%s] flash=%d", buf, flash);
+      pair = std::make_pair("flash", JsonValue((flash != 0) ? "true" : "false"));
+      result_obj->insert(pair);
+      break;
+    }
+    case EXIF_TAG_FOCAL_LENGTH: {
+      // RATIONAL - 1
+      Rational flength = GetRationalFromEntry(entry, exif_data);
+      if (flength.isValid()) {
+        LoggerD("Setting ExifInformation focal length to: %f (%s)",
+            flength.toDouble(), flength.toString().c_str());
+        pair = std::make_pair("focalLength", JsonValue(flength.toDouble()));
+        result_obj->insert(pair);
+      } else {
+        LoggerW("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));
+      LoggerD("Setting ExifInformation white balance to: [%s]", buf);
+      pair = std::make_pair("whiteBalanceValue",
+          JsonValue(static_cast<double>(entry->data[0])));
+      result_obj->insert(pair);
+      break;
+    }
+    case EXIF_TAG_GPS_LONGITUDE: {
+      // RATIONAL - 3
+      GCSPosition longitude;
+      if (GetGCSPositionFromEntry(entry, exif_data, longitude)) {
+        pair = std::make_pair("gpsLongitudeDegrees", JsonValue(longitude.degrees.toDouble()));
+        result_obj->insert(pair);
+        pair = std::make_pair("gpsLongitudeMinutes", JsonValue(longitude.minutes.toDouble()));
+        result_obj->insert(pair);
+        pair = std::make_pair("gpsLongitudeSeconds", JsonValue(longitude.seconds.toDouble()));
+        result_obj->insert(pair);
+        LoggerD("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 {
+        LoggerW("Couldn't set longitude pos - data is not valid.");
+      }
+      break;
+    }
+    case EXIF_TAG_GPS_LONGITUDE_REF: {
+      // ASCII - 2
+      if (entry->size < 1) {
+        LoggerW("Longitude ref entry do not contain enough data!");
+        break;
+      }
+
+      const char ref = static_cast<char>(entry->data[0]);
+      if ('E' == ref || 'e' == ref) {      // East
+        pair = std::make_pair("gpsLongitudeRef", JsonValue("EAST"));
+        result_obj->insert(pair);
+        LoggerD("Setting ExifInformation gps longitude REF to: EAST");
+      } else if ('W' == ref || 'w' == ref) {   // West
+        pair = std::make_pair("gpsLongitudeRef", JsonValue("WEST"));
+        result_obj->insert(pair);
+        LoggerD("Setting ExifInformation gps longitude REF to: WEST");
+      } else {
+        LoggerW("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));
+      LoggerD("Setting ExifInformation latitude to: [%s], tag->%s",
+          buf, exif_tag_get_name(entry->tag) );
+
+      GCSPosition latitude;
+      if (GetGCSPositionFromEntry(entry, exif_data, latitude)) {
+        pair = std::make_pair("gpsLatitudeDegrees", JsonValue(latitude.degrees.toDouble()));
+        result_obj->insert(pair);
+        pair = std::make_pair("gpsLatitudeMinutes", JsonValue(latitude.minutes.toDouble()));
+        result_obj->insert(pair);
+        pair = std::make_pair("gpsLatitudeSeconds", JsonValue(latitude.seconds.toDouble()));
+        result_obj->insert(pair);
+
+        LoggerD("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 {
+        LoggerW("Couldn't set latitude pos - data is not valid!");
+      }
+      break;
+    }
+    case EXIF_TAG_GPS_LATITUDE_REF: {
+      // ASCII - 2
+      if (entry->size < 1) {
+        LoggerW("Latitude ref entry do not contain enough data!");
+        break;
+      }
+
+      const char ref = static_cast<char>(entry->data[0]);
+      if ('N' == ref || 'n' == ref) {      // North
+        pair = std::make_pair("gpsLatitudeRef", JsonValue("NORTH"));
+        result_obj->insert(pair);
+        LoggerD("Setting ExifInformation gps latitude REF to: NORTH");
+      } else if ('S' == ref || 's' == ref) {   // South
+        pair = std::make_pair("gpsLatitudeRef", JsonValue("SOUTH"));
+        result_obj->insert(pair);
+        LoggerD("Setting ExifInformation gps latitude REF to: SOUTH");
+      } else {
+        LoggerW("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()) {
+        LoggerD("Setting ExifInformation gps altitude to: %f (%s)",
+            gps_altitude.toDouble(), gps_altitude.toString().c_str());
+        pair = std::make_pair("gpsAltitude", JsonValue(gps_altitude.toDouble()));
+        result_obj->insert(pair);
+      } else {
+        LoggerW("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]);
+      pair = std::make_pair("gpsAltitudeRef", JsonValue(static_cast<double>(altitude_ref)));
+      result_obj->insert(pair);
+      LoggerD("Setting ExifInformation gps altitude ref to: %d (%s)",
+            static_cast<int>(altitude_ref),
+            (altitude_ref > 0) ? "below sea level" : "above sea level");
+
+      break;
+    }
+    case EXIF_TAG_GPS_PROCESSING_METHOD: {
+      // UNDEFINED - Any
+      std::string type, value;
+      if (DecomposeExifUndefined(entry, type, value)) {
+        LoggerD("Extracted GPSProcessingMethod: [%s], len:%d, type:%s",
+            value.c_str(), value.length(), type.c_str());
+        pair = std::make_pair("gpsProcessingMethod", JsonValue(value));
+        result_obj->insert(pair);
+      } else {
+        LoggerW("GPSProcessingMethod tag contains invalid values!");
+      }
+      break;
+    }
+    case EXIF_TAG_GPS_DATE_STAMP: {
+      // ASCII - 11
+      pair = std::make_pair("gpsExifDate", JsonValue(std::string(buf)));
+      result_obj->insert(pair);
+      LoggerD("Setting ExifInformation gps date stamp to %s", std::string(buf).c_str());
+      break;
+    }
+    case EXIF_TAG_GPS_TIME_STAMP: {
+      // Rational - 3
+      LoggerD("Setting ExifInformation gps time stamp to: [%s]", buf);
+
+      Rationals time;
+      if (GetRationalsFromEntry(entry, exif_data, 3, time)) {
+        pair = std::make_pair("gpsExifTimeHours", JsonValue(time[0].toDouble()));
+        result_obj->insert(pair);
+        pair = std::make_pair("gpsExifTimeMinutes", JsonValue(time[1].toDouble()));
+        result_obj->insert(pair);
+        pair = std::make_pair("gpsExifTimeSeconds", JsonValue(time[2].toDouble()));
+        result_obj->insert(pair);
+      }
+      break;
+    }
+    case EXIF_TAG_USER_COMMENT: {
+      // UNDEFINED - Any
+      std::string type, value;
+      if (DecomposeExifUndefined(entry, type, value)) {
+        LoggerD("Extracted UserComment: [%s], len:%d, type:%s",
+            value.c_str(), value.length(), type.c_str());
+
+        pair = std::make_pair("userComment", JsonValue(value));
+        result_obj->insert(pair);
+      } else {
+        LoggerW("UserComment tag contains invalid values!");
+      }
+      break;
+    }
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+void GetExifInfo::ContentForeachFunctionProxy(ExifEntry *entry, void *user_data) {
+  LoggerD("Entered");
+  ExifDataHolder* holder = static_cast<ExifDataHolder*>(user_data);
+  if (!holder) {
+    LoggerE("holder is NULL");
+    return;
+  }
+
+  if (!holder->exif_data) {
+    LoggerE("exif_data is NULL!");
+    return;
+  }
+
+  JsonObject* result_obj_ptr = holder->result_obj_ptr;
+
+  PlatformResult status = ProcessEntry(entry, holder->exif_data, result_obj_ptr);
+  if (!status) {
+    LoggerE("Unsupported error while processing Exif entry.");
+  }
+}
+
+void GetExifInfo::DataForeachFunction(ExifContent *content, void *user_data) {
+  exif_content_foreach_entry(content, ContentForeachFunctionProxy, user_data);
+}
+
+PlatformResult GetExifInfo::LoadFromURI(const std::string& uri,
+                                        JsonValue* result) {
+  LoggerD("Entered");
+  // TODO(r.galka) it can be done on JS side
+  const std::string& file_path = ExifUtil::convertUriToPath(uri);
+  ExifData* ed = exif_data_new_from_file(file_path.c_str());
+  if (!ed) {
+    LoggerE("Error reading exif from file %s", file_path.c_str());
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+            "Error reading exif from file");
+  }
+
+  LoggerD("loadFromURI_into_json exif_data_foreach_content START");
+
+  JsonObject& result_obj = result->get<JsonObject>();
+
+  ExifDataHolder holder;
+  holder.exif_data = ed;
+  holder.result_obj_ptr = &result_obj;
+  exif_data_foreach_content(ed, DataForeachFunction,
+      static_cast<void *>(&holder));
+
+  LoggerD("loadFromURI_into_json exif_data_foreach_content END");
+
+  exif_data_unref(ed);
+
+  // uri is not taken from jgp Exif, so we add it here
+  holder.result_obj_ptr->insert(std::make_pair("uri", JsonValue(uri)));
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+}  // namespace exif
+}  // namespace extension
diff --git a/webWidgetTCT_device/src/exif/get_exif_info.h b/webWidgetTCT_device/src/exif/get_exif_info.h
new file mode 100755 (executable)
index 0000000..c14273a
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2015 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 WEBAPI_PLUGINS_EXIF_GET_EXIF_INFO_H_
+#define WEBAPI_PLUGINS_EXIF_GET_EXIF_INFO_H_
+
+#include <libexif/exif-loader.h>
+#include <string>
+
+#include "common/extension.h"
+#include "common/picojson.h"
+#include "common/platform_result.h"
+
+#include "exif/exif_gps_location.h"
+
+typedef picojson::value JsonValue;
+typedef picojson::object JsonObject;
+typedef picojson::array JsonArray;
+typedef std::string JsonString;
+
+namespace extension {
+namespace exif {
+
+extern const std::size_t EXIF_UNDEFINED_TYPE_LENGTH;
+
+class GetExifInfo {
+ public:
+  static common::PlatformResult ProcessEntry(ExifEntry* entry,
+                                             ExifData* exif_data,
+                                             JsonObject* result_obj);
+
+  static common::PlatformResult LoadFromURI(const std::string& uri,
+                                            JsonValue* result);
+
+ private:
+  GetExifInfo() { }  // private ctor - class can not be created
+
+  static void ContentForeachFunctionProxy(ExifEntry* entry, void* user_data);
+  static void DataForeachFunction(ExifContent* content, void* user_data);
+};
+
+typedef std::shared_ptr<GetExifInfo> GetExifInfoPtr;
+
+}  // namespace exif
+}  // namespace extension
+
+#endif  // WEBAPI_PLUGINS_EXIF_GET_EXIF_INFO_H__
diff --git a/webWidgetTCT_device/src/exif/jpeg_file.cc b/webWidgetTCT_device/src/exif/jpeg_file.cc
new file mode 100755 (executable)
index 0000000..2076c76
--- /dev/null
@@ -0,0 +1,751 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+//
+// For details of JPEG file format see:
+// http://www.media.mit.edu/pia/Research/deepview/exif.html
+
+#include "exif/jpeg_file.h"
+
+#include <iomanip>
+#include <limits>
+
+#include "common/assert.h"
+#include "common/logger.h"
+#include "common/platform_result.h"
+
+namespace extension {
+namespace exif {
+
+using common::PlatformResult;
+using common::ErrorCode;
+
+/**
+ * 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;
+  }
+}
+
+PlatformResult JpegFile::loadFile(const std::string& path, JpegFilePtr* jpg_ptr) {
+  LoggerD("Entered");
+  JpegFile* new_jpg = new (std::nothrow) JpegFile();
+  if (!new_jpg) {
+    LoggerE("Couldn't allocate Jpegfile!");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Memory allocation failed");
+  }
+
+  jpg_ptr->reset(new_jpg);
+
+  PlatformResult result = (*jpg_ptr)->load(path);
+  if (!result) {
+    return result;
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult JpegFile::load(const std::string& path) {
+  LoggerD("Entered file: %s", path.c_str());
+
+  m_source_file_path = path;
+
+  m_in_file = fopen(path.c_str(), "rb");
+  if (!m_in_file) {
+    LoggerE("Couldn't open Jpeg file: [%s]", path.c_str());
+    return PlatformResult(ErrorCode::NOT_FOUND_ERR, "Could not open JPEG file");
+  }
+
+  fseek(m_in_file, 0, SEEK_END);
+
+  long ftell_val = ftell(m_in_file);
+  if (0 > ftell_val) {
+    LoggerE("Input file [%s] access error! [%d]", path.c_str(), errno);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "JPEG file is invalid");
+  }
+
+  const std::size_t in_file_size = static_cast<size_t>(ftell_val);
+  fseek(m_in_file, 0, SEEK_SET);
+  LoggerD("JPEG file: [%s] size:%d", path.c_str(), in_file_size);
+  if (0 == in_file_size) {
+    LoggerE("Input file [%s] is empty!", path.c_str());
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "JPEG file is invalid");
+  }
+
+  m_in_data = new (std::nothrow) unsigned char[in_file_size];
+  if (!m_in_data) {
+    LoggerE("Couldn't allocate buffer with size: %d", in_file_size);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Memory allocation failed");
+  }
+
+  m_in_data_size = in_file_size;
+
+  const std::size_t read_bytes = fread(m_in_data, 1, m_in_data_size, m_in_file);
+  if (read_bytes != m_in_data_size) {
+    LoggerE("Couldn't read all: %d bytes. Read only: %d bytes!", m_in_data_size,
+        read_bytes);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Could not read JPEG file");
+  }
+
+  if (fclose(m_in_file) == EOF) {
+    LoggerE("Couldn't close input file: %s!", path.c_str());
+  }
+  m_in_file = NULL;
+
+  return generateListOfSections();
+}
+
+std::string JpegFile::getPartOfFile(const std::size_t offset,
+                                    const std::size_t num_bytes_before,
+                                    const std::size_t num_bytes_after) {
+  LoggerD("Entered");
+  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();
+}
+
+
+common::PlatformResult JpegFile::generateListOfSections() {
+  LoggerD("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) {
+    LoggerD("offset:%d | Starting iteration: %d", offset, iterration);
+    const std::size_t search_len = 10;
+    std::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) {
+      LoggerE("offset:%d | Couldn't find marker! RAW DATA:{%s}", offset,
+          getPartOfFile(offset, 0, 10).c_str());
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, "JPEG file is invalid");
+    }
+
+    const std::size_t section_offset = offset + search_offset - 1;
+    unsigned char* section_begin = m_in_data + section_offset;
+
+    offset = section_offset;  // Move to section begin
+    LoggerD("offset:%d | Moved to section begin", offset);
+
+    if (!isJpegMarker(section_begin[1])) {
+      LoggerE("offset:%d | Is not valid marker: 0x%x RAW DATA:{%s}", offset,
+          section_begin[1], getPartOfFile(section_offset, 0, 4).c_str());
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, "JPEG file is invalid");
+    }
+
+    const JpegMarker cur_marker = castToJpegMarker(section_begin[1]);
+    LoggerD("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) {
+        LoggerE("Couldn't allocate JpegFileSection");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "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) {
+      LoggerD("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) {
+        LoggerW("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.
+
+      // Include data
+      // size 2 bytes
+      const long total_section_len = readUShortBE(section_begin + 2);
+
+      // Exclude data
+      // size 2 bytes
+      const long section_data_len = total_section_len - 2;
+
+      LoggerD("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) {
+        LoggerE("offset:%d tag:0x%x | Error: total_section_len is: %d < 0",
+            offset, cur_marker, total_section_len);
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "JPEG file is invalid");
+      }
+
+      if (section_offset + 2 + total_section_len > m_in_data_size) {
+        LoggerE("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);
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "JPEG file is invalid");
+      }
+
+      if (JPEG_MARKER_APP1 == cur_marker) {
+        // TODO(Unknown): 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);
+
+        LoggerD("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) {
+          LoggerW("offset:%d tag:0x%x | Couldn't load Exif!",
+              offset, cur_marker);
+        }
+      }
+
+      // This just saves pointer not copying data
+      // 2 bytes marker + 2 bytes data size
+      section->data_ptr = section_begin + 2 + 2;
+      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 std::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)
+        std::size_t image_size = m_in_data_size - image_data_offset - 2;
+        LoggerW("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;
+
+        std::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) {
+          LoggerE("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 {
+          LoggerD("EOI tag found at offset: %d from SOS data", eoi_tag_index);
+
+          if (eoi_tag_index != image_size) {
+            LoggerW("Estimated image size:%d doesn't match EOI tag index:%d"
+                " delta:%d", image_size, eoi_tag_index,
+                image_size - eoi_tag_index);
+
+            LoggerW("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;
+            LoggerW("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;
+        LoggerD("offset:%d tag:0x%x | SOS Offset moved to next marker", offset,
+            cur_marker);
+      } else {
+        offset += section_data_len;
+        LoggerD("offset:%d tag:0x%x | Offset moved to next marker",
+            offset, cur_marker);
+      }
+    }
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+bool JpegFile::searchForTagInBuffer(const unsigned char* buffer_start,
+    const unsigned char* buffer_end,
+    const JpegMarker marker,
+    std::size_t& out_index) {
+  LoggerD("Entered start:%p end:%p marker:0x%x",
+      buffer_start, buffer_end, marker);
+
+  if (!buffer_start) {
+    LoggerE("buffer_start is NULL");
+    return false;
+  }
+
+  if (!buffer_end) {
+    LoggerE("buffer_end is NULL");
+    return false;
+  }
+
+  if (buffer_end <= buffer_start) {
+    LoggerE("buffer_end: %p <= buffer_start: %p", buffer_end, buffer_start);
+    return false;
+  }
+
+  LoggerD("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;
+}
+
+PlatformResult JpegFile::setNewExifData(ExifData* new_exif_data) {
+  LoggerD("Entered");
+  AssertMsg(new_exif_data, "Trying to set NULL exif_data!");
+
+  JpegFileSectionPtr exif = getExifSection();
+  if (!exif) {
+    LoggerW("Could't find Exif section - creating new one");
+    {
+      JpegFileSection* new_sec = new (std::nothrow) JpegFileSection();
+      if (!new_sec) {
+        LoggerE("Couldn't allocate JpegFileSection");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                "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) {
+        LoggerW("First section is not SOI - Start Of Image!");
+      } else {
+        soi_is_present = true;
+      }
+    }
+
+    if (!soi_is_present) {
+      LoggerW("SOI section is missing");
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, "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;
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+ExifData* JpegFile::getExifData() {
+  LoggerD("Entered");
+  JpegFileSectionPtr exif = getExifSection();
+  if (!exif) {
+    return NULL;
+  }
+
+  exif_data_ref(exif->exif_data);
+  return exif->exif_data;
+}
+
+PlatformResult JpegFile::saveToFile(const std::string& out_path) {
+  LoggerD("Entered out_path:%s", out_path.c_str());
+  PlatformResult status = saveToFilePriv(out_path);
+
+  if (status)
+    return status;
+
+  LoggerE("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) {
+    LoggerD("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) {
+      LoggerE("Couldn't open output file:"
+          " [%s] - JPEG file will not be restored!", out_path.c_str());
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+          "Couldn't open output file");
+    }
+
+    std::size_t bytes_wrote = fwrite(m_in_data, 1, m_in_data_size, outf);
+    if (bytes_wrote != m_in_data_size) {
+      fclose(outf);
+
+      LoggerE("Couldn't restore whole JPEG! "
+          "Only %d of %d bytes have been wrote!",
+          bytes_wrote, m_in_data_size);
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+          "Couldn't restore whole file");
+    }
+    if (EOF == fclose(outf)) {
+      LoggerE("Couldn't close restore output file: [%s]", out_path.c_str());
+    }
+
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+
+  return status;
+}
+
+PlatformResult JpegFile::saveToFilePriv(const std::string& out_path) {
+  LoggerD("Entered out_path:%s", out_path.c_str());
+
+  m_out_file = fopen(out_path.c_str(), "wb");
+  if (!m_out_file) {
+    LoggerE("Couldn't open output file: %s", out_path.c_str());
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Could not write JPEG file");
+  }
+
+  unsigned char tmp_buf[128];
+  std::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;
+
+    LoggerD("offset:%d | Section: %d marker 0x%x",
+        offset, section_index, cur_marker);
+
+    std::size_t bytes_to_write = 0;
+    std::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 ( cur_marker == 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) {
+          LoggerE("Couldn't generate RAW Exif data!");
+          return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                  "Could not save Exif in JPEG file");
+        }
+
+        LoggerD("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) {
+          LoggerE("exif_output_size:%d is greater then maximum JPEG section"
+              "data block size: %d", exif_output_size,
+              MAX_AVAILABLE_JPEG_SECTION_DATA_SIZE);
+          return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                  "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;
+    }
+
+    LoggerD("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) {
+      LoggerE("Couldn't wrote %d bytes! Only %d bytes wrote", bytes_to_write,
+          bytes_wrote);
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+              "Could not write JPEG file");
+    }
+
+    if (write_section_data && cur->size > 0) {
+      LoggerD("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) {
+        LoggerE("Couldn't wrote %d bytes! Only %d bytes wrote", bytes_to_write,
+            bytes_wrote);
+        return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                "Could not write JPEG file");
+      }
+    }
+
+    if (write_exif_data && exif_output_data && exif_output_size > 0) {
+      LoggerD("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) {
+        LoggerE("Couldn't wrote %d bytes! Only %d bytes wrote", bytes_to_write,
+            bytes_wrote);
+        return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                "Could not write JPEG file");
+      }
+    }
+
+    if (JPEG_MARKER_SOS == cur_marker) {
+      LoggerD("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) {
+        LoggerE("Couldn't wrote %d bytes! Only %d bytes wrote", bytes_to_write,
+            bytes_wrote);
+        return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                "Could not write JPEG file");
+      }
+    }
+  }
+
+  if (m_padding_data && m_padding_data_size > 0) {
+    LoggerD("Padding data exists and contains:%d bytes saving to JPEG file");
+    const std::size_t bytes_wrote = fwrite(m_image_data, 1, m_padding_data_size,
+        m_out_file);
+
+    if (bytes_wrote != m_padding_data_size) {
+      LoggerE("Couldn't wrote %d bytes! Only %d bytes wrote",
+          m_padding_data_size, bytes_wrote);
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+              "Could not write JPEG file");
+    }
+  }
+
+  if (fclose(m_out_file) == EOF) {
+    LoggerE("Couldn't close output file: %s", out_path.c_str());
+  }
+
+  m_out_file = NULL;
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+JpegFileSectionPtr JpegFile::getExifSection() {
+  LoggerD("Entered");
+  std::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) {
+        LoggerW("Warning: found APP1 section but exif_data is NULL"
+            " (Not Exif?)");
+        continue;
+      }
+
+      ++num_exif_sections;
+      if (!first_exif_section) {
+        first_exif_section = cur;
+      } else {
+        LoggerW("Warning: found %d APP1/Exif sections -"
+            " only first is currently supported!");
+      }
+    }
+  }
+
+  return first_exif_section;
+}
+
+}  // namespace exif
+}  // namespace extension
diff --git a/webWidgetTCT_device/src/exif/jpeg_file.h b/webWidgetTCT_device/src/exif/jpeg_file.h
new file mode 100755 (executable)
index 0000000..49554c1
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2015 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 EXIF_EXIF_JPEG_FILE_H_
+#define EXIF_EXIF_JPEG_FILE_H_
+
+#include <libexif/exif-data.h>
+#include <libexif/exif-entry.h>
+#include <libexif/exif-utils.h>
+
+#include <cstdio>
+#include <memory>
+#include <map>
+#include <string>
+#include <vector>
+
+#include "common/platform_result.h"
+
+namespace extension {
+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 common::PlatformResult loadFile(const std::string& path,
+                                         JpegFilePtr* jpg_ptr);
+  ~JpegFile();
+
+  common::PlatformResult 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();
+
+  common::PlatformResult saveToFile(const std::string& out_path);
+
+ private:
+  JpegFile();
+  //not copyable, not assignable
+  JpegFile(JpegFile const&) = delete;
+  JpegFile& operator=(JpegFile const&) = delete;
+
+  common::PlatformResult load(const std::string &path);
+
+  common::PlatformResult generateListOfSections();
+
+  std::string getPartOfFile(const std::size_t offset,
+                            const std::size_t num_bytes_before = 10,
+                            const std::size_t num_bytes_after = 10);
+
+  JpegFileSectionPtr getExifSection();
+
+  common::PlatformResult saveToFilePriv(const std::string &out_path);
+
+  /**
+   * Search for first occurrence 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,
+      std::size_t& out_index);
+
+  std::string m_source_file_path;
+
+  unsigned char* m_in_data;
+  std::size_t m_in_data_size;
+
+  unsigned char* m_image_data;
+  std::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;
+  std::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 extension
+
+#endif  // EXIF_EXIF_JPEG_FILE_H_
diff --git a/webWidgetTCT_device/src/exif/rational.cc b/webWidgetTCT_device/src/exif/rational.cc
new file mode 100755 (executable)
index 0000000..3aaaf91
--- /dev/null
@@ -0,0 +1,262 @@
+/*
+ * Copyright (c) 2015 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 "exif/rational.h"
+
+#include <cmath>
+#include <sstream>
+
+#include "common/logger.h"
+
+#include "exif/exif_util.h"
+
+namespace extension {
+namespace exif {
+
+namespace {
+const double DOUBLE_ERROR_REPRESENTATION = static_cast<double>(0x7FFFFFFF);
+}  // 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) {
+  LoggerD("Entered value:%f precision:%d", value, precision);
+  if (value < 0.0) {
+    LoggerW("Trying to create negative Rational: %f!", value);
+    return Rational();
+  }
+
+  if (value < 0.000000001) {
+    LoggerD("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 daemon 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 - (static_cast<double>(m[0][0]) / static_cast<double>(m[1][0]));
+  const long numerator0 = m[0][0];
+  const long denominator0 = m[1][0];
+
+  LoggerD("%ld/%ld, error = %e\n", numerator0, denominator0, error0);
+
+  /* now try other possibility */
+  ai = static_cast<long>(static_cast<double>(precision - m[1][1]) / static_cast<double>(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]));
+  LoggerD("%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;
+  }
+
+  LoggerD("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 static_cast<double>(nominator) / static_cast<double>(denominator);
+}
+
+Rational Rational::createFromExposureTimeString(const std::string& exp_time) {
+  LoggerD("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;
+  }
+
+  LoggerD("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(), "%5ld/%5ld", &nominator, &denominator) != 2) {
+      LoggerD("Failed to parse nominator/denominator string: [%s]",
+          fraction_part.c_str());
+      return Rational::createInvalid();
+    }
+  }
+
+  nominator += denominator * integer_value;
+  LoggerD("%d/%d -> %f",
+      nominator, denominator, static_cast<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 {
+  LoggerD("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;
+}
+
+}  // namespace exif
+}  // namespace extension
diff --git a/webWidgetTCT_device/src/exif/rational.h b/webWidgetTCT_device/src/exif/rational.h
new file mode 100755 (executable)
index 0000000..a88c51d
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2015 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 EXIF_EXIF_RATIONAL_H_
+#define EXIF_EXIF_RATIONAL_H_
+
+#include <libexif/exif-utils.h>
+#include <libexif/exif-entry.h>
+#include <libexif/exif-data.h>
+
+#include <string>
+#include <vector>
+#include <memory>
+
+namespace extension {
+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);
+  explicit 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;
+};
+
+}  // namespace exif
+}  // namespace extension
+
+#endif  // EXIF_EXIF_RATIONAL_H_
diff --git a/webWidgetTCT_device/src/filesystem/filesystem.gyp b/webWidgetTCT_device/src/filesystem/filesystem.gyp
new file mode 100755 (executable)
index 0000000..0ab9152
--- /dev/null
@@ -0,0 +1,44 @@
+{
+  'includes':[
+    '../common/common.gypi',
+  ],
+  'targets': [
+    {
+      'target_name': 'tizen_filesystem',
+      'type': 'loadable_module',
+      'variables': {
+        'packages': [
+          'icu-i18n',
+          'storage',
+        ],
+      },
+      'dependencies': [
+        '../common/common.gyp:tizen_common',
+      ],
+      'sources': [
+        'filesystem_api.js',
+        'filesystem_extension.cc',
+        'filesystem_extension.h',
+        'filesystem_file.cc',
+        'filesystem_file.h',
+        'filesystem_instance.cc',
+        'filesystem_instance.h',
+        'filesystem_manager.cc',
+        'filesystem_manager.h',
+        'filesystem_stat.cc',
+        'filesystem_stat.h',
+        'filesystem_utils.cc',
+        'filesystem_utils.h',
+      ],
+      'conditions': [
+        [ 'tizen == 1', {
+            'variables': { 'packages': [
+              'vconf',
+              'capi-appfw-app-manager',
+              'capi-appfw-package-manager',
+            ] },
+        }],
+      ],
+    },
+  ],
+}
diff --git a/webWidgetTCT_device/src/filesystem/filesystem_api.js b/webWidgetTCT_device/src/filesystem/filesystem_api.js
new file mode 100755 (executable)
index 0000000..cd2442c
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+//= require('base64.js');
+//= require('common.js');
+//= require('file_stream.js');
+//= require('file.js');
+//= require('file_system_manager.js');
diff --git a/webWidgetTCT_device/src/filesystem/filesystem_extension.cc b/webWidgetTCT_device/src/filesystem/filesystem_extension.cc
new file mode 100755 (executable)
index 0000000..0116ae6
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2015 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 "filesystem/filesystem_extension.h"
+
+#include "filesystem/filesystem_instance.h"
+
+// This will be generated from filesystem_api.js
+extern const char kSource_filesystem_api[];
+
+common::Extension* CreateExtension() {
+  return new FilesystemExtension;
+}
+
+FilesystemExtension::FilesystemExtension() {
+  SetExtensionName("tizen.filesystem");
+  SetJavaScriptAPI(kSource_filesystem_api);
+}
+
+FilesystemExtension::~FilesystemExtension() {}
+
+common::Instance* FilesystemExtension::CreateInstance() {
+  return new extension::filesystem::FilesystemInstance;
+}
diff --git a/webWidgetTCT_device/src/filesystem/filesystem_extension.h b/webWidgetTCT_device/src/filesystem/filesystem_extension.h
new file mode 100755 (executable)
index 0000000..b3d8bec
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2015 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 FILESYSTEM_FILESYSTEM_EXTENSION_H_
+#define FILESYSTEM_FILESYSTEM_EXTENSION_H_
+
+#include "common/extension.h"
+
+class FilesystemExtension : public common::Extension {
+ public:
+  FilesystemExtension();
+  virtual ~FilesystemExtension();
+
+ private:
+  virtual common::Instance* CreateInstance();
+};
+
+#endif // FILESYSTEM_FILESYSTEM_EXTENSION_H_
diff --git a/webWidgetTCT_device/src/filesystem/filesystem_file.cc b/webWidgetTCT_device/src/filesystem/filesystem_file.cc
new file mode 100755 (executable)
index 0000000..069aefc
--- /dev/null
@@ -0,0 +1,272 @@
+/*
+ * Copyright (c) 2015 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 "filesystem_file.h"
+#include <stdio.h>
+#include <unistd.h>
+#include <common/scope_exit.h>
+#include <common/logger.h>
+
+namespace extension {
+namespace filesystem {
+
+namespace {
+uint8_t characterToNumber(char c) {
+  if (c == '+') {
+    return 62;
+  }
+  if (c == '/') {
+    return 63;
+  }
+  if (c <= '9') {
+    return c + 0x04;
+  }
+  if (c <= 'Z') {
+    return c - 0x41;
+  }
+  if (c <= 'z') {
+    return c - 0x47;
+  }
+  return 0;
+}
+
+char numberToCharacter(uint8_t i) {
+  if (i <= 25) {
+    return 'A' + i;
+  }
+  if (i <= 51) {
+    return 'a' + i - 26;
+  }
+  if (i <= 61) {
+    return '0' + i - 52;
+  }
+  if (i == 62) {
+    return '+';
+  }
+  if (i == 63) {
+    return '/';
+  }
+  return 0;
+}
+
+bool validateCharacter(char c) {
+  if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') ||
+      (c >= 'A' && c <= 'Z') || (c == '=') || (c == '+') || (c == '/')) {
+    return true;
+  }
+  return false;
+}
+}  // namespace
+
+/**
+ * Data is encoded using Base64 encoding.
+ */
+
+bool FilesystemBuffer::DecodeData(const std::string& data) {
+  LoggerD("Enter");
+  if (data.length() % 4) {
+    LoggerE("Buffer has invalid length");
+    return false;
+  }
+
+  for (auto c : data) {
+    if (!validateCharacter(c)) {
+      LoggerE("Buffer has invalid character");
+      return false;
+    }
+  }
+
+  // Validate padding
+  for (size_t i = 0; i + 2 < data.length(); ++i) {
+    if (data[i] == '=') {
+      LoggerE("Unexpected padding character in string");
+      return false;
+    }
+  }
+
+  if (data[data.length() - 2] == '=' && data[data.length() - 1] != '=') {
+    LoggerE("Unexpected padding character in string");
+    return false;
+  }
+
+  clear();
+
+  if (data.length() == 0) {
+    return true;
+  }
+
+  int padding = 0;
+  if (data[data.length() - 1] == '=') {
+    padding++;
+  }
+
+  if (data[data.length() - 2] == '=') {
+    padding++;
+  }
+
+  for (size_t i = 0; i < data.length(); i += 4) {
+    uint8_t part[] = {
+        characterToNumber(data[i + 0]), characterToNumber(data[i + 1]),
+        characterToNumber(data[i + 2]), characterToNumber(data[i + 3])};
+    push_back(uint8_t((part[0] << 2) | (part[1] >> 4)));
+    if ((data.length() - i != 4) || (padding < 2)) {
+      push_back(uint8_t((part[1] << 4) | (part[2] >> 2)));
+    }
+    if ((data.length() - i != 4) || (padding < 1)) {
+      push_back(uint8_t((part[2] << 6) | (part[3])));
+    }
+  }
+  return true;
+}
+
+std::string FilesystemBuffer::EncodeData() const {
+  LoggerD("Enter");
+  std::string out;
+
+  for (size_t i = 0; i < size(); i += 3) {
+    uint8_t part[] = {safe_get(i), safe_get(i + 1), safe_get(i + 2)};
+    out.push_back(numberToCharacter(0x3F & (part[0] >> 2)));
+    out.push_back(numberToCharacter(0x3F & ((part[0] << 4) | (part[1] >> 4))));
+    out.push_back(numberToCharacter(0x3F & ((part[1] << 2) | (part[2] >> 6))));
+    out.push_back(numberToCharacter(0x3F & (part[2])));
+  }
+
+  if (out.size() == 0)
+    return out;
+
+  // Add padding
+  int fillup = (size() % 3);
+  if (fillup == 1) {
+    out[out.size() - 2] = '=';
+  }
+
+  if (fillup == 1 || fillup == 2) {
+    out[out.size() - 1] = '=';
+  }
+
+  return out;
+}
+
+FilesystemFile::FilesystemFile(const std::string& path_)
+    : path(path_) {}
+
+bool FilesystemFile::Read(uint8_t* data_p,
+                               size_t offset,
+                               size_t length,
+                               size_t* readed) {
+  LoggerE("entered");
+  size_t temp_read = 0;
+  if (!readed) {
+    readed = &temp_read;
+  }
+  FILE* file = fopen(path.c_str(), "r");
+  if (!file) {
+    LoggerE("Cannot open file %s to read!", path.c_str());
+    return false;
+  }
+  SCOPE_EXIT {
+    int status = fclose(file);
+    if (status) {
+      LoggerE("Cannot close file!");
+    }
+  };
+  int status;
+  status = fseek(file, offset, SEEK_SET);
+  if (status) {
+    LoggerE("Cannot perform seek!");
+    return false;
+  }
+
+  size_t data_size = length;
+  while (*readed < data_size) {
+    size_t part = fread(data_p, 1, length, file);
+
+    *readed += part;
+    data_p += part;
+    data_size -= part;
+
+    LoggerD("Readed part %li bytes", *readed);
+
+    if (ferror(file)) {
+      LoggerE("Error during file write!");
+      return false;
+    }
+
+    if (feof(file)) {
+      LoggerD("File is at end before buffer is filled. Finish.");
+      break;
+    }
+  }
+  LoggerD("Readed %li bytes", *readed);
+  return true;
+}
+
+bool FilesystemFile::Write(uint8_t* data_p, size_t data_size, size_t offset,
+                           size_t* written) {
+  LoggerD("Enter %s", path.c_str());
+  FILE* file = fopen(path.c_str(), "r+");
+  if (!file) {
+    LoggerE("Cannot open file %s to write!", path.c_str());
+    return false;
+  }
+
+  SCOPE_EXIT {
+    int status = fclose(file);
+    if (status) {
+      LoggerE("Cannot close file!");
+    }
+  };
+
+  int status;
+  status = fseek(file, offset, SEEK_SET);
+  LoggerD("Offset is %li, writing %i bytes", offset, data_size);
+  if (status) {
+    LoggerE("Cannot perform seek!");
+    return false;
+  }
+
+  while (*written < data_size) {
+    size_t part = fwrite(data_p, 1, data_size, file);
+
+    if (ferror(file)) {
+      LoggerE("Error during file write!");
+      return false;
+    }
+
+    *written += part;
+    data_p += part;
+    data_size -= part;
+  }
+
+  status = fflush(file);
+  if (status) {
+    LoggerE("Cannot flush file!");
+    return false;
+  }
+
+  status = fsync(fileno(file));
+  if (status) {
+    LoggerE("Cannot sync file!");
+    return false;
+  }
+  LoggerD("Written %li bytes", *written);
+
+  return true;
+}
+
+
+}  // namespace filesystem
+}  // namespace extension
diff --git a/webWidgetTCT_device/src/filesystem/filesystem_file.h b/webWidgetTCT_device/src/filesystem/filesystem_file.h
new file mode 100755 (executable)
index 0000000..e903e5c
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2015 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 FILESYSTEM_FILESYSTEM_FILE_H
+#define FILESYSTEM_FILESYSTEM_FILE_H
+
+#include <string>
+#include <vector>
+#include <stdint.h>
+
+namespace extension {
+namespace filesystem {
+
+class FilesystemBuffer : public std::vector<uint8_t> {
+ public:
+  bool DecodeData(const std::string& data);
+  std::string EncodeData() const;
+
+ private:
+  inline uint8_t safe_get(size_t i) const {
+    if (i >= size()) {
+      return 0;
+    }
+    return at(i);
+  }
+};
+
+class FilesystemFile {
+  const std::string path;
+
+ public:
+  FilesystemFile(const std::string& path_);
+
+  bool Read(u_int8_t* data_p, size_t offset, size_t length,
+            size_t* readed);
+  bool Write(uint8_t* data_p, size_t data_size, size_t offset, size_t* written);
+};
+
+}  // namespace filesystem
+}  // namespace extension
+
+#endif  // FILESYSTEM_FILESYSTEM_FILE_H
diff --git a/webWidgetTCT_device/src/filesystem/filesystem_instance.cc b/webWidgetTCT_device/src/filesystem/filesystem_instance.cc
new file mode 100755 (executable)
index 0000000..bee81b4
--- /dev/null
@@ -0,0 +1,595 @@
+/*
+ * Copyright (c) 2015 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 "filesystem/filesystem_instance.h"
+
+#include <glib.h>
+#include <functional>
+
+#include "common/filesystem/filesystem_provider.h"
+#include "common/picojson.h"
+#include "common/logger.h"
+#include "common/platform_exception.h"
+#include "common/task-queue.h"
+#include "filesystem_manager.h"
+
+namespace extension {
+namespace filesystem {
+
+namespace {
+// The privileges that required in Filesystem API
+const std::string kPrivilegeFilesystem = "";
+
+}  // namespace
+
+using namespace common;
+using namespace extension::filesystem;
+
+FilesystemInstance::FilesystemInstance() {
+  LoggerD("Enter");
+  using std::placeholders::_1;
+  using std::placeholders::_2;
+
+#define REGISTER_SYNC(c, x) \
+  RegisterSyncHandler(c, std::bind(&FilesystemInstance::x, this, _1, _2));
+#define REGISTER_ASYNC(c, x) \
+  RegisterSyncHandler(c, std::bind(&FilesystemInstance::x, this, _1, _2));
+
+  REGISTER_ASYNC("File_stat", FileStat);
+  REGISTER_SYNC("File_statSync", FileStatSync);
+  REGISTER_SYNC("File_createSync", FileCreateSync);
+  REGISTER_ASYNC("File_readDir", ReadDir);
+  REGISTER_ASYNC("File_rename", FileRename);
+  REGISTER_SYNC("File_readSync", FileReadSync);
+  REGISTER_SYNC("File_writeSync", FileWriteSync);
+  REGISTER_SYNC("Filesystem_fetchVirtualRoots", FilesystemFetchVirtualRoots);
+  REGISTER_SYNC("FileSystemManager_addStorageStateChangeListener",
+                StartListening);
+  REGISTER_SYNC("FileSystemManager_removeStorageStateChangeListener",
+                StopListening);
+  REGISTER_SYNC("FileSystemManager_fetchStorages",
+                FileSystemManagerFetchStorages);
+  REGISTER_ASYNC("FileSystemManager_mkdir", FileSystemManagerMakeDirectory);
+  REGISTER_SYNC("FileSystemManager_mkdirSync",
+                FileSystemManagerMakeDirectorySync);
+  REGISTER_ASYNC("File_unlinkFile", UnlinkFile);
+  REGISTER_ASYNC("File_removeDirectory", RemoveDirectory);
+  REGISTER_ASYNC("File_copyTo", CopyTo);
+#undef REGISTER_SYNC
+#undef REGISTER_ASYNC
+  FilesystemManager::GetInstance().AddListener(this);
+}
+
+FilesystemInstance::~FilesystemInstance() {
+  LoggerD("enter");
+  FilesystemManager::GetInstance().StopListening();
+  FilesystemManager::GetInstance().RemoveListener();
+}
+
+#define CHECK_EXIST(args, name, out)                                       \
+  if (!args.contains(name)) {                                              \
+    ReportError(TypeMismatchException(name " is required argument"), out); \
+    return;                                                                \
+  }
+
+void FilesystemInstance::FileCreateSync(const picojson::value& args, picojson::object& out)
+{
+  LoggerD("enter");
+  CHECK_EXIST(args, "location", out)
+
+  const std::string& location = args.get("location").get<std::string>();
+
+  auto onSuccess = [&](const FilesystemStat& data) {
+    LoggerD("enter");
+    ReportSuccess(data.toJSON(), out);
+  };
+
+  auto onError = [&](FilesystemError e) {
+    LoggerD("enter");
+    PrepareError(e, out);
+  };
+
+  FilesystemManager::GetInstance().CreateFile(location, onSuccess, onError);
+}
+
+void FilesystemInstance::FileRename(const picojson::value& args,
+                                    picojson::object& out) {
+  LoggerD("enter");
+  CHECK_EXIST(args, "callbackId", out)
+  CHECK_EXIST(args, "oldPath", out)
+  CHECK_EXIST(args, "newPath", out)
+
+  double callback_id = args.get("callbackId").get<double>();
+  const std::string& oldPath = args.get("oldPath").get<std::string>();
+  const std::string& newPath = args.get("newPath").get<std::string>();
+
+  auto onSuccess = [this, callback_id](const FilesystemStat& data) {
+    LoggerD("enter");
+    picojson::value response = picojson::value(picojson::object());
+    picojson::object& obj = response.get<picojson::object>();
+    obj["callbackId"] = picojson::value(callback_id);
+    ReportSuccess(data.toJSON(), obj);
+    Instance::PostMessage(this, response.serialize().c_str());
+  };
+
+  auto onError = [this, callback_id](FilesystemError e) {
+    LoggerD("enter");
+    picojson::value response = picojson::value(picojson::object());
+    picojson::object& obj = response.get<picojson::object>();
+    obj["callbackId"] = picojson::value(callback_id);
+    PrepareError(e, obj);
+    Instance::PostMessage(this, response.serialize().c_str());
+  };
+
+  FilesystemManager& fsm = FilesystemManager::GetInstance();
+  common::TaskQueue::GetInstance().Async(std::bind(
+      &FilesystemManager::Rename, &fsm, oldPath, newPath, onSuccess, onError));
+}
+
+void FilesystemInstance::FileReadSync(const common::ParsedDataRequest& req,
+                                      common::ParsedDataResponse& res) {
+  LoggerD("enter");
+  const picojson::value& args = req.args();
+  picojson::object& out = res.object();
+  CHECK_EXIST(args, "location", out)
+  CHECK_EXIST(args, "offset", out)
+  CHECK_EXIST(args, "length", out)
+
+  const std::string& location = args.get("location").get<std::string>();
+  size_t offset = static_cast<size_t>(args.get("offset").get<double>());
+  size_t length = static_cast<size_t>(args.get("length").get<double>());
+  const bool is_base64 = args.get("is_base64").get<bool>();
+
+  auto onSuccess = [this, &out, &length, &res, is_base64](const std::string& data, uint8_t* data_p, size_t readed) {
+    LoggerD("enter");
+    if (data_p) {
+      if (is_base64) {
+        gchar* encoded = g_base64_encode(data_p, length);
+        free(data_p);
+        // encoded will be freeed by runtime.
+        res.SetBuffer(reinterpret_cast<uint8_t*>(encoded), strlen(encoded) + 1);
+      } else {
+        res.SetBuffer(data_p, length);
+      }
+      out["data_size"] = picojson::value(static_cast<double>(readed));
+      ReportSuccess(out);
+    }
+  };
+
+  auto onError = [this, &out](FilesystemError e) {
+    LoggerD("enter");
+    PrepareError(e, out);
+  };
+
+  FilesystemManager::GetInstance().FileRead(
+      location, offset, length, onSuccess, onError);
+}
+
+void FilesystemInstance::FileWriteSync(const common::ParsedDataRequest& req, common::ParsedDataResponse& res) {
+  LoggerD("enter");
+  const picojson::value& args = req.args();
+  picojson::object& out = res.object();
+  CHECK_EXIST(args, "location", out)
+  CHECK_EXIST(args, "offset", out)
+
+  const std::string& location = args.get("location").get<std::string>();
+  const bool is_base64 = args.get("is_base64").get<bool>();
+  size_t offset = static_cast<size_t>(args.get("offset").get<double>());
+
+  auto onSuccess = [this, &out](size_t written) {
+    LoggerD("enter");
+    out["data_size"] = picojson::value(static_cast<double>(written));
+    ReportSuccess(out);
+  };
+
+  auto onError = [this, &out](FilesystemError e) {
+    LoggerD("enter");
+    PrepareError(e, out);
+  };
+  uint8_t* data_p = nullptr;
+  size_t data_size = 0;
+  if (is_base64) {
+    data_p = g_base64_decode(reinterpret_cast<char*>(req.buffer()),
+                             &data_size);
+  } else {
+    data_p = req.buffer();
+    data_size = req.buffer_length();
+  }
+  if (data_size > 0 && data_p) {
+    FilesystemManager::GetInstance().FileWrite(
+        location, data_p, data_size, offset, onSuccess, onError);
+  }
+  if (is_base64 && data_p) {
+    free(data_p);
+  }
+}
+
+void FilesystemInstance::FileStat(const picojson::value& args,
+                                  picojson::object& out) {
+  LoggerD("enter");
+  CHECK_EXIST(args, "callbackId", out)
+  CHECK_EXIST(args, "location", out)
+
+  double callback_id = args.get("callbackId").get<double>();
+  const std::string& location = args.get("location").get<std::string>();
+
+  auto onSuccess = [this, callback_id](const FilesystemStat& data) {
+    LoggerD("enter");
+    picojson::value response = picojson::value(picojson::object());
+    picojson::object& obj = response.get<picojson::object>();
+    obj["callbackId"] = picojson::value(callback_id);
+    ReportSuccess(data.toJSON(), obj);
+    Instance::PostMessage(this, response.serialize().c_str());
+  };
+
+  auto onError = [this, callback_id](FilesystemError e) {
+    LoggerD("enter");
+    picojson::value response = picojson::value(picojson::object());
+    picojson::object& obj = response.get<picojson::object>();
+    obj["callbackId"] = picojson::value(callback_id);
+    PrepareError(e, obj);
+    Instance::PostMessage(this, response.serialize().c_str());
+  };
+
+  FilesystemManager& fsm = FilesystemManager::GetInstance();
+  common::TaskQueue::GetInstance().Async(std::bind(
+      &FilesystemManager::StatPath, &fsm, location, onSuccess, onError));
+}
+
+void FilesystemInstance::FileStatSync(const picojson::value& args,
+                                      picojson::object& out) {
+  LoggerD("enter");
+  CHECK_EXIST(args, "location", out)
+
+  const std::string& location = args.get("location").get<std::string>();
+
+  auto onSuccess = [&](const FilesystemStat& data) {
+    LoggerD("enter");
+    ReportSuccess(data.toJSON(), out);
+  };
+
+  auto onError = [&](FilesystemError e) {
+    LoggerD("enter");
+    PrepareError(e, out);
+  };
+
+  FilesystemManager::GetInstance().StatPath(location, onSuccess, onError);
+}
+
+void FilesystemInstance::FilesystemFetchVirtualRoots(
+    const picojson::value& args, picojson::object& out) {
+  LoggerD("enter");
+
+  auto onSuccess = [&](const std::vector<common::VirtualRoot>& result) {
+    LoggerD("enter");
+    picojson::array roots;
+    for (const auto& root : result) {
+      roots.push_back(root.ToJson());
+    }
+    ReportSuccess(picojson::value(roots), out);
+  };
+
+  auto onError = [&](FilesystemError e) {
+    LoggerD("enter");
+    PrepareError(e, out);
+  };
+
+  FilesystemManager::GetInstance().GetVirtualRoots(onSuccess, onError);
+}
+
+void FilesystemInstance::FileSystemManagerFetchStorages(
+    const picojson::value& args,
+    picojson::object& out) {
+  LoggerD("enter");
+
+  auto onSuccess = [&](const common::Storages& result) {
+    LoggerD("enter");
+    picojson::array storages;
+    storages.reserve(result.size());
+    for (const auto& storage : result) {
+      storages.push_back(storage->ToJson());
+    }
+    ReportSuccess(picojson::value(storages), out);
+  };
+
+  auto onError = [&](FilesystemError e) {
+    LoggerD("enter");
+    PrepareError(e, out);
+  };
+
+  FilesystemManager::GetInstance().FetchStorages(onSuccess, onError);
+}
+void FilesystemInstance::StartListening(
+    const picojson::value& args,
+    picojson::object& out) {
+  LoggerD("enter");
+  if( args.contains("isPrivate")){
+    const bool is_private = args.get("isPrivate").get<bool>();
+    FilesystemManager::GetInstance().StartListening(is_private);
+    ReportSuccess(out);
+  }
+  else{
+    FilesystemManager::GetInstance().StartListening();
+    ReportSuccess(out);
+  }
+}
+
+void FilesystemInstance::StopListening(
+    const picojson::value& args,
+    picojson::object& out) {
+  LoggerD("enter");
+  FilesystemManager::GetInstance().StopListening();
+  ReportSuccess(out);
+}
+
+void FilesystemInstance::onFilesystemStateChangeSuccessCallback(const common::Storage& storage, bool is_private) {
+  LoggerD("entered");
+
+  picojson::value event = picojson::value(picojson::object());
+  picojson::object& obj = event.get<picojson::object>();
+  obj["label"] = picojson::value(storage.name());
+  obj["type"] = picojson::value(common::Storage::ToString(storage.type()));
+  obj["state"] = picojson::value(common::Storage::ToString(storage.state()));
+  if( is_private ) {
+    obj["listenerId"] = picojson::value("SynchronizeStorages");
+    Instance::PostMessage(this, event.serialize().c_str());
+  }
+
+  obj["listenerId"] = picojson::value("StorageStateChangeListener");
+  Instance::PostMessage(this, event.serialize().c_str());
+}
+
+void FilesystemInstance::onFilesystemStateChangeErrorCallback() {
+  LoggerD("enter");
+  picojson::value event = picojson::value(picojson::object());
+  picojson::object& obj = event.get<picojson::object>();
+  ReportError(UnknownException(std::string("Failed to registerd listener")), obj);
+  obj["listenerId"] = picojson::value("StorageStateChangeListener");
+  LoggerD("Posting: %s", event.serialize().c_str());
+  Instance::PostMessage(this, event.serialize().c_str());
+}
+
+void FilesystemInstance::FileSystemManagerMakeDirectory(
+    const picojson::value& args,
+    picojson::object& out) {
+  LoggerD("enter");
+  CHECK_EXIST(args, "callbackId", out)
+  CHECK_EXIST(args, "location", out)
+
+  double callback_id = args.get("callbackId").get<double>();
+  const std::string& location = args.get("location").get<std::string>();
+
+  auto onResult = [this, callback_id](FilesystemError e) {
+    LoggerD("enter");
+    picojson::value response = picojson::value(picojson::object());
+    picojson::object& obj = response.get<picojson::object>();
+    obj["callbackId"] = picojson::value(callback_id);
+    if (e == FilesystemError::DirectoryExists)
+      ReportSuccess(obj);
+    else
+      PrepareError(e, obj);
+    Instance::PostMessage(this, response.serialize().c_str());
+  };
+
+  auto onAction = [location, onResult]() {
+    FilesystemManager::GetInstance().MakeDirectory(location, onResult);
+  };
+
+  common::TaskQueue::GetInstance().Async(onAction);
+}
+
+void FilesystemInstance::FileSystemManagerMakeDirectorySync(
+    const picojson::value& args,
+    picojson::object& out) {
+  LoggerD("enter");
+  CHECK_EXIST(args, "location", out)
+
+  const std::string& location = args.get("location").get<std::string>();
+
+  auto onResult = [&](FilesystemError e) {
+    LoggerD("enter");
+    if (e == FilesystemError::DirectoryExists)
+      ReportSuccess(out);
+    else
+      PrepareError(e, out);
+  };
+
+  FilesystemManager::GetInstance().MakeDirectory(location, onResult);
+}
+
+void FilesystemInstance::ReadDir(const picojson::value& args,
+                                  picojson::object& out) {
+  LoggerD("enter");
+  CHECK_EXIST(args, "pathToDir", out)
+  CHECK_EXIST(args, "callbackId", out)
+
+  double callback_id = args.get("callbackId").get<double>();
+  const std::string& pathToDir = args.get("pathToDir").get<std::string>();
+
+  auto onSuccess = [this, callback_id](const std::vector<std::string>& paths) {
+    LoggerD("enter");
+    picojson::value result = picojson::value(picojson::array());;
+    picojson::array& statPaths = result.get<picojson::array>();
+    picojson::value response = picojson::value(picojson::object());
+    picojson::object& obj = response.get<picojson::object>();
+    obj["callbackId"] = picojson::value(callback_id);
+    for(auto path : paths) {
+      FilesystemStat stat = FilesystemStat::getStat(path);
+      statPaths.push_back(stat.toJSON());
+    }
+    ReportSuccess(result, obj);
+    Instance::PostMessage(this, response.serialize().c_str());
+  };
+
+  auto onError = [this, callback_id](FilesystemError e) {
+    LoggerD("enter");
+    picojson::value response = picojson::value(picojson::object());
+    picojson::object& obj = response.get<picojson::object>();
+    obj["callbackId"] = picojson::value(callback_id);
+    PrepareError(e, obj);
+    Instance::PostMessage(this, response.serialize().c_str());
+  };
+
+  FilesystemManager& fm = FilesystemManager::GetInstance();
+  common::TaskQueue::GetInstance().Async(std::bind(
+      &FilesystemManager::ReadDir, &fm, pathToDir, onSuccess, onError));
+}
+
+void FilesystemInstance::UnlinkFile(const picojson::value& args,
+                                  picojson::object& out) {
+  LoggerD("enter");
+  CHECK_EXIST(args, "pathToFile", out)
+
+  double callback_id = args.get("callbackId").get<double>();
+  const std::string& pathToFile = args.get("pathToFile").get<std::string>();
+
+  auto onSuccess = [this, callback_id]() {
+    LoggerD("enter");
+    picojson::value result = picojson::value();
+    picojson::value response = picojson::value(picojson::object());
+    picojson::object& obj = response.get<picojson::object>();
+    obj["callbackId"] = picojson::value(callback_id);
+    ReportSuccess(result, obj);
+    Instance::PostMessage(this, response.serialize().c_str());
+  };
+
+  auto onError = [this, callback_id](FilesystemError e) {
+    LoggerD("enter");
+    picojson::value response = picojson::value(picojson::object());
+    picojson::object& obj = response.get<picojson::object>();
+    obj["callbackId"] = picojson::value(callback_id);
+    PrepareError(e, obj);
+    Instance::PostMessage(this, response.serialize().c_str());
+  };
+
+  FilesystemManager& fm = FilesystemManager::GetInstance();
+  common::TaskQueue::GetInstance().Async(std::bind(
+      &FilesystemManager::UnlinkFile, &fm, pathToFile, onSuccess, onError));
+}
+
+void FilesystemInstance::RemoveDirectory(const picojson::value& args,
+                                  picojson::object& out) {
+  LoggerD("enter");
+  CHECK_EXIST(args, "pathToDelete", out)
+
+  double callback_id = args.get("callbackId").get<double>();
+  const std::string& pathToDelete = args.get("pathToDelete").get<std::string>();
+
+  auto onSuccess = [this, callback_id]() {
+    LoggerD("enter");
+    picojson::value result = picojson::value();
+    picojson::value response = picojson::value(picojson::object());
+    picojson::object& obj = response.get<picojson::object>();
+    obj["callbackId"] = picojson::value(callback_id);
+    ReportSuccess(result, obj);
+    Instance::PostMessage(this, response.serialize().c_str());
+  };
+
+  auto onError = [this, callback_id](FilesystemError e) {
+    LoggerD("enter");
+    picojson::value response = picojson::value(picojson::object());
+    picojson::object& obj = response.get<picojson::object>();
+    obj["callbackId"] = picojson::value(callback_id);
+    PrepareError(e, obj);
+    Instance::PostMessage(this, response.serialize().c_str());
+  };
+
+  FilesystemManager& fm = FilesystemManager::GetInstance();
+  common::TaskQueue::GetInstance().Async(std::bind(
+      &FilesystemManager::RemoveDirectory, &fm, pathToDelete, onSuccess, onError));
+}
+
+void FilesystemInstance::CopyTo(const picojson::value& args,
+                                  picojson::object& out) {
+  LoggerD("enter");
+  CHECK_EXIST(args, "callbackId", out)
+  CHECK_EXIST(args, "originFilePath", out)
+  CHECK_EXIST(args, "destinationFilePath", out)
+  CHECK_EXIST(args, "overwrite", out)
+
+  double callback_id = args.get("callbackId").get<double>();
+  const std::string& originPath = args.get("originFilePath").get<std::string>();
+  const std::string& destinationPath = args.get("destinationFilePath").get<std::string>();
+  const bool& overwrite = args.get("overwrite").get<bool>();
+
+  auto onSuccess = [this, callback_id]() {
+    LoggerD("enter");
+    picojson::value result = picojson::value();
+    picojson::value response = picojson::value(picojson::object());
+    picojson::object& obj = response.get<picojson::object>();
+    obj["callbackId"] = picojson::value(callback_id);
+    ReportSuccess(result, obj);
+    Instance::PostMessage(this, response.serialize().c_str());
+  };
+
+  auto onError = [this, callback_id](FilesystemError e) {
+    LoggerD("enter");
+    picojson::value response = picojson::value(picojson::object());
+    picojson::object& obj = response.get<picojson::object>();
+    obj["callbackId"] = picojson::value(callback_id);
+    PrepareError(e, obj);
+    Instance::PostMessage(this, response.serialize().c_str());
+  };
+
+  FilesystemManager& fm = FilesystemManager::GetInstance();
+  common::TaskQueue::GetInstance().Async(std::bind(
+      &FilesystemManager::CopyTo, &fm, originPath, destinationPath, overwrite, onSuccess, onError));
+}
+
+void FilesystemInstance::PrepareError(const FilesystemError& error, picojson::object& out)
+{
+  LoggerD("enter");
+  switch (error) {
+    case FilesystemError::NotFound:
+      LoggerE("NotFoundException - PLATFORM ERROR");
+      ReportError(NotFoundException("PLATFORM ERROR"), out);
+      break;
+    case FilesystemError::FileExists:
+      LoggerE("IOException - File already exists");
+      ReportError(IOException("File already exists"), out);
+      break;
+    case FilesystemError::DirectoryExists:
+      LoggerE("IOException - Directory already exists");
+      ReportError(IOException("Directory already exists"), out);
+      break;
+    case FilesystemError::PermissionDenied:
+      LoggerE("IOException - Permission denied");
+      ReportError(UnknownException("Permission denied"), out);
+      break;
+    case FilesystemError::IOError:
+      LoggerE("IOException - IO Error");
+      ReportError(IOException("IO Error"), out);
+      break;
+    case FilesystemError::Other:
+      LoggerE("UnknownException - PLATFORM ERROR other");
+      ReportError(UnknownException("PLATFORM ERROR other"), out);
+      break;
+    case FilesystemError::InvalidValue:
+      LoggerE("InvalidValuesException - PLATFORM ERROR");
+      ReportError(InvalidValuesException("PLATFORM ERROR"), out);
+      break;
+    default:
+      LoggerE("UnknownException - PLATFORM ERROR default");
+      ReportError(UnknownException("PLATFORM ERROR default"), out);
+      break;
+  }
+}
+
+
+#undef CHECK_EXIST
+
+}  // namespace filesystem
+}  // namespace extension
diff --git a/webWidgetTCT_device/src/filesystem/filesystem_instance.h b/webWidgetTCT_device/src/filesystem/filesystem_instance.h
new file mode 100755 (executable)
index 0000000..40d2fde
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2015 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 FILESYSTEM_FILESYSTEM_INSTANCE_H_
+#define FILESYSTEM_FILESYSTEM_INSTANCE_H_
+
+#include "common/extension.h"
+#include "filesystem_utils.h"
+#include <thread>
+#include <mutex>
+#include "filesystem_manager.h"
+#include "common/filesystem/storage.h"
+
+namespace extension {
+namespace filesystem {
+
+class FilesystemInstance : public common::ParsedDataInstance,
+                           FilesystemStateChangeListener {
+ public:
+  FilesystemInstance();
+  virtual ~FilesystemInstance();
+
+ private:
+  void FileCreateSync(const picojson::value& args, picojson::object& out);
+  void FileRename(const picojson::value& args, picojson::object& out);
+  void FileStat(const picojson::value& args, picojson::object& out);
+  void FileStatSync(const picojson::value& args, picojson::object& out);
+  void FileRead(const picojson::value& args, picojson::object& out);
+  void FileReadSync(const common::ParsedDataRequest& req, common::ParsedDataResponse& res);
+  void FileWrite(const picojson::value& args, picojson::object& out);
+  void FileWriteSync(const common::ParsedDataRequest& req, common::ParsedDataResponse& res);
+  void FilesystemFetchVirtualRoots(const picojson::value& args,
+                                   picojson::object& out);
+  void FileSystemManagerFetchStorages(const picojson::value& args,
+                                      picojson::object& out);
+  void FileSystemManagerMakeDirectory(const picojson::value& args,
+                                      picojson::object& out);
+  void FileSystemManagerMakeDirectorySync(const picojson::value& args,
+                                          picojson::object& out);
+  void ReadDir(const picojson::value& args, picojson::object& out);
+  void UnlinkFile(const picojson::value& args, picojson::object& out);
+  void RemoveDirectory(const picojson::value& args, picojson::object& out);
+  void StartListening(const picojson::value& args, picojson::object& out);
+  void StopListening(const picojson::value& args, picojson::object& out);
+  void CopyTo(const picojson::value& args, picojson::object& out);
+  void onFilesystemStateChangeErrorCallback();
+  void onFilesystemStateChangeSuccessCallback(const common::Storage& storage, bool is_private);
+  void PrepareError(const FilesystemError& error, picojson::object& out);
+};
+
+}  // namespace filesystem
+}  // namespace extension
+
+#endif  // FILESYSTEM_FILESYSTEM_INSTANCE_H_
diff --git a/webWidgetTCT_device/src/filesystem/filesystem_manager.cc b/webWidgetTCT_device/src/filesystem/filesystem_manager.cc
new file mode 100755 (executable)
index 0000000..ff746c6
--- /dev/null
@@ -0,0 +1,500 @@
+/*
+ * Copyright (c) 2015 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 "filesystem/filesystem_manager.h"
+
+#include <dirent.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fstream>
+#include <algorithm>
+#ifndef _XOPEN_SOURCE
+#define _XOPEN_SOURCE 500
+#endif
+#include <ftw.h>
+#undef _XOPEN_SOURCE
+
+#include <app_manager.h>
+#include <package_manager.h>
+#include <storage-expand.h>
+#include <storage.h>
+#include "common/logger.h"
+#include "common/tools.h"
+#include "common/scope_exit.h"
+#include "common/extension.h"
+#include "filesystem/filesystem_file.h"
+#ifdef TIZEN_TV
+#ifdef TIZEN_TV_PRODUCT
+#include "common/filesystem/filesystem_provider_capiusb.h"
+#else
+#include "common/filesystem/deviced.h"
+#endif
+#else
+#include "common/filesystem/filesystem_provider_storage.h"
+#endif
+
+namespace extension {
+namespace filesystem {
+
+using common::tools::GetErrorString;
+
+namespace {
+
+int unlink_cb(const char* fpath, const struct stat* sb, int typeflag,
+              struct FTW* ftwbuf) {
+  if (ftwbuf->level == 0)
+    return 0;
+
+  int result = remove(fpath);
+  if (result)
+    LoggerE("error occured");
+  return result;
+}
+
+int unlink_with_base_dir_cb(const char* fpath, const struct stat* sb,
+                            int typeflag, struct FTW* ftwbuf) {
+  int result = remove(fpath);
+  if (result)
+    LoggerE("error occured");
+  return result;
+}
+
+FilesystemError copyFile(const std::string& originPath,
+                         const std::string& destPath) {
+  LoggerD("enter src %s dst %s", originPath.c_str(), destPath.c_str());
+
+  std::ifstream src(originPath, std::ios::in | std::ios::binary);
+  std::ofstream dst(destPath, std::ios::out | std::ios::binary);
+
+  std::istreambuf_iterator<char> begin_source(src);
+  std::istreambuf_iterator<char> end_source;
+  std::ostreambuf_iterator<char> begin_dest(dst);
+  std::copy(begin_source, end_source, begin_dest);
+
+  if (src.fail() || dst.fail()) {
+    LoggerE("Cannot copy file");
+    return FilesystemError::IOError;
+  }
+  return FilesystemError::None;
+}
+
+FilesystemError copyDirectory(const std::string& originPath,
+                              const std::string& destPath) {
+  LoggerD("enter src %s dst %s", originPath.c_str(), destPath.c_str());
+  FilesystemStat destStat = FilesystemStat::getStat(destPath);
+
+  int status;
+  if (!destStat.valid) {
+    const mode_t create_mode = S_IRWXU | S_IRWXG | S_IRWXO;
+    status = mkdir(destPath.c_str(), create_mode);
+    if (status) {
+      LoggerE("Cannot create directory: %s", GetErrorString(errno).c_str());
+      return FilesystemError::Other;
+    }
+  }
+  DIR* dp = opendir(originPath.c_str());
+  if (dp == NULL) {
+    LoggerE("Cannot open directory: %s", GetErrorString(errno).c_str());
+    return FilesystemError::Other;
+  }
+  SCOPE_EXIT {
+    (void)closedir(dp);
+  };
+  struct dirent entry;
+  struct dirent* result = nullptr;
+  while (0 == (status = readdir_r(dp, &entry, &result)) && result != nullptr) {
+    if (strcmp(result->d_name, ".") == 0 || strcmp(result->d_name, "..") == 0)
+      continue;
+
+    std::string oldLocation = originPath + std::string("/")
+        + std::string(result->d_name);
+    std::string newLocation = destPath + std::string("/")
+        + std::string(result->d_name);
+    FilesystemError fstatus = FilesystemError::None;
+    if (result->d_type == DT_DIR) {
+      fstatus = copyDirectory(oldLocation, newLocation);
+    } else if (result->d_type == DT_REG) {
+      fstatus = copyFile(oldLocation, newLocation);
+    }
+    if (fstatus != FilesystemError::None) {
+      LoggerE("Error while copying tree");
+      return fstatus;
+    }
+  }
+  if (status != 0) {
+    LoggerE("error occured");
+    return FilesystemError::Other;
+  }
+  return FilesystemError::None;
+}
+
+FilesystemError perform_deep_copy(const std::string& originPath,
+                                  const std::string& destPath,
+                                  bool overwrite) {
+  LoggerD("enter src %s dst %s", originPath.c_str(), destPath.c_str());
+  FilesystemStat originStat = FilesystemStat::getStat(originPath);
+  FilesystemStat destStat = FilesystemStat::getStat(destPath);
+  int status;
+  std::string path = destPath;
+  if (!originStat.valid) {
+    LoggerE("Cannot retrieve stat in deep copy");
+    return FilesystemError::Other;
+  }
+
+  // Overwrite check
+  if (!overwrite && destStat.valid) {
+    // Do not overwrite file.
+    LoggerD("Cannot overwrite existing entity");
+    return FilesystemError::FileExists;
+  }
+
+  // Remove existing data.
+  if (destStat.valid) {
+    if (destStat.isDirectory) {
+      path.append("/");
+      if (originStat.isFile) {
+        std::string dstPathWithFilename = originPath.substr(
+            originPath.find_last_of("/") + 1);
+        path.append(dstPathWithFilename);
+        FilesystemStat destStatWithFilename = FilesystemStat::getStat(path);
+        if (destStatWithFilename.valid) {
+          status = remove(path.c_str());
+          if (status) {
+            LoggerE("Cannot remove old file: %s",
+                    GetErrorString(errno).c_str());
+            return FilesystemError::Other;
+          }
+        }
+      } else {
+        const int maxDirOpened = 64;
+        if (nftw(path.c_str(), unlink_cb, maxDirOpened,
+        FTW_DEPTH | FTW_PHYS) != 0) {
+          LoggerE("Error occured");
+          return FilesystemError::Other;
+        }
+      }
+    } else {
+      status = remove(path.c_str());
+      if (status) {
+        LoggerE("Cannot remove old directory: %s",
+                GetErrorString(errno).c_str());
+        return FilesystemError::Other;
+      }
+    }
+  }
+
+  if (originStat.isFile) {
+    return copyFile(originPath, path);
+  } else if (originStat.isDirectory) {
+    return copyDirectory(originPath, destPath);
+  }
+  return FilesystemError::None;
+}
+
+FilesystemError make_directory_worker(const std::string& path) {
+  LoggerD("enter: %s", path.c_str());
+  auto fsstat = FilesystemStat::getStat(path);
+  if (fsstat.valid) {
+    if (fsstat.isDirectory) {
+      LoggerD("Directory exists");
+      return FilesystemError::DirectoryExists;
+    } else {
+      LoggerD("It is a file and exists");
+      return FilesystemError::FileExists;
+    }
+  }
+
+  std::string parent_path = FilesystemUtils::get_dirname(path);
+  auto parent_result = make_directory_worker(parent_path);
+
+  if (parent_result == FilesystemError::DirectoryExists) {
+    LoggerD("Creating directrory: %s", path.c_str());
+    mode_t create_mode = S_IRWXU | S_IRWXG | S_IRWXO;
+    int r = mkdir(path.c_str(), create_mode);
+    if (r == 0) {
+      return FilesystemError::DirectoryExists;
+    }
+    LoggerD("Cannot create directory: %s", GetErrorString(errno).c_str());
+    return FilesystemError::Other;
+  }
+  return parent_result;
+}
+}  // namespace
+
+void FilesystemManager::FetchStorages(
+    const std::function<void(const common::Storages&)>& success_cb,
+    const std::function<void(FilesystemError)>& error_cb) {
+  LoggerD("Entered");
+
+  success_cb(fs_provider_.GetStorages());
+}
+
+void FilesystemManager::StartListening( bool is_private ) {
+  LoggerD("Entered");
+  auto set = std::bind(&FilesystemManager::OnUSBDeviceChanged, this,
+                       std::placeholders::_1, std::placeholders::_2,
+                       std::placeholders::_3);
+
+
+  is_private ? is_private_ = true : is_private_ = false;
+  fs_provider_.RegisterDeviceChangeState(set);
+}
+
+void FilesystemManager::StopListening() {
+  LoggerD("Entered");
+
+  fs_provider_.UnregisterDeviceChangeState();
+}
+
+void FilesystemManager::OnUSBDeviceChanged(common::Storage const& _storage,
+                                           common::StorageState _old,
+                                           common::StorageState _new) {
+  LoggerD("Entered");
+  listener_->onFilesystemStateChangeSuccessCallback(_storage, is_private_);
+}
+
+FilesystemManager::FilesystemManager()
+    : listener_(nullptr), is_private_(false),
+#ifdef TIZEN_TV
+#ifdef TIZEN_TV_PRODUCT
+      fs_provider_(common::FilesystemProviderCAPIUSB::Create())
+#else
+      fs_provider_(common::FilesystemProviderDeviced::Create())
+#endif
+#else
+      fs_provider_(common::FilesystemProviderStorage::Create())
+#endif
+{
+}
+
+FilesystemManager::~FilesystemManager() {
+  LoggerD("enter");
+}
+
+FilesystemManager& FilesystemManager::GetInstance() {
+  LoggerD("enter");
+  static FilesystemManager fs;
+  return fs;
+}
+
+void FilesystemManager::StatPath(
+    const std::string& path,
+    const std::function<void(const FilesystemStat&)>& success_cb,
+    const std::function<void(FilesystemError)>& error_cb) {
+  LoggerD("Enter");
+  FilesystemStat statData = FilesystemStat::getStat(path);
+  if (!statData.valid) {
+    error_cb(statData.error);
+    return;
+  }
+
+  success_cb(statData);
+}
+
+void FilesystemManager::GetVirtualRoots(
+    const std::function<void(const common::VirtualRoots &)>& success_cb,
+    const std::function<void(FilesystemError)>& error_cb) {
+  LoggerD("Enterd");
+
+  success_cb(fs_provider_.GetVirtualPaths());
+}
+
+void FilesystemManager::CreateFile(
+    const std::string& path,
+    const std::function<void(const FilesystemStat&)>& success_cb,
+    const std::function<void(FilesystemError)>& error_cb) {
+  LoggerD("enter");
+  const mode_t create_mode = S_IRWXU | S_IRWXG | S_IRWXO;
+  int status;
+  status = TEMP_FAILURE_RETRY(
+      open(path.c_str(), O_RDWR | O_CREAT, create_mode));
+  if (-1 == status) {
+    LoggerE("Cannot create or open file %s: %s", path.c_str(),
+            GetErrorString(errno).c_str());
+    error_cb(FilesystemError::Other);
+    return;
+  }
+  status = close(status);
+  if (0 != status) {
+    LoggerE("Cannot close file %s: %s", path.c_str(),
+            GetErrorString(errno).c_str());
+    error_cb(FilesystemError::Other);
+    return;
+  }
+  FilesystemStat stat = FilesystemStat::getStat(path);
+  if (stat.valid) {
+    success_cb(stat);
+  } else {
+    LoggerE("Cannot create stat data!");
+    error_cb(FilesystemError::Other);
+  }
+}
+
+void FilesystemManager::MakeDirectory(
+    const std::string& path,
+    const std::function<void(FilesystemError)>& result_cb) {
+  LoggerD("enter");
+  result_cb(make_directory_worker(path));
+}
+
+void FilesystemManager::Rename(
+    const std::string& oldPath, const std::string& newPath,
+    const std::function<void(const FilesystemStat&)>& success_cb,
+    const std::function<void(FilesystemError)>& error_cb) {
+  LoggerD("enter");
+  int status = rename(oldPath.c_str(), newPath.c_str());
+  if (0 == status) {
+    FilesystemStat fileStat = FilesystemStat::getStat(newPath);
+    if (fileStat.valid) {
+      success_cb(FilesystemStat::getStat(newPath));
+    } else {
+      LoggerE("Cannot perform stat on new path!");
+      error_cb(FilesystemError::Other);
+    }
+  } else {
+    LoggerE("Cannot rename file: %s", GetErrorString(errno).c_str());
+    error_cb(FilesystemError::Other);
+  }
+}
+
+void FilesystemManager::ReadDir(
+    const std::string& path,
+    const std::function<void(const std::vector<std::string>&)>& success_cb,
+    const std::function<void(FilesystemError)>& error_cb) {
+  LoggerD("entered");
+
+  std::vector<std::string> fileList;
+  DIR* dp = nullptr;
+  struct dirent entry;
+  struct dirent* result = nullptr;
+  int status = 0;
+
+  dp = opendir(path.c_str());
+  if (dp != NULL) {
+    while ((status = readdir_r(
+        dp, &entry, &result)) == 0 && result != nullptr) {
+      if (strcmp(result->d_name, ".") != 0 && strcmp(result->d_name, "..") != 0)
+        fileList.push_back(path + "/" + std::string(result->d_name));
+    }
+    (void) closedir(dp);
+    if (status == 0) {
+      success_cb(fileList);
+    } else {
+      LoggerE("error occured");
+      error_cb(FilesystemError::Other);
+    }
+  } else {
+    LoggerE("Couldn't open the directory");
+    error_cb(FilesystemError::Other);
+    return;
+  }
+}
+
+void FilesystemManager::UnlinkFile(
+    const std::string& path, const std::function<void()>& success_cb,
+    const std::function<void(FilesystemError)>& error_cb) {
+  LoggerD("enter");
+  if (unlink(path.c_str()) != 0) {
+    LoggerE("Error occured while deleting file");
+    error_cb(FilesystemError::Other);
+    return;
+  }
+  success_cb();
+}
+
+void FilesystemManager::RemoveDirectory(
+    const std::string& path, const std::function<void()>& success_cb,
+    const std::function<void(FilesystemError)>& error_cb) {
+  LoggerD("enter");
+  const int maxDirOpened = 64;
+  if (nftw(path.c_str(), unlink_with_base_dir_cb, maxDirOpened,
+           FTW_DEPTH | FTW_PHYS) != 0) {
+    LoggerE("Error occured");
+    error_cb(FilesystemError::Other);
+  }
+  success_cb();
+  return;
+}
+
+void FilesystemManager::FileRead(
+    const std::string& path,
+    size_t offset,
+    size_t length,
+    const std::function<void(const std::string&, uint8_t*, size_t)>& success_cb,
+    const std::function<void(FilesystemError)>& error_cb) {
+  LoggerD("enter");
+  uint8_t* data_p = nullptr;
+  FilesystemFile file(path);
+  std::string out_data;
+  size_t readed = 0;
+  data_p = (uint8_t*)calloc(1, sizeof(uint8_t) * length + 1);
+  if (!data_p || !file.Read(data_p, offset, length, &readed)) {
+    LoggerE("Cannot read file %s", path.c_str());
+    error_cb(FilesystemError::Other);
+    if (data_p) {
+      free (data_p);
+      data_p = nullptr;
+    }
+    return;
+  }
+  success_cb(out_data, data_p, readed);
+}
+
+void FilesystemManager::FileWrite(const std::string& path,
+               uint8_t* data_p,
+               size_t data_size,
+               size_t offset,
+               const std::function<void(size_t written)>& success_cb,
+               const std::function<void(FilesystemError)>& error_cb) {
+  LoggerD("enter");
+  FilesystemFile file(path);
+  size_t written = 0;
+  if (file.Write(data_p, data_size, offset, &written)) {
+    success_cb(written);
+  } else {
+    LoggerE("Cannot write to file %s!", path.c_str());
+    error_cb(FilesystemError::Other);
+  }
+}
+
+void FilesystemManager::CopyTo(
+    const std::string& originFilePath, const std::string& destinationFilePath,
+    const bool overwrite, const std::function<void()>& success_cb,
+    const std::function<void(FilesystemError)>& error_cb) {
+  LoggerD("enter");
+  FilesystemError retval = perform_deep_copy(originFilePath,
+                                             destinationFilePath, overwrite);
+  if (FilesystemError::None == retval) {
+    success_cb();
+  } else {
+    LoggerE("Failed: perform_deep_copy()");
+    error_cb(retval);
+  }
+}
+
+void FilesystemManager::AddListener(FilesystemStateChangeListener* listener) {
+  LoggerD("enter");
+  listener_ = listener;
+}
+
+void FilesystemManager::RemoveListener() {
+  LoggerD("enter");
+  listener_ = NULL;
+}
+}  // namespace filesystem
+}  // namespace extension
diff --git a/webWidgetTCT_device/src/filesystem/filesystem_manager.h b/webWidgetTCT_device/src/filesystem/filesystem_manager.h
new file mode 100755 (executable)
index 0000000..bc86e06
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2015 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 FILESYSTEM_FILESYSTEM_MANAGER_H_
+#define FILESYSTEM_FILESYSTEM_MANAGER_H_
+
+#include <functional>
+#include <string>
+#include <vector>
+#include <set>
+#include <memory>
+
+#include "filesystem/filesystem_stat.h"
+#include "filesystem/filesystem_utils.h"
+
+#include "common/filesystem/storage.h"
+#include "common/filesystem/filesystem_provider.h"
+
+namespace common {
+class FilesystemProvider;
+}
+
+namespace extension {
+namespace filesystem {
+
+class FilesystemStateChangeListener {
+ public:
+  virtual ~FilesystemStateChangeListener() {
+  }
+  virtual void onFilesystemStateChangeSuccessCallback(
+      const common::Storage& storage, bool isPrivate) = 0;
+  virtual void onFilesystemStateChangeErrorCallback() = 0;
+};
+
+class FilesystemManager {
+ private:
+  FilesystemStateChangeListener* listener_;
+  FilesystemManager();
+  common::FilesystemProviderRef fs_provider_;
+  bool is_private_;
+
+ public:
+  static FilesystemManager& GetInstance();
+  virtual ~FilesystemManager();
+
+  void UnlinkFile(const std::string& path,
+                  const std::function<void()>& success_cb,
+                  const std::function<void(FilesystemError)>& error_cb);
+
+  void StatPath(const std::string& path,
+                const std::function<void(const FilesystemStat&)>& success_cb,
+                const std::function<void(FilesystemError)>& error_cb);
+
+  void FetchStorages(
+      const std::function<void(
+          const common::Storages&)>& success_cb,
+      const std::function<void(FilesystemError)>& error_cb);
+
+  void GetVirtualRoots(
+      const std::function<void(const common::VirtualRoots &)>& success_cb,
+      const std::function<void(FilesystemError)>& error_cb);
+
+  void CreateFile(const std::string& path,
+                  const std::function<void(const FilesystemStat&)>& success_cb,
+                  const std::function<void(FilesystemError)>& error_cb);
+
+  void Rename(const std::string& oldPath, const std::string& newPath,
+              const std::function<void(const FilesystemStat&)>& success_cb,
+              const std::function<void(FilesystemError)>& error_cb);
+
+  void MakeDirectory(const std::string& path,
+                     const std::function<void(FilesystemError)>& result_cb);
+
+  void ReadDir(
+          const std::string& path,
+          const std::function<void(const std::vector<std::string>&)>& success_cb,
+          const std::function<void(FilesystemError)>& error_cb);
+
+  void RemoveDirectory(
+          const std::string& path,
+          const std::function<void()>& success_cb,
+          const std::function<void(FilesystemError)>& error_cb);
+
+  void FileRead(const std::string& path,
+                size_t offset,
+                size_t length,
+                const std::function<void(const std::string&, uint8_t*, size_t)>& success_cb,
+                const std::function<void(FilesystemError)>& error_cb);
+
+  void FileWrite(const std::string& path,
+                 uint8_t* data_p,
+                 size_t data_size,
+                 size_t offset,
+                 const std::function<void(size_t data_size)>& success_cb,
+                 const std::function<void(FilesystemError)>& error_cb);
+
+  void CopyTo(const std::string& originFilePath,
+              const std::string& destinationFilePath, const bool overwrite,
+              const std::function<void()>& success_cb,
+              const std::function<void(FilesystemError)>& error_cb);
+
+  virtual void StartListening(bool is_private = false);
+  virtual void StopListening();
+  void OnUSBDeviceChanged(common::Storage const& _virtualStorage,
+                          common::StorageState _old, common::StorageState _new);
+  void AddListener(FilesystemStateChangeListener* listener);
+  void RemoveListener();
+};
+}  // namespace filesystem
+}  // namespace extension
+
+#endif  // FILESYSTEM_FILESYSTEM_MANAGER_H_
diff --git a/webWidgetTCT_device/src/filesystem/filesystem_stat.cc b/webWidgetTCT_device/src/filesystem/filesystem_stat.cc
new file mode 100755 (executable)
index 0000000..04172ab
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2015 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 "filesystem_stat.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <common/logger.h>
+#include <common/tools.h>
+#include <common/scope_exit.h>
+
+namespace extension {
+namespace filesystem {
+
+using common::tools::GetErrorString;
+
+FilesystemStat::FilesystemStat()
+    : error(FilesystemError::None),
+      valid(false),
+      isFile(false),
+      isDirectory(false),
+      readOnly(false),
+      ctime(0),
+      mtime(0),
+      size(0),
+      nlink(0) {
+}
+
+picojson::value FilesystemStat::toJSON() const {
+  LoggerD("Enter");
+  picojson::value retval = picojson::value(picojson::object());
+  picojson::object& obj = retval.get<picojson::object>();
+
+  obj["path"] = picojson::value(path);
+  obj["isFile"] = picojson::value(isFile);
+  obj["isDirectory"] = picojson::value(isDirectory);
+  obj["readOnly"] = picojson::value(readOnly);
+  obj["ctime"] = picojson::value(static_cast<double>(ctime));
+  obj["mtime"] = picojson::value(static_cast<double>(mtime));
+  obj["size"] = picojson::value(static_cast<double>(size));
+  obj["nlink"] = picojson::value(static_cast<double>(nlink));
+
+  return retval;
+}
+
+FilesystemStat FilesystemStat::getStat(const std::string& path) {
+  LoggerD("Enter");
+  struct stat aStatObj;
+  FilesystemStat _result;
+
+  LoggerD("enter");
+
+  if (0 != stat(path.c_str(), &aStatObj)) {
+    LoggerE("Failed to stat path %s: (%d) %s", path.c_str(), errno, GetErrorString(errno).c_str());
+    if (ENOENT == errno) {
+      _result.error = FilesystemError::NotFound;
+    } else {
+      _result.error = FilesystemError::InvalidValue;
+    }
+    return _result;
+  }
+
+  _result.path = path;
+  _result.readOnly = true;
+  if (getuid() == aStatObj.st_uid && (aStatObj.st_mode & S_IWUSR) == S_IWUSR) {
+    _result.readOnly = false;
+  } else if (getgid() == aStatObj.st_gid &&
+             (aStatObj.st_mode & S_IWGRP) == S_IWGRP) {
+    _result.readOnly = false;
+  } else if ((aStatObj.st_mode & S_IWOTH) == S_IWOTH) {
+    _result.readOnly = false;
+  }
+
+  _result.isDirectory = S_ISDIR(aStatObj.st_mode);
+  _result.isFile = S_ISREG(aStatObj.st_mode);
+  _result.ctime = aStatObj.st_ctim.tv_sec;
+  _result.mtime = aStatObj.st_mtim.tv_sec;
+  _result.size = aStatObj.st_size;
+  _result.nlink = 0;
+  if (_result.isDirectory) {
+    // Count entries in directory
+    DIR* dir = opendir(path.c_str());
+    if (!dir) {
+      LoggerE("Cannot open directory: %s", GetErrorString(errno).c_str());
+      return _result;
+    }
+    SCOPE_EXIT {
+      (void) closedir(dir);
+    };
+
+    struct dirent entry;
+    struct dirent *result = nullptr;
+    int status;
+
+    while ( (0 == (status = readdir_r(dir, &entry, &result) ) && result != nullptr) ) {
+      std::string name = result->d_name;
+      if (name == "." || name == "..") {
+        continue;
+      }
+      _result.nlink++;
+    }
+
+    if (status != 0) {
+      LoggerE("Cannot count files in directory: %s", GetErrorString(errno).c_str());
+      return _result;
+    }
+  }
+
+  _result.valid = true;
+  return _result;
+}
+}  // namespace filesystem
+}  // namespace extension
diff --git a/webWidgetTCT_device/src/filesystem/filesystem_stat.h b/webWidgetTCT_device/src/filesystem/filesystem_stat.h
new file mode 100755 (executable)
index 0000000..f25429e
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2015 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 FILESYSTEM_FILESYSTEM_STAT_H
+#define FILESYSTEM_FILESYSTEM_STAT_H
+
+#include <string>
+
+#include "common/picojson.h"
+
+#include "filesystem/filesystem_utils.h"
+
+namespace extension {
+namespace filesystem {
+
+class FilesystemStat {
+  FilesystemStat();
+
+ public:
+  FilesystemError error;
+  bool valid;
+
+  std::string path;
+  bool isFile;
+  bool isDirectory;
+  bool readOnly;
+  int64_t ctime;
+  int64_t mtime;
+  size_t size;
+  size_t nlink;
+
+  picojson::value toJSON() const;
+
+  static FilesystemStat getStat(const std::string& path);
+};
+}  // namespace filesystem
+}  // namespace extension
+
+#endif  // FILESYSTEM_FILESYSTEM_STAT_H
diff --git a/webWidgetTCT_device/src/filesystem/filesystem_utils.cc b/webWidgetTCT_device/src/filesystem/filesystem_utils.cc
new file mode 100755 (executable)
index 0000000..50230c4
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2015 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 "filesystem_utils.h"
+
+#include <glib.h>
+#include <libgen.h>
+#include "common/logger.h"
+
+namespace FilesystemUtils {
+std::string get_storage_dir_path(int id, storage_directory_e typeToCheck) {
+  LoggerD("Enter");
+  char* platformPath = NULL;
+  int result = storage_get_directory(id, typeToCheck, &platformPath);
+  if (result != STORAGE_ERROR_NONE) {
+    LoggerD("Cannot retrieve path for type %i: %d (%s)", typeToCheck, result,
+            get_error_message(result));
+    return std::string();
+  }
+  std::string path = std::string(platformPath);
+  free(platformPath);
+  return path;
+}
+
+std::string get_dirname(const std::string& path) {
+  char* dir = g_path_get_dirname(path.c_str());
+  if (dir) {
+    std::string dir_result(dir);
+    g_free(dir);
+    return dir_result;
+  } else {
+    return std::string(".");
+  }
+}
+
+std::string get_basename(const std::string& path) {
+  // basename will modify content: pass a copy
+  std::string buf = path.c_str();
+  return std::string(basename(const_cast<char*>(buf.c_str())));
+}
+}
diff --git a/webWidgetTCT_device/src/filesystem/filesystem_utils.h b/webWidgetTCT_device/src/filesystem/filesystem_utils.h
new file mode 100755 (executable)
index 0000000..3522c59
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2015 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 FILESYSTEM_FILESYSTEM_UTILS_H
+#define FILESYSTEM_FILESYSTEM_UTILS_H
+
+#include <string>
+#include <storage-expand.h>
+#include "common/picojson.h"
+
+namespace extension {
+namespace filesystem {
+
+enum class FilesystemError {
+  None,
+  NotFound,
+  FileExists,
+  DirectoryExists,
+  PermissionDenied,
+  IOError,
+  InvalidValue,
+  Other
+};
+}  // namespace filesystem
+}  // namespace extension
+
+namespace FilesystemUtils {
+
+/**
+ * @brief get_storage_dir_path attempts to get path from storage.
+ * If path cannot be retrieved then an empty string is returned.
+ *
+ */
+std::string get_storage_dir_path(int id, storage_directory_e typeToCheck);
+
+std::string get_dirname(const std::string& path);
+std::string get_basename(const std::string& path);
+}
+
+#endif  // FILESYSTEM_FILESYSTEM_UTILS_H
diff --git a/webWidgetTCT_device/src/filesystem/js/base64.js b/webWidgetTCT_device/src/filesystem/js/base64.js
new file mode 100755 (executable)
index 0000000..cdbd518
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+var Base64 = {
+  _b64: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',
+  encode: function(data) {
+    var output = '';
+    var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
+    var i = 0;
+
+    data = this._utf8_encode(data);
+
+    while (i < data.length) {
+
+      chr1 = data.charCodeAt(i++);
+      chr2 = data.charCodeAt(i++);
+      chr3 = data.charCodeAt(i++);
+
+      enc1 = chr1 >> 2;
+      enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
+      enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
+      enc4 = chr3 & 63;
+
+      if (isNaN(chr2)) {
+        enc3 = enc4 = 64;
+      } else if (isNaN(chr3)) {
+        enc4 = 64;
+      }
+
+      output += this._b64.charAt(enc1) + this._b64.charAt(enc2) +
+                this._b64.charAt(enc3) + this._b64.charAt(enc4);
+
+    }
+
+    return output;
+  },
+  decode: function(data) {
+    var output = '';
+    var chr1, chr2, chr3;
+    var enc1, enc2, enc3, enc4;
+    var i = 0;
+
+    data = data.replace(/[^A-Za-z0-9\+\/\=]/g, '');
+
+    while (i < data.length) {
+
+      enc1 = this._b64.indexOf(data.charAt(i++));
+      enc2 = this._b64.indexOf(data.charAt(i++));
+      enc3 = this._b64.indexOf(data.charAt(i++));
+      enc4 = this._b64.indexOf(data.charAt(i++));
+
+      chr1 = (enc1 << 2) | (enc2 >> 4);
+      chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
+      chr3 = ((enc3 & 3) << 6) | enc4;
+
+      output += String.fromCharCode(chr1);
+
+      if (enc3 !== 64) {
+        output += String.fromCharCode(chr2);
+      }
+      if (enc4 !== 64) {
+        output += String.fromCharCode(chr3);
+      }
+
+    }
+
+    output = this._utf8_decode(output);
+
+    return output;
+  },
+  _utf8_encode: function(str) {
+    str = str.replace(/\r\n/g, '\n');
+    var utftext = '';
+
+    for (var n = 0; n < str.length; n++) {
+
+      var c = str.charCodeAt(n);
+
+      if (c < 128) {
+        utftext += String.fromCharCode(c);
+      }
+      else if ((c > 127) && (c < 2048)) {
+        utftext += String.fromCharCode((c >> 6) | 192);
+        utftext += String.fromCharCode((c & 63) | 128);
+      }
+      else {
+        utftext += String.fromCharCode((c >> 12) | 224);
+        utftext += String.fromCharCode(((c >> 6) & 63) | 128);
+        utftext += String.fromCharCode((c & 63) | 128);
+      }
+
+    }
+
+    return utftext;
+  },
+  _utf8_decode: function(utftext) {
+    var str = '';
+    var i = 0, c = 0, c1 = 0, c2 = 0;
+
+    while (i < utftext.length) {
+
+      c = utftext.charCodeAt(i);
+
+      if (c < 128) {
+        str += String.fromCharCode(c);
+        i++;
+      }
+      else if ((c > 191) && (c < 224)) {
+        c1 = utftext.charCodeAt(i + 1);
+        str += String.fromCharCode(((c & 31) << 6) | (c1 & 63));
+        i += 2;
+      }
+      else {
+        c1 = utftext.charCodeAt(i + 1);
+        c2 = utftext.charCodeAt(i + 2);
+        str += String.fromCharCode(((c & 15) << 12) | ((c1 & 63) << 6) | (c2 & 63));
+        i += 3;
+      }
+
+    }
+
+    return str;
+  }
+};
diff --git a/webWidgetTCT_device/src/filesystem/js/common.js b/webWidgetTCT_device/src/filesystem/js/common.js
new file mode 100755 (executable)
index 0000000..f2eb4c1
--- /dev/null
@@ -0,0 +1,352 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+var utils_ = xwalk.utils;
+var type_ = utils_.type;
+var converter_ = utils_.converter;
+var validator_ = utils_.validator;
+var types_ = validator_.Types;
+var native_ = new xwalk.utils.NativeManager(extension);
+
+function SetReadOnlyProperty(obj, n, v) {
+  Object.defineProperty(obj, n, {value: v, writable: false});
+}
+
+var FileSystemStorageType = {
+  INTERNAL: 'INTERNAL',
+  EXTERNAL: 'EXTERNAL'
+};
+
+var FileSystemStorageState = {
+  MOUNTED: 'MOUNTED',
+  REMOVED: 'REMOVED',
+  UNMOUNTABLE: 'UNMOUNTABLE'
+};
+
+var FileMode = {
+  r: 'r',
+  rw: 'rw',
+  w: 'w',
+  a: 'a'
+};
+
+var commonFS_ = (function() {
+  var cacheReady = false;
+  var listenerRegistered = false;
+  var cacheVirtualToReal = {};
+  var cacheStorages = [];
+  var uriPrefix = 'file://';
+
+  function clearCache() {
+    cacheVirtualToReal = {};
+    cacheStorages = [];
+    cacheReady = false;
+  }
+
+  function SynchronizeCallbacks(result) {
+      clearCache();
+    }
+  
+  function initCache() {
+    if (cacheReady) {
+      return;
+    }
+
+    var result = native_.callSync('Filesystem_fetchVirtualRoots', {});
+    if (native_.isFailure(result)) {
+      throw native_.getErrorObject(result);
+    }
+    var virtualRoots = native_.getResultObject(result);
+    for (var i = 0; i < virtualRoots.length; ++i) {
+      cacheVirtualToReal[virtualRoots[i].name] = {
+        path: virtualRoots[i].path,
+        label: virtualRoots[i].name,
+        type: FileSystemStorageType.INTERNAL,
+        state: FileSystemStorageState.MOUNTED
+      };
+    }
+
+    var result = native_.callSync('FileSystemManager_fetchStorages', {});
+    if (native_.isFailure(result)) {
+      throw native_.getErrorObject(result);
+    }
+
+    var storages = native_.getResultObject(result);
+    for (var i = 0; i < storages.length; ++i) {
+      cacheStorages.push({
+        path: storages[i].path,
+        label: storages[i].name,
+        type: storages[i].type,
+        state: storages[i].state,
+        storage_id: storages[i].storage_id
+      });
+    }
+
+    if (!listenerRegistered) {
+      try {
+          native_.addListener('SynchronizeStorages', SynchronizeCallbacks);
+          var result = native_.callSync('FileSystemManager_addStorageStateChangeListener', { isPrivate : true } );
+          if (native_.isFailure(result) ) {
+              throw native_.getErrorObject(result);
+          }
+        listenerRegistered = true;
+      } catch (e) {
+        console.log('Failed to register storage change listener, ' +
+                    'storage information may be corrupted: ' + e.message);
+      }
+    }
+
+    cacheReady = true;
+  }
+
+  function mergeMultipleSlashes(str) {
+    var retStr = str.replace(/(^(file\:\/\/\/)|^(file\:\/\/)|\/)\/{0,}/g, '$1');
+    return retStr;
+  }
+
+  function removeDotsFromPath(str) {
+    if(str === undefined){
+        return str;
+    }
+
+    var _pathTokens = str.split('/');
+    var _correctDir = [];
+    var _fileRealPath = _pathTokens[0];
+    _correctDir.push(_pathTokens[0]);
+    for (var i = 1; i < _pathTokens.length; ++i) {
+      if(_pathTokens[i] == "..") {
+        if (_fileRealPath == '') {
+          _fileRealPath = undefined;
+          break;
+        }
+        var _lastDir = _correctDir.pop();
+        _fileRealPath = _fileRealPath.substring(0, _fileRealPath.length - _lastDir.length - 1);
+      } else if(_pathTokens[i] != "."){
+        _fileRealPath += '/' + _pathTokens[i];
+        _correctDir.push(_pathTokens[i]);
+      }
+    }
+    return _fileRealPath;
+  }
+
+  function checkPathWithoutDots(aPath) {
+    if (-1 !== aPath.indexOf('/../')) {
+      return false;
+    }
+    if (-1 !== aPath.indexOf('/./')) {
+      return false;
+    }
+    // check if path ends with '/.' or '/..'
+    if (aPath.match(/\/\.\.?$/)) {
+      return false;
+    }
+    // check if path starts with './' or '../'
+    if (aPath.match(/^\.\.?\//)) {
+      return false;
+    }
+    return true;
+  }
+
+  function toRealPath(aPath) {
+    var _fileRealPath = '';
+
+    aPath = mergeMultipleSlashes(aPath);
+
+    if (aPath.indexOf(uriPrefix) === 0) {
+      _fileRealPath = aPath.substr(uriPrefix.length);
+    } else if (aPath[0] !== '/') {
+      //virtual path
+      initCache();
+
+      var _pathTokens = aPath.split('/');
+
+      if (cacheVirtualToReal[_pathTokens[0]]) {
+        _fileRealPath = cacheVirtualToReal[_pathTokens[0]].path;
+        for (var i = 1; i < _pathTokens.length; ++i) {
+          _fileRealPath += '/' + _pathTokens[i];
+        }
+      } else {
+        //If path token is not present in cache then it is invalid
+        _fileRealPath = undefined;
+        // check storages
+        for (var j = 0; j < cacheStorages.length; ++j) {
+          if (cacheStorages[j].label === _pathTokens[0]) {
+            _fileRealPath = cacheStorages[j].path;
+            for (var i = 1; i < _pathTokens.length; ++i) {
+              _fileRealPath += '/' + _pathTokens[i];
+            }
+            break;
+          }
+        }
+      }
+    } else {
+      _fileRealPath = aPath;
+    }
+    // this line makes that '.' and '..' is supported in paths, but each method handle those cases
+    // and return error (see commonFS_.checkPathWithoutDots() method)
+    _fileRealPath = removeDotsFromPath(_fileRealPath);
+    return _fileRealPath;
+  }
+
+  function toVirtualPath(aPath) {
+    aPath = mergeMultipleSlashes(aPath);
+    var _virtualPath = aPath;
+
+    if (_virtualPath.indexOf(uriPrefix) === 0) {
+      _virtualPath = _virtualPath.substr(uriPrefix.length);
+    }
+
+    initCache();
+
+    for (var virtual_root in cacheVirtualToReal) {
+      var real_root_path = cacheVirtualToReal[virtual_root].path;
+      if (_virtualPath.indexOf(real_root_path, 0) === 0) {
+        return _virtualPath.replace(real_root_path, virtual_root);
+      }
+    }
+
+    return _virtualPath;
+  }
+
+  function getFileInfo(aStatObj, secondIter, aMode) {
+    var _result = {},
+        _pathTokens,
+        _fileParentPath = '',
+        i;
+    var aPath = toVirtualPath(aStatObj.path);
+
+    _result.readOnly = aStatObj.readOnly;
+    _result.isFile = aStatObj.isFile;
+    _result.isDirectory = aStatObj.isDirectory;
+    _result.created = new Date(aStatObj.ctime * 1000);
+    _result.modified = new Date(aStatObj.mtime * 1000);
+    _result.fullPath = aPath;
+    _result.fileSize = aStatObj.size;
+    _result.mode = aMode;
+    if (_result.isDirectory) {
+      try {
+        _result.length = aStatObj.nlink;
+      } catch (err) {
+        _result.length = 0;
+      }
+    } else {
+      _result.length = undefined;
+    }
+
+    _pathTokens = aPath.split('/');
+    if (_pathTokens.length > 1) {
+      for (i = 0; i < _pathTokens.length - 1; ++i) {
+        _fileParentPath += _pathTokens[i] + '/';
+      }
+      _result.path = _fileParentPath;
+      _result.name = _pathTokens[_pathTokens.length - 1];
+      _result.parent = (secondIter) ? null : _fileParentPath;
+    } else {
+      _result.parent = null;
+      _result.path = aPath;
+      _result.name = '';
+    }
+    return _result;
+  }
+
+  function isLocationAllowed(aPath) {
+    if (!aPath) {
+      return false;
+    }
+    initCache();
+    if (aPath.indexOf(cacheVirtualToReal.ringtones.path) === 0) {
+      return false;
+    }
+    if (aPath.indexOf(cacheVirtualToReal['wgt-package'].path) === 0) {
+      return false;
+    }
+
+    return true;
+  }
+
+  function f_isSubDir(fullPathToCheck, fullPath) {
+    var realFullPath = toRealPath(fullPath);
+    return ((-1 !== fullPathToCheck.indexOf(realFullPath)) && (fullPathToCheck !== realFullPath));
+  };
+
+  function f_isCorrectRelativePath(relativePath) {
+    return ((0 !== relativePath.indexOf('/')) &&
+        (0 !== relativePath.indexOf('\\')) &&
+        (-1 === relativePath.indexOf('?')) &&
+        (-1 === relativePath.indexOf('*')) &&
+        (-1 === relativePath.indexOf(':')) &&
+        (-1 === relativePath.indexOf('"')) &&
+        (-1 === relativePath.indexOf('<')) &&
+        (-1 === relativePath.indexOf('>')));
+  };
+
+  function cloneStorage(storage) {
+
+    return {
+      label: storage.label,
+      type: storage.type,
+      state: storage.state
+    };
+  }
+
+  function getStorage(label) {
+    initCache();
+    for (var i = 0; i < cacheStorages.length; ++i) {
+      if (cacheStorages[i].label === label) {
+        return cloneStorage(cacheStorages[i]);
+      }
+    }
+
+    for (var key in cacheVirtualToReal) {
+        if (cacheVirtualToReal.hasOwnProperty(key)) {
+            if(cacheVirtualToReal[key].label === label) {
+              return cloneStorage(cacheVirtualToReal[key]);
+            }
+        }
+    }
+
+    return null;
+  }
+
+  function getAllStorages() {
+    var ret = [];
+    initCache();
+    for (var i = 0; i < cacheStorages.length; ++i) {
+      ret.push(cloneStorage(cacheStorages[i]));
+    }
+
+    for (var key in cacheVirtualToReal) {
+        if (cacheVirtualToReal.hasOwnProperty(key)) {
+          ret.push(cloneStorage(cacheVirtualToReal[key]));
+        }
+    }
+
+    return ret;
+  }
+
+  return {
+    clearCache: clearCache,
+    checkPathWithoutDots: checkPathWithoutDots,
+    toRealPath: toRealPath,
+    toVirtualPath: toVirtualPath,
+    getFileInfo: getFileInfo,
+    isLocationAllowed: isLocationAllowed,
+    f_isSubDir: f_isSubDir,
+    f_isCorrectRelativePath: f_isCorrectRelativePath,
+    getStorage: getStorage,
+    getAllStorages: getAllStorages
+  };
+})();
diff --git a/webWidgetTCT_device/src/filesystem/js/file.js b/webWidgetTCT_device/src/filesystem/js/file.js
new file mode 100755 (executable)
index 0000000..13f9589
--- /dev/null
@@ -0,0 +1,946 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+function File(data) {
+  function fileSizeGetter() {
+    var _realPath = commonFS_.toRealPath(this.fullPath);
+    var _result = native_.callSync('File_statSync', {location: _realPath});
+    var _aStatObj = native_.getResultObject(_result);
+    return _aStatObj.isFile ? _aStatObj.size : undefined;
+  }
+
+  Object.defineProperties(this, {
+    parent: {
+      value: (function(data) {
+        try {
+          if (data.parent) { // prevent recursive - only one parent
+            var _parentPath = data.path.substr(0, data.path.length - 1);
+            var _location = {location: commonFS_.toRealPath(_parentPath)};
+            var _result = native_.callSync('File_statSync', _location);
+            var _statObj = native_.getResultObject(_result);
+            var _info = commonFS_.getFileInfo(_statObj, true);
+            return new File(_info);
+          } else {
+            return null;
+          }
+        } catch (err) {
+          console.log(err.name, err.message);
+          return null;
+        }
+      }(data)),
+      writable: false,
+      enumerable: true
+    },
+    readOnly: {value: data.readOnly, writable: false, enumerable: true},
+    isFile: {value: data.isFile, writable: false, enumerable: true},
+    isDirectory: {value: data.isDirectory, writable: false, enumerable: true},
+    created: {value: data.created, writable: false, enumerable: true},
+    modified: {value: data.modified, writable: false, enumerable: true},
+    path: {value: data.path, writable: false, enumerable: true},
+    name: {value: data.name, writable: false, enumerable: true},
+    fullPath: {value: data.fullPath, writable: false, enumerable: true},
+    fileSize: {enumerable: true, set: function() {
+    }, get: fileSizeGetter},
+    length: {value: data.length, writable: false, enumerable: true},
+    mode: {value: data.mode, writable: false}
+  });
+}
+
+File.prototype.toURI = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.FILESYSTEM_READ);
+  return 'file://' + commonFS_.toRealPath(this.fullPath);
+};
+
+function stringToRegex(str) {
+  var _regString = '^';
+  if (str === '') {
+    return new RegExp(_regString, 'i');
+  }
+
+  str = str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&');
+
+  var _percentTokens = str.split('%');
+  var i;
+  for (i = 0; i < _percentTokens.length - 1; ++i) {
+    _regString = _regString + _percentTokens[i];
+    if (_regString[_regString.length - 1] === '\\') {
+      _regString = _regString.split('');
+      _regString.pop();
+      _regString = _regString.join('') + '%';
+    }
+    else if (_regString.lastIndexOf('\*') !== _regString.length - 2) {
+      _regString = _regString + '.*';
+    }
+  }
+  return new RegExp(_regString + _percentTokens[i] + '$', 'i');
+}
+
+
+function createFilter(fileFilter) {
+  if (type_.isNull(fileFilter)) {
+    return null;
+  }
+
+  var FileFilter = {
+    name: 'name',
+    startModified: 'startModified',
+    endModified: 'endModified',
+    startCreated: 'startCreated',
+    endCreated: 'endCreated'
+  };
+
+  var _fileFilter = {}, i;
+  for (i in fileFilter) {
+    if (!type_.isNullOrUndefined(fileFilter[i])) {
+      if (Object.keys(FileFilter).indexOf(i) >= 0) {
+        if (FileFilter.name === i) {
+          _fileFilter[i] = stringToRegex(fileFilter[i]);
+        } else {
+          if (!(fileFilter[i] instanceof Date)) {
+            throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+                'Invalid date');
+          }
+          _fileFilter[i] = fileFilter[i];
+        }
+      }
+    }
+  }
+
+  return !type_.isEmptyObject(_fileFilter) ? _fileFilter : null;
+}
+
+function matchRange(value, min, max) {
+  if (min !== undefined && value < min) {
+    return false;
+  }
+  if (max !== undefined && value > max) {
+    return false;
+  }
+  return true;
+}
+
+function matchName(value, filter_name) {
+  if (filter_name === undefined || filter_name.test(value)) {
+    return true;
+  }
+  return false;
+}
+
+function checkFile(file, fileFilter) {
+  if (!matchName(file.name, fileFilter.name)) {
+    return false;
+  }
+
+  if (!matchRange(file.modified, fileFilter.startModified, fileFilter.endModified)) {
+    return false;
+  }
+
+  if (!matchRange(file.created, fileFilter.startCreated, fileFilter.endCreated)) {
+    return false;
+  }
+
+  return true;
+}
+
+File.prototype.listFiles = function(onsuccess, onerror, filter) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.FILESYSTEM_READ);
+
+  var args = validator_.validateArgs(arguments, [
+    {name: 'onsuccess', type: types_.FUNCTION},
+    {name: 'onerror', type: types_.FUNCTION, optional: true, nullable: true},
+    {name: 'filter', type: types_.DICTIONARY, optional: true, nullable: true}
+  ]);
+
+  if (!arguments.length) {
+    throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR,
+        'Arguments missing');
+  }
+  if (!this.isDirectory) {
+    setTimeout(function() {
+      native_.callIfPossible(args.onerror,
+          new WebAPIException(WebAPIException.IO_ERR,
+          'File object which call this method is not directory'));
+    }, 0);
+    return;
+  }
+
+  var _fileFilter = null;
+
+  if (args.has.filter) {
+    _fileFilter = createFilter(args.filter);
+  }
+
+  var _myPath = this.fullPath;
+  var _realMyPath = commonFS_.toRealPath(_myPath);
+
+  var data = {
+    pathToDir: _realMyPath
+  };
+
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.onerror, native_.getErrorObject(result));
+      return;
+    }
+    var aFiles = native_.getResultObject(result);
+    var _result = [],
+        i,
+        _statObj,
+        _fileInfo;
+    for (i = 0; i < aFiles.length; ++i) {
+      _statObj = aFiles[i];
+      _fileInfo = commonFS_.getFileInfo(_statObj);
+
+      if (_fileFilter === null) {
+        _result.push(new File(_fileInfo));
+      } else if (checkFile(_fileInfo, _fileFilter)) {
+        _result.push(new File(_fileInfo));
+      }
+    }
+    native_.callIfPossible(args.onsuccess, _result);
+  };
+
+  native_.call('File_readDir', data, callback);
+};
+
+var Encoding = {
+  'utf-8': 'utf-8',
+  'iso-8859-1': 'iso-8859-1',
+  'sjis': 'sjis',  // backward compatibility
+  'null': 'utf-8',
+  'undefined': 'utf-8'
+};
+
+function _checkEncoding(encoding) {
+  encoding = String(encoding).toLowerCase();
+  if (undefined === Encoding[encoding]) {
+    throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR,
+        'Argument "encoding" has invalid value: ' + encoding);
+  } else {
+    return Encoding[encoding];
+  }
+}
+
+File.prototype.openStream = function(mode, onsuccess, onerror, encoding) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.FILESYSTEM_READ);
+
+  var args = validator_.validateArgs(arguments, [
+    {name: 'mode', type: types_.ENUM, values: ['r', 'rw', 'w', 'a']},
+    {name: 'onsuccess', type: types_.FUNCTION},
+    {name: 'onerror', type: types_.FUNCTION, optional: true, nullable: true},
+    {name: 'encoding', type: types_.STRING, optional: true, nullable: true}
+  ]);
+
+  if (arguments.length < 2) {
+    throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR,
+        'Arguments missing');
+  }
+  if (this.mode === 'r' && args.mode !== 'r') {
+    setTimeout(function() {
+      native_.callIfPossible(args.onerror,
+          new WebAPIException(WebAPIException.INVALID_VALUES_ERR, 'Read only mode'));
+    }, 0);
+    return;
+  }
+
+  if (this.isDirectory) {
+    var directoryMessage = 'This method should be called on file, not directory';
+    setTimeout(function() {
+      native_.callIfPossible(args.onerror, new WebAPIException(WebAPIException.IO_ERR,
+          directoryMessage));
+    }, 0);
+    return;
+  }
+
+  args.encoding = _checkEncoding(args.encoding);
+
+  var _realPath = commonFS_.toRealPath(this.fullPath);
+  var _result = native_.callSync('File_statSync', {location: _realPath});
+  if (native_.isFailure(_result)) {
+    setTimeout(function() {
+      native_.callIfPossible(args.onerror,
+          new WebAPIException(WebAPIException.IO_ERR, 'File does not exist'));
+    }, 0);
+    return;
+  }
+
+  var fileStream = new FileStream(this, args.mode, args.encoding);
+  setTimeout(function() {
+    native_.callIfPossible(args.onsuccess, fileStream);
+  }, 0);
+};
+
+File.prototype.readAsText = function(onsuccess, onerror, encoding) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.FILESYSTEM_READ);
+
+  var args = validator_.validateArgs(arguments, [
+    {name: 'onsuccess', type: types_.FUNCTION},
+    {name: 'onerror', type: types_.FUNCTION, optional: true, nullable: true},
+    {name: 'encoding', type: types_.STRING, optional: true, nullable: true}
+  ]);
+
+  if (!arguments.length) {
+    throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR,
+        'Arguments missing');
+  }
+  if (this.isDirectory) {
+    setTimeout(function() {
+      native_.callIfPossible(args.onerror,
+          new WebAPIException(WebAPIException.IO_ERR,
+              'File object which call this method is directory'));
+    }, 0);
+    return;
+  }
+
+  args.encoding = _checkEncoding(args.encoding);
+
+  var data = {
+    location: commonFS_.toRealPath(this.fullPath),
+    offset: 0,
+    length: 1024,
+    encoding: args.encoding,
+    is_base64: false
+  };
+
+  function readFile() {
+    var result, encoded, str = '';
+
+    do {
+      result = native_.callSyncData('File_readSync', data);
+
+      if (native_.isFailure(result)) {
+        setTimeout(function() {
+          native_.callIfPossible(args.onerror, native_.getErrorObject(result));
+        }, 0);
+        return;
+      }
+      str += result.output;
+      data.offset += result.reply.data_size;
+    } while (result.reply.data_size);
+
+    setTimeout(function() {
+      native_.callIfPossible(args.onsuccess, str);
+    }, 0);
+  }
+
+  setTimeout(readFile, 0);
+};
+
+File.prototype.copyTo = function(originFilePath, destinationFilePath, overwrite, onsuccess, onerror) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.FILESYSTEM_WRITE);
+
+  var args = validator_.validateArgs(arguments, [
+    {name: 'originFilePath', type: types_.STRING},
+    {name: 'destinationFilePath', type: types_.STRING},
+    {name: 'overwrite', type: types_.BOOLEAN},
+    {name: 'onsuccess', type: types_.FUNCTION, optional: true, nullable: true},
+    {name: 'onerror', type: types_.FUNCTION, optional: true, nullable: true}
+  ]);
+
+  if (arguments.length < 3) {
+    throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR,
+        'Invalid arguments given');
+  }
+
+  if (this.isFile) {
+    setTimeout(function() {
+      native_.callIfPossible(args.onerror,
+          new WebAPIException(WebAPIException.IO_ERR,
+          'File object which call this method is not directory'));
+    }, 0);
+    return;
+  }
+
+  // Validation against '.' and '..' directories used in path - not allowed
+  var resultSource = commonFS_.checkPathWithoutDots(args.originFilePath);
+  var resultDestination = commonFS_.checkPathWithoutDots(args.destinationFilePath);
+  if (!resultSource || !resultDestination) {
+    // path contains dots - it is not allowed - return InvalidValuesError
+    setTimeout(function() {
+      native_.callIfPossible(args.onerror,
+          new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+          'Path contains \'.\' or \'..\' - it is not allowed.'));
+    }, 0);
+    return;
+  }
+
+  var _realOriginalPath = commonFS_.toRealPath(args.originFilePath);
+  var _realDestinationPath = commonFS_.toRealPath(args.destinationFilePath);
+
+  if (!_realOriginalPath) {
+      setTimeout(function() {
+        native_.callIfPossible(args.onerror,
+            new WebAPIException(WebAPIException.NOT_FOUND_ERR,
+            'Source path is not valid'));
+      }, 0);
+      return;
+  }
+
+  if (!_realDestinationPath) {
+      setTimeout(function() {
+        native_.callIfPossible(args.onerror,
+            new WebAPIException(WebAPIException.NOT_FOUND_ERR,
+            'Destination path is not valid'));
+      }, 0);
+      return;
+  }
+
+  var resultOldPath = native_.callSync('File_statSync', {location: _realOriginalPath});
+  if (native_.isFailure(resultOldPath)) {
+    setTimeout(function() {
+      native_.callIfPossible(args.onerror, native_.getErrorObject(resultOldPath));
+    }, 0);
+    return;
+  }
+  var _oldNode = native_.getResultObject(resultOldPath);
+
+  var addFileName = false;
+  var lastChar = _realDestinationPath.substr(_realDestinationPath.length -1);
+
+  var resultNewPath = native_.callSync('File_statSync', {location: _realDestinationPath});
+  if (native_.isSuccess(resultNewPath)) {
+    var _newNode = native_.getResultObject(resultNewPath);
+    if (_newNode.isDirectory) {
+      if (lastChar !== '/') {
+        _realDestinationPath += '/';
+      }
+      addFileName = true;
+    }
+  } else {
+    var destinationFileName, destinationDirectoryPath;
+    if (lastChar !== '/') {
+      destinationFileName = _realDestinationPath.split('/').pop();
+    }
+    destinationDirectoryPath = _realDestinationPath.substr(0, _realDestinationPath.lastIndexOf('/') + 1);
+
+    var resultDestinationDirectory = native_.callSync('File_statSync', {location: destinationDirectoryPath});
+    if (native_.isFailure(resultDestinationDirectory)) {
+      setTimeout(function() {
+        native_.callIfPossible(args.onerror, native_.getErrorObject(resultDestinationDirectory));
+      }, 0);
+      return;
+    }
+
+    if (destinationFileName.length == 0) {
+      addFileName = true;
+    }
+  }
+
+  if (_oldNode.isFile && addFileName) {
+    _realDestinationPath += '/' + _realOriginalPath.split('/').pop();
+  }
+
+  if (!args.overwrite) {
+    var resultPath = native_.callSync('File_statSync', {location: _realDestinationPath});
+    if (native_.isSuccess(resultPath)) {
+      setTimeout(function() {
+        native_.callIfPossible(args.onerror,
+            new WebAPIException(WebAPIException.IO_ERR, 'Overwrite is not allowed'));
+      }, 0);
+      return;
+    }
+  }
+
+  if (!commonFS_.f_isSubDir(_realOriginalPath, this.fullPath)) {
+    var m1 = 'Source file should be subdirectory of: ' + this.fullPath;
+    setTimeout(function() {
+      native_.callIfPossible(args.onerror,
+          new WebAPIException(WebAPIException.INVALID_VALUES_ERR, m1));
+    }, 0);
+    return;
+  }
+
+  if (!commonFS_.isLocationAllowed(_realDestinationPath)) {
+    var m2 = 'Destination is read only folder: ' + this.fullPath;
+    setTimeout(function() {
+      native_.callIfPossible(args.onerror,
+          new WebAPIException(WebAPIException.INVALID_VALUES_ERR, m2));
+    }, 0);
+    return;
+  }
+
+  var data = {
+    originFilePath: _realOriginalPath,
+    destinationFilePath: _realDestinationPath,
+    overwrite: args.overwrite
+  };
+
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.onerror,
+          new WebAPIException(WebAPIException.IO_ERR, result));
+      return;
+    }
+    native_.callIfPossible(args.onsuccess);
+  };
+
+  native_.call('File_copyTo', data, callback);
+};
+
+File.prototype.moveTo = function(originFilePath, destinationFilePath, overwrite, onsuccess, onerror) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.FILESYSTEM_WRITE);
+
+  var args = validator_.validateArgs(arguments, [
+    {name: 'originFilePath', type: types_.STRING},
+    {name: 'destinationFilePath', type: types_.STRING},
+    {name: 'overwrite', type: types_.BOOLEAN},
+    {name: 'onsuccess', type: types_.FUNCTION, optional: true, nullable: true},
+    {name: 'onerror', type: types_.FUNCTION, optional: true, nullable: true}
+  ]);
+
+  if (arguments.length < 3) {
+    throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR,
+        'Arguments missing');
+  }
+  if (this.isFile) {
+    setTimeout(function() {
+      native_.callIfPossible(args.onerror,
+          new WebAPIException(WebAPIException.IO_ERR,
+          'File object which call this method is not directory'));
+    }, 0);
+    return;
+  }
+
+  // Validation against '.' and '..' directories used in path - not allowed
+  var resultSource = commonFS_.checkPathWithoutDots(args.originFilePath);
+  var resultDestination = commonFS_.checkPathWithoutDots(args.destinationFilePath);
+  if (!resultSource || !resultDestination) {
+    // path contains dots - it is not allowed - return InvalidValuesError
+    setTimeout(function() {
+      native_.callIfPossible(args.onerror,
+          new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+          'Path contains \'.\' or \'..\' - it is not allowed.'));
+    }, 0);
+    return;
+  }
+
+  var _realOriginalPath = commonFS_.toRealPath(args.originFilePath);
+  var _realDestinationPath = commonFS_.toRealPath(args.destinationFilePath);
+
+  if (!_realOriginalPath) {
+      setTimeout(function() {
+        native_.callIfPossible(args.onerror,
+            new WebAPIException(WebAPIException.NOT_FOUND_ERR,
+            'Source path is not valid'));
+      }, 0);
+      return;
+  }
+
+  if (!_realDestinationPath) {
+      setTimeout(function() {
+        native_.callIfPossible(args.onerror,
+            new WebAPIException(WebAPIException.NOT_FOUND_ERR,
+            'Destination path is not valid'));
+      }, 0);
+      return;
+  }
+
+  var resultOldPath = native_.callSync('File_statSync', {location: _realOriginalPath});
+  if (native_.isFailure(resultOldPath)) {
+    setTimeout(function() {
+      native_.callIfPossible(args.onerror,
+          new WebAPIException(WebAPIException.NOT_FOUND_ERR,
+          'Source file is not avalaible'));
+    }, 0);
+    return;
+  }
+
+  if (!args.overwrite) {
+    var resultNewPath = native_.callSync('File_statSync', {location: _realDestinationPath});
+    if (native_.isSuccess(resultNewPath)) {
+      setTimeout(function() {
+        native_.callIfPossible(args.onerror,
+            new WebAPIException(WebAPIException.IO_ERR, 'Overwrite is not allowed'));
+      }, 0);
+      return;
+    }
+  }
+
+  if (!commonFS_.f_isSubDir(_realOriginalPath, this.fullPath)) {
+    var m1 = 'Source file should be subdirectory of: ' + this.fullPath;
+    setTimeout(function() {
+      native_.callIfPossible(args.onerror,
+          new WebAPIException(WebAPIException.INVALID_VALUES_ERR, m1));
+    }, 0);
+    return;
+  }
+
+  if (this.mode === 'r' || !commonFS_.isLocationAllowed(_realDestinationPath)) {
+    var m2 = 'Source/Destination is read only folder: ' + this.fullPath;
+    setTimeout(function() {
+      native_.callIfPossible(args.onerror,
+          new WebAPIException(WebAPIException.INVALID_VALUES_ERR, m2));
+    }, 0);
+    return;
+  }
+
+  var data = {
+    oldPath: _realOriginalPath,
+    newPath: _realDestinationPath
+  };
+
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.onerror, new WebAPIException(WebAPIException.IO_ERR,
+          result));
+      return;
+    }
+    native_.callIfPossible(args.onsuccess);
+  };
+
+  native_.call('File_rename', data, callback);
+};
+
+File.prototype.createDirectory = function(dirPath) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.FILESYSTEM_WRITE);
+
+  var args = validator_.validateArgs(arguments, [
+    {name: 'dirPath', type: types_.STRING}
+  ]);
+
+  if (!arguments.length) {
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+        'Invalid path');
+  }
+  if (!args.dirPath.length) {
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+        'Invalid path');
+  }
+
+  var _newPath = this.fullPath + '/' + args.dirPath,
+          _statObj,
+          _fileInfo;
+
+  // Validation against '.' and '..' directories used in path - not allowed
+  var result = commonFS_.checkPathWithoutDots(_newPath);
+  if (!result) {
+    // path contains dots - it is not allowed - return InvalidValuesError
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+          'Path contains \'.\' or \'..\' - it is not allowed.');
+  }
+
+  var _realNewPath = commonFS_.toRealPath(_newPath);
+
+  if (!_realNewPath) {
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+          'Path is not valid');
+  }
+
+  if (this.isDirectory) {
+    if (this.mode === 'r') {
+      throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+          'Invalid path or readonly access');
+    }
+
+    var _resultExist = native_.callSync('File_statSync', {location: _realNewPath});
+    if (native_.isSuccess(_resultExist)) {
+      throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+          'Directory already exist');
+    }
+
+    var result = native_.callSync('FileSystemManager_mkdirSync', {location: _realNewPath});
+    if (native_.isFailure(result)) {
+      throw new WebAPIException(WebAPIException.IO_ERR, native_.getErrorObject(result));
+    }
+
+    var _result = native_.callSync('File_statSync', {location: _realNewPath});
+    _statObj = native_.getResultObject(_result);
+
+    _fileInfo = commonFS_.getFileInfo(_statObj, false, this.mode);
+    return new File(_fileInfo);
+  } else {
+    throw new WebAPIException(WebAPIException.IO_ERR,
+        'File object which call this method is not directory');
+  }
+};
+
+File.prototype.createFile = function(relativeFilePath) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.FILESYSTEM_WRITE);
+
+  var args = validator_.validateArgs(arguments, [
+    {name: 'relativeFilePath', type: types_.STRING}
+  ]);
+
+  if (!arguments.length) {
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+        'Argument "relativeFilePath" missing');
+  }
+  if (this.isFile) {
+    throw new WebAPIException(WebAPIException.IO_ERR,
+        'File object which call this method is not directory');
+  }
+
+  if (!commonFS_.f_isCorrectRelativePath(args.relativeFilePath) || this.mode === 'r') {
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+        'Invalid path or readonly acces');
+  }
+
+  var _outputPath = this.fullPath + '/' + args.relativeFilePath;
+
+  // Validation against '.' and '..' directories used in path - not allowed
+  var result = commonFS_.checkPathWithoutDots(_outputPath);
+  if (!result) {
+    // path contains dots - it is not allowed - return InvalidValuesError
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+          'Path contains \'.\' or \'..\' - it is not allowed.');
+  }
+
+  var _outputRealPath = commonFS_.toRealPath(_outputPath);
+  if (!_outputRealPath) {
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+          'Path is not valid');
+  }
+  var _resultExist = native_.callSync('File_statSync', {location: _outputRealPath});
+
+  if (native_.isSuccess(_resultExist)) {
+    throw new WebAPIException(WebAPIException.IO_ERR, 'Overwrite is not allowed');
+  }
+
+  var result = native_.callSync('File_createSync', {location: _outputRealPath});
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+
+  var _result = native_.callSync('File_statSync', {location: _outputRealPath});
+  var _statObj = native_.getResultObject(_result);
+  var _fileInfo = commonFS_.getFileInfo(_statObj, false, this.mode);
+
+  return new File(_fileInfo);
+
+};
+
+File.prototype.resolve = function(filePath) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.FILESYSTEM_READ);
+
+  var args = validator_.validateArgs(arguments, [
+    {name: 'filePath', type: types_.STRING}
+  ]);
+
+  if (!arguments.length) {
+    throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR,
+        'Argument "filePath" missing');
+  }
+  if (this.isFile) {
+    throw new WebAPIException(WebAPIException.IO_ERR,
+        'File object which call this method is not directory');
+  }
+
+  if (!commonFS_.f_isCorrectRelativePath(args.filePath)) {
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR, 'Invalid path');
+  }
+
+  var _newPath = this.fullPath + '/' + args.filePath;
+
+  // Validation against '.' and '..' directories used in path - not allowed
+  var result = commonFS_.checkPathWithoutDots(_newPath);
+  if (!result) {
+    // path contains dots - it is not allowed - return InvalidValuesError
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+          'Path contains \'.\' or \'..\' - it is not allowed.');
+  }
+
+  var _realPath = commonFS_.toRealPath(_newPath);
+  if (!_realPath) {
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+          'Path is not valid');
+  }
+  var _result = native_.callSync('File_statSync', {location: _realPath});
+  if (native_.isFailure(_result)) {
+    throw new WebAPIException(WebAPIException.NOT_FOUND_ERR, native_.getErrorObject(_result));
+  }
+  var _statObj = native_.getResultObject(_result);
+  var _fileInfo = commonFS_.getFileInfo(_statObj, false, this.mode);
+  return new File(_fileInfo);
+
+};
+
+File.prototype.deleteDirectory = function(directoryPath, recursive, onsuccess, onerror) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.FILESYSTEM_WRITE);
+
+  var args = validator_.validateArgs(arguments, [
+    {name: 'directoryPath', type: types_.STRING},
+    {name: 'recursive', type: types_.BOOLEAN},
+    {name: 'onsuccess', type: types_.FUNCTION, optional: true, nullable: true},
+    {name: 'onerror', type: types_.FUNCTION, optional: true, nullable: true}
+  ]);
+
+  if (arguments.length < 2) {
+    throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR,
+        'Arguments missing');
+  }
+  if (this.mode === 'r') {
+    setTimeout(function() {
+      native_.callIfPossible(args.onerror,
+          new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+              'Invalid path or readonly access'));
+    }, 0);
+    return;
+  }
+
+  // Validation against '.' and '..' directories used in path - not allowed
+  var result = commonFS_.checkPathWithoutDots(args.directoryPath);
+  if (!result) {
+    // path contains dots - it is not allowed - return InvalidValuesError
+    setTimeout(function() {
+      native_.callIfPossible(args.onerror,
+          new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+          'Path contains \'.\' or \'..\' - it is not allowed.'));
+    }, 0);
+    return;
+  }
+
+  var _myPath = commonFS_.toRealPath(args.directoryPath);
+
+  if (_myPath !== undefined && !commonFS_.f_isSubDir(_myPath, this.fullPath)) {
+    var m1 = 'Deleted directory should be under the current directory: ' + this.fullPath;
+    setTimeout(function() {
+      native_.callIfPossible(args.onerror,
+          new WebAPIException(WebAPIException.INVALID_VALUES_ERR, m1));
+    }, 0);
+    return;
+  }
+
+  var _result = native_.callSync('File_statSync', {location: _myPath});
+  if (native_.isFailure(_result)) {
+    setTimeout(function() {
+      native_.callIfPossible(args.onerror,
+          new WebAPIException(WebAPIException.NOT_FOUND_ERR, 'Directory not found'));
+    }, 0);
+    return;
+  }
+  var _statObj = native_.getResultObject(_result);
+  var _info = commonFS_.getFileInfo(_statObj);
+  var _node = new File(_info);
+
+  if (!_node.isDirectory) {
+    setTimeout(function() {
+      native_.callIfPossible(args.onerror,
+          new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+          'It is file not directory'));
+    }, 0);
+    return;
+  } else {
+    _node.listFiles(
+        function(files) {
+          if (files.length > 0) {
+            if (!args.recursive) {
+              native_.callIfPossible(args.onerror,
+                  new WebAPIException(WebAPIException.IO_ERR,
+                  'Non empty folder ' + _myPath + ' passed for non recursive delete'));
+              return;
+            }
+          }
+          var data = {
+            pathToDelete: _myPath
+          };
+
+          var callback = function(result) {
+            if (native_.isFailure(result)) {
+              native_.callIfPossible(args.onerror, native_.getErrorObject(result));
+            }
+            native_.callIfPossible(args.onsuccess);
+          };
+
+          native_.call('File_removeDirectory', data, callback);
+        },
+        function() {
+          native_.callIfPossible(args.onerror,
+              new WebAPIException(WebAPIException.IO_ERR,
+              'List files failed for ' + _myPath));
+        }
+    );
+  }
+};
+
+File.prototype.deleteFile = function(filePath, onsuccess, onerror) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.FILESYSTEM_WRITE);
+
+  var args = validator_.validateArgs(arguments, [
+    {name: 'filePath', type: types_.STRING},
+    {name: 'onsuccess', type: types_.FUNCTION, optional: true, nullable: true},
+    {name: 'onerror', type: types_.FUNCTION, optional: true, nullable: true}
+  ]);
+
+  if (!arguments.length) {
+    throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR,
+        'Argument "filePath" missing');
+  }
+  if (this.isFile) {
+    setTimeout(function() {
+      native_.callIfPossible(args.onerror,
+          new WebAPIException(WebAPIException.IO_ERR,
+          'File object which call this method is not directory'));
+    }, 0);
+    return;
+  }
+
+  // Validation against '.' and '..' directories used in path - not allowed
+  var result = commonFS_.checkPathWithoutDots(args.filePath);
+  if (!result) {
+    // path contains dots - it is not allowed - return InvalidValuesError
+    setTimeout(function() {
+      native_.callIfPossible(args.onerror,
+          new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+          'Path contains \'.\' or \'..\' - it is not allowed.'));
+    }, 0);
+    return;
+  }
+
+  var _fileRealPath = commonFS_.toRealPath(args.filePath);
+
+  var _result = native_.callSync('File_statSync', {location: _fileRealPath});
+  if (native_.isFailure(_result)) {
+    setTimeout(function() {
+      native_.callIfPossible(args.onerror,
+          new WebAPIException(WebAPIException.NOT_FOUND_ERR, 'File is not avalaible'));
+    }, 0);
+    return;
+  }
+  var _statObj = native_.getResultObject(_result);
+
+  if (_statObj.isDirectory) {
+    var message = 'Requested object is a directory.';
+    setTimeout(function() {
+      native_.callIfPossible(args.onerror,
+          new WebAPIException(WebAPIException.INVALID_VALUES_ERR, message));
+    }, 0);
+    return;
+  }
+
+  if (!commonFS_.f_isSubDir(_fileRealPath, this.fullPath) || this.mode === 'r') {
+    var _message = 'Deleted file [' + args.filePath + '] should have write access ' +
+            'and should be subdirectory of: [' + this.fullPath + ']';
+    setTimeout(function() {
+      native_.callIfPossible(args.onerror,
+          new WebAPIException(WebAPIException.INVALID_VALUES_ERR, _message));
+    }, 0);
+    return;
+  }
+
+  var data = {
+    pathToFile: _fileRealPath
+  };
+
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.onerror, native_.getErrorObject(result));
+      return;
+    }
+    native_.callIfPossible(args.onsuccess);
+  };
+
+  native_.call('File_unlinkFile', data, callback);
+};
diff --git a/webWidgetTCT_device/src/filesystem/js/file_stream.js b/webWidgetTCT_device/src/filesystem/js/file_stream.js
new file mode 100755 (executable)
index 0000000..1d9f5a6
--- /dev/null
@@ -0,0 +1,323 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+function _checkClosed(stream) {
+  if (stream._closed) {
+    throw new WebAPIException(WebAPIException.IO_ERR, 'Stream is closed.');
+  }
+}
+
+function _checkReadAccess(mode) {
+  if (mode !== 'r' && mode !== 'rw') {
+    throw new WebAPIException(WebAPIException.IO_ERR, 'Stream is not in read mode.');
+  }
+}
+
+function _checkWriteAccess(mode) {
+  if (mode !== 'a' && mode !== 'w' && mode !== 'rw') {
+    throw new WebAPIException(WebAPIException.IO_ERR, 'Stream is not in write mode.');
+  }
+}
+
+function FileStream(data, mode, encoding) {
+  var _totalBytes = data.fileSize || 0;
+  var _position = mode === 'a' ? _totalBytes : 0;
+
+  Object.defineProperties(this, {
+    eof: {
+      get: function() {
+        return _totalBytes < _position;
+      },
+      set: function(v) {
+      },
+      enumerable: true
+    },
+    position: {
+      get: function() {
+        return _position;
+      },
+      set: function(v) {
+        _position = Math.max(0, v);
+      },
+      enumerable: true
+    },
+    bytesAvailable: {
+      get: function() {
+        return this.eof ? -1 : Math.max(0, _totalBytes - _position);
+      },
+      set: function(v) {
+      },
+      enumerable: true
+    },
+    _mode: {
+      value: mode,
+      writable: false,
+      enumerable: false
+    },
+    _encoding: {
+      value: encoding,
+      writable: false,
+      enumerable: false
+    },
+    _file: {
+      value: data,
+      writable: false,
+      enumerable: false
+    },
+    _closed: {
+      value: false,
+      writable: true,
+      enumerable: false
+    }
+  });
+
+  this.write = function() {
+    xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.FILESYSTEM_WRITE);
+
+    var args = validator_.validateArgs(arguments, [
+      {
+        name: 'stringData',
+        type: types_.STRING
+      }
+    ]);
+
+    _checkClosed(this);
+    _checkWriteAccess(this._mode);
+    if (!arguments.length) {
+      throw new WebAPIException(WebAPIException.NOT_FOUND_ERR,
+          'Argument "stringData" missing');
+    }
+
+    var data = {
+      location: commonFS_.toRealPath(this._file.fullPath),
+      offset: this.position,
+      length: args.stringData.length,
+      is_base64: false,
+    };
+    var result = native_.callSyncData('File_writeSync', data, "string", args.stringData);
+    if (native_.isFailure(result.reply)) {
+      throw new WebAPIException(WebAPIException.IO_ERR, 'Could not write');
+    }
+    this.position = this.position + result.reply.data_size;
+    _totalBytes = Math.max(this.position, _totalBytes);
+  };
+
+  this.writeBytes = function() {
+    xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.FILESYSTEM_WRITE);
+
+    var args = validator_.validateArgs(arguments, [
+      {
+        name: 'byteData',
+        type: types_.ARRAY
+      }
+    ]);
+    _checkClosed(this);
+    _checkWriteAccess(this._mode);
+    if (!arguments.length) {
+      throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR,
+          'Argument "byteData" missing');
+    }
+
+    var data = {
+      location: commonFS_.toRealPath(this._file.fullPath),
+      offset: this.position,
+      length: args.byteData.length,
+      is_base64: false,
+    };
+
+    var result = native_.callSyncData('File_writeSync', data, "octet", args.byteData);
+
+    if (native_.isFailure(result.reply)) {
+      throw new WebAPIException(WebAPIException.IO_ERR, 'Could not write');
+    }
+    this.position = this.position + result.reply.data_size;
+    _totalBytes = Math.max(this.position, _totalBytes);
+  };
+}
+
+FileStream.prototype.close = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.FILESYSTEM_READ);
+  this._closed = true;
+};
+
+FileStream.prototype.read = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.FILESYSTEM_READ);
+
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'charCount',
+      type: types_.LONG
+    }
+  ]);
+
+  _checkClosed(this);
+  _checkReadAccess(this._mode);
+
+  if (!arguments.length) {
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+        'Argument "charCount" missing');
+  }
+  if (!type_.isNumber(args.charCount)) {
+    throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR,
+        'Argument "charCount" must be a number');
+  }
+  if (args.charCount <= 0) {
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+        'Argument "charCount" must be greater than 0');
+  }
+
+  var _count = this.bytesAvailable;
+
+  var data = {
+    location: commonFS_.toRealPath(this._file.fullPath),
+    offset: this.position || 0,
+    length: args.charCount > _count ? _count : args.charCount,
+    is_base64: false,
+  };
+
+  var result = native_.callSyncData('File_readSync', data);
+  if (native_.isFailure(result.reply)) {
+    throw new WebAPIException(WebAPIException.IO_ERR, 'Could not read');
+  }
+  this.position = this.position + result.reply.data_size;
+
+  return result.output;
+};
+
+FileStream.prototype.readBytes = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.FILESYSTEM_READ);
+
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'byteCount',
+      type: types_.LONG
+    }
+  ]);
+
+  _checkClosed(this);
+  _checkReadAccess(this._mode);
+
+  if (args.byteCount <= 0) {
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+        'Argument "byteCount" must be greater than 0');
+  }
+
+  var _count = this.bytesAvailable;
+
+  var data = {
+    location: commonFS_.toRealPath(this._file.fullPath),
+    offset: this.position || 0,
+    length: args.byteCount > _count ? _count : args.byteCount,
+    is_base64: false,
+  };
+
+  var result = native_.callSyncData('File_readSync', data, "octet");
+  if (native_.isFailure(result.reply)) {
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR, 'Could not read');
+  }
+
+  this.position = this.position + result.reply.data_size;
+
+  return result.output;
+};
+
+FileStream.prototype.readBase64 = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.FILESYSTEM_READ);
+
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'byteCount',
+      type: types_.LONG
+    }
+  ]);
+
+  _checkClosed(this);
+  _checkReadAccess(this._mode);
+
+  if (!arguments.length) {
+    throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR,
+        'Argument "byteCount" missing');
+  }
+  if (type_.isString(arguments[0]) && !arguments[0].length) {
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+        'Argument "byteCount" must be a number');
+  }
+  if (!type_.isNumber(arguments[0])) {
+    throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR,
+        'Argument "byteCount" must be a number');
+  }
+  if (args.byteCount <= 0) {
+    throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR,
+        'Argument "byteCount" must be greater than 0');
+  }
+
+  var _count = this.bytesAvailable;
+
+  var data = {
+    location: commonFS_.toRealPath(this._file.fullPath),
+    offset: this.position || 0,
+    length: args.byteCount > _count ? _count : args.byteCount,
+    is_base64: true
+  };
+
+  var result = native_.callSyncData('File_readSync', data);
+  if (native_.isFailure(result.reply)) {
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR, 'Could not read');
+  }
+  this.position = this.position + result.reply.data_size;
+
+  return result.output;
+};
+
+function _isBase64(str) {
+  var base64 = new RegExp('^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$');
+  return base64.test(str);
+}
+
+FileStream.prototype.writeBase64 = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.FILESYSTEM_WRITE);
+
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'base64Data',
+      type: types_.STRING
+    }
+  ]);
+
+  _checkClosed(this);
+  _checkWriteAccess(this._mode);
+
+  if (!arguments.length) {
+    throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR,
+        'Argument "base64Data" missing');
+  }
+  if (!args.base64Data.length || !_isBase64(args.base64Data)) {
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+        'Data is not base64');
+  }
+
+  var data = {
+    location: commonFS_.toRealPath(this._file.fullPath),
+    offset: this.position,
+    is_base64: true
+  };
+
+  var result = native_.callSyncData('File_writeSync', data, "string", args.base64Data);
+
+  if (native_.isFailure(result)) {
+    throw new WebAPIException(WebAPIException.IO_ERR, 'Could not write');
+  }
+  this.position = this.position + result.reply.data_size;
+};
diff --git a/webWidgetTCT_device/src/filesystem/js/file_system_manager.js b/webWidgetTCT_device/src/filesystem/js/file_system_manager.js
new file mode 100755 (executable)
index 0000000..7d6d2e8
--- /dev/null
@@ -0,0 +1,228 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+function FileSystemStorage(data) {
+  Object.defineProperties(this, {
+    label: {value: data.label, writable: false, enumerable: true},
+    type: {value: data.type, writable: false, enumerable: true},
+    state: {value: data.state, writable: false, enumerable: true}
+  });
+}
+
+var PATH_MAX = 4096;
+
+function FileSystemManager() {
+  Object.defineProperties(this, {
+    maxPathLength: {value: PATH_MAX, writable: false, enumerable: true}
+  });
+}
+
+FileSystemManager.prototype.resolve = function(location, onsuccess, onerror, mode) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.FILESYSTEM_READ);
+
+  var args = validator_.validateArgs(arguments, [
+    {name: 'location', type: types_.STRING},
+    {name: 'onsuccess', type: types_.FUNCTION},
+    {name: 'onerror', type: types_.FUNCTION, optional: true, nullable: true},
+    {name: 'mode', type: types_.ENUM, values: Object.keys(FileMode), optional: true, nullable: true}
+  ]);
+
+  if (!args.has.mode) {
+    args.mode = 'rw';
+  }
+
+  // resolving a path on unmounted storage should result in exception
+  var storage = commonFS_.getStorage(args.location.split('/')[0]);
+  if (storage && FileSystemStorageState.MOUNTED !== storage.state) {
+    setTimeout(function() {
+      native_.callIfPossible(args.onerror,
+          new WebAPIException(WebAPIException.NOT_FOUND_ERR,
+          'Storage is not mounted.'));
+    }, 0);
+    return;
+  }
+
+  // Validation against '.' and '..' directories used in path - not allowed
+  var result = commonFS_.checkPathWithoutDots(args.location);
+  if (!result) {
+    // path contains dots - it is not allowed - return InvalidValuesError
+    setTimeout(function() {
+      native_.callIfPossible(args.onerror,
+          new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+          'Path contains \'.\' or \'..\' - it is not allowed.'));
+    }, 0);
+    return;
+  }
+
+  var _realPath = commonFS_.toRealPath(args.location);
+
+  if (!_realPath) {
+    // invalid real path means that virtual root does not exist
+    setTimeout(function() {
+      native_.callIfPossible(args.onerror,
+          new WebAPIException(WebAPIException.NOT_FOUND_ERR,
+          'Specified virtual root does not exist.'));
+    }, 0);
+    return;
+  }
+
+  var _isLocationAllowed = commonFS_.isLocationAllowed(_realPath);
+
+  if (args.mode !== 'r' && !_isLocationAllowed) {
+    setTimeout(function() {
+      native_.callIfPossible(args.onerror,
+          new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+          'Provided arguments are not valid.'));
+    }, 0);
+    return;
+  }
+
+  var data = {
+    location: _realPath
+  };
+
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.onerror, native_.getErrorObject(result));
+      return;
+    }
+
+    var aStatObj = native_.getResultObject(result);
+    var _result = commonFS_.getFileInfo(aStatObj, false, args.mode);
+    if (_result.readOnly && args.mode !== 'r') {
+      native_.callIfPossible(args.onerror, new WebAPIException(WebAPIException.UNKNOWN_ERR, 'File is read-only.'));
+    } else {
+      native_.callIfPossible(args.onsuccess, new File(_result));
+      console.log("resolve success callback called");
+    }
+  };
+
+  var ret = native_.call('File_stat', data, callback);
+  if (native_.isFailure(ret)) {
+      throw native_.getErrorObject(ret);
+  }
+};
+
+FileSystemManager.prototype.getStorage = function(label, onsuccess, onerror) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.FILESYSTEM_READ);
+
+  var args = validator_.validateArgs(arguments, [
+    {name: 'label', type: types_.STRING},
+    {name: 'onsuccess', type: types_.FUNCTION},
+    {name: 'onerror', type: types_.FUNCTION, optional: true, nullable: true}
+  ]);
+
+  setTimeout(function() {
+    var storage = commonFS_.getStorage(args.label);
+
+    if (!storage) {
+      native_.callIfPossible(args.onerror,
+          new WebAPIException(WebAPIException.NOT_FOUND_ERR, 'Storage not found.'));
+    } else {
+      native_.callIfPossible(args.onsuccess, new FileSystemStorage(storage));
+    }
+  }, 0);
+};
+
+FileSystemManager.prototype.listStorages = function(onsuccess, onerror) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.FILESYSTEM_READ);
+
+  var args = validator_.validateArgs(arguments, [
+    {name: 'onsuccess', type: types_.FUNCTION},
+    {name: 'onerror', type: types_.FUNCTION, optional: true, nullable: true}
+  ]);
+
+  setTimeout(function() {
+    var storages = [];
+    var cache = commonFS_.getAllStorages();
+    for (var i = 0; i < cache.length; ++i) {
+      storages.push(new FileSystemStorage(cache[i]));
+    }
+
+    native_.callIfPossible(args.onsuccess, storages);
+  }, 0);
+};
+
+var callbackId = 0;
+var callbacks = {};
+
+function nextCallbackId() {
+  return ++callbackId;
+}
+
+function _StorageStateChangeListener(result) {
+  commonFS_.clearCache();
+  var storage = new FileSystemStorage(result);
+  for (var id in callbacks) {
+    native_.callIfPossible(callbacks[id], storage);
+    console.log("storage listener called");
+  }
+}
+
+FileSystemManager.prototype.addStorageStateChangeListener = function(onsuccess, onerror) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.FILESYSTEM_WRITE);
+
+  var args = validator_.validateArgs(arguments, [
+    {name: 'onsuccess', type: types_.FUNCTION},
+    {name: 'onerror', type: types_.FUNCTION, optional: true, nullable: true}
+  ]);
+
+  var register = false;
+  if (type_.isEmptyObject(callbacks)) {
+    register = true;
+  }
+
+  var id = nextCallbackId();
+  callbacks[id] = args.onsuccess;
+
+  if (register) {
+    native_.addListener('StorageStateChangeListener', _StorageStateChangeListener);
+    var result = native_.callSync('FileSystemManager_addStorageStateChangeListener', {});
+
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.onerror, native_.getErrorObject(result));
+      return;
+    }
+  }
+
+  return id;
+};
+
+FileSystemManager.prototype.removeStorageStateChangeListener = function(watchId) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.FILESYSTEM_WRITE);
+
+  var args = validator_.validateArgs(arguments, [
+    {name: 'watchId', type: types_.LONG}
+  ]);
+
+  if (!arguments.length) {
+    throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR,
+        'Missing watchId');
+  }
+  var id = args.watchId;
+
+  if (type_.isNullOrUndefined(callbacks[id])) {
+    throw new WebAPIException(WebAPIException.NOT_FOUND_ERR, 'Watch ID not found.');
+  }
+
+  delete callbacks[id];
+
+  if (type_.isEmptyObject(callbacks)) {
+    native_.callSync('FileSystemManager_removeStorageStateChangeListener', {});
+  }
+};
+
+exports = new FileSystemManager();
diff --git a/webWidgetTCT_device/src/humanactivitymonitor/humanactivitymonitor.gyp b/webWidgetTCT_device/src/humanactivitymonitor/humanactivitymonitor.gyp
new file mode 100755 (executable)
index 0000000..38f27a3
--- /dev/null
@@ -0,0 +1,34 @@
+{
+  'includes':[
+    '../common/common.gypi',
+  ],
+  'targets': [
+    {
+      'target_name': 'tizen_humanactivitymonitor',
+      'type': 'loadable_module',
+      'dependencies': [
+        '../common/common.gyp:tizen_common',
+      ],
+      'sources': [
+        'humanactivitymonitor_api.js',
+        'humanactivitymonitor_extension.cc',
+        'humanactivitymonitor_extension.h',
+        'humanactivitymonitor_instance.cc',
+        'humanactivitymonitor_instance.h',
+        'humanactivitymonitor_manager.cc',
+        'humanactivitymonitor_manager.h',
+      ],
+      'conditions': [
+        ['tizen == 1', {
+          'variables': {
+            'packages': [
+              'motion',
+              'capi-system-sensor',
+              'capi-location-manager',
+            ]
+          },
+        }],
+      ],
+    },
+  ],
+}
diff --git a/webWidgetTCT_device/src/humanactivitymonitor/humanactivitymonitor_api.js b/webWidgetTCT_device/src/humanactivitymonitor/humanactivitymonitor_api.js
new file mode 100755 (executable)
index 0000000..b7ccc35
--- /dev/null
@@ -0,0 +1,252 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+var utils_ = xwalk.utils;
+var type_ = utils_.type;
+var converter_ = utils_.converter;
+var validator_ = utils_.validator;
+var types_ = validator_.Types;
+var native_ = new xwalk.utils.NativeManager(extension);
+
+var callbackId = 0;
+var callbacks = {};
+
+function nextCallbackId() {
+  return callbackId++;
+}
+
+function SetReadOnlyProperty(obj, n, v) {
+  Object.defineProperty(obj, n, {value: v, writable: false});
+}
+
+var HumanActivityType = {
+  PEDOMETER: 'PEDOMETER',
+  WRIST_UP: 'WRIST_UP',
+  HRM: 'HRM',
+  GPS: 'GPS'
+};
+
+var PedometerStepStatus = {
+  NOT_MOVING: 'NOT_MOVING',
+  WALKING: 'WALKING',
+  RUNNING: 'RUNNING'
+};
+
+function convertActivityData(type, data) {
+  switch (type) {
+    case HumanActivityType.PEDOMETER:
+      // TODO(r.galka) Not Supported in current implementation
+      return undefined;
+    case HumanActivityType.WRIST_UP:
+      return null;
+    case HumanActivityType.HRM:
+      return new HumanActivityHRMData(data);
+    case HumanActivityType.GPS:
+      var gpsInfo = [];
+      for (var i = 0, max = data.length; i < max; i++) {
+        gpsInfo.push(new HumanActivityGPSInfo(data[i]));
+      }
+      return new HumanActivityGPSInfoArray(gpsInfo);
+  }
+}
+
+function HumanActivityMonitorManager() {
+}
+
+HumanActivityMonitorManager.prototype.getHumanActivityData = function(type, successCallback, errorCallback) {
+  var args = validator_.validateArgs(arguments, [
+    {name: 'type', type: types_.ENUM, values: Object.keys(HumanActivityType)},
+    {name: 'successCallback', type: types_.FUNCTION},
+    {name: 'errorCallback', type: types_.FUNCTION, optional: true, nullable: true}
+  ]);
+
+  if (args.type === HumanActivityType.WRIST_UP) {
+    throw new WebAPIException(WebAPIException.NOT_SUPPORTED_ERR);
+  }
+
+  var listenerId ='HumanActivityMonitor_'  + args.type;
+  if (!native_.isListenerSet(listenerId)) {
+    throw new WebAPIException(WebAPIException.SERVICE_NOT_AVAILABLE_ERR);
+  }
+
+  var data = {
+    type: args.type
+  };
+
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+      return;
+    }
+
+    native_.callIfPossible(args.successCallback,
+        convertActivityData(args.type, native_.getResultObject(result)));
+  };
+
+  native_.call('HumanActivityMonitorManager_getHumanActivityData', data, callback);
+};
+
+HumanActivityMonitorManager.prototype.start = function(type, changedCallback) {
+  // TODO(r.galka) check access
+  // HRM - http://tizen.org/privilege/healthinfo
+  // GPS - http://tizen.org/privilege/location
+
+  var args = validator_.validateArgs(arguments, [
+    {name: 'type', type: types_.ENUM, values: Object.keys(HumanActivityType)},
+    {name: 'changedCallback', type: types_.FUNCTION, optional: true, nullable: true}
+  ]);
+
+  var listenerId ='HumanActivityMonitor_'  + args.type;
+
+  var data = {
+    type: args.type,
+    listenerId: listenerId
+  };
+
+  if (!native_.isListenerSet(listenerId)) {
+    var result = native_.callSync('HumanActivityMonitorManager_start', data);
+    if (native_.isFailure(result)) {
+      throw native_.getErrorObject(result);
+    }
+  }
+
+  var listener = function(result) {
+    native_.callIfPossible(args.changedCallback, convertActivityData(args.type, result));
+  };
+  native_.addListener(listenerId, listener);
+};
+
+HumanActivityMonitorManager.prototype.stop = function(type) {
+  var args = validator_.validateArgs(arguments, [
+    {name: 'type', type: types_.ENUM, values: Object.keys(HumanActivityType)}
+  ]);
+
+  var data = {
+    type: args.type
+  };
+
+  var listenerId ='HumanActivityMonitor_'  + args.type;
+
+  if (!native_.isListenerSet(listenerId)) {
+    return;
+  }
+
+  var result = native_.callSync('HumanActivityMonitorManager_stop', data);
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+
+  native_.removeListener(listenerId);
+};
+
+HumanActivityMonitorManager.prototype.setAccumulativePedometerListener = function(changeCallback) {
+  var args = validator_.validateArgs(arguments, [
+    {name: 'changeCallback', type: types_.FUNCTION}
+  ]);
+
+  var data = {
+  };
+
+  var callback = function(result) {
+    native_.callIfPossible(args.changeCallback);
+  };
+
+  native_.call('HumanActivityMonitorManager_setAccumulativePedometerListener', data, callback);
+};
+
+HumanActivityMonitorManager.prototype.unsetAccumulativePedometerListener = function() {
+
+  var data = {
+  };
+
+  var result = native_.callSync(
+      'HumanActivityMonitorManager_unsetAccumulativePedometerListener', data);
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+};
+
+function StepDifference() {
+  SetReadOnlyProperty(this, 'stepCountDifference', null);
+  SetReadOnlyProperty(this, 'timestamp', null);
+}
+
+
+function HumanActivityData() {
+}
+
+
+function HumanActivityPedometerData() {
+  SetReadOnlyProperty(this, 'stepStatus', null);
+  SetReadOnlyProperty(this, 'speed', null);
+  SetReadOnlyProperty(this, 'walkingFrequency', null);
+  SetReadOnlyProperty(this, 'cumulativeDistance', null);
+  SetReadOnlyProperty(this, 'cumulativeCalorie', null);
+  SetReadOnlyProperty(this, 'cumulativeTotalStepCount', null);
+  SetReadOnlyProperty(this, 'cumulativeWalkStepCount', null);
+  SetReadOnlyProperty(this, 'cumulativeRunStepCount', null);
+  SetReadOnlyProperty(this, 'stepCountDifferences', null);
+}
+
+HumanActivityPedometerData.prototype = new HumanActivityData();
+HumanActivityPedometerData.prototype.constructor = HumanActivityPedometerData;
+
+
+function HumanActivityAccumulativePedometerData() {
+  SetReadOnlyProperty(this, 'stepStatus', null);
+  SetReadOnlyProperty(this, 'speed', null);
+  SetReadOnlyProperty(this, 'walkingFrequency', null);
+  SetReadOnlyProperty(this, 'accumulativeDistance', null);
+  SetReadOnlyProperty(this, 'accumulativeCalorie', null);
+  SetReadOnlyProperty(this, 'accumulativeTotalStepCount', null);
+  SetReadOnlyProperty(this, 'accumulativeWalkStepCount', null);
+  SetReadOnlyProperty(this, 'accumulativeRunStepCount', null);
+  SetReadOnlyProperty(this, 'stepCountDifferences', null);
+}
+
+HumanActivityAccumulativePedometerData.prototype = new HumanActivityData();
+HumanActivityAccumulativePedometerData.prototype.constructor = HumanActivityAccumulativePedometerData;
+
+
+function HumanActivityHRMData(data) {
+  SetReadOnlyProperty(this, 'heartRate', data.heartRate);
+  SetReadOnlyProperty(this, 'rRInterval', data.rRInterval);
+}
+
+HumanActivityHRMData.prototype = new HumanActivityData();
+HumanActivityHRMData.prototype.constructor = HumanActivityHRMData;
+
+
+function HumanActivityGPSInfo(data) {
+  SetReadOnlyProperty(this, 'latitude', data.latitude);
+  SetReadOnlyProperty(this, 'longitude', data.longitude);
+  SetReadOnlyProperty(this, 'altitude', data.altitude);
+  SetReadOnlyProperty(this, 'speed', data.speed);
+  SetReadOnlyProperty(this, 'errorRange', data.errorRange);
+  SetReadOnlyProperty(this, 'timestamp', data.timestamp);
+}
+
+
+function HumanActivityGPSInfoArray(data) {
+  SetReadOnlyProperty(this, 'gpsInfo', data);
+}
+
+HumanActivityGPSInfoArray.prototype = new HumanActivityData();
+HumanActivityGPSInfoArray.prototype.constructor = HumanActivityGPSInfoArray;
+
+
+exports = new HumanActivityMonitorManager();
diff --git a/webWidgetTCT_device/src/humanactivitymonitor/humanactivitymonitor_extension.cc b/webWidgetTCT_device/src/humanactivitymonitor/humanactivitymonitor_extension.cc
new file mode 100755 (executable)
index 0000000..d116516
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2015 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 "humanactivitymonitor/humanactivitymonitor_extension.h"
+
+#include "humanactivitymonitor/humanactivitymonitor_instance.h"
+
+// This will be generated from humanactivitymonitor_api.js
+extern const char kSource_humanactivitymonitor_api[];
+
+common::Extension* CreateExtension() {
+  return new HumanActivityMonitorExtension;
+}
+
+HumanActivityMonitorExtension::HumanActivityMonitorExtension() {
+  SetExtensionName("tizen.humanactivitymonitor");
+  SetJavaScriptAPI(kSource_humanactivitymonitor_api);
+}
+
+HumanActivityMonitorExtension::~HumanActivityMonitorExtension() {}
+
+common::Instance* HumanActivityMonitorExtension::CreateInstance() {
+  return new extension::humanactivitymonitor::HumanActivityMonitorInstance;
+}
diff --git a/webWidgetTCT_device/src/humanactivitymonitor/humanactivitymonitor_extension.h b/webWidgetTCT_device/src/humanactivitymonitor/humanactivitymonitor_extension.h
new file mode 100755 (executable)
index 0000000..a03c2ea
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2015 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 HUMANACTIVITYMONITOR_HUMANACTIVITYMONITOR_EXTENSION_H_
+#define HUMANACTIVITYMONITOR_HUMANACTIVITYMONITOR_EXTENSION_H_
+
+#include "common/extension.h"
+
+class HumanActivityMonitorExtension : public common::Extension {
+ public:
+  HumanActivityMonitorExtension();
+  virtual ~HumanActivityMonitorExtension();
+
+ private:
+  virtual common::Instance* CreateInstance();
+};
+
+#endif  // HUMANACTIVITYMONITOR_HUMANACTIVITYMONITOR_EXTENSION_H_
diff --git a/webWidgetTCT_device/src/humanactivitymonitor/humanactivitymonitor_instance.cc b/webWidgetTCT_device/src/humanactivitymonitor/humanactivitymonitor_instance.cc
new file mode 100755 (executable)
index 0000000..8b0ddf6
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2015 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 "humanactivitymonitor/humanactivitymonitor_instance.h"
+
+#include <functional>
+#include <memory>
+#include <string>
+
+#include "common/picojson.h"
+#include "common/logger.h"
+#include "common/platform_result.h"
+#include "common/task-queue.h"
+#include "humanactivitymonitor/humanactivitymonitor_manager.h"
+
+namespace extension {
+namespace humanactivitymonitor {
+
+using common::PlatformResult;
+using common::ErrorCode;
+using common::TaskQueue;
+
+HumanActivityMonitorInstance::HumanActivityMonitorInstance() {
+  LoggerD("Enter");
+  using std::placeholders::_1;
+  using std::placeholders::_2;
+
+#define REGISTER_SYNC(c, x) \
+    RegisterSyncHandler(c, std::bind(&HumanActivityMonitorInstance::x, this, _1, _2));
+  REGISTER_SYNC("HumanActivityMonitorManager_getHumanActivityData",
+                HumanActivityMonitorManagerGetHumanActivityData);
+  REGISTER_SYNC("HumanActivityMonitorManager_start",
+                HumanActivityMonitorManagerStart);
+  REGISTER_SYNC("HumanActivityMonitorManager_stop",
+                HumanActivityMonitorManagerStop);
+  REGISTER_SYNC("HumanActivityMonitorManager_setAccumulativePedometerListener",
+                HumanActivityMonitorManagerSetAccumulativePedometerListener);
+  REGISTER_SYNC("HumanActivityMonitorManager_unsetAccumulativePedometerListener",
+                HumanActivityMonitorManagerUnsetAccumulativePedometerListener);
+#undef REGISTER_SYNC
+}
+
+HumanActivityMonitorInstance::~HumanActivityMonitorInstance() {
+  LoggerD("Enter");
+}
+
+PlatformResult HumanActivityMonitorInstance::Init() {
+  LoggerD("Enter");
+  if (!manager_) {
+
+    manager_ = std::make_shared<HumanActivityMonitorManager>();
+    const PlatformResult& result = manager_->Init();
+    if (!result) {
+      LOGGER(ERROR) << "Error initializing manager: " << result.message();
+      manager_.reset();
+      return result;
+    }
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+#define CHECK_EXIST(args, name, out) \
+    if (!args.contains(name)) { \
+      ReportError(PlatformResult(ErrorCode::TYPE_MISMATCH_ERR, \
+          name" is required argument"), &out); \
+      return; \
+    }
+
+
+void HumanActivityMonitorInstance::HumanActivityMonitorManagerGetHumanActivityData(
+    const picojson::value& args, picojson::object& out) {
+  LoggerD("Enter");
+  CHECK_EXIST(args, "type", out)
+
+  PlatformResult result = Init();
+  if (!result) {
+    LoggerE("Failed: Init()");
+    ReportError(result, &out);
+    return;
+  }
+
+  auto get = [this, args]() -> void {
+    picojson::value response = picojson::value(picojson::object());
+    picojson::object& response_obj = response.get<picojson::object>();
+    response_obj["callbackId"] = args.get("callbackId");
+
+    picojson::value data = picojson::value();
+    PlatformResult result = manager_->GetHumanActivityData(
+        args.get("type").get<std::string>(),
+        &data);
+
+    if (result) {
+      ReportSuccess(data, response_obj);
+    } else {
+      LoggerE("Failed: manager_->GetHumanActivityData()");
+      ReportError(result, &response_obj);
+    }
+
+    Instance::PostMessage(this, response.serialize().c_str());
+  };
+
+  TaskQueue::GetInstance().Async(get);
+
+  ReportSuccess(out);
+}
+
+void HumanActivityMonitorInstance::HumanActivityMonitorManagerStart(
+    const picojson::value& args, picojson::object& out) {
+  LoggerD("Enter");
+  CHECK_EXIST(args, "type", out)
+
+  PlatformResult result = Init();
+  if (!result) {
+    LoggerE("Failed: Init()");
+    ReportError(result, &out);
+    return;
+  }
+
+  JsonCallback cb = [this, args](picojson::value* data) -> void {
+    if (!data) {
+      LOGGER(ERROR) << "No data passed to json callback";
+      return;
+    }
+
+    picojson::object& data_o = data->get<picojson::object>();
+    data_o["listenerId"] = args.get("listenerId");
+
+    Instance::PostMessage(this, data->serialize().c_str());
+  };
+
+  result = manager_->SetListener(args.get("type").get<std::string>(), cb);
+  if (result) {
+    ReportSuccess(out);
+  } else {
+    LoggerE("Failed: manager_->SetListener()");
+    ReportError(result, &out);
+  }
+}
+
+void HumanActivityMonitorInstance::HumanActivityMonitorManagerStop(
+    const picojson::value& args, picojson::object& out) {
+  LoggerD("Enter");
+  CHECK_EXIST(args, "type", out)
+
+  PlatformResult result = Init();
+  if (!result) {
+    LoggerE("Failed: Init()");
+    ReportError(result, &out);
+    return;
+  }
+
+  result = manager_->UnsetListener(args.get("type").get<std::string>());
+  if (result) {
+    ReportSuccess(out);
+  } else {
+    LoggerE("Failed: manager_->UnsetListener()");
+    ReportError(result, &out);
+  }
+}
+
+void HumanActivityMonitorInstance::HumanActivityMonitorManagerSetAccumulativePedometerListener(
+    const picojson::value& args, picojson::object& out) {
+  // TODO(r.galka) implement
+}
+
+void HumanActivityMonitorInstance::HumanActivityMonitorManagerUnsetAccumulativePedometerListener(
+    const picojson::value& args, picojson::object& out) {
+  // TODO(r.galka) implement
+}
+
+#undef CHECK_EXIST
+
+}  // namespace humanactivitymonitor
+}  // namespace extension
diff --git a/webWidgetTCT_device/src/humanactivitymonitor/humanactivitymonitor_instance.h b/webWidgetTCT_device/src/humanactivitymonitor/humanactivitymonitor_instance.h
new file mode 100755 (executable)
index 0000000..cd0fa89
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2015 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 HUMANACTIVITYMONITOR_HUMANACTIVITYMONITOR_INSTANCE_H_
+#define HUMANACTIVITYMONITOR_HUMANACTIVITYMONITOR_INSTANCE_H_
+
+#include <memory>
+
+#include "common/extension.h"
+#include "common/platform_result.h"
+#include "humanactivitymonitor/humanactivitymonitor_manager.h"
+
+namespace extension {
+namespace humanactivitymonitor {
+
+class HumanActivityMonitorInstance : public common::ParsedInstance {
+ public:
+  HumanActivityMonitorInstance();
+  virtual ~HumanActivityMonitorInstance();
+
+ private:
+  void HumanActivityMonitorManagerStop(
+      const picojson::value& args, picojson::object& out);
+  void HumanActivityMonitorManagerUnsetAccumulativePedometerListener(
+      const picojson::value& args, picojson::object& out);
+  void HumanActivityMonitorManagerGetHumanActivityData(
+      const picojson::value& args, picojson::object& out);
+  void HumanActivityMonitorManagerStart(
+      const picojson::value& args, picojson::object& out);
+  void HumanActivityMonitorManagerSetAccumulativePedometerListener(
+      const picojson::value& args, picojson::object& out);
+
+  std::shared_ptr<HumanActivityMonitorManager> manager_;
+  common::PlatformResult Init();
+};
+
+} // namespace humanactivitymonitor
+} // namespace extension
+
+#endif  // HUMANACTIVITYMONITOR_HUMANACTIVITYMONITOR_INSTANCE_H_
diff --git a/webWidgetTCT_device/src/humanactivitymonitor/humanactivitymonitor_manager.cc b/webWidgetTCT_device/src/humanactivitymonitor/humanactivitymonitor_manager.cc
new file mode 100755 (executable)
index 0000000..b666e09
--- /dev/null
@@ -0,0 +1,531 @@
+/*
+ * Copyright (c) 2015 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 "humanactivitymonitor/humanactivitymonitor_manager.h"
+
+#include <gesture_recognition.h>
+
+#include "common/logger.h"
+
+namespace extension {
+namespace humanactivitymonitor {
+
+using common::PlatformResult;
+using common::ErrorCode;
+
+HumanActivityMonitorManager::HumanActivityMonitorManager() {
+  LoggerD("Enter");
+}
+
+HumanActivityMonitorManager::~HumanActivityMonitorManager() {
+  LoggerD("Enter");
+  UnsetWristUpListener();
+  UnsetHrmListener();
+  UnsetGpsListener();
+}
+
+PlatformResult HumanActivityMonitorManager::Init() {
+  LoggerD("Enter");
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult HumanActivityMonitorManager::IsSupported(
+    const std::string& type) {
+
+  // check cache first
+  if (supported_.count(type)) {
+    return PlatformResult(supported_[type]
+        ? ErrorCode::NO_ERROR
+        : ErrorCode::NOT_SUPPORTED_ERR);
+  }
+
+  int ret;
+  bool supported = false;
+  if (type == kActivityTypePedometer) {
+    // TODO(r.galka) no native api for pedometer
+    // so just pass it for not supported.
+  } else if (type == kActivityTypeWristUp) {
+    ret = gesture_is_supported(GESTURE_WRIST_UP, &supported);
+    if (ret != SENSOR_ERROR_NONE) {
+      LOGGER(ERROR) << "gesture_is_supported(GESTURE_WRIST_UP), error: " << ret;
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "WRIST_UP gesture check failed");
+    }
+  } else if (type == kActivityTypeHrm) {
+    ret = sensor_is_supported(SENSOR_HRM, &supported);
+    if (ret != SENSOR_ERROR_NONE) {
+      LOGGER(ERROR) << "sensor_is_supported(HRM), error: " << ret;
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "HRM sensor check failed");
+    }
+  } else if (type == kActivityTypeGps) {
+    supported = location_manager_is_supported_method(LOCATIONS_METHOD_GPS);
+  } else {
+    return PlatformResult(ErrorCode::TYPE_MISMATCH_ERR);
+  }
+
+  supported_[type] = supported;
+
+  return PlatformResult(supported_[type]
+      ? ErrorCode::NO_ERROR
+      : ErrorCode::NOT_SUPPORTED_ERR);
+}
+
+PlatformResult HumanActivityMonitorManager::SetListener(
+    const std::string& type, JsonCallback callback) {
+
+  PlatformResult result = IsSupported(type);
+  if (!result) {
+    return result;
+  }
+
+  if (type == kActivityTypePedometer) {
+    // TODO(r.galka) Not Supported in current implementation.
+  }
+
+  if (type == kActivityTypeWristUp) {
+    return SetWristUpListener(callback);
+  }
+
+  if (type == kActivityTypeHrm) {
+    return SetHrmListener(callback);
+  }
+
+  if (type == kActivityTypeGps) {
+    return SetGpsListener(callback);
+  }
+
+  return PlatformResult(ErrorCode::UNKNOWN_ERR, "Undefined activity type");
+}
+
+PlatformResult HumanActivityMonitorManager::UnsetListener(
+    const std::string& type) {
+
+  PlatformResult result = IsSupported(type);
+  if (!result) {
+    return result;
+  }
+
+  if (type == kActivityTypePedometer) {
+    // TODO(r.galka) Not Supported in current implementation.
+  }
+
+  if (type == kActivityTypeWristUp) {
+    return UnsetWristUpListener();
+  }
+
+  if (type == kActivityTypeHrm) {
+    return UnsetHrmListener();
+  }
+
+  if (type == kActivityTypeGps) {
+    return UnsetGpsListener();
+  }
+
+  return PlatformResult(ErrorCode::UNKNOWN_ERR, "Undefined activity type");
+}
+
+PlatformResult HumanActivityMonitorManager::GetHumanActivityData(
+    const std::string& type,
+    picojson::value* data) {
+
+  LoggerD("Enter");
+  if (type == kActivityTypePedometer) {
+    // TODO(r.galka) Not Supported in current implementation.
+  }
+
+  if (type == kActivityTypeWristUp) {
+    return PlatformResult(ErrorCode::NOT_SUPPORTED_ERR);
+  }
+
+  if (type == kActivityTypeHrm) {
+    return GetHrmData(data);
+  }
+
+  if (type == kActivityTypeGps) {
+    return GetGpsData(data);
+  }
+
+  return PlatformResult(ErrorCode::UNKNOWN_ERR, "Undefined activity type");
+}
+
+// WRIST_UP
+PlatformResult HumanActivityMonitorManager::SetWristUpListener(
+    JsonCallback callback) {
+  LoggerD("Enter");
+  int ret;
+
+  ret = gesture_create(&gesture_handle_);
+  if (ret != GESTURE_ERROR_NONE) {
+    LOGGER(ERROR) << "Failed to create WRIST_UP handle, error: " << ret;
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Failed to create WRIST_UP listener");
+  }
+
+  ret = gesture_start_recognition(gesture_handle_,
+                                  GESTURE_WRIST_UP,
+                                  GESTURE_OPTION_DEFAULT,
+                                  OnWristUpEvent,
+                                  this);
+  if (ret != GESTURE_ERROR_NONE) {
+    LOGGER(ERROR) << "Failed to start WRIST_UP listener, error: " << ret;
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Failed to start WRIST_UP listener");
+  }
+
+  wrist_up_event_callback_ = callback;
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult HumanActivityMonitorManager::UnsetWristUpListener() {
+  LoggerD("Enter");
+
+  if (gesture_handle_) {
+    int ret = gesture_stop_recognition(gesture_handle_);
+    if (ret != GESTURE_ERROR_NONE) {
+      LOGGER(ERROR) << "Failed to stop WRIST_UP detection, error: " << ret;
+    }
+
+    ret = gesture_release(gesture_handle_);
+    if (ret != GESTURE_ERROR_NONE) {
+      LOGGER(ERROR) << "Failed to release WRIST_UP handle, error: " << ret;
+    }
+  }
+
+  wrist_up_event_callback_ = nullptr;
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+void HumanActivityMonitorManager::OnWristUpEvent(gesture_type_e gesture,
+                                                 const gesture_data_h data,
+                                                 double timestamp,
+                                                 gesture_error_e error,
+                                                 void* user_data) {
+  LoggerD("Enter");
+  HumanActivityMonitorManager* manager =
+      static_cast<HumanActivityMonitorManager*>(user_data);
+
+  if (!manager->wrist_up_event_callback_) {
+    LOGGER(ERROR) << "No WRIST_UP event callback registered, skipping.";
+    return;
+  }
+
+  picojson::value v = picojson::value(); // null value
+  manager->wrist_up_event_callback_(&v);
+}
+
+// HRM
+PlatformResult HumanActivityMonitorManager::SetHrmListener(
+    JsonCallback callback) {
+  LoggerD("Enter");
+  sensor_h hrm_sensor;
+  int ret;
+
+  ret = sensor_get_default_sensor(SENSOR_HRM, &hrm_sensor);
+  if (ret != SENSOR_ERROR_NONE) {
+    LOGGER(ERROR) << "Failed to get HRM sensor, error: " << ret;
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Failed to get HRM sensor");
+  }
+
+  ret = sensor_create_listener(hrm_sensor, &hrm_sensor_listener_);
+  if (ret != SENSOR_ERROR_NONE) {
+    LOGGER(ERROR) << "Failed to create HRM sensor listener, error: " << ret;
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Failed to create HRM sensor listener");
+  }
+
+  ret = sensor_listener_set_event_cb(hrm_sensor_listener_,
+                                     0,
+                                     OnHrmSensorEvent,
+                                     this);
+  if (ret != SENSOR_ERROR_NONE) {
+    LOGGER(ERROR) << "Failed to set HRM sensor listener, error: " << ret;
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Failed to set HRM sensor listener");
+  }
+
+  ret = sensor_listener_start(hrm_sensor_listener_);
+  if (ret != SENSOR_ERROR_NONE) {
+    LOGGER(ERROR) << "Failed to start HRM sensor listener, error: " << ret;
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Failed to start HRM sensor listener");
+  }
+
+  hrm_event_callback_ = callback;
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult HumanActivityMonitorManager::UnsetHrmListener() {
+  LoggerD("Enter");
+
+  if (hrm_sensor_listener_) {
+    int ret = sensor_listener_stop(hrm_sensor_listener_);
+    if (ret != SENSOR_ERROR_NONE) {
+      LOGGER(ERROR) << "Failed to stop HRM sensor, error: " << ret;
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "Failed to stop HRM sensor");
+    }
+
+    ret = sensor_listener_unset_event_cb(hrm_sensor_listener_);
+    if (ret != SENSOR_ERROR_NONE) {
+      LOGGER(ERROR) << "Failed to unset HRM sensor listener, error: " << ret;
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "Failed to unset HRM sensor listener");
+    }
+
+    ret = sensor_destroy_listener(hrm_sensor_listener_);
+    if (ret != SENSOR_ERROR_NONE) {
+      LOGGER(ERROR) << "Failed to destroy HRM sensor listener, error: " << ret;
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "Failed to destroy HRM sensor listener");
+    }
+  }
+
+  hrm_event_callback_ = nullptr;
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+static PlatformResult ConvertHrmEvent(sensor_event_s* event,
+                                      picojson::object* data) {
+  LOGGER(DEBUG) << "Sensor event:";
+  LOGGER(DEBUG) << "  |- accuracy: " << event->accuracy;
+  LOGGER(DEBUG) << "  |- timestamp: " << event->timestamp;
+  LOGGER(DEBUG) << "  |- value_count: " << event->value_count;
+
+  if (event->value_count < 2) {
+    LOGGER(ERROR) << "To few values of HRM event";
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "To few values of HRM event");
+  }
+
+  LOGGER(DEBUG) << "  |- values[0]: " << event->values[0];
+  LOGGER(DEBUG) << "  |- values[1]: " << event->values[1];
+
+  float hr = floor( event->values[0] + 0.5); // heart beat rate 0 ~ 220 integer (bpm)
+
+  // there are no public native api for peak to peak interval.
+  // but RRI = (60 / HR) * 1000
+  // or unofficially values[1] is rri (0 ~ 5000 ms)
+  float rri = floor(event->values[1] + 0.5);
+
+
+  (*data)["heartRate"] = picojson::value(static_cast<double>(hr));
+  (*data)["rRInterval"] = picojson::value(static_cast<double>(rri));
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+void HumanActivityMonitorManager::OnHrmSensorEvent(
+    sensor_h /*sensor*/, sensor_event_s *event, void *user_data) {
+
+  LoggerD("Enter");
+  HumanActivityMonitorManager* manager =
+      static_cast<HumanActivityMonitorManager*>(user_data);
+
+  if (!manager->hrm_event_callback_) {
+    LOGGER(ERROR) << "No HRM event callback registered, skipping.";
+    return;
+  }
+
+  picojson::value hrm_data = picojson::value(picojson::object());
+  PlatformResult result = ConvertHrmEvent(event,
+                                          &hrm_data.get<picojson::object>());
+  if (!result) {
+    LOGGER(ERROR) << "Failed to convert HRM data: " << result.message();
+    return;
+  }
+
+  manager->hrm_event_callback_(&hrm_data);
+}
+
+PlatformResult HumanActivityMonitorManager::GetHrmData(picojson::value* data) {
+  LoggerD("Enter");
+  if (!hrm_sensor_listener_) {
+    return PlatformResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR);
+  }
+
+  int ret;
+
+  sensor_event_s event;
+  ret = sensor_listener_read_data(hrm_sensor_listener_, &event);
+  if (ret != SENSOR_ERROR_NONE) {
+    LOGGER(ERROR) << "Failed to get HRM sensor data, error: " << ret;
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Failed to get HRM sensor data");
+  }
+
+  *data = picojson::value(picojson::object());
+  PlatformResult result = ConvertHrmEvent(&event,
+                                          &data->get<picojson::object>());
+  if (!result) {
+    return result;
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+// GPS
+PlatformResult HumanActivityMonitorManager::SetGpsListener(
+    JsonCallback callback) {
+  LoggerD("Enter");
+  int ret;
+
+  ret = location_manager_create(LOCATIONS_METHOD_GPS, &location_handle_);
+  if (ret != LOCATIONS_ERROR_NONE) {
+    LOGGER(ERROR) << "Failed to create location manager, error: " << ret;
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Failed to create location manager");
+  }
+
+  ret = location_manager_set_location_batch_cb(location_handle_,
+                                               OnGpsEvent,
+                                               1, // batch_interval
+                                               120, // batch_period
+                                               this);
+  if (ret != LOCATIONS_ERROR_NONE) {
+    LOGGER(ERROR) << "Failed to set location listener, error: " << ret;
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Failed to set location listener");
+  }
+
+  ret = location_manager_start_batch(location_handle_);
+  if (ret != LOCATIONS_ERROR_NONE) {
+    LOGGER(ERROR) << "Failed to start location manager, error: " << ret;
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Failed to start location manager");
+  }
+
+  gps_event_callback_ = callback;
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult HumanActivityMonitorManager::UnsetGpsListener() {
+  LoggerD("Enter");
+
+  if (location_handle_) {
+    int ret = location_manager_stop_batch(location_handle_);
+    if (ret != LOCATIONS_ERROR_NONE) {
+      LOGGER(ERROR) << "Failed to stop location manager, error: " << ret;
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "Failed to stop location manager");
+    }
+
+    ret = location_manager_unset_location_batch_cb(location_handle_);
+    if (ret != LOCATIONS_ERROR_NONE) {
+      LOGGER(ERROR) << "Failed to unset location listener, error: " << ret;
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "Failed to unset location listener");
+    }
+
+    ret = location_manager_destroy(location_handle_);
+    if (ret != LOCATIONS_ERROR_NONE) {
+      LOGGER(ERROR) << "Failed to destroy location manager, error: " << ret;
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "Failed to destroy location manager");
+    }
+  }
+
+  gps_event_callback_ = nullptr;
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+static bool ConvertGpsEvent(double latitude, double longitude, double altitude,
+                            double speed, double direction, double horizontal,
+                            double vertical, time_t timestamp,
+                            void* user_data) {
+  LoggerD("Enter");
+  picojson::array* gps_info_array = static_cast<picojson::array*>(user_data);
+
+  picojson::value gps_info = picojson::value(picojson::object());
+  picojson::object& gps_info_o = gps_info.get<picojson::object>();
+
+  gps_info_o["latitude"] = picojson::value(latitude);
+  gps_info_o["longitude"] = picojson::value(longitude);
+  gps_info_o["altitude"] = picojson::value(altitude);
+  gps_info_o["speed"] = picojson::value(speed);
+  // TODO(r.galka) errorRange not available in CAPI
+  gps_info_o["errorRange"] = picojson::value(static_cast<double>(0));
+  gps_info_o["timestamp"] = picojson::value(static_cast<double>(timestamp));
+
+  gps_info_array->push_back(gps_info);
+
+  return true;
+}
+
+void HumanActivityMonitorManager::OnGpsEvent(int num_of_location,
+                                             void *user_data) {
+  LoggerD("Enter");
+  HumanActivityMonitorManager* manager =
+      static_cast<HumanActivityMonitorManager*>(user_data);
+
+  if (!manager->gps_event_callback_) {
+    LOGGER(ERROR) << "No GPS event callback registered, skipping.";
+    return;
+  }
+
+  if (0 == num_of_location) {
+    LOGGER(ERROR) << "No GPS locations available, skipping.";
+    return;
+  }
+
+  picojson::value gps_info = picojson::value(picojson::array());
+  int ret = location_manager_foreach_location_batch(
+      manager->location_handle_,
+      ConvertGpsEvent,
+      &gps_info.get<picojson::array>());
+  if (ret != LOCATIONS_ERROR_NONE) {
+    LOGGER(ERROR) << "Failed to convert location, error: " << ret;
+    return;
+  }
+
+  manager->gps_event_callback_(&gps_info);
+}
+
+PlatformResult HumanActivityMonitorManager::GetGpsData(picojson::value* data) {
+  LoggerD("Enter");
+  if (!location_handle_) {
+    return PlatformResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR);
+  }
+
+  int ret;
+  double altitude, latitude, longitude, climb,
+      direction, speed, horizontal, vertical;
+  location_accuracy_level_e level;
+  time_t timestamp;
+  ret = location_manager_get_location(location_handle_, &altitude, &latitude,
+                                      &longitude, &climb, &direction, &speed,
+                                      &level, &horizontal, &vertical,
+                                      &timestamp);
+  if (ret != LOCATIONS_ERROR_NONE) {
+    LOGGER(ERROR) << "Failed to get location, error: " << ret;
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get location");
+  }
+
+  *data = picojson::value(picojson::array());
+  ConvertGpsEvent(latitude, longitude, altitude, speed, direction, horizontal,
+                  vertical, timestamp, &data->get<picojson::array>());
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+}  // namespace humanactivitymonitor
+}  // namespace extension
diff --git a/webWidgetTCT_device/src/humanactivitymonitor/humanactivitymonitor_manager.h b/webWidgetTCT_device/src/humanactivitymonitor/humanactivitymonitor_manager.h
new file mode 100755 (executable)
index 0000000..22293c3
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2015 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 HUMANACTIVITYMONITOR_HUMANACTIVITYMONITOR_MANAGER_H
+#define HUMANACTIVITYMONITOR_HUMANACTIVITYMONITOR_MANAGER_H
+
+#include <functional>
+#include <sensor.h>
+#include <gesture_recognition.h>
+#include <location_batch.h>
+#include <string>
+
+#include "common/picojson.h"
+#include "common/platform_result.h"
+
+namespace extension {
+namespace humanactivitymonitor {
+
+namespace {
+const std::string kActivityTypePedometer = "PEDOMETER";
+const std::string kActivityTypeWristUp = "WRIST_UP";
+const std::string kActivityTypeHrm = "HRM";
+const std::string kActivityTypeGps = "GPS";
+}
+
+typedef std::function<void(picojson::value*)> JsonCallback;
+
+class HumanActivityMonitorManager {
+ public:
+  HumanActivityMonitorManager();
+  virtual ~HumanActivityMonitorManager();
+
+  common::PlatformResult Init();
+
+  common::PlatformResult SetListener(const std::string& type,
+                                     JsonCallback callback);
+  common::PlatformResult UnsetListener(const std::string& type);
+
+  common::PlatformResult GetHumanActivityData(const std::string& type,
+                                              picojson::value* data);
+
+ private:
+  std::map<std::string, bool> supported_;
+  common::PlatformResult IsSupported(const std::string& type);
+
+  // WRIST_UP
+  gesture_h gesture_handle_;
+  JsonCallback wrist_up_event_callback_;
+  common::PlatformResult SetWristUpListener(JsonCallback callback);
+  common::PlatformResult UnsetWristUpListener();
+  static void OnWristUpEvent(gesture_type_e gesture,
+                             const gesture_data_h data,
+                             double timestamp,
+                             gesture_error_e error,
+                             void* user_data);
+
+  // HRM
+  sensor_listener_h hrm_sensor_listener_;
+  JsonCallback hrm_event_callback_;
+  common::PlatformResult SetHrmListener(JsonCallback callback);
+  common::PlatformResult UnsetHrmListener();
+  static void OnHrmSensorEvent(sensor_h sensor,
+                               sensor_event_s *event,
+                               void *user_data);
+  common::PlatformResult GetHrmData(picojson::value* data);
+
+  // GPS
+  location_manager_h location_handle_;
+  JsonCallback gps_event_callback_;
+  common::PlatformResult SetGpsListener(JsonCallback callback);
+  common::PlatformResult UnsetGpsListener();
+  static void OnGpsEvent(int num_of_location, void *user_data);
+  common::PlatformResult GetGpsData(picojson::value* data);
+};
+
+} // namespace humanactivitymonitor
+} // namespace extension
+
+#endif // HUMANACTIVITYMONITOR_HUMANACTIVITYMONITOR_MANAGER_H
diff --git a/webWidgetTCT_device/src/inputdevice/inputdevice.gyp b/webWidgetTCT_device/src/inputdevice/inputdevice.gyp
new file mode 100755 (executable)
index 0000000..77a76b0
--- /dev/null
@@ -0,0 +1,32 @@
+{
+  'includes':[
+    '../common/common.gypi',
+  ],
+  'targets': [
+    {
+      'target_name': 'tizen_inputdevice',
+      'type': 'loadable_module',
+      'dependencies': [
+        '../common/common.gyp:tizen_common',
+      ],
+      'sources': [
+        'inputdevice_api.js',
+        'inputdevice_extension.cc',
+        'inputdevice_extension.h',
+        'inputdevice_instance.cc',
+        'inputdevice_instance.h'
+      ],
+      'includes': [
+        '../common/pkg-config.gypi',
+      ],
+      'conditions': [
+        ['tizen == 1', {
+          'variables': {
+            'packages': [
+            ]
+          },
+        }],
+      ],
+    },
+  ],
+}
diff --git a/webWidgetTCT_device/src/inputdevice/inputdevice_api.js b/webWidgetTCT_device/src/inputdevice/inputdevice_api.js
new file mode 100755 (executable)
index 0000000..e3c37a2
--- /dev/null
@@ -0,0 +1,217 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+var native = new xwalk.utils.NativeManager(extension);
+var validator = xwalk.utils.validator;
+var types = validator.Types;
+var map = {
+  "VolumeUp": {
+      keyName: "XF86AudioRaiseVolume",
+      keyCode: 447
+  },
+  "VolumeDown": {
+      keyName: "XF86AudioLowerVolume",
+      keyCode: 448
+  },
+};
+
+
+function InputDeviceKey(dict) {
+  for (var key in dict) {
+    if (dict.hasOwnProperty(key)) {
+      Object.defineProperty(this, key, {
+        value: dict[key],
+        enumerable: true
+      });
+    }
+  }
+  Object.freeze(this);
+}
+
+
+/**
+ * This class provides access to the API functionalities through the tizen.tvinputdevice interface.
+ * @constructor
+ */
+function InputDeviceManager() {
+  if (!(this instanceof InputDeviceManager)) {
+    throw new TypeError;
+  }
+}
+
+/**
+ * Retrieves the list of keys can be registered with the registerKey() method.
+ * @return {array} Array of keys
+ */
+InputDeviceManager.prototype.getSupportedKeys = function() {
+
+  var re = [];
+  for (var key in map) {
+      if (map.hasOwnProperty(key)) {
+          re.push(new InputDeviceKey({name: key, code: map[key].keyCode}));
+      }
+  }
+  
+  return re;
+};
+
+
+/**
+ * Returns information about the key which has the given name.
+ * @param {!string} keyName  The key name
+ * @return {object} Key object
+ */
+InputDeviceManager.prototype.getKey = function(keyName) {
+  var args = validator.validateArgs(arguments, [
+    {name: 'keyName', type: types.STRING}
+  ]);
+
+  if (!map[args.keyName]) {
+      throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+      'Parameter "keyName" is invalid.');
+  }
+  
+  return new InputDeviceKey( { name: args.keyName, code: map[args.keyName].keyCode } );
+
+};
+
+
+/**
+ * Registers an input device key to receive DOM keyboard event when it is pressed or released.
+ * @param {!string} keyName  The key name
+ */
+InputDeviceManager.prototype.registerKey = function(keyName) {
+  var args = validator.validateArgs(arguments, [
+    {name: 'keyName', type: types.STRING}
+  ]);
+  if (!map[args.keyName]) {
+      throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+      'Parameter "keyName" is invalid.');
+  }
+
+  var ret = native.sendRuntimeSyncMessage('tizen://api/inputdevice/registerKey',map[args.keyName].keyName);
+
+  if (ret === 'error') {
+    throw new WebAPIException(WebAPIException.UNKNOWN_ERR, 'UnknownError');
+  }
+};
+
+
+/**
+ * Unregisters an input device key.
+ * @param {!string} keyName  The key name
+ */
+InputDeviceManager.prototype.unregisterKey = function(keyName) {
+  var args = validator.validateArgs(arguments, [
+    {name: 'keyName', type: types.STRING}
+  ]);
+  
+  if (!map[args.keyName]) {
+      throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+      'Parameter "keyName" is invalid.');
+  }
+  
+  var ret = native.sendRuntimeSyncMessage('tizen://api/inputdevice/unregisterKey',map[args.keyName].keyName);
+
+  if (ret === 'error') {
+    throw new WebAPIException(WebAPIException.UNKNOWN_ERR, 'UnknownError');
+  }
+};
+
+InputDeviceManager.prototype.registerKeyBatch = function() {
+  var args = validator.validateMethod(arguments, [
+    {
+      name: 'keyNames',
+      type: types.ARRAY,
+      values: types.STRING
+    },
+    {
+      name: 'successCallback',
+      type: types.FUNCTION,
+      optional: true,
+      nullable: true
+    },
+    {
+      name: 'errorCallback',
+      type: types.FUNCTION,
+      optional: true,
+      nullable: true
+    }
+  ]);
+
+  var keysList = "";
+  for (var i = 0; i < args.keyNames.length; ++i) {
+    if (!map[args.keyNames[i]]) {
+      throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+                                'Invalid key name: "' + args.keyNames[i] + '"');
+    }
+    keysList += map[args.keyNames[i]].keyName + ((i < args.keyNames.length - 1) ? "," : "");
+  }
+
+  setTimeout(function() {
+    var ret = native.sendRuntimeSyncMessage('tizen://api/inputdevice/registerKeyBatch', keysList);
+    if (ret === 'error') {
+      native.callIfPossible(args.errorCallback, new WebAPIException(
+          WebAPIException.UNKNOWN_ERR, 'Failed to register keys.'));
+    } else {
+      native.callIfPossible(args.successCallback);
+    }
+  }.bind(this), 0);
+};
+
+InputDeviceManager.prototype.unregisterKeyBatch = function() {
+  var args = validator.validateMethod(arguments, [
+    {
+      name: 'keyNames',
+      type: types.ARRAY,
+      values: types.STRING
+    },
+    {
+      name: 'successCallback',
+      type: types.FUNCTION,
+      optional: true,
+      nullable: true
+    },
+    {
+      name: 'errorCallback',
+      type: types.FUNCTION,
+      optional: true,
+      nullable: true
+    }
+  ]);
+
+  var keysList = "";
+  for (var i = 0; i < args.keyNames.length; ++i) {
+    if (!map[args.keyNames[i]]) {
+      throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+                                'Invalid key name: "' + args.keyNames[i] + '"');
+    }
+    keysList += map[args.keyNames[i]].keyName + ((i < args.keyNames.length - 1) ? "," : "");
+  }
+
+  setTimeout(function() {
+    var ret = native.sendRuntimeSyncMessage('tizen://api/inputdevice/unregisterKeyBatch', keysList);
+    if (ret === 'error') {
+      native.callIfPossible(args.errorCallback, new WebAPIException(
+          WebAPIException.UNKNOWN_ERR, 'Failed to unregister keys.'));
+    } else {
+      native.callIfPossible(args.successCallback);
+    }
+  }.bind(this), 0);
+};
+
+// Exports
+exports = new InputDeviceManager();
diff --git a/webWidgetTCT_device/src/inputdevice/inputdevice_extension.cc b/webWidgetTCT_device/src/inputdevice/inputdevice_extension.cc
new file mode 100755 (executable)
index 0000000..cf59eab
--- /dev/null
@@ -0,0 +1,30 @@
+// Copyright 2014 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "../inputdevice/inputdevice_extension.h"
+#include "../inputdevice/inputdevice_instance.h"
+
+// This will be generated from inputdevice_api.js
+extern const char kSource_inputdevice_api[];
+
+namespace extension {
+namespace inputdevice {
+
+InputDeviceExtension::InputDeviceExtension() {
+    SetExtensionName("tizen.inputdevice");
+    SetJavaScriptAPI(kSource_inputdevice_api);
+}
+
+InputDeviceExtension::~InputDeviceExtension() {}
+
+common::Instance* InputDeviceExtension::CreateInstance() {
+    return new InputDeviceInstance;
+}
+
+}  // namespace inputdevice
+}  // namespace extension
+
+common::Extension* CreateExtension() {
+    return new extension::inputdevice::InputDeviceExtension;
+}
diff --git a/webWidgetTCT_device/src/inputdevice/inputdevice_extension.h b/webWidgetTCT_device/src/inputdevice/inputdevice_extension.h
new file mode 100755 (executable)
index 0000000..ae38ead
--- /dev/null
@@ -0,0 +1,26 @@
+// Copyright 2014 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SRC_INPUTDEVICE_INPUTDEVICE_EXTENSION_H_
+#define SRC_INPUTDEVICE_INPUTDEVICE_EXTENSION_H_
+
+#include "common/extension.h"
+
+namespace extension {
+namespace inputdevice {
+
+class InputDeviceExtension : public common::Extension {
+ public:
+    InputDeviceExtension();
+    virtual ~InputDeviceExtension();
+
+ private:
+    virtual common::Instance* CreateInstance();
+};
+
+}  // namespace inputdevice
+}  // namespace extension
+
+#endif  // SRC_INPUTDEVICE_INPUTDEVICE_EXTENSION_H_
+
diff --git a/webWidgetTCT_device/src/inputdevice/inputdevice_instance.cc b/webWidgetTCT_device/src/inputdevice/inputdevice_instance.cc
new file mode 100755 (executable)
index 0000000..d5b7fc4
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2015 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 "../inputdevice/inputdevice_instance.h"
+#include "common/logger.h"
+
+
+namespace extension {
+namespace inputdevice {
+
+InputDeviceInstance::InputDeviceInstance() {
+    LOGD("Enter");
+}
+
+InputDeviceInstance::~InputDeviceInstance() {
+    LOGD("Enter");
+}
+
+}  // namespace inputdevice
+}  // namespace extension
diff --git a/webWidgetTCT_device/src/inputdevice/inputdevice_instance.h b/webWidgetTCT_device/src/inputdevice/inputdevice_instance.h
new file mode 100755 (executable)
index 0000000..c09b16a
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2015 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 SRC_INPUTDEVICE_INPUTDEVICE_INSTANCE_H_
+#define SRC_INPUTDEVICE_INPUTDEVICE_INSTANCE_H_
+
+#include "common/picojson.h"
+#include "common/extension.h"
+
+
+namespace extension {
+namespace inputdevice {
+
+class InputDeviceInstance : public common::ParsedInstance {
+ public:
+    InputDeviceInstance();
+    virtual ~InputDeviceInstance();
+
+ private:
+};
+
+}  // namespace inputdevice
+}  // namespace extension
+
+#endif  // SRC_INPUTDEVICE_INPUTDEVICE_INSTANCE_H_
diff --git a/webWidgetTCT_device/src/keymanager/keymanager.gyp b/webWidgetTCT_device/src/keymanager/keymanager.gyp
new file mode 100755 (executable)
index 0000000..1564135
--- /dev/null
@@ -0,0 +1,31 @@
+{
+  'includes':[
+    '../common/common.gypi',
+  ],
+  'targets': [
+    {
+      'target_name': 'tizen_keymanager',
+      'type': 'loadable_module',
+      'dependencies': [
+        '../common/common.gyp:tizen_common',
+      ],
+      'sources': [
+        'keymanager_api.js',
+        'keymanager_extension.cc',
+        'keymanager_extension.h',
+        'keymanager_instance.cc',
+        'keymanager_instance.h',
+      ],
+      'conditions': [
+        ['tizen == 1', {
+          'variables': {
+            'packages': [
+              'key-manager',
+              'pkgmgr-info',
+            ]
+          },
+        }],
+      ],
+    },
+  ],
+}
diff --git a/webWidgetTCT_device/src/keymanager/keymanager_api.js b/webWidgetTCT_device/src/keymanager/keymanager_api.js
new file mode 100755 (executable)
index 0000000..659b25d
--- /dev/null
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+var validator = xwalk.utils.validator;
+var converter = xwalk.utils.converter;
+var type = xwalk.utils.type;
+var native = new xwalk.utils.NativeManager(extension);
+
+var PermissionType = {
+  "NONE" : "NONE",
+  "READ": "READ",
+  "REMOVE" : "REMOVE",
+  "READ_REMOVE": "READ_REMOVE"
+};
+
+function KeyManager() {
+
+}
+
+KeyManager.prototype.saveData = function() {
+    xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.KEYMANAGER);
+    var args = validator.validateArgs(arguments, [
+      {
+        name: 'aliasName',
+        type: validator.Types.STRING
+      },
+      {
+        name: 'rawData',
+        type: validator.Types.STRING
+      },
+      {
+        name: "password",
+        type: validator.Types.STRING,
+        optional: true,
+        nullable: true
+      },
+      {
+        name: 'successCallback',
+        type: validator.Types.FUNCTION,
+        optional: true,
+        nullable: true
+      },
+      {
+        name: 'errorCallback',
+        type: validator.Types.FUNCTION,
+        optional: true,
+        nullable: true
+      }
+    ]);
+
+    native.call('KeyManager_saveData', {
+      aliasName: _trim(args.aliasName),
+      rawData: args.rawData,
+      password: (args.password ? converter.toString(args.password) : null)
+    }, function(msg) {
+        if (native.isFailure(msg)) {
+          native.callIfPossible(args.errorCallback, native.getErrorObject(msg));
+        } else {
+          native.callIfPossible(args.successCallback);
+        }
+      }
+    );
+  };
+
+KeyManager.prototype.removeData = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.KEYMANAGER);
+
+  var args = validator.validateArgs(arguments, [
+    {
+      name : 'dataAlias',
+      type : validator.Types.DICTIONARY
+    }
+  ]);
+
+  var data_alias = _trim(args.dataAlias.name);
+  if(args.dataAlias.hasOwnProperty('packageId')) {
+    data_alias = args.dataAlias.packageId + ' ' + data_alias;
+  }
+
+  var ret = native.callSync('KeyManager_removeAlias', {
+    aliasName: data_alias
+  });
+  if (native.isFailure(ret)) {
+    throw native.getErrorObject(ret);
+  }
+};
+
+KeyManager.prototype.getData = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.KEYMANAGER);
+  var args = validator.validateArgs(arguments, [
+    {
+      name: "dataAlias",
+      type: validator.Types.DICTIONARY
+    },
+    {
+      name: "password",
+      type: validator.Types.STRING,
+      optional: true,
+      nullable: true
+    }
+  ]);
+
+  var data_alias = _trim(args.dataAlias.name);
+  if(args.dataAlias.hasOwnProperty('packageId')) {
+    data_alias = args.dataAlias.packageId + ' ' + data_alias;
+  }
+
+  var ret = native.callSync('KeyManager_getData', {
+    name: data_alias,
+    password: args.password
+  });
+  if (native.isFailure(ret)) {
+    throw native.getErrorObject(ret);
+  }
+  var result = native.getResultObject(ret);
+  return result.rawData;
+};
+
+KeyManager.prototype.getDataAliasList = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.KEYMANAGER);
+  var ret = native.callSync('KeyManager_getDataAliasList', {});
+  if (native.isFailure(ret)) {
+    throw native.getErrorObject(ret);
+  }
+  return native.getResultObject(ret);
+};
+
+KeyManager.prototype.setPermission = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.KEYMANAGER);
+  var args = validator.validateArgs(arguments, [
+    {
+      name: "dataAlias",
+      type: validator.Types.DICTIONARY
+    },
+    {
+      name: "packageId",
+      type: validator.Types.STRING
+    },
+    {
+      name: 'permissionType',
+      type: validator.Types.ENUM,
+      values: Object.keys(PermissionType)
+    },
+    {
+      name: 'successCallback',
+      type: validator.Types.FUNCTION,
+      optional: true,
+      nullable: true
+    },
+    {
+      name: 'errorCallback',
+      type: validator.Types.FUNCTION,
+      optional: true,
+      nullable: true
+    }
+  ]);
+
+  var data_alias = _trim(args.dataAlias.name);
+  if(args.dataAlias.hasOwnProperty('packageId')) {
+    data_alias = args.dataAlias.packageId + ' ' + data_alias;
+  }
+
+  native.call('KeyManager_setPermissions', {
+    aliasName: data_alias,
+    packageId: args.packageId,
+    permissionType: args.permissionType
+  }, function(msg) {
+    if (native.isFailure(msg)) {
+      native.callIfPossible(args.errorCallback, native.getErrorObject(msg));
+    } else {
+      native.callIfPossible(args.successCallback);
+    }
+  });
+};
+
+function _trim(str){
+  var val = str;
+  if (!type.isString(str)) {
+    val = converter.toString(str);
+  }
+
+  return val.replace(/\s/gi, '');
+}
+
+exports = new KeyManager();
diff --git a/webWidgetTCT_device/src/keymanager/keymanager_extension.cc b/webWidgetTCT_device/src/keymanager/keymanager_extension.cc
new file mode 100755 (executable)
index 0000000..972c55e
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2015 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 "keymanager/keymanager_extension.h"
+
+#include "keymanager/keymanager_instance.h"
+
+namespace {
+const char* kKey = "tizen.KeyManagerKey";
+const char* kData = "tizen.KeyManagerData";
+const char* kCertificate = "tizen.KeyManagerCertificate";
+}
+
+// This will be generated from keymanager_api.js
+extern const char kSource_keymanager_api[];
+
+common::Extension* CreateExtension() {
+  return new KeyManagerExtension;
+}
+
+KeyManagerExtension::KeyManagerExtension() {
+  SetExtensionName("tizen.keymanager");
+  SetJavaScriptAPI(kSource_keymanager_api);
+  const char* entry_points[] = {
+      kKey,
+      kData,
+      kCertificate,
+      NULL
+  };
+  SetExtraJSEntryPoints(entry_points);
+}
+
+KeyManagerExtension::~KeyManagerExtension() {}
+
+common::Instance* KeyManagerExtension::CreateInstance() {
+  return new extension::keymanager::KeyManagerInstance;
+}
diff --git a/webWidgetTCT_device/src/keymanager/keymanager_extension.h b/webWidgetTCT_device/src/keymanager/keymanager_extension.h
new file mode 100755 (executable)
index 0000000..16abbf2
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2015 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 KEYMANAGER_KEYMANAGER_EXTENSION_H_
+#define KEYMANAGER_KEYMANAGER_EXTENSION_H_
+
+#include "common/extension.h"
+
+class KeyManagerExtension : public common::Extension {
+ public:
+  KeyManagerExtension();
+  virtual ~KeyManagerExtension();
+
+ private:
+  virtual common::Instance* CreateInstance();
+};
+
+#endif  // KEYMANAGER_KEYMANAGER_EXTENSION_H_
diff --git a/webWidgetTCT_device/src/keymanager/keymanager_instance.cc b/webWidgetTCT_device/src/keymanager/keymanager_instance.cc
new file mode 100755 (executable)
index 0000000..7060bb3
--- /dev/null
@@ -0,0 +1,294 @@
+/*
+ * Copyright (c) 2015 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 "keymanager/keymanager_instance.h"
+
+#include <ckmc/ckmc-manager.h>
+#include <glib.h>
+#include <pkgmgr-info.h>
+
+#include "common/logger.h"
+#include "common/optional.h"
+#include "common/platform_result.h"
+#include "common/scope_exit.h"
+#include "common/task-queue.h"
+#include "common/tools.h"
+#include "common/current_application.h"
+
+namespace extension {
+namespace keymanager {
+
+using common::ErrorCode;
+using common::optional;
+using common::PlatformResult;
+using common::TaskQueue;
+
+namespace {
+
+typedef std::vector<unsigned char> RawBuffer;
+
+typedef int (*AliasListFunction)(ckmc_alias_list_s**);
+
+void GetGenericAliasList(AliasListFunction func, picojson::object* out) {
+  LoggerD("Enter");
+
+  ckmc_alias_list_s* alias_list = nullptr;
+  int ret = func(&alias_list);
+
+  picojson::value result{picojson::array{}};
+
+  if (CKMC_ERROR_NONE == ret) {
+    auto& aliases = result.get<picojson::array>();
+
+    picojson::value resultElem = picojson::value(picojson::object());
+    picojson::object& obj = resultElem.get<picojson::object>();
+    ckmc_alias_list_s* head = alias_list;
+
+    char* saveptr = nullptr;
+    while (head) {
+      //aliases.push_back(picojson::value(head->alias ? head->alias : ""));
+      if(head->alias) {
+        char* tokenized = strtok_r(head->alias, " ", &saveptr);
+        if (NULL != tokenized) {
+          obj["packageId"] = picojson::value(tokenized);
+          tokenized = strtok_r(NULL, " ", &saveptr);
+          if (NULL != tokenized) {
+            obj["name"] = picojson::value(tokenized);
+          }
+        }
+
+        aliases.push_back(resultElem);
+      }
+
+      head = head->next;
+    }
+
+    if (alias_list) {
+      ckmc_alias_list_all_free(alias_list);
+    }
+  }
+
+  common::tools::ReportSuccess(result, *out);
+}
+}  // namespace
+
+KeyManagerInstance::KeyManagerInstance() {
+  LoggerD("Enter");
+  using std::placeholders::_1;
+  using std::placeholders::_2;
+
+  RegisterSyncHandler("KeyManager_getDataAliasList",
+      std::bind(&KeyManagerInstance::GetDataAliasList, this, _1, _2));
+
+  RegisterSyncHandler("KeyManager_saveData",
+      std::bind(&KeyManagerInstance::SaveData, this, _1, _2));
+
+  RegisterSyncHandler("KeyManager_getData",
+      std::bind(&KeyManagerInstance::GetData, this, _1, _2));
+
+  RegisterSyncHandler("KeyManager_removeAlias",
+      std::bind(&KeyManagerInstance::RemoveAlias, this, _1, _2));
+
+  RegisterSyncHandler("KeyManager_setPermissions",
+      std::bind(&KeyManagerInstance::SetPermission, this, _1, _2));
+}
+
+void KeyManagerInstance::GetDataAliasList(const picojson::value& args,
+                                          picojson::object& out) {
+  LoggerD("Enter");
+  GetGenericAliasList(ckmc_get_data_alias_list, &out);
+}
+
+PlatformResult KeyManagerInstance::GetError(int ret) {
+  char* error = get_error_message(ret);
+  if(CKMC_ERROR_NONE == ret) {
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+  else if(CKMC_ERROR_INVALID_PARAMETER == ret) {
+    LoggerD("%s", error);
+    return PlatformResult(ErrorCode::INVALID_VALUES_ERR, error);
+  }
+  else if(CKMC_ERROR_DB_ALIAS_UNKNOWN == ret) {
+    LoggerD("%s",error);
+    return PlatformResult(ErrorCode::NOT_FOUND_ERR, error);
+  }
+  else if(CKMC_ERROR_AUTHENTICATION_FAILED == ret) {
+    LoggerD("%s",error);
+    return PlatformResult(ErrorCode::VERIFICATION_ERR, error);
+  }
+  else {
+    LoggerD("%s", error);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, error);
+  }
+}
+
+void KeyManagerInstance::SaveData(const picojson::value& args,
+                                  picojson::object& out) {
+  LoggerD("Enter");
+
+  std::string data_raw = args.get("rawData").get<std::string>();
+  std::string alias = args.get("aliasName").get<std::string>();
+  const auto& password_value = args.get("password");
+
+  double callback_id = args.get("callbackId").get<double>();
+
+  auto save_data = [data_raw, password_value, alias](const std::shared_ptr<picojson::value>& result) {
+
+    unsigned char* data = new unsigned char[data_raw.size()];
+    std::copy(data_raw.begin(), data_raw.end(), data);
+
+    std::string password;
+    if (password_value.is<std::string>()) {
+      password = password_value.get<std::string>();
+      LoggerD("password %s ", password.c_str());
+    }
+
+    ckmc_raw_buffer_s raw_data { data, data_raw.size() };
+    ckmc_policy_s policy { password_value.is<std::string>() ?
+        const_cast<char*>(password.c_str()) : nullptr, true };
+
+    int ret = ckmc_save_data(alias.c_str(), raw_data, policy);
+
+    PlatformResult success = GetError(ret);
+
+    if (success) {
+      common::tools::ReportSuccess(result->get<picojson::object>());
+    } else {
+      LoggerE("Failed to save data: %d", ret);
+      common::tools::ReportError(success, &result->get<picojson::object>());
+    }
+
+    delete[] data;
+  };
+
+  auto save_data_result = [this, callback_id](const std::shared_ptr<picojson::value>& result) {
+    result->get<picojson::object>()["callbackId"] = picojson::value{callback_id};
+    Instance::PostMessage(this, result->serialize().c_str());
+  };
+
+  auto queue_data = std::shared_ptr<picojson::value>{new picojson::value{picojson::object()}};
+
+  TaskQueue::GetInstance().Queue<picojson::value>(
+      save_data,
+      save_data_result,
+      queue_data);
+
+  ReportSuccess(out);
+}
+
+void KeyManagerInstance::GetData(const picojson::value& args,
+                                 picojson::object& out) {
+  LoggerD("Enter");
+
+  const auto& data_alias = args.get("name").get<std::string>();
+  const auto& password_value = args.get("password");
+
+  std::string password;
+  if (password_value.is<std::string>()) {
+    password = password_value.get<std::string>();
+    LoggerD("password %s ", password.c_str());
+  }
+
+  LoggerD("data_alias: %s", data_alias.c_str());
+
+  ckmc_raw_buffer_s* data = nullptr;
+  int ret = ckmc_get_data(data_alias.c_str(),
+      password_value.is<std::string>() ? password.c_str() : nullptr, &data);
+
+  if (CKMC_ERROR_NONE == ret) {
+    picojson::object result;
+
+    result["rawData"] = picojson::value(std::string (data->data, data->data + data->size));
+
+    ckmc_buffer_free(data);
+    ReportSuccess(picojson::value{result}, out);
+  } else {
+    LoggerE("Failed to get data: %d", ret);
+
+    PlatformResult error = GetError(ret);
+
+    ReportError(error, &out);
+  }
+}
+
+KeyManagerInstance::~KeyManagerInstance() {
+  LoggerD("Enter");
+}
+
+void KeyManagerInstance::RemoveAlias(const picojson::value& args,
+                                   picojson::object& out) {
+  LoggerD("Enter");
+
+  const std::string& alias = args.get("aliasName").get<std::string>();
+  int ret = ckmc_remove_alias(alias.c_str());
+
+  if (CKMC_ERROR_NONE != ret) {
+    LoggerE("Failed to remove alias [%d]", ret);
+    PlatformResult result = GetError(ret);
+    ReportError(result, &out);
+  } else {
+    ReportSuccess(out);
+  }
+}
+
+void KeyManagerInstance::SetPermission(const picojson::value& args,
+                                            picojson::object& out) {
+  LoggerD("Enter");
+
+  const std::string& data_name = args.get("aliasName").get<std::string>();
+  const std::string& id = args.get("packageId").get<std::string>();
+  const double callback_id = args.get("callbackId").get<double>();
+  const std::string& access = args.get("permissionType").get<std::string>();
+
+  int permissions = CKMC_PERMISSION_NONE;
+  if( "NONE" == access) {
+    permissions = CKMC_PERMISSION_NONE;
+  }
+  else if ("READ" == access) {
+    permissions = CKMC_PERMISSION_READ;
+  }
+  else if ("REMOVE" == access) {
+    permissions = CKMC_PERMISSION_REMOVE;
+  }
+  else if("READ_REMOVE" == access) {
+    permissions = CKMC_PERMISSION_READ | CKMC_PERMISSION_REMOVE;
+  }
+
+  auto set_permissions = [data_name, id, permissions](const std::shared_ptr<picojson::value>& response) -> void {
+    int ret = ckmc_set_permission(data_name.c_str(), id.c_str(), permissions);
+
+    if (CKMC_ERROR_NONE != ret) {
+      PlatformResult result = GetError(ret);
+      common::tools::ReportError(result, &response->get<picojson::object>());
+    } else {
+      common::tools::ReportSuccess(response->get<picojson::object>());
+    }
+  };
+
+  auto set_permissions_response = [this, callback_id](const std::shared_ptr<picojson::value>& response) -> void {
+    picojson::object& obj = response->get<picojson::object>();
+    obj.insert(std::make_pair("callbackId", picojson::value(callback_id)));
+    Instance::PostMessage(this, response->serialize().c_str());
+  };
+
+  TaskQueue::GetInstance().Queue<picojson::value>(
+      set_permissions,
+      set_permissions_response,
+      std::make_shared<picojson::value>(picojson::object()));
+}
+
+} // namespace keymanager
+} // namespace extension
diff --git a/webWidgetTCT_device/src/keymanager/keymanager_instance.h b/webWidgetTCT_device/src/keymanager/keymanager_instance.h
new file mode 100755 (executable)
index 0000000..1d433bf
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2015 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 KEYMANAGER_KEYMANAGER_INSTANCE_H_
+#define KEYMANAGER_KEYMANAGER_INSTANCE_H_
+
+#include "common/extension.h"
+
+namespace extension {
+namespace keymanager {
+
+class KeyManagerInstance : public common::ParsedInstance {
+ public:
+  KeyManagerInstance();
+  virtual ~KeyManagerInstance();
+
+ private:
+
+  void GetDataAliasList(picojson::value const& args, picojson::object& out);
+
+  void SaveData(const picojson::value& args, picojson::object& out);
+  void GetData(const picojson::value& args, picojson::object& out);
+  void RemoveAlias(const picojson::value& args, picojson::object& out);
+
+  void SetPermission(const picojson::value& args, picojson::object& out);
+
+  static common::PlatformResult GetError(int ret);
+};
+
+} // namespace keymanager
+} // namespace extension
+
+#endif // KEYMANAGER_KEYMANAGER_INSTANCE_H_
diff --git a/webWidgetTCT_device/src/mediacontroller/mediacontroller.gyp b/webWidgetTCT_device/src/mediacontroller/mediacontroller.gyp
new file mode 100755 (executable)
index 0000000..9e91e32
--- /dev/null
@@ -0,0 +1,36 @@
+{
+  'includes':[
+    '../common/common.gypi',
+  ],
+  'targets': [
+    {
+      'target_name': 'tizen_mediacontroller',
+      'type': 'loadable_module',
+      'dependencies': [
+        '../common/common.gyp:tizen_common',
+      ],
+      'sources': [
+        'mediacontroller_api.js',
+        'mediacontroller_client.cc',
+        'mediacontroller_client.h',
+        'mediacontroller_extension.cc',
+        'mediacontroller_extension.h',
+        'mediacontroller_instance.cc',
+        'mediacontroller_instance.h',
+        'mediacontroller_server.cc',
+        'mediacontroller_server.h',
+        'mediacontroller_types.cc',
+        'mediacontroller_types.h',
+      ],
+      'conditions': [
+        ['tizen == 1', {
+          'variables': {
+            'packages': [
+              'capi-media-controller',
+            ]
+          },
+        }],
+      ],
+    },
+  ],
+}
diff --git a/webWidgetTCT_device/src/mediacontroller/mediacontroller_api.js b/webWidgetTCT_device/src/mediacontroller/mediacontroller_api.js
new file mode 100755 (executable)
index 0000000..7af9b64
--- /dev/null
@@ -0,0 +1,779 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+var _global = window || global || {};
+
+var utils_ = xwalk.utils;
+var type_ = utils_.type;
+var converter_ = utils_.converter;
+var validator_ = utils_.validator;
+var types_ = validator_.Types;
+var native_ = new xwalk.utils.NativeManager(extension);
+
+// TODO(r.galka) CAPI have no dedicated methods for position/shuffle/repeat change.
+// It should be updated when new version of CAPI will be available.
+// For now implementation is using internal commands.
+var internal_commands_ = {
+  sendPlaybackPosition: '__internal_sendPlaybackPosition',
+  sendShuffleMode: '__internal_sendShuffleMode',
+  sendRepeatMode: '__internal_sendRepeatMode'
+};
+
+function ListenerManager(native, listenerName, handle) {
+  this.listeners = {};
+  this.nextId = 1;
+  this.nativeSet = false;
+  this.native = native;
+  this.listenerName = listenerName;
+  this.handle = handle || function(msg, listener, watchId) {};
+}
+
+ListenerManager.prototype.addListener = function(callback) {
+  var id = this.nextId;
+  if (!this.nativeSet) {
+    this.native.addListener(this.listenerName, function(msg) {
+      for (var watchId in this.listeners) {
+        if (this.listeners.hasOwnProperty(watchId)) {
+          var stop = this.handle(msg, this.listeners[watchId], watchId);
+          if (stop) {
+            break;
+          }
+        }
+      }
+    }.bind(this));
+
+    this.nativeSet = true;
+  }
+
+  this.listeners[id] = callback;
+  ++this.nextId;
+  return id;
+};
+
+ListenerManager.prototype.removeListener = function(watchId) {
+  if (this.listeners.hasOwnProperty(watchId)) {
+    delete this.listeners[watchId];
+  }
+};
+
+var ServerCommandListener = new ListenerManager(native_, '_ServerCommandListener', function(msg, listener) {
+  var data = undefined;
+  data = listener(msg.clientName, msg.command, msg.data);
+
+  if (type_.isUndefined(data)) {
+   data = null;
+  }
+
+  var nativeData = {
+    clientName: msg.clientName,
+    replyId: msg.replyId,
+    data: data
+  };
+
+  var result = native_.callSync('MediaControllerServer_replyCommand', nativeData);
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+});
+
+var ReplyCommandListener = new ListenerManager(native_, '_ReplyCommandListener', function(msg, listener, watchId) {
+  if (msg.replyId === watchId) {
+    listener(msg.data);
+    this.removeListener(watchId);
+    return true;
+  }
+
+  return false;
+});
+
+var ServerPlaybackInfoListener = new ListenerManager(native_, '_ServerPlaybackInfoListener', function(msg, listener) {
+  if (msg.action === 'onplaybackstaterequest') {
+    listener[msg.action](msg.state);
+  }
+  if (msg.action === 'onplaybackpositionrequest') {
+    listener[msg.action](msg.position);
+  }
+  if (msg.action === 'onshufflemoderequest' || msg.action === 'onrepeatmoderequest') {
+    listener[msg.action](msg.mode);
+  }
+});
+
+var ServerInfoStatusListener = new ListenerManager(native_, '_ServerInfoStatusListener', function(msg, listener) {
+  listener(msg.state);
+});
+
+var ServerInfoPlaybackInfoListener = new ListenerManager(native_, '_ServerInfoPlaybackInfoListener', function(msg, listener) {
+  if (msg.action === 'onplaybackchanged') {
+    listener[msg.action](msg.state, msg.position);
+  }
+  if (msg.action === 'onshufflemodechanged' || msg.action === 'onrepeatmodechanged') {
+    listener[msg.action](msg.mode);
+  }
+  if (msg.action === 'onmetadatachanged') {
+    listener[msg.action](new MediaControllerMetadata(msg.metadata));
+  }
+});
+
+var EditManager = function() {
+  this.isAllowed = false;
+};
+
+EditManager.prototype.allow = function() {
+  this.isAllowed = true;
+};
+
+EditManager.prototype.disallow = function() {
+  this.isAllowed = false;
+};
+
+var edit_ = new EditManager();
+
+
+var MediaControllerServerState = {
+  ACTIVE: 'ACTIVE',
+  INACTIVE: 'INACTIVE'
+};
+
+var MediaControllerPlaybackState = {
+  PLAY: 'PLAY',
+  PAUSE: 'PAUSE',
+  STOP: 'STOP',
+  NEXT: 'NEXT',
+  PREV: 'PREV',
+  FORWARD: 'FORWARD',
+  REWIND: 'REWIND'
+};
+
+
+function MediaControllerManager() {}
+
+MediaControllerManager.prototype.getClient = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.MEDIACONTROLLER_CLIENT);
+
+  var result = native_.callSync('MediaControllerManager_getClient', {});
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+
+  return new MediaControllerClient(native_.getResultObject(result));
+};
+
+MediaControllerManager.prototype.createServer = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.MEDIACONTROLLER_SERVER);
+
+  var result = native_.callSync('MediaControllerManager_createServer', {});
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+
+  return new MediaControllerServer(native_.getResultObject(result));
+};
+
+
+var MediaControllerMetadata = function(data) {
+  var _title = '';
+  var _artist = '';
+  var _album = '';
+  var _author = '';
+  var _genre = '';
+  var _duration = '';
+  var _date = '';
+  var _copyright = '';
+  var _description = '';
+  var _trackNum = '';
+  var _picture = '';
+  Object.defineProperties(this, {
+    title: {
+      get: function() {return _title;},
+      set: function(v) {_title = converter_.toString(v)},
+      enumerable: true
+    },
+    artist: {
+      get: function() {return _artist;},
+      set: function(v) {_artist = converter_.toString(v)},
+      enumerable: true
+    },
+    album: {
+      get: function() {return _album;},
+      set: function(v) {_album = converter_.toString(v)},
+      enumerable: true
+    },
+    author: {
+      get: function() {return _author;},
+      set: function(v) {_author = converter_.toString(v)},
+      enumerable: true
+    },
+    genre: {
+      get: function() {return _genre;},
+      set: function(v) {_genre = converter_.toString(v)},
+      enumerable: true
+    },
+    duration: {
+      get: function() {return _duration;},
+      set: function(v) {_duration = converter_.toString(v)},
+      enumerable: true
+    },
+    date: {
+      get: function() {return _date;},
+      set: function(v) {_date = converter_.toString(v)},
+      enumerable: true
+    },
+    copyright: {
+      get: function() {return _copyright;},
+      set: function(v) {_copyright = converter_.toString(v)},
+      enumerable: true
+    },
+    description: {
+      get: function() {return _description;},
+      set: function(v) {_description = converter_.toString(v)},
+      enumerable: true
+    },
+    trackNum: {
+      get: function() {return _trackNum;},
+      set: function(v) {_trackNum = converter_.toString(v)},
+      enumerable: true
+    },
+    picture: {
+      get: function() {return _picture;},
+      set: function(v) {_picture = converter_.toString(v)},
+      enumerable: true
+    }
+  });
+
+  if (data instanceof _global.Object) {
+    for (var prop in data) {
+      if (data.hasOwnProperty(prop) && this.hasOwnProperty(prop)) {
+        this[prop] = data[prop];
+      }
+    }
+  }
+};
+
+var MediaControllerPlaybackInfo = function(data) {
+  var _state = 'STOP';
+  var _position = 0;
+  var _shuffleMode = false;
+  var _repeatMode = false;
+  var _metadata = new MediaControllerMetadata();
+  Object.defineProperties(this, {
+    state: {
+      get: function() {
+        return _state;
+      },
+      set: function(v) {
+        _state = edit_.isAllowed && v ? v : _state;
+      },
+      enumerable: true
+    },
+    position: {
+      get: function() {
+        return _position;
+      },
+      set: function(v) {
+        _position = edit_.isAllowed && v ? v : _position;
+      },
+      enumerable: true
+    },
+    shuffleMode: {
+      get: function() {
+        return _shuffleMode;
+      },
+      set: function(v) {
+        _shuffleMode = edit_.isAllowed && v ? v : _shuffleMode;
+      },
+      enumerable: true
+    },
+    repeatMode: {
+      get: function() {
+        return _repeatMode;
+      },
+      set: function(v) {
+        _repeatMode = edit_.isAllowed && v ? v : _repeatMode;
+      },
+      enumerable: true
+    },
+    metadata: {
+      get: function() {
+        return _metadata;
+      },
+      set: function(v) {
+        _metadata = edit_.isAllowed && v ? new MediaControllerMetadata(v) : _metadata;
+      },
+      enumerable: true
+    }
+  });
+
+  if (data instanceof _global.Object) {
+    for (var prop in data) {
+      if (data.hasOwnProperty(prop) && this.hasOwnProperty(prop)) {
+        this[prop] = data[prop];
+      }
+    }
+  }
+};
+
+function MediaControllerServer(data) {
+  Object.defineProperties(this, {
+    playbackInfo: {
+      value: new MediaControllerPlaybackInfo(data),
+      writable: false,
+      enumerable: true
+    }
+  });
+}
+
+MediaControllerServer.prototype.updatePlaybackState = function(state) {
+  var args = validator_.validateArgs(arguments, [
+    {name: 'state', type: types_.ENUM, values: Object.keys(MediaControllerPlaybackState)}
+  ]);
+
+  var data = {
+    state: args.state
+  };
+
+  var result = native_.callSync('MediaControllerServer_updatePlaybackState', data);
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+
+  edit_.allow();
+  this.playbackInfo.state = args.state;
+  edit_.disallow();
+};
+
+MediaControllerServer.prototype.updatePlaybackPosition = function(position) {
+  var args = validator_.validateArgs(arguments, [
+    {name: 'position', type: types_.UNSIGNED_LONG_LONG}
+  ]);
+
+  var data = {
+    position: args.position
+  };
+
+  var result = native_.callSync('MediaControllerServer_updatePlaybackPosition', data);
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+
+  edit_.allow();
+  this.playbackInfo.position = args.position;
+  edit_.disallow();
+};
+
+MediaControllerServer.prototype.updateShuffleMode = function(mode) {
+  var args = validator_.validateArgs(arguments, [
+    {name: 'mode', type: types_.BOOLEAN}
+  ]);
+
+  var data = {
+    mode: args.mode
+  };
+
+  var result = native_.callSync('MediaControllerServer_updateShuffleMode', data);
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+
+  edit_.allow();
+  this.playbackInfo.shuffleMode = args.mode;
+  edit_.disallow();
+};
+
+MediaControllerServer.prototype.updateRepeatMode = function(mode) {
+  var args = validator_.validateArgs(arguments, [
+    {name: 'mode', type: types_.BOOLEAN}
+  ]);
+
+  var data = {
+    mode: args.mode
+  };
+
+  var result = native_.callSync('MediaControllerServer_updateRepeatMode', data);
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+
+  edit_.allow();
+  this.playbackInfo.repeatMode = args.mode;
+  edit_.disallow();
+};
+
+MediaControllerServer.prototype.updateMetadata = function(metadata) {
+  var args = validator_.validateArgs(arguments, [
+    {name: 'metadata', type: types_.PLATFORM_OBJECT, values: MediaControllerMetadata}
+  ]);
+
+  var data = {
+    metadata: args.metadata
+  };
+
+  var result = native_.callSync('MediaControllerServer_updateMetadata', data);
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+
+  edit_.allow();
+  this.playbackInfo.metadata = args.metadata;
+  edit_.disallow();
+};
+
+MediaControllerServer.prototype.addChangeRequestPlaybackInfoListener = function(listener) {
+  var args = validator_.validateArgs(arguments, [{
+    name: 'listener',
+    type: types_.LISTENER,
+    values: [
+      'onplaybackstaterequest',
+      'onplaybackpositionrequest',
+      'onshufflemoderequest',
+      'onrepeatmoderequest'
+    ]
+  }]);
+
+  if (type_.isEmptyObject(ServerPlaybackInfoListener.listeners)) {
+    var result = native_.callSync('MediaControllerServer_addChangeRequestPlaybackInfoListener', {
+      listenerId: ServerPlaybackInfoListener.listenerName
+    });
+    if (native_.isFailure(result)) {
+      throw native_.getErrorObject(result);
+    }
+  }
+
+  return ServerPlaybackInfoListener.addListener(args.listener);
+};
+
+MediaControllerServer.prototype.removeChangeRequestPlaybackInfoListener = function(watchId) {
+  var args = validator_.validateArgs(arguments, [
+    {name: 'watchId', type: types_.LONG}
+  ]);
+
+  ServerPlaybackInfoListener.removeListener(args.watchId);
+
+  if (type_.isEmptyObject(ServerPlaybackInfoListener.listeners)) {
+    native_.callSync('MediaControllerServer_removeCommandListener');
+  }
+};
+
+MediaControllerServer.prototype.addCommandListener = function(listener) {
+  var args = validator_.validateArgs(arguments, [
+    {name: 'listener', type: types_.FUNCTION}
+  ]);
+
+  if (type_.isEmptyObject(ServerCommandListener.listeners)) {
+    var result = native_.callSync('MediaControllerServer_addCommandListener', {
+      listenerId: ServerCommandListener.listenerName
+    });
+    if (native_.isFailure(result)) {
+      throw native_.getErrorObject(result);
+    }
+  }
+
+  return ServerCommandListener.addListener(args.listener);
+};
+
+MediaControllerServer.prototype.removeCommandListener = function(watchId) {
+  var args = validator_.validateArgs(arguments, [
+    {name: 'watchId', type: types_.LONG}
+  ]);
+
+  ServerCommandListener.removeListener(args.watchId);
+
+  if (type_.isEmptyObject(ServerCommandListener.listeners)) {
+    native_.callSync('MediaControllerServer_removeCommandListener');
+  }
+};
+
+
+function MediaControllerClient() {}
+
+MediaControllerClient.prototype.findServers = function(successCallback, errorCallback) {
+  var args = validator_.validateArgs(arguments, [
+    {name: 'successCallback', type: types_.FUNCTION},
+    {name: 'errorCallback', type: types_.FUNCTION, optional: true, nullable: true}
+  ]);
+
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+      return;
+    }
+    var info = [];
+    var data = native_.getResultObject(result);
+    for (var i = 0; i < data.length; i++) {
+      info.push(new MediaControllerServerInfo(data[i]));
+    }
+    native_.callIfPossible(args.successCallback, info);
+  };
+
+  native_.call('MediaControllerClient_findServers', {}, callback);
+};
+
+MediaControllerClient.prototype.getLatestServerInfo = function() {
+
+  var result = native_.callSync('MediaControllerClient_getLatestServerInfo', {});
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+
+  var serverInfo = native_.getResultObject(result);
+  if (serverInfo) {
+    serverInfo = new MediaControllerServerInfo(serverInfo);
+  }
+  return serverInfo;
+};
+
+
+function MediaControllerServerInfo(data) {
+  Object.defineProperties(this, {
+    name: {
+      value: data.name,
+      writable: false,
+      enumerable: true
+    },
+    state: {
+      value: data.state,
+      writable: false,
+      enumerable: true
+    },
+    playbackInfo: {
+      get: function () {
+        var result = native_.callSync('MediaControllerClient_getPlaybackInfo', {name: this.name});
+        if (native_.isFailure(result)) {
+          throw new native_.getErrorObject(result);
+        }
+        edit_.allow();
+        var data = native_.getResultObject(result);
+        var playbackInfo = new MediaControllerPlaybackInfo(data);
+        edit_.disallow();
+
+        return playbackInfo;
+      }.bind(this),
+      set: function() {},
+      enumerable: true
+    }
+  });
+}
+
+
+MediaControllerServerInfo.prototype.sendPlaybackState = function(state, successCallback, errorCallback) {
+  var args = validator_.validateArgs(arguments, [
+    {name: 'state', type: types_.ENUM, values: Object.keys(MediaControllerPlaybackState)},
+    {name: 'successCallback', type: types_.FUNCTION, optional: true, nullable: true},
+    {name: 'errorCallback', type: types_.FUNCTION, optional: true, nullable: true}
+  ]);
+
+  var data = {
+    name: this.name,
+    state: args.state
+  };
+
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+      return;
+    }
+    native_.callIfPossible(args.successCallback);
+  };
+
+  native_.call('MediaControllerServerInfo_sendPlaybackState', data, callback);
+};
+
+MediaControllerServerInfo.prototype.sendPlaybackPosition = function(position, successCallback, errorCallback) {
+  var args = validator_.validateArgs(arguments, [
+    {name: 'position', type: types_.LONG_LONG},
+    {name: 'successCallback', type: types_.FUNCTION, optional: true, nullable: true},
+    {name: 'errorCallback', type: types_.FUNCTION, optional: true, nullable: true}
+  ]);
+
+  if (args.position < 0) {
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR);
+  }
+
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+      return;
+    }
+    native_.callIfPossible(args.successCallback);
+  };
+
+  var data = {
+    position: args.position
+  };
+
+  sendDefinedCommand(this.name, internal_commands_.sendPlaybackPosition, data, callback);
+};
+
+MediaControllerServerInfo.prototype.sendShuffleMode = function(mode, successCallback, errorCallback) {
+  var args = validator_.validateArgs(arguments, [
+    {name: 'mode', type: types_.BOOLEAN},
+    {name: 'successCallback', type: types_.FUNCTION, optional: true, nullable: true},
+    {name: 'errorCallback', type: types_.FUNCTION, optional: true, nullable: true}
+  ]);
+
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+      return;
+    }
+    native_.callIfPossible(args.successCallback);
+  };
+
+  var data = {
+    mode: args.mode
+  };
+  sendDefinedCommand(this.name, internal_commands_.sendShuffleMode, data, callback);
+};
+
+MediaControllerServerInfo.prototype.sendRepeatMode = function(mode, successCallback, errorCallback) {
+  var args = validator_.validateArgs(arguments, [
+    {name: 'mode', type: types_.BOOLEAN},
+    {name: 'successCallback', type: types_.FUNCTION, optional: true, nullable: true},
+    {name: 'errorCallback', type: types_.FUNCTION, optional: true, nullable: true}
+  ]);
+
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+      return;
+    }
+    native_.callIfPossible(args.successCallback);
+  };
+
+  var data = {
+    mode: args.mode
+  };
+  sendDefinedCommand(this.name, internal_commands_.sendRepeatMode, data, callback);
+};
+
+function sendDefinedCommand(name_, command_, data_, callback_) {
+  var nativeData = {
+    command: command_,
+    data: data_,
+    name: name_
+  };
+
+  var replyId = ReplyCommandListener.addListener(callback_);
+
+  nativeData.replyId = replyId;
+  nativeData.listenerId = ReplyCommandListener.listenerName;
+
+  native_.call('MediaControllerServerInfo_sendCommand', nativeData, callback_);
+};
+
+MediaControllerServerInfo.prototype.sendCommand = function(command, data, successCallback, errorCallback) {
+  var args = validator_.validateArgs(arguments, [
+    {name: 'command', type: types_.STRING},
+    {name: 'data', type: types_.DICTIONARY},
+    {name: 'successCallback', type: types_.FUNCTION},
+    {name: 'errorCallback', type: types_.FUNCTION, optional: true, nullable: true}
+  ]);
+
+  var nativeData = {
+    command: args.command,
+    data: args.data,
+    name: this.name
+  };
+
+  var replyId = ReplyCommandListener.addListener(successCallback);
+
+  nativeData.replyId = replyId;
+  nativeData.listenerId = ReplyCommandListener.listenerName;
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+      return;
+    }
+    args.successCallback(native_.getResultObject(result));
+  };
+
+  native_.call('MediaControllerServerInfo_sendCommand', nativeData, callback);
+};
+
+MediaControllerServerInfo.prototype.addServerStatusChangeListener = function(listener) {
+  var args = validator_.validateArgs(arguments, [
+    {name: 'listener', type: types_.FUNCTION}
+  ]);
+
+  if (type_.isEmptyObject(ServerInfoStatusListener.listeners)) {
+    var result = native_.callSync('MediaControllerServerInfo_addServerStatusChangeListener', {
+      listenerId: ServerInfoStatusListener.listenerName
+    });
+    if (native_.isFailure(result)) {
+      throw native_.getErrorObject(result);
+    }
+  }
+
+  return ServerInfoStatusListener.addListener(args.listener);
+};
+
+MediaControllerServerInfo.prototype.removeServerStatusChangeListener = function(watchId) {
+  var args = validator_.validateArgs(arguments, [
+    {name: 'watchId', type: types_.LONG}
+  ]);
+
+  ServerInfoStatusListener.removeListener(args.watchId);
+
+  if (type_.isEmptyObject(ServerInfoStatusListener.listeners)) {
+    native_.callSync('MediaControllerServerInfo_removeServerStatusChangeListener');
+  }
+};
+
+MediaControllerServerInfo.prototype.addPlaybackInfoChangeListener = function(listener) {
+  var args = validator_.validateArgs(arguments, [{
+    name: 'listener',
+    type: types_.LISTENER,
+    values: [
+      'onplaybackchanged',
+      'onshufflemodechanged',
+      'onrepeatmodechanged',
+      'onmetadatachanged'
+    ]
+  }]);
+
+  if (type_.isEmptyObject(ServerInfoPlaybackInfoListener.listeners)) {
+    var result = native_.callSync(
+        'MediaControllerServerInfo_addPlaybackInfoChangeListener', {
+          listenerId: ServerInfoPlaybackInfoListener.listenerName
+        });
+    if (native_.isFailure(result)) {
+      throw native_.getErrorObject(result);
+    }
+  }
+
+  return ServerInfoPlaybackInfoListener.addListener(args.listener);
+};
+
+MediaControllerServerInfo.prototype.removePlaybackInfoChangeListener = function(watchId) {
+  var args = validator_.validateArgs(arguments, [
+    {name: 'watchId', type: types_.LONG}
+  ]);
+
+  ServerInfoPlaybackInfoListener.removeListener(args.watchId);
+
+  if (type_.isEmptyObject(ServerInfoPlaybackInfoListener.listeners)) {
+    native_.callSync('MediaControllerServerInfo_removePlaybackInfoChangeListener');
+  }
+};
+
+
+exports = new MediaControllerManager();
diff --git a/webWidgetTCT_device/src/mediacontroller/mediacontroller_client.cc b/webWidgetTCT_device/src/mediacontroller/mediacontroller_client.cc
new file mode 100755 (executable)
index 0000000..7fe0894
--- /dev/null
@@ -0,0 +1,651 @@
+/*
+ * Copyright (c) 2015 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 "mediacontroller/mediacontroller_client.h"
+
+#include <bundle.h>
+#include <bundle_internal.h>
+#include <memory>
+
+#include "common/logger.h"
+#include "common/scope_exit.h"
+
+#include "mediacontroller/mediacontroller_types.h"
+
+namespace extension {
+namespace mediacontroller {
+
+using common::PlatformResult;
+using common::ErrorCode;
+
+MediaControllerClient::MediaControllerClient() : handle_(nullptr) {
+  LoggerD("Enter");
+}
+
+MediaControllerClient::~MediaControllerClient() {
+  LoggerD("Enter");
+  if (handle_) {
+    int ret = mc_client_destroy(handle_);
+    if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+      LOGGER(ERROR) << "Unable to destroy media controller client";
+    }
+  }
+}
+
+PlatformResult MediaControllerClient::Init() {
+  LoggerD("Enter");
+  int ret = mc_client_create(&handle_);
+  if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+    LOGGER(ERROR) << "Unable to create media controller client, error: " << ret;
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Unable to create media controller client");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult MediaControllerClient::FindServers(picojson::array* servers) {
+
+  LoggerD("Enter");
+  int ret;
+
+  ret = mc_client_foreach_server(handle_, FindServersCallback, servers);
+  if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+    LOGGER(ERROR) << "Unable to fetch active servers, error: " << ret;
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Unable to create media controller client");
+  }
+
+  // check latest server state - if exist
+  picojson::value latest_server = picojson::value();
+  PlatformResult result = GetLatestServerInfo(&latest_server);
+  if (!result) {
+    LOGGER(ERROR) << "GetLatestServerInfo failed, error: " << result.message();
+    return result;
+  }
+
+  if (latest_server.is<picojson::null>()) {
+    LOGGER(DEBUG) << "No latest server available";
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+
+  const std::string& latest_name = latest_server.get("name").get<std::string>();
+
+  // update current server state in list
+  for (auto& it : *servers) {
+    picojson::object& server = it.get<picojson::object>();
+    if (server["name"].get<std::string>() == latest_name) {
+      server["state"] = latest_server.get("state");
+      break;
+    }
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+bool MediaControllerClient::FindServersCallback(const char* server_name,
+                                                void* user_data) {
+
+  LoggerD("Enter");
+  picojson::array* servers = static_cast<picojson::array*>(user_data);
+
+  picojson::value server = picojson::value(picojson::object());
+  picojson::object& server_o = server.get<picojson::object>();
+  server_o["name"] = picojson::value(std::string(server_name));
+  // active by default in CAPI
+  server_o["state"] = picojson::value(std::string("ACTIVE"));
+
+  servers->push_back(server);
+
+  return true;
+}
+
+PlatformResult MediaControllerClient::GetLatestServerInfo(
+    picojson::value* server_info) {
+
+  LoggerD("Enter");
+  int ret;
+
+  char* name = nullptr;
+  SCOPE_EXIT {
+    free(name);
+  };
+  mc_server_state_e state;
+  ret = mc_client_get_latest_server_info(handle_, &name, &state);
+  if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+    LOGGER(ERROR) << "mc_client_get_latest_server_info failed, error: " << ret;
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Error getting latest server info");
+  }
+
+  if (!name) {
+    LOGGER(DEBUG) << "No active server available";
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+
+  std::string state_str;
+  PlatformResult result = Types::PlatformEnumToString(
+      Types::kMediaControllerServerState, static_cast<int>(state), &state_str);
+  if (!result) {
+    LOGGER(ERROR) << "PlatformEnumToString failed, error: " << result.message();
+    return result;
+  }
+
+  *server_info = picojson::value(picojson::object());
+  picojson::object& obj = server_info->get<picojson::object>();
+  obj["name"] = picojson::value(std::string(name));
+  obj["state"] = picojson::value(state_str);
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult MediaControllerClient::GetPlaybackInfo(
+    const std::string& server_name,
+    picojson::object* playback_info) {
+
+  LoggerD("Enter");
+  int ret;
+
+  mc_playback_h playback_h;
+  ret = mc_client_get_server_playback_info(handle_,
+                                           server_name.c_str(),
+                                           &playback_h);
+  if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+    LOGGER(ERROR) << "mc_client_get_latest_server_info failed, error: " << ret;
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Error getting latest server info");
+  }
+
+  SCOPE_EXIT {
+    mc_client_destroy_playback(playback_h);
+  };
+
+  // playback state
+  std::string state;
+  PlatformResult result = Types::ConvertPlaybackState(playback_h, &state);
+  if (!result) {
+    LOGGER(ERROR) << "ConvertPlaybackState failed, error: " << result.message();
+    return result;
+  }
+
+  // playback position
+  double position;
+  result = Types::ConvertPlaybackPosition(playback_h, &position);
+  if (!result) {
+    LOGGER(ERROR) << "ConvertPlaybackPosition failed, error: " << result.message();
+    return result;
+  }
+
+  // shuffle mode
+  mc_shuffle_mode_e shuffle;
+  ret = mc_client_get_server_shuffle_mode(
+      handle_, server_name.c_str(), &shuffle);
+  if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+    LOGGER(ERROR) << "mc_client_get_server_shuffle_mode failed, error: " << ret;
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Error getting shuffle mode");
+  }
+
+  // repeat mode
+  mc_repeat_mode_e repeat;
+  ret = mc_client_get_server_repeat_mode(
+      handle_, server_name.c_str(), &repeat);
+  if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+    LOGGER(ERROR) << "mc_client_get_server_repeat_mode failed, error: " << ret;
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Error getting repeat mode");
+  }
+
+  // metadata
+  picojson::value metadata = picojson::value(picojson::object());
+  result = GetMetadata(server_name, &metadata.get<picojson::object>());
+  if (!result) {
+    return result;
+  }
+
+  // fill return object
+  (*playback_info)["state"] = picojson::value(state);
+  (*playback_info)["position"] = picojson::value(position);
+  (*playback_info)["shuffleMode"] = picojson::value(shuffle == MC_SHUFFLE_MODE_ON);
+  (*playback_info)["repeatMode"] = picojson::value(repeat == MC_REPEAT_MODE_ON);
+  (*playback_info)["metadata"] = metadata;
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult MediaControllerClient::GetMetadata(
+    const std::string& server_name,
+    picojson::object* metadata) {
+
+  LoggerD("Enter");
+  int ret;
+
+  mc_metadata_h metadata_h;
+  ret = mc_client_get_server_metadata(handle_, server_name.c_str(),
+                                      &metadata_h);
+  if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+    LOGGER(ERROR) << "mc_client_get_server_metadata failed, error: " << ret;
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Error getting metadata");
+  }
+
+  SCOPE_EXIT {
+    mc_client_destroy_metadata(metadata_h);
+  };
+
+  PlatformResult result = Types::ConvertMetadata(metadata_h, metadata);
+  if (!result) {
+    return result;
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult MediaControllerClient::SetServerStatusChangeListener(
+    JsonCallback callback) {
+
+  LoggerD("Enter");
+  if (callback && server_status_listener_) {
+    LOGGER(ERROR) << "Listener already registered";
+    return PlatformResult(ErrorCode::INVALID_STATE_ERR,
+                          "Listener already registered");
+  }
+
+  server_status_listener_ = callback;
+
+  int ret;
+  if (callback) { // set platform callbacks
+
+    ret = mc_client_set_server_update_cb(handle_, OnServerStatusUpdate, this);
+    if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+      LOGGER(ERROR) << "Unable to set server status listener, error: " << ret;
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "Unable to set server status listener");
+    }
+
+  } else { // unset platform callbacks
+
+    ret = mc_client_unset_server_update_cb(handle_);
+    if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+      LOGGER(ERROR) << "Unable to unset server status listener, error: " << ret;
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "Unable to unset server status listener");
+    }
+
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+void MediaControllerClient::OnServerStatusUpdate(const char* server_name,
+                                                 mc_server_state_e state,
+                                                 void* user_data) {
+
+  LoggerD("Enter");
+  MediaControllerClient* client = static_cast<MediaControllerClient*>(user_data);
+
+  if (!client->server_status_listener_) {
+    LOGGER(DEBUG) << "No server status listener registered, skipping";
+    return;
+  }
+
+  // server state
+  std::string state_str;
+  PlatformResult result = Types::PlatformEnumToString(
+      Types::kMediaControllerServerState, static_cast<int>(state), &state_str);
+  if (!result) {
+    LOGGER(ERROR) << "PlatformEnumToString failed, error: " << result.message();
+    return;
+  }
+
+  picojson::value data = picojson::value(picojson::object());
+  picojson::object& data_o = data.get<picojson::object>();
+
+  data_o["state"] = picojson::value(state_str);
+
+  client->server_status_listener_(&data);
+}
+
+PlatformResult MediaControllerClient::SetPlaybackInfoListener(
+    JsonCallback callback) {
+
+  LoggerD("Enter");
+  if (callback && playback_info_listener_) {
+    LOGGER(ERROR) << "Listener already registered";
+    return PlatformResult(ErrorCode::INVALID_STATE_ERR,
+                          "Listener already registered");
+  }
+
+  playback_info_listener_ = callback;
+
+  int ret;
+  if (callback) { // set platform callbacks
+
+    ret = mc_client_set_playback_update_cb(handle_, OnPlaybackUpdate, this);
+    if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+      LOGGER(ERROR) << "Unable to register playback listener, error: " << ret;
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "Unable to register playback listener");
+    }
+
+    ret = mc_client_set_shuffle_mode_update_cb(handle_, OnShuffleModeUpdate, this);
+    if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+      LOGGER(ERROR) << "Unable to register shuffle mode listener, error: " << ret;
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "Unable to register shuffle mode listener");
+    }
+
+    ret = mc_client_set_repeat_mode_update_cb(handle_, OnRepeatModeUpdate, this);
+    if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+      LOGGER(ERROR) << "Unable to register repeat mode listener, error: " << ret;
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "Unable to register repeat mode listener");
+    }
+
+    ret = mc_client_set_metadata_update_cb(handle_, OnMetadataUpdate, this);
+    if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+      LOGGER(ERROR) << "Unable to register metadata listener, error: " << ret;
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "Unable to register metadata listener");
+    }
+
+  } else { // unset platform callbacks
+
+    ret = mc_client_unset_playback_update_cb(handle_);
+    if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+      LOGGER(ERROR) << "Unable to unregister playback listener, error: " << ret;
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "Unable to unregister playback listener");
+    }
+
+    ret = mc_client_unset_shuffle_mode_update_cb(handle_);
+    if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+      LOGGER(ERROR) << "Unable to unregister shuffle mode listener, error: " << ret;
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "Unable to unregister shuffle mode listener");
+    }
+
+    ret = mc_client_unset_repeat_mode_update_cb(handle_);
+    if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+      LOGGER(ERROR) << "Unable to unregister repeat mode listener, error: " << ret;
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "Unable to unregister repeat mode listener");
+    }
+
+    ret = mc_client_unset_metadata_update_cb(handle_);
+    if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+      LOGGER(ERROR) << "Unable to unregister metadata listener, error: " << ret;
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "Unable to unregister metadata listener");
+    }
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+};
+
+void MediaControllerClient::OnPlaybackUpdate(const char *server_name,
+                                             mc_playback_h playback,
+                                             void *user_data) {
+
+  LoggerD("Enter");
+  MediaControllerClient* client = static_cast<MediaControllerClient*>(user_data);
+
+  if (!client->playback_info_listener_) {
+    LOGGER(DEBUG) << "No playback info listener registered, skipping";
+    return;
+  }
+
+  // playback state
+  std::string state;
+  PlatformResult result = Types::ConvertPlaybackState(playback, &state);
+  if (!result) {
+    LOGGER(ERROR) << "ConvertPlaybackState failed, error: " << result.message();
+    return;
+  }
+
+  // playback position
+  double position;
+  result = Types::ConvertPlaybackPosition(playback, &position);
+  if (!result) {
+    LOGGER(ERROR) << "ConvertPlaybackPosition failed, error: " << result.message();
+    return;
+  }
+
+  picojson::value data = picojson::value(picojson::object());
+  picojson::object& data_o = data.get<picojson::object>();
+
+  data_o["action"] = picojson::value(std::string("onplaybackchanged"));
+  data_o["state"] = picojson::value(state);
+  data_o["position"] = picojson::value(position);
+
+  client->playback_info_listener_(&data);
+}
+
+void MediaControllerClient::OnShuffleModeUpdate(const char *server_name,
+                                             mc_shuffle_mode_e mode,
+                                             void *user_data) {
+
+  LoggerD("Enter");
+  MediaControllerClient* client = static_cast<MediaControllerClient*>(user_data);
+
+  if (!client->playback_info_listener_) {
+    LOGGER(DEBUG) << "No playback info listener registered, skipping";
+    return;
+  }
+
+  picojson::value data = picojson::value(picojson::object());
+  picojson::object& data_o = data.get<picojson::object>();
+
+  data_o["action"] = picojson::value(std::string("onshufflemodechanged"));
+  data_o["mode"] = picojson::value(mode == MC_SHUFFLE_MODE_ON);
+
+  client->playback_info_listener_(&data);
+}
+
+void MediaControllerClient::OnRepeatModeUpdate(const char *server_name,
+                                                mc_repeat_mode_e mode,
+                                                void *user_data) {
+
+  LoggerD("Enter");
+  MediaControllerClient* client = static_cast<MediaControllerClient*>(user_data);
+
+  if (!client->playback_info_listener_) {
+    LOGGER(DEBUG) << "No playback info listener registered, skipping";
+    return;
+  }
+
+  picojson::value data = picojson::value(picojson::object());
+  picojson::object& data_o = data.get<picojson::object>();
+
+  data_o["action"] = picojson::value(std::string("onrepeatmodechanged"));
+  data_o["mode"] = picojson::value(mode == MC_REPEAT_MODE_ON);
+
+  client->playback_info_listener_(&data);
+}
+
+void MediaControllerClient::OnMetadataUpdate(const char* server_name,
+                                             mc_metadata_h metadata_h,
+                                             void* user_data) {
+
+  LoggerD("Enter");
+  MediaControllerClient* client = static_cast<MediaControllerClient*>(user_data);
+
+  if (!client->playback_info_listener_) {
+    LOGGER(DEBUG) << "No playback info listener registered, skipping";
+    return;
+  }
+
+  picojson::value data = picojson::value(picojson::object());
+  picojson::object& data_o = data.get<picojson::object>();
+
+  picojson::value metadata = picojson::value(picojson::object());
+  PlatformResult result = Types::ConvertMetadata(
+      metadata_h, &metadata.get<picojson::object>());
+  if (!result) {
+    LOGGER(ERROR) << "ConvertMetadata failed, error: " << result.message();
+    return;
+  }
+
+  data_o["action"] = picojson::value(std::string("onmetadatachanged"));
+  data_o["metadata"] = metadata;
+
+  client->playback_info_listener_(&data);
+}
+
+PlatformResult MediaControllerClient::SendCommand(
+    const std::string& server_name,
+    const std::string& command,
+    const picojson::value& data,
+    const std::string& reply_id,
+    const JsonCallback& reply_cb) {
+
+  LoggerD("Enter");
+  bundle* bundle = bundle_create();
+  SCOPE_EXIT {
+    bundle_free(bundle);
+  };
+
+  int ret;
+  ret = bundle_add(bundle, "replyId", reply_id.c_str());
+  if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+    LOGGER(ERROR) << "bundle_add(replyId) failed, error: " << ret;
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Unable to add replyId to bundle");
+  }
+
+  ret = bundle_add(bundle, "data", data.serialize().c_str());
+  if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+    LOGGER(ERROR) << "bundle_add(data) failed, error: " << ret;
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Unable to add data to bundle");
+  }
+
+  ret = mc_client_send_custom_command(handle_,
+                                      server_name.c_str(),
+                                      command.c_str(),
+                                      bundle,
+                                      OnCommandReply,
+                                      this);
+  if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+    LOGGER(ERROR) << "mc_client_send_custom_command failed, error: " << ret;
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Error sending custom command");
+  }
+
+  command_reply_callback_ = reply_cb;
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+void MediaControllerClient::OnCommandReply(const char* server_name,
+                                           int result_code,
+                                           bundle* bundle,
+                                           void* user_data) {
+
+  LoggerD("Enter");
+  MediaControllerClient* client = static_cast<MediaControllerClient*>(user_data);
+
+  picojson::value reply = picojson::value(picojson::object());
+  picojson::object& reply_o = reply.get<picojson::object>();
+
+  int ret;
+  char* reply_id_str = nullptr;
+  char* data_str = nullptr;
+  SCOPE_EXIT {
+    free(reply_id_str);
+    free(data_str);
+  };
+
+  ret = bundle_get_str(bundle, "replyId", &reply_id_str);
+  if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+    LOGGER(ERROR) << "bundle_get_str(replyId) failed, error: " << ret;
+    return;
+  }
+
+  reply_o["replyId"] = picojson::value(std::string(reply_id_str));
+
+  ret = bundle_get_str(bundle, "data", &data_str);
+  if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+    LOGGER(ERROR) << "bundle_get_str(data) failed, error: " << ret;
+    return;
+  }
+
+  picojson::value data;
+  std::string err;
+  picojson::parse(data, data_str, data_str + strlen(data_str), &err);
+  if (!err.empty()) {
+    LOGGER(ERROR) << "Failed to parse bundle data: " << err;
+    return;
+  }
+  reply_o["data"] = data;
+
+  client->command_reply_callback_(&reply);
+}
+
+PlatformResult MediaControllerClient::SendPlaybackState(
+    const std::string& server_name,
+    const std::string& state) {
+
+  LoggerD("Enter");
+  int state_e;
+  PlatformResult result = Types::StringToPlatformEnum(
+      Types::kMediaControllerPlaybackState, state, &state_e);
+  if (!result) {
+    return result;
+  }
+
+  int ret;
+  ret = mc_client_send_playback_state_command(
+      handle_, server_name.c_str(), static_cast<mc_playback_states_e>(state_e));
+  if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+    LOGGER(ERROR) << "mc_client_send_playback_state_command failed, error: "
+        << ret;
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Error sending playback state");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult MediaControllerClient::SendPlaybackPosition(
+    const std::string& server_name,
+    double position) {
+
+  // TODO(r.galka) implement when dedicated method will be available in CAPI
+
+  return PlatformResult(ErrorCode::NOT_SUPPORTED_ERR);
+}
+
+PlatformResult MediaControllerClient::SendShuffleMode(
+    const std::string& server_name,
+    bool mode) {
+
+  // TODO(r.galka) implement when dedicated method will be available in CAPI
+
+  return PlatformResult(ErrorCode::NOT_SUPPORTED_ERR);
+}
+
+PlatformResult MediaControllerClient::SendRepeatMode(
+    const std::string& server_name,
+    bool mode) {
+
+  // TODO(r.galka) implement when dedicated method will be available in CAPI
+
+  return PlatformResult(ErrorCode::NOT_SUPPORTED_ERR);
+}
+
+} // namespace mediacontroller
+} // namespace extension
diff --git a/webWidgetTCT_device/src/mediacontroller/mediacontroller_client.h b/webWidgetTCT_device/src/mediacontroller/mediacontroller_client.h
new file mode 100755 (executable)
index 0000000..9d7b193
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2015 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 MEDIACONTROLLER_MEDIACONTROLLER_CLIENT_H_
+#define MEDIACONTROLLER_MEDIACONTROLLER_CLIENT_H_
+
+#include <media_controller_client.h>
+#include <string>
+
+#include "common/platform_result.h"
+
+#include "mediacontroller/mediacontroller_types.h"
+
+namespace extension {
+namespace mediacontroller {
+
+class MediaControllerClient {
+ public:
+  MediaControllerClient();
+  virtual ~MediaControllerClient();
+
+  common::PlatformResult Init();
+  common::PlatformResult FindServers(picojson::array* servers);
+  common::PlatformResult GetLatestServerInfo(picojson::value* server_info);
+  common::PlatformResult GetPlaybackInfo(const std::string& server_name,
+                                         picojson::object* playback_info);
+  common::PlatformResult GetMetadata(const std::string& server_name,
+                                         picojson::object* metadata);
+
+  common::PlatformResult SendPlaybackState(const std::string& server_name,
+                                           const std::string& state);
+  common::PlatformResult SendPlaybackPosition(const std::string& server_name,
+                                              double position);
+  common::PlatformResult SendShuffleMode(const std::string& server_name,
+                                         bool mode);
+  common::PlatformResult SendRepeatMode(const std::string& server_name,
+                                        bool mode);
+
+  common::PlatformResult SendCommand(const std::string& server_name,
+                                     const std::string& command,
+                                     const picojson::value& data,
+                                     const std::string& reply_id,
+                                     const JsonCallback& reply_cb);
+
+  common::PlatformResult SetServerStatusChangeListener(JsonCallback callback);
+  common::PlatformResult SetPlaybackInfoListener(JsonCallback callback);
+
+ private:
+  mc_client_h handle_;
+
+  JsonCallback playback_info_listener_;
+  JsonCallback server_status_listener_;
+  JsonCallback command_reply_callback_;
+
+  static bool FindServersCallback(const char* server_name, void* user_data);
+
+  static void OnServerStatusUpdate(const char *server_name,
+                                   mc_server_state_e state,
+                                   void *user_data);
+  static void OnCommandReply(const char* server_name,
+                             int result_code,
+                             bundle* bundle,
+                             void* user_data);
+  static void OnPlaybackUpdate(const char *server_name,
+                               mc_playback_h playback,
+                               void *user_data);
+  static void OnShuffleModeUpdate(const char *server_name,
+                                  mc_shuffle_mode_e mode,
+                                  void *user_data);
+  static void OnRepeatModeUpdate(const char *server_name,
+                                  mc_repeat_mode_e mode,
+                                  void *user_data);
+  static void OnMetadataUpdate(const char* server_name,
+                               mc_metadata_h metadata_h,
+                               void* user_data);
+};
+
+} // namespace mediacontroller
+} // namespace extension
+
+#endif  // MEDIACONTROLLER_MEDIACONTROLLER_CLIENT_H_
diff --git a/webWidgetTCT_device/src/mediacontroller/mediacontroller_extension.cc b/webWidgetTCT_device/src/mediacontroller/mediacontroller_extension.cc
new file mode 100755 (executable)
index 0000000..4485e13
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2015 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 "mediacontroller/mediacontroller_extension.h"
+
+#include "mediacontroller/mediacontroller_instance.h"
+
+// This will be generated from mediacontroller_api.js
+extern const char kSource_mediacontroller_api[];
+
+common::Extension* CreateExtension() {
+  return new MediaControllerExtension;
+}
+
+MediaControllerExtension::MediaControllerExtension() {
+  SetExtensionName("tizen.mediacontroller");
+  SetJavaScriptAPI(kSource_mediacontroller_api);
+}
+
+MediaControllerExtension::~MediaControllerExtension() {}
+
+common::Instance* MediaControllerExtension::CreateInstance() {
+  return new extension::mediacontroller::MediaControllerInstance;
+}
diff --git a/webWidgetTCT_device/src/mediacontroller/mediacontroller_extension.h b/webWidgetTCT_device/src/mediacontroller/mediacontroller_extension.h
new file mode 100755 (executable)
index 0000000..94e0391
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2015 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 MEDIACONTROLLER_MEDIACONTROLLER_EXTENSION_H_
+#define MEDIACONTROLLER_MEDIACONTROLLER_EXTENSION_H_
+
+#include "common/extension.h"
+
+class MediaControllerExtension : public common::Extension {
+ public:
+  MediaControllerExtension();
+  virtual ~MediaControllerExtension();
+
+ private:
+  virtual common::Instance* CreateInstance();
+};
+
+#endif  // MEDIACONTROLLER_MEDIACONTROLLER_EXTENSION_H_
diff --git a/webWidgetTCT_device/src/mediacontroller/mediacontroller_instance.cc b/webWidgetTCT_device/src/mediacontroller/mediacontroller_instance.cc
new file mode 100755 (executable)
index 0000000..18ed637
--- /dev/null
@@ -0,0 +1,773 @@
+/*
+ * Copyright (c) 2015 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 "mediacontroller/mediacontroller_instance.h"
+
+#include "common/logger.h"
+#include "common/picojson.h"
+#include "common/platform_result.h"
+#include "common/task-queue.h"
+
+#include "mediacontroller/mediacontroller_types.h"
+
+namespace extension {
+namespace mediacontroller {
+
+using common::ErrorCode;
+using common::PlatformResult;
+using common::TaskQueue;
+
+MediaControllerInstance::MediaControllerInstance() {
+  LoggerD("Enter");
+  using namespace std::placeholders;
+
+#define REGISTER_SYNC(c, x) \
+    RegisterSyncHandler(c, std::bind(&MediaControllerInstance::x, this, _1, _2));
+#define REGISTER_ASYNC(c, x) \
+    RegisterSyncHandler(c, std::bind(&MediaControllerInstance::x, this, _1, _2));
+
+  // server
+  REGISTER_SYNC("MediaControllerManager_createServer",
+      MediaControllerManagerCreateServer);
+  REGISTER_SYNC("MediaControllerServer_updatePlaybackState",
+      MediaControllerServerUpdatePlaybackState);
+  REGISTER_SYNC("MediaControllerServer_updatePlaybackPosition",
+      MediaControllerServerUpdatePlaybackPosition);
+  REGISTER_SYNC("MediaControllerServer_updateRepeatMode",
+      MediaControllerServerUpdateRepeatMode);
+  REGISTER_SYNC("MediaControllerServer_updateShuffleMode",
+      MediaControllerServerUpdateShuffleMode);
+  REGISTER_SYNC("MediaControllerServer_updateMetadata",
+      MediaControllerServerUpdateMetadata);
+  REGISTER_SYNC("MediaControllerServer_addChangeRequestPlaybackInfoListener",
+      MediaControllerServerAddChangeRequestPlaybackInfoListener);
+  REGISTER_SYNC("MediaControllerServer_removeChangeRequestPlaybackInfoListener",
+      MediaControllerServerRemoveChangeRequestPlaybackInfoListener);
+  REGISTER_SYNC("MediaControllerServer_addCommandListener",
+      MediaControllerServerAddCommandListener);
+  REGISTER_SYNC("MediaControllerServer_replyCommand",
+      MediaControllerServerReplyCommand);
+  REGISTER_SYNC("MediaControllerServer_removeCommandListener",
+      MediaControllerServerRemoveCommandListener);
+
+  // client
+  REGISTER_SYNC("MediaControllerManager_getClient",
+      MediaControllerManagerGetClient);
+  REGISTER_ASYNC("MediaControllerClient_findServers",
+      MediaControllerClientFindServers);
+  REGISTER_SYNC("MediaControllerClient_getLatestServerInfo",
+      MediaControllerClientGetLatestServerInfo);
+  REGISTER_SYNC("MediaControllerClient_getPlaybackInfo",
+      MediaControllerClientGetPlaybackInfo);
+  REGISTER_SYNC("MediaControllerServerInfo_sendPlaybackState",
+      MediaControllerServerInfoSendPlaybackState);
+  REGISTER_ASYNC("MediaControllerServerInfo_sendPlaybackPosition",
+      MediaControllerServerInfoSendPlaybackPosition);
+  REGISTER_ASYNC("MediaControllerServerInfo_sendRepeatMode",
+      MediaControllerServerInfoSendRepeatMode);
+  REGISTER_ASYNC("MediaControllerServerInfo_sendShuffleMode",
+      MediaControllerServerInfoSendShuffleMode);
+  REGISTER_ASYNC("MediaControllerServerInfo_sendCommand",
+      MediaControllerServerInfoSendCommand);
+  REGISTER_SYNC("MediaControllerServerInfo_addServerStatusChangeListener",
+      MediaControllerServerInfoAddServerStatusChangeListener);
+  REGISTER_SYNC("MediaControllerServerInfo_removeServerStatusChangeListener",
+      MediaControllerServerInfoRemoveServerStatusChangeListener);
+  REGISTER_SYNC("MediaControllerServerInfo_addPlaybackInfoChangeListener",
+      MediaControllerServerInfoAddPlaybackInfoChangeListener);
+  REGISTER_SYNC("MediaControllerServerInfo_removePlaybackInfoChangeListener",
+      MediaControllerServerInfoRemovePlaybackInfoChangeListener);
+
+#undef REGISTER_SYNC
+#undef REGISTER_ASYNC
+}
+
+MediaControllerInstance::~MediaControllerInstance() {
+  LoggerD("Enter");
+}
+
+#define CHECK_EXIST(args, name, out) \
+    if (!args.contains(name)) { \
+      ReportError(PlatformResult(ErrorCode::TYPE_MISMATCH_ERR, \
+          name" is required argument"), &out); \
+      return; \
+    }
+
+
+void MediaControllerInstance::MediaControllerManagerCreateServer(
+    const picojson::value& args,
+    picojson::object& out) {
+
+  LoggerD("Enter");
+  if (server_) {
+    ReportSuccess(out);
+    return;
+  }
+
+  server_ = std::make_shared<MediaControllerServer>();
+  const PlatformResult& result = server_->Init();
+  if (!result) {
+    server_.reset();
+    ReportError(result, &out);
+  }
+
+  ReportSuccess(out);
+}
+
+void MediaControllerInstance::MediaControllerServerUpdatePlaybackState(
+    const picojson::value& args,
+    picojson::object& out) {
+  LoggerD("Enter");
+  CHECK_EXIST(args, "state", out)
+
+  if (!server_) {
+    ReportError(PlatformResult(ErrorCode::INVALID_STATE_ERR,
+        "Server not initialized."), &out);
+    return;
+  }
+
+  const std::string& state = args.get("state").get<std::string>();
+  const PlatformResult& result = server_->SetPlaybackState(state);
+  if (!result) {
+    LoggerE("Failed server_->SetPlaybackState()");
+    ReportError(result, &out);
+    return;
+  }
+
+  ReportSuccess(out);
+}
+
+void MediaControllerInstance::MediaControllerServerUpdatePlaybackPosition(
+    const picojson::value& args,
+    picojson::object& out) {
+
+  LoggerD("Enter");
+  if (!server_) {
+    LoggerE("Failed: server_");
+    ReportError(PlatformResult(ErrorCode::INVALID_STATE_ERR,
+        "Server not initialized."), &out);
+    return;
+  }
+
+  CHECK_EXIST(args, "position", out)
+
+  double position = args.get("position").get<double>();
+  const PlatformResult& result = server_->SetPlaybackPosition(position);
+  if (!result) {
+    LoggerE("Failed: server_->SetPlaybackPosition()");
+    ReportError(result, &out);
+    return;
+  }
+
+  ReportSuccess(out);
+}
+
+void MediaControllerInstance::MediaControllerServerUpdateShuffleMode(
+    const picojson::value& args,
+    picojson::object& out) {
+
+  LoggerD("Enter");
+  if (!server_) {
+    LoggerE("Failed: server_");
+    ReportError(PlatformResult(ErrorCode::INVALID_STATE_ERR,
+        "Server not initialized."), &out);
+    return;
+  }
+
+  CHECK_EXIST(args, "mode", out)
+
+  bool mode = args.get("mode").get<bool>();
+
+  const PlatformResult& result = server_->SetShuffleMode(mode);
+  if (!result) {
+    LoggerE("Failed: server_->SetShuffleMode()");
+    ReportError(result, &out);
+    return;
+  }
+
+  ReportSuccess(out);
+}
+
+void MediaControllerInstance::MediaControllerServerUpdateRepeatMode(
+    const picojson::value& args,
+    picojson::object& out) {
+
+  LoggerD("Enter");
+
+  if (!server_) {
+    LoggerE("Failed: server_");
+    ReportError(PlatformResult(ErrorCode::INVALID_STATE_ERR,
+        "Server not initialized."), &out);
+    return;
+  }
+
+  CHECK_EXIST(args, "mode", out)
+
+  bool mode = args.get("mode").get<bool>();
+
+  const PlatformResult& result = server_->SetRepeatMode(mode);
+  if (!result) {
+    LoggerE("Failed: server_->SetRepeatMode()");
+    ReportError(result, &out);
+    return;
+  }
+
+  ReportSuccess(out);
+}
+
+void MediaControllerInstance::MediaControllerServerUpdateMetadata(
+    const picojson::value& args,
+    picojson::object& out) {
+
+  LoggerD("Enter");
+  if (!server_) {
+    LoggerE("Failed: server_");
+    ReportError(PlatformResult(ErrorCode::INVALID_STATE_ERR,
+        "Server not initialized."), &out);
+    return;
+  }
+
+  CHECK_EXIST(args, "metadata", out)
+
+  const picojson::object& metadata =
+      args.get("metadata").get<picojson::object>();
+
+  const PlatformResult& result = server_->SetMetadata(metadata);
+  if (!result) {
+    LoggerE("Failed: server_->SetMetadata()");
+    ReportError(result, &out);
+    return;
+  }
+
+  ReportSuccess(out);
+}
+
+void MediaControllerInstance::MediaControllerServerAddChangeRequestPlaybackInfoListener(
+    const picojson::value& args,
+    picojson::object& out) {
+
+  LoggerD("Enter");
+  if (!server_) {
+    LoggerE("Failed: server_");
+    ReportError(PlatformResult(ErrorCode::INVALID_STATE_ERR,
+                               "Server not initialized."), &out);
+    return;
+  }
+
+  CHECK_EXIST(args, "listenerId", out)
+
+  JsonCallback callback = [this, args](picojson::value* data) -> void {
+
+    if (!data) {
+      LOGGER(ERROR) << "No data passed to json callback";
+      return;
+    }
+
+    picojson::object& request_o = data->get<picojson::object>();
+    request_o["listenerId"] = args.get("listenerId");
+
+    Instance::PostMessage(this, data->serialize().c_str());
+  };
+
+  server_->SetChangeRequestPlaybackInfoListener(callback);
+
+  ReportSuccess(out);
+}
+
+void MediaControllerInstance::MediaControllerServerRemoveChangeRequestPlaybackInfoListener(
+    const picojson::value& args,
+    picojson::object& out) {
+
+  LoggerD("Enter");
+  if (!server_) {
+    LoggerE("Failed: server_");
+    ReportError(PlatformResult(ErrorCode::INVALID_STATE_ERR,
+                               "Server not initialized."), &out);
+    return;
+  }
+
+  server_->SetChangeRequestPlaybackInfoListener(nullptr);
+}
+
+void MediaControllerInstance::MediaControllerServerAddCommandListener(
+    const picojson::value& args,
+    picojson::object& out) {
+
+  LoggerD("Enter");
+  if (!server_) {
+    LoggerE("Failed: server_");
+    ReportError(PlatformResult(ErrorCode::INVALID_STATE_ERR,
+                               "Server not initialized."), &out);
+    return;
+  }
+
+  JsonCallback on_command = [this, args](picojson::value* request) -> void {
+
+    picojson::object& request_o = request->get<picojson::object>();
+    request_o["listenerId"] = args.get("listenerId");
+
+    Instance::PostMessage(this, request->serialize().c_str());
+  };
+
+  server_->set_command_listener(on_command);
+
+  ReportSuccess(out);
+}
+
+void MediaControllerInstance::MediaControllerServerReplyCommand(
+    const picojson::value& args,
+    picojson::object& out) {
+
+  LoggerD("Enter");
+  if (!server_) {
+    LoggerE("Failed: server_");
+    ReportError(PlatformResult(ErrorCode::INVALID_STATE_ERR,
+                               "Server not initialized."), &out);
+    return;
+  }
+
+  CHECK_EXIST(args, "clientName", out)
+  CHECK_EXIST(args, "replyId", out)
+  CHECK_EXIST(args, "data", out)
+
+  server_->CommandReply(args.get("clientName").get<std::string>(),
+                        args.get("replyId").to_str(),
+                        args.get("data"));
+
+  ReportSuccess(out);
+}
+
+void MediaControllerInstance::MediaControllerServerRemoveCommandListener(
+    const picojson::value& args,
+    picojson::object& out) {
+
+  LoggerD("Enter");
+  if (!server_) {
+    LoggerE("Failed: server_");
+    ReportError(PlatformResult(ErrorCode::INVALID_STATE_ERR,
+                               "Server not initialized."), &out);
+    return;
+  }
+
+  server_->set_command_listener(nullptr);
+
+  ReportSuccess(out);
+}
+
+void MediaControllerInstance::MediaControllerManagerGetClient(
+    const picojson::value& args,
+    picojson::object& out) {
+
+  LoggerD("Enter");
+  if (client_) {
+    ReportSuccess(out);
+    return;
+  }
+
+  client_ = std::make_shared<MediaControllerClient>();
+  const PlatformResult& result = client_->Init();
+  if (!result) {
+    client_.reset();
+    LoggerE("Failed: client_->Init()");
+    ReportError(result, &out);
+  }
+
+  ReportSuccess(out);
+}
+
+void MediaControllerInstance::MediaControllerClientFindServers(
+    const picojson::value& args,
+    picojson::object& out) {
+
+  LoggerD("Enter");
+  if (!client_) {
+    LoggerE("Failed: client_");
+
+    ReportError(PlatformResult(ErrorCode::INVALID_STATE_ERR,
+                               "Client not initialized."), &out);
+    return;
+  }
+
+  CHECK_EXIST(args, "callbackId", out)
+
+  auto search = [this, args]() -> void {
+
+    picojson::value response = picojson::value(picojson::object());
+    picojson::object& response_obj = response.get<picojson::object>();
+
+    picojson::value servers = picojson::value(picojson::array());
+    PlatformResult result = client_->FindServers(
+        &servers.get<picojson::array>());
+
+    response_obj["callbackId"] = args.get("callbackId");
+    if (result) {
+      ReportSuccess(servers, response_obj);
+    } else {
+      ReportError(result, &response_obj);
+    }
+
+    Instance::PostMessage(this, response.serialize().c_str());
+  };
+
+  TaskQueue::GetInstance().Async(search);
+
+  ReportSuccess(out);
+}
+
+void MediaControllerInstance::MediaControllerClientGetLatestServerInfo(
+    const picojson::value& args,
+    picojson::object& out) {
+
+  LoggerD("Enter");
+  if (!client_) {
+    LoggerE("Failed: client_");
+    ReportError(PlatformResult(ErrorCode::INVALID_STATE_ERR,
+                               "Client not initialized."), &out);
+    return;
+  }
+
+  picojson::value server_info = picojson::value();
+  PlatformResult result = client_->GetLatestServerInfo(&server_info);
+  if (!result) {
+    LoggerE("Failed: client_->GetLatestServerInfo");
+    ReportError(result, &out);
+    return;
+  }
+
+  ReportSuccess(server_info, out);
+}
+
+void MediaControllerInstance::MediaControllerClientGetPlaybackInfo(
+    const picojson::value& args,
+    picojson::object& out) {
+
+  LoggerD("Enter");
+  if (!client_) {
+    ReportError(PlatformResult(ErrorCode::INVALID_STATE_ERR,
+                               "Client not initialized."), &out);
+    return;
+  }
+
+  CHECK_EXIST(args, "name", out)
+
+  picojson::value playback_info = picojson::value(picojson::object());
+  PlatformResult result = client_->GetPlaybackInfo(
+      args.get("name").get<std::string>(),
+      &playback_info.get<picojson::object>());
+
+  if (!result) {
+    LoggerE("Failed: client_->GetPlaybackInfo");
+    ReportError(result, &out);
+    return;
+  }
+
+  ReportSuccess(playback_info, out);
+}
+
+void MediaControllerInstance::MediaControllerServerInfoSendPlaybackState(
+    const picojson::value& args,
+    picojson::object& out) {
+
+  LoggerD("Enter");
+  if (!client_) {
+    LoggerE("Failed: client_");
+    ReportError(PlatformResult(ErrorCode::INVALID_STATE_ERR,
+                               "Client not initialized."), &out);
+    return;
+  }
+
+  CHECK_EXIST(args, "callbackId", out)
+  CHECK_EXIST(args, "name", out)
+  CHECK_EXIST(args, "state", out)
+
+  auto send = [this, args]() -> void {
+    picojson::value response = picojson::value(picojson::object());
+    picojson::object& response_obj = response.get<picojson::object>();
+    response_obj["callbackId"] = args.get("callbackId");
+
+    PlatformResult result = client_->SendPlaybackState(
+        args.get("name").get<std::string>(),
+        args.get("state").get<std::string>());
+
+    if (result) {
+      ReportSuccess(response_obj);
+    } else {
+      LoggerE("Failed: client_->SendPlaybackState");
+      ReportError(result, &response_obj);
+    }
+
+    Instance::PostMessage(this, response.serialize().c_str());
+  };
+
+  TaskQueue::GetInstance().Async(send);
+
+  ReportSuccess(out);
+}
+
+void MediaControllerInstance::MediaControllerServerInfoSendPlaybackPosition(
+    const picojson::value& args,
+    picojson::object& out) {
+
+  LoggerD("Enter");
+  if (!client_) {
+    ReportError(PlatformResult(ErrorCode::INVALID_STATE_ERR,
+                               "Client not initialized."), &out);
+    return;
+  }
+
+  CHECK_EXIST(args, "callbackId", out)
+  CHECK_EXIST(args, "name", out)
+  CHECK_EXIST(args, "position", out)
+
+  auto send = [this, args]() -> void {
+    picojson::value response = picojson::value(picojson::object());
+    picojson::object& response_obj = response.get<picojson::object>();
+    response_obj["callbackId"] = args.get("callbackId");
+
+    PlatformResult result = client_->SendPlaybackPosition(
+        args.get("name").get<std::string>(),
+        args.get("position").get<double>());
+
+    if (result) {
+      ReportSuccess(response_obj);
+    } else {
+      LoggerE("Failed: client_->SendPlaybackPosition");
+      ReportError(result, &response_obj);
+    }
+
+    Instance::PostMessage(this, response.serialize().c_str());
+  };
+
+  TaskQueue::GetInstance().Async(send);
+
+  ReportSuccess(out);
+}
+
+void MediaControllerInstance::MediaControllerServerInfoSendShuffleMode(
+    const picojson::value& args,
+    picojson::object& out) {
+
+  LoggerD("Enter");
+
+  if (!client_) {
+    LOGGER(ERROR) << "Client not initialized.";
+    ReportError(PlatformResult(ErrorCode::INVALID_STATE_ERR,
+                               "Client not initialized."), &out);
+    return;
+  }
+
+  CHECK_EXIST(args, "callbackId", out)
+  CHECK_EXIST(args, "name", out)
+  CHECK_EXIST(args, "mode", out)
+
+  auto send = [this, args]() -> void {
+    picojson::value response = picojson::value(picojson::object());
+    picojson::object& response_obj = response.get<picojson::object>();
+    response_obj["callbackId"] = args.get("callbackId");
+
+    PlatformResult result = client_->SendShuffleMode(
+        args.get("name").get<std::string>(),
+        args.get("mode").get<bool>());
+
+    if (result) {
+      ReportSuccess(response_obj);
+    } else {
+      ReportError(result, &response_obj);
+    }
+
+    Instance::PostMessage(this, response.serialize().c_str());
+  };
+
+  TaskQueue::GetInstance().Async(send);
+
+  ReportSuccess(out);
+}
+
+void MediaControllerInstance::MediaControllerServerInfoSendRepeatMode(
+    const picojson::value& args,
+    picojson::object& out) {
+
+  LoggerD("Enter");
+  if (!client_) {
+    LOGGER(ERROR) << "Client not initialized.";
+    ReportError(PlatformResult(ErrorCode::INVALID_STATE_ERR,
+                               "Client not initialized."), &out);
+    return;
+  }
+
+  CHECK_EXIST(args, "callbackId", out)
+  CHECK_EXIST(args, "name", out)
+  CHECK_EXIST(args, "mode", out)
+
+  auto send = [this, args]() -> void {
+    picojson::value response = picojson::value(picojson::object());
+    picojson::object& response_obj = response.get<picojson::object>();
+    response_obj["callbackId"] = args.get("callbackId");
+
+    PlatformResult result = client_->SendRepeatMode(
+        args.get("name").get<std::string>(),
+        args.get("mode").get<bool>());
+
+    if (result) {
+      ReportSuccess(response_obj);
+    } else {
+      ReportError(result, &response_obj);
+    }
+
+    Instance::PostMessage(this, response.serialize().c_str());
+  };
+
+  TaskQueue::GetInstance().Async(send);
+
+  ReportSuccess(out);
+}
+
+void MediaControllerInstance::MediaControllerServerInfoSendCommand(
+    const picojson::value& args,
+    picojson::object& out) {
+
+  LoggerD("Enter");
+  if (!client_) {
+    LOGGER(ERROR) << "Client not initialized.";
+    ReportError(PlatformResult(ErrorCode::INVALID_STATE_ERR,
+                               "Client not initialized."), &out);
+    return;
+  }
+
+  CHECK_EXIST(args, "listenerId", out)
+  CHECK_EXIST(args, "replyId", out)
+  CHECK_EXIST(args, "name", out)
+  CHECK_EXIST(args, "command", out)
+  CHECK_EXIST(args, "data", out)
+
+  JsonCallback reply_cb = [this, args](picojson::value* reply) -> void {
+
+    picojson::object& reply_obj = reply->get<picojson::object>();
+
+    reply_obj["listenerId"] = args.get("listenerId");
+
+    Instance::PostMessage(this, reply->serialize().c_str());
+  };
+
+  PlatformResult result = client_->SendCommand(
+      args.get("name").get<std::string>(),
+      args.get("command").get<std::string>(),
+      args.get("data"),
+      args.get("replyId").to_str(),
+      reply_cb);
+
+  if (result) {
+    ReportSuccess(out);
+  } else {
+    ReportError(result, &out);
+  }
+}
+
+void MediaControllerInstance::MediaControllerServerInfoAddServerStatusChangeListener(
+    const picojson::value& args,
+    picojson::object& out) {
+
+  LoggerD("Enter");
+  if (!client_) {
+    ReportError(PlatformResult(ErrorCode::INVALID_STATE_ERR,
+                               "Client not initialized."), &out);
+    return;
+  }
+
+  CHECK_EXIST(args, "listenerId", out)
+
+  JsonCallback callback = [this, args](picojson::value* data) -> void {
+
+    if (nullptr == data) {
+      LOGGER(ERROR) << "No data passed to json callback";
+      return;
+    }
+
+    picojson::object& request_o = data->get<picojson::object>();
+    request_o["listenerId"] = args.get("listenerId");
+
+    Instance::PostMessage(this, data->serialize().c_str());
+  };
+
+  client_->SetServerStatusChangeListener(callback);
+
+  ReportSuccess(out);
+}
+
+void MediaControllerInstance::MediaControllerServerInfoRemoveServerStatusChangeListener(
+    const picojson::value& args,
+    picojson::object& out) {
+
+  LoggerD("Enter");
+  if (!client_) {
+    ReportError(PlatformResult(ErrorCode::INVALID_STATE_ERR,
+                               "Client not initialized."), &out);
+    return;
+  }
+
+  client_->SetServerStatusChangeListener(nullptr);
+}
+
+void MediaControllerInstance::MediaControllerServerInfoAddPlaybackInfoChangeListener(
+    const picojson::value& args,
+    picojson::object& out) {
+
+  LoggerD("Enter");
+  if (!client_) {
+    LoggerE("client_");
+    ReportError(PlatformResult(ErrorCode::INVALID_STATE_ERR,
+                               "Client not initialized."), &out);
+    return;
+  }
+
+  CHECK_EXIST(args, "listenerId", out)
+
+  JsonCallback callback = [this, args](picojson::value* data) -> void {
+
+    if (!data) {
+      LOGGER(ERROR) << "No data passed to json callback";
+      return;
+    }
+
+    picojson::object& request_o = data->get<picojson::object>();
+    request_o["listenerId"] = args.get("listenerId");
+
+    Instance::PostMessage(this, data->serialize().c_str());
+  };
+
+  client_->SetPlaybackInfoListener(callback);
+
+  ReportSuccess(out);
+}
+
+void MediaControllerInstance::MediaControllerServerInfoRemovePlaybackInfoChangeListener(
+    const picojson::value& args,
+    picojson::object& out) {
+
+  if (!client_) {
+    LoggerE("client_");
+    ReportError(PlatformResult(ErrorCode::INVALID_STATE_ERR,
+                               "Client not initialized."), &out);
+    return;
+  }
+
+  client_->SetPlaybackInfoListener(nullptr);
+}
+
+#undef CHECK_EXIST
+
+} // namespace mediacontroller
+} // namespace extension
diff --git a/webWidgetTCT_device/src/mediacontroller/mediacontroller_instance.h b/webWidgetTCT_device/src/mediacontroller/mediacontroller_instance.h
new file mode 100755 (executable)
index 0000000..cc13ad3
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2015 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 MEDIACONTROLLER_MEDIACONTROLLER_INSTANCE_H_
+#define MEDIACONTROLLER_MEDIACONTROLLER_INSTANCE_H_
+
+#include <memory>
+
+#include "common/extension.h"
+#include "mediacontroller/mediacontroller_client.h"
+#include "mediacontroller/mediacontroller_server.h"
+
+namespace extension {
+namespace mediacontroller {
+
+class MediaControllerInstance : public common::ParsedInstance {
+ public:
+  MediaControllerInstance();
+  virtual ~MediaControllerInstance();
+
+ private:
+  // server
+  void MediaControllerManagerCreateServer(const picojson::value& args, picojson::object& out);
+  void MediaControllerServerUpdatePlaybackState(const picojson::value& args, picojson::object& out);
+  void MediaControllerServerUpdatePlaybackPosition(const picojson::value& args, picojson::object& out);
+  void MediaControllerServerUpdateRepeatMode(const picojson::value& args, picojson::object& out);
+  void MediaControllerServerUpdateShuffleMode(const picojson::value& args, picojson::object& out);
+  void MediaControllerServerUpdateMetadata(const picojson::value& args, picojson::object& out);
+  void MediaControllerServerAddChangeRequestPlaybackInfoListener(const picojson::value& args, picojson::object& out);
+  void MediaControllerServerRemoveChangeRequestPlaybackInfoListener(const picojson::value& args, picojson::object& out);
+  void MediaControllerServerAddCommandListener(const picojson::value& args, picojson::object& out);
+  void MediaControllerServerReplyCommand(const picojson::value& args, picojson::object& out);
+  void MediaControllerServerRemoveCommandListener(const picojson::value& args, picojson::object& out);
+
+  // client
+  void MediaControllerManagerGetClient(const picojson::value& args, picojson::object& out);
+  void MediaControllerClientFindServers(const picojson::value& args, picojson::object& out);
+  void MediaControllerClientGetLatestServerInfo(const picojson::value& args, picojson::object& out);
+  void MediaControllerClientGetPlaybackInfo(const picojson::value& args, picojson::object& out);
+  void MediaControllerServerInfoSendPlaybackState(const picojson::value& args, picojson::object& out);
+  void MediaControllerServerInfoSendPlaybackPosition(const picojson::value& args, picojson::object& out);
+  void MediaControllerServerInfoSendRepeatMode(const picojson::value& args, picojson::object& out);
+  void MediaControllerServerInfoSendShuffleMode(const picojson::value& args, picojson::object& out);
+  void MediaControllerServerInfoSendCommand(const picojson::value& args, picojson::object& out);
+  void MediaControllerServerInfoAddServerStatusChangeListener(const picojson::value& args, picojson::object& out);
+  void MediaControllerServerInfoRemoveServerStatusChangeListener(const picojson::value& args, picojson::object& out);
+  void MediaControllerServerInfoAddPlaybackInfoChangeListener(const picojson::value& args, picojson::object& out);
+  void MediaControllerServerInfoRemovePlaybackInfoChangeListener(const picojson::value& args, picojson::object& out);
+
+  std::shared_ptr<MediaControllerClient> client_;
+  std::shared_ptr<MediaControllerServer> server_;
+};
+
+} // namespace mediacontroller
+} // namespace extension
+
+#endif // MEDIACONTROLLER_MEDIACONTROLLER_INSTANCE_H_
diff --git a/webWidgetTCT_device/src/mediacontroller/mediacontroller_server.cc b/webWidgetTCT_device/src/mediacontroller/mediacontroller_server.cc
new file mode 100755 (executable)
index 0000000..95e9192
--- /dev/null
@@ -0,0 +1,457 @@
+/*
+ * Copyright (c) 2015 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 "mediacontroller/mediacontroller_server.h"
+
+#include <bundle.h>
+#include <bundle_internal.h>
+
+#include "common/logger.h"
+#include "common/scope_exit.h"
+
+#include "mediacontroller/mediacontroller_types.h"
+
+namespace extension {
+namespace mediacontroller {
+
+namespace {
+// The privileges that are required in Application API
+const std::string kInternalCommandSendPlaybackPosition
+    = "__internal_sendPlaybackPosition";
+const std::string kInternalCommandSendShuffleMode
+    = "__internal_sendShuffleMode";
+const std::string kInternalCommandSendRepeatMode
+    = "__internal_sendRepeatMode";
+}  // namespace
+
+using common::PlatformResult;
+using common::ErrorCode;
+
+MediaControllerServer::MediaControllerServer() : handle_(nullptr) {
+  LoggerD("Enter");
+}
+
+MediaControllerServer::~MediaControllerServer() {
+
+  LoggerD("Enter");
+
+  if (handle_) {
+    int ret;
+    ret = mc_server_unset_custom_command_received_cb(handle_);
+    if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+      LOGGER(ERROR) << "Unable to unset command callback, error: " << ret;
+    }
+
+    ret = mc_server_destroy(handle_);
+    if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+      LOGGER(ERROR) << "mc_server_destroy() failed, error: " << ret;
+    }
+  }
+}
+
+PlatformResult MediaControllerServer::Init() {
+
+  LoggerD("Enter");
+
+  int ret = mc_server_create(&handle_);
+  if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+    LOGGER(ERROR) << "Unable to create media controller server, error: " << ret;
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Unable to create media controller server");
+  }
+
+  ret = mc_server_set_custom_command_received_cb(handle_,
+                                                 OnCommandReceived,
+                                                 this);
+  if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+    LOGGER(ERROR) << "Unable to set command callback, error: " << ret;
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Unable to set command callback");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult MediaControllerServer::SetPlaybackState(
+    const std::string& state) {
+
+  LoggerD("Enter");
+
+  int state_int;
+  PlatformResult result = Types::StringToPlatformEnum(
+      Types::kMediaControllerPlaybackState, state, &state_int);
+
+  if (!result) {
+    return result;
+  }
+
+  int ret = mc_server_set_playback_state(
+      handle_, static_cast<mc_playback_states_e>(state_int));
+  if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+    LOGGER(ERROR) << "mc_server_set_playback_state failed, error: " << ret;
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Error setting playback state");
+  }
+
+  ret = mc_server_update_playback_info(handle_);
+  if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+    LOGGER(ERROR) << "mc_server_update_playback_info failed, error: " << ret;
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Error updating playback info");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult MediaControllerServer::SetPlaybackPosition(double position) {
+
+  LoggerD("Enter");
+
+  int ret = mc_server_set_playback_position(
+      handle_, static_cast<unsigned long long>(position));
+  if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+    LOGGER(ERROR) << "mc_server_set_playback_position failed, error: " << ret;
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Error setting playback position");
+  }
+
+  ret = mc_server_update_playback_info(handle_);
+  if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+    LOGGER(ERROR) << "mc_server_update_playback_info failed, error: " << ret;
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Error updating playback info");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult MediaControllerServer::SetShuffleMode(bool mode) {
+
+  LoggerD("Enter");
+
+  int ret = mc_server_update_shuffle_mode(handle_,
+                                          mode ? MC_SHUFFLE_MODE_ON
+                                               : MC_SHUFFLE_MODE_OFF);
+  if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+    LOGGER(ERROR) << "mc_server_update_shuffle_mode failed, error: " << ret;
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Error updating shuffle mode");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult MediaControllerServer::SetRepeatMode(bool mode) {
+
+  LoggerD("Enter");
+
+  int ret = mc_server_update_repeat_mode(handle_,
+                                         mode ? MC_REPEAT_MODE_ON
+                                              : MC_REPEAT_MODE_OFF);
+  if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+    LOGGER(ERROR) << "mc_server_update_repeat_mode failed, error: " << ret;
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Error updating repeat mode");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult MediaControllerServer::SetMetadata(
+    const picojson::object& metadata) {
+
+  LoggerD("Enter");
+
+  int attribute_int, ret;
+  for (picojson::object::const_iterator i = metadata.begin();
+       i != metadata.end();
+       ++i) {
+
+    PlatformResult result = Types::StringToPlatformEnum(
+        Types::kMediaControllerMetadataAttribute, i->first, &attribute_int);
+    if (!result) {
+      return result;
+    }
+
+    ret = mc_server_set_metadata(handle_, static_cast<mc_meta_e>(attribute_int),
+                                 i->second.to_str().c_str());
+    if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+      LOGGER(ERROR) << "set_metadata failed for '" << i->first
+                    << "', error: " << ret;
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, "Error setting metadata");
+    }
+  }
+
+  ret = mc_server_update_metadata(handle_);
+  if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+    LOGGER(ERROR) << "mc_server_update_metadata failed, error: " << ret;
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Error updating metadata");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+void MediaControllerServer::OnCommandReceived(const char* client_name,
+                                              const char* command,
+                                              bundle* bundle,
+                                              void* user_data) {
+
+  LoggerD("Enter");
+
+  MediaControllerServer* server = static_cast<MediaControllerServer*>(user_data);
+
+  int ret;
+  char* data_str = nullptr;
+  char* reply_id_str = nullptr;
+  SCOPE_EXIT {
+    free(data_str);
+    free(reply_id_str);
+  };
+
+  ret = bundle_get_str(bundle, "data", &data_str);
+  if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+    LOGGER(ERROR) << "bundle_get_str(data) failed, error: " << ret;
+    return;
+  }
+
+  ret = bundle_get_str(bundle, "replyId", &reply_id_str);
+  if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+    LOGGER(ERROR) << "bundle_get_str(replyId) failed, error: " << ret;
+    return;
+  }
+
+  picojson::value data;
+  std::string err;
+  picojson::parse(data, data_str, data_str + strlen(data_str), &err);
+  if (!err.empty()) {
+    LOGGER(ERROR) << "Failed to parse bundle data: " << err;
+    return;
+  }
+
+  // TODO(r.galka) CAPI have no dedicated methods for position/shuffle/repeat change.
+  // It should be updated when new version of CAPI will be available.
+  // For now implementation is using internal commands.
+  if (command == kInternalCommandSendPlaybackPosition) {
+    double position = data.get("position").get<double>();
+    server->SetPlaybackPosition(position);
+    server->OnPlaybackPositionCommand(client_name,
+                                      static_cast<unsigned long long>(position),
+                                      server);
+    server->CommandReply(client_name, reply_id_str, data);
+    return;
+  }
+  if (command == kInternalCommandSendShuffleMode) {
+    bool mode = data.get("mode").get<bool>();
+    server->SetShuffleMode(mode);
+    server->OnShuffleModeCommand(client_name,
+                                 mode ? MC_SHUFFLE_MODE_ON : MC_SHUFFLE_MODE_OFF,
+                                 server);
+    server->CommandReply(client_name, reply_id_str, data);
+    return;
+  }
+  if (command == kInternalCommandSendRepeatMode) {
+    bool mode = data.get("mode").get<bool>();
+    server->SetRepeatMode(mode);
+    server->OnRepeatModeCommand(client_name,
+                                mode ? MC_REPEAT_MODE_ON : MC_REPEAT_MODE_OFF,
+                                server);
+    server->CommandReply(client_name, reply_id_str, data);
+    return;
+  }
+
+  if (server->command_listener_) {
+    picojson::value request = picojson::value(picojson::object());
+    picojson::object& request_o = request.get<picojson::object>();
+
+    request_o["clientName"] = picojson::value(std::string(client_name));
+    request_o["command"] = picojson::value(std::string(command));
+    request_o["replyId"] = picojson::value(std::string(reply_id_str));
+    request_o["data"] = data;
+
+    server->command_listener_(&request);
+  }
+}
+
+PlatformResult MediaControllerServer::CommandReply(
+    const std::string& client_name,
+    const std::string& reply_id,
+    const picojson::value& data) {
+
+  LoggerD("Enter");
+
+  int ret;
+
+  bundle* bundle = bundle_create();
+  SCOPE_EXIT {
+    bundle_free(bundle);
+  };
+
+  ret = bundle_add(bundle, "replyId", reply_id.c_str());
+  if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+    LOGGER(ERROR) << "bundle_add(replyId) failed, error: " << ret;
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Unable to add replyId to bundle");
+  }
+
+  ret = bundle_add(bundle, "data", data.serialize().c_str());
+  if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+    LOGGER(ERROR) << "bundle_add(data) failed, error: " << ret;
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Unable to add data to bundle");
+  }
+
+  ret = mc_server_send_command_reply(handle_, client_name.c_str(), 0, bundle);
+  if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+    LOGGER(ERROR) << "mc_server_send_command_reply failed, error: " << ret;
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Error sending command reply");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult MediaControllerServer::SetChangeRequestPlaybackInfoListener(
+    JsonCallback callback) {
+
+  LoggerD("Enter");
+
+  if (callback && change_request_playback_info_listener_) {
+    LOGGER(ERROR) << "Listener already registered";
+    return PlatformResult(ErrorCode::INVALID_STATE_ERR,
+                          "Listener already registered");
+  }
+
+  change_request_playback_info_listener_ = callback;
+
+  int ret;
+  if (callback) { // set platform callbacks
+    ret = mc_server_set_playback_state_command_received_cb(
+        handle_, OnPlaybackStateCommand, this);
+    if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+      LOGGER(ERROR) << "Unable to set playback state command listener, error: " << ret;
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "Unable to set playback state command listener");
+    }
+  } else { // unset platform callbacks
+    ret = mc_server_unset_playback_state_command_received_cb(handle_);
+    if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+      LOGGER(ERROR) << "Unable to unset playback state command listener, error: " << ret;
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "Unable to unset playback state command listener");
+    }
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+void MediaControllerServer::OnPlaybackStateCommand(const char* client_name,
+                                                   mc_playback_states_e state_e,
+                                                   void *user_data) {
+
+  LoggerD("Enter");
+
+  MediaControllerServer* server = static_cast<MediaControllerServer*>(user_data);
+
+  if (!server->change_request_playback_info_listener_) {
+    LOGGER(DEBUG) << "No change request playback info listener registered, skipping";
+    return;
+  }
+
+  std::string state;
+  PlatformResult result = Types::PlatformEnumToString(
+      Types::kMediaControllerPlaybackState,
+      static_cast<int>(state_e), &state);
+  if (!result) {
+    LOGGER(ERROR) << "PlatformEnumToString failed, error: " << result.message();
+    return;
+  }
+
+  picojson::value data = picojson::value(picojson::object());
+  picojson::object& data_o = data.get<picojson::object>();
+
+  data_o["action"] = picojson::value(std::string("onplaybackstaterequest"));
+  data_o["state"] = picojson::value(state);
+
+  server->change_request_playback_info_listener_(&data);
+}
+
+void MediaControllerServer::OnPlaybackPositionCommand(
+    const char* client_name,
+    unsigned long long position,
+    void* user_data) {
+
+  LoggerD("Enter");
+
+  MediaControllerServer* server = static_cast<MediaControllerServer*>(user_data);
+
+  if (!server->change_request_playback_info_listener_) {
+    LOGGER(DEBUG) << "No change request playback info listener registered, skipping";
+    return;
+  }
+
+  picojson::value data = picojson::value(picojson::object());
+  picojson::object& data_o = data.get<picojson::object>();
+
+  data_o["action"] = picojson::value(std::string("onplaybackpositionrequest"));
+  data_o["position"] = picojson::value(static_cast<double>(position));
+
+  server->change_request_playback_info_listener_(&data);
+}
+
+void MediaControllerServer::OnShuffleModeCommand(const char* client_name,
+                                                 mc_shuffle_mode_e mode,
+                                                 void* user_data) {
+
+  LoggerD("Enter");
+
+  MediaControllerServer* server = static_cast<MediaControllerServer*>(user_data);
+
+  if (!server->change_request_playback_info_listener_) {
+    LOGGER(DEBUG) << "No change request playback info listener registered, skipping";
+    return;
+  }
+
+  picojson::value data = picojson::value(picojson::object());
+  picojson::object& data_o = data.get<picojson::object>();
+
+  data_o["action"] = picojson::value(std::string("onshufflemoderequest"));
+  data_o["mode"] = picojson::value(mode == MC_SHUFFLE_MODE_ON);
+
+  server->change_request_playback_info_listener_(&data);
+}
+
+void MediaControllerServer::OnRepeatModeCommand(const char* client_name,
+                                                mc_repeat_mode_e mode,
+                                                void* user_data) {
+
+  LoggerD("Enter");
+
+  MediaControllerServer* server = static_cast<MediaControllerServer*>(user_data);
+
+  if (!server->change_request_playback_info_listener_) {
+    LOGGER(DEBUG) << "No change request playback info listener registered, skipping";
+    return;
+  }
+
+  picojson::value data = picojson::value(picojson::object());
+  picojson::object& data_o = data.get<picojson::object>();
+
+  data_o["action"] = picojson::value(std::string("onrepeatmoderequest"));
+  data_o["mode"] = picojson::value(mode == MC_REPEAT_MODE_ON);
+
+  server->change_request_playback_info_listener_(&data);
+}
+
+} // namespace mediacontroller
+} // namespace extension
diff --git a/webWidgetTCT_device/src/mediacontroller/mediacontroller_server.h b/webWidgetTCT_device/src/mediacontroller/mediacontroller_server.h
new file mode 100755 (executable)
index 0000000..1536ca9
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2015 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 MEDIACONTROLLER_MEDIACONTROLLER_SERVER_H_
+#define MEDIACONTROLLER_MEDIACONTROLLER_SERVER_H_
+
+#include <media_controller_server.h>
+#include <string>
+
+#include "common/platform_result.h"
+#include "mediacontroller/mediacontroller_types.h"
+
+namespace extension {
+namespace mediacontroller {
+
+class MediaControllerServer {
+ public:
+  MediaControllerServer();
+  virtual ~MediaControllerServer();
+
+  common::PlatformResult Init();
+  common::PlatformResult SetPlaybackState(const std::string& state);
+  common::PlatformResult SetPlaybackPosition(double position);
+  common::PlatformResult SetShuffleMode(bool mode);
+  common::PlatformResult SetRepeatMode(bool mode);
+  common::PlatformResult SetMetadata(const picojson::object& metadata);
+
+  common::PlatformResult SetChangeRequestPlaybackInfoListener(
+      JsonCallback callback);
+
+  common::PlatformResult CommandReply(const std::string& client_name,
+                                      const std::string& reply_id,
+                                      const picojson::value& data);
+
+  void set_command_listener(const JsonCallback& func) {
+    command_listener_ = func;
+  }
+
+ private:
+  mc_server_h handle_;
+
+  JsonCallback change_request_playback_info_listener_;
+  JsonCallback command_listener_;
+
+  static void OnPlaybackStateCommand(const char* client_name,
+                                     mc_playback_states_e state_e,
+                                     void *user_data);
+  static void OnPlaybackPositionCommand(const char* client_name,
+                                        unsigned long long position,
+                                        void* user_data);
+  static void OnShuffleModeCommand(const char* client_name,
+                                   mc_shuffle_mode_e mode,
+                                   void* user_data);
+  static void OnRepeatModeCommand(const char* client_name,
+                                  mc_repeat_mode_e mode,
+                                  void* user_data);
+
+  static void OnCommandReceived(const char* client_name,
+                                const char* command,
+                                bundle* data,
+                                void* user_data);
+};
+
+} // namespace mediacontroller
+} // namespace extension
+
+#endif  // MEDIACONTROLLER_MEDIACONTROLLER_SERVER_H_
diff --git a/webWidgetTCT_device/src/mediacontroller/mediacontroller_types.cc b/webWidgetTCT_device/src/mediacontroller/mediacontroller_types.cc
new file mode 100755 (executable)
index 0000000..122285e
--- /dev/null
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 2015 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 "mediacontroller/mediacontroller_types.h"
+
+#include <media_controller_client.h>
+
+#include "common/logger.h"
+#include "common/platform_result.h"
+#include "common/scope_exit.h"
+
+namespace extension {
+namespace mediacontroller {
+
+using common::PlatformResult;
+using common::ErrorCode;
+
+const std::string Types::kMediaControllerServerState
+    = "MediaControllerServerState";
+const std::string Types::kMediaControllerPlaybackState
+    = "MediaControllerPlaybackState";
+const std::string Types::kMediaControllerMetadataAttribute
+    = "MediaControllerMetadataAttribute";
+
+const PlatformEnumMap Types::platform_enum_map_ = {
+    {kMediaControllerServerState, {
+        {"ACTIVE", MC_SERVER_STATE_ACTIVATE},
+        {"INACTIVE", MC_SERVER_STATE_DEACTIVATE}}},
+    {kMediaControllerPlaybackState, {
+        {"PLAY", MC_PLAYBACK_STATE_PLAYING},
+        {"PAUSE", MC_PLAYBACK_STATE_PAUSED},
+        {"STOP", MC_PLAYBACK_STATE_STOPPED},
+        {"NEXT", MC_PLAYBACK_STATE_NEXT_FILE},
+        {"PREV", MC_PLAYBACK_STATE_PREV_FILE},
+        {"FORWARD", MC_PLAYBACK_STATE_FAST_FORWARD},
+        {"REWIND", MC_PLAYBACK_STATE_REWIND}}},
+    {kMediaControllerMetadataAttribute, {
+        {"title", MC_META_MEDIA_TITLE},
+        {"artist", MC_META_MEDIA_ARTIST},
+        {"album", MC_META_MEDIA_ALBUM},
+        {"author", MC_META_MEDIA_AUTHOR},
+        {"genre", MC_META_MEDIA_GENRE},
+        {"duration", MC_META_MEDIA_DURATION},
+        {"date", MC_META_MEDIA_DATE},
+        {"copyright", MC_META_MEDIA_COPYRIGHT},
+        {"description", MC_META_MEDIA_DESCRIPTION},
+        {"trackNum", MC_META_MEDIA_TRACK_NUM},
+        {"picture", MC_META_MEDIA_PICTURE}
+    }}
+};
+
+PlatformEnumReverseMap Types::platform_enum_reverse_map_ = {};
+
+PlatformResult Types::GetPlatformEnumMap(const std::string& type,
+                                  std::map<std::string, int>* enum_map) {
+
+  LoggerD("Enter");
+
+  auto iter = platform_enum_map_.find(type);
+  if (iter == platform_enum_map_.end()) {
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          std::string("Undefined platform enum type ") + type);
+  }
+
+  *enum_map = platform_enum_map_.at(type);
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult Types::StringToPlatformEnum(const std::string& type,
+                                           const std::string& value,
+                                           int* platform_enum) {
+
+  LoggerD("Enter");
+
+  std::map<std::string, int> def;
+  PlatformResult result = GetPlatformEnumMap(type, &def);
+  if (!result) {
+    return result;
+  }
+
+  auto def_iter = def.find(value);
+  if (def_iter != def.end()) {
+    *platform_enum = def_iter->second;
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+
+  std::string message =
+      "Platform enum value " + value + " not found for " + type;
+  return PlatformResult(ErrorCode::INVALID_VALUES_ERR, message);
+}
+
+PlatformResult Types::PlatformEnumToString(const std::string& type,
+                                           int value,
+                                           std::string* platform_str) {
+  LoggerD("Enter");
+
+  // TODO(r.galka) can be replaced by Boost.Bimap
+  if (platform_enum_reverse_map_.empty()) {
+    for (auto& def : platform_enum_map_) {
+      platform_enum_reverse_map_[def.first] = {};
+
+      for (auto& key : def.second) {
+        platform_enum_reverse_map_[def.first][key.second] = key.first;
+      }
+    }
+  }
+
+  auto it = platform_enum_reverse_map_.find(type);
+  if (it == platform_enum_reverse_map_.end()) {
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+        std::string("Undefined platform enum type ") + type);
+  }
+
+  auto def = platform_enum_reverse_map_.at(type);
+  auto def_it = def.find(value);
+  if (def_it != def.end()) {
+    *platform_str = def_it->second;
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+
+  std::string message = "Platform enum value " + std::to_string(value) +
+      " not found for " + type;
+  return PlatformResult(ErrorCode::INVALID_VALUES_ERR, message);
+}
+
+PlatformResult Types::ConvertPlaybackState(mc_playback_h playback_h,
+                                           std::string* state) {
+  LoggerD("Enter");
+
+  int ret;
+  mc_playback_states_e state_e;
+  ret = mc_client_get_playback_state(playback_h, &state_e);
+  if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+    LOGGER(ERROR) << "mc_client_get_playback_state failed, error: " << ret;
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Error getting playback state");
+  }
+  if (state_e == MC_PLAYBACK_STATE_NONE) {
+    state_e = MC_PLAYBACK_STATE_STOPPED;
+  }
+
+  PlatformResult result = Types::PlatformEnumToString(
+      Types::kMediaControllerPlaybackState,
+      static_cast<int>(state_e), state);
+  if (!result) {
+    LOGGER(ERROR) << "PlatformEnumToString failed, error: " << result.message();
+    return result;
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult Types::ConvertPlaybackPosition(mc_playback_h playback_h,
+                                              double* position) {
+  LoggerD("Enter");
+
+  int ret;
+
+  unsigned long long pos;
+  ret = mc_client_get_playback_position(playback_h, &pos);
+  if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+    LOGGER(ERROR) << "mc_client_get_playback_position failed, error: " << ret;
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Error getting playback position");
+  }
+
+  *position = static_cast<double>(pos);
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult Types::ConvertMetadata(mc_metadata_h metadata_h,
+                                      picojson::object* metadata) {
+  LoggerD("Enter");
+
+  std::map<std::string, int> metadata_fields;
+  PlatformResult result = GetPlatformEnumMap(
+      Types::kMediaControllerMetadataAttribute, &metadata_fields);
+  if (!result) {
+    LOGGER(ERROR) << "GetPlatformEnumMap failed, error: " << result.message();
+    return result;
+  }
+
+  char* value = nullptr;
+  SCOPE_EXIT {
+    free(value);
+  };
+
+  for (auto& field : metadata_fields) {
+    int ret = mc_client_get_metadata(metadata_h,
+                                 static_cast<mc_meta_e>(field.second),
+                                 &value);
+    if (ret != MEDIA_CONTROLLER_ERROR_NONE) {
+      LOGGER(ERROR) << "mc_client_get_metadata failed for field '"
+          << field.first << "', error: " << ret;
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "Error getting metadata");
+    }
+
+    (*metadata)[field.first] = picojson::value(std::string(value ? value : ""));
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+} // namespace mediacontroller
+} // namespace extension
diff --git a/webWidgetTCT_device/src/mediacontroller/mediacontroller_types.h b/webWidgetTCT_device/src/mediacontroller/mediacontroller_types.h
new file mode 100755 (executable)
index 0000000..0b50c44
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2015 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 MEDIACONTROLLER_MEDIACONTROLLER_TYPES_H_
+#define MEDIACONTROLLER_MEDIACONTROLLER_TYPES_H_
+
+#include <functional>
+#include <map>
+#include <media_controller_type.h>
+#include <string>
+
+#include "common/platform_result.h"
+
+namespace extension {
+namespace mediacontroller {
+
+typedef std::map<std::string, std::map<std::string, int>> PlatformEnumMap;
+typedef std::map<std::string, std::map<int, std::string>> PlatformEnumReverseMap;
+typedef std::function<void(picojson::value*)> JsonCallback;
+
+class Types {
+ public:
+  static const std::string kMediaControllerServerState;
+  static const std::string kMediaControllerPlaybackState;
+  static const std::string kMediaControllerMetadataAttribute;
+
+  static common::PlatformResult GetPlatformEnumMap(
+      const std::string& type, std::map<std::string, int>* platform_str);
+
+  static common::PlatformResult StringToPlatformEnum(const std::string& type,
+                                                     const std::string& value,
+                                                     int* platform_enum);
+
+  static common::PlatformResult PlatformEnumToString(const std::string& type,
+                                                     int value,
+                                                     std::string* platform_str);
+
+  static common::PlatformResult ConvertPlaybackState(mc_playback_h playback_h,
+                                                     std::string* state);
+  static common::PlatformResult ConvertPlaybackPosition(mc_playback_h playback_h,
+                                                        double* position);
+  static common::PlatformResult ConvertMetadata(mc_metadata_h metadata_h,
+                                                picojson::object* metadata);
+
+ private:
+  static const PlatformEnumMap platform_enum_map_;
+  // TODO(r.galka) can be replaced by Boost.Bimap
+  static PlatformEnumReverseMap platform_enum_reverse_map_;
+};
+
+} // namespace mediacontroller
+} // namespace extension
+
+#endif  // MEDIACONTROLLER_MEDIACONTROLLER_TYPES_H_
diff --git a/webWidgetTCT_device/src/mediakey/mediakey.gyp b/webWidgetTCT_device/src/mediakey/mediakey.gyp
new file mode 100755 (executable)
index 0000000..339ea01
--- /dev/null
@@ -0,0 +1,35 @@
+{
+  'includes':[
+    '../common/common.gypi',
+  ],
+  'targets': [
+    {
+      'target_name': 'tizen_mediakey',
+      'type': 'loadable_module',
+      'dependencies': [
+        '../common/common.gyp:tizen_common',
+      ],
+      'sources': [
+        'mediakey_api.js',
+        'mediakey_extension.cc',
+        'mediakey_extension.h',
+        'mediakey_instance.cc',
+        'mediakey_instance.h',
+        'mediakey_manager.cc',
+        'mediakey_manager.h'
+      ],
+      'includes': [
+        '../common/pkg-config.gypi',
+      ],
+      'conditions': [
+        ['tizen == 1', {
+         'variables': {
+            'packages': [
+              'capi-system-media-key',
+            ]
+          },
+        }],
+      ],
+    },
+  ],
+}
diff --git a/webWidgetTCT_device/src/mediakey/mediakey_api.js b/webWidgetTCT_device/src/mediakey/mediakey_api.js
new file mode 100755 (executable)
index 0000000..d04e382
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+var validator = xwalk.utils.validator;
+var type = xwalk.utils.type;
+var native = new xwalk.utils.NativeManager(extension);
+var converter_ = xwalk.utils.converter;
+
+var ON_PRESSED_MEDIA_KEY_EVENT_CALLBACK = 'onPressedMediaKeyEventCallback';
+var ON_RELEASED_MEDIA_KEY_EVENT_CALLBACK = 'onReleasedMediaKeyEventCallback';
+
+function MediaKeyManager() {
+  validator.isConstructorCall(this, MediaKeyManager);
+}
+
+MediaKeyManager.prototype.setMediaKeyEventListener = function(callback) {
+    var args = validator.validateArgs(arguments, [
+      {
+        name: 'callback',
+        type: validator.Types.LISTENER,
+        values: ['onpressed', 'onreleased']
+      }
+    ]);
+
+    var ret = native.callSync('MediaKeyManager_setMediaKeyEventListener', {});
+
+    if (native.isFailure(ret)) {
+        throw native.getErrorObject(ret);
+    }
+
+    native.removeListener(ON_PRESSED_MEDIA_KEY_EVENT_CALLBACK);
+    native.removeListener(ON_RELEASED_MEDIA_KEY_EVENT_CALLBACK);
+
+    native.addListener(ON_PRESSED_MEDIA_KEY_EVENT_CALLBACK, function(msg) {
+        native.callIfPossible(args.callback.onpressed, msg.type);
+    });
+    native.addListener(ON_RELEASED_MEDIA_KEY_EVENT_CALLBACK, function(msg) {
+        native.callIfPossible(args.callback.onreleased, msg.type);
+    });
+
+};
+
+MediaKeyManager.prototype.unsetMediaKeyEventListener = function() {
+    var ret = native.callSync('MediaKeyManager_unsetMediaKeyEventListener',{});
+
+    if (native.isFailure(ret)) {
+        throw native.getErrorObject(ret);
+    }
+
+    native.removeListener(ON_PRESSED_MEDIA_KEY_EVENT_CALLBACK);
+    native.removeListener(ON_RELEASED_MEDIA_KEY_EVENT_CALLBACK);
+};
+
+exports = new MediaKeyManager();
diff --git a/webWidgetTCT_device/src/mediakey/mediakey_extension.cc b/webWidgetTCT_device/src/mediakey/mediakey_extension.cc
new file mode 100755 (executable)
index 0000000..b10658c
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2015 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 "mediakey/mediakey_extension.h"
+#include "mediakey/mediakey_instance.h"
+#include "mediakey/mediakey_manager.h"
+
+// This will be generated from mediakey_api.js.
+extern const char kSource_mediakey_api[];
+
+namespace extension {
+namespace mediakey {
+
+MediaKeyExtension::MediaKeyExtension() {
+  SetExtensionName("tizen.mediakey");
+  SetJavaScriptAPI(kSource_mediakey_api);
+}
+
+MediaKeyExtension::~MediaKeyExtension() {
+}
+
+common::Instance* MediaKeyExtension::CreateInstance() {
+  return new MediaKeyInstance();
+}
+
+}  // namespace mediakey
+}  // namespace extension
+
+// entry point
+common::Extension* CreateExtension() {
+  return new extension::mediakey::MediaKeyExtension();
+}
+
diff --git a/webWidgetTCT_device/src/mediakey/mediakey_extension.h b/webWidgetTCT_device/src/mediakey/mediakey_extension.h
new file mode 100755 (executable)
index 0000000..7fa4b95
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2015 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 SRC_MEDIAKEY_MEDIAKEY_EXTENSION_H_
+#define SRC_MEDIAKEY_MEDIAKEY_EXTENSION_H_
+
+#include "common/extension.h"
+
+namespace extension {
+namespace mediakey {
+
+class MediaKeyManager;
+
+class MediaKeyExtension : public common::Extension {
+ public:
+  MediaKeyExtension();
+  virtual ~MediaKeyExtension();
+
+ private:
+  virtual common::Instance* CreateInstance();
+};
+
+}  // namespace mediakey
+}  // namespace extension
+
+#endif  // SRC_MEDIAKEY_MEDIAKEY_EXTENSION_H_
diff --git a/webWidgetTCT_device/src/mediakey/mediakey_instance.cc b/webWidgetTCT_device/src/mediakey/mediakey_instance.cc
new file mode 100755 (executable)
index 0000000..ec3af1b
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2015 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 <functional>
+#include <map>
+#include "common/logger.h"
+#include "mediakey/mediakey_instance.h"
+#include "mediakey/mediakey_manager.h"
+
+namespace extension {
+namespace mediakey {
+
+const std::map<media_key_e, std::string> kMediaKeyTypeMap = {
+    { MEDIA_KEY_PLAY, "MEDIA_PLAY" },
+    { MEDIA_KEY_STOP, "MEDIA_STOP" },
+    { MEDIA_KEY_PAUSE, "MEDIA_PAUSE" },
+    { MEDIA_KEY_PREVIOUS, "MEDIA_PREVIOUS" },
+    { MEDIA_KEY_NEXT, "MEDIA_NEXT" },
+    { MEDIA_KEY_FASTFORWARD, "MEDIA_FAST_FORWARD" },
+    { MEDIA_KEY_REWIND, "MEDIA_REWIND" },
+    { MEDIA_KEY_PLAYPAUSE, "MEDIA_PLAY_PAUSE" } };
+
+MediaKeyInstance::MediaKeyInstance() {
+  LoggerD("Entered");
+  using std::placeholders::_1;
+  using std::placeholders::_2;
+#define REGISTER_SYNC(c, x) \
+    RegisterSyncHandler(c, std::bind(&MediaKeyInstance::x, this, _1, _2));
+  REGISTER_SYNC("MediaKeyManager_setMediaKeyEventListener",
+                SetMediaKeyEventListener);
+  REGISTER_SYNC("MediaKeyManager_unsetMediaKeyEventListener",
+                UnsetMediaKeyEventListener);
+#undef REGISTER_SYNC
+}
+
+MediaKeyInstance::~MediaKeyInstance() {
+  LoggerD("Entered");
+  MediaKeyManager::GetInstance().UnregisterMediaKeyEventListener();
+}
+
+void MediaKeyInstance::SetMediaKeyEventListener(const picojson::value& args,
+                                                picojson::object& out) {
+
+  LoggerD("Enter");
+
+  common::PlatformResult result = MediaKeyManager::GetInstance()
+      .RegisterMediaKeyEventListener(this);
+  if (result.IsError()) {
+    LOGD("Error occured");
+    ReportError(result, &out);
+  } else {
+    ReportSuccess(out);
+  }
+}
+
+void MediaKeyInstance::UnsetMediaKeyEventListener(const picojson::value& args,
+                                                  picojson::object& out) {
+  LoggerD("Enter");
+  common::PlatformResult result = MediaKeyManager::GetInstance()
+      .UnregisterMediaKeyEventListener();
+  if (result.IsError()) {
+    LOGD("Error occured");
+    ReportError(result, &out);
+  } else {
+    ReportSuccess(out);
+  }
+}
+
+void MediaKeyInstance::OnPressedMediaKeyEventCallback(media_key_e type) {
+  LoggerD("Enter");
+  PostEvent("onPressedMediaKeyEventCallback", type);
+}
+
+void MediaKeyInstance::OnReleasedMediaKeyEventCallback(media_key_e type) {
+  LoggerD("Enter");
+  PostEvent("onReleasedMediaKeyEventCallback", type);
+}
+
+void MediaKeyInstance::PostEvent(const std::string& eventCallback,
+                                 media_key_e type) {
+  LoggerD("Enter");
+  auto k = kMediaKeyTypeMap.find(type);
+  if (k != kMediaKeyTypeMap.end()) {
+    picojson::value event = picojson::value(picojson::object());
+    picojson::object& obj = event.get<picojson::object>();
+    obj["listenerId"] = picojson::value(eventCallback);
+    obj["type"] = picojson::value((k->second).c_str());
+    Instance::PostMessage(this, event.serialize().c_str());
+  }
+  else {
+    LoggerD("Unsupported key");
+  }
+}
+
+}  // namespace mediakey
+}  // namespace extension
diff --git a/webWidgetTCT_device/src/mediakey/mediakey_instance.h b/webWidgetTCT_device/src/mediakey/mediakey_instance.h
new file mode 100755 (executable)
index 0000000..63c0239
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2015 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 SRC_MEDIAKEY_MEDIAKEY_INSTANCE_H_
+#define SRC_MEDIAKEY_MEDIAKEY_INSTANCE_H_
+
+#include <string>
+
+#include "common/extension.h"
+#include "common/picojson.h"
+
+#include "mediakey/mediakey_manager.h"
+
+namespace extension {
+namespace mediakey {
+
+class MediaKeyInstance : public common::ParsedInstance, public MediaKeyListener {
+ public:
+  MediaKeyInstance();
+  virtual ~MediaKeyInstance();
+
+ private:
+  void SetMediaKeyEventListener(const picojson::value& args,
+                                picojson::object& out);
+  void UnsetMediaKeyEventListener(const picojson::value& args,
+                                  picojson::object& out);
+  virtual void OnPressedMediaKeyEventCallback(media_key_e type);
+  virtual void OnReleasedMediaKeyEventCallback(media_key_e type);
+  void PostEvent(const std::string& event, media_key_e type);
+};
+
+}  // namespace mediakey
+}  // namespace extension
+
+#endif  // SRC_MEDIAKEY_MEDIAKEY_INSTANCE_H_
diff --git a/webWidgetTCT_device/src/mediakey/mediakey_manager.cc b/webWidgetTCT_device/src/mediakey/mediakey_manager.cc
new file mode 100755 (executable)
index 0000000..29ee1e0
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2015 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 "mediakey/mediakey_manager.h"
+#include "common/logger.h"
+#include "common/platform_exception.h"
+
+namespace extension {
+namespace mediakey {
+
+using common::UnknownException;
+using common::ErrorCode;
+MediaKeyListener::~MediaKeyListener() {
+  LoggerD("Enter");
+}
+
+MediaKeyManager& MediaKeyManager::GetInstance() {
+  static MediaKeyManager manager;
+  return manager;
+}
+
+MediaKeyManager::MediaKeyManager()
+    : m_media_key_listener(nullptr),
+      m_media_key_listener_registered(false) {
+  LoggerD("Enter");
+}
+
+common::PlatformResult MediaKeyManager::RegisterMediaKeyEventListener(
+    MediaKeyListener* listener) {
+  LoggerD("Enter");
+  if (!m_media_key_listener_registered) {
+    LoggerD("before calling media_key_reserve");
+    int ret = media_key_reserve(MediaKeyEventCallback, NULL);
+    LoggerD("after calling media_key_reserve - result = %d", ret);
+    if (MEDIA_KEY_ERROR_NONE != ret) {
+      LoggerD("Failed to register "
+              "a media keys change event callback: %d",
+              ret);
+      return common::PlatformResult(
+          ErrorCode::UNKNOWN_ERR,
+          "Failed to register a media keys change event callback");
+    }
+    m_media_key_listener = listener;
+    m_media_key_listener_registered = true;
+    LOGD("Added media keys change event callback");
+  }
+  return common::PlatformResult(ErrorCode::NO_ERROR);
+}
+common::PlatformResult MediaKeyManager::UnregisterMediaKeyEventListener() {
+  LoggerD("Enter");
+  if (m_media_key_listener_registered) {
+    int ret = media_key_release();
+    if (MEDIA_KEY_ERROR_NONE != ret) {
+      LoggerD("Failed to unregister "
+              "the change event callback function: %d",
+              ret);
+      return common::PlatformResult(
+          ErrorCode::UNKNOWN_ERR,
+          "Failed to unregister the change event callback function");
+    }
+  }
+  m_media_key_listener = NULL;
+  m_media_key_listener_registered = false;
+  return common::PlatformResult(ErrorCode::NO_ERROR);
+}
+
+void MediaKeyManager::MediaKeyEventCallback(media_key_e key,
+                                            media_key_event_e status,
+                                            void* user_data) {
+  LoggerD("Enter");
+  if (!GetInstance().m_media_key_listener) {
+    LOGD("Listener is null. Ignoring");
+    return;
+  }
+  if (MEDIA_KEY_STATUS_PRESSED == status) {
+    GetInstance().m_media_key_listener->OnPressedMediaKeyEventCallback(key);
+  } else if (MEDIA_KEY_STATUS_RELEASED == status) {
+    GetInstance().m_media_key_listener->OnReleasedMediaKeyEventCallback(key);
+  }
+}
+
+}  // namespace mediakey
+}  // namespace extension
diff --git a/webWidgetTCT_device/src/mediakey/mediakey_manager.h b/webWidgetTCT_device/src/mediakey/mediakey_manager.h
new file mode 100755 (executable)
index 0000000..7b95a23
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2015 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 <media_key.h>
+#include "common/platform_result.h"
+
+#ifndef SRC_MEDIAKEY_MEDIAKEY_MANAGER_H_
+#define SRC_MEDIAKEY_MEDIAKEY_MANAGER_H_
+
+namespace extension {
+namespace mediakey {
+
+class MediaKeyListener {
+ public:
+  virtual void OnPressedMediaKeyEventCallback(media_key_e type)= 0;
+  virtual void OnReleasedMediaKeyEventCallback(media_key_e type)= 0;
+  virtual ~MediaKeyListener();
+};
+
+class MediaKeyManager {
+ public:
+  common::PlatformResult RegisterMediaKeyEventListener(
+      MediaKeyListener* listener);
+  common::PlatformResult UnregisterMediaKeyEventListener();
+  static MediaKeyManager& GetInstance();
+  static void MediaKeyEventCallback(media_key_e key, media_key_event_e status,
+                                    void* user_data);
+
+ private:
+  // Not copyable, assignable, movable
+  MediaKeyManager(MediaKeyManager const&) = delete;
+  void operator=(MediaKeyManager const&) = delete;
+  MediaKeyManager(MediaKeyManager &&) = delete;
+
+  MediaKeyManager();
+  MediaKeyListener* m_media_key_listener;
+  bool m_media_key_listener_registered;
+};
+
+}  // namespace mediakey
+}  // namespace extension
+
+#endif  // SRC_MEDIAKEY_MEDIAKEY_MANAGER_H_
diff --git a/webWidgetTCT_device/src/messageport/messageport.gyp b/webWidgetTCT_device/src/messageport/messageport.gyp
new file mode 100755 (executable)
index 0000000..87e2e78
--- /dev/null
@@ -0,0 +1,32 @@
+{
+  'includes':[
+    '../common/common.gypi',
+  ],
+  'targets': [
+    {
+      'target_name': 'tizen_messageport',
+      'type': 'loadable_module',
+      'dependencies': [
+        '../common/common.gyp:tizen_common',
+      ],
+      'sources': [
+        'messageport_api.js',
+        'messageport_extension.cc',
+        'messageport_extension.h',
+        'messageport_instance.cc',
+        'messageport_instance.h',
+      ],
+      'conditions': [
+        ['tizen == 1', {
+          'variables': {
+            'packages': [
+              'vconf',
+              'capi-message-port',
+              'dlog'
+            ]
+          },
+        }],
+      ],
+    },
+  ],
+}
diff --git a/webWidgetTCT_device/src/messageport/messageport_api.js b/webWidgetTCT_device/src/messageport/messageport_api.js
new file mode 100755 (executable)
index 0000000..872c75f
--- /dev/null
@@ -0,0 +1,316 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+var validator_ = xwalk.utils.validator;
+var types_ = validator_.Types;
+
+
+var callbackId = 0;
+var callbacks = {};
+var ports = [];
+
+extension.setMessageListener(function(json) {
+  var msg = JSON.parse(json);
+  var listeners = callbacks[msg['local_port_id']];
+  var rmp;
+
+  console.log('Listeners length:' + listeners.length);
+
+  if (!msg.hasOwnProperty('remotePort'))
+    rmp = null;
+  else
+    rmp = new RemoteMessagePort(msg.remotePort, msg.remoteAppId, msg.trusted);
+  for (var i = 0; i < listeners.length; i++) {
+    var func = listeners[i][0];
+    func(msg.message, rmp);
+  }
+
+});
+
+function nextCallbackId() {
+  return callbackId++;
+}
+
+var ExceptionMap = {
+  'UnknownError' : WebAPIException.UNKNOWN_ERR,
+  'TypeMismatchError' : WebAPIException.TYPE_MISMATCH_ERR,
+  'InvalidValuesError' : WebAPIException.INVALID_VALUES_ERR,
+  'IOError' : WebAPIException.IO_ERR,
+  'ServiceNotAvailableError' : WebAPIException.SERVICE_NOT_AVAILABLE_ERR,
+  'SecurityError' : WebAPIException.SECURITY_ERR,
+  'NetworkError' : WebAPIException.NETWORK_ERR,
+  'NotSupportedError' : WebAPIException.NOT_SUPPORTED_ERR,
+  'NotFoundError' : WebAPIException.NOT_FOUND_ERR,
+  'InvalidAccessError' : WebAPIException.INVALID_ACCESS_ERR,
+  'AbortError' : WebAPIException.ABORT_ERR,
+  'QuotaExceededError' : WebAPIException.QUOTA_EXCEEDED_ERR
+};
+
+function callNative(cmd, args) {
+  var json = {'cmd': cmd, 'args': args};
+  var argjson = JSON.stringify(json);
+  var resultString = extension.internal.sendSyncMessage(argjson);
+  var result = JSON.parse(resultString);
+
+  if (typeof result !== 'object') {
+    throw new WebAPIException(WebAPIException.UNKNOWN_ERR);
+  }
+
+  if (result['status'] == 'success') {
+    if (result['result']) {
+      return result['result'];
+    }
+    return true;
+  }
+  else if (result['status'] == 'error') {
+    var err = result['error'];
+    if (err) {
+      if (ExceptionMap[err.name]) {
+        throw new WebAPIException(ExceptionMap[err.name], err.message);
+      } else {
+        throw new WebAPIException(WebAPIException.UNKNOWN_ERR, err.message);
+      }
+    }
+    return false;
+  }
+}
+
+
+function callNativeWithCallback(cmd, args, callback) {
+  if (callback) {
+    var id = nextCallbackId();
+    args['callbackId'] = id;
+    callbacks[id] = callback;
+  }
+
+  return callNative(cmd, args);
+}
+
+function SetReadOnlyProperty(obj, n, v) {
+  Object.defineProperty(obj, n, {value: v, writable: false});
+}
+
+
+function MessagePortManager() {
+  // constructor of MessagePortManager
+}
+
+
+MessagePortManager.prototype.requestLocalMessagePort = function(localMessagePortName) {
+  var args = validator_.validateArgs(arguments, [
+    {'name' : 'localMessagePortName', 'type': types_.STRING}
+  ]);
+
+  if ('' === args.localMessagePortName) {
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+                              'Port name cannot be empty.');
+  }
+
+  var localPortId;
+  var nativeParam = {
+    'localMessagePortName': args.localMessagePortName
+  };
+
+  try {
+
+    localPortId = callNative('MessagePortManager_requestLocalMessagePort', nativeParam);
+
+  } catch (e) {
+    throw e;
+  }
+
+  var returnObject = new LocalMessagePort(args.localMessagePortName, false);
+  ports[nativeParam.localMessagePortName] = localPortId;
+
+  return returnObject;
+};
+
+MessagePortManager.prototype.requestTrustedLocalMessagePort = function(localMessagePortName) {
+  var args = validator_.validateArgs(arguments, [
+    {'name' : 'localMessagePortName', 'type': types_.STRING}
+  ]);
+
+  if ('' === args.localMessagePortName) {
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+                              'Port name cannot be empty.');
+  }
+
+  var nativeParam = {
+    'localMessagePortName': args.localMessagePortName
+  };
+
+  try {
+
+    var localPortId = callNative('MessagePortManager_requestTrustedLocalMessagePort', nativeParam);
+
+  } catch (e) {
+    throw e;
+  }
+
+  var returnObject = new LocalMessagePort(args.localMessagePortName, true);
+  ports[nativeParam.localMessagePortName] = localPortId;
+
+  return returnObject;
+};
+
+MessagePortManager.prototype.requestRemoteMessagePort =
+    function(appId, remoteMessagePortName) {
+  var args = validator_.validateArgs(arguments, [
+    {'name' : 'appId', 'type': types_.STRING},
+    {'name' : 'remoteMessagePortName', 'type': types_.STRING}
+  ]);
+
+  var nativeParam = {
+    'appId': args.appId,
+    'remoteMessagePortName': args.remoteMessagePortName
+  };
+
+  try {
+
+    var syncResult = callNative('MessagePortManager_requestRemoteMessagePort', nativeParam);
+
+  } catch (e) {
+    throw e;
+  }
+
+  var returnObject = new RemoteMessagePort(args.remoteMessagePortName, args.appId, false);
+
+  return returnObject;
+};
+
+MessagePortManager.prototype.requestTrustedRemoteMessagePort =
+    function(appId, remoteMessagePortName) {
+  var args = validator_.validateArgs(arguments, [
+    {'name' : 'appId', 'type': types_.STRING},
+    {'name' : 'remoteMessagePortName', 'type': types_.STRING}
+  ]);
+
+  var nativeParam = {
+    'appId' : args.appId,
+    'remoteMessagePortName': args.remoteMessagePortName
+  };
+
+  try {
+
+    var syncResult = callNative('MessagePortManager_requestTrustedRemoteMessagePort', nativeParam);
+
+  } catch (e) {
+    throw e;
+  }
+
+  var returnObject = new RemoteMessagePort(args.remoteMessagePortName, args.appId, true);
+
+  return returnObject;
+};
+
+
+function LocalMessagePort(messagePortName, isTrusted) {
+  Object.defineProperties(this, {
+    'messagePortName': { value: messagePortName, writable: false, enumerable: true },
+    'isTrusted': { value: !!isTrusted, writable: false, enumerable: true }
+  });
+}
+
+
+LocalMessagePort.prototype.addMessagePortListener = function(listener) {
+  var args = validator_.validateArgs(arguments, [
+    {'name' : 'listener', 'type': types_.FUNCTION, 'nullable': false}
+  ]);
+
+  var portId = ports[this.messagePortName];
+
+  if (!callbacks.hasOwnProperty(portId)) callbacks[portId] = [];
+
+  callbackId++;
+  callbacks[portId].push([listener, callbackId]);
+
+  return callbackId;
+
+};
+
+LocalMessagePort.prototype.removeMessagePortListener = function(watchId) {
+  var args = validator_.validateArgs(arguments, [
+    {'name' : 'watchId', 'type': types_.LONG, 'nullable': false, 'optional': false }
+  ]);
+
+  var to_delete;
+  var listeners = callbacks[ports[this.messagePortName]];
+
+  for (var i = 0, j = listeners.length; i < j; i++) {
+    var listener_id = listeners[i][1];
+    if (watchId == listener_id) {
+      to_delete = i;
+      break;
+    }
+  }
+
+  if (typeof to_delete === 'undefined')
+    throw new WebAPIException(WebAPIException.NOT_FOUND_ERR,
+        'The port of the target application is not found.');
+
+  listeners.splice(to_delete, 1);
+
+};
+
+
+function RemoteMessagePort(messagePortName, appId, isTrusted) {
+  Object.defineProperties(this, {
+    'messagePortName': { value: messagePortName, writable: false },
+    'appId': { value: appId, writable: false },
+    'isTrusted': { value: !!isTrusted, writable: false }
+  });
+}
+
+RemoteMessagePort.prototype.sendMessage = function() {
+  var args = validator_.validateArgs(arguments, [
+    {'name' : 'data', 'type': types_.ARRAY},
+    {'name' : 'localMessagePort', 'type': types_.PLATFORM_OBJECT, 'optional' : true,
+      'nullable' : true, 'values' : LocalMessagePort }
+  ]);
+
+  var filtered_data = new Array(args.data.length);
+  var unique_data_key = {};
+
+  for (var i = 0, j = args.data.length; i < j; i++) {
+    if (!args.data[i].hasOwnProperty('key')) {
+      throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+          'MessagePortDataItem should contain \'key\' property.');
+    }
+    var key = args.data[i].key;
+    if ('' === key) {
+      throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+          'Property \'key\' should not be empty.');
+    }
+    if (true === unique_data_key[key]) {
+      throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+          'Property \'key\' should not be duplicated.');
+    }
+    filtered_data[i] = { key: key, value: args.data[i].value };
+    unique_data_key[key] = true;
+  }
+
+  var nativeParam = {
+    'appId': this.appId,
+    'messagePortName': this.messagePortName,
+    'data': filtered_data,
+    'trusted': this.isTrusted,
+    'local_port_id': args.localMessagePort ? ports[args.localMessagePort.messagePortName] : -1
+  };
+
+  var syncResult = callNative('RemoteMessagePort_sendMessage', nativeParam);
+};
+
+exports = new MessagePortManager();
diff --git a/webWidgetTCT_device/src/messageport/messageport_extension.cc b/webWidgetTCT_device/src/messageport/messageport_extension.cc
new file mode 100755 (executable)
index 0000000..d77a194
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2015 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 "messageport/messageport_extension.h"
+
+#include "messageport/messageport_instance.h"
+
+// This will be generated from messageport_api.js
+extern const char kSource_messageport_api[];
+
+common::Extension* CreateExtension() {
+  return new MessageportExtension;
+}
+
+MessageportExtension::MessageportExtension() {
+  SetExtensionName("tizen.messageport");
+  SetJavaScriptAPI(kSource_messageport_api);
+}
+
+MessageportExtension::~MessageportExtension() {}
+
+common::Instance* MessageportExtension::CreateInstance() {
+  return new extension::messageport::MessageportInstance;
+}
diff --git a/webWidgetTCT_device/src/messageport/messageport_extension.h b/webWidgetTCT_device/src/messageport/messageport_extension.h
new file mode 100755 (executable)
index 0000000..6ef1b9f
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2015 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 MESSAGEPORT_MESSAGEPORT_EXTENSION_H_
+#define MESSAGEPORT_MESSAGEPORT_EXTENSION_H_
+
+#include "common/extension.h"
+
+class MessageportExtension : public common::Extension {
+ public:
+  MessageportExtension();
+  virtual ~MessageportExtension();
+
+ private:
+  virtual common::Instance* CreateInstance();
+};
+
+#endif  // MESSAGEPORT_MESSAGEPORT_EXTENSION_H_
diff --git a/webWidgetTCT_device/src/messageport/messageport_instance.cc b/webWidgetTCT_device/src/messageport/messageport_instance.cc
new file mode 100755 (executable)
index 0000000..b2594b7
--- /dev/null
@@ -0,0 +1,385 @@
+/*
+ * Copyright (c) 2015 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 "messageport/messageport_instance.h"
+
+#include <functional>
+#include <vector>
+#include <string>
+
+#include "common/picojson.h"
+#include "common/logger.h"
+#include "common/platform_exception.h"
+
+namespace extension {
+namespace messageport {
+
+using common::TypeMismatchException;
+using common::InvalidValuesException;
+using common::UnknownException;
+using common::NotFoundException;
+using common::QuotaExceededException;
+
+MessageportInstance::MessageportInstance() {
+  LoggerD("Enter");
+  using std::placeholders::_1;
+  using std::placeholders::_2;
+  #define REGISTER_SYNC(c, x) \
+    RegisterSyncHandler(c, std::bind(&MessageportInstance::x, this, _1, _2));
+  REGISTER_SYNC("MessagePortManager_requestTrustedRemoteMessagePort",
+                MessagePortManagerRequesttrustedremotemessageport);
+  REGISTER_SYNC("MessagePortManager_requestLocalMessagePort",
+                MessagePortManagerRequestlocalmessageport);
+  REGISTER_SYNC("MessagePortManager_requestTrustedLocalMessagePort",
+                MessagePortManagerRequesttrustedlocalmessageport);
+  REGISTER_SYNC("MessagePortManager_requestRemoteMessagePort",
+                MessagePortManagerRequestremotemessageport);
+  REGISTER_SYNC("RemoteMessagePort_sendMessage", RemoteMessagePortSendmessage);
+  #undef REGISTER_SYNC
+}
+
+MessageportInstance::~MessageportInstance() {
+  LoggerD("Enter");
+}
+
+
+enum MessageportCallbacks {
+  MessagePortManagerRequesttrustedremotemessageportCallback,
+  MessagePortManagerRequestlocalmessageportCallback,
+  MessagePortManagerRequesttrustedlocalmessageportCallback,
+  MessagePortManagerRequestremotemessageportCallback,
+  LocalMessagePortRemovemessageportlistenerCallback,
+  RemoteMessagePortSendmessageCallback,
+  LocalMessagePortAddmessageportlistenerCallback
+};
+
+static void BundleJsonIterator(const char *k, const char *v, void *d) {
+  LoggerD("Enter");
+  picojson::value::array *array = static_cast<picojson::value::array *>(d);
+  picojson::value::object o;
+  o["key"] = picojson::value(k);
+  o["value"] = picojson::value(v);
+  array->push_back(picojson::value(o));
+}
+
+#define CHECK_EXIST(args, name, out) \
+    if (!args.contains(name)) {\
+      ReportError(TypeMismatchException(name" is required argument"), out);\
+      return;\
+    }
+
+static void OnReceiveLocalMessage(int local_port_id,
+  const char* remote_app_id, const char* remote_port,
+  bool trusted_remote_port, bundle* message, void* user_data) {
+
+  LoggerD("Enter");
+  MessageportInstance* object = static_cast<MessageportInstance*>(user_data);
+  picojson::value::object o;
+  picojson::value::array data;
+
+  o["local_port_id"] = picojson::value(static_cast<double>(local_port_id));
+
+  if (remote_port) {
+    o["remoteAppId"] = picojson::value(remote_app_id);
+    o["remotePort"] = picojson::value(remote_port);
+    o["trusted"] = picojson::value(trusted_remote_port);
+    LoggerD("Msg received from: %s", remote_app_id);
+  }
+
+  LoggerD("Msg received");
+
+  bundle_iterate(message, BundleJsonIterator, &data);
+
+  o["message"] = picojson::value(data);
+
+  common::Instance::PostMessage(object, picojson::value(o).serialize().c_str());
+}
+
+
+void MessageportInstance::MessagePortManagerRequestlocalmessageport
+  (const picojson::value& args, picojson::object& out) {
+  LoggerD("Enter");
+  CHECK_EXIST(args, "localMessagePortName", out)
+
+  int portId;
+  const std::string& localMessagePortName =
+    args.get("localMessagePortName").get<std::string>();
+
+  portId = message_port_register_local_port
+    (localMessagePortName.c_str(), OnReceiveLocalMessage, this);
+
+  LoggerD("Registering local port %s : %s", localMessagePortName.c_str(),
+    portId < 0 ? "false" : "true");
+
+
+  if (portId < 0) {
+    switch (portId) {
+      case MESSAGE_PORT_ERROR_INVALID_PARAMETER:
+        LoggerE("The input parameter contains an invalid value");
+        ReportError(InvalidValuesException
+          ("The input parameter contains an invalid value."), out);
+        break;
+      case MESSAGE_PORT_ERROR_OUT_OF_MEMORY:
+        LoggerE("Out of memory");
+        ReportError(UnknownException("Out of memory."), out);
+        break;
+      case MESSAGE_PORT_ERROR_IO_ERROR:
+        LoggerE("Internal I/O error ocurred");
+        ReportError(UnknownException("Internal I/O error ocurred."), out);
+        break;
+      default:
+        LoggerE("Unknown Exception: %d (%s)", portId, get_error_message(portId));
+        ReportError(UnknownException("Unknown Exception"), out);
+        break;
+      }
+  } else {
+    ReportSuccess(picojson::value(static_cast<double>(portId)), out);
+  }
+}
+
+void MessageportInstance::
+  MessagePortManagerRequesttrustedlocalmessageport
+    (const picojson::value& args, picojson::object& out) {
+
+  LoggerD("Enter");
+  CHECK_EXIST(args, "localMessagePortName", out)
+
+  int portId;
+  const std::string& localMessagePortName =
+    args.get("localMessagePortName").get<std::string>();
+
+  portId = message_port_register_trusted_local_port
+    (localMessagePortName.c_str(), OnReceiveLocalMessage, this);
+
+  LoggerD("Registering trusted local port %s:%s", localMessagePortName.c_str(),
+    portId < 0 ? "false" : "true");
+
+  if (portId < 0) {
+    switch (portId) {
+      case MESSAGE_PORT_ERROR_INVALID_PARAMETER:
+        LoggerE("The input parameter contains an invalid value");
+        ReportError(InvalidValuesException
+          ("The input parameter contains an invalid value."), out);
+        break;
+      case MESSAGE_PORT_ERROR_OUT_OF_MEMORY:
+        LoggerE("Out of memory");
+        ReportError(UnknownException("Out of memory."), out);
+        break;
+      case MESSAGE_PORT_ERROR_IO_ERROR:
+        LoggerE("Internal I/O error ocurred");
+        ReportError(UnknownException("Internal I/O error ocurred."), out);
+        break;
+      default:
+        LoggerE("Unknown Exception: %d (%s)", portId, get_error_message(portId));
+        ReportError(UnknownException("Unknown Exception"), out);
+        break;
+      }
+  } else {
+    ReportSuccess(picojson::value(static_cast<double>(portId)), out);
+  }
+}
+
+void MessageportInstance::
+  MessagePortManagerRequestremotemessageport
+    (const picojson::value& args, picojson::object& out) {
+  LoggerD("Enter");
+  CHECK_EXIST(args, "remoteMessagePortName", out)
+
+  const std::string& remoteMessagePortName =
+    args.get("remoteMessagePortName").get<std::string>();
+  const std::string& appId = args.get("appId").get<std::string>();
+
+  int ret;
+  bool portCheck;
+
+  ret = message_port_check_remote_port(appId.c_str(),
+    remoteMessagePortName.c_str(), &portCheck);
+
+  LoggerD("Checking remote port of %s: %s", remoteMessagePortName.c_str(),
+    portCheck ? "true" : "false");
+  LoggerD("Error code: %d (%s)", ret, get_error_message(ret));
+
+  if (ret == MESSAGE_PORT_ERROR_NONE) {
+    if (portCheck)  {
+      ReportSuccess(out);
+    } else {
+      LoggerE("The port of the target application is not found");
+      ReportError(
+          NotFoundException("The port of the target application is not found"),
+          out);
+    }
+  } else if (ret == MESSAGE_PORT_ERROR_INVALID_PARAMETER) {
+    LoggerE("An input parameter contains an invalid value");
+    ReportError(
+        InvalidValuesException("An input parameter contains an invalid value."),
+        out);
+  } else if (ret == MESSAGE_PORT_ERROR_OUT_OF_MEMORY) {
+    LoggerE("Out of memory");
+    ReportError(UnknownException("Out of memory."), out);
+  } else if (ret == MESSAGE_PORT_ERROR_IO_ERROR) {
+    // IO error means that remote port does not exist
+    LoggerE("The port of the target application is not found");
+    ReportError(
+        NotFoundException("The port of the target application is not found"),
+        out);
+  } else if (ret == MESSAGE_PORT_ERROR_PORT_NOT_FOUND) {
+    ReportError(
+        NotFoundException("The port of the target application is not found"),
+        out);
+  } else {
+    LoggerE("Unknown Error");
+    ReportError(UnknownException("Unknown Error"), out);
+  }
+}
+
+void MessageportInstance::
+  MessagePortManagerRequesttrustedremotemessageport
+    (const picojson::value& args, picojson::object& out) {
+  LoggerD("Enter");
+  CHECK_EXIST(args, "remoteMessagePortName", out)
+
+  const std::string& remoteMessagePortName =
+    args.get("remoteMessagePortName").get<std::string>();
+  const std::string& appId = args.get("appId").get<std::string>();
+
+  bool portCheck;
+  int ret;
+
+  ret = message_port_check_trusted_remote_port
+        (appId.c_str(), remoteMessagePortName.c_str(), &portCheck);
+
+  LoggerD("Checking trusted remote port of %s: %s",
+    remoteMessagePortName.c_str(), portCheck ? "true":"false");
+  LoggerD("Error code: %d (%s)", ret, get_error_message(ret));
+
+  if (ret == MESSAGE_PORT_ERROR_NONE) {
+    if (portCheck) {
+      ReportSuccess(out);
+    } else {
+
+      LoggerE("The port of the target application is not found");
+      ReportError(
+          NotFoundException("The port of the target application is not found"),
+          out);
+    }
+  } else if (ret == MESSAGE_PORT_ERROR_INVALID_PARAMETER) {
+    LoggerE("An input parameter contains an invalid value");
+    ReportError(
+        InvalidValuesException("An input parameter contains an invalid value."),
+        out);
+  } else if (ret == MESSAGE_PORT_ERROR_OUT_OF_MEMORY) {
+    LoggerE("Out of memory");
+    ReportError(UnknownException("Out of memory."), out);
+  } else if (ret == MESSAGE_PORT_ERROR_IO_ERROR) {
+    // IO error means that remote port does not exist
+    LoggerE("The port of the target application is not found");
+    ReportError(
+        NotFoundException("The port of the target application is not found"),
+        out);
+  } else if (ret == MESSAGE_PORT_ERROR_PORT_NOT_FOUND) {
+    ReportError(
+        NotFoundException("The port of the target application is not found"),
+        out);
+  } else if (ret == MESSAGE_PORT_ERROR_CERTIFICATE_NOT_MATCH) {
+    LoggerE("The remote application is not signed with the same certificate");
+    ReportError(
+        UnknownException(
+            "The remote application is not signed with the same certificate"),
+        out);
+  } else {
+    LoggerE("Unknown Error");
+    ReportError(UnknownException("Unknown Error"), out);
+  }
+}
+
+void MessageportInstance::RemoteMessagePortSendmessage
+  (const picojson::value& args, picojson::object& out) {
+  LoggerD("Enter");
+  const std::string& appId = args.get("appId").get<std::string>();
+  const std::string& message_port_name =
+    args.get("messagePortName").get<std::string>();
+  std::vector<picojson::value> data = args.get("data").get<picojson::array>();
+
+  long local_port_id =
+    static_cast<long>(args.get("local_port_id").get<double>());
+  bool trusted = args.get("trusted").get<bool>();
+
+  int result;
+
+  bundle* bundle = bundle_create();
+
+  for (picojson::value::array::iterator it = data.begin();
+       it != data.end(); ++it) {
+      bundle_add(bundle, (*it).get("key").to_str().c_str(),
+        (*it).get("value").to_str().c_str());
+  }
+
+  LoggerD("%s to %s", trusted ?
+    "Sending trusted messages" : "Sending normal messages",
+    message_port_name.c_str());
+
+  if (trusted) {
+    if (local_port_id < 0) {
+          result = message_port_send_trusted_message
+            (appId.c_str(), message_port_name.c_str(), bundle);
+        } else {
+          result = message_port_send_trusted_message_with_local_port
+            (appId.c_str(), message_port_name.c_str(), bundle, local_port_id);
+        }
+  } else {
+    if (local_port_id < 0) {
+      result = message_port_send_message
+        (appId.c_str(), message_port_name.c_str(), bundle);
+      LoggerD("-----------%s  & %s---------------",
+        appId.c_str(), message_port_name.c_str());
+    } else {
+      result = message_port_send_message_with_local_port
+        (appId.c_str(), message_port_name.c_str(), bundle, local_port_id);
+    }
+  }
+
+  bundle_free(bundle);
+
+  LoggerD("Error code: %d (%s)", result, get_error_message(result));
+  if (result == MESSAGE_PORT_ERROR_NONE)
+    ReportSuccess(out);
+  else if (result == MESSAGE_PORT_ERROR_INVALID_PARAMETER)
+    ReportError(InvalidValuesException
+      ("An input parameter contains an invalid value.") , out);
+  else if (result == MESSAGE_PORT_ERROR_PORT_NOT_FOUND)
+    ReportError(NotFoundException
+      ("The port of the target application is not found"), out);
+  else if (result == MESSAGE_PORT_ERROR_MAX_EXCEEDED)
+    ReportError(QuotaExceededException
+      ("The size of message has exceeded the maximum limit."), out);
+  else if (result == MESSAGE_PORT_ERROR_RESOURCE_UNAVAILABLE)
+    ReportError(UnknownException("A resource is temporarily unavailable"), out);
+  else if (result == MESSAGE_PORT_ERROR_OUT_OF_MEMORY)
+    ReportError(UnknownException("Out of memory."), out);
+  else if (result == MESSAGE_PORT_ERROR_IO_ERROR)
+    ReportError(UnknownException("Internal I/O error ocurred."), out);
+  else if (result == MESSAGE_PORT_ERROR_CERTIFICATE_NOT_MATCH)
+    ReportError(UnknownException
+      ("The remote application is not signed with the same certificate") , out);
+  else
+    ReportError(UnknownException("Unknown Exception"), out);
+}
+
+
+#undef CHECK_EXIST
+
+}  // namespace messageport
+}  // namespace extension
diff --git a/webWidgetTCT_device/src/messageport/messageport_instance.h b/webWidgetTCT_device/src/messageport/messageport_instance.h
new file mode 100755 (executable)
index 0000000..c4458d2
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2015 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 MESSAGEPORT_MESSAGEPORT_INSTANCE_H_
+#define MESSAGEPORT_MESSAGEPORT_INSTANCE_H_
+
+#include <bundle.h>
+#include <bundle_internal.h>
+#include <message_port.h>
+
+#include "common/extension.h"
+
+namespace extension {
+namespace messageport {
+
+class MessageportInstance : public common::ParsedInstance {
+ public:
+  MessageportInstance();
+  virtual ~MessageportInstance();
+
+ private:
+  void MessagePortManagerRequestlocalmessageport
+    (const picojson::value& args, picojson::object& out);
+  void MessagePortManagerRequesttrustedlocalmessageport
+    (const picojson::value& args, picojson::object& out);
+  void MessagePortManagerRequestremotemessageport
+    (const picojson::value& args, picojson::object& out);
+  void MessagePortManagerRequesttrustedremotemessageport
+    (const picojson::value& args, picojson::object& out);
+  void RemoteMessagePortSendmessage
+    (const picojson::value& args, picojson::object& out);
+};
+
+}  // namespace messageport
+}  // namespace extension
+
+#endif  // MESSAGEPORT_MESSAGEPORT_INSTANCE_H_
diff --git a/webWidgetTCT_device/src/messaging/DBus/DBusTypes.cpp b/webWidgetTCT_device/src/messaging/DBus/DBusTypes.cpp
new file mode 100755 (executable)
index 0000000..1a6489d
--- /dev/null
@@ -0,0 +1,32 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "messaging/DBus/DBusTypes.h"
+
+namespace extension {
+namespace messaging {
+namespace DBus {
+
+const char* kDBusPathNetworkStatus = "/User/Email/NetworkStatus";
+const char* kDBusIfaceNetworkStatus = "User.Email.NetworkStatus";
+const char* kDBusPathEmailStorageChange = "/User/Email/StorageChange";
+const char* kDBusIfaceEmailStorageChange = "User.Email.StorageChange";
+const char* kDBusNameSignalEmail = "email";
+
+} // namespace DBus
+} // namespace messaging
+} // namespace extension
diff --git a/webWidgetTCT_device/src/messaging/DBus/DBusTypes.h b/webWidgetTCT_device/src/messaging/DBus/DBusTypes.h
new file mode 100755 (executable)
index 0000000..0c9c56f
--- /dev/null
@@ -0,0 +1,36 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+namespace extension {
+namespace messaging {
+namespace DBus {
+
+/**
+ * List of Tizen path and interface names:
+ */
+extern const char* kDBusPathNetworkStatus;
+extern const char* kDBusIfaceNetworkStatus;
+extern const char* kDBusPathEmailStorageChange;
+extern const char* kDBusIfaceEmailStorageChange;
+/**
+ * Name of email signal
+ */
+extern const char* kDBusNameSignalEmail;
+
+} // namespace DBus
+} // namespace messaging
+} // namespace extension
diff --git a/webWidgetTCT_device/src/messaging/DBus/EmailSignalProxy.cpp b/webWidgetTCT_device/src/messaging/DBus/EmailSignalProxy.cpp
new file mode 100755 (executable)
index 0000000..f00a37d
--- /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.
+//
+
+/**
+ * @file        EmailSignalProxy.cpp
+ */
+
+#include "EmailSignalProxy.h"
+#include "common/logger.h"
+#include <cstring>
+#include "messaging/DBus/DBusTypes.h"
+
+namespace extension {
+namespace messaging {
+namespace DBus {
+
+EmailSignalProxy::EmailSignalProxy(const std::string& proxy_path,
+        const std::string& proxy_iface) :
+        common::dbus::Proxy (proxy_path,
+                      proxy_iface,
+                      kDBusNameSignalEmail,   //specify email signal details
+                      kDBusPathNetworkStatus,
+                      kDBusIfaceNetworkStatus)
+{
+}
+
+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;
+
+    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).
+    //
+    //LoggerD("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);
+
+    g_free(source);
+}
+
+} //namespace DBus
+} //namespace Messaging
+} //namespace DeviceAPI
diff --git a/webWidgetTCT_device/src/messaging/DBus/EmailSignalProxy.h b/webWidgetTCT_device/src/messaging/DBus/EmailSignalProxy.h
new file mode 100755 (executable)
index 0000000..01687a1
--- /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.
+//
+
+/**
+ * @file        EmailSignalProxy.h
+ */
+
+#ifndef __TIZEN_DBUS_EMAIL_SIGNAL_PROXY_H__
+#define __TIZEN_DBUS_EMAIL_SIGNAL_PROXY_H__
+
+#include "common/GDBus/proxy.h"
+
+namespace extension {
+namespace messaging {
+namespace DBus {
+
+class EmailSignalProxy;
+typedef std::shared_ptr<EmailSignalProxy> EmailSignalProxyPtr;
+
+class EmailSignalProxy : public common::dbus::Proxy {
+public:
+    virtual ~EmailSignalProxy();
+
+protected:
+    EmailSignalProxy(const std::string& proxy_path,
+            const std::string& proxy_iface);
+
+    /**
+     * 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/webWidgetTCT_device/src/messaging/DBus/LoadAttachmentProxy.cpp b/webWidgetTCT_device/src/messaging/DBus/LoadAttachmentProxy.cpp
new file mode 100755 (executable)
index 0000000..df4105b
--- /dev/null
@@ -0,0 +1,244 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT 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 "common/logger.h"
+#include "common/platform_result.h"
+
+#include <cstring>
+#include <email-types.h>
+#include "../message_service.h"
+#include "../message.h"
+#include "../message_body.h"
+#include "../email_manager.h"
+
+#include <email-api.h>
+
+namespace extension {
+namespace messaging {
+namespace DBus {
+
+using namespace common;
+
+/**
+  * This method perform very specified task (see warning comment) so it should not be
+  * visible outside LoadAttachmentProxy class.
+  */
+PlatformResult 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;
+
+    LoggerD("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) {
+        LoggerE("Couldn't get attachment data for attachmentId:%d", attachment->getId());
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Couldn't get attachment.");
+    }
+
+    LoggerD("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) {
+        LoggerD("set attachment path: %s", attachment_data_holder->attachment_path);
+        attachment->setFilePath(attachment_data_holder->attachment_path);
+
+        LoggerD("save_status: %d", attachment_data_holder->save_status);
+        LoggerD("attachment_size : %d", attachment_data_holder->attachment_size);
+    }
+    isSaved = attachment_data_holder->save_status;
+    attachment->setIsSaved(isSaved);
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+LoadAttachmentProxy::LoadAttachmentProxy(const std::string& path,
+        const std::string& iface) :
+        EmailSignalProxy(path, iface)
+{
+}
+
+LoadAttachmentProxy::~LoadAttachmentProxy()
+{
+}
+
+PlatformResult LoadAttachmentProxy::create(const std::string& path,
+                                           const std::string& iface,
+                                           LoadAttachmentProxyPtr* load_attachment_proxy) {
+    load_attachment_proxy->reset(new LoadAttachmentProxy(path, iface));
+    if ((*load_attachment_proxy)->isNotProxyGot()) {
+        LoggerE("Could not get load attachment proxy");
+        load_attachment_proxy->reset();
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Could not get load attachment proxy");
+    } else {
+        return PlatformResult(ErrorCode::NO_ERROR);
+    }
+}
+
+void LoadAttachmentProxy::addCallback(MessageAttachmentCallbackData* callbackOwned)
+{
+    if(callbackOwned->getMessageAttachment()) {
+        LoggerD("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()) {
+        LoggerD("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;
+        }
+    }
+
+    LoggerW("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;
+    }
+
+    LoggerD("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;
+
+    // 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;
+    }
+
+    LoggerD("Found callback for pair mailId:%d nth:%d", mail_id, nth);
+
+    PlatformResult ret = PlatformResult(ErrorCode::NO_ERROR);
+    if(NOTI_DOWNLOAD_ATTACH_FINISH == status) {
+        LoggerD("Message attachment downloaded!");
+
+        std::shared_ptr<MessageAttachment> att = callback->getMessageAttachment();
+        ret = updateAttachmentDataWithEmailGetAttachmentData(att);
+        if (!ret.IsError()) {
+            LoggerD("Updated Message attachment object");
+
+            auto json = callback->getJson();
+            picojson::object& obj = json->get<picojson::object>();
+            obj[JSON_ACTION] = picojson::value(JSON_CALLBACK_SUCCCESS);
+
+            picojson::object args;
+            args[JSON_DATA_MESSAGE_ATTACHMENT] = MessagingUtil::messageAttachmentToJson(
+                    callback->getMessageAttachment());
+            obj[JSON_DATA] = picojson::value(args);
+
+            callback->getQueue().resolve(
+                    obj.at(JSON_CALLBACK_ID).get<double>(),
+                    json->serialize()
+            );
+        }
+    } else if(NOTI_DOWNLOAD_ATTACH_FAIL) {
+        LoggerD("Load message attachment failed!");
+        ret = PlatformResult(ErrorCode::UNKNOWN_ERR, "Load message attachment failed!");
+    }
+    if (ret.IsError()) {
+        LoggerE("Exception in signal callback");
+        callback->setError(ret);
+        callback->getQueue().resolve(
+                callback->getJson()->get<picojson::object>().at(JSON_CALLBACK_ID).get<double>(),
+                callback->getJson()->serialize()
+        );
+    }
+
+    if(callback) {
+        removeCallback(callback);
+        delete callback;
+    }
+}
+
+} //namespace DBus
+} //namespace messaging
+} //namespace extension
diff --git a/webWidgetTCT_device/src/messaging/DBus/LoadAttachmentProxy.h b/webWidgetTCT_device/src/messaging/DBus/LoadAttachmentProxy.h
new file mode 100755 (executable)
index 0000000..9a163c1
--- /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        LoadAttachmentProxy.h
+ */
+
+#ifndef __TIZEN_DBUS_LOAD_ATTACHMENT_PROXY_H__
+#define __TIZEN_DBUS_LOAD_ATTACHMENT_PROXY_H__
+
+#include "common/platform_result.h"
+#include "EmailSignalProxy.h"
+#include <set>
+
+namespace extension {
+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;
+
+    virtual ~LoadAttachmentProxy();
+    static common::PlatformResult create(const std::string& path,
+                                         const std::string& iface,
+                                         LoadAttachmentProxyPtr* load_attachment_proxy);
+
+    //Passed callback will be owned by this proxy
+    void addCallback(MessageAttachmentCallbackData* callbackOwned);
+    void removeCallback(MessageAttachmentCallbackData* callback);
+
+protected:
+    LoadAttachmentProxy(const std::string& path,
+            const std::string& iface);
+    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 extension
+
+#endif // __TIZEN_DBUS_LOAD_ATTACHMENT_PROXY_H__
diff --git a/webWidgetTCT_device/src/messaging/DBus/LoadBodyProxy.cpp b/webWidgetTCT_device/src/messaging/DBus/LoadBodyProxy.cpp
new file mode 100755 (executable)
index 0000000..e6dfeaa
--- /dev/null
@@ -0,0 +1,224 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT 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>
+
+#include "common/logger.h"
+#include <cstring>
+#include "common/platform_result.h"
+
+#include "../message.h"
+#include "../message_body.h"
+#include "../email_manager.h"
+
+namespace extension {
+namespace messaging {
+namespace DBus {
+
+using namespace common;
+
+LoadBodyProxy::LoadBodyProxy(const std::string& path,
+        const std::string& iface) :
+        EmailSignalProxy(path, iface)
+{
+}
+
+LoadBodyProxy::~LoadBodyProxy()
+{
+}
+
+PlatformResult LoadBodyProxy::create(const std::string& path,
+                                     const std::string& iface,
+                                     LoadBodyProxyPtr* load_body_proxy) {
+    load_body_proxy->reset(new LoadBodyProxy(path, iface));
+    if ((*load_body_proxy)->isNotProxyGot()) {
+        LoggerE("Could not get load body proxy");
+        load_body_proxy->reset();
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Could not get load body proxy");
+    } else {
+        return PlatformResult(ErrorCode::NO_ERROR);
+    }
+}
+
+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;
+        }
+    }
+
+    LoggerW("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;
+    }
+
+    LoggerD("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) {
+        LoggerD("Download message body started ...");
+        // There is nothing more to do so we can return now.
+        return;
+    }
+
+    MessageBodyCallbackData* callback = NULL;
+
+    callback = findCallbackByOpHandle(op_handle);
+    if (!callback) {
+        LoggerE("Callback is null");
+    } else {
+        PlatformResult ret = PlatformResult(ErrorCode::NO_ERROR);
+        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) {
+                    ret = callback->getMessage()->updateEmailMessage(*mail_data);
+                    if (!ret.IsError()) {
+                        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);
+                // }
+                //
+            }
+
+            if (!ret.IsError()) {
+                LoggerD("Calling success callback");
+
+                auto json = callback->getJson();
+                picojson::object& obj = json->get<picojson::object>();
+                obj[JSON_ACTION] = picojson::value(JSON_CALLBACK_SUCCCESS);
+
+                picojson::object args;
+                args[JSON_DATA_MESSAGE_BODY] = MessagingUtil::messageBodyToJson(
+                        callback->getMessage()->getBody());
+                obj[JSON_DATA] = picojson::value(args);
+
+                callback->getQueue().resolve(
+                        obj.at(JSON_CALLBACK_ID).get<double>(),
+                        json->serialize()
+                );
+            }
+        } else if(NOTI_DOWNLOAD_BODY_FAIL == status) {
+            LoggerD("Load message body failed!");
+            ret = PlatformResult(ErrorCode::UNKNOWN_ERR, "Load message body failed!");
+        }
+
+        if (ret.IsError()) {
+            callback->setError(ret);
+            callback->getQueue().resolve(
+                    callback->getJson()->get<picojson::object>().at(JSON_CALLBACK_ID).get<double>(),
+                    callback->getJson()->serialize()
+            );
+        }
+
+        removeCallback(callback);
+        delete callback;
+    }
+}
+
+} //namespace DBus
+} //namespace messaging
+} //namespace extension
diff --git a/webWidgetTCT_device/src/messaging/DBus/LoadBodyProxy.h b/webWidgetTCT_device/src/messaging/DBus/LoadBodyProxy.h
new file mode 100755 (executable)
index 0000000..69f29c3
--- /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.
+//
+
+/**
+ * @file        LoadBodyProxy.h
+ */
+
+#ifndef __TIZEN_DBUS_LOAD_BODY_PROXY_H__
+#define __TIZEN_DBUS_LOAD_BODY_PROXY_H__
+
+#include "common/platform_result.h"
+#include "EmailSignalProxy.h"
+#include <set>
+
+namespace extension {
+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;
+
+    virtual ~LoadBodyProxy();
+
+    static common::PlatformResult create(const std::string& path,
+                                         const std::string& iface,
+                                         LoadBodyProxyPtr* load_body_proxy);
+    //Passed callback will be owned by this proxy
+    void addCallback(MessageBodyCallbackData* callbackOwned);
+    void removeCallback(MessageBodyCallbackData* callback);
+
+protected:
+    LoadBodyProxy(const std::string& path,
+            const std::string& iface);
+    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 extension
+
+#endif // __TIZEN_DBUS_LOAD_BODY_PROXY_H__
diff --git a/webWidgetTCT_device/src/messaging/DBus/MessageProxy.cpp b/webWidgetTCT_device/src/messaging/DBus/MessageProxy.cpp
new file mode 100755 (executable)
index 0000000..536435d
--- /dev/null
@@ -0,0 +1,310 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES 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 "common/GDBus/connection.h"
+#include "common/logger.h"
+#include "../message.h"
+#include "../message_email.h"
+#include "../message_conversation.h"
+//#include <MessageFolder.h>
+#include "../change_listener_container.h"
+#include "../email_manager.h"
+#include "messaging/DBus/DBusTypes.h"
+
+namespace extension {
+namespace messaging {
+namespace DBus {
+
+using namespace common;
+
+MessageProxy::MessageProxy():
+        common::dbus::Proxy(kDBusPathEmailStorageChange,
+                     kDBusIfaceEmailStorageChange,
+                     kDBusNameSignalEmail,
+                     kDBusPathEmailStorageChange,
+                     kDBusIfaceEmailStorageChange)
+{
+}
+
+MessageProxy::~MessageProxy()
+{
+}
+
+PlatformResult MessageProxy::create(MessageProxyPtr* message_proxy) {
+    message_proxy->reset(new MessageProxy());
+    if ((*message_proxy)->isNotProxyGot()) {
+        LoggerE("Could not get proxy");
+        message_proxy->reset();
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Could not get proxy");
+    } else {
+        return PlatformResult(ErrorCode::NO_ERROR);
+    }
+}
+
+void MessageProxy::signalCallback(GDBusConnection *connection,
+            const gchar *sender_name,
+            const gchar *object_path,
+            const gchar *interface_name,
+            const gchar *signal_name,
+            GVariant *parameters)
+{
+    LoggerD("Enter");
+    int status, account_id, object_id, thread_id;
+    char* name;
+    g_variant_get(parameters, "(iiisi)",
+            &status,
+            &account_id,
+            &object_id,
+            &name,
+            &thread_id);
+    LoggerD("status: %d", status);
+    LoggerD("account_id: %d", account_id);
+    LoggerD("object_id: %d", object_id);
+    LoggerD("name: %s", name);
+    LoggerD("thread_id: %d", thread_id);
+
+    PlatformResult ret(ErrorCode::NO_ERROR);
+    switch (status) {
+      case NOTI_MAIL_ADD:
+      case NOTI_MAIL_UPDATE:
+        ret = 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:
+        ret = handleMailboxEvent(account_id, object_id, status);
+        break;
+      default:
+        LoggerD("Unrecognized status: %d", status);
+    }
+    if (ret.IsError()){
+        LoggerE("%d (%s)", ret.error_code(), (ret.message()).c_str());
+    }
+    g_free(name);
+}
+
+PlatformResult MessageProxy::handleEmailEvent(int account_id, int mail_id, int thread_id, int event)
+{
+    LoggerD("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);
+
+            LoggerE("Failed to get mail data during setting conversation id in MessageProxy.");
+            //TODO maybe error should be ignored
+            return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                                  "Failed to get mail data during setting"
+                                  " conversation id in MessageProxy.");
+        }
+
+        thread_id = mail_data->thread_id;
+
+        if(EMAIL_ERROR_NONE != email_free_mail_data(&mail_data,1)) {
+            LoggerE("Failed to free mail data memory");
+        }
+    }
+
+    email_mail_data_t* mail_data = EmailManager::getInstance().loadMessage(mail_id);
+    if (mail_data == NULL) {
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to load email");
+    }
+    std::shared_ptr<Message> msg;
+    PlatformResult ret = Message::convertPlatformEmailToObject(*mail_data, &msg);
+    if (ret.IsError()) return ret;
+    ConversationPtr conv;
+    ret = MessageConversation::convertEmailConversationToObject(
+        thread_id, &conv);
+    if (ret.IsError()) return ret;
+
+    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) {
+                LoggerD("This thread is new, triggering conversationAdded");
+                ChangeListenerContainer::getInstance().callConversationAdded(eventConv);
+            } else {
+                LoggerD("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:
+            LoggerW("Unknown event type: %d", event);
+            break;
+
+    }
+    delete eventMsg;
+    delete eventConv;
+
+    EmailManager::getInstance().freeMessage(mail_data);
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+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) {
+                LoggerD("Mail delete id: %d", id);
+                ids.push_back(id);
+            }
+        }
+    }
+    return ids;
+}
+
+void MessageProxy::handleEmailRemoveEvent(int account_id, const std::string& idsString)
+{
+    LoggerD("Enter");
+    std::vector<int> ids = getMailIds(idsString);
+    if (ids.empty()) {
+        LoggerD("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)
+{
+    LoggerD("Enter");
+    std::vector<int> ids = getMailIds(idsString);
+    if (ids.empty()) {
+        LoggerD("Mail id list is empty.");
+        return;
+    }
+    EmailManager::getInstance().removeStatusCallback(ids, status);
+}
+
+void MessageProxy::handleThreadRemoveEvent(int account_id, int thread_id)
+{
+    LoggerD("Enter");
+    //event is called after thread is removed, so we just set thread id and type
+    ConversationPtr conv = std::make_shared<MessageConversation>();
+    conv->setConversationId(thread_id);
+    conv->setType(MessageType::EMAIL);
+
+    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;
+}
+
+PlatformResult MessageProxy::handleMailboxEvent(int account_id, int mailbox_id, int event)
+{
+    LoggerD("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)) {
+            LoggerE("Mailbox not retrieved");
+            delete eventFolder;
+            return PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to load mailbox");
+        }
+        folder.reset(new MessageFolder(*mail_box));
+        if (EMAIL_ERROR_NONE != email_free_mailbox(&mail_box, 1)) {
+            LoggerD("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:
+            LoggerW("Unknown event type: %d", event);
+    }
+    delete eventFolder;
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+} //namespace DBus
+} //namespace messaging
+} //namespace extension
diff --git a/webWidgetTCT_device/src/messaging/DBus/MessageProxy.h b/webWidgetTCT_device/src/messaging/DBus/MessageProxy.h
new file mode 100755 (executable)
index 0000000..04a8968
--- /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_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 <sstream>
+#include <email-types.h>
+#include "common/GDBus/proxy.h"
+#include "common/platform_result.h"
+
+namespace extension {
+namespace messaging {
+namespace DBus {
+
+class MessageProxy;
+typedef std::shared_ptr<MessageProxy> MessageProxyPtr;
+
+class MessageProxy: public common::dbus::Proxy {
+public:
+    virtual ~MessageProxy();
+    static common::PlatformResult create(MessageProxyPtr* message_proxy);
+protected:
+    MessageProxy();
+    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
+     */
+    common::PlatformResult 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);
+    common::PlatformResult handleMailboxEvent(int account_id, int mailbox_id, int event);
+};
+
+} //namespace DBus
+} //namespace messaging
+} //namespace extension
+
+#endif /* __TIZEN_MESSAGE_PROXY_H */
+
diff --git a/webWidgetTCT_device/src/messaging/DBus/SendProxy.cpp b/webWidgetTCT_device/src/messaging/DBus/SendProxy.cpp
new file mode 100755 (executable)
index 0000000..7e567a9
--- /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 "SendProxy.h"
+
+#include "common/logger.h"
+
+#include <email-types.h>
+#include "../email_manager.h"
+#include "messaging/DBus/DBusTypes.h"
+
+namespace extension {
+namespace messaging {
+namespace DBus {
+
+using namespace common;
+
+SendProxy::SendProxy():
+        EmailSignalProxy(kDBusPathNetworkStatus,
+            kDBusIfaceNetworkStatus)
+{
+}
+
+SendProxy::~SendProxy()
+{
+}
+
+PlatformResult SendProxy::create(SendProxyPtr* send_proxy) {
+    send_proxy->reset(new SendProxy());
+    if ((*send_proxy)->isNotProxyGot()) {
+        LoggerE("Could not get send proxy");
+        send_proxy->reset();
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Could not get send proxy");
+    } else {
+        return PlatformResult(ErrorCode::NO_ERROR);
+    }
+}
+
+void SendProxy::handleEmailSignal(const int status,
+            const int account_id,
+            const std::string& source,
+            const int mail_id,
+            const int error_code)
+{
+    LoggerD("Enter");
+    switch (status) {
+        case NOTI_SEND_FINISH:
+        case NOTI_SEND_FAIL:
+            LoggerD("Recognized status for email send");
+            LoggerD("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:
+            LoggerD("Unrecognized status %d, ignoring", status);
+    }
+}
+
+
+} //DBus
+} //messaging
+} //extension
diff --git a/webWidgetTCT_device/src/messaging/DBus/SendProxy.h b/webWidgetTCT_device/src/messaging/DBus/SendProxy.h
new file mode 100755 (executable)
index 0000000..ef7d5ef
--- /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_SEND_PROXY_H
+#define __TIZEN_SEND_PROXY_H
+
+#include "common/platform_result.h"
+#include "EmailSignalProxy.h"
+
+namespace extension {
+namespace messaging {
+namespace DBus {
+
+class SendProxy;
+typedef std::shared_ptr<SendProxy> SendProxyPtr;
+
+class SendProxy: public EmailSignalProxy {
+public:
+    virtual ~SendProxy();
+    static common::PlatformResult create(SendProxyPtr* send_proxy);
+protected:
+    SendProxy();
+    virtual void handleEmailSignal(const int status,
+            const int account_id,
+            const std::string& source,
+            const int op_handle,
+            const int error_code);
+};
+
+} //DBus
+} //messaging
+} //extension
+
+#endif /* __TIZEN_SEND_PROXY_H */
+
diff --git a/webWidgetTCT_device/src/messaging/DBus/SyncProxy.cpp b/webWidgetTCT_device/src/messaging/DBus/SyncProxy.cpp
new file mode 100755 (executable)
index 0000000..b04556e
--- /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.
+//
+
+/**
+ * @file        SyncProxy.cpp
+ */
+
+#include "SyncProxy.h"
+#include "common/logger.h"
+#include "common/platform_result.h"
+#include <cstring>
+#include <email-types.h>
+#include "../message_service.h"
+
+namespace extension {
+namespace messaging {
+namespace DBus {
+
+using namespace common;
+
+SyncProxy::SyncProxy(const std::string& path,
+        const std::string& iface) :
+        EmailSignalProxy(path, iface)
+{
+
+}
+
+SyncProxy::~SyncProxy()
+{
+
+}
+
+PlatformResult SyncProxy::create(const std::string& path,
+                                 const std::string& iface,
+                                 SyncProxyPtr* sync_proxy) {
+    sync_proxy->reset(new SyncProxy(path, iface));
+    if ((*sync_proxy)->isNotProxyGot()) {
+        LoggerE("Could not get sync proxy");
+        sync_proxy->reset();
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Could not get sync proxy");
+    } else {
+        return PlatformResult(ErrorCode::NO_ERROR);
+    }
+}
+
+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 = nullptr;
+  const auto it = m_callback_map.find(op_id);
+
+  if (it != m_callback_map.end()) {
+    cb = it->second;
+  } else {
+    LoggerE("Could not find callback");
+  }
+
+  return cb;
+}
+
+void SyncProxy::removeCallback(long op_id) {
+  auto it = m_callback_map.find(op_id);
+  if (it != m_callback_map.end()) {
+    delete it->second;
+    m_callback_map.erase(it);
+  } else {
+    LoggerE("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;
+    }
+
+    LoggerD("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) {
+        LoggerD("Sync started...");
+        // There is nothing more to do so we can return now.
+        return;
+    }
+
+    SyncCallbackData* callback = NULL;
+    CallbackMap::iterator callback_it;
+
+    PlatformResult ret = findSyncCallbackByOpHandle(op_handle, &callback_it);
+    if (ret.IsError()) {
+        LoggerE("Failed to find callback by handle - (%s)", ret.message().c_str());
+        return;
+    }
+
+    callback = dynamic_cast<SyncCallbackData*>(callback_it->second);
+    if (!callback) {
+        LoggerE("Callback is null");
+        return;
+    }
+
+    std::shared_ptr<picojson::value> response = callback->getJson();
+    picojson::object& obj = response->get<picojson::object>();
+    switch (status) {
+        case NOTI_DOWNLOAD_FINISH:
+            LoggerD("Sync finished!");
+            obj[JSON_ACTION] = picojson::value(JSON_CALLBACK_SUCCCESS);
+            callback->getQueue().resolve(
+                    obj.at(JSON_CALLBACK_ID).get<double>(),
+                    response->serialize()
+            );
+            break;
+
+        case NOTI_DOWNLOAD_FAIL:
+        {
+            LoggerD("Sync failed!");
+            callback->setError("UnknownError", "Sync failed!");
+            callback->getQueue().resolve(
+                    obj.at(JSON_CALLBACK_ID).get<double>(),
+                    response->serialize()
+            );
+        }
+        break;
+
+    }
+
+    if (callback) {
+        delete callback;
+        m_callback_map.erase(callback_it);
+    }
+}
+
+PlatformResult SyncProxy::findSyncCallbackByOpHandle(const int op_handle,
+                                                     SyncProxy::CallbackMap::iterator* it)
+{
+    *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 PlatformResult(ErrorCode::NO_ERROR);
+        }
+    }
+    // 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:
+    LoggerW("Could not find callback with op_handle: %d", op_handle);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Could not find callback");
+}
+
+} //namespace DBus
+} //namespace Messaging
+} //namespace DeviceAPI
diff --git a/webWidgetTCT_device/src/messaging/DBus/SyncProxy.h b/webWidgetTCT_device/src/messaging/DBus/SyncProxy.h
new file mode 100755 (executable)
index 0000000..bd7f379
--- /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.
+//
+
+/**
+ * @file        SyncProxy.h
+ */
+
+#ifndef __TIZEN_DBUS_SYNC_PROXY_H__
+#define __TIZEN_DBUS_SYNC_PROXY_H__
+
+#include "EmailSignalProxy.h"
+#include "common/platform_result.h"
+
+namespace extension {
+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;
+
+    virtual ~SyncProxy();
+
+    static common::PlatformResult create(const std::string& path,
+                                         const std::string& iface,
+                                         SyncProxyPtr* sync_proxy);
+    //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:
+    SyncProxy(const std::string& path,
+            const std::string& iface);
+
+    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);
+     */
+    common::PlatformResult findSyncCallbackByOpHandle(const int op_handle,
+                                                      CallbackMap::iterator* it);
+    CallbackMap m_callback_map;
+};
+
+} //namespace DBus
+} //namespace Messaging
+} //namespace DeviceAPI
+
+#endif // __TIZEN_DBUS_SYNC_PROXY_H__
diff --git a/webWidgetTCT_device/src/messaging/MsgCommon/AbstractFilter.cpp b/webWidgetTCT_device/src/messaging/MsgCommon/AbstractFilter.cpp
new file mode 100755 (executable)
index 0000000..36a05f2
--- /dev/null
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2015 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 "AbstractFilter.h"
+//#include "JSAttributeFilter.h"
+//#include "JSAttributeRangeFilter.h"
+//#include "JSCompositeFilter.h"
+#include "common/platform_exception.h"
+#include "common/logger.h"
+//#include <JSUtil.h>
+#include <algorithm>
+
+namespace extension {
+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;
+}
+
+bool AbstractFilter::isMatching(const FilterableObject* const tested_object) const
+{
+    LoggerE("Calling isMatching on AbstractFilter!");
+    return false;
+}
+
+AttributeFilterPtr castToAttributeFilter(AbstractFilterPtr from)
+{
+    if(ATTRIBUTE_FILTER != from->getFilterType()) {
+        LoggerE("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()) {
+        LoggerE("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()) {
+        LoggerE("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: {
+            LoggerE("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()) {
+        struct tm ftime = *initial_value->toDateTm();
+        from_time = mktime(&ftime);
+        initial_is_valid_time_value = true;
+    }
+    if (!initial_is_valid_time_value) {
+        LoggerE("initialValue is not Time!");
+        return false;
+    }
+
+    bool end_is_valid_time_value = false;
+    if (end_value && !end_value->isNullOrUndefined()) {
+        struct tm ttime =  *end_value->toDateTm();
+        to_time = mktime(&ttime);
+        end_is_valid_time_value = true;
+    }
+    if (end_is_valid_time_value) {
+        LoggerE("endValue is not Time!");
+        return false;
+    }
+
+    bool is_in_range = FilterUtils::isBetweenTimeRange(time_stamp, from_time, to_time);
+
+    LoggerD("%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/webWidgetTCT_device/src/messaging/MsgCommon/AbstractFilter.h b/webWidgetTCT_device/src/messaging/MsgCommon/AbstractFilter.h
new file mode 100755 (executable)
index 0000000..0ac41e4
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2015 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_TIZEN_ABSTRACT_FILTER_H__
+#define __TIZEN_TIZEN_ABSTRACT_FILTER_H__
+
+#include <memory>
+#include <vector>
+#include <sstream>
+//#include <JSArray.h>
+
+#include "Any.h"
+
+namespace extension {
+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/webWidgetTCT_device/src/messaging/MsgCommon/Any.cpp b/webWidgetTCT_device/src/messaging/MsgCommon/Any.cpp
new file mode 100755 (executable)
index 0000000..f70392d
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2015 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 "Any.h"
+
+#include <stdexcept>
+//#include <JSUtil.h>
+
+namespace extension {
+namespace tizen {
+
+Any::Any(picojson::value 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;
+//}
+
+picojson::value Any::getValue() const
+{
+    return m_value;
+}
+
+void Any::setValue(picojson::value value)
+{
+//    JSValueUnprotect(m_context, m_value);
+//    m_context = context;
+    m_value = value;
+//    JSValueProtect(m_context, m_value);
+}
+
+bool Any::isNullOrUndefined() const
+{
+    //TODO is it check for undefined?
+    return m_value.is<picojson::null>();
+}
+
+bool Any::toBool() const
+{
+    if (m_value.is<bool>()) {
+        return m_value.get<bool>();
+    } else {
+        return ("true" == this->toString());
+    }
+}
+
+long Any::toLong() const
+{
+    if (m_value.is<double>()) {
+        return static_cast<long>(m_value.get<double>());
+    } else if (m_value.is<std::string>()) {
+        try {
+            return std::stol(m_value.get<std::string>());
+        } catch (...) {
+            return static_cast<long>(0);
+        }
+    } else {
+        return static_cast<long>(0);
+    }
+}
+
+unsigned long Any::toULong() const
+{
+    if (m_value.is<double>()) {
+        return static_cast<unsigned long>(m_value.get<double>());
+    } else if (m_value.is<std::string>()) {
+        try {
+            return std::stoul(m_value.get<std::string>());
+        } catch (...) {
+            return static_cast<unsigned long>(0);
+        }
+    } else {
+        return static_cast<unsigned long>(0);
+    }
+}
+
+long long Any::toLongLong() const
+{
+    if (m_value.is<double>()) {
+        return static_cast<long long>(m_value.get<double>());
+    } else if (m_value.is<std::string>()) {
+        try {
+            return std::stoll(m_value.get<std::string>());
+        } catch (...) {
+            return static_cast<long long>(0);
+        }
+    } else {
+        return static_cast<long long>(0);
+    }
+}
+
+unsigned long long Any::toULongLong() const
+{
+    if (m_value.is<double>()) {
+        return static_cast<unsigned long long>(m_value.get<double>());
+    } else if (m_value.is<std::string>()) {
+        try {
+            return std::stoull(m_value.get<std::string>());
+        } catch (...) {
+            return static_cast<unsigned long long>(0);
+        }
+    } else {
+        return static_cast<unsigned long long>(0);
+    }
+}
+
+double Any::toDouble() const
+{
+    if (m_value.is<double>()) {
+        return m_value.get<double>();
+    } else if (m_value.is<std::string>()) {
+        try {
+            return std::stod(m_value.get<std::string>());
+        } catch (...) {
+            return 0.0;
+        }
+    } else {
+        return 0.0;
+    }
+}
+
+std::string Any::toString() const
+{
+    if (m_value.is<std::string>()) {
+        return m_value.get<std::string>();
+    } else {
+        return "";
+    }
+}
+
+std::tm* Any::toDateTm() const
+{
+    static std::tm t;
+    memset(&t, 0, sizeof(std::tm));
+    strptime(toString().c_str(), "%Y-%m-%dT%H:%M:%S.%zZ", &t);
+    return &t;
+}
+
+std::time_t Any::toTimeT() const
+{
+    std::time_t current_time;
+    std::time(&current_time);
+    struct tm timeinfo = {0};
+    long int gmtoff = 0;
+    tzset();
+    if (nullptr != localtime_r(&current_time, &timeinfo)) {
+      gmtoff = timeinfo.tm_gmtoff;
+
+      if (timeinfo.tm_isdst) {
+        // if dst is set then 1 hour should be subtracted.
+        // 1 hour = 60 second * 60 minutes = 3600 seconds
+        gmtoff -= 3600;
+      }
+    }
+    return mktime(toDateTm()) + gmtoff;
+}
+
+} // Tizen
+} // Device_API
diff --git a/webWidgetTCT_device/src/messaging/MsgCommon/Any.h b/webWidgetTCT_device/src/messaging/MsgCommon/Any.h
new file mode 100755 (executable)
index 0000000..009ae78
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2015 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_TIZEN_ANY_H__
+#define __TIZEN_TIZEN_ANY_H__
+
+#include <memory>
+//#include <JavaScriptCore/JavaScript.h>
+#include <string>
+#include <ctime>
+#include "common/picojson.h"
+
+namespace extension {
+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(picojson::value value);
+    virtual ~Any();
+
+//    JSContextRef getContext() const;
+    picojson::value getValue() const;
+    void setValue(picojson::value 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;
+    picojson::value m_value;
+};
+
+} // Tizen
+} // DeviceAPI
+
+#endif // __TIZEN_TIZEN_ANY_H__
diff --git a/webWidgetTCT_device/src/messaging/MsgCommon/AttributeFilter.cpp b/webWidgetTCT_device/src/messaging/MsgCommon/AttributeFilter.cpp
new file mode 100755 (executable)
index 0000000..e3207f8
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2015 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 "AttributeFilter.h"
+#include "common/platform_exception.h"
+#include "common/logger.h"
+
+namespace extension {
+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) {
+        LoggerE("Invalid object: NULL!");
+        return false;
+    }
+
+    return filtered_object->isMatchingAttribute(m_attribute_name, m_match_flag,
+            m_match_value);
+}
+
+} // Tizen
+} // DeviceAPI
diff --git a/webWidgetTCT_device/src/messaging/MsgCommon/AttributeFilter.h b/webWidgetTCT_device/src/messaging/MsgCommon/AttributeFilter.h
new file mode 100755 (executable)
index 0000000..b14ccbe
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2015 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_TIZEN_ATTRIBUTE_FILTER_H__
+#define __TIZEN_TIZEN_ATTRIBUTE_FILTER_H__
+
+#include "AbstractFilter.h"
+#include "Any.h"
+#include <string>
+
+namespace extension {
+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/webWidgetTCT_device/src/messaging/MsgCommon/AttributeRangeFilter.cpp b/webWidgetTCT_device/src/messaging/MsgCommon/AttributeRangeFilter.cpp
new file mode 100755 (executable)
index 0000000..4c30628
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2015 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 "AttributeRangeFilter.h"
+#include "common/platform_exception.h"
+#include "common/logger.h"
+
+namespace extension {
+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) {
+        LoggerE("Invalid object: NULL!");
+        return false;
+    }
+
+    return filtered_object->isMatchingAttributeRange(m_attribute_name, m_initial_value,
+            m_end_value);
+}
+
+} // Tizen
+} // DeviceAPI
diff --git a/webWidgetTCT_device/src/messaging/MsgCommon/AttributeRangeFilter.h b/webWidgetTCT_device/src/messaging/MsgCommon/AttributeRangeFilter.h
new file mode 100755 (executable)
index 0000000..4c0d8e1
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2015 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_TIZEN_ATTRIBUTE_RANGE_FILTER_H__
+#define __TIZEN_TIZEN_ATTRIBUTE_RANGE_FILTER_H__
+
+#include "AbstractFilter.h"
+#include "Any.h"
+#include <string>
+
+namespace extension {
+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/webWidgetTCT_device/src/messaging/MsgCommon/CompositeFilter.cpp b/webWidgetTCT_device/src/messaging/MsgCommon/CompositeFilter.cpp
new file mode 100755 (executable)
index 0000000..ea68e7e
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2015 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 "CompositeFilter.h"
+#include "common/platform_exception.h"
+//#include <GlobalContextManager.h>
+#include "common/logger.h"
+
+namespace extension {
+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::addFilter(const AbstractFilterPtr& filter)
+{
+    m_filters.push_back(filter);
+}
+
+bool CompositeFilter::isMatching(const FilterableObject* const filtered_object) const
+{
+    if (!filtered_object) {
+        LoggerE("Invalid object: NULL!");
+        return false;
+    }
+
+    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/webWidgetTCT_device/src/messaging/MsgCommon/CompositeFilter.h b/webWidgetTCT_device/src/messaging/MsgCommon/CompositeFilter.h
new file mode 100755 (executable)
index 0000000..e6d2c32
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2015 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_TIZEN_COMPOSITE_FILTER_H__
+#define __TIZEN_TIZEN_COMPOSITE_FILTER_H__
+
+#include "AbstractFilter.h"
+
+namespace extension {
+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 addFilter(const AbstractFilterPtr& filter);
+
+    virtual bool isMatching(const FilterableObject* const filtered_object) const;
+private:
+    CompositeFilterType m_type;
+    AbstractFilterPtrVector m_filters;
+};
+
+} //Tizen
+} //DeviceAPI
+
+#endif // __TIZEN_TIZEN_COMPOSITE_FILTER_H__
diff --git a/webWidgetTCT_device/src/messaging/MsgCommon/FilterIterator.cpp b/webWidgetTCT_device/src/messaging/MsgCommon/FilterIterator.cpp
new file mode 100755 (executable)
index 0000000..1ec3427
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2015 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 "FilterIterator.h"
+#include "common/platform_exception.h"
+#include "common/logger.h"
+
+using namespace common;
+
+namespace extension {
+namespace tizen {
+
+FilterIterator::FilterIterator(AbstractFilterPtr filter) :
+        m_root_filter(filter),
+        m_current_state(FIS_NOT_VALID)
+{
+    if (!m_root_filter) {
+        LoggerE("Trying to create FilterIterator with NULL filter");
+        m_root_filter = AbstractFilterPtr(new AbstractFilter());
+    }
+
+    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 (int)(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: {
+            LoggerE("Reached AbstractFilter!!");
+            m_current_state = FIS_NOT_VALID;
+        } break;
+    }
+
+    m_current_filter = next;
+}
+
+} // Tizen
+} // DeviceAPI
diff --git a/webWidgetTCT_device/src/messaging/MsgCommon/FilterIterator.h b/webWidgetTCT_device/src/messaging/MsgCommon/FilterIterator.h
new file mode 100755 (executable)
index 0000000..a3d92d0
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2015 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_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 extension {
+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)
+        {
+        }
+
+        CompositeFilterPtr filter;
+        int cur_sub_filter_index;
+    };
+
+    std::stack<CompositeIterState> m_composite_stack;
+};
+
+} // Tizen
+} // DeviceAPI
+
+#endif // __TIZEN_TIZEN_FILTER_ITERATOR_H__
diff --git a/webWidgetTCT_device/src/messaging/MsgCommon/SortMode.cpp b/webWidgetTCT_device/src/messaging/MsgCommon/SortMode.cpp
new file mode 100755 (executable)
index 0000000..6c2e36d
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2015 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 "SortMode.h"
+
+#include "common/logger.h"
+
+namespace extension {
+namespace tizen {
+
+SortMode::SortMode(const std::string &attribute_name, SortModeOrder order) :
+        m_attribute_name(attribute_name),
+        m_order(order)
+{
+    LoggerD("SortMode attributeName: %s, SortMode order: %s",
+            attribute_name.c_str(), (order == SortModeOrder::DESC) ? "DESC" : "ASC");
+}
+
+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/webWidgetTCT_device/src/messaging/MsgCommon/SortMode.h b/webWidgetTCT_device/src/messaging/MsgCommon/SortMode.h
new file mode 100755 (executable)
index 0000000..d9491b1
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2015 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_TIZEN_SORT_MODE_H__
+#define __TIZEN_TIZEN_SORT_MODE_H__
+
+#include <memory>
+#include <string>
+
+namespace extension {
+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/webWidgetTCT_device/src/messaging/change_listener_container.cc b/webWidgetTCT_device/src/messaging/change_listener_container.cc
new file mode 100755 (executable)
index 0000000..6f201c7
--- /dev/null
@@ -0,0 +1,456 @@
+/*
+ * Copyright (c) 2015 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 "change_listener_container.h"
+
+#include "email_manager.h"
+//#include "ShortMsgManager.h"
+
+namespace extension {
+namespace messaging {
+
+ChangeListenerContainer& ChangeListenerContainer::getInstance()
+{
+    LoggerD("Entered");
+    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)
+{
+    LoggerD("Entered");
+    // call getNextId() function to properly initialize static mutex inside
+    getNextId();
+}
+
+// --- Listeners registration functions ---
+long ChangeListenerContainer::addMessageChangeListener(
+        std::shared_ptr<MessagesChangeCallback> callback)
+{
+    LoggerD("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));
+        LoggerD("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));
+        LoggerD("Added callback for Email, watchId: %d", new_id);
+        return new_id;
+    }
+    LoggerE("Listener with invalid MessageService type - failed to register");
+    return -1;
+}
+
+long ChangeListenerContainer::addConversationChangeListener(
+        std::shared_ptr<ConversationsChangeCallback> callback)
+{
+    LoggerD("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));
+        LoggerD("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));
+        LoggerD("Added callback for Email, watchId: %d", new_id);
+        return new_id;
+    }
+    LoggerE("Listener with invalid MessageService type - failed to register");
+    return -1;
+}
+
+long ChangeListenerContainer::addFolderChangeListener(
+        std::shared_ptr<FoldersChangeCallback> callback)
+{
+    LoggerD("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));
+        LoggerD("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));
+        LoggerD("Added callback for Email, watchId: %d", new_id);
+        return new_id;
+    }
+    LoggerE("Listener with invalid MessageService type - failed to register");
+    return -1;
+}
+
+// --- listeners removal ---
+void ChangeListenerContainer::removeChangeListener(long id)
+{
+    LoggerD("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);
+    LoggerD("Locks done");
+    if(id<0 || id > m_current_id) {
+        LoggerE("Invalid id %d given.", id);
+        return;
+    }
+    if (removeCallbackIfExists<MessagesChangeCallback>(
+            m_short_message_callbacks,id)) {
+        LoggerD("ShortMessage message listener with id: %d removed", id);
+    }
+    else if (removeCallbackIfExists<ConversationsChangeCallback>(
+            m_short_conversation_callbacks, id)) {
+        LoggerD("ShortMessage conversation listener with id: %d removed", id);
+    }
+    else if (removeCallbackIfExists<FoldersChangeCallback>(
+            m_short_folder_callbacks, id)) {
+        LoggerD("ShortMessage folder listener with id: %d removed", id);
+    }
+    else if (removeCallbackIfExists<MessagesChangeCallback>(
+            m_email_message_callbacks, id)) {
+        LoggerD("Email message listener with id: %d removed", id);
+    }
+    else if (removeCallbackIfExists<ConversationsChangeCallback>(
+            m_email_conversation_callbacks, id)) {
+        LoggerD("Email conversation listener with id: %d removed", id);
+    }
+    else if (removeCallbackIfExists<FoldersChangeCallback>(
+            m_email_folder_callbacks,id)) {
+        LoggerD("Email folder listener with id: %d removed", id);
+    }
+    else {
+        LoggerW("WatchId %d not found", id);
+    }
+}
+
+// --- Callback invoking functions ---
+// -- for message --
+void ChangeListenerContainer::callMessageAdded(EventMessages* event)
+{
+    LoggerD("Entered");
+
+    if(MessageType(SMS) == event->service_type ||
+            MessageType(MMS) == event->service_type) {
+        LoggerD("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) {
+        LoggerD("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 {
+        LoggerW("Invalid event type (%d) - no callback called.", event->service_type);
+    }
+}
+
+void ChangeListenerContainer::callMessageUpdated(EventMessages* event)
+{
+    LoggerD("Entered");
+
+    if(MessageType(SMS) == event->service_type ||
+            MessageType(MMS) == event->service_type) {
+        LoggerD("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) {
+        LoggerD("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 {
+        LoggerW("Invalid event type (%d) - no callback called.", event->service_type);
+    }
+}
+
+void ChangeListenerContainer::callMessageRemoved(EventMessages* event)
+{
+    LoggerD("Entered");
+
+    if(MessageType(SMS) == event->service_type ||
+            MessageType(MMS) == event->service_type) {
+        LoggerD("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) {
+        LoggerD("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 {
+        LoggerW("Invalid event type (%d) - no callback called.", event->service_type);
+    }
+}
+
+// -- for conversation --
+void ChangeListenerContainer::callConversationAdded(EventConversations* event)
+{
+    LoggerD("Entered");
+
+    if(MessageType(SMS) == event->service_type ||
+            MessageType(MMS) == event->service_type) {
+        LoggerD("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) {
+        LoggerD("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 {
+        LoggerW("Invalid event type (%d) - no callback called.", event->service_type);
+    }
+}
+
+void ChangeListenerContainer::callConversationUpdated(EventConversations* event)
+{
+    LoggerD("Entered");
+
+    if(MessageType(SMS) == event->service_type ||
+            MessageType(MMS) == event->service_type) {
+        LoggerD("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) {
+        LoggerD("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 {
+        LoggerW("Invalid event type (%d) - no callback called.", event->service_type);
+    }
+}
+
+void ChangeListenerContainer::callConversationRemoved(EventConversations* event)
+{
+    LoggerD("Entered");
+
+    if(MessageType(SMS) == event->service_type ||
+            MessageType(MMS) == event->service_type) {
+        LoggerD("Calling conversationremoved for ShortConversation");
+        CCLmap callbacksCopy;
+        {
+            std::lock_guard<std::mutex> shortlock(m_short_lock);
+            LoggerD("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) {
+        LoggerD("Calling conversationremoved for Email");
+        CCLmap callbacksCopy;
+        {
+            std::lock_guard<std::mutex> maillock(m_email_lock);
+            LoggerD("m_email_conversation_callbacks.size() = %d",
+                m_email_conversation_callbacks.size());
+
+            callbacksCopy = m_email_conversation_callbacks;
+        }
+        callRemoved<ConversationsChangeCallback, EventConversations>(
+                callbacksCopy, event);
+    }
+    else {
+        LoggerW("Invalid event type (%d) - no callback called.", event->service_type);
+    }
+}
+
+// -- for folder --
+void ChangeListenerContainer::callFolderAdded(EventFolders* event)
+{
+    LoggerD("Entered");
+
+    if(MessageType(SMS) == event->service_type ||
+            MessageType(MMS) == event->service_type) {
+        LoggerD("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) {
+        LoggerD("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 {
+        LoggerW("Invalid event type (%d) - no callback called.", event->service_type);
+    }
+}
+
+
+void ChangeListenerContainer::callFolderUpdated(EventFolders* event)
+{
+    LoggerD("Entered");
+
+    if(MessageType(SMS) == event->service_type ||
+            MessageType(MMS) == event->service_type) {
+        LoggerD("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) {
+        LoggerD("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 {
+        LoggerW("Invalid event type (%d) - no callback called.", event->service_type);
+    }
+}
+
+void ChangeListenerContainer::callFolderRemoved(EventFolders* event)
+{
+    LoggerD("Entered");
+
+    if(MessageType(SMS) == event->service_type ||
+            MessageType(MMS) == event->service_type) {
+        LoggerD("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) {
+        LoggerD("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 {
+        LoggerW("Invalid event type (%d) - no callback called.", event->service_type);
+    }
+}
+
+int ChangeListenerContainer::getNextId() {
+    LoggerD("Entered");
+    // 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++;
+}
+
+} //namespace messaging
+} //namespace extension
diff --git a/webWidgetTCT_device/src/messaging/change_listener_container.h b/webWidgetTCT_device/src/messaging/change_listener_container.h
new file mode 100755 (executable)
index 0000000..4a76e4b
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+ * Copyright (c) 2015 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_CHANGE_LISTENER_CONTAINER_H__
+#define __TIZEN_CHANGE_LISTENER_CONTAINER_H__
+
+#include <memory>
+#include <mutex>
+#include <vector>
+#include <map>
+
+#include "common/logger.h"
+#include "common/platform_exception.h"
+
+#include "message.h"
+
+//#include "MessageConversation.h"
+//#include "MessageFolder.h"
+
+#include "messaging_util.h"
+#include "messages_change_callback.h"
+#include "conversations_change_callback.h"
+#include "folders_change_callback.h"
+
+namespace extension {
+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(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(
+                std::map<long,std::shared_ptr<T>>& collection, long id ) {
+            LoggerD("Entered");
+
+            auto itr = collection.find(id);
+            if ( itr != collection.end()) {
+                itr->second->setActive(false);
+                collection.erase(id);
+                return true;
+            }
+            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) {
+                        LoggerD("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::PlatformException &err) {
+                LoggerE("callAdded failed, %s: %s", err.name().c_str(),
+                        err.message().c_str());
+            }
+            catch (...) {
+                LoggerE("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) {
+                        LoggerD("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::PlatformException &err) {
+                LoggerE("callUpdated failed, %s: %s", err.name().c_str(),
+                        err.message().c_str());
+            }
+            catch (...) {
+                LoggerE("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) {
+                        LoggerD("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::PlatformException &err) {
+                LoggerE("callRemoved failed, %s: %s", err.name().c_str(),
+                        err.message().c_str());
+            }
+            catch (...) {
+                LoggerE("callRemoved failed");
+            }
+        }
+};
+
+
+} //namespace messaging
+} //namespace extension
+
+#endif // __TIZEN_CHANGE_LISTENER_CONTAINER_H__
diff --git a/webWidgetTCT_device/src/messaging/conversation_callback_data.cc b/webWidgetTCT_device/src/messaging/conversation_callback_data.cc
new file mode 100755 (executable)
index 0000000..8bf1191
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2015 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 "conversation_callback_data.h"
+#include "messaging_util.h"
+
+namespace extension {
+namespace messaging {
+
+ConversationCallbackData::ConversationCallbackData(PostQueue& queue):
+        m_filter(),
+        m_sort(),
+        m_limit(0),
+        m_offset(0),
+        m_is_error(false),
+        m_account_id(0),
+        m_service_type(UNDEFINED),
+        queue_(queue)
+{
+    LoggerD("Entered");
+}
+
+ConversationCallbackData::ConversationCallbackData(long cid, PostQueue& queue, bool keep):
+        m_filter(),
+        m_sort(),
+        m_limit(0),
+        m_offset(0),
+        m_is_error(false),
+        m_account_id(0),
+        m_service_type(UNDEFINED),
+        queue_(queue)
+{
+    LoggerD("Entered");
+    auto json = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+    picojson::object& o = json->get<picojson::object>();
+    o[JSON_CALLBACK_ID] = picojson::value(static_cast<double>(cid));
+    o[JSON_CALLBACK_KEEP] = picojson::value(keep);
+    setJson(json);
+}
+
+ConversationCallbackData::~ConversationCallbackData()
+{
+    LoggerD("Entered");
+}
+
+void ConversationCallbackData::setFilter(AbstractFilterPtr filter)
+{
+    m_filter = filter;
+}
+
+void ConversationCallbackData::setSortMode(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);
+}
+
+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)
+{
+    LoggerD("Entered");
+    // keep only first error in chain
+    if (!m_is_error) {
+        LoggerD("Error has not been set yet");
+        picojson::object& obj = m_json->get<picojson::object>();
+        obj[JSON_ACTION] = picojson::value(JSON_CALLBACK_ERROR);
+        auto objData = picojson::object();
+
+        objData[JSON_ERROR_NAME] = picojson::value(err_name);
+        objData[JSON_ERROR_MESSAGE] = picojson::value(err_message);
+
+        obj[JSON_DATA] = picojson::value(objData);
+
+        m_is_error = true;
+        m_err_name = err_name;
+        m_err_message = err_message;
+    }
+}
+
+void ConversationCallbackData::SetError(const common::PlatformResult& error)
+{
+    LoggerD("Entered");
+  // keep only first error in chain
+  if (!m_is_error) {
+      LoggerD("Error has not been set yet");
+    m_is_error = true;
+    picojson::object& obj = m_json->get<picojson::object>();
+    obj[JSON_ACTION] = picojson::value(JSON_CALLBACK_ERROR);
+    auto obj_data = picojson::object();
+    obj_data[JSON_ERROR_CODE] = picojson::value(static_cast<double>(error.error_code()));
+    obj_data[JSON_ERROR_MESSAGE] = picojson::value(error.message());
+    obj[JSON_DATA] = picojson::value(obj_data);
+  }
+}
+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;
+}
+
+AbstractFilterPtr ConversationCallbackData::getFilter() const
+{
+    return m_filter;
+}
+
+SortModePtr ConversationCallbackData::getSortMode() const
+{
+    return m_sort;
+}
+
+long ConversationCallbackData::getLimit() const
+{
+    return m_limit;
+}
+
+long ConversationCallbackData::getOffset() const
+{
+    return m_offset;
+}
+
+}//messaging
+}//extension
diff --git a/webWidgetTCT_device/src/messaging/conversation_callback_data.h b/webWidgetTCT_device/src/messaging/conversation_callback_data.h
new file mode 100755 (executable)
index 0000000..17cb5df
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2015 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 MESSAGING_CONVERSATION_CALLBACK_DATA_H_
+#define MESSAGING_CONVERSATION_CALLBACK_DATA_H_
+
+#include "common/callback_user_data.h"
+#include <memory>
+#include <string>
+#include <vector>
+#include "MsgCommon/AttributeFilter.h"
+#include "MsgCommon/SortMode.h"
+#include "messaging_util.h"
+
+using namespace extension::tizen;
+
+namespace extension {
+namespace messaging {
+
+class Message;
+class MessageConversation;
+
+class ConversationCallbackData: public common::CallbackUserData {
+public:
+    ConversationCallbackData(PostQueue& queue);
+    ConversationCallbackData(long cid, PostQueue& queue, bool keep = false);
+    virtual ~ConversationCallbackData();
+
+    void setFilter(AbstractFilterPtr filter);
+    void setSortMode(SortModePtr sortMode);
+    void setLimit(long limit);
+    void setOffset(long offset);
+    void addConversation(std::shared_ptr<MessageConversation> msg);
+
+    std::vector<std::shared_ptr<MessageConversation>> getConversations() const;
+
+    void setError(const std::string& err_name,
+            const std::string& err_message);
+    void SetError(const common::PlatformResult& error);
+    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;
+    AbstractFilterPtr getFilter() const;
+    SortModePtr getSortMode() const;
+    long getLimit() const;
+    long getOffset() const;
+
+    PostQueue& getQueue() { return queue_;};
+private:
+    AbstractFilterPtr m_filter;
+    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;
+    PostQueue& queue_;
+};
+
+}//messaging
+}//extension
+
+#endif // MESSAGING_CONVERSATION_CALLBACK_DATA_H_
diff --git a/webWidgetTCT_device/src/messaging/conversations_change_callback.cc b/webWidgetTCT_device/src/messaging/conversations_change_callback.cc
new file mode 100755 (executable)
index 0000000..9e0cc33
--- /dev/null
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2015 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 <JSWebAPIErrorFactory.h>
+//#include <PlatformException.h>
+//#include <JSUtil.h>
+//#include <GlobalContextManager.h>
+
+//#include "MessagingUtil.h"
+//#include "ConversationsChangeCallback.h"
+//#include "JSMessageConversation.h"
+//#include "MessagingUtil.h"
+
+#include "common/logger.h"
+#include "common/platform_exception.h"
+#include "messaging_instance.h"
+#include "messaging_util.h"
+
+#include "conversations_change_callback.h"
+
+namespace extension {
+namespace messaging {
+
+
+const char* CONVERSATIONSADDED = "conversationsadded";
+const char* CONVERSATIONSUPDATED = "conversationsupdated";
+const char* CONVERSATIONSREMOVED = "conversationsremoved";
+
+ConversationsChangeCallback::ConversationsChangeCallback(
+        long cid,
+        int service_id,
+        MessageType service_type,
+        PostQueue& queue) :
+        m_callback_data(cid, queue, true),
+        m_id(service_id),
+        m_msg_type(service_type),
+        m_is_act(true)
+{
+    LoggerD("Entered");
+}
+
+ConversationsChangeCallback::~ConversationsChangeCallback()
+{
+    LoggerD("Entered");
+}
+
+ConversationPtrVector ConversationsChangeCallback::filterConversations(
+        AbstractFilterPtr filter,
+        const ConversationPtrVector& source_conversations)
+{
+    LoggerD("Entered");
+    if (filter) {
+        LoggerD("filter pointer is valid");
+        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);
+            }
+
+            LoggerD("[%d] conversation id:%d", i, conversation->getConversationId());
+            LoggerD("[%d] conversation subject :%s", i, conversation->getSubject().c_str());
+            LoggerD("[%d] matched filter: %s", i, matched ? "YES" : "NO");
+        }
+
+        LoggerD("returning matching %d of %d conversations", filtered_conversations.size(),
+                source_conversations.size());
+
+        return filtered_conversations;
+    }
+    else {
+        LoggerD("filter pointer is not valid");
+        return source_conversations;
+    }
+}
+
+void ConversationsChangeCallback::added(
+        const ConversationPtrVector& conversations)
+{
+    LoggerD("Entered conversations.size()=%d", conversations.size());
+    if (!m_is_act) {
+        return;
+    }
+
+    ConversationPtrVector filtered = filterConversations(m_filter, conversations);
+
+    picojson::array array;
+    auto each = [&array] (std::shared_ptr<MessageConversation> c)->void {
+        array.push_back(MessagingUtil::conversationToJson(c));
+    };
+    for_each(filtered.begin(), filtered.end(), each);
+
+    LoggerD("Calling:%s with:%d added conversations", CONVERSATIONSADDED,
+        filtered.size());
+
+    auto json = m_callback_data.getJson();
+    picojson::object& obj = json->get<picojson::object>();
+    obj[JSON_ACTION] = picojson::value(CONVERSATIONSADDED);
+    obj[JSON_DATA] = picojson::value(array);
+
+    m_callback_data.getQueue().addAndResolve(obj.at(
+                JSON_CALLBACK_ID).get<double>(), PostPriority::MEDIUM, json->serialize());
+}
+
+void ConversationsChangeCallback::updated(
+        const ConversationPtrVector& conversations)
+{
+    LoggerD("Entered conversations.size()=%d", conversations.size());
+    if (!m_is_act) {
+        return;
+    }
+
+    ConversationPtrVector filtered = filterConversations(m_filter, conversations);
+
+    picojson::array array;
+    auto each = [&array] (std::shared_ptr<MessageConversation> c)->void {
+        array.push_back(MessagingUtil::conversationToJson(c));
+    };
+    for_each(filtered.begin(), filtered.end(), each);
+
+    LoggerD("Calling:%s with:%d added conversations", CONVERSATIONSUPDATED,
+        filtered.size());
+
+    auto json = m_callback_data.getJson();
+    picojson::object& obj = json->get<picojson::object>();
+    obj[JSON_ACTION] = picojson::value(CONVERSATIONSUPDATED);
+    obj[JSON_DATA] = picojson::value(array);
+
+    m_callback_data.getQueue().addAndResolve(obj.at(
+                JSON_CALLBACK_ID).get<double>(), PostPriority::LOW, json->serialize());
+}
+
+void ConversationsChangeCallback::removed(
+        const ConversationPtrVector& conversations)
+{
+    LoggerD("Entered conversations.size()=%d", conversations.size());
+    if (!m_is_act) {
+        return;
+    }
+
+    ConversationPtrVector filtered = filterConversations(m_filter, conversations);
+
+    picojson::array array;
+    auto each = [&array] (std::shared_ptr<MessageConversation> c)->void {
+        array.push_back(MessagingUtil::conversationToJson(c));
+    };
+    for_each(filtered.begin(), filtered.end(), each);
+
+    LoggerD("Calling:%s with:%d added conversations", CONVERSATIONSREMOVED,
+        filtered.size());
+
+    auto json = m_callback_data.getJson();
+    picojson::object& obj = json->get<picojson::object>();
+    obj[JSON_ACTION] = picojson::value(CONVERSATIONSREMOVED);
+    obj[JSON_DATA] = picojson::value(array);
+
+    m_callback_data.getQueue().addAndResolve(obj.at(
+                JSON_CALLBACK_ID).get<double>(), PostPriority::LAST, json->serialize());
+}
+
+void ConversationsChangeCallback::setFilter(tizen::AbstractFilterPtr filter)
+{
+    m_filter = filter;
+}
+
+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;
+}
+
+} //namespace messaging
+} //namespace extension
diff --git a/webWidgetTCT_device/src/messaging/conversations_change_callback.h b/webWidgetTCT_device/src/messaging/conversations_change_callback.h
new file mode 100755 (executable)
index 0000000..34d389a
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2015 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 __MESSAGING_CONVERSATIONS_CHANGE_CALLBACK_H__
+#define __MESSAGING_CONVERSATIONS_CHANGE_CALLBACK_H__
+
+#include "MsgCommon/AbstractFilter.h"
+
+#include "conversation_callback_data.h"
+#include "message_conversation.h"
+
+namespace extension {
+namespace messaging {
+
+extern const char* CONVERSATIONSADDED;
+extern const char* CONVERSATIONSUPDATED;
+extern const char* CONVERSATIONSREMOVED;
+
+class ConversationsChangeCallback {
+public:
+    ConversationsChangeCallback(
+            long cid,
+            int service_id,
+            MessageType service_type,
+            PostQueue& queue);
+    virtual ~ConversationsChangeCallback();
+
+    void added(const ConversationPtrVector& conversations);
+    void updated(const ConversationPtrVector& conversations);
+    void removed(const ConversationPtrVector& conversations);
+
+    void setFilter(tizen::AbstractFilterPtr filter);
+    tizen::AbstractFilterPtr getFilter() const;
+
+    int getServiceId() const;
+    MessageType getServiceType() const;
+
+    void setActive(bool act);
+    bool isActive();
+
+    void setItems(ConversationPtrVector& items);
+    ConversationPtrVector getItems();
+private:
+    static ConversationPtrVector filterConversations(
+            tizen::AbstractFilterPtr a_filter,
+            const ConversationPtrVector& a_sourceConversations);
+
+    ConversationCallbackData m_callback_data;
+    tizen::AbstractFilterPtr m_filter;
+    int m_id;
+    MessageType m_msg_type;
+    bool m_is_act;
+    ConversationPtrVector m_items;
+
+};
+
+} //messaging
+} //extension
+
+
+
+
+#endif // __MESSAGING_CONVERSATIONS_CHANGE_CALLBACK_H__
diff --git a/webWidgetTCT_device/src/messaging/email_manager.cc b/webWidgetTCT_device/src/messaging/email_manager.cc
new file mode 100755 (executable)
index 0000000..2833d99
--- /dev/null
@@ -0,0 +1,1491 @@
+/*
+ * Copyright (c) 2015 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 <JSWebAPIErrorFactory.h>
+//#include <JSWebAPIError.h>
+//#include <JSUtil.h>
+#include "common/logger.h"
+#include "common/scope_exit.h"
+#include <memory>
+#include "common/platform_exception.h"
+#include <sstream>
+//#include <GlobalContextManager.h>
+
+#include "MsgCommon/AbstractFilter.h"
+
+#include <email-api-network.h>
+#include <email-api-account.h>
+#include <email-api-mail.h>
+#include <email-api-mailbox.h>
+
+#include "email_manager.h"
+#include "messaging_util.h"
+#include "message_service.h"
+#include "message.h"
+#include "message_conversation.h"
+//#include "MessageCallbackUserData.h"
+//#include "MessagesCallbackUserData.h"
+#include "find_msg_callback_user_data.h"
+#include "conversation_callback_data.h"
+#include "message_email.h"
+#include "messaging_database_manager.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 "MsgCommon/FilterIterator.h"
+
+#include "common/scope_exit.h"
+#include "messaging/DBus/DBusTypes.h"
+
+using namespace common;
+using namespace extension::tizen;
+
+namespace extension {
+namespace messaging {
+
+namespace {
+const int ACCOUNT_ID_NOT_INITIALIZED = -1;
+const std::string FIND_FOLDERS_ATTRIBUTE_ACCOUNTID_NAME  = "serviceId";
+} //anonymous namespace
+
+EmailManager::EmailManager() : m_slot_size(-1), m_is_initialized(false)
+{
+    LoggerD("Entered");
+}
+
+EmailManager& EmailManager::getInstance()
+{
+    LoggerD("Entered");
+    static EmailManager instance;
+    return instance;
+}
+
+#define CHECK_ERROR(ret, message) \
+    if (ret.IsError()) { \
+        LoggerE(message); \
+        return ret; \
+    }
+
+PlatformResult EmailManager::InitializeEmailService()
+{
+    LoggerD("Entered");
+    EmailManager& instance = EmailManager::getInstance();
+
+    if (!instance.m_is_initialized) {
+        instance.getUniqueOpId();
+        const int non_err = EMAIL_ERROR_NONE;
+
+        if(non_err != email_service_begin()){
+            LoggerE("Email service failed to begin");
+            return PlatformResult(ErrorCode::UNKNOWN_ERR, "Email service failed to begin");
+        }
+
+        if(non_err != email_open_db()){
+            LoggerE("Email DB failed to open");
+            return PlatformResult(ErrorCode::UNKNOWN_ERR, "Email DB failed to open");
+        }
+
+        int slot_size = -1;
+        vconf_get_int("db/private/email-service/slot_size", &(slot_size));
+        if (slot_size > 0) {
+            instance.m_slot_size = slot_size;
+        }
+
+        PlatformResult ret = DBus::SyncProxy::create(DBus::kDBusPathNetworkStatus,
+                                                     DBus::kDBusIfaceNetworkStatus,
+                                                     &instance.m_proxy_sync);
+        CHECK_ERROR(ret, "create sync proxy failed");
+        if (!instance.m_proxy_sync) {
+            LoggerE("Sync proxy is null");
+            return PlatformResult(ErrorCode::UNKNOWN_ERR, "Sync proxy is null");
+        }
+        instance.m_proxy_sync->signalSubscribe();
+
+        ret = DBus::LoadBodyProxy::create(DBus::kDBusPathNetworkStatus,
+                                          DBus::kDBusIfaceNetworkStatus,
+                                          &instance.m_proxy_load_body);
+        CHECK_ERROR(ret, "create load body proxy failed");
+        if (!instance.m_proxy_load_body) {
+            LoggerE("Load body proxy is null");
+            return PlatformResult(ErrorCode::UNKNOWN_ERR, "Load body proxy is null");
+        }
+        instance.m_proxy_load_body->signalSubscribe();
+
+    //    ret = DBus::LoadAttachmentProxy::create(DBus::Proxy::DBUS_PATH_NETWORK_STATUS,
+    //                                            DBus::Proxy::DBUS_IFACE_NETWORK_STATUS,
+    //                                            &m_proxy_load_attachment);
+    //    CHECK_ERROR(ret, "create load attachment proxy failed");
+    //    if (!m_proxy_load_attachment) {
+    //        LoggerE("Load attachment proxy is null");
+    //        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Load attachment proxy is null");
+    //    }
+    //    m_proxy_load_attachment->signalSubscribe();
+
+        ret = DBus::MessageProxy::create(&instance.m_proxy_messageStorage);
+        CHECK_ERROR(ret, "create message proxy failed");
+        if (!instance.m_proxy_messageStorage) {
+            LoggerE("Message proxy is null");
+            return PlatformResult(ErrorCode::UNKNOWN_ERR, "Message proxy is null");
+        }
+        instance.m_proxy_messageStorage->signalSubscribe();
+
+        ret = DBus::SendProxy::create(&instance.m_proxy_send);
+        CHECK_ERROR(ret, "create send proxy failed");
+        if (!instance.m_proxy_send) {
+            LoggerE("Send proxy is null");
+            return PlatformResult(ErrorCode::UNKNOWN_ERR, "Send proxy is null");
+        }
+        instance.m_proxy_send->signalSubscribe();
+
+        instance.m_is_initialized = true;
+    }
+
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+EmailManager::~EmailManager()
+{
+    LoggerD("Entered");
+}
+
+PlatformResult EmailManager::addDraftMessagePlatform(int account_id,
+    std::shared_ptr<Message> message)
+{
+    LoggerD("Entered");
+    return addMessagePlatform(account_id, message, EMAIL_MAILBOX_TYPE_DRAFT);
+}
+
+PlatformResult EmailManager::addOutboxMessagePlatform(int account_id,
+    std::shared_ptr<Message> message)
+{
+  return addMessagePlatform(account_id, message, EMAIL_MAILBOX_TYPE_OUTBOX);
+}
+
+PlatformResult EmailManager::addMessagePlatform(int account_id,
+    std::shared_ptr<Message> message, email_mailbox_type_e mailbox_type)
+{
+    LoggerD("Entered");
+    email_mail_data_t* mail_data = NULL;
+    email_mail_data_t* mail_data_final = NULL;
+    int err = EMAIL_ERROR_NONE;
+
+    PlatformResult ret = Message::convertPlatformEmail(message, &mail_data);
+    if (ret.IsError()) return ret;
+
+    mail_data->account_id = account_id;
+
+    //Adding "from" email address
+    email_account_t* account = NULL;
+    err = email_get_account(account_id, GET_FULL_DATA_WITHOUT_PASSWORD, &account);
+    if(EMAIL_ERROR_NONE != err) {
+        LoggerE("email_get_account failed. [%d]\n",err);
+        err = email_free_mail_data(&mail_data,1);
+        if(EMAIL_ERROR_NONE != err) {
+            LoggerE("Failed to free mail data memory");
+        }
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Cannot retrieve email account information");
+    }
+    LoggerE("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());
+    LoggerE("FROM %s", mail_data->full_address_from);
+    err = email_free_account(&account,1);
+    if(EMAIL_ERROR_NONE != err) {
+        LoggerE("Failed to free account data memory");
+    }
+    //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) {
+        LoggerD("email_get_mailbox_by_mailbox_type failed. [%d]\n",err);
+        err = email_free_mail_data(&mail_data,1);
+        if(EMAIL_ERROR_NONE != err) {
+            LoggerE("Failed to free mail data memory");
+        }
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Cannot retrieve draft mailbox");
+    }
+    else {
+        LoggerD("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) {
+        LoggerD("email_add_mail failed. [%d]\n",err);
+        err = email_free_mail_data(&mail_data,1);
+        if(EMAIL_ERROR_NONE != err) {
+            LoggerE("Failed to free mail data memory");
+        }
+        err = email_free_mailbox(&mailbox_data, 1);
+        if (EMAIL_ERROR_NONE != err) {
+            LoggerE("Failed to destroy mailbox");
+        }
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Couldn't add message to draft mailbox");
+    }
+    else {
+        LoggerD("email_add_mail success.\n");
+    }
+
+    LoggerD("saved mail without attachments id = [%d]\n", mail_data->mail_id);
+
+    message->setId(mail_data->mail_id);
+    message->setMessageStatus(MessageStatus::STATUS_DRAFT);
+
+    if (message->getHasAttachment()){
+        ret = Message::addEmailAttachments(message);
+        if (ret.IsError()) return ret;
+    }
+
+    err = email_get_mail_data(message->getId(), &mail_data_final);
+    if(EMAIL_ERROR_NONE != err) {
+        LoggerE("Failed to retrieve added mail data");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Couldn't retrieve added mail data");
+    }
+    ret = message->updateEmailMessage(*mail_data_final);
+    if (ret.IsError()) return ret;
+
+    err = email_free_mail_data(&mail_data_final,1);
+    if(EMAIL_ERROR_NONE != err) {
+        LoggerE("Failed to free mail data final memory");
+    }
+
+    err = email_free_mail_data(&mail_data,1);
+    if(EMAIL_ERROR_NONE != err) {
+        LoggerE("Failed to free mail data memory");
+    }
+
+    err = email_free_mailbox(&mailbox_data, 1);
+    if (EMAIL_ERROR_NONE != err) {
+        LoggerE("Failed to destroy mailbox");
+    }
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+static gboolean addDraftMessageCompleteCB(void *data)
+{
+    LoggerD("Entered");
+    MessageCallbackUserData* callback =
+        static_cast<MessageCallbackUserData *>(data);
+    if (!callback) {
+        LoggerE("Callback is null");
+        return false;
+    }
+
+    auto json = callback->getJson();
+    picojson::object& obj = json->get<picojson::object>();
+    if (json->contains(JSON_CALLBACK_ID) && obj.at(JSON_CALLBACK_ID).is<double>()) {
+        if (callback->isError()) {
+            LoggerD("Calling error callback");
+            callback->getQueue().resolve(obj.at(JSON_CALLBACK_ID).get<double>(),
+                                             json->serialize()
+            );
+            callback->getMessage()->setMessageStatus(MessageStatus::STATUS_FAILED);
+        } else {
+            LoggerD("Calling success callback");
+            obj[JSON_ACTION] = picojson::value(JSON_CALLBACK_SUCCCESS);
+
+            picojson::object args;
+            args[JSON_DATA_MESSAGE] = MessagingUtil::messageToJson(callback->getMessage());
+            obj[JSON_DATA] = picojson::value(args);
+
+            callback->getQueue().resolve(
+                    obj.at(JSON_CALLBACK_ID).get<double>(),
+                    json->serialize()
+            );
+        }
+    } else {
+        LoggerE("Callback id is missing");
+        callback->getMessage()->setMessageStatus(MessageStatus::STATUS_FAILED);
+    }
+
+    delete callback;
+    callback = NULL;
+
+    return false;
+}
+
+void EmailManager::addDraftMessage(MessageCallbackUserData* callback)
+{
+  LoggerD("Entered");
+
+  if(!callback){
+    LoggerE("Callback is null");
+    return;
+  }
+  {
+    std::lock_guard<std::mutex> lock(m_mutex);
+    std::shared_ptr<Message> message = callback->getMessage();
+    PlatformResult ret = addDraftMessagePlatform(callback->getAccountId(), message);
+    if (ret.IsError()) {
+      LoggerE("%d (%s)", ret.error_code(), ret.message().c_str());
+      callback->setError(ret);
+    }
+  }
+  //Complete task
+  if (!g_idle_add(addDraftMessageCompleteCB, static_cast<void *>(callback))) {
+    LoggerE("g_idle addition failed");
+    delete callback;
+    callback = NULL;
+  }
+}
+
+//**** sending email ****
+static gboolean sendEmailCompleteCB(void* data)
+{
+    LoggerD("Entered");
+
+    MessageRecipientsCallbackData* callback =
+            static_cast<MessageRecipientsCallbackData*>(data);
+    if (!callback) {
+        LoggerE("Callback is null");
+        return false;
+    }
+
+    auto json = callback->getJson();
+    picojson::object& obj = json->get<picojson::object>();
+    if (json->contains(JSON_CALLBACK_ID) && obj.at(JSON_CALLBACK_ID).is<double>()) {
+        if (callback->isError()) {
+            LoggerD("Calling error callback");
+            callback->getQueue().resolve(obj.at(JSON_CALLBACK_ID).get<double>(),
+                                             json->serialize()
+            );
+            callback->getMessage()->setMessageStatus(MessageStatus::STATUS_FAILED);
+        }
+        else {
+            LoggerD("Calling success callback");
+            obj[JSON_ACTION] = picojson::value(JSON_CALLBACK_SUCCCESS);
+
+            std::vector<picojson::value> recipients;
+            auto addToRecipients = [&recipients](std::string& e)->void {
+                recipients.push_back(picojson::value(e));
+            };
+
+            auto toVect = callback->getMessage()->getTO();
+            std::for_each(toVect.begin(), toVect.end(), addToRecipients);
+
+            auto ccVect = callback->getMessage()->getCC();
+            std::for_each(ccVect.begin(), ccVect.end(), addToRecipients);
+
+            auto bccVect = callback->getMessage()->getBCC();
+            std::for_each(bccVect.begin(), bccVect.end(), addToRecipients);
+
+            picojson::object data;
+            data[JSON_DATA_RECIPIENTS] = picojson::value(recipients);
+            data[JSON_DATA_MESSAGE] = MessagingUtil::messageToJson(callback->getMessage());
+            obj[JSON_DATA] = picojson::value(data);
+
+            callback->getQueue().resolve(
+                    obj.at(JSON_CALLBACK_ID).get<double>(),
+                    json->serialize()
+            );
+            callback->getMessage()->setMessageStatus(MessageStatus::STATUS_SENT);
+        }
+    } else {
+        LoggerE("Callback id is missing");
+    }
+
+    delete callback;
+    callback = NULL;
+
+    return false;
+}
+
+PlatformResult EmailManager::sendMessage(MessageRecipientsCallbackData* callback)
+{
+  LoggerD("Entered");
+
+  if (!callback) {
+    LoggerE("Callback is null");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Callback is null");
+  }
+
+  int err = EMAIL_ERROR_NONE;
+  email_mail_data_t *mail_data = NULL;
+
+  PlatformResult platform_result(ErrorCode::NO_ERROR);
+
+  std::shared_ptr<Message> message = callback->getMessage();
+
+  if (message) {
+    if (!(message->is_id_set())) {
+      platform_result = addOutboxMessagePlatform(callback->getAccountId(), message);
+    }
+
+    if (platform_result) {
+      err = email_get_mail_data(message->getId(),&mail_data);
+      if (EMAIL_ERROR_NONE != err) {
+        LoggerE("email_get_mail_data failed. [%d]\n", err);
+        platform_result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get platform email structure");
+      } else {
+        LoggerD("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) {
+          LoggerE("Failed to send message %d", err);
+          platform_result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to send message");
+        } else {
+          LoggerD("req_id: %d", req_id);
+          callback->getMessage()->setMessageStatus(MessageStatus::STATUS_SENDING);
+          m_sendRequests[req_id] = callback;
+        }
+      }
+    }
+  } else {
+    LoggerE("Message is null");
+    platform_result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Message is null");
+  }
+
+  if (!platform_result) {
+    LoggerE("Message send failed");
+
+    callback->setError(platform_result);
+
+    if (!g_idle_add(sendEmailCompleteCB, static_cast<void*>(callback))) {
+      LoggerE("g_idle addition failed");
+      delete callback;
+      callback = NULL;
+    }
+  }
+
+  if (mail_data) {
+    err = email_free_mail_data(&mail_data, 1);
+
+    if (EMAIL_ERROR_NONE != err) {
+      LoggerE("Failed to free mail data memory");
+    }
+  }
+
+  return platform_result;
+}
+
+void EmailManager::sendStatusCallback(int mail_id,
+        email_noti_on_network_event status,
+        int error_code)
+{
+    LoggerD("Entered");
+
+    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()) {
+        LoggerD("Found request");
+        MessageRecipientsCallbackData* callback = it->second;
+        m_sendRequests.erase(it);
+
+        if (NOTI_SEND_FAIL == status) {
+            LoggerD("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:
+                {
+                    LoggerE("Network error %d", error_code);
+                    common::NetworkException e("Failed to send message");
+                    callback->setError(e.name(), e.message());
+                    break;
+                }
+                default:
+                    LoggerE("Unknown error %d", error_code);
+                    common::UnknownException ex("Failed to send message");
+                    callback->setError(ex.name(),ex.message());
+                    break;
+            }
+        } else if (NOTI_SEND_FINISH == status) {
+            LoggerD("Message sent successfully");
+        }
+
+        if (!g_idle_add(sendEmailCompleteCB, static_cast<void*>(callback))) {
+            LoggerE("g_idle addition failed");
+            delete callback;
+            callback = NULL;
+        }
+    } else {
+        LoggerW("No matching request found");
+    }
+}
+
+email_mail_data_t* EmailManager::loadMessage(int msg_id)
+{
+    LoggerD("Entered");
+    email_mail_data_t* mail_data = NULL;
+    int err = email_get_mail_data(msg_id, &mail_data);
+    if (EMAIL_ERROR_NONE != err) {
+        LoggerE("email_get_mail_data failed. [%d]", err);
+    } else {
+        LoggerD("email_get_mail_data success.");
+    }
+    return mail_data;
+}
+
+EmailManager::SendReqMapIterator EmailManager::getSendRequest(int mail_id)
+{
+    LoggerD("Entered");
+    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)
+{
+    LoggerD("Entered");
+    if(!mail_data) {
+        return;
+    }
+
+    int err = email_free_mail_data(&mail_data, 1);
+    if(EMAIL_ERROR_NONE != err) {
+        LoggerE("Could not free mail data!");
+    }
+}
+
+void EmailManager::loadMessageBody(MessageBodyCallbackData* callback)
+{
+    LoggerD("Entered");
+    if(!callback){
+        LoggerE("Callback is null");
+        return;
+    }
+
+    if(!callback->getMessage()) {
+        LoggerE("Callback's message is null");
+        return;
+    }
+
+    m_proxy_load_body->addCallback(callback);
+
+    const int mailId = callback->getMessage()->getId();
+
+    int op_handle = -1;
+    int err = email_download_body(mailId, 0, &op_handle);
+    if(EMAIL_ERROR_NONE != err){
+        LoggerE("Email download body failed, %d", err);
+        m_proxy_load_body->removeCallback(callback);
+        return;
+    }
+    callback->setOperationHandle(op_handle);
+}
+
+PlatformResult EmailManager::loadMessageAttachment(MessageAttachmentCallbackData* callback)
+{
+  LoggerD("Entered");
+
+  if (!callback) {
+    LoggerE("Callback is null");
+    return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Callback is null");
+  }
+
+  if (!callback->getMessageAttachment()) {
+    LoggerE("Callback's message attachment is null");
+    return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Callback's message attachment is null");
+  }
+
+  std::shared_ptr<MessageAttachment> msgAttachment = callback->getMessageAttachment();
+  LoggerD("attachmentId: [%d] mailId: [%d]", msgAttachment->getId(),
+          msgAttachment->getMessageId());
+
+  email_mail_data_t* mail_data = EmailManager::loadMessage(msgAttachment->getMessageId());
+
+  SCOPE_EXIT {
+    EmailManager::freeMessage(mail_data);
+  };
+
+  if (!mail_data) {
+    LoggerE("Couldn't get email_mail_data_t for messageId: %d", msgAttachment->getMessageId());
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Couldn't load message.");
+  }
+
+  AttachmentPtrVector attachments;
+  auto platform_result = Message::convertEmailToMessageAttachment(*mail_data, &attachments);
+
+  if (!platform_result) {
+    return platform_result;
+  }
+
+  LoggerD("Mail: [%d] contains: [%d] attachments",
+          msgAttachment->getMessageId(), attachments.size());
+
+  auto 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) {
+    LoggerE("Attachment with id: %d not found", msgAttachment->getId());
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Couldn't find attachment.");
+  }
+
+  LoggerD("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) {
+    LoggerE("Download email attachment failed with error: %d", err);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to load attachment.");
+  } else {
+    LoggerD("email_download_attachment returned handle: [%d]", op_handle);
+    callback->setOperationHandle(op_handle);
+    m_proxy_load_attachment->addCallback(callback);
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+}
+
+//#################################### sync: ###################################
+
+void EmailManager::sync(void* data)
+{
+  LoggerD("Entered");
+
+  SyncCallbackData* callback = static_cast<SyncCallbackData*>(data);
+
+  if (!callback) {
+    LoggerE("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) {
+    LoggerE("Email set slot size failed, %d", err);
+    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) {
+    LoggerE("Email sync header failed, %d", err);
+    m_proxy_sync->removeCallback(op_id);
+  } else {
+    callback->setOperationHandle(op_handle);
+  }
+}
+
+//#################################### ^sync ###################################
+
+//################################## syncFolder: ###############################
+
+void EmailManager::syncFolder(SyncFolderCallbackData* callback)
+{
+  LoggerD("Entered");
+
+  if (!callback) {
+    LoggerE("Callback is null");
+    return;
+  }
+
+  const long op_id = callback->getOpId();
+  m_proxy_sync->addCallback(op_id, callback);
+
+  if (!callback->getMessageFolder()) {
+    LoggerE("Callback's messageFolder is null");
+    m_proxy_sync->removeCallback(op_id);
+    return;
+  }
+
+  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;
+
+  int err = email_get_mailbox_by_mailbox_id(folder_id, &mailbox);
+
+  if (EMAIL_ERROR_NONE != err || NULL == mailbox) {
+    LoggerE("Couldn't get mailbox, error code: %d", err);
+    m_proxy_sync->removeCallback(op_id);
+    return;
+  }
+
+  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) {
+    LoggerE("Email set slot size failed, %d", err);
+  } else {
+    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) {
+      LoggerE("Email sync header failed, %d", err);
+      m_proxy_sync->removeCallback(op_id);
+    } else {
+      callback->setOperationHandle(op_handle);
+    }
+  }
+
+  if (NULL != mailbox) {
+    err = email_free_mailbox(&mailbox, 1);
+    if (EMAIL_ERROR_NONE != err) {
+      LoggerE("Failed to email_free_mailbox - err:%d ", err);
+    }
+    mailbox = NULL;
+  }
+}
+
+//#################################### ^syncFolder #############################
+
+//################################## stopSync: #################################
+
+void EmailManager::stopSync(long op_id)
+{
+  LoggerD("Entered");
+
+  SyncCallbackData* callback = static_cast<SyncCallbackData*>(m_proxy_sync->getCallback(op_id));
+
+  if (!callback) {
+    LoggerE("Callback is null");
+    return;
+  }
+
+  int err = email_cancel_job(callback->getAccountId(),
+                         callback->getOperationHandle(),
+                         EMAIL_CANCELED_BY_USER);
+
+  if (EMAIL_ERROR_NONE != err) {
+    LoggerE("Email cancel job failed, %d", err);
+  }
+
+  std::shared_ptr<picojson::value> response = callback->getJson();
+  picojson::object& obj = response->get<picojson::object>();
+
+  if (response->contains(JSON_CALLBACK_ID) && obj.at(JSON_CALLBACK_ID).is<double>()) {
+    callback->setError(PlatformResult(ErrorCode::ABORT_ERR, "Sync aborted by user"));
+
+    callback->getQueue().resolve(obj.at(JSON_CALLBACK_ID).get<double>(),
+                                     response->serialize());
+    m_proxy_sync->removeCallback(op_id);
+  } else {
+    LoggerE("Callback id is missing");
+  }
+}
+
+//################################## ^stopSync #################################
+
+void EmailManager::RemoveSyncCallback(long op_id) {
+  LoggerD("Entered");
+  m_proxy_sync->removeCallback(op_id);
+}
+
+void EmailManager::RemoveCallbacksByQueue(const PostQueue& q) {
+  LoggerD("Entered");
+
+  for (auto it = m_sendRequests.begin(); it != m_sendRequests.end();) {
+    if (&it->second->getQueue() == &q) {
+      delete it->second;
+      m_sendRequests.erase(it++);
+    } else {
+      ++it;
+    }
+  }
+}
+
+void removeEmailCompleteCB(MessagesCallbackUserData* callback)
+{
+  LoggerD("Entered");
+  if (!callback) {
+    LoggerE("Callback is null");
+    return;
+  }
+
+  auto json = callback->getJson();
+  picojson::object& obj = json->get<picojson::object>();
+  if (json->contains(JSON_CALLBACK_ID) && obj.at(JSON_CALLBACK_ID).is<double>()) {
+    if (callback->isError()) {
+      LoggerD("Calling error callback");
+      callback->getQueue().resolve(obj.at(JSON_CALLBACK_ID).get<double>(),
+                                       json->serialize()
+      );
+    } else {
+      LoggerD("Calling success callback");
+
+      obj[JSON_ACTION] = picojson::value(JSON_CALLBACK_SUCCCESS);
+      callback->getQueue().resolve(obj.at(JSON_CALLBACK_ID).get<double>(),
+                                       json->serialize()
+      );
+    }
+  } else {
+    LoggerE("Callback id is missing");
+  }
+
+  delete callback;
+  callback = NULL;
+}
+
+EmailManager::DeleteReqVector::iterator EmailManager::getDeleteRequest(
+        const std::vector<int> &ids)
+{
+    LoggerD("Entered");
+    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)
+{
+    LoggerD("Entered");
+    std::lock_guard<std::mutex> lock(m_mutex);
+    DeleteReqVector::iterator it = getDeleteRequest(ids);
+    if (it != m_deleteRequests.end()) {
+        LoggerD("Found request");
+        if (NOTI_MAIL_DELETE_FINISH == status) {
+            LoggerD("Successfully removed %d mails", ids.size());
+            it->messagesDeleted += ids.size();
+        }
+        MessagesCallbackUserData* callback = it->callback;
+        if (NOTI_MAIL_DELETE_FAIL == status) {
+            LoggerD("Failed to remove mail");
+            UnknownException e("Messages remove failed");
+            callback->setError(e.name(), e.message());
+        }
+        //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()) {
+            LoggerD("Calling callback");
+            m_deleteRequests.erase(it);
+            m_mutex.unlock();
+            removeEmailCompleteCB(callback);
+        } else {
+            LoggerD("Not all messages are removed, waiting for next callback");
+        }
+    } else {
+        LoggerD("Request not found, ignoring");
+    }
+}
+
+PlatformResult EmailManager::RemoveMessagesPlatform(MessagesCallbackUserData* callback)
+{
+  LoggerD("Entered");
+  int error;
+  email_mail_data_t *mail = NULL;
+
+  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) {
+      LoggerE("Invalid message type");
+      return PlatformResult(ErrorCode::TYPE_MISMATCH_ERR, "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) {
+      LoggerE("Couldn't retrieve mail data");
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, "Error while deleting mail");
+    }
+
+    //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) {
+      email_free_mail_data(&mail, 1);
+      LoggerE("Error while deleting mail");
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, "Error while deleting mail");
+    }
+    email_free_mail_data(&mail, 1);
+  }
+  //store delete request and wait for dbus response
+  DeleteReq request;
+  request.callback = callback;
+  request.messagesDeleted = 0;
+  m_deleteRequests.push_back(request);
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+void EmailManager::removeMessages(MessagesCallbackUserData* callback)
+{
+  LoggerD("Entered");
+
+  if (!callback){
+    LoggerE("Callback is null");
+    return;
+  }
+
+  PlatformResult ret = RemoveMessagesPlatform(callback);
+  if (ret.IsError()) {
+    LoggerE("%d (%s)", ret.error_code(), (ret.message()).c_str());
+    callback->SetError(ret);
+    removeEmailCompleteCB(callback);
+  }
+}
+
+PlatformResult EmailManager::UpdateMessagesPlatform(MessagesCallbackUserData* callback) {
+  LoggerD("Entered");
+  int error;
+  email_mail_data_t *mail = NULL;
+  SCOPE_EXIT {
+    if (mail) {
+      email_free_mail_data(&mail, 1);
+      mail = NULL;
+    }
+  };
+
+  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) {
+      LoggerE("Invalid message type");
+      return PlatformResult(ErrorCode::TYPE_MISMATCH_ERR, "Error while updating message");
+    }
+  }
+  for (auto it = messages.begin() ; it != messages.end(); ++it) {
+
+    PlatformResult ret = Message::convertPlatformEmail((*it), &mail);
+    if (ret.IsError()) return ret;
+
+    if((*it)->getHasAttachment())
+    {
+      LoggerD("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
+      PlatformResult ret = addDraftMessagePlatform(mail->account_id, (*it));
+      if (ret.IsError()) {
+        return ret;
+      }
+      LoggerD("mail added - new id = [%d]\n", (*it)->getId());
+
+      //storing old message id
+      (*it)->setOldId(mail->mail_id);
+      //deleting old mail
+      LoggerD("mail deleted = [%d]\n", mail->mail_id);
+      error = email_delete_mail(mail->mailbox_id,&mail->mail_id,1,1);
+      if (EMAIL_ERROR_NONE != error) {
+        LoggerE("Error while deleting old mail on update: %d", error);
+        return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                              "Error while deleting old mail on update");
+      }
+    } else {
+      LoggerD("There are no attachments, updating only email data.");
+      error = email_update_mail(mail, NULL, 0, NULL, 0);
+      if (EMAIL_ERROR_NONE != error) {
+        LoggerE("Error while updating mail");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Error while updating mail");
+      }
+    }
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+void EmailManager::updateMessages(MessagesCallbackUserData* callback)
+{
+    LoggerD("Entered");
+
+    if (!callback){
+        LoggerE("Callback is null");
+        return;
+    }
+
+    PlatformResult ret = UpdateMessagesPlatform(callback);
+    if (ret.IsError()) {
+      LoggerE("%d (%s)", ret.error_code(), (ret.message()).c_str());
+      callback->SetError(ret);
+    }
+
+    auto json = callback->getJson();
+    picojson::object& obj = json->get<picojson::object>();
+    if (json->contains(JSON_CALLBACK_ID) && obj.at(JSON_CALLBACK_ID).is<double>()) {
+      if (callback->isError()) {
+        LoggerD("Calling error callback");
+        callback->getQueue().resolve(obj.at(JSON_CALLBACK_ID).get<double>(),
+                                         json->serialize());
+      } else {
+        LoggerD("Calling success callback");
+        obj[JSON_ACTION] = picojson::value(JSON_CALLBACK_SUCCCESS);
+
+        picojson::array array;
+        auto messages = callback->getMessages();
+        size_t messages_size = messages.size();
+        for (size_t i = 0 ; i < messages_size; ++i) {
+          array.push_back(MessagingUtil::messageToJson(messages[i]));
+        }
+        obj[JSON_DATA] = picojson::value(array);
+
+        callback->getQueue().resolve(obj.at(JSON_CALLBACK_ID).get<double>(),
+                                         json->serialize()
+        );
+      }
+    } else {
+      LoggerE("Callback id is missing");
+    }
+    delete callback;
+    callback = NULL;
+}
+
+PlatformResult EmailManager::FindMessagesPlatform(FindMsgCallbackUserData* callback)
+{
+  LoggerD("Entered");
+  email_mail_data_t* mailList = NULL;
+  int mailListCount = 0;
+
+  SCOPE_EXIT {
+    if (mailListCount > 0 && mailList != NULL) {
+      if (EMAIL_ERROR_NONE != email_free_mail_data(&mailList, mailListCount)) {
+        LoggerW("Failed to free mailList");
+      }
+    }
+  };
+
+  std::lock_guard<std::mutex> lock(m_mutex);
+  std::pair<int, email_mail_data_t*> emails;
+  PlatformResult ret = MessagingDatabaseManager::getInstance().findEmails(callback, &emails);
+  if (ret.IsError()) return ret;
+  mailListCount = emails.first;
+  LoggerD("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;
+    ret = Message::convertPlatformEmailToObject(*nth_email, &email);
+    if (ret.IsError()) return ret;
+    callback->addMessage(email);
+    nth_email++;
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+void EmailManager::findMessages(FindMsgCallbackUserData* callback)
+{
+  LoggerD("Entered");
+
+  if(!callback){
+    LoggerE("Callback is null");
+    return;
+  }
+
+  PlatformResult ret = FindMessagesPlatform(callback);
+  if (ret.IsError()) {
+    LoggerE("%d (%s)", ret.error_code(), (ret.message()).c_str());
+    callback->SetError(ret);
+  }
+
+  //Complete task
+  LoggerD("callback: %p error: %d messages.size() = %d", callback, callback->isError(),
+          callback->getMessages().size());
+
+  auto json = callback->getJson();
+  picojson::object& obj = json->get<picojson::object>();
+  if (json->contains(JSON_CALLBACK_ID) && obj.at(JSON_CALLBACK_ID).is<double>()) {
+    if (callback->isError()) {
+      LoggerD("Calling error callback");
+      callback->getQueue().resolve( obj.at(JSON_CALLBACK_ID).get<double>(),
+                                        json->serialize());
+    } else {
+      LoggerD("Calling success callback");
+      std::vector<picojson::value> response;
+      auto messages = callback->getMessages();
+      std::for_each(messages.begin(), messages.end(), [&response](MessagePtr &message){
+        response.push_back(MessagingUtil::messageToJson(message));
+      });
+      obj[JSON_DATA] = picojson::value(response);
+      obj[JSON_ACTION] = picojson::value(JSON_CALLBACK_SUCCCESS);
+
+      callback->getQueue().resolve(obj.at(JSON_CALLBACK_ID).get<double>(),
+                                       json->serialize());
+    }
+  } else {
+    LoggerE("Failed to call findMessages callback.");
+  }
+
+  delete callback;
+  callback = NULL;
+}
+
+PlatformResult EmailManager::FindConversationsPlatform(ConversationCallbackData* callback)
+{
+  LoggerD("Entered");
+  int convListCount = 0;
+
+  std::lock_guard<std::mutex> lock(m_mutex);
+  std::vector<EmailConversationInfo> conversationsInfo;
+  PlatformResult ret = MessagingDatabaseManager::getInstance().
+      findEmailConversations(callback, &conversationsInfo);
+  if (ret.IsError()) return ret;
+
+  convListCount = conversationsInfo.size();
+  LoggerD("Found %d conversations", convListCount);
+
+  for (int i = 0; i < convListCount; ++i) {
+    std::shared_ptr<MessageConversation> conversation;
+    PlatformResult ret = MessageConversation::convertEmailConversationToObject(
+        conversationsInfo.at(i).id, &conversation);
+    conversation->setUnreadMessages(conversationsInfo.at(i).unreadMessages);
+    callback->addConversation(conversation);
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+void EmailManager::findConversations(ConversationCallbackData* callback)
+{
+    LoggerD("Entered");
+
+    if(!callback){
+        LoggerE("Callback is null");
+        return;
+    }
+
+    PlatformResult ret = FindConversationsPlatform(callback);
+    if (ret.IsError()) {
+        LoggerE("%d (%s)", ret.error_code(), (ret.message()).c_str());
+        callback->SetError(ret);
+    }
+
+    //Complete task
+    LoggerD("callback: %p error:%d conversations.size()=%d", callback, callback->isError(),
+            callback->getConversations().size());
+
+    auto json = callback->getJson();
+    picojson::object& obj = json->get<picojson::object>();
+    if (json->contains(JSON_CALLBACK_ID) && obj.at(JSON_CALLBACK_ID).is<double>()) {
+      if (callback->isError()) {
+        LoggerD("Calling error callback");
+        callback->getQueue().resolve(obj.at(JSON_CALLBACK_ID).get<double>(),
+                                         json->serialize());
+      } else {
+        LoggerD("Calling success callback");
+
+        std::vector<picojson::value> response;
+        auto messages = callback->getConversations();
+        std::for_each(messages.begin(), messages.end(),
+                      [&response](std::shared_ptr<MessageConversation> &conversation) {
+          response.push_back(MessagingUtil::conversationToJson(conversation));
+        }
+        );
+        obj[JSON_DATA] = picojson::value(response);
+        obj[JSON_ACTION] = picojson::value(JSON_CALLBACK_SUCCCESS);
+
+        callback->getQueue().resolve(obj.at(JSON_CALLBACK_ID).get<double>(),
+                                         json->serialize()
+        );
+      }
+    } else {
+      LoggerE("Failed to call findConversations callback.");
+    }
+
+    delete callback;
+    callback = NULL;
+}
+
+long EmailManager::getUniqueOpId()
+{
+    LoggerD("Entered");
+    // 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++;
+}
+
+PlatformResult EmailManager::FindFoldersPlatform(FoldersCallbackData* callback)
+{
+  LoggerD("Entered");
+  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;
+
+  SCOPE_EXIT {
+    if (mailboxes != NULL) {
+      if (EMAIL_ERROR_NONE != email_free_mailbox(&mailboxes,
+                                                 mailboxes_count)) {
+        LoggerW("Free mailboxes failed: %d", ret);
+      }
+    }
+  };
+
+  std::lock_guard<std::mutex> lock(m_mutex);
+
+  tizen::AbstractFilterPtr filter = callback->getFilter();
+  if (!filter) {
+    LoggerE("Filter not provided");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "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()) {
+        LoggerE("[ERROR] >>> invalid Filter type: %d", cf->getType());
+        return PlatformResult(ErrorCode::TYPE_MISMATCH_ERR, "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 {
+          LoggerE("The attribute name: %s is invalid", attr_name.c_str());
+          return PlatformResult(ErrorCode::INVALID_VALUES_ERR,
+                                "The attribute name is invalid");
+        }
+      }
+    }
+  }
+
+  LoggerD("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) {
+      LoggerE("Cannot get folders: %d", ret);
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, "Platform error, cannot get folders");
+    }
+
+    if (mailboxes_count <= 0) {
+      LoggerD("Empty mailboxes");
+    }
+    else {
+      LoggerD("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++;
+      }
+    }
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+void EmailManager::findFolders(FoldersCallbackData* callback)
+{
+    LoggerD("Entered");
+
+    if (!callback){
+        LoggerE("Callback is null");
+        return;
+    }
+
+    PlatformResult ret = FindFoldersPlatform(callback);
+    if (ret.IsError()) {
+      LoggerE("%d (%s)", ret.error_code(), (ret.message()).c_str());
+      callback->SetError(ret);
+    }
+
+    //Complete task
+    LoggerD("callback: %p error:%d folders.size()=%d", callback, callback->isError(),
+            callback->getFolders().size());
+
+    auto json = callback->getJson();
+    picojson::object& obj = json->get<picojson::object>();
+    if (json->contains(JSON_CALLBACK_ID) && obj.at(JSON_CALLBACK_ID).is<double>()) {
+      if (callback->isError()) {
+        LoggerD("Calling error callback");
+        callback->getQueue().resolve(obj.at(JSON_CALLBACK_ID).get<double>(),
+                                         json->serialize());
+      } else {
+        LoggerD("Calling success callback");
+
+        std::vector<picojson::value> response;
+        auto folders = callback->getFolders();
+        std::for_each(folders.begin(), folders.end(),
+                      [&response](std::shared_ptr<MessageFolder> &folder) {
+          response.push_back(MessagingUtil::folderToJson(folder));
+        }
+        );
+        obj[JSON_DATA] = picojson::value(response);
+        obj[JSON_ACTION] = picojson::value(JSON_CALLBACK_SUCCCESS);
+
+        callback->getQueue().resolve(obj.at(JSON_CALLBACK_ID).get<double>(),
+                                         json->serialize());
+      }
+    } else {
+      LoggerE("Unknown error when calling findFolders callback.");
+    }
+
+    delete callback;
+    callback = NULL;
+}
+
+PlatformResult EmailManager::RemoveConversationsPlatform(ConversationCallbackData* callback)
+{
+  LoggerD("Entered");
+  int error;
+  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) {
+      LoggerE("Invalid message type");
+      return PlatformResult(ErrorCode::TYPE_MISMATCH_ERR,
+                            "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) {
+      LoggerE("Couldn't delete email conversation data");
+      return PlatformResult(ErrorCode::TYPE_MISMATCH_ERR,
+                            "Error while deleting email conversation");
+    }
+
+    // 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 {
+      struct timespec sleep_time = { 0, 300L * 1000L * 1000L };
+      nanosleep(&sleep_time, nullptr);
+      LoggerD("Waiting to delete this email thread...");
+      error = email_get_thread_information_by_thread_id(
+          thread_id, &thread_info);
+
+      if (thread_info != NULL) {
+        free(thread_info);
+        thread_info = NULL;
+      }
+    } while (error != EMAIL_ERROR_MAIL_NOT_FOUND);
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+void EmailManager::removeConversations(ConversationCallbackData* callback)
+{
+    LoggerD("Entered");
+
+    if (!callback){
+        LoggerE("Callback is null");
+        return;
+    }
+
+    PlatformResult ret = RemoveConversationsPlatform(callback);
+    if (ret.IsError()) {
+      LoggerE("%d (%s)", ret.error_code(), (ret.message()).c_str());
+      callback->SetError(ret);
+    }
+
+    auto json = callback->getJson();
+    picojson::object& obj = json->get<picojson::object>();
+    if (json->contains(JSON_CALLBACK_ID) && obj.at(JSON_CALLBACK_ID).is<double>()) {
+      if (callback->isError()) {
+        LoggerD("Calling error callback");
+        callback->getQueue().resolve(obj.at(JSON_CALLBACK_ID).get<double>(),
+                                         json->serialize());
+      } else {
+        LoggerD("Calling success callback");
+        obj[JSON_ACTION] = picojson::value(JSON_CALLBACK_SUCCCESS);
+
+        callback->getQueue().resolve(obj.at(JSON_CALLBACK_ID).get<double>(),
+                                         json->serialize());
+      }
+    } else {
+      LoggerE("Unknown error when calling removeConversations callback.");
+    }
+
+    delete callback;
+    callback = NULL;
+}
+
+} // Messaging
+} // DeviceAPI
diff --git a/webWidgetTCT_device/src/messaging/email_manager.h b/webWidgetTCT_device/src/messaging/email_manager.h
new file mode 100755 (executable)
index 0000000..a2f752d
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+/**
+ * @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 "common/callback_user_data.h"
+#include "common/GDBus/connection.h"
+#include "common/platform_exception.h"
+#include "common/platform_result.h"
+
+#include "messaging_util.h"
+#include "message_service.h"
+
+#include "DBus/SyncProxy.h"
+#include "DBus/LoadBodyProxy.h"
+#include "DBus/LoadAttachmentProxy.h"
+#include "DBus/MessageProxy.h"
+#include "DBus/SendProxy.h"
+
+namespace extension {
+namespace messaging {
+
+//class Message;
+//class MessageCallbackUserData;
+class FindMsgCallbackUserData;
+//class SyncFolderCallbackData;
+class MessageBodyCallbackData;
+
+class EmailManager {
+public:
+    static EmailManager& getInstance();
+    static common::PlatformResult InitializeEmailService();
+
+    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);
+
+    common::PlatformResult 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);
+    common::PlatformResult loadMessageAttachment(MessageAttachmentCallbackData* callback);
+
+    void sync(void* data);
+    void syncFolder(SyncFolderCallbackData* callback);
+    void stopSync(long op_id);
+
+    void RemoveSyncCallback(long op_id);
+    void RemoveCallbacksByQueue(const PostQueue& q);
+
+//    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();
+    common::PlatformResult addDraftMessagePlatform(int account_id,
+        std::shared_ptr<Message> message);
+    common::PlatformResult addOutboxMessagePlatform(int account_id,
+        std::shared_ptr<Message> message);
+    common::PlatformResult addMessagePlatform(int account_id, std::shared_ptr<Message> message,
+        email_mailbox_type_e mailbox_type);
+    common::PlatformResult UpdateMessagesPlatform(MessagesCallbackUserData* callback);
+    common::PlatformResult RemoveMessagesPlatform(
+        MessagesCallbackUserData* callback);
+    common::PlatformResult FindMessagesPlatform(FindMsgCallbackUserData* callback);
+    common::PlatformResult FindConversationsPlatform(ConversationCallbackData* callback);
+    common::PlatformResult FindFoldersPlatform(FoldersCallbackData* callback);
+    common::PlatformResult RemoveConversationsPlatform(ConversationCallbackData* callback);
+
+    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;
+    bool m_is_initialized;
+};
+
+} // Messaging
+} // DeviceAPI
+#endif // __TIZEN_EMAIL_MANAGER_H__
diff --git a/webWidgetTCT_device/src/messaging/find_msg_callback_user_data.cc b/webWidgetTCT_device/src/messaging/find_msg_callback_user_data.cc
new file mode 100755 (executable)
index 0000000..fa8cc97
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+/**
+ * @file: FindMsgCallbackUserData.cpp
+ */
+
+#include "find_msg_callback_user_data.h"
+#include "common/picojson.h"
+
+namespace extension {
+namespace messaging {
+
+FindMsgCallbackUserData::FindMsgCallbackUserData(PostQueue& queue):
+        CallbackUserData(),
+        m_limit(0),
+        m_offset(0),
+        m_is_error(false),
+        m_account_id(0),
+        m_service_type(UNDEFINED),
+        queue_(queue)
+{
+    LoggerD("Entered");
+}
+
+FindMsgCallbackUserData::~FindMsgCallbackUserData()
+{
+    LoggerD("Entered");
+}
+
+void FindMsgCallbackUserData::setFilter(AbstractFilterPtr filter)
+{
+    m_filter = filter;
+}
+
+void FindMsgCallbackUserData::setSortMode(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)
+{
+    LoggerD("Entered");
+    // keep only first error in chain
+    if (!m_is_error) {
+        LoggerD("Error has not been set yet");
+        m_is_error = true;
+        m_err_name = err_name;
+        m_err_message = err_message;
+
+        picojson::object& obj = m_json->get<picojson::object>();
+        obj[JSON_ACTION] = picojson::value(JSON_CALLBACK_ERROR);
+
+        auto obj_error = picojson::object();
+        obj_error[JSON_ERROR_NAME] = picojson::value(err_name);
+        obj_error[JSON_ERROR_MESSAGE] = picojson::value(err_message);
+        obj[JSON_DATA] = picojson::value(obj_error);
+    }
+}
+
+void FindMsgCallbackUserData::SetError(const common::PlatformResult& error)
+{
+    LoggerD("Entered");
+    // keep only first error in chain
+    if (!m_is_error) {
+    LoggerD("Error has not been set yet");
+    m_is_error = true;
+    picojson::object& obj = m_json->get<picojson::object>();
+    obj[JSON_ACTION] = picojson::value(JSON_CALLBACK_ERROR);
+    auto obj_data = picojson::object();
+    obj_data[JSON_ERROR_CODE] = picojson::value(static_cast<double>(error.error_code()));
+    obj_data[JSON_ERROR_MESSAGE] = picojson::value(error.message());
+    obj[JSON_DATA] = picojson::value(obj_data);
+  }
+}
+
+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;
+}
+
+AbstractFilterPtr FindMsgCallbackUserData::getFilter() const
+{
+    return m_filter;
+}
+
+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/webWidgetTCT_device/src/messaging/find_msg_callback_user_data.h b/webWidgetTCT_device/src/messaging/find_msg_callback_user_data.h
new file mode 100755 (executable)
index 0000000..48e6067
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+/**
+ * @file: FindMsgCallbackUserData.h
+ */
+
+#ifndef __TIZEN_FIND_MSG_CALLBACK_USER_DATA_H
+#define __TIZEN_FIND_MSG_CALLBACK_USER_DATA_H
+
+#include "common/callback_user_data.h"
+#include <memory>
+#include <string>
+#include <vector>
+#include "MsgCommon/AttributeFilter.h"
+#include "MsgCommon/SortMode.h"
+#include "messaging_util.h"
+#include "common/platform_result.h"
+
+using namespace extension::tizen;
+
+namespace extension {
+namespace messaging {
+
+class Message;
+
+class FindMsgCallbackUserData: public common::CallbackUserData {
+public:
+    FindMsgCallbackUserData(PostQueue& queue);
+    virtual ~FindMsgCallbackUserData();
+
+    void setFilter(AbstractFilterPtr filter);
+    void setSortMode(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);
+    void SetError(const common::PlatformResult& error);
+    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;
+    AbstractFilterPtr getFilter() const;
+    SortModePtr getSortMode() const;
+    long getLimit() const;
+    long getOffset() const;
+
+    PostQueue& getQueue() { return queue_;};
+private:
+    AbstractFilterPtr m_filter;
+    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;
+    PostQueue& queue_;
+};
+
+}//Messaging
+}//DeviceAPI
+
+#endif /* __TIZEN_FIND_MSG_CALLBACK_USER_DATA_H */
diff --git a/webWidgetTCT_device/src/messaging/folders_callback_data.cc b/webWidgetTCT_device/src/messaging/folders_callback_data.cc
new file mode 100755 (executable)
index 0000000..ad34e66
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2015 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 "folders_callback_data.h"
+
+namespace extension {
+namespace messaging {
+
+
+FoldersCallbackData::FoldersCallbackData(PostQueue& queue):
+        m_filter(),
+        m_is_error(false),
+        queue_(queue)
+{
+    LoggerD("Entered");
+}
+
+FoldersCallbackData::FoldersCallbackData(long cid, PostQueue& queue, bool keep):
+        m_filter(),
+        m_is_error(false),
+        queue_(queue)
+{
+    LoggerD("Entered");
+    auto json = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+    picojson::object& o = json->get<picojson::object>();
+    o[JSON_CALLBACK_ID] = picojson::value(static_cast<double>(cid));
+    o[JSON_CALLBACK_KEEP] = picojson::value(keep);
+    setJson(json);
+}
+
+FoldersCallbackData::~FoldersCallbackData() {
+    LoggerD("Entered");
+}
+
+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(tizen::AbstractFilterPtr filter)
+{
+    m_filter = filter;
+}
+
+tizen::AbstractFilterPtr FoldersCallbackData::getFilter() const
+{
+    return m_filter;
+}
+
+void FoldersCallbackData::setError(const std::string& err_name,
+        const std::string& err_message)
+{
+    LoggerD("Entered");
+    // keep only first error in chain
+    if (!m_is_error) {
+        LoggerD("Error has not been set yet");
+        m_is_error = true;
+        m_err_name = err_name;
+        m_err_message = err_message;
+
+        picojson::object& obj = m_json->get<picojson::object>();
+        obj[JSON_ACTION] = picojson::value(JSON_CALLBACK_ERROR);
+
+        auto obj_error = picojson::object();
+        obj_error[JSON_ERROR_NAME] = picojson::value(err_name);
+        obj_error[JSON_ERROR_MESSAGE] = picojson::value(err_message);
+        obj[JSON_DATA] = picojson::value(obj_error);
+    }
+}
+
+void FoldersCallbackData::SetError(const common::PlatformResult& error)
+{
+    LoggerD("Entered");
+  // keep only first error in chain
+  if (!m_is_error) {
+      LoggerD("Error has not been set yet");
+    m_is_error = true;
+    picojson::object& obj = m_json->get<picojson::object>();
+    obj[JSON_ACTION] = picojson::value(JSON_CALLBACK_ERROR);
+    auto obj_data = picojson::object();
+    obj_data[JSON_ERROR_CODE] = picojson::value(static_cast<double>(error.error_code()));
+    obj_data[JSON_ERROR_MESSAGE] = picojson::value(error.message());
+    obj[JSON_DATA] = picojson::value(obj_data);
+  }
+}
+
+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
+}//extension
diff --git a/webWidgetTCT_device/src/messaging/folders_callback_data.h b/webWidgetTCT_device/src/messaging/folders_callback_data.h
new file mode 100755 (executable)
index 0000000..0fcfcd9
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2015 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_FOLDERS_CALLBACK_DATA_H__
+#define __TIZEN_FOLDERS_CALLBACK_DATA_H__
+
+#include "common/callback_user_data.h"
+#include "common/platform_result.h"
+
+#include <memory>
+#include <vector>
+#include <string>
+
+#include "MsgCommon/AbstractFilter.h"
+
+#include "message_folder.h"
+#include "messaging_util.h"
+
+namespace extension {
+namespace messaging {
+
+class MessageFolder;
+
+class FoldersCallbackData: public common::CallbackUserData {
+public:
+    FoldersCallbackData(PostQueue& queue);
+    FoldersCallbackData(long cid, PostQueue& queue, bool keep = false);
+    virtual ~FoldersCallbackData();
+
+    void addFolder(std::shared_ptr<MessageFolder> folder);
+    const std::vector<std::shared_ptr<MessageFolder>>& getFolders() const;
+
+    void setFilter(tizen::AbstractFilterPtr filter);
+    tizen::AbstractFilterPtr getFilter() const;
+
+    void setError(const std::string& err_name,
+            const std::string& err_message);
+    void SetError(const common::PlatformResult& error);
+    bool isError() const;
+    std::string getErrorName() const;
+    std::string getErrorMessage() const;
+
+    PostQueue& getQueue() { return queue_;};
+private:
+    std::vector<std::shared_ptr<MessageFolder>> m_folders;
+    tizen::AbstractFilterPtr m_filter;
+    bool m_is_error;
+    std::string m_err_name;
+    std::string m_err_message;
+    PostQueue& queue_;
+
+};
+
+}//messaging
+}//extension
+
+#endif /* __TIZEN_FOLDERS_CALLBACK_DATA_H__ */
diff --git a/webWidgetTCT_device/src/messaging/folders_change_callback.cc b/webWidgetTCT_device/src/messaging/folders_change_callback.cc
new file mode 100755 (executable)
index 0000000..810cc57
--- /dev/null
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2015 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 "common/logger.h"
+#include "common/platform_exception.h"
+#include "messaging_instance.h"
+#include "messaging_util.h"
+
+#include "folders_change_callback.h"
+
+namespace extension {
+namespace messaging {
+
+const char* FOLDERSADDED = "foldersadded";
+const char* FOLDERSUPDATED = "foldersupdated";
+const char* FOLDERSREMOVED = "foldersremoved";
+
+FoldersChangeCallback::FoldersChangeCallback(
+        long cid,
+        int service_id,
+        MessageType service_type,
+        PostQueue& queue):
+    m_callback_data(cid, queue, true),
+    m_id(service_id),
+    m_msg_type(service_type),
+    m_is_act(true)
+{
+    LoggerD("Entered");
+}
+
+FoldersChangeCallback::~FoldersChangeCallback()
+{
+    LoggerD("Entered");
+}
+
+FolderPtrVector FoldersChangeCallback::filterFolders(
+        tizen::AbstractFilterPtr filter,
+        const FolderPtrVector& source_folders)
+{
+    LoggerD("Entered");
+    if (filter) {
+        LoggerD("filter pointer is valid");
+        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);
+            }
+
+            LoggerD("[%d] folder id:%s", i, folder->getId().c_str());
+            LoggerD("[%d] folder name:%s", i, folder->getName().c_str());
+            LoggerD("[%d] matched filter: %s", i, matched ? "YES" : "NO");
+        }
+
+        return filtered_folders;
+    }
+    else {
+        return source_folders;
+    }
+}
+
+void FoldersChangeCallback::added(const FolderPtrVector& folders)
+{
+    LoggerD("Entered folders.size()=%d", folders.size());
+    if (!m_is_act) {
+        return;
+    }
+
+    FolderPtrVector filtered = filterFolders(m_filter, folders);
+
+    picojson::array array;
+    auto each = [&array] (std::shared_ptr<MessageFolder> f)->void {
+        array.push_back(MessagingUtil::folderToJson(f));
+    };
+    for_each(filtered.begin(), filtered.end(), each);
+
+    LoggerD("Calling:%s with:%d added folders", FOLDERSADDED,
+            filtered.size());
+
+    auto json = m_callback_data.getJson();
+    picojson::object& obj = json->get<picojson::object>();
+    obj[JSON_ACTION] = picojson::value(FOLDERSADDED);
+    obj[JSON_DATA] = picojson::value(array);
+
+    if (json->contains(JSON_CALLBACK_ID) && obj.at(JSON_CALLBACK_ID).is<double>()) {
+      m_callback_data.getQueue().addAndResolve(obj.at(
+          JSON_CALLBACK_ID).get<double>(), PostPriority::MEDIUM, json->serialize());
+    } else {
+      LoggerE("Callback id is missing");
+    }
+}
+
+void FoldersChangeCallback::updated(const FolderPtrVector& folders)
+{
+    LoggerD("Entered folders.size()=%d", folders.size());
+    if (!m_is_act) {
+        return;
+    }
+
+    FolderPtrVector filtered = filterFolders(m_filter, folders);
+
+    picojson::array array;
+    auto each = [&array] (std::shared_ptr<MessageFolder> f)->void {
+        array.push_back(MessagingUtil::folderToJson(f));
+    };
+    for_each(filtered.begin(), filtered.end(), each);
+
+    LoggerD("Calling:%s with:%d updated folders", FOLDERSUPDATED,
+            filtered.size());
+
+    auto json = m_callback_data.getJson();
+    picojson::object& obj = json->get<picojson::object>();
+    obj[JSON_ACTION] = picojson::value(FOLDERSUPDATED);
+    obj[JSON_DATA] = picojson::value(array);
+
+    if (json->contains(JSON_CALLBACK_ID) && obj.at(JSON_CALLBACK_ID).is<double>()) {
+      m_callback_data.getQueue().addAndResolve(obj.at(
+          JSON_CALLBACK_ID).get<double>(), PostPriority::LOW, json->serialize());
+    } else {
+      LoggerE("Callback id is missing");
+    }
+}
+
+void FoldersChangeCallback::removed(const FolderPtrVector& folders)
+{
+    LoggerD("Entered folders.size()=%d", folders.size());
+    if (!m_is_act) {
+        return;
+    }
+
+    FolderPtrVector filtered = filterFolders(m_filter, folders);
+
+    picojson::array array;
+    auto each = [&array] (std::shared_ptr<MessageFolder> f)->void {
+        array.push_back(MessagingUtil::folderToJson(f));
+    };
+    for_each(filtered.begin(), filtered.end(), each);
+
+    LoggerD("Calling:%s with:%d removed folders", FOLDERSREMOVED,
+            filtered.size());
+
+    auto json = m_callback_data.getJson();
+    picojson::object& obj = json->get<picojson::object>();
+    obj[JSON_ACTION] = picojson::value(FOLDERSREMOVED);
+    obj[JSON_DATA] = picojson::value(array);
+
+    if (json->contains(JSON_CALLBACK_ID) && obj.at(JSON_CALLBACK_ID).is<double>()) {
+      m_callback_data.getQueue().addAndResolve(obj.at(
+          JSON_CALLBACK_ID).get<double>(), PostPriority::LAST, json->serialize());
+    } else {
+      LoggerE("Callback id is missing");
+    }
+}
+
+void FoldersChangeCallback::setFilter(tizen::AbstractFilterPtr filter)
+{
+    m_filter = filter;
+}
+
+tizen::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;
+}
+
+} //namespace messaging
+} //namespace extension
+
diff --git a/webWidgetTCT_device/src/messaging/folders_change_callback.h b/webWidgetTCT_device/src/messaging/folders_change_callback.h
new file mode 100755 (executable)
index 0000000..69d3d14
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2015 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 __MESSAGING_FOLDERS_CHANGE_CALLBACK_H__
+#define __MESSAGING_FOLDERS_CHANGE_CALLBACK_H__
+
+
+#include "MsgCommon/AbstractFilter.h"
+
+#include "messaging_util.h"
+#include "message_folder.h"
+
+#include "folders_callback_data.h"
+
+//#include <MultiCallbackUserData.h>
+
+namespace extension {
+namespace messaging {
+
+extern const char* FOLDERSADDED;
+extern const char* FOLDERSUPDATED;
+extern const char* FOLDERSREMOVED;
+
+class FoldersChangeCallback {
+public:
+    FoldersChangeCallback(
+            long cid,
+            int service_id,
+            MessageType service_type,
+            PostQueue& queue);
+    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();
+
+private:
+    static FolderPtrVector filterFolders(tizen::AbstractFilterPtr filter,
+            const FolderPtrVector& source_folders);
+
+    FoldersCallbackData m_callback_data;
+    tizen::AbstractFilterPtr m_filter;
+    int m_id;
+    MessageType m_msg_type;
+    bool m_is_act;
+    FolderPtrVector m_items;
+};
+
+} //messaging
+} //extension
+
+#endif // __MESSAGING_FOLDERS_CHANGE_CALLBACK_H__
diff --git a/webWidgetTCT_device/src/messaging/message.cc b/webWidgetTCT_device/src/messaging/message.cc
new file mode 100755 (executable)
index 0000000..129b1c7
--- /dev/null
@@ -0,0 +1,1755 @@
+/*
+ * Copyright (c) 2015 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 "message.h"
+
+#include <time.h>
+#include <sys/stat.h>
+#include <sstream>
+
+#include "common/logger.h"
+#include "common/platform_exception.h"
+#include "common/scope_exit.h"
+
+#include "Ecore_File.h"
+#include "message_email.h"
+#include "message_sms.h"
+#include "message_mms.h"
+#include "short_message_manager.h"
+#include "messaging_util.h"
+
+using common::ErrorCode;
+using common::PlatformResult;
+
+namespace extension {
+namespace messaging {
+
+using namespace common;
+
+// *** constructor
+Message::Message():
+    m_id(-1), m_old_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(-1), 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)
+{
+    LoggerD("Message constructor (%p)", this);
+}
+
+Message::~Message()
+{
+    LoggerD("Message destructor (%p)", this);
+}
+
+// *** attribute getters
+int Message::getId() const
+{
+    return m_id;
+}
+
+int Message::getOldId() const
+{
+    if (-1 == m_old_id) {
+        return m_id;
+    }
+    return m_old_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;
+}
+
+std::string Message::getTypeString() const {
+  return MessagingUtil::messageTypeToString(getType());
+}
+
+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;
+}
+
+std::vector<std::string> Message::getCC() const
+{
+    return m_cc;
+}
+
+std::vector<std::string> Message::getBCC() const
+{
+    return m_bcc;
+}
+
+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;
+}
+
+int Message::getServiceId() const
+{
+    return m_service_id;
+}
+
+TelNetworkDefaultDataSubs_t Message::getSimIndex() const
+{
+    return m_sim_index;
+}
+
+// *** attributes setters
+void Message::setId(int id)
+{
+    LoggerD("Entered");
+    m_id = id;
+    m_id_set = true;
+    m_body->setMessageId(m_id);
+    for (auto& att : m_attachments) {
+        att->setMessageId(m_id);
+    }
+}
+
+void Message::setOldId(int id)
+{
+    LoggerD("Entered");
+    m_old_id = id;
+}
+
+
+void Message::setConversationId(int id)
+{
+    LoggerD("Entered");
+    m_conversation_id = id;
+    m_conversation_id_set = true;
+}
+
+void Message::setFolderId(int id)
+{
+    LoggerD("Entered");
+    m_folder_id = id;
+    m_folder_id_set = true;
+}
+
+// type setting not allowed - no setter for type
+
+void Message::setTimeStamp(time_t timestamp)
+{
+    LoggerD("Entered");
+    m_timestamp = timestamp;
+    m_timestamp_set = true;
+}
+
+void Message::setFrom(std::string from)
+{
+    LoggerD("Entered");
+    m_from = from;
+    m_from_set = true;
+}
+
+void Message::setTO(std::vector<std::string> &to)
+{
+    LoggerD("Entered");
+    // Recipient's format validation should be done by Core API service
+    m_to = to;
+
+    if(m_to.empty()) {
+        LoggerD("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)
+{
+    LoggerD("Entered");
+    // 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)
+{
+    LoggerD("Entered");
+    m_is_read = read;
+}
+
+// has attachment can't be set explicity -> no setter for this flag
+
+void Message::setIsHighPriority(bool highpriority)
+{
+    LoggerD("Entered");
+    // 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)
+{
+    LoggerD("Entered");
+    m_in_response = inresp;
+    m_in_response_set = true;
+}
+
+void Message::setMessageStatus(MessageStatus status)
+{
+    LoggerD("Entered");
+    m_status = status;
+}
+
+void Message::setMessageAttachments(AttachmentPtrVector &attachments)
+{
+    // implementation provided only for MMS and email
+}
+
+void Message::setServiceId(int service_id)
+{
+    LoggerD("Entered");
+    m_service_id = service_id;
+    m_service_id_set = true;
+}
+
+void Message::setSimIndex(TelNetworkDefaultDataSubs_t sim_index)
+{
+    LoggerD("Entered");
+    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)
+{
+    LoggerD("Entered");
+    std::string address = "";
+    unsigned size = recipients.size();
+    for (unsigned i=0; i<size; ++i)
+    {
+        address += "<"+recipients[i]+">; ";
+    }
+
+    return address;
+}
+
+PlatformResult saveToTempFile(const std::string &data, std::string* file_name)
+{
+    LoggerD("Entered");
+    char buf[] = "XXXXXX";
+
+    mode_t mask = umask(S_IWGRP | S_IWOTH);
+    mkstemp(buf);   //Just generate unique name
+
+    std::string tmp_name = std::string("/tmp/") + buf;
+
+    mode_t old_mask = umask(mask);
+    FILE *file = fopen(tmp_name.c_str(), "w");
+    umask(old_mask);
+
+    if (NULL == file) {
+        LoggerE("Failed to create file");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to create file");
+    }
+    if (fprintf(file, "%s", data.c_str()) < 0) {
+        LoggerE("Failed to write data into file");
+        fclose(file);
+        remove(tmp_name.c_str());
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to write data into file");
+    }
+    fflush(file);
+    fclose(file);
+    *file_name = tmp_name;
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult copyFileToTemp(const std::string& sourcePath, std::string* result_path)
+{
+    LoggerD("Entered");
+    char buf[] = "XXXXXX";
+    std::string fileName, attPath, tmpPath;
+
+    mode_t mask = umask(S_IWGRP | S_IWOTH);
+    int err = mkstemp(buf);
+    if (-1 == err) {
+        LoggerW("Failed to create unique filename");
+    }
+
+    umask(mask);
+    std::string dirPath = "/tmp/" + std::string(buf);
+
+    if ( sourcePath[0] != '/' ) {
+//  FIXME When filesystem will be available
+//         attPath = sourcePath; change to attPath = Filesystem::External::fromVirtualPath(sourcePath);
+        attPath = 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) {
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                "Error while copying file to temp: the source path is invalid.");
+    }
+
+    fileName = attPath.substr(slashPos + 1);
+    tmpPath = dirPath + "/" + fileName;
+
+    LoggerD("attPath: %s, tmpPath: %s", attPath.c_str(), tmpPath.c_str());
+    if(EINA_TRUE != ecore_file_mkdir(dirPath.c_str())) {
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "Unknown error while creating temp directory.");
+    }
+
+    FILE *f1, *f2;
+    size_t num;
+    int ret = 1;
+
+    f1 = fopen(attPath.c_str(), "rb");
+    if (!f1) {
+        LoggerE("Fail open attPath");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Fail open attPath");
+    }
+    f2 = fopen(tmpPath.c_str(), "wb");
+    if (!f2) {
+        LoggerE("Fail open tmpPath");
+        fclose (f1);
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Fail open tmpPath");
+    }
+
+    while ((num = fread(buf, 1, sizeof(buf), f1)) > 0) {
+        if (fwrite(buf, 1, num, f2) != num)
+            ret = 0;
+    }
+
+    fclose (f1);
+    fclose (f2);
+
+    if(EINA_TRUE != ret /*ecore_file_cp(attPath.c_str(), tmpPath.c_str())*/) {
+        std::string error = "Unknown error while copying file to temp. ";
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, error.c_str());
+    }
+
+    *result_path = dirPath;
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult removeDirFromTemp(const std::string& dirPath)
+{
+    LoggerD("Entered");
+    if(EINA_TRUE != ecore_file_recursive_rm(dirPath.c_str())) {
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error while deleting temp directory.");
+    }
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult Message::convertPlatformEmail(std::shared_ptr<Message> message,
+                                                 email_mail_data_t** result_mail_data)
+{
+    LoggerD("Entered");
+    email_mail_data_t* mail_data = nullptr;
+    if(EMAIL != message->getType()) {
+        LoggerE("Invalid type");
+        return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid type.");
+    }
+
+    if(message->is_id_set()) {
+        email_get_mail_data(message->getId(), &mail_data);
+    } else {
+        mail_data = (email_mail_data_t*)malloc(sizeof(email_mail_data_t));
+        if (!mail_data) {
+          LoggerE("malloc failure");
+          return PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to allocate memory.");
+        }
+        memset(mail_data, 0x00, sizeof(email_mail_data_t));
+    }
+
+  std::unique_ptr<email_mail_data_t, void (*)(email_mail_data_t*)> mail_data_ptr(
+      mail_data, [](email_mail_data_t* mail) {email_free_mail_data(&mail, 1);});
+
+    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()) {
+        LoggerD("get Body success");
+        std::shared_ptr<MessageBody> body;
+        body = message->getBody();
+        if(!body->getPlainBody().empty()) {
+            std::string body_file_path = "";
+            PlatformResult ret = saveToTempFile(body->getPlainBody(), &body_file_path);
+            if (ret.IsError()) return ret;
+            mail_data->file_path_plain = strdup(body_file_path.c_str());
+            if(!mail_data->file_path_plain)
+            {
+                LoggerE("Plain Body file is NULL.");
+                return PlatformResult(ErrorCode::UNKNOWN_ERR, "Plain Body file is NULL.");
+            }
+        }
+
+        if(!body->getHtmlBody().empty()) {
+            std::string html_file_path = "";
+            PlatformResult ret = saveToTempFile(body->getHtmlBody(), &html_file_path);
+            mail_data->file_path_html = strdup(html_file_path.c_str());
+            if(!mail_data->file_path_html)
+            {
+                LoggerE("Html Body file is NULL.");
+                return PlatformResult(ErrorCode::UNKNOWN_ERR, "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 = "";
+            PlatformResult ret = saveToTempFile(body->getPlainBody(), &html_file_path);
+            mail_data->file_path_html = strdup(html_file_path.c_str());
+            if(!mail_data->file_path_html)
+            {
+                LoggerE("Plain Body file is NULL.");
+                return PlatformResult(ErrorCode::UNKNOWN_ERR, "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;
+    }
+
+    *result_mail_data = mail_data_ptr.release();  // release ownership
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult addSingleEmailAttachment(std::shared_ptr<Message> message,
+        std::shared_ptr<MessageAttachment> att, AttachmentType attType)
+{
+    LoggerD("Entered");
+    std::string dirPath = "";
+    PlatformResult ret = copyFileToTemp(att->getFilePath(), &dirPath);
+    if (ret.IsError()) return ret;
+
+    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());
+    if (att->isMimeTypeSet()) {
+        tmp->attachment_mime_type = strdup(att->getMimeType().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) {
+        LoggerE("Error while adding attachment %d", err);
+        err = email_free_attachment_data(&tmp, 1);
+        if (EMAIL_ERROR_NONE != err) {
+            LoggerW("Failed to free attachment data");
+        }
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown error while adding attachment");
+    }
+
+    att->setId(tmp->attachment_id);
+    att->setMessageId(id);
+    err = email_free_attachment_data(&tmp, 1);
+    if (EMAIL_ERROR_NONE != err) {
+        LoggerW("Failed to free attachment data");
+    }
+
+    return removeDirFromTemp(dirPath);
+}
+
+PlatformResult Message::addEmailAttachments(std::shared_ptr<Message> message)
+{
+    LoggerD("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();
+    LoggerD("Attachments size: %d", attachments.size());
+    LoggerD("Inline attachments size: %d", inlineAttachments.size());
+    LoggerD("Adding attachments for mail id = [%d]\n", message->getId());
+    for (auto it = attachments.begin(); it != attachments.end(); ++it) {
+        PlatformResult ret = addSingleEmailAttachment(message, *it, AttachmentType::EXTERNAL);
+        if (ret.IsError()) return ret;
+    }
+    for (auto it = inlineAttachments.begin(); it != inlineAttachments.end(); ++it) {
+        PlatformResult ret = addSingleEmailAttachment(message, *it, AttachmentType::INLINE);
+        if (ret.IsError()) return ret;
+    }
+
+    //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
+    PlatformResult ret = Message::convertPlatformEmail(message, &mail);
+    if (ret.IsError()) return ret;
+
+    error = email_get_attachment_data_list(mail->mail_id, &attachment_data_list, &attachment_data_count);
+    if (EMAIL_ERROR_NONE != error) {
+        email_free_mail_data(&mail, 1);
+        email_free_attachment_data(&attachment_data_list,attachment_data_count);
+        LoggerE("Error while adding attachments. Failed to get attachment list.");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                              "Error while adding attachments. Failed to get attachment 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) {
+        email_free_mail_data(&mail, 1);
+        email_free_attachment_data(&attachment_data_list,attachment_data_count);
+        LoggerE("Error while re-adding mail: %d", error);
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Error while re-adding mail");
+    }
+    LoggerD("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);
+    }
+    email_free_attachment_data(&attachment_data_list,attachment_data_count);
+
+    //deleting mail without attachments
+    error = email_delete_mail(mail->mailbox_id,&tmp_id,1,1);
+    if (EMAIL_ERROR_NONE != error) {
+        email_free_mail_data(&mail, 1);
+        LoggerE("Error while deleting mail from server: %d", error);
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Error while deleting mail from server");
+    }
+    email_free_mail_data(&mail, 1);
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult Message::addSMSRecipientsToStruct(const std::vector<std::string> &recipients,
+        msg_struct_t &msg)
+{
+    LoggerD("Entered");
+    const unsigned size = recipients.size();
+    for (unsigned int i = 0; i < size; ++i) {
+        char *address = const_cast<char *>(recipients.at(i).c_str());
+
+        LoggerD("[%d] address:[%s]", i, address);
+        msg_struct_t tmpAddr = NULL;
+        if (MSG_SUCCESS
+                == msg_list_add_item(msg, MSG_MESSAGE_ADDR_LIST_HND, &tmpAddr)) {
+            msg_set_int_value(tmpAddr, MSG_ADDRESS_INFO_ADDRESS_TYPE_INT,
+                    MSG_ADDRESS_TYPE_PLMN);
+            msg_set_int_value(tmpAddr, MSG_ADDRESS_INFO_RECIPIENT_TYPE_INT,
+                    MSG_RECIPIENTS_TYPE_TO);
+            msg_set_str_value(tmpAddr, MSG_ADDRESS_INFO_ADDRESS_VALUE_STR,
+                    address, strlen(address));
+        }
+        else {
+            LoggerE("failed to add address[%d] %s", i, address);
+            return PlatformResult(ErrorCode::UNKNOWN_ERR, "failed to add address");
+        }
+    }
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult Message::addMMSRecipientsToStruct(const std::vector<std::string> &recipients,
+        msg_struct_t &msg, int type)
+{
+    LoggerD("Entered");
+    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());
+        LoggerD("[%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) {
+            msg_set_int_value(tmpAddr, MSG_ADDRESS_INFO_ADDRESS_TYPE_INT,
+                    address_type);
+            msg_set_int_value(tmpAddr, MSG_ADDRESS_INFO_RECIPIENT_TYPE_INT,
+                    type);
+            msg_set_str_value(tmpAddr, MSG_ADDRESS_INFO_ADDRESS_VALUE_STR,
+                    address, strlen(address));
+        }
+        else {
+            LoggerE("[%d] failed to add address: [%s], error: %d", i, address, error);
+            return PlatformResult (ErrorCode::UNKNOWN_ERR, "failed to add address");
+        }
+    }
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult Message::addMMSBodyAndAttachmentsToStruct(const AttachmentPtrVector &attach,
+        msg_struct_t &mms_struct, Message* message)
+{
+    LoggerD("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();
+                LoggerD("att[%d]: org filepath: %s", i, filepath.c_str());
+// TODO uncomment when filesystem will be available
+//                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);
+//                    LoggerD("att[%d]: org virtual filepath: %s", i, filepath.c_str());
+//                }
+                msg_set_str_value(tmpAtt, MSG_MMS_ATTACH_FILEPATH_STR,
+                        const_cast<char*>(filepath.c_str()), filepath.size());
+                const size_t last_slash_idx = filepath.find_last_of("\\/");
+                if (std::string::npos != last_slash_idx) {
+                    filepath.erase(0, last_slash_idx + 1);
+                }
+
+                LoggerD("att[%d] filename: %s", i, filepath.c_str());
+                msg_set_str_value(tmpAtt, MSG_MMS_ATTACH_FILENAME_STR,
+                        const_cast<char*>(filepath.c_str()), filepath.size());
+                struct stat st;
+                if (stat(const_cast<char*>(filepath.c_str()), &st)) {
+                    LoggerE("Stat error");
+                }
+                const int fsize = st.st_size;
+                msg_set_int_value(tmpAtt, MSG_MMS_ATTACH_FILESIZE_INT, fsize);
+                LoggerD("att[%d]: filesize: %d", i,fsize);
+            }
+
+            //-------------------------------------------------------------------------
+            //set mime type
+            if (attach.at(i)->isMimeTypeSet()) {
+                unsigned int type = MessageAttachment::MIMETypeStringToEnum(
+                        attach.at(i)->getMimeType());
+                msg_set_int_value(tmpAtt, MSG_MMS_ATTACH_MIME_TYPE_INT, type);
+                msg_set_str_value(tmpAtt, MSG_MMS_ATTACH_CONTENT_TYPE_STR,
+                                  const_cast<char*>(attach.at(i)->getMimeType().c_str()),
+                                  MSG_MSG_ID_LEN);
+
+                LoggerD("att[%d]: setting mime type:0x%x (orignal:%s)", i, type,
+                    attach.at(i)->getMimeType().c_str());
+            }
+        } else {
+            LoggerE("att[%d]: failed to add attachment");
+            return PlatformResult(ErrorCode::UNKNOWN_ERR, "failed to add attachment");
+        }
+    }
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult Message::convertPlatformShortMessageToStruct(Message* message,
+        msg_handle_t handle, msg_struct_t* result_msg)
+{
+    LoggerD("Entered");
+
+    if (message->getType() != SMS && message->getType() != MMS) {
+        LoggerD("Invalid type");
+        return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid type");
+    }
+
+    msg_error_t err = MSG_SUCCESS;
+
+    msg_struct_t msg = msg_create_struct(MSG_STRUCT_MESSAGE_INFO);
+    std::unique_ptr<msg_struct_t, int (*)(msg_struct_t*)> msg_ptr(&msg, msg_release_struct);
+
+    if (message->is_id_set()) { // id is set - the message exists in database
+        msg_message_id_t id = (msg_message_id_t) message->getId();
+        msg_struct_t send_opt = msg_create_struct(MSG_STRUCT_SENDOPT);
+        std::unique_ptr<msg_struct_t, int (*)(msg_struct_t*)> send_opt_ptr(&send_opt, msg_release_struct);
+        err = msg_get_message(handle, id, msg, send_opt);
+        if (err != MSG_SUCCESS) {
+            LoggerD("msg_get_message() Fail [%d]", err);
+            return PlatformResult(ErrorCode::UNKNOWN_ERR, "msg_get_message() Fail");
+        }
+        LoggerD("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
+            if (MSG_SUCCESS
+                    != msg_set_int_value(msg, MSG_MESSAGE_TYPE_INT, MSG_TYPE_SMS)) {
+                LoggerE("Set SMS type error");
+                return PlatformResult(ErrorCode::UNKNOWN_ERR, "Set SMS type error");
+            }
+        } else {
+            // Set message type to MMS
+            if (MSG_SUCCESS
+                    != msg_set_int_value(msg, MSG_MESSAGE_TYPE_INT, MSG_TYPE_MMS)) {
+                LoggerE("Set MMS type error");
+                return PlatformResult(ErrorCode::UNKNOWN_ERR, "Set MMS type error");
+            }
+        }
+    }
+
+    int type;
+    msg_get_int_value(msg, MSG_MESSAGE_TYPE_INT, &type);
+    LoggerD("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()) {
+            msg_set_str_value(msg, MSG_MESSAGE_SMS_DATA_STR, const_cast<char*>
+                    (body->getPlainBody().c_str()), body->getPlainBody().size());
+        }
+
+        // Reset SMS recipients
+        int error = msg_list_clear(msg, MSG_MESSAGE_ADDR_LIST_HND);
+        if( MSG_SUCCESS != error) {
+            LoggerE("Failed to clear address list, error: %d", error);
+            return PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to clear address list");
+        }
+
+        // Set SMS recipients
+        std::vector<std::string> recp_list = message->getTO();
+        if (!recp_list.empty()) {
+            PlatformResult ret = message->addSMSRecipientsToStruct(recp_list, msg);
+            if (ret.IsError()) return ret;
+        }
+
+    } else if (type == MSG_TYPE_MMS) {
+        // Set message type to MMS
+        if (MSG_SUCCESS
+                != msg_set_int_value(msg, MSG_MESSAGE_TYPE_INT, MSG_TYPE_MMS)) {
+            LoggerE("Message(%p): Set MMS type error", message);
+            return PlatformResult(ErrorCode::UNKNOWN_ERR, "Set MMS type error");
+        }
+        // Create MMS data
+        msg_struct_t mms_data = msg_create_struct(MSG_STRUCT_MMS);
+        if (mms_data == NULL) {
+            LoggerE("Message(%p): Set MMS data error", message);
+            return PlatformResult(ErrorCode::UNKNOWN_ERR, "Set MMS data error");
+        } else {
+            std::unique_ptr<msg_struct_t, int (*)(msg_struct_t*)> mms_data_ptr(&mms_data, msg_release_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) {
+                    LoggerE("Message(%p): Set MMS subject error: %d", message, r);
+                    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Set MMS subject error");
+                }
+            }
+            // Set MMS message text
+            std::shared_ptr<MessageBody> body;
+            body = message->getBody();
+            if (!body->getPlainBody().empty()) {
+                LoggerD("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;
+                msg_list_add_item(mms_data, MSG_STRUCT_MMS_REGION, &region);
+                msg_set_str_value(region, MSG_MMS_REGION_ID_STR, const_cast<char*>("Text"), 4);
+
+                msg_set_int_value(region, MSG_MMS_REGION_LENGTH_LEFT_INT, 0);
+                msg_set_int_value(region, MSG_MMS_REGION_LENGTH_TOP_INT, 0);
+                msg_set_int_value(region, MSG_MMS_REGION_LENGTH_WIDTH_INT,
+                        ROOT_LAYOUT_WIDTH);
+                msg_set_int_value(region, MSG_MMS_REGION_LENGTH_HEIGHT_INT,
+                        ROOT_LAYOUT_HEIGHT);
+                msg_set_int_value(region, MSG_MMS_REGION_BGCOLOR_INT, WHITE_COLOR);
+
+                msg_set_bool_value(region, MSG_MMS_REGION_LENGTH_LEFT_PERCENT_BOOL, true);
+                msg_set_bool_value(region, MSG_MMS_REGION_LENGTH_TOP_PERCENT_BOOL, true);
+                msg_set_bool_value(region, MSG_MMS_REGION_LENGTH_WIDTH_PERCENT_BOOL, true);
+                msg_set_bool_value(region, MSG_MMS_REGION_LENGTH_HEIGHT_PERCENT_BOOL, true);
+
+                //----------------------------------------------------------------------------
+                //Page
+                msg_struct_t page;
+                msg_list_add_item(mms_data, MSG_STRUCT_MMS_PAGE, &page);
+                msg_set_int_value(page, MSG_MMS_PAGE_PAGE_DURATION_INT, 0);
+
+                //----------------------------------------------------------------------------
+                //Media
+                msg_struct_t media;
+                msg_list_add_item(page, MSG_STRUCT_MMS_MEDIA, &media);
+                msg_set_int_value(media, MSG_MMS_MEDIA_TYPE_INT, MMS_SMIL_MEDIA_TEXT);
+                msg_set_str_value(media, MSG_MMS_MEDIA_REGION_ID_STR,
+                        const_cast<char*>("Text"), 4);
+
+                std::string body_file_path = "";
+                PlatformResult ret = saveToTempFile(body->getPlainBody(), &body_file_path);
+                if (ret.IsError()) return ret;
+
+                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) {
+                    LoggerE("Message(%p): Failed to set mms body filepath", message);
+                    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to set mms body filepath");
+                }
+                msg_set_str_value(media, MSG_MMS_MEDIA_CONTENT_TYPE_STR,
+                                  const_cast<char*>("text/plain"), 10);
+
+                //----------------------------------------------------------------------------
+                //Smile text
+                msg_struct_t smil_text;
+                msg_get_struct_handle(media, MSG_MMS_MEDIA_SMIL_TEXT_HND, &smil_text);
+                msg_set_int_value(smil_text, MSG_MMS_SMIL_TEXT_COLOR_INT, BLACK_COLOR);
+                msg_set_int_value(smil_text, MSG_MMS_SMIL_TEXT_SIZE_INT,
+                        MMS_SMIL_FONT_SIZE_NORMAL);
+                msg_set_bool_value(smil_text, MSG_MMS_SMIL_TEXT_BOLD_BOOL, true);
+            } else {
+                LoggerD("Message(%p): PlainBody is EMPTY", message);
+            }
+            // Set MMS attachments
+            AttachmentPtrVector attach_list = message->getMessageAttachments();
+            LoggerD("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());
+
+            msg_set_int_value(mms_data, MSG_MESSAGE_ATTACH_COUNT_INT,
+                    attach_list.size());
+            if (!attach_list.empty()) {
+                PlatformResult ret =addMMSBodyAndAttachmentsToStruct(attach_list, mms_data, message);
+                if (ret.IsError()) return ret;
+            }
+            // Set MMS body
+            int r = msg_set_mms_struct(msg, mms_data);
+            if (r != MSG_SUCCESS) {
+                LoggerE("Message(%p): Set MMS body error: %d", message, r);
+                return PlatformResult (ErrorCode::UNKNOWN_ERR, "Set MMS body error");
+            }
+        }
+
+        // Reset MMS recipients
+        msg_list_clear(msg, MSG_MESSAGE_ADDR_LIST_HND);
+
+        std::vector<std::string> recp_list = message->getTO();
+        PlatformResult ret = message->addMMSRecipientsToStruct(recp_list, msg, MSG_RECIPIENTS_TYPE_TO);
+        if (ret.IsError()) return ret;
+
+        recp_list = message->getCC();
+        ret = message->addMMSRecipientsToStruct(recp_list, msg, MSG_RECIPIENTS_TYPE_CC);
+        if (ret.IsError()) return ret;
+
+        recp_list = message->getBCC();
+        ret =message->addMMSRecipientsToStruct(recp_list, msg, MSG_RECIPIENTS_TYPE_BCC);
+        if (ret.IsError()) return ret;
+    }
+    else {
+        LoggerE("Message(%p): Invalid message type", message);
+        return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid message type");
+    }
+
+    // set common attributes for SMS and MMS
+    // Set message conversation id
+    if (message->is_conversation_id_set()) {
+        msg_set_int_value(msg, MSG_MESSAGE_THREAD_ID_INT, message->getConversationId());
+    }
+    // Set message folder id
+    if (message->is_folder_id_set()) {
+        msg_set_int_value(msg, MSG_MESSAGE_FOLDER_ID_INT, message->getFolderId());
+    }
+    // Set message timestamp
+    if (message->is_timestamp_set()) {
+        msg_set_int_value(msg, MSG_MESSAGE_DISPLAY_TIME_INT, message->getTimestamp());
+    }
+    // Set message from
+    if (message->is_from_set()) {
+        msg_set_str_value(msg, MSG_MESSAGE_REPLY_ADDR_STR, const_cast<char*>
+                (message->getFrom().c_str()), message->getFrom().size());
+    }
+    // Set message if is response
+    if (message->is_in_response_set()) {
+        msg_set_int_value(msg, MSG_MESSAGE_DIRECTION_INT, message->getInResponseTo());
+    }
+
+    // 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) {
+            LoggerE("Failed to set sim index, error: %d", error);
+            return PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to set sim index");
+        }
+    }
+
+    // Set message if is read
+    msg_set_bool_value(msg, MSG_MESSAGE_READ_BOOL, message->getIsRead());
+
+    LoggerD("End");
+    *result_msg = msg;
+    msg_ptr.release();  // release ownership
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+std::string Message::getShortMsgSenderFromStruct(msg_struct_t &msg)
+{
+    LoggerD("Entered");
+    msg_list_handle_t addr_list = NULL;
+    msg_get_list_handle(msg, MSG_MESSAGE_ADDR_LIST_HND, (void **)&addr_list);
+
+    char str_phone_number[MAX_ADDRESS_VAL_LEN];
+    const int count = msg_list_length(addr_list);
+    LoggerD("Number of addresses: %d", count);
+
+    for (int i = 0; i < count; ++i)
+    {
+        int tempInt = 0;
+        msg_get_int_value(msg, MSG_MESSAGE_DIRECTION_INT, &tempInt);
+        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);
+            msg_get_str_value(cur_addr_info, MSG_ADDRESS_INFO_ADDRESS_VALUE_STR,
+                    str_phone_number, MAX_ADDRESS_VAL_LEN);
+
+            LoggerD("[%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 {
+            LoggerD("[%d/%d] is NOT of TYPE_MT skipping, is:%d", i, count, type);
+        }
+    }
+
+    return std::string();
+}
+
+PlatformResult Message::getSMSRecipientsFromStruct(msg_struct_t &msg,
+                                                   std::vector<std::string>* result_address)
+{
+    LoggerD("Entered");
+    std::vector<std::string> address;
+    msg_list_handle_t addr_list = NULL;
+    if (MSG_SUCCESS
+            == msg_get_list_handle(msg, MSG_MESSAGE_ADDR_LIST_HND,
+                    (void **) &addr_list)) {
+        int size = msg_list_length(addr_list);
+        for (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);
+            msg_get_str_value(addr_info, MSG_ADDRESS_INFO_ADDRESS_VALUE_STR,
+                    infoStr, MAX_ADDRESS_VAL_LEN);
+            address.push_back(std::string(infoStr));
+        }
+    } else {
+        LoggerE("failed to get recipients");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "failed to add recipients");
+    }
+    *result_address = address;
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult Message::getMMSRecipientsFromStruct(msg_struct_t &msg,
+        int type, std::vector<std::string>* result_address)
+{
+    LoggerD("Entered");
+    std::vector<std::string> address;
+    msg_list_handle_t addr_list = NULL;
+    if (MSG_SUCCESS
+            == msg_get_list_handle(msg, MSG_MESSAGE_ADDR_LIST_HND,
+                    (void **) &addr_list)) {
+        int size = msg_list_length(addr_list);
+        for (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);
+            msg_get_int_value(addr_info, MSG_ADDRESS_INFO_RECIPIENT_TYPE_INT,
+                    &tempInt);
+            if (tempInt == type) {
+                msg_get_str_value(addr_info, MSG_ADDRESS_INFO_ADDRESS_VALUE_STR,
+                        infoStr, MAX_ADDRESS_VAL_LEN);
+                address.push_back(std::string(infoStr));
+            }
+        }
+    } else {
+        LoggerE("failed to get recipients");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "failed to add recipients");
+    }
+    *result_address = address;
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult Message::setMMSBodyAndAttachmentsFromStruct(Message* message,
+        msg_struct_t &msg)
+{
+    LoggerD("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) {
+        LoggerE("Cannot get mms struct, error:%d", error);
+        msg_release_struct(&mms_struct);
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "cannot get mms 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);
+        LoggerD("MSG_MMS_PAGE_LIST length:%d", pageLen);
+
+        for (int p = 0; p < pageLen; ++p) {
+            msg_struct_t page = (msg_struct_t) msg_list_nth_data(page_list, p);
+            if (!page) {
+                LoggerE("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);
+                LoggerD("[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) {
+                        LoggerE("returned media is null, continue");
+                        continue;
+                    }
+                    // add media from pages to attachments vector
+                    //set file path
+                    memset(infoStr, 0, MSG_FILEPATH_LEN_MAX + 1);
+                    msg_get_str_value(media, MSG_MMS_MEDIA_FILEPATH_STR, infoStr,
+                            MSG_FILEPATH_LEN_MAX);
+                    LoggerD("[p:%d, m:%d] attachment file path:%s", p, m, infoStr);
+
+                    msg_get_int_value(media, MSG_MMS_MEDIA_TYPE_INT, &tempInt);
+                    const int msg_media_type = tempInt;
+                    std::string msg_media_type_str =
+                            MessageAttachment::MIMETypeEnumToString(msg_media_type);
+
+                    LoggerD("[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)) {
+                      LoggerD("Loading body from file: %s ", infoStr);
+
+                      std::string result = "";
+                      PlatformResult ret = MessagingUtil::loadFileContentToString(infoStr, &result);
+                      if (ret.IsSuccess()) {
+
+                        message->getBody()->setPlainBody(result);
+                        body_has_been_set = true;
+
+                        LoggerD("Loaded body: %s",
+                                message->getBody()->getPlainBody().c_str());
+                      } else {
+                        LoggerE("Unhandled error: %d (%s)!",
+                                ret.error_code(), ret.message().c_str());
+                        LoggerD("[p:%d, m:%d] body is not set", p, m);
+                      }
+                    } else {
+                        std::shared_ptr<MessageAttachment> ma (new MessageAttachment());
+                        ma->setFilePath(infoStr);
+
+                        //set message id
+                        msg_get_int_value(msg, MSG_MESSAGE_STORAGE_ID_INT, &tempInt);
+                        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();
+                        LoggerD("[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());
+                    }
+
+                    msg_release_struct(&media);
+                }
+            } else {
+                msg_release_struct(&mms_struct);
+                LoggerE("failed to get attachment");
+                return PlatformResult(ErrorCode::UNKNOWN_ERR, "failed to get attachment");
+            }
+            msg_release_struct(&page);
+        }
+    } else {
+        msg_release_struct(&mms_struct);
+        LoggerE("failed to get attachment");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "failed to get attachment");
+    }
+
+    if(false == body_has_been_set) {
+        LoggerW("Warning: body has not been set!");
+    }
+
+    LoggerD("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 size = msg_list_length(attach_list);
+        LoggerD("MSG_MMS_ATTACH_LIST length:%d", size);
+
+        for (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) {
+                LoggerW("[att:%d] attach_info is NULL!", i);
+                continue;
+            }
+
+            std::shared_ptr<MessageAttachment> ma (new MessageAttachment());
+
+            //set message id
+            msg_get_int_value(msg, MSG_MESSAGE_ID_INT, &tempInt);
+            ma->setMessageId(tempInt);
+
+            //set file path
+            msg_get_str_value(attach_info, MSG_MMS_ATTACH_FILEPATH_STR, infoStr,
+                    MSG_FILEPATH_LEN_MAX);
+            ma->setFilePath(infoStr);
+
+            //set attachment id
+            ma->setId(message->m_attachments.size() + 1);
+
+            //set mime type
+            msg_get_int_value(attach_info, MSG_MMS_ATTACH_MIME_TYPE_INT, &tempInt);
+            std::string type = MessageAttachment::MIMETypeEnumToString(tempInt);
+            ma->setMimeType(type);
+
+            MessageAttachment* att = ma.get();
+            LoggerD("[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;
+
+            msg_release_struct(&attach_info);
+        }
+    } else {
+        msg_release_struct(&mms_struct);
+        LoggerE("failed to get attachment");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "failed to add attachment");
+    }
+
+    LoggerD("after MSG_MMS_ATTACH_LIST attachments count is:%d",
+            message->m_attachments.size());
+    msg_release_struct(&mms_struct);
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult Message::convertPlatformShortMessageToObject(msg_struct_t msg, Message** result_message){
+    LoggerD("Entered");
+    std::unique_ptr<Message> message;
+    int infoInt;
+    bool infoBool;
+    char infoStr[MAX_ADDRESS_VAL_LEN + 1];
+    //get type
+    msg_get_int_value(msg, MSG_MESSAGE_TYPE_INT, &infoInt);
+    if (infoInt == MSG_TYPE_SMS) {
+        message = std::unique_ptr<Message>(new MessageSMS());
+        // get SMS body
+        std::shared_ptr<MessageBody> body(new MessageBody());
+        char msgInfoStr[MAX_MSG_TEXT_LEN + 1];
+        msg_get_str_value(msg, MSG_MESSAGE_SMS_DATA_STR, msgInfoStr, MAX_MSG_TEXT_LEN);
+        body->setPlainBody(std::string(msgInfoStr));
+        message->setBody(body);
+        // get recipients
+        std::vector<std::string> recp_list;
+        PlatformResult ret = message->getSMSRecipientsFromStruct(msg, &recp_list);
+        if (ret.IsError()) {
+          LoggerE("failed to get SMS recipients from struct");
+          return ret;
+        }
+
+        message->setTO(recp_list);
+    } else if (infoInt == MSG_TYPE_MMS) {
+        message = std::unique_ptr<Message>(new MessageMMS());
+
+        // get MMS body
+        msg_get_int_value(msg, MSG_MESSAGE_DATA_SIZE_INT, &infoInt);
+        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) {
+                LoggerE("Error:%d occured during: "
+                        "msg_get_str_value(...,MSG_MESSAGE_MMS_TEXT_STR,...)", error);
+            } else {
+                //Check if fetched string is not empty
+                if((mms_body_str.get())[0] != 0) {
+                    LoggerD("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 {
+                    LoggerW("Warning: fetched plain body is empty "
+                            "despite reported length is:%d!", mms_body_length);
+                }
+
+                LoggerD("Set plain body: [%s]", message->getBody()->getPlainBody().c_str());
+            }
+        } else {
+            LoggerW("Warning: mms plain body length is 0!");
+        }
+
+        // get recipients
+        std::vector<std::string> recp_list;
+        PlatformResult ret = getMMSRecipientsFromStruct(msg, MSG_RECIPIENTS_TYPE_TO, &recp_list);
+        if (ret.IsError()) {
+          LoggerE("failed to get MMS recipients from struct");
+          return ret;
+        }
+        message->setTO(recp_list);
+        ret = getMMSRecipientsFromStruct(msg, MSG_RECIPIENTS_TYPE_CC, &recp_list);
+        if (ret.IsError()) {
+          LoggerE("failed to get MMS recipients from struct");
+          return ret;
+        }
+        message->setCC(recp_list);
+        ret = getMMSRecipientsFromStruct(msg, MSG_RECIPIENTS_TYPE_BCC, &recp_list);
+        if (ret.IsError()) {
+          LoggerE("failed to get MMS recipients from struct");
+          return ret;
+        }
+        message->setBCC(recp_list);
+        // get subject
+        memset(infoStr, 0, MAX_ADDRESS_VAL_LEN + 1);
+        msg_get_str_value(msg, MSG_MESSAGE_SUBJECT_STR, infoStr, MAX_SUBJECT_LEN);
+        message->setSubject(infoStr);
+        //set attachments
+        ret = setMMSBodyAndAttachmentsFromStruct(message.get(), msg);
+        if (ret.IsError()) {
+          LoggerE("failed to set body attachments from struct");
+          return ret;
+        }
+    } else {
+        LoggerE("Invalid Message type: %d", infoInt);
+        return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Invalid Message type");
+    }
+
+    // get id
+    msg_get_int_value(msg, MSG_MESSAGE_ID_INT, &infoInt);
+    message->setId(infoInt);
+    // get conversation id
+    msg_get_int_value(msg, MSG_MESSAGE_THREAD_ID_INT, &infoInt);
+    message->setConversationId(infoInt);
+    // get folder id
+    msg_get_int_value(msg, MSG_MESSAGE_FOLDER_ID_INT, &infoInt);
+    message->setFolderId(infoInt);
+    // get timestamp
+    msg_get_int_value(msg, MSG_MESSAGE_DISPLAY_TIME_INT, &infoInt);
+    message->setTimeStamp(infoInt);
+    // get from
+    const std::string& from = Message::getShortMsgSenderFromStruct(msg);
+    message->setFrom(from);
+    LoggerD("Message(%p) from is: %s", message.get(), message->getFrom().c_str());
+    // get if is in response
+    msg_get_int_value(msg, MSG_MESSAGE_DIRECTION_INT, &infoInt);
+    LoggerD("Message(%p) direction is: %d", message.get(), infoInt);
+    message->setInResponseTo(infoInt);
+    // get is read
+    msg_get_bool_value(msg, MSG_MESSAGE_READ_BOOL, &infoBool);
+    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);
+
+        LoggerD("MSG_MESSAGE_FOLDER_ID:%d -> messageStatus:%s", infoInt,
+                MessagingUtil::messageStatusToString(msg_status).c_str());
+    }
+    else
+    {
+        LoggerE("Couldn't get MSG_MESSAGE_FOLDER_ID_INT, error:%d", error);
+        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 {
+                LoggerW("warning undefined messageStatus: %d!", infoInt);
+                msg_status = MessageStatus::STATUS_UNDEFINED;
+            }
+            message->setMessageStatus(msg_status);
+
+            LoggerD("MSG_SENT_STATUS_NETWORK_STATUS:%d MessageStatus:%s", infoInt,
+                MessagingUtil::messageStatusToString(msg_status).c_str());
+        } else {
+            LoggerE("Couldn't get MSG_SENT_STATUS_NETWORK_STATUS_INT, error:%d", error);
+
+            if(0 == message->getId()) {
+                LoggerW("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);
+            }
+        }
+    }
+
+    LoggerD("End");
+    *result_message = message.release();  // release ownership
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult Message::findShortMessageById(const int id, MessagePtr* message) {
+    LoggerD("Entered");
+    msg_struct_t msg;
+    PlatformResult ret = ShortMsgManager::getInstance().getMessage(id, &msg);
+    if (ret.IsError()) {
+        return ret;
+    }
+    Message* message_ptr = nullptr;
+    ret = Message::convertPlatformShortMessageToObject(msg, &message_ptr);
+    msg_release_struct(&msg);
+    if (ret.IsError()) {
+        return ret;
+    }
+    message->reset(message_ptr);
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+std::vector<std::string> Message::split(const std::string& input,
+        char delimiter)
+{
+    LoggerD("Entered");
+    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)
+{
+    LoggerD("Entered");
+    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)
+{
+    LoggerD("Entered");
+    std::shared_ptr<MessageBody> body (new MessageBody());
+    body->updateBody(mail);
+    return body;
+}
+
+PlatformResult Message::convertEmailToMessageAttachment(email_mail_data_t& mail,
+                                                        AttachmentPtrVector* att)
+{
+  LoggerD("Entered");
+  email_attachment_data_t* attachment = NULL;
+  int attachmentCount = 0;
+
+  if (EMAIL_ERROR_NONE != email_get_attachment_data_list(mail.mail_id,
+                                                         &attachment, &attachmentCount)) {
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Couldn't get attachment.");
+  }
+  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);
+    }
+  }
+
+  email_free_attachment_data(&attachment, attachmentCount);
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult Message::convertPlatformEmailToObject(
+        email_mail_data_t& mail, std::shared_ptr<Message>* result)
+{
+    LoggerD("Entered");
+    Message* message = new MessageEmail();
+    PlatformResult ret = message->updateEmailMessage(mail);
+    if (ret.IsError()) {
+      delete message;
+      return ret;
+    }
+    (*result).reset(message);
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult Message::updateEmailMessage(email_mail_data_t& mail)
+{
+    LoggerW("This should be called on MessageEmail instance");
+    return PlatformResult(ErrorCode::NOT_SUPPORTED_ERR,
+                          "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 = MESSAGE_ATTRIBUTE_ID;
+const std::string SERVICE_ID = "serviceId";
+const std::string CONVERSATION_ID = MESSAGE_ATTRIBUTE_CONVERSATION_ID;
+const std::string FOLDER_ID = MESSAGE_ATTRIBUTE_FOLDER_ID;
+const std::string TYPE = MESSAGE_ATTRIBUTE_TYPE;
+const std::string TIMESTAMP = MESSAGE_ATTRIBUTE_TIMESTAMP;
+const std::string FROM = MESSAGE_ATTRIBUTE_FROM;
+const std::string TO = MESSAGE_ATTRIBUTE_TO;
+const std::string CC = MESSAGE_ATTRIBUTE_CC;
+const std::string BCC = MESSAGE_ATTRIBUTE_BCC;
+const std::string BODY_PLAIN_BODY = "body.plainBody";
+const std::string IS_READ = MESSAGE_ATTRIBUTE_IS_READ;
+const std::string HAS_ATTACHMENT = MESSAGE_ATTRIBUTE_HAS_ATTACHMENT;
+const std::string IS_HIGH_PRIORITY = MESSAGE_ATTRIBUTE_IS_HIGH_PRIORITY;
+const std::string SUBJECT = MESSAGE_ATTRIBUTE_SUBJECT;
+
+} //namespace MESSAGE_FILTER_ATTRIBUTE
+
+bool Message::isMatchingAttribute(const std::string& attribute_name,
+            const FilterMatchFlag match_flag,
+            AnyPtr match_value) const
+{
+    LoggerD("Entered");
+    auto key = match_value->toString();
+    LoggerD("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) {
+        return FilterUtils::isStringMatching(key, getTypeString(), 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 {
+        LoggerD("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
+{
+    LoggerD("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 {
+        LoggerD("attribute:%s is NOT SUPPORTED", attribute_name.c_str());
+    }
+
+    return false;
+}
+
+} //messaging
+} //extension
diff --git a/webWidgetTCT_device/src/messaging/message.h b/webWidgetTCT_device/src/messaging/message.h
new file mode 100755 (executable)
index 0000000..5b130a1
--- /dev/null
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 2015 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 MESSAGING_MESSAGE_H_
+#define MESSAGING_MESSAGE_H_
+
+#include <time.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string>
+#include <vector>
+#include <memory>
+#include <msg.h>
+#include <msg_storage.h>
+#include <email-api.h>
+#include <TelNetwork.h>
+
+#include "message_attachment.h"
+#include "messaging_util.h"
+#include "message_body.h"
+#include "MsgCommon/AbstractFilter.h"
+#include "common/platform_result.h"
+
+namespace extension {
+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
+};
+
+using namespace tizen;
+
+class Message : public FilterableObject {
+public:
+// constructor
+    Message();
+    virtual ~Message();
+
+// attributes getters
+    int getId() const;
+    int getOldId() const;
+    int getConversationId() const;
+    int getFolderId() const;
+    MessageType getType() const;
+    std::string getTypeString() const;
+    time_t getTimestamp() const;
+    std::string getFrom() const;
+    std::vector<std::string> getTO() const;
+    std::vector<std::string> getCC() const;
+    std::vector<std::string> getBCC() const;
+    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;
+    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 setOldId(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
+    common::PlatformResult addSMSRecipientsToStruct(const std::vector<std::string> &recipients,
+            msg_struct_t &msg);
+    // gets recipients list for SMS message
+    common::PlatformResult 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 common::PlatformResult 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 common::PlatformResult convertPlatformShortMessageToStruct(Message* message,
+            msg_handle_t handle, msg_struct_t* result);
+    // gets recipients list for SMS message
+    common::PlatformResult getSMSRecipientsFromStruct(msg_struct_t &msg,
+                                              std::vector<std::string>* result_address);
+    // gets recipients list for MMS message
+    static common::PlatformResult getMMSRecipientsFromStruct(msg_struct_t &msg,
+            int type, std::vector<std::string>* result_address);
+    // function for filling Message attributes
+    static common::PlatformResult convertPlatformShortMessageToObject(msg_struct_t msg, Message** message);
+    static common::PlatformResult findShortMessageById(const int id, MessagePtr* message);
+    static common::PlatformResult addMMSBodyAndAttachmentsToStruct(const AttachmentPtrVector &attach,
+            msg_struct_t &mms_struct,
+            Message* message);
+    static common::PlatformResult setMMSBodyAndAttachmentsFromStruct(Message *message,
+            msg_struct_t &msg);
+
+    static common::PlatformResult convertPlatformEmail(std::shared_ptr<Message> message,
+                                                   email_mail_data_t** result);
+    static common::PlatformResult 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 common::PlatformResult convertPlatformEmailToObject(email_mail_data_t& mail,
+                                                               std::shared_ptr<Message>* result);
+    static std::shared_ptr<MessageBody> convertEmailToMessageBody(email_mail_data_t& mail);
+    static common::PlatformResult convertEmailToMessageAttachment(email_mail_data_t& mail,
+                                                                  AttachmentPtrVector* result);
+
+    // tizen::FilterableObject
+    virtual bool isMatchingAttribute(const std::string& attribute_name,
+          const FilterMatchFlag match_flag,
+          AnyPtr match_value) const;
+
+    virtual bool isMatchingAttributeRange(const std::string& attribute_name,
+          AnyPtr initial_value,
+          AnyPtr end_value) const;
+
+protected:
+    //! Message id
+    int m_id;
+    //! Old Message id - for email update hack
+    int m_old_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
+    std::vector<std::string> m_to;
+    //! Message CarbonCopy recipients (used only for email)
+    std::vector<std::string> m_cc;
+    //! Message BlindCarbonCopy recipients (used only for email)
+    std::vector<std::string> 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
+    AttachmentPtrVector 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
+}    //extension
+
+#endif /* MESSAGING_MESSAGE_H_ */
+
diff --git a/webWidgetTCT_device/src/messaging/message_attachment.cc b/webWidgetTCT_device/src/messaging/message_attachment.cc
new file mode 100755 (executable)
index 0000000..278c902
--- /dev/null
@@ -0,0 +1,596 @@
+/*
+ * Copyright (c) 2015 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 <ctype.h>
+#include <unordered_map>
+
+#include "message_attachment.h"
+
+#include "common/logger.h"
+
+namespace extension {
+namespace messaging {
+
+std::map<std::string, unsigned int>& MessageAttachment::MIMETypeStringToEnumMap = initializeMIMETypeStringToEnumMap();
+std::map<unsigned int, std::string>& MessageAttachment::MIMETypeEnumToStringMap = initializeMIMETypeEnumToStringMap();
+
+MessageAttachment::MessageAttachment() : fs_provider_(common::FilesystemProviderStorage::Create())
+{
+    LoggerD("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()
+{
+    LoggerD("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
+{
+    LoggerD("Entered");
+    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)
+{
+    LoggerD("Entered");
+
+    m_filePath = fs_provider_.GetRealPath(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()
+{
+    LoggerD("Entered");
+    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()
+{
+    LoggerD("Entered");
+    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)
+{
+    LoggerD("Entered");
+    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)
+{
+    LoggerD("Entered");
+    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)
+{
+    LoggerD("Entered");
+    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);
+
+        LoggerD("save status: %d", attachment_data.save_status);
+        LoggerD("attachment_size : %d", attachment_data.attachment_size);
+        isSaved = attachment_data.save_status;
+    }
+
+    setIsSaved(isSaved);
+}
+
+} // messaging
+} // extension
diff --git a/webWidgetTCT_device/src/messaging/message_attachment.h b/webWidgetTCT_device/src/messaging/message_attachment.h
new file mode 100755 (executable)
index 0000000..931f46b
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2015 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 MESSAGING_MESSAGE_ATTACHMENT_H_
+#define MESSAGING_MESSAGE_ATTACHMENT_H_
+
+#include <string>
+#include <memory>
+#include <vector>
+#include <map>
+#include <msg_types.h>
+#include <email-types.h>
+#include "common/filesystem/filesystem_provider_storage.h"
+
+namespace extension {
+namespace messaging {
+
+class MessageAttachment;
+
+struct MessageAttachmentHolder {
+    std::shared_ptr<MessageAttachment> ptr;
+};
+
+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;
+    common::FilesystemProviderStorage& fs_provider_;
+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
+} // extension
+
+#endif // MESSAGING_MESSAGE_ATTACHMENT_H_
diff --git a/webWidgetTCT_device/src/messaging/message_body.cc b/webWidgetTCT_device/src/messaging/message_body.cc
new file mode 100755 (executable)
index 0000000..9c843f7
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2015 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 "message_body.h"
+
+#include "common/logger.h"
+#include "common/platform_exception.h"
+
+#include "messaging_util.h"
+
+namespace extension {
+namespace messaging {
+
+using namespace common;
+
+MessageBody::MessageBody() : m_messageId(1),
+                             m_messageId_set(false),
+                             m_loaded(false),
+                             m_plainBody(""),
+                             m_htmlBody("")
+{
+    LoggerD("Entered");
+}
+
+MessageBody::~MessageBody()
+{
+    LoggerD("Entered");
+}
+
+// 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;
+}
+
+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;
+}
+
+PlatformResult MessageBody::updateBody(email_mail_data_t& mail)
+{
+    LoggerD("Entered");
+    setMessageId(mail.mail_id);
+    setLoaded(mail.body_download_status);
+
+    if (mail.file_path_plain) {
+      SLoggerD("Plain body: %s", mail.file_path_plain);
+      std::string result = "";
+      PlatformResult ret = MessagingUtil::loadFileContentToString(mail.file_path_plain,
+                                                                  &result);
+      if (ret.IsError()) {
+        LoggerE("Fail to open plain body.");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                              "Fail to open plain body.");
+      }
+      setPlainBody(result);
+    }
+
+    if (mail.file_path_html) {
+      SLoggerD("HTML body: %s", mail.file_path_html);
+      std::string result = "";
+      PlatformResult ret = MessagingUtil::loadFileContentToString(mail.file_path_html,
+                                                                  &result);
+      if (ret.IsError()) {
+        LoggerE("Fail to open html body.");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                              "Fail to open html body.");
+      }
+      setHtmlBody(result);
+    }
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+} // messaging
+} // extension
diff --git a/webWidgetTCT_device/src/messaging/message_body.h b/webWidgetTCT_device/src/messaging/message_body.h
new file mode 100755 (executable)
index 0000000..1e8164a
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2015 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 MESSAGING_MESSAGE_BODY_H_
+#define MESSAGING_MESSAGE_BODY_H_
+
+#include <email-types.h>
+#include <vector>
+#include <string>
+
+#include "message_attachment.h"
+#include "common/platform_result.h"
+
+namespace extension {
+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;
+    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
+     */
+    common::PlatformResult 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;
+    AttachmentPtrVector m_inlineAttachments;
+};
+
+} // messaging
+} // extension
+
+#endif // MESSAGING_MESSAGE_BODY_H_
diff --git a/webWidgetTCT_device/src/messaging/message_callback_user_data.cc b/webWidgetTCT_device/src/messaging/message_callback_user_data.cc
new file mode 100755 (executable)
index 0000000..e584261
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2015 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 "message_callback_user_data.h"
+#include "messaging_util.h"
+
+namespace extension {
+namespace messaging {
+
+MessageCallbackUserData::MessageCallbackUserData(PostQueue& queue):
+        common::CallbackUserData(),
+        m_is_error(false),
+        queue_(queue),
+        m_account_id(-1)
+{
+    LoggerD("Entered");
+}
+
+MessageCallbackUserData::~MessageCallbackUserData() {
+    LoggerD("Entered");
+}
+
+void MessageCallbackUserData::setMessage(std::shared_ptr<Message> message) {
+    m_message = message;
+}
+
+std::shared_ptr<Message> MessageCallbackUserData::getMessage() const {
+    return m_message;
+}
+
+void MessageCallbackUserData::setAccountId(int account_id){
+    m_account_id = account_id;
+}
+
+int MessageCallbackUserData::getAccountId() const
+{
+    return m_account_id;
+}
+
+void MessageCallbackUserData::setError(const std::string& err_name,
+        const std::string& err_message)
+{
+    LoggerD("Entered");
+    // keep only first error in chain
+    if (!m_is_error) {
+        LoggerD("Error has not been set yet");
+        picojson::object& obj = m_json->get<picojson::object>();
+        obj[JSON_ACTION] = picojson::value(JSON_CALLBACK_ERROR);
+        auto objData = picojson::object();
+
+        objData[JSON_ERROR_NAME] = picojson::value(err_name);
+        objData[JSON_ERROR_MESSAGE] = picojson::value(err_message);
+
+        obj[JSON_DATA] = picojson::value(objData);
+
+        m_is_error = true;
+        m_err_name = err_name;
+        m_err_message = err_message;
+    }
+}
+
+void MessageCallbackUserData::setError(const common::PlatformResult& error)
+{
+  LoggerD("Entered");
+  // keep only first error in chain
+  if (!m_is_error) {
+    LoggerD("Error has not been set yet");
+    m_is_error = true;
+    picojson::object& obj = m_json->get<picojson::object>();
+    obj[JSON_ACTION] = picojson::value(JSON_CALLBACK_ERROR);
+    auto obj_data = picojson::object();
+
+    obj_data[JSON_ERROR_CODE] = picojson::value(static_cast<double>(error.error_code()));
+    obj_data[JSON_ERROR_MESSAGE] = picojson::value(error.message());
+
+    obj[JSON_DATA] = picojson::value(obj_data);
+  }
+}
+
+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;
+}
+
+}//messaging
+}//extension
diff --git a/webWidgetTCT_device/src/messaging/message_callback_user_data.h b/webWidgetTCT_device/src/messaging/message_callback_user_data.h
new file mode 100755 (executable)
index 0000000..d6afe5c
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2015 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 MESSAGING_MESSAGE_CALLBACK_USER_DATA_H_
+#define MESSAGING_MESSAGE_CALLBACK_USER_DATA_H_
+
+#include "common/callback_user_data.h"
+#include "common/platform_result.h"
+
+#include <memory>
+#include <string>
+
+namespace extension {
+namespace messaging {
+
+class Message;
+class PostQueue;
+
+class MessageCallbackUserData: public common::CallbackUserData {
+public:
+    MessageCallbackUserData(PostQueue& queue);
+    virtual ~MessageCallbackUserData();
+
+    void setMessage(std::shared_ptr<Message> message);
+    std::shared_ptr<Message> getMessage() const;
+
+    void setAccountId(int account_id);
+    int getAccountId() const;
+
+    void setError(const std::string& err_name,
+            const std::string& err_message);
+    void setError(const common::PlatformResult& error);
+    bool isError() const;
+    std::string getErrorName() const;
+    std::string getErrorMessage() const;
+
+    PostQueue& getQueue() { return queue_;};
+
+private:
+    bool m_is_error;
+    PostQueue& queue_;
+    std::string m_err_name;
+    std::string m_err_message;
+    std::shared_ptr<Message> m_message;
+    int m_account_id;
+
+};
+
+}//messaging
+}//extension
+
+#endif /* MESSAGING_MESSAGE_CALLBACK_USER_DATA_H_ */
+
diff --git a/webWidgetTCT_device/src/messaging/message_conversation.cc b/webWidgetTCT_device/src/messaging/message_conversation.cc
new file mode 100755 (executable)
index 0000000..eb26e3b
--- /dev/null
@@ -0,0 +1,568 @@
+/*
+ * Copyright (c) 2015 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 "common/logger.h"
+#include "common/platform_exception.h"
+
+#include "messaging_util.h"
+#include "message.h"
+#include "message_conversation.h"
+
+#define MAX_THREAD_DATA_LEN 128
+
+using common::ErrorCode;
+using common::PlatformResult;
+
+namespace extension {
+namespace messaging {
+
+using namespace tizen;
+
+// *** constructor
+MessageConversation::MessageConversation():
+    m_conversation_id(-1),
+    m_conversation_type(UNDEFINED),
+    m_timestamp(-1),
+    m_count(0),
+    m_unread_messages(0),
+    m_is_read(false),
+    m_last_message_id(-1)
+{
+    LoggerD("Message Conversation constructor.");
+}
+
+MessageConversation::~MessageConversation()
+{
+    LoggerD("Message Conversation destructor.");
+}
+// *** attributes getters
+int MessageConversation::getConversationId() const
+{
+    return m_conversation_id;
+}
+
+MessageType MessageConversation::getType() const
+{
+    return m_conversation_type;
+}
+
+std::string MessageConversation::getTypeString() const {
+  return MessagingUtil::messageTypeToString(getType());
+}
+
+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;
+}
+
+PlatformResult MessageConversation::convertMsgConversationToObject(
+        unsigned int threadId, msg_handle_t handle, std::shared_ptr<MessageConversation>* result)
+{
+    LoggerD("Entered");
+    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;
+
+    int tempInt;
+    bool tempBool;
+    int nToCnt;
+    unsigned int lastMsgIndex = 0;
+    char msgData[MAX_THREAD_DATA_LEN] = {0,};
+
+    msgInfo = msg_create_struct(MSG_STRUCT_MESSAGE_INFO);
+    std::unique_ptr<std::remove_pointer<msg_struct_t*>::type, int(*)(msg_struct_t*)>
+        msg_info_ptr(&msgInfo, &msg_release_struct);
+        // automatically release the memory
+    sendOpt = msg_create_struct(MSG_STRUCT_SENDOPT);
+    std::unique_ptr<std::remove_pointer<msg_struct_t*>::type, int(*)(msg_struct_t*)>
+        send_opt_ptr(&sendOpt, &msg_release_struct);
+        // automatically release the memory
+
+    conversation->m_conversation_id = threadId;
+
+    msg_thread = msg_create_struct(MSG_STRUCT_THREAD_INFO);
+    std::unique_ptr<std::remove_pointer<msg_struct_t*>::type, int(*)(msg_struct_t*)>
+        msg_thread_ptr(&msg_thread, &msg_release_struct);
+        // automatically release the memory
+    msg_error_t err = msg_get_thread(handle, conversation->m_conversation_id, msg_thread);
+    if (err != MSG_SUCCESS)
+    {
+      LoggerE("Failed to retrieve thread.");
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to retrieve thread.");
+    }
+    msg_get_int_value(msg_thread, MSG_THREAD_MSG_TYPE_INT, &tempInt);
+    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;
+    }
+
+    msg_get_int_value(msg_thread, MSG_THREAD_MSG_TIME_INT, &tempInt);
+    conversation->m_timestamp = tempInt;
+
+    msg_get_int_value(msg_thread, MSG_THREAD_UNREAD_COUNT_INT, &tempInt);
+    conversation->m_unread_messages = tempInt;
+
+    msg_get_str_value(msg_thread, MSG_THREAD_MSG_DATA_STR, msgData, MAX_THREAD_DATA_LEN);
+
+    conversation->setPreview(msgData);
+
+    err = msg_get_conversation_view_list(handle, conversation->m_conversation_id,
+                                         &convViewList);
+    std::unique_ptr<std::remove_pointer<msg_struct_list_s*>::type, int(*)(msg_struct_list_s*)>
+        conv_view_list_ptr(&convViewList, &msg_release_list_struct);
+        // automatically release the memory
+    if (err != MSG_SUCCESS)
+    {
+      LoggerE("Get conversation(msg) view list fail.");
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, "Get conversation(msg) view list fail.");
+    }
+
+    lastMsgIndex = convViewList.nCount - 1;
+    conversation->m_count = convViewList.nCount;
+
+    msg_get_bool_value(convViewList.msg_struct_info[lastMsgIndex], MSG_CONV_MSG_READ_BOOL, &tempBool);
+    conversation->m_is_read = tempBool;
+
+    msg_get_int_value(convViewList.msg_struct_info[lastMsgIndex], MSG_CONV_MSG_ID_INT, &tempInt);
+    conversation->m_last_message_id = tempInt;
+
+    if (msg_get_message(handle, conversation->m_last_message_id, msgInfo,
+                        sendOpt) != MSG_SUCCESS)
+    {
+      LoggerE("Get message fail.");
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, "get message fail.");
+    }
+
+    msg_get_int_value(convViewList.msg_struct_info[lastMsgIndex], MSG_CONV_MSG_DIRECTION_INT, &tempInt);
+
+    msg_get_list_handle(msgInfo, MSG_MESSAGE_ADDR_LIST_HND, (void **)&addr_list);
+    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);
+        msg_get_str_value(addr_info, MSG_ADDRESS_INFO_ADDRESS_VALUE_STR, strNumber, MAX_ADDRESS_VAL_LEN);
+
+        if (strNumber[0] != '\0')
+        {
+          conversation->m_from = strNumber;
+        }
+        else
+        {
+          LoggerD("address is null ");
+        }
+      }
+      else
+      {
+        LoggerD("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,};
+          msg_get_str_value(addr_info, MSG_ADDRESS_INFO_ADDRESS_VALUE_STR, strNumber, MAX_ADDRESS_VAL_LEN);
+
+          conversation->m_to.push_back(strNumber);
+        }
+      }
+      else
+      {
+        LoggerD("address fetch fail");
+      }
+    }
+
+    char strTemp[MAX_SUBJECT_LEN] = {0};
+    msg_get_str_value(msgInfo, MSG_MESSAGE_SUBJECT_STR, strTemp, MAX_SUBJECT_LEN);
+
+    conversation->setSubject(strTemp);
+
+    *result = conversation;
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult MessageConversation::convertEmailConversationToObject(
+        unsigned int threadId, std::shared_ptr<MessageConversation>* result)
+{
+    LoggerD("Entered");
+    std::shared_ptr<MessageConversation> conversation (new MessageConversation());
+
+    email_mail_list_item_t *resultMail = NULL;
+
+    if(email_get_thread_information_ex(threadId, &resultMail) != EMAIL_ERROR_NONE)
+    {
+        if (resultMail)
+        {
+            if(resultMail->eas_data)
+            {
+                free(resultMail->eas_data);
+            }
+            free(resultMail);
+        }
+
+        LoggerE("Couldn't get conversation");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Couldn't get conversation.");
+    } else {
+        if (!resultMail)
+        {
+            LoggerE("Data is null");
+            return PlatformResult(ErrorCode::UNKNOWN_ERR, "Get email data fail.");
+        }
+
+        email_mail_data_t* mailData = NULL;
+
+        if (email_get_mail_data(resultMail->mail_id,
+                &mailData) != EMAIL_ERROR_NONE)
+        {
+            free(resultMail);
+            return PlatformResult(ErrorCode::UNKNOWN_ERR, "Get email data fail.");
+        }
+
+        if (!mailData) {
+            free(resultMail);
+            return PlatformResult(ErrorCode::UNKNOWN_ERR, "Get email data fail.");
+        }
+
+        int index = 0;
+        int count = 0;
+        conversation->m_unread_messages = 0;
+        email_mail_list_item_t *mailList = NULL;
+
+        if (email_get_mail_list(mailData->account_id, 0, threadId, 0,
+            resultMail->thread_item_count, EMAIL_SORT_DATETIME_HIGH, &mailList,
+            &count) != EMAIL_ERROR_NONE)
+        {
+            email_free_mail_data(&mailData , 1);
+            free(resultMail);
+            return PlatformResult(ErrorCode::UNKNOWN_ERR, "Get email data list fail.");
+        }
+
+        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 = MessageType::EMAIL;
+
+        conversation->m_timestamp = resultMail->date_time;
+
+        if (resultMail->preview_text[0] != '\0')
+        {
+            conversation->setPreview(resultMail->preview_text);
+        }
+
+        if (resultMail->subject[0] != '\0')
+        {
+            conversation->setSubject(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)
+        {
+            email_free_mail_data(&mailData , 1);
+        }
+    }
+
+    if (resultMail != NULL)
+    {
+        free(resultMail);
+    }
+
+    *result = conversation;
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+void MessageConversation::setConversationId(int id)
+{
+    m_conversation_id = id;
+}
+
+void MessageConversation::setType(MessageType type)
+{
+    m_conversation_type = type;
+}
+
+void MessageConversation::setTimestamp(time_t timestamp)
+{
+    m_timestamp = timestamp;
+}
+
+void MessageConversation::setMessageCount(int count)
+{
+    m_count = count;
+}
+
+void MessageConversation::setUnreadMessages(int unread_messages)
+{
+    m_unread_messages = unread_messages;
+}
+
+void MessageConversation::setPreview(std::string preview)
+{
+    m_preview = SanitizeUtf8String(preview);
+}
+
+void MessageConversation::setSubject(std::string conversation_subject)
+{
+    m_conversation_subject = SanitizeUtf8String(conversation_subject);
+}
+
+void MessageConversation::setIsRead(bool is_read)
+{
+    m_is_read = is_read;
+}
+
+void MessageConversation::setFrom(std::string from)
+{
+    m_from = from;
+}
+
+void MessageConversation::setTo(std::vector<std::string> &to)
+{
+    m_to = to;
+}
+
+void MessageConversation::setCC(std::vector<std::string> &cc)
+{
+    m_cc = cc;
+}
+
+void MessageConversation::setBCC(std::vector<std::string> &bcc)
+{
+    m_bcc = bcc;
+}
+
+void MessageConversation::setLastMessageId(int last_message_id)
+{
+    m_last_message_id = last_message_id;
+}
+
+/**
+ *
+ *  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 = MESSAGE_CONVERSATION_ATTRIBUTE_ID;
+const std::string TYPE = MESSAGE_CONVERSATION_ATTRIBUTE_TYPE;
+const std::string TIMESTAMP = MESSAGE_CONVERSATION_ATTRIBUTE_TIMESTAMP;
+const std::string MESSAGE_COUNT = MESSAGE_CONVERSATION_ATTRIBUTE_MESSAGE_COUNT;
+const std::string UNREAD_MESSAGES = MESSAGE_CONVERSATION_ATTRIBUTE_UNREAD_MESSAGES;
+const std::string PREVIEW = MESSAGE_CONVERSATION_ATTRIBUTE_PREVIEW;
+const std::string FROM = MESSAGE_CONVERSATION_ATTRIBUTE_FROM;
+const std::string TO = MESSAGE_CONVERSATION_ATTRIBUTE_TO;
+} //namespace CONVERSATION_FILTER_ATTRIBUTE
+
+bool MessageConversation::isMatchingAttribute(const std::string& attribute_name,
+            const FilterMatchFlag match_flag,
+            AnyPtr match_value) const
+{
+    LoggerD("Entered");
+    auto key = match_value->toString();
+    LoggerD("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) {
+        return FilterUtils::isStringMatching(key, getTypeString(), 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 {
+        LoggerD("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
+{
+    LoggerD("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 {
+        LoggerD("attribute:%s is NOT SUPPORTED", attribute_name.c_str());
+    }
+    return false;
+}
+
+std::string MessageConversation::SanitizeUtf8String(const std::string& input) {
+  LoggerD("Entered");
+
+  std::string result = input;
+  const gchar* end = nullptr;
+
+  while (FALSE == g_utf8_validate(result.c_str(), -1, &end)) {
+    result = result.substr(0, end - result.c_str());
+  }
+
+  return result;
+}
+
+}    //messaging
+}    //extension
+
diff --git a/webWidgetTCT_device/src/messaging/message_conversation.h b/webWidgetTCT_device/src/messaging/message_conversation.h
new file mode 100755 (executable)
index 0000000..5a2dc42
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2015 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_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 "messaging_util.h"
+#include "MsgCommon/AbstractFilter.h"
+
+namespace extension {
+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;
+    std::string getTypeString() 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 common::PlatformResult convertEmailConversationToObject(
+        unsigned int threadId, std::shared_ptr<MessageConversation>* result);
+    /**
+     *
+     * @param threadId Id of Message (not Conversation)
+     * @param handle
+     * @return
+     */
+    static common::PlatformResult convertMsgConversationToObject(
+        unsigned int threadId, msg_handle_t handle, std::shared_ptr<MessageConversation>* result);
+
+    virtual void setConversationId(int id);
+    virtual void setType(MessageType type);
+    virtual void setTimestamp(time_t timestamp);
+    virtual void setMessageCount(int count);
+    virtual void setUnreadMessages(int unread_messages);
+    virtual void setPreview(std::string preview);
+    virtual void setSubject(std::string conversation_subject);
+    virtual void setIsRead(bool is_read);
+    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 setLastMessageId(int last_message_id);
+
+    // 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:
+    std::string SanitizeUtf8String(const std::string& input);
+
+    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
+}    //extension
+
+#endif // __TIZEN_MESSAGE_CONVERSATION_H__
diff --git a/webWidgetTCT_device/src/messaging/message_email.cc b/webWidgetTCT_device/src/messaging/message_email.cc
new file mode 100755 (executable)
index 0000000..bbb4f08
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2015 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 "message_email.h"
+
+#include "common/logger.h"
+#include "common/platform_exception.h"
+
+namespace extension {
+namespace messaging {
+
+using namespace common;
+
+MessageEmail::MessageEmail():
+    Message()
+{
+    LoggerD("MessageEmail constructor.");
+    this->m_type = MessageType(EMAIL);
+}
+
+MessageEmail::~MessageEmail()
+{
+    LoggerD("MessageEmail destructor.");
+}
+
+// *** overrided methods
+void MessageEmail::setCC(std::vector<std::string> &cc)
+{
+    LoggerD("Entered");
+    // CC recipient's format validation should be done by email service
+    m_cc = cc;
+
+    if(m_cc.empty()) {
+        LoggerD("Recipient's list cleared");
+        return;
+    }
+}
+
+void MessageEmail::setBCC(std::vector<std::string> &bcc)
+{
+    LoggerD("Entered");
+    // BCC recipient's format validation should be done by email service
+    m_bcc = bcc;
+
+    if(m_bcc.empty()) {
+        LoggerD("Recipient's list cleared");
+        return;
+    }
+}
+
+void MessageEmail::setSubject(std::string subject)
+{
+    LoggerD("Entered");
+    m_subject = subject;
+}
+
+void MessageEmail::setIsHighPriority(bool highpriority)
+{
+    LoggerD("Entered");
+    m_high_priority = highpriority;
+}
+
+void MessageEmail::setMessageAttachments(AttachmentPtrVector &attachments)
+{
+    LoggerD("Entered");
+    m_attachments = attachments;
+
+    m_has_attachment = true;
+    if(m_attachments.empty()) {
+        LoggerD("Recipient's list cleared");
+        m_has_attachment = false;
+    }
+}
+
+bool MessageEmail::getHasAttachment() const
+{
+    LoggerD("MessageEmail::getHasAttachment()");
+    return m_has_attachment || !m_body->getInlineAttachments().empty();
+}
+
+PlatformResult MessageEmail::updateEmailMessage(email_mail_data_t& mail)
+{
+    LoggerD("Entered");
+
+    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) {
+        LoggerW("Subject is null");
+    } else {
+        LoggerD("Subject: %s", mail.subject);
+        setSubject(mail.subject);
+    }
+
+    PlatformResult ret = getBody()->updateBody(mail);
+    if (ret.IsError()) {
+        LoggerE("Update Email body failed");
+        return ret;
+    }
+
+    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;
+    ret = convertEmailToMessageAttachment(mail, &att);
+    if (ret.IsError()) return ret;
+
+    setMessageAttachments(att);
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+} // messaging
+} // extension
diff --git a/webWidgetTCT_device/src/messaging/message_email.h b/webWidgetTCT_device/src/messaging/message_email.h
new file mode 100755 (executable)
index 0000000..0ca9f6a
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2015 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 MESSAGING_MESSAGE_EMAIL_H_
+#define MESSAGING_MESSAGE_EMAIL_H_
+
+#include "message.h"
+
+namespace extension {
+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 common::PlatformResult updateEmailMessage(email_mail_data_t& mail);
+
+private:
+    // function that verifies recipient's list validity
+    bool isValidRecpientsVector(std::vector<std::string> &recipients);
+};
+
+} // messaging
+} // extension
+
+#endif // MESSAGING_MESSAGE_EMAIL_H_
diff --git a/webWidgetTCT_device/src/messaging/message_folder.cc b/webWidgetTCT_device/src/messaging/message_folder.cc
new file mode 100755 (executable)
index 0000000..355675e
--- /dev/null
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2015 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 "messaging_util.h"
+#include "message_folder.h"
+
+namespace extension {
+namespace messaging {
+
+using namespace tizen;
+
+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)
+{
+    LoggerD("Entered");
+}
+
+MessageFolder::MessageFolder(email_mailbox_t mailbox)
+{
+    LoggerD("Entered");
+    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)
+{
+    LoggerD("Entered");
+    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
+{
+    LoggerD("Entered");
+    auto key = match_value->toString();
+    LoggerD("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 {
+        LoggerD("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
+{
+    LoggerD("Entered");
+    LoggerD("attribute_name: %s NOT SUPPORTED", attribute_name.c_str());
+    return false;
+}
+
+}    //messaging
+}    //extension
diff --git a/webWidgetTCT_device/src/messaging/message_folder.h b/webWidgetTCT_device/src/messaging/message_folder.h
new file mode 100755 (executable)
index 0000000..70317ad
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2015 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_MESSAGING_MESSAGE_FOLDER_H__
+#define __TIZEN_MESSAGING_MESSAGE_FOLDER_H__
+
+#include <string>
+#include <memory>
+#include <vector>
+
+#include <email-types.h>
+#include "MsgCommon/AbstractFilter.h"
+
+namespace extension {
+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
+}    //extension
+
+#endif // __TIZEN_MESSAGING_MESSAGE_FOLDER_H__
diff --git a/webWidgetTCT_device/src/messaging/message_mms.cc b/webWidgetTCT_device/src/messaging/message_mms.cc
new file mode 100755 (executable)
index 0000000..edd0e91
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2015 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 "message_mms.h"
+
+#include "common/platform_exception.h"
+#include "common/logger.h"
+
+namespace extension {
+namespace messaging {
+
+MessageMMS::MessageMMS():
+    Message()
+{
+    LoggerD("MessageMMS constructor.");
+    this->m_type = MessageType(MessageType(MMS));
+}
+
+MessageMMS::~MessageMMS()
+{
+    LoggerD("MessageMMS destructor.");
+}
+
+// *** overrided methods
+void MessageMMS::setCC(std::vector<std::string> &cc)
+{
+    LoggerD("Entered");
+    // CC recipient's format validation should be done by email service
+    m_cc = cc;
+
+    if(m_cc.empty()) {
+        LoggerD("Recipient's list cleared");
+        return;
+    }
+}
+
+void MessageMMS::setBCC(std::vector<std::string> &bcc)
+{
+    LoggerD("Entered");
+    // BCC recipient's format validation should be done by email service
+    m_bcc = bcc;
+
+    if(m_bcc.empty()) {
+        LoggerD("Recipient's list cleared");
+        return;
+    }
+}
+
+void MessageMMS::setSubject(std::string subject)
+{
+    m_subject = subject;
+}
+
+void MessageMMS::setMessageAttachments(AttachmentPtrVector &attachments)
+{
+    LoggerD("Entered");
+    m_attachments = attachments;
+
+    m_has_attachment = true;
+    if(m_attachments.empty()) {
+        LoggerD("Recipient's list cleared");
+        m_has_attachment = false;
+    }
+}
+
+bool MessageMMS::getHasAttachment() const
+{
+    LoggerD("MessageMMS::getHasAttachment()");
+    // TODO: Analyze relation between hasAttachment flag and inlineAttachments
+    return m_has_attachment;
+}
+
+} // messaging
+} // extension
diff --git a/webWidgetTCT_device/src/messaging/message_mms.h b/webWidgetTCT_device/src/messaging/message_mms.h
new file mode 100755 (executable)
index 0000000..cb25250
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2015 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_MESSAGE_MMS_H__
+#define __TIZEN_MESSAGE_MMS_H__
+
+// Header with core msg-service declarations
+#include <msg.h>
+
+#include "message.h"
+#include "message_attachment.h"
+
+namespace extension {
+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
+} // extension
+
+#endif // __TIZEN_MESSAGE_MMS_H__
diff --git a/webWidgetTCT_device/src/messaging/message_service.cc b/webWidgetTCT_device/src/messaging/message_service.cc
new file mode 100755 (executable)
index 0000000..0ee7c0e
--- /dev/null
@@ -0,0 +1,521 @@
+/*
+ * Copyright (c) 2015 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 "message_service.h"
+
+#include <sstream>
+
+#include "common/logger.h"
+#include "common/platform_exception.h"
+#include "common/assert.h"
+
+#include "messaging_util.h"
+#include "message_storage_email.h"
+#include "message_storage_short_msg.h"
+#include "message.h"
+
+using common::ErrorCode;
+using common::PlatformResult;
+
+namespace extension {
+namespace messaging {
+
+namespace{
+const char* JSON_SERVICE_ID = "id";
+const char* JSON_SERVICE_TYPE = "type";
+const char* JSON_SERVICE_NAME = "name";
+}
+
+//#################### MessageRecipientsCallbackData ####################
+
+MessageRecipientsCallbackData::MessageRecipientsCallbackData(PostQueue& queue):
+        m_is_error(false),
+        m_account_id(-1),
+        m_sim_index(TAPI_NETWORK_DEFAULT_DATA_SUBS_UNKNOWN),
+        m_default_sim_index(TAPI_NETWORK_DEFAULT_DATA_SUBS_UNKNOWN),
+        queue_(queue)
+{
+    LoggerD("Entered");
+    m_msg_recipients = std::vector<std::string>();
+}
+
+MessageRecipientsCallbackData::~MessageRecipientsCallbackData()
+{
+    LoggerD("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)
+{
+    LoggerD("Entered");
+    // keep only first error in chain
+    if (!m_is_error) {
+        LoggerD("Error has not been set yet");
+        m_is_error = true;
+
+        picojson::object& obj = m_json->get<picojson::object>();
+        obj[JSON_ACTION] = picojson::value(JSON_CALLBACK_ERROR);
+        auto obj_error = picojson::object();
+
+        obj_error[JSON_ERROR_NAME] = picojson::value(err_name);
+        obj_error[JSON_ERROR_MESSAGE] = picojson::value(err_message);
+
+        obj[JSON_DATA] = picojson::value(obj_error);
+    }
+}
+
+void MessageRecipientsCallbackData::setError(const PlatformResult& error)
+{
+  LoggerD("Entered");
+  // keep only first error in chain
+  if (!m_is_error) {
+    LoggerD("Error has not been set yet");
+    m_is_error = true;
+
+    picojson::object& obj = m_json->get<picojson::object>();
+    obj[JSON_ACTION] = picojson::value(JSON_CALLBACK_ERROR);
+    auto obj_error = picojson::object();
+
+    obj_error[JSON_ERROR_CODE] = picojson::value(static_cast<double>(error.error_code()));
+    obj_error[JSON_ERROR_MESSAGE] = picojson::value(error.message());
+
+    obj[JSON_DATA] = picojson::value(obj_error);
+  }
+}
+
+bool MessageRecipientsCallbackData::isError() const
+{
+    return m_is_error;
+}
+
+void MessageRecipientsCallbackData::setAccountId(int account_id){
+    m_account_id = account_id;
+}
+
+int MessageRecipientsCallbackData::getAccountId() const
+{
+    return m_account_id;
+}
+
+bool MessageRecipientsCallbackData::setSimIndex(
+    int sim_index)
+{
+    LoggerD("Entered");
+    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 {
+        LoggerD("Empty cp name list");
+    }
+
+    sim_index--;
+    if (sim_index >= sim_count || sim_index < -1) {
+        LoggerE("Sim index out of bound %d : %d", sim_index, sim_count);
+        common::InvalidValuesException err("The index of sim is out of bound");
+        this->setError(err.name(), err.message());
+        return false;
+    }
+
+    m_sim_index = static_cast<TelNetworkDefaultDataSubs_t>(sim_index);
+
+    return true;
+}
+
+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():
+//        CallbackUserData(globalCtx),
+        m_is_error(false),
+        m_op_handle(-1),
+        m_callback_id(-1)
+{
+    LoggerD("Entered");
+}
+
+BaseMessageServiceCallbackData::~BaseMessageServiceCallbackData()
+{
+    LoggerD("Entered");
+}
+
+void BaseMessageServiceCallbackData::setError(const std::string& err_name,
+        const std::string& err_message)
+{
+    LoggerD("Entered");
+    // keep only first error in chain
+    if (!m_is_error) {
+        LoggerD("Error has not been set yet");
+        m_is_error = true;
+
+        picojson::object& obj = m_json->get<picojson::object>();
+        obj[JSON_ACTION] = picojson::value(JSON_CALLBACK_ERROR);
+
+        auto obj_error = picojson::object();
+        obj_error[JSON_ERROR_NAME] = picojson::value(err_name);
+        obj_error[JSON_ERROR_MESSAGE] = picojson::value(err_message);
+        obj[JSON_DATA] = picojson::value(obj_error);
+    }
+}
+
+void BaseMessageServiceCallbackData::setError(const PlatformResult& error)
+{
+  LoggerD("Entered");
+  // keep only first error in chain
+  if (!m_is_error) {
+    LoggerD("Error has not been set yet");
+    m_is_error = true;
+
+    picojson::object& obj = m_json->get<picojson::object>();
+    obj[JSON_ACTION] = picojson::value(JSON_CALLBACK_ERROR);
+    auto obj_error = picojson::object();
+
+    obj_error[JSON_ERROR_CODE] = picojson::value(static_cast<double>(error.error_code()));
+    obj_error[JSON_ERROR_MESSAGE] = picojson::value(error.message());
+
+    obj[JSON_DATA] = picojson::value(obj_error);
+  }
+}
+
+bool BaseMessageServiceCallbackData::isError() const
+{
+    return m_is_error;
+}
+
+void BaseMessageServiceCallbackData::setOperationHandle(const int op_handle)
+{
+    m_op_handle = op_handle;
+}
+
+int BaseMessageServiceCallbackData::getOperationHandle() const
+{
+    return m_op_handle;
+}
+
+void BaseMessageServiceCallbackData::setCallbackId(const double callback_id)
+{
+    m_callback_id = callback_id;
+}
+
+double BaseMessageServiceCallbackData::getCallbackId() const
+{
+    return m_callback_id;
+}
+
+//#################### MessageBodyCallbackData ####################
+
+MessageBodyCallbackData::MessageBodyCallbackData(PostQueue& queue):
+    queue_(queue)
+{
+    LoggerD("Entered");
+}
+
+MessageBodyCallbackData::~MessageBodyCallbackData()
+{
+    LoggerD("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(PostQueue& queue):
+        m_nth(0),
+        queue_(queue)
+{
+    LoggerD("Entered");
+}
+
+MessageAttachmentCallbackData::~MessageAttachmentCallbackData()
+{
+    LoggerD("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(PostQueue& queue):
+//        BaseMessageServiceCallbackData(globalCtx),
+        m_is_limit(false),
+        m_limit(0),
+        m_op_id(-1),
+        m_account_id(-1),
+        queue_(queue)
+{
+    LoggerD("Entered");
+}
+
+SyncCallbackData::~SyncCallbackData()
+{
+    LoggerD("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(PostQueue& queue):
+    SyncCallbackData(queue)
+{
+    LoggerD("Entered");
+}
+
+SyncFolderCallbackData::~SyncFolderCallbackData()
+{
+    LoggerD("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,
+                    const std::string& name):
+        m_id(id),
+        m_msg_type(msgType),
+        m_name(name)
+{
+    LoggerD("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:
+            LoggerE("Undefined message type: %d", msgType);
+            Assert(false);
+            break;
+    }
+}
+
+MessageService::~MessageService()
+{
+    LoggerD("Entered");
+}
+
+picojson::object MessageService::toPicoJS() const
+{
+    LoggerD("Entered");
+    picojson::object picojs = picojson::object();
+    picojs[JSON_SERVICE_ID] = picojson::value(std::to_string(m_id));
+    picojs[JSON_SERVICE_TYPE] = picojson::value(getMsgServiceTypeString());
+    picojs[JSON_SERVICE_NAME] = picojson::value(m_name);
+    return picojs;
+}
+
+int MessageService::getMsgServiceId() const
+{
+    return m_id;
+}
+
+std::string MessageService::getMsgServiceIdStr() const
+{
+    return std::to_string(m_id);
+}
+
+MessageType MessageService::getMsgServiceType() const
+{
+    return m_msg_type;
+}
+
+std::string MessageService::getMsgServiceTypeString() const {
+  return MessagingUtil::messageTypeToString(getMsgServiceType());
+}
+
+std::string MessageService::getMsgServiceName() const
+{
+    return m_name;
+}
+
+MessageStoragePtr MessageService::getMsgStorage() const
+{
+    return m_storage;
+}
+
+common::PlatformResult MessageService::sendMessage(MessageRecipientsCallbackData *callback)
+{
+    // this method should be overwritten be specific services
+    LoggerE("Cannot send message");
+    delete callback;
+    return PlatformResult(ErrorCode::NOT_SUPPORTED_ERR, "Unable to send message.");
+}
+
+PlatformResult MessageService::loadMessageBody(MessageBodyCallbackData* callback)
+{
+    // this method should be overwritten by specific services
+    LoggerE("Cannot load message body");
+    delete callback;
+    return PlatformResult(ErrorCode::NOT_SUPPORTED_ERR, "Cannot load message body");
+}
+
+PlatformResult MessageService::loadMessageAttachment(MessageAttachmentCallbackData* callback)
+{
+    // this method should be overwritten by email service
+    // for MMS and SMS this function is not supported
+    LoggerE("Cannot load message attachment");
+    delete callback;
+    return PlatformResult(ErrorCode::NOT_SUPPORTED_ERR, "Cannot load message attachment");
+}
+
+PlatformResult MessageService::sync(SyncCallbackData *callback, long* operation_id)
+{
+    // this method should be overwritten by email service
+    // for MMS and SMS this function is not supported
+    LoggerE("Cannot sync with external server");
+    delete callback;
+    return PlatformResult(ErrorCode::NOT_SUPPORTED_ERR, "Cannot sync with external server");
+}
+
+PlatformResult MessageService::syncFolder(SyncFolderCallbackData *callback, long* operation_id)
+{
+    // this method should be overwritten by email service
+    // for MMS and SMS this function is not supported
+    LoggerE("Cannot sync folder with external server");
+    delete callback;
+    return PlatformResult(ErrorCode::NOT_SUPPORTED_ERR, "Cannot sync folder with external server");
+}
+
+PlatformResult MessageService::stopSync(long op_id)
+{
+    // this method should be overwritten by email service
+    // for MMS and SMS this function is not supported
+    LoggerE("Cannot stop sync with external server");
+    return PlatformResult(ErrorCode::NOT_SUPPORTED_ERR, "Cannot stop sync with external server");
+}
+
+} // messaging
+} // extension
+
diff --git a/webWidgetTCT_device/src/messaging/message_service.h b/webWidgetTCT_device/src/messaging/message_service.h
new file mode 100755 (executable)
index 0000000..8952362
--- /dev/null
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 2015 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 MESSAGING_MESSAGE_SERVICE_H_
+#define MESSAGING_MESSAGE_SERVICE_H_
+
+#include <ITapiNetwork.h>
+#include <memory>
+#include <string>
+
+#include "common/picojson.h"
+#include "common/callback_user_data.h"
+#include "common/platform_result.h"
+
+#include "messaging_util.h"
+#include "message_storage.h"
+#include "message.h"
+
+namespace extension {
+namespace messaging {
+
+enum MessageServiceAccountId
+{
+    UNKNOWN_ACCOUNT_ID = 0,
+    SMS_ACCOUNT_ID = 101,
+    MMS_ACCOUNT_ID = 102
+};
+
+class MessageRecipientsCallbackData : public common::CallbackUserData {
+public:
+    MessageRecipientsCallbackData(PostQueue& queue);
+    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);
+    void setError(const common::PlatformResult& error);
+    bool isError() const;
+
+    void setAccountId(int account_id);
+    int getAccountId() const;
+
+    bool setSimIndex(int sim_index);
+    TelNetworkDefaultDataSubs_t getSimIndex() const;
+    void setDefaultSimIndex(TelNetworkDefaultDataSubs_t sim_index);
+    TelNetworkDefaultDataSubs_t getDefaultSimIndex() const;
+    bool isSetSimIndex() const;
+
+    PostQueue& getQueue() { return queue_;};
+
+private:
+    std::shared_ptr<Message> m_message;
+    bool m_is_error;
+    std::vector<std::string> m_msg_recipients;
+    int m_account_id;
+    TelNetworkDefaultDataSubs_t m_sim_index;
+    TelNetworkDefaultDataSubs_t m_default_sim_index;
+    PostQueue& queue_;
+};
+
+class BaseMessageServiceCallbackData : public common::CallbackUserData {
+public:
+    BaseMessageServiceCallbackData();
+    virtual ~BaseMessageServiceCallbackData();
+
+    void setError(const std::string& err_name,
+            const std::string& err_message);
+    void setError(const common::PlatformResult& error);
+    bool isError() 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;
+    void setCallbackId(const double callback_id);
+    double getCallbackId() const;
+
+protected:
+    bool m_is_error;
+
+    int m_op_handle;
+    double m_callback_id;
+};
+
+class MessageBodyCallbackData : public BaseMessageServiceCallbackData {
+public:
+    MessageBodyCallbackData(PostQueue& queue);
+    virtual ~MessageBodyCallbackData();
+
+    void setMessage(std::shared_ptr<Message> message);
+    std::shared_ptr<Message> getMessage() const;
+
+    PostQueue& getQueue() { return queue_;};
+private:
+    std::shared_ptr<Message> m_message;
+    PostQueue& queue_;
+};
+
+class MessageAttachmentCallbackData : public BaseMessageServiceCallbackData {
+public:
+    MessageAttachmentCallbackData(PostQueue& queue);
+    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;
+
+    PostQueue& getQueue() { return queue_;};
+private:
+    std::shared_ptr<MessageAttachment> m_message_attachment;
+    int m_nth;
+    PostQueue& queue_;
+};
+
+class SyncCallbackData : public BaseMessageServiceCallbackData {
+public:
+    SyncCallbackData(PostQueue& queue);
+    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;
+
+    PostQueue& getQueue() { return queue_;};
+protected:
+    bool m_is_limit;
+    unsigned long m_limit;
+
+    long m_op_id;
+    int m_account_id;
+    PostQueue& queue_;
+};
+
+class SyncFolderCallbackData : public SyncCallbackData {
+public:
+    SyncFolderCallbackData(PostQueue& queue);
+    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:
+    virtual ~MessageService();
+
+    virtual int getMsgServiceId() const;
+    virtual std::string getMsgServiceIdStr() const;
+    virtual MessageType getMsgServiceType() const;
+    std::string getMsgServiceTypeString() const;
+    virtual std::string getMsgServiceName() const;
+
+    virtual MessageStoragePtr getMsgStorage() const;
+
+    virtual common::PlatformResult sendMessage(MessageRecipientsCallbackData *callback);
+    virtual common::PlatformResult loadMessageBody(MessageBodyCallbackData* callback);
+    virtual common::PlatformResult loadMessageAttachment(MessageAttachmentCallbackData* callback);
+    virtual common::PlatformResult sync(SyncCallbackData *callback, long* operation_id);
+    virtual common::PlatformResult syncFolder(SyncFolderCallbackData *callback, long* operation_id);
+    virtual common::PlatformResult stopSync(long op_id);
+
+    picojson::object toPicoJS() const;
+
+protected:
+    /**
+     * We have child classes MessageServiceEmail and MessageServiceShortMsg which
+     * should provide specialized implementation.
+     */
+    MessageService(int id,
+            MessageType msgType,
+            const std::string& name);
+
+    int m_id;
+    MessageType m_msg_type;
+    std::string m_name;
+    MessageStoragePtr m_storage;
+};
+
+} // messaging
+} // extension
+#endif // MESSAGING_MESSAGE_SERVICE_EMAIL_H_
diff --git a/webWidgetTCT_device/src/messaging/message_service_email.cc b/webWidgetTCT_device/src/messaging/message_service_email.cc
new file mode 100755 (executable)
index 0000000..9c5ee86
--- /dev/null
@@ -0,0 +1,267 @@
+/*
+ * Copyright (c) 2015 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 "message_service_email.h"
+#include "email_manager.h"
+
+#include "common/logger.h"
+
+using common::ErrorCode;
+using common::PlatformResult;
+
+namespace extension {
+namespace messaging {
+
+MessageServiceEmail::MessageServiceEmail(int id, std::string name)
+        : MessageService(id,
+                MessageType::EMAIL,
+                name)
+{
+    LoggerD("Entered");
+}
+
+MessageServiceEmail::~MessageServiceEmail() {
+  LoggerD("Entered");
+
+  for (auto id : registered_callbacks_) {
+    // this may internally fail, because we don't have information about
+    // callbacks which already have fired
+    EmailManager::getInstance().RemoveSyncCallback(id);
+  }
+}
+
+static gboolean sendMessageTask(void* data)
+{
+  LoggerD("Entered");
+
+  auto ret = EmailManager::getInstance().sendMessage(static_cast<MessageRecipientsCallbackData*>(data));
+
+  if (!ret) {
+    LoggerE("Error: %d - %s", ret.error_code(), ret.message().c_str());
+  }
+
+  return FALSE;
+}
+
+PlatformResult MessageServiceEmail::sendMessage(MessageRecipientsCallbackData *callback)
+{
+    LoggerD("Entered");
+
+    if (!callback) {
+        LoggerE("Callback is null");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Callback is null");
+    }
+
+    callback->setAccountId(m_id);
+
+    guint id = g_idle_add(sendMessageTask, static_cast<void*>(callback));
+    if (!id) {
+        LoggerE("g_idle_add fails");
+        delete callback;
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Could not add task");
+    }
+
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+static gboolean loadMessageBodyTask(void* data)
+{
+    LoggerD("Entered");
+
+    EmailManager::getInstance().loadMessageBody(static_cast<MessageBodyCallbackData*>(data));
+
+    return FALSE;
+}
+
+PlatformResult MessageServiceEmail::loadMessageBody(MessageBodyCallbackData* callback)
+{
+    LoggerD("Entered");
+    if (!callback) {
+        LoggerE("Callback is null");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Callback is null");
+    }
+
+    guint id = g_idle_add(loadMessageBodyTask, static_cast<void*>(callback));
+    if (!id) {
+        LoggerE("g_idle_add failed");
+        delete callback;
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Could not add task");
+    }
+
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+static gboolean loadMessageAttachmentTask(void* data)
+{
+  LoggerD("Entered");
+
+  auto callback = static_cast<MessageAttachmentCallbackData*>(data);
+
+  if (callback) {
+    auto att = callback->getMessageAttachment();
+
+    // if the attachment is already saved, then it doesn't need to load again.
+    if (att->isFilePathSet() && att->isSaved()) {
+      auto json = callback->getJson();
+      picojson::object& obj = json->get<picojson::object>();
+      obj[JSON_ACTION] = picojson::value(JSON_CALLBACK_SUCCCESS);
+
+      if (json->contains(JSON_CALLBACK_ID) && obj.at(JSON_CALLBACK_ID).is<double>()) {
+        picojson::object args;
+        args[JSON_DATA_MESSAGE_ATTACHMENT] = MessagingUtil::messageAttachmentToJson(att);
+        obj[JSON_DATA] = picojson::value(args);
+
+        callback->getQueue().resolve(
+            obj.at(JSON_CALLBACK_ID).get<double>(),
+            json->serialize()
+        );
+      } else {
+        LoggerE("json is incorrect - missing required member");
+      }
+      delete callback;
+      callback = nullptr;
+    } else {
+      const auto ret = EmailManager::getInstance().loadMessageAttachment(callback);
+
+      if (!ret) {
+        LoggerE("Error: %d - %s", ret.error_code(), ret.message().c_str());
+      }
+    }
+  } else {
+    LoggerE("Callback is null");
+  }
+
+  return FALSE;
+}
+
+PlatformResult MessageServiceEmail::loadMessageAttachment(MessageAttachmentCallbackData *callback)
+{
+  LoggerD("Entered");
+  guint id = g_idle_add(loadMessageAttachmentTask, static_cast<void*>(callback));
+  if (!id) {
+    LoggerE("g_idle_add failed");
+    delete callback;
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Could not add task");
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+static gboolean syncTask(void* data)
+{
+  LoggerD("Entered");
+
+  EmailManager::getInstance().sync(data);
+
+  return FALSE;
+}
+
+PlatformResult MessageServiceEmail::sync(SyncCallbackData *callback, long* operation_id)
+{
+  LoggerD("Entered");
+
+  if (!callback) {
+    LoggerE("Callback is null");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Callback is null");
+  }
+
+  long op_id = EmailManager::getInstance().getUniqueOpId();
+  callback->setOpId(op_id);
+
+  guint id = g_idle_add(syncTask, static_cast<void*>(callback));
+  if (!id) {
+    LoggerE("g_idle_add failed");
+    delete callback;
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Could not add task");
+  }
+  *operation_id = op_id;
+  registered_callbacks_.insert(op_id);
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+static gboolean syncFolderTask(void* data)
+{
+    LoggerD("Entered");
+
+    EmailManager::getInstance().syncFolder(static_cast<SyncFolderCallbackData*>(data));
+
+    return FALSE;
+}
+
+PlatformResult MessageServiceEmail::syncFolder(SyncFolderCallbackData *callback, long* operation_id)
+{
+  LoggerD("Entered");
+  if (!callback) {
+    LoggerE("Callback is null");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Callback is null");
+  }
+
+  if (!callback->getMessageFolder()) {
+    LoggerE("Message folder is null");
+    delete callback;
+    return PlatformResult(ErrorCode::TYPE_MISMATCH_ERR, "Message folder is null");
+  }
+
+  long op_id = EmailManager::getInstance().getUniqueOpId();
+  callback->setOpId(op_id);
+
+  guint id = g_idle_add(syncFolderTask, callback);
+  if (!id) {
+    LoggerE("g_idle_add fails");
+    delete callback;
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Could not add task");
+  }
+  *operation_id = op_id;
+  registered_callbacks_.insert(op_id);
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+static gboolean stopSyncTask(void* data)
+{
+  LoggerD("Entered");
+
+  if (!data) {
+    LoggerE("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);
+
+  return FALSE;
+}
+
+PlatformResult MessageServiceEmail::stopSync(long op_id)
+{
+  LoggerD("Entered");
+
+  registered_callbacks_.erase(op_id);
+  long* data = new long(op_id);
+  guint id = g_idle_add(stopSyncTask, static_cast<void*>(data));
+
+  if (!id) {
+    LoggerE("g_idle_add failed");
+    delete data;
+    data = NULL;
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Could not add task");
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+} // messaging
+} // extension
+
diff --git a/webWidgetTCT_device/src/messaging/message_service_email.h b/webWidgetTCT_device/src/messaging/message_service_email.h
new file mode 100755 (executable)
index 0000000..e78801b
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2015 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 MESSAGING_MESSAGE_SERVICE_EMAIL_H_
+#define MESSAGING_MESSAGE_SERVICE_EMAIL_H_
+
+#include "message_service.h"
+
+#include <unordered_set>
+
+namespace extension {
+namespace messaging {
+
+class MessageServiceEmail : public MessageService {
+public:
+    MessageServiceEmail(int id, std::string name);
+    virtual ~MessageServiceEmail();
+
+    virtual common::PlatformResult sendMessage(MessageRecipientsCallbackData *callback);
+    virtual common::PlatformResult loadMessageBody(MessageBodyCallbackData* callback);
+    virtual common::PlatformResult loadMessageAttachment(MessageAttachmentCallbackData* callback);
+    virtual common::PlatformResult sync(SyncCallbackData *callback, long* operation_id);
+    virtual common::PlatformResult syncFolder(SyncFolderCallbackData *callback, long* operation_id);
+    virtual common::PlatformResult stopSync(long op_id);
+
+private:
+    std::unordered_set<long> registered_callbacks_;
+};
+
+} // messaging
+} // extension
+
+#endif // MESSAGING_MESSAGE_SERVICE_EMAIL_H_
diff --git a/webWidgetTCT_device/src/messaging/message_service_short_msg.cc b/webWidgetTCT_device/src/messaging/message_service_short_msg.cc
new file mode 100755 (executable)
index 0000000..0c405f5
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2015 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 "message_service_short_msg.h"
+#include "messaging_instance.h"
+#include "short_message_manager.h"
+#include "common/logger.h"
+#include "common/platform_exception.h"
+
+#include <tapi_common.h>
+#include <ITapiSim.h>
+#include <ITapiNetwork.h>
+
+//#include <JSWebAPIErrorFactory.h>
+//#include <JSWebAPIError.h>
+//#include <JSUtil.h>
+//#include "JSMessage.h"
+
+//using namespace DeviceAPI::Common;
+
+using common::ErrorCode;
+using common::PlatformResult;
+
+namespace extension {
+namespace messaging {
+
+MessageServiceShortMsg::MessageServiceShortMsg(int id, MessageType msgType)
+        : MessageService(id,
+                msgType,
+                MessagingUtil::messageTypeToString(msgType))
+{
+    LoggerD("Entered");
+}
+
+MessageServiceShortMsg::~MessageServiceShortMsg()
+{
+    LoggerD("Entered");
+}
+
+static gboolean sendMessageThread(void* data)
+{
+  LoggerD("Entered");
+
+  auto ret = ShortMsgManager::getInstance().sendMessage(static_cast<MessageRecipientsCallbackData*>(data));
+
+  if (!ret) {
+    LoggerE("Error: %d - %s", ret.error_code(), ret.message().c_str());
+  }
+
+  return FALSE;
+}
+
+PlatformResult MessageServiceShortMsg::sendMessage(MessageRecipientsCallbackData *callback)
+{
+    LoggerD("Entered");
+    if (!callback) {
+        LoggerE("Callback is null");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Callback is null");
+    }
+
+    /*
+     * 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);
+
+    int ret = tel_get_network_default_data_subscription(handle, &default_sim);
+    if (ret != TAPI_API_SUCCESS) {
+        LoggerE("Failed to find default sim index %d", ret);
+    }
+
+    LoggerD("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 {
+            LoggerD("Empty cp name list");
+        }
+
+        if (sim_index >= sim_count) {
+            LoggerE("Sim index out of count %d : %d", sim_index, sim_count);
+            delete callback;
+            return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "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))) {
+        LoggerE("g_idle_add fails");
+        delete callback;
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Could not add task");
+    }
+
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+static gboolean loadMessageBodyTask(void* data)
+{
+    LoggerD("Entered");
+    MessageBodyCallbackData* callback = static_cast<MessageBodyCallbackData*>(data);
+    if(!callback) {
+        LoggerE("callback is NULL");
+        return FALSE;
+    }
+
+    std::shared_ptr<MessageBody> body = callback->getMessage()->getBody();
+    auto json = callback->getJson();
+    picojson::object& obj = json->get<picojson::object>();
+    obj[JSON_ACTION] = picojson::value(JSON_CALLBACK_SUCCCESS);
+
+    if (json->contains(JSON_CALLBACK_ID) && obj.at(JSON_CALLBACK_ID).is<double>()) {
+      picojson::object args;
+      args[JSON_DATA_MESSAGE_BODY] = MessagingUtil::messageBodyToJson(body);
+      obj[JSON_DATA] = picojson::value(args);
+
+      callback->getQueue().resolve(
+          obj.at(JSON_CALLBACK_ID).get<double>(),
+          json->serialize()
+      );
+    } else {
+      LoggerE("json is incorrect - missing required member");
+    }
+    return FALSE;
+}
+
+PlatformResult MessageServiceShortMsg::loadMessageBody(MessageBodyCallbackData *callback)
+{
+    LoggerD("Entered");
+    if (!callback) {
+        LoggerE("Callback is null");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Callback is null");
+    }
+
+    guint id = g_idle_add(loadMessageBodyTask, static_cast<void*>(callback));
+    if (!id) {
+        LoggerE("g_idle_add fails");
+        delete callback;
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Could not add task");
+    }
+
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+MessageServiceShortMsg* MessageServiceShortMsg::GetMmsMessageService() {
+  return new (std::nothrow) MessageServiceShortMsg(
+      MessageServiceAccountId::MMS_ACCOUNT_ID, MessageType::MMS);
+}
+
+MessageServiceShortMsg* MessageServiceShortMsg::GetSmsMessageService() {
+  return new (std::nothrow) MessageServiceShortMsg(
+      MessageServiceAccountId::SMS_ACCOUNT_ID, MessageType::SMS);
+}
+
+} // namespace messaging
+} // namespace extension
+
diff --git a/webWidgetTCT_device/src/messaging/message_service_short_msg.h b/webWidgetTCT_device/src/messaging/message_service_short_msg.h
new file mode 100755 (executable)
index 0000000..727385f
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2015 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 __MESSAGING_MESSAGE_SERVICE_SHORT_MSG_H__
+#define __MESSAGING_MESSAGE_SERVICE_SHORT_MSG_H__
+
+#include "message_service.h"
+#include "messaging_util.h"
+
+namespace extension {
+namespace messaging {
+
+class MessageServiceShortMsg : public MessageService {
+public:
+    virtual ~MessageServiceShortMsg();
+
+    common::PlatformResult sendMessage(MessageRecipientsCallbackData *callback);
+
+    virtual common::PlatformResult loadMessageBody(MessageBodyCallbackData *callback);
+
+    static MessageServiceShortMsg* GetMmsMessageService();
+    static MessageServiceShortMsg* GetSmsMessageService();
+
+protected:
+    MessageServiceShortMsg(int id, MessageType msgType);
+};
+
+} // namespace messaging
+} // namespace extension
+#endif // __MESSAGING_MESSAGE_SERVICE_SHORT_MSG_H__
diff --git a/webWidgetTCT_device/src/messaging/message_sms.cc b/webWidgetTCT_device/src/messaging/message_sms.cc
new file mode 100755 (executable)
index 0000000..0f02ec4
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2015 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 <iterator>
+
+#include "message_sms.h"
+
+namespace extension {
+namespace messaging {
+
+MessageSMS::MessageSMS():
+    Message()
+{
+    LoggerD("MessageSMS constructor.");
+    this->m_type = MessageType(MessageType(SMS));
+}
+
+MessageSMS::~MessageSMS()
+{
+    LoggerD("MessageSMS destructor.");
+}
+
+} // messaging
+} // extension
diff --git a/webWidgetTCT_device/src/messaging/message_sms.h b/webWidgetTCT_device/src/messaging/message_sms.h
new file mode 100755 (executable)
index 0000000..5b252ff
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2015 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 __MESSAGING_MESSAGE_SMS_H__
+#define __MESSAGING_MESSAGE_SMS_H__
+
+// Header with core msg-service declarations
+#include <msg.h>
+
+#include "message.h"
+
+namespace extension {
+namespace messaging {
+
+class MessageSMS: public Message {
+public:
+// constructor
+    MessageSMS();
+    ~MessageSMS();
+
+};
+
+} // messaging
+} // extension
+
+#endif // __MESSAGING_MESSAGE_SMS_H__
diff --git a/webWidgetTCT_device/src/messaging/message_storage.cc b/webWidgetTCT_device/src/messaging/message_storage.cc
new file mode 100755 (executable)
index 0000000..7ce8304
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2015 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 "message_storage.h"
+#include "messages_change_callback.h"
+#include "conversations_change_callback.h"
+#include "folders_change_callback.h"
+#include "change_listener_container.h"
+
+#include "common/logger.h"
+
+namespace extension {
+namespace messaging {
+
+MessageStorage::MessageStorage(int id, MessageType msgType) :
+        m_id(id), m_msg_type(msgType)
+{
+    LoggerD("Entered");
+}
+
+MessageStorage::~MessageStorage() {
+  LoggerD("Entered");
+
+  for (auto id : registered_listeners_) {
+    ChangeListenerContainer::getInstance().removeChangeListener(id);
+  }
+}
+
+int MessageStorage::getMsgServiceId() const
+{
+    LoggerD("Entered");
+    return m_id;
+}
+
+MessageType MessageStorage::getMsgServiceType() const
+{
+    LoggerD("Entered");
+    return m_msg_type;
+}
+
+std::string MessageStorage::getMsgServiceTypeString() const {
+  return MessagingUtil::messageTypeToString(getMsgServiceType());
+}
+
+long MessageStorage::addMessagesChangeListener(std::shared_ptr<MessagesChangeCallback> callback)
+{
+    LoggerD("Entered");
+    long id = ChangeListenerContainer::getInstance().addMessageChangeListener(callback);
+    registered_listeners_.insert(id);
+    return id;
+}
+
+long MessageStorage::addConversationsChangeListener(
+        std::shared_ptr<ConversationsChangeCallback> callback)
+{
+    LoggerD("Entered");
+    long id = ChangeListenerContainer::getInstance().addConversationChangeListener(callback);
+    registered_listeners_.insert(id);
+    return id;
+}
+
+long MessageStorage::addFoldersChangeListener(std::shared_ptr<FoldersChangeCallback> callback)
+{
+    LoggerD("Entered");
+    long id = ChangeListenerContainer::getInstance().addFolderChangeListener(callback);
+    registered_listeners_.insert(id);
+    return id;
+}
+
+void MessageStorage::removeChangeListener(long watchId)
+{
+    LoggerD("Entered");
+    ChangeListenerContainer::getInstance().removeChangeListener(watchId);
+    registered_listeners_.erase(watchId);
+}
+
+} //messaging
+} //extension
diff --git a/webWidgetTCT_device/src/messaging/message_storage.h b/webWidgetTCT_device/src/messaging/message_storage.h
new file mode 100755 (executable)
index 0000000..6db19f1
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2015 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 MESSAGING_MESSAGE_STORAGE_H_
+#define MESSAGING_MESSAGE_STORAGE_H_
+
+#include <memory>
+#include <unordered_set>
+
+#include "common/platform_result.h"
+#include "common/logger.h"
+
+#include "messaging_util.h"
+#include "message_callback_user_data.h"
+#include "messages_callback_user_data.h"
+#include "conversation_callback_data.h"
+#include "find_msg_callback_user_data.h"
+#include "folders_callback_data.h"
+
+namespace extension {
+namespace messaging {
+
+class MessagesChangeCallback;
+class ConversationsChangeCallback;
+class FoldersChangeCallback;
+
+class MessageStorage;
+typedef std::shared_ptr<MessageStorage> MessageStoragePtr;
+
+class MessageStorage {
+public:
+    MessageStorage(int id, MessageType msgType);
+    virtual ~MessageStorage();
+
+    virtual int getMsgServiceId() const;
+    virtual MessageType getMsgServiceType() const;
+    std::string getMsgServiceTypeString() 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(long watchId);
+
+protected:
+    int m_id;
+    MessageType m_msg_type;
+    std::unordered_set<long> registered_listeners_;
+};
+
+}    //messaging
+}    //extension
+
+#endif /* MESSAGING_MESSAGE_STORAGE_H_ */
+
diff --git a/webWidgetTCT_device/src/messaging/message_storage_email.cc b/webWidgetTCT_device/src/messaging/message_storage_email.cc
new file mode 100755 (executable)
index 0000000..cbb63d9
--- /dev/null
@@ -0,0 +1,241 @@
+/*
+ * Copyright (c) 2015 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 "message_storage_email.h"
+
+#include <glib.h>
+
+#include "common/platform_exception.h"
+
+#include "email_manager.h"
+#include "message.h"
+
+namespace extension {
+namespace messaging {
+
+MessageStorageEmail::MessageStorageEmail(int id) :
+        MessageStorage(id, MessageType::EMAIL)
+{
+    LoggerD("Entered");
+}
+
+MessageStorageEmail::~MessageStorageEmail()
+{
+    LoggerD("Entered");
+}
+
+static gboolean addDraftMessageTask(void* data)
+{
+    LoggerD("Entered");
+
+    MessageCallbackUserData *callback = static_cast<MessageCallbackUserData*>(data);
+    EmailManager::getInstance().addDraftMessage(callback);
+
+    return FALSE;
+}
+
+void MessageStorageEmail::addDraftMessage(MessageCallbackUserData* callback) {
+    LoggerD("Entered");
+
+    if (!callback) {
+        LoggerE("Callback is null");
+        return;
+    }
+
+    callback->setAccountId(m_id);
+
+    guint id = g_idle_add(addDraftMessageTask, static_cast<void*>(callback));
+    if (!id) {
+        LoggerE("g_idle_add failed");
+        delete callback;
+        callback = NULL;
+    }
+}
+
+static gboolean removeMessagesTask(void* data)
+{
+    LoggerD("Entered");
+
+    MessagesCallbackUserData *callback = static_cast<MessagesCallbackUserData*>(data);
+    EmailManager::getInstance().removeMessages(callback);
+
+    return FALSE;
+}
+
+void MessageStorageEmail::removeMessages(MessagesCallbackUserData* callback)
+{
+    LoggerD("Entered");
+
+    if (!callback) {
+        LoggerE("Callback is null");
+        return;
+    }
+
+    callback->setMessageServiceType(m_msg_type);
+
+    guint id = g_idle_add(removeMessagesTask, static_cast<void*>(callback));
+    if (!id) {
+        LoggerE("g_idle_add failed");
+        delete callback;
+        callback = NULL;
+    }
+}
+
+static gboolean updateMessagesTask(void* data)
+{
+    LoggerD("Entered");
+
+    MessagesCallbackUserData *callback = static_cast<MessagesCallbackUserData*>(data);
+    EmailManager::getInstance().updateMessages(callback);
+
+    return FALSE;
+}
+
+void MessageStorageEmail::updateMessages(MessagesCallbackUserData* callback)
+{
+    LoggerD("Entered");
+
+    if (!callback) {
+        LoggerE("Callback is null");
+        return;
+    }
+
+    callback->setMessageServiceType(m_msg_type);
+    guint id = g_idle_add(updateMessagesTask, static_cast<void*>(callback));
+    if (!id) {
+        LoggerE("g_idle_add failed");
+        delete callback;
+        callback = NULL;
+    }
+}
+
+static gboolean findMessagesTask(void* data)
+{
+    LoggerD("Entered");
+
+    FindMsgCallbackUserData *callback = static_cast<FindMsgCallbackUserData*>(data);
+    EmailManager::getInstance().findMessages(callback);
+
+    return FALSE;
+}
+
+void MessageStorageEmail::findMessages(FindMsgCallbackUserData* callback)
+{
+    LoggerD("Entered");
+
+    if (!callback) {
+        LoggerE("Callback is null");
+        return;
+    }
+
+    callback->setAccountId(m_id);
+    callback->setMessageServiceType(m_msg_type);
+
+    guint id = g_idle_add(findMessagesTask, static_cast<void*>(callback));
+    if (!id) {
+        LoggerE("g_idle_add failed");
+        delete callback;
+        callback = NULL;
+    }
+}
+
+static gboolean findConversationsTask(void* data)
+{
+    LoggerD("Entered");
+
+    ConversationCallbackData *callback = static_cast<ConversationCallbackData*>(data);
+    EmailManager::getInstance().findConversations(callback);
+
+    return FALSE;
+}
+
+void MessageStorageEmail::findConversations(ConversationCallbackData* callback)
+{
+    LoggerD("Entered");
+
+    if (!callback) {
+        LoggerE("Callback is null");
+        return;
+    }
+
+    callback->setAccountId(m_id);
+    callback->setMessageServiceType(m_msg_type);
+    guint id = g_idle_add(findConversationsTask, static_cast<void*>(callback));
+    if (!id) {
+        LoggerE("g_idle_add failed");
+        delete callback;
+        callback = NULL;
+    }
+}
+
+static gboolean removeConversationsTask(void* data)
+{
+    LoggerD("Entered");
+
+    ConversationCallbackData *callback = static_cast<ConversationCallbackData*>(data);
+    EmailManager::getInstance().removeConversations(callback);
+
+    return FALSE;
+}
+
+void MessageStorageEmail::removeConversations(ConversationCallbackData* callback)
+{
+    LoggerD("Entered");
+
+    if (!callback) {
+        LoggerE("Callback is null");
+        return;
+    }
+
+    callback->setMessageServiceType(m_msg_type);
+
+    guint id = g_idle_add(removeConversationsTask, static_cast<void*>(callback));
+    if (!id) {
+        LoggerE("g_idle_add failed");
+        delete callback;
+        callback = NULL;
+    }
+}
+
+static gboolean findFoldersTask(void* data)
+{
+    LoggerD("Entered");
+
+    FoldersCallbackData *callback = static_cast<FoldersCallbackData*>(data);
+    EmailManager::getInstance().findFolders(callback);
+
+    return FALSE;
+}
+
+void MessageStorageEmail::findFolders(FoldersCallbackData* callback)
+{
+    LoggerD("Entered");
+
+    if (!callback) {
+        LoggerE("Callback is null");
+        return;
+    }
+
+    guint id = g_idle_add(findFoldersTask, static_cast<void*>(callback));
+    if (!id) {
+        LoggerE("g_idle_add failed");
+        delete callback;
+        callback = NULL;
+    }
+}
+
+} //messaging
+} //extension
diff --git a/webWidgetTCT_device/src/messaging/message_storage_email.h b/webWidgetTCT_device/src/messaging/message_storage_email.h
new file mode 100755 (executable)
index 0000000..fe943e7
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2015 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 MESSAGING_MESSAGE_STORAGE_EMAIL_H_
+#define MESSAGING_MESSAGE_STORAGE_EMAIL_H_
+
+#include "message_storage.h"
+
+namespace extension {
+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
+} //extension
+
+#endif /* MESSAGING_MESSAGE_STORAGE_EMAIL_H_ */
+
diff --git a/webWidgetTCT_device/src/messaging/message_storage_short_msg.cc b/webWidgetTCT_device/src/messaging/message_storage_short_msg.cc
new file mode 100755 (executable)
index 0000000..0c81118
--- /dev/null
@@ -0,0 +1,283 @@
+/*
+ * Copyright (c) 2015 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 "common/logger.h"
+#include "common/platform_exception.h"
+
+#include "messaging_util.h"
+#include "message_sms.h"
+#include "short_message_manager.h"
+#include "message_storage_short_msg.h"
+#include "messaging_instance.h"
+
+namespace extension {
+namespace messaging {
+
+MessageStorageShortMsg::MessageStorageShortMsg(int id, MessageType msgType):
+        MessageStorage(id, msgType) {
+    LoggerD("Entered");
+}
+
+MessageStorageShortMsg::~MessageStorageShortMsg() {
+    LoggerD("Entered");
+}
+
+static gboolean addDraftMessageTask(void* data) {
+    LoggerD("Entered");
+
+    MessageCallbackUserData *callback = static_cast<MessageCallbackUserData*>(data);
+    ShortMsgManager::getInstance().addDraftMessage(callback);
+
+    return false;
+}
+
+void MessageStorageShortMsg::addDraftMessage(MessageCallbackUserData* callback) {
+    LoggerD("Entered");
+
+    if (!callback) {
+        LoggerE("Callback is null");
+        return;
+    }
+
+    guint id = g_idle_add(addDraftMessageTask, static_cast<void*>(callback));
+    if (!id) {
+        LoggerE("g_idle_add failed");
+        delete callback;
+        return;
+    }
+}
+
+static gboolean removeMessagesTask(void* data) {
+    LoggerD("Entered");
+
+    MessagesCallbackUserData *callback = static_cast<MessagesCallbackUserData*>(data);
+    ShortMsgManager::getInstance().removeMessages(callback);
+
+    return false;
+}
+
+void MessageStorageShortMsg::removeMessages(MessagesCallbackUserData* callback)
+{
+    LoggerD("Entered");
+
+    if (!callback) {
+        LoggerE("Callback is null");
+        return;
+    }
+
+    callback->setMessageServiceType(m_msg_type);
+
+    guint id = g_idle_add(removeMessagesTask, static_cast<void*>(callback));
+    if (!id) {
+        LoggerE("g_idle_add failed");
+        delete callback;
+        return;
+    }
+}
+
+static gboolean updateMessagesTask(void* data) {
+    LoggerD("Entered");
+
+    MessagesCallbackUserData *callback = static_cast<MessagesCallbackUserData*>(data);
+    ShortMsgManager::getInstance().updateMessages(callback);
+
+    return false;
+}
+
+void MessageStorageShortMsg::updateMessages(MessagesCallbackUserData* callback)
+{
+    LoggerD("Entered");
+
+    if (!callback) {
+        LoggerE("Callback is null");
+        return;
+    }
+
+    callback->setMessageServiceType(m_msg_type);
+
+    guint id = g_idle_add(updateMessagesTask, static_cast<void*>(callback));
+    if (!id) {
+        LoggerE("g_idle_add failed");
+        delete callback;
+        return;
+    }
+}
+
+static gboolean findMessagesTask(void* data) {
+    LoggerD("Entered");
+
+    FindMsgCallbackUserData *callback = static_cast<FindMsgCallbackUserData*>(data);
+    ShortMsgManager::getInstance().findMessages(callback);
+
+    return false;
+}
+
+void MessageStorageShortMsg::findMessages(FindMsgCallbackUserData* callback)
+{
+    LoggerD("Entered");
+
+    if (!callback) {
+        LoggerE("Callback is null");
+        return;
+    }
+
+    callback->setMessageServiceType(m_msg_type);
+
+    guint id = g_idle_add(findMessagesTask, static_cast<void*>(callback));
+    if (!id) {
+        LoggerE("g_idle_add failed");
+        delete callback;
+        return;
+    }
+}
+
+static gboolean findConversationsTask(void* data) {
+    LoggerD("Entered");
+
+    ConversationCallbackData *callback = static_cast<ConversationCallbackData*>(data);
+    ShortMsgManager::getInstance().findConversations(callback);
+
+    return false;
+}
+
+void MessageStorageShortMsg::findConversations(ConversationCallbackData* callback)
+{
+    LoggerD("Entered");
+
+    if (!callback) {
+        LoggerE("Callback is null");
+        return;
+    }
+
+    callback->setMessageServiceType(m_msg_type);
+
+    guint id = g_idle_add(findConversationsTask, static_cast<void*>(callback));
+    if (!id) {
+        LoggerE("g_idle_add failed");
+        delete callback;
+        return;
+    }
+}
+
+static gboolean removeConversationsTask(void* data) {
+    LoggerD("Entered");
+
+    ConversationCallbackData *callback = static_cast<ConversationCallbackData*>(data);
+    ShortMsgManager::getInstance().removeConversations(callback);
+
+    return false;
+}
+
+void MessageStorageShortMsg::removeConversations(ConversationCallbackData* callback)
+{
+    LoggerD("Entered");
+
+    if (!callback) {
+        LoggerE("Callback is null");
+        return;
+    }
+
+    callback->setMessageServiceType(m_msg_type);
+
+    guint id = g_idle_add(removeConversationsTask, static_cast<void*>(callback));
+    if (!id) {
+        LoggerE("g_idle_add failed");
+        delete callback;
+        return;
+    }
+}
+
+static gboolean findFoldersCB(void* data)
+{
+    LoggerD("Entered");
+
+    FoldersCallbackData *callback = static_cast<FoldersCallbackData*>(data);
+
+    auto json = callback->getJson();
+    picojson::object& obj = json->get<picojson::object>();
+
+    if (json->contains(JSON_CALLBACK_ID) && obj.at(JSON_CALLBACK_ID).is<double>()) {
+      picojson::array array;
+      auto each = [&array](std::shared_ptr<MessageFolder> folder)->void {
+        array.push_back(MessagingUtil::folderToJson(folder));
+      };
+
+      auto folders = callback->getFolders();
+      for_each(folders.begin(), folders.end(), each);
+
+      obj[JSON_DATA] = picojson::value(array);
+      obj[JSON_ACTION] = picojson::value(JSON_CALLBACK_SUCCCESS);
+
+
+     callback->getQueue().resolve(
+          obj.at(JSON_CALLBACK_ID).get<double>(),
+          json->serialize()
+      );
+    } else {
+      LoggerE("json is incorrect - missing required member");
+    }
+    delete callback;
+    callback = NULL;
+
+    return FALSE;
+}
+
+
+void MessageStorageShortMsg::findFolders(FoldersCallbackData* callback)
+{
+    LoggerD("Entered");
+    if (!callback){
+        LoggerE("Callback is null");
+        return;
+    }
+
+    std::string content_type = getMsgServiceTypeString();
+    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) {
+        LoggerE("g_idle_add failed");
+        delete callback;
+        callback = NULL;
+    }
+}
+
+} // messaging
+} // extension
diff --git a/webWidgetTCT_device/src/messaging/message_storage_short_msg.h b/webWidgetTCT_device/src/messaging/message_storage_short_msg.h
new file mode 100755 (executable)
index 0000000..2d7e40e
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2015 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 __MESSAGING_MESSAGE_STORAGE_SMS_H
+#define __MESSAGING_MESSAGE_STORAGE_SMS_H
+
+#include "message_storage.h"
+
+
+namespace extension {
+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
+} // extension
+
+#endif /* __MESSAGING_MESSAGE_STORAGE_SMS_H */
+
diff --git a/webWidgetTCT_device/src/messaging/messages_callback_user_data.cc b/webWidgetTCT_device/src/messaging/messages_callback_user_data.cc
new file mode 100755 (executable)
index 0000000..92838f6
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2015 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 "messages_callback_user_data.h"
+
+namespace extension {
+namespace messaging {
+
+MessagesCallbackUserData::MessagesCallbackUserData(PostQueue& queue):
+        common::CallbackUserData(),
+        m_is_error(false),
+        m_service_type(MessageType::UNDEFINED),
+        queue_(queue)
+{
+    LoggerD("Entered");
+}
+
+MessagesCallbackUserData::MessagesCallbackUserData(long cid, PostQueue& queue, bool keep):
+        common::CallbackUserData(),
+        m_is_error(false),
+        m_service_type(MessageType::UNDEFINED),
+        queue_(queue)
+{
+    LoggerD("Entered");
+    auto json = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+    picojson::object& o = json->get<picojson::object>();
+    o[JSON_CALLBACK_ID] = picojson::value(static_cast<double>(cid));
+    o[JSON_CALLBACK_KEEP] = picojson::value(keep);
+    setJson(json);
+}
+
+MessagesCallbackUserData::~MessagesCallbackUserData() {
+    LoggerD("Entered");
+}
+
+void MessagesCallbackUserData::addMessage(std::shared_ptr<Message> msg)
+{
+    LoggerD("Entered");
+    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)
+{
+    LoggerD("Entered");
+    // keep only first error in chain
+    if (!m_is_error) {
+        LoggerD("Error has not been set yet");
+        picojson::object& obj = m_json->get<picojson::object>();
+        obj[JSON_ACTION] = picojson::value(JSON_CALLBACK_ERROR);
+        auto objData = picojson::object();
+
+        objData[JSON_ERROR_NAME] = picojson::value(err_name);
+        objData[JSON_ERROR_MESSAGE] = picojson::value(err_message);
+
+        obj[JSON_DATA] = picojson::value(objData);
+
+        m_is_error = true;
+        m_err_name = err_name;
+        m_err_message = err_message;
+    }
+}
+
+void MessagesCallbackUserData::SetError(const common::PlatformResult& error)
+{
+  // keep only first error in chain
+  if (!m_is_error) {
+    LoggerD("Error has not been set yet");
+    m_is_error = true;
+    picojson::object& obj = m_json->get<picojson::object>();
+    obj[JSON_ACTION] = picojson::value(JSON_CALLBACK_ERROR);
+    auto obj_data = picojson::object();
+    obj_data[JSON_ERROR_CODE] = picojson::value(static_cast<double>(error.error_code()));
+    obj_data[JSON_ERROR_MESSAGE] = picojson::value(error.message());
+    obj[JSON_DATA] = picojson::value(obj_data);
+  }
+}
+
+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;
+}
+
+}//messaging
+}//extension
diff --git a/webWidgetTCT_device/src/messaging/messages_callback_user_data.h b/webWidgetTCT_device/src/messaging/messages_callback_user_data.h
new file mode 100755 (executable)
index 0000000..d1ee4ee
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2015 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 MESSAGING_MESSAGES_CALLBACK_USER_DATA_H_
+#define MESSAGING_MESSAGES_CALLBACK_USER_DATA_H_
+
+#include "common/callback_user_data.h"
+#include "common/platform_result.h"
+
+#include <memory>
+#include <string>
+
+#include "messaging_util.h"
+
+namespace extension {
+namespace messaging {
+
+class Message;
+
+class MessagesCallbackUserData: public common::CallbackUserData {
+public:
+    MessagesCallbackUserData(PostQueue& queue);
+    MessagesCallbackUserData(long cid, PostQueue& queue, bool keep = false);
+    virtual ~MessagesCallbackUserData();
+
+    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);
+    void SetError(const common::PlatformResult& error);
+    bool isError() const;
+    std::string getErrorName() const;
+    std::string getErrorMessage() const;
+
+    void setMessageServiceType(MessageType m_msg_type);
+    MessageType getMessageServiceType() const;
+
+    PostQueue& getQueue() { return queue_;};
+
+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;
+    PostQueue& queue_;
+};
+
+}//messaging
+}//extension
+
+#endif /* MESSAGING_MESSAGES_CALLBACK_USER_DATA_H_ */
diff --git a/webWidgetTCT_device/src/messaging/messages_change_callback.cc b/webWidgetTCT_device/src/messaging/messages_change_callback.cc
new file mode 100755 (executable)
index 0000000..19bdec5
--- /dev/null
@@ -0,0 +1,267 @@
+/*
+ * Copyright (c) 2015 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 <JSWebAPIErrorFactory.h>
+//#include <JSUtil.h>
+
+#include "common/logger.h"
+#include "common/platform_exception.h"
+#include "messaging_instance.h"
+
+#include "messages_change_callback.h"
+//#include "JSMessage.h"
+//#include "AbstractFilter.h"
+//#include "MessagingUtil.h"
+
+namespace extension {
+namespace messaging {
+
+namespace {
+
+std::string limitedString(const std::string& src,
+                          const size_t max_len = 40)
+{
+    LoggerD("Entered");
+    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(
+        long cid,
+        int service_id,
+        MessageType service_type,
+        PostQueue& queue) :
+        m_callback_data(cid, queue, true),
+        m_service_id(service_id),
+        m_msg_type(service_type),
+        m_is_act(true)
+{
+    LoggerD("Entered");
+}
+
+MessagesChangeCallback::~MessagesChangeCallback()
+{
+    LoggerD("Entered");
+}
+
+MessagePtrVector MessagesChangeCallback::filterMessages(
+        tizen::AbstractFilterPtr filter,
+        const MessagePtrVector& source_messages,
+        const int service_id)
+{
+    LoggerD("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);
+            }
+
+            LoggerD("[%d] is Message(%p) {", i, message.get());
+            LoggerD("[%d] messageId: %d", i, message->getId());
+            LoggerD("[%d] message subject: %s", i, message->getSubject().c_str());
+            LoggerD("[%d] from: %s", i, message->getFrom().c_str());
+
+            if(message->getBody()) {
+                const std::string& pBody = message->getBody()->getPlainBody();
+                LoggerD("[%d] message plainBody: %s", i, limitedString(pBody).c_str());
+            }
+
+            LoggerD("[%d] matched filter: %s", i, matched ? "YES" : "NO");
+            LoggerD("[%d] }");
+        }
+
+        LoggerD("returning matching %d of %d messages", filtered_messages.size(),
+                source_messages.size());
+        return filtered_messages;
+    }
+    else {
+        LoggerD("Abstract filter pointer is null");
+        return source_messages;
+    }
+}
+
+void MessagesChangeCallback::added(const MessagePtrVector& msgs)
+{
+    LoggerD("Entered num messages: %d", msgs.size());
+    if (!m_is_act) {
+        return;
+    }
+    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) {
+        LoggerD("All messages were filtered out, not calling callback");
+        return;
+    }
+
+    picojson::array array;
+    auto each = [&array] (std::shared_ptr<Message> m)->void {
+        array.push_back(MessagingUtil::messageToJson(m));
+    };
+
+    for_each(filtered_msgs.begin(), filtered_msgs.end(), each);
+
+    LoggerD("Calling:%s with:%d added messages", MESSAGESADDED,
+        filtered_msgs.size());
+
+    auto json = m_callback_data.getJson();
+    picojson::object& obj = json->get<picojson::object>();
+    if (json->contains(JSON_CALLBACK_ID) && obj.at(JSON_CALLBACK_ID).is<double>()) {
+      obj[JSON_ACTION] = picojson::value(MESSAGESADDED);
+      obj[JSON_DATA] = picojson::value(array);
+
+      m_callback_data.getQueue().addAndResolve(obj.at(
+          JSON_CALLBACK_ID).get<double>(), PostPriority::MEDIUM, json->serialize());
+    } else {
+      LoggerE("json is incorrect - missing required member");
+    }
+}
+
+void MessagesChangeCallback::updated(const MessagePtrVector& msgs)
+{
+    LoggerD("Entered num messages: %d", msgs.size());
+    if (!m_is_act) {
+        return;
+    }
+    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) {
+        LoggerD("All messages were filtered out, not calling callback");
+        return;
+    }
+
+    picojson::array array;
+    auto each = [&array] (std::shared_ptr<Message> m)->void {
+        array.push_back(MessagingUtil::messageToJson(m));
+    };
+
+    for_each(filtered_msgs.begin(), filtered_msgs.end(), each);
+
+    LoggerD("Calling:%s with:%d updated messages", MESSAGESUPDATED,
+        filtered_msgs.size());
+
+    auto json = m_callback_data.getJson();
+    picojson::object& obj = json->get<picojson::object>();
+    if (json->contains(JSON_CALLBACK_ID) && obj.at(JSON_CALLBACK_ID).is<double>()) {
+      obj[JSON_ACTION] = picojson::value(MESSAGESUPDATED);
+      obj[JSON_DATA] = picojson::value(array);
+
+      m_callback_data.getQueue().addAndResolve(obj.at(
+          JSON_CALLBACK_ID).get<double>(), PostPriority::LOW, json->serialize());
+    } else {
+      LoggerE("json is incorrect - missing required member");
+    }
+}
+
+void MessagesChangeCallback::removed(const MessagePtrVector& msgs)
+{
+    LoggerD("Enter event: msgs.size() = %d", msgs.size());
+    if (!m_is_act) {
+        return;
+    }
+
+    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) {
+        LoggerD("All messages were filtered out, not calling callback");
+        return;
+    }
+
+    picojson::array array;
+    auto each = [&array] (std::shared_ptr<Message> m)->void {
+        array.push_back(MessagingUtil::messageToJson(m));
+    };
+
+    for_each(filtered_msgs.begin(), filtered_msgs.end(), each);
+
+    LoggerD("Calling:%s with:%d removed messages", MESSAGESREMOVED,
+        filtered_msgs.size());
+
+    auto json = m_callback_data.getJson();
+    picojson::object& obj = json->get<picojson::object>();
+    if (json->contains(JSON_CALLBACK_ID) && obj.at(JSON_CALLBACK_ID).is<double>()) {
+      obj[JSON_ACTION] = picojson::value(MESSAGESREMOVED);
+      LoggerD("MESSAGES: %s", picojson::value(array).serialize().c_str());
+      obj[JSON_DATA] = picojson::value(array);
+
+      m_callback_data.getQueue().addAndResolve(obj.at(
+          JSON_CALLBACK_ID).get<double>(), PostPriority::LAST, json->serialize());
+    } else {
+      LoggerE("json is incorrect - missing required member");
+    }
+}
+
+void MessagesChangeCallback::setFilter(tizen::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;
+}
+
+
+} //namespace messaging
+} //namespace extension
diff --git a/webWidgetTCT_device/src/messaging/messages_change_callback.h b/webWidgetTCT_device/src/messaging/messages_change_callback.h
new file mode 100755 (executable)
index 0000000..457d9cc
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2015 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_MESSAGES_CHANGE_CALLBACK_H__
+#define __TIZEN_MESSAGES_CHANGE_CALLBACK_H__
+
+//#include <JavaScriptCore/JavaScript.h>
+
+//#include <MultiCallbackUserData.h>
+
+#include "MsgCommon/AbstractFilter.h"
+
+#include "message.h"
+#include "messaging_util.h"
+#include "messages_callback_user_data.h"
+
+namespace extension {
+namespace messaging {
+
+extern const char* MESSAGESADDED;
+extern const char* MESSAGESUPDATED;
+extern const char* MESSAGESREMOVED;
+
+class MessagesChangeCallback {
+public:
+    MessagesChangeCallback(
+            long cid,
+            int service_id,
+            MessageType service_type,
+            PostQueue& queue);
+    virtual ~MessagesChangeCallback();
+
+    void added(const MessagePtrVector& messages);
+    void updated(const MessagePtrVector& messages);
+    void removed(const MessagePtrVector& messages);
+
+    void setFilter(tizen::AbstractFilterPtr filter);
+    tizen::AbstractFilterPtr getFilter() const;
+
+    int getServiceId() const;
+    MessageType getServiceType() const;
+    static MessagePtrVector filterMessages(
+            tizen::AbstractFilterPtr a_filter,
+            const MessagePtrVector& a_sourceMessages,
+            const int service_id);
+
+    void setActive(bool act);
+    bool isActive();
+
+    void setItems(MessagePtrVector& items);
+    MessagePtrVector getItems();
+private:
+    MessagesCallbackUserData m_callback_data;
+    tizen::AbstractFilterPtr m_filter;
+    int m_service_id;
+    MessageType m_msg_type;
+    bool m_is_act;
+    MessagePtrVector m_items;
+};
+
+} //namespace messaging
+} //namespace extension
+
+
+#endif // __TIZEN_MESSAGES_CHANGE_CALLBACK_H__
diff --git a/webWidgetTCT_device/src/messaging/messaging.gyp b/webWidgetTCT_device/src/messaging/messaging.gyp
new file mode 100755 (executable)
index 0000000..7234709
--- /dev/null
@@ -0,0 +1,129 @@
+
+{
+  'includes':[
+    '../common/common.gypi',
+  ],
+  'targets': [
+    {
+      'target_name': 'tizen_messaging',
+      'type': 'loadable_module',
+      'dependencies': [
+        '../common/common.gyp:tizen_common',
+      ],
+      'variables': {
+        'packages': [
+            'msg-service',
+            'email-service',
+            'capi-system-info',
+            'ecore',
+            'ecore-file',
+            'tapi',
+            'vconf',
+            'db-util'
+        ],
+      },
+      'sources': [
+        'messaging_api.js',
+        'email_manager.cc',
+        'email_manager.h',
+        'messaging_instance.cc',
+        'messaging_instance.h',
+        'messaging_extension.cc',
+        'messaging_extension.h',
+        'messaging_manager.cc',
+        'messaging_manager.h',
+        'messaging_util.cc',
+        'messaging_util.h',
+        'message_service.cc',
+        'message_service.h',
+        'message_service_email.cc',
+        'message_service_email.h',
+        'message_storage.cc',
+        'message_storage.h',
+        'message_storage_email.cc',
+        'message_storage_email.h',
+        'message.cc',
+        'message.h',
+        'message_email.cc',
+        'message_email.h',
+        'message_attachment.cc',
+        'message_attachment.h',
+        'message_body.cc',
+        'message_body.h',
+        'message_callback_user_data.cc',
+        'message_callback_user_data.h',
+        'find_msg_callback_user_data.cc',
+        'find_msg_callback_user_data.h',
+        'messaging_database_manager.cc',
+        'messaging_databese_manager.h',
+        'DBus/EmailSignalProxy.cpp',
+        'DBus/EmailSignalProxy.h',
+        'DBus/LoadAttachmentProxy.cpp',
+        'DBus/LoadAttachmentProxy.h',
+        'DBus/LoadBodyProxy.cpp',
+        'DBus/LoadBodyProxy.h',
+        'DBus/MessageProxy.cpp',
+        'DBus/MessageProxy.h',
+        'DBus/SendProxy.cpp',
+        'DBus/SendProxy.h',
+        'DBus/SyncProxy.cpp',
+        'DBus/SyncProxy.h',
+        'DBus/DBusTypes.h',
+        'DBus/DBusTypes.cpp',
+        'MsgCommon/Any.cpp',
+        'MsgCommon/Any.h',
+        'MsgCommon/AbstractFilter.cpp',
+        'MsgCommon/AbstractFilter.h',
+        'MsgCommon/SortMode.cpp',
+        'MsgCommon/SortMode.h',
+        'MsgCommon/AttributeFilter.cpp',
+        'MsgCommon/AttributeFilter.h',
+        'MsgCommon/AttributeRangeFilter.cpp',
+        'MsgCommon/AttributeRangeFilter.h',
+        'MsgCommon/CompositeFilter.cpp',
+        'MsgCommon/CompositeFilter.h',
+        'MsgCommon/FilterIterator.cpp',
+        'MsgCommon/FilterIterator.h',
+        'message_callback_user_data.cc',
+        'message_callback_user_data.h',
+        'messages_callback_user_data.cc',
+        'messages_callback_user_data.h',
+        'change_listener_container.cc',
+        'change_listener_container.h',
+        'messages_change_callback.cc',
+        'messages_change_callback.h',
+        'message_folder.cc',
+        'message_folder.h',
+        'message_conversation.cc',
+        'message_conversation.h',
+        'conversation_callback_data.cc',
+        'conversation_callback_data.h',
+        'folders_callback_data.cc',
+        'folders_callback_data.h',
+        'conversations_change_callback.cc',
+        'conversations_change_callback.h',
+        'folders_change_callback.cc',
+        'folders_change_callback.h',
+        'message_service_short_msg.cc',
+        'message_service_short_msg.h',
+        'message_sms.cc',
+        'message_sms.h',
+        'message_storage_short_msg.cc',
+        'message_storage_short_msg.h',
+        'short_message_manager.cc',
+        'short_message_manager.h',
+        'message_mms.cc',
+        'message_mms.h'
+      ],
+      'includes': [
+        '../common/pkg-config.gypi',
+      ],
+      'conditions': [
+        ['tizen == 1', {
+          'variables': {
+          },
+        }],
+      ],
+    },
+  ],
+}
diff --git a/webWidgetTCT_device/src/messaging/messaging_api.js b/webWidgetTCT_device/src/messaging/messaging_api.js
new file mode 100755 (executable)
index 0000000..4ce117e
--- /dev/null
@@ -0,0 +1,1601 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+var validator_ = xwalk.utils.validator;
+var types_ = validator_.Types;
+var T_ = xwalk.utils.type;
+var bridge = xwalk.utils.NativeBridge(extension, true);
+
+function throwException_(err) {
+    throw new WebAPIException(err.code, err.name, err.message);
+}
+
+var Property = {
+    W: 1 << 0,   // WRITABLE
+    E: 1 << 1,   // ENUMERABLE
+    C: 1 << 2    // CONFIGURABLE
+}
+
+function addTypeToFilter_(data)
+{
+    var filter = {};
+
+    for(var field in data) {
+        filter[field] = data[field];
+    }
+
+    if (data instanceof tizen.AttributeFilter) {
+        filter.filterType = "AttributeFilter";
+        //convert to string
+        filter.matchValue = String(filter.matchValue);
+    } else if (data instanceof tizen.AttributeRangeFilter) {
+        filter.filterType = "AttributeRangeFilter";
+    } else if (data instanceof tizen.CompositeFilter) {
+        filter.filterType = "CompositeFilter";
+        // recursively convert all sub-filters
+        filter.filters = [];
+        for (var i = 0; i < data.filters.length; ++i) {
+            filter.filters[i] = addTypeToFilter_(data.filters[i]);
+        }
+    } else {
+        filter.filterType = "Unknown";
+    }
+
+    return filter;
+}
+
+/**
+ * Example usage:
+ * function Messaging () {
+ *     propertyFactory_(this, 'ids', [2,3,4], Property.W | Property.E | Property.C);
+ *     propertyFactory_(this, 'name', 'Name', Property.E);
+ *     propertyFactory_(this, 'age', 25, Property.W);
+ *     propertyFactory_(this, 'something', 1);
+ *     propertyFactory_(this, 'getSomething', Property.E, {get: function(){return 100;}});
+ * }
+ * Will produce:
+ * var m = new Messaging();
+ * {
+ *     id: [2,3,4],
+ *     name: 'Name',
+ *     age: 25
+ * }
+ *
+ * m.name = 'A brand new name';
+ * console.log(m.name); // Name
+ */
+function propertyFactory_(that, name, value, flags, options) {
+    flags = flags || 0;
+    if (options === null || typeof options !== 'object') {
+        options = {};
+    }
+    if (!(options.get) && !(options.set)) {
+        options.value = value;
+    }
+    if ((flags & Property.W) != 0) { options.writable     = true; }
+    if ((flags & Property.E) != 0) { options.enumerable   = true; }
+    if ((flags & Property.C) != 0) { options.configurable = true; }
+    Object.defineProperty(
+        that,
+        name,
+        options
+    );
+}
+
+function InternalValues_(data) {
+    if (!(this instanceof InternalValues_)) {
+        return new InternalValues_(data);
+    }
+    for(var key in data) {
+        if (data.hasOwnProperty(key)) {
+            this[key] = data[key];
+        }
+    }
+}
+
+function updateInternal_(internal, data) {
+    var values = new InternalValues_(data);
+    for(var key in data) {
+        if (values.hasOwnProperty(key) && internal.hasOwnProperty(key)) {
+            internal[key] = values;
+        }
+    }
+}
+
+/**
+ * Specifies the Messaging service tags.
+ */
+var MessageServiceTag = ['messaging.sms', 'messaging.mms', 'messaging.email'];
+
+function Message(type, data) {
+    if (!(this instanceof Message)) {
+        throw new TypeError("Constructor called like a function");
+    }
+    if (MessageServiceTag.indexOf(type) === -1) {
+        throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR);
+    }
+    if ( !data || typeof data !== 'object') { // 'data' is optional
+        data = {};
+    }
+
+    // set initial data from internal MessageInit_ object or to default values
+    var internal       = data instanceof MessageInit_,
+        id             = internal ? data.id             : null,
+        conversationId = internal ? data.conversationId : null,
+        folderId       = internal ? data.folderId       : null,
+        timestamp      = internal ? data.timestamp      : null,
+        from           = internal ? data.from           : null,
+        hasAttachment  = internal ? data.hasAttachment  : false,
+        isRead         = internal ? data.isRead         : false,
+        inResponseTo   = internal ? data.inResponseTo   : null;
+    // create MessageBody object
+    var body = new MessageBody({messageId: id, plainBody: data.plainBody, htmlBody: data.htmlBody});
+    // check 'to', 'cc' and 'bcc' fields
+    var to = data.to;
+    if (!(to instanceof Array)) {
+        to = [];
+    }
+    var cc = data.cc;
+    if (!(cc instanceof Array)) {
+        cc = [];
+    }
+    var bcc = data.bcc;
+    if (!(bcc instanceof Array)) {
+        bcc = [];
+    }
+    // 'attachments' private variable, getter and setter
+    var attachments = (internal ? data.attachments : []) || [];
+
+    var _internal = {
+        id: id || null,
+        conversationId: conversationId || null,
+        folderId: folderId || null,
+        type: type,
+        timestamp: timestamp || null,
+        from: from,
+        to: to || [],
+        cc: cc || [],
+        bcc: bcc || [],
+        body: body,
+        isRead: isRead || false,
+        hasAttachment: hasAttachment || false,
+        isHighPriority: data.isHighPriority || false,
+        subject: data.subject || '',
+        inResponseTo: inResponseTo || null,
+        attachments: attachments
+    };
+    // id
+    Object.defineProperty(
+        this,
+        'id',
+        {
+            get: function () {return _internal.id;},
+            set: function (value) { if (value instanceof InternalValues_) _internal.id = value.id;},
+            enumerable: true
+        }
+    );
+
+    //conversationId
+    Object.defineProperty(
+        this,
+        'conversationId',
+        {
+            get: function () {return _internal.conversationId;},
+            set: function (value) {
+                if (value instanceof InternalValues_)
+                    _internal.conversationId = value.conversationId;
+            },
+            enumerable: true
+        }
+    );
+
+    // folderId
+    Object.defineProperty(
+        this,
+        'folderId',
+        {
+            get: function () {return _internal.folderId;},
+            set: function (value) {
+                if (value instanceof InternalValues_) _internal.folderId = value.folderId;
+            },
+            enumerable: true
+        }
+    );
+
+    // type
+    Object.defineProperty(
+        this,
+        'type',
+        {
+            get: function () {return _internal.type;},
+            set: function (value) {return;},
+            enumerable: true
+        }
+    );
+
+    // timestamp
+    Object.defineProperty(
+        this,
+        'timestamp',
+        {
+            get: function () {
+                return _internal.timestamp ? new Date(_internal.timestamp * 1000) : _internal.timestamp;
+            },
+            set: function (value) {
+                if (value instanceof InternalValues_) {
+                    _internal.timestamp = value.timestamp;
+                }
+            },
+            enumerable: true
+        }
+    );
+
+    // from
+    Object.defineProperty(
+        this,
+        'from',
+        {
+            get: function () {return _internal.from;},
+            set: function (value) {
+                if (value instanceof InternalValues_) _internal.from = value.from;
+            },
+            enumerable: true
+        }
+    );
+
+    // to
+    Object.defineProperty(
+        this,
+        'to',
+        {
+            get: function () {return _internal.to;},
+            set: function (value) {
+                if (value instanceof InternalValues_) value = value.to;
+                if (value instanceof Array) _internal.to = value;
+            },
+            enumerable: true
+        }
+    );
+
+    // cc
+    Object.defineProperty(
+        this,
+        'cc',
+        {
+            get: function () {return _internal.cc;},
+            set: function (value) {
+                if (value instanceof InternalValues_) value = value.cc;
+                if (value instanceof Array) _internal.cc = value;
+            },
+            enumerable: true
+        }
+    );
+
+    // bcc
+    Object.defineProperty(
+        this,
+        'bcc',
+        {
+            get: function () {return _internal.bcc;},
+            set: function (value) {
+                if (value instanceof InternalValues_) value = value.bcc;
+                if (value instanceof Array) _internal.bcc = value;
+            },
+            enumerable: true
+        }
+    );
+
+    // body
+    Object.defineProperty(
+        this,
+        'body',
+        {
+            get: function () {return _internal.body;},
+            set: function (value) {
+                if (value instanceof InternalValues_) _internal.body = new MessageBody(value.body);
+                if (value instanceof MessageBody) _internal.body = value;
+            },
+            enumerable: true
+        }
+    );
+
+    // isRead
+    Object.defineProperty(
+        this,
+        'isRead',
+        {
+            get: function () {return _internal.isRead;},
+            set: function (value) {
+                if (value instanceof InternalValues_) {value = value.isRead;}
+                _internal.isRead = !!value;
+            },
+            enumerable: true
+        }
+    );
+
+    // hasAttachment
+    Object.defineProperty(
+        this,
+        'hasAttachment',
+        {
+            get: function () {return _internal.attachments.length > 0;},
+            set: function (value) {
+                if (value instanceof InternalValues_)
+                    _internal.hasAttachment = value.hasAttachment;
+            },
+            enumerable: true
+        }
+    );
+
+    // isHighPriority
+    Object.defineProperty(
+        this,
+        'isHighPriority',
+        {
+            get: function () {return _internal.isHighPriority;},
+            set: function (value) {
+                if (value instanceof InternalValues_) value = value.isHighPriority;
+                _internal.isHighPriority = !!value;
+            },
+            enumerable: true
+        }
+    );
+
+    // subject
+    Object.defineProperty(
+        this,
+        'subject',
+        {
+            get: function () {return _internal.subject;},
+            set: function (value) {
+                if (value instanceof InternalValues_) value = value.subject;
+                _internal.subject = String(value);
+            },
+            enumerable: true
+        }
+    );
+
+    // inResponseTo
+    Object.defineProperty(
+        this,
+        'inResponseTo',
+        {
+            get: function () {return _internal.inResponseTo;},
+            set: function (value) {
+                if (value instanceof InternalValues_) _internal.inResponseTo = value.inResponseTo;
+            },
+            enumerable: true
+        }
+    );
+
+    // messageStatus
+    Object.defineProperty(
+        this,
+        'messageStatus',
+        {
+            get: function () {
+                if (_internal.id) {
+                    // TODO create CPP layer
+                    /*
+                     *return bridge.sync({
+                     *    cmd: 'Message_messageStatus',
+                     *    args: {
+                     *        id: _internal.id
+                     *    }
+                     *});
+                     */
+                    return _internal.messageStatus;
+                } else {
+                    return '';
+                }
+            },
+            set: function (value) {return;},
+            enumerable: true
+        }
+    );
+
+    // attachments
+    Object.defineProperty(
+        this,
+        'attachments',
+        {
+            get: function () {return _internal.attachments;},
+            set: function(value) {
+                if (value instanceof InternalValues_) {
+                    value = value.attachments;
+                    for (var k = 0; k < value.length; ++k) {
+                        if (!(value[k] instanceof tizen.MessageAttachment)) {
+                            if (_internal.attachments[k]) {
+                                updateInternal_(_internal.attachments[k], value[k]);
+                            } else {
+                                _internal.attachments[k] = new MessageAttachment(
+                                        new InternalValues_(value[k]));
+                            }
+                        } else {
+                            _internal.attachments[k] = value[k];
+                        }
+                    }
+                    // if new array is shorter than the old one, remove excess elements
+                    if (value.length < _internal.length) {
+                        _internal.splice(value.length, _internal.length - value.length);
+                    }
+                } else if (T_.isArray(value)) {
+                    for (var k = 0; k < value.length; ++k) {
+                        if (!(value[k] instanceof tizen.MessageAttachment)) {
+                            return;
+                        }
+                    }
+                    _internal.attachments = value;
+                }
+            },
+            enumerable: true
+        }
+    );
+};
+
+function MessageInit(data) {
+    if (!(this instanceof MessageInit)) {
+        return new MessageInit(data);
+    }
+    if (data === null || typeof data !== 'object') {
+        data = {};
+    }
+    propertyFactory_(this, 'subject'       , data.subject        || ''   , Property.E | Property.W);
+    propertyFactory_(this, 'to'            , data.to             || []   , Property.E | Property.W);
+    propertyFactory_(this, 'cc'            , data.cc             || []   , Property.E | Property.W);
+    propertyFactory_(this, 'bcc'           , data.bcc            || []   , Property.E | Property.W);
+    propertyFactory_(this, 'plainBody'     , data.plainBody      || ''   , Property.E | Property.W);
+    propertyFactory_(this, 'htmlBody'      , data.htmlBody       || ''   , Property.E | Property.W);
+    propertyFactory_(this, 'isHighPriority', data.isHighPriority || false, Property.E | Property.W);
+};
+
+function MessageInit_(data) {
+    if (!(this instanceof MessageInit_)) {
+        return new MessageInit_(data);
+    }
+    if ( !data || typeof data !== 'object') {
+        data = {};
+    }
+    this.id             = data.id             || null;
+    this.conversationId = data.conversationId || null;
+    this.folderId       = data.folderId       || null;
+    this.timestamp      = data.timestamp      || null;
+    this.from           = data.from           || '';
+    this.to             = data.to             || [];
+    this.cc             = data.cc             || [];
+    this.bcc            = data.bcc            || [];
+    this.isRead         = data.isRead         || false;
+    this.hasAttachment  = data.hasAttachment  || null;
+    this.isHighPriority = data.isHighPriority || false;
+    this.subject        = data.subject        || '';
+    this.inResponseTo   = data.inResponseTo   || null;
+    this.attachments = [];
+    this.plainBody      = data.body ? data.body.plainBody : '';
+    this.htmlBody       = data.body ? data.body.htmlBody : '';
+
+    var self = this;
+    if (data.attachments && data.attachments.constructor === Array) {
+        data.attachments.forEach(function(el) {
+           if (!el) return;
+
+           if (el.constructor === MessageAttachment) {
+               self.attachments.push(el);
+           } else {
+               self.attachments.push(new MessageAttachment(new InternalValues_(el)));
+           }
+        });
+    }
+};
+
+function MessageBody(data) {
+    if (!this instanceof MessageBody) {
+        return new MessageBody(data);
+    }
+    if (data === null || typeof data !== 'object') {
+        data = {};
+    }
+
+    var _internal = {
+        messageId: data.messageId || null,
+        loaded: data.loaded || false,
+        plainBody: data.plainBody || '',
+        htmlBody: data.htmlBody || '',
+        inlineAttachments: data.inlineAttachments || []
+    };
+
+    // messageId
+    Object.defineProperty(
+        this,
+        'messageId',
+        {
+            get: function () {return _internal.messageId;},
+            set: function (value) {
+                if (value instanceof InternalValues_) _internal.messageId = value.messageId;
+            },
+            enumerable: true
+        }
+    );
+
+    // loaded
+    Object.defineProperty(
+        this,
+        'loaded',
+        {
+            get: function () {return _internal.loaded;},
+            set: function (value) {
+                if (value instanceof InternalValues_) _internal.loaded = value.loaded;
+            },
+            enumerable: true
+        }
+    );
+
+    // plainBody
+    Object.defineProperty(
+        this,
+        'plainBody',
+        {
+            get: function () {return _internal.plainBody;},
+            set: function (value) {
+                if (value instanceof InternalValues_) {
+                    _internal.plainBody = String(value.plainBody);
+                } else {
+                    _internal.plainBody = String(value);
+                }
+            },
+            enumerable: true
+        }
+    );
+
+    // htmlBody
+    Object.defineProperty(
+        this,
+        'htmlBody',
+        {
+            get: function () {return _internal.htmlBody;},
+            set: function (value) {
+                if (value instanceof InternalValues_) {
+                    _internal.htmlBody = String(value.htmlBody);
+                } else {
+                    _internal.htmlBody = String(value);
+                }
+            },
+            enumerable: true
+        }
+    );
+
+    // inlineAttachments
+    Object.defineProperty(
+        this,
+        'inlineAttachments',
+        {
+            get: function () {return _internal.inlineAttachments;},
+            set: function (value) {
+                if (value instanceof InternalValues_) {
+                    _internal.inlineAttachments = value.inlineAttachments;
+                } else if (T_.isArray(value)) {
+                    _internal.inlineAttachments = value;
+                }
+            },
+            enumerable: true
+        }
+    );
+};
+
+var messageAttachmentsLoaded = {};
+
+function MessageAttachment(first, second) {
+    validator_.isConstructorCall(this, MessageAttachment);
+    if (!this instanceof MessageAttachment) {
+        return new MessageAttachment(data);
+    }
+
+    var internalConstructor = first instanceof InternalValues_;
+    var _internal = {
+        messageId: internalConstructor ? first.messageId : null,
+        id: internalConstructor ? first.id : null,
+        mimeType: internalConstructor ? first.mimeType : (undefined == second ? null : second),
+        filePath: internalConstructor ? first.filePath : first,
+    };
+
+    // messageId
+    Object.defineProperty(
+        this,
+        'messageId',
+        {
+            get: function () {return _internal.messageId;},
+            set: function (value) {
+                if (value instanceof InternalValues_) _internal.messageId = value.messageId;
+            },
+            enumerable: true
+        }
+    );
+    // id
+    Object.defineProperty(
+        this,
+        'id',
+        {
+            get: function () {return _internal.id;},
+            set: function (value) {
+                if (value instanceof InternalValues_) _internal.id = value.id;
+            },
+            enumerable: true
+        }
+    );
+    // mimeType
+    Object.defineProperty(
+        this,
+        'mimeType',
+        {
+            get: function () {return _internal.mimeType;},
+            set: function (value) {
+                if (value instanceof InternalValues_) _internal.mimeType = value.mimeType;
+            },
+            enumerable: true
+        }
+    );
+    // filePath
+    Object.defineProperty(
+        this,
+        'filePath',
+        {
+            get: function () {
+                if (_internal.id && !messageAttachmentsLoaded[_internal.id]) {
+                    return null;
+                }
+
+                return _internal.filePath;
+            },
+            set: function (value) {
+                if (value instanceof InternalValues_) _internal.filePath = value.filePath;
+            },
+            enumerable: true
+        }
+    );
+};
+
+function Messaging() {};
+
+/**
+ * Gets the messaging service of a given type for a given account.
+ * @param {!MessageServiceTag} messageServiceType Type of the services to be retrieved.
+ * @param {!MessageServiceArraySuccessCallback} successCallback Callback function that is called
+ *     when the services are successfully retrieved.
+ * @param {ErrorCallback} errorCallback Callback function that is called when an error occurs.
+ */
+Messaging.prototype.getMessageServices = function () {
+    var args = validator_.validateArgs(arguments, [
+        {name: 'messageServiceType', type: types_.ENUM, values: MessageServiceTag},
+        {name: 'successCallback', type: types_.FUNCTION},
+        {name: 'errorCallback', type: types_.FUNCTION, optional: true, nullable: true}
+    ]);
+
+    bridge.async({
+        cmd: 'Messaging_getMessageServices',
+        args: {
+            messageServiceType: args.messageServiceType
+        }
+    }).then({
+        success: function (data) {
+            var servicesArr = [];
+            data.forEach(function(e){
+                servicesArr.push(new MessageService(e));
+            });
+            args.successCallback.call(null, servicesArr);
+        },
+        error: function (e) {
+            if (args.errorCallback) {
+                args.errorCallback.call(
+                    null,
+                    new WebAPIException(e.error)
+                )
+            }
+        }
+    });
+}
+function MessageStorage(){};
+function MessageService(data) {
+    propertyFactory_(this, 'id', data.id, Property.E);
+    propertyFactory_(this, 'type', data.type, Property.E);
+    propertyFactory_(this, 'name', data.name, Property.E);
+    propertyFactory_(this, 'messageStorage', new MessageStorage(this), Property.E);
+};
+
+MessageService.prototype.sendMessage = function () {
+    xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.MESSAGING_WRITE);
+
+    var args = validator_.validateArgs(arguments, [
+        {name: 'message', type: types_.PLATFORM_OBJECT, values: tizen.Message},
+        {name: 'successCallback', type: types_.FUNCTION, optional: true, nullable: true},
+        {name: 'errorCallback', type: types_.FUNCTION, optional: true, nullable: true},
+        {name: 'simIndex', type: types_.LONG, optional: true, nullable: true}
+    ]);
+
+    if (args.message.type != this.type) {
+        throw new tizen.WebAPIException(tizen.WebAPIException.TYPE_MISMATCH_ERR);
+    }
+
+    var self = this;
+    bridge.async({
+        cmd: 'MessageService_sendMessage',
+        args: {
+            message: args.message,
+            simIndex: args.simIndex || 1,
+            serviceId: self.id
+        }
+    }).then({
+        success: function (data) {
+            var message = data.message;
+            if (message) {
+                var body = message.body;
+                if (body) {
+                    updateInternal_(args.message.body, body)
+                    delete message.body;
+                }
+                updateInternal_(args.message, message);
+            }
+
+            if (args.successCallback) {
+                args.successCallback.call(null, data.recipients);
+            }
+        },
+        error: function (e) {
+            if (args.errorCallback) {
+                args.errorCallback.call(
+                    null,
+                    new WebAPIException(e.error)
+                )
+            }
+        }
+    });
+};
+
+MessageService.prototype.loadMessageBody = function () {
+    xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.MESSAGING_WRITE);
+
+    var args = validator_.validateArgs(arguments, [
+        {name: 'message', type: types_.PLATFORM_OBJECT, values: tizen.Message},
+        {name: 'successCallback', type: types_.FUNCTION},
+        {name: 'errorCallback', type: types_.FUNCTION, optional: true, nullable: true}
+    ]);
+
+    if (args.message.type != this.type) {
+        throw new tizen.WebAPIException(tizen.WebAPIException.TYPE_MISMATCH_ERR);
+    }
+
+    var self = this;
+
+    bridge.async({
+        cmd: 'MessageService_loadMessageBody',
+        args: {
+            message: args.message,
+            serviceId: self.id
+        }
+    }).then({
+        success: function (data) {
+            var body = data.messageBody;
+            if (body) {
+                updateInternal_(args.message.body, body)
+            }
+
+            args.successCallback.call(
+                null,
+                args.message
+            );
+        },
+        error: function (e) {
+            if (args.errorCallback) {
+                args.errorCallback.call(
+                    null,
+                    new WebAPIException(e.error)
+                )
+            }
+        }
+    });
+};
+MessageService.prototype.loadMessageAttachment = function () {
+    xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.MESSAGING_WRITE);
+
+    var args = validator_.validateArgs(arguments, [
+        {name: 'attachment', type: types_.PLATFORM_OBJECT, values: MessageAttachment},
+        {name: 'successCallback', type: types_.FUNCTION},
+        {name: 'errorCallback', type: types_.FUNCTION, optional: true, nullable: true}
+    ]);
+
+    var self = this;
+    var firstCall = false;
+    if (!messageAttachmentsLoaded[args.attachment.id]) {
+        firstCall = true;
+        messageAttachmentsLoaded[args.attachment.id] = true;
+    }
+
+    bridge.async({
+        cmd: 'MessageService_loadMessageAttachment',
+        args: {
+            attachment: args.attachment,
+            serviceId: self.id
+        }
+    }).then({
+        success: function (data) {
+            if (args.successCallback) {
+                var messageAttachment = data.messageAttachment;
+                if (messageAttachment) {
+                    updateInternal_(args.attachment, messageAttachment);
+                }
+
+                args.successCallback.call(
+                    null,
+                    args.attachment
+                );
+            }
+        },
+        error: function (e) {
+            if (firstCall) {
+                messageAttachmentsLoaded[args.attachment.id] = false;
+            }
+            if (args.errorCallback) {
+                args.errorCallback.call(
+                    null,
+                    new WebAPIException(e.error)
+                )
+            }
+        }
+    });
+};
+
+MessageService.prototype.sync = function () {
+    xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.MESSAGING_WRITE);
+
+    var args = validator_.validateArgs(arguments, [
+        {name: 'successCallback', type: types_.FUNCTION, optional: true, nullable: true},
+        {name: 'errorCallback', type: types_.FUNCTION, optional: true, nullable: true},
+        {name: 'limit', type: types_.UNSIGNED_LONG, optional: true, nullable: true}
+    ]);
+
+    var self = this;
+    var cid = bridge.listener({
+        success: function () {
+            if (args.successCallback) {
+                args.successCallback.call(null);
+            }
+        },
+        error: function (e) {
+            if (args.errorCallback) {
+                args.errorCallback.call(
+                    null,
+                    new WebAPIException(e.error)
+                )
+            }
+        }
+    });
+
+    var result = bridge.sync({
+        cmd: 'MessageService_sync',
+        cid: cid,
+        args: {
+            id: self.id,
+            limit: args.limit || null
+        }
+    });
+
+    return result;
+};
+
+MessageService.prototype.syncFolder = function () {
+    xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.MESSAGING_WRITE);
+
+    var args = validator_.validateArgs(arguments, [
+        {name: 'folder', type: types_.PLATFORM_OBJECT, values: MessageFolder},
+        {name: 'successCallback', type: types_.FUNCTION, optional: true, nullable: true},
+        {name: 'errorCallback', type: types_.FUNCTION, optional: true, nullable: true},
+        {name: 'limit', type: types_.UNSIGNED_LONG, optional: true, nullable: true}
+    ]);
+
+    var self = this;
+    var cid = bridge.listener({
+        success: function () {
+            if (args.successCallback) {
+                args.successCallback.call(null);
+            }
+        },
+        error: function (e) {
+            if (args.errorCallback) {
+                args.errorCallback.call(
+                    null,
+                    new WebAPIException(e.error)
+                )
+            }
+        }
+    });
+
+    var result = bridge.sync({
+        cmd: 'MessageService_syncFolder',
+        cid: cid,
+        args: {
+            id: self.id,
+            folder: args.folder,
+            limit: args.limit || null
+        }
+    });
+
+    return result;
+};
+
+MessageService.prototype.stopSync = function () {
+    var args = validator_.validateArgs(arguments, [
+        {name: 'opId', type: types_.LONG}
+    ]);
+
+    var self = this;
+    bridge.sync({
+        cmd: 'MessageService_stopSync',
+        args: {
+            id: self.id,
+            opId: args.opId
+        }
+    });
+};
+
+function MessageStorage(service) {
+    propertyFactory_(this, 'service', service);
+};
+
+MessageStorage.prototype.addDraftMessage = function () {
+    xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.MESSAGING_WRITE);
+
+    var args = validator_.validateArgs(arguments, [
+        {name: 'message', type: types_.PLATFORM_OBJECT, values: tizen.Message},
+        {name: 'successCallback', type: types_.FUNCTION, optional: true, nullable: true},
+        {name: 'errorCallback', type: types_.FUNCTION, optional: true, nullable: true}
+    ]);
+
+    if (args.message.type != this.service.type) {
+        throw new tizen.WebAPIException(tizen.WebAPIException.TYPE_MISMATCH_ERR);
+    }
+
+    var self = this;
+    bridge.async({
+        cmd: 'MessageStorage_addDraftMessage',
+        args: {
+            message: args.message,
+            serviceId: self.service.id
+        }
+    }).then({
+        success: function (data) {
+            var message = data.message;
+            if (message) {
+                var body = message.body;
+                if (body) {
+                    updateInternal_(args.message.body, body)
+                    delete message.body;
+                }
+                var attachments = message.attachments;
+                if (attachments) {
+                    for (var i = 0; i < attachments.length; i++) {
+                        messageAttachmentsLoaded[attachments[i].id] = true;
+                    }
+                }
+                updateInternal_(args.message, message);
+            }
+
+            if (args.successCallback) {
+                args.successCallback.call(null);
+            }
+        },
+        error: function (e) {
+            if (args.errorCallback) {
+                args.errorCallback.call(
+                    null,
+                    new WebAPIException(e.error)
+                )
+            }
+        }
+    });
+};
+
+MessageStorage.prototype.findMessages = function () {
+    xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.MESSAGING_READ);
+
+    var args = validator_.validateArgs(arguments, [
+        {
+            name: 'filter',
+            type: types_.PLATFORM_OBJECT,
+            values: [tizen.AttributeFilter, tizen.AttributeRangeFilter, tizen.CompositeFilter]
+        },
+        {name: 'successCallback', type: types_.FUNCTION},
+        {name: 'errorCallback', type: types_.FUNCTION, optional: true, nullable: true},
+        {name: 'sort', type: types_.PLATFORM_OBJECT, values: tizen.SortMode, optional: true,
+                nullable: true},
+        {name: 'limit', type: types_.UNSIGNED_LONG, optional: true, nullable: true},
+        {name: 'offset', type: types_.UNSIGNED_LONG, optional: true, nullable: true}
+    ]);
+
+    var self = this;
+
+    bridge.async({
+        cmd: 'MessageStorage_findMessages',
+        args: {
+            filter: addTypeToFilter_(args.filter) || null,
+            sort: args.sort || null,
+            limit: args.limit || null,
+            offset: args.offset || null,
+            serviceId: self.service.id,
+            type: self.service.type
+        }
+    }).then({
+        success: function (data) {
+            var messages = [];
+            data.forEach(function (el) {
+                messages.push(new tizen.Message(el.type, new MessageInit_(el)));
+            });
+            args.successCallback.call(null, messages);
+        },
+        error: function (e) {
+            if (args.errorCallback) {
+                args.errorCallback.call(
+                    null,
+                    new WebAPIException(e.error)
+                )
+            }
+        }
+    });
+};
+
+MessageStorage.prototype.removeMessages = function () {
+    xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.MESSAGING_WRITE);
+
+    var args = validator_.validateArgs(arguments, [
+        {name: 'messages', type: types_.ARRAY, values: Message},
+        {name: 'successCallback', type: types_.FUNCTION, optional: true, nullable: true},
+        {name: 'errorCallback', type: types_.FUNCTION, optional: true, nullable: true}
+    ]);
+
+    var self = this;
+
+    args.messages.forEach(function(msg) {
+        if (msg.type != self.service.type) {
+            throw new tizen.WebAPIException(tizen.WebAPIException.TYPE_MISMATCH_ERR);
+        }
+    });
+
+    bridge.async({
+        cmd: 'MessageStorage_removeMessages',
+        args: {
+            messages: args.messages,
+            serviceId: self.service.id,
+            type: self.service.type
+        }
+    }).then({
+        success: function () {
+            if (args.successCallback) {
+                args.successCallback.call(null);
+            }
+        },
+        error: function (e) {
+            if (args.errorCallback) {
+                args.errorCallback.call(
+                    null,
+                    new WebAPIException(e.error)
+                )
+            }
+        }
+    });
+};
+
+MessageStorage.prototype.updateMessages = function () {
+    xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.MESSAGING_WRITE);
+
+    var args = validator_.validateArgs(arguments, [
+        {name: 'messages', type: types_.ARRAY, values: Message},
+        {name: 'successCallback', type: types_.FUNCTION, optional: true, nullable: true},
+        {name: 'errorCallback', type: types_.FUNCTION, optional: true, nullable: true}
+    ]);
+
+    var self = this;
+
+    args.messages.forEach(function(msg) {
+        if (msg.type != self.service.type) {
+            throw new tizen.WebAPIException(tizen.WebAPIException.TYPE_MISMATCH_ERR);
+        }
+    });
+
+    bridge.async({
+        cmd: 'MessageStorage_updateMessages',
+        args: {
+            messages: args.messages,
+            serviceId: self.service.id
+        }
+    }).then({
+        success: function (data) {
+            var originals = {},
+                    i = args.messages.length,
+                    m;
+            while (i--) {
+                m = args.messages[i];
+                if (m.id) {
+                    originals[m.id] = m;
+                }
+            }
+
+            i = data.length;
+            while (i--) {
+                m = data[i];
+                if (originals[m.oldId]) {
+                    var body = m.body;
+                    if (body) {
+                        updateInternal_(originals[m.oldId].body, body)
+                        delete m.body;
+                    }
+                    updateInternal_(originals[m.oldId], m);
+                }
+            }
+
+            if (args.successCallback) {
+                args.successCallback.call(null);
+            }
+        },
+        error: function (e) {
+            if (args.errorCallback) {
+                args.errorCallback.call(
+                    null,
+                    new WebAPIException(e.error)
+                )
+            }
+        }
+    });
+};
+
+MessageStorage.prototype.findConversations = function () {
+    xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.MESSAGING_READ);
+
+    var args = validator_.validateArgs(arguments, [
+        {
+            name: 'filter',
+            type: types_.PLATFORM_OBJECT,
+            values: [tizen.AttributeFilter, tizen.AttributeRangeFilter, tizen.CompositeFilter]
+        },
+        {name: 'successCallback', type: types_.FUNCTION},
+        {name: 'errorCallback', type: types_.FUNCTION, optional: true, nullable: true},
+        {name: 'sort', type: types_.PLATFORM_OBJECT, values: tizen.SortMode, optional: true,
+                nullable: true},
+        {name: 'limit', type: types_.UNSIGNED_LONG, optional: true, nullable: true},
+        {name: 'offset', type: types_.UNSIGNED_LONG, optional: true, nullable: true}
+    ]);
+
+    var self = this;
+
+    bridge.async({
+        cmd: 'MessageStorage_findConversations',
+        args: {
+            filter: addTypeToFilter_(args.filter),
+            sort: args.sort || null,
+            limit: args.limit || null,
+            offset: args.offset || null,
+            serviceId: self.service.id
+        }
+    }).then({
+        success: function (data) {
+            var conversations = [];
+            data.forEach(function (el) {
+                conversations.push(new MessageConversation(el));
+            });
+            args.successCallback.call(null, conversations);
+        },
+        error: function (e) {
+            if (args.errorCallback) {
+                args.errorCallback.call(
+                    null,
+                    new WebAPIException(e.error)
+                )
+            }
+        }
+    });
+};
+
+MessageStorage.prototype.removeConversations = function () {
+    xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.MESSAGING_WRITE);
+
+    var args = validator_.validateArgs(arguments, [
+        {name: 'conversations', type: types_.ARRAY},
+        {name: 'successCallback', type: types_.FUNCTION, optional: true, nullable: true},
+        {name: 'errorCallback', type: types_.FUNCTION, optional: true, nullable: true}
+    ]);
+
+    args.conversations.forEach(function (el) {
+        if (!el || el.constructor !== MessageConversation) {
+            throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR);
+        }
+    });
+
+    var self = this;
+
+    bridge.async({
+        cmd: 'MessageStorage_removeConversations',
+        args: {
+            conversations: args.conversations,
+            serviceId: self.service.id,
+            type: self.service.type
+        }
+    }).then({
+        success: function () {
+            if (args.successCallback) {
+                args.successCallback.call(null);
+            }
+        },
+        error: function (e) {
+            if (args.errorCallback) {
+                args.errorCallback.call(
+                    null,
+                    new WebAPIException(e.error)
+                )
+            }
+        }
+    });
+};
+
+MessageStorage.prototype.findFolders = function () {
+    xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.MESSAGING_READ);
+
+    var args = validator_.validateArgs(arguments, [
+        {
+            name: 'filter',
+            type: types_.PLATFORM_OBJECT,
+            values: [tizen.AttributeFilter, tizen.AttributeRangeFilter, tizen.CompositeFilter]
+        },
+        {name: 'successCallback', type: types_.FUNCTION},
+        {name: 'errorCallback', type: types_.FUNCTION, optional: true, nullable: true}
+    ]);
+
+    var self = this;
+
+    bridge.async({
+        cmd: 'MessageStorage_findFolders',
+        args: {
+            filter: addTypeToFilter_(args.filter),
+            sort: args.sort || null,
+            limit: args.limit || null,
+            offset: args.offset || null,
+            serviceId: self.service.id
+        }
+    }).then({
+        success: function (data) {
+            var folders = [];
+            data.forEach(function (el) {
+                folders.push(new MessageFolder(el));
+            });
+            args.successCallback.call(null, folders);
+        },
+        error: function (e) {
+            if (args.errorCallback) {
+                args.errorCallback.call(
+                    null,
+                    new WebAPIException(e.error)
+                )
+            }
+        }
+    });
+};
+
+MessageStorage.prototype.addMessagesChangeListener = function () {
+    xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.MESSAGING_READ);
+
+    var args = validator_.validateArgs(arguments, [
+        {name: 'messagesChangeCallback', type: types_.LISTENER,
+                values: ['messagesadded', 'messagesupdated', 'messagesremoved']},
+        {
+            name: 'filter',
+            type: types_.PLATFORM_OBJECT,
+            values: [tizen.AttributeFilter, tizen.AttributeRangeFilter, tizen.CompositeFilter],
+            optional: true,
+            nullable: true
+        }
+    ]);
+
+    var self = this;
+
+    var cid = bridge.listener({
+        messagesadded: function (data) {
+            if (args.messagesChangeCallback.messagesadded) {
+                var messages = [];
+                data.forEach(function (el) {
+                    messages.push(new tizen.Message(el.type, new MessageInit_(el)));
+                });
+                args.messagesChangeCallback.messagesadded.call(null, messages);
+            }
+        },
+        messagesupdated: function (data) {
+            if (args.messagesChangeCallback.messagesupdated) {
+                var messages = [];
+                data.forEach(function (el) {
+                    messages.push(new tizen.Message(el.type, new MessageInit_(el)));
+                });
+                args.messagesChangeCallback.messagesupdated.call(null, messages);
+            }
+        },
+        messagesremoved: function (data) {
+            if (args.messagesChangeCallback.messagesremoved) {
+                var messages = [];
+                data.forEach(function (el) {
+                    messages.push(new tizen.Message(el.type, new MessageInit_(el)));
+                });
+                args.messagesChangeCallback.messagesremoved.call(null, messages);
+            }
+        }
+    });
+
+    var result = bridge.sync({
+        cmd: 'MessageStorage_addMessagesChangeListener',
+        cid: cid,
+        args: {
+            filter: args.filter ? addTypeToFilter_(args.filter) : null,
+            serviceId: self.service.id
+        }
+    });
+
+    bridge.attach(cid, 'watchId', result);
+    return result;
+};
+
+MessageStorage.prototype.addConversationsChangeListener = function () {
+    xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.MESSAGING_READ);
+
+    var args = validator_.validateArgs(arguments, [
+        {name: 'conversationsChangeCallback', type: types_.LISTENER,
+                values: ['conversationsadded', 'conversationsupdated', 'conversationsremoved']},
+        {
+            name: 'filter',
+            type: types_.PLATFORM_OBJECT,
+            values: [tizen.AttributeFilter, tizen.AttributeRangeFilter, tizen.CompositeFilter],
+            optional: true,
+            nullable: true
+        }
+    ]);
+
+    var self = this;
+
+    var cid = bridge.listener({
+        conversationsadded: function (data) {
+            if (args.conversationsChangeCallback.conversationsadded) {
+                var conversations = [];
+                data.forEach(function (el) {
+                    conversations.push(new MessageConversation(el));
+                });
+                args.conversationsChangeCallback.conversationsadded.call(null, conversations);
+            }
+        },
+        conversationsupdated: function (data) {
+            if (args.conversationsChangeCallback.conversationsupdated) {
+                var conversations = [];
+                data.forEach(function (el) {
+                   conversations.push(new MessageConversation(el));
+                });
+                args.conversationsChangeCallback.conversationsupdated.call(null, conversations);
+            }
+        },
+        conversationsremoved: function (data) {
+            if (args.conversationsChangeCallback.conversationsremoved) {
+                var conversations = [];
+                data.forEach(function (el) {
+                    conversations.push(new MessageConversation(el));
+                });
+                args.conversationsChangeCallback.conversationsremoved.call(null, conversations);
+            }
+        }
+    });
+
+    var result = bridge.sync({
+        cmd: 'MessageStorage_addConversationsChangeListener',
+        cid: cid,
+        args: {
+            filter: args.filter ? addTypeToFilter_(args.filter) : null,
+            serviceId: self.service.id
+        }
+    });
+
+    bridge.attach(cid, 'watchId', result);
+    return result;
+};
+
+MessageStorage.prototype.addFoldersChangeListener = function () {
+    xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.MESSAGING_READ);
+
+    var args = validator_.validateArgs(arguments, [
+        {name: 'foldersChangeCallback', type: types_.LISTENER,
+                values: ['foldersadded', 'foldersupdated', 'foldersremoved']},
+        {
+            name: 'filter',
+            type: types_.PLATFORM_OBJECT,
+            values: [tizen.AttributeFilter, tizen.AttributeRangeFilter, tizen.CompositeFilter],
+            optional: true,
+            nullable: true
+        }
+    ]);
+
+    var self = this;
+
+    var cid = bridge.listener({
+        foldersadded: function (data) {
+            if (args.foldersChangeCallback.foldersadded) {
+                var folders = [];
+                data.forEach(function (el) {
+                    folders.push(new MessageFolder(el));
+                });
+                args.foldersChangeCallback.foldersadded.call(null, folders);
+            }
+        },
+        foldersupdated: function (data) {
+            if (args.foldersChangeCallback.foldersupdated) {
+                var folders = [];
+                data.forEach(function (el) {
+                    folders.push(new MessageFolder(el));
+                });
+                args.foldersChangeCallback.foldersupdated.call(null, folders);
+            }
+        },
+        foldersremoved: function (data) {
+            if (args.foldersChangeCallback.foldersremoved) {
+                var folders = [];
+                data.forEach(function (el) {
+                    folders.push(new MessageFolder(el));
+                });
+                args.foldersChangeCallback.foldersremoved.call(null, folders);
+            }
+        }
+    });
+
+    var result = bridge.sync({
+        cmd: 'MessageStorage_addFoldersChangeListener',
+        cid: cid,
+        args: {
+            filter: args.filter ? addTypeToFilter_(args.filter) : null,
+            serviceId: self.service.id
+        }
+    });
+
+    bridge.attach(cid, 'watchId', result);
+    return result;
+};
+
+MessageStorage.prototype.removeChangeListener = function () {
+    xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.MESSAGING_READ);
+
+    var args = validator_.validateArgs(arguments, [
+        {name: 'watchId', type: types_.LONG}
+    ]);
+
+    var self = this;
+
+    var result = bridge.sync({
+        cmd: 'MessageStorage_removeChangeListener',
+        args: {
+            watchId: args.watchId,
+            serviceId: self.service.id
+        }
+    });
+
+    bridge.find('watchId', args.watchId).forEach(function (e) {
+        bridge.remove(e.id);
+    });
+    return result;
+};
+
+function MessageConversation(data) {
+    propertyFactory_(this, 'id'            , data.id             || null , Property.E);
+    propertyFactory_(this, 'type'          , data.type           || ''   , Property.E);
+    propertyFactory_(this, 'timestamp'     , data.timestamp ? new Date(data.timestamp * 1000) : null , Property.E);
+    propertyFactory_(this, 'messageCount'  , data.messageCount   || 0    , Property.E);
+    propertyFactory_(this, 'unreadMessages', data.unreadMessages || 0    , Property.E);
+    propertyFactory_(this, 'preview'       , data.preview        || ''   , Property.E);
+    propertyFactory_(this, 'subject'       , data.subject        || ''   , Property.E);
+    propertyFactory_(this, 'isRead'        , data.isRead         || false, Property.E);
+    propertyFactory_(this, 'from'          , data.from           || null , Property.E);
+    propertyFactory_(this, 'to'            , data.to             || []   , Property.E);
+    propertyFactory_(this, 'cc'            , data.cc             || []   , Property.E);
+    propertyFactory_(this, 'bcc'           , data.bcc            || []   , Property.E);
+    propertyFactory_(this, 'lastMessageId' , data.lastMessageId  || null , Property.E);
+};
+
+function MessageFolder(data) {
+    var _internal = {
+            id: data.id || null,
+            parentId: data.parentId || null,
+            serviceId: data.serviceId || '',
+            contentType: data.contentType || '',
+            name: data.name || '',
+            path: data.path || '',
+            type: data.type || '',
+            synchronizable: data.synchronizable || false
+        };
+
+        Object.defineProperty(
+            this,
+            'id',
+            {
+                get: function () {return _internal.id;},
+                enumerable: true
+            }
+        );
+
+        Object.defineProperty(
+                this,
+                'parentId',
+                {
+                    get: function () {return _internal.parentId;},
+                    enumerable: true
+                }
+        );
+
+        Object.defineProperty(
+                this,
+                'serviceId',
+                {
+                    get: function () {return _internal.serviceId;},
+                    enumerable: true
+                }
+        );
+
+        Object.defineProperty(
+                this,
+                'contentType',
+                {
+                    get: function () {return _internal.contentType;},
+                    enumerable: true
+                }
+        );
+
+        Object.defineProperty(
+                this,
+                'name',
+                {
+                    get: function () {return _internal.name;},
+                    set: function (value) { if (value) _internal.name = value;},
+                    enumerable: true
+                }
+        );
+
+        Object.defineProperty(
+                this,
+                'path',
+                {
+                    get: function () {return _internal.path;},
+                    enumerable: true
+                }
+        );
+
+        Object.defineProperty(
+                this,
+                'type',
+                {
+                    get: function () {return _internal.type;},
+                    enumerable: true
+                }
+        );
+
+        Object.defineProperty(
+                this,
+                'synchronizable',
+                {
+                    get: function () {return _internal.synchronizable;},
+                    set: function (value) { _internal.synchronizable = Boolean(value);},
+                    enumerable: true
+                }
+        );
+};
+
+tizen.Message = Message;
+
+tizen.MessageAttachment = MessageAttachment;
+
+exports = new Messaging();
diff --git a/webWidgetTCT_device/src/messaging/messaging_database_manager.cc b/webWidgetTCT_device/src/messaging/messaging_database_manager.cc
new file mode 100755 (executable)
index 0000000..8731c7f
--- /dev/null
@@ -0,0 +1,964 @@
+/*
+ * Copyright (c) 2015 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 <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 "common/logger.h"
+#include "common/platform_exception.h"
+
+#include "conversation_callback_data.h"
+#include "messaging_database_manager.h"
+#include "messaging_manager.h"
+
+using namespace common;
+using namespace extension::tizen;
+
+namespace extension {
+namespace messaging {
+
+AttributeInfo::AttributeInfo() :
+        sql_name(),
+        sql_type(UNDEFINED_TYPE),
+        any_type(PrimitiveType_NoType)
+{
+    LoggerD("Entered");
+}
+
+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)
+{
+    LoggerD("Entered");
+}
+
+AttributeInfo::AttributeInfo(const AttributeInfo& other) :
+        sql_name(other.sql_name),
+        sql_type(other.sql_type),
+        any_type(other.any_type)
+{
+    LoggerD("Entered");
+}
+
+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()
+{
+    LoggerD("Entered");
+// 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()
+{
+    LoggerD("Entered");
+}
+
+MessagingDatabaseManager& MessagingDatabaseManager::getInstance()
+{
+    LoggerD("Entered");
+    static MessagingDatabaseManager instance;
+    return instance;
+}
+
+__thread sqlite3* sqlHandle = NULL;
+__thread sqlite3_stmt* stmt = NULL;
+
+msg_error_t MessagingDatabaseManager::connect()
+{
+    LoggerD("Entered");
+    if (NULL == sqlHandle) {
+        char strDBName[64];
+
+        memset(strDBName, 0x00, sizeof(strDBName));
+        snprintf(strDBName, sizeof(strDBName), "%s", MSG_DB_NAME);
+
+        int err = db_util_open(strDBName, &sqlHandle, DB_UTIL_REGISTER_HOOK_METHOD);
+
+        if (SQLITE_OK != err) {
+            LoggerE("DB connecting fail [%d]", err);
+            return MSG_ERR_DB_CONNECT;
+        }
+
+        LoggerD("DB connecting success: [%d]", sqlHandle);
+    } else {
+        LoggerD("DB connection exists: [%d]", sqlHandle);
+    }
+
+    return MSG_SUCCESS;
+}
+
+msg_error_t MessagingDatabaseManager::disconnect()
+{
+    LoggerD("Entered");
+    msg_error_t err = 0;
+    if (NULL != sqlHandle) {
+        err = db_util_close(sqlHandle);
+
+        if (SQLITE_OK != err) {
+            LoggerE("DB disconnecting fail [%d]", err);
+            return MSG_ERR_DB_DISCONNECT;
+        }
+
+        sqlHandle = NULL;
+        LoggerD("DB disconnecting success");
+    }
+
+    return MSG_SUCCESS;
+}
+
+msg_error_t MessagingDatabaseManager::getTable(std::string sqlQuery,
+        char*** results,
+        int* resultsCount)
+{
+    LoggerD("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) {
+        LoggerE("Getting table fail [%d] error_msg:%s querry was:%s", err, error_msg,
+                sqlQuery.c_str());
+        freeTable(results);
+        return MSG_ERR_DB_GETTABLE;
+    }
+
+    LoggerD("Getting table success");
+    if (0 == *resultsCount) {
+        LoggerD("No results");
+    }
+
+    disconnect();
+    return MSG_SUCCESS;
+}
+
+void MessagingDatabaseManager::freeTable(char*** results)
+{
+    LoggerD("Entered");
+    if (*results) {
+        sqlite3_free_table(*results);
+        *results = NULL;
+    }
+}
+
+int MessagingDatabaseManager::cellToInt(char** array, int cellId)
+{
+    LoggerD("Entered");
+    if (NULL == array) {
+        LoggerD("Array is NULL");
+        return 0;
+    }
+
+    char* tmp = *(array + cellId);
+    if (NULL == tmp) {
+        LoggerD("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
+{
+    LoggerD("Entered");
+    if(!match_value) {
+        LoggerD("Warning: match value is NULL");
+        return std::string();
+    }
+
+    std::ostringstream converter;
+    switch(type) {
+        case PrimitiveType_NoType: {
+            LoggerD("Warning: match value is no type");
+            return std::string();
+        }
+        case PrimitiveType_Null: {
+            LoggerD("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: {
+            LoggerD("Warning: match value is not specified");
+            return std::string();
+        }
+    }
+}
+
+PlatformResult MessagingDatabaseManager::getAttributeFilterQuery(AbstractFilterPtr filter,
+        AttributeInfoMap& attribute_map, MessageType msgType, std::string* result)
+{
+    LoggerD("Entered");
+
+    std::ostringstream sqlQuery;
+    AttributeFilterPtr attr_filter = castToAttributeFilter(filter);
+    if(!attr_filter) {
+        LoggerE("passed filter is not valid AttributeFilter!");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                              "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 {
+        LoggerE("The attribute: %s does not exist.", attribute_name.c_str());
+        return PlatformResult(ErrorCode::INVALID_VALUES_ERR,
+                              "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();
+
+    LoggerD("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) {
+        LoggerD("Attribute name: serviceId");
+
+        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) {
+        LoggerD("Attribute name: type");
+        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 {
+            LoggerE("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);
+            return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                                  "The value does not match service type.");
+        }
+    }
+    else if ("isRead" == attribute_name || "hasAttachment" == attribute_name) {
+        LoggerD("Attribute name: isRead or hasAttachment");
+        if (attr_filter->getMatchValue()->toBool()) {
+            sqlQuery << "> 0";
+        } else {
+            sqlQuery << "= 0";
+        }
+    }
+    else if ("isHighPriority" == attribute_name) {
+        LoggerD("Attribute name: isHighPriority");
+        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 {
+        LoggerD("Another attribute");
+        // 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:
+              return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                                    "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 << ") ";
+    *result = sqlQuery.str();
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult MessagingDatabaseManager::getAttributeRangeFilterQuery(AbstractFilterPtr filter,
+        AttributeInfoMap& attribute_map, MessageType msg_type, std::string* result)
+{
+    LoggerD("Entered");
+
+    std::ostringstream sql_query, converter;
+    std::string initial_value, end_value;
+
+    AttributeRangeFilterPtr attr_range_filter = castToAttributeRangeFilter(filter);
+    if(!attr_range_filter) {
+        LoggerE("passed filter is not valid AttributeRangeFilter!");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                              "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 << ") ";
+    *result = sql_query.str();
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult MessagingDatabaseManager::getCompositeFilterQuery(AbstractFilterPtr filter,
+        AttributeInfoMap& attribute_map, MessageType msg_type, std::string* result)
+{
+    LoggerD("Entered");
+    std::ostringstream sql_query;
+
+    CompositeFilterPtr comp_filter = castToCompositeFilter(filter);
+    if(!comp_filter) {
+        LoggerE("passed filter is not valid CompositeFilter!");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                              "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: {
+              std::string query;
+              PlatformResult ret = getAttributeFilterQuery(filters_arr[i], attribute_map, msg_type, &query);
+              if (ret.IsError()) {
+                  LoggerE("Get attribute filter query failed (%s)", ret.message().c_str());
+                  return ret;
+              }
+              sql_query << query;
+              break;
+            }
+            case ATTRIBUTE_RANGE_FILTER: {
+              std::string query;
+              PlatformResult ret = getAttributeRangeFilterQuery(filters_arr[i], attribute_map, msg_type, &query);
+              if (ret.IsError()) {
+                  LoggerE("Get attribute filter range filter query failed (%s)", ret.message().c_str());
+                  return ret;
+              }
+              sql_query << query;
+              break;
+            }
+            case COMPOSITE_FILTER: {
+              std::string query;
+              PlatformResult ret = getCompositeFilterQuery(filters_arr[i], attribute_map, msg_type, &query);
+              if (ret.IsError()) {
+                  LoggerE("Get composite filter query failed (%s)", ret.message().c_str());
+                  return ret;
+              }
+              sql_query << query;
+              break;
+            }
+            default:
+                LoggerE("Error while querying message - unsupported filter type: %d",
+                        filter_type);
+                return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                                      "Error while querying message.");
+        }
+
+        if (i != (size - 1)) {
+            sql_query << logical_operator;
+        }
+    }
+    sql_query << ") ";
+
+    *result = sql_query.str();
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult MessagingDatabaseManager::addFilters(AbstractFilterPtr filter,
+        SortModePtr sort_mode, long limit, long offset, AttributeInfoMap& attribute_map,
+        MessageType msg_type, std::string* result)
+{
+    LoggerD("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 {
+            LoggerE("The service type is incorrect - msg_type is UNDEFINED");
+            return PlatformResult(ErrorCode::UNKNOWN_ERR, "The service type is incorrect.");
+        }
+    }
+
+    if(filter) {
+        // Filter query
+        switch (filter->getFilterType()) {
+            case ATTRIBUTE_FILTER: {
+              std::string query;
+              PlatformResult ret = getAttributeFilterQuery(filter, attribute_map, msg_type, &query);
+              if (ret.IsError()) {
+                  LoggerE("Get attribute filter query failed (%s)", ret.message().c_str());
+                  return ret;
+              }
+              sql_query << query;
+              break;
+            }
+            case ATTRIBUTE_RANGE_FILTER: {
+              std::string query;
+              PlatformResult ret = getAttributeRangeFilterQuery(filter, attribute_map, msg_type, &query);
+              if (ret.IsError()) {
+                  LoggerE("Get attribute range filter query failed (%s)", ret.message().c_str());
+                  return ret;
+              }
+              sql_query << query;
+              break;
+            }
+            case COMPOSITE_FILTER : {
+              std::string query;
+              PlatformResult ret = getCompositeFilterQuery(filter, attribute_map, msg_type, &query);
+              if (ret.IsError()) {
+                  LoggerE("Get composite filter query failed (%s)", ret.message().c_str());
+                  return ret;
+              }
+              sql_query << query;
+              break;
+            }
+            default:
+                LoggerE("The filter type is incorrect: %d", filter->getFilterType());
+                return PlatformResult(ErrorCode::UNKNOWN_ERR, "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 {
+            LoggerE("The attribute does not exist.");
+            return PlatformResult(ErrorCode::UNKNOWN_ERR, "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 << " ";
+    }
+
+    *result = sql_query.str();
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult MessagingDatabaseManager::findShortMessages(
+        FindMsgCallbackUserData* callback, std::vector<int>* result)
+{
+    LoggerD("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();
+
+    std::string filters_query;
+    PlatformResult ret = addFilters(filter, sortMode, limit, offset, m_msg_attr_map,
+                                    msgType, &filters_query);
+    if (ret.IsError()) {
+        LoggerE("Add filters failed (%s)", ret.message().c_str());
+        return ret;
+    }
+    sqlQuery << filters_query;
+    LoggerD("%s", sqlQuery.str().c_str());
+
+    // Getting results from database
+    msg_error_t err = getTable(sqlQuery.str(), &results, &resultsCount);
+    if (MSG_SUCCESS != err) {
+        LoggerE("Getting results from database failed [%d]", err);
+        freeTable(&results);
+        return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                              "Error while getting data from database.");
+    }
+
+    for (int i = 0; i < resultsCount; ++i) {
+        messagesIds.push_back(cellToInt(results, cellId++));
+        LoggerD("id: %d", messagesIds.at(messagesIds.size() - 1));
+    }
+
+    freeTable(&results);
+    *result = messagesIds;
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult MessagingDatabaseManager::findEmails(
+        FindMsgCallbackUserData* callback, std::pair<int, email_mail_data_t*>* result)
+{
+    LoggerD("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();
+
+    std::string filters_query;
+    PlatformResult ret = addFilters(filter, sortMode, limit, offset,
+                                    m_email_attr_map, msgType, &filters_query);
+    if (ret.IsError()) {
+        LoggerE("Add filters failed (%s)", ret.message().c_str());
+        return ret;
+    }
+    sqlWhereClause << "WHERE "
+            << m_email_attr_map["serviceId"].sql_name << " = " << accountId << " AND "
+            << filters_query;
+    LoggerD("%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) {
+        LoggerE("Getting mail list fail [%d]", err);
+
+        if (EMAIL_ERROR_MAIL_NOT_FOUND == err) {
+            resultsCount = 0;
+        } else {
+          return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                                "Error while getting data from database.");
+        }
+    }
+
+    *result = std::make_pair(resultsCount, results);
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult MessagingDatabaseManager::findShortMessageConversations(
+        ConversationCallbackData* callback, std::vector<int>* result)
+{
+    LoggerD("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();
+
+    std::string filters_query;
+    PlatformResult ret = addFilters(filter, sortMode, limit, offset, m_msg_conv_attr_map,
+                                    msgType, &filters_query);
+    if (ret.IsError()) {
+        LoggerE("Add filters failed (%s)", ret.message().c_str());
+        return ret;
+    }
+    sqlQuery << filters_query;
+    LoggerD("%s", sqlQuery.str().c_str());
+
+    // Getting results from database
+    msg_error_t err = getTable(sqlQuery.str(), &results, &resultsCount);
+    if (MSG_SUCCESS != err) {
+        LoggerE("Getting results from database failed [%d]", err);
+        freeTable(&results);
+        return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                              "Error while getting data from database.");
+    }
+
+    for (int i = 0; i < resultsCount; ++i) {
+        conversationsIds.push_back(cellToInt(results, cellId++));
+        LoggerD("id: %d", conversationsIds.at(conversationsIds.size() - 1));
+    }
+
+    freeTable(&results);
+    *result = conversationsIds;
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult MessagingDatabaseManager::findEmailConversations(
+        ConversationCallbackData* callback, std::vector<EmailConversationInfo>* result)
+{
+    LoggerD("Entered");
+    std::ostringstream sqlWhereClause;
+    int resultsCount;
+    email_mail_data_t* results;
+    std::map<int, int> conversationsBag;
+    std::vector<EmailConversationInfo> conversationsInfo;
+
+    // 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();
+
+    std::string filters_query;
+    PlatformResult ret = addFilters(filter, sortMode, limit, offset, m_email_conv_attr_map,
+                                    msgType, &filters_query);
+    if (ret.IsError()) {
+        LoggerE("Add filters failed (%s)", ret.message().c_str());
+        return ret;
+    }
+    sqlWhereClause << "WHERE "
+            << m_email_conv_attr_map["serviceId"].sql_name << " = " << accountId << " AND "
+            << filters_query;
+    LoggerD("%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) {
+        LoggerE("Getting mail list fail [%d]", err);
+
+        if (EMAIL_ERROR_MAIL_NOT_FOUND == err) {
+            resultsCount = 0;
+        } else {
+          return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                                "Error while getting data from database.");
+        }
+    }
+
+    // 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];
+    }
+
+    email_free_mail_data(&results, resultsCount);
+    *result = conversationsInfo;
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+} // Messaging
+} // DeviceAPI
diff --git a/webWidgetTCT_device/src/messaging/messaging_database_manager.h b/webWidgetTCT_device/src/messaging/messaging_database_manager.h
new file mode 100755 (executable)
index 0000000..bfa7f4b
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2015 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_MSG_DATABASE_MANAGER_H__
+#define __TIZEN_MSG_DATABASE_MANAGER_H__
+
+#include <iostream>
+#include <map>
+
+#include <msg.h>
+#include <db-util.h>
+#include "MsgCommon/AbstractFilter.h"
+
+#include "common/platform_result.h"
+#include "find_msg_callback_user_data.h"
+//#include "ConversationCallbackData.h"
+
+namespace extension {
+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();
+    common::PlatformResult findShortMessages(FindMsgCallbackUserData* callback, std::vector<int>* result);
+    common::PlatformResult findEmails(FindMsgCallbackUserData* callback,
+                                                  std::pair<int, email_mail_data_t*>* result);
+    common::PlatformResult findShortMessageConversations(ConversationCallbackData* callback,
+                                                         std::vector<int>* result);
+    common::PlatformResult findEmailConversations(ConversationCallbackData* callback,
+                                                  std::vector<EmailConversationInfo>* result);
+
+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;
+    common::PlatformResult getAttributeFilterQuery(tizen::AbstractFilterPtr filter,
+            AttributeInfoMap& attributeMap, MessageType msgType, std::string* result);
+    common::PlatformResult getAttributeRangeFilterQuery(tizen::AbstractFilterPtr filter,
+            AttributeInfoMap& attributeMap, MessageType msgType, std::string* result);
+    common::PlatformResult getCompositeFilterQuery(tizen::AbstractFilterPtr filter,
+            AttributeInfoMap& attributeMap, MessageType msgType, std::string* result);
+    common::PlatformResult addFilters(tizen::AbstractFilterPtr filter,
+                                      tizen::SortModePtr sortMode, long limit, long offset,
+                                      AttributeInfoMap& attributeMap, MessageType msgType,
+                                      std::string* result);
+
+    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/webWidgetTCT_device/src/messaging/messaging_extension.cc b/webWidgetTCT_device/src/messaging/messaging_extension.cc
new file mode 100755 (executable)
index 0000000..67d0747
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2015 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 "common/logger.h"
+#include "messaging_extension.h"
+#include "messaging_instance.h"
+#include "email_manager.h"
+
+namespace {
+  const char* kMessaging = "tizen.messaging";
+  const char* kMessage = "tizen.Message";
+  const char* kMessageAttachment = "tizen.MessageAttachment";
+}
+// This will be generated from messaging_api.js.
+extern const char kSource_messaging_api[];
+
+using namespace common;
+
+common::Extension* CreateExtension() {
+  return new MessagingExtension;
+}
+
+MessagingExtension::MessagingExtension() {
+  LoggerD("Entered");
+  SetExtensionName(kMessaging);
+  SetJavaScriptAPI(kSource_messaging_api);
+  const char* entry_points[] = {
+    kMessage,
+    kMessageAttachment,
+    NULL
+  };
+  SetExtraJSEntryPoints(entry_points);
+}
+
+MessagingExtension::~MessagingExtension() {
+  LoggerD("Entered");
+}
+
+common::Instance* MessagingExtension::CreateInstance() {
+  LoggerD("Entered");
+  PlatformResult ret = extension::messaging::EmailManager::InitializeEmailService();
+  if (ret.IsError()) {
+      LoggerE("Initializing the email service failed (%s)", ret.message().c_str());
+      return nullptr;
+  }
+  return new extension::messaging::MessagingInstance();
+}
diff --git a/webWidgetTCT_device/src/messaging/messaging_extension.h b/webWidgetTCT_device/src/messaging/messaging_extension.h
new file mode 100755 (executable)
index 0000000..6de078e
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015 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 MESSAGING_MESSAGING_EXTENSION_H_
+#define MESSAGING_MESSAGING_EXTENSION_H_
+
+#include "common/extension.h"
+
+class MessagingExtension : public common::Extension {
+ public:
+  MessagingExtension();
+  virtual ~MessagingExtension();
+
+ private:
+  virtual common::Instance* CreateInstance();
+};
+
+#endif // MESSAGING_MESSAGING_EXTENSION_H_
+
diff --git a/webWidgetTCT_device/src/messaging/messaging_instance.cc b/webWidgetTCT_device/src/messaging/messaging_instance.cc
new file mode 100755 (executable)
index 0000000..9d89182
--- /dev/null
@@ -0,0 +1,871 @@
+/*
+ * Copyright (c) 2015 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 "messaging_instance.h"
+
+#include <sstream>
+#include <stdexcept>
+
+#include "common/logger.h"
+
+#include "MsgCommon/AbstractFilter.h"
+#include "messages_change_callback.h"
+#include "conversations_change_callback.h"
+#include "folders_change_callback.h"
+#include "messages_callback_user_data.h"
+#include "find_msg_callback_user_data.h"
+#include "folders_callback_data.h"
+#include "messaging_manager.h"
+#include "messaging_util.h"
+#include "message_storage.h"
+#include "message.h"
+
+using common::ErrorCode;
+using common::PlatformResult;
+
+namespace extension {
+namespace messaging {
+
+namespace{
+const char* FUN_GET_MESSAGE_SERVICES = "Messaging_getMessageServices";
+const char* GET_MESSAGE_SERVICES_ARGS_MESSAGE_SERVICE_TYPE = "messageServiceType";
+
+const char* FUN_MESSAGE_SERVICE_SEND_MESSAGE =  "MessageService_sendMessage";
+const char* SEND_MESSAGE_ARGS_MESSAGE = "message";
+const char* SEND_MESSAGE_ARGS_SIMINDEX = "simIndex";
+
+const char* FUN_MESSAGE_SERVICE_LOAD_MESSAGE_BODY = "MessageService_loadMessageBody";
+
+const char* FUN_MESSAGE_SERVICE_LOAD_MESSAGE_ATTACHMENT = "MessageService_loadMessageAttachment";
+const char* LOAD_MESSAGE_ATTACHMENT_ARGS_ATTACHMENT = "attachment";
+
+const char* FUN_MESSAGE_SERVICE_SYNC = "MessageService_sync";
+const char* SYNC_ARGS_ID = "id";
+const char* SYNC_ARGS_LIMIT = "limit";
+
+const char* FUN_MESSAGE_SERVICE_SYNC_FOLDER = "MessageService_syncFolder";
+const char* SYNC_FOLDER_ARGS_ID = "id";
+const char* SYNC_FOLDER_ARGS_FOLDER = "folder";
+const char* SYNC_FOLDER_ARGS_LIMIT = "limit";
+
+const char* FUN_MESSAGE_SERVICE_STOP_SYNC = "MessageService_stopSync";
+const char* STOP_SYNC_ARGS_ID = "id";
+const char* STOP_SYNC_ARGS_OPID = "opId";
+
+const char* FUN_MESSAGE_STORAGE_ADD_DRAFT_MESSAGE = "MessageStorage_addDraftMessage";
+const char* ADD_DRAFT_MESSAGE_ARGS_MESSAGE = "message";
+
+const char* FUN_MESSAGE_STORAGE_FIND_MESSAGES = "MessageStorage_findMessages";
+
+const char* FUN_MESSAGE_STORAGE_REMOVE_MESSAGES = "MessageStorage_removeMessages";
+const char* REMOVE_MESSAGES_ARGS_MESSAGES = "messages";
+
+const char* FUN_MESSAGE_STORAGE_UPDATE_MESSAGES = "MessageStorage_updateMessages";
+const char* UPDATE_MESSAGES_ARGS_MESSAGES = "messages";
+
+const char* FUN_MESSAGE_STORAGE_FIND_CONVERSATIONS = "MessageStorage_findConversations";
+const char* FIND_CONVERSATIONS_ARGS_LIMIT = "limit";
+const char* FIND_CONVERSATIONS_ARGS_OFFSET = "offset";
+
+const char* FUN_MESSAGE_STORAGE_REMOVE_CONVERSATIONS = "MessageStorage_removeConversations";
+const char* REMOVE_CONVERSATIONS_ARGS_CONVERSATIONS = "conversations";
+
+const char* FUN_MESSAGE_STORAGE_FIND_FOLDERS = "MessageStorage_findFolders";
+const char* FIND_FOLDERS_ARGS_LIMIT = "limit";
+const char* FIND_FOLDERS_ARGS_OFFSET = "offset";
+
+const char* FUN_MESSAGE_STORAGE_ADD_MESSAGES_CHANGE_LISTENER =
+        "MessageStorage_addMessagesChangeListener";
+
+const char* FUN_MESSAGE_STORAGE_ADD_CONVERSATIONS_CHANGE_LISTENER =
+        "MessageStorage_addConversationsChangeListener";
+
+const char* FUN_MESSAGE_STORAGE_ADD_FOLDER_CHANGE_LISTENER =
+        "MessageStorage_addFoldersChangeListener";
+
+const char* FUN_MESSAGE_STORAGE_REMOVE_CHANGE_LISTENER = "MessageStorage_removeChangeListener";
+const char* REMOVE_CHANGE_LISTENER_ARGS_WATCHID = "watchId";
+
+const char* FUNCTIONS_HIDDEN_ARGS_SERVICE_ID = "serviceId";
+
+auto getServiceIdFromJSON = [](picojson::object& data) -> int {
+    std::string serviceStrId;
+    try {
+        serviceStrId =
+        MessagingUtil::getValueFromJSONObject<std::string>(data,FUNCTIONS_HIDDEN_ARGS_SERVICE_ID);
+        return std::stoi(serviceStrId);
+    }
+    catch(...) {
+        return -1;
+    }
+};
+
+}
+
+MessagingInstance::MessagingInstance():
+    manager_(*this),
+    queue_(*this)
+{
+    LoggerD("Entered");
+    using std::placeholders::_1;
+    using std::placeholders::_2;
+    #define REGISTER_ASYNC(c,x) \
+      RegisterHandler(c, std::bind(&MessagingInstance::x, this, _1, _2));
+      REGISTER_ASYNC(FUN_GET_MESSAGE_SERVICES, GetMessageServices);
+      REGISTER_ASYNC(FUN_MESSAGE_SERVICE_SEND_MESSAGE, MessageServiceSendMessage);
+      REGISTER_ASYNC(FUN_MESSAGE_SERVICE_LOAD_MESSAGE_BODY, MessageServiceLoadMessageBody);
+      REGISTER_ASYNC(FUN_MESSAGE_SERVICE_LOAD_MESSAGE_ATTACHMENT, MessageServiceLoadMessageAttachment);
+      REGISTER_ASYNC(FUN_MESSAGE_STORAGE_ADD_DRAFT_MESSAGE, MessageStorageAddDraft);
+      REGISTER_ASYNC(FUN_MESSAGE_STORAGE_FIND_MESSAGES, MessageStorageFindMessages);
+      REGISTER_ASYNC(FUN_MESSAGE_STORAGE_REMOVE_MESSAGES, MessageStorageRemoveMessages);
+      REGISTER_ASYNC(FUN_MESSAGE_STORAGE_UPDATE_MESSAGES, MessageStorageUpdateMessages);
+      REGISTER_ASYNC(FUN_MESSAGE_STORAGE_FIND_CONVERSATIONS, MessageStorageFindConversations);
+      REGISTER_ASYNC(FUN_MESSAGE_STORAGE_REMOVE_CONVERSATIONS, MessageStorageRemoveConversations);
+      REGISTER_ASYNC(FUN_MESSAGE_STORAGE_FIND_FOLDERS, MessageStorageFindFolders);
+    #undef REGISTER_ASYNC
+    #define REGISTER_SYNC(c,x) \
+      RegisterSyncHandler(c, std::bind(&MessagingInstance::x, this, _1, _2));
+      REGISTER_SYNC(FUN_MESSAGE_SERVICE_SYNC, MessageServiceSync);
+      REGISTER_SYNC(FUN_MESSAGE_SERVICE_STOP_SYNC, MessageServiceStopSync);
+      REGISTER_SYNC(FUN_MESSAGE_SERVICE_SYNC_FOLDER, MessageServiceSyncFolder);
+      REGISTER_SYNC(FUN_MESSAGE_STORAGE_ADD_MESSAGES_CHANGE_LISTENER, MessageStorageAddMessagesChangeListener);
+      REGISTER_SYNC(FUN_MESSAGE_STORAGE_ADD_CONVERSATIONS_CHANGE_LISTENER, MessageStorageAddConversationsChangeListener);
+      REGISTER_SYNC(FUN_MESSAGE_STORAGE_ADD_FOLDER_CHANGE_LISTENER, MessageStorageAddFolderChangeListener);
+      REGISTER_SYNC(FUN_MESSAGE_STORAGE_REMOVE_CHANGE_LISTENER, MessageStorageRemoveChangeListener);
+    #undef REGISTER_SYNC
+}
+
+MessagingInstance::~MessagingInstance()
+{
+    LoggerD("Entered");
+}
+
+#define POST_AND_RETURN(ret, json, obj, action) \
+    LoggerE("Error occured: (%s)", ret.message().c_str()); \
+    picojson::object args; \
+    ReportError(ret, &args); \
+    obj[JSON_DATA] = picojson::value(args); \
+    obj[JSON_ACTION] = picojson::value(action); \
+    queue_.addAndResolve( \
+            obj.at(JSON_CALLBACK_ID).get<double>(), \
+            PostPriority::HIGH, \
+            json->serialize() \
+    ); \
+    return;
+
+void MessagingInstance::GetMessageServices(const picojson::value& args,
+                                           picojson::object& out)
+{
+  LoggerD("Entered");
+
+  if (!args.contains(JSON_DATA) || !args.contains(JSON_CALLBACK_ID) ||
+      !args.get(JSON_CALLBACK_ID).is<double>()) {
+    LoggerE("json is incorrect - missing required member");
+    return;
+  }
+
+  picojson::value data = args.get(JSON_DATA);
+  picojson::value serviceTag = data.get<picojson::object>().
+      at(GET_MESSAGE_SERVICES_ARGS_MESSAGE_SERVICE_TYPE);
+  const double callbackId = args.get(JSON_CALLBACK_ID).get<double>();
+  // above values should be validated in js
+  manager_.getMessageServices(serviceTag.to_str(), callbackId);
+}
+
+void MessagingInstance::MessageServiceSendMessage(const picojson::value& args,
+        picojson::object& out)
+{
+    LoggerD("Entered");
+
+    if (!args.contains(JSON_DATA) || !args.contains(JSON_CALLBACK_ID) ||
+        !args.get(JSON_CALLBACK_ID).is<double>()) {
+      LoggerE("json is incorrect - missing required member");
+      return;
+    }
+
+    picojson::object data = args.get(JSON_DATA).get<picojson::object>();
+    picojson::value v_message = data.at(SEND_MESSAGE_ARGS_MESSAGE);
+    const double callbackId = args.get(JSON_CALLBACK_ID).get<double>();
+
+    auto json = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+    picojson::object& obj = json->get<picojson::object>();
+    obj[JSON_CALLBACK_ID] = picojson::value(callbackId);
+
+    std::shared_ptr<Message> message;
+    PlatformResult ret = MessagingUtil::jsonToMessage(v_message, &message);
+    if (ret.IsError()) {
+      POST_AND_RETURN(ret, json, obj, JSON_CALLBACK_ERROR)
+    }
+
+    MessageRecipientsCallbackData* callback = new MessageRecipientsCallbackData(queue_);
+    long simIndex = 0;
+    int serviceId = 0;
+
+    callback->setJson(json);
+    callback->setMessage(message);
+    serviceId = getServiceIdFromJSON(data);
+    callback->setAccountId(serviceId);
+    simIndex = static_cast<long>
+      (MessagingUtil::getValueFromJSONObject<double>(data,SEND_MESSAGE_ARGS_SIMINDEX));
+
+    if (!callback->setSimIndex(simIndex)) {
+      delete callback;
+      callback = nullptr;
+      POST_AND_RETURN(PlatformResult(ErrorCode::UNKNOWN_ERR, "set sim index failed"),
+                      json, obj, JSON_CALLBACK_ERROR)
+    }
+
+    queue_.add(static_cast<long>(callbackId), PostPriority::HIGH);
+    auto service = manager_.getMessageService(serviceId);
+
+    ret = service->sendMessage(callback);
+    if (!ret) {
+      POST_AND_RETURN(ret, json, obj, JSON_CALLBACK_ERROR)
+    }
+}
+
+void MessagingInstance::MessageServiceLoadMessageBody(const picojson::value& args,
+        picojson::object& out)
+{
+    LoggerD("Entered");
+
+    if (!args.contains(JSON_DATA) || !args.contains(JSON_CALLBACK_ID) ||
+        !args.get(JSON_CALLBACK_ID).is<double>()) {
+      LoggerE("json is incorrect - missing required member");
+      return;
+    }
+
+    picojson::object data = args.get(JSON_DATA).get<picojson::object>();
+
+    picojson::value json_message = data.at(ADD_DRAFT_MESSAGE_ARGS_MESSAGE);
+    const double callbackId = args.get(JSON_CALLBACK_ID).get<double>();
+
+    auto json = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+    picojson::object& obj = json->get<picojson::object>();
+    obj[JSON_CALLBACK_ID] = picojson::value(callbackId);
+
+    std::shared_ptr<Message> message;
+    PlatformResult ret = MessagingUtil::jsonToMessage(json_message, &message);
+    if (ret.IsError()) {
+      POST_AND_RETURN(ret, json, obj, JSON_CALLBACK_ERROR)
+    }
+
+    MessageBodyCallbackData* callback = new MessageBodyCallbackData(queue_);
+
+    callback->setJson(json);
+    callback->setMessage(message);
+
+    queue_.add(static_cast<long>(callbackId), PostPriority::HIGH);
+    auto service = manager_.getMessageService(getServiceIdFromJSON(data));
+    ret = service->loadMessageBody(callback);
+    if (ret.IsError()) {
+      POST_AND_RETURN(ret, json, obj, JSON_CALLBACK_ERROR)
+    }
+}
+
+void MessagingInstance::MessageServiceLoadMessageAttachment(const picojson::value& args,
+        picojson::object& out)
+{
+    LoggerD("Entered");
+
+    if (!args.contains(JSON_DATA) || !args.contains(JSON_CALLBACK_ID) ||
+        !args.get(JSON_CALLBACK_ID).is<double>()) {
+      LoggerE("json is incorrect - missing required member");
+      return;
+    }
+
+    picojson::object data = args.get(JSON_DATA).get<picojson::object>();
+    picojson::value attachment = data.at(LOAD_MESSAGE_ATTACHMENT_ARGS_ATTACHMENT);
+    const double callbackId = args.get(JSON_CALLBACK_ID).get<double>();
+
+    MessageAttachmentCallbackData* callback = new MessageAttachmentCallbackData(queue_);
+    callback->setMessageAttachment(MessagingUtil::jsonToMessageAttachment(attachment));
+
+    auto json = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+    picojson::object& obj = json->get<picojson::object>();
+    obj[JSON_CALLBACK_ID] = picojson::value(callbackId);
+    callback->setJson(json);
+
+    queue_.add(static_cast<long>(callbackId), PostPriority::HIGH);
+    auto service = manager_.getMessageService(getServiceIdFromJSON(data));
+    const auto result = service->loadMessageAttachment(callback);
+    if (result.IsError()) {
+      POST_AND_RETURN(result, json, obj, JSON_CALLBACK_ERROR)
+    }
+}
+
+void MessagingInstance::MessageServiceSync(const picojson::value& args,
+        picojson::object& out)
+{
+    LoggerD("Entered");
+
+    if (!args.contains(JSON_DATA) || !args.contains(JSON_CALLBACK_ID) ||
+        !args.get(JSON_CALLBACK_ID).is<double>()) {
+      LoggerE("json is incorrect - missing required member");
+      return;
+    }
+
+    picojson::object data = args.get(JSON_DATA).get<picojson::object>();
+    picojson::value v_id = data.at(SYNC_ARGS_ID);
+    picojson::value v_limit = data.at(SYNC_ARGS_LIMIT);
+    const double callbackId = args.get(JSON_CALLBACK_ID).get<double>();
+
+    int id = -1;
+    try {
+        id = std::stoi(v_id.get<std::string>());
+    } catch(...) {
+        LoggerE("Problem with MessageService");
+        ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR), &out);
+        return;
+    }
+    long limit = 0;
+    if (v_limit.is<double>()) {
+        limit = static_cast<long>(v_limit.get<double>());
+    }
+
+    auto json = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+    picojson::object& obj = json->get<picojson::object>();
+    obj[JSON_CALLBACK_ID] = picojson::value(callbackId);
+
+    SyncCallbackData *callback = new SyncCallbackData(queue_);
+    callback->setJson(json);
+    callback->setAccountId(id);
+    callback->setLimit(limit);
+
+    queue_.add(static_cast<long>(callbackId), PostPriority::HIGH);
+    long op_id = -1;
+
+    const auto result = manager_.getMessageService(id)->sync(callback, &op_id);
+
+    if (result) {
+      ReportSuccess(picojson::value(static_cast<double>(op_id)), out);
+    } else {
+      ReportError(result, &out);
+    }
+}
+
+void MessagingInstance::MessageServiceSyncFolder(const picojson::value& args,
+        picojson::object& out)
+{
+    LoggerD("Entered");
+
+    if (!args.contains(JSON_DATA) || !args.contains(JSON_CALLBACK_ID) ||
+        !args.get(JSON_CALLBACK_ID).is<double>()) {
+      LoggerE("json is incorrect - missing required member");
+      return;
+    }
+
+    picojson::object data = args.get(JSON_DATA).get<picojson::object>();
+    picojson::value v_id = data.at(SYNC_FOLDER_ARGS_ID);
+    picojson::value v_folder = data.at(SYNC_FOLDER_ARGS_FOLDER);
+    picojson::value v_limit = data.at(SYNC_FOLDER_ARGS_LIMIT);
+    const double callbackId = args.get(JSON_CALLBACK_ID).get<double>();
+
+    int id = -1;
+    try {
+        id = std::stoi(v_id.get<std::string>());
+    } catch(...) {
+        LoggerE("Problem with MessageService");
+        ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR), &out);
+        return;
+    }
+
+    long limit = 0;
+    if (v_limit.is<double>()) {
+        limit = static_cast<long>(v_limit.get<double>());
+    }
+
+    auto json = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+    picojson::object& obj = json->get<picojson::object>();
+    obj[JSON_CALLBACK_ID] = picojson::value(callbackId);
+
+    SyncFolderCallbackData *callback = new SyncFolderCallbackData(queue_);
+    callback->setJson(json);
+    callback->setAccountId(id);
+    callback->setMessageFolder(MessagingUtil::jsonToMessageFolder(v_folder));
+    callback->setLimit(limit);
+
+    queue_.add(static_cast<long>(callbackId), PostPriority::HIGH);
+    long op_id = -1;
+
+    const auto result = manager_.getMessageService(id)->syncFolder(callback, &op_id);
+    if (result) {
+        ReportSuccess(picojson::value(static_cast<double>(op_id)), out);
+    } else {
+        ReportError(result, &out);
+    }
+}
+
+void MessagingInstance::MessageServiceStopSync(const picojson::value& args,
+        picojson::object& out)
+{
+    LoggerD("Entered");
+
+    if (!args.contains(JSON_DATA) || !args.contains(JSON_CALLBACK_ID) ||
+        !args.get(JSON_CALLBACK_ID).is<double>()) {
+      LoggerE("json is incorrect - missing required member");
+      return;
+    }
+
+    picojson::object data = args.get(JSON_DATA).get<picojson::object>();
+
+    if (data.find(STOP_SYNC_ARGS_ID) != data.end()) {
+        picojson::value v_id = data.at(STOP_SYNC_ARGS_ID);
+        picojson::value v_op_id = data.at(STOP_SYNC_ARGS_OPID);
+
+        int id = -1;
+        try {
+            id = std::stoi(v_id.get<std::string>());
+        } catch(...) {
+            LoggerD("Problem with MessageService");
+            ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR), &out);
+            return;
+        }
+
+        long op_id = 0;
+        if (v_op_id.is<double>()) {
+            op_id = static_cast<long>(v_op_id.get<double>());
+        }
+
+        const auto result = manager_.getMessageService(id)->stopSync(op_id);
+
+        if (result) {
+            ReportSuccess(out);
+        } else {
+            ReportError(result, &out);
+        }
+    } else {
+        LoggerE("Unknown error");
+        ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR), &out);
+    }
+}
+
+void MessagingInstance::MessageStorageAddDraft(const picojson::value& args,
+        picojson::object& out)
+{
+    LoggerD("Entered");
+
+    if (!args.contains(JSON_DATA) || !args.contains(JSON_CALLBACK_ID) ||
+        !args.get(JSON_CALLBACK_ID).is<double>()) {
+      LoggerE("json is incorrect - missing required member");
+      return;
+    }
+
+    picojson::object data = args.get(JSON_DATA).get<picojson::object>();
+    picojson::value v_message = data.at(ADD_DRAFT_MESSAGE_ARGS_MESSAGE);
+    const double callbackId = args.get(JSON_CALLBACK_ID).get<double>();
+
+    auto json = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+    picojson::object& obj = json->get<picojson::object>();
+    obj[JSON_CALLBACK_ID] = picojson::value(callbackId);
+
+    std::shared_ptr<Message> message;
+    PlatformResult ret = MessagingUtil::jsonToMessage(v_message, &message);
+    if (ret.IsError()) {
+      POST_AND_RETURN(ret, json, obj, JSON_CALLBACK_ERROR)
+    }
+
+    MessageCallbackUserData* callback = new MessageCallbackUserData(queue_);
+    callback->setMessage(message);
+
+    int serviceId = getServiceIdFromJSON(data);
+    callback->setAccountId(serviceId);
+
+    callback->setJson(json);
+
+    queue_.add(static_cast<long>(callbackId), PostPriority::HIGH);
+    auto service = manager_.getMessageService(serviceId);
+    service->getMsgStorage()->addDraftMessage(callback);
+}
+
+void MessagingInstance::MessageStorageFindMessages(const picojson::value& args,
+        picojson::object& out)
+{
+    LoggerD("Entered");
+
+    if (!args.contains(JSON_DATA) || !args.contains(JSON_CALLBACK_ID) ||
+        !args.get(JSON_CALLBACK_ID).is<double>()) {
+      LoggerE("json is incorrect - missing required member");
+      return;
+    }
+
+    picojson::object data = args.get(JSON_DATA).get<picojson::object>();
+    const double callbackId = args.get(JSON_CALLBACK_ID).get<double>();
+
+    auto json = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+    picojson::object& obj = json->get<picojson::object>();
+    obj[JSON_CALLBACK_ID] = picojson::value(callbackId);
+
+    AbstractFilterPtr filter;
+    PlatformResult ret = MessagingUtil::jsonToAbstractFilter(data, &filter);
+    if (ret.IsError()) {
+      POST_AND_RETURN(ret, json, obj, JSON_CALLBACK_ERROR)
+    }
+    auto sortMode = MessagingUtil::jsonToSortMode(data);
+
+    long limit = static_cast<long>
+            (MessagingUtil::getValueFromJSONObject<double>(data, FIND_FOLDERS_ARGS_LIMIT));
+
+    long offset = static_cast<long>
+            (MessagingUtil::getValueFromJSONObject<double>(data, FIND_FOLDERS_ARGS_OFFSET));
+
+    int serviceId = getServiceIdFromJSON(data);
+    auto storage = manager_.getMessageService(serviceId)->getMsgStorage();
+
+    FindMsgCallbackUserData* callback = new FindMsgCallbackUserData(queue_);
+    callback->setFilter(filter);
+    callback->setLimit(limit);
+    callback->setOffset(offset);
+    callback->setAccountId(serviceId);
+    callback->setSortMode(sortMode);
+    callback->setJson(json);
+
+    queue_.add(static_cast<long>(callbackId), PostPriority::HIGH);
+    storage->findMessages(callback);
+}
+
+void MessagingInstance::MessageStorageRemoveMessages(const picojson::value& args,
+        picojson::object& out)
+{
+    LoggerD("Entered");
+
+    if (!args.contains(JSON_DATA) || !args.contains(JSON_CALLBACK_ID) ||
+        !args.get(JSON_CALLBACK_ID).is<double>()) {
+      LoggerE("json is incorrect - missing required member");
+      return;
+    }
+
+    picojson::object data = args.get(JSON_DATA).get<picojson::object>();
+    picojson::array messages = data.at(REMOVE_MESSAGES_ARGS_MESSAGES).get<picojson::array>();
+    const double callbackId = args.get(JSON_CALLBACK_ID).get<double>();
+
+    MessagesCallbackUserData* callback = new MessagesCallbackUserData(queue_);
+
+    auto each = [callback] (picojson::value& v)->void {
+      std::shared_ptr<Message> message;
+      PlatformResult ret = MessagingUtil::jsonToMessage(v, &message);
+      if (ret.IsSuccess()) {
+        callback->addMessage(message);
+      }
+    };
+
+    for_each(messages.begin(), messages.end(), each);
+
+    auto json = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+    picojson::object& obj = json->get<picojson::object>();
+    obj[JSON_CALLBACK_ID] = picojson::value(callbackId);
+    callback->setJson(json);
+
+    auto service = manager_.getMessageService(getServiceIdFromJSON(data));
+
+    queue_.add(static_cast<long>(callbackId), PostPriority::HIGH);
+    service->getMsgStorage()->removeMessages(callback);
+}
+
+void MessagingInstance::MessageStorageUpdateMessages(const picojson::value& args,
+        picojson::object& out)
+{
+    LoggerD("Entered");
+
+    if (!args.contains(JSON_DATA) || !args.contains(JSON_CALLBACK_ID) ||
+        !args.get(JSON_CALLBACK_ID).is<double>()) {
+      LoggerE("json is incorrect - missing required member");
+      return;
+    }
+
+    picojson::object data = args.get(JSON_DATA).get<picojson::object>();
+    picojson::value pico_messages = data.at(UPDATE_MESSAGES_ARGS_MESSAGES);
+    auto pico_array = pico_messages.get<picojson::array>();
+    const double callbackId = args.get(JSON_CALLBACK_ID).get<double>();
+
+    auto callback = new MessagesCallbackUserData(queue_);
+
+    std::for_each(pico_array.begin(), pico_array.end(), [&callback](picojson::value& v)->void {
+       std::shared_ptr<Message> message;
+       PlatformResult ret = MessagingUtil::jsonToMessage(v, &message);
+       if (ret.IsSuccess()) {
+         callback->addMessage(message);
+       }
+    });
+
+    auto json = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+    picojson::object& obj = json->get<picojson::object>();
+    obj[JSON_CALLBACK_ID] = picojson::value(callbackId);
+    callback->setJson(json);
+
+    auto service = manager_.getMessageService(getServiceIdFromJSON(data));
+
+    queue_.add(static_cast<long>(callbackId), PostPriority::HIGH);
+    service->getMsgStorage()->updateMessages(callback);
+}
+
+void MessagingInstance::MessageStorageFindConversations(const picojson::value& args,
+        picojson::object& out)
+{
+    LoggerD("Entered");
+
+    if (!args.contains(JSON_DATA) || !args.contains(JSON_CALLBACK_ID) ||
+        !args.get(JSON_CALLBACK_ID).is<double>()) {
+      LoggerE("json is incorrect - missing required member");
+      return;
+    }
+
+    picojson::object data = args.get(JSON_DATA).get<picojson::object>();
+    const double callbackId = args.get(JSON_CALLBACK_ID).get<double>();
+
+    auto json = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+    picojson::object& obj = json->get<picojson::object>();
+    obj[JSON_CALLBACK_ID] = picojson::value(callbackId);
+
+    AbstractFilterPtr filter;
+    PlatformResult ret = MessagingUtil::jsonToAbstractFilter(data, &filter);
+    if (ret.IsError()) {
+      POST_AND_RETURN(ret, json, obj, JSON_CALLBACK_ERROR)
+    }
+    auto sortMode = MessagingUtil::jsonToSortMode(data);
+    long limit = static_cast<long>
+            (MessagingUtil::getValueFromJSONObject<double>(data, FIND_CONVERSATIONS_ARGS_LIMIT));
+    long offset = static_cast<long>
+            (MessagingUtil::getValueFromJSONObject<double>(data, FIND_CONVERSATIONS_ARGS_OFFSET));
+
+    int serviceId = getServiceIdFromJSON(data);
+
+    ConversationCallbackData* callback = new ConversationCallbackData(queue_);
+    callback->setFilter(filter);
+    callback->setLimit(limit);
+    callback->setOffset(offset);
+    callback->setAccountId(serviceId);
+    callback->setSortMode(sortMode);
+    callback->setJson(json);
+
+    queue_.add(static_cast<long>(callbackId), PostPriority::HIGH);
+    auto storage = manager_.getMessageService(serviceId)->getMsgStorage();
+    storage->findConversations(callback);
+}
+
+void MessagingInstance::MessageStorageRemoveConversations(const picojson::value& args,
+        picojson::object& out)
+{
+    LoggerD("Entered");
+
+    if (!args.contains(JSON_DATA) || !args.contains(JSON_CALLBACK_ID) ||
+        !args.get(JSON_CALLBACK_ID).is<double>()) {
+      LoggerE("json is incorrect - missing required member");
+      return;
+    }
+
+    picojson::object data = args.get(JSON_DATA).get<picojson::object>();
+    picojson::array conversations = data.at(REMOVE_CONVERSATIONS_ARGS_CONVERSATIONS).get<picojson::array>();
+    const double callbackId = args.get(JSON_CALLBACK_ID).get<double>();
+
+    auto json = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+    picojson::object& obj = json->get<picojson::object>();
+    obj[JSON_CALLBACK_ID] = picojson::value(callbackId);
+
+    ConversationCallbackData* callback = new ConversationCallbackData(queue_);
+
+    PlatformResult ret(ErrorCode::NO_ERROR);
+    for (auto it = conversations.begin(); it != conversations.end(); ++it) {
+      std::shared_ptr<MessageConversation> conversation;
+      ret = MessagingUtil::jsonToMessageConversation(*it, &conversation);
+      if (ret.IsError()) {
+        delete callback;
+        POST_AND_RETURN(ret, json, obj, JSON_CALLBACK_ERROR)
+      }
+      callback->addConversation(conversation);
+    }
+
+    callback->setJson(json);
+
+    auto service = manager_.getMessageService(getServiceIdFromJSON(data));
+
+    queue_.add(static_cast<long>(callbackId), PostPriority::HIGH);
+    service->getMsgStorage()->removeConversations(callback);
+}
+
+void MessagingInstance::MessageStorageFindFolders(const picojson::value& args,
+        picojson::object& out)
+{
+    LoggerD("Entered");
+
+    if (!args.contains(JSON_DATA) || !args.contains(JSON_CALLBACK_ID) ||
+        !args.get(JSON_CALLBACK_ID).is<double>()) {
+      LoggerE("json is incorrect - missing required member");
+      return;
+    }
+
+    picojson::object data = args.get(JSON_DATA).get<picojson::object>();
+    const double callbackId = args.get(JSON_CALLBACK_ID).get<double>();
+
+    auto json = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+    picojson::object& obj = json->get<picojson::object>();
+    obj[JSON_CALLBACK_ID] = picojson::value(callbackId);
+
+    AbstractFilterPtr filter;
+    PlatformResult ret = MessagingUtil::jsonToAbstractFilter(data, &filter);
+    if (ret.IsError()) {
+      POST_AND_RETURN(ret, json, obj, JSON_CALLBACK_ERROR)
+    }
+
+    FoldersCallbackData* callback = new FoldersCallbackData(queue_);
+    callback->setFilter(filter);
+    callback->setJson(json);
+
+    queue_.add(static_cast<long>(callbackId), PostPriority::HIGH);
+    auto service = manager_.getMessageService(getServiceIdFromJSON(data));
+    service->getMsgStorage()->findFolders(callback);
+}
+
+void MessagingInstance::MessageStorageAddMessagesChangeListener(const picojson::value& args,
+        picojson::object& out)
+{
+    LoggerD("Entered");
+
+    if (!args.contains(JSON_DATA) || !args.contains(JSON_CALLBACK_ID) ||
+        !args.get(JSON_CALLBACK_ID).is<double>()) {
+      LoggerE("json is incorrect - missing required member");
+      return;
+    }
+
+    picojson::object data = args.get(JSON_DATA).get<picojson::object>();
+    const double callbackId = args.get(JSON_CALLBACK_ID).get<double>();
+
+    auto json = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+    picojson::object& obj = json->get<picojson::object>();
+    obj[JSON_CALLBACK_ID] = picojson::value(callbackId);
+
+    AbstractFilterPtr filter;
+    PlatformResult ret = MessagingUtil::jsonToAbstractFilter(data, &filter);
+    if (ret.IsError()) {
+      POST_AND_RETURN(ret, json, obj, JSON_CALLBACK_ERROR)
+    }
+
+    int serviceId = getServiceIdFromJSON(data);
+
+    auto service = manager_.getMessageService(serviceId);
+
+    std::shared_ptr<MessagesChangeCallback> callback(new MessagesChangeCallback(
+        static_cast<long>(callbackId), serviceId, service->getMsgServiceType(),queue_));
+
+    callback->setFilter(filter);
+
+    long op_id = service->getMsgStorage()->addMessagesChangeListener(callback);
+
+    picojson::value v(static_cast<double>(op_id));
+    ReportSuccess(v, out);
+}
+
+void MessagingInstance::MessageStorageAddConversationsChangeListener(const picojson::value& args,
+        picojson::object& out)
+{
+    LoggerD("Entered");
+
+    if (!args.contains(JSON_DATA) || !args.contains(JSON_CALLBACK_ID) ||
+        !args.get(JSON_CALLBACK_ID).is<double>()) {
+      LoggerE("json is incorrect - missing required member");
+      return;
+    }
+
+    picojson::object data = args.get(JSON_DATA).get<picojson::object>();
+    const double callbackId = args.get(JSON_CALLBACK_ID).get<double>();
+
+    auto json = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+    picojson::object& obj = json->get<picojson::object>();
+    obj[JSON_CALLBACK_ID] = picojson::value(callbackId);
+
+    AbstractFilterPtr filter;
+    PlatformResult ret = MessagingUtil::jsonToAbstractFilter(data, &filter);
+    if (ret.IsError()) {
+      POST_AND_RETURN(ret, json, obj, JSON_CALLBACK_ERROR)
+    }
+
+    int serviceId = getServiceIdFromJSON(data);
+
+    auto service = manager_.getMessageService(serviceId);
+
+    std::shared_ptr<ConversationsChangeCallback> callback(new ConversationsChangeCallback(
+        static_cast<long>(callbackId), serviceId, service->getMsgServiceType(), queue_));
+
+    callback->setFilter(filter);
+
+    long op_id = service->getMsgStorage()->addConversationsChangeListener(callback);
+
+    picojson::value v(static_cast<double>(op_id));
+    ReportSuccess(v, out);
+}
+
+void MessagingInstance::MessageStorageAddFolderChangeListener(const picojson::value& args,
+        picojson::object& out)
+{
+    LoggerD("Entered");
+
+    if (!args.contains(JSON_DATA) || !args.contains(JSON_CALLBACK_ID) ||
+        !args.get(JSON_CALLBACK_ID).is<double>()) {
+      LoggerE("json is incorrect - missing required member");
+      return;
+    }
+
+    picojson::object data = args.get(JSON_DATA).get<picojson::object>();
+    const double callbackId = args.get(JSON_CALLBACK_ID).get<double>();
+
+    auto json = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+    picojson::object& obj = json->get<picojson::object>();
+    obj[JSON_CALLBACK_ID] = picojson::value(callbackId);
+
+    AbstractFilterPtr filter;
+    PlatformResult ret = MessagingUtil::jsonToAbstractFilter(data, &filter);
+    if (ret.IsError()) {
+      POST_AND_RETURN(ret, json, obj, JSON_CALLBACK_ERROR)
+    }
+
+    int serviceId = getServiceIdFromJSON(data);
+
+    auto service = manager_.getMessageService(serviceId);
+
+    std::shared_ptr<FoldersChangeCallback> callback(new FoldersChangeCallback(
+        static_cast<long>(callbackId), serviceId, service->getMsgServiceType(), queue_));
+
+    callback->setFilter(filter);
+
+    long op_id = service->getMsgStorage()->addFoldersChangeListener(callback);
+
+    picojson::value v(static_cast<double>(op_id));
+    ReportSuccess(v, out);
+}
+
+void MessagingInstance::MessageStorageRemoveChangeListener(const picojson::value& args,
+        picojson::object& out)
+{
+    LoggerD("Entered");
+
+    if (!args.contains(JSON_DATA)) {
+      LoggerE("json is incorrect - missing required member");
+      return;
+    }
+
+    picojson::object data = args.get(JSON_DATA).get<picojson::object>();
+    const long watchId = static_cast<long>(
+            data.at(REMOVE_CHANGE_LISTENER_ARGS_WATCHID).get<double>());
+
+    auto service = manager_.getMessageService(getServiceIdFromJSON(data));
+
+    service->getMsgStorage()->removeChangeListener(watchId);
+    ReportSuccess(out);
+}
+
+} // namespace messaging
+} // namespace extension
+
diff --git a/webWidgetTCT_device/src/messaging/messaging_instance.h b/webWidgetTCT_device/src/messaging/messaging_instance.h
new file mode 100755 (executable)
index 0000000..c5f0b51
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2015 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 MESSAGING_MESSAGING_INSTANCE_H_
+#define MESSAGING_MESSAGING_INSTANCE_H_
+
+#include "common/extension.h"
+
+#include "messaging_manager.h"
+#include "messaging_util.h"
+
+namespace extension {
+namespace messaging {
+
+class MessagingInstance: public common::ParsedInstance {
+public:
+  MessagingInstance();
+  virtual ~MessagingInstance();
+private:
+    void GetMessageServices(const picojson::value& args, picojson::object& out);
+
+    void MessageServiceSendMessage(const picojson::value& args,
+            picojson::object& out);
+    void MessageServiceLoadMessageBody(const picojson::value& args,
+            picojson::object& out);
+    void MessageServiceLoadMessageAttachment(const picojson::value& args,
+            picojson::object& out);
+    void MessageServiceSync(const picojson::value& args, picojson::object& out);
+    void MessageServiceSyncFolder(const picojson::value& args,
+            picojson::object& out);
+    void MessageServiceStopSync(const picojson::value& args,
+            picojson::object& out);
+
+    void MessageStorageAddDraft(const picojson::value& args,
+            picojson::object& out);
+    void MessageStorageFindMessages(const picojson::value& args,
+            picojson::object& out);
+    void MessageStorageRemoveMessages(const picojson::value& args,
+            picojson::object& out);
+    void MessageStorageUpdateMessages(const picojson::value& args,
+            picojson::object& out);
+    void MessageStorageFindConversations(const picojson::value& args,
+            picojson::object& out);
+    void MessageStorageRemoveConversations(const picojson::value& args,
+            picojson::object& out);
+    void MessageStorageFindFolders(const picojson::value& args,
+            picojson::object& out);
+    void MessageStorageAddMessagesChangeListener(const picojson::value& args,
+            picojson::object& out);
+    void MessageStorageAddConversationsChangeListener(const picojson::value& args,
+            picojson::object& out);
+    void MessageStorageAddFolderChangeListener(const picojson::value& args,
+            picojson::object& out);
+    void MessageStorageRemoveChangeListener(const picojson::value& args,
+            picojson::object& out);
+
+    MessagingManager manager_;
+    PostQueue queue_;
+};
+
+} // namespace messaging
+} // namespace extension
+
+#endif // MESSAGING_MESSAGING_INSTANCE_H_
diff --git a/webWidgetTCT_device/src/messaging/messaging_manager.cc b/webWidgetTCT_device/src/messaging/messaging_manager.cc
new file mode 100755 (executable)
index 0000000..4c119e5
--- /dev/null
@@ -0,0 +1,278 @@
+/*
+ * Copyright (c) 2015 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 "messaging_manager.h"
+
+#include <email-api.h>
+#include <email-types.h>
+#include <glib.h>
+#include <memory>
+#include <sstream>
+#include <stdexcept>
+
+#include "common/extension.h"
+#include "common/logger.h"
+#include "common/picojson.h"
+#include "common/platform_exception.h"
+#include "common/task-queue.h"
+
+#include "messaging_instance.h"
+#include "short_message_manager.h"
+#include "messaging_util.h"
+
+using common::ErrorCode;
+using common::PlatformResult;
+
+namespace extension {
+namespace messaging {
+
+namespace {
+const int UNDEFINED_MESSAGE_SERVICE = -1;
+}
+
+MsgManagerCallbackData::MsgManagerCallbackData(MessagingInstance& instance):
+    json(nullptr),
+    services_map(nullptr),
+    sms_service(nullptr),
+    mms_service(nullptr),
+    instance_(instance) {
+    LoggerD("Entered");
+}
+
+MessagingManager::MessagingManager(MessagingInstance& instance):
+    instance_(instance)
+{
+    LoggerD("Entered");
+    int ret = msg_open_msg_handle(&m_msg_handle);
+    if (ret != MSG_SUCCESS) {
+        LoggerE("Cannot get message handle: %d", ret);
+    } else {
+        ShortMsgManager::getInstance().registerStatusCallback(m_msg_handle);
+    }
+
+    m_sms_service = std::make_pair(UNDEFINED_MESSAGE_SERVICE, nullptr);
+    m_mms_service = std::make_pair(UNDEFINED_MESSAGE_SERVICE, nullptr);
+}
+
+MessagingManager::~MessagingManager()
+{
+    LoggerD("Entered");
+    int ret = msg_close_msg_handle(&m_msg_handle);
+    if (ret != MSG_SUCCESS) {
+        LoggerW("Cannot close message handle: %d", ret);
+    }
+
+    std::for_each(m_email_services.begin(), m_email_services.end(),
+            [](std::pair<int, MessageService*> el) {
+                delete el.second;
+        }
+    );
+    m_email_services.clear();
+
+    if (m_sms_service.second) {
+        delete m_sms_service.second;
+    }
+    if (m_mms_service.second) {
+        delete m_mms_service.second;
+    }
+}
+
+static gboolean callbackCompleted(const std::shared_ptr<MsgManagerCallbackData>& user_data)
+{
+    LoggerD("Entered");
+    std::shared_ptr<picojson::value> response = user_data->json;
+    common::Instance::PostMessage(&user_data->instance_, response->serialize().c_str());
+    return false;
+}
+
+static void* getMsgServicesThread(const std::shared_ptr<MsgManagerCallbackData>& user_data)
+{
+  LoggerD("Entered");
+
+  std::shared_ptr<picojson::value> response = user_data->json;
+  picojson::object& obj = response->get<picojson::object>();
+  MessageType type = MessageType::UNDEFINED;
+
+  auto platform_result = MessagingUtil::stringToMessageType(response->get(JSON_DATA).get<std::string>(), &type);
+
+  if (platform_result) {
+    switch (type) {
+      case MessageType::SMS:
+        LoggerD("MessageService for SMS");
+        {
+          if (user_data->sms_service->second) {
+            delete user_data->sms_service->second;
+          }
+
+          MessageService* service = MessageServiceShortMsg::GetSmsMessageService();
+
+          if (!service) {
+            LoggerE("MessageService for SMS creation failed");
+            platform_result = PlatformResult(ErrorCode::UNKNOWN_ERR, "MessageService for SMS creation failed");
+          } else {
+            *(user_data->sms_service) = std::make_pair(service->getMsgServiceId(), service);
+
+            // TODO FIXME
+            picojson::array array;
+            array.push_back(picojson::value(service->toPicoJS()));
+            obj[JSON_DATA] = picojson::value(array);
+            obj[JSON_ACTION] = picojson::value(JSON_CALLBACK_SUCCCESS);
+
+            // service is stored, so it cannot be deleted
+            service = nullptr;
+          }
+        }
+        break;
+
+      case MessageType::MMS:
+        LoggerD("MessageService for MMS");
+        {
+          if (user_data->mms_service->second) {
+            delete user_data->mms_service->second;
+          }
+
+          MessageService* service = MessageServiceShortMsg::GetMmsMessageService();
+
+          if (!service) {
+            LoggerE("MessageService for MMS creation failed");
+            platform_result = PlatformResult(ErrorCode::UNKNOWN_ERR, "MessageService for SMS creation failed");
+          } else {
+            *(user_data->mms_service) = std::make_pair(service->getMsgServiceId(), service);
+
+            picojson::array array;
+            array.push_back(picojson::value(service->toPicoJS()));
+            obj[JSON_DATA] = picojson::value(array);
+            obj[JSON_ACTION] = picojson::value(JSON_CALLBACK_SUCCCESS);
+
+            // service is stored, so it cannot be deleted
+            service = nullptr;
+          }
+        }
+        break;
+
+      case MessageType::EMAIL:
+        LoggerD("MessageService for EMAIL");
+        {
+          email_account_t* email_accounts = nullptr;
+          int count = 0;
+
+          // TODO FIXME need to work on readability of that case
+          if (email_get_account_list(&email_accounts, &count) != EMAIL_ERROR_NONE) {
+            LoggerE("Method failed: email_get_account_list()");
+            platform_result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Error during getting account list");
+          } else {
+            std::vector<MessageService*> msgServices;
+
+            for (int i = 0; i < count && platform_result; ++i) {
+              std::string name = "[";
+              if (email_accounts[i].account_name) {
+                name += email_accounts[i].account_name;
+              }
+              name += "] ";
+              name += email_accounts[i].incoming_server_user_name;
+              LoggerD("Account[%d/%d] id: %d, name: %s", i, count,
+                      email_accounts[i].account_id, name.c_str());
+
+              MessageService* service = new (std::nothrow) MessageServiceEmail(email_accounts[i].account_id,
+                                                                               name.c_str());
+              if (!service) {
+                LoggerD("message service[%d] is NULL", i);
+                std::for_each(msgServices.begin(), msgServices.end(),
+                              [](MessageService* service) {
+                                delete service;
+                              });
+                msgServices.clear();
+                LoggerE("MessageService for email creation failed");
+                platform_result = PlatformResult(ErrorCode::UNKNOWN_ERR, "MessageService for email creation failed");
+              } else {
+                msgServices.push_back(service);
+              }
+
+              // service is stored, so it cannot be deleted
+              service = nullptr;
+            }
+
+            email_free_account(&email_accounts, count);
+
+            if (platform_result) {
+              std::map<int, MessageService*>& email_services = *(user_data->services_map);
+              std::for_each(email_services.begin(), email_services.end(),
+                            [](std::pair<int, MessageService*> el) {
+                              delete el.second;
+                            });
+              email_services.clear();
+
+              std::vector<picojson::value> response;
+              std::for_each(msgServices.begin(), msgServices.end(),
+                            [&response, &email_services](MessageService* service) {
+                              response.push_back(picojson::value(service->toPicoJS()));
+                              email_services.insert(std::pair<int, MessageService*>(service->getMsgServiceId(), service));
+                            });
+              obj[JSON_DATA] = picojson::value(response);
+              obj[JSON_ACTION] = picojson::value(JSON_CALLBACK_SUCCCESS);
+            }
+          }
+        }
+        break;
+      default:
+        platform_result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Service type is undefined");
+    }
+  } else {
+    LoggerE("Unsupported service type");
+    platform_result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Unsupported service type");
+  }
+
+  if (!platform_result) {
+    LoggerE("Unknown error");
+    obj[JSON_DATA] = platform_result.ToJSON();
+    obj[JSON_ACTION] = picojson::value(JSON_CALLBACK_ERROR);
+  }
+
+  return nullptr;
+}
+
+void MessagingManager::getMessageServices(const std::string& type, double callbackId)
+{
+    LoggerD("Entered");
+
+    auto json = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+    picojson::object& obj = json->get<picojson::object>();
+    obj[JSON_CALLBACK_ID] = picojson::value(callbackId);
+    obj[JSON_DATA] = picojson::value(type);
+
+    auto user_data = std::shared_ptr<MsgManagerCallbackData>(new MsgManagerCallbackData(instance_));
+    user_data->json = json;
+    user_data->services_map = &m_email_services;
+    user_data->sms_service = &m_sms_service;
+    user_data->mms_service = &m_mms_service;
+
+    common::TaskQueue::GetInstance().Queue<MsgManagerCallbackData>
+        (getMsgServicesThread, callbackCompleted, user_data);
+}
+
+MessageService* MessagingManager::getMessageService(const int id) {
+    if (id == m_sms_service.first) {
+        return m_sms_service.second;
+    } else if (id == m_mms_service.first) {
+        return m_mms_service.second;
+    } else {
+        return m_email_services[id];
+    }
+}
+
+} // namespace messaging
+} // namespace extension
+
diff --git a/webWidgetTCT_device/src/messaging/messaging_manager.h b/webWidgetTCT_device/src/messaging/messaging_manager.h
new file mode 100755 (executable)
index 0000000..4f26b62
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2015 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 MESSAGING_MESSAGING_MANAGER_H_
+#define MESSAGING_MESSAGING_MANAGER_H_
+
+#include <msg.h>
+#include <string>
+#include <map>
+
+#include "message_service_email.h"
+#include "message_service_short_msg.h"
+
+namespace extension {
+namespace messaging {
+
+class MessagingInstance;
+
+class MsgManagerCallbackData {
+public:
+    explicit MsgManagerCallbackData(MessagingInstance& instance_);
+    std::shared_ptr<picojson::value> json;
+    std::map<int, MessageService*>* services_map;
+    std::pair<int, MessageService*>* sms_service;
+    std::pair<int, MessageService*>* mms_service;
+    MessagingInstance& instance_;
+};
+
+class MessagingManager {
+public:
+  explicit MessagingManager(MessagingInstance& instance);
+  MessagingManager(const MessagingManager &);
+  virtual ~MessagingManager();
+
+  void getMessageServices(const std::string& type, double callbackId);
+  MessageService* getMessageService(const int id);
+
+private:
+    void operator=(const MessagingManager &);
+
+    msg_handle_t m_msg_handle;
+    std::map<int, MessageService*> m_email_services;
+    std::pair<int, MessageService*> m_sms_service;
+    std::pair<int, MessageService*> m_mms_service;
+
+    MessagingInstance& instance_;
+};
+
+} // namespace messaging
+} // namespace extension
+
+#endif // MESSAGING_MESSAGING_MANAGER_H_
+
diff --git a/webWidgetTCT_device/src/messaging/messaging_util.cc b/webWidgetTCT_device/src/messaging/messaging_util.cc
new file mode 100755 (executable)
index 0000000..f1a7aa5
--- /dev/null
@@ -0,0 +1,1370 @@
+/*
+ * Copyright (c) 2015 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 "messaging_util.h"
+
+#include <glib.h>
+
+#include <fstream>
+#include <stdexcept>
+#include <streambuf>
+#include <sstream>
+#include <cstdlib>
+
+#include <email-api-account.h>
+#include "message_email.h"
+#include "message_sms.h"
+#include "message_mms.h"
+#include "message_conversation.h"
+#include "messaging_instance.h"
+#include "messaging/email_manager.h"
+
+#include "tizen/tizen.h"
+#include "common/logger.h"
+#include "common/platform_exception.h"
+#include "common/scope_exit.h"
+#include "common/assert.h"
+
+using common::ErrorCode;
+using common::PlatformResult;
+
+namespace extension {
+namespace messaging {
+using namespace common;
+
+const char* JSON_ACTION = "action";
+const char* JSON_CALLBACK_ID = "cid";
+const char* JSON_CALLBACK_SUCCCESS = "success";
+const char* JSON_CALLBACK_ERROR = "error";
+const char* JSON_CALLBACK_PROGRESS = "progress";
+const char* JSON_CALLBACK_KEEP = "keep";
+const char* JSON_DATA = "args";
+const char* JSON_DATA_MESSAGE = "message";
+const char* JSON_DATA_MESSAGE_BODY = "messageBody";
+const char* JSON_DATA_MESSAGE_ATTACHMENT = "messageAttachment";
+const char* JSON_DATA_RECIPIENTS = "recipients";
+const char* JSON_ERROR_MESSAGE = "message";
+const char* JSON_ERROR_NAME = "name";
+const char* JSON_ERROR_CODE = "code";
+
+const char* MESSAGE_ATTRIBUTE_ID = "id";
+const char* MESSAGE_ATTRIBUTE_OLD_ID = "oldId";
+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";
+const char* MESSAGE_ATTRIBUTE_MESSAGE_BODY = "body";
+
+const char* MESSAGE_BODY_ATTRIBUTE_MESSAGE_ID = "messageId";
+const char* MESSAGE_BODY_ATTRIBUTE_LOADED = "loaded";
+const char* MESSAGE_BODY_ATTRIBUTE_PLAIN_BODY = "plainBody";
+const char* MESSAGE_BODY_ATTRIBUTE_HTML_BODY = "htmlBody";
+const char* MESSAGE_BODY_ATTRIBUTE_INLINE_ATTACHMENTS = "inlineAttachments";
+
+const char* MESSAGE_ATTRIBUTE_MESSAGE_ATTACHMENTS = "attachments";
+const char* MESSAGE_ATTACHMENT_ATTRIBUTE_ID = "id";
+const char* MESSAGE_ATTACHMENT_ATTRIBUTE_MESSAGE_ID = "messageId";
+const char* MESSAGE_ATTACHMENT_ATTRIBUTE_MIME_TYPE = "mimeType";
+const char* MESSAGE_ATTACHMENT_ATTRIBUTE_FILE_PATH = "filePath";
+
+const char* MESSAGE_FOLDER_ATTRIBUTE_ID = "id";
+const char* MESSAGE_FOLDER_ATTRIBUTE_PARENT_ID = "parentId";
+const char* MESSAGE_FOLDER_ATTRIBUTE_SERVICE_ID = "serviceId";
+const char* MESSAGE_FOLDER_ATTRIBUTE_CONTENT_TYPE = "contentType";
+const char* MESSAGE_FOLDER_ATTRIBUTE_NAME = "name";
+const char* MESSAGE_FOLDER_ATTRIBUTE_PATH = "path";
+const char* MESSAGE_FOLDER_ATTRIBUTE_TYPE = "type";
+const char* MESSAGE_FOLDER_ATTRIBUTE_SYNCHRONIZABLE = "synchronizable";
+
+const char* MESSAGE_CONVERSATION_ATTRIBUTE_ID = "id";
+const char* MESSAGE_CONVERSATION_ATTRIBUTE_TYPE = "type";
+const char* MESSAGE_CONVERSATION_ATTRIBUTE_TIMESTAMP = "timestamp";
+const char* MESSAGE_CONVERSATION_ATTRIBUTE_MESSAGE_COUNT = "messageCount";
+const char* MESSAGE_CONVERSATION_ATTRIBUTE_UNREAD_MESSAGES = "unreadMessages";
+const char* MESSAGE_CONVERSATION_ATTRIBUTE_PREVIEW = "preview";
+const char* MESSAGE_CONVERSATION_ATTRIBUTE_SUBJECT = "subject";
+const char* MESSAGE_CONVERSATION_ATTRIBUTE_IS_READ = "isRead";
+const char* MESSAGE_CONVERSATION_ATTRIBUTE_FROM = "from";
+const char* MESSAGE_CONVERSATION_ATTRIBUTE_TO = "to";
+const char* MESSAGE_CONVERSATION_ATTRIBUTE_CC = "cc";
+const char* MESSAGE_CONVERSATION_ATTRIBUTE_BCC = "bcc";
+const char* MESSAGE_CONVERSATION_ATTRIBUTE_LAST_MESSAGE_ID = "lastMessageId";
+
+namespace {
+const std::string TYPE_SMS = "messaging.sms";
+const std::string TYPE_MMS = "messaging.mms";
+const std::string TYPE_EMAIL = "messaging.email";
+const std::string SENT = "SENT";
+const std::string SENDING = "SENDING";
+const std::string FAILED = "FAILED";
+const std::string DRAFT = "DRAFT";
+
+const std::string JSON_TO_ATTRIBUTE_NAME = "attributeName";
+const std::string JSON_TO_ORDER = "order";
+const std::string JSON_TO_SORT = "sort";
+const std::string JSON_TO_FILTER = "filter";
+const std::string JSON_TO_MATCH_FLAG = "matchFlag";
+const std::string JSON_TO_MATCH_VALUE = "matchValue";
+const std::string JSON_TO_INITIAL_VALUE = "initialValue";
+const std::string JSON_TO_END_VALUE = "endValue";
+const std::string JSON_TO_TYPE = "type";
+const std::string JSON_TO_FILTER_ARRAY = "filters";
+
+const char* JSON_FILTER_TYPE = "filterType";
+const char* JSON_FILTER_ATTRIBUTE_TYPE = "AttributeFilter";
+const char* JSON_FILTER_ATTRIBUTE_RANGE_TYPE = "AttributeRangeFilter";
+const char* JSON_FILTER_COMPOSITE_TYPE = "CompositeFilter";
+
+const std::map<std::string, MessageType> stringToTypeMap = {
+    {TYPE_SMS, MessageType::SMS},
+    {TYPE_MMS, MessageType::MMS},
+    {TYPE_EMAIL, MessageType::EMAIL}
+};
+
+const std::map<MessageType, std::string> typeToStringMap = {
+    {MessageType::SMS, TYPE_SMS},
+    {MessageType::MMS, TYPE_MMS},
+    {MessageType::EMAIL, TYPE_EMAIL}
+};
+
+const std::string FOLDER_TYPE_INBOX = "INBOX";
+const std::string FOLDER_TYPE_OUTBOX = "OUTBOX";
+const std::string FOLDER_TYPE_DRAFTS = "DRAFTS";
+const std::string FOLDER_TYPE_SENTBOX = "SENTBOX";
+
+} // namespace
+
+std::string MessagingUtil::messageFolderTypeToString(MessageFolderType type)
+{
+    LoggerD("Entered");
+    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 "";
+    }
+}
+
+MessageFolderType MessagingUtil::stringToMessageFolderType(std::string type)
+{
+    LoggerD("Entered");
+    if (FOLDER_TYPE_INBOX == type) {
+        return MessageFolderType::MESSAGE_FOLDER_TYPE_INBOX;
+    }
+    if (FOLDER_TYPE_OUTBOX == type) {
+        return MessageFolderType::MESSAGE_FOLDER_TYPE_OUTBOX;
+    }
+    if (FOLDER_TYPE_DRAFTS == type) {
+        return MessageFolderType::MESSAGE_FOLDER_TYPE_DRAFTS;
+    }
+    if (FOLDER_TYPE_SENTBOX == type) {
+        return MessageFolderType::MESSAGE_FOLDER_TYPE_SENTBOX;
+    }
+    return MessageFolderType::MESSAGE_FOLDER_TYPE_NOTSTANDARD;
+}
+
+PlatformResult MessagingUtil::stringToMessageType(const std::string& str, MessageType* out)
+{
+  LoggerD("Entered");
+  const auto it = stringToTypeMap.find(str);
+
+  if (it == stringToTypeMap.end()) {
+    LoggerE("Not supported type: %s", str.c_str());
+    return PlatformResult(ErrorCode::TYPE_MISMATCH_ERR, "Not supported type: " + str);
+  } else {
+    *out = it->second;
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+}
+
+common::PlatformResult MessagingUtil::messageTypeToString(MessageType type, std::string* out)
+{
+  LoggerD("Entered");
+  const auto it = typeToStringMap.find(type);
+
+  if (it == typeToStringMap.end()) {
+    LoggerE("Invalid MessageType: %d", type);
+    return PlatformResult(ErrorCode::TYPE_MISMATCH_ERR, "Invalid MessageType");
+  } else {
+    *out = it->second;
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+}
+
+std::string MessagingUtil::messageTypeToString(MessageType type) {
+  LoggerD("Entered");
+  std::string type_str;
+  PlatformResult platform_result = messageTypeToString(type, &type_str);
+  Assert(platform_result);
+  return type_str;
+}
+
+std::string MessagingUtil::ltrim(const std::string& input)
+{
+    LoggerD("Entered");
+    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)
+{
+    LoggerD("Entered");
+    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)
+{
+    LoggerD("Entered");
+    std::vector<std::string> extractedAddresses;
+    for(auto it = addresses.begin(); it != addresses.end(); ++it) {
+        extractedAddresses.push_back(MessagingUtil::extractSingleEmailAddress(*it));
+    }
+
+    return extractedAddresses;
+}
+
+PlatformResult MessagingUtil::loadFileContentToString(const std::string& file_path, std::string* result)
+{
+    LoggerD("Entered");
+    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();
+        *result = ConvertToUtf8(file_path, outString);
+    } else {
+        std::stringstream ss_error_msg;
+        ss_error_msg << "Failed to open file: " << file_path;
+        return PlatformResult(ErrorCode::IO_ERR, ss_error_msg.str().c_str());
+    }
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+namespace {
+
+std::string GetFilename(const std::string& file_path) {
+  LoggerD("Entered");
+  const auto start = file_path.find_last_of("/\\");
+  const auto basename = file_path.substr(std::string::npos == start ? 0 : start + 1);
+  return basename.substr(0, basename.find_last_of("."));
+}
+
+std::string PerformConversion(const std::string& input, const gchar* from_charset) {
+  LoggerD("Entered");
+
+  GIConv cd = g_iconv_open("UTF-8//IGNORE", from_charset);
+
+  if ((GIConv)-1 == cd) {
+    LoggerE("Failed to open iconv.");
+    return input;
+  }
+
+  SCOPE_EXIT {
+    g_iconv_close(cd);
+  };
+
+  // copied from glib/gconvert.c, g_convert does not handle "//IGNORE" properly
+  static const gsize kNulTerminatorLength = 4;
+  const gchar* str = input.c_str();
+  gssize len = input.size();
+
+  gchar* p = const_cast<gchar*>(str);
+  gsize inbytes_remaining = len;
+  gsize outbuf_size = len + kNulTerminatorLength;
+  gsize outbytes_remaining = outbuf_size - kNulTerminatorLength;
+  gchar* dest = nullptr;
+  gchar* outp = nullptr;
+  gboolean have_error = FALSE;
+  gboolean done = FALSE;
+  gboolean reset = FALSE;
+
+  outp = dest = static_cast<gchar*>(g_malloc(outbuf_size));
+
+  if (!dest) {
+    LoggerE("Failed to allocate memory.");
+    return input;
+  }
+
+  SCOPE_EXIT {
+    g_free(dest);
+  };
+
+  while (!done && !have_error) {
+    gsize err = 0;
+
+    if (reset) {
+      err = g_iconv(cd, nullptr, &inbytes_remaining, &outp, &outbytes_remaining);
+    } else {
+      err = g_iconv(cd, &p, &inbytes_remaining, &outp, &outbytes_remaining);
+    }
+
+    if (static_cast<gsize>(-1) == err) {
+      switch (errno) {
+        case EINVAL:
+          LoggerD("EINVAL");
+          // Incomplete text, do not report an error
+          done = TRUE;
+          break;
+
+        case E2BIG:
+          {
+            LoggerD("E2BIG");
+            gsize used = outp - dest;
+
+            outbuf_size *= 2;
+            dest = static_cast<gchar*>(g_realloc(dest, outbuf_size));
+
+            outp = dest + used;
+            outbytes_remaining = outbuf_size - used - kNulTerminatorLength;
+          }
+          break;
+
+        case EILSEQ:
+          if (0 == inbytes_remaining) {
+            LoggerD("EILSEQ reported, but whole input buffer was processed, assuming it's OK");
+          } else {
+            LoggerE("EILSEQ");
+            have_error = TRUE;
+          }
+          break;
+
+        default:
+          LoggerE("Conversion error: %d", errno);
+          have_error = TRUE;
+          break;
+      }
+    } else {
+      if (!reset) {
+        // call g_iconv with NULL inbuf to cleanup shift state
+        reset = TRUE;
+        inbytes_remaining = 0;
+      } else {
+        done = TRUE;
+      }
+    }
+  }
+
+  memset(outp, 0, kNulTerminatorLength);
+
+  if ((p - str) != len) {
+    LoggerE("Partial character sequence at end of input");
+    have_error = TRUE;
+  }
+
+  std::string result;
+
+  if (!have_error) {
+    result = dest;
+  } else {
+    LoggerE("Conversion error");
+  }
+
+  return result;
+}
+
+}  // namespace
+
+std::string MessagingUtil::ConvertToUtf8(const std::string& file_path, const std::string& contents) {
+  LoggerD("Entered");
+
+  // in case of messages, encoding of the file contents is stored as its filename
+  // is case of draft messages, it is not...
+  std::string encoding = GetFilename(file_path);
+
+  LoggerD("encoding: %s", encoding.c_str());
+
+  // implementation taken from apps/home/email.git,
+  // file Project-Files/common/src/email-utils.c
+
+  gchar* from_charset = g_ascii_strup(encoding.c_str(), -1);
+
+  if (0 == g_ascii_strcasecmp(from_charset, "KS_C_5601-1987")) {
+    // "ks_c_5601-1987" is not an encoding name. It's just a charset.
+    // There's no code page on IANA for "ks_c_5601-1987".
+    // So we should convert this to encoding name "EUC-KR"
+    // CP949 is super set of EUC-KR, we use CP949 first
+    LoggerD("change: KS_C_5601-1987 ===> CP949");
+    g_free(from_charset);
+    from_charset = g_strdup("CP949");
+  } else if (0 == g_ascii_strcasecmp(from_charset, "ISO-2022-JP")) {
+    // iso-2022-jp-2 is a superset of iso-2022-jp. In some email,
+    // iso-2022-jp is not converted to utf8 correctly. So in this case,
+    // we use iso-2022-jp-2 instead.
+    LoggerD("change: ISO-2022-JP ===> ISO-2022-JP-2");
+    g_free(from_charset);
+    from_charset = g_strdup("ISO-2022-JP-2");
+  }
+
+  std::string output;
+
+  // if charset is unknown, conversion is not needed
+  if ((0 != g_ascii_strcasecmp(from_charset, UNKNOWN_CHARSET_PLAIN_TEXT_FILE))) {
+    // we're performing UTF-8 to UTF-8 conversion to remove malformed data
+    LoggerD("performing conversion");
+
+    output = PerformConversion(contents, from_charset);
+
+    if ("" == output && 0 == g_ascii_strcasecmp(from_charset, "CP949")) {
+      LoggerD("change: CP949 ===> EUC-KR, try again");
+      output = PerformConversion(contents, "EUC-KR");
+    }
+
+    if ("" == output) {
+      LoggerE("Conversion failed");
+      // conversion failed, use original contents
+      output = contents;
+    }
+  } else {
+    // no conversion
+    output = contents;
+  }
+
+  g_free(from_charset);
+
+  return output;
+}
+
+std::string MessagingUtil::messageStatusToString(MessageStatus status) {
+    LoggerD("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.
+            LoggerD("Unsupported or undefined MessageStatus");
+            return "";
+    }
+}
+
+picojson::value MessagingUtil::messageBodyToJson(std::shared_ptr<MessageBody> body)
+{
+    LoggerD("Entered");
+    picojson::object b;
+    b[MESSAGE_BODY_ATTRIBUTE_MESSAGE_ID] = picojson::value(std::to_string(body->getMessageId()));
+    b[MESSAGE_BODY_ATTRIBUTE_LOADED] = picojson::value(body->getLoaded());
+    b[MESSAGE_BODY_ATTRIBUTE_PLAIN_BODY] = picojson::value(body->getPlainBody());
+    b[MESSAGE_BODY_ATTRIBUTE_HTML_BODY] = picojson::value(body->getHtmlBody());
+
+    std::vector<picojson::value> array;
+
+    auto vectorToAttachmentArray = [&array] (std::shared_ptr<MessageAttachment>& a)->void {
+        array.push_back(MessagingUtil::messageAttachmentToJson(a));
+    };
+    auto inlineAttachments = body->getInlineAttachments();
+    for_each(inlineAttachments.begin(), inlineAttachments.end(), vectorToAttachmentArray);
+
+    b[MESSAGE_BODY_ATTRIBUTE_INLINE_ATTACHMENTS] = picojson::value(array);
+    array.clear();
+
+    picojson::value v(b);
+    return v;
+}
+
+picojson::value MessagingUtil::messageToJson(std::shared_ptr<Message> message)
+{
+    LoggerD("Entered");
+    picojson::object o;
+
+    std::vector<picojson::value> array;
+    std::vector<std::string> bcc, cc;
+    auto vectorToArray = [&array] (std::string& s)->void {
+        array.push_back(picojson::value(s));
+    };
+
+    switch (message->getType()) {
+    case MessageType::SMS:
+        break;
+    case MessageType::MMS:
+        o[MESSAGE_ATTRIBUTE_HAS_ATTACHMENT] = picojson::value(message->getHasAttachment());
+        o[MESSAGE_ATTRIBUTE_SUBJECT] = picojson::value(message->getSubject());
+        o[MESSAGE_ATTRIBUTE_OLD_ID] = picojson::value(std::to_string(message->getOldId()));
+        break;
+    case MessageType::EMAIL:
+
+        cc = message->getCC();
+        for_each(cc.begin(), cc.end(), vectorToArray);
+        o[MESSAGE_ATTRIBUTE_CC] = picojson::value(array);
+        array.clear();
+
+        bcc = message->getBCC();
+        for_each(bcc.begin(), bcc.end(), vectorToArray);
+        o[MESSAGE_ATTRIBUTE_BCC] = picojson::value(array);
+        array.clear();
+
+        o[MESSAGE_ATTRIBUTE_HAS_ATTACHMENT] = picojson::value(message->getHasAttachment());
+        o[MESSAGE_ATTRIBUTE_IS_HIGH_PRIORITY] = picojson::value(message->getIsHighPriority());
+        o[MESSAGE_ATTRIBUTE_SUBJECT] = picojson::value(message->getSubject());
+        o[MESSAGE_ATTRIBUTE_OLD_ID] = picojson::value(std::to_string(message->getOldId()));
+
+        break;
+    default:
+        LoggerW("Unsupported message type");
+        break;
+    }
+
+    o[MESSAGE_ATTRIBUTE_ID] =
+            message->is_id_set()
+            ? picojson::value(std::to_string(message->getId()))
+            : picojson::value();
+    o[MESSAGE_ATTRIBUTE_CONVERSATION_ID]=
+            message->is_conversation_id_set()
+            ? picojson::value(std::to_string(message->getConversationId()))
+            : picojson::value();
+    o[MESSAGE_ATTRIBUTE_FOLDER_ID] =
+            message->is_folder_id_set()
+            ? picojson::value(std::to_string(message->getFolderId()))
+            : picojson::value();
+    o[MESSAGE_ATTRIBUTE_TYPE] = picojson::value(message->getTypeString());
+    o[MESSAGE_ATTRIBUTE_TIMESTAMP] =
+            message->is_timestamp_set()
+            ? picojson::value(static_cast<double>(message->getTimestamp()))
+            : picojson::value();
+    o[MESSAGE_ATTRIBUTE_FROM] =
+            message->is_from_set()
+            ? picojson::value(message->getFrom())
+            : picojson::value(std::string(""));
+
+    std::vector<std::string> to = message->getTO();
+    for_each(to.begin(), to.end(), vectorToArray);
+    o[MESSAGE_ATTRIBUTE_TO] = picojson::value(array);
+    array.clear();
+
+    o[MESSAGE_ATTRIBUTE_IS_READ] = picojson::value(message->getIsRead());
+    o[MESSAGE_ATTRIBUTE_IN_RESPONSE_TO] =
+            message->is_in_response_set()
+            ? picojson::value(std::to_string(message->getInResponseTo()))
+            : picojson::value();
+
+    // TODO MessageStatus has type MessageStatus
+    //o[MESSAGE_ATTRIBUTE_MESSAGE_STATUS] = picojson::value(message->getMessageStatus());
+
+    std::shared_ptr<MessageBody> body = message->getBody();
+    o[MESSAGE_ATTRIBUTE_BODY] = MessagingUtil::messageBodyToJson(body);
+
+    auto vectorToAttachmentArray = [&array] (std::shared_ptr<MessageAttachment>& a)->void {
+        array.push_back(MessagingUtil::messageAttachmentToJson(a));
+    };
+    auto attachments = message->getMessageAttachments();
+    for_each(attachments.begin(), attachments.end(), vectorToAttachmentArray);
+    o[MESSAGE_ATTRIBUTE_ATTACHMENTS] = picojson::value(array);
+    array.clear();
+
+    picojson::value v(o);
+    return v;
+}
+
+picojson::value MessagingUtil::conversationToJson(std::shared_ptr<MessageConversation> conversation)
+{
+    LoggerD("Entered");
+    picojson::object o;
+
+    o[MESSAGE_CONVERSATION_ATTRIBUTE_ID] = picojson::value(std::to_string(conversation->getConversationId()));
+
+    o[MESSAGE_CONVERSATION_ATTRIBUTE_TYPE] = picojson::value(conversation->getTypeString());
+
+    o[MESSAGE_CONVERSATION_ATTRIBUTE_TIMESTAMP] =
+            picojson::value(static_cast<double>(conversation->getTimestamp()));
+
+    o[MESSAGE_CONVERSATION_ATTRIBUTE_MESSAGE_COUNT] =
+            picojson::value(static_cast<double>(conversation->getMessageCount()));
+
+    o[MESSAGE_CONVERSATION_ATTRIBUTE_UNREAD_MESSAGES] =
+            picojson::value(static_cast<double>(conversation->getUnreadMessages()));
+
+    o[MESSAGE_CONVERSATION_ATTRIBUTE_PREVIEW] =
+            picojson::value(conversation->getPreview());
+
+    o[MESSAGE_CONVERSATION_ATTRIBUTE_IS_READ] =
+            picojson::value(conversation->getIsRead());
+
+    o[MESSAGE_CONVERSATION_ATTRIBUTE_FROM] =
+            picojson::value(conversation->getFrom());
+
+    o[MESSAGE_CONVERSATION_ATTRIBUTE_LAST_MESSAGE_ID] =
+            picojson::value(std::to_string(conversation->getLastMessageId()));
+
+    std::vector<picojson::value> array;
+    auto vectorToArray = [&array] (std::string& s)->void {
+        array.push_back(picojson::value(s));
+    };
+
+    std::vector<std::string> to = conversation->getTo();
+    for_each(to.begin(), to.end(), vectorToArray);
+    o[MESSAGE_ATTRIBUTE_TO] = picojson::value(array);
+    array.clear();
+    std::vector<std::string> cc, bcc;
+
+    switch (conversation->getType()) {
+        case MessageType::SMS:
+            break;
+        case MessageType::MMS:
+            o[MESSAGE_ATTRIBUTE_SUBJECT] = picojson::value(conversation->getSubject());
+            break;
+        case MessageType::EMAIL:
+            o[MESSAGE_ATTRIBUTE_SUBJECT] = picojson::value(conversation->getSubject());
+
+            cc = conversation->getCC();
+            for_each(cc.begin(), cc.end(), vectorToArray);
+            o[MESSAGE_ATTRIBUTE_CC] = picojson::value(array);
+            array.clear();
+
+            bcc = conversation->getBCC();
+            for_each(bcc.begin(), bcc.end(), vectorToArray);
+            o[MESSAGE_ATTRIBUTE_BCC] = picojson::value(array);
+            array.clear();
+
+            break;
+        default:
+            LoggerW("Unsupported message type");
+            break;
+        }
+
+    picojson::value v(o);
+    return v;
+}
+
+picojson::value MessagingUtil::folderToJson(std::shared_ptr<MessageFolder> folder)
+{
+    LoggerD("Entered");
+
+    picojson::object o;
+
+    o[MESSAGE_FOLDER_ATTRIBUTE_ID] = picojson::value(folder->getId());
+    o[MESSAGE_FOLDER_ATTRIBUTE_PARENT_ID] =
+            folder->isParentIdSet()
+            ? picojson::value(folder->getParentId())
+            : picojson::value();
+    o[MESSAGE_FOLDER_ATTRIBUTE_SERVICE_ID] =  picojson::value(folder->getServiceId());
+    o[MESSAGE_FOLDER_ATTRIBUTE_CONTENT_TYPE] = picojson::value(folder->getContentType());
+    o[MESSAGE_FOLDER_ATTRIBUTE_NAME] = picojson::value(folder->getName());
+    o[MESSAGE_FOLDER_ATTRIBUTE_PATH] = picojson::value(folder->getPath());
+    o[MESSAGE_FOLDER_ATTRIBUTE_TYPE] =
+            picojson::value(MessagingUtil::messageFolderTypeToString(folder->getType()));
+    o[MESSAGE_FOLDER_ATTRIBUTE_SYNCHRONIZABLE] = picojson::value(folder->getSynchronizable());
+
+    picojson::value v(o);
+    return v;
+}
+
+PlatformResult MessagingUtil::jsonToMessage(const picojson::value& json,
+                                            std::shared_ptr<Message>* result_message)
+{
+    LoggerD("Entered");
+    std::shared_ptr<Message> message;
+    picojson::object data = json.get<picojson::object>();
+    std::string type = data.at("type").get<std::string>();
+    MessageType mtype = UNDEFINED;
+    auto platform_result = MessagingUtil::stringToMessageType(type, &mtype);
+
+    if (!platform_result) {
+      return platform_result;
+    }
+
+    switch (mtype) {
+    case MessageType::SMS:
+        LoggerD("SMS type");
+        if(data.at(MESSAGE_ATTRIBUTE_ID).is<picojson::null>()) {
+            message = std::shared_ptr<Message>(new MessageSMS());
+            break;
+        }
+    case MessageType::MMS:
+        LoggerD("MMS type");
+        if(data.at(MESSAGE_ATTRIBUTE_ID).is<picojson::null>()) {
+            message = std::shared_ptr<Message>(new MessageMMS());
+        } else {
+            std::string mid = data.at(MESSAGE_ATTRIBUTE_ID).get<std::string>();
+            int message_id = std::atoi(mid.c_str());
+            platform_result = Message::findShortMessageById(message_id, &message);
+            if (!platform_result) return platform_result;
+        }
+        break;
+    case MessageType::EMAIL:
+        if (!data.at(MESSAGE_ATTRIBUTE_ID).is<picojson::null>()) {
+            std::string mid = data.at(MESSAGE_ATTRIBUTE_ID).get<std::string>();
+            int mail_id = std::atoi(mid.c_str());
+            email_mail_data_t* mail = NULL;
+            if (EMAIL_ERROR_NONE != email_get_mail_data(mail_id, &mail)) {
+                // TODO what should happen?
+                LoggerE("Fatal error: message not found: %d!", mail_id);
+                return PlatformResult(ErrorCode::TYPE_MISMATCH_ERR,
+                                      "Failed to find specified email.");
+            } else {
+                platform_result = Message::convertPlatformEmailToObject(*mail, &message);
+                email_free_mail_data(&mail,1);
+                if (!platform_result) return platform_result;
+            }
+        } else {
+            message = std::shared_ptr<Message>(new MessageEmail());
+        }
+        break;
+    default:
+        LoggerE("Not supported message type");
+        break;
+    }
+
+    std::vector<std::string> result;
+    PlatformResult conv_res(ErrorCode::NO_ERROR);
+    auto arrayVectorStringConverter = [&result, &conv_res] (picojson::value& v)->void {
+      if (!v.is<std::string>()) {
+        const std::string message = "Passed array holds incorrect values "
+            + v.serialize() + " is not a correct string value";
+        LoggerE("Error: %s", message.c_str());
+        conv_res = PlatformResult(ErrorCode::INVALID_VALUES_ERR, message);
+      }
+      if (conv_res.IsError()) {
+        return;
+      }
+      result.push_back(v.get<std::string>());
+    };
+
+    auto subject = MessagingUtil::getValueFromJSONObject<std::string>(data,
+            MESSAGE_ATTRIBUTE_SUBJECT);
+    message->setSubject(subject);
+
+    auto toJS = MessagingUtil::getValueFromJSONObject<std::vector<picojson::value>>(data,
+            MESSAGE_ATTRIBUTE_TO);
+    for_each(toJS.begin(), toJS.end(), arrayVectorStringConverter);
+    if (conv_res.IsError()) {
+      return conv_res;
+    }
+    message->setTO(result);
+    result.clear();
+
+
+    auto ccJS = MessagingUtil::getValueFromJSONObject<
+            std::vector<picojson::value>>(data, MESSAGE_ATTRIBUTE_CC);
+    for_each(ccJS.begin(), ccJS.end(), arrayVectorStringConverter);
+    if (conv_res.IsError()) {
+      return conv_res;
+    }
+    message->setCC(result);
+    result.clear();
+
+    auto bccJS = MessagingUtil::getValueFromJSONObject<
+            std::vector<picojson::value>>(data, MESSAGE_ATTRIBUTE_BCC);
+    for_each(bccJS.begin(), bccJS.end(), arrayVectorStringConverter);
+    if (conv_res.IsError()) {
+      return conv_res;
+    }
+    message->setBCC(result);
+    result.clear();
+
+    auto priority = MessagingUtil::getValueFromJSONObject<bool>(data,
+            MESSAGE_ATTRIBUTE_IS_HIGH_PRIORITY);
+    message->setIsHighPriority(priority);
+
+    auto isRead = MessagingUtil::getValueFromJSONObject<bool>(data,
+            MESSAGE_ATTRIBUTE_IS_READ);
+    message->setIsRead(isRead);
+
+    std::shared_ptr<MessageBody> body = MessagingUtil::jsonToMessageBody(
+            data[MESSAGE_ATTRIBUTE_MESSAGE_BODY]);
+    message->setBody(body);
+
+    AttachmentPtrVector attachments;
+    auto ma = data.at(MESSAGE_ATTRIBUTE_MESSAGE_ATTACHMENTS).get<std::vector<picojson::value>>();
+
+    auto arrayVectorAttachmentConverter = [&attachments] (picojson::value& v)->void
+    {
+        std::shared_ptr<MessageAttachment> attachment =
+                MessagingUtil::jsonToMessageAttachment(v);
+
+        attachments.push_back(attachment);
+    };
+
+    for_each(ma.begin(), ma.end(), arrayVectorAttachmentConverter);
+    message->setMessageAttachments(attachments);
+
+    *result_message = message;
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+std::shared_ptr<MessageBody> MessagingUtil::jsonToMessageBody(const picojson::value& json)
+{
+    LoggerD("Entered");
+
+    std::shared_ptr<MessageBody> body = std::shared_ptr<MessageBody>(new MessageBody());
+    picojson::object data = json.get<picojson::object>();
+
+    bool loaded = MessagingUtil::getValueFromJSONObject<bool>(data,
+            MESSAGE_BODY_ATTRIBUTE_LOADED);
+    body->setLoaded(loaded);
+
+    std::string html = MessagingUtil::getValueFromJSONObject<std::string>(data,
+            MESSAGE_BODY_ATTRIBUTE_HTML_BODY);
+    body->setHtmlBody(html);
+
+    std::string plain = MessagingUtil::getValueFromJSONObject<std::string>(data,
+            MESSAGE_BODY_ATTRIBUTE_PLAIN_BODY);
+    body->setPlainBody(plain);
+
+    if (!data.at(MESSAGE_BODY_ATTRIBUTE_MESSAGE_ID).is<picojson::null>()) {
+        int messageId = std::atoi(MessagingUtil::getValueFromJSONObject<std::string>(data,
+                    MESSAGE_BODY_ATTRIBUTE_MESSAGE_ID).c_str());
+        body->setMessageId(messageId);
+    }
+
+    AttachmentPtrVector inlineAttachments;
+    auto ma = data.at(MESSAGE_BODY_ATTRIBUTE_INLINE_ATTACHMENTS ).get<picojson::array>();
+
+    auto arrayVectorAttachmentConverter = [&inlineAttachments] (picojson::value& v)->void
+    {
+        inlineAttachments.push_back(jsonToMessageAttachment(v));
+    };
+
+    for_each(ma.begin(), ma.end(), arrayVectorAttachmentConverter);
+    body->setInlineAttachments(inlineAttachments);
+
+    return body;
+}
+
+std::shared_ptr<MessageFolder> MessagingUtil::jsonToMessageFolder(const picojson::value& json)
+{
+    LoggerD("Entered");
+
+    picojson::object data = json.get<picojson::object>();
+
+    std::string id = MessagingUtil::getValueFromJSONObject<std::string>(data,
+            MESSAGE_FOLDER_ATTRIBUTE_ID).c_str();
+
+    std::string parent_id = MessagingUtil::getValueFromJSONObject<std::string>(data,
+            MESSAGE_FOLDER_ATTRIBUTE_PARENT_ID).c_str();
+
+    std::string service_id = MessagingUtil::getValueFromJSONObject<std::string>(data,
+            MESSAGE_FOLDER_ATTRIBUTE_SERVICE_ID).c_str();
+
+    std::string content_type = MessagingUtil::getValueFromJSONObject<std::string>(data,
+            MESSAGE_FOLDER_ATTRIBUTE_CONTENT_TYPE).c_str();
+
+    std::string name = MessagingUtil::getValueFromJSONObject<std::string>(data,
+            MESSAGE_FOLDER_ATTRIBUTE_NAME).c_str();
+
+    std::string path = MessagingUtil::getValueFromJSONObject<std::string>(data,
+            MESSAGE_FOLDER_ATTRIBUTE_PATH).c_str();
+
+    std::string type_str = MessagingUtil::getValueFromJSONObject<std::string>(data,
+            MESSAGE_FOLDER_ATTRIBUTE_TYPE).c_str();
+    MessageFolderType type = MessagingUtil::stringToMessageFolderType(type_str);
+
+    bool synchronizable = MessagingUtil::getValueFromJSONObject<bool>(data,
+            MESSAGE_FOLDER_ATTRIBUTE_SYNCHRONIZABLE);
+
+    std::shared_ptr<MessageFolder> folder = std::shared_ptr<MessageFolder>(
+            new MessageFolder(
+                    id,
+                    parent_id,
+                    service_id,
+                    content_type,
+                    name,
+                    path,
+                    type,
+                    synchronizable));
+
+    return folder;
+}
+
+tizen::SortModePtr MessagingUtil::jsonToSortMode(const picojson::object& json)
+{
+    LoggerD("Entered");
+    using namespace tizen;
+
+    const auto it = json.find(JSON_TO_SORT);
+
+    if (json.end() == it || it->second.is<picojson::null>()) {
+      return SortModePtr();
+    }
+
+    auto dataSort = getValueFromJSONObject<picojson::object>(json, JSON_TO_SORT);
+    auto name = getValueFromJSONObject<std::string>(dataSort, JSON_TO_ATTRIBUTE_NAME);
+    auto ord = getValueFromJSONObject<std::string>(dataSort, JSON_TO_ORDER);
+    SortModeOrder order = ( ord == STR_SORT_DESC) ? SortModeOrder::DESC : SortModeOrder::ASC;
+    return SortModePtr(new SortMode(name, order));
+}
+
+PlatformResult MessagingUtil::jsonToAbstractFilter(const picojson::object& json,
+                                                   tizen::AbstractFilterPtr* result)
+{
+    LoggerD("Entered");
+
+    const auto it = json.find(JSON_TO_FILTER);
+
+    if (json.end() == it || it->second.is<picojson::null>()) {
+        *result = AbstractFilterPtr();
+        return PlatformResult(ErrorCode::NO_ERROR);
+    }
+
+    return jsonFilterToAbstractFilter(json.at(JSON_TO_FILTER).get<picojson::object>(), result);
+}
+
+PlatformResult MessagingUtil::jsonFilterToAbstractFilter(const picojson::object& filter,
+                                                         tizen::AbstractFilterPtr* result)
+{
+    LoggerD("Entered");
+    const auto& type = filter.at(JSON_FILTER_TYPE).get<std::string>();
+
+    if (JSON_FILTER_ATTRIBUTE_TYPE == type) {
+
+        return jsonFilterToAttributeFilter(filter, result);
+    }
+    if (JSON_FILTER_ATTRIBUTE_RANGE_TYPE == type) {
+        return jsonFilterToAttributeRangeFilter(filter, result);
+    }
+    if (JSON_FILTER_COMPOSITE_TYPE == type) {
+        return jsonFilterToCompositeFilter(filter, result);
+    }
+
+    LoggerE("Unsupported filter type: %s", type.c_str());
+    return PlatformResult(ErrorCode::TYPE_MISMATCH_ERR, "Unsupported filter type");
+}
+
+PlatformResult MessagingUtil::jsonFilterToAttributeFilter(const picojson::object& filter,
+                                                          tizen::AbstractFilterPtr* result)
+{
+    LoggerD("Entered");
+
+    using namespace tizen;
+
+    auto name = getValueFromJSONObject<std::string>(filter, JSON_TO_ATTRIBUTE_NAME);
+    auto matchFlagStr = getValueFromJSONObject<std::string>(filter, JSON_TO_MATCH_FLAG);
+
+    FilterMatchFlag filterMatch;
+
+    if (STR_MATCH_EXACTLY == matchFlagStr) {
+        filterMatch = FilterMatchFlag::EXACTLY;
+    }
+    else if (STR_MATCH_FULLSTRING == matchFlagStr) {
+        filterMatch = FilterMatchFlag::FULLSTRING;
+    }
+    else if (STR_MATCH_CONTAINS == matchFlagStr) {
+        filterMatch = FilterMatchFlag::CONTAINS;
+    }
+    else if (STR_MATCH_STARTSWITH == matchFlagStr) {
+        filterMatch = FilterMatchFlag::STARTSWITH;
+    }
+    else if (STR_MATCH_ENDSWITH == matchFlagStr) {
+        filterMatch = FilterMatchFlag::ENDSWITH;
+    }
+    else if (STR_MATCH_EXISTS == matchFlagStr) {
+        filterMatch = FilterMatchFlag::EXISTS;
+    }
+    else {
+        LoggerE("Filter name is not recognized: %s", matchFlagStr.c_str());
+        return PlatformResult(ErrorCode::TYPE_MISMATCH_ERR, "Filter name is not recognized");
+    }
+
+    auto attributePtr = new AttributeFilter(name);
+    attributePtr->setMatchFlag(filterMatch);
+    attributePtr->setMatchValue(AnyPtr(new Any(filter.at(JSON_TO_MATCH_VALUE))));
+    (*result).reset(attributePtr);
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult MessagingUtil::jsonFilterToAttributeRangeFilter(const picojson::object& filter,
+                                                       tizen::AbstractFilterPtr* result)
+{
+    LoggerD("Entered");
+
+    auto name = getValueFromJSONObject<std::string>(filter, JSON_TO_ATTRIBUTE_NAME);
+
+    auto attributeRangePtr = new tizen::AttributeRangeFilter(name);
+    attributeRangePtr->setInitialValue(AnyPtr(new Any(filter.at(JSON_TO_INITIAL_VALUE))));
+    attributeRangePtr->setEndValue(AnyPtr(new Any(filter.at(JSON_TO_END_VALUE))));
+
+    (*result).reset(attributeRangePtr);
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult MessagingUtil::jsonFilterToCompositeFilter(const picojson::object& filter,
+                                                          tizen::AbstractFilterPtr* result)
+{
+    LoggerD("Entered");
+
+    using namespace tizen;
+
+    const auto& type = filter.at(JSON_TO_TYPE).get<std::string>();
+
+    CompositeFilterType filterType = CompositeFilterType::UNION;
+
+    if (STR_FILTEROP_OR == type) {
+        filterType = CompositeFilterType::UNION;
+    }
+    else if (STR_FILTEROP_AND == type) {
+        filterType = CompositeFilterType::INTERSECTION;
+    }
+    else {
+        LoggerE("Composite filter type is not recognized: %s", type.c_str());
+        return PlatformResult(ErrorCode::TYPE_MISMATCH_ERR,
+                              "Composite filter type is not recognized");
+    }
+
+    auto compositeFilter = new CompositeFilter(filterType);
+
+    for (const auto& a : filter.at(JSON_TO_FILTER_ARRAY).get<picojson::array>()) {
+      AbstractFilterPtr filter;
+      PlatformResult ret = jsonFilterToAbstractFilter(a.get<picojson::object>(), &filter);
+      if (ret.IsError()) {
+          delete compositeFilter;
+          LoggerD("Convert JSON filter to Abstract filter failed (%s)", ret.message().c_str());
+          return ret;
+      }
+      compositeFilter->addFilter(filter);
+    }
+
+    (*result).reset(compositeFilter);
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+std::shared_ptr<MessageAttachment> MessagingUtil::jsonToMessageAttachment(const picojson::value& json)
+{
+    LoggerD("Entered");
+
+    picojson::object data = json.get<picojson::object>();
+    int attachmentId = std::atoi(getValueFromJSONObject<std::string>(data,
+            MESSAGE_ATTACHMENT_ATTRIBUTE_ID).c_str());
+    int messageId = std::atoi(getValueFromJSONObject<std::string>(data,
+            MESSAGE_ATTACHMENT_ATTRIBUTE_MESSAGE_ID).c_str());
+    std::string mimeType =
+            getValueFromJSONObject<std::string>(data, MESSAGE_ATTACHMENT_ATTRIBUTE_MIME_TYPE);
+    std::string filePath =
+            getValueFromJSONObject<std::string>(data, MESSAGE_ATTACHMENT_ATTRIBUTE_FILE_PATH);
+    auto attachmentPtr = std::shared_ptr<MessageAttachment>(new MessageAttachment());
+
+    attachmentPtr->setId(attachmentId);
+    attachmentPtr->setMessageId(messageId);
+    attachmentPtr->setMimeType(mimeType);
+    attachmentPtr->setFilePath(filePath);
+
+    return attachmentPtr;
+}
+
+picojson::value MessagingUtil::messageAttachmentToJson(std::shared_ptr<MessageAttachment> attachment)
+{
+    LoggerD("Entered");
+
+    picojson::object o;
+    o[MESSAGE_ATTACHMENT_ATTRIBUTE_ID] =
+            attachment->isIdSet()
+            ? picojson::value(std::to_string(attachment->getId()))
+            : picojson::value();
+
+    o[MESSAGE_ATTACHMENT_ATTRIBUTE_MESSAGE_ID] =
+            attachment->isMessageIdSet()
+            ? picojson::value(std::to_string(attachment->getMessageId()))
+            : picojson::value();
+
+    o[MESSAGE_ATTACHMENT_ATTRIBUTE_MIME_TYPE] =
+            attachment->isMimeTypeSet()
+            ? picojson::value(attachment->getMimeType())
+            : picojson::value();
+
+    o[MESSAGE_ATTACHMENT_ATTRIBUTE_FILE_PATH] =
+            attachment->isFilePathSet()
+            ? picojson::value(attachment->getFilePath())
+            : picojson::value();
+
+    return picojson::value(o);
+}
+
+PlatformResult MessagingUtil::jsonToMessageConversation(const picojson::value& json,
+                                        std::shared_ptr<MessageConversation>* result_conversation)
+{
+    LoggerD("Entered");
+    std::shared_ptr<MessageConversation> conversation;
+    picojson::object data = json.get<picojson::object>();
+    std::string type = data.at("type").get<std::string>();
+    MessageType mtype = UNDEFINED;
+    auto platform_result = MessagingUtil::stringToMessageType(type, &mtype);
+
+    if (!platform_result) return platform_result;
+
+    conversation = std::shared_ptr<MessageConversation>(new MessageConversation());
+
+    conversation->setType(mtype);
+
+    int id = std::atoi(MessagingUtil::getValueFromJSONObject<std::string>(data,
+        MESSAGE_CONVERSATION_ATTRIBUTE_ID).c_str());
+    conversation->setConversationId(id);
+
+    /// MESSAGE_CONVERSATION_ATTRIBUTE_TIMESTAMP ?
+
+    int messageCount = std::atoi(MessagingUtil::getValueFromJSONObject<std::string>(data,
+        MESSAGE_CONVERSATION_ATTRIBUTE_MESSAGE_COUNT).c_str());
+    conversation->setMessageCount(messageCount);
+
+    int unreadMessages = std::atoi(MessagingUtil::getValueFromJSONObject<std::string>(data,
+        MESSAGE_CONVERSATION_ATTRIBUTE_UNREAD_MESSAGES).c_str());
+    conversation->setUnreadMessages(unreadMessages);
+
+    std::string preview = MessagingUtil::getValueFromJSONObject<std::string>(data,
+        MESSAGE_CONVERSATION_ATTRIBUTE_PREVIEW);
+    conversation->setPreview(preview);
+
+    std::string subject = MessagingUtil::getValueFromJSONObject<std::string>(data,
+        MESSAGE_CONVERSATION_ATTRIBUTE_SUBJECT);
+    conversation->setSubject(subject);
+
+    /// MESSAGE_CONVERSATION_ATTRIBUTE_IS_READ ?
+
+    std::vector<std::string> result;
+    auto arrayVectorStringConverter = [&result] (picojson::value& v)->void {
+        result.push_back(v.get<std::string>());
+    };
+
+    std::string from = MessagingUtil::getValueFromJSONObject<std::string>(data,
+        MESSAGE_CONVERSATION_ATTRIBUTE_FROM);
+    conversation->setFrom(from);
+
+    auto toJS = MessagingUtil::getValueFromJSONObject<std::vector<picojson::value>>(
+        data, MESSAGE_CONVERSATION_ATTRIBUTE_TO);
+    for_each(toJS.begin(), toJS.end(), arrayVectorStringConverter);
+    conversation->setTo(result);
+    result.clear();
+
+    auto ccJS = MessagingUtil::getValueFromJSONObject<
+            std::vector<picojson::value>>(data, MESSAGE_ATTRIBUTE_CC);
+    for_each(ccJS.begin(), ccJS.end(), arrayVectorStringConverter);
+    conversation->setCC(result);
+    result.clear();
+
+    auto bccJS = MessagingUtil::getValueFromJSONObject<
+            std::vector<picojson::value>>(data, MESSAGE_ATTRIBUTE_BCC);
+    for_each(bccJS.begin(), bccJS.end(), arrayVectorStringConverter);
+    conversation->setBCC(result);
+    result.clear();
+
+    int lastMessageId = std::atoi(MessagingUtil::getValueFromJSONObject<std::string>(data,
+        MESSAGE_CONVERSATION_ATTRIBUTE_LAST_MESSAGE_ID).c_str());
+    conversation->setLastMessageId(lastMessageId);
+
+    *result_conversation = conversation;
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PostQueue::PostQueue(MessagingInstance& instance): instance_(instance)
+{
+    LoggerD("Entered: [%p]", this);
+}
+PostQueue::~PostQueue()
+{
+    LoggerD("Entered: [%p]", this);
+
+    EmailManager::getInstance().RemoveCallbacksByQueue(*this);
+}
+
+void PostQueue::addAndResolve(const long cid, PostPriority priority, const std::string &json)
+{
+    LoggerD("Entered");
+
+    std::shared_ptr<PostTask> t(new PostTask(priority));
+    t->attach(json);
+    tasks_mutex_.lock();
+    tasks_.push_back(std::make_pair(cid, t));
+    tasks_mutex_.unlock();
+
+    resolve(PostPriority::HIGH);
+
+    return;
+}
+
+void PostQueue::add(const long cid, PostPriority priority)
+{
+    LoggerD("Entered");
+
+    tasks_mutex_.lock();
+    tasks_.push_back(std::make_pair(cid, std::shared_ptr<PostTask>(new PostTask(priority))));
+    tasks_mutex_.unlock();
+
+    return;
+}
+
+void PostQueue::resolve(const long cid, const std::string &json)
+{
+    LoggerD("Entered: [%p]", this);
+
+    tasks_mutex_.lock();
+
+    TasksCollection::iterator i;
+    i = std::find_if(tasks_.begin(), tasks_.end(), [&cid] (TasksCollectionItem item)->bool {
+        return (cid == item.first);
+    });
+
+    if (tasks_.end() == i) {
+        LoggerD("Not found cid");
+        tasks_mutex_.unlock();
+        return;
+    }
+
+    i->second->attach(json);
+    tasks_mutex_.unlock();
+
+    resolve(PostPriority::HIGH);
+    return;
+}
+
+void PostQueue::resolve(PostPriority p)
+{
+    LoggerD("Entered: [%p]", this);
+
+    TasksCollection::iterator i;
+
+    tasks_mutex_.lock();
+    i = std::find_if(tasks_.begin(), tasks_.end(), [&p] (TasksCollectionItem item)->bool {
+        return (p == item.second->priority());
+    });
+
+    if (tasks_.end() == i) {
+        // not found
+        tasks_mutex_.unlock();
+
+        if (PostPriority::LAST != p) {
+            return resolve(static_cast<PostPriority>(p-1));
+        } else {
+            return;
+        }
+    }
+
+    if (TaskState::READY == i->second->state()) {
+        i->second->resolve();
+        std::string json = i->second->json();
+
+        i = tasks_.erase(i);
+        tasks_mutex_.unlock();
+
+        Instance::PostMessage(&instance_, json.c_str());
+    } else if (TaskState::NEW == i->second->state()) {
+        tasks_mutex_.unlock();
+
+        return;
+    } else if (TaskState::DONE == i->second->state()) {
+        i = tasks_.erase(i);
+        tasks_mutex_.unlock();
+    }
+
+    return resolve(static_cast<PostPriority>(p));
+}
+
+PostQueue::PostTask::PostTask()
+{
+    LoggerD("Entered");
+    priority_ = PostPriority::LOW;
+    state_ = TaskState::NEW;
+}
+PostQueue::PostTask::PostTask(PostPriority p)
+{
+    LoggerD("Entered");
+    priority_ = p;
+    state_ = TaskState::NEW;
+}
+PostQueue::PostTask::~PostTask()
+{
+    LoggerD("Entered");
+}
+
+void PostQueue::PostTask::attach(const std::string &j)
+{
+    LoggerD("Entered");
+    if (TaskState::DONE == state_) {
+        return;
+    }
+    json_ = j;
+    state_ = TaskState::READY;
+    return;
+}
+
+PostPriority PostQueue::PostTask::priority()
+{
+    return priority_;
+}
+
+PostQueue::TaskState PostQueue::PostTask::state()
+{
+    return state_;
+}
+
+std::string PostQueue::PostTask::json()
+{
+    return json_;
+}
+
+void PostQueue::PostTask::resolve()
+{
+    LoggerD("Entered");
+    if (TaskState::READY == state_) {
+        state_ = TaskState::DONE;
+    }
+    return;
+}
+
+
+} // messaging
+} // extension
diff --git a/webWidgetTCT_device/src/messaging/messaging_util.h b/webWidgetTCT_device/src/messaging/messaging_util.h
new file mode 100755 (executable)
index 0000000..cbd8bcd
--- /dev/null
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 2015 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 MESSAGING_MESSAGING_UTIL_H_
+#define MESSAGING_MESSAGING_UTIL_H_
+
+#include <string>
+#include <vector>
+#include <memory>
+#include <mutex>
+#include <map>
+#include <stdexcept>
+#include "common/logger.h"
+#include "common/picojson.h"
+#include "common/platform_result.h"
+
+#include "MsgCommon/SortMode.h"
+#include "MsgCommon/AttributeFilter.h"
+#include "MsgCommon/AbstractFilter.h"
+
+#include "message_folder.h"
+#include "message_attachment.h"
+#include "common/platform_result.h"
+
+namespace extension {
+namespace messaging {
+
+extern const char* JSON_ACTION;
+extern const char* JSON_CALLBACK_ID;
+extern const char* JSON_CALLBACK_SUCCCESS;
+extern const char* JSON_CALLBACK_ERROR;
+extern const char* JSON_CALLBACK_PROGRESS;
+extern const char* JSON_CALLBACK_KEEP;
+extern const char* JSON_DATA;
+extern const char* JSON_DATA_MESSAGE;
+extern const char* JSON_DATA_MESSAGE_BODY;
+extern const char* JSON_DATA_MESSAGE_ATTACHMENT;
+extern const char* JSON_DATA_RECIPIENTS;
+extern const char* JSON_ERROR_MESSAGE;
+extern const char* JSON_ERROR_NAME;
+extern const char* JSON_ERROR_CODE;
+
+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; // used also in dictionary
+extern const char* MESSAGE_ATTRIBUTE_CC; // used also in dictionary
+extern const char* MESSAGE_ATTRIBUTE_BCC; // used also in dictionary
+extern const char* MESSAGE_ATTRIBUTE_BODY;
+extern const char* MESSAGE_ATTRIBUTE_IS_READ;
+extern const char* MESSAGE_ATTRIBUTE_IS_HIGH_PRIORITY; // used also in dictionary
+extern const char* MESSAGE_ATTRIBUTE_SUBJECT; // used also in dictionary
+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;
+extern const char* MESSAGE_ATTRIBUTE_MESSAGE_BODY;
+extern const char* MESSAGE_ATTRIBUTE_MESSAGE_ATTACHMENT;
+
+extern const char* MESSAGE_BODY_ATTRIBUTE_MESSAGE_ID;
+extern const char* MESSAGE_BODY_ATTRIBUTE_LOADED;
+extern const char* MESSAGE_BODY_ATTRIBUTE_PLAIN_BODY;
+extern const char* MESSAGE_BODY_ATTRIBUTE_HTML_BODY;
+
+extern const char* MESSAGE_ATTRIBUTE_MESSAGE_ATTACHMENT;
+extern const char* MESSAGE_ATTACHMENT_ATTRIBUTE_ID;
+extern const char* MESSAGE_ATTACHMENT_ATTRIBUTE_MESSAGE_ID;
+extern const char* MESSAGE_ATTACHMENT_ATTRIBUTE_MIME_TYPE;
+extern const char* MESSAGE_ATTACHMENT_ATTRIBUTE_FILE_PATH;
+
+extern const char* MESSAGE_FOLDER_ATTRIBUTE_SERVICE_ID;
+
+extern const char* MESSAGE_CONVERSATION_ATTRIBUTE_ID;
+extern const char* MESSAGE_CONVERSATION_ATTRIBUTE_TYPE;
+extern const char* MESSAGE_CONVERSATION_ATTRIBUTE_TIMESTAMP;
+extern const char* MESSAGE_CONVERSATION_ATTRIBUTE_MESSAGE_COUNT;
+extern const char* MESSAGE_CONVERSATION_ATTRIBUTE_UNREAD_MESSAGES;
+extern const char* MESSAGE_CONVERSATION_ATTRIBUTE_PREVIEW;
+extern const char* MESSAGE_CONVERSATION_ATTRIBUTE_SUBJECT;
+extern const char* MESSAGE_CONVERSATION_ATTRIBUTE_IS_READ;
+extern const char* MESSAGE_CONVERSATION_ATTRIBUTE_FROM;
+extern const char* MESSAGE_CONVERSATION_ATTRIBUTE_TO;
+extern const char* MESSAGE_CONVERSATION_ATTRIBUTE_CC;
+extern const char* MESSAGE_CONVERSATION_ATTRIBUTE_BCC;
+extern const char* MESSAGE_CONVERSATION_ATTRIBUTE_LAST_MESSAGE_ID;
+
+enum MessageType {
+    UNDEFINED = 0,
+    SMS,
+    MMS,
+    EMAIL
+};
+
+enum MessageStatus {
+    STATUS_UNDEFINED = 0,
+    STATUS_DRAFT,
+    STATUS_SENDING,
+    STATUS_SENT,
+    STATUS_LOADED,
+    STATUS_FAILED
+};
+
+class Conversation;
+class MessageConversation;
+class Message;
+class MessageBody;
+class MessagingInstance;
+
+class MessagingUtil {
+public:
+    static std::string messageFolderTypeToString(MessageFolderType);
+    static MessageFolderType stringToMessageFolderType(std::string type);
+    static common::PlatformResult stringToMessageType(const std::string& str, MessageType* out);
+    static common::PlatformResult messageTypeToString(MessageType type, std::string* out);
+    static std::string messageTypeToString(MessageType type);
+    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);
+
+    static picojson::value messageBodyToJson(std::shared_ptr<MessageBody> body);
+    static picojson::value messageToJson(std::shared_ptr<Message> message);
+    static picojson::value messageAttachmentToJson(std::shared_ptr<MessageAttachment> attachment);
+    static picojson::value conversationToJson(std::shared_ptr<MessageConversation> conversation);
+    static picojson::value folderToJson(std::shared_ptr<MessageFolder> folder);
+    static common::PlatformResult jsonToMessage(const picojson::value& json,
+                                                std::shared_ptr<Message>* result);
+    static std::shared_ptr<MessageBody> jsonToMessageBody(const picojson::value& json);
+    static std::shared_ptr<MessageFolder> jsonToMessageFolder(const picojson::value& json);
+    static tizen::SortModePtr jsonToSortMode(const picojson::object& json);
+    static common::PlatformResult jsonToAbstractFilter(const picojson::object& json,
+                                                       tizen::AbstractFilterPtr* result);
+    static common::PlatformResult jsonToMessageConversation(const picojson::value& json,
+                                      std::shared_ptr<MessageConversation>* result_conversation);
+    static std::shared_ptr<MessageAttachment> jsonToMessageAttachment(const picojson::value& json);
+
+    template <class T>
+    static T getValueFromJSONObject(const picojson::object& v, const std::string& key)
+    {
+        picojson::value value;
+        try{
+            value = v.at(key);
+        } catch(const std::out_of_range& e){
+            return T();
+        }
+
+        if (value.is<T>()) {
+            return value.get<T>();
+        } else {
+            return T();
+        }
+    }
+    /**
+    * 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 common::PlatformResult loadFileContentToString(const std::string& file_path, std::string* result);
+    static std::string messageStatusToString(MessageStatus status);
+
+private:
+    static common::PlatformResult jsonFilterToAbstractFilter(const picojson::object& json,
+                                                         tizen::AbstractFilterPtr* result);
+    static common::PlatformResult jsonFilterToAttributeFilter(const picojson::object& json,
+                                                         tizen::AbstractFilterPtr* result);
+    static common::PlatformResult jsonFilterToAttributeRangeFilter(const picojson::object& json,
+                                                         tizen::AbstractFilterPtr* result);
+    static common::PlatformResult jsonFilterToCompositeFilter(const picojson::object& json,
+                                                         tizen::AbstractFilterPtr* result);
+
+    static std::string ConvertToUtf8(const std::string& file_path, const std::string& contents);
+};
+
+enum PostPriority {
+    LAST = 0,
+    LOW,
+    MEDIUM,
+    HIGH
+};
+
+class PostQueue {
+public:
+    explicit PostQueue(MessagingInstance& instance);
+    ~PostQueue();
+
+    void addAndResolve(const long cid, PostPriority priority, const std::string &json);
+    void add(const long cid, PostPriority priority = PostPriority::LAST);
+    void resolve(const long cid, const std::string &json);
+
+    enum TaskState {
+        NEW = 0,
+        READY,
+        DONE
+    };
+
+private:
+    class PostTask;
+    typedef std::pair<long, std::shared_ptr<PostTask>> TasksCollectionItem;
+    typedef std::vector<TasksCollectionItem> TasksCollection;
+
+    PostQueue(const PostQueue &);
+    void operator=(const PostQueue &);
+    void resolve(PostPriority p);
+    TasksCollection tasks_;
+    std::mutex tasks_mutex_;
+
+    MessagingInstance& instance_;
+
+    class PostTask {
+    public:
+        PostTask();
+        PostTask(PostPriority p);
+        ~PostTask();
+        void attach(const std::string &j);
+        PostPriority priority();
+        TaskState state();
+        std::string json();
+        void resolve();
+    private:
+        std::string json_;
+        PostPriority priority_;
+        TaskState state_;
+    };
+};
+
+} // messaging
+} // extension
+#endif // MESSAGING_MESSAGING_UTIL_H_
diff --git a/webWidgetTCT_device/src/messaging/short_message_manager.cc b/webWidgetTCT_device/src/messaging/short_message_manager.cc
new file mode 100755 (executable)
index 0000000..3d017d0
--- /dev/null
@@ -0,0 +1,1277 @@
+/*
+ * Copyright (c) 2015 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 <msg-service/msg.h>
+#include <msg_transport.h>
+#include <msg_storage.h>
+#include <unordered_set>
+
+#include "common/platform_exception.h"
+#include "common/logger.h"
+
+#include "messaging_util.h"
+#include "messaging_instance.h"
+#include "message_service.h"
+#include "message_sms.h"
+//#include "MessageMMS.h"
+//#include "JSMessageConversation.h"
+#include "messaging_database_manager.h"
+
+#include "short_message_manager.h"
+
+using common::ErrorCode;
+using common::PlatformResult;
+
+namespace extension {
+namespace messaging {
+
+ShortMsgManager& ShortMsgManager::getInstance()
+{
+    LoggerD("Entered");
+
+    static ShortMsgManager instance;
+    return instance;
+}
+
+static gboolean sendMessageCompleteCB(void* data)
+{
+    LoggerD("Entered callback:%p", data);
+
+    MessageRecipientsCallbackData* callback =
+            static_cast<MessageRecipientsCallbackData*>(data);
+    if (!callback) {
+        LoggerE("Callback is null");
+        return false;
+    }
+
+    if (callback->isError()) {
+      callback->getQueue().resolve(
+                callback->getJson()->get<picojson::object>().at(JSON_CALLBACK_ID).get<double>(),
+                callback->getJson()->serialize()
+        );
+        callback->getMessage()->setMessageStatus(MessageStatus::STATUS_FAILED);
+    }
+    else {
+        std::shared_ptr<Message> message = callback->getMessage();
+
+        LoggerD("Calling success callback with: %d recipients", message->getTO().size());
+
+        auto json = callback->getJson();
+        picojson::object& obj = json->get<picojson::object>();
+        obj[JSON_ACTION] = picojson::value(JSON_CALLBACK_SUCCCESS);
+
+        std::vector<picojson::value> recipients;
+        auto addToRecipients = [&recipients](std::string& e)->void {
+            recipients.push_back(picojson::value(e));
+        };
+
+        auto toVect = callback->getMessage()->getTO();
+        std::for_each(toVect.begin(), toVect.end(), addToRecipients);
+
+        picojson::object data;
+        data[JSON_DATA_RECIPIENTS] = picojson::value(recipients);
+        data[JSON_DATA_MESSAGE] = MessagingUtil::messageToJson(message);
+        obj[JSON_DATA] = picojson::value(data);
+
+        callback->getQueue().resolve(
+                obj.at(JSON_CALLBACK_ID).get<double>(),
+                json->serialize()
+        );
+        callback->getMessage()->setMessageStatus(MessageStatus::STATUS_SENT);
+    }
+
+    delete callback;
+    callback = NULL;
+
+    return false;
+}
+
+static gboolean addDraftMessageCompleteCB(void *data)
+{
+    LoggerD("Enter");
+    auto callback = static_cast<MessageCallbackUserData *>(data);
+    if (!callback) {
+        LoggerE("Callback is null");
+        return FALSE;
+    }
+
+    if (callback->isError()) {
+        LoggerD("Calling error callback");
+
+        callback->getQueue().resolve(
+                callback->getJson()->get<picojson::object>().at(JSON_CALLBACK_ID).get<double>(),
+                callback->getJson()->serialize()
+        );
+        callback->getMessage()->setMessageStatus(MessageStatus::STATUS_FAILED);
+    } else {
+        LoggerD("Calling success callback");
+
+        auto json = callback->getJson();
+        picojson::object& obj = json->get<picojson::object>();
+        obj[JSON_ACTION] = picojson::value(JSON_CALLBACK_SUCCCESS);
+
+        picojson::object args;
+        args[JSON_DATA_MESSAGE] = MessagingUtil::messageToJson(callback->getMessage());
+        obj[JSON_DATA] = picojson::value(args);
+
+        callback->getQueue().resolve(
+                obj.at(JSON_CALLBACK_ID).get<double>(),
+                json->serialize()
+        );
+    }
+
+    delete callback;
+    callback = NULL;
+
+    return FALSE;
+}
+
+
+PlatformResult ShortMsgManager::addDraftMessagePlatform(std::shared_ptr<Message> message)
+{
+    LoggerD("Add new message(%p)", message.get());
+
+    // Save platform msg to get ID
+    msg_struct_t platform_msg = nullptr;
+    PlatformResult ret = Message::convertPlatformShortMessageToStruct(message.get(),
+                                                                      m_msg_handle, &platform_msg);
+    if (ret.IsError()) {
+        LoggerD("Convert Platform Short Message to Struct failed (%s)", ret.message().c_str());
+        return ret;
+    }
+
+    if (NULL == platform_msg) {
+        LoggerE("Failed to prepare platform message");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Cannot prepare platform message");
+    }
+
+    msg_struct_t send_opt = msg_create_struct(MSG_STRUCT_SENDOPT);
+    msg_set_bool_value(send_opt, MSG_SEND_OPT_SETTING_BOOL, false);
+    const int msg_id = msg_add_message(m_msg_handle, platform_msg, send_opt);
+    if (msg_id < MSG_SUCCESS) {
+        LoggerE("Message(%p): Failed to add draft, error: %d", message.get(), msg_id);
+        msg_release_struct(&send_opt);
+        msg_release_struct(&platform_msg);
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Cannot add message to draft");
+    }
+
+    LoggerD("Message(%p): New message ID: %d", message.get(), msg_id);
+    msg_set_int_value(platform_msg, MSG_MESSAGE_ID_INT, msg_id);
+    message->setId(msg_id);
+    message->setMessageStatus(MessageStatus::STATUS_DRAFT);
+
+    msg_struct_t msg_conv = msg_create_struct(MSG_STRUCT_CONV_INFO);
+    msg_error_t err = msg_get_conversation(m_msg_handle, msg_id, msg_conv);
+    if (MSG_SUCCESS == err) {
+        int conversationId = 0;
+        msg_get_int_value(msg_conv, MSG_CONV_MSG_THREAD_ID_INT, &conversationId);
+        message->setConversationId(conversationId);
+    } else {
+        LoggerE("Message(%p): Failed to get conv", message.get());
+    }
+    Message* msgInfo = nullptr;
+    ret = Message::convertPlatformShortMessageToObject(
+        platform_msg, &msgInfo);
+    if (ret.IsError()) {
+        LoggerD("Convert Platform Short Message to Object failed (%s)", ret.message().c_str());
+        return ret;
+    }
+    const int folderId = msgInfo->getFolderId();
+    message->setFolderId(folderId);
+    const time_t timestamp = msgInfo->getTimestamp();
+    message->setTimeStamp(timestamp);
+
+    const std::string from = msgInfo->getFrom();
+    LoggerD("From: %s", from.c_str());
+    message->setFrom(from);
+
+    const bool isRead = msgInfo->getIsRead();
+    message->setIsRead(isRead);
+
+    const int inResponseTo = msgInfo->getInResponseTo();
+    message->setInResponseTo(inResponseTo);
+
+    if (msg_release_struct(&platform_msg) != MSG_SUCCESS) {
+        LoggerW("Platform message is already destroyed");
+    }
+    if (msg_release_struct(&msg_conv) != MSG_SUCCESS) {
+        LoggerW("Platform message is already destroyed");
+    }
+    if (msg_release_struct(&send_opt) != MSG_SUCCESS) {
+        LoggerW("Platform message is already destroyed");
+    }
+    delete msgInfo;
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult ShortMsgManager::SendMessagePlatform(MessageRecipientsCallbackData* callback)
+{
+  LoggerD("Entered");
+  std::lock_guard<std::mutex> lock(m_mutex);
+
+  PlatformResult platform_result(ErrorCode::NO_ERROR);
+  int msg_id;
+  Message* msgInfo = nullptr;
+  msg_struct_t platform_msg = nullptr;
+  msg_struct_t send_opt = nullptr;
+  msg_struct_t msg_conv = nullptr;
+  msg_struct_t req = nullptr;
+
+  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)) {
+    LoggerD("Add message to draft");
+    platform_result = addDraftMessagePlatform(message);
+
+  }
+  if(platform_result.IsSuccess()) {
+    msg_id = message->getId();
+    LoggerD("Message ID: %d", msg_id);
+
+    platform_msg = msg_create_struct(MSG_STRUCT_MESSAGE_INFO);
+    send_opt = msg_create_struct(MSG_STRUCT_SENDOPT);
+    msg_conv = msg_create_struct(MSG_STRUCT_CONV_INFO);
+    ret = msg_get_message(m_msg_handle, msg_id, platform_msg, send_opt);
+    if (MSG_SUCCESS != ret) {
+      LoggerE("Failed to get platform message structure: %d", ret);
+      platform_result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Cannot get platform Message structure");
+    } else {
+      // Send message
+      message->setMessageStatus(MessageStatus::STATUS_SENDING);
+      req = msg_create_struct(MSG_STRUCT_REQUEST_INFO);
+      msg_set_struct_handle(req, MSG_REQUEST_MESSAGE_HND, platform_msg);
+
+      int req_id = -1;
+      ret = msg_get_int_value(req, MSG_REQUEST_REQUESTID_INT, &req_id);
+      if (MSG_SUCCESS != ret) {
+        LoggerE("Failed to get send request ID: %d", ret);
+        platform_result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get send request ID");
+      } else {
+        if (MessageType::MMS == message->getType()) {
+          LoggerD("Send MMS message");
+          ret = msg_mms_send_message(m_msg_handle, req);
+        }
+        else if (MessageType::SMS == message->getType()) {
+          LoggerD("Send SMS message");
+          ret = msg_sms_send_message(m_msg_handle, req);
+        }
+        else {
+          LoggerE("Invalid message type: %d", message->getType());
+          platform_result = PlatformResult(ErrorCode::TYPE_MISMATCH_ERR, "Invalid message type");
+        }
+
+        if (platform_result) {
+          if (ret != MSG_SUCCESS) {
+            LoggerE("Failed to send message: %d", ret);
+            platform_result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to send message");
+          } else {
+            ret = msg_get_int_value(req, MSG_REQUEST_REQUESTID_INT, &req_id);
+            if (ret != MSG_SUCCESS) {
+              LoggerE("Failed to get message request ID: %d", ret);
+              platform_result = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get send request");
+            }
+            if (platform_result.IsSuccess()) {
+              LoggerD("req_id: %d", req_id);
+
+              platform_result = Message::convertPlatformShortMessageToObject(platform_msg, &msgInfo);
+              if (platform_result.IsSuccess()) {
+
+                int conversationId;
+                ret = msg_get_conversation(m_msg_handle, msg_id, msg_conv);
+                if (MSG_SUCCESS != ret) {
+                  LoggerE("Failed to get conv");
+                }
+                msg_get_int_value(msg_conv, MSG_CONV_MSG_THREAD_ID_INT,
+                                  &conversationId);
+                message->setConversationId(conversationId);
+
+                int folderId = msgInfo->getFolderId();
+                message->setFolderId(folderId);
+
+                time_t timestamp = msgInfo->getTimestamp();
+                message->setTimeStamp(timestamp);
+
+                std::string from = msgInfo->getFrom();
+                LoggerD("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;
+                LoggerD("Send MSG_SUCCESS");
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+
+  if (msg_release_struct(&req) != MSG_SUCCESS) {
+    LoggerW("Request structure is already destroyed");
+  }
+  if (msg_release_struct(&platform_msg) != MSG_SUCCESS) {
+    LoggerW("Platform message is already destroyed");
+  }
+  if (msg_release_struct(&send_opt) != MSG_SUCCESS) {
+    LoggerW("Platform message is already destroyed");
+  }
+  if (msg_release_struct(&msg_conv) != MSG_SUCCESS) {
+    LoggerW("Platform message is already destroyed");
+  }
+
+  delete msgInfo;
+
+  return platform_result;
+}
+
+PlatformResult ShortMsgManager::sendMessage(MessageRecipientsCallbackData* callback)
+{
+  LoggerD("Entered");
+
+  if (!callback){
+    LoggerE("Callback is null");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Callback is null");
+  }
+
+  PlatformResult platform_result(ErrorCode::NO_ERROR);
+
+  platform_result = SendMessagePlatform(callback);
+
+  if (!platform_result) {
+    LoggerE("Message send failed");
+
+    callback->setError(platform_result);
+
+    if (!g_idle_add(sendMessageCompleteCB, static_cast<void*>(callback))) {
+      LoggerE("g_idle addition failed");
+      delete callback;
+      callback = NULL;
+    }
+  }
+  return platform_result;
+}
+
+void ShortMsgManager::sendStatusCallback(msg_struct_t sent_status)
+{
+    LoggerD("Entered");
+    int reqId = 0;
+    int status = MSG_NETWORK_NOT_SEND;
+
+    msg_get_int_value(sent_status, MSG_SENT_STATUS_REQUESTID_INT, &reqId);
+    LoggerD("Send msg %d", reqId);
+    msg_get_int_value(sent_status, MSG_SENT_STATUS_NETWORK_STATUS_INT, &status);
+    LoggerD("Send msg status: %d", status);
+
+    if(MSG_NETWORK_SEND_SUCCESS != status
+        && MSG_NETWORK_SEND_FAIL != status
+        && MSG_NETWORK_SEND_TIMEOUT != status)
+    {
+        LoggerD("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()) {
+        LoggerD("Matching request found");
+
+        MessageRecipientsCallbackData* callback = it->second;
+        m_sendRequests.erase(it);
+
+        if (MSG_NETWORK_SEND_FAIL == status
+                || MSG_NETWORK_SEND_TIMEOUT == status) {
+            LoggerE("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"));
+
+            common::UnknownException e("Send message failed");
+            callback->setError(e.name(), e.message());
+        }
+
+        if (!g_idle_add(sendMessageCompleteCB, static_cast<void*>(callback))) {
+            LoggerE("g_idle addition failed");
+            delete callback;
+            callback = NULL;
+        }
+    }
+    else {
+        LoggerE("No matching request found");
+    }
+
+    return;
+}
+
+static void sent_status_cb(msg_handle_t handle,
+        msg_struct_t sent_status,
+        void *data)
+{
+    LoggerD("Entered");
+    ShortMsgManager::getInstance().sendStatusCallback(sent_status);
+
+    return;
+}
+
+PlatformResult ShortMsgManager::callProperEventMessages(EventMessages* event,
+        msg_storage_change_type_t storageChangeType)
+{
+    LoggerD("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 {
+        PlatformResult ret = ShortMsgManager::getConversationsForMessages(
+                event->items, storageChangeType, &(eventConv->items));
+        if (ret.IsError()) {
+          LoggerD("Error while getting conversations for message");
+          delete event;
+          delete eventConv;
+          return ret;
+        }
+    }
+
+    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);
+                    }
+
+                    LoggerD("%s conversation with id:%d last_msg_id:d",
+                            (new_conv ? "ADDED" : "UPDATED"),
+                            cur_conv->getConversationId(), cur_conv->getLastMessageId());
+                }
+
+                LoggerD("num conversations:all=%d added=%d update=%d", eventConv->items.size(),
+                        added_conv.size(), updated_conv.size());
+
+                if(false == added_conv.empty()) {
+                    LoggerD("%d new conversations, calling onConversationAdded",
+                            added_conv.size());
+                    eventConv->items = added_conv;
+                    ChangeListenerContainer::getInstance().callConversationAdded(
+                            eventConv);
+                }
+
+                if(false == updated_conv.empty()) {
+                    LoggerD("%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()) {
+                LoggerD("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:
+            LoggerW("Unknown storageChangeType: %d", storageChangeType);
+    }
+    delete event;
+    delete eventConv;
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+void ShortMsgManager::storage_change_cb(msg_handle_t handle,
+        msg_storage_change_type_t storageChangeType,
+        msg_id_list_s *pMsgIdList,
+        void* data)
+{
+    LoggerD("Entered handle:%p sChangeType:%d numMsgs:%d", handle, storageChangeType,
+            pMsgIdList->nCount);
+
+    if (MSG_STORAGE_CHANGE_CONTACT == storageChangeType) {
+        LoggerD("storageChangeType is MSG_STORAGE_CHANGE_CONTACT, ignoring");
+        return;
+    }
+
+    if (pMsgIdList->nCount < 1) {
+        LoggerW("no messages in callback list");
+        return;
+    }
+
+    LoggerD("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;
+
+    // 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];
+                LoggerD("pMsgIdList[%d] = %d", i, msg_id);
+
+                std::map<int, MessagePtr> ::iterator it = cur_rem_msgs.find(msg_id);
+                if(it != cur_rem_msgs.end()) {
+                    LoggerD("[%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()) {
+                        LoggerD("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 {
+                        LoggerW("Couldn't find ConversationPtr object with id:%d",
+                                cur_rem_conv_id);
+                    }
+                }
+            }
+        }
+
+    } else {
+        PlatformResult ret(ErrorCode::NO_ERROR);
+        for (int i = 0; i < pMsgIdList->nCount; ++i) {
+
+            msg_struct_t msg;
+            ret = ShortMsgManager::getInstance().getMessage(pMsgIdList->msgIdList[i], &msg);
+            if (ret.IsError() || NULL == msg) {
+                LoggerE("Failed to load short message");
+                delete eventSMS;
+                eventSMS = NULL;
+                delete eventMMS;
+                eventMMS = NULL;
+                return;
+            }
+            std::shared_ptr<Message> message;
+            Message* message_ptr = nullptr;
+            ret = Message::convertPlatformShortMessageToObject(msg, &message_ptr);
+            if (ret.IsError()) {
+                LoggerE("Failed to load short message");
+                msg_release_struct(&msg);
+                delete eventSMS;
+                eventSMS = NULL;
+                delete eventMMS;
+                eventMMS = NULL;
+                return;
+            }
+            message.reset(message_ptr);
+            msg_release_struct(&msg);
+            switch (message->getType()) {
+                case MessageType::SMS:
+                    eventSMS->items.push_back(message);
+                    break;
+                case MessageType::MMS:
+                    eventMMS->items.push_back(message);
+                    break;
+                default:
+                    LoggerE("Unsupported message type");
+                    delete eventSMS;
+                    eventSMS = NULL;
+                    delete eventMMS;
+                    eventMMS = NULL;
+                    return;
+            }
+        }
+    }
+
+    if (!eventSMS->items.empty() || !eventSMS->removed_conversations.empty()) {
+        PlatformResult ret = ShortMsgManager::callProperEventMessages(eventSMS, storageChangeType);
+        //PlatformResult could be ignored here. eventSMS is deleted in callProperEventMessages()
+    } else {
+        LoggerD("No SMS messages, not triggering eventSMS");
+        delete eventSMS;
+        eventSMS = NULL;
+    }
+    if (!eventMMS->items.empty() || !eventMMS->removed_conversations.empty()) {
+        PlatformResult ret = ShortMsgManager::callProperEventMessages(eventMMS, storageChangeType);
+        //PlatformResult could be ignored here. eventMMS is deleted in callProperEventMessages()
+    } else {
+        LoggerD("No MMS messages, not triggering eventMMS");
+        delete eventMMS;
+        eventMMS = NULL;
+    }
+}
+
+void ShortMsgManager::registerStatusCallback(msg_handle_t msg_handle)
+{
+    LoggerD("Entered");
+    m_msg_handle = msg_handle;
+    // set message sent status callback
+    if (MSG_SUCCESS != msg_reg_sent_status_callback(m_msg_handle,
+            &sent_status_cb, NULL)) {
+        LoggerE("sent status callback register error!!!");
+    }
+    if (MSG_SUCCESS != msg_reg_storage_change_callback(m_msg_handle,
+            &storage_change_cb, NULL)) {
+        LoggerE("storage change callback register error!");
+    }
+}
+
+void ShortMsgManager::addDraftMessage(MessageCallbackUserData* callback)
+{
+    LoggerD("Enter");
+
+    if(!callback){
+        LoggerE("Callback is null");
+        return;
+    }
+    {
+      std::lock_guard<std::mutex> lock(m_mutex);
+      std::shared_ptr<Message> message = callback->getMessage();
+
+      PlatformResult ret = addDraftMessagePlatform(message);
+      if (ret.IsError()) {
+        LoggerE("%d (%s)", ret.error_code(), ret.message().c_str());
+        callback->setError(ret);
+      }
+    }
+
+    // Complete task
+    if (!g_idle_add(addDraftMessageCompleteCB, static_cast<void *>(callback))) {
+        LoggerE("g_idle addition failed");
+        delete callback;
+        callback = NULL;
+    }
+}
+
+void ShortMsgManager::removeMessages(MessagesCallbackUserData* callback)
+{
+    LoggerD("Entered");
+
+    if (!callback){
+        LoggerE("Callback is null");
+        return;
+    }
+
+    std::vector<std::shared_ptr<Message>> messages;
+
+    {
+        std::lock_guard<std::mutex> lock(m_mutex);
+        messages = callback->getMessages();
+        MessageType type = callback->getMessageServiceType();
+        for(auto it = messages.begin() ; it != messages.end(); ++it) {
+            if((*it)->getType() != type) {
+                LoggerE("Invalid message type: %d", (*it)->getType());
+                callback->SetError(PlatformResult(ErrorCode::TYPE_MISMATCH_ERR, "Error while deleting message"));
+                break;
+            }
+        }
+
+        if (!callback->isError()) {
+            for (auto it = messages.begin() ; it != messages.end(); ++it) {
+                const int id = (*it)->getId();
+
+                //Store message object
+                LoggerD("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:
+                        LoggerD("Unknown message type: %d", (*it)->getType());
+                        break;
+                }
+
+               int error = msg_delete_message(m_msg_handle, id);
+                if (MSG_SUCCESS != error) {
+                    LoggerE("Error while deleting message");
+                    callback->SetError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Error while deleting message"));
+                    break;
+                }
+            }
+        }
+    }
+
+    if (callback->isError()) {
+        LoggerD("Calling error callback");
+        callback->getQueue().resolve(
+                callback->getJson()->get<picojson::object>().at(JSON_CALLBACK_ID).get<double>(),
+                callback->getJson()->serialize()
+        );
+    } else {
+        LoggerD("Calling success callback");
+
+        auto json = callback->getJson();
+        picojson::object& obj = json->get<picojson::object>();
+        obj[JSON_ACTION] = picojson::value(JSON_CALLBACK_SUCCCESS);
+
+        callback->getQueue().resolve(
+                obj.at(JSON_CALLBACK_ID).get<double>(),
+                json->serialize()
+        );
+    }
+
+    delete callback;
+    callback = NULL;
+}
+
+void ShortMsgManager::updateMessages(MessagesCallbackUserData* callback)
+{
+    LoggerD("Entered");
+
+    if (!callback){
+        LoggerE("Callback is null");
+        return;
+    }
+
+    LoggerD("messages to update: %d", callback->getMessages().size());
+
+    {
+        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) {
+                LoggerE("Invalid message type");
+                callback->SetError(PlatformResult(ErrorCode::TYPE_MISMATCH_ERR, "Error while updating message"));
+                break;
+            }
+        }
+        if (!callback->isError()) {
+            for (auto it = messages.begin() ; it != messages.end(); ++it) {
+                LoggerD("updating Message(%p) msg_id:%d", (*it).get(), (*it)->getId());
+
+                msg_struct_t platform_msg = nullptr;
+                PlatformResult ret = Message::convertPlatformShortMessageToStruct(it->get(), m_msg_handle, &platform_msg);
+                if (ret.IsError()) {
+                    LoggerE("%s", ret.message().c_str());
+                    callback->SetError(ret);
+                    break;
+                }
+                if (NULL == platform_msg) {
+                    LoggerE("Failed to prepare platform message");
+                    callback->SetError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Cannot prepare platform message"));
+                    break;
+                }
+                msg_struct_t sendOpt = msg_create_struct(MSG_STRUCT_SENDOPT);
+                int error = msg_update_message(m_msg_handle, platform_msg, sendOpt);
+                msg_release_struct(&platform_msg);
+                msg_release_struct(&sendOpt);
+                if (error != MSG_SUCCESS) {
+                    LoggerE("Failed to update message %d", (*it)->getId());
+                    callback->SetError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Error while updating message"));
+                    break;
+                }
+            }
+        }
+    }
+
+    if (callback->isError()) {
+        LoggerD("Calling error callback");
+
+        callback->getQueue().resolve(
+                callback->getJson()->get<picojson::object>().at(JSON_CALLBACK_ID).get<double>(),
+                callback->getJson()->serialize()
+        );
+    } else {
+        LoggerD("Calling success callback");
+
+        auto json = callback->getJson();
+        picojson::object& obj = json->get<picojson::object>();
+
+        auto messages = callback->getMessages();
+        picojson::array array;
+        auto each = [&array] (std::shared_ptr<Message> m)->void {
+            array.push_back(MessagingUtil::messageToJson(m));
+        };
+
+        for_each(messages.begin(), messages.end(), each);
+
+        obj[JSON_DATA] = picojson::value(array);
+
+        obj[JSON_ACTION] = picojson::value(JSON_CALLBACK_SUCCCESS);
+
+        callback->getQueue().resolve(
+                obj.at(JSON_CALLBACK_ID).get<double>(),
+                json->serialize()
+        );
+    }
+
+    delete callback;
+    callback = NULL;
+}
+
+PlatformResult ShortMsgManager::getMessage(int msg_id, msg_struct_t* out_msg)
+{
+    LoggerD("Entered");
+    msg_struct_t sendOpt = msg_create_struct(MSG_STRUCT_SENDOPT);
+    msg_struct_t msg = msg_create_struct(MSG_STRUCT_MESSAGE_INFO);
+
+    int error = msg_get_message(m_msg_handle, msg_id, msg, sendOpt);
+    if (MSG_SUCCESS != error) {
+        LoggerE("Couldn't retrieve message from service, msgId: %d, error:%d", msg_id, error);
+        msg_release_struct(&sendOpt);
+        msg_release_struct(&msg);
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Couldn't retrieve message from service");
+    }
+    msg_release_struct(&sendOpt);
+    *out_msg = msg;
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult ShortMsgManager::getConversationsForMessages(
+        MessagePtrVector messages,
+        msg_storage_change_type_t storageChangeType, ConversationPtrVector* result)
+{
+    LoggerD("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);
+        LoggerD("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;
+            PlatformResult ret = MessageConversation::convertMsgConversationToObject(
+                    conv_id, ShortMsgManager::getInstance().m_msg_handle, &conv);
+            if (ret.IsError()) {
+                LoggerD("Convert msg conversation to object failed (%s)", ret.message().c_str());
+                return ret;
+            }
+            LoggerD("Pushed conv=%p", conv.get());
+            convs.push_back(conv);
+        }
+    }
+    *result = convs;
+    return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+void ShortMsgManager::findMessages(FindMsgCallbackUserData* callback)
+{
+    LoggerD("Entered");
+
+    if(!callback){
+        LoggerE("Callback is null");
+        return;
+    }
+
+    {
+        std::lock_guard<std::mutex> lock(m_mutex);
+        std::vector<int> messagesIds;
+        PlatformResult ret = MessagingDatabaseManager::getInstance().findShortMessages(callback, &messagesIds);
+        if (ret.IsError()) {
+            LoggerE("Failed to find short message: %s (%d)", ret.message().c_str(), ret.error_code());
+            callback->SetError(ret);
+        }
+
+        if (!callback->isError()) {
+            int msgListCount = messagesIds.size();
+            LoggerD("Found %d messages", msgListCount);
+
+            msg_struct_t msg;
+            msg_struct_t send_opt;
+            msg_error_t err;
+            for (int i = 0; i < msgListCount; i++) {
+                msg = msg_create_struct(MSG_STRUCT_MESSAGE_INFO);
+                send_opt = msg_create_struct(MSG_STRUCT_SENDOPT);
+                std::unique_ptr<msg_struct_t, int (*)(msg_struct_t*)> msg_ptr(&msg, msg_release_struct);
+                std::unique_ptr<msg_struct_t, int (*)(msg_struct_t*)> send_opt_ptr(&send_opt, msg_release_struct);
+
+                err = msg_get_message(m_msg_handle, messagesIds.at(i), msg, send_opt);
+
+                if (MSG_SUCCESS != err) {
+                    LoggerE("Failed to get platform message structure: %d", err);
+                    callback->SetError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Cannot get platform Message structure"));
+                    break;
+                }
+
+                Message* message = nullptr;
+                PlatformResult ret = Message::convertPlatformShortMessageToObject(msg, &message);
+                if (ret.IsError()) {
+                    if (ErrorCode::INVALID_VALUES_ERR == ret.error_code()) {
+                      LoggerW("Ignore messages with not supported/unrecognized type");
+                      continue;
+                    }
+                    LoggerE("Cannot get platform Message structure");
+                    callback->SetError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Cannot get platform Message structure"));
+                    break;
+                }
+                if (!callback->isError()) {
+                    callback->addMessage(std::shared_ptr<Message>{message});
+                    LoggerD("Created message with id %d:", messagesIds[i]);
+                }
+            }
+        }
+    }
+
+    if (callback->isError()) {
+        LoggerD("Calling error callback");
+        callback->getQueue().resolve(
+                callback->getJson()->get<picojson::object>().at(JSON_CALLBACK_ID).get<double>(),
+                callback->getJson()->serialize()
+        );
+    } else {
+        LoggerD("Calling success callback with %d messages:",
+                callback->getMessages().size());
+
+        auto json = callback->getJson();
+        picojson::object& obj = json->get<picojson::object>();
+
+        std::vector<picojson::value> response;
+        auto messages = callback->getMessages();
+        std::for_each(messages.begin(), messages.end(), [&response](MessagePtr &message){
+            response.push_back(MessagingUtil::messageToJson(message));
+        });
+
+        obj[JSON_DATA] = picojson::value(response);
+        obj[JSON_ACTION] = picojson::value(JSON_CALLBACK_SUCCCESS);
+
+        callback->getQueue().resolve(
+                obj.at(JSON_CALLBACK_ID).get<double>(),
+                json->serialize()
+        );
+    }
+
+    delete callback;
+    callback = NULL;
+}
+
+void ShortMsgManager::findConversations(ConversationCallbackData* callback)
+{
+    LoggerD("Entered");
+
+    if(!callback){
+        LoggerE("Callback is null");
+        return;
+    }
+
+    {
+        std::lock_guard<std::mutex> lock(m_mutex);
+        std::vector<int> conversationsIds;
+        PlatformResult ret = MessagingDatabaseManager::getInstance().
+            findShortMessageConversations(callback, &conversationsIds);
+        if (ret.IsError()) {
+            LoggerE("Cannot get platform Message structure");
+            callback->SetError(ret);
+        }
+
+        if (!callback->isError()) {
+            int convListCount = conversationsIds.size();
+            LoggerD("Found %d conversations", convListCount);
+
+            for (int i = 0; i < convListCount; i++) {
+                std::shared_ptr<MessageConversation> conversation;
+                PlatformResult ret = MessageConversation::convertMsgConversationToObject(
+                                conversationsIds.at(i), m_msg_handle, &conversation);
+                if (ret.IsSuccess()) {
+                  callback->addConversation(conversation);
+                } else {
+                  callback->SetError(ret);
+                }
+            }
+        }
+    }
+
+    if (callback->isError()) {
+        LoggerD("Calling error callback");
+        callback->getQueue().resolve(
+                callback->getJson()->get<picojson::object>().at(JSON_CALLBACK_ID).get<double>(),
+                callback->getJson()->serialize()
+        );
+    } else {
+        LoggerD("Calling success callback");
+        auto json = callback->getJson();
+        picojson::object& obj = json->get<picojson::object>();
+
+        std::vector<picojson::value> response;
+        auto conversations = callback->getConversations();
+        std::for_each(conversations.begin(), conversations.end(),
+                [&response](std::shared_ptr<MessageConversation> &conversation) {
+                    response.push_back(MessagingUtil::conversationToJson(conversation));
+                }
+        );
+        obj[JSON_DATA] = picojson::value(response);
+        obj[JSON_ACTION] = picojson::value(JSON_CALLBACK_SUCCCESS);
+
+        callback->getQueue().resolve(
+                obj.at(JSON_CALLBACK_ID).get<double>(),
+                json->serialize()
+        );
+    }
+
+    delete callback;
+    callback = NULL;
+}
+
+void ShortMsgManager::removeConversations(ConversationCallbackData* callback)
+{
+    LoggerD("Entered");
+
+    if (!callback){
+        LoggerE("Callback is null");
+        return;
+    }
+
+    int error = MSG_SUCCESS;
+    msg_handle_t handle = NULL;
+
+    {
+        std::lock_guard<std::mutex> lock(m_mutex);
+        ConversationPtrVector conversations = callback->getConversations();
+        const MessageType type = callback->getMessageServiceType();
+
+        std::map<int, int>* msg_id_conv_id_map = NULL;
+        std::map<int, ConversationPtr>* conv_id_object_map = NULL;
+
+        error = msg_open_msg_handle(&handle);
+        if (MSG_SUCCESS != error) {
+            LoggerE("Open message handle error: %d", error);
+            callback->SetError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Error while creatng message handle"));
+        }
+
+        if (!callback->isError()) {
+          for(auto it = conversations.begin() ; it != conversations.end(); ++it) {
+              if((*it)->getType() != type) {
+                  LoggerE("Invalid message type");
+                  callback->SetError(PlatformResult(ErrorCode::TYPE_MISMATCH_ERR,
+                                     "Error while deleting message conversation"));
+                  break;
+              }
+          }
+        }
+
+        if (!callback->isError()) {
+            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 {
+                LoggerE("Invalid message type:%d for ShortMsgManager!", type);
+                callback->SetError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Invalid message type for ShortMsgManager!"));
+            }
+        }
+
+        if (!callback->isError()) {
+            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();
+
+                LoggerD("[%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;
+
+                            LoggerD("[%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 {
+                            LoggerE("[%d] Couldn't get msg_id, error: %d!", error);
+                        }
+                    }
+                } else {
+                    LoggerE("[%d] Couldn' get conversation view list for conv_id:%d error: %d",
+                            conv_index, conv_id, error);
+                }
+
+                msg_release_list_struct(&conv_view_list);
+
+                error = msg_delete_thread_message_list(handle, (msg_thread_id_t) conv_id,
+                        FALSE);
+                if (MSG_SUCCESS != error) {
+                    LoggerE("Error while deleting message conversation");
+                    callback->SetError(PlatformResult(ErrorCode::UNKNOWN_ERR,
+                                                      "Error while deleting message conversation"));
+                    break;
+                }
+            }
+        }
+    }
+
+    if (!callback->isError()) {
+        error = msg_close_msg_handle(&handle);
+        if (MSG_SUCCESS != error) {
+            LoggerW("Cannot close message handle: %d", error);
+        }
+    }
+
+    if (callback->isError()) {
+        LoggerD("Calling error callback");
+        callback->getQueue().resolve(
+                callback->getJson()->get<picojson::object>().at(JSON_CALLBACK_ID).get<double>(),
+                callback->getJson()->serialize()
+        );
+    } else {
+        LoggerD("Calling success callback");
+
+        auto json = callback->getJson();
+        picojson::object& obj = json->get<picojson::object>();
+        obj[JSON_ACTION] = picojson::value(JSON_CALLBACK_SUCCCESS);
+
+        callback->getQueue().resolve(
+                obj.at(JSON_CALLBACK_ID).get<double>(),
+                json->serialize()
+        );
+    }
+
+    delete callback;
+    callback = NULL;
+}
+
+ShortMsgManager::ShortMsgManager() : m_msg_handle(NULL)
+{
+    LoggerD("Entered");
+}
+
+ShortMsgManager::~ShortMsgManager()
+{
+    LoggerD("Entered");
+    LoggerD("m_sms_removed_messages.size() = %d",
+            m_sms_removed_messages.size());
+    LoggerD("m_mms_removed_messages.size() = %d",
+            m_mms_removed_messages.size());
+    LoggerD("m_sms_removed_msg_id_conv_id_map.size() = %d",
+            m_sms_removed_msg_id_conv_id_map.size());
+    LoggerD("m_sms_removed_conv_id_object_map.size() = %d",
+            m_sms_removed_conv_id_object_map.size());
+    LoggerD("m_mms_removed_msg_id_conv_id_map.size() = %d",
+            m_mms_removed_msg_id_conv_id_map.size());
+    LoggerD("m_mms_removed_conv_id_object_map.size() = %d",
+            m_mms_removed_conv_id_object_map.size());
+}
+
+} // messaging
+} // extension
diff --git a/webWidgetTCT_device/src/messaging/short_message_manager.h b/webWidgetTCT_device/src/messaging/short_message_manager.h
new file mode 100755 (executable)
index 0000000..2c20695
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2015 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 __MESSAGING_SEND_SHORT_MSG_MANAGER_H__
+#define __MESSAGING_SEND_SHORT_MSG_MANAGER_H__
+
+#include <glib.h>
+#include <mutex>
+#include <map>
+
+#include <msg_storage_types.h>
+#include <msg_types.h>
+
+//#include <CallbackUserData.h>
+
+#include "common/platform_result.h"
+#include "change_listener_container.h"
+#include "messaging_util.h"
+#include "message_service.h"
+#include "message_sms.h"
+#include "message_conversation.h"
+
+namespace extension {
+namespace messaging {
+
+class FindMsgCallbackUserData;
+
+class ShortMsgManager {
+public:
+    static ShortMsgManager& getInstance();
+
+    common::PlatformResult 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);
+    common::PlatformResult getMessage(int msg_id, msg_struct_t* out_msg);
+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);
+
+    common::PlatformResult addDraftMessagePlatform(std::shared_ptr<Message> message);
+    common::PlatformResult SendMessagePlatform(MessageRecipientsCallbackData* callback);
+    /**
+     * 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 common::PlatformResult getConversationsForMessages(
+            MessagePtrVector messages,
+            msg_storage_change_type_t storageChangeType, ConversationPtrVector* result);
+    static common::PlatformResult 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
+} // extension
+#endif // __MESSAGING_SEND_SHORT_MSG_MANAGER_H__
diff --git a/webWidgetTCT_device/src/networkbearerselection/networkbearerselection.gyp b/webWidgetTCT_device/src/networkbearerselection/networkbearerselection.gyp
new file mode 100755 (executable)
index 0000000..f441d57
--- /dev/null
@@ -0,0 +1,34 @@
+{
+  'includes':[
+    '../common/common.gypi',
+  ],
+  'targets': [
+    {
+      'target_name': 'tizen_networkbearerselection',
+      'type': 'loadable_module',
+      'dependencies': [
+        '../common/common.gyp:tizen_common',
+      ],
+      'variables': {
+        'packages': [
+          'icu-i18n',
+          'capi-network-connection',
+        ],
+      },
+      'sources': [
+        'networkbearerselection_api.js',
+        'networkbearerselection_extension.cc',
+        'networkbearerselection_extension.h',
+        'networkbearerselection_instance.cc',
+        'networkbearerselection_instance.h',
+        'networkbearerselection_manager.cc',
+        'networkbearerselection_manager.h',
+      ],
+      'conditions': [
+        [ 'tizen == 1', {
+            'variables': { 'packages': ['vconf'] },
+        }],
+      ],
+    },
+  ],
+}
diff --git a/webWidgetTCT_device/src/networkbearerselection/networkbearerselection_api.js b/webWidgetTCT_device/src/networkbearerselection/networkbearerselection_api.js
new file mode 100755 (executable)
index 0000000..7aec196
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+var utils_ = xwalk.utils;
+var type_ = utils_.type;
+var converter_ = utils_.converter;
+var validator_ = utils_.validator;
+var types_ = validator_.Types;
+var native_ = new xwalk.utils.NativeManager(extension);
+
+
+var NetworkType = {
+  CELLULAR: 'CELLULAR',
+  UNKNOWN: 'UNKNOWN'
+};
+
+var callbackId = 0;
+var callbacks = {};
+
+function nextCallbackId() {
+  return callbackId++;
+}
+
+function _networkBearerSelectionCallback(result) {
+  var id, callback;
+
+  for (id in callbacks) {
+    if (callbacks.hasOwnProperty(result.id)) {
+      callback = callbacks[id];
+      if (result.state === 'Success') {
+        native_.callIfPossible(callback.onsuccess);
+      }
+      if (result.state === 'Disconnected') {
+        native_.callIfPossible(callback.ondisconnected);
+        native_.removeListener('NetworkBearerSelectionCallback_' + id);
+        delete callbacks[id];
+      }
+      if (result.state === 'Error') {
+        native_.callIfPossible(callback.onerror, native_.getErrorObject(result));
+        native_.removeListener('NetworkBearerSelectionCallback_' + id);
+        delete callbacks[id];
+      }
+    }
+  }
+}
+
+function NetworkBearerSelection() {}
+
+NetworkBearerSelection.prototype.requestRouteToHost = function(networkType, domainName, successCallback, errorCallback) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.NETWORKBEARERSELECTION);
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.INTERNET);
+
+  var args = validator_.validateArgs(arguments, [
+    {name: 'networkType', type: types_.ENUM, values: Object.keys(NetworkType)},
+    {name: 'domainName', type: types_.STRING},
+    {name: 'successCallback', type: types_.LISTENER, values: ['onsuccess', 'ondisconnected']},
+    {name: 'errorCallback', type: types_.FUNCTION, optional: true, nullable: true}
+  ]);
+
+  var id = nextCallbackId();
+
+  var nativeParam = {
+    networkType: args.networkType,
+    domainName: args.domainName,
+    id: id
+  };
+
+  callbacks[id] = {
+    onsuccess: args.successCallback.onsuccess,
+    ondisconnected: args.successCallback.ondisconnected,
+    onerror: args.errorCallback
+  };
+
+  native_.addListener('NetworkBearerSelectionCallback_' + id, _networkBearerSelectionCallback);
+  var result = native_.callSync('NetworkBearerSelection_requestRouteToHost', nativeParam);
+
+  if (native_.isFailure(result)) {
+    native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+  }
+};
+
+NetworkBearerSelection.prototype.releaseRouteToHost = function(networkType, domainName, successCallback, errorCallback) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.NETWORKBEARERSELECTION);
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.INTERNET);
+
+  var args = validator_.validateArgs(arguments, [
+    {name: 'networkType', type: types_.ENUM, values: Object.keys(NetworkType)},
+    {name: 'domainName', type: types_.STRING},
+    {name: 'successCallback', type: types_.FUNCTION},
+    {name: 'errorCallback', type: types_.FUNCTION, optional: true, nullable: true}
+  ]);
+
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+      return;
+    }
+
+    native_.callIfPossible(args.successCallback);
+  };
+
+  native_.call('NetworkBearerSelection_releaseRouteToHost', args, callback);
+};
+
+
+exports = new NetworkBearerSelection();
diff --git a/webWidgetTCT_device/src/networkbearerselection/networkbearerselection_extension.cc b/webWidgetTCT_device/src/networkbearerselection/networkbearerselection_extension.cc
new file mode 100755 (executable)
index 0000000..119e269
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2015 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 "networkbearerselection/networkbearerselection_extension.h"
+
+#include "networkbearerselection/networkbearerselection_instance.h"
+
+// This will be generated from networkbearerselection_api.js
+extern const char kSource_networkbearerselection_api[];
+
+common::Extension* CreateExtension() {
+  return new NetworkBearerSelectionExtension;
+}
+
+NetworkBearerSelectionExtension::NetworkBearerSelectionExtension() {
+  SetExtensionName("tizen.networkbearerselection");
+  SetJavaScriptAPI(kSource_networkbearerselection_api);
+}
+
+NetworkBearerSelectionExtension::~NetworkBearerSelectionExtension() {}
+
+common::Instance* NetworkBearerSelectionExtension::CreateInstance() {
+  return new extension::networkbearerselection::NetworkBearerSelectionInstance;
+}
diff --git a/webWidgetTCT_device/src/networkbearerselection/networkbearerselection_extension.h b/webWidgetTCT_device/src/networkbearerselection/networkbearerselection_extension.h
new file mode 100755 (executable)
index 0000000..b1c81a0
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2015 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 NETWORKBEARERSELECTION_NETWORKBEARERSELECTION_EXTENSION_H_
+#define NETWORKBEARERSELECTION_NETWORKBEARERSELECTION_EXTENSION_H_
+
+#include "common/extension.h"
+
+class NetworkBearerSelectionExtension : public common::Extension {
+ public:
+  NetworkBearerSelectionExtension();
+  virtual ~NetworkBearerSelectionExtension();
+
+ private:
+  virtual common::Instance* CreateInstance();
+};
+
+#endif  // NETWORKBEARERSELECTION_NETWORKBEARERSELECTION_EXTENSION_H_
diff --git a/webWidgetTCT_device/src/networkbearerselection/networkbearerselection_instance.cc b/webWidgetTCT_device/src/networkbearerselection/networkbearerselection_instance.cc
new file mode 100755 (executable)
index 0000000..fa334ce
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2015 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 "networkbearerselection/networkbearerselection_instance.h"
+
+#include <functional>
+
+#include "common/picojson.h"
+#include "common/logger.h"
+#include "common/platform_exception.h"
+#include "common/task-queue.h"
+
+namespace extension {
+namespace networkbearerselection {
+
+using namespace common;
+using namespace extension::networkbearerselection;
+
+NetworkBearerSelectionInstance::NetworkBearerSelectionInstance() {
+  LoggerD("Enter");
+  using std::placeholders::_1;
+  using std::placeholders::_2;
+
+#define REGISTER_SYNC(c, x) \
+  RegisterSyncHandler(      \
+      c, std::bind(&NetworkBearerSelectionInstance::x, this, _1, _2));
+#define REGISTER_ASYNC(c, x) \
+  RegisterSyncHandler(           \
+      c, std::bind(&NetworkBearerSelectionInstance::x, this, _1, _2));
+  REGISTER_SYNC("NetworkBearerSelection_requestRouteToHost",
+                NetworkBearerSelectionRequestRouteToHost);
+  REGISTER_ASYNC("NetworkBearerSelection_releaseRouteToHost",
+                 NetworkBearerSelectionReleaseRouteToHost);
+#undef REGISTER_SYNC
+#undef REGISTER_ASYNC
+
+  NetworkBearerSelectionManager::GetInstance()->AddListener(this);
+}
+
+NetworkBearerSelectionInstance::~NetworkBearerSelectionInstance() {
+  LoggerD("Enter");
+  NetworkBearerSelectionManager::GetInstance()->RemoveListener(this);
+}
+
+#define CHECK_EXIST(args, name, out)                                       \
+  if (!args.contains(name)) {                                              \
+    ReportError(TypeMismatchException(name " is required argument"), out); \
+    return;                                                                \
+  }
+
+void NetworkBearerSelectionInstance::NetworkBearerSelectionRequestRouteToHost(
+    const picojson::value& args,
+    picojson::object& out) {
+  LoggerD("enter");
+
+  CHECK_EXIST(args, "domainName", out)
+  CHECK_EXIST(args, "id", out)
+
+  const std::string& domainName = args.get("domainName").get<std::string>();
+  const int listenerId = static_cast<int>(args.get("id").get<double>());
+
+  auto get = [=]()->void {
+    NetworkBearerSelectionManager::GetInstance()->requestRouteToHost(
+        domainName);
+  };
+
+  listenerMap.insert(std::make_pair(domainName, listenerId));
+
+  common::TaskQueue::GetInstance().Async(get);
+  ReportSuccess(out);
+}
+
+void NetworkBearerSelectionInstance::NetworkBearerSelectionReleaseRouteToHost(
+    const picojson::value& args,
+    picojson::object& out) {
+  LoggerD("enter");
+
+  CHECK_EXIST(args, "callbackId", out)
+  CHECK_EXIST(args, "domainName", out)
+  const double callback_id = args.get("callbackId").get<double>();
+  const std::string& domainName = args.get("domainName").get<std::string>();
+
+  auto get = [ this, callback_id ](bool status)->void {
+    LoggerD("enter");
+    picojson::value response = picojson::value(picojson::object());
+    picojson::object& obj = response.get<picojson::object>();
+    if (status)
+      ReportSuccess(obj);
+    else
+      ReportError(UnknownException("PLATFORM ERROR"), obj);
+    obj["callbackId"] = picojson::value(callback_id);
+    Instance::PostMessage(this, response.serialize().c_str());
+  };
+
+  auto reply = [=](bool status)->void {
+    LoggerD("enter");
+    common::TaskQueue::GetInstance().Async(std::bind(get, status));
+  };
+
+  bool status =
+      NetworkBearerSelectionManager::GetInstance()->releaseRouteToHost(
+          domainName, reply);
+  if (status) {
+    ReportSuccess(out);
+  } else {
+    ReportError(out);
+  }
+}
+
+void NetworkBearerSelectionInstance::onNBSSuccess(
+    const std::string& domain_name) {
+  LoggerD("enter");
+  picojson::value event = picojson::value(picojson::object());
+  picojson::object& obj = event.get<picojson::object>();
+  obj["domainName"] = picojson::value(domain_name);
+  obj["state"] = picojson::value("Success");
+
+  auto iterRange = listenerMap.equal_range(domain_name);
+  for (auto iter = iterRange.first; iter != iterRange.second; ++iter) {
+    auto listenerId = (*iter).second;
+    obj["listenerId"] = picojson::value("NetworkBearerSelectionCallback_" +
+                                        std::to_string(listenerId));
+    obj["id"] = picojson::value(static_cast<double>(listenerId));
+    LoggerD("Posting: %s", event.serialize().c_str());
+    Instance::PostMessage(this, event.serialize().c_str());
+  }
+}
+
+void NetworkBearerSelectionInstance::onNBSError(const std::string& domain_name,
+                                                const std::string& info) {
+  LoggerD("enter");
+  picojson::value event = picojson::value(picojson::object());
+  picojson::object& obj = event.get<picojson::object>();
+  ReportError(UnknownException(info), obj);
+  obj["domainName"] = picojson::value(domain_name);
+  obj["state"] = picojson::value("Error");
+
+  auto iterRange = listenerMap.equal_range(domain_name);
+  for (auto iter = iterRange.first; iter != iterRange.second; ++iter) {
+    auto listenerId = (*iter).second;
+    obj["listenerId"] = picojson::value("NetworkBearerSelectionCallback_" +
+                                        std::to_string(listenerId));
+    obj["id"] = picojson::value(static_cast<double>(listenerId));
+    LoggerD("Posting: %s", event.serialize().c_str());
+    Instance::PostMessage(this, event.serialize().c_str());
+  }
+  listenerMap.erase(domain_name);
+}
+
+void NetworkBearerSelectionInstance::onNBSDisconnect(
+    const std::string& domain_name) {
+  LoggerD("enter");
+  picojson::value event = picojson::value(picojson::object());
+  picojson::object& obj = event.get<picojson::object>();
+  obj["domainName"] = picojson::value(domain_name);
+  obj["state"] = picojson::value("Disconnected");
+
+  auto iterRange = listenerMap.equal_range(domain_name);
+  for (auto iter = iterRange.first; iter != iterRange.second; ++iter) {
+    auto listenerId = (*iter).second;
+    obj["listenerId"] = picojson::value("NetworkBearerSelectionCallback_" +
+                                        std::to_string(listenerId));
+    obj["id"] = picojson::value(static_cast<double>(listenerId));
+    LoggerD("Posting: %s", event.serialize().c_str());
+    Instance::PostMessage(this, event.serialize().c_str());
+  }
+  listenerMap.erase(domain_name);
+}
+
+#undef CHECK_EXIST
+
+}  // namespace networkbearerselection
+}  // namespace extension
diff --git a/webWidgetTCT_device/src/networkbearerselection/networkbearerselection_instance.h b/webWidgetTCT_device/src/networkbearerselection/networkbearerselection_instance.h
new file mode 100755 (executable)
index 0000000..d07d49c
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2015 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 NETWORKBEARERSELECTION_NETWORKBEARERSELECTION_INSTANCE_H_
+#define NETWORKBEARERSELECTION_NETWORKBEARERSELECTION_INSTANCE_H_
+
+#include "common/extension.h"
+#include "networkbearerselection_manager.h"
+#include <map>
+
+namespace extension {
+namespace networkbearerselection {
+
+class NetworkBearerSelectionInstance : public common::ParsedInstance,
+                                       public NetworkBearerSelectionListener {
+ public:
+  NetworkBearerSelectionInstance();
+  virtual ~NetworkBearerSelectionInstance();
+
+ private:
+  void NetworkBearerSelectionRequestRouteToHost(const picojson::value& args,
+                                                picojson::object& out);
+  void NetworkBearerSelectionReleaseRouteToHost(const picojson::value& args,
+                                                picojson::object& out);
+
+  virtual void onNBSSuccess(const std::string& domain_name);
+  virtual void onNBSError(const std::string& domain_name,
+                          const std::string& info);
+  virtual void onNBSDisconnect(const std::string& domain_name);
+
+  std::multimap<std::string, int> listenerMap;
+};
+
+}  // namespace networkbearerselection
+}  // namespace extension
+
+#endif  // NETWORKBEARERSELECTION_NETWORKBEARERSELECTION_INSTANCE_H_
diff --git a/webWidgetTCT_device/src/networkbearerselection/networkbearerselection_manager.cc b/webWidgetTCT_device/src/networkbearerselection/networkbearerselection_manager.cc
new file mode 100755 (executable)
index 0000000..40eebdf
--- /dev/null
@@ -0,0 +1,451 @@
+/*
+ * Copyright (c) 2015 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 "networkbearerselection_manager.h"
+#include "common/logger.h"
+
+#include <netdb.h>
+#include <arpa/inet.h>
+#include <memory>
+
+namespace extension {
+namespace networkbearerselection {
+
+namespace {
+const char* kPlatformError = "Platform error";
+}
+
+struct NetworkBearerSelectionRequestEvent {
+  std::string domain_name;
+  NetworkBearerSelectionRequestEvent(const std::string& dm) : domain_name(dm) {}
+};
+
+struct NetworkBearerSelectionReleaseEvent {
+  std::string domain_name;
+  NetworkBearerSelectionManager::ReleaseReplyCallback callback;
+  NetworkBearerSelectionReleaseEvent(
+      const std::string& dm,
+      const NetworkBearerSelectionManager::ReleaseReplyCallback& cb)
+      : domain_name(dm), callback(cb) {}
+};
+
+void NetworkBearerSelectionManager::AddListener(
+    NetworkBearerSelectionListener* listener) {
+  LoggerD("Enter");
+  std::lock_guard<std::mutex> lock(m_mutex);
+  m_listeners.push_back(listener);
+}
+
+void NetworkBearerSelectionManager::RemoveListener(
+    NetworkBearerSelectionListener* listener) {
+  LoggerD("Enter");
+  std::lock_guard<std::mutex> lock(m_mutex);
+  m_listeners.remove(listener);
+}
+
+NetworkBearerSelectionManager* NetworkBearerSelectionManager::GetInstance() {
+  LoggerD("Enter");
+  static NetworkBearerSelectionManager instance;
+  return &instance;
+}
+
+NetworkBearerSelectionManager::NetworkBearerSelectionManager()
+    : m_connectionHandle(nullptr),
+      m_profileHandle(nullptr),
+      m_connectionState(ConnectionState::Unknown),
+      m_isConnectionOpen(false) {
+  LoggerD("Enter");
+  int ret = connection_create(&m_connectionHandle);
+
+  if (CONNECTION_ERROR_NONE == ret) {
+    LoggerD("Client registration success");
+  } else {
+    LoggerE("Client registration failed");
+    m_connectionHandle = nullptr;
+  }
+}
+
+NetworkBearerSelectionManager::~NetworkBearerSelectionManager() {
+  LoggerD("Enter");
+  if (m_connectionHandle != nullptr) {
+    LoggerD("Client deregistration success");
+    if (m_profileHandle) {
+      connection_profile_destroy(m_profileHandle);
+      m_profileHandle = nullptr;
+    }
+    connection_destroy(m_connectionHandle);
+  } else {
+    LoggerE("Client deregistration failed");
+  }
+}
+
+void NetworkBearerSelectionManager::connection_state_changed_callback(
+    connection_profile_state_e state,
+    void* user_data) {
+  LoggerD("enter");
+  if (user_data != nullptr) {
+    LoggerD("Callback registration Succeeded");
+    if (state == CONNECTION_PROFILE_STATE_ASSOCIATION) {
+      LoggerD("association state");
+      return;
+    }
+    NetworkBearerSelectionRequestEvent* event =
+        static_cast<NetworkBearerSelectionRequestEvent*>(user_data);
+
+    if (state == CONNECTION_PROFILE_STATE_DISCONNECTED) {
+      std::string domain_name = event->domain_name;
+      NetworkBearerSelectionManager::GetInstance()->deregistStateChangeListener(domain_name);
+      delete event;
+
+      NetworkBearerSelectionManager::GetInstance()->makeDisconnectCallback(domain_name);
+    }
+  }
+}
+
+void NetworkBearerSelectionManager::connection_profile_opened_callback(
+    connection_error_e result,
+    void* user_data) {
+  LoggerD("enter");
+  if (user_data == nullptr) {
+    LoggerD("Error: null passed in profile open callback");
+    return;
+  }
+
+  NetworkBearerSelectionRequestEvent* event =
+      static_cast<NetworkBearerSelectionRequestEvent*>(user_data);
+  std::string domain_name = event->domain_name;
+  delete event;
+
+  if (result == CONNECTION_ERROR_NONE) {
+    LoggerD("Connection open Succeeded");
+    if (user_data != nullptr) {
+      NetworkBearerSelectionManager::GetInstance()->registStateChangeListener(
+          domain_name);
+    }
+  } else {
+    LoggerD("Connection open Failed");
+    NetworkBearerSelectionManager::GetInstance()->makeErrorCallback(
+        domain_name, kPlatformError);
+  }
+}
+
+void NetworkBearerSelectionManager::connection_closed_callback(
+    connection_error_e result,
+    void* user_data) {
+  LoggerD("enter");
+  if (user_data == nullptr) {
+    LoggerD("Error: null passed in profile open callback");
+    return;
+  }
+
+  NetworkBearerSelectionReleaseEvent* event =
+      static_cast<NetworkBearerSelectionReleaseEvent*>(user_data);
+  std::string domain_name = event->domain_name;
+  ReleaseReplyCallback callback = event->callback;
+  delete event;
+
+  if (result == CONNECTION_ERROR_NONE) {
+    LoggerD("Connection close Succeeded");
+    if (user_data != nullptr) {
+      NetworkBearerSelectionManager::GetInstance()->deregistStateChangeListener(
+          domain_name);
+      callback(true);
+    }
+  } else {
+    callback(false);
+  }
+}
+
+void NetworkBearerSelectionManager::connection_closed_callback2(
+    connection_error_e result,
+    void* user_data) {
+  LoggerD("enter");
+  if (result == CONNECTION_ERROR_NONE) {
+    LoggerD("Connection close Succeeded");
+  }
+}
+
+void NetworkBearerSelectionManager::requestRouteToHost(
+    const std::string& domain_name) {
+  LoggerD("NetworkBearerSelectionManager::requestRouteToHost");
+  connection_profile_h profileHandle;
+
+  if (m_connectionState == ConnectionState::Connected) {
+    LoggerD("connection is already opened.");
+    for (std::list<std::string>::iterator it = m_domainNames.begin();
+         it != m_domainNames.end();
+         it++) {
+      if (*it == domain_name) {
+        LoggerD("Same domain name is exist in list.");
+        makeSuccessCallback(domain_name);
+        return;
+      }
+    }
+  }
+
+  if (m_profileHandle) {
+    connection_profile_destroy(m_profileHandle);
+    m_profileHandle = nullptr;
+  }
+
+  if (connection_get_default_cellular_service_profile(
+          m_connectionHandle,
+          CONNECTION_CELLULAR_SERVICE_TYPE_INTERNET,
+          &m_profileHandle) != CONNECTION_ERROR_NONE) {
+    LoggerE("Fail to get profile handle");
+    makeErrorCallback(domain_name, kPlatformError);
+    return;
+  }
+
+  char* defaultProfileName_c = nullptr;
+  std::string defaultProfileName;
+
+  connection_profile_get_name(m_profileHandle, &defaultProfileName_c);
+  if (defaultProfileName_c == nullptr) {
+    LoggerE("default profile is not exist.");
+    makeErrorCallback(domain_name, kPlatformError);
+    return;
+  }
+  defaultProfileName = defaultProfileName_c;
+  free(defaultProfileName_c);
+  defaultProfileName_c = nullptr;
+
+  if (connection_get_current_profile(m_connectionHandle, &profileHandle) !=
+      CONNECTION_ERROR_NONE) {
+    LoggerE("Fail to get current profile handle");
+    makeErrorCallback(domain_name, kPlatformError);
+    return;
+  }
+
+  char* currentProfileName_c = nullptr;
+  std::string currentProfileName;
+  if (connection_profile_get_name(profileHandle, &currentProfileName_c) !=
+      CONNECTION_ERROR_NONE) {
+    LoggerE("Fail to get current profile name");
+    makeErrorCallback(domain_name, kPlatformError);
+    return;
+  }
+
+  if (currentProfileName_c == nullptr) {
+    LoggerE("current profile is not exist.");
+    makeErrorCallback(domain_name, kPlatformError);
+    return;
+  }
+  currentProfileName = currentProfileName_c;
+  free(currentProfileName_c);
+  currentProfileName_c = nullptr;
+
+  if (defaultProfileName != currentProfileName) {
+    NetworkBearerSelectionRequestEvent* event =
+        new NetworkBearerSelectionRequestEvent(domain_name);
+    if (connection_open_profile(m_connectionHandle,
+                                m_profileHandle,
+                                connection_profile_opened_callback,
+                                event) != CONNECTION_ERROR_NONE) {
+      LoggerE("Connection open Failed");
+      delete event;
+      makeErrorCallback(domain_name, kPlatformError);
+    } else {
+      m_isConnectionOpen = true;
+    }
+  } else {
+    registStateChangeListener(domain_name);
+  }
+}
+
+bool NetworkBearerSelectionManager::releaseRouteToHost(
+    const std::string& domain_name,
+    const ReleaseReplyCallback& reply_cb) {
+  LoggerD("enter");
+  for (std::list<std::string>::iterator it = m_domainNames.begin();
+       it != m_domainNames.end();
+       it++) {
+    if (*it == domain_name) {
+      LoggerD("Same domain name is exist in list.");
+      m_domainNames.remove(domain_name);
+      LoggerD("list size : %i", m_domainNames.size());
+      if (m_domainNames.size() == 0) {
+        if (!m_profileHandle) {
+          // TODO: ALREADY_IN_USE EXCEPTION
+          return false;
+        }
+
+        if (connection_profile_unset_state_changed_cb(m_profileHandle) !=
+            CONNECTION_ERROR_NONE) {
+          LoggerE("unset callback is failed");
+          if (m_profileHandle) {
+            connection_profile_destroy(m_profileHandle);
+            m_profileHandle = NULL;
+          }
+          return true;
+        }
+
+        if (m_isConnectionOpen) {
+          NetworkBearerSelectionReleaseEvent* event =
+              new NetworkBearerSelectionReleaseEvent(domain_name, reply_cb);
+          if (connection_close_profile(m_connectionHandle,
+                                       m_profileHandle,
+                                       connection_closed_callback,
+                                       event) != CONNECTION_ERROR_NONE) {
+            LoggerE("connection close failed");
+            delete event;
+            reply_cb(false);
+          } else {
+            m_isConnectionOpen = false;
+            deregistStateChangeListener(domain_name);
+          }
+        } else {
+          reply_cb(true);
+        }
+      }
+      return true;
+    }
+  }
+
+  // TODO: INVALID_ARGUMENT_EXCEPTION
+  return false;
+}
+
+void NetworkBearerSelectionManager::registStateChangeListener(
+    const std::string& domain_name) {
+  LoggerD("enter");
+  char* interfaceName = nullptr;
+  char* hostAddr = nullptr;
+  std::unique_ptr<char, void(*)(void*)> host_addr_ptr(nullptr, &std::free);
+  struct addrinfo* servinfo = nullptr;
+
+  if (connection_profile_get_network_interface_name(
+          m_profileHandle, &interfaceName) != CONNECTION_ERROR_NONE) {
+    LoggerE("Fail to get interface name!");
+    if (m_profileHandle) {
+      connection_profile_destroy(m_profileHandle);
+      m_profileHandle = nullptr;
+    }
+    makeErrorCallback(domain_name, kPlatformError);
+  } else {
+    LoggerD("Interface name : %s", interfaceName);
+  }
+
+  LoggerD("Domain name to be resolved: %s", domain_name.c_str());
+
+  int ret_val = getaddrinfo(domain_name.c_str() , nullptr , nullptr , &servinfo);
+  if (0 != ret_val) {
+    LoggerE("Error while calling getaddrinfo(): %s", gai_strerror(ret_val));
+    if (m_profileHandle) {
+      connection_profile_destroy(m_profileHandle);
+      m_profileHandle = nullptr;
+    }
+    makeErrorCallback(domain_name, kPlatformError);
+    return;
+  } else {
+    hostAddr = new char[servinfo->ai_addrlen + 1];
+    host_addr_ptr.reset(hostAddr);
+
+    struct in_addr  *addr = nullptr;
+    if (AF_INET == servinfo->ai_family) {
+      struct sockaddr_in *ipv = (struct sockaddr_in *)servinfo->ai_addr;
+      addr = &(ipv->sin_addr);
+    } else {
+      struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)servinfo->ai_addr;
+      addr = (struct in_addr *) &(ipv6->sin6_addr);
+    }
+    if (nullptr == inet_ntop(servinfo->ai_family, addr, hostAddr, servinfo->ai_addrlen)) {
+      LoggerE("Error while calling inet_ntop()");
+      if (m_profileHandle) {
+        connection_profile_destroy(m_profileHandle);
+        m_profileHandle = nullptr;
+      }
+      makeErrorCallback(domain_name, kPlatformError);
+      freeaddrinfo(servinfo);
+      return;
+    }
+    LoggerD("hostAddr : %s", hostAddr);
+
+    freeaddrinfo(servinfo);
+  }
+
+  NetworkBearerSelectionRequestEvent* event =
+      new NetworkBearerSelectionRequestEvent(domain_name);
+  if (connection_profile_set_state_changed_cb(m_profileHandle,
+                                              connection_state_changed_callback,
+                                              event) != CONNECTION_ERROR_NONE) {
+    LoggerE("Callback register is failed.");
+    if (m_profileHandle) {
+      connection_profile_destroy(m_profileHandle);
+      m_profileHandle = nullptr;
+    }
+    delete event;
+  } else {
+    if (connection_add_route(m_connectionHandle, interfaceName, hostAddr) !=
+        CONNECTION_ERROR_NONE) {
+      LoggerE("add route is failed.");
+      connection_profile_unset_state_changed_cb(m_profileHandle);
+      makeErrorCallback(domain_name, kPlatformError);
+    } else {
+      LoggerD("add route is successed.");
+      m_domainNames.push_back(domain_name);
+      makeSuccessCallback(domain_name);
+    }
+  }
+}
+
+void NetworkBearerSelectionManager::deregistStateChangeListener(
+    const std::string& domain_name) {
+  LoggerD("enter");
+  if (m_profileHandle) {
+    connection_profile_unset_state_changed_cb(m_profileHandle);
+    connection_profile_destroy(m_profileHandle);
+    m_profileHandle = NULL;
+  }
+  m_domainNames.remove(domain_name);
+  m_connectionState = ConnectionState::Disconnected;
+}
+
+void NetworkBearerSelectionManager::makeSuccessCallback(
+    const std::string& domain_name) {
+  LoggerD("enter");
+  std::lock_guard<std::mutex> lock(m_mutex);
+  for (NetworkBearerSelectionListener* listener : m_listeners)
+    listener->onNBSSuccess(domain_name);
+}
+
+void NetworkBearerSelectionManager::makeErrorCallback(
+    const std::string& domain_name,
+    const char* info) {
+  LoggerD("enter");
+  std::string l_info = info;
+  makeErrorCallback(domain_name, l_info);
+}
+
+void NetworkBearerSelectionManager::makeErrorCallback(
+    const std::string& domain_name,
+    const std::string& info) {
+  LoggerD("enter");
+  std::lock_guard<std::mutex> lock(m_mutex);
+  for (NetworkBearerSelectionListener* listener : m_listeners)
+    listener->onNBSError(domain_name, info);
+}
+
+void NetworkBearerSelectionManager::makeDisconnectCallback(
+    const std::string& domain_name) {
+  LoggerD("enter");
+  std::lock_guard<std::mutex> lock(m_mutex);
+  for (NetworkBearerSelectionListener* listener : m_listeners)
+    listener->onNBSDisconnect(domain_name);
+}
+
+}  // namespace networkbearerselection
+}  // namespace extension
diff --git a/webWidgetTCT_device/src/networkbearerselection/networkbearerselection_manager.h b/webWidgetTCT_device/src/networkbearerselection/networkbearerselection_manager.h
new file mode 100755 (executable)
index 0000000..ad2b055
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2015 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 NETWORKBEARERSELECTION_NETWORKBEARERSELECTION_MANAGER_H_
+#define NETWORKBEARERSELECTION_NETWORKBEARERSELECTION_MANAGER_H_
+
+#include <string>
+#include <list>
+#include <mutex>
+#include <functional>
+#include <device/callback.h>
+#include <net_connection.h>
+
+namespace extension {
+namespace networkbearerselection {
+
+enum class ConnectionState {
+  Unknown,
+  Connected,
+  Disconnected,
+  ConnectionFailed
+};
+
+enum class NetworkType {
+  Cellular,
+  Unknown
+};
+
+class NetworkBearerSelectionListener {
+ public:
+  virtual void onNBSSuccess(const std::string& domain_name) = 0;
+  virtual void onNBSError(const std::string& domain_name,
+                          const std::string& info) = 0;
+  virtual void onNBSDisconnect(const std::string& domain_name) = 0;
+};
+
+class NetworkBearerSelectionManager {
+ public:
+  typedef std::function<void(bool)> ReleaseReplyCallback;
+  void AddListener(NetworkBearerSelectionListener* listener);
+  void RemoveListener(NetworkBearerSelectionListener* listener);
+
+  void requestRouteToHost(const std::string& domain_name);
+  bool releaseRouteToHost(const std::string& domain_name,
+                          const ReleaseReplyCallback& reply_cb);
+
+  static NetworkBearerSelectionManager* GetInstance();
+
+  NetworkBearerSelectionManager(const NetworkBearerSelectionManager&) = delete;
+  NetworkBearerSelectionManager& operator=(
+      const NetworkBearerSelectionManager&) = delete;
+
+ private:
+  static void connection_state_changed_callback(
+      connection_profile_state_e state,
+      void* user_data);
+  static void connection_profile_opened_callback(connection_error_e result,
+                                                 void* user_data);
+  static void connection_closed_callback(connection_error_e result,
+                                         void* user_data);
+  static void connection_closed_callback2(connection_error_e result,
+                                          void* user_data);
+
+  void registStateChangeListener(const std::string& domain_name);
+  void deregistStateChangeListener(const std::string& domain_name);
+
+  void makeSuccessCallback(const std::string& domain_name);
+  void makeErrorCallback(const std::string& domain_name, const char* info);
+  void makeErrorCallback(const std::string& domain_name,
+                         const std::string& info);
+  void makeDisconnectCallback(const std::string& domain_name);
+
+  NetworkBearerSelectionManager();
+  ~NetworkBearerSelectionManager();
+
+  std::list<NetworkBearerSelectionListener*> m_listeners;
+
+  connection_h m_connectionHandle;
+  connection_profile_h m_profileHandle;
+  std::list<std::string> m_domainNames;
+  ConnectionState m_connectionState;
+  bool m_isConnectionOpen;
+  std::mutex m_mutex;
+};
+
+}  // namespace networkbearerselection
+}  // namespace extension
+
+#endif  // NETWORKBEARERSELECTION_NETWORKBEARERSELECTION_MANAGER_H_
diff --git a/webWidgetTCT_device/src/nfc/aid_data.cc b/webWidgetTCT_device/src/nfc/aid_data.cc
new file mode 100755 (executable)
index 0000000..c6af525
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2015 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 "nfc/aid_data.h"
+#include "common/logger.h"
+
+namespace extension {
+namespace nfc {
+
+AIDData::AIDData(nfc_se_type_e se_type, const char* aid, bool read_only)
+    : se_type_(se_type),
+      aid_(aid),
+      read_only_(read_only)
+{
+  LoggerD("Entered");
+}
+
+picojson::value AIDData::toJSON() const {
+  LoggerD("Entered");
+  picojson::value retval = picojson::value(picojson::object());
+  picojson::object& obj = retval.get<picojson::object>();
+
+  obj["aid"] = picojson::value();
+  obj["type"] = picojson::value();
+  obj["readOnly"] = picojson::value();
+  return retval;
+}
+
+}  // nfc
+}  // extension
diff --git a/webWidgetTCT_device/src/nfc/aid_data.h b/webWidgetTCT_device/src/nfc/aid_data.h
new file mode 100755 (executable)
index 0000000..14774c3
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2015 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 NFC_AID_DATA_H_
+#define NFC_AID_DATA_H_
+
+#include <network/nfc.h>
+
+#include <vector>
+
+#include "common/picojson.h"
+
+namespace extension {
+namespace nfc {
+
+class AIDData {
+ public:
+  AIDData(nfc_se_type_e se_type, const char* aid, bool read_only);
+  picojson::value toJSON() const;
+
+ private:
+  nfc_se_type_e se_type_;
+  const char* aid_;
+  bool read_only_;
+};
+
+typedef std::vector<AIDData> AIDDataVector;
+
+}  // nfc
+}  // extension
+
+#endif  // NFC_AID_DATA_H_
diff --git a/webWidgetTCT_device/src/nfc/defs.h b/webWidgetTCT_device/src/nfc/defs.h
new file mode 100755 (executable)
index 0000000..5fa260c
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015 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 NFC_DEFS_H
+#define NFC_DEFS_H
+
+#define JSON_AID                                               "aid"
+#define JSON_APDU                                              "apdu"
+#define JSON_CALLBACK_ID                                       "callbackId"
+#define JSON_CATEGORY                                          "category"
+#define JSON_DATA                                              "data"
+#define JSON_EVENT_TYPE                                        "eventType"
+#define JSON_LENGTH                                            "length"
+#define JSON_LISTENER_ID                                       "listenerId"
+#define JSON_MODE                                              "mode"
+#define JSON_TYPE                                              "type"
+
+#define DATA_NFC_SE_TYPE_ESE                                   "ESE"
+#define DATA_NFC_SE_TYPE_UICC                                  "UICC"
+#define DATA_NFC_SE_TYPE_HCE                                   "HCE"
+
+#endif  // NFC_DEFS_H
diff --git a/webWidgetTCT_device/src/nfc/nfc.gyp b/webWidgetTCT_device/src/nfc/nfc.gyp
new file mode 100755 (executable)
index 0000000..25b02f9
--- /dev/null
@@ -0,0 +1,47 @@
+{
+  'includes':[
+    '../common/common.gypi',
+  ],
+  'targets': [
+    {
+      'target_name': 'tizen_nfc',
+      'type': 'loadable_module',
+      'dependencies': [
+        '../common/common.gyp:tizen_common',
+      ],
+      'sources': [
+        'nfc_api.js',
+        'nfc_extension.cc',
+        'nfc_extension.h',
+        'nfc_instance.cc',
+        'nfc_instance.h',
+        'nfc_adapter.cc',
+        'nfc_adapter.h',
+        'nfc_util.cc',
+        'nfc_util.h',
+        'nfc_message_utils.cc',
+        'nfc_message_utils.h',
+        'nfc_platform_callbacks.h',
+        'aid_data.cc',
+        'aid_data.h'
+      ],
+      'includes': [
+        '../common/pkg-config.gypi',
+      ],
+      'conditions': [
+        ['tizen == 1', {
+          'variables': {
+            'packages': [
+                'capi-system-info',
+                'capi-network-nfc',
+                'capi-appfw-application'
+            ]
+          },
+        }],
+        ['tizen_feature_app_control_settings_support == 1', {
+          'defines': ['APP_CONTROL_SETTINGS_SUPPORT'],
+        }],
+      ],
+    },
+  ],
+}
diff --git a/webWidgetTCT_device/src/nfc/nfc_adapter.cc b/webWidgetTCT_device/src/nfc/nfc_adapter.cc
new file mode 100755 (executable)
index 0000000..beb1dab
--- /dev/null
@@ -0,0 +1,1576 @@
+/*
+ * Copyright (c) 2015 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 "nfc/nfc_adapter.h"
+
+#include <glib.h>
+
+#include <memory>
+#include <string>
+
+#include "common/assert.h"
+#include "common/converter.h"
+#include "common/extension.h"
+#include "common/logger.h"
+#include "common/platform_exception.h"
+#include "nfc/aid_data.h"
+#include "nfc/defs.h"
+#include "nfc/nfc_message_utils.h"
+#include "nfc/nfc_util.h"
+
+using namespace common;
+using namespace std;
+
+namespace extension {
+namespace nfc {
+
+namespace {
+
+const std::string CARD_ELEMENT = "CardElement";
+const std::string TRANSACTION = "Transaction";
+const std::string HCE_EVENT_DATA = "HCEEventData";
+
+const std::string ACTIVE_SECURE_ELEMENT_CHANGED = "ActiveSecureElementChanged";
+const std::string CARD_EMULATION_MODE_CHANGED = "CardEmulationModeChanged";
+const std::string TRANSACTION_EVENT_LISTENER_ESE = "TransactionEventListener_ESE";
+const std::string TRANSACTION_EVENT_LISTENER_UICC = "TransactionEventListener_UICC";
+const std::string PEER_LISTENER = "PeerListener";
+const std::string HCE_EVENT_LISTENER = "HCEEventListener";
+
+void HCEEventCallback(nfc_se_h handle,
+                  nfc_hce_event_type_e event_type,
+                  unsigned char* apdu,
+                  unsigned int apdu_len,
+                  void* /*user_data*/) {
+  LoggerD("Entered");
+  NFCAdapter::GetInstance()->SetSEHandle(handle);
+
+  picojson::value response = picojson::value(picojson::object());
+  picojson::object& response_obj = response.get<picojson::object>();
+  response_obj[JSON_LISTENER_ID] = picojson::value(HCE_EVENT_LISTENER);
+  response_obj[JSON_TYPE] = picojson::value(HCE_EVENT_DATA);
+
+  // HCE Event Data
+  picojson::value event_data = picojson::value(picojson::object());
+  picojson::object& event_data_obj = event_data.get<picojson::object>();
+  event_data_obj[JSON_EVENT_TYPE] = picojson::value(NFCUtil::ToStr(event_type));
+  event_data_obj[JSON_APDU] = picojson::value(
+      NFCUtil::FromUCharArray(apdu, apdu_len));
+  event_data_obj[JSON_LENGTH] = picojson::value(static_cast<double>(apdu_len));
+  tools::ReportSuccess(event_data, response_obj);
+
+  NFCAdapter::GetInstance()->RespondAsync(response.serialize().c_str());
+}
+
+}  // anonymous namespace
+
+NFCAdapter::NFCAdapter():
+            m_last_tag_handle(nullptr),
+            m_is_tag_listener_set(false),
+            m_latest_tag_id(0),
+            m_is_listener_set(false),
+            m_is_transaction_ese_listener_set(false),
+            m_is_transaction_uicc_listener_set(false),
+            m_is_transaction_hce_listener_set(false),
+            m_is_peer_listener_set(false),
+            m_latest_peer_id(0),
+            m_peer_handle(nullptr),
+            m_is_ndef_listener_set(false),
+            m_se_handle(nullptr),
+            m_is_hce_listener_set(false),
+            responder_(nullptr)
+{
+  LoggerD("Entered");
+  // NFC library initialization
+  int ret = nfc_manager_initialize();
+  if(ret != NFC_ERROR_NONE) {
+    LoggerE("Could not initialize NFC Manager, error: %d", ret);
+  }
+}
+
+NFCAdapter::~NFCAdapter() {
+  LoggerD("Entered");
+  if (m_is_listener_set) {
+    nfc_manager_unset_se_event_cb();
+  }
+  if (m_is_peer_listener_set) {
+    nfc_manager_unset_p2p_target_discovered_cb();
+  }
+  if (m_is_transaction_ese_listener_set) {
+    nfc_manager_unset_se_transaction_event_cb(NFC_SE_TYPE_ESE);
+  }
+  if (m_is_transaction_uicc_listener_set) {
+    nfc_manager_unset_se_transaction_event_cb(NFC_SE_TYPE_UICC);
+  }
+  if (m_is_ndef_listener_set) {
+    nfc_p2p_unset_data_received_cb(m_peer_handle);
+  }
+  if (m_is_tag_listener_set) {
+    nfc_manager_unset_tag_discovered_cb();
+  }
+  if (m_is_hce_listener_set) {
+    nfc_manager_unset_hce_event_cb();
+  }
+
+  // NFC library deinitialization
+  int ret = nfc_manager_deinitialize();
+  if(ret != NFC_ERROR_NONE) {
+    LoggerE("Could not deinitialize NFC Manager, error: %d", ret);
+  }
+}
+
+void NFCAdapter::SetResponder(IResponder* responder) {
+  LoggerD("Entered");
+  responder_ = responder;
+}
+
+void NFCAdapter::RespondAsync(const char* msg) {
+  LoggerD("Entered");
+  AssertMsg(GetInstance()->responder_, "Handler variable should be set");
+  GetInstance()->responder_->RespondAsync(msg);
+}
+
+static picojson::value CreateEventError(double callbackId, const PlatformResult& ret) {
+  LoggerD("Entered");
+  picojson::value event = picojson::value(picojson::object());
+  picojson::object& obj = event.get<picojson::object>();
+  tools::ReportError(ret, &obj);
+  obj[JSON_CALLBACK_ID] = picojson::value(callbackId);
+
+  return event;
+}
+
+static picojson::value createEventSuccess(double callbackId) {
+  LoggerD("Entered");
+  picojson::value event = picojson::value(picojson::object());
+  picojson::object& obj = event.get<picojson::object>();
+  tools::ReportSuccess(obj);
+  obj[JSON_CALLBACK_ID] = picojson::value(callbackId);
+
+  return event;
+}
+
+static gboolean setPoweredCompleteCB(void* user_data) {
+  LoggerD("Entered");
+  double* callbackId = static_cast<double*>(user_data);
+  picojson::value event = createEventSuccess(*callbackId);
+  NFCAdapter::GetInstance()->RespondAsync(event.serialize().c_str());
+
+  delete callbackId;
+  callbackId = NULL;
+  return false;
+}
+
+static void targetDetectedCallback(nfc_discovered_type_e type,
+                                   nfc_p2p_target_h target,
+                                   void* /*user_data*/) {
+  LoggerD("Entered");
+  picojson::value event = picojson::value(picojson::object());
+  picojson::object& obj = event.get<picojson::object>();
+  obj[JSON_LISTENER_ID] = picojson::value(PEER_LISTENER);
+
+  NFCAdapter* adapter = NFCAdapter::GetInstance();
+
+  //unregister previous NDEF listener
+  if (adapter->IsNDEFListenerSet()) {
+    adapter->UnsetReceiveNDEFListener(adapter->GetPeerId());
+  }
+
+  if (NFC_DISCOVERED_TYPE_ATTACHED == type) {
+    adapter->SetPeerHandle(target);
+    obj["action"] = picojson::value("onattach");
+    adapter->IncreasePeerId();
+    obj["id"] = picojson::value(static_cast<double>(adapter->GetPeerId()));
+  } else {
+    adapter->SetPeerHandle(NULL);
+    obj["action"] = picojson::value("ondetach");
+  }
+  NFCAdapter::GetInstance()->RespondAsync(event.serialize().c_str());
+}
+
+NFCAdapter* NFCAdapter::GetInstance() {
+  LoggerD("Entered");
+  static NFCAdapter instance;
+  return &instance;
+}
+
+bool NFCAdapter::GetPowered() {
+  LoggerD("Entered");
+  return nfc_manager_is_activated();
+}
+
+#ifndef APP_CONTROL_SETTINGS_SUPPORT
+
+static void NFCSetActivationCompletedCallback(nfc_error_e error,
+                                              void* user_data) {
+  LoggerD("Entered");
+  double* callbackId = static_cast<double*>(user_data);
+
+  if (NFC_ERROR_NONE != error) {
+    PlatformResult result = NFCUtil::CodeToResult(error, NFCUtil::getNFCErrorMessage(error).c_str());
+    picojson::value event = CreateEventError(*callbackId, result);
+
+    NFCAdapter::GetInstance()->RespondAsync(event.serialize().c_str());
+  } else {
+    picojson::value event = createEventSuccess(*callbackId);
+
+    NFCAdapter::GetInstance()->RespondAsync(event.serialize().c_str());
+  }
+  delete callbackId;
+  callbackId = NULL;
+}
+
+#endif
+
+static void se_event_callback(nfc_se_event_e se_event, void* /*user_data*/) {
+  LoggerD("Entered");
+  picojson::value event = picojson::value(picojson::object());
+  picojson::object& obj = event.get<picojson::object>();
+  tools::ReportSuccess(obj);
+  LoggerD("se_event_occured: %d", se_event);
+
+  string result = "";
+  switch (se_event) {
+    case NFC_SE_EVENT_SE_TYPE_CHANGED:
+      NFCAdapter::GetInstance()->GetActiveSecureElement(&result);
+      obj.insert(make_pair(JSON_LISTENER_ID,
+          picojson::value(ACTIVE_SECURE_ELEMENT_CHANGED)));
+      break;
+    case NFC_SE_EVENT_CARD_EMULATION_CHANGED:
+      NFCAdapter::GetInstance()->GetCardEmulationMode(&result);
+      obj.insert(make_pair(JSON_LISTENER_ID,
+          picojson::value(CARD_EMULATION_MODE_CHANGED)));
+      break;
+    default:
+      LoggerE("Unsupported se_event: %d", se_event);
+      return;
+  }
+
+  obj.insert(make_pair(JSON_TYPE, picojson::value(CARD_ELEMENT)));
+  obj.insert(make_pair(JSON_MODE, picojson::value(result)));
+  NFCAdapter::GetInstance()->RespondAsync(event.serialize().c_str());
+}
+
+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*/) {
+  LoggerD("Entered");
+  picojson::value response = picojson::value(picojson::object());
+  picojson::object& response_obj = response.get<picojson::object>();
+  tools::ReportSuccess(response_obj);
+  picojson::array& aid_array = response_obj.insert(std::make_pair(JSON_AID,
+                                                                  picojson::value(picojson::array()))).first->second.get<picojson::array>();
+  picojson::array& data_array = response_obj.insert(std::make_pair(JSON_DATA,
+                                                                   picojson::value(picojson::array()))).first->second.get<picojson::array>();
+
+  for (unsigned int i = 0; i < aid_size; i++) {
+    aid_array.push_back(picojson::value(static_cast<double>(_aid[i])));
+  }
+
+  for (unsigned int i = 0; i < param_size; i++) {
+    aid_array.push_back(picojson::value(static_cast<double>(param[i])));
+  }
+
+  if (NFC_SE_TYPE_ESE == type) {
+    response_obj.insert(make_pair(JSON_LISTENER_ID,
+        picojson::value(TRANSACTION_EVENT_LISTENER_ESE)));
+  } else {
+    response_obj.insert(make_pair(JSON_LISTENER_ID,
+        picojson::value(TRANSACTION_EVENT_LISTENER_UICC)));
+  }
+
+  response_obj.insert(make_pair(JSON_TYPE, picojson::value(TRANSACTION)));
+  NFCAdapter::GetInstance()->RespondAsync(response.serialize().c_str());
+}
+
+#ifdef APP_CONTROL_SETTINGS_SUPPORT
+static void PostMessage(double* callbackId) {
+  picojson::value event = CreateEventError(*callbackId,
+                                           PlatformResult(ErrorCode::UNKNOWN_ERR,
+                                                          "SetPowered failed."));
+  NFCAdapter::GetInstance()->RespondAsync(event.serialize().c_str());
+  delete callbackId;
+  callbackId = NULL;
+}
+#endif
+
+PlatformResult NFCAdapter::SetPowered(const picojson::value& args) {
+  LoggerD("Entered");
+  double* callbackId = new double(args.get(JSON_CALLBACK_ID).get<double>());
+
+  bool powered = args.get("powered").get<bool>();
+
+  if (nfc_manager_is_activated() == powered) {
+    if (!g_idle_add(setPoweredCompleteCB, static_cast<void*>(callbackId))) {
+      LoggerE("g_idle addition failed");
+      delete callbackId;
+      callbackId = NULL;
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, "SetPowered failed.");
+    }
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+
+#ifdef APP_CONTROL_SETTINGS_SUPPORT
+  app_control_h service = NULL;
+
+  int ret = app_control_create(&service);
+  if (ret != APP_CONTROL_ERROR_NONE) {
+    LoggerE("app_control_create failed: %d", ret);
+    delete callbackId;
+    callbackId = NULL;
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "SetPowered failed.");
+  }
+
+  ret = app_control_set_operation(service, "http://tizen.org/appcontrol/operation/setting/nfc");
+  if (ret != APP_CONTROL_ERROR_NONE) {
+    LoggerE("app_control_set_operation failed: %d", ret);
+    app_control_destroy(service);
+    delete callbackId;
+    callbackId = NULL;
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "SetPowered failed.");
+  }
+
+  ret = app_control_add_extra_data(service, "type", "nfc");
+  if (ret != APP_CONTROL_ERROR_NONE) {
+    LoggerE("app_control_add_extra_data failed: %d", ret);
+    app_control_destroy(service);
+    delete callbackId;
+    callbackId = NULL;
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "SetPowered failed.");
+  }
+
+  ret = app_control_send_launch_request(service, [](app_control_h request,
+      app_control_h reply, app_control_result_e result, void* user_data) {
+    double* callbackId = static_cast<double*>(user_data);
+    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) {
+        LoggerE("app_control_get_extra_data failed: %d", ret);
+        PostMessage(callbackId);
+        return;
+      }
+      LoggerD("app_control result: %s", type);
+    } else {
+      LoggerE("NFC enable app control failed : %d", result);
+      PostMessage(callbackId);
+      return;
+    }
+
+    if (!g_idle_add(setPoweredCompleteCB, static_cast<void*>(callbackId))) {
+      LoggerE("g_idle addition failed");
+      PostMessage(callbackId);
+      return;
+    }
+  }, static_cast<void*>(callbackId));
+
+  if (ret != APP_CONTROL_ERROR_NONE) {
+    LoggerE("app_control_send_launch_request failed: %d", ret);
+    app_control_destroy(service);
+    delete callbackId;
+    callbackId = NULL;
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "SetPowered failed.");
+  }
+
+  ret = app_control_destroy(service);
+  if (ret != APP_CONTROL_ERROR_NONE) {
+    LoggerE("app_control_destroy failed: %d", ret);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "SetPowered failed.");
+  }
+#else
+  int ret = nfc_manager_set_activation(powered,
+      NFCSetActivationCompletedCallback, static_cast<void*>(callbackId));
+
+  if (NFC_ERROR_NONE != ret) {
+    LoggerE("setPowered failed %d",ret);
+    delete callbackId;
+    callbackId = NULL;
+    return NFCUtil::CodeToResult(ret, "setPowered failed.");
+  }
+#endif
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult NFCAdapter::GetCardEmulationMode(std::string* mode) {
+  LoggerD("Entered");
+
+  nfc_se_card_emulation_mode_type_e card_mode;
+  int ret = nfc_se_get_card_emulation_mode(&card_mode);
+
+  if (NFC_ERROR_NONE != ret) {
+    LoggerE("Failed to get card emulation mode %d", ret);
+    return NFCUtil::CodeToResult(ret, "Failed to get card emulation mode");
+  }
+
+  return NFCUtil::ToStringCardEmulationMode(card_mode, mode);
+}
+
+PlatformResult NFCAdapter::SetCardEmulationMode(const std::string& mode) {
+  LoggerD("Entered");
+
+  nfc_se_card_emulation_mode_type_e new_mode;
+  PlatformResult result = NFCUtil::ToCardEmulationMode(mode, &new_mode);
+  if (result.IsError()) {
+    return result;
+  }
+  LoggerD("Card emulation mode value: %x", (int)new_mode);
+
+  std::string current_mode = "";
+  result = GetCardEmulationMode(&current_mode);
+
+  if (result.IsError()) {
+    LoggerD("Error: %s", result.message().c_str());
+    return result;
+  }
+
+  if (mode.compare(current_mode) == 0) {
+    LoggerD("Card emulation mode already set to given value (%s)",
+            mode.c_str());
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+
+  int ret = NFC_ERROR_NONE;
+  switch (new_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:
+      // Should never go here - in case of invalid mode
+      // platformResult is returned from convertert few lines above
+      LoggerE("Invalid card emulation mode: %s", mode.c_str());
+      return PlatformResult(ErrorCode::INVALID_VALUES_ERR,
+                            "Invalid card emulation mode given.");
+  }
+
+  if (NFC_ERROR_NONE != ret) {
+    LoggerE("Failed to set card emulation mode %d", ret);
+    return NFCUtil::CodeToResult(ret, "Failed to set card emulation mode");
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult NFCAdapter::GetActiveSecureElement(std::string* type) {
+  LoggerD("Entered");
+
+  nfc_se_type_e se_type = NFC_SE_TYPE_DISABLE;
+  int ret = nfc_manager_get_se_type(&se_type);
+  if (NFC_ERROR_NONE != ret) {
+    LoggerE("Failed to get active secure element type: %d", ret);
+    return NFCUtil::CodeToResult(ret,
+        "Unable to get active secure element type");
+  }
+
+  return NFCUtil::ToStringSecureElementType(se_type, type);
+}
+
+PlatformResult NFCAdapter::SetActiveSecureElement(std::string element) {
+  LoggerD("Entered");
+
+  // if given value is not correct secure element type then
+  // there's no sense to get current value for comparison
+  nfc_se_type_e new_type = NFC_SE_TYPE_DISABLE;
+  PlatformResult result = NFCUtil::ToSecureElementType(element, &new_type);
+
+  if (result.IsError()) {
+    LoggerD("Error: %s", result.message().c_str());
+    return result;
+  }
+  LoggerD("Secure element type value: %x", (int)new_type);
+
+  std::string current_type = "";
+  result = GetActiveSecureElement(&current_type);
+
+  if (result.IsError()) {
+    LoggerD("Error: %s", result.message().c_str());
+    return result;
+  }
+
+  if (element == current_type) {
+    LoggerD("Active secure element type already set to: %s", element.c_str());
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+
+  int ret = nfc_manager_set_se_type(new_type);
+  if (NFC_ERROR_NONE != ret) {
+    LoggerE("Failed to set active secure element type: %d", ret);
+    return NFCUtil::CodeToResult(ret,
+        "Unable to set active secure element type");
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult NFCAdapter::SetExclusiveModeForTransaction(bool exmode) {
+  LoggerD("Entered");
+
+  int ret = NFC_ERROR_NONE;
+  if (exmode) {
+    ret = nfc_manager_enable_transaction_fg_dispatch();
+  } else {
+    ret = nfc_manager_disable_transaction_fg_dispatch();
+  }
+
+  if (NFC_ERROR_NONE != ret) {
+    LoggerE("Failed to set exclusive mode for transaction: %d", ret);
+    return NFCUtil::CodeToResult(ret,
+        "Setting exclusive mode for transaction failed.");
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult NFCAdapter::AddCardEmulationModeChangeListener() {
+  LoggerD("Entered");
+  if (!m_is_listener_set) {
+    int ret = nfc_manager_set_se_event_cb(se_event_callback, nullptr);
+    if (NFC_ERROR_NONE != ret) {
+      LoggerE("AddCardEmulationModeChangeListener failed: %d", ret);
+      return NFCUtil::CodeToResult(ret,
+                                 NFCUtil::getNFCErrorMessage(ret).c_str());
+    }
+    m_is_listener_set = true;
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult NFCAdapter::RemoveCardEmulationModeChangeListener() {
+  LoggerD("Entered");
+  if (!nfc_manager_is_supported()) {
+    LoggerE("NFC Not Supported");
+    return PlatformResult(ErrorCode::NOT_SUPPORTED_ERR, "NFC Not Supported");
+  }
+
+  if (m_is_listener_set) {
+    nfc_manager_unset_se_event_cb();
+    m_is_listener_set = false;
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+
+PlatformResult NFCAdapter::AddTransactionEventListener(
+    const picojson::value& args) {
+  LoggerD("Entered");
+
+  nfc_se_type_e se_type = NFC_SE_TYPE_DISABLE;
+  PlatformResult result = NFCUtil::ToSecureElementType(
+      args.get(JSON_TYPE).get<string>(), &se_type);
+  if (result.IsError()) {
+    LoggerD("Error: %s", result.message().c_str());
+    return result;
+  }
+
+  int ret = NFC_ERROR_NONE;
+  if (NFC_SE_TYPE_ESE == se_type) {
+    if (!m_is_transaction_ese_listener_set) {
+      ret = nfc_manager_set_se_transaction_event_cb(se_type,
+          transaction_event_callback, NULL);
+      m_is_transaction_ese_listener_set = true;
+    }
+  } else if (NFC_SE_TYPE_UICC == se_type) {
+    if (!m_is_transaction_uicc_listener_set) {
+      ret = nfc_manager_set_se_transaction_event_cb(se_type,
+          transaction_event_callback, NULL);
+      m_is_transaction_uicc_listener_set = true;
+    }
+  } else if (NFC_SE_TYPE_HCE == se_type) {
+    if (!m_is_transaction_hce_listener_set) {
+      ret = nfc_manager_set_se_transaction_event_cb(se_type,
+          transaction_event_callback, NULL);
+      m_is_transaction_hce_listener_set = true;
+    }
+  }
+
+  if (NFC_ERROR_NONE != ret) {
+    LoggerE("AddTransactionEventListener failed: %d", ret);
+    return NFCUtil::CodeToResult(ret, NFCUtil::getNFCErrorMessage(ret).c_str());
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult NFCAdapter::RemoveTransactionEventListener(
+    const picojson::value& args) {
+  LoggerD("Entered");
+
+  nfc_se_type_e se_type = NFC_SE_TYPE_DISABLE;
+  PlatformResult result =
+      NFCUtil::ToSecureElementType(args.get(JSON_TYPE).get<string>(), &se_type);
+  if (result.IsError()) {
+    return result;
+  }
+
+  if (se_type == NFC_SE_TYPE_ESE) {
+    nfc_manager_unset_se_transaction_event_cb(se_type);
+    m_is_transaction_ese_listener_set = false;
+  } else if (se_type == NFC_SE_TYPE_UICC) {
+    nfc_manager_unset_se_transaction_event_cb(se_type);
+    m_is_transaction_uicc_listener_set = false;
+  } else if (se_type == NFC_SE_TYPE_HCE) {
+    nfc_manager_unset_se_transaction_event_cb(se_type);
+    m_is_transaction_hce_listener_set = false;
+  } else {
+    AssertMsg(false, "Invalid NFC SecureElement type");
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult NFCAdapter::AddActiveSecureElementChangeListener() {
+  LoggerD("Entered");
+  if (!m_is_listener_set) {
+    int ret = nfc_manager_set_se_event_cb(se_event_callback, nullptr);
+    if (NFC_ERROR_NONE != ret) {
+      LoggerE("AddActiveSecureElementChangeListener failed: %d", ret);
+      return NFCUtil::CodeToResult(ret,
+                                 NFCUtil::getNFCErrorMessage(ret).c_str());
+    }
+    m_is_listener_set = true;
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult NFCAdapter::RemoveActiveSecureElementChangeListener() {
+  LoggerD("Entered");
+  if (!nfc_manager_is_supported()) {
+    LoggerE("NFC Not Supported");
+    return PlatformResult(ErrorCode::NOT_SUPPORTED_ERR, "NFC Not Supported");
+  }
+
+  if (m_is_listener_set) {
+    nfc_manager_unset_se_event_cb();
+    m_is_listener_set = false;
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+void NFCAdapter::SetPeerHandle(nfc_p2p_target_h handle) {
+  LoggerD("Entered");
+  m_peer_handle = handle;
+}
+
+nfc_p2p_target_h NFCAdapter::GetPeerHandle() {
+  LoggerD("Entered");
+  return m_peer_handle;
+}
+
+int NFCAdapter::GetPeerId() {
+  LoggerD("Entered");
+  return m_latest_peer_id;
+}
+
+void NFCAdapter::IncreasePeerId() {
+  LoggerD("Entered");
+  m_latest_peer_id++;
+}
+
+PlatformResult NFCAdapter::PeerIsConnectedGetter(int peer_id, bool* state) {
+  LoggerD("Entered");
+  if (m_latest_peer_id != peer_id || !m_peer_handle) {
+    *state = false;
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+
+  nfc_p2p_target_h handle = NULL;
+  int ret = nfc_manager_get_connected_target(&handle);
+  if (NFC_ERROR_NONE != ret) {
+    LoggerE("Failed to get connected target handle: %d", ret);
+    return NFCUtil::CodeToResult(ret, "Failed to get connected target.");
+  }
+
+  *state = (m_peer_handle == handle);
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult NFCAdapter::SetPeerListener() {
+  LoggerD("Entered");
+  if (!nfc_manager_is_supported()) {
+    LoggerE("NFC Not Supported");
+    return PlatformResult(ErrorCode::NOT_SUPPORTED_ERR, "NFC Not Supported");
+  }
+
+  if (!m_is_peer_listener_set) {
+    int ret = nfc_manager_set_p2p_target_discovered_cb (targetDetectedCallback, NULL);
+    if (NFC_ERROR_NONE != ret) {
+      LoggerE("Failed to set listener: %d", ret);
+      return NFCUtil::CodeToResult(ret, "setPeerListener failed");
+    }
+    m_is_peer_listener_set = true;
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult NFCAdapter::UnsetPeerListener() {
+  LoggerD("Entered");
+  if (!nfc_manager_is_supported()) {
+    LoggerE("NFC Not Supported");
+    return PlatformResult(ErrorCode::NOT_SUPPORTED_ERR, "NFC Not Supported");
+  }
+
+  if (m_is_peer_listener_set) {
+    nfc_manager_unset_p2p_target_discovered_cb();
+    m_is_peer_listener_set = false;
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+static void targetReceivedCallback(nfc_p2p_target_h /*target*/,
+                                   nfc_ndef_message_h message,
+                                   void* /*data*/) {
+  LoggerD("Entered");
+  unsigned char* raw_data = NULL;
+  unsigned int size;
+  if (NFC_ERROR_NONE != nfc_ndef_message_get_rawdata(message, &raw_data, &size)) {
+    LoggerE("Unknown error while getting raw data of message.");
+    free(raw_data);
+    return;
+  }
+
+  picojson::value event = picojson::value(picojson::object());
+  picojson::object& obj = event.get<picojson::object>();
+  obj.insert(make_pair("listenerId", picojson::value("ReceiveNDEFListener")));
+  obj.insert(make_pair("id", picojson::value(static_cast<double>(NFCAdapter::GetInstance()->GetPeerId()))));
+
+  NFCMessageUtils::ReportNdefMessageFromData(raw_data, size, obj);
+
+  NFCAdapter::GetInstance()->RespondAsync(event.serialize().c_str());
+  free(raw_data);
+}
+
+PlatformResult NFCAdapter::SetReceiveNDEFListener(int peer_id) {
+  LoggerD("Entered");
+  //unregister previous NDEF listener
+  if (m_is_ndef_listener_set) {
+    int ret = nfc_p2p_unset_data_received_cb(m_peer_handle);
+    if (NFC_ERROR_NONE != ret) {
+      LoggerW("Unregister ReceiveNDEFListener error: %d", ret);
+    }
+    m_is_ndef_listener_set = false;
+  }
+
+  //check if peer object is still connected
+  bool is_connected = false;
+  PlatformResult result = PeerIsConnectedGetter(peer_id, &is_connected);
+  if (result.IsError()) {
+    LoggerD("Error: %s", result.message().c_str());
+    return result;
+  }
+
+  if (!is_connected) {
+    LoggerE("Target is not connected");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Target is not connected.");
+  }
+
+  int ret = nfc_p2p_set_data_received_cb(m_peer_handle, targetReceivedCallback, NULL);
+  if (NFC_ERROR_NONE != ret) {
+    LoggerE("Failed to set NDEF listener: %d", ret);
+    return NFCUtil::CodeToResult(ret, "Failed to set NDEF listener");
+  }
+
+  m_is_ndef_listener_set = true;
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult NFCAdapter::UnsetReceiveNDEFListener(int peer_id) {
+  LoggerD("Entered");
+  if (m_is_ndef_listener_set) {
+    //check if peer object is still connected
+
+    bool is_connected = false;
+    PlatformResult result = PeerIsConnectedGetter(peer_id, &is_connected);
+    if (result.IsError()) {
+      LoggerD("Error: %s", result.message().c_str());
+      return result;
+    }
+
+    if (!is_connected) {
+      LoggerE("Target is not connected");
+    }
+
+    int ret = nfc_p2p_unset_data_received_cb(m_peer_handle);
+    if (NFC_ERROR_NONE != ret) {
+      LoggerE("Unregister ReceiveNDEFListener error: %d", ret);
+      return NFCUtil::CodeToResult(ret, "Failed to set NDEF listener");
+    }
+
+    m_is_ndef_listener_set = false;
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+bool NFCAdapter::IsNDEFListenerSet() {
+  LoggerD("Entered");
+  return m_is_ndef_listener_set;
+}
+
+
+// NFCTag related functions
+PlatformResult NFCAdapter::TagTypeGetter(int /*tag_id*/, std::string* type) {
+  LoggerD("Entered");
+
+  nfc_tag_type_e nfc_type = NFC_UNKNOWN_TARGET;
+
+  int err = nfc_tag_get_type(m_last_tag_handle, &nfc_type);
+  if(NFC_ERROR_NONE != err) {
+    LoggerE("Failed to get tag type: %d", err);
+    return NFCUtil::CodeToResult(err, "Failed to get tag type");
+  }
+
+  *type = NFCUtil::ToStringNFCTag(nfc_type);
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult NFCAdapter::TagIsSupportedNDEFGetter(int /*tag_id*/,
+                                                    bool* is_supported) {
+  LoggerD("Entered");
+
+  int err = nfc_tag_is_support_ndef(m_last_tag_handle, is_supported);
+  if(NFC_ERROR_NONE != err) {
+    LoggerE("Failed to check if NDEF is supported %d", err);
+    return NFCUtil::CodeToResult(err,
+                               "Failed to check if NDEF is supported");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult NFCAdapter::TagNDEFSizeGetter(int /*tag_id*/,
+                                             unsigned int* size) {
+  LoggerD("Entered");
+
+  int err = nfc_tag_get_ndef_size(m_last_tag_handle, size);
+  if(NFC_ERROR_NONE != err) {
+    LoggerE("Failed to get tag NDEF size: %d, %s", err);
+    return NFCUtil::CodeToResult(err,
+                               "Failed to get tag NDEF size");
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+static bool tagPropertiesGetterCb(const char* key,
+                                  const unsigned char* value,
+                                  int value_size,
+                                  void* user_data) {
+  LoggerD("Entered");
+  if (user_data) {
+    UCharVector tag_info = NFCUtil::ToVector(value, value_size);
+    (static_cast<NFCTagPropertiesT*>(user_data))->push_back(
+        std::make_pair(key, tag_info));
+    return true;
+  }
+  return false;
+}
+
+PlatformResult NFCAdapter::TagPropertiesGetter(int /*tag_id*/,
+                                               NFCTagPropertiesT* properties) {
+  LoggerD("Entered");
+
+  int err = nfc_tag_foreach_information(m_last_tag_handle,
+                                        tagPropertiesGetterCb, (void*)properties);
+  if(NFC_ERROR_NONE != err) {
+    LoggerE("Error occured while getting NFC properties: %d", err);
+    return NFCUtil::CodeToResult(err,
+                               "Error occured while getting NFC properties");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult NFCAdapter::TagIsConnectedGetter(int tag_id, bool* state) {
+  LoggerD("Entered");
+
+  PlatformResult result = PlatformResult(ErrorCode::NO_ERROR);
+
+  if(tag_id != m_latest_tag_id || NULL == m_last_tag_handle) {
+    // internaly stored tag id changed -> new tag has been already connected
+    // internaly stored tag handle NULL -> tag has been disconnected
+    LoggerD("NFCTag () not connected (id differs or invalid handle)");
+    *state = false;
+    return result;
+  }
+
+  nfc_tag_h handle = NULL;
+  int ret = nfc_manager_get_connected_tag(&handle);
+  if(NFC_ERROR_NONE != ret) {
+    LoggerE("Failed to get connected tag: %s",
+            NFCUtil::getNFCErrorMessage(ret).c_str());
+    // exception is thrown here to return undefined in JS layer
+    // instead of false
+    return NFCUtil::CodeToResult(ret, "Failed to get connected tag");
+  }
+
+  if(m_last_tag_handle != handle) {
+    LoggerD("Last known handle and current handle differs");
+    *state = false;
+  } else {
+    *state = true;
+  }
+
+  return result;
+}
+
+int NFCAdapter::GetNextTagId() {
+  LoggerD("Entered");
+  return ++m_latest_tag_id;
+}
+
+
+static void tagEventCallback(nfc_discovered_type_e type,
+                             nfc_tag_h tag,
+                             void* /*data*/) {
+  LoggerD("Entered");
+
+  picojson::value event = picojson::value(picojson::object());
+  picojson::object& obj = event.get<picojson::object>();
+  obj.insert(make_pair("listenerId", picojson::value("TagListener")));
+
+  NFCAdapter* adapter = NFCAdapter::GetInstance();
+  // Tag detected event
+  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) {
+      LoggerE("setTagListener failed %d",result);
+      return;
+    }
+    // Fetch new id and set detected tag handle in NFCAdapter
+    int generated_id = adapter->GetNextTagId();
+    adapter->SetTagHandle(tag);
+
+    obj.insert(make_pair("action", picojson::value("onattach")));
+    obj.insert(make_pair("id", picojson::value(static_cast<double>(generated_id))));
+    obj.insert(make_pair("type", picojson::value(NFCUtil::ToStringNFCTag(tag_type))));
+
+    NFCAdapter::GetInstance()->RespondAsync(event.serialize().c_str());
+  }
+  // Tag disconnected event
+  else if (NFC_DISCOVERED_TYPE_DETACHED == type) {
+    // Set stored tag handle to NULL
+    adapter->SetTagHandle(NULL);
+
+    obj.insert(make_pair("action", picojson::value("ondetach")));
+    NFCAdapter::GetInstance()->RespondAsync(event.serialize().c_str());
+  }
+  // ERROR - should never happen
+  else {
+    LoggerE("Invalid NFC discovered type: %d (%x)", type, type);
+  }
+
+}
+
+PlatformResult  NFCAdapter::SetTagListener() {
+  LoggerD("Entered");
+
+  if (!m_is_tag_listener_set) {
+    nfc_manager_set_tag_filter(NFC_TAG_FILTER_ALL_ENABLE);
+    int result = nfc_manager_set_tag_discovered_cb (tagEventCallback, NULL);
+    if (NFC_ERROR_NONE != result) {
+      LoggerE("Failed to register tag listener: %d", result);
+      return NFCUtil::CodeToResult(result, "Failed to register tag listener.");
+    }
+    m_is_tag_listener_set = true;
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+void NFCAdapter::UnsetTagListener() {
+  LoggerD("Entered");
+
+  if(m_is_tag_listener_set) {
+    nfc_manager_unset_tag_discovered_cb();
+    m_is_tag_listener_set = false;
+  }
+}
+
+void NFCAdapter::SetTagHandle(nfc_tag_h tag) {
+  LoggerD("Entered");
+  m_last_tag_handle = tag;
+}
+
+static void tagReadNDEFCb(nfc_error_e result,
+                          nfc_ndef_message_h message,
+                          void* data) {
+  LoggerD("Entered");
+
+  if(!data) {
+    // Can not continue if unable to get callbackId
+    LoggerE("NULL callback id given");
+    return;
+  }
+
+  double callbackId = *((double*)data);
+  delete (double*)data;
+  data = NULL;
+
+  if(NFC_ERROR_NONE != result) {
+    // create exception and post error message (call error callback)
+    picojson::value event = CreateEventError(callbackId, PlatformResult(ErrorCode::UNKNOWN_ERR,
+                                                                        "Failed to read NDEF message"));
+    NFCAdapter::GetInstance()->RespondAsync(event.serialize().c_str());
+    return;
+  }
+
+  unsigned char* raw_data = NULL;
+  unsigned int size = 0;
+
+  int ret = nfc_ndef_message_get_rawdata(message, &raw_data, &size);
+  if(NFC_ERROR_NONE != ret) {
+    LoggerE("Failed to get message data: %d", ret);
+
+    // release data if any allocated
+    free(raw_data);
+
+    // create exception and post error message (call error callback)
+    picojson::value event = CreateEventError(callbackId, PlatformResult(ErrorCode::UNKNOWN_ERR,
+                                                                        "Failed to retrieve NDEF message data"));
+    NFCAdapter::GetInstance()->RespondAsync(event.serialize().c_str());
+    return;
+  }
+
+  // create success event, fill it with data and call success callback
+  picojson::value event = createEventSuccess(callbackId);
+  picojson::object& obj = event.get<picojson::object>();
+
+  NFCMessageUtils::ReportNdefMessageFromData(raw_data, size, obj);
+
+  NFCAdapter::GetInstance()->RespondAsync(event.serialize().c_str());
+  free(raw_data);
+}
+
+PlatformResult NFCAdapter::TagReadNDEF(int tag_id,
+                                       const picojson::value& args) {
+  LoggerD("Entered");
+
+  bool is_connected = false;
+  PlatformResult result = TagIsConnectedGetter(tag_id, &is_connected);
+  if (result.IsError()) {
+    return result;
+  }
+
+  double callbackId = args.get(JSON_CALLBACK_ID).get<double>();
+  LoggerD("Received callback id: %f", callbackId);
+
+  if(!is_connected) {
+    picojson::value event = CreateEventError(callbackId,
+                                             PlatformResult(ErrorCode::UNKNOWN_ERR,
+                                                            "Tag is no more connected."));
+    NFCAdapter::GetInstance()->RespondAsync(event.serialize().c_str());
+    return PlatformResult(ErrorCode::NO_ERROR);;
+  }
+
+  double* callbackIdPointer = new double(callbackId);
+  int ret = nfc_tag_read_ndef(m_last_tag_handle, tagReadNDEFCb,
+                                 (void*)(callbackIdPointer));
+  if(NFC_ERROR_NONE != ret) {
+    LoggerE("Failed to read NDEF message from tag: %d", ret);
+    delete callbackIdPointer;
+    callbackIdPointer = NULL;
+
+    // for permission related error throw exception ...
+    if(NFC_ERROR_SECURITY_RESTRICTED == ret ||
+        NFC_ERROR_PERMISSION_DENIED == ret) {
+      LoggerD("Error: %d", ret);
+      return PlatformResult(ErrorCode::SECURITY_ERR, "Failed to read NDEF - permission denied");
+    }
+
+    LoggerE("Preparing error callback to call");
+    // ... otherwise call error callback
+    std::string errMessage = NFCUtil::getNFCErrorMessage(ret);
+
+    result = NFCUtil::CodeToResult(ret, errMessage.c_str());
+
+    picojson::value event = CreateEventError(callbackId, result);
+    NFCAdapter::GetInstance()->RespondAsync(event.serialize().c_str());
+  }
+  delete callbackIdPointer;
+  callbackIdPointer = NULL;
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult NFCAdapter::TagWriteNDEF(int tag_id,
+                                        const picojson::value& args) {
+  LoggerD("Entered");
+
+  bool is_connected = false;
+  PlatformResult result = TagIsConnectedGetter(tag_id, &is_connected);
+  if (result.IsError()) {
+    LoggerD("Error: %s", result.message().c_str());
+    return result;
+  }
+
+  double callbackId = args.get(JSON_CALLBACK_ID).get<double>();
+  LoggerD("Received callback id: %f", callbackId);
+
+  if(!is_connected) {
+    picojson::value event = CreateEventError(callbackId,
+                                             PlatformResult(ErrorCode::UNKNOWN_ERR,
+                                                            "Tag is no more connected."));
+    NFCAdapter::GetInstance()->RespondAsync(event.serialize().c_str());
+    return PlatformResult(ErrorCode::NO_ERROR);;
+  }
+
+  const picojson::array& records_array = FromJson<picojson::array>(
+      args.get<picojson::object>(), "records");
+
+  const int size = static_cast<int>(args.get("recordsSize").get<double>());
+
+  nfc_ndef_message_h message = NULL;
+  result = NFCMessageUtils::NDEFMessageToStruct(records_array, size, &message);
+
+  if (result.IsError()) {
+    LoggerD("Error: %s", result.message().c_str());
+    return result;
+  }
+
+  if(message){
+    int ret = nfc_tag_write_ndef(m_last_tag_handle, message, NULL, NULL);
+
+    NFCMessageUtils::RemoveMessageHandle(message);
+    if (NFC_ERROR_NONE != ret){
+
+      // for permission related error throw exception
+      if(NFC_ERROR_SECURITY_RESTRICTED == ret ||
+          NFC_ERROR_PERMISSION_DENIED == ret) {
+        LoggerE("Error: %d", ret);
+        return PlatformResult(ErrorCode::SECURITY_ERR, "Failed to read NDEF - permission denied");
+      }
+
+      LoggerE("Error occured when sending message: %d", ret);
+      std::string errMessage = NFCUtil::getNFCErrorMessage(ret);
+
+      result = NFCUtil::CodeToResult(ret, errMessage.c_str());
+      picojson::value event = CreateEventError(callbackId, result);
+      // create and post error message
+      NFCAdapter::GetInstance()->RespondAsync(event.serialize().c_str());
+    }
+    else {
+      // create and post success message
+      picojson::value event = createEventSuccess(callbackId);
+      NFCAdapter::GetInstance()->RespondAsync(event.serialize().c_str());
+    }
+  } else {
+    LoggerE("Invalid message handle");
+    picojson::value event = CreateEventError(callbackId, PlatformResult(ErrorCode::INVALID_VALUES_ERR,
+                                                                        "Message is not valid"));
+    NFCAdapter::GetInstance()->RespondAsync(event.serialize().c_str());
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+static void tagTransceiveCb(nfc_error_e err,
+                            unsigned char* buffer,
+                            int buffer_size,
+                            void* data) {
+  LoggerD("Entered");
+  std::unique_ptr<unsigned char> buffer_ptr(buffer);
+  buffer = nullptr;
+
+  if (!data) {
+    // no callback id - unable to report success, neither error
+    LoggerE("Unable to launch transceive callback");
+    return;
+  }
+  double callback_id = *(reinterpret_cast<double*>(data));
+  delete reinterpret_cast<double*>(data);
+  data = nullptr;
+
+  if (NFC_ERROR_NONE != err) {
+
+    LoggerE("NFCTag transceive failed: %d", err);
+
+    // create exception and post error message (call error callback)
+    std::string error_message = NFCUtil::getNFCErrorMessage(err);
+
+    PlatformResult result = NFCUtil::CodeToResult(err, error_message.c_str());
+    picojson::value event = CreateEventError(callback_id, result);
+    NFCAdapter::GetInstance()->RespondAsync(event.serialize().c_str());
+    return;
+  }
+
+  // create result and push to JS layer
+  picojson::value response = createEventSuccess(callback_id);
+  picojson::object& response_obj = response.get<picojson::object>();
+  tools::ReportSuccess(response_obj);
+  response_obj[JSON_DATA] =
+      picojson::value(NFCUtil::FromUCharArray(buffer_ptr.get(), buffer_size));
+
+  NFCAdapter::GetInstance()->RespondAsync(response.serialize().c_str());
+}
+
+PlatformResult NFCAdapter::TagTransceive(int tag_id, const picojson::value& args) {
+
+  LoggerD("Entered");
+  bool is_connected = false;
+  PlatformResult result = TagIsConnectedGetter(tag_id, &is_connected);
+  if (result.IsError()) {
+    return result;
+  }
+
+  double callback_id = args.get(JSON_CALLBACK_ID).get<double>();
+  LoggerD("Received callback id: %f", callback_id);
+
+  if(!is_connected) {
+    picojson::value event = CreateEventError(callback_id,
+        PlatformResult(ErrorCode::UNKNOWN_ERR, "Tag is no more connected."));
+    NFCAdapter::GetInstance()->RespondAsync(event.serialize().c_str());
+    return PlatformResult(ErrorCode::NO_ERROR);;
+ }
+
+  const picojson::array& data_array = FromJson<picojson::array>(
+      args.get<picojson::object>(), JSON_DATA);
+
+  unsigned char* buffer = NFCUtil::DoubleArrayToUCharArray(data_array);
+  double* callback_id_pointer = new double(callback_id);
+
+  int ret = nfc_tag_transceive(m_last_tag_handle, buffer,
+      data_array.size(), tagTransceiveCb, (void*) callback_id_pointer);
+
+  if (NFC_ERROR_NONE != ret) {
+    delete callback_id_pointer;
+    callback_id_pointer = nullptr;
+    delete[] buffer;
+    buffer = nullptr;
+
+    // for permission related error throw exception
+    if(NFC_ERROR_SECURITY_RESTRICTED == ret ||
+        NFC_ERROR_PERMISSION_DENIED == ret) {
+      LoggerE("Error: %d", ret);
+      return PlatformResult(ErrorCode::SECURITY_ERR,
+          "Failed to read NDEF - permission denied");
+    }
+
+    std::string error_message = NFCUtil::getNFCErrorMessage(ret);
+
+    LoggerE("NFCTag transceive failed: %d", ret);
+
+    result = NFCUtil::CodeToResult(ret, error_message.c_str());
+    picojson::value event = CreateEventError(callback_id, result);
+    NFCAdapter::GetInstance()->RespondAsync(event.serialize().c_str());
+  }
+  delete callback_id_pointer;
+  callback_id_pointer = nullptr;
+  delete[] buffer;
+  buffer = nullptr;
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult NFCAdapter::GetCachedMessage(picojson::object& out) {
+  LoggerD("Entered");
+  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) {
+    LoggerE("Error: %d", result);
+    NFCMessageUtils::RemoveMessageHandle(message_handle);
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+  if (NFC_ERROR_NONE != result) {
+    LoggerE("Failed to get cached message: %d", result);
+    NFCMessageUtils::RemoveMessageHandle(message_handle);
+    return NFCUtil::CodeToResult(result, "Failed to get cached message");
+  }
+  unsigned char* raw_data = NULL;
+  unsigned int size;
+  if (NFC_ERROR_NONE != nfc_ndef_message_get_rawdata(message_handle,
+                                                     &raw_data, &size)) {
+    LoggerE("Unknown error while getting message.");
+    free(raw_data);
+    NFCMessageUtils::RemoveMessageHandle(message_handle);
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+  PlatformResult ret = NFCMessageUtils::ReportNdefMessageFromData(raw_data,
+      size, out);
+  free(raw_data);
+  if (ret.IsError()) {
+    LoggerE("Error: %d", ret.message().c_str());
+    NFCMessageUtils::RemoveMessageHandle(message_handle);
+    return ret;
+  }
+  NFCMessageUtils::RemoveMessageHandle(message_handle);
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+static void peerSentCallback(nfc_error_e result, void* user_data) {
+  LoggerD("Entered");
+  double* callbackId = static_cast<double*>(user_data);
+
+  if (NFC_ERROR_NONE != result){
+    LoggerE("Error: %d", result);
+    std::string error_message = NFCUtil::getNFCErrorMessage(result);
+
+    PlatformResult ret = NFCUtil::CodeToResult(result, error_message.c_str());
+    picojson::value event = CreateEventError(*callbackId, ret);
+    NFCAdapter::GetInstance()->RespondAsync(event.serialize().c_str());
+  } else {
+    picojson::value event = createEventSuccess(*callbackId);
+    NFCAdapter::GetInstance()->RespondAsync(event.serialize().c_str());
+  }
+
+  delete callbackId;
+  callbackId = NULL;
+}
+
+static gboolean sendNDEFErrorCB(void* user_data) {
+  LoggerD("Entered");
+  peerSentCallback(NFC_ERROR_INVALID_NDEF_MESSAGE, user_data);
+  return false;
+}
+
+PlatformResult NFCAdapter::sendNDEF(int peer_id, const picojson::value& args) {
+  LoggerD("Entered");
+  bool is_connected = false;
+  PlatformResult result = PeerIsConnectedGetter(peer_id, &is_connected);
+  if (result.IsError()) {
+    LoggerE("Error: %s", result.message().c_str());
+    return result;
+  }
+
+  double* callbackId = new double(args.get(JSON_CALLBACK_ID).get<double>());
+
+  if (!is_connected) {
+    picojson::value event = CreateEventError(*callbackId,
+        PlatformResult(ErrorCode::UNKNOWN_ERR, "Peer is no more connected"));
+    NFCAdapter::GetInstance()->RespondAsync(event.serialize().c_str());
+    delete callbackId;
+    callbackId = NULL;
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+
+  const picojson::array& records_array =
+      FromJson<picojson::array>(args.get<picojson::object>(), "records");
+  const int size = static_cast<int>(args.get("recordsSize").get<double>());
+
+  nfc_ndef_message_h message = NULL;
+  result = NFCMessageUtils::NDEFMessageToStruct(
+      records_array, size, &message);
+  if (message) {
+    int ret = nfc_p2p_send(m_peer_handle, message, peerSentCallback,
+        static_cast<void*>(callbackId));
+    NFCMessageUtils::RemoveMessageHandle(message);
+    if (NFC_ERROR_NONE != ret) {
+      LoggerE("sendNDEF failed %d",ret);
+      delete callbackId;
+      callbackId = NULL;
+      return NFCUtil::CodeToResult(ret, "sendNDEF failed.");
+    }
+  } else {
+    if (!g_idle_add(sendNDEFErrorCB, static_cast<void*>(callbackId))) {
+      LoggerE("g_idle addition failed");
+      delete callbackId;
+      callbackId = NULL;
+    }
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+void NFCAdapter::SetSEHandle(nfc_se_h handle) {
+  LoggerD("Entered");
+  m_se_handle = handle;
+}
+
+nfc_se_h NFCAdapter::GetSEHandle() {
+  LoggerD("Entered");
+  return m_se_handle;
+}
+
+PlatformResult NFCAdapter::AddHCEEventListener() {
+  LoggerD("Entered");
+  if (!m_is_hce_listener_set) {
+    int ret = nfc_manager_set_hce_event_cb(HCEEventCallback, nullptr);
+    if (NFC_ERROR_NONE != ret) {
+      LoggerE("AddHCEEventListener failed: %d", ret);
+      return NFCUtil::CodeToResult(ret,
+          NFCUtil::getNFCErrorMessage(ret).c_str());
+    }
+    m_is_hce_listener_set = true;
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult NFCAdapter::RemoveHCEEventListener() {
+  LoggerD("Entered");
+  if (m_is_hce_listener_set) {
+    nfc_manager_unset_hce_event_cb();
+    m_is_hce_listener_set = false;
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+void NFCAdapter::SendHostAPDUResponse(
+    const UCharVector& apdu,
+    const std::function<void()>& success_cb,
+    const std::function<void(const PlatformResult&)>& error_cb) {
+  LoggerD("Entered");
+
+  if (!nfc_manager_is_supported()) {
+    LoggerE("NFC Not Supported");
+    error_cb(PlatformResult(ErrorCode::NOT_SUPPORTED_ERR, "NFC Not Supported"));
+    return;
+  }
+
+  int ret = nfc_hce_send_apdu_response(m_se_handle,
+      const_cast<unsigned char*>(apdu.data()),
+      static_cast<unsigned int>(apdu.size()));
+  if (NFC_ERROR_NONE == ret) {
+    success_cb();
+  } else {
+    LoggerE("Error: %d", ret);
+    error_cb(
+        NFCUtil::CodeToResult(ret, NFCUtil::getNFCErrorMessage(ret).c_str()));
+  }
+}
+
+PlatformResult NFCAdapter::IsActivatedHandlerForAID(
+    const std::string& type,
+    const std::string& aid,
+    bool* is_activated_handler) {
+  AssertMsg(is_activated_handler, "Poiner can not be null!");
+  LoggerD("Entered");
+
+  nfc_se_type_e se_type;
+  PlatformResult result = NFCUtil::ToSecureElementType(type, &se_type);
+  if (!result.IsError()) {
+    LoggerE("Error: %s", result.message().c_str());
+    return result;
+  }
+
+  int ret = nfc_se_is_activated_handler_for_aid(se_type,
+                                                aid.c_str(),
+                                                is_activated_handler);
+  if (NFC_ERROR_NONE != ret) {
+    LoggerE("IsActivatedHandlerForAID failed: %d", ret);
+    return NFCUtil::CodeToResult(ret,
+        NFCUtil::getNFCErrorMessage(ret).c_str());
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult NFCAdapter::IsActivatedHandlerForCategory(
+    const std::string& type,
+    nfc_card_emulation_category_type_e category,
+    bool* is_activated_handler) {
+  LoggerD("Entered");
+  AssertMsg(is_activated_handler, "Poiner can not be null!");
+
+  nfc_se_type_e se_type;
+  PlatformResult result = NFCUtil::ToSecureElementType(type, &se_type);
+  if (!result.IsError()) {
+    LoggerE("Error: %s", result.message().c_str());
+    return result;
+  }
+
+  int ret = nfc_se_is_activated_handler_for_category(se_type,
+                                                     category,
+                                                     is_activated_handler);
+  if (NFC_ERROR_NONE != ret) {
+    LoggerE("IsActivatedHandlerForCategory failed: %d", ret);
+    return NFCUtil::CodeToResult(ret,
+        NFCUtil::getNFCErrorMessage(ret).c_str());
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult NFCAdapter::RegisterAID(
+    const std::string& type,
+    const std::string& aid,
+    nfc_card_emulation_category_type_e category) {
+  LoggerD("Entered");
+  nfc_se_type_e se_type;
+  PlatformResult result = NFCUtil::ToSecureElementType(type, &se_type);
+  if (!result.IsError()) {
+    LoggerE("Error: %s", result.message().c_str());
+    return result;
+  }
+
+  int ret = nfc_se_register_aid(se_type, category, aid.c_str());
+  if (NFC_ERROR_NONE != ret) {
+    LoggerE("RegisterAID failed: %d", ret);
+    return NFCUtil::CodeToResult(ret,
+        NFCUtil::getNFCErrorMessage(ret).c_str());
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult NFCAdapter::UnregisterAID(
+    const std::string& type,
+    const std::string& aid,
+    nfc_card_emulation_category_type_e category) {
+  LoggerD("Entered");
+  nfc_se_type_e se_type;
+  PlatformResult result = NFCUtil::ToSecureElementType(type, &se_type);
+  if (!result.IsError()) {
+    LoggerE("Error: %s", result.message().c_str());
+    return result;
+  }
+
+  int ret = nfc_se_unregister_aid(se_type, category, aid.c_str());
+  if (NFC_ERROR_NONE != ret) {
+    LoggerE("UnregisterAID failed: %d", ret);
+    return NFCUtil::CodeToResult(ret,
+        NFCUtil::getNFCErrorMessage(ret).c_str());
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+static void SaveRow(nfc_se_type_e se_type,
+                   const char* aid,
+                   bool read_only,
+                   void* user_data) {
+  LoggerD("Entered");
+  AssertMsg(aid, "Poiner can not be null!");
+  AssertMsg(user_data, "Poiner can not be null!");
+  AIDDataVector* aids = static_cast<AIDDataVector*>(user_data);
+  aids->push_back(AIDData(se_type, aid, read_only));
+};
+
+void NFCAdapter::GetAIDsForCategory(
+    const std::string& type,
+    nfc_card_emulation_category_type_e category,
+    const std::function<void(const AIDDataVector&)>& success_cb,
+    const std::function<void(const PlatformResult&)>& error_cb) {
+  LoggerD("Entered");
+  nfc_se_type_e se_type;
+  PlatformResult result = NFCUtil::ToSecureElementType(type, &se_type);
+  if (!result.IsError()) {
+    LoggerE("Error: %s", result.message().c_str());
+    error_cb(result);
+    return;
+  }
+
+  AIDDataVector aids{};
+  int ret = nfc_se_foreach_registered_aids(se_type, category, SaveRow, &aids);
+  if (NFC_ERROR_NONE != ret) {
+    LoggerE("GetAIDsForCategory failed: %d", ret);
+    error_cb(NFCUtil::CodeToResult(ret,
+        NFCUtil::getNFCErrorMessage(ret).c_str()));
+  }
+  success_cb(aids);
+}
+
+}// nfc
+}// extension
diff --git a/webWidgetTCT_device/src/nfc/nfc_adapter.h b/webWidgetTCT_device/src/nfc/nfc_adapter.h
new file mode 100755 (executable)
index 0000000..cec14c9
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2015 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 NFC_NFC_ADAPTER_H_
+#define NFC_NFC_ADAPTER_H_
+
+#ifdef APP_CONTROL_SETTINGS_SUPPORT
+#include <app_control.h>
+#endif
+#include <network/nfc.h>
+
+#include <list>
+#include <memory>
+
+#include "common/picojson.h"
+#include "common/platform_result.h"
+#include "nfc/aid_data.h"
+#include "nfc/nfc_util.h"
+
+namespace extension {
+namespace nfc {
+
+typedef std::list<std::pair<std::string, UCharVector>> NFCTagPropertiesT;
+
+class NFCAdapter {
+ public:
+  static NFCAdapter* GetInstance();
+
+  // Interface provides method PostMessage() that returns asynchronous response.
+  class IResponder {
+  public:
+    virtual void RespondAsync(const char* msg) = 0;
+  };
+
+  void SetResponder(IResponder* responder);
+  void RespondAsync(const char* msg);
+
+  bool GetPowered();
+  common::PlatformResult SetPowered(const picojson::value& args);
+
+  // cardEmulationMode getter and setter
+  common::PlatformResult GetCardEmulationMode(std::string* mode);
+  common::PlatformResult SetCardEmulationMode(const std::string& mode);
+  // activeSecureElement getter and setter
+  common::PlatformResult GetActiveSecureElement(std::string* type);
+  common::PlatformResult SetActiveSecureElement(std::string element);
+
+  // Adapter methods
+  common::PlatformResult  SetExclusiveModeForTransaction(bool exmode);
+
+  common::PlatformResult AddCardEmulationModeChangeListener();
+  common::PlatformResult RemoveCardEmulationModeChangeListener();
+  common::PlatformResult AddTransactionEventListener(const picojson::value& args);
+  common::PlatformResult RemoveTransactionEventListener(const picojson::value& args);
+  common::PlatformResult AddActiveSecureElementChangeListener();
+  common::PlatformResult RemoveActiveSecureElementChangeListener();
+  common::PlatformResult GetCachedMessage(picojson::object& out);
+
+  void SetPeerHandle(nfc_p2p_target_h handle);
+  nfc_p2p_target_h GetPeerHandle();
+  int GetPeerId();
+  void IncreasePeerId();
+  common::PlatformResult PeerIsConnectedGetter(int peer_id, bool* state);
+  common::PlatformResult SetPeerListener();
+  common::PlatformResult UnsetPeerListener();
+  common::PlatformResult SetReceiveNDEFListener(int peer_id);
+  common::PlatformResult UnsetReceiveNDEFListener(int peer_id);
+  common::PlatformResult sendNDEF(int peer_id, const picojson::value& args);
+  bool IsNDEFListenerSet();
+
+  // NFCTag related methods
+  // attributes
+  common::PlatformResult TagTypeGetter(int tag_id, std::string* type);
+  common::PlatformResult TagIsSupportedNDEFGetter(int tag_id, bool* is_supported);
+  common::PlatformResult TagNDEFSizeGetter(int tag_id, unsigned int* size);
+  common::PlatformResult TagPropertiesGetter(int tag_id, NFCTagPropertiesT* properties);
+  common::PlatformResult TagIsConnectedGetter(int tag_id, bool* state);
+  // methods
+  common::PlatformResult TagReadNDEF(int tag_id, const picojson::value& args);
+  common::PlatformResult TagWriteNDEF(int tag_id, const picojson::value& args);
+  common::PlatformResult TagTransceive(int tag_id, const picojson::value& args);
+  // listeners
+  common::PlatformResult SetTagListener();
+  void UnsetTagListener();
+  int GetNextTagId();
+  void SetTagHandle(nfc_tag_h tag);
+
+  // HCE
+  void SetSEHandle(nfc_se_h handle);
+  nfc_se_h GetSEHandle();
+  common::PlatformResult AddHCEEventListener();
+  common::PlatformResult RemoveHCEEventListener();
+  void SendHostAPDUResponse(
+      const UCharVector& apdu,
+      const std::function<void()>& success_cb,
+      const std::function<void(const common::PlatformResult&)>& error_cb);
+  common::PlatformResult IsActivatedHandlerForAID(const std::string& type,
+                                                  const std::string& aid,
+                                                  bool* is_activated_handler);
+  common::PlatformResult IsActivatedHandlerForCategory(
+      const std::string& type,
+      nfc_card_emulation_category_type_e category,
+      bool* is_activated_handler);
+  common::PlatformResult RegisterAID(
+      const std::string& type,
+      const std::string& aid,
+      nfc_card_emulation_category_type_e category);
+  common::PlatformResult UnregisterAID(
+      const std::string& type,
+      const std::string& aid,
+      nfc_card_emulation_category_type_e category);
+  void GetAIDsForCategory(
+      const std::string& type,
+      nfc_card_emulation_category_type_e category,
+      const std::function<void(const AIDDataVector&)>& success_cb,
+      const std::function<void(const common::PlatformResult&)>& error_cb);
+
+
+ private:
+  NFCAdapter();
+  virtual ~NFCAdapter();
+
+  nfc_tag_h m_last_tag_handle;
+  bool m_is_tag_listener_set;
+  int m_latest_tag_id;
+  bool m_is_listener_set;
+  bool m_is_transaction_ese_listener_set;
+  bool m_is_transaction_uicc_listener_set;
+  bool m_is_transaction_hce_listener_set;
+  bool m_is_peer_listener_set;
+  int m_latest_peer_id;
+  nfc_p2p_target_h m_peer_handle;
+  bool m_is_ndef_listener_set;
+  nfc_se_h m_se_handle;
+  bool m_is_hce_listener_set;
+
+  IResponder* responder_;
+};
+
+} // nfc
+} // extension
+
+#endif // NFC_NFC_ADAPTER_H_
diff --git a/webWidgetTCT_device/src/nfc/nfc_api.js b/webWidgetTCT_device/src/nfc/nfc_api.js
new file mode 100755 (executable)
index 0000000..2522eca
--- /dev/null
@@ -0,0 +1,1503 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+var validator_ = xwalk.utils.validator;
+var types_ = validator_.Types;
+var type_ = xwalk.utils.type;
+var converter_ = xwalk.utils.converter;
+var native_ = new xwalk.utils.NativeManager(extension);
+
+
+var NDEFRecordTextEncoding = {
+  UTF8: 'UTF8',
+  UTF16: 'UTF16'
+};
+
+var NFCTagType = {
+  GENERIC_TARGET: 'GENERIC_TARGET',
+  ISO14443_A: 'ISO14443_A',
+  ISO14443_4A: 'ISO14443_4A',
+  ISO14443_3A: 'ISO14443_3A',
+  MIFARE_MINI: 'MIFARE_MINI',
+  MIFARE_1K: 'MIFARE_1K',
+  MIFARE_4K: 'MIFARE_4K',
+  MIFARE_ULTRA: 'MIFARE_ULTRA',
+  MIFARE_DESFIRE: 'MIFARE_DESFIRE',
+  ISO14443_B: 'ISO14443_B',
+  ISO14443_4B: 'ISO14443_4B',
+  ISO14443_BPRIME: 'ISO14443_BPRIME',
+  FELICA: 'FELICA',
+  JEWEL: 'JEWEL',
+  ISO15693: 'ISO15693',
+  UNKNOWN_TARGET: 'UNKNOWN_TARGET'
+};
+
+var CardEmulationMode = {
+  ALWAYS_ON: 'ALWAYS_ON',
+  OFF: 'OFF'
+};
+
+var SecureElementType = {
+  ESE: 'ESE',
+  UICC: 'UICC',
+  HCE: 'HCE'
+};
+
+var CardEmulationCategoryType = {
+  PAYMENT: 'PAYMENT',
+  OTHER: 'OTHER'
+};
+
+var HCEEventType = {
+  DEACTIVATED: 'DEACTIVATED',
+  ACTIVATED: 'ACTIVATED',
+  APDU_RECEIVED: 'APDU_RECEIVED'
+};
+
+function HCEEventData(data) {
+  Object.defineProperties(this, {
+    eventType: {
+      value: data.eventType,
+      writable: false,
+      enumerable: true
+    },
+    apdu: {
+      value: data.apdu || [],
+      writable: false,
+      enumerable: true
+    },
+    length: {
+      value: data.length || 0,
+      writable: false,
+      enumerable: true
+    }
+  });
+}
+
+function ListenerManager(native, listenerName) {
+  this.listeners = {};
+  this.nextId = 1;
+  this.nativeSet = false;
+  this.native = native;
+  this.listenerName = listenerName;
+}
+
+ListenerManager.prototype.onListenerCalled = function(msg) {
+  for (var key in this.listeners) {
+    if (this.listeners.hasOwnProperty(key)) {
+      if ('CardElement' === msg.type) {
+        this.listeners[key](msg.mode);
+      } else if ('Transaction' === msg.type) {
+        this.listeners[key](msg.aid, msg.data);
+      } else if('HCEEventData' === msg.type) {
+        var hceData = new HCEEventData(msg.result);
+        this.listeners[key](hceData);
+      }
+    }
+  }
+};
+
+ListenerManager.prototype.addListener = function(callback) {
+  var id = this.nextId;
+  if (!this.nativeSet) {
+    this.native.addListener(this.listenerName, this.onListenerCalled.bind(this));
+    this.nativeSet = true;
+  }
+  this.listeners[id] = callback;
+  ++this.nextId;
+  return id;
+};
+
+ListenerManager.prototype.removeListener = function(watchId) {
+  if (this.listeners.hasOwnProperty(watchId)) {
+    delete this.listeners[watchId];
+  }
+};
+
+var PEER_LISTENER = 'PeerListener';
+var RECEIVE_NDEF_LISTENER = 'ReceiveNDEFListener';
+var CARD_EMULATION_MODE_LISTENER = 'CardEmulationModeChanged';
+var ACTIVE_SECURE_ELEMENT_LISTENER = 'ActiveSecureElementChanged';
+var TRANSACTION_EVENT_ESE_LISTENER = 'TransactionEventListener_ESE';
+var TRANSACTION_EVENT_UICC_LISTENER = 'TransactionEventListener_UICC';
+var HCE_EVENT_LISTENER = 'HCEEventListener';
+var TAG_LISTENER = 'TagListener';
+var cardEmulationModeListener = new ListenerManager(native_, CARD_EMULATION_MODE_LISTENER);
+var activeSecureElementChangeListener = new ListenerManager(native_, ACTIVE_SECURE_ELEMENT_LISTENER);
+var transactionEventListenerEse = new ListenerManager(native_, TRANSACTION_EVENT_ESE_LISTENER);
+var transactionEventListenerUicc = new ListenerManager(native_, TRANSACTION_EVENT_UICC_LISTENER);
+var HCEEventListener = new ListenerManager(native_, HCE_EVENT_LISTENER);
+
+
+//////////////////NFCManager /////////////////
+
+function NFCManager() {
+  Object.defineProperties(this, {
+    NFC_RECORD_TNF_EMPTY: {value: 0, writable: false, enumerable: true},
+    NFC_RECORD_TNF_WELL_KNOWN: {value: 1, writable: false, enumerable: true},
+    NFC_RECORD_TNF_MIME_MEDIA: {value: 2, writable: false, enumerable: true},
+    NFC_RECORD_TNF_URI: {value: 3, writable: false, enumerable: true},
+    NFC_RECORD_TNF_EXTERNAL_RTD: {value: 4, writable: false, enumerable: true},
+    NFC_RECORD_TNF_UNKNOWN: {value: 5, writable: false, enumerable: true},
+    NFC_RECORD_TNF_UNCHANGED: {value: 6, writable: false, enumerable: true}
+  });
+}
+
+NFCManager.prototype.getDefaultAdapter = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.NFC_COMMON);
+
+  // First check NFC suppor on C++ level
+  var result = native_.callSync(
+      'NFCManager_getDefaultAdapter',
+      {}
+      );
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+
+  // If NFC is supported then return new NFCAdapter instance
+  return new NFCAdapter();
+};
+
+NFCManager.prototype.setExclusiveMode = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.NFC_COMMON);
+
+  var args = validator_.validateArgs(arguments, [
+    {name: 'exclusiveMode', type: types_.BOOLEAN}
+  ]);
+
+  var result = native_.callSync('NFCManager_setExclusiveMode', {
+    exclusiveMode: args.exclusiveMode
+  });
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+};
+
+//////////////////NFCAdapter /////////////////
+
+function NFCAdapter() {
+  function poweredGetter() {
+    var ret = native_.callSync('NFCAdapter_getPowered');
+
+    if (native_.isFailure(ret)) {
+      return false;
+    }
+
+    return native_.getResultObject(ret);
+  }
+
+  function cardEmulationModeGetter() {
+    xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.NFC_CARDEMULATION);
+
+    var result = native_.callSync('NFCAdapter_cardEmulationModeGetter');
+
+    if (native_.isFailure(result)) {
+      throw native_.getErrorObject(result);
+    }
+
+    return native_.getResultObject(result);
+  }
+
+  function cardEmulationModeSetter(cem) {
+    xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.NFC_CARDEMULATION);
+
+    var args = validator_.validateArgs(arguments, [
+      {name: 'emulationMode', type: types_.STRING}
+    ]);
+
+    var result = native_.callSync(
+        'NFCAdapter_cardEmulationModeSetter',
+        { 'emulationMode': args.emulationMode}
+        );
+
+    if (native_.isFailure(result)) {
+      throw native_.getErrorObject(result);
+    }
+    return;
+  }
+
+  function activeSecureElementGetter() {
+    xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.NFC_CARDEMULATION);
+
+    var result = native_.callSync('NFCAdapter_activeSecureElementGetter');
+
+    if (native_.isFailure(result)) {
+      throw native_.getErrorObject(result);
+    }
+
+    return native_.getResultObject(result);
+  }
+
+  function activeSecureElementSetter(ase) {
+    xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.NFC_CARDEMULATION);
+
+    var args = validator_.validateArgs(arguments, [
+      {name: 'secureElement', type: types_.STRING}
+    ]);
+
+    var result = native_.callSync(
+        'NFCAdapter_activeSecureElementSetter',
+        { 'secureElement': args.secureElement}
+        );
+
+    if (native_.isFailure(result)) {
+      throw native_.getErrorObject(result);
+    }
+    return;
+  }
+
+  Object.defineProperties(this, {
+    powered: {enumerable: true,
+      set: function() {},
+      get: poweredGetter
+    },
+    cardEmulationMode: {enumerable: true,
+      set: cardEmulationModeSetter,
+      get: cardEmulationModeGetter
+    },
+    activeSecureElement: {enumerable: true,
+      set: activeSecureElementSetter,
+      get: activeSecureElementGetter
+    }
+  });
+}
+
+NFCAdapter.prototype.setPowered = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.NFC_ADMIN);
+
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'powered',
+      type: types_.BOOLEAN
+    },
+    {
+      name: 'successCallback',
+      type: types_.FUNCTION,
+      optional: true,
+      nullable: true
+    },
+    {
+      name: 'errorCallback',
+      type: types_.FUNCTION,
+      optional: true,
+      nullable: true
+    }
+  ]);
+
+  native_.call('NFCAdapter_setPowered', {
+    powered: args.powered
+  }, function(result) {
+    if (native_.isFailure(result)) {
+      args.errorCallback(result.error);
+    } else {
+      args.successCallback();
+    }
+  });
+};
+
+NFCAdapter.prototype.setTagListener = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.NFC_TAG);
+
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'listener',
+      type: types_.LISTENER,
+      values: ['onattach', 'ondetach']
+    },
+    {
+      name: 'tagType',
+      type: types_.ARRAY,
+      values: types_.STRING,
+      optional: true,
+      nullable: true
+    }
+  ]);
+
+  if (!type_.isNullOrUndefined(args.tagType)) {
+    for (var i = 0; i < args.tagType.length; i++) {
+      if (NFCTagType[args.tagType[i]] === undefined) {
+        throw new WebAPIException(
+            WebAPIException.TYPE_MISMATCH_ERR, 'Invalid tag type.');
+      }
+    }
+  }
+
+  // Listener object creation
+  var listenerCallback = function(message) {
+    var tagObject = undefined;
+
+    if ('onattach' === message.action) {
+      tagObject = new NFCTag(message.id);
+
+      // If filter is set for listener but tag type is not searched one
+      if (!type_.isNullOrUndefined(args.tagType) &&
+          args.tagType.indexOf(tagObject.type) < 0) {
+        return;
+      }
+    }
+    args.listener[message.action](tagObject);
+  };
+
+  // Register (acivate) core listener if not done yet
+  if (!native_.isListenerSet(TAG_LISTENER)) {
+    var result = native_.callSync('NFCAdapter_setTagListener');
+    if (native_.isFailure(result)) {
+      throw native_.getErrorObject(result);
+    }
+  }
+
+  native_.addListener(TAG_LISTENER, listenerCallback);
+  return;
+};
+
+NFCAdapter.prototype.setPeerListener = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.NFC_P2P);
+
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'listener',
+      type: types_.LISTENER,
+      values: ['onattach', 'ondetach']
+    }
+  ]);
+
+  var listener = function(msg) {
+    var data = undefined;
+    if ('onattach' === msg.action) {
+      data = new NFCPeer(msg.id);
+    }
+    args.listener[msg.action](data);
+  };
+
+  if (!native_.isListenerSet(PEER_LISTENER)) {
+    var result = native_.callSync('NFCAdapter_setPeerListener');
+    if (native_.isFailure(result)) {
+      throw native_.getErrorObject(result);
+    }
+  }
+
+  native_.addListener(PEER_LISTENER, listener);
+  return;
+};
+
+NFCAdapter.prototype.unsetTagListener = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.NFC_TAG);
+
+  native_.removeListener(TAG_LISTENER);
+
+  var result = native_.callSync('NFCAdapter_unsetTagListener');
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+
+  return;
+};
+
+NFCAdapter.prototype.unsetPeerListener = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.NFC_P2P);
+
+  native_.removeListener(PEER_LISTENER);
+
+  var result = native_.callSync('NFCAdapter_unsetPeerListener');
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+
+  return;
+};
+
+NFCAdapter.prototype.addCardEmulationModeChangeListener = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.NFC_CARDEMULATION);
+
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'callback',
+      type: types_.FUNCTION
+    }
+  ]);
+
+  if (type_.isEmptyObject(cardEmulationModeListener.listeners) &&
+      type_.isEmptyObject(activeSecureElementChangeListener.listeners)) {
+    var result = native_.callSync(
+        'NFCAdapter_addCardEmulationModeChangeListener');
+    if (native_.isFailure(result)) {
+      throw native_.getErrorObject(result);
+    }
+  }
+
+  return cardEmulationModeListener.addListener(args.callback);
+};
+
+NFCAdapter.prototype.removeCardEmulationModeChangeListener = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.NFC_CARDEMULATION);
+
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'listenerId',
+      type: types_.LONG
+    }
+  ]);
+  cardEmulationModeListener.removeListener(args.listenerId);
+
+  if (type_.isEmptyObject(cardEmulationModeListener.listeners) &&
+      type_.isEmptyObject(activeSecureElementChangeListener.listeners)) {
+    native_.callSync('NFCAdapter_removeCardEmulationModeChangeListener');
+  }
+};
+
+NFCAdapter.prototype.addTransactionEventListener = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.NFC_CARDEMULATION);
+
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'type',
+      type: types_.ENUM,
+      values: type_.getValues(SecureElementType)
+    },
+    {
+      name: 'callback',
+      type: types_.FUNCTION
+    }
+  ]);
+
+  var result;
+
+  if (SecureElementType.ESE === args.type) {
+    if (type_.isEmptyObject(transactionEventListenerEse.listeners)) {
+      result = native_.callSync('NFCAdapter_addTransactionEventListener', {
+        type: args.type});
+      if (native_.isFailure(result)) {
+        throw native_.getErrorObject(result);
+      }
+    }
+    return transactionEventListenerEse.addListener(args.callback);
+  } else {
+    if (type_.isEmptyObject(transactionEventListenerUicc.listeners)) {
+      result = native_.callSync('NFCAdapter_addTransactionEventListener', {
+        type: args.type});
+      if (native_.isFailure(result)) {
+        throw native_.getErrorObject(result);
+      }
+    }
+    return transactionEventListenerUicc.addListener(args.callback);
+  }
+};
+
+NFCAdapter.prototype.removeTransactionEventListener = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.NFC_CARDEMULATION);
+
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'watchId',
+      type: types_.LONG
+    }
+  ]);
+
+  var ese_empty = type_.isEmptyObject(transactionEventListenerEse.listeners);
+  var uicc_empty = type_.isEmptyObject(transactionEventListenerUicc.listeners);
+
+  transactionEventListenerEse.removeListener(args.watchId);
+  transactionEventListenerUicc.removeListener(args.watchId);
+
+  if (type_.isEmptyObject(transactionEventListenerEse.listeners) && !ese_empty) {
+    native_.callSync('NFCAdapter_removeTransactionEventListener', {
+      type: SecureElementType.ESE});
+  }
+
+  if (type_.isEmptyObject(transactionEventListenerUicc.listeners)
+            && !uicc_empty) {
+    native_.callSync('NFCAdapter_removeTransactionEventListener', {
+      type: SecureElementType.UICC});
+  }
+
+};
+
+NFCAdapter.prototype.addActiveSecureElementChangeListener = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.NFC_CARDEMULATION);
+
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'callback',
+      type: types_.FUNCTION
+    }
+  ]);
+
+  if (type_.isEmptyObject(cardEmulationModeListener.listeners) &&
+      type_.isEmptyObject(activeSecureElementChangeListener.listeners)) {
+    var result = native_.callSync(
+        'NFCAdapter_addActiveSecureElementChangeListener');
+    if (native_.isFailure(result)) {
+      throw native_.getErrorObject(result);
+    }
+  }
+
+  return activeSecureElementChangeListener.addListener(args.callback);
+};
+
+NFCAdapter.prototype.removeActiveSecureElementChangeListener = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.NFC_CARDEMULATION);
+
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'listenerId',
+      type: types_.LONG
+    }
+  ]);
+  activeSecureElementChangeListener.removeListener(args.listenerId);
+
+  if (type_.isEmptyObject(cardEmulationModeListener.listeners) &&
+      type_.isEmptyObject(activeSecureElementChangeListener.listeners)) {
+    native_.callSync('NFCAdapter_removeCardEmulationModeChangeListener');
+  }
+};
+
+NFCAdapter.prototype.getCachedMessage = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.NFC_COMMON);
+
+  var result = native_.callSync('NFCAdapter_getCachedMessage');
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+
+  if (!result.records) {
+    return new tizen.NDEFMessage();
+  }
+
+  return new tizen.NDEFMessage(toRecordsArray(result.records));
+};
+
+NFCAdapter.prototype.setExclusiveModeForTransaction = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.NFC_CARDEMULATION);
+
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'transactionMode',
+      type: types_.BOOLEAN
+    }
+  ]);
+
+  var result = native_.callSync(
+      'NFCAdapter_setExclusiveModeForTransaction',
+      { 'transactionMode': args.transactionMode}
+      );
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+  return;
+};
+
+NFCAdapter.prototype.addHCEEventListener = function(eventCallback) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.NFC_CARDEMULATION);
+
+  var args = validator_.validateArgs(arguments, [
+    {name: 'eventCallback', type: types_.FUNCTION}
+  ]);
+
+  if (!arguments.length || !type_.isFunction(arguments[0])) {
+    throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR);
+  }
+
+  if (type_.isEmptyObject(HCEEventListener.listeners)) {
+    var result = native_.callSync('NFCAdapter_addHCEEventListener');
+    if (native_.isFailure(result)) {
+      throw native_.getErrorObject(result);
+    }
+  }
+
+  return HCEEventListener.addListener(args.eventCallback);
+};
+
+NFCAdapter.prototype.removeHCEEventListener = function(watchId) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.NFC_CARDEMULATION);
+
+  var args = validator_.validateArgs(arguments, [
+    {name: 'watchId', type: types_.LONG}
+  ]);
+
+  if (!arguments.length || !type_.isNumber(arguments[0])) {
+    throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR);
+  }
+
+  HCEEventListener.removeListener(args.watchId);
+
+  if (type_.isEmptyObject(HCEEventListener.listeners)) {
+    var result = native_.callSync('NFCAdapter_removeHCEEventListener');
+    if (native_.isFailure(result)) {
+      throw native_.getErrorObject(result);
+    }
+  }
+};
+
+NFCAdapter.prototype.sendHostAPDUResponse = function(apdu, successCallback, errorCallback) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.NFC_CARDEMULATION);
+
+  var args = validator_.validateArgs(arguments, [
+    {name: 'apdu', type: types_.ARRAY, values: types_.BYTE},
+    {name: 'successCallback', type: types_.FUNCTION, optional: true, nullable: true},
+    {name: 'errorCallback', type: types_.FUNCTION, optional: true, nullable: true}
+  ]);
+
+  if (!arguments.length || !type_.isArray(arguments[0])) {
+    throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR);
+  }
+
+  var data = {
+    apdu: args.apdu
+  };
+
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+      return;
+    }
+    native_.callIfPossible(args.successCallback);
+  };
+
+  native_.call('NFCAdapter_sendHostAPDUResponse', data, callback);
+};
+
+NFCAdapter.prototype.isActivatedHandlerForAID = function(type, aid) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.NFC_CARDEMULATION);
+
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'type',
+      type: types_.ENUM,
+      values: type_.getValues(SecureElementType)
+    },
+    {name: 'aid', type: types_.STRING}
+  ]);
+
+  if (arguments.length < 2) {
+    throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR);
+  }
+
+  var data = {
+    type: args.type,
+    aid: args.aid
+  };
+
+  var result = native_.callSync('NFCAdapter_isActivatedHandlerForAID', data);
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+  return native_.getResultObject(result);
+};
+
+NFCAdapter.prototype.isActivatedHandlerForCategory = function(type, category) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.NFC_CARDEMULATION);
+
+  var args = validator_.validateArgs(arguments, [{
+    name: 'type',
+    type: types_.ENUM,
+    values: type_.getValues(SecureElementType)
+  }, {
+    name: 'category',
+    type: types_.ENUM,
+    values: Object.keys(CardEmulationCategoryType)
+  }]);
+
+  if (arguments.length < 2) {
+    throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR);
+  }
+
+  var data = {
+    type: args.type,
+    category: args.category
+  };
+
+  var result = native_.callSync('NFCAdapter_isActivatedHandlerForCategory', data);
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+  return native_.getResultObject(result);
+};
+
+NFCAdapter.prototype.registerAID = function(type, aid, category) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.NFC_CARDEMULATION);
+
+  var args = validator_.validateArgs(arguments, [{
+    name: 'type',
+    type: types_.ENUM,
+    values: type_.getValues(SecureElementType)
+  }, {
+    name: 'aid',
+    type: types_.STRING
+  }, {
+    name: 'category',
+    type: types_.ENUM,
+    values: Object.keys(CardEmulationCategoryType)
+  }]);
+
+  if (arguments.length < 3 || !type_.isString(arguments[0])) {
+    throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR);
+  }
+
+  var data = {
+    type: args.type,
+    aid: args.aid,
+    category: args.category
+  };
+
+  var result = native_.callSync('NFCAdapter_registerAID', data);
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+};
+
+NFCAdapter.prototype.unregisterAID = function(type, aid, category) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.NFC_CARDEMULATION);
+
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'type',
+      type: types_.ENUM,
+      values: type_.getValues(SecureElementType)
+    },
+    {name: 'aid', type: types_.STRING},
+    {name: 'category', type: types_.ENUM, values: Object.keys(CardEmulationCategoryType)}
+  ]);
+
+  if (arguments.length < 3 || !type_.isString(arguments[0])) {
+    throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR);
+  }
+
+  var data = {
+    type: args.type,
+    aid: args.aid,
+    category: args.category
+  };
+
+  var result = native_.callSync('NFCAdapter_unregisterAID', data);
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+};
+
+function AIDData(data) {
+  Object.defineProperties(this, {
+    type: {
+      value: data.type,
+      writable: false,
+      enumerable: true
+    },
+    aid: {
+      value: data.aid || [],
+      writable: false,
+      enumerable: true
+    },
+    readOnly: {
+      value: data.readOnly || false,
+      writable: false,
+      enumerable: true
+    }
+  });
+}
+
+NFCAdapter.prototype.getAIDsForCategory = function(type, category, successCallback, errorCallback) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.NFC_CARDEMULATION);
+
+  var args = validator_.validateArgs(arguments, [{
+    name: 'type',
+    type: types_.ENUM,
+    values: type_.getValues(SecureElementType)
+  }, {
+    name: 'category',
+    type: types_.ENUM,
+    values: Object.keys(CardEmulationCategoryType)
+  }, {
+    name: 'successCallback',
+    type: types_.FUNCTION
+  }, {
+    name: 'errorCallback',
+    type: types_.FUNCTION,
+    optional: true,
+    nullable: true
+  }]);
+
+  if (arguments.length < 3) {
+    throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR);
+  }
+
+  var data = {
+    type: args.type,
+    category: args.category
+  };
+
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+      return;
+    }
+    var aids = [];
+    var r = native_.getResultObject(result);
+    for (var i = 0; i < r.length; i++) {
+      aids.push(new AIDData(r[i]));
+    }
+    native_.callIfPossible(args.successCallback, aids);
+  };
+
+  native_.call('NFCAdapter_getAIDsForCategory', data, callback);
+};
+
+function InternalRecordData(tnf, type, payload, id) {
+  this.tnf = tnf;
+  this.type = type;
+  this.payload = payload;
+  this.id = id;
+};
+
+var toRecordsArray = function(array) {
+  var result = [];
+  if (type_.isNullOrUndefined(array) || !type_.isArray(array)) {
+    return result;
+  }
+
+  for (var i = 0; i < array.length; i++) {
+    var data = new InternalRecordData(array[i].tnf, array[i].type, array[i].payload, array[i].id);
+
+    if (array[i].recordType == 'Record') {
+      result.push(new tizen.NDEFRecord(data.tnf_, data.type_, data.payload_, data.id_));
+      continue;
+    }
+
+    if (array[i].recordType == 'RecordText') {
+      result.push(new tizen.NDEFRecordText(array[i].text, array[i].languageCode,
+          array[i].encoding, data));
+      continue;
+    }
+
+    if (array[i].recordType == 'RecordURI') {
+      result.push(new tizen.NDEFRecordURI(array[i].uri, data));
+      continue;
+    }
+
+    if (array[i].recordType == 'RecordMedia') {
+      result.push(new tizen.NDEFRecordMedia(array[i].mimeType, array[i].data, data));
+      continue;
+    }
+  }
+
+  return result;
+};
+
+//////////////////NFCTag /////////////////
+
+function NFCTag(tagid) {
+
+  var _my_id = tagid;
+
+  function TypeGetter() {
+
+    var result = native_.callSync('NFCTag_typeGetter', {'id' : _my_id});
+
+    if (native_.isFailure(result)) {
+      return;
+    }
+    return native_.getResultObject(result);
+  }
+
+  function IsSupportedNDEFGetter() {
+
+    var result = native_.callSync('NFCTag_isSupportedNDEFGetter', {'id' : _my_id});
+
+    if (native_.isFailure(result)) {
+      return;
+    }
+    return native_.getResultObject(result);
+  }
+
+  function NDEFSizeGetter() {
+
+    var result = native_.callSync('NFCTag_NDEFSizeGetter', {'id' : _my_id});
+
+    if (native_.isFailure(result)) {
+      return;
+    }
+    return native_.getResultObject(result);
+  }
+
+  function PropertiesGetter() {
+
+    var result = native_.callSync('NFCTag_propertiesGetter', {'id' : _my_id});
+
+    if (native_.isFailure(result)) {
+      return;
+    }
+
+    console.log('Current result: ' + result);
+
+    var result_array = {};
+    for (var i in result.result) {
+      var current = result.result[i];
+      var keys = Object.keys(current);
+      for (var x in keys) {
+        result_array[keys[x]] = current[keys[x]];
+      }
+    }
+    return result_array;
+  }
+
+  function IsConnectedGetter() {
+
+    var result = native_.callSync('NFCTag_isConnectedGetter', {'id' : _my_id});
+
+    if (native_.isFailure(result)) {
+      return;
+    }
+    return native_.getResultObject(result);
+  }
+
+  // Function defined here (not outside Tag "constructor"
+  // because access to internal _my_id variable is needed)
+  NFCTag.prototype.readNDEF = function() {
+    xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.NFC_TAG);
+
+    var args = validator_.validateArgs(arguments, [
+      {
+        name: 'readCallback',
+        type: types_.FUNCTION
+      },
+      {
+        name: 'errorCallback',
+        type: types_.FUNCTION,
+        optional: true,
+        nullable: true
+      }
+    ]);
+
+    native_.call('NFCTag_readNDEF', {'id' : _my_id},
+        function(result) {
+          if (native_.isFailure(result)) {
+            if (!type_.isNullOrUndefined(args.errorCallback)) {
+              args.errorCallback(native_.getErrorObject(result));
+            }
+          } else {
+            var message = new tizen.NDEFMessage(toRecordsArray(result.records));
+            args.readCallback(message);
+          }
+        });
+
+  };
+
+  NFCTag.prototype.writeNDEF = function() {
+    xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.NFC_TAG);
+
+    var args = validator_.validateArgs(arguments, [
+      {
+        name: 'message',
+        type: types_.PLATFORM_OBJECT,
+        values: tizen.NDEFMessage
+      },
+      {
+        name: 'successCallback',
+        type: types_.FUNCTION,
+        optional: true,
+        nullable: true
+      },
+      {
+        name: 'errorCallback',
+        type: types_.FUNCTION,
+        optional: true,
+        nullable: true
+      }
+    ]);
+
+    native_.call('NFCTag_writeNDEF',
+        {
+          'id' : _my_id,
+          'records' : args.message.records,
+          'recordsSize' : args.message.recordCount
+        },
+        function(result) {
+          if (native_.isFailure(result)) {
+            if (!type_.isNullOrUndefined(args.errorCallback)) {
+              args.errorCallback(native_.getErrorObject(result));
+            }
+          } else {
+            if (!type_.isNullOrUndefined(args.successCallback)) {
+              args.successCallback();
+            }
+          }
+        });
+
+  };
+
+  NFCTag.prototype.transceive = function() {
+    xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.NFC_TAG);
+
+    var args = validator_.validateArgs(arguments, [
+      {
+        name: 'data',
+        type: types_.ARRAY
+      },
+      {
+        name: 'dataCallback',
+        type: types_.FUNCTION
+      },
+      {
+        name: 'errorCallback',
+        type: types_.FUNCTION,
+        optional: true,
+        nullable: true
+      }
+    ]);
+
+    native_.call('NFCTag_transceive',
+        {
+          'id' : _my_id,
+          'data' : args.data
+        },
+        function(result) {
+          if (native_.isFailure(result)) {
+            if (!type_.isNullOrUndefined(args.errorCallback)) {
+              args.errorCallback(result.error);
+            }
+          } else {
+            if (!type_.isNullOrUndefined(args.dataCallback)) {
+              args.dataCallback(result.data);
+            }
+          }
+        });
+
+  };
+
+  Object.defineProperties(this, {
+    type: {
+      set: function() {},
+      get: TypeGetter,
+      enumerable: true
+    },
+    isSupportedNDEF: {
+      set: function() {},
+      get: IsSupportedNDEFGetter,
+      enumerable: true
+    },
+    ndefSize: {
+      set: function() {},
+      get: NDEFSizeGetter,
+      enumerable: true
+    },
+    properties: {
+      set: function() {},
+      get: PropertiesGetter,
+      enumerable: true
+    },
+    isConnected: {
+      set: function() {},
+      get: IsConnectedGetter,
+      enumerable: true
+    }
+  });
+}
+
+
+//////////////////NFCPeer /////////////////
+
+function NFCPeer(peerid) {
+  var _my_id = peerid;
+
+  function isConnectedGetter() {
+    var ret = native_.callSync('NFCAdapter_PeerIsConnectedGetter', {'id' : _my_id});
+    if (native_.isFailure(ret)) {
+      return false;
+    }
+    return native_.getResultObject(ret);
+  }
+
+  NFCPeer.prototype.sendNDEF = function() {
+    xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.NFC_P2P);
+
+    var args = validator_.validateArgs(arguments, [
+      {
+        name: 'message',
+        type: types_.PLATFORM_OBJECT,
+        values: tizen.NDEFMessage
+      },
+      {
+        name: 'successCallback',
+        type: types_.FUNCTION,
+        optional: true,
+        nullable: true
+      },
+      {
+        name: 'errorCallback',
+        type: types_.FUNCTION,
+        optional: true,
+        nullable: true
+      }
+    ]);
+
+    native_.call('NFCPeer_sendNDEF', {
+      'id' : _my_id,
+      'records' : args.message.records,
+      'recordsSize' : args.message.recordCount
+    }, function(result) {
+      if (native_.isFailure(result)) {
+        args.errorCallback(result.error);
+      } else {
+        args.successCallback();
+      }
+    });
+  };
+
+  NFCPeer.prototype.setReceiveNDEFListener = function() {
+    xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.NFC_P2P);
+
+    var args = validator_.validateArgs(arguments, [
+      {
+        name: 'listener',
+        type: types_.FUNCTION
+      }
+    ]);
+
+    var listener = function(msg) {
+      var data = undefined;
+      if ('onsuccess' === msg.action && _my_id === msg.id) {
+        data = new NDEFMessage(msg);
+      }
+      args.listener[msg.action](data);
+    };
+
+    var result = native_.callSync('NFCPeer_setReceiveNDEFListener', {'id' : _my_id});
+    if (native_.isFailure(result)) {
+      throw native_.getErrorObject(result);
+    }
+
+    native_.addListener(RECEIVE_NDEF_LISTENER, listener);
+    return;
+  };
+
+  NFCPeer.prototype.unsetReceiveNDEFListener = function() {
+    xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.NFC_P2P);
+
+    native_.removeListener(RECEIVE_NDEF_LISTENER);
+
+    var result = native_.callSync('NFCPeer_unsetReceiveNDEFListener', {'id' : _my_id});
+    if (native_.isFailure(result)) {
+      throw native_.getErrorObject(result);
+    }
+
+    return;
+  };
+
+  Object.defineProperties(this, {
+    isConnected: {
+      enumerable: true,
+      set: function() {},
+      get: isConnectedGetter
+    }
+  });
+}
+
+var toByteArray = function(array, max_size, nullable) {
+  var resultArray = [];
+  if (type_.isNullOrUndefined(array) && nullable === true)
+    return resultArray;
+
+  var convertedArray = converter_.toArray(array);
+  var len = convertedArray.length;
+
+  if (len > max_size)
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR);
+  for (var i = 0; i < len; i++) {
+    resultArray.push(converter_.toOctet(convertedArray[i]));
+  }
+  return resultArray;
+};
+
+var isArrayOfType = function(array, type) {
+  for (var i = 0; i < array.length; i++) {
+    if (!(array[i] instanceof type))
+      return false;
+  }
+  return true;
+};
+
+//////////////////NDEFMessage /////////////////
+//[Constructor(),
+// Constructor(NDEFRecord[] ndefRecords),
+// Constructor(byte[] rawData)]
+//interface NDEFMessage {
+//  readonly attribute long recordCount;
+//
+//  attribute NDEFRecord[] records;
+//
+//  byte[] toByte() raises(WebAPIException);
+//};
+
+tizen.NDEFMessage = function(data) {
+  validator_.isConstructorCall(this, tizen.NDEFMessage);
+  var records_ = [];
+
+  try {
+    if (arguments.length >= 1) {
+      if (type_.isArray(data)) {
+        if (isArrayOfType(data, tizen.NDEFRecord)) {
+          records_ = data;
+        } else {
+          var raw_data_ = toByteArray(data);
+          var result = native_.callSync(
+              'NDEFMessage_constructor', {
+                                'rawData': raw_data_,
+                                'rawDataSize' : raw_data_.length
+              }
+              );
+          var records_array = result.result.records;
+          for (var i = 0; i < records_array.length; i++) {
+            records_.push(new tizen.NDEFRecord(records_array[i].tnf,
+                                records_array[i].type, records_array[i].payload,
+                                records_array[i].id));
+          }
+        }
+      } else {
+        throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR);
+      }
+    }
+  } catch (e) {
+    //constructor call failed - empty object should be created
+    records_ = undefined;
+  }
+
+  var recordsSetter = function(data) {
+    if (type_.isArray(data)) {
+      // Do not check type of array elements - allow all arrays
+      //if ( isArrayOfType(data, tizen.NDEFRecord) ) {
+      records_ = data;
+      //}
+    }
+  };
+
+  Object.defineProperties(this, {
+    recordCount: { enumerable: true,
+      set: function() {},
+      get: function() { return records_ ? records_.length : undefined;}},
+    records: { enumerable: true,
+      set: recordsSetter,
+      get: function() {return records_;}}
+  });
+};
+
+tizen.NDEFMessage.prototype.toByte = function() {
+  var result = native_.callSync(
+      'NDEFMessage_toByte', {
+        'records' : this.records,
+        'recordsSize' : this.recordCount
+      }
+      );
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+
+  return toByteArray(result.result.bytes);
+};
+
+//helper for inherited object constructors /////////////////////////////////////////////
+function InternalData() {
+}
+
+//////////////////NDEFRecord /////////////////
+tizen.NDEFRecord = function(first, type, payload, id) {
+  var tnf_ = undefined;
+  var typ_ = undefined;
+  var payload_ = undefined;
+  var id_ = undefined;
+  //if it is inherited call, then ignore validation
+  if (!(first instanceof InternalData)) {
+    validator_.isConstructorCall(this, tizen.NDEFRecord);
+    try {
+      if (arguments.length >= 1) {
+        if (type_.isArray(first)) {
+          var raw_data_ = toByteArray(first);
+          var result = native_.callSync(
+              'NDEFRecord_constructor', {
+                'rawData': raw_data_,
+                'rawDataSize' : raw_data_.length
+              }
+              );
+          if (native_.isFailure(result)) {
+            throw native_.getErrorObject(result);
+          }
+          tnf_ = converter_.toLong(result.result.tnf);
+          typ_ = toByteArray(result.result.type, 255);
+          payload_ = toByteArray(result.result.payload, Math.pow(2, 32) - 1);
+          id_ = toByteArray(result.result.id, 255);
+        } else if (arguments.length >= 3) {
+          tnf_ = converter_.toLong(first);
+          typ_ = toByteArray(type, 255);
+          payload_ = toByteArray(payload, Math.pow(2, 32) - 1);
+          id_ = toByteArray(id, 255, true, []);
+        }
+      } else {
+        throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR);
+      }
+    } catch (e) {
+      //constructor call failed - empty object should be created
+      tnf_ = undefined;
+      typ_ = undefined;
+      payload_ = undefined;
+      id_ = undefined;
+    }
+  }
+
+  Object.defineProperties(this, {
+    tnf: {value: tnf_, writable: false, enumerable: true},
+    type: {value: typ_, writable: false, enumerable: true},
+    id: {value: id_, writable: false, enumerable: true},
+    payload: {value: payload_, writable: false, enumerable: true}
+  });
+};
+
+//////////////////NDEFRecordText /////////////////
+tizen.NDEFRecordText = function(text, languageCode, encoding, internal_) {
+  var text_ = undefined;
+  var languageCode_ = undefined;
+  var encoding_ = NDEFRecordTextEncoding[encoding] ?
+      NDEFRecordTextEncoding[encoding] : NDEFRecordTextEncoding['UTF8'];
+  try {
+    if (arguments.length >= 2) {
+      text_ = converter_.toString(text);
+      languageCode_ = converter_.toString(languageCode);
+
+      if (!type_.isNullOrUndefined(internal_) && (internal_ instanceof InternalRecordData)) {
+        tizen.NDEFRecord.call(this, internal_.tnf_, internal_.type_, internal_.payload_, internal_.id_);
+      } else {
+        var result = native_.callSync(
+            'NDEFRecordText_constructor', {
+              'text': text_,
+              'languageCode' : languageCode_,
+              'encoding' : encoding_
+            }
+            );
+        if (native_.isFailure(result)) {
+          throw native_.getErrorObject(result);
+        }
+        tizen.NDEFRecord.call(this, result.result.tnf, result.result.type,
+            result.result.payload, result.result.id);
+      }
+    } else {
+      throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR);
+    }
+  } catch (e) {
+    //constructor call failed - empty object should be created
+    tizen.NDEFRecord.call(this);
+    text_ = undefined;
+    languageCode_ = undefined;
+    encoding_ = undefined;
+  }
+
+  Object.defineProperties(this, {
+    text: {value: text_, writable: false, enumerable: true},
+    languageCode: {value: languageCode_, writable: false, enumerable: true},
+    encoding: {value: encoding_, writable: false, enumerable: true}
+  });
+};
+
+tizen.NDEFRecordText.prototype = new tizen.NDEFRecord(new InternalData());
+
+tizen.NDEFRecordText.prototype.constructor = tizen.NDEFRecordText;
+
+//////////////////NDEFRecordURI /////////////////
+tizen.NDEFRecordURI = function(uri, internal_) {
+  var uri_ = undefined;
+  try {
+    if (arguments.length >= 1) {
+      uri_ = converter_.toString(uri);
+
+      if (!type_.isNullOrUndefined(internal_) && (internal_ instanceof InternalRecordData)) {
+        tizen.NDEFRecord.call(this, internal_.tnf_, internal_.type_, internal_.payload_, internal_.id_);
+      } else {
+        var result = native_.callSync(
+            'NDEFRecordURI_constructor', {
+              'uri': uri_
+            }
+            );
+        if (native_.isFailure(result)) {
+          throw native_.getErrorObject(result);
+        }
+        tizen.NDEFRecord.call(this, result.result.tnf, result.result.type,
+            result.result.payload, result.result.id);
+      }
+    } else {
+      throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR);
+    }
+  } catch (e) {
+    //constructor call failed - empty object should be created
+    tizen.NDEFRecord.call(this);
+    uri_ = undefined;
+  }
+
+  Object.defineProperties(this, {
+    uri: {value: uri_, writable: false, enumerable: true}
+  });
+};
+
+tizen.NDEFRecordURI.prototype = new tizen.NDEFRecord(new InternalData());
+
+tizen.NDEFRecordURI.prototype.constructor = tizen.NDEFRecordURI;
+
+//////////////////NDEFRecordMedia /////////////////
+tizen.NDEFRecordMedia = function(mimeType, data, internal_) {
+  var mimeType_ = undefined;
+  var data_ = undefined;
+  try {
+    if (arguments.length >= 2) {
+      mimeType_ = converter_.toString(mimeType);
+      data_ = toByteArray(data, Math.pow(2, 32) - 1);
+
+      if (!type_.isNullOrUndefined(internal_) && (internal_ instanceof InternalRecordData)) {
+        tizen.NDEFRecord.call(this, internal_.tnf_, internal_.type_, internal_.payload_, internal_.id_);
+      } else {
+        var result = native_.callSync(
+            'NDEFRecordMedia_constructor', {
+              'mimeType': mimeType_,
+              'data': data_,
+              'dataSize': data_.length
+            }
+            );
+        if (native_.isFailure(result)) {
+          throw native_.getErrorObject(result);
+        }
+        tizen.NDEFRecord.call(this, result.result.tnf, result.result.type,
+            result.result.payload, result.result.id);
+      }
+    } else {
+      throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR);
+    }
+  } catch (e) {
+    //constructor call failed - empty object should be created
+    tizen.NDEFRecord.call(this);
+    mimeType_ = undefined;
+  }
+
+  Object.defineProperties(this, {
+    mimeType: {value: mimeType_, writable: false, enumerable: true}
+  });
+};
+
+tizen.NDEFRecordMedia.prototype = new tizen.NDEFRecord(new InternalData());
+
+tizen.NDEFRecordMedia.prototype.constructor = tizen.NDEFRecordMedia;
+//Exports
+exports = new NFCManager();
diff --git a/webWidgetTCT_device/src/nfc/nfc_extension.cc b/webWidgetTCT_device/src/nfc/nfc_extension.cc
new file mode 100755 (executable)
index 0000000..4475d8d
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2015 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 "nfc/nfc_extension.h"
+
+#include "nfc/nfc_instance.h"
+#include "common/logger.h"
+
+extern const char kSource_nfc_api[];
+
+common::Extension* CreateExtension() {
+  return new NFCExtension;
+}
+
+NFCExtension::NFCExtension() {
+  LoggerD("Entered");
+  SetExtensionName("tizen.nfc");
+  SetJavaScriptAPI(kSource_nfc_api);
+
+  const char* entry_points[] = {
+      "tizen.NDEFMessage",
+      "tizen.NDEFRecord",
+      "tizen.NDEFRecordText",
+      "tizen.NDEFRecordURI",
+      "tizen.NDEFRecordMedia",
+      NULL
+  };
+  SetExtraJSEntryPoints(entry_points);
+}
+
+NFCExtension::~NFCExtension()
+{
+  LoggerD("Entered");
+}
+
+common::Instance* NFCExtension::CreateInstance() {
+  LoggerD("Entered");
+  return new extension::nfc::NFCInstance();
+}
diff --git a/webWidgetTCT_device/src/nfc/nfc_extension.h b/webWidgetTCT_device/src/nfc/nfc_extension.h
new file mode 100755 (executable)
index 0000000..15e4867
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2015 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 NFC_NFC_EXTENSION_H_
+#define NFC_NFC_EXTENSION_H_
+
+#include "common/extension.h"
+
+class NFCExtension : public common::Extension {
+ public:
+  NFCExtension();
+  virtual ~NFCExtension();
+ private:
+  // common::Extension implementation.
+  virtual common::Instance* CreateInstance();
+};
+
+#endif  // NFC_NFC_EXTENSION_H_
diff --git a/webWidgetTCT_device/src/nfc/nfc_instance.cc b/webWidgetTCT_device/src/nfc/nfc_instance.cc
new file mode 100755 (executable)
index 0000000..7649d61
--- /dev/null
@@ -0,0 +1,1031 @@
+/*
+ * Copyright (c) 2015 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 "nfc/nfc_instance.h"
+
+#include <network/nfc.h>
+
+#include "common/converter.h"
+#include "common/logger.h"
+#include "common/picojson.h"
+#include "common/platform_exception.h"
+#include "common/platform_result.h"
+#include "common/task-queue.h"
+#include "nfc/defs.h"
+#include "nfc/nfc_message_utils.h"
+#include "nfc/nfc_util.h"
+#include <system_info.h>
+
+namespace extension {
+namespace nfc {
+
+using namespace common;
+using namespace extension::nfc;
+
+void NFCInstance::RespondAsync(const char* msg) {
+  LoggerD("Entered");
+  Instance::PostMessage(this, msg);
+}
+
+static bool isTagSupported(){
+    LoggerD("Entered");
+    bool supported = true;
+    if (system_info_get_platform_bool(
+                    "http://tizen.org/feature/network.nfc.tag", &supported)
+                    != SYSTEM_INFO_ERROR_NONE) {
+        LoggerD("Can't check Tag is supported or not");
+    }
+    return supported;
+}
+
+static bool isP2PSupported(){
+    LoggerD("Entered");
+    bool supported = true;
+    if (system_info_get_platform_bool(
+                    "http://tizen.org/feature/network.nfc.p2p", &supported)
+                    != SYSTEM_INFO_ERROR_NONE) {
+        LoggerD("Can't check Tag is supported or not");
+    }
+    return supported;
+}
+
+NFCInstance::NFCInstance() {
+  LoggerD("Entered");
+  using std::placeholders::_1;
+  using std::placeholders::_2;
+#define REGISTER_ASYNC(c,x) \
+  RegisterSyncHandler(c, std::bind(&NFCInstance::x, this, _1, _2));
+#define REGISTER_SYNC(c,x) \
+  RegisterSyncHandler(c, std::bind(&NFCInstance::x, this, _1, _2));
+  REGISTER_SYNC("NFCManager_getDefaultAdapter", GetDefaultAdapter);
+  REGISTER_SYNC("NFCManager_setExclusiveMode", SetExclusiveMode);
+  REGISTER_ASYNC("NFCAdapter_setPowered", SetPowered);
+  REGISTER_SYNC("NFCAdapter_getPowered", GetPowered);
+  REGISTER_SYNC("NFCAdapter_cardEmulationModeSetter", CardEmulationModeSetter);
+  REGISTER_SYNC("NFCAdapter_cardEmulationModeGetter", CardEmulationModeGetter);
+  REGISTER_SYNC("NFCAdapter_activeSecureElementSetter", ActiveSecureElementSetter);
+  REGISTER_SYNC("NFCAdapter_activeSecureElementGetter", ActiveSecureElementGetter);
+  REGISTER_SYNC("NFCAdapter_setPeerListener", SetPeerListener);
+  REGISTER_SYNC("NFCAdapter_setTagListener", SetTagListener);
+  REGISTER_SYNC("NFCAdapter_PeerIsConnectedGetter", PeerIsConnectedGetter);
+  REGISTER_SYNC("NFCAdapter_unsetTagListener", UnsetTagListener);
+  REGISTER_SYNC("NFCAdapter_unsetPeerListener", UnsetPeerListener);
+  REGISTER_SYNC("NFCAdapter_addCardEmulationModeChangeListener",
+                AddCardEmulationModeChangeListener);
+  REGISTER_SYNC("NFCAdapter_removeCardEmulationModeChangeListener",
+                RemoveCardEmulationModeChangeListener);
+  REGISTER_SYNC("NFCAdapter_addTransactionEventListener",
+                AddTransactionEventListener);
+  REGISTER_SYNC("NFCAdapter_removeTransactionEventListener",
+                RemoveTransactionEventListener);
+  REGISTER_SYNC("NFCAdapter_addActiveSecureElementChangeListener",
+                AddActiveSecureElementChangeListener);
+  REGISTER_SYNC("NFCAdapter_removeActiveSecureElementChangeListener",
+                RemoveActiveSecureElementChangeListener);
+  REGISTER_SYNC("NFCAdapter_getCachedMessage", GetCachedMessage);
+  REGISTER_SYNC("NFCAdapter_setExclusiveModeForTransaction",
+                SetExclusiveModeForTransaction);
+
+  // HCE related methods
+  REGISTER_SYNC("NFCAdapter_addHCEEventListener", AddHCEEventListener);
+  REGISTER_SYNC("NFCAdapter_removeHCEEventListener", RemoveHCEEventListener);
+  REGISTER_ASYNC("NFCAdapter_sendHostAPDUResponse", SendHostAPDUResponse);
+  REGISTER_SYNC("NFCAdapter_isActivatedHandlerForAID",
+                IsActivatedHandlerForAID);
+  REGISTER_SYNC("NFCAdapter_isActivatedHandlerForCategory",
+                IsActivatedHandlerForCategory);
+  REGISTER_SYNC("NFCAdapter_registerAID", RegisterAID);
+  REGISTER_SYNC("NFCAdapter_unregisterAID", UnregisterAID);
+  REGISTER_ASYNC("NFCAdapter_getAIDsForCategory", GetAIDsForCategory);
+
+  REGISTER_SYNC("NFCPeer_setReceiveNDEFListener", SetReceiveNDEFListener);
+  REGISTER_SYNC("NFCPeer_unsetReceiveNDEFListener", UnsetReceiveNDEFListener);
+  REGISTER_SYNC("NDEFMessage_toByte", ToByte);
+  //Message related methods
+  REGISTER_SYNC("NDEFMessage_constructor", NDEFMessageContructor);
+  REGISTER_SYNC("NDEFRecord_constructor", NDEFRecordContructor);
+  REGISTER_SYNC("NDEFRecordText_constructor", NDEFRecordTextContructor);
+  REGISTER_SYNC("NDEFRecordURI_constructor", NDEFRecordURIContructor);
+  REGISTER_SYNC("NDEFRecordMedia_constructor", NDEFRecordMediaContructor);
+
+  // NFCTag attributes getters
+  REGISTER_SYNC("NFCTag_typeGetter", TagTypeGetter);
+  REGISTER_SYNC("NFCTag_isSupportedNDEFGetter", TagIsSupportedNDEFGetter);
+  REGISTER_SYNC("NFCTag_NDEFSizeGetter", TagNDEFSizeGetter);
+  REGISTER_SYNC("NFCTag_propertiesGetter", TagPropertiesGetter);
+  REGISTER_SYNC("NFCTag_isConnectedGetter", TagIsConnectedGetter);
+
+  REGISTER_ASYNC("NFCTag_readNDEF", ReadNDEF);
+  REGISTER_ASYNC("NFCTag_writeNDEF", WriteNDEF);
+  REGISTER_ASYNC("NFCTag_transceive", Transceive );
+  REGISTER_ASYNC("NFCPeer_sendNDEF", SendNDEF);
+#undef REGISTER_SYNC
+#undef REGISTER_ASYNC
+
+  // Set a PostMessageHandler at NFCAdapter to provide mechanizm of returning
+  // asynchronous response
+  NFCAdapter::GetInstance()->SetResponder(this);
+}
+
+#define CHECK_EXIST(args, name, out)                                           \
+  if (!args.contains(name)) {                                                  \
+    LoggerE("args doesn't contain attribute '%s'", name);                      \
+    ReportError(TypeMismatchException(name" is required argument"), out);      \
+    return;                                                                    \
+  }
+
+NFCInstance::~NFCInstance() {
+  LoggerD("Entered");
+}
+
+void NFCInstance::GetDefaultAdapter(
+    const picojson::value& args, picojson::object& out) {
+
+  // Default NFC adapter is created at JS level
+  // Here there's only check for NFC support
+  LoggerD("Entered");
+
+  if(!nfc_manager_is_supported()) {
+    LoggerE("NFC manager is not supported");
+    // According to API reference only Security and Unknown
+    // exceptions are allowed here
+    ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR,
+                               "NFC manager not supported"), &out);
+  }
+  else {
+    ReportSuccess(out);
+  }
+}
+
+void NFCInstance::SetExclusiveMode(
+    const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+  CHECK_EXIST(args, "exclusiveMode", out);
+  bool exmode = args.get("exclusiveMode").get<bool>();
+
+  int ret = nfc_manager_set_system_handler_enable(!exmode);
+  if (NFC_ERROR_NONE != ret) {
+    LoggerE("Error: %d", ret);
+    PlatformResult result = NFCUtil::CodeToResult(ret,
+                                                  "Failed to set exclusive mode.");
+    ReportError(result, &out);
+  } else {
+    ReportSuccess(out);
+  }
+}
+
+//TODO(g.rynkowski): Rewrite to asynchronous approach
+void NFCInstance::SetPowered(
+    const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+  PlatformResult result = NFCAdapter::GetInstance()->SetPowered(args);
+  if (result.IsSuccess()) {
+    ReportSuccess(out);
+  } else {
+    LoggerE("Error: %s", result.message().c_str());
+    ReportError(result, &out);
+  }
+}
+
+void NFCInstance::GetPowered(
+    const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+  bool ret = NFCAdapter::GetInstance()->GetPowered();
+  ReportSuccess(picojson::value(ret), out);
+}
+
+void NFCInstance::CardEmulationModeSetter(
+    const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+  CHECK_EXIST(args, "emulationMode", out);
+  std::string mode = args.get("emulationMode").get<std::string>();
+  PlatformResult result = NFCAdapter::GetInstance()->SetCardEmulationMode(mode);
+  if (result.IsSuccess()) {
+    ReportSuccess(out);
+  } else {
+    LoggerE("Error: %s", result.message().c_str());
+    ReportError(result, &out);
+  }
+}
+
+void NFCInstance::CardEmulationModeGetter(
+    const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+  std::string mode = "";
+  PlatformResult result = NFCAdapter::GetInstance()->GetCardEmulationMode(&mode);
+  if (result.IsSuccess()) {
+    ReportSuccess(picojson::value(mode), out);
+  } else {
+    LoggerE("Error: %s", result.message().c_str());
+    ReportError(result, &out);
+  }
+}
+
+void NFCInstance::ActiveSecureElementSetter(
+    const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+  CHECK_EXIST(args, "secureElement", out);
+  std::string ase = args.get("secureElement").get<std::string>();
+  PlatformResult result = NFCAdapter::GetInstance()->SetActiveSecureElement(ase);
+  if (result.IsSuccess()) {
+    ReportSuccess(out);
+  } else {
+    LoggerE("Error: %s", result.message().c_str());
+    ReportError(result, &out);
+  }
+}
+
+void NFCInstance::ActiveSecureElementGetter(
+    const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+  std::string ase = "";
+  PlatformResult result = NFCAdapter::GetInstance()->GetActiveSecureElement(&ase);
+  if (result.IsSuccess()) {
+    ReportSuccess(picojson::value(ase), out);
+  } else {
+    LoggerE("Error: %s", result.message().c_str());
+    ReportError(result, &out);
+  }
+}
+
+void NFCInstance::SetTagListener(
+    const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+    bool supported = isTagSupported();
+      if (supported) {
+          SLoggerE("Tag is supported");
+      } else {
+          SLoggerE("Tag is not supported");
+          ReportError(
+              common::PlatformResult(common::ErrorCode::NOT_SUPPORTED_ERR,
+                                     "Tag is not supported on this device."),
+              &out);
+          return;
+      }
+  PlatformResult result = NFCAdapter::GetInstance()->SetTagListener();
+  if (result.IsSuccess()) {
+    ReportSuccess(out);
+  } else {
+    LoggerE("Error: %s", result.message().c_str());
+    ReportError(result, &out);
+  }
+}
+
+void NFCInstance::PeerIsConnectedGetter(
+    const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+  CHECK_EXIST(args, "id", out);
+
+  int peer_id = (int)args.get("id").get<double>();
+  bool ret = false;
+  PlatformResult result = NFCAdapter::GetInstance()->PeerIsConnectedGetter(peer_id, &ret);
+
+  if (result.IsSuccess()) {
+    ReportSuccess(picojson::value(ret), out);
+  } else {
+    LoggerE("Error: %s", result.message().c_str());
+    ReportError(result, &out);
+  }
+
+}
+
+void NFCInstance::SetPeerListener(
+    const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+  bool supported = isP2PSupported();
+  if (supported) {
+    SLoggerE("P2P is supported");
+  } else {
+    SLoggerE("P2P is not supported");
+    ReportError(
+        common::PlatformResult(common::ErrorCode::NOT_SUPPORTED_ERR,
+                               "P2P is not supported on this device."),
+                               &out);
+    return;
+  }
+  PlatformResult result = NFCAdapter::GetInstance()->SetPeerListener();
+  if (result.IsSuccess()) {
+    ReportSuccess(out);
+  } else {
+    LoggerE("Error: %s", result.message().c_str());
+    ReportError(result, &out);
+  }
+}
+
+void NFCInstance::UnsetTagListener(
+    const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+  bool supported = isTagSupported();
+  if (supported) {
+    SLoggerE("Tag is supported");
+  } else {
+    SLoggerE("Tag is not supported");
+    ReportError(
+        common::PlatformResult(common::ErrorCode::NOT_SUPPORTED_ERR,
+                               "Tag is not supported on this device."),
+                               &out);
+    return;
+  }
+  NFCAdapter::GetInstance()->UnsetTagListener();
+  ReportSuccess(out);
+}
+
+void NFCInstance::UnsetPeerListener(
+    const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+    bool supported = isP2PSupported();
+      if (supported) {
+          SLoggerE("P2P is supported");
+      } else {
+          SLoggerE("P2P is not supported");
+          ReportError(
+              common::PlatformResult(common::ErrorCode::NOT_SUPPORTED_ERR,
+                                     "P2P is not supported on this device."),
+              &out);
+          return;
+      }
+  PlatformResult result = NFCAdapter::GetInstance()->UnsetPeerListener();
+  if (result.IsSuccess()) {
+    ReportSuccess(out);
+  } else {
+    LoggerE("Error: %s", result.message().c_str());
+    ReportError(result, &out);
+  }
+}
+
+void NFCInstance::AddCardEmulationModeChangeListener(
+    const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+  PlatformResult result = NFCAdapter::GetInstance()->AddCardEmulationModeChangeListener();
+  if (result.IsSuccess()) {
+    ReportSuccess(out);
+  } else {
+    LoggerE("Error: %s", result.message().c_str());
+    ReportError(result, &out);
+  }
+}
+
+void NFCInstance::RemoveCardEmulationModeChangeListener(
+    const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+  PlatformResult result = NFCAdapter::GetInstance()->RemoveCardEmulationModeChangeListener();
+  if (result.IsSuccess()) {
+    ReportSuccess(out);
+  } else {
+    LoggerE("Error: %s", result.message().c_str());
+    ReportError(result, &out);
+  }
+}
+
+void NFCInstance::AddTransactionEventListener(
+    const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+  PlatformResult result = NFCAdapter::GetInstance()->AddTransactionEventListener(args);
+  if (result.IsSuccess()) {
+    ReportSuccess(out);
+  } else {
+    LoggerE("Error: %s", result.message().c_str());
+    ReportError(result, &out);
+  }
+}
+
+void NFCInstance::RemoveTransactionEventListener(
+    const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+  PlatformResult result = NFCAdapter::GetInstance()->RemoveTransactionEventListener(args);
+  if (result.IsSuccess()) {
+    ReportSuccess(out);
+  } else {
+    LoggerE("Error: %s", result.message().c_str());
+    ReportError(result, &out);
+  }
+}
+
+void NFCInstance::AddActiveSecureElementChangeListener(
+    const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+  PlatformResult result = NFCAdapter::GetInstance()->AddActiveSecureElementChangeListener();
+  if (result.IsSuccess()) {
+    ReportSuccess(out);
+  } else {
+    LoggerE("Error: %s", result.message().c_str());
+    ReportError(result, &out);
+  }
+}
+
+void NFCInstance::RemoveActiveSecureElementChangeListener(
+    const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+  PlatformResult result = NFCAdapter::GetInstance()->RemoveActiveSecureElementChangeListener();
+  if (result.IsSuccess()) {
+    ReportSuccess(out);
+  } else {
+    LoggerE("Error: %s", result.message().c_str());
+    ReportError(result, &out);
+  }
+}
+
+void NFCInstance::GetCachedMessage(
+    const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+  picojson::value result = picojson::value(picojson::object());
+  picojson::object& result_obj = result.get<picojson::object>();
+
+  PlatformResult ret = NFCAdapter::GetInstance()->GetCachedMessage(result_obj);
+  if (ret.IsSuccess()) {
+    ReportSuccess(result, out);
+  } else {
+    LoggerE("Error: %s", ret.message().c_str());
+    ReportError(ret, &out);
+  }
+}
+
+void NFCInstance::SetExclusiveModeForTransaction(
+    const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+  CHECK_EXIST(args, "transactionMode", out);
+
+  bool transaction_mode = args.get("transactionMode").get<bool>();
+  PlatformResult result = NFCAdapter::GetInstance()->SetExclusiveModeForTransaction(
+        transaction_mode);
+  if (result.IsSuccess()) {
+    ReportSuccess(out);
+  } else {
+    LoggerE("Error: %s", result.message().c_str());
+    ReportError(result, &out);
+  }
+}
+
+//TODO(g.rynkowski): Rewrite to asynchronous approach
+void NFCInstance::ReadNDEF(
+    const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+  CHECK_EXIST(args, "id", out);
+
+  int tag_id = static_cast<int>(args.get("id").get<double>());
+  LoggerD("Tag id: %d", tag_id);
+
+  PlatformResult result = NFCAdapter::GetInstance()->TagReadNDEF(tag_id, args);
+  if (result.IsSuccess()) {
+    ReportSuccess(out);
+  } else {
+    LoggerE("Error: %s", result.message().c_str());
+    ReportError(result, &out);
+  }
+}
+
+//TODO(g.rynkowski): Rewrite to asynchronous approach
+void NFCInstance::WriteNDEF(
+    const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+  CHECK_EXIST(args, "id", out);
+
+  int tag_id = static_cast<int>(args.get("id").get<double>());
+  LoggerD("Tag id: %d", tag_id);
+
+  PlatformResult result = NFCAdapter::GetInstance()->TagWriteNDEF(tag_id, args);
+  if (result.IsSuccess()) {
+    ReportSuccess(out);
+  } else {
+    LoggerE("Error: %s", result.message().c_str());
+    ReportError(result, &out);
+  }
+}
+
+//TODO(g.rynkowski): Rewrite to asynchronous approach
+void NFCInstance::Transceive(
+    const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+
+  CHECK_EXIST(args, "id", out);
+  int tag_id = static_cast<int>(args.get("id").get<double>());
+  LoggerD("Tag id: %d", tag_id);
+
+  PlatformResult result = NFCAdapter::GetInstance()->TagTransceive(tag_id, args);
+  if (result.IsSuccess()) {
+    ReportSuccess(out);
+  } else {
+    LoggerE("Error: %s", result.message().c_str());
+    ReportError(result, &out);
+  }
+}
+
+void NFCInstance::SetReceiveNDEFListener(
+    const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+  CHECK_EXIST(args, "id", out);
+
+  int peer_id = (int)args.get("id").get<double>();
+  PlatformResult result = NFCAdapter::GetInstance()->SetReceiveNDEFListener(peer_id);
+  if (result.IsSuccess()) {
+    ReportSuccess(out);
+  } else {
+    LoggerE("Error: %s", result.message().c_str());
+    ReportError(result, &out);
+  }
+}
+
+void NFCInstance::UnsetReceiveNDEFListener(
+    const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+  CHECK_EXIST(args, "id", out);
+
+  int peer_id = (int)args.get("id").get<double>();
+  PlatformResult result = NFCAdapter::GetInstance()->UnsetReceiveNDEFListener(peer_id);
+  if (result.IsSuccess()) {
+    ReportSuccess(out);
+  } else {
+    LoggerE("Error: %s", result.message().c_str());
+    ReportError(result, &out);
+  }
+}
+
+//TODO(g.rynkowski): Rewrite to asynchronous approach
+void NFCInstance::SendNDEF(
+    const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+  CHECK_EXIST(args, "id", out);
+
+  int peer_id = static_cast<int>(args.get("id").get<double>());
+  LoggerD("Peer id: %d", peer_id);
+
+  PlatformResult result = NFCAdapter::GetInstance()->sendNDEF(peer_id, args);
+
+  if (result.IsSuccess()) {
+    ReportSuccess(out);
+  } else {
+    LoggerE("Error: %s", result.message().c_str());
+    ReportError(result, &out);
+  }
+}
+
+void NFCInstance::ToByte(
+    const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+
+  picojson::value result = picojson::value(picojson::object());
+  picojson::object& result_obj = result.get<picojson::object>();
+  PlatformResult ret = NFCMessageUtils::NDEFMessageToByte(args, result_obj);
+
+  if (ret.IsSuccess()) {
+    ReportSuccess(result, out);
+  } else {
+    LoggerE("Error: %s", ret.message().c_str());
+    ReportError(ret, &out);
+  }
+}
+
+//Message related methods
+void NFCInstance::NDEFMessageContructor(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+  picojson::value result = picojson::value(picojson::object());
+  picojson::object& result_obj = result.get<picojson::object>();
+  PlatformResult ret = NFCMessageUtils::ReportNDEFMessage(args, result_obj);
+
+  if (ret.IsSuccess()) {
+    ReportSuccess(result, out);
+  } else {
+    LoggerE("Error: %s", ret.message().c_str());
+    ReportError(ret, &out);
+  }
+}
+
+void NFCInstance::NDEFRecordContructor(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+  picojson::value result = picojson::value(picojson::object());
+  picojson::object& result_obj = result.get<picojson::object>();
+  PlatformResult ret = NFCMessageUtils::ReportNDEFRecord(args, result_obj);
+
+  if (ret.IsSuccess()) {
+    ReportSuccess(result, out);
+  } else {
+    LoggerE("Error: %s", ret.message().c_str());
+    ReportError(ret, &out);
+  }
+}
+
+void NFCInstance::NDEFRecordTextContructor(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+
+  picojson::value result = picojson::value(picojson::object());
+  picojson::object& result_obj = result.get<picojson::object>();
+  PlatformResult ret = NFCMessageUtils::ReportNDEFRecordText(args, result_obj);
+
+  if (ret.IsSuccess()) {
+    ReportSuccess(result, out);
+  } else {
+    LoggerE("Error: %s", ret.message().c_str());
+    ReportError(ret, &out);
+  }
+}
+
+void NFCInstance::NDEFRecordURIContructor(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+  picojson::value result = picojson::value(picojson::object());
+  picojson::object& result_obj = result.get<picojson::object>();
+  PlatformResult ret = NFCMessageUtils::ReportNDEFRecordURI(args, result_obj);
+
+  if (ret.IsSuccess()) {
+    ReportSuccess(result, out);
+  } else {
+    LoggerE("Error: %s", ret.message().c_str());
+    ReportError(ret, &out);
+  }
+}
+
+void NFCInstance::NDEFRecordMediaContructor(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+
+  picojson::value result = picojson::value(picojson::object());
+  picojson::object& result_obj = result.get<picojson::object>();
+  PlatformResult ret = NFCMessageUtils::ReportNDEFRecordMedia(args, result_obj);
+
+  if (ret.IsSuccess()) {
+    ReportSuccess(result, out);
+  } else {
+    LoggerE("Error: %s", ret.message().c_str());
+    ReportError(ret, &out);
+  }
+}
+
+// NFCTag attributes getters
+void NFCInstance::TagTypeGetter(
+    const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+
+  CHECK_EXIST(args, "id", out);
+  int tag_id = (int)args.get("id").get<double>();
+  LoggerD("Tag id: %d", tag_id);
+
+  // Function below throws exception if core API call fails
+  bool is_connected = false;
+  PlatformResult result = NFCAdapter::GetInstance()->TagIsConnectedGetter(tag_id, &is_connected);
+
+  if (result.IsError()) {
+    LoggerE("Error: %s", result.message().c_str());
+    ReportError(result, &out);
+    return;
+  }
+
+  if (!is_connected) {
+    LoggerE("Tag with id %d is not connected anymore", tag_id);
+    // If tag is not connected then attribute's value
+    // should be undefined
+    ReportError(out);
+    return;
+  }
+
+  std::string tag_type = "";
+  result = NFCAdapter::GetInstance()->TagTypeGetter(tag_id, &tag_type);
+
+  if (result.IsSuccess()) {
+    ReportSuccess(picojson::value(tag_type), out);
+  } else {
+    LoggerE("Error: %s", result.message().c_str());
+    ReportError(result, &out);
+  }
+}
+
+void NFCInstance::TagIsSupportedNDEFGetter(
+    const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+
+  int tag_id = (int)args.get("id").get<double>();
+  LoggerD("Tag id: %d", tag_id);
+
+  // Function below throws exception if core API call fails
+  bool is_connected = false;
+  PlatformResult result = NFCAdapter::GetInstance()->TagIsConnectedGetter(tag_id, &is_connected);
+
+  if (result.IsError()) {
+    LoggerE("Error: %s", result.message().c_str());
+    ReportError(result, &out);
+    return;
+  }
+
+  if (!is_connected) {
+    LoggerE("Tag with id %d is not connected anymore", tag_id);
+    // If tag is not connected then attribute's value
+    // should be undefined
+    ReportError(out);
+    return;
+  }
+
+  bool is_supported = false;
+  result = NFCAdapter::GetInstance()->TagIsSupportedNDEFGetter(tag_id, &is_supported);
+  if (result.IsSuccess()) {
+    ReportSuccess(picojson::value(is_supported), out);
+  } else {
+    LoggerE("Error: %s", result.message().c_str());
+    ReportError(result, &out);
+  }
+}
+
+void NFCInstance::TagNDEFSizeGetter(
+    const picojson::value& args, picojson::object& out) {
+
+  LoggerD("Entered");
+
+  int tag_id = (int)args.get("id").get<double>();
+  LoggerD("Tag id: %d", tag_id);
+
+  // Function below throws exception if core API call fails
+  bool is_connected = false;
+  PlatformResult result = NFCAdapter::GetInstance()->TagIsConnectedGetter(tag_id, &is_connected);
+
+  if (result.IsError()) {
+    LoggerE("Error: %s", result.message().c_str());
+    ReportError(result, &out);
+    return;
+  }
+
+  if (!is_connected) {
+    LoggerE("Tag with id %d is not connected anymore", tag_id);
+    // If tag is not connected then attribute's value
+    // should be undefined
+    ReportError(out);
+    return;
+  }
+
+  unsigned int ndef_size;
+  result = NFCAdapter::GetInstance()->TagNDEFSizeGetter(tag_id, &ndef_size);
+
+  if (result.IsSuccess()) {
+    ReportSuccess(picojson::value((double)ndef_size), out);
+  } else {
+    LoggerE("Error: %s", result.message().c_str());
+    ReportError(result, &out);
+  }
+}
+
+void NFCInstance::TagPropertiesGetter(
+    const picojson::value& args, picojson::object& out) {
+
+  LoggerD("Entered");
+
+  int tag_id = (int)args.get("id").get<double>();
+  LoggerD("Tag id: %d", tag_id);
+
+  // Function below throws exception if core API call fails
+  bool is_connected = false;
+  PlatformResult result = NFCAdapter::GetInstance()->TagIsConnectedGetter(tag_id, &is_connected);
+
+  if (result.IsError()) {
+    LoggerE("Error: %s", result.message().c_str());
+    ReportError(result, &out);
+    return;
+  }
+
+  if (!is_connected) {
+    LoggerE("Tag with id %d is not connected anymore", tag_id);
+    // If tag is not connected then attribute's value
+    // should be undefined
+    ReportError(out);
+    return;
+  }
+
+  NFCTagPropertiesT prop;
+
+  result = NFCAdapter::GetInstance()->TagPropertiesGetter(tag_id, &prop);
+  if (result.IsSuccess()) {
+    picojson::value properties = picojson::value(picojson::array());
+    picojson::array& properties_array = properties.get<picojson::array>();
+    for (auto it = prop.begin() ; it != prop.end(); it++) {
+      picojson::value val = picojson::value(picojson::object());
+      picojson::object& obj = val.get<picojson::object>();
+
+      picojson::value value_vector = picojson::value(picojson::array());
+      picojson::array& value_vector_obj = value_vector.get<picojson::array>();
+
+      for (size_t i = 0 ; i < it->second.size(); i++) {
+        value_vector_obj.push_back(picojson::value(
+            std::to_string(it->second[i])));
+      }
+
+      obj[it->first] = value_vector;
+      properties_array.push_back(val);
+    }
+    ReportSuccess(properties, out);
+  } else {
+    LoggerE("Error: %s", result.message().c_str());
+    ReportError(result, &out);
+  }
+
+}
+
+void NFCInstance::TagIsConnectedGetter(
+    const picojson::value& args, picojson::object& out) {
+
+  LoggerD("Entered");
+
+  CHECK_EXIST(args, "id", out);
+  int tag_id = (int)args.get("id").get<double>();
+  LoggerD("Tag id: %d", tag_id);
+
+  bool connected = false;
+  PlatformResult result = NFCAdapter::GetInstance()->TagIsConnectedGetter(tag_id, &connected);
+
+  if (result.IsSuccess()) {
+    ReportSuccess(picojson::value(connected), out);
+  } else {
+    LoggerE("Error: %s", result.message().c_str());
+    ReportError(result, &out);
+  }
+}
+
+void NFCInstance::AddHCEEventListener(const picojson::value& args,
+                                      picojson::object& out) {
+  PlatformResult result = NFCAdapter::GetInstance()->AddHCEEventListener();
+  if (result.IsSuccess()) {
+    ReportSuccess(out);
+  } else {
+    LoggerE("Error: %s", result.message().c_str());
+    ReportError(result, &out);
+  }
+}
+
+void NFCInstance::RemoveHCEEventListener(const picojson::value& args,
+                                         picojson::object& out) {
+  PlatformResult result = NFCAdapter::GetInstance()->RemoveHCEEventListener();
+  if (result.IsSuccess()) {
+    ReportSuccess(out);
+  } else {
+    LoggerE("Error: %s", result.message().c_str());
+    ReportError(result, &out);
+  }
+}
+
+void NFCInstance::SendHostAPDUResponse(const picojson::value& args,
+                                       picojson::object& out) {
+  LoggerD("Entered");
+  CHECK_EXIST(args, JSON_APDU, out);
+  const picojson::array& apdu_array = FromJson<picojson::array>(
+      args.get<picojson::object>(), JSON_APDU);
+  const UCharVector& apdu = NFCUtil::DoubleArrayToUCharVector(apdu_array);
+  const double& callback_id = args.get(JSON_CALLBACK_ID).get<double>();
+
+  auto success_cb = [this, callback_id]() -> void {
+    LoggerD("Entered");
+    picojson::value response = picojson::value(picojson::object());
+    picojson::object& response_obj = response.get<picojson::object>();
+    response_obj[JSON_CALLBACK_ID] = picojson::value(callback_id);
+    ReportSuccess(response_obj);
+    Instance::PostMessage(this, response.serialize().c_str());
+  };
+
+  auto error_cb = [this, callback_id](const PlatformResult& error) -> void {
+    LoggerD("Entered error_cb: %s", error.message().c_str());
+    picojson::value response = picojson::value(picojson::object());
+    picojson::object& response_obj = response.get<picojson::object>();
+    response_obj[JSON_CALLBACK_ID] = picojson::value(callback_id);
+    ReportError(error, &response_obj);
+    Instance::PostMessage(this, response.serialize().c_str());
+  };
+
+  common::TaskQueue::GetInstance().Async(
+      std::bind(&NFCAdapter::SendHostAPDUResponse, NFCAdapter::GetInstance(),
+          apdu, success_cb, error_cb));
+}
+
+void NFCInstance::IsActivatedHandlerForAID(const picojson::value& args,
+                                           picojson::object& out) {
+  LoggerD("Entered");
+  CHECK_EXIST(args, JSON_TYPE, out);
+  CHECK_EXIST(args, JSON_AID, out);
+
+  const std::string& aid = args.get(JSON_AID).get<std::string>();
+  bool is_activated_handler = false;
+
+  PlatformResult result = NFCAdapter::GetInstance()->IsActivatedHandlerForAID(
+      args.get(JSON_TYPE).get<std::string>(),
+      aid,
+      &is_activated_handler);
+  if (result.IsSuccess()) {
+    ReportSuccess(picojson::value(is_activated_handler), out);
+  } else {
+    LoggerE("Error: %s", result.message().c_str());
+    ReportError(result, &out);
+  }
+}
+
+void NFCInstance::IsActivatedHandlerForCategory(const picojson::value& args,
+                                                picojson::object& out) {
+  LoggerD("Entered");
+  CHECK_EXIST(args, JSON_TYPE, out);
+  CHECK_EXIST(args, JSON_CATEGORY, out);
+
+  nfc_card_emulation_category_type_e category =
+      NFCUtil::StringToCategory(args.get(JSON_CATEGORY).get<std::string>());
+  bool is_activated_handler = false;
+
+  PlatformResult result =
+      NFCAdapter::GetInstance()->IsActivatedHandlerForCategory(
+          args.get(JSON_TYPE).get<std::string>(),
+          category,
+          &is_activated_handler);
+  if (result.IsSuccess()) {
+    ReportSuccess(picojson::value(is_activated_handler), out);
+  } else {
+    LoggerE("Error: %s", result.message().c_str());
+    ReportError(result, &out);
+  }
+}
+
+void NFCInstance::RegisterAID(const picojson::value& args,
+                              picojson::object& out) {
+  LoggerD("Entered");
+  CHECK_EXIST(args, JSON_TYPE, out);
+  CHECK_EXIST(args, JSON_AID, out);
+  CHECK_EXIST(args, JSON_CATEGORY, out);
+
+  nfc_card_emulation_category_type_e category =
+      NFCUtil::StringToCategory(args.get(JSON_CATEGORY).get<std::string>());
+
+  PlatformResult result = NFCAdapter::GetInstance()->RegisterAID(
+      args.get(JSON_TYPE).get<std::string>(),
+      args.get(JSON_AID).get<std::string>(),
+      category);
+  if (result.IsSuccess()) {
+    ReportSuccess(out);
+  } else {
+    LoggerE("Error: %s", result.message().c_str());
+    ReportError(result, &out);
+  }
+}
+
+void NFCInstance::UnregisterAID(const picojson::value& args,
+                                picojson::object& out) {
+  LoggerD("Entered");
+  CHECK_EXIST(args, JSON_TYPE, out);
+  CHECK_EXIST(args, JSON_AID, out);
+  CHECK_EXIST(args, JSON_CATEGORY, out);
+
+  nfc_card_emulation_category_type_e category =
+      NFCUtil::StringToCategory(args.get(JSON_CATEGORY).get<std::string>());
+
+  PlatformResult result =
+      NFCAdapter::GetInstance()->UnregisterAID(
+          args.get(JSON_TYPE).get<std::string>(),
+          args.get(JSON_AID).get<std::string>(),
+          category);
+  if (result.IsSuccess()) {
+    ReportSuccess(out);
+  } else {
+    LoggerE("Error: %s", result.message().c_str());
+    ReportError(result, &out);
+  }
+}
+
+void NFCInstance::GetAIDsForCategory(const picojson::value& args,
+                                     picojson::object& out) {
+  LoggerD("Entered");
+  CHECK_EXIST(args, JSON_TYPE, out);
+  CHECK_EXIST(args, JSON_CATEGORY, out);
+  const std::string& type = args.get(JSON_TYPE).get<std::string>();
+  nfc_card_emulation_category_type_e required_category =
+      NFCUtil::StringToCategory(args.get(JSON_CATEGORY).get<std::string>());
+  const double& callback_id = args.get(JSON_CALLBACK_ID).get<double>();
+
+  auto success_cb = [this, callback_id](const AIDDataVector& data) -> void {
+    LoggerD("enter");
+    picojson::array aids;
+    aids.reserve(data.size());
+    for (const auto& aid : data) {
+      aids.push_back(aid.toJSON());
+    }
+    picojson::value response = picojson::value(picojson::object());
+    picojson::object& response_obj = response.get<picojson::object>();
+    response_obj[JSON_CALLBACK_ID] = picojson::value(callback_id);
+    ReportSuccess(picojson::value(aids), response_obj);
+    Instance::PostMessage(this, response.serialize().c_str());
+  };
+
+  auto error_cb = [this, callback_id](const PlatformResult& error) -> void {
+    LoggerD("entered error_cb: %s", error.message().c_str());
+    picojson::value response = picojson::value(picojson::object());
+    picojson::object& response_obj = response.get<picojson::object>();
+    response_obj[JSON_CALLBACK_ID] = picojson::value(callback_id);
+    ReportError(error, &response_obj);
+    Instance::PostMessage(this, response.serialize().c_str());
+  };
+
+  common::TaskQueue::GetInstance().Async(
+      std::bind(&NFCAdapter::GetAIDsForCategory, NFCAdapter::GetInstance(),
+                type, required_category, success_cb, error_cb));
+}
+
+} // namespace nfc
+} // namespace extension
diff --git a/webWidgetTCT_device/src/nfc/nfc_instance.h b/webWidgetTCT_device/src/nfc/nfc_instance.h
new file mode 100755 (executable)
index 0000000..78795e4
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2015 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 NFC_NFC_INSTANCE_H_
+#define NFC_NFC_INSTANCE_H_
+
+#include "common/extension.h"
+#include "nfc/nfc_adapter.h"
+
+namespace extension {
+namespace nfc {
+
+class NFCInstance: public common::ParsedInstance, NFCAdapter::IResponder
+{
+ public:
+  NFCInstance();
+  virtual ~NFCInstance();
+
+  void RespondAsync(const char* msg);
+
+ private:
+  void GetDefaultAdapter(const picojson::value& args, picojson::object& out);
+  void SetExclusiveMode(const picojson::value& args, picojson::object& out);
+  void SetPowered(const picojson::value& args, picojson::object& out);
+  void GetPowered(const picojson::value& args, picojson::object& out);
+  void CardEmulationModeSetter(const picojson::value& args, picojson::object& out);
+  void CardEmulationModeGetter(const picojson::value& args, picojson::object& out);
+  void ActiveSecureElementSetter(const picojson::value& args, picojson::object& out);
+  void ActiveSecureElementGetter(const picojson::value& args, picojson::object& out);
+  void SetTagListener(const picojson::value& args, picojson::object& out);
+  void PeerIsConnectedGetter(const picojson::value& args, picojson::object& out);
+  void SetPeerListener(const picojson::value& args, picojson::object& out);
+  void UnsetTagListener(const picojson::value& args, picojson::object& out);
+  void UnsetPeerListener(const picojson::value& args, picojson::object& out);
+  void AddCardEmulationModeChangeListener(const picojson::value& args, picojson::object& out);
+  void RemoveCardEmulationModeChangeListener(const picojson::value& args, picojson::object& out);
+  void AddTransactionEventListener(const picojson::value& args, picojson::object& out);
+  void RemoveTransactionEventListener(const picojson::value& args, picojson::object& out);
+  void AddActiveSecureElementChangeListener(const picojson::value& args, picojson::object& out);
+  void RemoveActiveSecureElementChangeListener(const picojson::value& args, picojson::object& out);
+  void GetCachedMessage(const picojson::value& args, picojson::object& out);
+  void SetExclusiveModeForTransaction(const picojson::value& args, picojson::object& out);
+  void ReadNDEF(const picojson::value& args, picojson::object& out);
+  void WriteNDEF(const picojson::value& args, picojson::object& out);
+  void Transceive(const picojson::value& args, picojson::object& out);
+  void SetReceiveNDEFListener(const picojson::value& args, picojson::object& out);
+  void UnsetReceiveNDEFListener(const picojson::value& args, picojson::object& out);
+  void SendNDEF(const picojson::value& args, picojson::object& out);
+  void ToByte(const picojson::value& args, picojson::object& out);
+
+  // Message related methods
+  void NDEFMessageContructor(const picojson::value& args, picojson::object& out);
+  void NDEFMessageToByte(const picojson::value& args, picojson::object& out);
+  void NDEFRecordContructor(const picojson::value& args, picojson::object& out);
+  void NDEFRecordTextContructor(const picojson::value& args, picojson::object& out);
+  void NDEFRecordURIContructor(const picojson::value& args, picojson::object& out);
+  void NDEFRecordMediaContructor(const picojson::value& args, picojson::object& out);
+
+  // NFCTag attributes getters
+  void TagTypeGetter(const picojson::value& args, picojson::object& out);
+  void TagIsSupportedNDEFGetter(const picojson::value& args, picojson::object& out);
+  void TagNDEFSizeGetter(const picojson::value& args, picojson::object& out);
+  void TagPropertiesGetter(const picojson::value& args, picojson::object& out);
+  void TagIsConnectedGetter(const picojson::value& args, picojson::object& out);
+
+  // HCE related methods
+  void AddHCEEventListener(const picojson::value& args, picojson::object& out);
+  void RemoveHCEEventListener(const picojson::value& args, picojson::object& out);
+  void SendHostAPDUResponse(const picojson::value& args, picojson::object& out);
+  void IsActivatedHandlerForAID(const picojson::value& args, picojson::object& out);
+  void IsActivatedHandlerForCategory(const picojson::value& args, picojson::object& out);
+  void RegisterAID(const picojson::value& args, picojson::object& out);
+  void UnregisterAID(const picojson::value& args, picojson::object& out);
+  void GetAIDsForCategory(const picojson::value& args, picojson::object& out);
+};
+
+} // namespace nfc
+} // namespace extension
+
+#endif // NFC_NFC_INSTANCE_H_
diff --git a/webWidgetTCT_device/src/nfc/nfc_message_utils.cc b/webWidgetTCT_device/src/nfc/nfc_message_utils.cc
new file mode 100755 (executable)
index 0000000..1b2deae
--- /dev/null
@@ -0,0 +1,996 @@
+/*
+ * Copyright (c) 2015 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 "nfc/nfc_message_utils.h"
+
+#include <memory>
+
+#include "common/converter.h"
+#include "common/logger.h"
+#include "common/platform_exception.h"
+#include "nfc/nfc_util.h"
+
+using namespace common;
+
+namespace extension {
+namespace nfc {
+
+namespace {
+const char* NFC_TEXT_UTF16 = "UTF16";
+const char* NFC_TEXT_UTF8 = "UTF8";
+
+const int RECORD_TYPE_TEXT = 0x54;
+const int RECORD_TYPE_URI = 0x55;
+
+const int TNF_MIN = 0;
+const int TNF_MAX = 6;
+
+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
+};
+}
+
+/* -------------------------------COMMON FUNCTIONS------------------------------------ */
+void NFCMessageUtils::RemoveMessageHandle(nfc_ndef_message_h message_handle)
+{
+  LoggerD("Entered");
+  if (message_handle) {
+    int result = nfc_ndef_message_destroy(message_handle);
+    if (NFC_ERROR_NONE != result) {
+      LoggerE("Can't destroy NdefMessage: %d, %s", result,
+              NFCUtil::getNFCErrorMessage(result).c_str());
+    }
+    message_handle = NULL;
+  }
+}
+
+static void removeRecordHandle(nfc_ndef_record_h record_handle)
+{
+  LoggerD("Entered");
+  if (record_handle) {
+    int result = nfc_ndef_record_destroy(record_handle);
+    if (NFC_ERROR_NONE != result) {
+      LoggerE("Can't destroy NdefMessage: %d, %s", result,
+              NFCUtil::getNFCErrorMessage(result).c_str());
+    }
+    record_handle = NULL;
+  }
+}
+
+static PlatformResult getTnfFromHandle(nfc_ndef_record_h handle,
+                              nfc_ndef_message_h message_handle,
+                              short *tnf)
+{
+  LoggerD("Entered");
+  nfc_record_tnf_e record_tnf;
+  int result = nfc_ndef_record_get_tnf(handle, &record_tnf);
+  if (NFC_ERROR_NONE != result) {
+    LoggerE("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 {
+      NFCMessageUtils::RemoveMessageHandle(message_handle);
+    }
+    return NFCUtil::CodeToResult(result, "Can't get record's tnf");
+  }
+
+  *tnf = static_cast<short>(record_tnf);
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+static PlatformResult getTypeNameFromHandle(nfc_ndef_record_h handle,
+                                         nfc_ndef_message_h message_handle,
+                                         UCharVector *type)
+{
+  LoggerD("Entered");
+  unsigned char* type_name;
+  int type_size, result;
+
+  result = nfc_ndef_record_get_type(handle, &type_name, &type_size);
+  if (NFC_ERROR_NONE != result) {
+    LoggerE("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 {
+      NFCMessageUtils::RemoveMessageHandle(message_handle);
+    }
+    return NFCUtil::CodeToResult(result, "Can't get record's type");
+  }
+  *type = NFCUtil::ToVector(type_name, type_size);
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+static PlatformResult getIdFromHandle(nfc_ndef_record_h handle,
+                                   nfc_ndef_message_h message_handle,
+                                   UCharVector *id)
+{
+  LoggerD("Entered");
+  unsigned char* tmp_id;
+  int id_size, result;
+
+  result = nfc_ndef_record_get_id(handle, &tmp_id, &id_size);
+  if (NFC_ERROR_NONE != result) {
+    LoggerE("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 {
+      NFCMessageUtils::RemoveMessageHandle(message_handle);
+    }
+    return NFCUtil::CodeToResult(result, "Can't get record's id");
+  }
+
+  *id = NFCUtil::ToVector(tmp_id, id_size);
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+static PlatformResult getPayloadFromHandle(nfc_ndef_record_h handle,
+                                        nfc_ndef_message_h message_handle,
+                                        UCharVector *payload)
+{
+  LoggerD("Entered");
+  unsigned char* tmp_payload;
+  unsigned int payload_size;
+  int result;
+
+  result = nfc_ndef_record_get_payload(handle, &tmp_payload, &payload_size);
+  if (NFC_ERROR_NONE != result) {
+    LoggerE("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 {
+      NFCMessageUtils::RemoveMessageHandle(message_handle);
+    }
+    return NFCUtil::CodeToResult(result, "Can't get record's payload");
+  }
+
+  *payload = NFCUtil::ToVector(tmp_payload, payload_size);
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+static nfc_encode_type_e convertToNfcEncodeUTF(const std::string& encode_string)
+{
+  LoggerD("Entered");
+  if (NFC_TEXT_UTF16 == encode_string) {
+    return NFC_ENCODE_UTF_16;
+  }
+  else {
+    return NFC_ENCODE_UTF_8;
+  }
+}
+
+static std::string convertEncodingToString(nfc_encode_type_e encoding)
+{
+  LoggerD("Entered");
+  if (encoding == NFC_ENCODE_UTF_16) {
+    return NFC_TEXT_UTF16;
+  } else {
+    return NFC_TEXT_UTF8;
+  }
+}
+
+/* -------------------------------MESSAGE FUNCTIONS------------------------------------ */
+PlatformResult NFCMessageUtils::ToNdefRecords(const nfc_ndef_message_h message, picojson::array& array)
+{
+  LoggerD("Entered");
+  if (NULL != message) {
+    int count;
+    int result = nfc_ndef_message_get_record_count(message, &count);
+    if (NFC_ERROR_NONE != result) {
+      LoggerE("Can't get record count: %d, %s", result,
+              NFCUtil::getNFCErrorMessage(result).c_str());
+      RemoveMessageHandle(message);
+      return NFCUtil::CodeToResult(result, "Can't get record count");
+    }
+    for (int i = 0; i < count; ++i) {
+      array.push_back(picojson::value(picojson::object()));
+      picojson::object& record_obj = array.back().get<picojson::object>();
+
+      nfc_ndef_record_h record_handle = NULL;
+      int result = nfc_ndef_message_get_record(message, i, &record_handle);
+      if (NFC_ERROR_NONE != result) {
+        LoggerE("Can't get Ndef Record: %d, %s", result,
+                NFCUtil::getNFCErrorMessage(result).c_str());
+        RemoveMessageHandle(message);
+        return NFCUtil::CodeToResult(result, "Can't get Ndef Record");
+      }
+      short tnf;
+      PlatformResult ret = getTnfFromHandle(record_handle, message, &tnf);
+      if (ret.IsError()) {
+        LoggerE("Error: %s", ret.message().c_str());
+        return ret;
+      }
+      UCharVector type;
+      ret = getTypeNameFromHandle(record_handle, message, &type);
+      if (ret.IsError()) {
+        LoggerE("Error: %s", ret.message().c_str());
+        return ret;
+      }
+
+      if (NFC_RECORD_TNF_MIME_MEDIA == tnf) {
+        ret = ReportNdefRecordMediaFromMessage(message, i, record_obj);
+        if (ret.IsError()) {
+          LoggerE("Error: %s", ret.message().c_str());
+          return ret;
+        }
+        record_obj.insert(std::make_pair("recordType", picojson::value("RecordMedia")));
+        continue;
+      } else if (NFC_RECORD_TNF_WELL_KNOWN == tnf) {
+        if (!type.empty()) {
+          if (RECORD_TYPE_TEXT == type[0]) {
+            ret = ReportNdefRecordTextFromMessage(message, i, record_obj);
+            if (ret.IsError()) {
+              LoggerE("Error: %s", ret.message().c_str());
+              return ret;
+            }
+            record_obj.insert(std::make_pair("recordType", picojson::value("RecordText")));
+            continue;
+          }
+          if (RECORD_TYPE_URI == type[0]) {
+            ret = ReportNdefRecordURIFromMessage(message, i, record_obj);
+            if (ret.IsError()) {
+              LoggerE("Error: %s", ret.message().c_str());
+              return ret;
+            }
+            record_obj.insert(std::make_pair("recordType", picojson::value("RecordURI")));
+            continue;
+          }
+        }
+      }
+      ret = ConstructNdefRecordFromRecordHandle(record_handle, record_obj);
+      if (ret.IsError()) {
+        LoggerE("Error: %s", ret.message().c_str());
+        return ret;
+      }
+      record_obj.insert(std::make_pair("recordType", picojson::value("Record")));
+    }
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult NFCMessageUtils::ReportNdefMessageFromData(unsigned char* data, unsigned long size,
+                                                picojson::object& out)
+{
+  LoggerD("Entered");
+  nfc_ndef_message_h message = NULL;
+
+  int result = nfc_ndef_message_create_from_rawdata(&message, data, size);
+  if (NFC_ERROR_NONE != result) {
+    LoggerE("Can't create Ndef Message from data");
+    return NFCUtil::CodeToResult(result, "Can't create Ndef Message from data");
+  }
+  picojson::value records_array = picojson::value(picojson::array());
+  picojson::array& records_array_obj = records_array.get<picojson::array>();
+  PlatformResult ret = ToNdefRecords(message, records_array_obj);
+
+  if (ret.IsError()) {
+    LoggerE("Error: %s", ret.message().c_str());
+    RemoveMessageHandle(message);
+    return ret;
+  }
+
+  out.insert(std::make_pair("records", picojson::value(records_array)));
+
+  RemoveMessageHandle(message);
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult NFCMessageUtils::ReportNDEFMessage(const picojson::value& args, picojson::object& out){
+  LoggerD("Entered");
+  const picojson::array& raw_data =
+      FromJson<picojson::array>(args.get<picojson::object>(), "rawData");
+  const int size = static_cast<int>(args.get("rawDataSize").get<double>());
+
+  std::unique_ptr<unsigned char[]> data(new unsigned char[size]);
+
+  for (size_t i = 0; i < size; i++) {
+    data[i] = static_cast<unsigned char>(raw_data[i].get<double>());
+  }
+
+  return ReportNdefMessageFromData(data.get(), size, out);
+}
+
+static PlatformResult NdefRecordGetHandle(picojson::value& record,
+                            nfc_ndef_record_h *record_handle)
+{
+  LoggerD("Entered");
+  if (!record.is<picojson::object>() || !record.contains("tnf") || !record.contains("type") ||
+      !record.contains("id") || !record.contains("payload")) {
+    return PlatformResult(ErrorCode::TYPE_MISMATCH_ERR, "Record is empty");
+  }
+  const picojson::object& record_obj = record.get<picojson::object>();
+  short tnf_from_json = static_cast<short>(record.get("tnf").get<double>());
+  nfc_record_tnf_e tnf = static_cast<nfc_record_tnf_e>(tnf_from_json);
+  const picojson::array& type_data =
+      FromJson<picojson::array>(record_obj, "type");
+  int type_size = type_data.size();
+  std::unique_ptr<unsigned char[]> type(new unsigned char[type_size]);
+  for (size_t i = 0; i < type_size; i++) {
+    type[i] = static_cast<unsigned char>(type_data[i].get<double>());
+  }
+  const picojson::array& id_data =
+      FromJson<picojson::array>(record_obj, "id");
+  int id_size = id_data.size();
+  std::unique_ptr<unsigned char[]> id(new unsigned char[id_size]);
+  for (size_t i = 0; i < id_size; i++) {
+    id[i] = static_cast<unsigned char>(id_data[i].get<double>());
+  }
+  const picojson::array& payload_data =
+      FromJson<picojson::array>(record_obj, "payload");
+  int payload_size = payload_data.size();
+  std::unique_ptr<unsigned char[]> payload(new unsigned char[payload_size]);
+  for (size_t i = 0; i < payload_size; i++) {
+    payload[i] = static_cast<unsigned char>(payload_data[i].get<double>());
+  }
+  if ((tnf_from_json < TNF_MIN) || (tnf_from_json > TNF_MAX)) {
+    LoggerE("Not supported tnf");
+    return PlatformResult(ErrorCode::TYPE_MISMATCH_ERR, "Type mismatch");
+  }
+  const int BYTE_ARRAY_MAX = 255;
+  nfc_ndef_record_h ndef_record_handle = NULL;
+  int result = nfc_ndef_record_create(&ndef_record_handle,
+                                      tnf, type.get(), type_size > BYTE_ARRAY_MAX ? BYTE_ARRAY_MAX : type_size,
+                                          id.get(), id_size > BYTE_ARRAY_MAX ? BYTE_ARRAY_MAX : id_size,
+                                              payload.get(), payload_size);
+  if (NFC_ERROR_NONE != result) {
+    removeRecordHandle(ndef_record_handle);
+    LoggerE("Can't create Ndef Record: %d, %s", result,
+            NFCUtil::getNFCErrorMessage(result).c_str());
+    return NFCUtil::CodeToResult(result, "Can't create Ndef Record");
+  }
+  *record_handle = ndef_record_handle;
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult NFCMessageUtils::NDEFMessageToStruct(const picojson::array& records_array,
+                                                        const int size,
+                                                        nfc_ndef_message_h *message)
+{
+  LoggerD("Entered");
+  if (!size) {
+    LoggerE("No records in message");
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+
+  nfc_ndef_message_h ndef_message;
+  int result = nfc_ndef_message_create(&ndef_message);
+
+  if (NFC_ERROR_NONE != result) {
+    RemoveMessageHandle(ndef_message);
+    LoggerE("Can't create Ndef Message: %d, %s", result,
+            NFCUtil::getNFCErrorMessage(result).c_str());
+    return NFCUtil::CodeToResult(result, "Can't create Ndef Message");
+  }
+
+  for (picojson::value record : records_array) {
+    nfc_ndef_record_h record_handle;
+    PlatformResult ret = NdefRecordGetHandle(record, &record_handle);
+
+    if (ret.IsError()) {
+      LoggerE("Error: %s", ret.message().c_str());
+      RemoveMessageHandle(ndef_message);
+      return ret;
+    }
+
+    result = nfc_ndef_message_append_record(ndef_message, record_handle);
+    if (NFC_ERROR_NONE != result) {
+      LoggerE("record can't be inserted: %d, %s", result,
+              NFCUtil::getNFCErrorMessage(result).c_str());
+      removeRecordHandle(record_handle);
+      RemoveMessageHandle(ndef_message);
+      return NFCUtil::CodeToResult(result, "Invalid NDEF Message");
+    }
+  }
+  *message = ndef_message;
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult NFCMessageUtils::NDEFMessageToByte(const picojson::value& args, picojson::object& out){
+  LoggerD("Entered");
+  //input
+  const picojson::array& records_array =
+      FromJson<picojson::array>(args.get<picojson::object>(), "records");
+  const int size = static_cast<int>(args.get("recordsSize").get<double>());
+
+  //output
+  picojson::value byte_array = picojson::value(picojson::array());
+  picojson::array& byte_array_obj = byte_array.get<picojson::array>();
+
+  nfc_ndef_message_h message = NULL;
+
+  PlatformResult ret = NDEFMessageToStruct(records_array, size, &message);
+
+  if (ret.IsError()) {
+    LoggerE("Error: %s", ret.message().c_str());
+    return ret;
+  }
+
+  if (!message) {
+    out.insert(std::make_pair("bytes", picojson::value(byte_array)));
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+
+  unsigned char* raw_data = NULL;
+
+  unsigned int raw_data_size = 0;
+  int result = nfc_ndef_message_get_rawdata(message, &raw_data, &raw_data_size);
+
+  RemoveMessageHandle(message);
+  message = NULL;
+
+  if (NFC_ERROR_NONE != result) {
+    LoggerE("Can't get serial bytes of NDEF message: %d, %s", result,
+            NFCUtil::getNFCErrorMessage(result).c_str());
+    return NFCUtil::CodeToResult(result, "Can't get serial bytes of NDEF message");
+  }
+
+  for (size_t i = 0 ; i < raw_data_size; i++) {
+    byte_array_obj.push_back(picojson::value(std::to_string(raw_data[i])));
+  }
+  if (raw_data) {
+    free(raw_data);
+  }
+  out.insert(std::make_pair("bytes", picojson::value(byte_array)));
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+/* -------------------------------RECORD FUNCTIONS------------------------------------ */
+static void ConstructRecordJson(short _tnf, const UCharVector& _type_name,
+                                const UCharVector& _id, const UCharVector& _payload, picojson::object& out)
+{
+  LoggerD("Entered");
+  out.insert(std::make_pair("tnf", picojson::value(std::to_string(_tnf))));
+
+  picojson::value type_array = picojson::value(picojson::array());
+  picojson::array& type_array_obj = type_array.get<picojson::array>();
+  for (size_t i = 0 ; i < _type_name.size(); i++) {
+    type_array_obj.push_back(picojson::value(std::to_string(_type_name[i])));
+  }
+  out.insert(std::make_pair("type", picojson::value(type_array)));
+
+  picojson::value id_array = picojson::value(picojson::array());
+  picojson::array& id_array_obj = id_array.get<picojson::array>();
+  for (size_t i = 0 ; i < _id.size(); i++) {
+    id_array_obj.push_back(picojson::value(std::to_string(_id[i])));
+  }
+  out.insert(std::make_pair("id", picojson::value(id_array)));
+
+  picojson::value payload_array = picojson::value(picojson::array());
+  picojson::array& payload_array_obj = payload_array.get<picojson::array>();
+  for (size_t i = 0 ; i < _payload.size(); i++) {
+    payload_array_obj.push_back(picojson::value(std::to_string(_payload[i])));
+  }
+  out.insert(std::make_pair("payload", picojson::value(payload_array)));
+}
+
+PlatformResult NFCMessageUtils::ConstructNdefRecordFromRecordHandle(nfc_ndef_record_h record_handle,
+                                                          picojson::object& out)
+{
+  LoggerD("Entered");
+
+  short _tnf;
+  PlatformResult ret = getTnfFromHandle(record_handle, NULL, &_tnf);
+  if (ret.IsError()) {
+    LoggerE("Error: %s", ret.message().c_str());
+    return ret;
+  }
+  UCharVector _type_name;
+  ret = getTypeNameFromHandle(record_handle, NULL, &_type_name);
+  if (ret.IsError()) {
+    LoggerE("Error: %s", ret.message().c_str());
+    return ret;
+  }
+  UCharVector _id;
+  ret = getIdFromHandle(record_handle, NULL, &_id);
+  if (ret.IsError()) {
+    LoggerE("Error: %s", ret.message().c_str());
+    return ret;
+  }
+  UCharVector _payload;
+  ret = getPayloadFromHandle(record_handle, NULL, &_payload);
+  if (ret.IsError()) {
+    LoggerE("Error: %s", ret.message().c_str());
+    return ret;
+  }
+
+  //constructing json
+  ConstructRecordJson(_tnf, _type_name, _id, _payload, out);
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult NFCMessageUtils::ReportNdefRecordFromMessage(nfc_ndef_message_h message_handle,
+                                                  const int index, picojson::object& out)
+{
+  LoggerD("Entered");
+  nfc_ndef_record_h record_handle = NULL;
+  int result = nfc_ndef_message_get_record(message_handle, index, &record_handle);
+  if (NFC_ERROR_NONE != result) {
+    LoggerE("Can't get NdefRecord: %d, %s", result,
+            NFCUtil::getNFCErrorMessage(result).c_str());
+    RemoveMessageHandle(message_handle);
+    return NFCUtil::CodeToResult(result, "Can't get NdefRecord");
+  }
+
+  return ConstructNdefRecordFromRecordHandle(record_handle, out);
+}
+
+PlatformResult NFCMessageUtils::ReportNDEFRecord(const picojson::value& args, picojson::object& out){
+  LoggerD("Entered");
+  const picojson::array& raw_data =
+      FromJson<picojson::array>(args.get<picojson::object>(), "rawData");
+  const int size = static_cast<int>(args.get("rawDataSize").get<double>());
+
+  std::unique_ptr<unsigned char[]> data(new unsigned char[size]);
+
+  for (size_t i = 0; i < size; i++) {
+    data[i] = static_cast<unsigned char>(raw_data[i].get<double>());
+  }
+  nfc_ndef_message_h message_handle = NULL;
+
+  int result = nfc_ndef_message_create_from_rawdata(&message_handle, data.get(), size);
+  if (NFC_ERROR_NONE != result) {
+    LoggerE("Can't create NdefMessage from data: %d, %s", result,
+            NFCUtil::getNFCErrorMessage(result).c_str());
+    return NFCUtil::CodeToResult(result, "Can't create NdefMessage from data");
+  }
+
+  int count;
+  result = nfc_ndef_message_get_record_count(message_handle, &count);
+  if (NFC_ERROR_NONE != result) {
+    LoggerE("Can't get record count: %d, %s", result,
+            NFCUtil::getNFCErrorMessage(result).c_str());
+    RemoveMessageHandle(message_handle);
+    return NFCUtil::CodeToResult(result, "Can't get record count");
+  }
+
+  PlatformResult ret = ReportNdefRecordFromMessage(message_handle, 0, out);
+
+  RemoveMessageHandle(message_handle);
+
+  if (ret.IsError()) {
+    LoggerE("Error: %s", ret.message().c_str());
+    return ret;
+  }
+
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+/* -------------------------------RECORD TEXT FUNCTIONS------------------------------------ */
+static PlatformResult getTextFromHandle(nfc_ndef_record_h handle,
+                                     nfc_ndef_message_h message_handle,
+                                     std::string *text)
+{
+  LoggerD("Entered");
+  char* tmp_text = NULL;
+  int result = nfc_ndef_record_get_text(handle, &tmp_text);
+  if (NFC_ERROR_NONE != result) {
+    LoggerE("Can't get record's text: %d, %s", result,
+            NFCUtil::getNFCErrorMessage(result).c_str());
+    NFCMessageUtils::RemoveMessageHandle(message_handle);
+    return NFCUtil::CodeToResult(result, "Can't get record's text");
+  }
+
+  std::string text_string(tmp_text);
+  free(tmp_text);
+  tmp_text = NULL;
+  *text = text_string;
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+static PlatformResult getLanguageCodeFromHandle(nfc_ndef_record_h handle,
+                                             nfc_ndef_message_h message_handle,
+                                             std::string *language)
+{
+  LoggerD("Entered");
+  char* language_code = NULL;
+  int result = nfc_ndef_record_get_langcode(handle, &language_code);
+  if (NFC_ERROR_NONE != result) {
+    LoggerE("Can't get record's languageCode: %d, %s", result,
+            NFCUtil::getNFCErrorMessage(result).c_str());
+    NFCMessageUtils::RemoveMessageHandle(message_handle);
+    return NFCUtil::CodeToResult(result, "Can't get record's languageCode");
+  }
+
+  std::string language_string(language_code);
+  free(language_code);
+  language_code = NULL;
+  *language = language_string;
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+static PlatformResult getEncodingFromHandle(nfc_ndef_record_h handle,
+                                               nfc_ndef_message_h message_handle,
+                                               nfc_encode_type_e *encoding_type)
+{
+  LoggerD("Entered");
+  nfc_encode_type_e encoding;
+  int result = nfc_ndef_record_get_encode_type(handle, &encoding);
+  if (NFC_ERROR_NONE != result) {
+    LoggerE("Can't get record's encoding: %d, %s", result,
+            NFCUtil::getNFCErrorMessage(result).c_str());
+    NFCMessageUtils::RemoveMessageHandle(message_handle);
+    return NFCUtil::CodeToResult(result, "Can't get record's encoding");
+  }
+
+  *encoding_type = encoding;
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+static PlatformResult ReportNDEFRecordTextFromText(const std::string& text, const std::string& language_code,
+                                         const std::string& encoding_str, picojson::object& out)
+{
+  LoggerD("Entered");
+  nfc_encode_type_e encoding = convertToNfcEncodeUTF(encoding_str);
+  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) {
+    LoggerE("Unknown error while getting text record: %d, %s", result,
+            NFCUtil::getNFCErrorMessage(result).c_str());
+    return NFCUtil::CodeToResult(result,"Can't create text record");
+  }
+
+  short _tnf;
+  PlatformResult ret = getTnfFromHandle(handle, NULL, &_tnf);
+  if (ret.IsError()) {
+    LoggerE("Error: %s", ret.message().c_str());
+    return ret;
+  }
+  UCharVector _type_name;
+  ret = getTypeNameFromHandle(handle, NULL, &_type_name);
+  if (ret.IsError()) {
+    LoggerE("Error: %s", ret.message().c_str());
+    return ret;
+  }
+  UCharVector _id;
+  ret = getIdFromHandle(handle, NULL, &_id);
+  if (ret.IsError()) {
+    LoggerE("Error: %s", ret.message().c_str());
+    return ret;
+  }
+  UCharVector _payload;
+  ret = getPayloadFromHandle(handle, NULL, &_payload);
+  if (ret.IsError()) {
+    LoggerE("Error: %s", ret.message().c_str());
+    return ret;
+  }
+
+  //constructing json
+  ConstructRecordJson(_tnf, _type_name, _id, _payload, out);
+
+  removeRecordHandle(handle);
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult NFCMessageUtils::ReportNdefRecordTextFromMessage(nfc_ndef_message_h message_handle,
+                                                      const int index, picojson::object& out)
+{
+  LoggerD("Entered");
+  nfc_ndef_record_h record_handle = NULL;
+  //This function just return the pointer of record.
+  int result = nfc_ndef_message_get_record(message_handle, index, &record_handle);
+  if (NFC_ERROR_NONE != result) {
+    LoggerE("Can't get Ndef Record: %d, %s", result,
+            NFCUtil::getNFCErrorMessage(result).c_str());
+    RemoveMessageHandle(message_handle);
+    return NFCUtil::CodeToResult(result, "Can't get Ndef Record");
+  }
+
+
+  nfc_encode_type_e encoding;
+  PlatformResult ret = getEncodingFromHandle(record_handle, message_handle, &encoding);
+  if (ret.IsError()) {
+    LoggerE("Error: %s", ret.message().c_str());
+    return ret;
+  }
+  std::string encoding_str = convertEncodingToString(encoding);
+
+  std::string text;
+  ret = getTextFromHandle(record_handle, message_handle, &text);
+  if (ret.IsError()) {
+    LoggerE("Error: %s", ret.message().c_str());
+    return ret;
+  }
+  std::string language_code;
+  ret = getLanguageCodeFromHandle(record_handle, message_handle, &language_code);
+  if (ret.IsError()) {
+    LoggerE("Error: %s", ret.message().c_str());
+    return ret;
+  }
+
+  ret = ReportNDEFRecordTextFromText(text, language_code, encoding_str, out);
+  if (ret.IsError()) {
+    LoggerE("Error: %s", ret.message().c_str());
+    return ret;
+  }
+
+  out.insert(std::make_pair("text", picojson::value(text)));
+  out.insert(std::make_pair("languageCode", picojson::value(language_code)));
+  out.insert(std::make_pair("encoding", picojson::value(encoding_str)));
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult NFCMessageUtils::ReportNDEFRecordText(const picojson::value& args, picojson::object& out){
+  LoggerD("Entered");
+  const std::string& text = args.get("text").get<std::string>();
+  const std::string& language_code = args.get("languageCode").get<std::string>();
+  const std::string& encoding_str = args.get("encoding").get<std::string>();
+
+  return ReportNDEFRecordTextFromText(text, language_code, encoding_str, out);
+}
+
+/* -------------------------------RECORD URI FUNCTIONS------------------------------------ */
+static PlatformResult getURIFromHandle(nfc_ndef_record_h handle,
+                                    nfc_ndef_message_h message_handle,
+                                    std::string* uri_handle)
+{
+  LoggerD("Entered");
+  char* uri = NULL;
+  int result = nfc_ndef_record_get_uri(handle, &uri);
+  if (NFC_ERROR_NONE != result) {
+    LoggerE("Can't get record's uri: %d, %s", result,
+            NFCUtil::getNFCErrorMessage(result).c_str());
+    NFCMessageUtils::RemoveMessageHandle(message_handle);
+    return NFCUtil::CodeToResult(result, "Can't get record's uri");
+  }
+
+  std::string uri_string(uri);
+  free(uri);
+  uri = NULL;
+  *uri_handle = uri_string;
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+static PlatformResult ReportNDEFRecordURIFromURI(const std::string& uri, picojson::object& out)
+{
+  LoggerD("Entered");
+  nfc_ndef_record_h handle = NULL;
+
+  int result = nfc_ndef_record_create_uri(&handle, uri.c_str());
+  if(NFC_ERROR_NONE != result) {
+    LoggerE("Unknown error while creating NdefRecordURI: %d, %s", result,
+            NFCUtil::getNFCErrorMessage(result).c_str());
+    return NFCUtil::CodeToResult(result, "Unknown error while creating NdefRecordURI");
+  }
+
+  short _tnf;
+  PlatformResult ret = getTnfFromHandle(handle, NULL, &_tnf);
+  if (ret.IsError()) {
+    LoggerE("Error: %s", ret.message().c_str());
+    return ret;
+  }
+  UCharVector _type_name;
+  ret = getTypeNameFromHandle(handle, NULL, &_type_name);
+  if (ret.IsError()) {
+    LoggerE("Error: %s", ret.message().c_str());
+    return ret;
+  }
+  UCharVector _id;
+  ret = getIdFromHandle(handle, NULL, &_id);
+  if (ret.IsError()) {
+    LoggerE("Error: %s", ret.message().c_str());
+    return ret;
+  }
+  UCharVector _payload;
+  ret = getPayloadFromHandle(handle, NULL, &_payload);
+  if (ret.IsError()) {
+    LoggerE("Error: %s", ret.message().c_str());
+    return ret;
+  }
+
+  //constructing json
+  ConstructRecordJson(_tnf, _type_name, _id, _payload, out);
+
+  removeRecordHandle(handle);
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult NFCMessageUtils::ReportNdefRecordURIFromMessage(nfc_ndef_message_h message_handle,
+                                                     const int index, picojson::object& out)
+{
+  LoggerD("Entered");
+  nfc_ndef_record_h record_handle = NULL;
+  //This function just return the pointer of record.
+  int result = nfc_ndef_message_get_record(message_handle, index, &record_handle);
+  if (NFC_ERROR_NONE != result) {
+    LoggerE("Can't get Ndef Record: %d, %s", result,
+            NFCUtil::getNFCErrorMessage(result).c_str());
+    RemoveMessageHandle(message_handle);
+    return NFCUtil::CodeToResult(result, "Can't get Ndef Record");
+  }
+
+  std::string uri;
+  PlatformResult ret = getURIFromHandle(record_handle, message_handle, &uri);
+  if (ret.IsError()) {
+    LoggerE("Error: %s", ret.message().c_str());
+    return ret;
+  }
+  ret = ReportNDEFRecordURIFromURI(uri, out);
+  if (ret.IsError()) {
+    LoggerE("Error: %s", ret.message().c_str());
+    return ret;
+  }
+  out.insert(std::make_pair("uri", picojson::value(uri)));
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult NFCMessageUtils::ReportNDEFRecordURI(const picojson::value& args, picojson::object& out){
+  LoggerD("Entered");
+
+  const std::string& uri = args.get("uri").get<std::string>();
+  return ReportNDEFRecordURIFromURI(uri, out);
+}
+
+/* -------------------------------RECORD MEDIA FUNCTIONS------------------------------------ */
+static PlatformResult getMimeTypeFromHandle(nfc_ndef_record_h handle,
+                                         nfc_ndef_message_h message_handle,
+                                         std::string *mime)
+{
+  LoggerD("Entered");
+  char* mime_type = NULL;
+  int result = nfc_ndef_record_get_mime_type(handle, &mime_type);
+  if (NFC_ERROR_NONE != result) {
+    LoggerE("Can't get record's mime_type: %d, %s", result,
+            NFCUtil::getNFCErrorMessage(result).c_str());
+    NFCMessageUtils::RemoveMessageHandle(message_handle);
+    return NFCUtil::CodeToResult(result, "Can't get record's mime_type");
+  }
+
+  std::string mime_string(mime_type);
+  free(mime_type);
+  mime_type = NULL;
+  *mime = mime_string;
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult NFCMessageUtils::ReportNdefRecordMediaFromMessage(nfc_ndef_message_h message_handle,
+                                                       const int index, picojson::object& out)
+{
+  LoggerD("Entered");
+  nfc_ndef_record_h record_handle = NULL;
+  //This function just return the pointer of record.
+  int result = nfc_ndef_message_get_record(message_handle, index, &record_handle);
+  if (NFC_ERROR_NONE != result) {
+    LoggerE("Can't get Ndef Record: %d, %s", result,
+            NFCUtil::getNFCErrorMessage(result).c_str());
+    RemoveMessageHandle(message_handle);
+    return NFCUtil::CodeToResult(result, "Can't get Ndef Record");
+  }
+
+  std::string mime_type;
+  PlatformResult ret = getMimeTypeFromHandle(record_handle, message_handle, &mime_type);
+  if (ret.IsError()) {
+    LoggerE("Error: %s", ret.message().c_str());
+    return ret;
+  }
+  short _tnf;
+  ret = getTnfFromHandle(record_handle, message_handle, &_tnf);
+  if (ret.IsError()) {
+    LoggerE("Error: %s", ret.message().c_str());
+    return ret;
+  }
+  UCharVector _type_name;
+  ret = getTypeNameFromHandle(record_handle, message_handle, &_type_name);
+  if (ret.IsError()) {
+    LoggerE("Error: %s", ret.message().c_str());
+    return ret;
+  }
+  UCharVector _id;
+  ret = getIdFromHandle(record_handle, message_handle, &_id);
+  if (ret.IsError()) {
+    LoggerE("Error: %s", ret.message().c_str());
+    return ret;
+  }
+  UCharVector _payload;
+  ret = getPayloadFromHandle(record_handle, message_handle, &_payload);
+  if (ret.IsError()) {
+    LoggerE("Error: %s", ret.message().c_str());
+    return ret;
+  }
+
+  //constructing json
+  ConstructRecordJson(_tnf, _type_name, _id, _payload, out);
+  out.insert(std::make_pair("mimeType", picojson::value(mime_type)));
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult NFCMessageUtils::ReportNDEFRecordMedia(const picojson::value& args, picojson::object& out){
+  LoggerD("Entered");
+
+  const std::string& mime_type = args.get("mimeType").get<std::string>();
+  const picojson::array& raw_data =
+      FromJson<picojson::array>(args.get<picojson::object>(), "data");
+  const int size = static_cast<int>(args.get("dataSize").get<double>());
+
+  std::unique_ptr<unsigned char[]> data(new unsigned char[size]);
+  for (size_t i = 0; i < size; i++) {
+    data[i] = static_cast<unsigned char>(raw_data[i].get<double>());
+  }
+
+  nfc_ndef_record_h handle = NULL;
+
+  short _tnf = NFC_RECORD_TNF_UNKNOWN;
+  UCharVector _type_name;
+  UCharVector _id;
+  UCharVector _payload;
+
+  int result = nfc_ndef_record_create_mime(&handle, mime_type.c_str(), data.get(),
+                                           size);
+  if (NFC_ERROR_NONE != result) {
+    LoggerE("Unknown error while getting mimeType: %s - %d: %s",
+            mime_type.c_str(), result,
+            NFCUtil::getNFCErrorMessage(result).c_str());
+    //Do not throw just return default values
+    //NFCUtil::throwNFCException(result, "Unknown error while getting mimeType");
+  } else {
+
+    PlatformResult ret = getTnfFromHandle(handle, NULL, &_tnf);
+    if (ret.IsError()) {
+      LoggerE("Error: %s", ret.message().c_str());
+      return ret;
+    }
+    ret = getTypeNameFromHandle(handle, NULL, &_type_name);
+    if (ret.IsError()) {
+      LoggerE("Error: %s", ret.message().c_str());
+      return ret;
+    }
+    ret = getIdFromHandle(handle, NULL, &_id);
+    if (ret.IsError()) {
+      LoggerE("Error: %s", ret.message().c_str());
+      return ret;
+    }
+    ret = getPayloadFromHandle(handle, NULL, &_payload);
+    if (ret.IsError()) {
+      LoggerE("Error: %s", ret.message().c_str());
+      return ret;
+    }
+  }
+
+  //constructing json
+  ConstructRecordJson(_tnf, _type_name, _id, _payload, out);
+
+  removeRecordHandle(handle);
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+} // NFC
+} // DeviceApi
diff --git a/webWidgetTCT_device/src/nfc/nfc_message_utils.h b/webWidgetTCT_device/src/nfc/nfc_message_utils.h
new file mode 100755 (executable)
index 0000000..7bd5eb4
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2015 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_NFC_NFC_MESSAGE_UTILS_H_
+#define __TIZEN_NFC_NFC_MESSAGE_UTILS_H_
+
+#include <network/nfc.h>
+
+#include <string>
+#include <vector>
+
+#include "common/picojson.h"
+#include "common/platform_result.h"
+
+namespace extension {
+namespace nfc {
+
+typedef std::vector<unsigned char> UCharVector;
+
+class NFCMessageUtils
+{
+ public:
+  static common::PlatformResult ToNdefRecords(const nfc_ndef_message_h message, picojson::array& array);
+  static common::PlatformResult ReportNdefMessageFromData(unsigned char* data, unsigned long size,
+                                        picojson::object& out);
+  static common::PlatformResult ReportNDEFMessage(const picojson::value& args, picojson::object& out);
+  static common::PlatformResult NDEFMessageToStruct(const picojson::array& records_array,
+                                                const int size,
+                                                nfc_ndef_message_h *message);
+  static common::PlatformResult NDEFMessageToByte(const picojson::value& args, picojson::object& out);
+  static common::PlatformResult ConstructNdefRecordFromRecordHandle(nfc_ndef_record_h record_handle,
+                                                  picojson::object& out);
+  static common::PlatformResult ReportNdefRecordFromMessage(nfc_ndef_message_h message_handle,
+                                          const int index, picojson::object& out);
+  static common::PlatformResult ReportNDEFRecord(const picojson::value& args, picojson::object& out);
+  static common::PlatformResult ReportNdefRecordTextFromMessage(nfc_ndef_message_h message_handle,
+                                              const int index, picojson::object& out);
+  static common::PlatformResult ReportNDEFRecordText(const picojson::value& args, picojson::object& out);
+  static common::PlatformResult ReportNdefRecordURIFromMessage(nfc_ndef_message_h message_handle,
+                                             const int index, picojson::object& out);
+  static common::PlatformResult ReportNDEFRecordURI(const picojson::value& args, picojson::object& out);
+  static common::PlatformResult ReportNdefRecordMediaFromMessage(nfc_ndef_message_h message_handle,
+                                               const int index, picojson::object& out);
+  static common::PlatformResult ReportNDEFRecordMedia(const picojson::value& args, picojson::object& out);
+  static void RemoveMessageHandle(nfc_ndef_message_h message_handle);
+};
+
+}  // nfc
+}  // extension
+
+#endif  // __TIZEN_NFC_NFC_MESSAGE_UTILS_H_
diff --git a/webWidgetTCT_device/src/nfc/nfc_util.cc b/webWidgetTCT_device/src/nfc/nfc_util.cc
new file mode 100755 (executable)
index 0000000..11d0e8c
--- /dev/null
@@ -0,0 +1,388 @@
+/*
+ * Copyright (c) 2015 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 "nfc/nfc_util.h"
+
+#include "common/assert.h"
+#include "common/logger.h"
+#include "common/platform_exception.h"
+#include "nfc/defs.h"
+
+using namespace common;
+
+namespace extension {
+namespace nfc {
+
+UCharVector NFCUtil::ToVector(const unsigned char* ch, const int size)
+{
+  LoggerD("Entered");
+  UCharVector vec(ch, ch + size / sizeof(char));
+  return vec;
+}
+
+PlatformResult NFCUtil::CodeToResult(const int errorCode,
+                                     const std::string& message) {
+  LoggerD("Entered");
+  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:
+      return PlatformResult(ErrorCode::INVALID_VALUES_ERR, message);
+    case NFC_ERROR_SECURITY_RESTRICTED:
+    case NFC_ERROR_PERMISSION_DENIED:
+      return PlatformResult(ErrorCode::SECURITY_ERR, message);
+    case NFC_ERROR_NOT_SUPPORTED:
+      return PlatformResult(ErrorCode::NOT_SUPPORTED_ERR, message);
+    case NFC_ERROR_NOT_ACTIVATED:
+    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:
+    case NFC_ERROR_NOT_INITIALIZED:
+    default:
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, message);
+  }
+}
+
+std::string NFCUtil::getNFCErrorString(const int error_code)
+{
+  LoggerD("Error code : %d",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 INVALID_VALUES_ERROR_NAME_STR;
+    case NFC_ERROR_NO_DEVICE:
+    case NFC_ERROR_OUT_OF_MEMORY:
+    case NFC_ERROR_OPERATION_FAILED:
+    case NFC_ERROR_DEVICE_BUSY:
+      return UNKNOWN_ERROR_NAME_STR;
+    case NFC_ERROR_NOT_ACTIVATED:
+      return SERVICE_NOT_AVAILABLE_ERROR_NAME_STR;
+    case NFC_ERROR_NOT_SUPPORTED:
+      return NOT_SUPPORTED_ERROR_NAME_STR;
+    case NFC_ERROR_TIMED_OUT:
+      return TIMEOUT_ERROR_NAME_STR;
+  }
+  return UNKNOWN_ERROR_NAME_STR;
+}
+
+const std::string NFCUtil::getNFCErrorMessage(const int error_code) {
+  LoggerD("Error code : %d", 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";
+    default:
+      return "UnknownError";
+  }
+}
+
+std::string NFCUtil::ToStringNFCTag(nfc_tag_type_e tag_type)
+{
+  LoggerD("Entered");
+  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;
+  }
+}
+
+PlatformResult NFCUtil::ToNfcTagString(const std::string& type_string, nfc_tag_type_e* tag_type)
+{
+  LoggerD("Entered");
+  if (GENERIC_TARGET == type_string) {
+    *tag_type = NFC_GENERIC_PICC;
+  }
+  else if (ISO14443_A == type_string) {
+    *tag_type = NFC_ISO14443_A_PICC;
+  }
+  else if (ISO14443_4A == type_string) {
+    *tag_type = NFC_ISO14443_4A_PICC;
+  }
+  else if (ISO14443_3A == type_string) {
+    *tag_type = NFC_ISO14443_3A_PICC;
+  }
+  else if (MIFARE_MINI == type_string) {
+    *tag_type = NFC_MIFARE_MINI_PICC;
+  }
+  else if (MIFARE_1K == type_string) {
+    *tag_type = NFC_MIFARE_1K_PICC;
+  }
+  else if (MIFARE_4K == type_string) {
+    *tag_type = NFC_MIFARE_4K_PICC;
+  }
+  else if (MIFARE_ULTRA == type_string) {
+    *tag_type = NFC_MIFARE_ULTRA_PICC;
+  }
+  else if (MIFARE_DESFIRE == type_string) {
+    *tag_type = NFC_MIFARE_DESFIRE_PICC;
+  }
+  else if (ISO14443_B == type_string) {
+    *tag_type = NFC_ISO14443_B_PICC;
+  }
+  else if (ISO14443_4B == type_string) {
+    *tag_type = NFC_ISO14443_4B_PICC;
+  }
+  else if (ISO14443_BPRIME == type_string) {
+    *tag_type = NFC_ISO14443_BPRIME_PICC;
+  }
+  else if (FELICA == type_string) {
+    *tag_type = NFC_FELICA_PICC;
+  }
+  else if (JEWEL == type_string) {
+    *tag_type = NFC_JEWEL_PICC;
+  }
+  else if (ISO15693 == type_string) {
+    *tag_type = NFC_ISO15693_PICC;
+  }
+  else if (UNKNOWN_TARGET == type_string) {
+    *tag_type = NFC_UNKNOWN_TARGET;
+  }
+  else {
+    return PlatformResult(ErrorCode::TYPE_MISMATCH_ERR, "No Match Tag Type");
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult NFCUtil::ToStringCardEmulationMode(
+    const nfc_se_card_emulation_mode_type_e card_mode, std::string* mode)
+{
+  LoggerD("Entered");
+  switch (card_mode)
+  {
+    case NFC_SE_CARD_EMULATION_MODE_OFF:
+      *mode = OFF;
+      break;
+    case NFC_SE_CARD_EMULATION_MODE_ON:
+      *mode = ALWAYS_ON;
+      break;
+    default:
+      LoggerE("No Match Card Emulation mode: %x", card_mode);
+      return PlatformResult(ErrorCode::TYPE_MISMATCH_ERR, "No Match Card Emulation mode");
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult NFCUtil::ToCardEmulationMode(
+    const std::string& mode_string,
+    nfc_se_card_emulation_mode_type_e* mode) {
+  LoggerD("Entered");
+  if (mode_string == ALWAYS_ON) {
+    *mode = NFC_SE_CARD_EMULATION_MODE_ON;
+  } else if (mode_string == OFF) {
+    *mode = NFC_SE_CARD_EMULATION_MODE_OFF;
+  } else {
+    LoggerE("No Match Card Emulation mode: %s", mode_string.c_str());
+    return PlatformResult(ErrorCode::TYPE_MISMATCH_ERR, "No Match Card Emulation mode");
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult NFCUtil::ToStringSecureElementType(const nfc_se_type_e se_type,
+                                                  std::string* type) {
+  LoggerD("Entered");
+  switch (se_type) {
+    case NFC_SE_TYPE_ESE:
+      *type = DATA_NFC_SE_TYPE_ESE;
+      break;
+    case NFC_SE_TYPE_UICC:
+      *type = DATA_NFC_SE_TYPE_UICC;
+      break;
+    case NFC_SE_TYPE_HCE:
+      *type = DATA_NFC_SE_TYPE_HCE;
+      break;
+    default:
+      LoggerE("No Match Secure Element Type: %x", se_type);
+      return PlatformResult(ErrorCode::TYPE_MISMATCH_ERR, "No Match Secure Element Type");
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult NFCUtil::ToSecureElementType(const std::string& type_string,
+                                            nfc_se_type_e* type) {
+  LoggerD("Entered");
+  if (type_string == DATA_NFC_SE_TYPE_ESE) {
+    *type = NFC_SE_TYPE_ESE;
+  } else if (type_string == DATA_NFC_SE_TYPE_UICC) {
+    *type = NFC_SE_TYPE_UICC;
+  } else if (type_string == DATA_NFC_SE_TYPE_HCE) {
+    *type = NFC_SE_TYPE_HCE;
+  } else {
+    LoggerE("No Match Secure Element Type: %s", type_string.c_str());
+    return PlatformResult(ErrorCode::TYPE_MISMATCH_ERR, "No Match Secure Element Type");
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+void NFCUtil::setDefaultFilterValues(std::vector<nfc_tag_type_e>& filter)
+{
+  LoggerD("Entered");
+  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);
+}
+
+// Convertion of enum to HCEEventType(characters sequence).
+const char* NFCUtil::ToStr(nfc_hce_event_type_e event_type) {
+  LoggerD("Entered");
+  switch (event_type) {
+    case NFC_HCE_EVENT_DEACTIVATED:
+      return "DEACTIVATED";
+    case NFC_HCE_EVENT_ACTIVATED:
+      return "ACTIVATED";
+    case NFC_HCE_EVENT_APDU_RECEIVED:
+      return "APDU_RECEIVED";
+    default:
+      AssertMsg(false, "That event type is incorrect.");
+  }
+}
+
+// Convertion of enum to SecureElementType(characters sequence).
+// Warning! DISABLE and SDCARD are not mentioned at widl spec.
+const char* NFCUtil::ToStr(nfc_se_type_e se_type) {
+  LoggerD("Entered");
+  switch (se_type) {
+    case NFC_SE_TYPE_DISABLE:
+      return "DISABLE";
+    case NFC_SE_TYPE_ESE:
+      return "ESE";
+    case NFC_SE_TYPE_UICC:
+      return "UICC";
+    case NFC_SE_TYPE_SDCARD:
+      return "SDCARD";
+    case NFC_SE_TYPE_HCE:
+      return "HCE";
+    default:
+      AssertMsg(false, "That event type is incorrect.");
+  }
+}
+
+// Convertion CardEmulationCategoryType(characters sequence) to enum.
+nfc_card_emulation_category_type_e NFCUtil::StringToCategory(const std::string& category_type) {
+  LoggerD("Entered");
+  if (category_type == "PAYMENT")
+    return NFC_CARD_EMULATION_CATEGORY_PAYMENT;
+  if (category_type == "OTHER")
+    return NFC_CARD_EMULATION_CATEGORY_OTHER;
+  AssertMsg(false, "That category type is incorrect.");
+}
+
+unsigned char* NFCUtil::DoubleArrayToUCharArray(const picojson::array& array_in) {
+  LoggerD("Entered");
+  unsigned char* result_array = new unsigned char[array_in.size()];
+  for(std::size_t i = 0; i < array_in.size(); ++i) {
+    result_array[i] = static_cast<unsigned char>(array_in.at(i).get<double>());
+  }
+  return result_array;
+}
+
+UCharVector NFCUtil::DoubleArrayToUCharVector(const picojson::array& array_in) {
+  LoggerD("Entered");
+  return ToVector(NFCUtil::DoubleArrayToUCharArray(array_in), array_in.size());
+}
+
+picojson::array NFCUtil::FromUCharArray(unsigned char* array,
+                                        unsigned int apdu_len) {
+  LoggerD("Entered");
+  picojson::array apdu_array;
+  apdu_array.reserve(apdu_len);
+  for(int i = 0; i < apdu_len; ++i)
+    apdu_array.push_back(picojson::value(static_cast<double>(array[i])));
+  return apdu_array;
+}
+
+}  // nfc
+}  // extension
diff --git a/webWidgetTCT_device/src/nfc/nfc_util.h b/webWidgetTCT_device/src/nfc/nfc_util.h
new file mode 100755 (executable)
index 0000000..78b3784
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2015 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_NFC_NFCUTIL_H_
+#define __TIZEN_NFC_NFCUTIL_H_
+
+#include <network/nfc.h>
+
+#include <string>
+#include <vector>
+
+#include "common/platform_result.h"
+
+namespace extension {
+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 UNKNOWN_ERROR_NAME_STR = "UnknownError";
+const std::string INVALID_VALUES_ERROR_NAME_STR = "InvalidValuesError";
+const std::string TIMEOUT_ERROR_NAME_STR = "TimeoutError";
+const std::string SERVICE_NOT_AVAILABLE_ERROR_NAME_STR = "ServiceNotAvailableError";
+const std::string NOT_SUPPORTED_ERROR_NAME_STR = "NotSupportedError";
+}
+
+typedef std::vector<unsigned char> UCharVector;
+
+class NFCUtil
+{
+ public:
+  static UCharVector ToVector(const unsigned char* ch, const int size);
+  static common::PlatformResult CodeToResult(const int errorCode,
+                                             const std::string& message);
+  static std::string getNFCErrorString(const int error_code);
+  static const std::string getNFCErrorMessage(const int error_code);
+  static std::string ToStringNFCTag(const nfc_tag_type_e tag_type);
+  static common::PlatformResult ToNfcTagString(const std::string& type_string,
+                                               nfc_tag_type_e* tag_type);
+  static common::PlatformResult ToStringCardEmulationMode(
+      const nfc_se_card_emulation_mode_type_e card_mode, std::string *mode);
+  static common::PlatformResult ToCardEmulationMode(
+      const std::string& mode_string,
+      nfc_se_card_emulation_mode_type_e* mode);
+  static common::PlatformResult ToStringSecureElementType(const nfc_se_type_e se_type, std::string *type);
+  static common::PlatformResult ToSecureElementType(const std::string& type_string, nfc_se_type_e *type);
+  static void setDefaultFilterValues(std::vector<nfc_tag_type_e>& filter);
+  static const char* ToStr(nfc_hce_event_type_e event_type);
+  static const char* ToStr(nfc_se_type_e se_type);
+  static nfc_card_emulation_category_type_e StringToCategory(const std::string& category_type);
+  static unsigned char* DoubleArrayToUCharArray(const picojson::array& array_in);
+  static UCharVector DoubleArrayToUCharVector(const picojson::array& array_in);
+  static picojson::array FromUCharArray(unsigned char* array, unsigned int apdu_len);
+};
+
+} // nfc
+} // extension
+
+#endif // __TIZEN_NFC_NFCUTIL_H_
diff --git a/webWidgetTCT_device/src/notification/notification.gyp b/webWidgetTCT_device/src/notification/notification.gyp
new file mode 100755 (executable)
index 0000000..9c219a8
--- /dev/null
@@ -0,0 +1,35 @@
+{
+  'includes':[
+    '../common/common.gypi',
+  ],
+  'targets': [
+    {
+      'target_name': 'tizen_notification',
+      'type': 'loadable_module',
+      'dependencies': [
+        '../common/common.gyp:tizen_common',
+      ],
+      'sources': [
+        'notification_api.js',
+        'notification_extension.cc',
+        'notification_extension.h',
+        'notification_instance.cc',
+        'notification_instance.h',
+        'notification_manager.h',
+        'notification_manager.cc',
+        'status_notification.cc',
+        'status_notification.h'
+      ],
+      'conditions': [
+        ['tizen == 1', {
+          'variables': {
+            'packages': [
+              'notification',
+              'capi-system-device',
+            ]
+          },
+        }],
+      ],
+    },
+  ],
+}
diff --git a/webWidgetTCT_device/src/notification/notification_api.js b/webWidgetTCT_device/src/notification/notification_api.js
new file mode 100755 (executable)
index 0000000..aefbeff
--- /dev/null
@@ -0,0 +1,616 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+var _global = window || global || {};
+
+var utils_ = xwalk.utils;
+var type_ = utils_.type;
+var converter_ = utils_.converter;
+var validator_ = utils_.validator;
+var types_ = validator_.Types;
+var privilege_ = xwalk.utils.privilege;
+var native_ = new xwalk.utils.NativeManager(extension);
+
+function convertColorToInt(rgbaColor) {
+  var color = rgbaColor.length === 7 ? rgbaColor + 'ff' : rgbaColor;
+  var isLengthOk = color.length === 9;
+  var isHash = color.substr(0, 1) === '#';
+  var hex = '0123456789abcdefABCDEF';
+  var isHex = true;
+  var c = color.replace('#', '');
+
+  for (var i = 0; i < c.length; i++) {
+    if (hex.indexOf(c[i]) < 0) {
+      isHex = false;
+    }
+  }
+
+  if (!isLengthOk || !isHash || !isHex) {
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR, 'invalid value');
+  }
+
+  return parseInt('0x' + c);
+}
+
+var EditManager = function() {
+  this.canEdit = false;
+};
+
+EditManager.prototype.allow = function() {
+  this.canEdit = true;
+};
+
+EditManager.prototype.disallow = function() {
+  this.canEdit = false;
+};
+
+var _edit = new EditManager();
+
+var NotificationType = {
+  STATUS: 'STATUS'
+};
+
+var StatusNotificationType = {
+  SIMPLE: 'SIMPLE',
+  THUMBNAIL: 'THUMBNAIL',
+  ONGOING: 'ONGOING',
+  PROGRESS: 'PROGRESS'
+};
+
+var NotificationProgressType = {
+  PERCENTAGE: 'PERCENTAGE',
+  BYTE: 'BYTE'
+};
+
+var LEDCustomFlags = {
+  LED_CUSTOM_DUTY_ON: 'LED_CUSTOM_DUTY_ON',
+  LED_CUSTOM_DEFAULT: 'LED_CUSTOM_DEFAULT'
+};
+
+function NotificationManager() {}
+
+
+NotificationManager.prototype.post = function(notification) {
+  xwalk.utils.checkPrivilegeAccess(privilege_.NOTIFICATION);
+
+  var args = validator_.validateArgs(arguments, [
+    {name: 'notification', type: types_.PLATFORM_OBJECT, values: StatusNotification}
+  ]);
+
+  var data = {
+    notification: args.notification
+  };
+
+  var result = native_.callSync('NotificationManager_post', data);
+
+  if (native_.isFailure(result)) {
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR);
+  }
+
+  _edit.allow();
+  var d = native_.getResultObject(result);
+  notification.id = d.id;
+  notification.postedTime = new Date(d.postedTime) || new Date();
+  notification.type = d.type || NotificationType.STATUS;
+  _edit.disallow();
+};
+
+NotificationManager.prototype.update = function(notification) {
+  xwalk.utils.checkPrivilegeAccess(privilege_.NOTIFICATION);
+
+  var args = validator_.validateArgs(arguments, [
+    {name: 'notification', type: types_.PLATFORM_OBJECT, values: StatusNotification}
+  ]);
+
+  if (!arguments.length) {
+    throw new WebAPIException(WebAPIException.NOT_FOUND_ERR);
+  }
+  if (!args.notification.id) {
+    throw new WebAPIException(WebAPIException.UNKNOWN_ERR);
+  }
+
+  var data = {
+    notification: args.notification
+  };
+
+  var result = native_.callSync('NotificationManager_update', data);
+
+  if (native_.isFailure(result)) {
+    throw new WebAPIException(WebAPIException.NOT_FOUND_ERR,
+        native_.getErrorObject(result));
+  }
+};
+
+NotificationManager.prototype.remove = function(id) {
+  xwalk.utils.checkPrivilegeAccess(privilege_.NOTIFICATION);
+
+  var args = validator_.validateArgs(arguments, [
+    {name: 'id', type: types_.STRING}
+  ]);
+
+  if (!arguments.length || !(parseInt(arguments[0]) > 0)) {
+    throw new WebAPIException(WebAPIException.NOT_FOUND_ERR);
+  }
+
+  var data = {
+    id: args.id
+  };
+
+  var result = native_.callSync('NotificationManager_remove', data);
+
+  if (native_.isFailure(result)) {
+    throw new WebAPIException(WebAPIException.NOT_FOUND_ERR,
+        native_.getErrorObject(result));
+  }
+};
+
+NotificationManager.prototype.removeAll = function() {
+  xwalk.utils.checkPrivilegeAccess(privilege_.NOTIFICATION);
+
+  var result = native_.callSync('NotificationManager_removeAll', {});
+
+  if (native_.isFailure(result)) {
+    throw new WebAPIException(WebAPIException.UNKNOWN_ERR,
+        native_.getErrorObject(result));
+  }
+};
+
+NotificationManager.prototype.get = function(id) {
+  var args = validator_.validateArgs(arguments, [
+    {name: 'id', type: types_.STRING}
+  ]);
+
+  if (!arguments.length) {
+    throw new WebAPIException(WebAPIException.NOT_FOUND_ERR);
+  }
+
+  var data = {
+    id: args.id
+  };
+
+  var result = native_.callSync('NotificationManager_get', data);
+
+  if (native_.isFailure(result)) {
+    throw new WebAPIException(WebAPIException.NOT_FOUND_ERR,
+        native_.getErrorObject(result));
+  }
+
+  var n = native_.getResultObject(result);
+
+  _edit.allow();
+  var returnObject = new StatusNotification(n.statusType, n.title, n);
+  _edit.disallow();
+
+  return returnObject;
+};
+
+NotificationManager.prototype.getAll = function() {
+  var result = native_.callSync('NotificationManager_getAll', {});
+
+  if (native_.isFailure(result)) {
+    throw new WebAPIException(WebAPIException.NOT_FOUND_ERR,
+        native_.getErrorObject(result));
+  }
+
+  var n = native_.getResultObject(result);
+  var notifications = [];
+
+  _edit.allow();
+  for (var i = 0; i < n.length; i++) {
+    notifications.push(new StatusNotification(n[i].statusType, n[i].title, n[i]));
+  }
+  _edit.disallow();
+
+  return notifications;
+};
+
+/**
+ * Plays the custom effect of the service LED that is located to the front of a device.
+ *
+ * @param timeOn Number
+ * @param timeOff Number
+ * @param color String
+ * @param flags Array
+ */
+NotificationManager.prototype.playLEDCustomEffect = function(timeOn, timeOff, color, flags) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.LED);
+
+  var args = validator_.validateArgs(arguments, [
+    {name: 'timeOn', type: types_.LONG},
+    {name: 'timeOff', type: types_.LONG},
+    {name: 'color', type: types_.STRING},
+    {name: 'flags', type: types_.ARRAY, values: types_.STRING}
+  ]);
+
+  for (var i = 0; i < args.flags.length; ++i) {
+    if (Object.keys(LEDCustomFlags).indexOf(args.flags[i]) < 0) {
+      throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR, 'invalid value');
+    }
+  }
+
+  args.color = convertColorToInt(args.color);
+  var result = native_.callSync('NotificationManager_playLEDCustomEffect', args);
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+};
+
+/**
+ * Stops the custom effect of the service LED that is located to the front of a device.
+ */
+NotificationManager.prototype.stopLEDCustomEffect = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.LED);
+
+  var result = native_.callSync('NotificationManager_stopLEDCustomEffect');
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+};
+
+
+function NotificationInitDict(data) {
+  var _iconPath = null;
+  var _soundPath = null;
+  var _vibration = false;
+  var _appControl = null;
+  var _appId = null;
+  var _progressType = NotificationProgressType.PERCENTAGE;
+  var _progressValue = null;
+  var checkProgressValue = function(v) {
+    if ((_progressType === NotificationProgressType.PERCENTAGE && (v >= 0 && v <= 100))
+            || (_progressType === NotificationProgressType.BYTE &&
+            converter_.toUnsignedLong(v) >= 0)) {
+      return true;
+    }
+    return false;
+  };
+  var _number = null;
+  var _subIconPath = null;
+  var _detailInfo = [];
+  var checkDetailInfo = function(v) {
+    if (type_.isNull(v)) {
+      return true;
+    }
+    if (!type_.isArray(v)) {
+      return false;
+    }
+    for (var i = 0; i < v.length; ++i) {
+      if (!(v[i] instanceof tizen.NotificationDetailInfo)) {
+        return false;
+      }
+    }
+    return true;
+  };
+  var setDetailInfo = function(v) {
+    var _d = [];
+    for (var i = 0; i < v.length; ++i) {
+      _d.push(new tizen.NotificationDetailInfo(v[i].mainText, v[i].subText || null));
+    }
+    return _d;
+  };
+  var _ledColor = null;
+  var isHex = function(v) {
+    return v.length === 7 && v.substr(0, 1) === '#' && (/^([0-9A-Fa-f]{2})+$/).test(v.substr(1, 7));
+  };
+  var _ledOnPeriod = 0;
+  var _ledOffPeriod = 0;
+  var _backgroundImagePath = null;
+  var _thumbnails = [];
+  var checkThumbnails = function(v) {
+    if (type_.isNull(v)) {
+      return true;
+    }
+    if (!type_.isArray(v)) {
+      return false;
+    }
+    for (var i = 0; i < v.length; ++i) {
+      if (!type_.isString(v[i])) {
+        return false;
+      }
+    }
+    return true;
+  };
+
+  Object.defineProperties(this, {
+    iconPath: {
+      get: function() {
+        return _iconPath;
+      },
+      set: function(v) {
+        _iconPath = type_.isString(v) || type_.isNull(v) ? v : _iconPath;
+      },
+      enumerable: true
+    },
+    soundPath: {
+      get: function() {
+        return _soundPath;
+      },
+      set: function(v) {
+        _soundPath = type_.isString(v) || type_.isNull(v) ? v : _soundPath;
+      },
+      enumerable: true
+    },
+    vibration: {
+      get: function() {
+        return _vibration;
+      },
+      set: function(v) {
+        _vibration = type_.isBoolean(v) ? v : _vibration;
+      },
+      enumerable: true
+    },
+    appControl: {
+      get: function() {
+        return _appControl;
+      },
+      set: function(v) {
+        _appControl = _edit.canEdit && v
+            ? new tizen.ApplicationControl(v.operation, v.uri || null, v.mime || null, v.category
+                    || null, v.data || [])
+            : v instanceof tizen.ApplicationControl || type_.isNull(v) ? v : _appControl;
+      },
+      enumerable: true
+    },
+    appId: {
+      get: function() {
+        return _appId;
+      },
+      set: function(v) {
+        _appId = type_.isString(v) && !(/\s/.test(v)) || type_.isNull(v) ? v : _appId;
+      },
+      enumerable: true
+    },
+    progressType: {
+      get: function() {
+        return _progressType;
+      },
+      set: function(v) {
+        _progressType = Object.keys(NotificationProgressType).indexOf(v) >= 0 ? v : _progressType;
+      },
+      enumerable: true
+    },
+    progressValue: {
+      get: function() {
+        if (null === _progressValue) {
+          return _progressValue;
+        }
+
+        return (_progressType === NotificationProgressType.PERCENTAGE)
+            ? _progressValue * 100
+            : _progressValue;
+      },
+      set: function(v) {
+        if (type_.isNull(v)) {
+          _progressValue = v;
+          return;
+        }
+        if (checkProgressValue(v)) {
+          _progressValue = (_progressType === NotificationProgressType.PERCENTAGE)
+            ? v / 100
+            : converter_.toUnsignedLong(v);
+        }
+      },
+      enumerable: true
+    },
+    number: {
+      get: function() {
+        return _number;
+      },
+      set: function(v) {
+        _number = type_.isNumber(v) || type_.isNull(v) ? v : _number;
+      },
+      enumerable: true
+    },
+    subIconPath: {
+      get: function() {
+        return _subIconPath;
+      },
+      set: function(v) {
+        _subIconPath = type_.isString(v) || type_.isNull(v) ? v : _subIconPath;
+      },
+      enumerable: true
+    },
+    detailInfo: {
+      get: function() {
+        return _detailInfo;
+      },
+      set: function(v) {
+        _detailInfo = _edit.canEdit && v ? setDetailInfo(v) : checkDetailInfo(v) ? v : _detailInfo;
+      },
+      enumerable: true
+    },
+    ledColor: {
+      get: function() {
+        return _ledColor;
+      },
+      set: function(v) {
+        _ledColor = (type_.isString(v) && isHex(v)) || type_.isNull(v) ? v : _ledColor;
+      },
+      enumerable: true
+    },
+    ledOnPeriod: {
+      get: function() {
+        return _ledOnPeriod;
+      },
+      set: function(v) {
+        _ledOnPeriod = type_.isNumber(v) ? v : _ledOnPeriod;
+      },
+      enumerable: true
+    },
+    ledOffPeriod: {
+      get: function() {
+        return _ledOffPeriod;
+      },
+      set: function(v) {
+        _ledOffPeriod = type_.isNumber(v) ? v : _ledOffPeriod;
+      },
+      enumerable: true
+    },
+    backgroundImagePath: {
+      get: function() {
+        return _backgroundImagePath;
+      },
+      set: function(v) {
+        _backgroundImagePath = type_.isString(v) || type_.isNull(v) ? v : _backgroundImagePath;
+      },
+      enumerable: true
+    },
+    thumbnails: {
+      get: function() {
+        return _thumbnails;
+      },
+      set: function(v) {
+        _thumbnails = checkThumbnails(v) ? v : _thumbnails;
+      },
+      enumerable: true
+    }
+  });
+
+  if (data instanceof _global.Object) {
+    for (var prop in data) {
+      if (this.hasOwnProperty(prop)) {
+        this[prop] = data[prop];
+      }
+    }
+  }
+}
+
+function Notification(data) {
+  var _id;
+  var _type = NotificationType.STATUS;
+  var _postedTime;
+  var _title;
+  var _content = null;
+
+  Object.defineProperties(this, {
+    id: {
+      get: function() {
+        return _id;
+      },
+      set: function(v) {
+        _id = _edit.canEdit && v ? v : _id;
+      },
+      enumerable: true
+    },
+    type: {
+      get: function() {
+        return _type;
+      },
+      set: function(v) {
+        _type = _edit.canEdit
+            ? converter_.toEnum(v, Object.keys(NotificationType), false)
+            : _type;
+      },
+      enumerable: true
+    },
+    postedTime: {
+      get: function() {
+        return _postedTime;
+      },
+      set: function(v) {
+        _postedTime = _edit.canEdit && v ? new Date(v) : _postedTime;
+      },
+      enumerable: true
+    },
+    title: {
+      get: function() {
+        return _title;
+      },
+      set: function(v) {
+        _title = converter_.toString(v);
+      },
+      enumerable: true
+    },
+    content: {
+      get: function() {
+        return _content;
+      },
+      set: function(v) {
+        _content = type_.isString(v) || type_.isNull(v) ? v : _content;
+      },
+      enumerable: true
+    }
+  });
+
+  if (data instanceof _global.Object) {
+    for (var prop in data) {
+      if (data.hasOwnProperty(prop) && this.hasOwnProperty(prop)) {
+        this[prop] = data[prop];
+      }
+    }
+  }
+}
+
+function StatusNotification(statusType, title, notificationInitDict) {
+  validator_.isConstructorCall(this, StatusNotification);
+  type_.isObject(notificationInitDict) ?
+      notificationInitDict.title = title :
+      notificationInitDict = {title: title};
+  NotificationInitDict.call(this, notificationInitDict);
+  Notification.call(this, notificationInitDict);
+
+  var _statusType = (Object.keys(StatusNotificationType)).indexOf(statusType) >= 0
+      ? statusType : StatusNotificationType.SIMPLE;
+
+  Object.defineProperties(this, {
+    statusType: {
+      get: function() {
+        return _statusType;
+      },
+      set: function(v) {
+        _statusType = (Object.keys(StatusNotificationType)).indexOf(v) >= 0 && _edit.canEdit
+            ? v : _statusType;
+      },
+      enumerable: true
+    }
+  });
+}
+
+StatusNotification.prototype = new Notification();
+StatusNotification.prototype.constructor = StatusNotification;
+
+
+function NotificationDetailInfo(mainText, subText) {
+  validator_.isConstructorCall(this, NotificationDetailInfo);
+
+  var _mainText = type_.isString(mainText) ? mainText : '';
+  var _subText = type_.isString(subText) ? subText : null;
+
+  Object.defineProperties(this, {
+    mainText: {
+      get: function() {
+        return _mainText;
+      },
+      set: function(v) {
+        _mainText = type_.isString(v) ? v : _mainText;
+      },
+      enumerable: true
+    },
+    subText: {
+      get: function() {
+        return _subText;
+      },
+      set: function(v) {
+        _subText = type_.isString(v) ? v : _subText;
+      },
+      enumerable: true
+    }
+  });
+}
+
+exports = new NotificationManager();
+tizen.StatusNotification = StatusNotification;
+tizen.NotificationDetailInfo = NotificationDetailInfo;
diff --git a/webWidgetTCT_device/src/notification/notification_extension.cc b/webWidgetTCT_device/src/notification/notification_extension.cc
new file mode 100755 (executable)
index 0000000..99a315c
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2015 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 "notification/notification_extension.h"
+#include "notification/notification_instance.h"
+
+// This will be generated from notification_api.js
+extern const char kSource_notification_api[];
+
+common::Extension* CreateExtension() { return new NotificationExtension; }
+
+NotificationExtension::NotificationExtension() {
+  SetExtensionName("tizen.notification");
+  SetJavaScriptAPI(kSource_notification_api);
+
+  const char* entry_points[] = {"tizen.StatusNotification",
+                                "tizen.NotificationDetailInfo", NULL};
+  SetExtraJSEntryPoints(entry_points);
+}
+
+NotificationExtension::~NotificationExtension() {}
+
+common::Instance* NotificationExtension::CreateInstance() {
+  return new extension::notification::NotificationInstance;
+}
diff --git a/webWidgetTCT_device/src/notification/notification_extension.h b/webWidgetTCT_device/src/notification/notification_extension.h
new file mode 100755 (executable)
index 0000000..832dd2c
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2015 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 NOTIFICATION_NOTIFICATION_EXTENSION_H_
+#define NOTIFICATION_NOTIFICATION_EXTENSION_H_
+
+#include "common/extension.h"
+
+class NotificationExtension : public common::Extension {
+ public:
+  NotificationExtension();
+  virtual ~NotificationExtension();
+
+ private:
+  virtual common::Instance* CreateInstance();
+};
+
+#endif  // NOTIFICATION_NOTIFICATION_EXTENSION_H_
diff --git a/webWidgetTCT_device/src/notification/notification_instance.cc b/webWidgetTCT_device/src/notification/notification_instance.cc
new file mode 100755 (executable)
index 0000000..5c571ba
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2015 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 "notification/notification_instance.h"
+
+#include <functional>
+
+#include "common/logger.h"
+#include "common/picojson.h"
+#include "common/platform_result.h"
+
+#include "notification/notification_manager.h"
+
+namespace extension {
+namespace notification {
+
+using namespace common;
+
+NotificationInstance::NotificationInstance() {
+  LoggerD("Enter");
+  using std::placeholders::_1;
+  using std::placeholders::_2;
+#define REGISTER_SYNC(c, x) \
+  RegisterSyncHandler(c, std::bind(&NotificationInstance::x, this, _1, _2));
+  REGISTER_SYNC("NotificationManager_get", NotificationManagerGet);
+  REGISTER_SYNC("NotificationManager_update", NotificationManagerUpdate);
+  REGISTER_SYNC("NotificationManager_remove", NotificationManagerRemove);
+  REGISTER_SYNC("NotificationManager_getAll", NotificationManagerGetAll);
+  REGISTER_SYNC("NotificationManager_post", NotificationManagerPost);
+  REGISTER_SYNC("NotificationManager_removeAll", NotificationManagerRemoveAll);
+  REGISTER_SYNC("NotificationManager_playLEDCustomEffect",
+      NotificationManagerPlayLEDCustomEffect);
+  REGISTER_SYNC("NotificationManager_stopLEDCustomEffect",
+      NotificationManagerStopLEDCustomEffect);
+#undef REGISTER_SYNC
+
+  manager_ = NotificationManager::GetInstance();
+}
+
+NotificationInstance::~NotificationInstance() {
+  LoggerD("Enter");
+}
+
+#define CHECK_EXIST(args, name, out)                                       \
+  if (!args.contains(name)) {                                              \
+    ReportError(TypeMismatchException(name " is required argument"), out); \
+    return;                                                                \
+  }
+
+void NotificationInstance::NotificationManagerPost(const picojson::value& args,
+                                                   picojson::object& out) {
+
+  LoggerD("Enter");
+  picojson::value val{picojson::object{}};
+  PlatformResult status =
+      manager_->Post(args.get<picojson::object>(), val.get<picojson::object>());
+
+  if (status.IsSuccess()) {
+    ReportSuccess(val, out);
+  } else {
+    LoggerE("Failed");
+    ReportError(status, &out);
+  }
+}
+
+void NotificationInstance::NotificationManagerUpdate(
+    const picojson::value& args,
+    picojson::object& out) {
+
+  LoggerD("Enter");
+  PlatformResult status = manager_->Update(args.get<picojson::object>());
+
+  if (status.IsSuccess()) {
+    ReportSuccess(out);
+  } else {
+    LoggerE("Failed");
+    ReportError(status, &out);
+  }
+}
+
+void NotificationInstance::NotificationManagerRemove(
+    const picojson::value& args,
+    picojson::object& out) {
+
+  LoggerD("Enter");
+  PlatformResult status = manager_->Remove(args.get<picojson::object>());
+
+  if (status.IsSuccess()) {
+    ReportSuccess(out);
+  } else {
+    LoggerE("Failed");
+    ReportError(status, &out);
+  }
+}
+
+void NotificationInstance::NotificationManagerRemoveAll(
+    const picojson::value& args,
+    picojson::object& out) {
+
+  LoggerD("Enter");
+  PlatformResult status = manager_->RemoveAll();
+
+  if (status.IsSuccess()) {
+    ReportSuccess(out);
+  } else {
+    LoggerE("Failed");
+    ReportError(status, &out);
+  }
+}
+
+void NotificationInstance::NotificationManagerGet(const picojson::value& args,
+                                                  picojson::object& out) {
+  LoggerD("Enter");
+  picojson::value val{picojson::object{}};
+
+  PlatformResult status =
+      manager_->Get(args.get<picojson::object>(), val.get<picojson::object>());
+
+  if (status.IsSuccess()) {
+    ReportSuccess(val, out);
+  } else {
+    LoggerE("Failed");
+    ReportError(status, &out);
+  }
+}
+
+void NotificationInstance::NotificationManagerGetAll(
+    const picojson::value& args,
+    picojson::object& out) {
+  LoggerD("Enter");
+  picojson::value val{picojson::array{}};
+
+  PlatformResult status = manager_->GetAll(val.get<picojson::array>());
+
+  if (status.IsSuccess()) {
+    ReportSuccess(val, out);
+  } else {
+    LoggerE("Failed");
+    ReportError(status, &out);
+  }
+}
+
+void NotificationInstance::NotificationManagerPlayLEDCustomEffect(
+    const picojson::value& args, picojson::object& out) {
+
+  LoggerD("Enter");
+
+  PlatformResult status = manager_->PlayLEDCustomEffect(args.get<picojson::object>());
+
+  if (status.IsSuccess()) {
+    ReportSuccess(out);
+  } else {
+    LoggerE("Failed");
+    ReportError(status, &out);
+  }
+}
+
+void NotificationInstance::NotificationManagerStopLEDCustomEffect(
+    const picojson::value& /*args*/, picojson::object& out) {
+
+  LoggerD("Enter");
+
+  PlatformResult status = manager_->StopLEDCustomEffect();
+
+  if (status.IsSuccess()) {
+    ReportSuccess(out);
+  } else {
+    LoggerE("Failed");
+    ReportError(status, &out);
+  }
+}
+
+#undef CHECK_EXIST
+
+}  // namespace notification
+}  // namespace extension
diff --git a/webWidgetTCT_device/src/notification/notification_instance.h b/webWidgetTCT_device/src/notification/notification_instance.h
new file mode 100755 (executable)
index 0000000..3a1e2e7
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2015 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 NOTIFICATION_NOTIFICATION_INSTANCE_H_
+#define NOTIFICATION_NOTIFICATION_INSTANCE_H_
+
+#include "common/extension.h"
+#include "notification/notification_manager.h"
+
+namespace extension {
+namespace notification {
+
+class NotificationInstance : public common::ParsedInstance {
+ public:
+  NotificationInstance();
+  virtual ~NotificationInstance();
+
+ private:
+  NotificationManager* manager_;
+
+  void NotificationManagerPost(const picojson::value& args,
+                               picojson::object& out);
+  void NotificationManagerUpdate(const picojson::value& args,
+                                 picojson::object& out);
+  void NotificationManagerRemove(const picojson::value& args,
+                                 picojson::object& out);
+  void NotificationManagerRemoveAll(const picojson::value& args,
+                                    picojson::object& out);
+  void NotificationManagerGet(const picojson::value& args,
+                              picojson::object& out);
+  void NotificationManagerGetAll(const picojson::value& args,
+                                 picojson::object& out);
+
+  void NotificationManagerPlayLEDCustomEffect(const picojson::value& args,
+                                              picojson::object& out);
+  void NotificationManagerStopLEDCustomEffect(const picojson::value& args,
+                                              picojson::object& out);
+};
+
+}  // namespace notification
+}  // namespace extension
+
+#endif  // NOTIFICATION_NOTIFICATION_INSTANCE_H_
diff --git a/webWidgetTCT_device/src/notification/notification_manager.cc b/webWidgetTCT_device/src/notification/notification_manager.cc
new file mode 100755 (executable)
index 0000000..c9c1f41
--- /dev/null
@@ -0,0 +1,242 @@
+/*
+ * Copyright (c) 2015 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 "notification/notification_manager.h"
+
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <app_control_internal.h>
+#include <device/led.h>
+#include <notification_internal.h>
+
+#include "common/converter.h"
+#include "common/logger.h"
+#include "common/scope_exit.h"
+
+#include "notification/status_notification.h"
+
+namespace extension {
+namespace notification {
+
+using namespace common;
+
+NotificationManager::NotificationManager() {
+  LoggerD("Enter");
+}
+
+NotificationManager::~NotificationManager() {
+  LoggerD("Enter");
+}
+
+NotificationManager* NotificationManager::GetInstance() {
+  LoggerD("Enter");
+  static NotificationManager instance;
+  return &instance;
+}
+
+PlatformResult NotificationManager::Post(const picojson::object& args,
+                                         picojson::object& out) {
+  LoggerD("Enter");
+  return StatusNotification::FromJson(args, false, &out);
+}
+
+PlatformResult NotificationManager::Update(const picojson::object& args) {
+  LoggerD("Enter");
+  return StatusNotification::FromJson(args, true, NULL);
+}
+
+PlatformResult NotificationManager::Remove(const picojson::object& args) {
+  LoggerD("Enter");
+  int id = std::stoi(FromJson<std::string>(args, "id"));
+
+  int ret = notification_delete_by_priv_id(NULL, NOTIFICATION_TYPE_NONE, id);
+  if (ret != NOTIFICATION_ERROR_NONE) {
+    LoggerE("Cannot remove notification error: %d", ret);
+    return PlatformResult(ErrorCode::NOT_FOUND_ERR,
+                          "Cannot remove notification error");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult NotificationManager::RemoveAll() {
+  LoggerD("Enter");
+  int ret = notification_delete_all(NOTIFICATION_TYPE_NOTI);
+  if (ret != NOTIFICATION_ERROR_NONE) {
+    LoggerE("Notification remove all failed: %d", ret);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Notification noti remove all failed");
+  }
+
+  ret = notification_delete_all(NOTIFICATION_TYPE_ONGOING);
+  if (ret != NOTIFICATION_ERROR_NONE) {
+    LoggerE("Notification remove all failed: %d", ret);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Notification ongoing remove all failed");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult NotificationManager::Get(const picojson::object& args,
+                                        picojson::object& out) {
+  LoggerD("Enter");
+  int id = std::stoi(FromJson<std::string>(args, "id"));
+
+  app_control_h app_control = nullptr;
+  notification_h noti_handle = nullptr;
+
+  SCOPE_EXIT {
+    if (app_control) {
+      app_control_destroy(app_control);
+    }
+    free(noti_handle);
+  };
+
+  PlatformResult status = StatusNotification::GetNotiHandle(id, &noti_handle);
+  if (status.IsError())
+  {
+    LoggerE("Failed: GetNotiHandle");
+    return status;
+  }
+
+  status = StatusNotification::GetAppControl(noti_handle, &app_control);
+  if (status.IsError())
+  {
+    LoggerE("Failed: GetAppControl");
+    return status;
+  }
+  status = StatusNotification::ToJson(id, noti_handle, app_control, &out);
+  if (status.IsError())
+  {
+    LoggerE("Failed: ToJson");
+    return status;
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult NotificationManager::GetAll(picojson::array& out) {
+  LoggerD("Enter");
+  notification_h noti = nullptr;
+  notification_list_h noti_list = nullptr;
+  notification_list_h noti_list_iter = nullptr;
+  char* package = nullptr;
+
+  if (APP_ERROR_NONE == app_get_id(&package)) {
+    LoggerD("Package id: %s", package);
+  } else {
+    LoggerD("Could not get package id");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Could not get package id");
+  }
+  const std::string package_str = package;
+  free(package);
+
+  int ret = notification_get_detail_list(package_str.c_str(), NOTIFICATION_GROUP_ID_NONE,
+                                         NOTIFICATION_PRIV_ID_NONE, -1, &noti_list);
+  if (NOTIFICATION_ERROR_NONE != ret) {
+    LoggerD("Get notification list error: %d", ret);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Get notification list error");
+  }
+
+  SCOPE_EXIT { notification_free_list(noti_list); };
+
+  noti_list_iter = notification_list_get_head(noti_list);
+
+  while (nullptr != noti_list_iter) {
+    noti = notification_list_get_data(noti_list_iter);
+    if (nullptr != noti) {
+      int noti_priv = -1;
+      ret = notification_get_id(noti, NULL, &noti_priv);
+      if (NOTIFICATION_ERROR_NONE != ret) {
+        LoggerE("Cannot get notification id, error: %d", ret);
+        return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                              "Cannot get notification id error");
+      }
+
+      app_control_h app_control = nullptr;
+      PlatformResult status =
+          StatusNotification::GetAppControl(noti, &app_control);
+
+      SCOPE_EXIT {
+          if (app_control) {
+              app_control_destroy(app_control);
+          }
+      };
+
+      if (status.IsError())
+        return status;
+
+      picojson::object noti_item = picojson::object();
+
+      status =
+          StatusNotification::ToJson(noti_priv, noti, app_control, &noti_item);
+      if (status.IsError())
+        return status;
+
+      out.push_back(picojson::value(noti_item));
+    }
+
+    noti_list_iter = notification_list_get_next(noti_list_iter);
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult NotificationManager::PlayLEDCustomEffect(
+    const picojson::object& args) {
+  LoggerD("Enter");
+
+  int timeOn = FromJson<double>(args, "timeOn");
+  int timeOff = FromJson<double>(args, "timeOff");
+  unsigned int color = FromJson<double>(args, "color");
+
+  auto& flags = FromJson<picojson::array>(args, "flags");
+  unsigned int platformFlags = 0;
+  for (auto flag : flags) {
+    std::string flagStr = JsonCast<std::string>(flag);
+    if (flagStr == "LED_CUSTOM_DEFAULT")
+      platformFlags |= LED_CUSTOM_DEFAULT;
+    else if (flagStr == "LED_CUSTOM_DUTY_ON")
+      platformFlags |= LED_CUSTOM_DUTY_ON;
+  }
+
+  int ret;
+  ret = device_led_play_custom(timeOn, timeOff, color, platformFlags);
+  if (ret != DEVICE_ERROR_NONE) {
+    LOGGER(ERROR) << "Cannot play LED custom effect: " << ret;
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Cannot play LED custom effect");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult NotificationManager::StopLEDCustomEffect() {
+  LoggerD("Enter");
+
+  int ret = device_led_stop_custom();
+  if (ret != DEVICE_ERROR_NONE) {
+    LOGGER(ERROR) << "Cannot stop LED custom effect: " << ret;
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Cannot stop LED custom effect");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+}  // namespace notification
+}  // namespace extension
diff --git a/webWidgetTCT_device/src/notification/notification_manager.h b/webWidgetTCT_device/src/notification/notification_manager.h
new file mode 100755 (executable)
index 0000000..eaeac9f
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2015 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 NOTIFICATION_NOTIFICATION_MANAGER_H_
+#define NOTIFICATION_NOTIFICATION_MANAGER_H_
+
+#include <notification.h>
+
+#include "common/picojson.h"
+#include "common/platform_result.h"
+
+namespace extension {
+namespace notification {
+
+class NotificationManager {
+ public:
+  static NotificationManager* GetInstance();
+
+  common::PlatformResult Post(const picojson::object& args,
+                              picojson::object& out);
+  common::PlatformResult Update(const picojson::object& args);
+  common::PlatformResult Remove(const picojson::object& args);
+  common::PlatformResult RemoveAll();
+  common::PlatformResult Get(const picojson::object& args,
+                             picojson::object& out);
+  common::PlatformResult GetAll(picojson::array& out);
+
+  common::PlatformResult PlayLEDCustomEffect(const picojson::object& args);
+  common::PlatformResult StopLEDCustomEffect();
+
+ private:
+  NotificationManager();
+  virtual ~NotificationManager();
+};
+
+}  // namespace notification
+}  // namespace extension
+
+#endif /* NOTIFICATION_NOTIFICATION_MANAGER_H_ */
diff --git a/webWidgetTCT_device/src/notification/status_notification.cc b/webWidgetTCT_device/src/notification/status_notification.cc
new file mode 100755 (executable)
index 0000000..73aa21e
--- /dev/null
@@ -0,0 +1,1393 @@
+/*
+ * Copyright (c) 2015 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 "notification/status_notification.h"
+
+#include <notification.h>
+#include <notification_internal.h>
+#include <app_control_internal.h>
+
+#include "common/converter.h"
+#include "common/logger.h"
+#include "common/scope_exit.h"
+#include "common/virtual_fs.h"
+
+namespace extension {
+namespace notification {
+
+using namespace common;
+
+const std::string kProgressTypePercentage = "PERCENTAGE";
+const std::string kProgressTypeByte = "BYTE";
+
+const InformationEnumMap StatusNotification::info_map_ = {
+    {0, NOTIFICATION_TEXT_TYPE_INFO_1},
+    {1, NOTIFICATION_TEXT_TYPE_INFO_2},
+    {2, NOTIFICATION_TEXT_TYPE_INFO_3}};
+
+const InformationEnumMap StatusNotification::info_sub_map_ = {
+    {0, NOTIFICATION_TEXT_TYPE_INFO_SUB_1},
+    {1, NOTIFICATION_TEXT_TYPE_INFO_SUB_2},
+    {2, NOTIFICATION_TEXT_TYPE_INFO_SUB_3}};
+
+const ImageEnumMap StatusNotification::thumbnails_map_ = {
+    {0, NOTIFICATION_IMAGE_TYPE_LIST_1},
+    {1, NOTIFICATION_IMAGE_TYPE_LIST_2},
+    {2, NOTIFICATION_IMAGE_TYPE_LIST_3},
+    {3, NOTIFICATION_IMAGE_TYPE_LIST_4}};
+
+StatusNotification::StatusNotification() {
+}
+
+StatusNotification::~StatusNotification() {
+}
+
+bool StatusNotification::IsColorFormatNumberic(const std::string& color) {
+  LoggerD("Enter");
+  std::string hexCode = "0123456789abcdef";
+  if (color.length() != 7 || '#' != color[0]) {
+    return false;
+  }
+
+  for (size_t i = 1; i < color.length(); i++) {
+    if (std::string::npos == hexCode.find(color[i])) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
+PlatformResult StatusNotification::SetLayout(notification_h noti_handle,
+                                             const std::string& noti_type) {
+
+  LoggerD("Enter");
+  notification_ly_type_e noti_layout = NOTIFICATION_LY_NONE;
+
+  if (noti_type == "SIMPLE") {
+    long number;
+    PlatformResult status =
+        GetNumber(noti_handle, NOTIFICATION_TEXT_TYPE_EVENT_COUNT, &number);
+    if (status.IsError())
+    {
+      LoggerE("Failed: GetNumber");
+      return status;
+    }
+    if (number > 0)
+      noti_layout = NOTIFICATION_LY_NOTI_EVENT_MULTIPLE;
+    else
+      noti_layout = NOTIFICATION_LY_NOTI_EVENT_SINGLE;
+  } else if (noti_type == "THUMBNAIL") {
+    noti_layout = NOTIFICATION_LY_NOTI_THUMBNAIL;
+  }
+  if (noti_type == "ONGOING") {
+    noti_layout = NOTIFICATION_LY_ONGOING_EVENT;
+  } else if (noti_type == "PROGRESS") {
+    noti_layout = NOTIFICATION_LY_ONGOING_PROGRESS;
+  }
+  int ret = notification_set_layout(noti_handle, noti_layout);
+  if (ret != NOTIFICATION_ERROR_NONE) {
+    LoggerE("Set notification layout error: %d", ret);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Set notification layout error");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+static bool ServiceExtraDataCb(app_control_h service,
+                               const char* key,
+                               void* user_data) {
+  LoggerD("Enter");
+  if (nullptr == user_data || nullptr == key) {
+    LoggerE("User data or key not exist");
+    return true;
+  }
+
+  picojson::array* control_data = static_cast<picojson::array*>(user_data);
+
+  int length = 0;
+  char** value = NULL;
+  SCOPE_EXIT { free(value); };
+
+  int ret = app_control_get_extra_data_array(service, key, &value, &length);
+  if (ret != APP_CONTROL_ERROR_NONE) {
+    LoggerE("Get app control extra data error: %d", ret);
+    return true;
+  }
+
+  if (!value || !length) {
+    LoggerE("Get app control extra data value error");
+    return true;
+  }
+
+  picojson::array values = picojson::array();
+  for (int index = 0; index < length; ++index) {
+    values.push_back(picojson::value(value[index]));
+  }
+
+  picojson::object data_control_elem = picojson::object();
+  data_control_elem["key"] = picojson::value(key);
+  data_control_elem["value"] = picojson::value(values);
+
+  control_data->push_back(picojson::value(data_control_elem));
+
+  return true;
+}
+
+PlatformResult StatusNotification::Create(notification_type_e noti_type,
+                                          notification_h* noti_handle) {
+  LoggerD("Enter");
+  *noti_handle = notification_create(noti_type);
+  if (!noti_handle) {
+    LoggerE("Cannot make new notification object");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Cannot make new notification object");
+  }
+
+  if (NOTIFICATION_TYPE_ONGOING == noti_type) {
+    int ret = notification_set_display_applist(
+        *noti_handle,
+        NOTIFICATION_DISPLAY_APP_NOTIFICATION_TRAY |
+            NOTIFICATION_DISPLAY_APP_INDICATOR);
+    if (ret != NOTIFICATION_ERROR_NONE) {
+      LoggerE("Cannot make new notification object: %d", ret);
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "Cannot set notification display applist");
+    }
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult StatusNotification::StatusTypeFromPlatform(
+    notification_type_e noti_type,
+    notification_ly_type_e noti_layout,
+    std::string* type) {
+  LoggerD("Enter");
+  if (noti_type == NOTIFICATION_TYPE_NOTI) {
+    if (noti_layout == NOTIFICATION_LY_NOTI_EVENT_SINGLE ||
+        noti_layout == NOTIFICATION_LY_NOTI_EVENT_MULTIPLE) {
+      *type = "SIMPLE";
+    } else if (noti_layout == NOTIFICATION_LY_NOTI_THUMBNAIL) {
+      *type = "THUMBNAIL";
+    }
+  } else if (noti_type == NOTIFICATION_TYPE_ONGOING) {
+    if (noti_layout == NOTIFICATION_LY_ONGOING_EVENT) {
+      *type = "ONGOING";
+    } else if (noti_layout == NOTIFICATION_LY_ONGOING_PROGRESS) {
+      *type = "PROGRESS";
+    }
+  } else {
+    LoggerE("Notification type not found");
+    return PlatformResult(ErrorCode::NOT_FOUND_ERR,
+                          "Notification type not found");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult StatusNotification::StatusTypeToPlatform(
+    const std::string& type,
+    notification_type_e* noti_type) {
+  LoggerD("Enter");
+  if (type == "SIMPLE" || type == "THUMBNAIL") {
+    *noti_type = NOTIFICATION_TYPE_NOTI;
+  } else if (type == "ONGOING" || type == "PROGRESS") {
+    *noti_type = NOTIFICATION_TYPE_ONGOING;
+  } else {
+    LoggerI("Invalide noti type: %s", type.c_str());
+    return PlatformResult(ErrorCode::TYPE_MISMATCH_ERR,
+                          "Invalide notification type");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult StatusNotification::GetImage(
+    notification_h noti_handle,
+    notification_image_type_e image_type,
+    std::string* image_path) {
+  LoggerD("Enter");
+  char* path = NULL;
+
+  *image_path = "";
+
+  if (notification_get_image(noti_handle, image_type, &path) !=
+      NOTIFICATION_ERROR_NONE) {
+    LoggerE("Get notification image error, image_type: %d", image_type);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Get notification image error");
+  }
+  if (path) {
+    *image_path = path;
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult StatusNotification::SetImage(
+    notification_h noti_handle,
+    notification_image_type_e image_type,
+    const std::string& image_path) {
+  LoggerD("Enter");
+  int ret = notification_set_image(noti_handle, image_type, image_path.c_str());
+  if (ret != NOTIFICATION_ERROR_NONE) {
+    LoggerE("Set notification image error, image_type: %d, error: %d",
+            image_type,
+            ret);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Set notification image error");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult StatusNotification::GetText(notification_h noti_handle,
+                                           notification_text_type_e text_type,
+                                           std::string* noti_text) {
+  LoggerD("Enter");
+  char* text = NULL;
+
+  *noti_text = "";
+
+  if (notification_get_text(noti_handle, text_type, &text) !=
+      NOTIFICATION_ERROR_NONE) {
+    LoggerE("Get notification text error, text_type: %d", text_type);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Get notification text error");
+  }
+
+  if (text)
+    *noti_text = text;
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult StatusNotification::SetText(notification_h noti_handle,
+                                           notification_text_type_e text_type,
+                                           const std::string& noti_text) {
+  LoggerD("Enter");
+  int ret = notification_set_text(noti_handle,
+                                  text_type,
+                                  noti_text.c_str(),
+                                  NULL,
+                                  NOTIFICATION_VARIABLE_TYPE_NONE);
+  if (ret != NOTIFICATION_ERROR_NONE) {
+    LoggerE("Set notification text error, text_type: %d, error: %d",
+            text_type,
+            ret);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Set notification text error");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult StatusNotification::GetNumber(notification_h noti_handle,
+                                             notification_text_type_e text_type,
+                                             long* number) {
+  LoggerD("Enter");
+  std::string text;
+  PlatformResult status = GetText(noti_handle, text_type, &text);
+  if (status.IsError())
+    return status;
+
+  if (text.length())
+    *number = std::stol(text);
+  else
+    *number = -1;
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult StatusNotification::GetDetailInfos(notification_h noti_handle,
+                                                  picojson::array* out) {
+  LoggerD("Enter");
+  if (info_map_.size() != info_sub_map_.size()) {
+    LoggerE("Different notification information types element size");
+    return PlatformResult(
+        ErrorCode::VALIDATION_ERR,
+        "Different notification information types element size");
+  }
+
+  picojson::value detail_info = picojson::value(picojson::object());
+  picojson::object& detail_info_obj = detail_info.get<picojson::object>();
+
+  std::string text;
+  size_t info_map_size = info_map_.size();
+  for (size_t idx = 0; idx < info_map_size; ++idx) {
+    PlatformResult status = GetText(noti_handle, info_map_.at(idx), &text);
+    if (status.IsError())
+      return status;
+
+    if (!text.length())
+      break;
+
+    detail_info_obj["mainText"] = picojson::value(text);
+
+    status = GetText(noti_handle, info_sub_map_.at(idx), &text);
+    if (status.IsError())
+      return status;
+
+    if (text.length()) {
+      detail_info_obj["subText"] = picojson::value(text);
+    }
+
+    out->push_back(detail_info);
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult StatusNotification::SetDetailInfos(
+    notification_h noti_handle,
+    const picojson::array& value) {
+  LoggerD("Enter");
+  size_t idx = 0;
+
+  size_t info_map_size = info_map_.size();
+  for (auto& item : value) {
+    const picojson::object& obj = JsonCast<picojson::object>(item);
+
+    PlatformResult status =
+        SetText(noti_handle,
+                info_map_.at(idx),
+                common::FromJson<std::string>(obj, "mainText"));
+    if (status.IsError())
+      return status;
+
+    if (picojson::value(obj).contains("subText") && !IsNull(obj, "subText")) {
+      PlatformResult status =
+          SetText(noti_handle,
+                  info_sub_map_.at(idx),
+                  common::FromJson<std::string>(obj, "subText"));
+      if (status.IsError())
+        return status;
+    }
+
+    ++idx;
+
+    if (idx > info_map_size) {
+      LoggerE("Too many values in notification detailInfo array");
+      return PlatformResult(ErrorCode::INVALID_VALUES_ERR,
+                            "Too many values in notification detailInfo array");
+    }
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult StatusNotification::GetLedColor(notification_h noti_handle,
+                                               std::string* led_color) {
+  LoggerD("Enter");
+  unsigned int color = 0;
+  notification_led_op_e type = NOTIFICATION_LED_OP_ON;
+
+  if (notification_get_led(noti_handle, &type, (int*)&color) !=
+      NOTIFICATION_ERROR_NONE) {
+    LoggerE("Get notification led displaying option error");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Get notification led displaying option error");
+  }
+
+  *led_color = "";
+  std::stringstream stream;
+
+  if (NOTIFICATION_LED_OP_OFF != type) {
+    color = 0x00FFFFFF & color;
+    stream << std::hex << color;
+    *led_color = "#" + stream.str();
+
+    while (led_color->length() < 7) {
+      led_color->insert(1, "0");
+    }
+
+    std::transform(
+        led_color->begin(), led_color->end(), led_color->begin(), ::tolower);
+  }
+
+  LoggerD("color:%s", (*led_color).c_str());
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult StatusNotification::SetLedColor(notification_h noti_handle,
+                                               const std::string& led_color) {
+  LoggerD("Enter");
+  std::string color_str = led_color;
+  std::transform(
+      color_str.begin(), color_str.end(), color_str.begin(), ::tolower);
+
+  if (!IsColorFormatNumberic(color_str)) {
+    LoggerE("Led color is not numeric value: %s", color_str.c_str());
+    return PlatformResult(ErrorCode::INVALID_VALUES_ERR,
+                          "Led color is not numeric value");
+  }
+
+  std::stringstream stream;
+  unsigned int color = 0;
+  notification_led_op_e type = NOTIFICATION_LED_OP_ON;
+  std::string color_code =
+      color_str.substr(1, color_str.length()).insert(0, "ff");
+
+  stream << std::hex << color_code;
+  stream >> color;
+
+  if (color != 0)
+    type = NOTIFICATION_LED_OP_ON_CUSTOM_COLOR;
+  else
+    type = NOTIFICATION_LED_OP_OFF;
+
+  int ret = notification_set_led(noti_handle, type, static_cast<int>(color));
+  if (ret != NOTIFICATION_ERROR_NONE) {
+    LoggerE("Set notification led color eror: %d", ret);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Set notification led color eror");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult StatusNotification::GetLedPeriod(notification_h noti_handle,
+                                                unsigned long* on_period,
+                                                unsigned long* off_period) {
+  LoggerD("Enter");
+  int on_time = 0;
+  int off_time = 0;
+
+  if (notification_get_led_time_period(noti_handle, &on_time, &off_time) !=
+      NOTIFICATION_ERROR_NONE) {
+    LoggerE("Get notification led on/off period error");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Get notification led on/off period error");
+  }
+
+  if (on_period)
+    *on_period = on_time;
+  if (off_period)
+    *off_period = off_time;
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult StatusNotification::SetLedOnPeriod(notification_h noti_handle,
+                                                  unsigned long on_period) {
+  LoggerD("Enter");
+  unsigned long off_period = 0;
+  PlatformResult status = GetLedPeriod(noti_handle, nullptr, &off_period);
+  if (status.IsError())
+    return status;
+
+  int ret =
+      notification_set_led_time_period(noti_handle, on_period, off_period);
+  if (ret != NOTIFICATION_ERROR_NONE) {
+    LoggerE("Set notification led on period error: %d", ret);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Set notification led on period error");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult StatusNotification::SetLedOffPeriod(notification_h noti_handle,
+                                                   unsigned long off_period) {
+  LoggerD("Enter");
+  unsigned long on_period = 0;
+  PlatformResult status = GetLedPeriod(noti_handle, &on_period, nullptr);
+  if (status.IsError())
+    return status;
+
+  int ret =
+      notification_set_led_time_period(noti_handle, on_period, off_period);
+  if (ret != NOTIFICATION_ERROR_NONE) {
+    LoggerE("Set notification led off period error: %d", ret);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Set notification led off period error");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult StatusNotification::GetThumbnails(notification_h noti_handle,
+                                                 picojson::array* out) {
+  LoggerD("Enter");
+  std::string text;
+  size_t thumbnails_map_size = thumbnails_map_.size();
+  for (size_t idx = 0; idx < thumbnails_map_size; ++idx) {
+    PlatformResult status =
+        GetImage(noti_handle, thumbnails_map_.at(idx), &text);
+    if (status.IsError())
+      return status;
+
+    if (!text.length())
+      break;
+
+    out->push_back(picojson::value(VirtualFs::GetInstance().GetVirtualPath(text)));
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult StatusNotification::SetThumbnails(notification_h noti_handle,
+                                                 const picojson::array& value) {
+  LoggerD("Enter");
+  size_t idx = 0;
+
+  size_t thumbnails_map_size = thumbnails_map_.size();
+  for (auto& item : value) {
+    const std::string& text = JsonCast<std::string>(item);
+    std::string real_path = VirtualFs::GetInstance().GetRealPath(text);
+
+    PlatformResult status =
+        SetImage(noti_handle, thumbnails_map_.at(idx), real_path);
+    if (status.IsError())
+      return status;
+
+    ++idx;
+
+    if (idx > thumbnails_map_size) {
+      LoggerE("Too many values in notification thumbnail array");
+      return PlatformResult(ErrorCode::INVALID_VALUES_ERR,
+                            "Too many values in notification thumbnail array");
+    }
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult StatusNotification::GetSoundPath(notification_h noti_handle,
+                                                std::string* sound_path) {
+  LoggerD("Enter");
+  *sound_path = "";
+
+  const char* path = NULL;
+  notification_sound_type_e type = NOTIFICATION_SOUND_TYPE_NONE;
+
+  if (notification_get_sound(noti_handle, &type, &path) !=
+      NOTIFICATION_ERROR_NONE) {
+    LoggerE("Get notification sound error");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Get notification sound error");
+  }
+
+  LoggerD("Sound type = %d", type);
+
+  if (path && (type == NOTIFICATION_SOUND_TYPE_USER_DATA)) {
+    *sound_path = path;
+  }
+
+  LoggerD("Sound path = %s", sound_path->c_str());
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult StatusNotification::SetSoundPath(notification_h noti_handle,
+                                                const std::string& sound_path) {
+  LoggerD("Enter");
+  int ret = notification_set_sound(
+      noti_handle, NOTIFICATION_SOUND_TYPE_USER_DATA, sound_path.c_str());
+  if (ret != NOTIFICATION_ERROR_NONE) {
+    LoggerE("Set notification sound error: %d", ret);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Set notification sound error");
+  }
+
+  LoggerD("Sound path = %s", sound_path.c_str());
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult StatusNotification::GetVibration(notification_h noti_handle,
+                                                bool* vibration) {
+  LoggerD("Enter");
+  notification_vibration_type_e vib_type = NOTIFICATION_VIBRATION_TYPE_NONE;
+
+  if (notification_get_vibration(noti_handle, &vib_type, NULL) !=
+      NOTIFICATION_ERROR_NONE) {
+    LoggerE("Get notification vibration error");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Get notification vibration error");
+  }
+
+  if (NOTIFICATION_VIBRATION_TYPE_DEFAULT == vib_type ||
+      NOTIFICATION_VIBRATION_TYPE_USER_DATA == vib_type) {
+    *vibration = true;
+  } else {
+    *vibration = false;
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult StatusNotification::SetVibration(notification_h noti_handle,
+                                                bool vibration) {
+  LoggerD("Enter");
+  bool platform_vibration;
+  PlatformResult status = GetVibration(noti_handle, &platform_vibration);
+  if (status.IsError())
+    return status;
+
+  if (platform_vibration != vibration) {
+    notification_vibration_type_e vib_type = NOTIFICATION_VIBRATION_TYPE_NONE;
+
+    if (vibration) {
+      vib_type = NOTIFICATION_VIBRATION_TYPE_DEFAULT;
+    }
+
+    int ret = notification_set_vibration(noti_handle, vib_type, NULL);
+    if (ret != NOTIFICATION_ERROR_NONE) {
+      LoggerE("Set notification vibration error: %d", ret);
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "Set notification vibration error");
+    }
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult StatusNotification::GetApplicationControl(
+    app_control_h app_handle,
+    picojson::object* out_ptr) {
+  LoggerD("Enter");
+  picojson::object& out = *out_ptr;
+
+  char* operation = NULL;
+  char* uri = NULL;
+  char* mime = NULL;
+  char* category = NULL;
+  SCOPE_EXIT {
+    free(operation);
+    free(uri);
+    free(mime);
+    free(category);
+  };
+
+  int ret = app_control_get_operation(app_handle, &operation);
+  if (ret != APP_CONTROL_ERROR_NONE) {
+    LoggerE("Get application control operation error: %d", ret);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Get application control operation error");
+  }
+  if (operation) {
+    out["operation"] = picojson::value(operation);
+    LoggerD("operation = %s", operation);
+  }
+
+  if (app_control_get_uri(app_handle, &uri) != APP_CONTROL_ERROR_NONE) {
+    LoggerE("Get application control uri error");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Get application control uri error");
+  }
+  if (uri) {
+    out["uri"] = picojson::value(uri);
+    LoggerD("uri = %s", uri);
+  }
+
+  if (app_control_get_mime(app_handle, &mime) != APP_CONTROL_ERROR_NONE) {
+    LoggerE("Get application control mime error");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Get application control mime error");
+  }
+  if (mime) {
+    out["mime"] = picojson::value(mime);
+    LoggerD("mime = %s", mime);
+  }
+
+  if (app_control_get_category(app_handle, &category) !=
+      APP_CONTROL_ERROR_NONE) {
+    LoggerE("Get application control category error");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Get application control category error");
+  }
+  if (category) {
+    out["category"] = picojson::value(category);
+    LoggerD("category = %s", category);
+  }
+
+  picojson::array app_control_data = picojson::array();
+  if (app_control_foreach_extra_data(
+          app_handle, ServiceExtraDataCb, (void*)&app_control_data) !=
+      APP_CONTROL_ERROR_NONE) {
+    LoggerE("Get application control data error");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Get application control data error");
+  }
+  out["data"] = picojson::value(app_control_data);
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult StatusNotification::SetApplicationControl(
+    app_control_h app_handle,
+    const picojson::object& app_ctrl) {
+  LoggerD("Enter");
+  picojson::value val(app_ctrl);
+  const std::string& operation =
+      common::FromJson<std::string>(app_ctrl, "operation");
+
+  int ret;
+  if (operation.length()) {
+    ret = app_control_set_operation(app_handle, operation.c_str());
+  } else {
+    ret = app_control_set_operation(app_handle, APP_CONTROL_OPERATION_DEFAULT);
+  }
+  if (ret != APP_CONTROL_ERROR_NONE) {
+    LoggerE("Set application control operation error: %d", ret);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Set application control operation error");
+  }
+
+  if (val.contains("uri") && !IsNull(app_ctrl, "uri")) {
+    const std::string& uri = common::FromJson<std::string>(app_ctrl, "uri");
+    ret = app_control_set_uri(app_handle, uri.c_str());
+    if (ret != APP_CONTROL_ERROR_NONE) {
+      LoggerE("Set application control uri error: %d", ret);
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "Set application control uri error");
+    }
+  }
+
+  if (val.contains("mime") && !IsNull(app_ctrl, "mime")) {
+    const std::string& mime = common::FromJson<std::string>(app_ctrl, "mime");
+    ret = app_control_set_mime(app_handle, mime.c_str());
+    if (ret != APP_CONTROL_ERROR_NONE) {
+      LoggerE("Set application control mime error: %d", ret);
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "Set application control mime error");
+    }
+  }
+
+  if (val.contains("category") && !IsNull(app_ctrl, "category")) {
+    const std::string& category =
+        common::FromJson<std::string>(app_ctrl, "category");
+    ret = app_control_set_category(app_handle, category.c_str());
+    if (ret != APP_CONTROL_ERROR_NONE) {
+      LoggerE("Set application control category error: %d", ret);
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "Set application control category error");
+    }
+  }
+
+  if (!picojson::value(app_ctrl).contains("data") || IsNull(app_ctrl, "data")) {
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+
+  auto& items = common::FromJson<picojson::array>(app_ctrl, "data");
+
+  int idx = 0;
+
+  for (auto item : items) {
+    const picojson::object& obj = JsonCast<picojson::object>(item);
+    const std::string key = common::FromJson<std::string>(obj, "key");
+    const picojson::array values =
+        common::FromJson<picojson::array>(obj, "value");
+    const char** arrayValue =
+        (const char**)calloc(sizeof(char*), values.size());
+    SCOPE_EXIT { free(arrayValue); };
+    idx = 0;
+    for (auto& item : values) {
+      arrayValue[idx] = JsonCast<std::string>(item).c_str();
+      ++idx;
+    }
+    ret = app_control_add_extra_data_array(
+        app_handle, key.c_str(), arrayValue, values.size());
+    if (ret != APP_CONTROL_ERROR_NONE) {
+      LoggerE("Set application control extra data error: %d", ret);
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "Set application control extra data error");
+    }
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult StatusNotification::GetApplicationId(app_control_h app_handle,
+                                                    std::string* app_id) {
+  LoggerD("Enter");
+  char* app_id_str = NULL;
+  SCOPE_EXIT { free(app_id_str); };
+
+  *app_id = "";
+
+  if (app_control_get_app_id(app_handle, &app_id_str) !=
+      APP_CONTROL_ERROR_NONE) {
+    LoggerE("Get applicaiton ID failed");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Get applicaiton ID failed");
+  }
+
+  if (app_id_str != NULL) {
+    *app_id = app_id_str;
+  }
+
+  LoggerD("Get appId = %s", /*(*app_id).c_str()*/ app_id_str);
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult StatusNotification::SetApplicationId(app_control_h app_handle,
+                                                    const std::string& app_id) {
+  LoggerD("Enter");
+  int ret = app_control_set_app_id(app_handle, app_id.c_str());
+  if (ret != APP_CONTROL_ERROR_NONE) {
+    LoggerE("Set applicaiton ID error: %d", ret);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Set applicaiton ID error");
+  }
+
+  LoggerD("Set appId = %s", app_id.c_str());
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult StatusNotification::GetProgressValue(
+    notification_h noti_handle,
+    const std::string& progess_type,
+    double* progress_value) {
+  LoggerD("Enter");
+  double tmp_progress_value = 0.0;
+
+  if (progess_type == kProgressTypeByte) {
+    if (notification_get_size(noti_handle, &tmp_progress_value) !=
+        NOTIFICATION_ERROR_NONE) {
+      LoggerE("Get notification size error");
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "Get notification size error");
+    }
+  } else if (progess_type == kProgressTypePercentage) {
+    if (notification_get_progress(noti_handle, &tmp_progress_value) !=
+        NOTIFICATION_ERROR_NONE) {
+      LoggerE("Get notification progress error");
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "Get notification progress error");
+    }
+  } else {
+    LoggerE("Unknown notification progress type: %s ", progess_type.c_str());
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Unknown notification progress type");
+  }
+
+  LOGGER(DEBUG) << "Progress " << progess_type << " = " << tmp_progress_value;
+
+  *progress_value = tmp_progress_value;
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult StatusNotification::SetProgressValue(
+    notification_h noti_handle,
+    const std::string& progress_type,
+    double progress_value,
+    bool is_update) {
+  LoggerD("Enter");
+  int ret;
+
+  if (progress_type == kProgressTypeByte) {
+    ret = notification_set_size(noti_handle, progress_value);
+
+    if (is_update) {
+      ret = notification_update_size(noti_handle, NOTIFICATION_PRIV_ID_NONE,
+          progress_value);
+    }
+  } else if (progress_type == kProgressTypePercentage) {
+    ret = notification_set_progress(noti_handle, progress_value);
+
+    if (is_update) {
+      ret = notification_update_progress(noti_handle, NOTIFICATION_PRIV_ID_NONE,
+          progress_value);
+    }
+  } else {
+    LoggerE("Unknown notification progress type: %s ", progress_type.c_str());
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Unknown notification progress type");
+  }
+
+  if (ret != NOTIFICATION_ERROR_NONE) {
+    LoggerE("Set notification progress/size error: %d", ret);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Set notification progress/size error");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult StatusNotification::GetPostedTime(notification_h noti_handle,
+                                                 time_t* posted_time) {
+  LoggerD("Enter");
+  *posted_time = 0;
+
+  if (notification_get_insert_time(noti_handle, posted_time) !=
+      NOTIFICATION_ERROR_NONE) {
+    LoggerE("Get notification posted time error");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Get notification posted time error");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult StatusNotification::GetNotiHandle(int id,
+                                                 notification_h* noti_handle) {
+  LoggerD("Enter");
+  *noti_handle = notification_load(NULL, id);
+  if (NULL == *noti_handle) {
+    LoggerE("Not found or removed notification id");
+    return PlatformResult(ErrorCode::NOT_FOUND_ERR,
+                          "Not found or removed notification id");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult StatusNotification::GetAppControl(notification_h noti_handle,
+                                                 app_control_h* app_control) {
+  LoggerD("Enter");
+  int ret =
+      notification_get_launch_option(noti_handle,
+                                     NOTIFICATION_LAUNCH_OPTION_APP_CONTROL,
+                                     static_cast<void*>(app_control));
+  if (ret != NOTIFICATION_ERROR_NONE) {
+    LoggerE("Notification get launch option error: %d", ret);
+    return PlatformResult(ErrorCode::INVALID_VALUES_ERR,
+                          "Notification get launch option error");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult StatusNotification::CreateAppControl(
+    app_control_h* app_control) {
+  LoggerD("Enter");
+  int ret = app_control_create(app_control);
+  if (ret != APP_CONTROL_ERROR_NONE) {
+    LoggerE("Application create error: %d", ret);
+    return PlatformResult(ErrorCode::INVALID_VALUES_ERR,
+                          "Application create error");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult StatusNotification::SetAppControl(notification_h noti_handle,
+                                                 app_control_h app_control) {
+  LoggerD("Enter");
+  int ret =
+      notification_set_launch_option(noti_handle,
+                                     NOTIFICATION_LAUNCH_OPTION_APP_CONTROL,
+                                     static_cast<void*>(app_control));
+  if (ret != APP_CONTROL_ERROR_NONE) {
+    LoggerE("Notification set launch option error: %d", ret);
+    return PlatformResult(ErrorCode::INVALID_VALUES_ERR,
+                          "Notification set launch option error");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult StatusNotification::ToJson(int id,
+                                          notification_h noti_handle,
+                                          app_control_h app_handle,
+                                          picojson::object* out_ptr) {
+  LoggerD("Enter");
+  picojson::object& out = *out_ptr;
+
+  out["id"] = picojson::value(std::to_string(id));
+  out["type"] = picojson::value("STATUS");
+
+  // Nitification type
+  notification_type_e noti_type = NOTIFICATION_TYPE_NONE;
+  int ret = notification_get_type(noti_handle, &noti_type);
+  if (ret != NOTIFICATION_ERROR_NONE) {
+    LoggerE("Notification get type error: %d", ret);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Notification get type error");
+  }
+
+  notification_ly_type_e noti_layout = NOTIFICATION_LY_NONE;
+  ret = notification_get_layout(noti_handle, &noti_layout);
+  if (ret != NOTIFICATION_ERROR_NONE) {
+    LoggerE("Notification get layout error: %d", ret);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Notification get layout error");
+  }
+
+  std::string noti_type_str;
+  PlatformResult status =
+      StatusTypeFromPlatform(noti_type, noti_layout, &noti_type_str);
+  if (status.IsError())
+    return status;
+  out["statusType"] = picojson::value(noti_type_str);
+
+  std::string value_str;
+  status = GetImage(noti_handle, NOTIFICATION_IMAGE_TYPE_ICON, &value_str);
+  if (status.IsError())
+    return status;
+  if (value_str.length()) {
+    out["iconPath"] = picojson::value(VirtualFs::GetInstance().GetVirtualPath(value_str));
+  }
+
+  status = GetImage(noti_handle, NOTIFICATION_IMAGE_TYPE_ICON_SUB, &value_str);
+  if (status.IsError())
+    return status;
+  if (value_str.length()) {
+    out["subIconPath"] = picojson::value(VirtualFs::GetInstance().GetVirtualPath(value_str));
+  }
+
+  long number;
+  status = GetNumber(noti_handle, NOTIFICATION_TEXT_TYPE_EVENT_COUNT, &number);
+  if (status.IsError())
+    return status;
+  if (number >= 0) {
+    out["number"] = picojson::value(static_cast<double>(number));
+  }
+
+  picojson::array detail_infos = picojson::array();
+  status = GetDetailInfos(noti_handle, &detail_infos);
+  if (status.IsError())
+    return status;
+  if (detail_infos.size()) {
+    out["detailInfo"] = picojson::value(detail_infos);
+  }
+
+  status = GetLedColor(noti_handle, &value_str);
+  if (status.IsError())
+    return status;
+  if (value_str.length()) {
+    out["ledColor"] = picojson::value(value_str);
+  }
+
+  unsigned long on_period;
+  unsigned long off_period;
+  status = GetLedPeriod(noti_handle, &on_period, &off_period);
+  if (status.IsError())
+    return status;
+  out["ledOnPeriod"] = picojson::value(static_cast<double>(on_period));
+  out["ledOffPeriod"] = picojson::value(static_cast<double>(off_period));
+
+  status =
+      GetImage(noti_handle, NOTIFICATION_IMAGE_TYPE_BACKGROUND, &value_str);
+  if (status.IsError())
+    return status;
+  if (value_str.length()) {
+    out["backgroundImagePath"] = picojson::value(VirtualFs::GetInstance().GetVirtualPath(value_str));
+  }
+
+  picojson::array thumbnails = picojson::array();
+  status = GetThumbnails(noti_handle, &thumbnails);
+  if (status.IsError())
+    return status;
+  if (thumbnails.size()) {
+    out["thumbnails"] = picojson::value(thumbnails);
+  }
+
+  status = GetSoundPath(noti_handle, &value_str);
+  if (status.IsError())
+    return status;
+  if (value_str.length()) {
+    out["soundPath"] = picojson::value(VirtualFs::GetInstance().GetVirtualPath(value_str));
+  }
+
+  bool vibration;
+  status = GetVibration(noti_handle, &vibration);
+  if (status.IsError())
+    return status;
+  out["vibration"] = picojson::value(vibration);
+
+  picojson::object app_control = picojson::object();
+  status = GetApplicationControl(app_handle, &app_control);
+  if (status.IsError())
+    return status;
+  if (app_control.size()) {
+    out["appControl"] = picojson::value(app_control);
+  }
+
+  status = GetApplicationId(app_handle, &value_str);
+  if (status.IsError())
+    return status;
+  if (value_str.length()) {
+    out["appId"] = picojson::value(value_str);
+  }
+
+  std::string progress_type;
+  status =
+      GetImage(noti_handle, NOTIFICATION_IMAGE_TYPE_LIST_5, &progress_type);
+  if (status.IsError())
+    return status;
+  out["progressType"] = picojson::value(progress_type);
+
+  double progress_value;
+  status = GetProgressValue(noti_handle, progress_type, &progress_value);
+  if (status.IsError())
+    return status;
+  out["progressValue"] = picojson::value(progress_value);
+
+  time_t posted_time;
+  status = GetPostedTime(noti_handle, &posted_time);
+  if (status.IsError())
+    return status;
+  out["postedTime"] =
+      picojson::value(static_cast<double>(posted_time) * 1000.0);
+
+  status = GetText(noti_handle, NOTIFICATION_TEXT_TYPE_TITLE, &value_str);
+  if (status.IsError())
+    return status;
+  out["title"] = picojson::value(value_str);
+
+  status = GetText(noti_handle, NOTIFICATION_TEXT_TYPE_CONTENT, &value_str);
+  if (status.IsError())
+    return status;
+  if (value_str.length()) {
+    out["content"] = picojson::value(value_str);
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult StatusNotification::FromJson(const picojson::object& args,
+                                            bool is_update,
+                                            picojson::object* out_ptr) {
+  LoggerD("Enter");
+  picojson::object noti_obj =
+      common::FromJson<picojson::object>(args, "notification");
+
+  const std::string& status_type =
+      common::FromJson<std::string>(noti_obj, "statusType");
+
+  notification_type_e noti_type;
+  PlatformResult status = StatusTypeToPlatform(status_type, &noti_type);
+  if (status.IsError())
+    return status;
+
+  int id = NOTIFICATION_PRIV_ID_NONE;
+  int ret;
+
+  notification_h noti_handle = nullptr;
+  app_control_h app_control = NULL;
+
+  SCOPE_EXIT {
+    if (app_control) {
+      app_control_destroy(app_control);
+    }
+    free(noti_handle);
+  };
+
+  if (is_update) {
+    id = std::stoi(common::FromJson<std::string>(noti_obj, "id"));
+
+    PlatformResult status = GetNotiHandle(id, &noti_handle);
+    if (status.IsError())
+      return status;
+
+  } else {
+    status = Create(noti_type, &noti_handle);
+    if (status.IsError())
+      return status;
+  }
+
+  status = SetLayout(noti_handle, status_type);
+  if (status.IsError()) {
+    return status;
+  }
+
+  picojson::value val(noti_obj);
+  if (val.contains("iconPath") && !IsNull(noti_obj, "iconPath")) {
+    const std::string& value_str = common::FromJson<std::string>(noti_obj, "iconPath");
+    std::string real_path = VirtualFs::GetInstance().GetRealPath(value_str);
+
+    status = SetImage(noti_handle, NOTIFICATION_IMAGE_TYPE_ICON, real_path);
+    if (status.IsError()) {
+      return status;
+    }
+  }
+
+  if (val.contains("subIconPath") && !IsNull(noti_obj, "subIconPath")) {
+    const std::string& value_str =
+        common::FromJson<std::string>(noti_obj, "subIconPath");
+    std::string real_path = VirtualFs::GetInstance().GetRealPath(value_str);
+
+    status = SetImage(noti_handle, NOTIFICATION_IMAGE_TYPE_ICON_SUB, real_path);
+    if (status.IsError()) {
+      return status;
+    }
+  }
+
+  if (val.contains("number") && !IsNull(noti_obj, "number")) {
+    const std::string& value_str =
+        std::to_string(common::FromJson<double>(noti_obj, "number"));
+    status =
+        SetText(noti_handle, NOTIFICATION_TEXT_TYPE_EVENT_COUNT, value_str);
+    if (status.IsError()) {
+      return status;
+    }
+  }
+
+  if (val.contains("detailInfo") && !IsNull(noti_obj, "detailInfo")) {
+    status = SetDetailInfos(
+        noti_handle, common::FromJson<picojson::array>(noti_obj, "detailInfo"));
+    if (status.IsError()) {
+      return status;
+    }
+  }
+
+  if (val.contains("ledColor") && !IsNull(noti_obj, "ledColor")) {
+    status = SetLedColor(noti_handle,
+                         common::FromJson<std::string>(noti_obj, "ledColor"));
+    if (status.IsError()) {
+      return status;
+    }
+  }
+
+  status = SetLedOnPeriod(noti_handle,
+                          static_cast<unsigned long>(common::FromJson<double>(
+                              noti_obj, "ledOnPeriod")));
+  if (status.IsError()) {
+    return status;
+  }
+
+  status = SetLedOffPeriod(noti_handle,
+                           static_cast<unsigned long>(common::FromJson<double>(
+                               noti_obj, "ledOffPeriod")));
+  if (status.IsError()) {
+    return status;
+  }
+
+  if (val.contains("backgroundImagePath")
+      && !IsNull(noti_obj, "backgroundImagePath")) {
+    const std::string& value_str = common::FromJson<std::string>(noti_obj, "backgroundImagePath");
+    std::string real_path = VirtualFs::GetInstance().GetRealPath(value_str);
+
+    status = SetImage(noti_handle, NOTIFICATION_IMAGE_TYPE_BACKGROUND, real_path);
+    if (status.IsError()) {
+      return status;
+    }
+  }
+
+  if (val.contains("thumbnails") && !IsNull(noti_obj, "thumbnails")) {
+    status = SetThumbnails(
+        noti_handle, common::FromJson<picojson::array>(noti_obj, "thumbnails"));
+    if (status.IsError()) {
+      return status;
+    }
+  }
+
+  if (val.contains("soundPath") && !IsNull(noti_obj, "soundPath")) {
+    const std::string& value_str = common::FromJson<std::string>(noti_obj, "soundPath");
+    std::string real_path = VirtualFs::GetInstance().GetRealPath(value_str);
+
+    status = SetSoundPath(noti_handle, real_path);
+    if (status.IsError()) {
+      return status;
+    }
+  }
+
+  status =
+      SetVibration(noti_handle, common::FromJson<bool>(noti_obj, "vibration"));
+  if (status.IsError()) {
+    return status;
+  }
+
+  status = CreateAppControl(&app_control);
+  if (status.IsError()) {
+    return status;
+  }
+
+  if (val.contains("appControl") && !IsNull(noti_obj, "appControl")) {
+    status = SetApplicationControl(
+        app_control,
+        common::FromJson<picojson::object>(noti_obj, "appControl"));
+    if (status.IsError()) {
+      return status;
+    }
+  }
+
+  if (val.contains("appId") && !IsNull(noti_obj, "appId")) {
+    status = SetApplicationId(app_control,
+                              common::FromJson<std::string>(noti_obj, "appId"));
+    if (status.IsError()) {
+      return status;
+    }
+  }
+
+  const std::string& progress_type =
+      common::FromJson<std::string>(noti_obj, "progressType");
+  status = SetImage(noti_handle, NOTIFICATION_IMAGE_TYPE_LIST_5, progress_type);
+  if (status.IsError()) {
+    return status;
+  }
+
+  if (val.contains("progressValue") && !IsNull(noti_obj, "progressValue")) {
+    double progressValue = common::FromJson<double>(noti_obj, "progressValue");
+    status = SetProgressValue(noti_handle, progress_type, progressValue,
+        is_update);
+
+    if (status.IsError()) {
+      return status;
+    }
+  }
+
+  status = SetText(noti_handle,
+                   NOTIFICATION_TEXT_TYPE_TITLE,
+                   common::FromJson<std::string>(noti_obj, "title"));
+  if (status.IsError()) {
+    return status;
+  }
+
+  if (val.contains("content") && !IsNull(noti_obj, "content")) {
+    status = SetText(noti_handle,
+                     NOTIFICATION_TEXT_TYPE_CONTENT,
+                     common::FromJson<std::string>(noti_obj, "content"));
+    if (status.IsError()) {
+      return status;
+    }
+  }
+
+  status = SetAppControl(noti_handle, app_control);
+
+  if (is_update) {
+    ret = notification_update(noti_handle);
+
+  } else {
+    ret = notification_insert(noti_handle, &id);
+    if (NOTIFICATION_ERROR_NONE != ret) {
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+          "Cannot insert notification");
+    }
+  }
+  if (ret != NOTIFICATION_ERROR_NONE) {
+    LoggerE("Post/Update notification error: %d", ret);
+    return PlatformResult(ErrorCode::INVALID_VALUES_ERR,
+                          "Post/Update notification error");
+  }
+
+  time_t posted_time;
+  status = GetPostedTime(noti_handle, &posted_time);
+  if (status.IsError()) {
+    return status;
+  }
+
+  if (is_update) {
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+
+  picojson::object& out = *out_ptr;
+  out["id"] = picojson::value(std::to_string(id));
+  out["postedTime"] =
+      picojson::value(static_cast<double>(posted_time) * 1000.0);
+  out["type"] = picojson::value("STATUS");
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+}  // namespace notification
+}  // namespace extension
diff --git a/webWidgetTCT_device/src/notification/status_notification.h b/webWidgetTCT_device/src/notification/status_notification.h
new file mode 100755 (executable)
index 0000000..ae50e8d
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2015 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 NOTIFICATION_STATUS_NOTIFICATION_H_
+#define NOTIFICATION_STATUS_NOTIFICATION_H_
+
+#include <notification.h>
+#include <app_control.h>
+
+#include "common/picojson.h"
+#include "common/platform_result.h"
+
+namespace extension {
+namespace notification {
+
+typedef std::map<int, notification_text_type_e> InformationEnumMap;
+typedef std::map<int, notification_image_type_e> ImageEnumMap;
+
+class StatusNotification {
+ public:
+  static common::PlatformResult ToJson(int id,
+                                       notification_h noti_handle,
+                                       app_control_h app_handle,
+                                       picojson::object* out_ptr);
+  static common::PlatformResult FromJson(const picojson::object& args,
+                                         bool is_update,
+                                         picojson::object* out_ptr);
+  static common::PlatformResult GetAppControl(notification_h noti_handle,
+                                              app_control_h* app_control);
+  static common::PlatformResult GetNotiHandle(int id,
+                                              notification_h* noti_handle);
+
+ private:
+  StatusNotification();
+  virtual ~StatusNotification();
+
+  static const InformationEnumMap info_map_;
+  static const InformationEnumMap info_sub_map_;
+  static const ImageEnumMap thumbnails_map_;
+
+  static common::PlatformResult StatusTypeFromPlatform(
+      notification_type_e noti_type,
+      notification_ly_type_e noti_layout,
+      std::string* type);
+  static common::PlatformResult StatusTypeToPlatform(
+      const std::string& type,
+      notification_type_e* noti_type);
+  static common::PlatformResult Create(notification_type_e noti_type,
+                                       notification_h* noti_handle);
+  static common::PlatformResult GetImage(notification_h noti_handle,
+                                         notification_image_type_e image_type,
+                                         std::string* image_path);
+  static common::PlatformResult SetImage(notification_h noti_handle,
+                                         notification_image_type_e image_type,
+                                         const std::string& image_path);
+  static common::PlatformResult GetText(notification_h noti_handle,
+                                        notification_text_type_e text_type,
+                                        std::string* noti_text);
+  static common::PlatformResult SetText(notification_h noti_handle,
+                                        notification_text_type_e text_type,
+                                        const std::string& noti_text);
+  static common::PlatformResult GetNumber(notification_h noti_handle,
+                                          notification_text_type_e text_type,
+                                          long* number);
+  static common::PlatformResult GetDetailInfos(notification_h noti_handle,
+                                               picojson::array* out);
+  static common::PlatformResult SetDetailInfos(notification_h noti_handle,
+                                               const picojson::array& value);
+  static common::PlatformResult GetLedColor(notification_h noti_handle,
+                                            std::string* led_color);
+  static common::PlatformResult SetLedColor(notification_h noti_handle,
+                                            const std::string& led_color);
+  static common::PlatformResult GetLedPeriod(notification_h noti_handle,
+                                             unsigned long* on_period,
+                                             unsigned long* off_period);
+  static common::PlatformResult SetLedOnPeriod(notification_h noti_handle,
+                                               unsigned long on_period);
+  static common::PlatformResult SetLedOffPeriod(notification_h noti_handle,
+                                                unsigned long off_period);
+  static common::PlatformResult GetThumbnails(notification_h noti_handle,
+                                              picojson::array* out);
+  static common::PlatformResult SetThumbnails(notification_h noti_handle,
+                                              const picojson::array& value);
+  static common::PlatformResult GetSoundPath(notification_h noti_handle,
+                                             std::string* sound_path);
+  static common::PlatformResult SetSoundPath(notification_h noti_handle,
+                                             const std::string& sound_path);
+  static common::PlatformResult GetVibration(notification_h noti_handle,
+                                             bool* vibration);
+  static common::PlatformResult SetVibration(notification_h noti_handle,
+                                             bool vibration);
+  static common::PlatformResult GetApplicationControl(
+      app_control_h app_handle,
+      picojson::object* out_ptr);
+  static common::PlatformResult SetApplicationControl(
+      app_control_h app_handle,
+      const picojson::object& app_ctrl);
+  static common::PlatformResult GetApplicationId(app_control_h app_handle,
+                                                 std::string* app_id);
+  static common::PlatformResult SetApplicationId(app_control_h app_handle,
+                                                 const std::string& app_id);
+  static common::PlatformResult GetProgressValue(
+      notification_h noti_handle,
+      const std::string& progess_type,
+      double* progress_value);
+  static common::PlatformResult SetProgressValue(
+      notification_h noti_handle,
+      const std::string& progress_type,
+      double progress_value,
+      bool is_update);
+  static common::PlatformResult GetPostedTime(notification_h noti_handle,
+                                              time_t* posted_time);
+  static common::PlatformResult SetLayout(notification_h noti_handle,
+                                          const std::string& noti_type);
+  static common::PlatformResult SetAppControl(notification_h noti_handle,
+                                              app_control_h app_control);
+  static common::PlatformResult CreateAppControl(app_control_h* app_control);
+
+  static bool IsColorFormatNumberic(const std::string& color);
+};
+
+}  // namespace notification
+}  // namespace extension
+
+#endif /* NOTIFICATION_STATUS_NOTIFICATION_H_ */
diff --git a/webWidgetTCT_device/src/package/package.gyp b/webWidgetTCT_device/src/package/package.gyp
new file mode 100755 (executable)
index 0000000..bd95af3
--- /dev/null
@@ -0,0 +1,35 @@
+{
+  'includes':[
+    '../common/common.gypi',
+  ],
+  'targets': [
+    {
+      'target_name': 'tizen_package',
+      'type': 'loadable_module',
+      'dependencies': [
+        '../common/common.gyp:tizen_common',
+      ],
+      'sources': [
+        'package_api.js',
+        'package_extension.cc',
+        'package_extension.h',
+        'package_instance.cc',
+        'package_instance.h',
+        'package_info_provider.cc',
+        'package_info_provider.h'
+      ],
+      'conditions': [
+        ['tizen == 1', {
+          'variables': {
+            'packages': [
+              'capi-appfw-package-manager',
+              'capi-appfw-app-manager',
+              'pkgmgr-info',
+              'pkgmgr'
+            ]
+          },
+        }],
+      ],
+    },
+  ],
+}
diff --git a/webWidgetTCT_device/src/package/package_api.js b/webWidgetTCT_device/src/package/package_api.js
new file mode 100755 (executable)
index 0000000..58e49b4
--- /dev/null
@@ -0,0 +1,341 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+var validator_ = xwalk.utils.validator;
+var privilege_ = xwalk.utils.privilege;
+var types_ = validator_.Types;
+
+
+var callbackId = 0;
+var callbacks = {};
+var infoEventListenerId = -1;
+
+function invokeListener(result) {
+  if (result.listener === 'infoEvent') {
+    var listener = callbacks[infoEventListenerId];
+    listener(result);
+  }
+}
+
+extension.setMessageListener(function(json) {
+  var result = JSON.parse(json);
+
+  if (result.hasOwnProperty('listener')) {
+    invokeListener(result);
+  } else {
+    var callback = callbacks[result['callbackId']];
+    callback(result);
+  }
+});
+
+function nextCallbackId() {
+  return callbackId++;
+}
+
+function callNative(cmd, args) {
+  var json = {'cmd': cmd, 'args': args};
+  var argjson = JSON.stringify(json);
+  var resultString = extension.internal.sendSyncMessage(argjson);
+  var result = JSON.parse(resultString);
+
+  if (typeof result !== 'object') {
+    throw new WebAPIException(WebAPIException.UNKNOWN_ERR);
+  }
+
+  if (result['status'] == 'success') {
+    if (undefined !== result['result']) {
+      return result['result'];
+    }
+    return true;
+  } else if (result['status'] == 'error') {
+    var err = result['error'];
+    if (err) {
+      throw new WebAPIException(err);
+    }
+    return false;
+  }
+}
+
+function callNativeWithCallback(cmd, args, callback) {
+  if (callback) {
+    var id = nextCallbackId();
+    args['callbackId'] = id;
+    callbacks[id] = callback;
+  }
+
+  return callNative(cmd, args);
+}
+
+function SetReadOnlyProperty(obj, n, v) {
+  if (arguments.length > 2)
+    Object.defineProperty(
+        obj, n, {value: v, writable: false, enumerable: true, configurable: true});
+  else
+    Object.defineProperty(obj, n, {writable: false, enumerable: true, configurable: true});
+}
+
+function PackageInformation(obj) {
+  var lastModified = obj.lastModified;
+  obj.lastModified = new Date(lastModified);
+
+  SetReadOnlyProperty(this, 'id', obj.id); // read only property
+  SetReadOnlyProperty(this, 'name', obj.name); // read only property
+  SetReadOnlyProperty(this, 'iconPath', obj.iconPath); // read only property
+  SetReadOnlyProperty(this, 'version', obj.version); // read only property
+  SetReadOnlyProperty(this, 'lastModified', obj.lastModified); // read only property
+  SetReadOnlyProperty(this, 'author', obj.author); // read only property
+  SetReadOnlyProperty(this, 'description', obj.description); // read only property
+  SetReadOnlyProperty(this, 'appIds', obj.appIds); // read only property
+
+  var totalSize;
+  var dataSize;
+
+  Object.defineProperty(this, 'totalSize', {
+    enumerable: true,
+    set: function() {},
+    get: function() {
+      if (undefined === totalSize) {
+        try {
+          totalSize = callNative('PackageManager_getTotalSize', {id: this.id});
+        } catch (e) {
+          totalSize = -1;
+        }
+      }
+      return totalSize;
+    }
+  });
+
+  Object.defineProperty(this, 'dataSize', {
+    enumerable: true,
+    set: function() {},
+    get: function() {
+      if (undefined === dataSize) {
+        try {
+          dataSize = callNative('PackageManager_getDataSize', {id: this.id});
+        } catch (e) {
+          dataSize = -1;
+        }
+      }
+      return dataSize;
+    }
+  });
+}
+
+function PackageManager() {
+  // constructor of PackageManager
+}
+
+
+PackageManager.prototype.install = function(packageFileURI, progressCallback) {
+  xwalk.utils.checkPrivilegeAccess(privilege_.PACKAGEMANAGER_INSTALL);
+
+  var args = validator_.validateArgs(arguments, [
+    {'name' : 'packageFileURI', 'type' : types_.STRING},
+    {'name' : 'progressCallback',
+      'type' : types_.LISTENER,
+      'values' : ['onprogress', 'oncomplete']},
+    {'name' : 'errorCallback', 'type' : types_.FUNCTION, 'optional' : true, 'nullable' : true}
+  ]);
+
+  var nativeParam = {
+    'packageFileURI': args.packageFileURI
+  };
+
+  try {
+    var syncResult = callNativeWithCallback(
+        'PackageManager_install',
+        nativeParam,
+        function(result) {
+          if (result.status == 'progress') {
+            args.progressCallback.onprogress(result.id, result.progress);
+          } else if (result.status == 'complete') {
+            args.progressCallback.oncomplete(result.id);
+          } else if (result.status == 'error') {
+            var err = result['error'];
+            if (err) {
+              args.errorCallback(new WebAPIException(err));
+              return;
+            }
+          }
+
+          if (result.status == 'complete' || result.status == 'error') {
+            delete callbacks[result['callbackId']];
+          }
+        });
+  } catch (e) {
+    throw e;
+  }
+};
+
+PackageManager.prototype.uninstall = function(id, progressCallback) {
+  xwalk.utils.checkPrivilegeAccess(privilege_.PACKAGEMANAGER_INSTALL);
+
+  var args = validator_.validateArgs(arguments, [
+    {'name' : 'id', 'type' : types_.STRING},
+    {'name' : 'progressCallback',
+      'type' : types_.LISTENER,
+      'values' : ['onprogress', 'oncomplete']},
+    {'name' : 'errorCallback', 'type' : types_.FUNCTION, 'optional' : true, 'nullable' : true}
+  ]);
+
+  var nativeParam = {
+    'id': args.id
+  };
+
+  try {
+    var syncResult = callNativeWithCallback(
+        'PackageManager_uninstall',
+        nativeParam,
+        function(result) {
+          if (result.status == 'progress') {
+            args.progressCallback.onprogress(result.id, result.progress);
+          } else if (result.status == 'complete') {
+            args.progressCallback.oncomplete(result.id);
+          } else if (result.status == 'error') {
+            var err = result['error'];
+            if (err) {
+              args.errorCallback(new WebAPIException(err));
+              return;
+            }
+          }
+
+          if (result.status == 'complete' || result.status == 'error') {
+            delete callbacks[result['callbackId']];
+          }
+        });
+  } catch (e) {
+    throw e;
+  }
+
+};
+
+PackageManager.prototype.getPackagesInfo = function(successCallback, errorCallback) {
+  xwalk.utils.checkPrivilegeAccess(privilege_.PACKAGE_INFO);
+
+  var args = validator_.validateArgs(arguments, [
+    {'name' : 'successCallback', 'type' : types_.FUNCTION},
+    {'name' : 'errorCallback', 'type' : types_.FUNCTION, 'optional' : true, 'nullable' : true}
+  ]);
+
+  var nativeParam = {
+  };
+
+  try {
+    var syncMsg = callNativeWithCallback(
+        'PackageManager_getPackagesInfo',
+        nativeParam,
+        function(result) {
+          if (result.status == 'success') {
+            for (var i = 0; i < result.informationArray.length; i++) {
+              result.informationArray[i] = new PackageInformation(result.informationArray[i]);
+            }
+            args.successCallback(result.informationArray);
+          } else if (result.status == 'error') {
+            var err = result['error'];
+            if (err) {
+              args.errorCallback(new tizen.WebAPIError(err.name, err.message));
+              return;
+            }
+          }
+
+          delete callbacks[result['callbackId']];
+        });
+  } catch (e) {
+    throw e;
+  }
+};
+
+PackageManager.prototype.getPackageInfo = function() {
+  xwalk.utils.checkPrivilegeAccess(privilege_.PACKAGE_INFO);
+
+  var args = validator_.validateArgs(arguments, [
+    {'name': 'id', 'type': types_.STRING, 'optional' : true, 'nullable' : true}
+  ]);
+
+  var nativeParam = {
+  };
+
+  if (args['id']) {
+    nativeParam['id'] = args.id;
+  }
+
+  try {
+    var syncResult = callNative('PackageManager_getPackageInfo', nativeParam);
+    return new PackageInformation(syncResult);
+  } catch (e) {
+    throw e;
+  }
+};
+
+PackageManager.prototype.setPackageInfoEventListener = function(eventCallback) {
+  xwalk.utils.checkPrivilegeAccess(privilege_.PACKAGE_INFO);
+
+  var args = validator_.validateArgs(
+      arguments,
+      [
+        {'name' : 'eventCallback',
+          'type' : types_.LISTENER,
+          'values' : ['oninstalled', 'onupdated', 'onuninstalled']}
+      ]);
+
+  var nativeParam = {
+  };
+
+  try {
+    var syncResult = callNativeWithCallback(
+        'PackageManager_setPackageInfoEventListener',
+        nativeParam,
+        function(result) {
+          if (result.status == 'installed') {
+            args.eventCallback.oninstalled(new PackageInformation(result.info));
+          } else if (result.status == 'updated') {
+            args.eventCallback.onupdated(new PackageInformation(result.info));
+          } else if (result.status == 'uninstalled') {
+            args.eventCallback.onuninstalled(result.id);
+          }
+        });
+
+    if (infoEventListenerId === -1) {
+      infoEventListenerId = nativeParam.callbackId;
+    } else {
+      delete callbacks[infoEventListenerId];
+      infoEventListenerId = nativeParam.callbackId;
+    }
+
+  } catch (e) {
+    throw e;
+  }
+};
+
+PackageManager.prototype.unsetPackageInfoEventListener = function() {
+  xwalk.utils.checkPrivilegeAccess(privilege_.PACKAGE_INFO);
+
+  var nativeParam = {
+  };
+
+  try {
+    var syncResult = callNative('PackageManager_unsetPackageInfoEventListener', nativeParam);
+    if (syncResult === true) {
+      delete callbacks[infoEventListenerId];
+      infoEventListenerId = -1;
+    }
+  } catch (e) {
+    throw e;
+  }
+};
+
+exports = new PackageManager();
+
diff --git a/webWidgetTCT_device/src/package/package_extension.cc b/webWidgetTCT_device/src/package/package_extension.cc
new file mode 100755 (executable)
index 0000000..578b404
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2015 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 "package/package_extension.h"
+
+#include "package/package_instance.h"
+#include "common/logger.h"
+
+// This will be generated from package_api.js
+extern const char kSource_package_api[];
+
+common::Extension* CreateExtension() {
+  LoggerD("Enter");
+  return new PackageExtension;
+}
+
+PackageExtension::PackageExtension() {
+  LoggerD("Enter");
+  SetExtensionName("tizen.package");
+  SetJavaScriptAPI(kSource_package_api);
+}
+
+PackageExtension::~PackageExtension() {
+  LoggerD("Enter");
+}
+
+common::Instance* PackageExtension::CreateInstance() {
+  LoggerD("Enter");
+  return new extension::package::PackageInstance;
+}
diff --git a/webWidgetTCT_device/src/package/package_extension.h b/webWidgetTCT_device/src/package/package_extension.h
new file mode 100755 (executable)
index 0000000..ed3cc43
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2015 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 PACKAGE_PACKAGE_EXTENSION_H_
+#define PACKAGE_PACKAGE_EXTENSION_H_
+
+#include "common/extension.h"
+
+class PackageExtension : public common::Extension {
+ public:
+  PackageExtension();
+  virtual ~PackageExtension();
+
+ private:
+  virtual common::Instance* CreateInstance();
+};
+
+#endif  // PACKAGE_PACKAGE_EXTENSION_H_
diff --git a/webWidgetTCT_device/src/package/package_info_provider.cc b/webWidgetTCT_device/src/package/package_info_provider.cc
new file mode 100755 (executable)
index 0000000..986a26b
--- /dev/null
@@ -0,0 +1,310 @@
+/*
+ * Copyright (c) 2015 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 "package/package_info_provider.h"
+
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <time.h>
+#include <app_manager.h>
+#include <package_manager.h>
+#include <package-manager.h>
+
+#include <functional>
+
+#include "common/logger.h"
+#include "common/tools.h"
+
+namespace extension {
+namespace package {
+
+using common::UnknownException;
+using common::NotFoundException;
+
+using common::ErrorCode;
+using common::PlatformResult;
+using common::tools::ReportError;
+using common::tools::ReportSuccess;
+
+#define REPORT_ERROR(out, exception) \
+  out["status"] = picojson::value("error"); \
+  out["error"] = exception.ToJSON();
+
+static int PackageInfoGetListCb(
+    const pkgmgrinfo_pkginfo_h info, void *user_data) {
+  LoggerD("Enter");
+
+  picojson::array* array_data = static_cast<picojson::array*>(user_data);
+  if ( !array_data ) {
+    LoggerE("user_data is NULL");
+    return PMINFO_R_ERROR;
+  }
+
+  picojson::object object_info;
+  if ( PackageInfoProvider::ConvertToPackageToObject(
+      info, object_info) ) {
+    array_data->push_back(picojson::value(object_info));
+  }
+
+  return PMINFO_R_OK;
+}
+
+void PackageInfoProvider::GetPackagesInfo(
+    picojson::object& out) {
+  LoggerD("Enter");
+
+  clock_t start_time, end_time;
+  start_time = clock();
+
+  picojson::array array_data;
+  int ret = pkgmgrinfo_pkginfo_get_list(PackageInfoGetListCb, &array_data);
+  if (ret != PMINFO_R_OK) {
+    LoggerE("Failed to get package information: %d (%s)", ret, get_error_message(ret));
+    REPORT_ERROR(out, UnknownException("Any other platform error occurs"));
+    return;
+  }
+
+  end_time = clock();
+  LoggerD(">>>>>>>>>>>>>>> GetPackagesInfo Time : %f s\n",
+      (static_cast<double>(end_time-start_time)) / CLOCKS_PER_SEC);
+
+  LoggerD("status: success");
+  out["status"] = picojson::value("success");
+  out["informationArray"] = picojson::value(array_data);
+}
+
+void PackageInfoProvider::GetPackageInfo(picojson::object& out) {
+  LoggerD("Enter");
+
+  char* package_id = NULL;
+  if ( GetCurrentPackageId(&package_id) ) {
+    GetPackageInfo(package_id, out);
+    free(package_id);
+  } else {
+    LoggerE("Failed to get current package ID");
+    REPORT_ERROR(out, NotFoundException("The package with the specified ID is not found"));
+  }
+}
+
+void PackageInfoProvider::GetPackageInfo(
+    const char* package_id, picojson::object& out) {
+  LoggerD("Enter");
+
+  if ( strlen(package_id) <= 0 ) {
+    LoggerE("Wrong Package ID");
+    REPORT_ERROR(out, NotFoundException("The package with the specified ID is not found"));
+    return;
+  }
+
+  pkgmgrinfo_pkginfo_h info;
+  int ret = pkgmgrinfo_pkginfo_get_pkginfo(package_id, &info);
+  if (ret != PMINFO_R_OK) {
+    LoggerE("Failed to get pkginfo: %d (%s)", ret, get_error_message(ret));
+    REPORT_ERROR(out, NotFoundException("The package with the specified ID is not found"));
+    return;
+  }
+
+  picojson::object object_info;
+  if ( !ConvertToPackageToObject(info, object_info) ) {
+    LoggerE("Failed to convert pkginfo to object");
+    REPORT_ERROR(out, UnknownException(
+        "The package information cannot be retrieved " \
+        "because of a platform error"));
+    return;
+  }
+
+  pkgmgrinfo_pkginfo_destroy_pkginfo(info);
+  out["status"] = picojson::value("success");
+  out["result"] = picojson::value(object_info);
+}
+
+static bool PackageAppInfoCb(
+    package_info_app_component_type_e comp_type,
+    const char *app_id,
+    void *user_data) {
+  LoggerD("Enter");
+
+  picojson::array* array_data =
+      static_cast<picojson::array*>(user_data);
+  if ( !array_data ) {
+    LoggerE("user_data is NULL");
+    return false;
+  }
+
+  array_data->push_back(picojson::value(app_id));
+  return true;
+}
+
+bool PackageInfoProvider:: ConvertToPackageToObject(
+    const pkgmgrinfo_pkginfo_h info, picojson::object& out) {
+  int ret = 0;
+
+  char* id = NULL;
+  ret = pkgmgrinfo_pkginfo_get_pkgid(info, &id);
+  if ( (ret != PMINFO_R_OK) || (id == NULL) ) {
+    LoggerE("Failed to get package id: %d (%s)", ret, get_error_message(ret));
+    return false;
+  }
+  out["id"] = picojson::value(id);
+
+  char* name = NULL;
+  ret = pkgmgrinfo_pkginfo_get_label(info, &name);
+  if ( (ret != PMINFO_R_OK) || (name == NULL) ) {
+    LoggerE("[%s] Failed to get package name: %d (%s)", id, ret, get_error_message(ret));
+    return false;
+  }
+  out["name"] = picojson::value(name);
+
+  char* iconPath = NULL;
+  ret = pkgmgrinfo_pkginfo_get_icon(info, &iconPath);
+  if ( (ret != PMINFO_R_OK) || (iconPath == NULL) ) {
+    LoggerE("[%s] Failed to get package iconPath: %d (%s)", id, ret, get_error_message(ret));
+    return false;
+  }
+  out["iconPath"] = picojson::value(iconPath);
+
+  char* version = NULL;
+  ret = pkgmgrinfo_pkginfo_get_version(info, &version);
+  if ( (ret != PMINFO_R_OK) || (version == NULL) ) {
+    LoggerE("[%s] Failed to get package version: %d (%s)", id, ret, get_error_message(ret));
+    return false;
+  }
+  out["version"] = picojson::value(version);
+
+  int lastModified = 0;
+  ret = pkgmgrinfo_pkginfo_get_installed_time(info, &lastModified);
+  if ( (ret != PMINFO_R_OK) ) {
+    LoggerE("[%s] Failed to get package lastModified: %d (%s)", id, ret, get_error_message(ret));
+    return false;
+  }
+  // This value will be converted into JavaScript Date object
+  double lastModified_double = lastModified * 1000.0;
+  out["lastModified"] = picojson::value(lastModified_double);
+
+  char* author = NULL;
+  ret = pkgmgrinfo_pkginfo_get_author_name(info, &author);
+  if ( (ret != PMINFO_R_OK) || (author == NULL) ) {
+    LoggerE("[%s] Failed to get package author: %d (%s)", id, ret, get_error_message(ret));
+    return false;
+  }
+  out["author"] = picojson::value(author);
+
+  char* description = NULL;
+  ret = pkgmgrinfo_pkginfo_get_description(info, &description);
+  if ( (ret != PMINFO_R_OK) || (description == NULL) ) {
+    LoggerE("[%s] Failed to get package description: %d (%s)", id, ret, get_error_message(ret));
+    return false;
+  }
+  out["description"] = picojson::value(description);
+
+  package_info_h package_info;
+  ret = package_info_create(id, &package_info);
+  if ( ret != PACKAGE_MANAGER_ERROR_NONE ) {
+    LoggerE("Failed to create package info: %d (%s)", ret, get_error_message(ret));
+    return false;
+  }
+
+  picojson::array array_data;
+  ret = package_info_foreach_app_from_package(package_info,
+      PACKAGE_INFO_ALLAPP, PackageAppInfoCb, &array_data);
+  if ( ret != PACKAGE_MANAGER_ERROR_NONE ) {
+    LoggerE("Failed to get app info: %d (%s)", ret, get_error_message(ret));
+    ret = package_info_destroy(package_info);
+    return false;
+  }
+  out["appIds"] = picojson::value(array_data);
+
+  ret = package_info_destroy(package_info);
+  if ( ret != PACKAGE_MANAGER_ERROR_NONE ) {
+    LoggerE("Failed to destroy package info: %d (%s)", ret, get_error_message(ret));
+  }
+
+  return true;
+}
+
+namespace {
+
+void GetSize(const std::string& id, int service_mode, picojson::object* out) {
+  LoggerD("Enter");
+  pkgmgr_client* pc = pkgmgr_client_new(PC_REQUEST);
+  int size = pkgmgr_client_request_service(PM_REQUEST_GET_SIZE, service_mode,
+                                           pc,
+                                           NULL,
+                                           id.c_str(), NULL, NULL, NULL);
+  pkgmgr_client_free(pc);
+
+  if (size < 0) {
+    LoggerE("Request service failed: %d (%s)", size, get_error_message(size));
+    ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get size"),
+                out);
+  } else {
+    ReportSuccess(picojson::value(static_cast<double>(size)), *out);
+  }
+}
+
+}  // namespace
+
+void PackageInfoProvider::GetTotalSize(const std::string& id,
+                                       picojson::object* out) {
+  LoggerD("Enter");
+  GetSize(id, PM_GET_TOTAL_SIZE, out);
+}
+
+void PackageInfoProvider::GetDataSize(const std::string& id,
+                                      picojson::object* out) {
+  LoggerD("Enter");
+  GetSize(id, PM_GET_DATA_SIZE, out);
+}
+
+bool PackageInfoProvider::GetCurrentPackageId(
+    char** package_id) {
+  LoggerD("Enter");
+
+  int ret = 0;
+  char *app_id = NULL;
+
+  int pid = getpid();
+  ret = app_manager_get_app_id(pid, &app_id);
+  if ( ret != APP_MANAGER_ERROR_NONE ) {
+    LoggerE("Failed to get app id: %d (%s)", ret, get_error_message(ret));
+    return false;
+  }
+
+  app_info_h handle;
+  ret = app_info_create(app_id, &handle);
+  free(app_id);
+  if ( ret != APP_MANAGER_ERROR_NONE ) {
+    LoggerE("Fail to get app info: %d (%s)", ret, get_error_message(ret));
+    return false;
+  }
+
+  ret = app_info_get_package(handle, package_id);
+  app_info_destroy(handle);
+  if ( (ret != APP_MANAGER_ERROR_NONE) || (*package_id == NULL) ) {
+    LoggerE("Fail to get pkg id: %d (%s)", ret, get_error_message(ret));
+    return false;
+  }
+
+  return true;
+}
+
+
+
+#undef REPORT_ERROR
+
+}  // namespace package
+}  // namespace extension
diff --git a/webWidgetTCT_device/src/package/package_info_provider.h b/webWidgetTCT_device/src/package/package_info_provider.h
new file mode 100755 (executable)
index 0000000..e08cfee
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2015 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 PACKAGE_PACKAGE_INFO_PROVIDER_H_
+#define PACKAGE_PACKAGE_INFO_PROVIDER_H_
+
+#include <pkgmgr-info.h>
+
+#include "common/extension.h"
+#include "common/picojson.h"
+#include "common/platform_exception.h"
+
+namespace extension {
+namespace package {
+
+class PackageInfoProvider {
+ public:
+  PackageInfoProvider();
+  virtual ~PackageInfoProvider();
+
+  /* out["status"] = "success" or "error"
+  * If status is "success", then the result(picojson::value)
+  * will be stored in out["informationArray"].
+  * If status is "error", then the error(picojson::value)
+  * will be stored in out["error"].
+  */
+  static void GetPackagesInfo(picojson::object& out);
+
+  /* out["status"] = "success" or "error"
+  * If status is "success", then the result(picojson::value)
+  * will be stored in out["result"].
+  * If status is "error", then the error(picojson::value)
+  * will be stored in out["error"].
+  */
+  static void GetPackageInfo(picojson::object& out);
+  static void GetPackageInfo(const char* package_id,
+      picojson::object& out);
+
+  static bool ConvertToPackageToObject(
+      const pkgmgrinfo_pkginfo_h info, picojson::object& out);
+
+  static void GetTotalSize(const std::string& id, picojson::object* out);
+  static void GetDataSize(const std::string& id, picojson::object* out);
+
+ private:
+  static bool GetCurrentPackageId(char** package_id);
+};
+
+}  // namespace package
+}  // namespace extension
+
+#endif  // PACKAGE_PACKAGE_INFO_PROVIDER_H_
diff --git a/webWidgetTCT_device/src/package/package_instance.cc b/webWidgetTCT_device/src/package/package_instance.cc
new file mode 100755 (executable)
index 0000000..6df9b3e
--- /dev/null
@@ -0,0 +1,523 @@
+/*
+ * Copyright (c) 2015 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 "package/package_instance.h"
+
+#include <functional>
+#include <string>
+
+#include "package/package_info_provider.h"
+#include "common/logger.h"
+#include "common/task-queue.h"
+#include "common/picojson.h"
+
+namespace extension {
+namespace package {
+
+using common::TaskQueue;
+using common::PlatformException;
+using common::UnknownException;
+using common::NotFoundException;
+using common::TypeMismatchException;
+using common::SecurityException;
+
+using common::ErrorCode;
+using common::PlatformResult;
+
+typedef enum _PackageThreadWorkType {
+  PackageThreadWorkNone = 0,
+  PackageThreadWorkGetPackagesInfo,
+} PackageThreadWorkType;
+
+class PackageUserData {
+ public:
+  PackageUserData(PackageInstance* ins,
+      int id,
+      PackageThreadWorkType task) {
+    instance_ = ins;
+    callback_id_ = id;
+    work_ = task;
+  }
+
+  PackageInstance* instance_;
+  int callback_id_;
+  PackageThreadWorkType work_;
+  picojson::object data_;
+};
+typedef std::shared_ptr<PackageUserData> PackageUserDataPtr;
+
+static void* PackageThreadWork(
+    const PackageUserDataPtr& userData) {
+  LoggerD("Enter");
+
+  switch ( userData->work_ ) {
+    case PackageThreadWorkGetPackagesInfo: {
+      picojson::object output;
+      PackageInfoProvider::GetPackagesInfo(output);
+      userData->data_ = output;
+      break;
+    }
+    default: {
+      LoggerE("Invalid Callback Type");
+    }
+  }
+
+  return NULL;
+}
+
+static gboolean PackageAfterWork(
+    const PackageUserDataPtr& userData) {
+  LoggerD("Enter");
+
+  userData->data_["callbackId"] =
+      picojson::value(static_cast<double>(userData->callback_id_));
+  picojson::value result = picojson::value(userData->data_);
+  common::Instance::PostMessage(userData->instance_, result.serialize().c_str());
+
+  return FALSE;
+}
+
+static void PackageRequestCb(
+    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) {
+  LoggerD("Enter");
+
+  PackageInstance* instance = static_cast<PackageInstance*>(user_data);
+  if ( !instance ) {
+    LoggerE("instance is NULL");
+    return;
+  }
+
+  picojson::object param;
+  LoggerD("Request type: %d, state: %d, progress: %d", event_type, event_state, progress);
+  if (PACKAGE_MANAGER_EVENT_STATE_FAILED == event_state) {
+    LoggerE("[Failed]");
+    param["status"] = picojson::value("error");
+    param["error"] = UnknownException(
+        "It is not allowed to install the package by the platform or " \
+        "any other platform error occurs").ToJSON();
+  } else if (PACKAGE_MANAGER_EVENT_STATE_STARTED == event_state ||
+      PACKAGE_MANAGER_EVENT_STATE_PROCESSING == event_state) {
+    // this 'or' condition is needed to handle onprogress callback even on uninstall process,
+    // with this additional check manual TCT uninstall/onprogress pass
+    param["status"] = picojson::value("progress");
+    param["progress"] = picojson::value(static_cast<double>(progress));
+    param["id"] = picojson::value(std::string(package));
+  } else if (PACKAGE_MANAGER_EVENT_STATE_COMPLETED == event_state) {
+    param["status"] = picojson::value("complete");
+    param["id"] = picojson::value(std::string(package));
+  }
+
+  instance->InvokeCallback(id, param);
+  if ( event_state == PACKAGE_MANAGER_EVENT_STATE_COMPLETED
+      || event_state == PACKAGE_MANAGER_EVENT_STATE_FAILED ) {
+    LoggerD("Request has been completed");
+    instance->DeregisterCallback(id);
+  }
+}
+
+static void PackageListenerCb(
+    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) {
+  LoggerD("Enter");
+
+  PackageInstance* instance = static_cast<PackageInstance*>(user_data);
+  if ( !instance ) {
+    LoggerE("instance is NULL");
+    return;
+  }
+
+  if ( error != PACKAGE_MANAGER_ERROR_NONE ) {
+    LoggerE("Failed");
+    return;
+  }
+
+  picojson::object param;
+  param["listener"] = picojson::value("infoEvent");
+
+  LoggerD("Listener type: %d , state: %d, progress: %d",
+          event_type, event_state, progress);
+  if ( event_type == PACKAGE_MANAGER_EVENT_TYPE_INSTALL
+      && event_state == PACKAGE_MANAGER_EVENT_STATE_COMPLETED ) {
+    LoggerD("[Installed]");
+    param["status"] = picojson::value("installed");
+    picojson::object info;
+    PackageInfoProvider::GetPackageInfo(package, info);
+    param["info"] = picojson::value(info["result"]);
+    instance->InvokeListener(param);
+  } else if ( event_type == PACKAGE_MANAGER_EVENT_TYPE_UNINSTALL
+      && event_state == PACKAGE_MANAGER_EVENT_STATE_COMPLETED ) {
+    LoggerD("[Uninstalled]");
+    param["status"] = picojson::value("uninstalled");
+    param["id"] = picojson::value(std::string(package));
+    instance->InvokeListener(param);
+  } else if ( event_type == PACKAGE_MANAGER_EVENT_TYPE_UPDATE
+      && event_state == PACKAGE_MANAGER_EVENT_STATE_COMPLETED ) {
+    LoggerD("[Updated]");
+    param["status"] = picojson::value("updated");
+    picojson::object info;
+    PackageInfoProvider::GetPackageInfo(package, info);
+    param["info"] = picojson::value(info["result"]);
+    instance->InvokeListener(param);
+  }
+}
+
+static std::string 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;
+}
+
+static std::string convertUriToPath(const std::string& uri) {
+    std::string result;
+    std::string schema("file://");
+    std::string str = ltrim(uri);
+
+    std::string _schema = str.substr(0, schema.size());
+    if ( _schema == schema ) {
+        result = str.substr(schema.size());
+    } else {
+        result = str;
+    }
+
+    return result;
+}
+
+PackageInstance::PackageInstance() {
+  LoggerD("Enter");
+
+  int ret = package_manager_request_create(&request_);
+  if (ret != PACKAGE_MANAGER_ERROR_NONE) {
+    LoggerE("Failed to created package manager request: %d (%s)", ret, get_error_message(ret));
+    request_ = NULL;
+  }
+
+  ret = package_manager_request_set_event_cb(request_, PackageRequestCb,
+      static_cast<void*>(this));
+  if (ret != PACKAGE_MANAGER_ERROR_NONE) {
+    LoggerE("Failed to set request event callback: %d (%s)", ret, get_error_message(ret));
+  }
+
+  ret = package_manager_create(&manager_);
+  if (ret != PACKAGE_MANAGER_ERROR_NONE) {
+    LoggerE("Failed to created package manager: %d (%s)", ret, get_error_message(ret));
+    manager_ = NULL;
+  }
+
+  is_package_info_listener_set_ = false;
+
+  using std::placeholders::_1;
+  using std::placeholders::_2;
+  #define REGISTER_SYNC(c, x) \
+    RegisterSyncHandler(c, std::bind(&PackageInstance::x, this, _1, _2));
+  REGISTER_SYNC("PackageManager_setPackageInfoEventListener",
+      PackageManagerSetpackageinfoeventlistener);
+  REGISTER_SYNC("PackageManager_install",
+      PackageManagerInstall);
+  REGISTER_SYNC("PackageManager_getPackagesInfo",
+      PackageManagerGetpackagesinfo);
+  REGISTER_SYNC("PackageManager_uninstall",
+      PackageManagerUninstall);
+  REGISTER_SYNC("PackageManager_unsetPackageInfoEventListener",
+      PackageManagerUnsetpackageinfoeventlistener);
+  REGISTER_SYNC("PackageManager_getPackageInfo",
+      PackageManagerGetpackageinfo);
+  REGISTER_SYNC("PackageManager_getTotalSize",
+      PackageManagerGetTotalSize);
+  REGISTER_SYNC("PackageManager_getDataSize",
+      PackageManagerGetDataSize);
+  #undef REGISTER_SYNC
+}
+
+PackageInstance::~PackageInstance() {
+  LoggerD("Enter");
+  package_manager_request_unset_event_cb(request_);
+  package_manager_request_destroy(request_);
+  package_manager_destroy(manager_);
+}
+
+#define CHECK_EXIST(args, name, out) \
+    if (  !args.contains(name) ) {\
+      ReportError(TypeMismatchException(name" is required argument"), out);\
+      return;\
+    }
+
+void PackageInstance::RegisterCallback(
+    int request_id, int callback_id) {
+  LoggerD("Enter");
+  callbacks_map_[request_id] = callback_id;
+}
+
+void PackageInstance::DeregisterCallback(int request_id) {
+  LoggerD("Enter");
+  callbacks_map_.erase(request_id);
+}
+
+void PackageInstance::InvokeCallback(
+    int request_id, picojson::object& param) {
+  LoggerD("Enter");
+
+  int callback_id = callbacks_map_[request_id];
+
+  param["callbackId"] = picojson::value(
+      static_cast<double>(callback_id));
+  picojson::value result = picojson::value(param);
+  Instance::PostMessage(this, result.serialize().c_str());
+}
+
+void PackageInstance::PackageManagerInstall(
+    const picojson::value& args, picojson::object& out) {
+  LoggerD("Enter");
+
+  CHECK_EXIST(args, "callbackId", out)
+  CHECK_EXIST(args, "packageFileURI", out)
+
+  int callback_id = static_cast<int>(
+      args.get("callbackId").get<double>());
+  const std::string& packageFileURI =
+      convertUriToPath(args.get("packageFileURI").get<std::string>());
+
+  if ( !request_ ) {
+    LoggerE("package_manager_request_h is NULL");
+    InvokeErrorCallbackAsync(callback_id,
+      UnknownException("It is not allowed to install the package by " \
+          "the platform or any other platform error occurs"));
+    return;
+  }
+
+  int request_id = 0;
+  int ret = package_manager_request_install(
+      request_, packageFileURI.c_str(), &request_id);
+  if ( ret != PACKAGE_MANAGER_ERROR_NONE ) {
+    if ( ret == PACKAGE_MANAGER_ERROR_INVALID_PARAMETER ) {
+      LoggerE("The package is not found at the specified location");
+      InvokeErrorCallbackAsync(callback_id,
+          NotFoundException(
+          "The package is not found at the specified location"));
+    } else {
+      LoggerE("Failed to install package: %d (%s)", ret, get_error_message(ret));
+      InvokeErrorCallbackAsync(callback_id,
+          UnknownException("It is not allowed to install the package by " \
+          "the platform or any other platform error occurs"));
+    }
+  } else {
+    RegisterCallback(request_id, callback_id);
+  }
+
+  ReportSuccess(out);
+}
+
+void PackageInstance::PackageManagerUninstall(
+    const picojson::value& args, picojson::object& out) {
+  LoggerD("Enter");
+
+  CHECK_EXIST(args, "callbackId", out)
+  CHECK_EXIST(args, "id", out)
+
+  int callback_id =
+      static_cast<int>(args.get("callbackId").get<double>());
+  const std::string& id = args.get("id").get<std::string>();
+
+  if ( !request_ ) {
+    LoggerE("package_manager_request_h is NULL");
+    InvokeErrorCallbackAsync(callback_id,
+        UnknownException("It is not allowed to install the package by " \
+        "the platform or any other platform error occurs"));
+    return;
+  }
+
+  int request_id = 0;
+  int ret = package_manager_request_uninstall(request_, id.c_str(), &request_id);
+  if ( ret != PACKAGE_MANAGER_ERROR_NONE ) {
+    if ( ret == PACKAGE_MANAGER_ERROR_INVALID_PARAMETER ) {
+      LoggerE("The package is not found at the specified location");
+      InvokeErrorCallbackAsync(callback_id,
+        NotFoundException(
+            "The package is not found at the specified location"));
+    } else {
+      LoggerE("Failed to uninstall package: %d (%s)", ret, get_error_message(ret));
+      InvokeErrorCallbackAsync(callback_id, UnknownException(
+          "It is not allowed to install the package by the platform or " \
+          "any other platform error occurs"));
+    }
+  } else {
+    RegisterCallback(request_id, callback_id);
+  }
+
+  ReportSuccess(out);
+}
+void PackageInstance::PackageManagerGetpackagesinfo(
+    const picojson::value& args, picojson::object& out) {
+  LoggerD("Enter");
+
+  CHECK_EXIST(args, "callbackId", out)
+  int callback_id =
+      static_cast<int>(args.get("callbackId").get<double>());
+
+  PackageUserDataPtr userData(new PackageUserData(
+      this, callback_id, PackageThreadWorkGetPackagesInfo));
+  TaskQueue::GetInstance().Queue<PackageUserData>(
+      PackageThreadWork, PackageAfterWork, userData);
+  ReportSuccess(out);
+}
+void PackageInstance::PackageManagerGetpackageinfo(
+    const picojson::value& args, picojson::object& out) {
+  LoggerD("Enter");
+
+  if ( args.contains("id") ) {
+    std::string id = args.get("id").get<std::string>();
+    PackageInfoProvider::GetPackageInfo(id.c_str(), out);
+  } else {
+    PackageInfoProvider::GetPackageInfo(out);
+  }
+}
+
+void PackageInstance::PackageManagerGetTotalSize(const picojson::value& args,
+                                                 picojson::object& out) {
+  LoggerD("Enter");
+
+  const auto& id = args.get("id");
+
+  if (id.is<std::string>()) {
+    PackageInfoProvider::GetTotalSize(id.get<std::string>(), &out);
+  } else {
+    ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Missing id parameter"),
+                &out);
+  }
+}
+
+void PackageInstance::PackageManagerGetDataSize(const picojson::value& args,
+                                                picojson::object& out) {
+  LoggerD("Enter");
+
+  const auto& id = args.get("id");
+
+  if (id.is<std::string>()) {
+    PackageInfoProvider::GetDataSize(id.get<std::string>(), &out);
+  } else {
+    ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Missing id parameter"),
+                &out);
+  }
+}
+
+void PackageInstance::InvokeListener(picojson::object& param) {
+  LoggerD("Enter");
+  picojson::value result = picojson::value(param);
+  Instance::PostMessage(this, result.serialize().c_str());
+}
+
+void PackageInstance::
+    PackageManagerSetpackageinfoeventlistener(
+    const picojson::value& args, picojson::object& out) {
+  LoggerD("Enter");
+
+  CHECK_EXIST(args, "callbackId", out)
+
+  if ( is_package_info_listener_set_ ) {
+    LoggerD("Already set");
+    ReportSuccess(out);
+    return;
+  }
+
+  if ( !manager_ ) {
+    LoggerE("package_manager_h is NULL");
+    ReportError(
+        UnknownException("The package list change event cannot be " \
+        "generated because of a platform error"),
+        out);
+    return;
+  }
+
+  int ret = package_manager_set_event_cb(
+      manager_, PackageListenerCb, static_cast<void*>(this));
+  if (ret != PACKAGE_MANAGER_ERROR_NONE) {
+    LoggerE("Failed to set event callback: %d (%s)", ret, get_error_message(ret));
+    ReportError(
+        UnknownException("The package list change event cannot be " \
+        "generated because of a platform error"),
+        out);
+    return;
+  }
+
+  is_package_info_listener_set_ = true;
+  ReportSuccess(out);
+}
+
+void PackageInstance::
+    PackageManagerUnsetpackageinfoeventlistener(
+    const picojson::value& args, picojson::object& out) {
+  LoggerD("Enter");
+
+  if ( !is_package_info_listener_set_ ) {
+    LoggerD("Listener is not set");
+    ReportSuccess(out);
+    return;
+  }
+
+  if ( !manager_ ) {
+    LoggerE("package_manager_h is NULL");
+    ReportError(
+        UnknownException("The listener removal request fails" \
+        "because of a platform error"),
+        out);
+    return;
+  }
+
+  int ret = package_manager_unset_event_cb(manager_);
+  if (ret != PACKAGE_MANAGER_ERROR_NONE) {
+    LoggerE("Failed to unset event callback: %d (%s)", ret, get_error_message(ret));
+    ReportError(
+        UnknownException("The listener removal request fails" \
+        "because of a platform error"),
+        out);
+    return;
+  }
+
+  is_package_info_listener_set_ = false;
+  ReportSuccess(out);
+}
+
+void PackageInstance::InvokeErrorCallbackAsync(
+    int callback_id, const PlatformException& ex) {
+  LoggerD("Enter");
+
+  picojson::object param;
+  ReportError(ex, param);
+  PackageUserDataPtr userData(new PackageUserData(
+      this, callback_id, PackageThreadWorkNone));
+  userData->data_ = param;
+  TaskQueue::GetInstance().Async
+    <PackageUserData>(PackageAfterWork, userData);
+}
+
+#undef CHECK_EXIST
+
+}  // namespace package
+}  // namespace extension
diff --git a/webWidgetTCT_device/src/package/package_instance.h b/webWidgetTCT_device/src/package/package_instance.h
new file mode 100755 (executable)
index 0000000..2d22d81
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2015 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 PACKAGE_PACKAGE_INSTANCE_H_
+#define PACKAGE_PACKAGE_INSTANCE_H_
+
+#include <package_manager.h>
+
+#include <map>
+
+#include "common/extension.h"
+#include "common/platform_exception.h"
+
+namespace extension {
+namespace package {
+
+class PackageInstance : public common::ParsedInstance {
+ public:
+  PackageInstance();
+  virtual ~PackageInstance();
+
+  void InvokeCallback(int request_id, picojson::object& param);
+  void InvokeListener(picojson::object& param);
+  void DeregisterCallback(int request_id);
+
+ private:
+  package_manager_request_h request_;
+  package_manager_h manager_;
+  bool is_package_info_listener_set_;
+  std::map<int, int> callbacks_map_;  // <request_id, callbackId>
+
+  void RegisterCallback(int request_id, int callback_id);
+  void InvokeErrorCallbackAsync
+    (int callback_id, const common::PlatformException& ex);
+
+  void PackageManagerInstall
+    (const picojson::value& args, picojson::object& out);
+  void PackageManagerUninstall(
+    const picojson::value& args, picojson::object& out);
+  void PackageManagerGetpackagesinfo
+    (const picojson::value& args, picojson::object& out);
+  void PackageManagerGetpackageinfo
+    (const picojson::value& args, picojson::object& out);
+  void PackageManagerGetTotalSize(const picojson::value& args,
+                                  picojson::object& out);
+  void PackageManagerGetDataSize(const picojson::value& args,
+                                 picojson::object& out);
+  void PackageManagerSetpackageinfoeventlistener
+    (const picojson::value& args, picojson::object& out);
+  void PackageManagerUnsetpackageinfoeventlistener
+    (const picojson::value& args, picojson::object& out);
+};
+
+}  // namespace package
+}  // namespace extension
+
+#endif  // PACKAGE_PACKAGE_INSTANCE_H_
diff --git a/webWidgetTCT_device/src/power/power.gyp b/webWidgetTCT_device/src/power/power.gyp
new file mode 100755 (executable)
index 0000000..8b6c10f
--- /dev/null
@@ -0,0 +1,36 @@
+{
+  'includes':[
+    '../common/common.gypi',
+  ],
+  'targets': [
+    {
+      'target_name': 'tizen_power',
+      'type': 'loadable_module',
+      'dependencies': [
+        '../common/common.gyp:tizen_common',
+      ],
+      'sources': [
+        'power_api.js',
+        'power_extension.cc',
+        'power_extension.h',
+        'power_instance.cc',
+        'power_instance.h',
+        'power_manager.cc',
+        'power_manager.h',
+        'power_platform_proxy.cc',
+        'power_platform_proxy.h'
+      ],
+      'conditions': [
+        ['tizen == 1', {
+          'variables': {
+            'packages': [
+              'capi-system-device',
+              'deviced',
+              'vconf',
+            ]
+          },
+        }],
+      ],
+    },
+  ],
+}
diff --git a/webWidgetTCT_device/src/power/power_api.js b/webWidgetTCT_device/src/power/power_api.js
new file mode 100755 (executable)
index 0000000..bb049c1
--- /dev/null
@@ -0,0 +1,310 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+var validator_ = xwalk.utils.validator;
+var privilege_ = xwalk.utils.privilege;
+var types_ = validator_.Types;
+var native_ = new xwalk.utils.NativeManager(extension);
+
+function ListenerManager(native, listenerName) {
+  this.listener;
+  this.native = native;
+  this.listenerName = listenerName;
+}
+
+ListenerManager.prototype.onListenerCalled = function(msg) {
+  if(this.listener) {
+    this.listener(msg.prev_state, msg.new_state);
+  }
+};
+
+ListenerManager.prototype.addListener = function(callback) {
+  this.native.addListener(this.listenerName, this.onListenerCalled.bind(this));
+  this.listener = callback;
+};
+
+ListenerManager.prototype.removeListener = function() {
+  this.native.removeListener(this.listenerName);
+  delete this.listener;
+};
+
+var screenStateChangeListener = new ListenerManager(native_, "SCREEN_STATE_LISTENER");
+
+function callNative(cmd, args) {
+    var json = {'cmd':cmd, 'args':args};
+    var argjson = JSON.stringify(json);
+    var resultString = extension.internal.sendSyncMessage(argjson);
+    var result = JSON.parse(resultString);
+
+    if (typeof result !== 'object') {
+        throw new WebAPIException(WebAPIException.UNKNOWN_ERR);
+    }
+
+    if (result['status'] == 'success') {
+        if('result' in result) {
+            return result['result'];
+        }
+        return true;
+    } else if (result['status'] == 'error') {
+        var err = result['error'];
+        if(err) {
+            throw new WebAPIException(err);
+        }
+        return false;
+    }
+}
+
+function callNativeWithCallback(cmd, args, callback) {
+    if(callback) {
+        var id = nextCallbackId();
+        args['callbackId'] = id;
+        callbacks[id] = callback;
+    }
+
+    return callNative(cmd, args);
+}
+
+function SetReadOnlyProperty(obj, n, v){
+    Object.defineProperty(obj, n, {value:v, writable: false});
+}
+
+var PowerResource = {
+    'SCREEN': 'SCREEN',
+    'CPU': 'CPU'
+};
+
+/**
+ * An enumerator that indicates the power state for screen resource.
+ * @enum {string}
+ */
+var PowerScreenState = {
+    'SCREEN_OFF': 'SCREEN_OFF',
+    'SCREEN_DIM': 'SCREEN_DIM',
+    'SCREEN_NORMAL': 'SCREEN_NORMAL',
+    'SCREEN_BRIGHT': 'SCREEN_BRIGHT'
+};
+
+/**
+ * An enumerator that indicates the power state for cpu resource.
+ * @enum {string}
+ */
+var PowerCpuState = {
+    'CPU_AWAKE': 'CPU_AWAKE'
+};
+
+/**
+ * This class provides functions to request and release power resource.
+ * @constructor
+ */
+function PowerManager() {
+    // constructor of PowerManager
+}
+
+/**
+ * Requests the minimum-state for a power resource.
+ * @param {!PowerResource} resource The power resource for which the request
+ *     is made.
+ * @param {!PowerState} state The minimal state in which the power resource
+ *     is desired to be.
+ */
+PowerManager.prototype.request = function(resource, state) {
+   xwalk.utils.checkPrivilegeAccess(privilege_.POWER);
+
+   var args = validator_.validateArgs(arguments, [
+        {'name' : 'resource', 'type': types_.ENUM, 'values' : ['SCREEN', 'CPU']},
+        {'name' : 'state', 'type': types_.ENUM, 'values' : ['SCREEN_OFF', 'SCREEN_DIM', 'SCREEN_NORMAL', 'SCREEN_BRIGHT', 'CPU_AWAKE']}
+    ]);
+
+    var nativeParam = {
+    };
+
+    if (args['resource']) {
+        nativeParam['resource'] = args.resource;
+    }
+    if (args['state']) {
+        nativeParam['state'] = args.state;
+    }
+
+    try {
+        var syncResult = callNative('PowerManager_request', nativeParam);
+        // if you need synchronous result from native function using 'syncResult'.
+    } catch(e) {
+        throw e;
+    }
+};
+
+/**
+ * Releases the power state request for the given resource.
+ * @param {!PowerResource} resource The resource for which requests are to
+ *     be removed.
+ */
+PowerManager.prototype.release = function(resource) {
+    var args = validator_.validateArgs(arguments, [
+        {'name' : 'resource', 'type': types_.ENUM, 'values' : ['SCREEN', 'CPU']}
+    ]);
+
+    if (!PowerResource.hasOwnProperty(args.resource))
+        throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR);
+
+    var nativeParam = {
+    };
+    if (args['resource']) {
+        nativeParam['resource'] = args.resource;
+    }
+    try {
+        var syncResult = callNative('PowerManager_release', nativeParam);
+        // if you need synchronous result from native function using 'syncResult'.
+    } catch(e) {
+        throw e;
+    }
+
+};
+
+/**
+ * Sets the screen state change callback and monitors its state changes.
+ * @param {!function} listener The screen state change callback.
+ */
+PowerManager.prototype.setScreenStateChangeListener = function(listener) {
+    var args = validator_.validateArgs(arguments, [
+        {name: 'listener', type: types_.FUNCTION}
+    ]);
+
+    screenStateChangeListener.addListener(args.listener);
+};
+
+/**
+ * Unsets the screen state change callback and stop monitoring it.
+ */
+PowerManager.prototype.unsetScreenStateChangeListener = function() {
+    screenStateChangeListener.removeListener();
+};
+
+/**
+ * Gets the screen brightness level of an application, from 0 to 1.
+ * @return {number} Current screen brightness value.
+ */
+PowerManager.prototype.getScreenBrightness = function() {
+    var nativeParam = {
+    };
+       var syncResult = 0;
+
+    try {
+        syncResult = callNative('PowerManager_getScreenBrightness', nativeParam);
+        // if you need synchronous result from native function using 'syncResult'.
+    } catch(e) {
+        throw e;
+    }
+
+       return syncResult;
+}
+
+/**
+ * Sets the screen brightness level for an application, from 0 to 1.
+ * @param {!number} brightness The screen brightness value to set.
+ */
+PowerManager.prototype.setScreenBrightness = function(brightness) {
+    xwalk.utils.checkPrivilegeAccess(privilege_.POWER);
+
+    var args = validator_.validateArgs(arguments, [
+        {'name' : 'brightness', 'type': types_.DOUBLE}
+    ]);
+
+    if (args.brightness < 0 || args.brightness > 1)
+        throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR);
+
+    var nativeParam = {
+            'brightness': args.brightness
+    };
+    try {
+        var syncResult = callNative('PowerManager_setScreenBrightness', nativeParam);
+        // if you need synchronous result from native function using 'syncResult'.
+    } catch(e) {
+        throw e;
+    }
+}
+
+/**
+ * Returns true if the screen is on.
+ * @return {boolean} true if screen is on.
+ */
+PowerManager.prototype.isScreenOn = function() {
+    var nativeParam = {
+    };
+       var syncResult = 0;
+
+    try {
+        syncResult = callNative('PowerManager_isScreenOn', nativeParam);
+        // if you need synchronous result from native function using 'syncResult'.
+    } catch(e) {
+        throw e;
+    }
+
+       return syncResult;
+}
+
+/**
+ * Restores the screen brightness to the system default setting value.
+ */
+PowerManager.prototype.restoreScreenBrightness = function() {
+    var nativeParam = {
+    };
+
+    try {
+        var syncResult = callNative('PowerManager_restoreScreenBrightness', nativeParam);
+        // if you need synchronous result from native function using 'syncResult'.
+    } catch(e) {
+        throw e;
+    }
+}
+
+/**
+ * Turns on the screen.
+ */
+PowerManager.prototype.turnScreenOn = function() {
+    xwalk.utils.checkPrivilegeAccess(privilege_.POWER);
+
+    var nativeParam = {
+    };
+
+    try {
+        var syncResult = callNative('PowerManager_turnScreenOn', nativeParam);
+        // if you need synchronous result from native function using 'syncResult'.
+    } catch(e) {
+        throw e;
+    }
+}
+
+/**
+ * Turns off the screen.
+ */
+PowerManager.prototype.turnScreenOff = function() {
+    xwalk.utils.checkPrivilegeAccess(privilege_.POWER);
+
+    var nativeParam = {
+    };
+
+    try {
+        var syncResult = callNative('PowerManager_turnScreenOff', nativeParam);
+        // if you need synchronous result from native function using 'syncResult'.
+    } catch(e) {
+        throw e;
+    }
+
+}
+
+
+exports = new PowerManager();
+
diff --git a/webWidgetTCT_device/src/power/power_extension.cc b/webWidgetTCT_device/src/power/power_extension.cc
new file mode 100755 (executable)
index 0000000..e497351
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2015 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 "power/power_extension.h"
+
+#include "power/power_instance.h"
+
+// This will be generated from power_api.js
+extern const char kSource_power_api[];
+
+common::Extension* CreateExtension() {
+  return new PowerExtension;
+}
+
+PowerExtension::PowerExtension() {
+  SetExtensionName("tizen.power");
+  SetJavaScriptAPI(kSource_power_api);
+}
+
+PowerExtension::~PowerExtension() {}
+
+common::Instance* PowerExtension::CreateInstance() {
+  return new extension::power::PowerInstance;
+}
diff --git a/webWidgetTCT_device/src/power/power_extension.h b/webWidgetTCT_device/src/power/power_extension.h
new file mode 100755 (executable)
index 0000000..4a4d965
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015 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 POWER_POWER_EXTENSION_H_
+#define POWER_POWER_EXTENSION_H_
+
+#include "common/extension.h"
+
+class PowerExtension : public common::Extension {
+ public:
+  PowerExtension();
+  virtual ~PowerExtension();
+
+ private:
+  virtual common::Instance* CreateInstance();
+};
+
+#endif // POWER_POWER_EXTENSION_H_
+
diff --git a/webWidgetTCT_device/src/power/power_instance.cc b/webWidgetTCT_device/src/power/power_instance.cc
new file mode 100755 (executable)
index 0000000..5d2e132
--- /dev/null
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2015 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 "power/power_instance.h"
+
+#include <functional>
+
+#include <device/display.h>
+#include <device/power.h>
+#include <device/callback.h>
+
+#include "common/picojson.h"
+#include "common/logger.h"
+#include "common/platform_exception.h"
+
+#include "power_manager.h"
+
+namespace extension {
+namespace power {
+
+namespace {
+const std::map<std::string, PowerResource> kPowerResourceMap = {
+    {"SCREEN", POWER_RESOURCE_SCREEN},
+    {"CPU", POWER_RESOURCE_CPU}
+};
+
+const std::map<std::string, PowerState> kPowerStateMap = {
+    {"SCREEN_OFF", POWER_STATE_SCREEN_OFF},
+    {"SCREEN_DIM", POWER_STATE_SCREEN_DIM},
+    {"SCREEN_NORMAL", POWER_STATE_SCREEN_NORMAL},
+    {"SCREEN_BRIGHT", POWER_STATE_SCREEN_BRIGHT},
+    {"CPU_AWAKE", POWER_STATE_CPU_AWAKE}
+};
+} // namespace
+
+using namespace common;
+using namespace extension::power;
+
+PowerInstance::PowerInstance() {
+  LoggerD("Enter");
+  using std::placeholders::_1;
+  using std::placeholders::_2;
+
+  #define REGISTER_SYNC(c,x) \
+    RegisterSyncHandler(c, std::bind(&PowerInstance::x, this, _1, _2));
+  REGISTER_SYNC("PowerManager_turnScreenOff", PowerManagerTurnscreenoff);
+  REGISTER_SYNC("PowerManager_restoreScreenBrightness", PowerManagerRestorescreenbrightness);
+  REGISTER_SYNC("PowerManager_request", PowerManagerRequest);
+  REGISTER_SYNC("PowerManager_getScreenBrightness", PowerManagerGetscreenbrightness);
+  REGISTER_SYNC("PowerManager_release", PowerManagerRelease);
+  REGISTER_SYNC("PowerManager_isScreenOn", PowerManagerIsscreenon);
+  REGISTER_SYNC("PowerManager_turnScreenOn", PowerManagerTurnscreenon);
+  REGISTER_SYNC("PowerManager_setScreenBrightness", PowerManagerSetscreenbrightness);
+  #undef REGISTER_SYNC
+  PowerManager::GetInstance()->AddListener(this);
+}
+
+PowerInstance::~PowerInstance() {
+  LoggerD("Enter");
+  PowerManager::GetInstance()->RemoveListener(this);
+}
+
+enum PowerCallbacks {
+  PowerManagerTurnscreenoffCallback,
+  PowerManagerRestorescreenbrightnessCallback,
+  PowerManagerRequestCallback,
+  PowerManagerGetscreenbrightnessCallback,
+  PowerManagerReleaseCallback,
+  PowerManagerUnsetscreenstatechangelistenerCallback,
+  PowerManagerIsscreenonCallback,
+  PowerManagerTurnscreenonCallback,
+  PowerManagerSetscreenbrightnessCallback,
+  PowerManagerSetscreenstatechangelistenerCallback
+};
+
+#define CHECK_EXIST(args, name, out) \
+    if (!args.contains(name)) {\
+      ReportError(TypeMismatchException(name" is required argument"), out);\
+      return;\
+    }
+
+void PowerInstance::PowerManagerRequest(const picojson::value& args, picojson::object& out) {
+  LoggerD("Enter");
+  const std::string& resource = args.get("resource").get<std::string>();
+  const std::string& state = args.get("state").get<std::string>();
+
+  PlatformResult result =
+      PowerManager::GetInstance()->Request(kPowerResourceMap.at(resource),
+                                           kPowerStateMap.at(state));
+  if (result.IsError())
+    ReportError(result, &out);
+  else
+    ReportSuccess(out);
+}
+
+void PowerInstance::PowerManagerRelease(const picojson::value& args, picojson::object& out) {
+  LoggerD("Enter");
+  const std::string& resource = args.get("resource").get<std::string>();
+  PlatformResult result =
+      PowerManager::GetInstance()->Release(kPowerResourceMap.at(resource));
+  if (result.IsError())
+    ReportError(result, &out);
+  else
+    ReportSuccess(out);
+}
+
+void PowerInstance::PowerManagerGetscreenbrightness(const picojson::value& args,
+                                                    picojson::object& out) {
+  LoggerD("Enter");
+  double brightness;
+  PlatformResult result =
+      PowerManager::GetInstance()->GetScreenBrightness(&brightness);
+  if (result.IsError())
+    ReportError(result, &out);
+  else
+    ReportSuccess(picojson::value(brightness), out);
+}
+
+void PowerInstance::PowerManagerSetscreenbrightness(const picojson::value& args,
+                                                    picojson::object& out) {
+  LoggerD("Enter");
+  CHECK_EXIST(args, "brightness", out)
+
+  double brightness = args.get("brightness").get<double>();
+  PlatformResult result =
+      PowerManager::GetInstance()->SetScreenBrightness(brightness);
+  if (result.IsError())
+    ReportError(result, &out);
+  else
+    ReportSuccess(out);
+}
+
+void PowerInstance::PowerManagerIsscreenon(const picojson::value& args, picojson::object& out) {
+  LoggerD("Enter");
+  bool state = false;
+  PlatformResult result = PowerManager::GetInstance()->IsScreenOn(&state);
+  if (result.IsError())
+    ReportError(result, &out);
+  else
+    ReportSuccess(picojson::value(state), out);
+}
+
+void PowerInstance::PowerManagerRestorescreenbrightness(const picojson::value& args, picojson::object& out) {
+  LoggerD("Enter");
+  PlatformResult result =
+      PowerManager::GetInstance()->RestoreScreenBrightness();
+  if (result.IsError())
+    ReportError(result, &out);
+  else
+    ReportSuccess(out);
+}
+
+void PowerInstance::PowerManagerTurnscreenon(const picojson::value& args, picojson::object& out) {
+  LoggerD("Enter");
+  PlatformResult result = PowerManager::GetInstance()->SetScreenState(true);
+  if (result.IsError())
+    ReportError(result, &out);
+  else
+    ReportSuccess(out);
+}
+
+void PowerInstance::PowerManagerTurnscreenoff(const picojson::value& args, picojson::object& out) {
+  LoggerD("Enter");
+  PlatformResult result = PowerManager::GetInstance()->SetScreenState(false);
+  if (result.IsError())
+    ReportError(result, &out);
+  else
+    ReportSuccess(out);
+}
+
+void PowerInstance::OnScreenStateChanged(PowerState prev_state, PowerState new_state) {
+  LoggerD("Enter");
+  picojson::value event = picojson::value(picojson::object());
+  picojson::object& obj = event.get<picojson::object>();
+  obj["cmd"] = picojson::value("ScreenStateChanged");
+  obj["listenerId"] = picojson::value("SCREEN_STATE_LISTENER");
+  for (auto it = kPowerStateMap.begin(); it != kPowerStateMap.end(); ++it) {
+    if (it->second == prev_state) {
+      obj["prev_state"] = picojson::value(it->first);
+    }
+    if (it->second == new_state) {
+      obj["new_state"] = picojson::value(it->first);
+    }
+  }
+
+  Instance::PostMessage(this, event.serialize().c_str());
+}
+
+#undef CHECK_EXIST
+} // namespace power
+} // namespace extension
diff --git a/webWidgetTCT_device/src/power/power_instance.h b/webWidgetTCT_device/src/power/power_instance.h
new file mode 100755 (executable)
index 0000000..d156825
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2015 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 POWER_POWER_INSTANCE_H_
+#define POWER_POWER_INSTANCE_H_
+
+#include "common/extension.h"
+
+#include "power_manager.h"
+
+namespace extension {
+namespace power {
+
+class PowerInstance
+    : public common::ParsedInstance,
+      public PowerManagerListener {
+ public:
+  PowerInstance();
+  virtual ~PowerInstance();
+
+ private:
+  void PowerManagerRequest(const picojson::value& args, picojson::object& out);
+  void PowerManagerRelease(const picojson::value& args, picojson::object& out);
+  void PowerManagerGetscreenbrightness(const picojson::value& args, picojson::object& out);
+  void PowerManagerSetscreenbrightness(const picojson::value& args, picojson::object& out);
+  void PowerManagerIsscreenon(const picojson::value& args, picojson::object& out);
+  void PowerManagerRestorescreenbrightness(const picojson::value& args, picojson::object& out);
+  void PowerManagerTurnscreenon(const picojson::value& args, picojson::object& out);
+  void PowerManagerTurnscreenoff(const picojson::value& args, picojson::object& out);
+  void SetScreenState(const picojson::value& args, picojson::object& out);
+
+  // Override
+  void OnScreenStateChanged(PowerState prev_state, PowerState new_state);
+};
+
+} // namespace power
+} // namespace extension
+
+#endif // POWER_POWER_INSTANCE_H_
diff --git a/webWidgetTCT_device/src/power/power_manager.cc b/webWidgetTCT_device/src/power/power_manager.cc
new file mode 100755 (executable)
index 0000000..5965b6f
--- /dev/null
@@ -0,0 +1,473 @@
+/*
+ * Copyright (c) 2015 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 "power_manager.h"
+
+#include <unistd.h>
+
+#include <cstring>
+#include <algorithm>
+
+#include <vconf.h>
+#include <device/display.h>
+#include <device/power.h>
+#include <device/callback.h>
+
+#include "common/logger.h"
+#include "power_platform_proxy.h"
+
+using namespace common;
+using namespace std;
+
+namespace extension {
+namespace power {
+
+PowerManager::PowerManager()
+    : current_state_(POWER_STATE_SCREEN_NORMAL),
+      bright_state_enabled_(false),
+      current_brightness_(-1),
+      should_be_read_from_cache_(false),
+      set_custom_brightness_(false),
+      current_requested_state_(POWER_STATE_NONE) {
+
+  LoggerD("Enter");
+
+  display_state_e platform_state = DISPLAY_STATE_NORMAL;
+  int ret = device_display_get_state(&platform_state);
+  if (DEVICE_ERROR_NONE != ret)
+    LoggerE("device_display_get_state failed (%d)", ret);
+
+  switch (platform_state) {
+    case DISPLAY_STATE_NORMAL :
+      current_state_ = POWER_STATE_SCREEN_NORMAL;
+      break;
+    case DISPLAY_STATE_SCREEN_DIM :
+      current_state_ = POWER_STATE_SCREEN_DIM;
+      break;
+    case DISPLAY_STATE_SCREEN_OFF :
+      current_state_ = POWER_STATE_SCREEN_OFF;
+      break;
+    default:
+      current_state_ = POWER_STATE_NONE;
+      break;
+  }
+
+  ret = device_add_callback(DEVICE_CALLBACK_DISPLAY_STATE,
+                            PowerManager::OnPlatformStateChangedCB,
+                            static_cast<void*>(this));
+  if (DEVICE_ERROR_NONE != ret)
+    LoggerE("device_add_callback failed (%d)", ret);
+}
+
+PowerManager::~PowerManager() {
+  LoggerD("Enter");
+  int ret = device_remove_callback(DEVICE_CALLBACK_DISPLAY_STATE,
+                                   PowerManager::OnPlatformStateChangedCB);
+  if (DEVICE_ERROR_NONE != ret)
+    LoggerE("device_remove_callback failed (%d)", ret);
+}
+
+PowerManager* PowerManager::GetInstance(){
+  LoggerD("Enter");
+  static PowerManager instance;
+  return &instance;
+}
+
+void PowerManager::OnPlatformStateChangedCB(device_callback_e type, void* value, void* user_data) {
+  LoggerD("Enter");
+  PowerManager* object = static_cast<PowerManager*>(user_data);
+  if (object == NULL){
+    LoggerE("User data is NULL");
+    return;
+  }
+  if (type != DEVICE_CALLBACK_DISPLAY_STATE){
+    LoggerE("type is not DISPLAY_STATE");
+    return;
+  }
+  display_state_e state = static_cast<display_state_e>(reinterpret_cast<int>(value));
+  PowerState current = POWER_STATE_SCREEN_OFF;
+  switch (state) {
+    case DISPLAY_STATE_NORMAL :
+      current = object->bright_state_enabled_ ? POWER_STATE_SCREEN_BRIGHT : POWER_STATE_SCREEN_NORMAL;
+      break;
+    case DISPLAY_STATE_SCREEN_DIM :
+      current = POWER_STATE_SCREEN_DIM;
+      break;
+    case DISPLAY_STATE_SCREEN_OFF :
+    {
+      current = POWER_STATE_SCREEN_OFF;
+      if (object->set_custom_brightness_ == true) {
+        PlatformResult result = object->RestoreScreenBrightness();
+        if (result.IsError()) {
+          LOGGER(ERROR) << "RestoreScreenBrightness failed";
+          return;
+        }
+        object->set_custom_brightness_ = false;
+      }
+      break;
+    }
+  }
+  object->BroadcastScreenState(current);
+}
+
+void PowerManager::AddListener(PowerManagerListener* listener) {
+  LoggerD("Enter");
+  auto it = std::find(listeners_.begin(), listeners_.end(), listener);
+  if (it == listeners_.end())
+    listeners_.push_back(listener);
+}
+
+void PowerManager::RemoveListener(PowerManagerListener* listener) {
+  LoggerD("Enter");
+  listeners_.remove(listener);
+}
+
+PlatformResult PowerManager::Request(PowerResource resource, PowerState state) {
+  LoggerD("Enter");
+  if (resource == POWER_RESOURCE_SCREEN && state == POWER_STATE_CPU_AWAKE)
+    return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "invalid PowerState");
+  if (resource == POWER_RESOURCE_CPU && state != POWER_STATE_CPU_AWAKE)
+    return PlatformResult(ErrorCode::INVALID_VALUES_ERR, "invalid PowerState");
+
+  if(current_requested_state_ == POWER_STATE_SCREEN_DIM) {
+    int ret = PowerPlatformProxy::GetInstance().UnlockState();
+    if (ret < 0) {
+      LoggerE("deviceUnlockState error %d", ret);
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "device_power_request_unlock error");
+    }
+  }
+
+  int ret = 0;
+  switch (state) {
+    case POWER_STATE_CPU_AWAKE:
+    {
+      ret = device_power_request_lock(POWER_LOCK_CPU, 0);
+      if (DEVICE_ERROR_NONE != ret) {
+        LoggerE("device_power_request_lock error %d", ret);
+        return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                              "device_power_request_lock error");
+      }
+      break;
+    }
+    case POWER_STATE_SCREEN_DIM:
+    {
+      ret = PowerPlatformProxy::GetInstance().LockState();
+      if (ret < 0) {
+        LoggerE("device_power_request_lock error %d", ret);
+        return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                              "device_power_request_lock error");
+      }
+      break;
+    }
+    case POWER_STATE_SCREEN_NORMAL:
+    {
+      ret = device_power_request_lock(POWER_LOCK_DISPLAY, 0);
+      if (DEVICE_ERROR_NONE != ret) {
+        LoggerE("device_power_request_lock error %d", ret);
+        return PlatformResult(ErrorCode::INVALID_VALUES_ERR,
+                              "device_power_request_lock error");
+      }
+      break;
+    }
+    case POWER_STATE_SCREEN_BRIGHT:
+    {
+      int max_brightness;
+      ret = device_display_get_max_brightness(0, &max_brightness);
+      if (DEVICE_ERROR_NONE != ret) {
+        LoggerE("Platform error while getting max brightness: %d", ret);
+        return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                              "Platform error while getting max brightness");
+      }
+
+      PlatformResult set_result = SetPlatformBrightness(max_brightness);
+      if (set_result.IsError())
+        return set_result;
+      LoggerD("Succeeded setting the brightness to a max level: %d", max_brightness);
+
+      ret = device_display_change_state(DISPLAY_STATE_NORMAL);
+      if (DEVICE_ERROR_NONE != ret) {
+        LoggerE("device_display_change_state(DISPLAY_STATE_NORMAL) error %d", ret);
+        return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                              "device_display_change_state error");
+      }
+
+      ret = device_power_request_lock(POWER_LOCK_DISPLAY, 0);
+      if (DEVICE_ERROR_NONE != ret) {
+        LoggerE("device_power_request_lock error %d", ret);
+        return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                              "device_power_request_lock error");
+      }
+
+      bright_state_enabled_ = true;
+
+      display_state_e platform_state = DISPLAY_STATE_NORMAL;
+      ret = device_display_get_state(&platform_state);
+      if (DEVICE_ERROR_NONE != ret)
+        LoggerE("device_display_get_state failed (%d)", ret);
+      if (platform_state == DISPLAY_STATE_NORMAL)
+        BroadcastScreenState(POWER_STATE_SCREEN_BRIGHT);
+      break;
+    }
+    case POWER_STATE_SCREEN_OFF:
+      LoggerE("SCREEN_OFF state cannot be requested");
+      return PlatformResult(ErrorCode::INVALID_VALUES_ERR,
+                            "SCREEN_OFF state cannot be requested");
+    default:
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "Platform error while locking state");
+  }
+
+  current_requested_state_ = state;
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult PowerManager::Release(PowerResource resource) {
+  LoggerD("Enter");
+  int ret;
+  if (POWER_RESOURCE_SCREEN == resource) {
+    ret = device_power_release_lock(POWER_LOCK_DISPLAY);
+    if (DEVICE_ERROR_NONE != ret)
+      LoggerE("Platform return value from dim unlock: %d", ret);
+
+    if (bright_state_enabled_) {
+      ret = PowerPlatformProxy::GetInstance().SetBrightnessFromSettings();
+      if (DEVICE_ERROR_NONE != ret) {
+        LoggerE("Platform error while setting restore brightness %d", ret);
+        return  PlatformResult(ErrorCode::UNKNOWN_ERR,
+                    "Platform error while setting restore brightness");
+      }
+    }
+    bright_state_enabled_ = false;
+
+    display_state_e platform_state = DISPLAY_STATE_NORMAL;
+    if(current_requested_state_ == POWER_STATE_SCREEN_DIM) {
+      ret = PowerPlatformProxy::GetInstance().UnlockState();
+      if (DEVICE_ERROR_NONE != ret) {
+        LoggerE("Failed to UnlockState (%d)", ret);
+      }
+    }
+    ret = device_display_get_state(&platform_state);
+    if (DEVICE_ERROR_NONE != ret) {
+      LoggerE("device_display_get_state failed (%d)", ret);
+    } else {
+      if (DISPLAY_STATE_NORMAL == platform_state) {
+        BroadcastScreenState(POWER_STATE_SCREEN_NORMAL);
+      }
+    }
+
+    current_requested_state_ = POWER_STATE_NONE;
+  } else if (POWER_RESOURCE_CPU == resource) {
+    ret = device_power_release_lock(POWER_LOCK_CPU);
+    if (DEVICE_ERROR_NONE != ret)
+      LoggerE("Platform return value from off unlock: %d", ret);
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult PowerManager::GetScreenBrightness(double* output) {
+  LoggerD("Enter");
+  int brightness = GetPlatformBrightness();
+  LoggerD("Brightness value: %d", brightness);
+
+  int max_brightness;
+  int ret = device_display_get_max_brightness(0, &max_brightness);
+  if (DEVICE_ERROR_NONE != ret) {
+    LoggerE("Platform error while getting brightness: %d", ret);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Platform error while getting max brightness");
+  }
+  *output = (double)brightness/(double)max_brightness;
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult PowerManager::SetScreenBrightness(double brightness) {
+  LoggerD("Enter");
+  if (brightness > 1 || brightness < 0)
+    return PlatformResult(ErrorCode::INVALID_VALUES_ERR,
+                          "brightness should be 0 <= brightness <= 1");
+  int max_brightness;
+  int ret = device_display_get_max_brightness(0, &max_brightness);
+  if (DEVICE_ERROR_NONE != ret) {
+    LoggerE("Platform error while setting restore brightness: %d", ret);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Platform error while getting max brightness");
+  }
+
+  int platform_brightness = (int)(brightness * max_brightness);
+  if (platform_brightness == 0) {
+    platform_brightness = 1;
+  }
+  PlatformResult set_result = SetPlatformBrightness(platform_brightness);
+  if (set_result.IsError())
+    return set_result;
+  LoggerD("Set the brightness value: %d", platform_brightness);
+  return set_result;
+}
+
+PlatformResult PowerManager::IsScreenOn(bool* state) {
+  LoggerD("Enter");
+  display_state_e platform_state = DISPLAY_STATE_NORMAL;
+
+  int ret = device_display_get_state(&platform_state);
+  if (DEVICE_ERROR_NONE != ret) {
+    LoggerE("device_display_get_state failed (%d)", ret);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Error while getting screen state.");
+  }
+
+  *state = (DISPLAY_STATE_SCREEN_OFF != platform_state);
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult PowerManager::SetScreenState(bool onoff) {
+  LoggerD("Enter");
+  int ret = device_display_change_state(onoff ? DISPLAY_STATE_NORMAL : DISPLAY_STATE_SCREEN_OFF);
+  if (DEVICE_ERROR_NONE != ret) {
+    LoggerE("Platform error while changing screen state %d", ret);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Platform error while changing screen state");
+  }
+
+  int timeout = 100;
+  bool state = false;
+  while (timeout--) {
+    PlatformResult result = IsScreenOn(&state);
+    if (result.IsError()) {
+      return result;
+    }
+
+    if (state == onoff) {
+      break;
+    }
+
+    struct timespec sleep_time = { 0, 100L * 1000L * 1000L };
+    nanosleep(&sleep_time, nullptr);
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult PowerManager::RestoreScreenBrightness() {
+  LoggerD("Enter");
+  int ret = PowerPlatformProxy::GetInstance().SetBrightnessFromSettings();
+  if (DEVICE_ERROR_NONE != ret) {
+    LoggerE("Platform error while restoring brightness %d", ret);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Platform error while restoring brightness");
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult PowerManager::SetPlatformBrightness(int brightness) {
+  LoggerD("Enter");
+  if (current_state_ == POWER_STATE_SCREEN_DIM) {
+    current_brightness_ = brightness;
+    LoggerD("Current state is not normal state the value is saved in cache: %d", brightness);
+    should_be_read_from_cache_ = true;
+    return PlatformResult(ErrorCode::NO_ERROR);
+  } else if (current_state_ == POWER_STATE_SCREEN_BRIGHT) {
+    current_brightness_ = brightness;
+    LoggerD("Current state is not normal state the value is saved in cache: %d", brightness);
+    should_be_read_from_cache_ = true;
+    return PlatformResult(ErrorCode::NO_ERROR);
+  } else {
+    should_be_read_from_cache_ = false;
+  }
+
+  int ret = PowerPlatformProxy::GetInstance().SetBrightness(brightness);
+  if (ret != 0) {
+    LoggerE("Platform error while setting %d brightness: %d", brightness, ret);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Platform error while setting brightness.");
+  }
+  set_custom_brightness_ = true;
+  current_brightness_ = brightness;
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+int PowerManager::GetPlatformBrightness(){
+  LoggerD("Entered");
+
+  int brightness = 0;
+
+  int is_custom_mode = PowerPlatformProxy::GetInstance().IsCustomBrightness();
+  if ((is_custom_mode && current_brightness_ != -1) || should_be_read_from_cache_) {
+    LoggerD("return custom brightness %d", current_brightness_);
+    return current_brightness_;
+  }
+
+  int is_auto_brightness = 0;
+  vconf_get_int(VCONFKEY_SETAPPL_BRIGHTNESS_AUTOMATIC_INT, &is_auto_brightness);
+  if (is_auto_brightness == 1) {
+    int 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 {
+    LoggerD("Brightness via DBUS");
+    brightness = PowerPlatformProxy::GetInstance().GetBrightness();
+  }
+  LoggerD("BRIGHTNESS(%s) %d", is_auto_brightness == 1 ? "auto" : "fix" , brightness);
+
+  return brightness;
+}
+
+
+PlatformResult PowerManager::RestoreSettedBrightness() {
+  LoggerD("Enter");
+  PlatformResult result(ErrorCode::NO_ERROR);
+  int is_custom_mode = 0;
+  vconf_get_int(VCONFKEY_PM_CUSTOM_BRIGHTNESS_STATUS, &is_custom_mode);
+  if (is_custom_mode || should_be_read_from_cache_) {
+    if (current_brightness_ == -1) {
+      // brightness was changed in other process
+      result = RestoreScreenBrightness();
+    } else {
+      result = SetPlatformBrightness(current_brightness_);
+    }
+  }
+  should_be_read_from_cache_ = false;
+  return result;
+}
+
+void PowerManager::BroadcastScreenState(PowerState current) {
+  LoggerD("Enter");
+  if (current_state_ == current)
+    return;
+
+  PowerState prev_state = current_state_;
+  current_state_ = current;
+
+  if (current_state_ == POWER_STATE_SCREEN_NORMAL) {
+    if (prev_state == POWER_STATE_SCREEN_DIM) {
+      PlatformResult result = RestoreSettedBrightness();
+      if (result.IsError()) {
+        LOGGER(ERROR) << "Error restore custom brightness " << result.message();
+      }
+    } else if (prev_state == POWER_STATE_SCREEN_OFF) {
+      should_be_read_from_cache_ = false;
+    }
+  }
+
+  for (auto it = listeners_.begin(); it != listeners_.end(); ++it) {
+    (*it)->OnScreenStateChanged(prev_state, current_state_);
+  }
+}
+
+} // namespace power
+} // namespace extension
diff --git a/webWidgetTCT_device/src/power/power_manager.h b/webWidgetTCT_device/src/power/power_manager.h
new file mode 100755 (executable)
index 0000000..56191ac
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2015 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 POWER_POWER_MANAGER_H_
+#define POWER_POWER_MANAGER_H_
+
+#include <string>
+#include <list>
+#include <device/callback.h>
+
+#include "common/platform_result.h"
+
+namespace extension {
+namespace power {
+
+enum PowerResource {
+  POWER_RESOURCE_SCREEN = 0,
+  POWER_RESOURCE_CPU = 1,
+};
+
+enum PowerState {
+  POWER_STATE_NONE = 0,
+  POWER_STATE_SCREEN_OFF,
+  POWER_STATE_SCREEN_DIM,
+  POWER_STATE_SCREEN_NORMAL,
+  POWER_STATE_SCREEN_BRIGHT,
+  POWER_STATE_CPU_AWAKE,
+};
+
+class PowerManagerListener {
+ public:
+  virtual void OnScreenStateChanged(PowerState prev_state, PowerState new_state)=0;
+};
+
+class PowerManager {
+ public:
+  void AddListener(PowerManagerListener* listener);
+  void RemoveListener(PowerManagerListener* listener);
+  common::PlatformResult Request(PowerResource resource, PowerState state);
+  common::PlatformResult Release(PowerResource resource);
+  common::PlatformResult GetScreenBrightness(double* output);
+  common::PlatformResult SetScreenBrightness(double brightness);
+  common::PlatformResult RestoreScreenBrightness();
+  common::PlatformResult IsScreenOn(bool* state);
+  common::PlatformResult SetScreenState(bool onoff);
+
+  static PowerManager* GetInstance();
+ private:
+  int GetPlatformBrightness();
+  common::PlatformResult SetPlatformBrightness(int brightness);
+  common::PlatformResult RestoreSettedBrightness();
+
+  PowerManager();
+  virtual ~PowerManager();
+
+  void BroadcastScreenState(PowerState current);
+
+  static void OnPlatformStateChangedCB(device_callback_e type, void* value, void* user_data);
+
+  std::list<PowerManagerListener*> listeners_;
+
+  PowerState current_state_;
+  bool bright_state_enabled_;
+  int current_brightness_;
+  bool should_be_read_from_cache_;
+  bool set_custom_brightness_;
+  PowerState current_requested_state_;
+};
+
+} // namespace power
+} // namespace extension
+
+#endif // POWER_POWER_MANAGER_H_
+
diff --git a/webWidgetTCT_device/src/power/power_platform_proxy.cc b/webWidgetTCT_device/src/power/power_platform_proxy.cc
new file mode 100755 (executable)
index 0000000..568b71e
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2015 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 "power_platform_proxy.h"
+
+#include <algorithm>
+
+#include "common/logger.h"
+
+using namespace common;
+
+namespace extension {
+namespace power {
+
+PowerPlatformProxy::PowerPlatformProxy() :
+    dbus_op_("org.tizen.system.deviced",
+             "/Org/Tizen/System/DeviceD/Display",
+             "org.tizen.system.deviced.display")
+{
+  LoggerD("Entered");
+}
+
+PowerPlatformProxy::~PowerPlatformProxy()
+{
+  LoggerD("Entered");
+}
+
+PowerPlatformProxy& PowerPlatformProxy::GetInstance()
+{
+  LoggerD("Entered");
+  static PowerPlatformProxy instance;
+  return instance;
+}
+
+int PowerPlatformProxy::LockState()
+{
+  LoggerD("Entered");
+  DBusOperationArguments args;
+  args.AddArgumentString("lcddim");
+  args.AddArgumentString("staycurstate");
+  args.AddArgumentString("NULL");
+  args.AddArgumentInt32(0);
+
+  return dbus_op_.InvokeSyncGetInt("lockstate", &args);
+}
+
+int PowerPlatformProxy::UnlockState()
+{
+  LoggerD("Entered");
+  DBusOperationArguments args;
+  args.AddArgumentString("lcddim");
+  args.AddArgumentString("keeptimer");
+
+  return dbus_op_.InvokeSyncGetInt("unlockstate", &args);
+}
+
+int PowerPlatformProxy::SetBrightnessFromSettings()
+{
+  LoggerD("Entered");
+  return dbus_op_.InvokeSyncGetInt("ReleaseBrightness", NULL);
+}
+
+int PowerPlatformProxy::SetBrightness(int val)
+{
+  LoggerD("Entered");
+  DBusOperationArguments args;
+  args.AddArgumentInt32(val);
+
+  return dbus_op_.InvokeSyncGetInt("HoldBrightness", &args);
+}
+
+int PowerPlatformProxy::GetBrightness() {
+  LoggerD("Entered");
+  return dbus_op_.InvokeSyncGetInt("CurrentBrightness", NULL);
+}
+
+int PowerPlatformProxy::IsCustomBrightness() {
+  LoggerD("Entered");
+  return dbus_op_.InvokeSyncGetInt("CustomBrightness", NULL);
+}
+
+} // namespace power
+} // namespace extension
diff --git a/webWidgetTCT_device/src/power/power_platform_proxy.h b/webWidgetTCT_device/src/power/power_platform_proxy.h
new file mode 100755 (executable)
index 0000000..25cacff
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2015 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 POWER_POWER_PLATFORM_PROXY_H_
+#define POWER_POWER_PLATFORM_PROXY_H_
+
+#include "common/dbus_operation.h"
+
+namespace extension {
+namespace power {
+
+class PowerPlatformProxy {
+ public:
+       int LockState();
+       int UnlockState();
+       int SetBrightnessFromSettings();
+       int SetBrightness(int val);
+
+  int GetBrightness();
+  int IsCustomBrightness();
+
+  static PowerPlatformProxy& GetInstance();
+
+ private:
+  PowerPlatformProxy();
+  virtual ~PowerPlatformProxy();
+
+       common::DBusOperation dbus_op_;
+};
+
+} // namespace power
+} // namespace extension
+
+#endif // POWER_POWER_PLATFORM_PROXY_H_
diff --git a/webWidgetTCT_device/src/push/push.gyp b/webWidgetTCT_device/src/push/push.gyp
new file mode 100755 (executable)
index 0000000..317c0a6
--- /dev/null
@@ -0,0 +1,37 @@
+{
+  'includes':[
+    '../common/common.gypi',
+  ],
+  'targets': [
+    {
+      'target_name': 'tizen_push',
+      'type': 'loadable_module',
+      'dependencies': [
+        '../common/common.gyp:tizen_common',
+      ],
+      'sources': [
+        'push_api.js',
+        'push_extension.cc',
+        'push_extension.h',
+        'push_instance.cc',
+        'push_instance.h',
+        'push_manager.cc',
+        'push_manager.h'
+      ],
+      'includes': [
+        '../common/pkg-config.gypi',
+      ],
+      'conditions': [
+        ['tizen == 1', {
+          'variables': {
+            'packages': [
+              'push',
+              'capi-appfw-application',
+              'libpcrecpp',
+            ]
+          },
+        }],
+      ],
+    },
+  ],
+}
diff --git a/webWidgetTCT_device/src/push/push_api.js b/webWidgetTCT_device/src/push/push_api.js
new file mode 100755 (executable)
index 0000000..09de6fc
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+var native = new xwalk.utils.NativeManager(extension);
+var validator = xwalk.utils.validator;
+var validatorType = xwalk.utils.type;
+var Privilege = xwalk.utils.privilege;
+
+/**
+ * @const
+ * @type {string}
+ */
+var NOTIFICATION_LISTENER = 'Push_Notification_Listener';
+
+function PushMessage(dict) {
+  for (var key in dict) {
+    if (dict.hasOwnProperty(key)) {
+      Object.defineProperty(this, key, {
+        value: key === 'date' ? new Date(dict[key] * 1000) : dict[key],
+        enumerable: true
+      });
+    }
+  }
+  Object.freeze(this);
+}
+
+
+
+/**
+ * @constructor
+ */
+function PushManager() {
+  if (!(this instanceof PushManager)) {
+    throw new TypeError;
+  }
+}
+
+PushManager.prototype.registerService = function(appControl, successCallback, errorCallback) {
+  xwalk.utils.checkPrivilegeAccess(Privilege.PUSH);
+  var data = validator.validateArgs(arguments, [
+    {
+      name: 'appControl',
+      type: validator.Types.PLATFORM_OBJECT,
+      values: tizen.ApplicationControl
+    },
+    {
+      name: 'successCallback',
+      type: validator.Types.FUNCTION
+    },
+    {
+      name: 'errorCallback',
+      type: validator.Types.FUNCTION,
+      optional: true,
+      nullable: true
+    }
+  ]);
+  var ret = native.call('Push_registerService', {
+    operation: data.appControl.operation,
+    uri: data.appControl.uri,
+    mime: data.appControl.mime,
+    category: data.appControl.category,
+    data: data.appControl.data
+  }, function(msg) {
+    if (msg.error) {
+      if (validatorType.isFunction(data.errorCallback)) {
+        data.errorCallback(native.getErrorObject(msg));
+      }
+    } else {
+      data.successCallback(msg.registrationId);
+    }
+  });
+  if (native.isFailure(ret)) {
+    throw native.getErrorObject(ret);
+  }
+};
+
+PushManager.prototype.unregisterService = function(successCallback, errorCallback) {
+  xwalk.utils.checkPrivilegeAccess(Privilege.PUSH);
+  var data = validator.validateArgs(arguments, [
+    {
+      name: 'successCallback',
+      type: validator.Types.FUNCTION,
+      optional: true,
+      nullable: true
+    },
+    {
+      name: 'errorCallback',
+      type: validator.Types.FUNCTION,
+      optional: true,
+      nullable: true
+    }
+  ]);
+  native.call('Push_unregisterService', {}, function(msg) {
+    if (msg.error) {
+      if (validatorType.isFunction(data.errorCallback)) {
+        data.errorCallback(native.getErrorObject(msg));
+      }
+    } else if (validatorType.isFunction(data.successCallback)) {
+      data.successCallback();
+    }
+  });
+};
+
+PushManager.prototype.connectService = function(notificationCallback) {
+  xwalk.utils.checkPrivilegeAccess(Privilege.PUSH);
+  var data = validator.validateArgs(arguments, [
+    {
+      name: 'notificationCallback',
+      type: validator.Types.FUNCTION
+    }
+  ]);
+  var ret = native.callSync('Push_connectService', {});
+  if (native.isFailure(ret)) {
+    throw native.getErrorObject(ret);
+  }
+  native.addListener(NOTIFICATION_LISTENER, function(msg) {
+    data.notificationCallback(new PushMessage(msg.pushMessage));
+  });
+};
+
+PushManager.prototype.disconnectService = function() {
+  xwalk.utils.checkPrivilegeAccess(Privilege.PUSH);
+  var ret = native.callSync('Push_disconnectService', {});
+  if (native.isFailure(ret)) {
+    throw native.getErrorObject(ret);
+  }
+  native.removeListener(NOTIFICATION_LISTENER);
+};
+
+PushManager.prototype.getRegistrationId = function() {
+  xwalk.utils.checkPrivilegeAccess(Privilege.PUSH);
+  var ret = native.callSync('Push_getRegistrationId', {});
+  if (native.isFailure(ret)) {
+    throw native.getErrorObject(ret);
+  }
+  return native.getResultObject(ret);
+};
+
+PushManager.prototype.getUnreadNotifications = function() {
+  xwalk.utils.checkPrivilegeAccess(Privilege.PUSH);
+  var ret = native.callSync('Push_getUnreadNotifications', {});
+  if (native.isFailure(ret)) {
+    throw native.getErrorObject(ret);
+  }
+};
+
+exports = new PushManager();
diff --git a/webWidgetTCT_device/src/push/push_extension.cc b/webWidgetTCT_device/src/push/push_extension.cc
new file mode 100755 (executable)
index 0000000..e2028e2
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2015 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 "push/push_extension.h"
+#include "push/push_instance.h"
+
+// This will be generated from push_api.js
+extern const char kSource_push_api[];
+
+namespace extension {
+namespace push {
+
+PushExtension::PushExtension() {
+    SetExtensionName("tizen.push");
+    SetJavaScriptAPI(kSource_push_api);
+}
+
+PushExtension::~PushExtension() {}
+
+PushManager& PushExtension::manager() {
+    // Initialize API on first request
+    return PushManager::getInstance();
+}
+
+common::Instance* PushExtension::CreateInstance() {
+    return new PushInstance;
+}
+
+}  // namespace push
+}  // namespace extension
+
+common::Extension* CreateExtension() {
+    return new extension::push::PushExtension;
+}
diff --git a/webWidgetTCT_device/src/push/push_extension.h b/webWidgetTCT_device/src/push/push_extension.h
new file mode 100755 (executable)
index 0000000..4a86d6a
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2015 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 SRC_PUSH_PUSH_EXTENSION_H_
+#define SRC_PUSH_PUSH_EXTENSION_H_
+
+#include "common/extension.h"
+#include "push/push_manager.h"
+
+namespace extension {
+namespace push {
+
+class PushExtension : public common::Extension {
+ public:
+    PushExtension();
+    virtual ~PushExtension();
+
+    PushManager& manager();
+
+ private:
+    virtual common::Instance* CreateInstance();
+};
+
+}  // namespace push
+}  // namespace extension
+
+#endif  // SRC_PUSH_PUSH_EXTENSION_H_
+
diff --git a/webWidgetTCT_device/src/push/push_instance.cc b/webWidgetTCT_device/src/push/push_instance.cc
new file mode 100755 (executable)
index 0000000..c22e613
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2015 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 "push/push_instance.h"
+#include <string>
+#include <vector>
+#include "common/logger.h"
+#include "push/push_manager.h"
+
+namespace extension {
+namespace push {
+
+PushInstance::PushInstance(): m_ignoreNotificationEvents(true) {
+    LoggerD("Enter");
+    using std::placeholders::_1;
+    using std::placeholders::_2;
+
+    #define REGISTER_ASYNC(c, func) \
+        RegisterSyncHandler(c, func);
+    #define REGISTER_SYNC(c, func) \
+        RegisterSyncHandler(c, func);
+
+    REGISTER_ASYNC("Push_registerService",
+        std::bind(&PushInstance::registerService, this, _1, _2));
+    REGISTER_ASYNC("Push_unregisterService",
+        std::bind(&PushInstance::unregisterService, this, _1, _2));
+    REGISTER_SYNC("Push_connectService",
+        std::bind(&PushInstance::connectService, this, _1, _2));
+    REGISTER_SYNC("Push_disconnectService",
+        std::bind(&PushInstance::disconnectService, this, _1, _2));
+    REGISTER_SYNC("Push_getRegistrationId",
+        std::bind(&PushInstance::getRegistrationId, this, _1, _2));
+    REGISTER_SYNC("Push_getUnreadNotifications",
+        std::bind(&PushInstance::getUnreadNotifications, this, _1, _2));
+    PushManager::getInstance().setListener(this);
+
+    #undef REGISTER_ASYNC
+    #undef REGISTER_SYNC
+}
+
+void PushInstance::registerService(const picojson::value& args,
+        picojson::object& out) {
+    LoggerD("Enter");
+
+    PushManager::ApplicationControl appControl;
+    appControl.operation = args.get("operation").get<std::string>();
+    if (args.get("uri").is<std::string>()) {
+        appControl.uri = args.get("uri").get<std::string>();
+    }
+    if (args.get("mime").is<std::string>()) {
+        appControl.mime = args.get("mime").get<std::string>();
+    }
+    if (args.get("category").is<std::string>()) {
+        appControl.category = args.get("category").get<std::string>();
+    }
+    if (args.get("data").is<picojson::null>() == false) {
+        std::vector<picojson::value> dataArray =
+                args.get("data").get<picojson::array>();
+        for (auto &item : dataArray) {
+            std::string key = item.get("key").get<std::string>();
+            std::vector<picojson::value> values =
+                    item.get("value").get<picojson::array>();
+            for (auto &value : values) {
+                appControl.data[key].push_back(value.to_str());
+            }
+        }
+    }
+    common::PlatformResult result = PushManager::getInstance().registerService(
+            appControl,
+            args.get("callbackId").get<double>());
+    if (result.IsError()) {
+        LoggerE("Error occured");
+        ReportError(result, &out);
+    } else {
+        picojson::value result;
+        ReportSuccess(result, out);
+    }
+}
+
+void PushInstance::unregisterService(const picojson::value& args,
+        picojson::object& out) {
+    LoggerD("Enter");
+
+    common::PlatformResult result = PushManager::getInstance()
+            .unregisterService(args.get("callbackId").get<double>());
+    if (result.IsError()) {
+        LoggerE("Error occured");
+        ReportError(result, &out);
+    } else {
+        picojson::value res;
+        ReportSuccess(res, out);
+    }
+}
+
+void PushInstance::connectService(const picojson::value& args,
+        picojson::object& out) {
+    LoggerD("Enter");
+
+    m_ignoreNotificationEvents = false;
+    picojson::value result;
+    ReportSuccess(result, out);
+}
+
+void PushInstance::disconnectService(const picojson::value& args,
+        picojson::object& out) {
+    LoggerD("Enter");
+
+    m_ignoreNotificationEvents = true;
+    picojson::value result;
+    ReportSuccess(result, out);
+}
+
+void PushInstance::getRegistrationId(const picojson::value& args,
+        picojson::object& out) {
+    LoggerD("Enter");
+
+    std::string id;
+    common::PlatformResult result = PushManager::getInstance()
+            .getRegistrationId(id);
+    if (result.IsError()) {
+        // this method should fail silently and return null
+        picojson::value res = picojson::value();
+        ReportSuccess(res, out);
+    } else {
+        picojson::value res(id);
+        ReportSuccess(res, out);
+    }
+}
+
+void PushInstance::getUnreadNotifications(const picojson::value& args,
+        picojson::object& out) {
+    LoggerD("Enter");
+
+    common::PlatformResult result = PushManager::getInstance()
+            .getUnreadNotifications();
+    if (result.IsError()) {
+        LoggerE("Error occured");
+        ReportError(result, &out);
+    } else {
+        picojson::value res;
+        ReportSuccess(res, out);
+    }
+}
+
+void PushInstance::onPushRegister(double callbackId,
+        common::PlatformResult result, const std::string& id) {
+    LoggerD("Enter");
+    picojson::value::object dict;
+    dict["callbackId"] = picojson::value(callbackId);
+    if (result.IsError()) {
+        dict["error"] = result.ToJSON();
+    } else {
+        dict["registrationId"] = picojson::value(id);
+    }
+    picojson::value res(dict);
+    Instance::PostMessage(this, res.serialize().c_str());
+}
+
+void PushInstance::onPushNotify(const std::string& appData,
+        const std::string& alertMessage, double date) {
+    LoggerD("Enter");
+    if (m_ignoreNotificationEvents) {
+        LoggerD("Listener not set, ignoring event");
+    }
+    picojson::value::object dict;
+    dict["listenerId"] = picojson::value("Push_Notification_Listener");
+    picojson::value::object pushMessage;
+    pushMessage["appData"] = picojson::value(appData);
+    pushMessage["alertMessage"] = picojson::value(alertMessage);
+    pushMessage["date"] = picojson::value(date);
+    dict["pushMessage"] = picojson::value(pushMessage);
+    picojson::value resultListener(dict);
+    Instance::PostMessage(this, resultListener.serialize().c_str());
+}
+
+void PushInstance::onDeregister(double callbackId,
+        common::PlatformResult result) {
+    LoggerD("Enter");
+    picojson::value::object dict;
+    dict["callbackId"] = picojson::value(callbackId);
+    if (result.IsError()) {
+        dict["error"] = result.ToJSON();
+    }
+    picojson::value res(dict);
+    Instance::PostMessage(this, res.serialize().c_str());
+}
+
+PushInstance::~PushInstance() {
+    LoggerD("Enter");
+}
+
+}  // namespace push
+}  // namespace extension
diff --git a/webWidgetTCT_device/src/push/push_instance.h b/webWidgetTCT_device/src/push/push_instance.h
new file mode 100755 (executable)
index 0000000..8800b59
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2015 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 SRC_PUSH_PUSH_INSTANCE_H_
+#define SRC_PUSH_PUSH_INSTANCE_H_
+
+#include <string>
+#include "common/extension.h"
+#include "push/push_manager.h"
+
+namespace extension {
+namespace push {
+
+class PushInstance: public common::ParsedInstance, public EventListener {
+ public:
+    PushInstance();
+    virtual ~PushInstance();
+    virtual void onPushRegister(double callbackId,
+            common::PlatformResult result, const std::string& id);
+    virtual void onPushNotify(const std::string& appData,
+            const std::string& alertMessage, double date);
+    virtual void onDeregister(double callbackId, common::PlatformResult result);
+
+ private:
+     void registerService(const picojson::value& args, picojson::object& out);
+     void unregisterService(const picojson::value& args, picojson::object& out);
+     void connectService(const picojson::value& args, picojson::object& out);
+     void disconnectService(const picojson::value& args, picojson::object& out);
+     void getRegistrationId(const picojson::value& args, picojson::object& out);
+     void getUnreadNotifications(const picojson::value& args,
+            picojson::object& out);
+
+     bool m_ignoreNotificationEvents;
+};
+
+}  // namespace push
+}  // namespace extension
+
+#endif  // SRC_PUSH_PUSH_INSTANCE_H_
diff --git a/webWidgetTCT_device/src/push/push_manager.cc b/webWidgetTCT_device/src/push/push_manager.cc
new file mode 100755 (executable)
index 0000000..18c9715
--- /dev/null
@@ -0,0 +1,388 @@
+/*
+ * Copyright (c) 2015 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 "push/push_manager.h"
+#include <unistd.h>
+#include <pcrecpp.h>
+#include <app_control.h>
+#include <app_manager.h>
+#include "common/logger.h"
+
+namespace extension {
+namespace push {
+
+using common::PlatformResult;
+using common::ErrorCode;
+
+PushManager::PushManager() :
+    m_handle(NULL),
+    m_listener(NULL),
+    m_state(PUSH_STATE_UNREGISTERED) {
+    LoggerD("Enter");
+    initAppId();
+
+    int ret = push_connect(m_pkgId.c_str(), onPushState, onPushNotify, NULL,
+        &m_handle);
+    if (ret != PUSH_ERROR_NONE) {
+        LoggerE("Failed to connect to push (%d)", ret);
+    }
+}
+
+PushManager::~PushManager() {
+    LoggerD("Enter");
+    push_disconnect(m_handle);
+}
+
+void PushManager::setListener(EventListener* listener) {
+    LoggerD("Enter");
+    m_listener = listener;
+}
+
+void PushManager::initAppId() {
+    LoggerD("Enter");
+    int pid = getpid();
+    char *temp = NULL;
+    int ret = app_manager_get_app_id(pid, &temp);
+    if (ret != APP_MANAGER_ERROR_NONE || temp == NULL) {
+        LoggerE("Failed to get appid (%d)", ret);
+        return;
+    }
+
+    m_appId = temp;
+    free(temp);
+    temp = NULL;
+
+    app_info_h info;
+    ret = app_manager_get_app_info(m_appId.c_str(), &info);
+    if (ret != APP_MANAGER_ERROR_NONE) {
+        LoggerE("Failed to get app info (%d)", ret);
+        return;
+    }
+
+    ret = app_info_get_package(info, &temp);
+    if (ret == APP_MANAGER_ERROR_NONE && temp != NULL) {
+        m_pkgId = temp;
+        free(temp);
+    } else {
+        LoggerE("Failed to get pkg id (%d)", ret);
+    }
+
+    app_info_destroy(info);
+}
+
+PushManager& PushManager::getInstance() {
+  static PushManager instance;
+  return instance;
+}
+
+PlatformResult PushManager::registerService(
+        const ApplicationControl &appControl, double callbackId) {
+    LoggerD("Enter");
+    app_control_h service;
+    int ret = app_control_create(&service);
+    if (ret != APP_CONTROL_ERROR_NONE) {
+        LoggerE("Failed to create service: app_control_create failed(%d)", ret);
+        return common::PlatformResult(ErrorCode::UNKNOWN_ERR,
+            "Failed to create service");
+    }
+
+    if (appControl.operation.empty()) {
+        LoggerE("Operation is empty");
+        app_control_destroy(service);
+        return common::PlatformResult(ErrorCode::INVALID_VALUES_ERR,
+            "Operation is empty");
+    }
+    ret = app_control_set_operation(service, appControl.operation.c_str());
+    if (ret != APP_CONTROL_ERROR_NONE) {
+        LoggerE("Failed to set operation: app_control_set_operation failed(%d)", ret);
+        app_control_destroy(service);
+        return common::PlatformResult(ErrorCode::UNKNOWN_ERR,
+            "Failed to set operation");
+    }
+
+    if (!appControl.uri.empty()) {
+        ret = app_control_set_uri(service, appControl.uri.c_str());
+        if (ret != APP_CONTROL_ERROR_NONE) {
+            LoggerE("Failed to set uri: app_control_set_uri failed(%d)", ret);
+            app_control_destroy(service);
+            return common::PlatformResult(ErrorCode::UNKNOWN_ERR,
+                "Failed to set uri");
+        }
+    }
+
+    if (!appControl.mime.empty()) {
+        ret = app_control_set_mime(service, appControl.mime.c_str());
+        if (ret != APP_CONTROL_ERROR_NONE) {
+            LoggerE("Failed to set mime: app_control_set_mime failed(%d)", ret);
+            app_control_destroy(service);
+            return common::PlatformResult(ErrorCode::UNKNOWN_ERR,
+                "Failed to set mime");
+        }
+    }
+
+    if (!appControl.category.empty()) {
+        ret = app_control_set_category(service, appControl.category.c_str());
+        if (ret != APP_CONTROL_ERROR_NONE) {
+            LoggerE("Failed to set category: app_control_set_category failed");
+            app_control_destroy(service);
+            return common::PlatformResult(ErrorCode::UNKNOWN_ERR,
+                "Failed to set category");
+        }
+    }
+
+    ret = app_control_set_app_id(service, m_appId.c_str());
+    if (ret != APP_CONTROL_ERROR_NONE) {
+        LoggerE("Failed to set app id: app_control_set_app_id failed(%d)", ret);
+        app_control_destroy(service);
+        return common::PlatformResult(ErrorCode::UNKNOWN_ERR,
+            "Failed to set app id");
+    }
+
+    for (auto &item : appControl.data) {
+        if (item.second.size() == 1) {
+            ret = app_control_add_extra_data(service, item.first.c_str(),
+                item.second.front().c_str());
+        } else {
+            const char *values[item.second.size()];
+            for (size_t i = 0; i < item.second.size(); ++i) {
+                values[i] = item.second.at(i).c_str();
+            }
+            ret = app_control_add_extra_data_array(service,
+                item.first.c_str(), values, item.second.size());
+        }
+        if (ret != APP_CONTROL_ERROR_NONE) {
+            LoggerE(
+                "Failed to set extra data: app_control_add_extra_data failed(%d)", ret);
+            app_control_destroy(service);
+            return common::PlatformResult(ErrorCode::UNKNOWN_ERR,
+                "Failed to set extra data");
+        }
+    }
+
+    double* pcallback = new double(callbackId);
+    ret = push_register(m_handle, service, onPushRegister, pcallback);
+    app_control_destroy(service);
+    if (ret != PUSH_ERROR_NONE) {
+        delete pcallback;
+        if (ret == PUSH_ERROR_INVALID_PARAMETER) {
+          LoggerE("[push_register] PUSH_ERROR_INVALID_PARAMETER");
+        } else if (ret == PUSH_ERROR_OUT_OF_MEMORY) {
+          LoggerE("[push_register] PUSH_ERROR_OUT_OF_MEMORY");
+        } else if (ret == PUSH_ERROR_NOT_CONNECTED) {
+          LoggerE("[push_register] PUSH_ERROR_NOT_CONNECTED");
+        } else if (ret == PUSH_ERROR_OPERATION_FAILED) {
+          LoggerE("[push_register] PUSH_ERROR_OPERATION_FAILED");
+        }
+        LoggerE("Failed to register push: push_register failed (%d)", ret);
+        return common::PlatformResult(ErrorCode::UNKNOWN_ERR,
+            "Failed to register");
+    }
+
+    return common::PlatformResult(ErrorCode::NO_ERROR);
+}
+
+common::PlatformResult PushManager::unregisterService(double callbackId) {
+    LoggerD("Enter");
+    double* pcallbackId = new double(callbackId);
+    if (m_state == PUSH_STATE_UNREGISTERED) {
+        LoggerD("Already unregister, call unregister callback");
+        if (!g_idle_add(onFakeDeregister, pcallbackId)) {
+            delete pcallbackId;
+            LoggerE("g_idle_add failed");
+            return common::PlatformResult(ErrorCode::UNKNOWN_ERR,
+                "Unknown error");
+        }
+    } else {
+        int ret = push_deregister(m_handle, onDeregister, pcallbackId);
+        if (ret != PUSH_ERROR_NONE) {
+            delete pcallbackId;
+            if (ret == PUSH_ERROR_INVALID_PARAMETER) {
+              LoggerE("[push_deregister] PUSH_ERROR_INVALID_PARAMETER");
+            } else if (ret == PUSH_ERROR_OUT_OF_MEMORY) {
+              LoggerE("[push_deregister] PUSH_ERROR_OUT_OF_MEMORY");
+            } else if (ret == PUSH_ERROR_NOT_CONNECTED) {
+              LoggerE("[push_deregister] PUSH_ERROR_NOT_CONNECTED");
+            } else if (ret == PUSH_ERROR_OPERATION_FAILED) {
+              LoggerE("[push_deregister] PUSH_ERROR_OPERATION_FAILED");
+            }
+            LoggerE("Failed to deregister: push_deregister failed (%d)", ret);
+            return common::PlatformResult(ErrorCode::UNKNOWN_ERR,
+                "Unknown error");
+        }
+    }
+    return common::PlatformResult(ErrorCode::NO_ERROR);
+}
+
+common::PlatformResult PushManager::getRegistrationId(std::string& id) {
+    LoggerD("Enter");
+    char* temp = NULL;
+    int ret = push_get_registration_id(m_handle, &temp);
+    if (ret != PUSH_ERROR_NONE) {
+        if (ret == PUSH_ERROR_INVALID_PARAMETER) {
+          LoggerE("[push_get_registration_id]   PUSH_ERROR_INVALID_PARAMETER");
+        } else if (ret == PUSH_ERROR_OUT_OF_MEMORY) {
+          LoggerE("[push_get_registration_id]   PUSH_ERROR_OUT_OF_MEMORY");
+        } else if (ret == PUSH_ERROR_NO_DATA) {
+          LoggerE("[push_get_registration_id]   PUSH_ERROR_NO_DATA");
+        }
+        LoggerE("Failed to get id: push_get_registration_id failed (%d)", ret);
+        return common::PlatformResult(ErrorCode::UNKNOWN_ERR,
+            "Unknown error");
+    }
+    id = temp;
+    free(temp);
+    return common::PlatformResult(ErrorCode::NO_ERROR);
+}
+
+common::PlatformResult PushManager::getUnreadNotifications() {
+    LoggerD("Enter");
+    int ret = push_request_unread_notification(m_handle);
+    if (ret != PUSH_ERROR_NONE) {
+        LoggerE(
+            "Failed to send request: push_request_unread_notification failed (%d)", ret);
+        return common::PlatformResult(ErrorCode::UNKNOWN_ERR,
+            "Unknown error");
+    }
+    return common::PlatformResult(ErrorCode::NO_ERROR);
+}
+
+void PushManager::onPushState(push_state_e state, const char* err,
+        void* user_data) {
+    LoggerD("Enter %d, err: %s", state, err);
+    getInstance().m_state = state;
+}
+
+void PushManager::onPushNotify(push_notification_h noti, void* user_data) {
+    LoggerD("Enter");
+    if (!getInstance().m_listener) {
+        LoggerW("Listener not set, ignoring");
+        return;
+    }
+
+    char* temp = NULL;
+    int ret = push_get_notification_data(noti, &temp);
+    if (ret != PUSH_ERROR_NONE) {
+        LoggerE("Failed to get appData");
+        return;
+    }
+    std::string appData = temp;
+    free(temp);
+
+    temp = NULL;
+    ret = push_get_notification_message(noti, &temp);
+    if (ret != PUSH_ERROR_NONE) {
+        LoggerE("Failed to get message");
+        return;
+    }
+
+    // parse query string and find value for alertMessage
+    pcrecpp::StringPiece input(temp);
+    pcrecpp::RE re("([^=]+)=([^&]*)&?");
+    string key;
+    string value;
+    std::string alertMessage;
+    while (re.Consume(&input, &key, &value)) {
+        if (key == "alertMessage") {
+            alertMessage = value;
+            break;
+        }
+    }
+    free(temp);
+
+    int64_t date = -1;
+    ret = push_get_notification_time(noti, &date);
+    if (ret != PUSH_ERROR_NONE) {
+        LoggerE("Failed to get date");
+        return;
+    }
+    getInstance().m_listener->onPushNotify(appData, alertMessage, date);
+}
+
+void PushManager::onPushRegister(push_result_e result, const char* msg,
+        void* user_data) {
+    LoggerD("Enter");
+    if (!getInstance().m_listener) {
+        LoggerW("Listener not set, ignoring");
+        return;
+    }
+    double* callbackId = static_cast<double*>(user_data);
+    std::string id;
+    PlatformResult res(ErrorCode::NO_ERROR);
+    if (result == PUSH_RESULT_SUCCESS) {
+        LoggerD("Success");
+        char *temp = NULL;
+        int ret = push_get_registration_id(getInstance().m_handle, &temp);
+        if (ret == PUSH_ERROR_NONE) {
+            LoggerD("Registration id retrieved");
+            id = temp;
+            free(temp);
+        } else {
+            LoggerD("Failed to retrieve registration id: push_get_registration_id(%d)", ret);
+            res = PlatformResult(ErrorCode::UNKNOWN_ERR,
+                "Failed to retrieve registration id");
+        }
+    } else {
+        if (result == PUSH_RESULT_TIMEOUT) {
+            LoggerE("PUSH_RESULT_TIMEOUT");
+        } else if (result == PUSH_RESULT_SERVER_ERROR) {
+            LoggerE("PUSH_RESULT_SERVER_ERROR");
+        } else if (result == PUSH_RESULT_SYSTEM_ERROR) {
+            LoggerE("PUSH_RESULT_SYSTEM_ERROR");
+        }
+        res = PlatformResult(ErrorCode::UNKNOWN_ERR,
+                msg == NULL ? "Unknown error" : msg);
+    }
+    // onPushState is not always called when onPushRegister is successfull
+    getInstance().m_state = PUSH_STATE_REGISTERED;
+    getInstance().m_listener->onPushRegister(*callbackId, res, id);
+    delete callbackId;
+}
+
+gboolean PushManager::onFakeDeregister(gpointer user_data) {
+    LoggerD("Enter");
+    if (!getInstance().m_listener) {
+        LoggerW("Listener not set, ignoring");
+        return G_SOURCE_REMOVE;
+    }
+    double* callbackId = static_cast<double*>(user_data);
+    getInstance().m_listener->onDeregister(*callbackId,
+        PlatformResult(ErrorCode::NO_ERROR));
+    delete callbackId;
+    return G_SOURCE_REMOVE;
+}
+
+void PushManager::onDeregister(push_result_e result, const char* msg,
+        void* user_data) {
+    LoggerD("Enter");
+    if (!getInstance().m_listener) {
+        LoggerW("Listener not set, ignoring");
+        return;
+    }
+    double* callbackId = static_cast<double*>(user_data);
+    if (result == PUSH_RESULT_SUCCESS) {
+        getInstance().m_listener->onDeregister(*callbackId,
+            PlatformResult(ErrorCode::NO_ERROR));
+    } else {
+        getInstance().m_listener->onDeregister(*callbackId,
+            PlatformResult(ErrorCode::UNKNOWN_ERR,
+                msg == NULL ? "Unknown error" : msg));
+    }
+    delete callbackId;
+}
+
+}  // namespace push
+}  // namespace extension
+
diff --git a/webWidgetTCT_device/src/push/push_manager.h b/webWidgetTCT_device/src/push/push_manager.h
new file mode 100755 (executable)
index 0000000..a1a66e3
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2015 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 SRC_PUSH_PUSH_MANAGER_H_
+#define SRC_PUSH_PUSH_MANAGER_H_
+
+#include <push.h>
+#include <glib.h>
+#include <string>
+#include <vector>
+#include <map>
+#include "common/platform_result.h"
+
+namespace extension {
+namespace push {
+
+class EventListener {
+ public:
+    virtual void onPushRegister(double callbackId,
+            common::PlatformResult result, const std::string& id) = 0;
+    virtual void onPushNotify(const std::string& appData,
+            const std::string& alertMessage, double date) = 0;
+    virtual void onDeregister(double callbackId,
+            common::PlatformResult result) = 0;
+    virtual ~EventListener() {}
+};
+
+class PushManager {
+ public:
+    static PushManager& getInstance();
+    virtual ~PushManager();
+
+    void setListener(EventListener* listener);
+    struct ApplicationControl {
+        std::string operation;
+        std::string uri;
+        std::string mime;
+        std::string category;
+        std::map<std::string, std::vector<std::string> > data;
+    };
+    common::PlatformResult registerService(const ApplicationControl &appControl,
+        double callbackId);
+    common::PlatformResult unregisterService(double callbackId);
+    common::PlatformResult getRegistrationId(std::string &id);
+    common::PlatformResult getUnreadNotifications();
+
+ private:
+    PushManager();
+    void initAppId();
+    static void onPushState(push_state_e state, const char *err,
+        void *user_data);
+    static void onPushNotify(push_notification_h noti, void *user_data);
+    static void onPushRegister(push_result_e result, const char *msg,
+        void *user_data);
+    static gboolean onFakeDeregister(gpointer user_data);
+    static void onDeregister(push_result_e result, const char *msg,
+        void *user_data);
+
+    push_connection_h m_handle;
+    EventListener* m_listener;
+    push_state_e m_state;
+    std::string m_appId;
+    std::string m_pkgId;
+};
+
+}  // namespace push
+}  // namespace extension
+
+#endif  // SRC_PUSH_PUSH_MANAGER_H_
+
diff --git a/webWidgetTCT_device/src/radio/radio.gyp b/webWidgetTCT_device/src/radio/radio.gyp
new file mode 100755 (executable)
index 0000000..79d37d5
--- /dev/null
@@ -0,0 +1,37 @@
+{
+  'includes':[
+    '../common/common.gypi',
+  ],
+  'targets': [
+    {
+      'target_name': 'tizen_fmradio',
+      'type': 'loadable_module',
+      'dependencies': [
+        '../common/common.gyp:tizen_common',
+      ],
+      'sources': [
+        'radio_api.js',
+        'radio_extension.cc',
+        'radio_extension.h',
+        'radio_manager.cc',
+        'radio_manager.h',
+        'radio_instance.cc',
+        'radio_instance.h'
+      ],
+       'includes': [
+        '../common/pkg-config.gypi',
+        ],
+      'conditions': [
+        ['tizen == 1', {
+          'variables': {
+            'packages': [
+                'vconf',
+                'capi-media-radio',
+                'capi-system-runtime-info',
+            ]
+          },
+        }],
+      ],
+    },
+  ],
+}
diff --git a/webWidgetTCT_device/src/radio/radio_api.js b/webWidgetTCT_device/src/radio/radio_api.js
new file mode 100755 (executable)
index 0000000..beaba45
--- /dev/null
@@ -0,0 +1,369 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+var validator_ = xwalk.utils.validator;
+var types_ = validator_.Types;
+var native_ = new xwalk.utils.NativeManager(extension);
+
+var _listeners_FMRadioInterrupted;
+var _listeners_AntennaChange;
+
+var RadioState = {
+    PLAYING : 'PLAYING',
+    SCANNING : 'SCANNING',
+    READY : 'READY'
+};
+
+function FMRadioInterruptCallbackManager() {
+
+    this.oninterrupted;
+    this.oninterruptfinished;
+};
+
+FMRadioInterruptCallbackManager.prototype.FMRadioInterruptedCBSwitch = function(args) {
+    if (args.action == 'oninterrupted')
+        this.oninterrupted(args.reason);
+    else
+        this.oninterruptfinished();
+};
+
+FMRadioInterruptCallbackManager.prototype.FMRadioInterruptedSet = function(oi, oif) {
+    this.oninterrupted = oi;
+    this.oninterruptfinished = oif;
+    native_.addListener('FMRadio_Interrupted', this.FMRadioInterruptedCBSwitch
+            .bind(this));
+};
+
+FMRadioInterruptCallbackManager.prototype.FMRadioInterruptedUnset = function() {
+    native_.removeListener('FMRadio_Interrupted');
+};
+
+function FMRadioScanCallbackManager() {
+
+    this.radioScanCallback;
+
+};
+
+FMRadioScanCallbackManager.prototype.FMRadioScanCBSwitch = function(args) {
+    this.radioScanCallback(args.frequency);
+};
+
+FMRadioScanCallbackManager.prototype.FMRadioScanSet = function(cb) {
+    this.radioScanCallback = cb;
+    native_.addListener('FMRadio_Onfrequencyfound',
+            this.FMRadioScanCBSwitch.bind(this));
+};
+
+FMRadioScanCallbackManager.prototype.FMRadioScanUnset = function() {
+    native_.removeListener('FMRadio_Onfrequencyfound');
+};
+
+function FMRadioAntennaChangeCallbackManager() {
+
+    this.onchanged;
+
+};
+
+FMRadioAntennaChangeCallbackManager.prototype.FMRadioAntennaCBSwitch = function(args) {
+    this.onchanged(args.connected);
+};
+
+FMRadioAntennaChangeCallbackManager.prototype.FMRadioAntennaChangeSet = function(cb) {
+    this.onchanged = cb;
+    native_.addListener('FMRadio_Antenna', this.FMRadioAntennaCBSwitch
+            .bind(this));
+};
+
+FMRadioAntennaChangeCallbackManager.prototype.FMRadioAntennaUnset = function() {
+    native_.removeListener('FMRadio_Antenna');
+};
+
+var antennaCBmanager = new FMRadioAntennaChangeCallbackManager();
+var interruptedCBmanager = new FMRadioInterruptCallbackManager();
+var scanCBmanager = new FMRadioScanCallbackManager();
+
+function FMRadioManager() {
+    Object.defineProperties(this, {
+        'frequency' : {
+            enumerable : true,
+            get : frequencyGetter,
+            set : function() {
+            }
+        },
+        'frequencyUpperBound' : {
+            enumerable : true,
+            get : frequencyUpperGetter,
+            set : function() {
+            }
+        },
+        'frequencyLowerBound' : {
+            enumerable : true,
+            get : frequencyLowerGetter,
+            set : function() {
+            }
+        },
+        'signalStrength' : {
+            enumerable : true,
+            get : signalStrengthGetter,
+            set : function() {
+            }
+        },
+        'state' : {
+            enumerable : true,
+            get : radioStateGetter,
+            set : function() {
+            }
+        },
+        'isAntennaConnected' : {
+            enumerable : true,
+            get : isAntennaConnectedGetter,
+            set : function() {
+            }
+        },
+        'mute' : {
+            enumerable : true,
+            get : muteGetter,
+            set : muteSetter
+        }
+    });
+
+    function muteGetter() {
+        var ret = native_.callSync('FMRadio_MuteGetter');
+        return native_.getResultObject(ret);
+    }
+
+    function muteSetter() {
+
+        var args = validator_.validateArgs(arguments, [ {
+            name : 'mute',
+            type : types_.BOOLEAN
+        } ]);
+        native_.callSync('FMRadio_MuteSetter', args);
+    }
+
+    function radioStateGetter() {
+        var ret = native_.callSync('FMRadio_RadioStateGetter');
+
+        return native_.getResultObject(ret);
+    }
+
+    function isAntennaConnectedGetter() {
+        var ret = native_.callSync('FMRadio_IsAntennaConnectedGetter');
+
+        return native_.getResultObject(ret);
+    }
+
+    function signalStrengthGetter() {
+        var ret = native_.callSync('FMRadio_SignalStrengthGetter');
+
+        return native_.getResultObject(ret);
+    }
+
+    function frequencyGetter() {
+
+        var ret = native_.callSync('FMRadio_FrequencyGetter');
+
+        return native_.getResultObject(ret);
+    }
+
+    function frequencyUpperGetter() {
+        return 108;
+    }
+
+    function frequencyLowerGetter() {
+        return 87.5;
+    }
+}
+
+FMRadioManager.prototype.seekUp = function() {
+    var args = validator_.validateArgs(arguments, [ {
+        name : 'successCallback',
+        type : types_.FUNCTION,
+        optional : true,
+        nullable : true
+    }, {
+        name : 'errorCallback',
+        type : types_.FUNCTION,
+        optional : true,
+        nullable : true
+    } ]);
+
+    native_.call('FMRadio_SeekUp', {}, function(result) {
+        if (native_.isFailure(result)) {
+            if (args.errorCallback)
+                args.errorCallback(native_.getErrorObject(result));
+        } else {
+            if (args.successCallback)
+                args.successCallback();
+        }
+    });
+
+};
+
+FMRadioManager.prototype.start = function() {
+    var args = validator_.validateArgs(arguments, [ {
+        name : 'frequency',
+        type : types_.DOUBLE,
+        optional : true,
+        nullable : true
+    } ]);
+
+    if (args.frequency) {
+        if (args.frequency < this.frequencyLowerBound
+                || args.frequency > this.frequencyUpperBound)
+            throw new WebAPIException(
+                    WebAPIException.INVALID_VALUES_ERR,
+                    'Frequency out of bounds');
+    }
+    var result = native_.callSync('FMRadio_Start', {
+        'frequency' : args.frequency ? args.frequency
+                : this.frequencyLowerBound
+    });
+    if (native_.isFailure(result)) {
+        throw native_.getErrorObject(result);
+    }
+};
+
+FMRadioManager.prototype.seekDown = function() {
+    var args = validator_.validateArgs(arguments, [ {
+        name : 'successCallback',
+        type : types_.FUNCTION,
+        optional : true,
+        nullable : true
+    }, {
+        name : 'errorCallback',
+        type : types_.FUNCTION,
+        optional : true,
+        nullable : true
+    } ]);
+
+    native_.call('FMRadio_SeekDown', {}, function(result) {
+        if (native_.isFailure(result)) {
+            if (args.errorCallback)
+                args.errorCallback(native_.getErrorObject(result));
+        } else {
+            if (args.successCallback)
+                args.successCallback();
+        }
+    });
+};
+
+FMRadioManager.prototype.scanStart = function() {
+    var args = validator_.validateArgs(arguments, [ {
+        name : 'radioScanCallback',
+        type : types_.LISTENER,
+        values : [ 'onfrequencyfound', 'onfinished' ]
+    }, {
+        name : 'errorCallback',
+        type : types_.FUNCTION,
+        optional : true,
+        nullable : true
+    } ]);
+
+    scanCBmanager.FMRadioScanSet(args.radioScanCallback.onfrequencyfound);
+
+    native_.call('FMRadio_ScanStart', {}, function(result) {
+        if (native_.isFailure(result)) {
+            if (args.errorCallback)
+                args.errorCallback(native_.getErrorObject(result));
+
+        } else {
+            scanCBmanager.FMRadioScanUnset();
+            args.radioScanCallback.onfinished(result.frequencies);
+        }
+    });
+};
+
+FMRadioManager.prototype.stop = function() {
+    var ret = native_.callSync('FMRadio_Stop');
+    if (native_.isFailure(ret)) {
+        throw native_.getErrorObject(ret);
+    }
+};
+
+FMRadioManager.prototype.scanStop = function() {
+    var args = validator_.validateArgs(arguments, [ {
+        name : 'successCallback',
+        type : types_.FUNCTION,
+        optional : true,
+        nullable : true
+    }, {
+        name : 'errorCallback',
+        type : types_.FUNCTION,
+        optional : true,
+        nullable : true
+    } ]);
+
+    native_.call('FMRadio_ScanStop', {}, function(result) {
+        if (native_.isFailure(result)) {
+            if (args.errorCallback)
+                args.errorCallback(native_.getErrorObject(result));
+        } else {
+
+            args.successCallback();
+
+        }
+    });
+};
+
+FMRadioManager.prototype.setFMRadioInterruptedListener = function() {
+
+    var args = validator_.validateArgs(arguments, [ {
+        name : 'interruptCallback',
+        type : types_.LISTENER,
+        values : [ 'oninterrupted', 'oninterruptfinished' ]
+    } ]);
+    interruptedCBmanager.FMRadioInterruptedSet(args.interruptCallback.oninterrupted,
+            args.interruptCallback.oninterruptfinished);
+
+    var ret = native_.callSync('FMRadio_SetFMRadioInterruptedListener');
+    if (native_.isFailure(ret)) {
+        throw native_.getErrorObject(ret);
+    }
+};
+
+FMRadioManager.prototype.unsetFMRadioInterruptedListener = function() {
+
+    interruptedCBmanager.FMRadioInterruptedUnset();
+    var ret = native_.callSync('FMRadio_UnsetFMRadioInterruptedListener');
+    if (native_.isFailure(ret)) {
+        throw native_.getErrorObject(ret);
+    }
+};
+
+FMRadioManager.prototype.setAntennaChangeListener = function() {
+    var args = validator_.validateArgs(arguments, [ {
+        name : 'changeCallback',
+        type : types_.FUNCTION
+    } ]);
+
+    antennaCBmanager.FMRadioAntennaChangeSet(args.changeCallback);
+    var ret = native_.callSync('FMRadio_SetAntennaChangeListener');
+    if (native_.isFailure(ret)) {
+        throw native_.getErrorObject(ret);
+    }
+};
+
+FMRadioManager.prototype.unsetAntennaChangeListener = function() {
+
+    antennaCBmanager.FMRadioAntennaUnset();
+    var ret = native_.callSync('FMRadio_UnsetAntennaChangeListener');
+    if (native_.isFailure(ret)) {
+        throw native_.getErrorObject(ret);
+    }
+};
+
+exports = new FMRadioManager();
diff --git a/webWidgetTCT_device/src/radio/radio_extension.cc b/webWidgetTCT_device/src/radio/radio_extension.cc
new file mode 100755 (executable)
index 0000000..968e8a1
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2015 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 "radio/radio_extension.h"
+#include "radio/radio_instance.h"
+
+#include <common/logger.h>
+
+// This will be generated from radio_api.js
+extern const char kSource_radio_api[];
+
+common::Extension* CreateExtension() {
+  return new RadioExtension;
+}
+
+RadioExtension::RadioExtension() {
+  SetExtensionName("tizen.fmradio");
+  SetJavaScriptAPI(kSource_radio_api);
+  LoggerD("RadioExtension()");
+}
+
+RadioExtension::~RadioExtension() {
+}
+
+common::Instance* RadioExtension::CreateInstance() {
+  return new extension::radio::RadioInstance();
+}
diff --git a/webWidgetTCT_device/src/radio/radio_extension.h b/webWidgetTCT_device/src/radio/radio_extension.h
new file mode 100755 (executable)
index 0000000..b3c6cda
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015 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 RADIO_RADIO_EXTENSION_H_
+#define RADIO_RADIO_EXTENSION_H_
+
+#include "common/extension.h"
+
+class RadioExtension : public common::Extension {
+ public:
+  RadioExtension();
+  virtual ~RadioExtension();
+
+ private:
+  virtual common::Instance* CreateInstance();
+};
+
+#endif //RADIO_RADIO_EXTENSION_H_
+
diff --git a/webWidgetTCT_device/src/radio/radio_instance.cc b/webWidgetTCT_device/src/radio/radio_instance.cc
new file mode 100755 (executable)
index 0000000..4773f4b
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 2015 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 "radio/radio_instance.h"
+
+#include <functional>
+
+#include <radio.h>
+
+#include "common/logger.h"
+
+namespace extension {
+namespace radio {
+
+using namespace common;
+using namespace extension::radio;
+
+RadioInstance::RadioInstance()
+    : manager_(*this) {
+  LoggerD("Enter");
+  using std::placeholders::_1;
+  using std::placeholders::_2;
+
+  #define REGISTER_SYNC(c,x) \
+    RegisterSyncHandler(c, std::bind(&RadioInstance::x, this, _1, _2));
+
+  REGISTER_SYNC("FMRadio_Start", Start);
+  REGISTER_SYNC("FMRadio_Stop", Stop);
+  REGISTER_SYNC("FMRadio_SetFMRadioInterruptedListener", SetFMRadioInterruptedListener);
+  REGISTER_SYNC("FMRadio_UnsetFMRadioInterruptedListener", UnsetFMRadioInterruptedListener);
+  REGISTER_SYNC("FMRadio_SetAntennaChangeListener", SetAntennaChangeListener);
+  REGISTER_SYNC("FMRadio_UnsetAntennaChangeListener", UnsetAntennaChangeListener);
+  REGISTER_SYNC("FMRadio_FrequencyGetter", FrequencyGetter);
+  REGISTER_SYNC("FMRadio_SignalStrengthGetter", SignalStrengthGetter);
+  REGISTER_SYNC("FMRadio_IsAntennaConnectedGetter", AntennaGetter);
+  REGISTER_SYNC("FMRadio_RadioStateGetter", StateGetter);
+  REGISTER_SYNC("FMRadio_MuteSetter", MuteSetter);
+  REGISTER_SYNC("FMRadio_MuteGetter", MuteGetter);
+  #undef REGISTER_SYNC
+  #define REGISTER_ASYNC(c,x) \
+    RegisterSyncHandler(c, std::bind(&RadioInstance::x, this, _1, _2));
+  REGISTER_ASYNC("FMRadio_SeekUp", SeekUp);
+  REGISTER_ASYNC("FMRadio_SeekDown", SeekDown);
+  REGISTER_ASYNC("FMRadio_ScanStart", ScanStart);
+  REGISTER_ASYNC("FMRadio_ScanStop", ScanStop);
+  #undef REGISTER_ASYNC
+
+  LoggerD("RadioInstance()");
+}
+
+RadioInstance::~RadioInstance() {
+  LoggerD("Enter");
+}
+
+void RadioInstance::MuteGetter(const picojson::value& args,
+                               picojson::object& out) {
+  LoggerD("Enter");
+  ReportSuccess(picojson::value(manager_.IsMuted()), out);
+}
+
+void RadioInstance::MuteSetter(const picojson::value& args,
+                               picojson::object& out) {
+  LoggerD("Enter");
+  manager_.SetMute(args.get("mute").get<bool>());
+  ReportSuccess(out);
+}
+
+void RadioInstance::AntennaGetter(const picojson::value& args,
+                                  picojson::object& out) {
+  LoggerD("Enter");
+  ReportSuccess(picojson::value(manager_.HasAntenna()), out);
+}
+
+void RadioInstance::StateGetter(const picojson::value& args,
+                                picojson::object& out) {
+  LoggerD("Enter");
+  ReportSuccess(picojson::value(manager_.GetState()), out);
+}
+
+void RadioInstance::FrequencyGetter(const picojson::value& args,
+                                    picojson::object& out) {
+  LoggerD("Enter");
+  ReportSuccess(picojson::value(manager_.GetFrequency()), out);
+}
+
+void RadioInstance::SignalStrengthGetter(const picojson::value& args,
+                                         picojson::object& out) {
+  LoggerD("Enter");
+  ReportSuccess(picojson::value(manager_.GetSignalStrength()), out);
+}
+
+void RadioInstance::SeekUp(const picojson::value& args, picojson::object& out) {
+  LoggerD("Enter");
+  manager_.SeekUp(args.get("callbackId").get<double>());
+  ReportSuccess(out);
+}
+
+void RadioInstance::SeekDown(const picojson::value& args,
+                             picojson::object& out) {
+  LoggerD("Enter");
+  manager_.SeekDown(args.get("callbackId").get<double>());
+  ReportSuccess(out);
+}
+
+void RadioInstance::Start(const picojson::value& args, picojson::object& out) {
+  LoggerD("Enter");
+
+  PlatformResult result = manager_.Start(args.get("frequency").get<double>());
+
+  if (result) {
+    ReportSuccess(out);
+  } else {
+    LoggerE("Failed");
+    ReportError(result, &out);
+  }
+}
+
+void RadioInstance::Stop(const picojson::value& args, picojson::object& out) {
+  LoggerD("Enter");
+
+  PlatformResult result = manager_.Stop();
+
+  if (result) {
+    ReportSuccess(out);
+  } else {
+    LoggerE("Failed");
+    ReportError(result, &out);
+  }
+}
+
+void RadioInstance::ScanStart(const picojson::value& args,
+                              picojson::object& out) {
+  LoggerD("Enter");
+  manager_.ScanStart(args.get("callbackId").get<double>());
+  ReportSuccess(out);
+}
+
+void RadioInstance::ScanStop(const picojson::value& args,
+                             picojson::object& out) {
+  LoggerD("Enter");
+  manager_.ScanStop(args.get("callbackId").get<double>());
+  ReportSuccess(out);
+}
+
+void RadioInstance::SetFMRadioInterruptedListener(const picojson::value& args,
+                                                  picojson::object& out) {
+  LoggerD("Enter");
+
+  PlatformResult result = manager_.SetFMRadioInterruptedListener();
+
+  if (result) {
+    ReportSuccess(out);
+  } else {
+    LoggerE("Failed");
+    ReportError(result, &out);
+  }
+}
+
+void RadioInstance::UnsetFMRadioInterruptedListener(const picojson::value& args,
+                                                    picojson::object& out) {
+  LoggerD("Enter");
+
+  PlatformResult result = manager_.UnsetFMRadioInterruptedListener();
+
+  if (result) {
+    ReportSuccess(out);
+  } else {
+    LoggerE("Failed");
+    ReportError(result, &out);
+  }
+}
+
+void RadioInstance::SetAntennaChangeListener(const picojson::value& args,
+                                             picojson::object& out) {
+  LoggerD("Enter");
+
+  PlatformResult result = manager_.SetAntennaChangeListener();
+
+  if (result) {
+    ReportSuccess(out);
+  } else {
+    LoggerE("Failed");
+    ReportError(result, &out);
+  }
+}
+
+void RadioInstance::UnsetAntennaChangeListener(const picojson::value& args,
+                                               picojson::object& out) {
+  LoggerD("Enter");
+
+  PlatformResult result = manager_.UnsetAntennaChangeListener();
+
+  if (result) {
+    ReportSuccess(out);
+  } else {
+    LoggerE("Failed");
+    ReportError(result, &out);
+  }
+}
+
+} // namespace radio
+} // namespace extension
diff --git a/webWidgetTCT_device/src/radio/radio_instance.h b/webWidgetTCT_device/src/radio/radio_instance.h
new file mode 100755 (executable)
index 0000000..4784906
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2015 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 RADIO_RADIO_INSTANCE_H_
+#define RADIO_RADIO_INSTANCE_H_
+
+#include "common/extension.h"
+#include "common/picojson.h"
+
+#include "radio/radio_manager.h"
+
+namespace extension {
+namespace radio {
+
+class RadioInstance : public common::ParsedInstance {
+ public:
+  RadioInstance();
+  virtual ~RadioInstance();
+
+ private:
+  void MuteGetter(const picojson::value& args, picojson::object& out);
+  void MuteSetter(const picojson::value& args, picojson::object& out);
+  void FrequencyGetter(const picojson::value& args, picojson::object& out);
+  void SignalStrengthGetter(const picojson::value& args, picojson::object& out);
+  void AntennaGetter(const picojson::value& args, picojson::object& out);
+  void StateGetter(const picojson::value& args, picojson::object& out);
+  void SeekUp(const picojson::value& args, picojson::object& out);
+  void SeekDown(const picojson::value& args, picojson::object& out);
+  void ScanStart(const picojson::value& args, picojson::object& out);
+  void ScanStop(const picojson::value& args, picojson::object& out);
+  void Start(const picojson::value& args, picojson::object& out);
+  void Stop(const picojson::value& args, picojson::object& out);
+  void SetFMRadioInterruptedListener(const picojson::value& args, picojson::object& out);
+  void UnsetFMRadioInterruptedListener(const picojson::value& args, picojson::object& out);
+  void SetAntennaChangeListener(const picojson::value& args, picojson::object& out);
+  void UnsetAntennaChangeListener(const picojson::value& args, picojson::object& out);
+
+  FMRadioManager manager_;
+};
+
+} // namespace radio
+} // namespace extension
+
+#endif
diff --git a/webWidgetTCT_device/src/radio/radio_manager.cc b/webWidgetTCT_device/src/radio/radio_manager.cc
new file mode 100755 (executable)
index 0000000..e75970e
--- /dev/null
@@ -0,0 +1,544 @@
+/*
+ * Copyright (c) 2015 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 "radio_manager.h"
+
+#include <unistd.h>
+#include <cstring>
+#include <algorithm>
+#include <glib.h>
+#include <runtime_info.h>
+#include <vconf.h>
+
+#include "common/logger.h"
+#include "common/extension.h"
+#include "common/task-queue.h"
+
+#include "radio/radio_instance.h"
+
+using namespace common;
+using namespace std;
+
+namespace extension {
+namespace radio {
+
+namespace {
+
+const int kLowestFrequency = 87500;
+const int kHighestFrequency = 108000;
+
+const char* RADIO_STATE_ERROR = "ERROR";
+std::map<radio_state_e, const char*> radio_state = {
+  { RADIO_STATE_READY, "READY" },
+  { RADIO_STATE_PLAYING, "PLAYING" },
+  { RADIO_STATE_SCANNING, "SCANNING" },
+};
+static const double FREQ_LOWER = 87.5;
+
+static void AddCallbackID(double callbackId, picojson::object* obj) {
+  obj->insert(std::make_pair("callbackId", picojson::value(callbackId)));
+}
+
+PlatformResult GetPlatformResult(const std::string& str, int err) {
+  LoggerD("Enter");
+
+  string message = str + " : " + to_string(err);
+
+  switch (err) {
+    case RADIO_ERROR_INVALID_PARAMETER:
+      return PlatformResult(ErrorCode::INVALID_VALUES_ERR, message);
+
+    case RADIO_ERROR_INVALID_STATE:
+      return PlatformResult(ErrorCode::INVALID_STATE_ERR, message);
+
+    case RADIO_ERROR_NOT_SUPPORTED:
+      return PlatformResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR, message);
+
+    default:
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, message);
+  }
+}
+
+PlatformResult CheckError(const std::string& str, int err) {
+  LoggerE("%s() error %d", str.c_str(), err);
+
+  switch (err) {
+    case RADIO_ERROR_NONE:
+      return PlatformResult(ErrorCode::NO_ERROR);
+
+    default:
+      return GetPlatformResult(str, err);
+  }
+}
+
+string TranslateInterruptedCode(int code) {
+  LoggerD("Enter");
+#define STRINGIFY(c) case c: return #c
+  switch (code) {
+    STRINGIFY(RADIO_INTERRUPTED_BY_MEDIA);
+    STRINGIFY(RADIO_INTERRUPTED_BY_CALL);
+    STRINGIFY(RADIO_INTERRUPTED_BY_EARJACK_UNPLUG);
+    STRINGIFY(RADIO_INTERRUPTED_BY_RESOURCE_CONFLICT);
+    STRINGIFY(RADIO_INTERRUPTED_BY_ALARM);
+    STRINGIFY(RADIO_INTERRUPTED_BY_EMERGENCY);
+    STRINGIFY(RADIO_INTERRUPTED_BY_RESUMABLE_MEDIA);
+    STRINGIFY(RADIO_INTERRUPTED_BY_NOTIFICATION);
+    default: return "UNKNOWN_INTERRUPTED_ERROR_CODE";
+  }
+#undef STRINGIFY
+}
+
+int TokHz(double frequency) {
+  return static_cast<int>(frequency * 1000.0);
+}
+
+double ToMHz(int frequency) {
+  return static_cast<double>(frequency) / 1000.0;
+}
+
+struct RadioData {
+  explicit RadioData(FMRadioManager& manager)
+      : manager_(manager),
+        callback_id_(0.0) {
+  }
+
+  FMRadioManager& manager_;
+  double callback_id_;
+};
+
+struct RadioScanData : public RadioData {
+  using RadioData::RadioData;
+  std::vector<int> frequencies_;
+};
+
+void RadioSeekCallback(int frequency, void* user_data) {
+  LoggerD("Enter, freq: %d", frequency);
+
+  RadioData* data = static_cast<RadioData*>(user_data);
+
+  if (frequency >= kLowestFrequency && frequency <= kHighestFrequency) {
+    common::TaskQueue::GetInstance().Async(std::bind(
+      &FMRadioManager::PostResultCallbackSuccess, &data->manager_,
+      data->callback_id_));
+  } else {
+    common::TaskQueue::GetInstance().Async(std::bind(
+      &FMRadioManager::PostResultFailure, &data->manager_,
+      data->callback_id_, PlatformResult(ErrorCode::UNKNOWN_ERR,
+        "Unsupported frequency")));
+  }
+  delete data;
+}
+
+void ScanStartCallback(int frequency, void* user_data) {
+  LoggerD("Enter");
+
+  RadioScanData* data = static_cast<RadioScanData*>(user_data);
+  data->frequencies_.push_back(frequency);
+
+  picojson::value event{picojson::object()};
+  auto& obj = event.get<picojson::object>();
+  obj.insert(std::make_pair("frequency", picojson::value(ToMHz(frequency))));
+  obj.insert(std::make_pair("listenerId", picojson::value("FMRadio_Onfrequencyfound")));
+  common::TaskQueue::GetInstance().Async(std::bind(
+    &FMRadioManager::PostMessage, &data->manager_, event.serialize()));
+}
+
+void PostAsyncSuccess(FMRadioManager* manager, double callbackId, picojson::value* event) {
+  manager->PostResultSuccess(callbackId, event);
+  delete event;
+}
+
+void ScanCompleteCallback(void* user_data) {
+  LoggerD("Enter");
+
+  RadioScanData* data = static_cast<RadioScanData*>(user_data);
+
+  picojson::value* event = new picojson::value(picojson::object());
+  auto& obj = event->get<picojson::object>();
+  obj.insert(std::make_pair("name", picojson::value("onfinished")));
+
+  picojson::array frequencies;
+  for (auto frequency : data->frequencies_) {
+    frequencies.push_back(picojson::value(ToMHz(frequency)));
+  }
+
+  obj.insert(std::make_pair("frequencies", picojson::value(frequencies)));
+  common::TaskQueue::GetInstance().Async(std::bind(&PostAsyncSuccess,
+    &data->manager_, data->callback_id_, event));
+
+  delete data;
+}
+
+void ScanStopCallback(void *user_data) {
+  LoggerD("Enter");
+  RadioData* data = static_cast<RadioData*>(user_data);
+
+  common::TaskQueue::GetInstance().Async(std::bind(
+    &FMRadioManager::PostResultCallbackSuccess, &data->manager_, data->callback_id_));
+  delete data;
+}
+
+void RadioInterruptedCallback(radio_interrupted_code_e code, void *user_data) {
+  LoggerD("Enter");
+
+  picojson::value event{picojson::object()};
+  auto& obj = event.get<picojson::object>();
+
+  obj.insert(std::make_pair("listenerId", picojson::value("FMRadio_Interrupted")));
+
+  if (code == RADIO_INTERRUPTED_COMPLETED) {
+    obj.insert(
+        std::make_pair("action", picojson::value("oninterruptfinished")));
+  } else {
+    obj.insert(std::make_pair("action", picojson::value("oninterrupted")));
+    obj.insert(std::make_pair("reason", picojson::value(TranslateInterruptedCode(code))));
+  }
+
+  FMRadioManager* manager = static_cast<FMRadioManager*>(user_data);
+  common::TaskQueue::GetInstance().Async(std::bind(
+    &FMRadioManager::PostMessage, manager, event.serialize()));
+}
+
+
+void RadioAntennaCallback(runtime_info_key_e key, void* user_data) {
+  LoggerD("Enter");
+
+  bool connected = false;
+  const auto err = runtime_info_get_value_bool(key, &connected);
+  if (RADIO_ERROR_NONE != err) {
+    LoggerE("runtime_info_get_value_bool() failed: %d", err);
+  }
+
+  picojson::value event{picojson::object()};
+  auto& obj = event.get<picojson::object>();
+
+  obj.insert(std::make_pair("connected", picojson::value(connected)));
+  obj.insert(std::make_pair("listenerId", picojson::value("FMRadio_Antenna")));
+
+  FMRadioManager* manager = static_cast<FMRadioManager*>(user_data);
+  common::TaskQueue::GetInstance().Async(std::bind(
+    &FMRadioManager::PostMessage, manager, event.serialize()));
+}
+
+} // namespace
+
+bool FMRadioManager::IsMuted() {
+  LoggerD("Enter");
+
+  bool muted = false;
+  const auto err = radio_is_muted(radio_instance_, &muted);
+
+  if (RADIO_ERROR_NONE != err) {
+    LoggerE("radio_is_muted() failed: %d", err);
+  }
+
+  return muted;
+}
+
+void FMRadioManager::SetMute(bool mute) {
+  LoggerD("Enter");
+
+  const auto err = radio_set_mute(radio_instance_, mute);
+
+  if (RADIO_ERROR_NONE != err) {
+    LoggerE("radio_set_mute() failed: %d", err);
+  }
+}
+
+bool FMRadioManager::HasAntenna() {
+  LoggerD("Enter");
+
+  bool connected = false;
+  const auto err = runtime_info_get_value_bool(RUNTIME_INFO_KEY_AUDIO_JACK_CONNECTED,
+                                               &connected);
+
+  if (RUNTIME_INFO_ERROR_NONE != err) {
+    LoggerE("runtime_info_get_value_bool() failed: %d", err);
+  }
+
+  return connected;
+}
+
+const char* FMRadioManager::GetState() {
+  LoggerD("Enter");
+
+  radio_state_e state;
+
+  const auto err = radio_get_state(radio_instance_, &state);
+
+  if (RADIO_ERROR_NONE != err) {
+    LoggerE("radio_get_state() failed: %d", err);
+    return RADIO_STATE_ERROR;
+  }
+
+  const auto s = radio_state.find(state);
+
+  if (radio_state.end() != s) {
+    return s->second;
+  } else {
+    LoggerE("Unknown state: %d", state);
+    return RADIO_STATE_ERROR;
+  }
+}
+
+PlatformResult FMRadioManager::SetFrequency(double frequency) {
+  LoggerD("Enter");
+  return CheckError("radio_set_frequency", radio_set_frequency(radio_instance_, TokHz(frequency)));
+}
+
+double FMRadioManager::GetFrequency() {
+  LoggerD("Enter");
+
+  int frequency = 0;
+  const auto err = radio_get_frequency(radio_instance_, &frequency);
+
+  if (RADIO_ERROR_NONE != err) {
+    LoggerE("radio_get_frequency() failed: %d", err);
+    return FREQ_LOWER;
+  } else {
+    LoggerD("Frequency: %d", frequency);
+    return ToMHz(frequency);
+  }
+}
+
+double FMRadioManager::GetSignalStrength() {
+  LoggerD("Enter");
+
+  int strength = 0;
+  const auto err = radio_get_signal_strength(radio_instance_, &strength);
+
+  if (RADIO_ERROR_NONE != err) {
+    LoggerE("radio_get_signal_strength() failed: %d", err);
+    return 0;
+  } else {
+    return strength;
+  }
+}
+
+FMRadioManager::FMRadioManager(RadioInstance& instance)
+    : instance_(instance),
+      radio_instance_(nullptr) {
+  LoggerD("Enter");
+
+  const auto err = radio_create(&radio_instance_);
+
+  if (RADIO_ERROR_NONE != err) {
+    LoggerE("radio_create() failed: %d", err);
+    radio_instance_ = nullptr;
+  }
+}
+
+FMRadioManager::~FMRadioManager() {
+  LoggerD("Enter");
+
+  if (radio_instance_) {
+    const auto err = radio_destroy(radio_instance_);
+
+    if (RADIO_ERROR_NONE != err) {
+      LoggerE("radio_destroy() failed: %d", err);
+    }
+
+    radio_instance_ = nullptr;
+  }
+}
+
+PlatformResult FMRadioManager::Start(double frequency) {
+  LoggerD("Enter, frequency: %f", frequency);
+
+  radio_state_e state;
+  const auto err = radio_get_state(radio_instance_, &state);
+
+  if (RADIO_ERROR_NONE != err) {
+    LoggerE("radio_get_state() failed: %d", err);
+    return GetPlatformResult("radio_get_state() failed.", err);
+  }
+
+  if (RADIO_STATE_READY != state) {
+    if (RADIO_STATE_PLAYING == state) {
+      return PlatformResult(ErrorCode::NO_ERROR);
+    }
+    return PlatformResult(ErrorCode::INVALID_STATE_ERR, "Invalid radio state.");
+  }
+
+  PlatformResult result = SetFrequency(frequency);
+
+  if (!result) {
+    return result;
+  }
+
+  return CheckError("radio_start", radio_start(radio_instance_));
+}
+
+PlatformResult FMRadioManager::Stop() {
+  LoggerD("Enter");
+
+  radio_state_e state;
+  const auto err = radio_get_state(radio_instance_, &state);
+
+  if (RADIO_ERROR_NONE != err) {
+    LoggerE("radio_get_state() failed: %d", err);
+    return GetPlatformResult("radio_get_state() failed.", err);
+  }
+
+  if (RADIO_STATE_PLAYING != state) {
+    return PlatformResult(ErrorCode::INVALID_STATE_ERR, "Invalid radio state.");
+  }
+
+  return CheckError("radio_stop", radio_stop(radio_instance_));
+}
+
+void FMRadioManager::SeekUp(double callback_id) {
+  LoggerD("Enter");
+
+  RadioData* user_data = new RadioData(*this);
+  user_data->callback_id_ = callback_id;
+
+  const auto err = radio_seek_up(radio_instance_, RadioSeekCallback, user_data);
+
+  if (RADIO_ERROR_NONE != err) {
+    LoggerE("Failed");
+    PostResultFailure(callback_id, GetPlatformResult("radio_seek_up", err));
+    delete user_data;
+  }
+}
+
+void FMRadioManager::SeekDown(double callback_id) {
+  LoggerD("Enter");
+
+  RadioData* user_data = new RadioData(*this);
+  user_data->callback_id_ = callback_id;
+
+  const auto err = radio_seek_down(radio_instance_, RadioSeekCallback, user_data);
+
+  if (RADIO_ERROR_NONE != err) {
+    LoggerE("Failed");
+    PostResultFailure(callback_id, GetPlatformResult("radio_seek_down", err));
+    delete user_data;
+  }
+}
+
+void FMRadioManager::ScanStart(double callback_id) {
+  LoggerD("Enter");
+
+  RadioScanData* user_data = new RadioScanData(*this);
+  user_data->callback_id_ = callback_id;
+
+  auto err = radio_set_scan_completed_cb(radio_instance_, ScanCompleteCallback,
+                                         user_data);
+  if (RADIO_ERROR_NONE != err) {
+    PostResultFailure(callback_id,
+                      GetPlatformResult("radio_set_scan_completed_cb", err));
+    delete user_data;
+    return;
+  }
+
+  err = radio_scan_start(radio_instance_, ScanStartCallback, user_data);
+  if (RADIO_ERROR_NONE != err) {
+    radio_unset_scan_completed_cb(radio_instance_);
+    PostResultFailure(callback_id, GetPlatformResult("radio_scan_start", err));
+    delete user_data;
+  }
+}
+
+void FMRadioManager::ScanStop(double callback_id) {
+  LoggerD("Enter");
+
+  RadioScanData* user_data = new RadioScanData(*this);
+  user_data->callback_id_ = callback_id;
+
+  auto err = radio_unset_scan_completed_cb(radio_instance_);
+  if (RADIO_ERROR_NONE != err) {
+    LoggerE("Failed");
+    PostResultFailure(callback_id,
+                      GetPlatformResult("radio_unset_scan_completed_cb", err));
+    delete user_data;
+    return;
+  }
+
+  err = radio_scan_stop(radio_instance_, ScanStopCallback, user_data);
+  if (RADIO_ERROR_NONE != err) {
+    LoggerE("Failed");
+    PostResultFailure(callback_id, GetPlatformResult("radio_scan_stop", err));
+    delete user_data;
+  }
+}
+
+common::PlatformResult FMRadioManager::SetFMRadioInterruptedListener() {
+  LoggerD("Enter");
+
+  const auto err = radio_set_interrupted_cb(radio_instance_,
+                                            RadioInterruptedCallback,
+                                            this);
+  return CheckError("radio_set_interrupted_cb", err);
+}
+
+common::PlatformResult FMRadioManager::UnsetFMRadioInterruptedListener() {
+  LoggerD("Enter");
+
+  const auto err = radio_unset_interrupted_cb(radio_instance_);
+  return CheckError("radio_unset_interrupted_cb", err);
+}
+
+common::PlatformResult FMRadioManager::SetAntennaChangeListener() {
+  LoggerD("Enter");
+
+  const auto err = runtime_info_set_changed_cb(
+                            RUNTIME_INFO_KEY_AUDIO_JACK_CONNECTED,
+                            RadioAntennaCallback,
+                            this);
+  return CheckError("runtime_info_set_changed_cb", err);
+}
+
+common::PlatformResult FMRadioManager::UnsetAntennaChangeListener() {
+  LoggerD("Enter");
+
+  const auto err = runtime_info_unset_changed_cb(RUNTIME_INFO_KEY_AUDIO_JACK_CONNECTED);
+  return CheckError("runtime_info_unset_changed_cb", err);
+}
+
+void FMRadioManager::PostMessage(const std::string& msg) const {
+  LoggerD("Enter");
+
+  Instance::PostMessage(&instance_, msg.c_str());
+}
+void FMRadioManager::PostResultSuccess(double callbackId, picojson::value* event) const {
+  auto& obj = event->get<picojson::object>();
+
+  tools::ReportSuccess(obj);
+  AddCallbackID(callbackId, &obj);
+
+  PostMessage(event->serialize());
+}
+
+void FMRadioManager::PostResultCallbackSuccess(double callbackId) const {
+  picojson::value event{picojson::object()};
+
+  PostResultSuccess(callbackId, &event);
+}
+
+void FMRadioManager::PostResultFailure(double callbackId, const PlatformResult& result) const {
+  picojson::value event{picojson::object()};
+  auto& obj = event.get<picojson::object>();
+
+  tools::ReportError(result, &obj);
+  AddCallbackID(callbackId, &obj);
+
+  PostMessage(event.serialize());
+}
+
+} // namespace radio
+} // namespace extension
+
diff --git a/webWidgetTCT_device/src/radio/radio_manager.h b/webWidgetTCT_device/src/radio/radio_manager.h
new file mode 100755 (executable)
index 0000000..614f415
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2015 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 FMRADIO_FMRADIO_MANAGER_H_
+#define FMRADIO_FMRADIO_MANAGER_H_
+
+#include <list>
+#include <string>
+#include <vector>
+#include <mutex>
+
+#include <radio.h>
+#include <runtime_info.h>
+
+#include "common/picojson.h"
+#include "common/platform_result.h"
+
+namespace extension {
+namespace radio {
+
+class RadioInstance;
+
+class FMRadioManager {
+ public:
+  explicit FMRadioManager(RadioInstance& instance);
+  // FMRadioManager destroys radio_h in destructor, so it cannot be copyable
+  FMRadioManager(const FMRadioManager& other) = delete;
+  ~FMRadioManager();
+
+  common::PlatformResult Start(double freq);
+  common::PlatformResult Stop();
+  void SeekUp(double callback_id);
+  void SeekDown(double callback_id);
+  void ScanStart(double callback_id);
+  void ScanStop(double callback_id);
+  common::PlatformResult SetFMRadioInterruptedListener();
+  common::PlatformResult UnsetFMRadioInterruptedListener();
+  common::PlatformResult SetAntennaChangeListener();
+  common::PlatformResult UnsetAntennaChangeListener();
+
+  bool IsMuted();
+  void SetMute(bool mute);
+  common::PlatformResult SetFrequency(double frequency);
+  double GetFrequency();
+  double GetSignalStrength();
+  bool HasAntenna();
+  const char* GetState();
+
+  void PostMessage(const std::string& msg) const;
+  void PostResultSuccess(double callbackId, picojson::value* event) const;
+  void PostResultCallbackSuccess(double callbackId) const;
+  void PostResultFailure(double callbackId, const common::PlatformResult& result) const;
+
+ private:
+  RadioInstance& instance_;
+  radio_h radio_instance_;
+};
+
+} // namespace radio
+} // namespace extension
+
+#endif // RADIO_RADIO_MANAGER_H_
diff --git a/webWidgetTCT_device/src/secureelement/secureelement.gyp b/webWidgetTCT_device/src/secureelement/secureelement.gyp
new file mode 100755 (executable)
index 0000000..a302c6a
--- /dev/null
@@ -0,0 +1,37 @@
+{
+  'includes':[
+    '../common/common.gypi',
+  ],
+  'targets': [
+    {
+      'target_name': 'tizen_secureelement',
+      'type': 'loadable_module',
+      'dependencies': [
+        '../common/common.gyp:tizen_common',
+      ],
+      'sources': [
+        'secureelement_api.js',
+        'secureelement_extension.cc',
+        'secureelement_extension.h',
+        'secureelement_instance.cc',
+        'secureelement_instance.h',
+        'secureelement_seservice.cc',
+        'secureelement_seservice.h',
+        'secureelement_reader.cc',
+        'secureelement_reader.h',
+        'secureelement_session.cc',
+        'secureelement_session.h',
+        'secureelement_channel.cc',
+        'secureelement_channel.h',
+      ],
+      'includes': [
+        '../common/pkg-config.gypi',
+      ],
+      'conditions': [
+        [ 'tizen == 1', {
+            'variables': { 'packages': ['smartcard-service', 'smartcard-service-common'] },
+        }],
+      ],
+    },
+  ],
+}
diff --git a/webWidgetTCT_device/src/secureelement/secureelement_api.js b/webWidgetTCT_device/src/secureelement/secureelement_api.js
new file mode 100755 (executable)
index 0000000..9398573
--- /dev/null
@@ -0,0 +1,366 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+var validator_ = xwalk.utils.validator;
+var privilege_ = xwalk.utils.privilege;
+var types_ = validator_.Types;
+var type_utils = xwalk.utils.type;
+var native_ = new xwalk.utils.NativeManager(extension);
+
+//////////////////SEService/////////////////
+
+function ListenerManager(native, listenerName) {
+    this.listeners = {};
+    this.nextId = 1;
+    this.nativeSet = false;
+    this.native = native;
+    this.listenerName = listenerName;
+};
+
+ListenerManager.prototype.onListenerCalled = function(msg) {
+    var d = undefined;
+    switch (msg.action) {
+    case 'onSEReady':
+    case 'onSENotReady':
+        d = new Reader(msg.handle);
+        break;
+    default:
+        console.log('Unknown mode: ' + msg.action);
+        return;
+    }
+
+    for (var watchId in this.listeners) {
+        if (this.listeners.hasOwnProperty(watchId) && this.listeners[watchId][msg.action]) {
+            this.listeners[watchId][msg.action](d);
+        }
+    }
+};
+
+ListenerManager.prototype.addListener = function(callback) {
+    xwalk.utils.checkPrivilegeAccess(privilege_.SECUREELEMENT);
+
+    var id = this.nextId;
+    if (!this.nativeSet) {
+        this.native.addListener(this.listenerName, this.onListenerCalled.bind(this));
+        this.native.callSync('SEService_registerSEListener');
+        this.nativeSet = true;
+    }
+
+    this.listeners[id] = callback;
+    ++this.nextId;
+
+    return id;
+};
+
+ListenerManager.prototype.removeListener = function(watchId) {
+    xwalk.utils.checkPrivilegeAccess(privilege_.SECUREELEMENT);
+
+    if (this.listeners.hasOwnProperty(watchId)) {
+      delete this.listeners[watchId];
+    }
+
+    if (this.nativeSet && type_utils.isEmptyObject(this.listeners)) {
+        this.native.callSync('SEService_unregisterSEListener');
+        this.native.removeListener(this.listenerName);
+        this.nativeSet = false;
+    }
+};
+
+var SE_CHANGE_LISTENER = 'SecureElementChangeListener';
+var SEChangeListener = new ListenerManager(native_, SE_CHANGE_LISTENER);
+
+function SEService() {
+}
+
+SEService.prototype.getReaders = function() {
+    xwalk.utils.checkPrivilegeAccess(privilege_.SECUREELEMENT);
+
+    var args = validator_.validateArgs(arguments, [
+        { name: "successCallback", type: types_.FUNCTION },
+        { name: "errorCallback", type: types_.FUNCTION, optional: true, nullable: true }
+    ]);
+
+    var callback = function(result) {
+        if(native_.isFailure(result)) {
+            native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+        } else {
+            var result_obj = native_.getResultObject(result);
+            var readers_array = [];
+
+            result_obj.forEach(function (data) {
+                readers_array.push(new Reader(data));
+            });
+
+            args.successCallback(readers_array);
+        }
+    };
+
+    native_.call('SEService_getReaders', {}, callback);
+};
+
+SEService.prototype.registerSEListener = function() {
+    var args = validator_.validateArgs(arguments, [
+        {
+            name : 'eventCallback',
+            type : types_.LISTENER,
+            values: ['onSEReady', 'onSENotReady']
+        }
+    ]);
+
+    return SEChangeListener.addListener(args.eventCallback);
+};
+
+SEService.prototype.unregisterSEListener = function() {
+    var args = validator_.validateArgs(arguments, [
+        {
+            name : 'id',
+            type : types_.UNSIGNED_LONG
+        }
+    ]);
+
+    SEChangeListener.removeListener(args.id);
+}
+
+SEService.prototype.shutdown = function() {
+    xwalk.utils.checkPrivilegeAccess(privilege_.SECUREELEMENT);
+
+    var result = native_.callSync('SEService_shutdown', {});
+
+    if (native_.isFailure(result)) {
+        throw native_.getErrorObject(result);
+    }
+};
+
+//////////////////Reader/////////////////
+
+function Reader(reader_handle) {
+    Object.defineProperties(this, {
+        isPresent:  {   configurable: false,
+                        enumerable: true,
+                        set: function() {},
+                        get: function() {
+                            var callArgs = { handle: reader_handle };
+                            var result = native_.callSync('SEReader_isPresent', callArgs);
+                            if (native_.isFailure(result)) {
+                              console.log('SEReader_isPresent error: ' + native_.getErrorObject(result));
+                              return false;
+                            } else {
+                              return native_.getResultObject(result).isPresent;
+                            }
+                        }},
+        _handle:    {   configurable: false,
+                        enumerable: false,
+                        set: function() {},
+                        get: function() { return reader_handle }}
+    });
+}
+
+Reader.prototype.getName = function() {
+    xwalk.utils.checkPrivilegeAccess(privilege_.SECUREELEMENT);
+
+    var callArgs = { handle: this._handle };
+    var result = native_.callSync('SEReader_getName', callArgs);
+
+    if(native_.isFailure(result)) {
+        throw native_.getErrorObject(result);
+    }
+
+    return native_.getResultObject(result).name;
+};
+
+Reader.prototype.openSession = function() {
+    xwalk.utils.checkPrivilegeAccess(privilege_.SECUREELEMENT);
+
+    var args = validator_.validateArgs(arguments, [
+        { name: "successCallback", type: types_.FUNCTION },
+        { name: "errorCallback", type: types_.FUNCTION, optional: true, nullable: true }
+    ]);
+
+    var callback = function(result) {
+        if(native_.isFailure(result)) {
+            native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+        } else {
+            var result_obj = native_.getResultObject(result);
+            var session = new Session(result_obj.handle);
+            args.successCallback(session);
+        }
+    };
+
+    var callArgs = { handle: this._handle };
+
+    native_.call('SEReader_openSession', callArgs, callback);
+};
+
+Reader.prototype.closeSessions = function() {
+    xwalk.utils.checkPrivilegeAccess(privilege_.SECUREELEMENT);
+    var callArgs = { handle: this._handle };
+    var result = native_.callSync('SEReader_closeSessions', callArgs);
+    if (native_.isFailure(result)) {
+      throw native_.getErrorObject(result);
+    }
+};
+
+//////////////////Channel/////////////////
+
+function Channel( channel_handle, is_basic_channel) {
+    Object.defineProperties(this, {
+        _handle:    { enumerable: false, configurable: false, set: function() {}, get: function() { return channel_handle }},
+        isBasicChannel:   { enumerable: true, configurable: false, set: function() {}, get: function() { return is_basic_channel }}
+    });
+}
+
+Channel.prototype.close = function() {
+    xwalk.utils.checkPrivilegeAccess(privilege_.SECUREELEMENT);
+    var callArgs = { handle: this._handle };
+    native_.callSync('SEChannel_close', callArgs);
+};
+
+Channel.prototype.transmit = function() {
+    xwalk.utils.checkPrivilegeAccess(privilege_.SECUREELEMENT);
+
+    var args = validator_.validateArgs(arguments, [
+        { name: "command", type: types_.ARRAY, values: types_.BYTE },
+        { name: "successCallback", type: types_.FUNCTION },
+        { name: "errorCallback", type: types_.FUNCTION, optional: true, nullable: true }
+    ]);
+
+    var callback = function(result) {
+        if ( native_.isFailure(result)) {
+            native_.callIfPossible( args.errorCallback, native_.getErrorObject(result));
+        } else {
+            var result_obj = native_.getResultObject(result);
+            args.successCallback(result_obj.response);
+        }
+    }
+
+    var callArgs = {
+        handle: this._handle,
+        command: args.command
+    };
+
+    native_.call('SEChannel_transmit', callArgs, callback);
+}
+
+Channel.prototype.getSelectResponse = function() {
+    xwalk.utils.checkPrivilegeAccess(privilege_.SECUREELEMENT);
+    var callArgs = { handle: this._handle };
+    native_.callSync('SEChannel_getSelectResponse', callArgs);
+}
+
+//////////////////Session/////////////////
+
+function Session(session_handle) {
+    Object.defineProperties(this, {
+        isClosed:   { configurable: false,
+                      enumerable: true,
+                      set: function() {},
+                      get: function() {
+                        var callArgs = { handle: session_handle };
+                        var result = native_.callSync('SESession_isClosed', callArgs);
+                        if (native_.isFailure(result)) {
+                          console.log('SESession_isClosed error: ' + native_.getErrorObject(result));
+                          return true;
+                        } else {
+                          return native_.getResultObject(result).isClosed;
+                        }
+                      }
+                    },
+        _handle:    { enumerable: false,
+                      configurable: false,
+                      set: function() {},
+                      get: function() { return session_handle }}
+    });
+}
+
+Session.prototype.openBasicChannel = function() {
+    xwalk.utils.checkPrivilegeAccess(privilege_.SECUREELEMENT);
+
+    var args = validator_.validateArgs(arguments, [
+        { name: "aid", type: types_.ARRAY, values: types_.BYTE },
+        { name: "successCallback", type: types_.FUNCTION },
+        { name: "errorCallback", type: types_.FUNCTION, optional: true, nullable: true }
+    ]);
+
+    var callback = function(result) {
+        if ( native_.isFailure(result)) {
+            native_.callIfPossible( args.errorCallback, native_.getErrorObject(result));
+        } else {
+            var result_obj = native_.getResultObject(result);
+            var channel = new Channel( result_obj.handle, result_obj.isBasicChannel);
+            args.successCallback(channel);
+        }
+    }
+
+    var callArgs = {
+        handle: this._handle,
+        aid: args.aid
+    };
+
+    native_.call('SESession_openBasicChannel', callArgs, callback);
+};
+
+Session.prototype.openLogicalChannel = function() {
+    xwalk.utils.checkPrivilegeAccess(privilege_.SECUREELEMENT);
+
+    var args = validator_.validateArgs(arguments, [
+        { name: "aid", type: types_.ARRAY, values: types_.BYTE },
+        { name: "successCallback", type: types_.FUNCTION },
+        { name: "errorCallback", type: types_.FUNCTION, optional: true, nullable: true }
+    ]);
+
+    var callback = function(result) {
+        if ( native_.isFailure(result)) {
+            native_.callIfPossible( args.errorCallback, native_.getErrorObject(result));
+        } else {
+            var result_obj = native_.getResultObject(result);
+            var channel = new Channel( result_obj.handle, result_obj.isBasicChannel);
+            args.successCallback(channel);
+        }
+    }
+
+    var callArgs = {
+        handle: this._handle,
+        aid: args.aid
+    };
+
+    native_.call('SESession_openLogicalChannel', callArgs, callback);
+}
+
+Session.prototype.getATR = function() {
+    xwalk.utils.checkPrivilegeAccess(privilege_.SECUREELEMENT);
+    var callArgs = { handle: this._handle };
+    var result = native_.callSync('SESession_getATR', callArgs);
+    if (native_.isFailure(result)) {
+        throw native_.getErrorObject(result);
+    } else {
+        return native_.getResultObject(result);
+    }
+}
+
+Session.prototype.close = function() {
+    xwalk.utils.checkPrivilegeAccess(privilege_.SECUREELEMENT);
+    var callArgs = { handle: this._handle };
+    native_.callSync('SESession_close', callArgs);
+}
+
+Session.prototype.closeChannels = function() {
+    xwalk.utils.checkPrivilegeAccess(privilege_.SECUREELEMENT);
+    var callArgs = { handle: this._handle };
+    native_.callSync('SESession_closeChannels', callArgs);
+}
+
+
+exports = new SEService();
diff --git a/webWidgetTCT_device/src/secureelement/secureelement_channel.cc b/webWidgetTCT_device/src/secureelement/secureelement_channel.cc
new file mode 100755 (executable)
index 0000000..e7355d3
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2015 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 "common/picojson.h"
+#include "common/logger.h"
+#include "secureelement_channel.h"
+
+using namespace smartcard_service_api;
+
+namespace extension {
+namespace secureelement {
+
+void SEChannel::close() {
+    LoggerD("Entered");
+    if (m_channel_ptr && !m_channel_ptr->isClosed()) {
+        m_channel_ptr->closeSync();
+    }
+}
+
+
+ByteArray SEChannel::transmit(const picojson::array& v_command) {
+    LoggerD("Entered");
+    ByteArray response;
+    if ( m_channel_ptr) {
+        size_t v_command_size = v_command.size();
+        uint8_t* command = new uint8_t[v_command_size];
+        for (size_t i = 0; i < v_command_size; i++) {
+            command[i] = (uint8_t) static_cast<long>(v_command[i].get<double>());
+        }
+        ByteArray ba_command(command, v_command.size());
+        delete [] command;
+        m_channel_ptr->transmitSync( ba_command, response);
+    }
+    return response;
+}
+
+
+ByteArray SEChannel::getSelectResponse() {
+    LoggerD("Entered");
+    ByteArray response;
+    if ( m_channel_ptr) {
+        response = m_channel_ptr->getSelectResponse();
+    }
+    return response;
+}
+
+} // secureelement
+} // extension
diff --git a/webWidgetTCT_device/src/secureelement/secureelement_channel.h b/webWidgetTCT_device/src/secureelement/secureelement_channel.h
new file mode 100755 (executable)
index 0000000..4d62643
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2015 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_CHANNEL_H_
+#define SECUREELEMENT_CHANNEL_H_
+
+#include <ClientChannel.h>
+#include "common/picojson.h"
+
+namespace extension {
+namespace secureelement {
+
+class SEChannel {
+public:
+    SEChannel( smartcard_service_api::ClientChannel* channel_ptr) : m_channel_ptr(channel_ptr) {};
+    virtual ~SEChannel() {};
+    void close();
+    smartcard_service_api::ByteArray transmit(const picojson::array& v_command);
+    smartcard_service_api::ByteArray getSelectResponse();
+private:
+    smartcard_service_api::ClientChannel* m_channel_ptr;
+};
+
+} // secureelement
+} // extension
+
+#endif // SECUREELEMENT_CHANNEL_H_
diff --git a/webWidgetTCT_device/src/secureelement/secureelement_extension.cc b/webWidgetTCT_device/src/secureelement/secureelement_extension.cc
new file mode 100755 (executable)
index 0000000..0035898
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2015 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 "secureelement/secureelement_extension.h"
+
+#include "secureelement/secureelement_instance.h"
+
+common::Extension* CreateExtension() {
+  return new SecureElementExtension;
+}
+
+// This will be generated from secureelement_api.js.
+extern const char kSource_secureelement_api[];
+
+SecureElementExtension::SecureElementExtension() {
+  SetExtensionName("tizen.seService");
+  SetJavaScriptAPI(kSource_secureelement_api);
+}
+
+SecureElementExtension::~SecureElementExtension() {}
+
+common::Instance* SecureElementExtension::CreateInstance() {
+  return new extension::secureelement::SecureElementInstance();
+}
diff --git a/webWidgetTCT_device/src/secureelement/secureelement_extension.h b/webWidgetTCT_device/src/secureelement/secureelement_extension.h
new file mode 100755 (executable)
index 0000000..377925f
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2015 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_SECUREELEMENT_EXTENSION_H_
+#define SECUREELEMENT_SECUREELEMENT_EXTENSION_H_
+
+#include "common/extension.h"
+
+class SecureElementExtension : public common::Extension {
+public:
+    SecureElementExtension();
+    virtual ~SecureElementExtension();
+private:
+    // common::Extension implementation.
+    virtual common::Instance* CreateInstance();
+};
+
+#endif  // SECUREELEMENT_SECUREELEMENT_EXTENSION_H_
diff --git a/webWidgetTCT_device/src/secureelement/secureelement_instance.cc b/webWidgetTCT_device/src/secureelement/secureelement_instance.cc
new file mode 100755 (executable)
index 0000000..e486668
--- /dev/null
@@ -0,0 +1,381 @@
+/*
+ * Copyright (c) 2015 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 "secureelement/secureelement_instance.h"
+
+#include <SEService.h>
+#include <Reader.h>
+#include "common/picojson.h"
+#include "common/logger.h"
+#include "common/task-queue.h"
+
+#include "secureelement_reader.h"
+#include "secureelement_session.h"
+#include "secureelement_channel.h"
+
+namespace extension {
+namespace secureelement {
+
+using namespace common;
+using namespace smartcard_service_api;
+
+SecureElementInstance::SecureElementInstance()
+    : service_(*this) {
+    LoggerD("Entered");
+
+    using std::placeholders::_1;
+    using std::placeholders::_2;
+
+#define REGISTER_SYNC(c,x) \
+    RegisterSyncHandler(c, std::bind(&SecureElementInstance::x, this, _1, _2));
+
+    REGISTER_SYNC("SEService_registerSEListener", RegisterSEListener);
+    REGISTER_SYNC("SEService_unregisterSEListener", UnregisterSEListener);
+    REGISTER_SYNC("SEService_shutdown", Shutdown);
+    REGISTER_SYNC("SEReader_getName", GetName);
+    REGISTER_SYNC("SEReader_isPresent", IsPresent);
+    REGISTER_SYNC("SEReader_closeSessions", CloseSessions);
+    REGISTER_SYNC("SESession_getATR", GetATR);
+    REGISTER_SYNC("SESession_isClosed", IsSessionClosed);
+    REGISTER_SYNC("SESession_close", CloseSession);
+    REGISTER_SYNC("SESession_closeChannels", CloseChannels);
+    REGISTER_SYNC("SEChannel_close", CloseChannel);
+    REGISTER_SYNC("SEChannel_getSelectResponse", GetSelectResponse);
+#undef REGISTER_SYNC
+
+#define REGISTER(c,x) \
+    RegisterSyncHandler(c, std::bind(&SecureElementInstance::x, this, _1, _2));
+
+    REGISTER("SEService_getReaders", GetReaders);
+    REGISTER("SEReader_openSession", OpenSession);
+    REGISTER("SESession_openBasicChannel", OpenBasicChannel);
+    REGISTER("SESession_openLogicalChannel ", OpenLogicalChannel);
+    REGISTER("SEChannel_transmit", Transmit);
+#undef REGISTER
+}
+
+SecureElementInstance::~SecureElementInstance() {
+}
+
+void SecureElementInstance::GetReaders(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+
+  double callback_id = 0.0;
+  if (args.contains("callbackId")) {
+    callback_id = args.get("callbackId").get<double>();
+  }
+
+  service_.GetReaders(callback_id);
+  ReportSuccess(out);
+}
+
+void SecureElementInstance::RegisterSEListener(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+  service_.RegisterSEListener();
+  ReportSuccess(out);
+}
+
+void SecureElementInstance::UnregisterSEListener(
+    const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+  service_.UnregisterSEListener();
+  ReportSuccess(out);
+}
+
+void SecureElementInstance::Shutdown(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+  service_.Shutdown();
+  ReportSuccess(out);
+}
+
+void SecureElementInstance::GetName(
+        const picojson::value& args, picojson::object& out) {
+    LoggerD("Entered");
+    Reader* reader_ptr = (Reader*) static_cast<long>(args.get("handle").get<double>());
+    SEReader seReader(reader_ptr);
+    picojson::value result = seReader.getName();
+    ReportSuccess(result, out);
+}
+
+void SecureElementInstance::IsPresent(
+        const picojson::value& args, picojson::object& out) {
+    LoggerD("Entered");
+
+    Reader* reader_ptr = (Reader*) static_cast<long>(args.get("handle").get<double>());
+    SEReader seReader(reader_ptr);
+    picojson::value result = seReader.isPresent();
+    ReportSuccess(result, out);
+}
+
+void SecureElementInstance::CloseSessions(
+        const picojson::value& args, picojson::object& out) {
+    LoggerD("Entered");
+    Reader* reader_ptr = (Reader*) static_cast<long>(args.get("handle").get<double>());
+    SEReader seReader(reader_ptr);
+    seReader.closeSessions();
+    ReportSuccess(out);
+}
+
+void SecureElementInstance::CloseChannel( const picojson::value& args, picojson::object& out) {
+    LoggerD("Entered");
+    ClientChannel* channel_ptr = (ClientChannel*) static_cast<long>(args.get("handle").get<double>());
+    SEChannel seChannel(channel_ptr);
+    seChannel.close();
+    ReportSuccess(out);
+}
+
+void SecureElementInstance::GetSelectResponse( const picojson::value& args, picojson::object& out) {
+    LoggerD("Entered");
+    ClientChannel* channel_ptr = (ClientChannel*) static_cast<long>(args.get("handle").get<double>());
+    SEChannel seChannel(channel_ptr);
+
+    ByteArray select_response = seChannel.getSelectResponse();
+    picojson::value result = picojson::value(picojson::array());
+    picojson::array& arr = result.get<picojson::array>();
+    size_t select_response_size = select_response.size();
+    for (size_t i = 0; i < select_response_size; i++) {
+        arr.push_back(picojson::value(static_cast<double>(select_response[i])));
+    }
+    ReportSuccess( result, out);
+}
+
+void SecureElementInstance::OpenSession(
+        const picojson::value& args, picojson::object& out) {
+    LoggerD("Entered");
+    const double callback_id = args.get("callbackId").get<double>();
+    Reader* reader_ptr = (Reader*) static_cast<long>(args.get("handle").get<double>());
+
+    auto open_session = [this, reader_ptr](const std::shared_ptr<picojson::value>& response) -> void {
+        LoggerD("Opening session");
+        try {
+            SEReader seReader(reader_ptr);
+            picojson::value result = seReader.openSession();
+            ReportSuccess(result, response->get<picojson::object>());
+        } catch (const ErrorIO& err) {
+            LoggerD("Library reported ErrorIO!");
+            ReportError(PlatformResult(ErrorCode::IO_ERR), &response->get<picojson::object>());
+        } catch (const ErrorIllegalState& err) {
+            LoggerD("Library reported ErrorIllegalState!");
+            ReportError(PlatformResult(ErrorCode::INVALID_STATE_ERR), &response->get<picojson::object>());
+        } catch (const ErrorIllegalParameter& err) {
+            LoggerD("Library reported ErrorIllegalParameter!");
+            ReportError(PlatformResult(ErrorCode::INVALID_VALUES_ERR), &response->get<picojson::object>());
+        } catch (const ErrorSecurity& err) {
+            LoggerD("Library reported ErrorSecurity!");
+            ReportError(PlatformResult(ErrorCode::SECURITY_ERR), &response->get<picojson::object>());
+        } catch (const ExceptionBase& err) {
+            LoggerD("Library reported ExceptionBase!");
+            ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR), &response->get<picojson::object>());
+        }
+    };
+
+    auto open_session_response = [this, callback_id](const std::shared_ptr<picojson::value>& response) -> void {
+        LoggerD("Getting response");
+
+        picojson::object& obj = response->get<picojson::object>();
+        obj.insert(std::make_pair("callbackId", picojson::value(callback_id)));
+        Instance::PostMessage(this, response->serialize().c_str());
+    };
+
+    auto data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+
+    TaskQueue::GetInstance().Queue<picojson::value>(
+            open_session,
+            open_session_response,
+            data);
+}
+
+// Session functions
+
+void SecureElementInstance::OpenBasicChannel( const picojson::value& args, picojson::object& out) {
+    LoggerD("Enter");
+    const double callback_id = args.get("callbackId").get<double>();
+    const picojson::array v_aid = args.get("aid").get<picojson::value::array>();
+    Session* session_ptr = (Session*) static_cast<long>(args.get("handle").get<double>());
+
+    auto open = [this, v_aid, session_ptr](const std::shared_ptr<picojson::value>& response) -> void {
+        LoggerD("Opening basic channel");
+        try {
+            SESession seSession(session_ptr);
+            picojson::value result = seSession.openBasicChannel(v_aid);
+            ReportSuccess(result, response->get<picojson::object>());
+        } catch (const ErrorIO& err) {
+            LoggerD("Library reported ErrorIO!");
+            ReportError(PlatformResult(ErrorCode::IO_ERR), &response->get<picojson::object>());
+        } catch (const ErrorIllegalState& err) {
+            LoggerD("Library reported ErrorIllegalState!");
+            ReportError(PlatformResult(ErrorCode::INVALID_STATE_ERR), &response->get<picojson::object>());
+        } catch (const ErrorIllegalParameter& err) {
+            LoggerD("Library reported ErrorIllegalParameter!");
+            ReportError(PlatformResult(ErrorCode::INVALID_VALUES_ERR), &response->get<picojson::object>());
+        } catch (const ErrorSecurity& err) {
+            LoggerD("Library reported ErrorSecurity!");
+            ReportError(PlatformResult(ErrorCode::SECURITY_ERR), &response->get<picojson::object>());
+        } catch (const ExceptionBase& err) {
+            LoggerD("Library reported ExceptionBase!");
+            ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR), &response->get<picojson::object>());
+        }
+    };
+
+    auto get_response = [this, callback_id](const std::shared_ptr<picojson::value>& response) -> void {
+        LoggerD("Getting response");
+        picojson::object& obj = response->get<picojson::object>();
+        obj.insert(std::make_pair("callbackId", picojson::value(callback_id)));
+        Instance::PostMessage(this, response->serialize().c_str());
+    };
+
+    auto data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+
+    TaskQueue::GetInstance().Queue<picojson::value>(open, get_response, data);
+}
+
+
+void SecureElementInstance::OpenLogicalChannel( const picojson::value& args, picojson::object& out) {
+    LoggerD("Enter");
+    const double callback_id = args.get("callbackId").get<double>();
+    const picojson::array v_aid = args.get("aid").get<picojson::value::array>();
+    Session* session_ptr = (Session*) static_cast<long>(args.get("handle").get<double>());
+
+    auto open = [this, v_aid, session_ptr](const std::shared_ptr<picojson::value>& response) -> void {
+        LoggerD("Opening basic channel");
+        try {
+            SESession seSession(session_ptr);
+            picojson::value result = seSession.openLogicalChannel(v_aid);
+            ReportSuccess(result, response->get<picojson::object>());
+        } catch (const ErrorIO& err) {
+            LoggerD("Library reported ErrorIO!");
+            ReportError(PlatformResult(ErrorCode::IO_ERR), &response->get<picojson::object>());
+        } catch (const ErrorIllegalState& err) {
+            LoggerD("Library reported ErrorIllegalState!");
+            ReportError(PlatformResult(ErrorCode::INVALID_STATE_ERR), &response->get<picojson::object>());
+        } catch (const ErrorIllegalParameter& err) {
+            LoggerD("Library reported ErrorIllegalParameter!");
+            ReportError(PlatformResult(ErrorCode::INVALID_VALUES_ERR), &response->get<picojson::object>());
+        } catch (const ErrorSecurity& err) {
+            LoggerD("Library reported ErrorSecurity!");
+            ReportError(PlatformResult(ErrorCode::SECURITY_ERR), &response->get<picojson::object>());
+        } catch (const ExceptionBase& err) {
+            LoggerD("Library reported ExceptionBase!");
+            ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR), &response->get<picojson::object>());
+        }
+    };
+
+    auto get_response = [this, callback_id](const std::shared_ptr<picojson::value>& response) -> void {
+        LoggerD("Getting response");
+        picojson::object& obj = response->get<picojson::object>();
+        obj.insert(std::make_pair("callbackId", picojson::value(callback_id)));
+        Instance::PostMessage(this, response->serialize().c_str());
+    };
+
+    auto data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+
+    TaskQueue::GetInstance().Queue<picojson::value>(open, get_response, data);
+}
+
+
+void SecureElementInstance::GetATR( const picojson::value& args, picojson::object& out) {
+    LoggerD("Enter");
+
+    Session* session_ptr = (Session*) static_cast<long>(args.get("handle").get<double>());
+    SESession seSession(session_ptr);
+
+    ByteArray atr_result = seSession.getATR();
+    picojson::value result = picojson::value(picojson::array());
+    picojson::array& arr = result.get<picojson::array>();
+    size_t atr_result_size = atr_result.size();
+    for (size_t i = 0; i < atr_result_size; i++) {
+        arr.push_back(picojson::value(static_cast<double>(atr_result[i])));
+    }
+    ReportSuccess( result, out);
+}
+
+
+void SecureElementInstance::IsSessionClosed( const picojson::value& args, picojson::object& out) {
+    LoggerD("Enter");
+    Session* session_ptr = (Session*) static_cast<long>(args.get("handle").get<double>());
+    SESession seSession(session_ptr);
+    picojson::value result = seSession.isClosed();
+    ReportSuccess( result, out);
+}
+
+
+void SecureElementInstance::CloseSession( const picojson::value& args, picojson::object& out) {
+    LoggerD("Enter");
+    Session* session_ptr = (Session*) static_cast<long>(args.get("handle").get<double>());
+    SESession seSession(session_ptr);
+    seSession.close();
+    ReportSuccess(out);
+}
+
+
+void SecureElementInstance::CloseChannels( const picojson::value& args, picojson::object& out) {
+    LoggerD("Enter");
+    Session* session_ptr = (Session*) static_cast<long>(args.get("handle").get<double>());
+    SESession seSession(session_ptr);
+    seSession.closeChannels();
+    ReportSuccess(out);
+}
+
+void SecureElementInstance::Transmit( const picojson::value& args, picojson::object& out) {
+    LoggerD("Enter");
+    const double callback_id = args.get("callbackId").get<double>();
+    const picojson::array v_command = args.get("command").get<picojson::value::array>();
+    ClientChannel* channel_ptr = (ClientChannel*) static_cast<long>(args.get("handle").get<double>());
+
+    auto open = [this, v_command, channel_ptr](const std::shared_ptr<picojson::value>& response) -> void {
+        LoggerD("Transmit APDDU command to secure element");
+        try {
+            SEChannel seChannel(channel_ptr);
+            ByteArray transmit_response = seChannel.transmit(v_command);
+            picojson::value result = picojson::value(picojson::array());
+            picojson::array& arr = result.get<picojson::array>();
+            size_t transmit_response_size = transmit_response.size();
+            for (size_t i = 0; i < transmit_response_size; i++) {
+                arr.push_back(picojson::value(static_cast<double>(transmit_response[i])));
+            }
+            ReportSuccess( result, response->get<picojson::object>());
+        } catch (const ErrorIO& err) {
+            LoggerD("Library reported ErrorIO!");
+            ReportError(PlatformResult(ErrorCode::IO_ERR), &response->get<picojson::object>());
+        } catch (const ErrorIllegalState& err) {
+            LoggerD("Library reported ErrorIllegalState!");
+            ReportError(PlatformResult(ErrorCode::INVALID_STATE_ERR), &response->get<picojson::object>());
+        } catch (const ErrorIllegalParameter& err) {
+            LoggerD("Library reported ErrorIllegalParameter!");
+            ReportError(PlatformResult(ErrorCode::INVALID_VALUES_ERR), &response->get<picojson::object>());
+        } catch (const ErrorSecurity& err) {
+            LoggerD("Library reported ErrorSecurity!");
+            ReportError(PlatformResult(ErrorCode::SECURITY_ERR), &response->get<picojson::object>());
+        } catch (const ExceptionBase& err) {
+            LoggerD("Library reported ExceptionBase!");
+            ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR), &response->get<picojson::object>());
+        }
+    };
+
+    auto get_response = [this, callback_id](const std::shared_ptr<picojson::value>& response) -> void {
+        LoggerD("Getting response");
+        picojson::object& obj = response->get<picojson::object>();
+        obj.insert(std::make_pair("callbackId", picojson::value(callback_id)));
+        Instance::PostMessage(this, response->serialize().c_str());
+    };
+
+    auto data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+
+    TaskQueue::GetInstance().Queue<picojson::value>(open, get_response, data);
+}
+
+} // namespace secureelement
+} // namespace extension
diff --git a/webWidgetTCT_device/src/secureelement/secureelement_instance.h b/webWidgetTCT_device/src/secureelement/secureelement_instance.h
new file mode 100755 (executable)
index 0000000..1f0ff9c
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2015 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_SECUREELEMENT_INSTANCE_H_
+#define SECUREELEMENT_SECUREELEMENT_INSTANCE_H_
+
+#include "common/extension.h"
+#include "secureelement_seservice.h"
+
+namespace extension {
+namespace secureelement {
+
+class SecureElementInstance: public common::ParsedInstance {
+public:
+    SecureElementInstance();
+    virtual ~SecureElementInstance();
+
+private:
+    /* SEService methods */
+    void GetReaders(const picojson::value& args, picojson::object& out);
+    void RegisterSEListener(const picojson::value& args, picojson::object& out);
+    void UnregisterSEListener(const picojson::value& args, picojson::object& out);
+    void Shutdown(const picojson::value& args, picojson::object& out);
+
+    /* Reader methods */
+    void GetName(const picojson::value& args, picojson::object& out);
+    void IsPresent(const picojson::value& args, picojson::object& out);
+    void OpenSession(const picojson::value& args, picojson::object& out);
+    void CloseSessions(const picojson::value& args, picojson::object& out);
+
+    /* Session methods */
+    void OpenBasicChannel(const picojson::value& args, picojson::object& out);
+    void OpenLogicalChannel(const picojson::value& args, picojson::object& out);
+    void GetATR(const picojson::value& args, picojson::object& out);
+    void IsSessionClosed(const picojson::value& args, picojson::object& out);
+    void CloseSession(const picojson::value& args, picojson::object& out);
+    void CloseChannels(const picojson::value& args, picojson::object& out);
+
+    /* Channel methods */
+    void CloseChannel(const picojson::value& args, picojson::object& out);
+    void Transmit(const picojson::value& args, picojson::object& out);
+    void GetSelectResponse(const picojson::value& args, picojson::object& out);
+
+    SEService service_;
+};
+
+} // namespace secureelement
+} // namespace extension
+
+#endif // SECUREELEMENT_SECUREELEMENT_INSTANCE_H_
diff --git a/webWidgetTCT_device/src/secureelement/secureelement_reader.cc b/webWidgetTCT_device/src/secureelement/secureelement_reader.cc
new file mode 100755 (executable)
index 0000000..3ad2845
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2015 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 "secureelement_reader.h"
+
+#include <Session.h>
+#include <Reader.h>
+#include "common/picojson.h"
+#include "common/logger.h"
+
+using namespace smartcard_service_api;
+using namespace std;
+
+namespace extension {
+namespace secureelement {
+
+
+picojson::value SEReader::getName() {
+    LoggerD("Entered");
+
+    picojson::value result = picojson::value(picojson::object());
+    picojson::object& obj = result.get<picojson::object>();
+
+    if(m_reader) {
+        obj.insert(std::make_pair("name", picojson::value(m_reader->getName())));
+    }
+
+    return result;
+}
+
+picojson::value SEReader::isPresent() {
+    LoggerD("Entered");
+
+    picojson::value result = picojson::value(picojson::object());
+    picojson::object& obj = result.get<picojson::object>();
+
+    if(m_reader) {
+        obj.insert(std::make_pair("isPresent", picojson::value(m_reader->isSecureElementPresent())));
+    }
+
+    return result;
+}
+
+picojson::value SEReader::openSession() {
+    LoggerD("Entered");
+
+    picojson::value result = picojson::value(picojson::object());
+    picojson::object& obj = result.get<picojson::object>();
+
+    if(m_reader) {
+        Session *session_ptr = static_cast<Session*>(m_reader->openSessionSync());
+
+        obj.insert(std::make_pair("handle", picojson::value((double) (long) session_ptr)));
+        obj.insert(std::make_pair("isClosed", picojson::value(session_ptr->isClosed())));
+    }
+
+    return result;
+}
+
+void SEReader::closeSessions() {
+    LoggerD("Entered");
+
+    if(m_reader) {
+        m_reader->closeSessions();
+    }
+}
+
+}// secureelement
+}// extension
diff --git a/webWidgetTCT_device/src/secureelement/secureelement_reader.h b/webWidgetTCT_device/src/secureelement/secureelement_reader.h
new file mode 100755 (executable)
index 0000000..fc2d777
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2015 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_READER_H_
+#define SECUREELEMENT_READER_H_
+
+#include "common/picojson.h"
+#include <Reader.h>
+
+namespace extension {
+namespace secureelement {
+
+class SEReader {
+public:
+    SEReader(smartcard_service_api::Reader* reader_ptr) : m_reader(reader_ptr) {};
+    ~SEReader() {};
+
+    picojson::value getName();
+    picojson::value isPresent();
+    picojson::value openSession();
+    void closeSessions();
+private:
+    smartcard_service_api::Reader* m_reader;
+};
+
+} // secureelement
+} // extension
+
+#endif // SECUREELEMENT_READER_H_
diff --git a/webWidgetTCT_device/src/secureelement/secureelement_seservice.cc b/webWidgetTCT_device/src/secureelement/secureelement_seservice.cc
new file mode 100755 (executable)
index 0000000..290bd94
--- /dev/null
@@ -0,0 +1,238 @@
+/*
+ * Copyright (c) 2015 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 "secureelement/secureelement_seservice.h"
+
+#include "common/logger.h"
+#include "common/task-queue.h"
+#include "common/platform_result.h"
+
+
+#include "secureelement/secureelement_instance.h"
+
+using namespace smartcard_service_api;
+using namespace common;
+using namespace tools;
+
+namespace extension {
+namespace secureelement {
+
+namespace {
+const int SE_INSERTED = 1;
+const int SE_REMOVED = 2;
+}
+
+class SEServiceEventHandler : public SEServiceListener {
+  void serviceConnected(SEServiceHelper *service, void *context) {
+    LoggerD("Entered");
+    if (context) {
+      (static_cast<SEService*>(context))->ServiceConnected();
+    } else {
+      LoggerE("Context is null");
+    }
+  }
+
+  void eventHandler(SEServiceHelper *service, char *se_name, int event, void *context) {
+    LoggerD("Entered");
+    if (context) {
+      (static_cast<SEService*>(context))->EventHandler(se_name, event);
+    } else {
+      LoggerE("Context is null");
+    }
+  }
+
+  void errorHandler(SEServiceHelper *service, int error, void *context) {
+    LoggerE("Error handler called, code: %d", error);
+    if (context) {
+      (static_cast<SEService*>(context))->ErrorHandler(error);
+    } else {
+      LoggerE("Context is null");
+    }
+  }
+};
+
+static SEServiceEventHandler se_event_handler;
+
+SEService::SEService(SecureElementInstance& instance)
+    : is_initialized_(false),
+      is_listener_set_(false),
+      is_error_(false),
+      instance_(instance) {
+  LoggerD("Entered");
+
+  se_service_ = new smartcard_service_api::SEService((void *)this, &se_event_handler);
+}
+
+SEService::~SEService() {
+  LoggerD("Entered");
+
+  if (is_initialized_) {
+    se_service_->shutdownSync();
+    is_initialized_ = false;
+  }
+
+  delete se_service_;
+  se_service_ = nullptr;
+}
+
+void SEService::GetReaders(double callback_id) {
+  LoggerD("Entered");
+
+  auto get_readers = [this](
+      const std::shared_ptr<picojson::value>& response) -> void {
+    picojson::value result = picojson::value(picojson::array());
+    picojson::array& result_array = result.get<picojson::array>();
+
+    std::vector<smartcard_service_api::ReaderHelper *> readers = se_service_->getReaders();
+    for (std::size_t i = 0; i < readers.size(); i++) {
+      if (readers[i]->isSecureElementPresent()) {
+        result_array.push_back(picojson::value((double) (long) readers[i]));
+      }
+    }
+
+    ReportSuccess(result, response->get<picojson::object>());
+  };
+
+  auto get_readers_response = [this, callback_id](
+      const std::shared_ptr<picojson::value>& response) -> void {
+    picojson::object& obj = response->get<picojson::object>();
+    obj.insert(std::make_pair("callbackId", picojson::value(callback_id)));
+    Instance::PostMessage(&instance_, response->serialize().c_str());
+  };
+
+  if (is_error_) {
+    // there has been an error, report it asynchronously
+    LoggerE("Failed: is_error_");
+    std::shared_ptr<picojson::value> response{new picojson::value{picojson::object{}}};
+    ReportError(
+        PlatformResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR,
+                       "Unable to connect to service."),
+        &response->get<picojson::object>());
+    TaskQueue::GetInstance().Async<picojson::value>(get_readers_response, response);
+    return;
+  }
+
+  if (!is_initialized_) {
+    // not yet ready, wait for the platform callback, send the response then
+    get_readers_callbacks_.push_back(callback_id);
+    return;
+  }
+
+  auto data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+
+  // everything's fine, get the readers, send the response
+  TaskQueue::GetInstance().Queue<picojson::value>(
+      get_readers,
+      get_readers_response,
+      data);
+}
+
+void SEService::RegisterSEListener() {
+  LoggerD("Entered");
+
+  is_listener_set_ = true;
+}
+
+void SEService::UnregisterSEListener() {
+  LoggerD("Entered");
+
+  is_listener_set_ = false;
+}
+
+void SEService::Shutdown() {
+  LoggerD("Entered");
+
+  if (is_initialized_) {
+      se_service_->shutdownSync();
+      is_initialized_ = false;
+  }
+}
+
+void SEService::ServiceConnected() {
+  LoggerD("Entered");
+
+  is_initialized_ = true;
+
+  // send the response to pending GetReaders callbacks
+  for (const auto& callback_id : get_readers_callbacks_) {
+    GetReaders(callback_id);
+  }
+  get_readers_callbacks_.clear();
+
+  // notify the listeners
+  if (!is_listener_set_) {
+    LoggerE("SE listener is not set.");
+    return;
+  }
+
+  std::vector<smartcard_service_api::ReaderHelper *> readers = se_service_->getReaders();
+  for (std::size_t i = 0; i < readers.size(); i++) {
+    if (readers[i]->isSecureElementPresent()) {
+      picojson::value result = picojson::value(picojson::object());
+      picojson::object& obj = result.get<picojson::object>();
+
+      obj.insert(std::make_pair("action", picojson::value("onSEReady")));
+      obj.insert(std::make_pair("handle", picojson::value((double) (long) readers[i])));
+
+      Instance::PostMessage(&instance_, result.serialize().c_str());
+    }
+  }
+}
+
+void SEService::EventHandler(char *se_name, int event) {
+  LoggerD("Entered");
+
+  if (SE_INSERTED != event && SE_REMOVED != event) {
+    LoggerD("Incorrect event type");
+    return;
+  }
+
+  if (is_initialized_ && is_listener_set_) {
+    bool is_present = event == SE_INSERTED;
+
+    std::vector<smartcard_service_api::ReaderHelper *> readers = se_service_->getReaders();
+    for (std::size_t i = 0; i < readers.size(); i++) {
+      if (!strcmp(se_name, readers[i]->getName()) &&
+          readers[i]->isSecureElementPresent() != is_present) {
+        picojson::value result = picojson::value(picojson::object());
+        picojson::object& obj = result.get<picojson::object>();
+
+        if (is_present) {
+          obj.insert(std::make_pair("action", picojson::value("onSEReady")));
+        } else {
+          obj.insert(std::make_pair("action", picojson::value("onSENotReady")));
+        }
+
+        obj.insert(std::make_pair("handle", picojson::value((double) (long) readers[i])));
+        Instance::PostMessage(&instance_, result.serialize().c_str());
+        return;
+      }
+    }
+  }
+}
+
+void SEService::ErrorHandler(int error) {
+  LoggerD("Entered");
+  is_error_ = true;
+
+  for (const auto& callback_id : get_readers_callbacks_) {
+    GetReaders(callback_id);
+  }
+  get_readers_callbacks_.clear();
+}
+
+} // secureelement
+} // extension
diff --git a/webWidgetTCT_device/src/secureelement/secureelement_seservice.h b/webWidgetTCT_device/src/secureelement/secureelement_seservice.h
new file mode 100755 (executable)
index 0000000..5ac4067
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2015 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_SESERVICE_H_
+#define SECUREELEMENT_SESERVICE_H_
+
+#include <SEService.h>
+#include <SEServiceHelper.h>
+
+namespace extension {
+namespace secureelement {
+
+class SecureElementInstance;
+
+class SEService {
+ public:
+  explicit SEService(SecureElementInstance& instance);
+  ~SEService();
+
+  void GetReaders(double callback_id);
+  void RegisterSEListener();
+  void UnregisterSEListener();
+  void Shutdown();
+
+  void ServiceConnected();
+  void EventHandler(char *se_name, int event);
+  void ErrorHandler(int error);
+ private:
+  SEService(const SEService&) = delete;
+  SEService& operator=(const SEService&) = delete;
+
+  smartcard_service_api::SEService *se_service_;
+  bool is_initialized_;
+  bool is_listener_set_;
+  bool is_error_;
+  std::vector<double> get_readers_callbacks_;
+  SecureElementInstance& instance_;
+};
+
+} // secureelement
+} // extension
+
+#endif // SECUREELEMENT_SESERVICE_H_
diff --git a/webWidgetTCT_device/src/secureelement/secureelement_session.cc b/webWidgetTCT_device/src/secureelement/secureelement_session.cc
new file mode 100755 (executable)
index 0000000..35fee11
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2015 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 <Session.h>
+#include <ClientChannel.h>
+#include "common/picojson.h"
+#include "common/logger.h"
+#include "secureelement_session.h"
+
+using namespace smartcard_service_api;
+
+namespace extension {
+namespace secureelement {
+
+picojson::value SESession::openBasicChannel(const picojson::array& v_aid) {
+    LoggerD("Entered");
+
+    size_t v_aid_size = v_aid.size();
+    unsigned char* aid = new unsigned char[v_aid_size];
+    for (size_t i = 0; i < v_aid_size; i++) {
+        aid[i] = static_cast<unsigned char>(v_aid[i].get<double>());
+    }
+    ByteArray aid_byte_array( aid, (unsigned int) v_aid.size());
+    ClientChannel* channel_ptr = static_cast<ClientChannel*>(m_session_ptr->openBasicChannelSync( aid_byte_array));
+    delete [] aid;
+
+    picojson::value result = picojson::value(picojson::object());
+    picojson::object& obj = result.get<picojson::object>();
+    obj.insert(std::make_pair("handle", picojson::value((double) (long) channel_ptr)));
+    obj.insert(std::make_pair("isBasicChannel", picojson::value(channel_ptr->isBasicChannel())));
+
+    return result;
+}
+
+
+picojson::value SESession::openLogicalChannel(const picojson::array& v_aid) {
+    LoggerD("Entered");
+
+    size_t v_aid_size = v_aid.size();
+    unsigned char* aid = new unsigned char[v_aid_size];
+    for (size_t i = 0; i < v_aid_size; i++) {
+        aid[i] = static_cast<unsigned char>(v_aid[i].get<double>());
+    }
+    ByteArray aid_byte_array( aid, (unsigned int) v_aid.size());
+    ClientChannel* channel_ptr = static_cast<ClientChannel*>(m_session_ptr->openLogicalChannelSync( aid_byte_array));
+    delete [] aid;
+
+    picojson::value result = picojson::value(picojson::object());
+    picojson::object& obj = result.get<picojson::object>();
+    obj.insert(std::make_pair("handle", picojson::value((double) (long) channel_ptr)));
+    obj.insert(std::make_pair("isBasicChannel", picojson::value(channel_ptr->isBasicChannel())));
+
+    return result;
+}
+
+
+picojson::value SESession::isClosed() {
+    LoggerD("Entered");
+    bool is_closed = m_session_ptr->isClosed();
+    picojson::value result = picojson::value(picojson::object());
+    picojson::object& obj = result.get<picojson::object>();
+    obj.insert(std::make_pair("isClosed", picojson::value(is_closed)));
+    return result;
+}
+
+
+void SESession::close() {
+    LoggerD("Entered");
+    if ( m_session_ptr) {
+        m_session_ptr->closeSync();
+    }
+}
+
+
+ByteArray SESession::getATR() {
+    LoggerD("Entered");
+    ByteArray response;
+    if ( m_session_ptr) {
+        response = m_session_ptr->getATRSync();
+    }
+    return response;
+}
+
+
+void SESession::closeChannels() {
+    LoggerD("Entered");
+    if ( m_session_ptr) {
+        m_session_ptr->closeChannels();
+    }
+}
+
+
+} // secureelement
+} // extension
diff --git a/webWidgetTCT_device/src/secureelement/secureelement_session.h b/webWidgetTCT_device/src/secureelement/secureelement_session.h
new file mode 100755 (executable)
index 0000000..891380c
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2015 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_SESSION_H_
+#define SECUREELEMENT_SESSION_H_
+
+#include <Session.h>
+#include "common/picojson.h"
+#include "common/logger.h"
+
+namespace extension {
+namespace secureelement {
+
+class SESession {
+public:
+    SESession(smartcard_service_api::Session* session_ptr)
+        : m_session_ptr(session_ptr) {
+    }
+
+    ~SESession() {};
+    picojson::value openBasicChannel( const picojson::array& v_aid);
+    picojson::value openLogicalChannel( const picojson::array& v_aid);
+    picojson::value isClosed();
+    void close();
+    smartcard_service_api::ByteArray getATR();
+    void closeChannels();
+private:
+    smartcard_service_api::Session* m_session_ptr;
+};
+
+} // secureelement
+} // extension
+
+#endif // SECUREELEMENT_SESSION_H_
diff --git a/webWidgetTCT_device/src/sensor/sensor.gyp b/webWidgetTCT_device/src/sensor/sensor.gyp
new file mode 100755 (executable)
index 0000000..22c3fd7
--- /dev/null
@@ -0,0 +1,35 @@
+{
+  'includes':[
+    '../common/common.gypi',
+  ],
+  'targets': [
+    {
+      'target_name': 'tizen_sensor',
+      'type': 'loadable_module',
+      'dependencies': [
+        '../common/common.gyp:tizen_common',
+      ],
+      'sources': [
+        'sensor_api.js',
+        'sensor_extension.cc',
+        'sensor_extension.h',
+        'sensor_instance.cc',
+        'sensor_instance.h',
+        'sensor_service.cc',
+        'sensor_service.h'
+      ],
+      'includes': [
+        '../common/pkg-config.gypi',
+      ],
+      'conditions': [
+        ['tizen == 1', {
+          'variables': {
+            'packages': [
+              'capi-system-sensor',
+            ]
+          },
+        }],
+      ],
+    },
+  ],
+}
\ No newline at end of file
diff --git a/webWidgetTCT_device/src/sensor/sensor_api.js b/webWidgetTCT_device/src/sensor/sensor_api.js
new file mode 100755 (executable)
index 0000000..b6c24d1
--- /dev/null
@@ -0,0 +1,512 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+var validator_ = xwalk.utils.validator;
+var converter_ = xwalk.utils.converter;
+var types_ = validator_.Types;
+var T_ = xwalk.utils.type;
+var native_ = new xwalk.utils.NativeManager(extension);
+
+// Enums
+var SensorType = {
+    LIGHT : 'LIGHT',
+    MAGNETIC : 'MAGNETIC',
+    PRESSURE : 'PRESSURE',
+    PROXIMITY : 'PROXIMITY',
+    ULTRAVIOLET : 'ULTRAVIOLET',
+    HRM_RAW : 'HRM_RAW',
+};
+
+var ProximityState = {
+    FAR : 'FAR',
+    NEAR : 'NEAR'
+};
+
+var MagneticSensorAccuracy = {
+    UNDEFINED : 'ACCURACY_UNDEFINED',
+    BAD : 'ACCURACY_BAD',
+    NORMAL : 'ACCURACY_NORMAL',
+    GOOD : 'ACCURACY_GOOD',
+    VERYGOOD : 'ACCURACY_VERYGOOD'
+};
+
+// helper class for sensor listeners
+var SensorListener = function (type, constructor) {
+    this.sensorType = type;
+    this.isStarted = false;
+    this.callback = undefined;
+    this.constructor = constructor;
+};
+
+SensorListener.prototype.tryCall = function (object) {
+    if (this.callback) {
+        this.callback(new this.constructor(object));
+    }
+};
+
+SensorListener.prototype.start = function (successCallback, errorCallback) {
+    if (!this.isStarted) {
+        // sensor not started
+        var thisObject = this;
+        native_.call('Sensor_start', {'sensorType' : thisObject.sensorType},
+                function(result) {
+                    if (native_.isFailure(result)) {
+                        if(!T_.isNullOrUndefined(errorCallback)) {
+                            errorCallback(native_.getErrorObject(result));
+                        }
+                    } else {
+                        thisObject.isStarted = true;
+                        successCallback();
+                    }
+                }
+        );
+    } else {
+        // sensor is already started - just call success callback
+        setTimeout(function(){successCallback()}, 0);
+    }
+};
+
+SensorListener.prototype.stop = function () {
+    if (this.isStarted) {
+        var result = native_.callSync('Sensor_stop', {'sensorType' : this.sensorType});
+        if (native_.isFailure(result)) {
+            throw native_.getErrorObject(result);
+        }
+        this.isStarted = false;
+    }
+};
+
+SensorListener.prototype.setListener = function (successCallback) {
+    if (!this.callback) {
+        //call platform only if there was no listener registered
+        var result = native_.callSync('Sensor_setChangeListener', {'sensorType' : this.sensorType});
+        if (native_.isFailure(result)) {
+            throw native_.getErrorObject(result);
+        }
+    }
+    this.callback = successCallback;
+};
+
+SensorListener.prototype.unsetListener = function () {
+    if (this.callback) {
+        //unregister in platform only if there is callback registered
+        this.callback = undefined;
+        var result = native_.callSync('Sensor_unsetChangeListener', {'sensorType' : this.sensorType});
+        if (native_.isFailure(result)) {
+            throw native_.getErrorObject(result);
+        }
+    }
+};
+
+SensorListener.prototype.getData = function (successCallback, errorCallback) {
+    var thisObj = this;
+    if (!thisObj.isStarted) {
+        setTimeout(function() {
+            if (!T_.isNullOrUndefined(errorCallback)) {
+                errorCallback(new WebAPIException(
+                        WebAPIException.SERVICE_NOT_AVAILABLE_ERR,
+                        'Service is not available.'));
+            }
+        }, 0);
+    } else {
+        native_.call('Sensor_getData', { type : thisObj.sensorType },
+                function(result) {
+            if (native_.isFailure(result)) {
+                if(!T_.isNullOrUndefined(errorCallback)) {
+                    errorCallback(native_.getErrorObject(result));
+                }
+            } else {
+                successCallback(new thisObj.constructor(result));
+            }
+        });
+    }
+};
+
+var _supportedSensors = [];
+var _isChecked = false;
+var _sensorListeners = {
+    'LIGHT'       : {},
+    'MAGNETIC'    : {},
+    'PRESSURE'    : {},
+    'PROXIMITY'   : {},
+    'ULTRAVIOLET' : {},
+    'HRM_RAW'     : {},
+};
+
+var _listener = function(object) {
+    _sensorListeners[object.sensorType].tryCall(object);
+};
+
+var SENSOR_CHANGED_LISTENER = 'SensorChangedListener';
+native_.addListener(SENSOR_CHANGED_LISTENER, _listener);
+
+function getAvailableSensors() {
+    var result = native_.callSync('SensorService_getAvailableSensors', {});
+    if (native_.isFailure(result)) {
+        throw native_.getErrorObject(result);
+    }
+    _supportedSensors = native_.getResultObject(result);
+    _isChecked = true;
+}
+
+function SensorService() {
+};
+
+SensorService.prototype.getDefaultSensor = function() {
+    var args = validator_.validateArgs(arguments, [
+        {
+            name : 'type',
+            type : types_.ENUM,
+            values : T_.getValues(SensorType)
+        }
+    ]);
+
+    if (!_isChecked) {
+        getAvailableSensors();
+    }
+
+    var index = _supportedSensors.indexOf(args.type);
+    if (index === -1) {
+        throw new WebAPIException(WebAPIException.NOT_SUPPORTED_ERR, 'Not supported.');
+    } else if (_supportedSensors[index] === SensorType.LIGHT) {
+        return new LightSensor();
+    } else if (_supportedSensors[index] === SensorType.MAGNETIC) {
+        return new MagneticSensor();
+    } else if (_supportedSensors[index] === SensorType.PRESSURE) {
+        return new PressureSensor();
+    } else if (_supportedSensors[index] === SensorType.PROXIMITY) {
+        return new ProximitySensor();
+    } else if (_supportedSensors[index] === SensorType.ULTRAVIOLET) {
+        return new UltravioletSensor();
+    } else if (_supportedSensors[index] === SensorType.HRM_RAW) {
+        xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.HEALTHINFO);
+        return new HRMRawSensor();
+    }
+};
+
+SensorService.prototype.getAvailableSensors = function() {
+    if (!_isChecked) {
+        getAvailableSensors();
+    }
+
+    return _supportedSensors.slice();
+};
+
+//////////////////////Sensor classes//////////////////////////////////////////////////////////
+//// Base Sensor class
+var Sensor = function (type) {
+    Object.defineProperties(this, {
+        sensorType : {value: type, writable: false, enumerable: true}
+    });
+};
+
+Sensor.prototype.start = function() {
+    var args = validator_.validateArgs(arguments, [
+       {
+           name : 'successCallback',
+           type : types_.FUNCTION
+       },
+       {
+           name : 'errorCallback',
+           type : types_.FUNCTION,
+           optional : true,
+           nullable : true
+       }
+    ]);
+
+    _sensorListeners[this.sensorType].start(args.successCallback, args.errorCallback);
+};
+
+Sensor.prototype.stop = function() {
+    _sensorListeners[this.sensorType].stop();
+};
+
+Sensor.prototype.setChangeListener = function() {
+    var args = validator_.validateArgs(arguments, [
+       {
+           name : 'successCallback',
+           type: types_.FUNCTION
+       }
+    ]);
+
+    _sensorListeners[this.sensorType].setListener(args.successCallback);
+};
+
+Sensor.prototype.unsetChangeListener = function() {
+    _sensorListeners[this.sensorType].unsetListener();
+};
+
+//// LightSensor
+var LightSensor = function(data) {
+    Sensor.call(this, SensorType.LIGHT);
+};
+
+LightSensor.prototype = new Sensor();
+
+LightSensor.prototype.constructor = Sensor;
+
+LightSensor.prototype.getLightSensorData = function() {
+    var args = validator_.validateArgs(arguments, [
+       {
+           name : 'successCallback',
+           type : types_.FUNCTION
+       },
+       {
+           name : 'errorCallback',
+           type : types_.FUNCTION,
+           optional : true,
+           nullable : true
+       }
+    ]);
+
+    _sensorListeners[this.sensorType].getData(args.successCallback, args.errorCallback);
+};
+
+//// MagneticSensor
+var MagneticSensor = function(data) {
+    Sensor.call(this, SensorType.MAGNETIC);
+};
+
+MagneticSensor.prototype = new Sensor();
+
+MagneticSensor.prototype.constructor = Sensor;
+
+MagneticSensor.prototype.getMagneticSensorData = function() {
+    var args = validator_.validateArgs(arguments, [
+       {
+           name : 'successCallback',
+           type : types_.FUNCTION
+       },
+       {
+           name : 'errorCallback',
+           type : types_.FUNCTION,
+           optional : true,
+           nullable : true
+       }
+    ]);
+
+    _sensorListeners[this.sensorType].getData(args.successCallback, args.errorCallback);
+};
+
+//// PressureSensor
+var PressureSensor = function(data) {
+    Sensor.call(this, SensorType.PRESSURE);
+};
+
+PressureSensor.prototype = new Sensor();
+
+PressureSensor.prototype.constructor = Sensor;
+
+PressureSensor.prototype.getPressureSensorData = function() {
+    var args = validator_.validateArgs(arguments, [
+       {
+           name : 'successCallback',
+           type : types_.FUNCTION
+       },
+       {
+           name : 'errorCallback',
+           type : types_.FUNCTION,
+           optional : true,
+           nullable : true
+       }
+    ]);
+
+    _sensorListeners[this.sensorType].getData(args.successCallback, args.errorCallback);
+};
+
+//// ProximitySensor
+var ProximitySensor = function(data) {
+    Sensor.call(this, SensorType.PROXIMITY);
+};
+
+ProximitySensor.prototype = new Sensor();
+
+ProximitySensor.prototype.constructor = Sensor;
+
+ProximitySensor.prototype.getProximitySensorData = function() {
+    var args = validator_.validateArgs(arguments, [
+       {
+           name : 'successCallback',
+           type : types_.FUNCTION
+       },
+       {
+           name : 'errorCallback',
+           type : types_.FUNCTION,
+           optional : true,
+           nullable : true
+       }
+    ]);
+
+    _sensorListeners[this.sensorType].getData(args.successCallback, args.errorCallback);
+};
+
+//// UltravioletSensor
+var UltravioletSensor = function(data) {
+    Sensor.call(this, SensorType.ULTRAVIOLET);
+};
+
+UltravioletSensor.prototype = new Sensor();
+
+UltravioletSensor.prototype.constructor = Sensor;
+
+UltravioletSensor.prototype.getUltravioletSensorData = function() {
+    var args = validator_.validateArgs(arguments, [
+       {
+           name : 'successCallback',
+           type : types_.FUNCTION
+       },
+       {
+           name : 'errorCallback',
+           type : types_.FUNCTION,
+           optional : true,
+           nullable : true
+       }
+    ]);
+
+    _sensorListeners[this.sensorType].getData(args.successCallback, args.errorCallback);
+};
+
+////HRMRawSensor
+var HRMRawSensor = function(data) {
+    Sensor.call(this, SensorType.HRM_RAW);
+};
+
+HRMRawSensor.prototype = new Sensor();
+
+HRMRawSensor.prototype.constructor = Sensor;
+
+HRMRawSensor.prototype.getHRMRawSensorData = function() {
+    var args = validator_.validateArgs(arguments, [
+       {
+           name : 'successCallback',
+           type : types_.FUNCTION
+       },
+       {
+           name : 'errorCallback',
+           type : types_.FUNCTION,
+           optional : true,
+           nullable : true
+       }
+    ]);
+
+    xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.HEALTHINFO);
+
+    _sensorListeners[this.sensorType].getData(args.successCallback, args.errorCallback);
+};
+
+////////////////////// Sensor Data classes/////////////////////////////////////////////////////
+////Base SensorData class
+var SensorData = function () {
+};
+
+//// SensorLightData
+var SensorLightData = function(data) {
+    SensorData.call(this);
+    Object.defineProperties(this, {
+        lightLevel : {value: data.lightLevel, writable: false, enumerable: true}
+    });
+};
+
+SensorLightData.prototype = new SensorData();
+
+SensorLightData.prototype.constructor = SensorData;
+
+_sensorListeners[SensorType.LIGHT] = new SensorListener(SensorType.LIGHT,
+        SensorLightData);
+
+//// SensorMagneticData
+var SensorMagneticData = function(data) {
+    SensorData.call(this);
+    Object.defineProperties(this, {
+        x : {value: data.x, writable: false, enumerable: true},
+        y : {value: data.y, writable: false, enumerable: true},
+        z : {value: data.z, writable: false, enumerable: true},
+        accuracy : {value: data.accuracy, writable: false, enumerable: true}
+    });
+};
+
+SensorMagneticData.prototype = new SensorData();
+
+SensorMagneticData.prototype.constructor = SensorData;
+
+_sensorListeners[SensorType.MAGNETIC] = new SensorListener(SensorType.MAGNETIC,
+        SensorMagneticData);
+
+//// SensorPressureData
+var SensorPressureData = function(data) {
+    SensorData.call(this);
+    Object.defineProperties(this, {
+        pressure : {value: data.pressure, writable: false, enumerable: true}
+    });
+};
+
+SensorPressureData.prototype = new SensorData();
+
+SensorPressureData.prototype.constructor = SensorData;
+
+_sensorListeners[SensorType.PRESSURE] = new SensorListener(SensorType.PRESSURE,
+        SensorPressureData);
+
+//// SensorProximityData
+var SensorProximityData = function(data) {
+    SensorData.call(this);
+    Object.defineProperties(this, {
+        proximityState : {value: data.proximityState, writable: false, enumerable: true}
+    });
+};
+
+SensorProximityData.prototype = new SensorData();
+
+SensorProximityData.prototype.constructor = SensorData;
+
+_sensorListeners[SensorType.PROXIMITY] = new SensorListener(SensorType.PROXIMITY,
+        SensorProximityData);
+
+//// SensorUltravioletData
+var SensorUltravioletData = function(data) {
+    SensorData.call(this);
+    Object.defineProperties(this, {
+        ultravioletLevel : {value: data.ultravioletLevel, writable: false, enumerable: true}
+    });
+};
+
+
+SensorUltravioletData.prototype = new SensorData();
+
+SensorUltravioletData.prototype.constructor = SensorData;
+
+_sensorListeners[SensorType.ULTRAVIOLET] = new SensorListener(SensorType.ULTRAVIOLET,
+        SensorUltravioletData);
+
+////SensorHRMRawData
+var SensorHRMRawData = function(data) {
+    SensorData.call(this);
+    Object.defineProperties(this, {
+        lightType : {value: data.lightType, writable: false, enumerable: true},
+        lightIntensity : {value: data.lightIntensity, writable: false, enumerable: true}
+    });
+};
+
+
+SensorHRMRawData.prototype = new SensorData();
+
+SensorHRMRawData.prototype.constructor = SensorData;
+
+_sensorListeners[SensorType.HRM_RAW] = new SensorListener(SensorType.HRM_RAW,
+        SensorHRMRawData);
+
+// Exports
+exports = new SensorService();
diff --git a/webWidgetTCT_device/src/sensor/sensor_extension.cc b/webWidgetTCT_device/src/sensor/sensor_extension.cc
new file mode 100755 (executable)
index 0000000..e9b165b
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2015 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 "sensor/sensor_extension.h"
+#include "sensor/sensor_instance.h"
+
+// This will be generated from sensor_api.js
+extern const char kSource_sensor_api[];
+
+common::Extension* CreateExtension() {
+  return new SensorExtension;
+}
+
+SensorExtension::SensorExtension() {
+  SetExtensionName("tizen.sensorservice");
+  SetJavaScriptAPI(kSource_sensor_api);
+}
+
+SensorExtension::~SensorExtension() {}
+
+common::Instance* SensorExtension::CreateInstance() {
+  return new extension::sensor::SensorInstance();
+}
diff --git a/webWidgetTCT_device/src/sensor/sensor_extension.h b/webWidgetTCT_device/src/sensor/sensor_extension.h
new file mode 100755 (executable)
index 0000000..2eb03d8
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2015 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 SENSOR_SENSOR_EXTENSION_H_
+#define SENSOR_SENSOR_EXTENSION_H_
+
+#include "common/extension.h"
+
+class SensorExtension : public common::Extension {
+ public:
+  SensorExtension();
+  virtual ~SensorExtension();
+
+ private:
+  virtual common::Instance* CreateInstance();
+};
+
+#endif // SENSOR_SENSOR_EXTENSION_H_
diff --git a/webWidgetTCT_device/src/sensor/sensor_instance.cc b/webWidgetTCT_device/src/sensor/sensor_instance.cc
new file mode 100755 (executable)
index 0000000..ca0e37a
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2015 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 "sensor/sensor_instance.h"
+
+#include "common/picojson.h"
+#include "common/logger.h"
+#include "common/platform_exception.h"
+
+namespace extension {
+namespace sensor {
+
+using namespace common;
+
+SensorInstance::SensorInstance()
+    : service_(*this) {
+  LoggerD("Entered");
+  using std::placeholders::_1;
+  using std::placeholders::_2;
+
+#define REGISTER_SYNC(c,x) \
+    RegisterSyncHandler(c, std::bind(&SensorInstance::x, this, _1, _2));
+  REGISTER_SYNC("SensorService_getAvailableSensors", GetAvailableSensors);
+  REGISTER_SYNC("Sensor_stop", SensorStop);
+  REGISTER_SYNC("Sensor_setChangeListener", SensorSetChangeListener);
+  REGISTER_SYNC("Sensor_unsetChangeListener", SensorUnsetChangeListener);
+#undef REGISTER_SYNC
+#define REGISTER_ASYNC(c,x) \
+    RegisterSyncHandler(c, std::bind(&SensorInstance::x, this, _1, _2));
+  REGISTER_ASYNC("Sensor_start", SensorStart);
+  REGISTER_ASYNC("Sensor_getData", SensorGetData);
+#undef REGISTER_ASYNC
+}
+
+SensorInstance::~SensorInstance() {
+  LoggerD("Entered");
+}
+
+void SensorInstance::GetAvailableSensors(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+  service_.GetAvailableSensors(out);
+}
+
+void SensorInstance::SensorStop(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+  service_.SensorStop(args, out);
+}
+
+void SensorInstance::SensorSetChangeListener(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+  service_.SensorSetChangeListener(args, out);
+}
+
+void SensorInstance::SensorUnsetChangeListener(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+  service_.SensorUnsetChangeListener(args, out);
+}
+
+void SensorInstance::SensorStart(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+  service_.SensorStart(args, out);
+}
+
+void SensorInstance::SensorGetData(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+
+  service_.GetSensorData(args, out);
+}
+
+} // namespace sensor
+} // namespace extension
diff --git a/webWidgetTCT_device/src/sensor/sensor_instance.h b/webWidgetTCT_device/src/sensor/sensor_instance.h
new file mode 100755 (executable)
index 0000000..c798e16
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2015 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 SENSOR_SENSOR_INSTANCE_H_
+#define SENSOR_SENSOR_INSTANCE_H_
+
+#include "common/extension.h"
+
+#include "sensor/sensor_service.h"
+
+namespace extension {
+namespace sensor {
+
+class SensorInstance : public common::ParsedInstance {
+ public:
+  SensorInstance();
+  virtual ~SensorInstance();
+
+ private:
+  void GetAvailableSensors(const picojson::value& args, picojson::object& out);
+  void SensorStop(const picojson::value& args, picojson::object& out);
+  void SensorSetChangeListener(const picojson::value& args, picojson::object& out);
+  void SensorUnsetChangeListener(const picojson::value& args, picojson::object& out);
+  void SensorStart(const picojson::value& args, picojson::object& out);
+  void SensorGetData(const picojson::value& args, picojson::object& out);
+
+  SensorService service_;
+};
+
+} // namespace sensor
+} // namespace extension
+
+#endif // SENSOR_SENSOR_INSTANCE_H_
diff --git a/webWidgetTCT_device/src/sensor/sensor_service.cc b/webWidgetTCT_device/src/sensor/sensor_service.cc
new file mode 100755 (executable)
index 0000000..cdb0914
--- /dev/null
@@ -0,0 +1,752 @@
+/*
+ * Copyright (c) 2015 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 "sensor_service.h"
+
+#include <string>
+#include <memory>
+#include <mutex>
+
+#include "common/task-queue.h"
+#include "common/logger.h"
+#include "common/optional.h"
+#include "common/platform_exception.h"
+#include "sensor_instance.h"
+
+using namespace common;
+using namespace common::tools;
+
+namespace extension {
+namespace sensor {
+
+namespace {
+#define CHECK_EXIST(args, name, out) \
+  if (!args.contains(name)) {\
+    ReportError(TypeMismatchException(name" is required argument"), out);\
+      return;\
+    }
+
+static std::map<sensor_type_e, std::string> type_to_string_map;
+static std::map<std::string, sensor_type_e> string_to_type_map;
+
+static std::string GetAccuracyString(int accuracy) {
+  LoggerD("Entered");
+  switch (static_cast<sensor_data_accuracy_e>(accuracy)) {
+    case SENSOR_DATA_ACCURACY_BAD:
+      return "ACCURACY_BAD";
+    case SENSOR_DATA_ACCURACY_NORMAL:
+      return "ACCURACY_NORMAL";
+    case SENSOR_DATA_ACCURACY_GOOD:
+      return "ACCURACY_GOOD";
+    case SENSOR_DATA_ACCURACY_VERYGOOD:
+      return "ACCURACY_VERYGOOD";
+    default:
+      return "ACCURACY_UNDEFINED";
+  }
+}
+
+static const std::string kSensorTypeTag = "sensorType";
+static const std::string kListenerId = "listenerId";
+static const std::string kSensorChangedListener = "SensorChangedListener";
+
+void ReportSensorData(sensor_type_e sensor_type, sensor_event_s* sensor_event,
+                      picojson::object* out) {
+  LoggerD("Entered");
+
+  switch (sensor_type) {
+    case SENSOR_LIGHT: {
+      (*out)["lightLevel"] = picojson::value(static_cast<double>(sensor_event->values[0]));
+      break;
+    }
+    case SENSOR_MAGNETIC: {
+      (*out)["x"] = picojson::value(static_cast<double>(sensor_event->values[0]));
+      (*out)["y"] = picojson::value(static_cast<double>(sensor_event->values[1]));
+      (*out)["z"] = picojson::value(static_cast<double>(sensor_event->values[2]));
+      (*out)["accuracy"] = picojson::value(GetAccuracyString(sensor_event->accuracy));
+      break;
+    }
+    case SENSOR_PRESSURE: {
+      (*out)["pressure"] = picojson::value(static_cast<double>(sensor_event->values[0]));
+      break;
+    }
+    case SENSOR_PROXIMITY: {
+      const int state = static_cast<int>(sensor_event->values[0]);
+      (*out)["proximityState"] = picojson::value(state ? "NEAR" : "FAR");
+      break;
+    }
+    case SENSOR_ULTRAVIOLET: {
+      (*out)["ultravioletLevel"] = picojson::value(static_cast<double>(sensor_event->values[0]));
+      break;
+    }
+    case SENSOR_HRM_LED_IR:
+    case SENSOR_HRM_LED_RED:
+    case SENSOR_HRM_LED_GREEN: {
+      (*out)["lightType"] = picojson::value(type_to_string_map[sensor_type]);
+      (*out)["lightIntensity"] = picojson::value(static_cast<double>(sensor_event->values[0]));
+      break;
+    }
+    default: {
+      ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Unsupported type"), out);
+      return;
+    }
+  }
+  (*out)[kListenerId] = picojson::value(kSensorChangedListener);
+  (*out)[kSensorTypeTag] = picojson::value(type_to_string_map[sensor_type]);
+}
+
+std::string GetSensorErrorMessage(const int error_code) {
+  LoggerD("Entered");
+
+  switch (error_code) {
+    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";
+  }
+}
+
+PlatformResult GetSensorPlatformResult(const int error_code, const std::string &hint) {
+  LoggerD("Entered");
+
+  std::string message = hint + " : " + GetSensorErrorMessage(error_code);
+
+  switch (error_code) {
+    case SENSOR_ERROR_NOT_SUPPORTED:
+      return PlatformResult(ErrorCode::NOT_SUPPORTED_ERR, message);
+    default:
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, message);
+  }
+}
+
+bool MagneticEventComparator(sensor_event_s* l, sensor_event_s* r) {
+  return (l->values[0] == r->values[0] &&
+          l->values[1] == r->values[1] &&
+          l->values[2] == r->values[2] &&
+          l->accuracy == r->accuracy);
+}
+
+} // namespace
+
+class SensorData {
+ public:
+  typedef bool (*EventComparator)(sensor_event_s* l, sensor_event_s* r);
+
+  SensorData(SensorInstance& instance, sensor_type_e type_enum,
+             const std::string& name, EventComparator comparator =
+                 DefaultEventComparator);
+  virtual ~SensorData();
+
+  PlatformResult IsSupported(bool* supported);
+  virtual PlatformResult Start();
+  virtual PlatformResult Stop();
+  virtual PlatformResult SetChangeListener();
+  virtual PlatformResult UnsetChangeListener();
+  virtual PlatformResult GetSensorData(picojson::object* data);
+
+  sensor_type_e type() const { return type_enum_; }
+  bool is_supported();
+
+  bool UpdateEvent(sensor_event_s* event);
+
+ protected:
+  virtual PlatformResult CheckInitialization();
+  virtual PlatformResult IsSupportedImpl(bool* supported) const;
+
+ private:
+  static void SensorCallback(sensor_h sensor, sensor_event_s* event, void* user_data);
+  static bool DefaultEventComparator(sensor_event_s* l, sensor_event_s* r);
+
+  sensor_type_e type_enum_;
+  EventComparator comparator_;
+  sensor_h handle_;
+  sensor_listener_h listener_;
+  sensor_event_s previous_event_;
+  common::optional<bool> is_supported_;
+  SensorInstance& instance_;
+};
+
+SensorData::SensorData(SensorInstance& instance, sensor_type_e type_enum,
+                       const std::string& name, EventComparator comparator)
+    : type_enum_(type_enum),
+      comparator_(comparator),
+      handle_(nullptr),
+      listener_(nullptr),
+      previous_event_(),
+      instance_(instance) {
+  type_to_string_map.insert(std::make_pair(type_enum, name));
+  string_to_type_map.insert(std::make_pair(name, type_enum));
+
+  LoggerD("Entered: %s", type_to_string_map[type()].c_str());
+}
+
+SensorData::~SensorData() {
+  LoggerD("Entered: %s", type_to_string_map[type()].c_str());
+
+  if (listener_) {
+    sensor_destroy_listener(listener_);
+  }
+}
+
+void SensorData::SensorCallback(sensor_h sensor, sensor_event_s* event, void* user_data) {
+  LoggerD("Entered");
+
+  SensorData* that = static_cast<SensorData*>(user_data);
+
+  if (!that) {
+    LoggerE("user_data is null");
+    return;
+  }
+
+  LoggerD("Entered: %s", type_to_string_map[that->type()].c_str());
+
+  if (!that->UpdateEvent(event)) {
+    // value didn't change - ignore
+    return;
+  }
+
+  picojson::value result = picojson::value(picojson::object());
+  picojson::object& object = result.get<picojson::object>();
+  ReportSensorData(that->type(), event, &object);
+  Instance::PostMessage(&that->instance_, result.serialize().c_str());
+}
+
+bool SensorData::DefaultEventComparator(sensor_event_s* l, sensor_event_s* r) {
+  return (l->values[0] == r->values[0]);
+}
+
+PlatformResult SensorData::CheckInitialization() {
+  LoggerD("Entered: %s", type_to_string_map[type()].c_str());
+
+  if (!handle_) {
+    LoggerD("initialization of handle and listener");
+    int ret = sensor_get_default_sensor(type_enum_, &handle_);
+    if (SENSOR_ERROR_NONE != ret) {
+      LoggerE("sensor_get_default_sensor : %d", ret);
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, "sensor_get_default_sensor");
+    }
+
+    ret = sensor_create_listener(handle_, &listener_);
+    if (SENSOR_ERROR_NONE != ret) {
+      LoggerE("sensor_create_listener : %d", ret);
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, "sensor_create_listener");
+    }
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SensorData::IsSupported(bool* supported) {
+  LoggerD("Entered: %s", type_to_string_map[type()].c_str());
+
+  if (!is_supported_) {
+    bool is_supported = false;
+    auto res = IsSupportedImpl(&is_supported);
+    if (!res) {
+      return res;
+    } else {
+      is_supported_ = is_supported;
+    }
+  }
+
+  *supported = *is_supported_;
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SensorData::IsSupportedImpl(bool* supported) const {
+  LoggerD("Entered: %s", type_to_string_map[type()].c_str());
+
+  bool is_supported = false;
+  int ret = sensor_is_supported(type_enum_, &is_supported);
+  if (SENSOR_ERROR_NONE != ret) {
+    LoggerE("Failed to check if sensor %s is supported", type_to_string_map[type_enum_].c_str());
+    return GetSensorPlatformResult(ret, "sensor_is_supported");
+  } else {
+    *supported = is_supported;
+    LoggerD("supported: %d", is_supported);
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+}
+
+bool SensorData::is_supported() {
+  LoggerD("Entered: %s", type_to_string_map[type()].c_str());
+
+  if (!is_supported_) {
+    bool is_supported = false;
+    auto res = IsSupportedImpl(&is_supported);
+    if (!res) {
+      is_supported_ = false;
+    } else {
+      is_supported_ = is_supported;
+    }
+  }
+
+  return *is_supported_;
+}
+
+bool SensorData::UpdateEvent(sensor_event_s* event) {
+  LoggerD("Entered: %s", type_to_string_map[type()].c_str());
+
+  if (comparator_(&previous_event_, event)) {
+    // previous and current events are the same -> no update
+    return false;
+  } else {
+    previous_event_ = *event;
+    return true;
+  }
+}
+
+PlatformResult SensorData::Start() {
+  LoggerD("Entered: %s", type_to_string_map[type()].c_str());
+
+  auto res = CheckInitialization();
+
+  if (!res) {
+    LoggerE("Sensor initialization for sensor %s failed", type_to_string_map[type_enum_].c_str());
+    return res;
+  }
+
+  sensor_listener_set_option(listener_, SENSOR_OPTION_ALWAYS_ON);
+  int ret = sensor_listener_start(listener_);
+  if (SENSOR_ERROR_NONE != ret) {
+    LoggerE("sensor_listener_start : %d", ret);
+    return GetSensorPlatformResult(ret, "sensor_listener_start");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SensorData::Stop() {
+  LoggerD("Entered: %s", type_to_string_map[type()].c_str());
+
+  auto res = CheckInitialization();
+
+  if (!res) {
+    LoggerE("Sensor initialization for sensor %s failed", type_to_string_map[type_enum_].c_str());
+    return res;
+  }
+
+  int ret = sensor_listener_stop(listener_);
+  if (SENSOR_ERROR_NONE != ret) {
+    LoggerE("sensor_listener_stop : %d", ret);
+    return GetSensorPlatformResult(ret, "sensor_listener_stop");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SensorData::SetChangeListener() {
+  LoggerD("Entered: %s", type_to_string_map[type()].c_str());
+
+  auto res = CheckInitialization();
+
+  if (!res) {
+    LoggerE("Sensor initialization for sensor %s failed", type_to_string_map[type_enum_].c_str());
+    return res;
+  }
+
+  int ret = sensor_listener_set_event_cb(listener_, 100, SensorCallback, this);
+  if (SENSOR_ERROR_NONE != ret) {
+    LoggerE("sensor_listener_set_event_cb : %d", ret);
+    return GetSensorPlatformResult(ret, "sensor_listener_set_event_cb");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SensorData::UnsetChangeListener() {
+  LoggerD("Entered: %s", type_to_string_map[type()].c_str());
+
+  auto res = CheckInitialization();
+
+  if (!res) {
+    LoggerE("Sensor initialization for sensor %s failed", type_to_string_map[type_enum_].c_str());
+    return res;
+  }
+
+  int ret = sensor_listener_unset_event_cb(listener_);
+  if (SENSOR_ERROR_NONE != ret) {
+    LoggerE("sensor_listener_unset_event_cb : %d", ret);
+    return GetSensorPlatformResult(ret, "sensor_listener_unset_event_cb");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SensorData::GetSensorData(picojson::object* data) {
+  LoggerD("Entered: %s", type_to_string_map[type()].c_str());
+
+  auto res = CheckInitialization();
+
+  if (!res) {
+    LoggerE("Sensor initialization for sensor %s failed", type_to_string_map[type_enum_].c_str());
+    return res;
+  }
+
+  sensor_event_s sensor_event;
+  int ret = sensor_listener_read_data(listener_, &sensor_event);
+  if (SENSOR_ERROR_NONE != ret) {
+    LoggerE("sensor_listener_read_data : %d", ret);
+    return GetSensorPlatformResult(ret, "sensor_listener_read_data");
+  }
+
+  ReportSensorData(type_enum_, &sensor_event, data);
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+class HrmSensorData : public SensorData {
+ public:
+  explicit HrmSensorData(SensorInstance& instance);
+  virtual ~HrmSensorData();
+
+  virtual PlatformResult Start();
+  virtual PlatformResult Stop();
+  virtual PlatformResult SetChangeListener();
+  virtual PlatformResult UnsetChangeListener();
+  virtual PlatformResult GetSensorData(picojson::object* data);
+
+ private:
+  void AddSensor(SensorData* sensor);
+  PlatformResult CallMember(PlatformResult (SensorData::*member) ());
+  virtual PlatformResult IsSupportedImpl(bool* supported) const;
+
+  std::map<sensor_type_e, std::shared_ptr<SensorData>> hrm_sensors_;
+};
+
+HrmSensorData::HrmSensorData(SensorInstance& instance)
+    : SensorData(instance, SENSOR_CUSTOM, "HRM_RAW") {
+  LoggerD("Entered: %s", type_to_string_map[type()].c_str());
+  AddSensor(new SensorData(instance, SENSOR_HRM_LED_IR, "LED_IR"));
+  AddSensor(new SensorData(instance, SENSOR_HRM_LED_RED, "LED_RED"));
+  AddSensor(new SensorData(instance, SENSOR_HRM_LED_GREEN, "LED_GREEN"));
+}
+
+HrmSensorData::~HrmSensorData() {
+  LoggerD("Entered: %s", type_to_string_map[type()].c_str());
+}
+
+void HrmSensorData::AddSensor(SensorData* sensor) {
+  LoggerD("Entered: %s", type_to_string_map[type()].c_str());
+  hrm_sensors_.insert(std::make_pair(sensor->type(), std::shared_ptr<SensorData>(sensor)));
+}
+
+PlatformResult HrmSensorData::CallMember(PlatformResult (SensorData::*member) ()) {
+  LoggerD("Entered: %s", type_to_string_map[type()].c_str());
+  for (const auto& sensor : hrm_sensors_) {
+    if (sensor.second->is_supported()) {
+      auto res = (sensor.second.get()->*member)();
+      if (!res) {
+        return res;
+      }
+    }
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult HrmSensorData::IsSupportedImpl(bool* supported) const {
+  LoggerD("Entered: %s", type_to_string_map[type()].c_str());
+  bool result = false;
+
+  bool hrm_supported = false;
+  int ret = sensor_is_supported(SENSOR_HRM, &hrm_supported);
+  if (ret == SENSOR_ERROR_NONE){
+    LoggerD("HRM support is: %d", hrm_supported);
+    result |= hrm_supported;
+  }
+
+  for (const auto& sensor : hrm_sensors_) {
+    bool is_supported = false;
+    auto res = sensor.second->IsSupported(&is_supported);
+    LoggerD("supported: %d", is_supported);
+    if (!res) {
+      return res;
+    }
+    result |= is_supported;
+  }
+  LoggerD("result supported: %d", result);
+  *supported = result;
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult HrmSensorData::Start() {
+  LoggerD("Entered: %s", type_to_string_map[type()].c_str());
+  return CallMember(&SensorData::Start);
+}
+
+PlatformResult HrmSensorData::Stop() {
+  LoggerD("Entered: %s", type_to_string_map[type()].c_str());
+  return CallMember(&SensorData::Stop);
+}
+
+PlatformResult HrmSensorData::SetChangeListener() {
+  LoggerD("Entered: %s", type_to_string_map[type()].c_str());
+  return CallMember(&SensorData::SetChangeListener);
+}
+
+PlatformResult HrmSensorData::UnsetChangeListener() {
+  LoggerD("Entered: %s", type_to_string_map[type()].c_str());
+  return CallMember(&SensorData::UnsetChangeListener);
+}
+
+PlatformResult HrmSensorData::GetSensorData(picojson::object* data) {
+  LoggerD("Entered: %s", type_to_string_map[type()].c_str());
+  for (const auto& sensor : hrm_sensors_) {
+    if (sensor.second->is_supported()) {
+      // HRMRawSensor.getHRMRawSensorData() can return only one value,
+      // so we're returning the data from the first available sensor
+      return sensor.second->GetSensorData(data);
+    }
+  }
+
+  // use default values when are no available HRM sensors
+  const sensor_type_e default_sensor_type = SENSOR_HRM_LED_IR;
+  const double default_sensor_value = 0.0;
+
+  LoggerD("There are no supported HRM sensors - returning default values");
+  (*data)["lightType"] = picojson::value(type_to_string_map[default_sensor_type]);
+  (*data)["lightIntensity"] = picojson::value(default_sensor_value);
+  (*data)[kListenerId] = picojson::value(kSensorChangedListener);
+  (*data)[kSensorTypeTag] = picojson::value(type_to_string_map[default_sensor_type]);
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+SensorService::SensorService(SensorInstance& instance)
+    : instance_(instance) {
+  LoggerD("Entered");
+
+  AddSensor(new SensorData(instance, SENSOR_LIGHT, "LIGHT"));
+  AddSensor(new SensorData(instance, SENSOR_MAGNETIC, "MAGNETIC", MagneticEventComparator));
+  AddSensor(new SensorData(instance, SENSOR_PRESSURE, "PRESSURE"));
+  AddSensor(new SensorData(instance, SENSOR_PROXIMITY, "PROXIMITY"));
+  AddSensor(new SensorData(instance, SENSOR_ULTRAVIOLET, "ULTRAVIOLET"));
+  AddSensor(new HrmSensorData(instance));
+}
+
+SensorService::~SensorService() {
+  LoggerD("Entered");
+}
+
+void SensorService::GetAvailableSensors(picojson::object& out) {
+  LoggerD("Entered");
+
+  bool is_supported = false;
+
+  picojson::value result = picojson::value(picojson::array());
+  picojson::array& result_array = result.get<picojson::array>();
+
+  for (const auto& sensor : sensors_) {
+    auto res = sensor.second->IsSupported(&is_supported);
+    if (!res) {
+      LoggerE("Failed to check if sensor is supported: %s", type_to_string_map[sensor.first].c_str());
+      ReportError(res, &out);
+      return;
+    }
+
+    if (is_supported) {
+      result_array.push_back(picojson::value(type_to_string_map[sensor.first]));
+    }
+  }
+
+  ReportSuccess(result, out);
+}
+
+void SensorService::SensorStart(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+  CHECK_EXIST(args, "callbackId", out)
+  int callback_id = static_cast<int>(args.get("callbackId").get<double>());
+  const std::string type_str =
+      args.contains(kSensorTypeTag) ? args.get(kSensorTypeTag).get<std::string>() : "";
+  LoggerD("input type: %s" , type_str.c_str());
+
+  sensor_type_e type_enum = string_to_type_map[type_str];
+
+  auto start = [this, type_enum, type_str](const std::shared_ptr<picojson::value>& result) {
+    auto sensor_data = GetSensor(type_enum);
+    if (!sensor_data) {
+      LoggerD("Sensor data is null");
+      ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Sensor data is null"),
+                         &(result->get<picojson::object>()));
+      return;
+    }
+
+    PlatformResult res = sensor_data->Start();
+    if (!res) {
+      LoggerE("Failed to start sensor: %s", type_str.c_str());
+      ReportError(res, &(result->get<picojson::object>()));
+    } else {
+      ReportSuccess(result->get<picojson::object>());
+    }
+  };
+  auto start_result = [this, callback_id](const std::shared_ptr<picojson::value>& result) {
+    result->get<picojson::object>()["callbackId"] = picojson::value{static_cast<double>(callback_id)};
+    Instance::PostMessage(&instance_, result->serialize().c_str());
+  };
+
+  auto data = std::shared_ptr<picojson::value>{new picojson::value{picojson::object()}};
+
+  TaskQueue::GetInstance().Queue<picojson::value>(
+      start,
+      start_result,
+      data);
+  ReportSuccess(out);
+}
+
+void SensorService::SensorStop(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+  const std::string type_str =
+      args.contains(kSensorTypeTag) ? args.get(kSensorTypeTag).get<std::string>() : "";
+  LoggerD("input type: %s" , type_str.c_str());
+
+  sensor_type_e type_enum = string_to_type_map[type_str];
+
+  auto sensor_data = GetSensor(type_enum);
+  if (!sensor_data) {
+    LoggerD("Sensor data is null");
+    ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Sensor data is null"), &out);
+    return;
+  }
+
+  PlatformResult res = sensor_data->Stop();
+  if (!res) {
+    LoggerE("Failed to stop sensor: %s", type_str.c_str());
+    ReportError(res, &out);
+  } else {
+    ReportSuccess(out);
+  }
+}
+
+void SensorService::SensorSetChangeListener(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+  const std::string type_str =
+      args.contains(kSensorTypeTag) ? args.get(kSensorTypeTag).get<std::string>() : "";
+  LoggerD("input type: %s" , type_str.c_str());
+
+  sensor_type_e type_enum = string_to_type_map[type_str];
+
+  auto sensor_data = GetSensor(type_enum);
+  if (!sensor_data) {
+    LoggerD("Sensor data is null");
+    ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Sensor data is null"), &out);
+    return;
+  }
+
+  PlatformResult res = sensor_data->SetChangeListener();
+  if (!res) {
+    LoggerE("Failed to set change listener for sensor: %s", type_str.c_str());
+    ReportError(res, &out);
+  } else {
+    ReportSuccess(out);
+  }
+}
+
+void SensorService::SensorUnsetChangeListener(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+  const std::string type_str =
+      args.contains(kSensorTypeTag) ? args.get(kSensorTypeTag).get<std::string>() : "";
+  LoggerD("input type: %s" , type_str.c_str());
+
+  sensor_type_e type_enum = string_to_type_map[type_str];
+
+  auto sensor_data = GetSensor(type_enum);
+  if (!sensor_data) {
+    LoggerD("Sensor data is null");
+    ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Sensor data is null"), &out);
+    return;
+  }
+
+  PlatformResult res = sensor_data->UnsetChangeListener();
+  if (!res) {
+    LoggerE("Failed to remove change listener for sensor: %s", type_str.c_str());
+    ReportError(res, &out);
+  } else {
+    ReportSuccess(out);
+  }
+}
+
+std::shared_ptr<SensorData> SensorService::GetSensor(sensor_type_e type_enum) {
+  LoggerD("Entered");
+  auto sensor = sensors_.find(type_enum);
+
+  if (sensors_.end() == sensor) {
+    return nullptr;
+  } else {
+    return sensor->second;
+  }
+}
+
+void SensorService::AddSensor(SensorData* sensor) {
+  LoggerD("Entered");
+  sensors_.insert(std::make_pair(sensor->type(), std::shared_ptr<SensorData>(sensor)));
+}
+
+void SensorService::GetSensorData(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+
+  CHECK_EXIST(args, "callbackId", out);
+  CHECK_EXIST(args, "type", out);
+
+  int callback_id = static_cast<int>(args.get("callbackId").get<double>());
+  sensor_type_e sensor_type = string_to_type_map[args.get("type").get<std::string>()];
+
+  auto get_data = [this, sensor_type](const std::shared_ptr<picojson::value>& result) {
+    picojson::object& object = result->get<picojson::object>();
+    auto sensor_data = this->GetSensor(sensor_type);
+
+    if (!sensor_data) {
+      LoggerD("Sensor data is null");
+      ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Sensor data is null"), &object);
+      return;
+    }
+
+    PlatformResult res = sensor_data->GetSensorData(&object);
+    if (!res) {
+      LoggerE("Failed to read data for sensor: %s", type_to_string_map[sensor_type].c_str());
+      ReportError(res, &object);
+    } else {
+      ReportSuccess(object);
+    }
+  };
+
+  auto get_data_result = [this, callback_id](const std::shared_ptr<picojson::value>& result) {
+    result->get<picojson::object>()["callbackId"] = picojson::value{static_cast<double>(callback_id)};
+
+    Instance::PostMessage(&instance_, result->serialize().c_str());
+  };
+
+  auto data = std::shared_ptr<picojson::value>{new picojson::value{picojson::object()}};
+
+  TaskQueue::GetInstance().Queue<picojson::value>(
+      get_data,
+      get_data_result,
+      data);
+
+  ReportSuccess(out);
+}
+
+} // namespace sensor
+} // namespace extension
diff --git a/webWidgetTCT_device/src/sensor/sensor_service.h b/webWidgetTCT_device/src/sensor/sensor_service.h
new file mode 100755 (executable)
index 0000000..6de19d5
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2015 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 SENSOR_SENSOR_SERVICE_H_
+#define SENSOR_SENSOR_SERVICE_H_
+
+#include <memory>
+
+#include <sensor.h>
+
+#include "common/picojson.h"
+#include "common/platform_result.h"
+
+namespace extension {
+namespace sensor {
+
+class SensorData;
+class SensorInstance;
+
+class SensorService {
+ public:
+  explicit SensorService(SensorInstance& instance);
+  ~SensorService();
+
+  void GetAvailableSensors(picojson::object& out);
+  void SensorStart(const picojson::value& args, picojson::object& out);
+  void SensorStop(const picojson::value& args, picojson::object& out);
+  void SensorSetChangeListener(const picojson::value& args, picojson::object& out);
+  void SensorUnsetChangeListener(const picojson::value& args, picojson::object& out);
+  void GetSensorData(const picojson::value& args, picojson::object& out);
+
+ private:
+  std::shared_ptr<SensorData> GetSensor(sensor_type_e type_enum);
+  void AddSensor(SensorData* sensor);
+
+  std::map<sensor_type_e, std::shared_ptr<SensorData>> sensors_;
+  SensorInstance& instance_;
+};
+
+} // namespace sensor
+} // namespace extension
+
+#endif // SENSOR_SENSOR_SERVICE_H_
diff --git a/webWidgetTCT_device/src/smartcontroller/smartcontroller.gyp b/webWidgetTCT_device/src/smartcontroller/smartcontroller.gyp
new file mode 100755 (executable)
index 0000000..d305e5c
--- /dev/null
@@ -0,0 +1,34 @@
+{
+  'includes':[
+    '../common/common.gypi',
+  ],
+  'targets': [
+    {
+      'target_name': 'tizen_smartcontroller',
+      'type': 'loadable_module',
+      'dependencies': [
+        '../common/common.gyp:tizen_common',
+      ],
+      'sources': [
+        'smartcontroller_api.js',
+        'smartcontroller_extension.cc',
+        'smartcontroller_extension.h',
+        'smartcontroller_instance.cc',
+        'smartcontroller_instance.h',
+        'smartcontroller_manager.cc',
+        'smartcontroller_manager.h',
+        'smartcontroller_data.cc',
+        'smartcontroller_data.h',
+      ],
+      'conditions': [
+        ['tizen == 1', {
+          'variables': {
+            'packages': [
+              'capi-network-bluetooth',
+            ]
+          },
+        }],
+      ],
+    },
+  ],
+}
diff --git a/webWidgetTCT_device/src/smartcontroller/smartcontroller_api.js b/webWidgetTCT_device/src/smartcontroller/smartcontroller_api.js
new file mode 100755 (executable)
index 0000000..b576f50
--- /dev/null
@@ -0,0 +1,120 @@
+// Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var native = new xwalk.utils.NativeManager(extension);
+var validator = xwalk.utils.validator;
+var converter = xwalk.utils.converter;
+var Type = xwalk.utils.type;
+
+var SmartControllerTouchMode = {
+  "PRESSED": "PRESSED",
+  "RELEASED": "RELEASED"
+};
+
+function SmartControllerChangeCallbackData(dict) {
+    for (var key in dict) {
+      if (dict.hasOwnProperty(key)) {
+        Object.defineProperty(this, key, {
+          value: dict[key],
+          enumerable: true
+        });
+      }
+    }
+  }
+
+function ListenerManager(native, listenerName, addListenerId, removeListenerId) {
+    this.listeners = {};
+    this.listenerName = listenerName;
+    this.nextId = 1;
+    this.addId = addListenerId;
+    this.removeId = removeListenerId;
+    this.nativeListenerRegistered = false;
+    native.addListener(listenerName, this.onListenerCalled.bind(this));
+  }
+
+  ListenerManager.prototype.onListenerCalled = function(msg) {
+    var data = new SmartControllerChangeCallbackData(msg.data);
+    for (var key in this.listeners) {
+      if (this.listeners.hasOwnProperty(key)) {
+        this.listeners[key](data);
+      }
+    }
+  };
+
+  ListenerManager.prototype.addListener = function(callback) {
+    var id = this.nextId;
+    if (this.addId && !(this.nativeListenerRegistered)) {
+        var result = native.callSync(this.addId);
+        if (native.isFailure(result)) {
+          throw native.getErrorObject(result);
+        }
+        this.nativeListenerRegistered = true;
+      }
+    this.listeners[id] = callback;
+    ++this.nextId;
+    return id;
+  };
+
+  ListenerManager.prototype.removeListener = function(watchId) {
+      if (this.listeners.hasOwnProperty(watchId)) {
+        delete this.listeners[watchId];
+      }
+      if (this.nativeListenerRegistered && Type.isEmptyObject(this.listeners)) {
+          native.callSync(this.removeId);
+          native.removeListener(this.listenerName);
+          this.nativeListenerRegistered = false;
+      }
+    };
+
+
+var SMART_CONTROLLER_CHANGE_LISTENER = 'SmartControllerChanged';
+var SMART_CONTROLLER_ADD_CHANGE_LISTENER = 'SmartControllerManager_addChangeListener';
+var SMART_CONTROLLER_REMOVE_CHANGE_LISTENER = 'SmartControllerManager_removeChangeListener';
+var SMART_CONTROLLER_IS_CONNECTED = 'SmartControllerManager_isConnected';
+
+var smartControllerListener = new ListenerManager(
+        native,
+        SMART_CONTROLLER_CHANGE_LISTENER,
+        SMART_CONTROLLER_ADD_CHANGE_LISTENER,
+        SMART_CONTROLLER_REMOVE_CHANGE_LISTENER
+        );
+
+function SmartControllerManager() {
+    if (!(this instanceof SmartControllerManager)) {
+        throw new TypeError;
+      }
+}
+
+SmartControllerManager.prototype.isConnected = function() {
+  var ret = native.callSync(SMART_CONTROLLER_IS_CONNECTED);
+  if (native.isFailure(ret)) {
+    throw native.getErrorObject(ret);
+  }
+
+  return native.getResultObject(ret);
+};
+
+SmartControllerManager.prototype.addChangeListener = function(callback) {
+  var args = validator.validateArgs(arguments, [
+    {
+      name: 'callback',
+      type: validator.Types.FUNCTION
+    }
+  ]);
+
+    return smartControllerListener.addListener(args.callback);
+  };
+
+SmartControllerManager.prototype.removeChangeListener = function() {
+  var args = validator.validateArgs(arguments, [
+      {
+        name : 'watchId',
+        type : validator.Types.LONG
+      }
+  ]);
+
+  smartControllerListener.removeListener(args.watchId);
+};
+
+exports = new SmartControllerManager();
\ No newline at end of file
diff --git a/webWidgetTCT_device/src/smartcontroller/smartcontroller_data.cc b/webWidgetTCT_device/src/smartcontroller/smartcontroller_data.cc
new file mode 100755 (executable)
index 0000000..ee06a1d
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2015 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 "smartcontroller/smartcontroller_data.h"
+#include "common/logger.h"
+#include "bluetooth.h"
+
+namespace extension {
+namespace smartcontroller {
+
+const std::string kPressedMode = "PRESSED";
+const std::string kReleasedMode = "RELEASED";
+const float kMaxRange = 65535.0;
+const float kHalfMaxRange = 32767.0;
+const float kNominator1 = 8.0;
+const float kNominator2 = 2000.0;
+const float kSubtrahend1 = 4.0;
+const float kSubtrahend2 = 1000;
+
+
+SmartControllerData::SmartControllerData() :
+  m_samplingTime(0), m_sensorType(0), m_touchMode(""),
+  m_sensor_x(0, 0), m_sensor_y(0, 0), m_sensor_z(0, 0) {
+}
+
+SmartControllerData::~SmartControllerData() {
+}
+
+long SmartControllerData::getSamplingTime() const {
+    return m_samplingTime;
+}
+
+void SmartControllerData::setSamplingTime(long samplingTime) {
+  m_samplingTime = samplingTime;
+}
+
+long SmartControllerData::getSensorType() const {
+    return m_sensorType;
+}
+
+void SmartControllerData::setSensorType(long sensorType) {
+  m_sensorType = sensorType;
+}
+
+std::string SmartControllerData::getTouchMode() const {
+    return m_touchMode;
+}
+
+void SmartControllerData::setTouchMode(int samplingTime) {
+  LoggerD("Enter");
+  switch(samplingTime) {
+    case 0:
+      m_touchMode = kPressedMode;
+      break;
+    case 2:
+      m_touchMode = kReleasedMode;
+      break;
+  }
+}
+
+sensorInfo SmartControllerData::getSensorInfo(SensorType type) const {
+  switch(type) {
+    case kSensor_x:
+      return m_sensor_x;
+      break;
+    case kSensor_y:
+      return m_sensor_y;
+      break;
+    case kSensor_z:
+      return m_sensor_z;
+      break;
+    default:
+      LoggerW("Unknown sensor type");
+      return sensorInfo(0,0);
+  }
+}
+
+void SmartControllerData::setSensorInfo(sensor_info_s sensorInfo, SensorType type) {
+  LoggerD("Enter");
+  float accel = kNominator1/kMaxRange*(static_cast<signed short>(sensorInfo.accel_data))
+          +kSubtrahend1 - kNominator1*kHalfMaxRange/kMaxRange;
+  long gyro = kNominator2/kMaxRange*(static_cast<signed short>(sensorInfo.gyro_data))
+          +kSubtrahend2 - kNominator2*kHalfMaxRange/kMaxRange;
+  LoggerD("accel: %f", accel);
+  LoggerD("gyro: %f", gyro);
+  switch(type) {
+    case kSensor_x:
+      m_sensor_x.m_Accel = accel;
+      m_sensor_x.m_Gyro = gyro;
+      break;
+    case kSensor_y:
+      m_sensor_y.m_Accel = accel;
+      m_sensor_y.m_Gyro = gyro;
+      break;
+    case kSensor_z:
+      m_sensor_z.m_Accel = accel;
+      m_sensor_z.m_Gyro = gyro;
+      break;
+  }
+}
+
+
+}  //  namespace smartcontroller
+}  //  namespace extension
diff --git a/webWidgetTCT_device/src/smartcontroller/smartcontroller_data.h b/webWidgetTCT_device/src/smartcontroller/smartcontroller_data.h
new file mode 100755 (executable)
index 0000000..343261c
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2015 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 SMARTCONTROLLER_SMARTCONTROLLER_DATA_H_
+#define SMARTCONTROLLER_SMARTCONTROLLER_DATA_H_
+
+#include <string>
+#include "bluetooth.h"
+
+namespace extension {
+namespace smartcontroller {
+
+struct sensorInfo {
+  float m_Accel;
+  long m_Gyro;
+  sensorInfo(long Accel, long Gyro) :
+    m_Accel(Accel), m_Gyro(Gyro)
+  {}
+};
+
+enum SensorType {
+  kSensor_x,
+  kSensor_y,
+  kSensor_z,
+  kUnknown
+};
+
+class SmartControllerData {
+ public:
+  SmartControllerData();
+  ~SmartControllerData();
+
+    long getSamplingTime() const;
+    void setSamplingTime(long samplingTime);
+
+    long getSensorType() const;
+    void setSensorType(long sensorType);
+
+    std::string getTouchMode() const;
+    void setTouchMode(int samplingTime);
+
+    sensorInfo getSensorInfo(SensorType type) const;
+    void setSensorInfo(sensor_info_s sensorInfo, SensorType type);
+
+ private:
+    long m_samplingTime;
+    long m_sensorType;
+    std::string m_touchMode;
+    sensorInfo m_sensor_x;
+    sensorInfo m_sensor_y;
+    sensorInfo m_sensor_z;
+};
+
+}  //  namespace smartcontroller
+}  //  namespace extension
+
+#endif  // SMARTCONTROLLER_SMARTCONTROLLER_DATA_H_
diff --git a/webWidgetTCT_device/src/smartcontroller/smartcontroller_extension.cc b/webWidgetTCT_device/src/smartcontroller/smartcontroller_extension.cc
new file mode 100755 (executable)
index 0000000..d23afb7
--- /dev/null
@@ -0,0 +1,25 @@
+// Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "smartcontroller/smartcontroller_extension.h"
+
+#include "smartcontroller/smartcontroller_instance.h"
+
+// This will be generated from smartcontroller_api.js
+extern const char kSource_smartcontroller_api[];
+
+common::Extension* CreateExtension() {
+  return new SmartControllerExtension;
+}
+
+SmartControllerExtension::SmartControllerExtension() {
+  SetExtensionName("tizen.smartremotecontroller");
+  SetJavaScriptAPI(kSource_smartcontroller_api);
+}
+
+SmartControllerExtension::~SmartControllerExtension() {}
+
+common::Instance* SmartControllerExtension::CreateInstance() {
+  return new extension::smartcontroller::SmartControllerInstance;
+}
diff --git a/webWidgetTCT_device/src/smartcontroller/smartcontroller_extension.h b/webWidgetTCT_device/src/smartcontroller/smartcontroller_extension.h
new file mode 100755 (executable)
index 0000000..4030ff9
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SMARTCONTROLLER_SMARTCONTROLLER_EXTENSION_H_
+#define SMARTCONTROLLER_SMARTCONTROLLER_EXTENSION_H_
+
+#include "common/extension.h"
+
+class SmartControllerExtension : public common::Extension {
+ public:
+  SmartControllerExtension();
+  virtual ~SmartControllerExtension();
+
+ private:
+  virtual common::Instance* CreateInstance();
+};
+
+#endif  // SMARTCONTROLLER_SMARTCONTROLLER_EXTENSION_H_
diff --git a/webWidgetTCT_device/src/smartcontroller/smartcontroller_instance.cc b/webWidgetTCT_device/src/smartcontroller/smartcontroller_instance.cc
new file mode 100755 (executable)
index 0000000..7332a46
--- /dev/null
@@ -0,0 +1,108 @@
+// Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "smartcontroller/smartcontroller_instance.h"
+#include "smartcontroller/smartcontroller_manager.h"
+#include "smartcontroller/smartcontroller_data.h"
+
+#include <functional>
+
+#include "common/logger.h"
+#include "common/picojson.h"
+#include "common/platform_result.h"
+
+namespace extension {
+namespace smartcontroller {
+
+
+SmartControllerInstance::SmartControllerInstance() {
+  LoggerD("Enter");
+  using std::placeholders::_1;
+  using std::placeholders::_2;
+
+  RegisterSyncHandler("SmartControllerManager_isConnected",
+    std::bind(&SmartControllerInstance::IsConnected, this, _1, _2));
+  RegisterSyncHandler("SmartControllerManager_addChangeListener",
+    std::bind(&SmartControllerInstance::AddChangeListener, this, _1, _2));
+  RegisterSyncHandler("SmartControllerManager_removeChangeListener",
+    std::bind(&SmartControllerInstance::RemoveChangeListener, this, _1, _2));
+
+  SmartControllerManager::getInstance().registerListener(this);
+}
+
+SmartControllerInstance::~SmartControllerInstance() {
+  LoggerD("Enter");
+  SmartControllerManager::getInstance().unregisterListener();
+}
+
+void SmartControllerInstance::IsConnected(const picojson::value& args,
+                                         picojson::object& out) {
+  LoggerD("Enter");
+  bool connected = false;
+  common::PlatformResult result =
+        SmartControllerManager::getInstance().IsConnected(&connected);
+  if (result.IsError()) {
+    LoggerD("Error occured");
+    ReportError(result, &out);
+  } else
+    ReportSuccess(picojson::value(connected), out);
+}
+
+void SmartControllerInstance::AddChangeListener(const picojson::value& args,
+                                         picojson::object& out) {
+  LoggerD("Enter");
+  SmartControllerManager::getInstance().AddChangeListener(&out);
+}
+
+void SmartControllerInstance::RemoveChangeListener(const picojson::value& args,
+                                         picojson::object& out) {
+  LoggerD("Enter");
+  SmartControllerManager::getInstance().RemoveChangeListener(&out);
+}
+
+void SmartControllerInstance::onSmartControllerChange() {
+  LoggerD("Enter");
+  SmartControllerData* sc_data =
+      SmartControllerManager::getInstance().getSmartControllerData();
+  picojson::value::object data;
+  data.insert(
+      std::make_pair("samplingTime",
+          picojson::value(static_cast<double>(sc_data->getSamplingTime()))));
+  data.insert(
+      std::make_pair("sensorType",
+          picojson::value(static_cast<double>(sc_data->getSensorType()))));
+  data.insert(
+      std::make_pair("touchMode",
+          picojson::value(sc_data->getTouchMode())));
+  data.insert(
+      std::make_pair("xAccel",
+          picojson::value(static_cast<double>(sc_data->getSensorInfo(kSensor_x).m_Accel))));
+  data.insert(
+      std::make_pair("xGyro",
+          picojson::value(static_cast<double>(sc_data->getSensorInfo(kSensor_x).m_Gyro))));
+  data.insert(
+      std::make_pair("yAccel",
+          picojson::value(static_cast<double>(sc_data->getSensorInfo(kSensor_y).m_Accel))));
+  data.insert(
+      std::make_pair("yGyro",
+          picojson::value(static_cast<double>(sc_data->getSensorInfo(kSensor_y).m_Gyro))));
+  data.insert(
+      std::make_pair("zAccel",
+          picojson::value(static_cast<double>(sc_data->getSensorInfo(kSensor_z).m_Accel))));
+  data.insert(
+      std::make_pair("zGyro",
+          picojson::value(static_cast<double>(sc_data->getSensorInfo(kSensor_z).m_Gyro))));
+
+  picojson::value::object dict;
+  dict["listenerId"] = picojson::value("SmartControllerChanged");
+  dict["data"] = picojson::value(data);
+  dict["success"] = picojson::value(true);
+  picojson::value resultListener(dict);
+  //PostMessage(resultListener.serialize().c_str());
+  Instance::PostMessage(this, resultListener.serialize().c_str());
+}
+
+
+} // namespace smartcontroller
+} // namespace extension
diff --git a/webWidgetTCT_device/src/smartcontroller/smartcontroller_instance.h b/webWidgetTCT_device/src/smartcontroller/smartcontroller_instance.h
new file mode 100755 (executable)
index 0000000..2f67e8b
--- /dev/null
@@ -0,0 +1,30 @@
+// Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SMARTCONTROLLER_SMARTCONTROLLER_INSTANCE_H_
+#define SMARTCONTROLLER_SMARTCONTROLLER_INSTANCE_H_
+
+#include "common/extension.h"
+#include "smartcontroller/smartcontroller_manager.h"
+
+namespace extension {
+namespace smartcontroller {
+
+class SmartControllerInstance :
+  public common::ParsedInstance,
+  public EventListener {
+ public:
+  SmartControllerInstance();
+  virtual ~SmartControllerInstance();
+ private:
+  virtual void onSmartControllerChange();
+  void IsConnected(picojson::value const& args, picojson::object& out);
+  void AddChangeListener(picojson::value const& args, picojson::object& out);
+  void RemoveChangeListener(picojson::value const& args, picojson::object& out);
+};
+
+} // namespace smartcontroller
+} // namespace extension
+
+#endif // SMARTCONTROLLER_SMARTCONTROLLER_INSTANCE_H_
diff --git a/webWidgetTCT_device/src/smartcontroller/smartcontroller_manager.cc b/webWidgetTCT_device/src/smartcontroller/smartcontroller_manager.cc
new file mode 100755 (executable)
index 0000000..329c163
--- /dev/null
@@ -0,0 +1,173 @@
+// Copyright 2014 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "smartcontroller/smartcontroller_manager.h"
+#include "smartcontroller/smartcontroller_data.h"
+#include "common/picojson.h"
+#include "common/logger.h"
+#include "common/platform_result.h"
+#include "common/extension.h"
+#include "bluetooth.h"
+
+namespace extension {
+namespace smartcontroller {
+
+using namespace common;
+using namespace tools;
+
+using common::ErrorCode;
+
+SmartControllerManager::SmartControllerManager() :
+  m_listener(nullptr),
+  bt_hid_is_initialized(false),
+  bt_hid_is_connected(false),
+  bt_hid_sensor_data_set(false),
+  m_SmartControllerData(NULL)
+{
+  LoggerD("Entered");
+  int ret = bt_initialize();
+  if (BT_ERROR_NONE == ret) {
+    LoggerD("Bluetooth service is initialized.");
+
+    ret = bt_hid_host_initialize(HostConnectionStateChangedCB, this);
+    if (BT_ERROR_NONE == ret) {
+      LoggerD("Bluetooth HID(Human Interface Device) Host is initialized.");
+      bt_hid_is_initialized = true;
+    }
+    else {
+      LoggerD("Bluetooth HID(Human Interface Device) Host initialization failed, error: %d (%s)",
+          ret, get_error_message(ret));
+    }
+  }
+  else {
+    LoggerD("Bluetooth service initialization error: %d (%s)", ret, get_error_message(ret));
+  }
+  m_SmartControllerData = new SmartControllerData();
+}
+
+SmartControllerManager::~SmartControllerManager() {
+  if (bt_hid_is_initialized) {
+    int ret =bt_hid_host_deinitialize();
+    if (BT_ERROR_NONE == ret) {
+      LoggerD("Bluetooth HID(Human Interface Device) Host is deinitialized");
+    } else {
+      LoggerE("Bluetooth HID(Human Interface Device) Host deinitialization failed: %d (%s)",
+          ret, get_error_message(ret));
+    }
+    ret = bt_deinitialize();
+    if (BT_ERROR_NONE == ret) {
+      LoggerD("Bluetooth service is deinitialized");
+    } else {
+      LoggerE("Bluetooth service deinitialization failed: %d (%s)",
+          ret, get_error_message(ret));
+    }
+  }
+  delete m_SmartControllerData;
+}
+
+void SmartControllerManager::HostConnectionStateChangedCB(int result,
+                bool connected, const char *remote_address, void *user_data) {
+  LoggerD("Entered");
+
+  SmartControllerManager* sm_manager = static_cast<SmartControllerManager*>(user_data);
+  if (!sm_manager) {
+    LoggerD("User data is NULL");
+    return;
+  }
+
+  sm_manager->bt_hid_is_connected = connected;
+}
+
+void SmartControllerManager::HidSensorChangedCB(
+        bt_smart_rc_sensor_data_s *sensor_data, void *user_data) {
+  LoggerD("Entered");
+
+  SmartControllerManager* sm_manager = static_cast<SmartControllerManager*>(user_data);
+  if (!sm_manager) {
+    LoggerD("User data is NULL");
+    return;
+  }
+  if (!(sm_manager->m_listener)) {
+    LoggerD("Listener is NULL");
+    return;
+  }
+  SmartControllerData* sc_data =
+          SmartControllerManager::getInstance().getSmartControllerData();
+  sc_data->setSamplingTime(static_cast<long>(sensor_data->sampling_time));
+  sc_data->setSensorType(static_cast<long>(sensor_data->sensor_type));
+  sc_data->setTouchMode(static_cast<int>(sensor_data->touch_mode));
+  sc_data->setSensorInfo(sensor_data->x, kSensor_x);
+  sc_data->setSensorInfo(sensor_data->y, kSensor_y);
+  sc_data->setSensorInfo(sensor_data->z, kSensor_z);
+  sm_manager->m_listener->onSmartControllerChange();
+}
+
+SmartControllerManager& SmartControllerManager::getInstance() {
+  LoggerD("Entered");
+  static SmartControllerManager instance;
+  return instance;
+}
+
+common::PlatformResult SmartControllerManager::IsConnected(bool* isConnected) {
+  LoggerD("Enter");
+  int ret = bt_hid_get_smart_remote_conn_status(isConnected);
+  if (BT_ERROR_NONE != ret) {
+    LoggerE("Failed to get connection status for smart remote: %d (%s)",
+        ret, get_error_message(ret));
+    return common::PlatformResult(ErrorCode::UNKNOWN_ERR,
+      "Unknown error. Failed to get connection status for smart remote");
+  }
+  LoggerD("Connection status for smart remote: %d", *isConnected);
+  return common::PlatformResult(ErrorCode::NO_ERROR);
+}
+
+void SmartControllerManager::AddChangeListener(picojson::object* out) {
+  LoggerD("Entered");
+  if (bt_hid_is_initialized) {
+    int ret = bt_hid_set_sensor_data_receive_cb(HidSensorChangedCB, this);
+    if (BT_ERROR_NONE != ret) {
+      LoggerD("Failed to set sensor data receive callback. Error code: %d (%s)",
+          ret, get_error_message(ret));
+      ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR,
+                                 "Failed to set sensor data receive callback"), out);
+      return;
+    }
+    bt_hid_sensor_data_set = true;
+  }
+  ReportSuccess(*out);
+}
+
+void SmartControllerManager::RemoveChangeListener(picojson::object* out) {
+  LoggerD("Entered");
+  if (bt_hid_sensor_data_set) {
+    int ret = bt_hid_unset_sensor_data_receive_cb();
+    if (BT_ERROR_NONE != ret) {
+      LoggerD("Failed to unset sensor data receive callback. Error code: %d (%s)",
+          ret, get_error_message(ret));
+      ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR,
+                                 "Failed to unset sensor data receive callback"), out);
+      return;
+    }
+  }
+  ReportSuccess(*out);
+}
+
+void SmartControllerManager::registerListener(EventListener* pListener) {
+    LoggerD("Enter");
+    m_listener = pListener;
+}
+
+void SmartControllerManager::unregisterListener() {
+    LoggerD("Enter");
+    m_listener = NULL;
+}
+
+SmartControllerData* SmartControllerManager::getSmartControllerData() const {
+  return m_SmartControllerData;
+}
+
+
+}  // namespace smartcontroller
+}  // namespace extension
+
diff --git a/webWidgetTCT_device/src/smartcontroller/smartcontroller_manager.h b/webWidgetTCT_device/src/smartcontroller/smartcontroller_manager.h
new file mode 100755 (executable)
index 0000000..e16cac5
--- /dev/null
@@ -0,0 +1,58 @@
+// Copyright 2014 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SMARTCONTROLLER_SMARTCONTROLLER_MANAGER_H_
+#define SMARTCONTROLLER_SMARTCONTROLLER_MANAGER_H_
+
+#include "common/platform_result.h"
+#include "bluetooth.h"
+#include "smartcontroller/smartcontroller_data.h"
+
+namespace extension {
+namespace smartcontroller {
+
+class EventListener {
+ public:
+    virtual void onSmartControllerChange() = 0;
+    virtual ~EventListener() {
+    }
+};
+
+class SmartControllerManager {
+ public:
+  common::PlatformResult IsConnected(bool* isConnected);
+  void AddChangeListener(picojson::object* out);
+  void RemoveChangeListener(picojson::object* out);
+
+  // Not copyable, assignable, movable
+  SmartControllerManager(SmartControllerManager const&) = delete;
+  SmartControllerManager(SmartControllerManager &&) = delete;
+  SmartControllerManager& operator=(const SmartControllerManager &) = delete;
+  SmartControllerManager& operator=(SmartControllerManager &&) = delete;
+
+  static SmartControllerManager& getInstance();
+  void registerListener(EventListener* pListener);
+  void unregisterListener();
+  SmartControllerData* getSmartControllerData() const;
+  private:
+  SmartControllerManager();
+  virtual ~SmartControllerManager();
+
+  static void HostConnectionStateChangedCB(int result,
+                  bool connected, const char *remote_address, void *user_data);
+  static void HidSensorChangedCB(bt_smart_rc_sensor_data_s *sensor_data,
+                                 void *user_data);
+
+  EventListener* m_listener;
+  bool bt_hid_is_initialized;
+  bool bt_hid_is_connected;
+  bool bt_hid_sensor_data_set;
+  SmartControllerData* m_SmartControllerData;
+};
+
+}  // namespace smartcontroller
+}  // namespace extension
+
+#endif  // SMARTCONTROLLER_SMARTCONTROLLER_MANAGER_H_
+
diff --git a/webWidgetTCT_device/src/sound/sound.gyp b/webWidgetTCT_device/src/sound/sound.gyp
new file mode 100755 (executable)
index 0000000..e421089
--- /dev/null
@@ -0,0 +1,38 @@
+{
+  'includes':[
+    '../common/common.gypi',
+  ],
+  'targets': [
+    {
+      'target_name': 'tizen_sound',
+      'type': 'loadable_module',
+      'dependencies': [
+        '../common/common.gyp:tizen_common',
+      ],
+      'variables': {
+        'packages': [
+          'icu-i18n',
+        ],
+      },
+      'sources': [
+        'sound_api.js',
+        'sound_extension.cc',
+        'sound_extension.h',
+        'sound_instance.cc',
+        'sound_instance.h',
+        'sound_manager.cc',
+        'sound_manager.h',
+      ],
+      'conditions': [
+        [ 'tizen == 1', {
+            'variables': {
+              'packages': [
+                'vconf',
+                'capi-media-sound-manager',
+              ]
+            },
+        }],
+      ],
+    },
+  ],
+}
diff --git a/webWidgetTCT_device/src/sound/sound_api.js b/webWidgetTCT_device/src/sound/sound_api.js
new file mode 100755 (executable)
index 0000000..d66a489
--- /dev/null
@@ -0,0 +1,260 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+var utils_ = xwalk.utils;
+var type_ = utils_.type;
+var converter_ = utils_.converter;
+var validator_ = utils_.validator;
+var privilege_ = utils_.privilege;
+var types_ = validator_.Types;
+var native_ = new xwalk.utils.NativeManager(extension);
+
+
+var SoundType = {
+  SYSTEM: 'SYSTEM',
+  NOTIFICATION: 'NOTIFICATION',
+  ALARM: 'ALARM',
+  MEDIA: 'MEDIA',
+  VOICE: 'VOICE',
+  RINGTONE: 'RINGTONE'
+};
+
+var SoundModeType = {
+  SOUND: 'SOUND',
+  VIBRATE: 'VIBRATE',
+  MUTE: 'MUTE'
+};
+
+function _createSoundDeviceInfoArray(e) {
+  var devices_array = [];
+
+  e.forEach(function (data) {
+    devices_array.push(new SoundDeviceInfo(data));
+  });
+
+  return devices_array;
+};
+
+function ListenerManager(native, listenerName) {
+  this.listeners = {};
+  this.nextId = 1;
+  this.nativeSet = false;
+  this.native = native;
+  this.listenerName = listenerName;
+};
+
+ListenerManager.prototype.onListenerCalled = function(msg) {
+  var obj = new SoundDeviceInfo(msg);
+  for (var watchId in this.listeners) {
+    if (this.listeners.hasOwnProperty(watchId)) {
+      this.listeners[watchId](obj);
+    }
+  }
+};
+
+ListenerManager.prototype.addListener = function(callback) {
+  var id = this.nextId;
+  if (!this.nativeSet) {
+    this.native.addListener(this.listenerName, this.onListenerCalled.bind(this));
+    this.native.callSync('SoundManager_addDeviceStateChangeListener');
+    this.nativeSet = true;
+  }
+
+  this.listeners[id] = callback;
+  ++this.nextId;
+
+  return id;
+};
+
+ListenerManager.prototype.removeListener = function(watchId) {
+  if (this.listeners.hasOwnProperty(watchId)) {
+    delete this.listeners[watchId];
+  } else {
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+        'Listener with id: ' + watchId + ' does not exist.');
+  }
+
+  if (this.nativeSet && type_.isEmptyObject(this.listeners)) {
+      this.native.callSync('SoundManager_removeDeviceStateChangeListener');
+      this.native.removeListener(this.listenerName);
+      this.nativeSet = false;
+  }
+};
+
+var DEVICE_STATE_CHANGE_LISTENER = 'SoundDeviceStateChangeCallback';
+var soundDeviceStateChangeListener = new ListenerManager(native_, DEVICE_STATE_CHANGE_LISTENER);
+
+function SoundManager() {}
+
+SoundManager.prototype.getSoundMode = function() {
+  var result = native_.callSync('SoundManager_getSoundMode');
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+
+  return native_.getResultObject(result);
+};
+
+SoundManager.prototype.setVolume = function(type, volume) {
+  utils_.checkPrivilegeAccess(privilege_.VOLUME_SET);
+
+  var args = validator_.validateArgs(arguments, [
+    {name: 'type', type: types_.ENUM, values: Object.keys(SoundType)},
+    {name: 'volume', type: types_.DOUBLE}
+  ]);
+
+  if (args.volume < 0 || args.volume > 1) {
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR);
+  }
+  var result = native_.callSync('SoundManager_setVolume', args);
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+};
+
+SoundManager.prototype.getVolume = function(type) {
+  var args = validator_.validateArgs(arguments, [
+    {name: 'type', type: types_.ENUM, values: Object.keys(SoundType)}
+  ]);
+
+  var result = native_.callSync('SoundManager_getVolume', args);
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+
+  return native_.getResultObject(result);
+};
+
+var _soundModeChangeListener;
+
+function _soundModeChangeListenerCallback(result) {
+  native_.callIfPossible(_soundModeChangeListener, native_.getResultObject(result));
+}
+
+SoundManager.prototype.setSoundModeChangeListener = function(callback) {
+  var args = validator_.validateArgs(arguments, [
+    {name: 'callback', type: types_.FUNCTION}
+  ]);
+
+  _soundModeChangeListener = args.callback;
+  native_.addListener('SoundModeChangeListener', _soundModeChangeListenerCallback);
+
+  var result = native_.callSync('SoundManager_setSoundModeChangeListener', {});
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+};
+
+SoundManager.prototype.unsetSoundModeChangeListener = function() {
+  native_.removeListener('SoundModeChangeListener', _soundModeChangeListenerCallback);
+
+  var result = native_.callSync('SoundManager_unsetSoundModeChangeListener', {});
+
+  _soundModeChangeListener = undefined;
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+};
+
+var _volumeChangeListener;
+
+function _volumeChangeListenerCallback(result) {
+  native_.callIfPossible(_volumeChangeListener, result.type, result.volume);
+}
+
+SoundManager.prototype.setVolumeChangeListener = function(callback) {
+  var args = validator_.validateArgs(arguments, [
+    {name: 'callback', type: types_.FUNCTION}
+  ]);
+
+  _volumeChangeListener = args.callback;
+  native_.addListener('VolumeChangeListener', _volumeChangeListenerCallback);
+
+  var result = native_.callSync('SoundManager_setVolumeChangeListener', {});
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+};
+
+SoundManager.prototype.unsetVolumeChangeListener = function() {
+  native_.removeListener('VolumeChangeListener', _volumeChangeListenerCallback);
+
+  var result = native_.callSync('SoundManager_unsetVolumeChangeListener', {});
+
+  _volumeChangeListener = undefined;
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+};
+
+SoundManager.prototype.getConnectedDeviceList = function() {
+  var result = native_.callSync('SoundManager_getConnectedDeviceList', {});
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+
+  var devices = _createSoundDeviceInfoArray(native_.getResultObject(result));
+  return devices;
+};
+
+SoundManager.prototype.getActivatedDeviceList = function() {
+  var result = native_.callSync('SoundManager_getActivatedDeviceList', {});
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+
+  var devices = _createSoundDeviceInfoArray(native_.getResultObject(result));
+  return devices;
+};
+
+SoundManager.prototype.addDeviceStateChangeListener = function() {
+  var args = validator_.validateArgs(arguments, [
+    {
+       name : 'eventCallback',
+       type : types_.FUNCTION
+     }
+  ]);
+
+  return soundDeviceStateChangeListener.addListener(args.eventCallback);
+};
+
+SoundManager.prototype.removeDeviceStateChangeListener = function() {
+  var args = validator_.validateArgs(arguments, [
+    {
+       name : 'watchId',
+       type : types_.LONG
+    }
+  ]);
+
+  soundDeviceStateChangeListener.removeListener(args.watchId);
+};
+
+function SoundDeviceInfo(data) {
+  Object.defineProperties(this, {
+    id: {value: data.id, writable: false, enumerable: true},
+    name: {value: data.name, writable: false, enumerable: true},
+    device : {value: data.device, writable: false, enumerable: true},
+    direction : {value: data.direction, writable: false, enumerable: true},
+    isConnected: {value: data.isConnected, writable: false, enumerable: true},
+    isActivated: {value: data.isActivated, writable: false, enumerable: true},
+  });
+};
+
+exports = new SoundManager();
diff --git a/webWidgetTCT_device/src/sound/sound_extension.cc b/webWidgetTCT_device/src/sound/sound_extension.cc
new file mode 100755 (executable)
index 0000000..400cdf5
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2015 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 "sound/sound_extension.h"
+
+#include "sound/sound_instance.h"
+
+// This will be generated from sound_api.js
+extern const char kSource_sound_api[];
+
+common::Extension* CreateExtension() {
+  return new SoundExtension;
+}
+
+SoundExtension::SoundExtension() {
+  SetExtensionName("tizen.sound");
+  SetJavaScriptAPI(kSource_sound_api);
+}
+
+SoundExtension::~SoundExtension() {}
+
+common::Instance* SoundExtension::CreateInstance() {
+  return new extension::sound::SoundInstance();
+}
diff --git a/webWidgetTCT_device/src/sound/sound_extension.h b/webWidgetTCT_device/src/sound/sound_extension.h
new file mode 100755 (executable)
index 0000000..8b964c5
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2015 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 SOUND_SOUND_EXTENSION_H_
+#define SOUND_SOUND_EXTENSION_H_
+
+#include "common/extension.h"
+
+class SoundExtension : public common::Extension {
+ public:
+  SoundExtension();
+  virtual ~SoundExtension();
+
+ private:
+  virtual common::Instance* CreateInstance();
+};
+
+#endif // SOUND_SOUND_EXTENSION_H_
diff --git a/webWidgetTCT_device/src/sound/sound_instance.cc b/webWidgetTCT_device/src/sound/sound_instance.cc
new file mode 100755 (executable)
index 0000000..ac25768
--- /dev/null
@@ -0,0 +1,217 @@
+/*
+ * Copyright (c) 2015 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 "sound/sound_instance.h"
+
+#include <functional>
+
+#include "common/picojson.h"
+#include "common/logger.h"
+#include "common/platform_exception.h"
+#include "sound_manager.h"
+
+namespace extension {
+namespace sound {
+
+using namespace common;
+using namespace extension::sound;
+
+SoundInstance::SoundInstance(): manager_(*this) {
+  LoggerD("Enter");
+  using std::placeholders::_1;
+  using std::placeholders::_2;
+
+  #define REGISTER_SYNC(c,x) \
+    RegisterSyncHandler(c, std::bind(&SoundInstance::x, this, _1, _2));
+  REGISTER_SYNC("SoundManager_setVolume", SoundManagerSetVolume);
+  REGISTER_SYNC("SoundManager_unsetSoundModeChangeListener", SoundManagerUnsetSoundModeChangeListener);
+  REGISTER_SYNC("SoundManager_getVolume", SoundManagerGetVolume);
+  REGISTER_SYNC("SoundManager_unsetVolumeChangeListener", SoundManagerUnsetVolumeChangeListener);
+  REGISTER_SYNC("SoundManager_setSoundModeChangeListener", SoundManagerSetSoundModeChangeListener);
+  REGISTER_SYNC("SoundManager_setVolumeChangeListener", SoundManagerSetVolumeChangeListener);
+  REGISTER_SYNC("SoundManager_getSoundMode", SoundManagerGetSoundMode);
+  REGISTER_SYNC("SoundManager_getConnectedDeviceList", SoundManagerGetConnectedDeviceList);
+  REGISTER_SYNC("SoundManager_getActivatedDeviceList", SoundManagerGetActivatedDeviceList);
+  REGISTER_SYNC("SoundManager_addDeviceStateChangeListener",
+                SoundManagerAddDeviceStateChangeListener);
+  REGISTER_SYNC("SoundManager_removeDeviceStateChangeListener",
+                SoundManagerRemoveDeviceStateChangeListener);
+  #undef REGISTER_SYNC
+}
+
+SoundInstance::~SoundInstance() {
+  LoggerD("Enter");
+}
+
+#define CHECK_EXIST(args, name, out) \
+    if (!args.contains(name)) {\
+      ReportError(TypeMismatchException(name" is required argument"), out);\
+      return;\
+    }
+
+void SoundInstance::SoundManagerGetSoundMode(const picojson::value& args,
+                                             picojson::object& out) {
+  LoggerD("Enter");
+  std::string sound_mode_type;
+  PlatformResult status = manager_.GetSoundMode(&sound_mode_type);
+
+  if (status.IsSuccess()) {
+    ReportSuccess(picojson::value(sound_mode_type), out);
+  } else {
+    LoggerE("Failed");
+    ReportError(status, &out);
+  }
+}
+
+void SoundInstance::SoundManagerSetVolume(const picojson::value& args,
+                                          picojson::object& out) {
+  LoggerD("Enter");
+  PlatformResult status = manager_.SetVolume(args.get<picojson::object>());
+
+  if (status.IsSuccess()) {
+    ReportSuccess(out);
+  } else {
+    LoggerE("Failed");
+    ReportError(status, &out);
+  }
+}
+
+
+void SoundInstance::SoundManagerGetVolume(const picojson::value& args,
+                                          picojson::object& out) {
+  LoggerD("Enter");
+  double volume;
+  PlatformResult status =
+      manager_.GetVolume(args.get<picojson::object>(), &volume);
+
+  if (status.IsSuccess()) {
+    ReportSuccess(picojson::value(volume), out);
+  } else {
+    LoggerE("Failed");
+    ReportError(status, &out);
+  }
+}
+
+void SoundInstance::SoundManagerSetSoundModeChangeListener(const picojson::value& args, picojson::object& out) {
+  LoggerD("Enter");
+  PlatformResult status = manager_.SetSoundModeChangeListener(this);
+
+  if (status.IsSuccess()) {
+    ReportSuccess(out);
+  } else {
+    LoggerE("Failed");
+    ReportError(status, &out);
+  }
+}
+
+void SoundInstance::SoundManagerUnsetSoundModeChangeListener(const picojson::value& args, picojson::object& out) {
+  PlatformResult status = manager_.UnsetSoundModeChangeListener();
+
+  LoggerD("Enter");
+
+  if (status.IsSuccess()) {
+    ReportSuccess(out);
+  } else {
+    LoggerE("Failed");
+    ReportError(status, &out);
+  }
+}
+
+void SoundInstance::OnSoundModeChange(const std::string& newmode)
+{
+  LoggerD("Enter");
+  picojson::value event = picojson::value(picojson::object());
+  picojson::object& obj = event.get<picojson::object>();
+  picojson::value result = picojson::value(newmode);
+  ReportSuccess(result, obj);
+  obj["listenerId"] = picojson::value("SoundModeChangeListener");
+  LoggerD("Posting: %s", event.serialize().c_str());
+  Instance::PostMessage(this, event.serialize().c_str());
+}
+
+
+void SoundInstance::SoundManagerSetVolumeChangeListener(
+    const picojson::value& args, picojson::object& out) {
+  LoggerD("Enter");
+  PlatformResult status = manager_.SetVolumeChangeListener();
+
+  if (status.IsSuccess()) {
+    ReportSuccess(out);
+  } else {
+    LoggerE("Failed");
+    ReportError(status, &out);
+  }
+}
+
+void SoundInstance::SoundManagerUnsetVolumeChangeListener(
+    const picojson::value& args, picojson::object& out) {
+  LoggerD("Enter");
+  PlatformResult status = manager_.UnsetVolumeChangeListener();
+
+  if (status.IsSuccess()) {
+    ReportSuccess(out);
+  } else {
+    LoggerE("Failed");
+    ReportError(status, &out);
+  }
+}
+
+void SoundInstance::SoundManagerGetConnectedDeviceList(
+    const picojson::value& args, picojson::object& out) {
+
+  LoggerD("Entered");
+  manager_.GetDeviceList(SOUND_DEVICE_ALL_MASK, out);
+}
+
+void SoundInstance::SoundManagerGetActivatedDeviceList(
+    const picojson::value& args, picojson::object& out) {
+
+  LoggerD("Entered");
+  manager_.GetDeviceList(SOUND_DEVICE_STATE_ACTIVATED_MASK, out);
+}
+
+void SoundInstance::SoundManagerAddDeviceStateChangeListener(
+    const picojson::value& args, picojson::object& out) {
+
+  LoggerD("Entered");
+  PlatformResult result = manager_.AddDeviceStateChangeListener();
+
+  if (result.IsSuccess()) {
+    ReportSuccess(out);
+  } else {
+    LoggerE("Failed");
+    ReportError(result, &out);
+  }
+}
+
+void SoundInstance::SoundManagerRemoveDeviceStateChangeListener(
+    const picojson::value& args, picojson::object& out) {
+
+  LoggerD("Entered");
+  PlatformResult result = manager_.RemoveDeviceStateChangeListener();
+
+  if (result.IsSuccess()) {
+    ReportSuccess(out);
+  } else {
+    LoggerE("Failed");
+    ReportError(result, &out);
+  }
+}
+
+#undef CHECK_EXIST
+
+} // namespace sound
+} // namespace extension
diff --git a/webWidgetTCT_device/src/sound/sound_instance.h b/webWidgetTCT_device/src/sound/sound_instance.h
new file mode 100755 (executable)
index 0000000..700246e
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2015 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 SOUND_SOUND_INSTANCE_H_
+#define SOUND_SOUND_INSTANCE_H_
+
+#include "common/extension.h"
+#include "sound_manager.h"
+
+namespace extension {
+namespace sound {
+
+class SoundInstance : public common::ParsedInstance, public SoundManagerSoundModeChangedListener {
+ public:
+  SoundInstance();
+  virtual ~SoundInstance();
+
+ private:
+  void SoundManagerSetVolume(const picojson::value& args, picojson::object& out);
+  void SoundManagerUnsetSoundModeChangeListener(const picojson::value& args, picojson::object& out);
+  void SoundManagerGetVolume(const picojson::value& args, picojson::object& out);
+  void SoundManagerUnsetVolumeChangeListener(const picojson::value& args, picojson::object& out);
+  void SoundManagerSetSoundModeChangeListener(const picojson::value& args, picojson::object& out);
+  void SoundManagerSetVolumeChangeListener(const picojson::value& args, picojson::object& out);
+  void SoundManagerGetSoundMode(const picojson::value& args, picojson::object& out);
+  void SoundManagerGetConnectedDeviceList(const picojson::value& args, picojson::object& out);
+  void SoundManagerGetActivatedDeviceList(const picojson::value& args, picojson::object& out);
+  void SoundManagerAddDeviceStateChangeListener(const picojson::value& args, picojson::object& out);
+  void SoundManagerRemoveDeviceStateChangeListener(
+      const picojson::value& args, picojson::object& out);
+
+  void OnSoundModeChange(const std::string& newmode);
+
+  SoundManager manager_;
+};
+
+} // namespace sound
+} // namespace extension
+
+#endif // SOUND_SOUND_INSTANCE_H_
diff --git a/webWidgetTCT_device/src/sound/sound_manager.cc b/webWidgetTCT_device/src/sound/sound_manager.cc
new file mode 100755 (executable)
index 0000000..c0ef677
--- /dev/null
@@ -0,0 +1,630 @@
+/*
+ * Copyright (c) 2015 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 "sound/sound_manager.h"
+
+#include <tizen/tizen.h>
+#include <vconf.h>
+#include <vconf-keys.h>
+
+#include "common/task-queue.h"
+
+//This constant was originally defined in vconf.h. However, in tizen 3, it
+//appears, it is removed (or defined only in vconf-internals.h)
+//It is not clear, if it is final solution, or not.
+#ifndef VCONF_OK
+#define VCONF_OK 0
+#endif
+
+#include "sound/sound_instance.h"
+#include "common/logger.h"
+#include "common/converter.h"
+
+namespace extension {
+namespace sound {
+
+using namespace common;
+using namespace common::tools;
+
+const std::map<std::string, sound_type_e> SoundManager::platform_enum_map_ = {
+    {"SYSTEM", SOUND_TYPE_SYSTEM},
+    {"NOTIFICATION", SOUND_TYPE_NOTIFICATION},
+    {"ALARM", SOUND_TYPE_ALARM},
+    {"MEDIA", SOUND_TYPE_MEDIA},
+    {"VOICE", SOUND_TYPE_VOICE},
+    {"RINGTONE", SOUND_TYPE_RINGTONE}};
+
+PlatformResult SoundManager::StrToPlatformEnum(const std::string& key,
+                                               sound_type_e* sound_type) {
+  LoggerD("Enter");
+  if (platform_enum_map_.find(key) == platform_enum_map_.end()) {
+    std::string message = "Platform enum value not found for key " + key;
+    return PlatformResult(ErrorCode::INVALID_VALUES_ERR, message);
+  }
+
+  *sound_type = platform_enum_map_.at(key);
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SoundManager::PlatformEnumToStr(const sound_type_e value,
+                                               std::string* sound_type) {
+  LoggerD("Enter");
+  for (auto& item : platform_enum_map_) {
+    if (item.second == value) {
+      *sound_type = item.first;
+
+      return PlatformResult(ErrorCode::NO_ERROR);
+    }
+  }
+
+  std::string message =
+      "Platform enum value " + std::to_string(value) + " not found";
+
+  return PlatformResult(ErrorCode::INVALID_VALUES_ERR, message);
+}
+
+std::string SoundManager::SoundDeviceTypeToString(sound_device_type_e type) {
+  LoggerD("Enter");
+  switch (type) {
+    case SOUND_DEVICE_BUILTIN_SPEAKER:
+      return "SPEAKER";
+    case SOUND_DEVICE_BUILTIN_RECEIVER:
+      return "RECEIVER";
+    case SOUND_DEVICE_BUILTIN_MIC:
+      return "MIC";
+    case SOUND_DEVICE_AUDIO_JACK:
+      return "AUDIO_JACK";
+    case SOUND_DEVICE_BLUETOOTH:
+      return "BLUETOOTH";
+    case SOUND_DEVICE_HDMI:
+      return "HDMI";
+    case SOUND_DEVICE_MIRRORING:
+      return "MIRRORING";
+    case SOUND_DEVICE_USB_AUDIO:
+      return "USB_AUDIO";
+    default:
+      LoggerE("Invalid sound_device_type_e: %d", type);
+      return "";
+  }
+}
+
+std::string SoundManager::SoundIOTypeToString(sound_device_io_direction_e type) {
+  LoggerD("Enter");
+  switch (type) {
+    case SOUND_DEVICE_IO_DIRECTION_IN:
+      return "IN";
+    case SOUND_DEVICE_IO_DIRECTION_OUT:
+      return "OUT";
+    case SOUND_DEVICE_IO_DIRECTION_BOTH:
+      return "BOTH";
+    default:
+      LoggerE("Invalid sound_device_io_direction_e: %d", type);
+      return "";
+  }
+}
+
+SoundManager::SoundManager(SoundInstance& instance)
+    : is_volume_change_listener_(false),
+      soundModeChangeListening(false),
+      sound_device_change_listener_(false),
+      instance_(instance),
+      soundModeListener(nullptr) {
+  FillMaxVolumeMap();
+}
+
+SoundManager::~SoundManager() {
+  LoggerD("Enter");
+  if (soundModeChangeListening) {
+    int status = vconf_ignore_key_changed(VCONFKEY_SETAPPL_VIBRATION_STATUS_BOOL, SoundManager::soundModeChangedCb);
+    if (VCONF_OK != status) {
+      LoggerE("Cannot disable listener!");
+    }
+  }
+
+  if (sound_device_change_listener_) {
+    if (SOUND_MANAGER_ERROR_NONE != sound_manager_unset_device_connected_cb()) {
+      LoggerE("Cannot unregister connection listener!");
+    }
+
+    if (SOUND_MANAGER_ERROR_NONE != sound_manager_unset_device_information_changed_cb()) {
+      LoggerE("Cannot unregister information listener!");
+    }
+  }
+
+  if (is_volume_change_listener_) {
+    if (SOUND_MANAGER_ERROR_NONE != sound_manager_unset_volume_changed_cb()) {
+      LoggerE("Cannot unregister volume listener!");
+    }
+  }
+}
+
+void SoundManager::FillMaxVolumeMap() {
+  LoggerD("Enter");
+  int max = 100;
+  int ret;
+
+  for (auto& item : platform_enum_map_) {
+    max = 100;
+
+    ret = sound_manager_get_max_volume(item.second, &max);
+    if (ret != SOUND_MANAGER_ERROR_NONE) {
+      LoggerE("SoundManagerGetMaxVolumeFailed : %d", ret);
+    }
+
+    LoggerD("maxVolume: %d - %d", item.second, max);
+
+    max_volume_map_[item.second] = max;
+  }
+}
+
+PlatformResult SoundManager::GetMaxVolume(sound_type_e type, int* max_volume) {
+  LoggerD("Enter");
+  auto it = max_volume_map_.find(type);
+  if (it == max_volume_map_.end()) {
+    std::string sound_type;
+    PlatformResult status = PlatformEnumToStr(type, &sound_type);
+    if (status.IsError()) return status;
+    LoggerE("Failed to find maxVolume of type: %s", sound_type.c_str());
+
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to find maxVolume");
+  }
+
+  *max_volume = it->second;
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+double SoundManager::ConvertToSystemVolume(int max_volume, int volume) {
+  LoggerD("Enter");
+  return round(static_cast<double>(volume) * 10 / max_volume) / 10;
+}
+
+void SoundManager::VolumeChangeCallback(sound_type_e type, unsigned int value) {
+  LoggerD("VolumeChangeCallback: type: %d, value: %d", type, value);
+
+  // Prepare response
+  picojson::value response = picojson::value(picojson::object());
+  picojson::object& response_obj = response.get<picojson::object>();
+
+  response_obj.insert(
+      std::make_pair("listenerId", picojson::value("VolumeChangeListener")));
+
+  std::string sound_type;
+  PlatformResult status = PlatformEnumToStr(type, &sound_type);
+  if (status.IsError())
+      return;
+
+  response_obj.insert(
+      std::make_pair("type", picojson::value(sound_type)));
+
+  int max_volume;
+  status = GetMaxVolume(type, &max_volume);
+  if (status.IsError())
+      return;
+
+  response_obj.insert(std::make_pair(
+      "volume",
+      picojson::value(ConvertToSystemVolume(max_volume, value))));
+
+  Instance::PostMessage(&instance_, response.serialize().c_str());
+}
+
+PlatformResult SoundManager::GetSoundMode(std::string* sound_mode_type) {
+  LoggerD("Enter");
+  int isEnableSound = 0;
+  int isEnableVibrate = 0;
+
+  *sound_mode_type = "MUTE";
+
+  int ret = vconf_get_bool(VCONFKEY_SETAPPL_SOUND_STATUS_BOOL, &isEnableSound);
+  if (VCONF_OK != ret) {
+    LoggerE("Unknown error : %d", ret);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Unknown error: " + std::to_string(ret));
+  }
+
+  ret =
+      vconf_get_bool(VCONFKEY_SETAPPL_VIBRATION_STATUS_BOOL, &isEnableVibrate);
+  if (VCONF_OK != ret) {
+    LoggerE("Unknown error : %d", ret);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Unknown error: " + std::to_string(ret));
+  }
+
+  if (isEnableSound && isEnableVibrate) {
+    LoggerE("Wrong state (sound && vibration)");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Platform has wrong state.");
+  }
+
+  if (isEnableSound) {
+    *sound_mode_type = "SOUND";
+  } else if (isEnableVibrate) {
+    *sound_mode_type = "VIBRATE";
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SoundManager::SetVolume(const picojson::object& args) {
+  LoggerD("Enter");
+  const std::string& type = FromJson<std::string>(args, "type");
+  double volume = FromJson<double>(args, "volume");
+
+  LoggerD("SoundType: %s", type.c_str());
+  LoggerD("volume: %f", volume);
+
+  if (volume > 1.0 || volume < 0.0) {
+    LoggerE("Volume should be the value between 0 and 1.");
+    return PlatformResult(ErrorCode::INVALID_VALUES_ERR,
+                          "Volume should be the value between 0 and 1.");
+  }
+
+  sound_type_e sound_type;
+  PlatformResult status = SoundManager::StrToPlatformEnum(type, &sound_type);
+  if (status.IsError()) return status;
+
+  auto it = max_volume_map_.find(sound_type);
+  if (it == max_volume_map_.end()) {
+    LoggerE("Failed to find maxVolume of type: %d", type.c_str());
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to find maxVolume");
+  }
+
+  int max_volume = it->second;
+  int value = round(volume * max_volume);
+  LoggerD("volume: %lf, maxVolume: %d, value: %d", volume, max_volume, value);
+
+  int ret = sound_manager_set_volume(sound_type, value);
+  if (ret != SOUND_MANAGER_ERROR_NONE) {
+    LoggerE("Failed to set volume: %d", ret);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to set volume");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SoundManager::GetVolume(const picojson::object& args,
+                                       double* volume) {
+  LoggerD("Enter");
+  const std::string& type = FromJson<std::string>(args, "type");
+  int value = 0;
+
+  sound_type_e type_enum;
+  PlatformResult status = SoundManager::StrToPlatformEnum(type, &type_enum);
+  if (status.IsError()) return status;
+
+  int max_volume;
+  status = GetMaxVolume(type_enum, &max_volume);
+  if (status.IsError()) return status;
+
+  int ret = sound_manager_get_volume(type_enum, &value);
+  if (ret != SOUND_MANAGER_ERROR_NONE) {
+    LoggerE("Failed to get volume: %d", ret);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get volume");
+  }
+
+  *volume = ConvertToSystemVolume(max_volume, value);
+  LoggerD("volume: %lf, maxVolume: %d, value: %d", volume, max_volume, value);
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+void SoundManager::soundModeChangedCb(keynode_t*, void* user_data)
+{
+  LoggerD("Enter");
+  if (user_data == nullptr) {
+    LoggerE("Invalid callback data!");
+    return;
+  }
+  SoundManager* self = static_cast<SoundManager*>(user_data);
+
+  std::string soundModeType;
+  PlatformResult status = self->GetSoundMode(&soundModeType);
+
+  if (status.IsSuccess() && self->soundModeListener) {
+    self->soundModeListener->OnSoundModeChange(soundModeType);
+  } else {
+    LoggerE("No SoundModeListener attached");
+  }
+}
+
+PlatformResult SoundManager::SetSoundModeChangeListener(
+    SoundManagerSoundModeChangedListener* listener) {
+  LoggerD("Enter");
+  soundModeListener = listener;
+  if (soundModeChangeListening) return PlatformResult(ErrorCode::NO_ERROR);
+
+  int status = vconf_notify_key_changed(VCONFKEY_SETAPPL_VIBRATION_STATUS_BOOL,
+                                        SoundManager::soundModeChangedCb, this);
+  if (VCONF_OK == status) {
+    soundModeChangeListening = true;
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+
+  LoggerE("SoundModeChangeListener no setted");
+  return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                        "SoundModeChangeListener no setted");
+}
+
+PlatformResult SoundManager::UnsetSoundModeChangeListener() {
+  LoggerD("Enter");
+  soundModeListener = nullptr;
+  if (!soundModeChangeListening) {
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+
+  int status = vconf_ignore_key_changed(VCONFKEY_SETAPPL_VIBRATION_STATUS_BOOL,
+                                        SoundManager::soundModeChangedCb);
+  if (VCONF_OK == status) {
+    soundModeChangeListening = false;
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+
+  LoggerE("SoundModeChangeListener no unsetted");
+  return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                        "SoundModeChangeListener no unsetted");
+}
+
+PlatformResult SoundManager::SetVolumeChangeListener() {
+  LoggerD("Enter");
+  if (!is_volume_change_listener_) {
+    int ret = sound_manager_set_volume_changed_cb(
+        [](sound_type_e type, unsigned int value, void* ud) {
+          return static_cast<SoundManager*>(ud)
+              ->VolumeChangeCallback(type, value);
+        },
+        static_cast<void*>(this));
+
+    if (ret != SOUND_MANAGER_ERROR_NONE) {
+      LoggerE("Failed to set volume changed callback: error code: %d", ret);
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "Failed to set volume changed callback");
+    }
+
+    is_volume_change_listener_ = true;
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SoundManager::UnsetVolumeChangeListener() {
+  LoggerD("Enter");
+  if (!is_volume_change_listener_) {
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+
+  int ret = sound_manager_unset_volume_changed_cb();
+  if (ret != SOUND_MANAGER_ERROR_NONE) {
+    LoggerE("Failed to unset volume changed callback");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Failed to unset volume changed callback");
+  }
+
+  is_volume_change_listener_ = false;
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+void SoundManager::GetDeviceList(sound_device_mask_e mask, picojson::object& out) {
+  LoggerD("Entered");
+
+  sound_device_list_h device_list = nullptr;
+  sound_device_h device = nullptr;
+
+  picojson::value response = picojson::value(picojson::array());
+  picojson::array& response_array = response.get<picojson::array>();
+
+  int ret = sound_manager_get_current_device_list(mask, &device_list);
+  if (SOUND_MANAGER_ERROR_NONE != ret && SOUND_MANAGER_ERROR_NO_DATA != ret) {
+    ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Getting device list failed"), &out);
+    return;
+  }
+
+  while (!(ret = sound_manager_get_next_device(device_list, &device))) {
+    picojson::value val = picojson::value(picojson::object());
+    picojson::object& obj = val.get<picojson::object>();
+    PlatformResult result = GetDeviceInfo(device, true, false, &obj);
+
+    if (result.IsError()) {
+      ReportError(result, &out);
+      return;
+    }
+    response_array.push_back(val);
+  }
+
+  ReportSuccess(response, out);
+}
+
+PlatformResult SoundManager::GetDeviceInfo(sound_device_h device,
+                                           bool is_connected,
+                                           bool check_connection,
+                                           picojson::object* obj) {
+  LoggerD("Entered");
+
+  //get id
+  int id = 0;
+  int ret = sound_manager_get_device_id(device, &id);
+  if (SOUND_MANAGER_ERROR_NONE != ret) {
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Getting device id failed");
+  }
+  obj->insert(std::make_pair("id", picojson::value(static_cast<double>(id))));
+
+  //get name
+  char *name = nullptr;
+  ret = sound_manager_get_device_name(device, &name);
+  if (SOUND_MANAGER_ERROR_NONE != ret) {
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Getting device name failed");
+  }
+  obj->insert(std::make_pair("name", picojson::value(name)));
+
+  //get type
+  sound_device_type_e type = SOUND_DEVICE_BUILTIN_SPEAKER;
+  ret = sound_manager_get_device_type(device, &type);
+  if (SOUND_MANAGER_ERROR_NONE != ret) {
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Getting device type failed");
+  }
+  obj->insert(std::make_pair("device", picojson::value(SoundDeviceTypeToString(type))));
+
+  //get direction
+  sound_device_io_direction_e direction = SOUND_DEVICE_IO_DIRECTION_IN;
+  ret = sound_manager_get_device_io_direction (device, &direction);
+  if (SOUND_MANAGER_ERROR_NONE != ret) {
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Getting device direction failed");
+  }
+  obj->insert(std::make_pair("direction", picojson::value(SoundIOTypeToString(direction))));
+
+  //get state
+  sound_device_state_e state = SOUND_DEVICE_STATE_DEACTIVATED;
+  ret = sound_manager_get_device_state(device, &state);
+  if (SOUND_MANAGER_ERROR_NONE != ret) {
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Getting device state failed");
+  }
+  obj->insert(std::make_pair("isActivated", picojson::value(static_cast<bool>(state))));
+
+  //get connection
+  if (check_connection) {
+    return IsDeviceConnected(type, direction, obj);
+  }
+
+  obj->insert(std::make_pair("isConnected", picojson::value(is_connected)));
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SoundManager::IsDeviceConnected(sound_device_type_e type,
+                                               sound_device_io_direction_e direction,
+                                               picojson::object* obj) {
+  LoggerD("Entered");
+
+  sound_device_mask_e mask = SOUND_DEVICE_ALL_MASK;
+  switch (direction) {
+    case SOUND_DEVICE_IO_DIRECTION_IN:
+      mask = SOUND_DEVICE_IO_DIRECTION_IN_MASK;
+      break;
+    case SOUND_DEVICE_IO_DIRECTION_OUT:
+      mask = SOUND_DEVICE_IO_DIRECTION_OUT_MASK;
+      break;
+    case SOUND_DEVICE_IO_DIRECTION_BOTH:
+      mask = SOUND_DEVICE_IO_DIRECTION_BOTH_MASK;
+      break;
+    default:
+      LoggerD("Invalid IOType (%d)", direction);
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, "Invalid IO type");
+  }
+
+  sound_device_list_h device_list = nullptr;
+  sound_device_h device = nullptr;
+  sound_device_type_e device_type = SOUND_DEVICE_BUILTIN_SPEAKER;
+
+  int ret = sound_manager_get_current_device_list(mask, &device_list);
+  if (SOUND_MANAGER_ERROR_NONE != ret) {
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Getting device list failed");
+  }
+
+  while (!(ret = sound_manager_get_next_device(device_list, &device))) {
+    ret = sound_manager_get_device_type(device, &device_type);
+    if (SOUND_MANAGER_ERROR_NONE != ret) {
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, "Getting device type failed");
+    }
+
+    if (type == device_type) {
+      obj->insert(std::make_pair("isConnected", picojson::value(true)));
+      return PlatformResult(ErrorCode::NO_ERROR);
+    }
+  }
+
+  obj->insert(std::make_pair("isConnected", picojson::value(false)));
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+void SoundManager::DeviceChangeCB(sound_device_h device, bool is_connected, bool check_connection) {
+  LoggerD("Entered");
+
+  picojson::value response = picojson::value(picojson::object());
+  picojson::object& response_obj = response.get<picojson::object>();
+
+  PlatformResult result = GetDeviceInfo(device, is_connected, check_connection, &response_obj);
+
+  if (result.IsSuccess()) {
+    response_obj.insert(std::make_pair(
+        "listenerId", picojson::value("SoundDeviceStateChangeCallback")));
+
+    auto call_response = [this, response]()->void {
+      Instance::PostMessage(&instance_, response.serialize().c_str());
+    };
+
+    TaskQueue::GetInstance().Async(call_response);
+  }
+}
+
+void DeviceConnectionChangeCB(sound_device_h device, bool is_connected, void *user_data) {
+  LoggerD("Entered");
+  SoundManager* h = static_cast<SoundManager*>(user_data);
+  h->DeviceChangeCB(device, is_connected, false);
+}
+
+void DeviceActivationChangeCB(sound_device_h device, sound_device_changed_info_e changed_info,
+                              void *user_data) {
+  LoggerD("Entered");
+
+  if (SOUND_DEVICE_CHANGED_INFO_STATE == changed_info) {
+    SoundManager* h = static_cast<SoundManager*>(user_data);
+    h->DeviceChangeCB(device, false, true);
+  }
+}
+
+PlatformResult SoundManager::AddDeviceStateChangeListener() {
+  LoggerD("Entered");
+
+  int ret = SOUND_MANAGER_ERROR_NONE;
+  sound_device_mask_e mask = SOUND_DEVICE_ALL_MASK;
+
+  if (!sound_device_change_listener_) {
+    ret = sound_manager_set_device_connected_cb(mask, DeviceConnectionChangeCB, this);
+    if (SOUND_MANAGER_ERROR_NONE != ret) {
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, "Setting connection listener failed");
+    }
+
+    ret = sound_manager_set_device_information_changed_cb(mask, DeviceActivationChangeCB, this);
+    if (SOUND_MANAGER_ERROR_NONE != ret) {
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, "Setting information listener failed");
+    }
+
+    sound_device_change_listener_ = true;
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SoundManager::RemoveDeviceStateChangeListener() {
+  LoggerD("Entered");
+
+  if (sound_device_change_listener_) {
+    if (SOUND_MANAGER_ERROR_NONE != sound_manager_unset_device_connected_cb()) {
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, "Unsetting information listener failed");
+    }
+
+    if (SOUND_MANAGER_ERROR_NONE != sound_manager_unset_device_information_changed_cb()) {
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, "Unsetting information listener failed");
+    }
+
+    sound_device_change_listener_ = false;
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+}  // namespace sound
+}  // namespace extension
diff --git a/webWidgetTCT_device/src/sound/sound_manager.h b/webWidgetTCT_device/src/sound/sound_manager.h
new file mode 100755 (executable)
index 0000000..b0319a3
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2015 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 SOUND_SOUND_MANAGER_H_
+#define SOUND_SOUND_MANAGER_H_
+
+#include <sound_manager.h>
+
+#include "common/picojson.h"
+#include "common/platform_result.h"
+#include <vconf.h>
+
+namespace extension {
+namespace sound {
+
+class SoundManagerSoundModeChangedListener {
+ public:
+  virtual ~SoundManagerSoundModeChangedListener() {}
+  virtual void OnSoundModeChange(const std::string& newmode) = 0;
+};
+
+class SoundInstance;
+
+class SoundManager {
+ public:
+  explicit SoundManager(SoundInstance& instance);
+  ~SoundManager();
+
+  common::PlatformResult GetSoundMode(std::string* sound_mode_type);
+  common::PlatformResult SetVolume(const picojson::object& args);
+  common::PlatformResult GetVolume(const picojson::object& args,
+                                   double* volume);
+  common::PlatformResult SetSoundModeChangeListener(
+      SoundManagerSoundModeChangedListener* listener);
+  common::PlatformResult UnsetSoundModeChangeListener();
+  common::PlatformResult SetVolumeChangeListener();
+  common::PlatformResult UnsetVolumeChangeListener();
+  void GetDeviceList(sound_device_mask_e mask, picojson::object& out);
+  void DeviceChangeCB(sound_device_h device, bool is_connected, bool check_connection);
+  common::PlatformResult AddDeviceStateChangeListener();
+  common::PlatformResult RemoveDeviceStateChangeListener();
+
+ private:
+
+  std::map<sound_type_e, int> max_volume_map_;
+  bool is_volume_change_listener_;
+
+  static const std::map<std::string, sound_type_e> platform_enum_map_;
+
+  void FillMaxVolumeMap();
+  common::PlatformResult GetMaxVolume(sound_type_e type, int* max_volume);
+  void VolumeChangeCallback(sound_type_e type, unsigned int value);
+
+  static common::PlatformResult StrToPlatformEnum(const std::string& key,
+                                                  sound_type_e* sound_type);
+  static common::PlatformResult PlatformEnumToStr(const sound_type_e value,
+                                                  std::string* sound_type);
+
+  common::PlatformResult GetDeviceInfo(sound_device_h device,
+                                       bool is_connected,
+                                       bool check_connection,
+                                       picojson::object* obj);
+  common::PlatformResult IsDeviceConnected(sound_device_type_e type,
+                                           sound_device_io_direction_e direction,
+                                           picojson::object* obj);
+  static std::string SoundDeviceTypeToString(sound_device_type_e type);
+  static std::string SoundIOTypeToString(sound_device_io_direction_e type);
+  static double ConvertToSystemVolume(int max_volume, int volume);
+  static void soundModeChangedCb(keynode_t* node, void* user_data);
+  bool soundModeChangeListening;
+  bool sound_device_change_listener_;
+  SoundInstance& instance_;
+  SoundManagerSoundModeChangedListener* soundModeListener;
+};
+
+}  // namespace sound
+}  // namespace extension
+
+#endif  // SOUND_SOUND_MANAGER_H_
diff --git a/webWidgetTCT_device/src/systeminfo/systeminfo-utils.cpp b/webWidgetTCT_device/src/systeminfo/systeminfo-utils.cpp
new file mode 100755 (executable)
index 0000000..3d59195
--- /dev/null
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 2015 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 "systeminfo-utils.h"
+#include "systeminfo/systeminfo_instance.h"
+
+#include <memory>
+
+#include <net_connection.h>
+#include <device.h>
+
+#include "common/logger.h"
+#include "common/platform_exception.h"
+
+namespace extension {
+namespace systeminfo {
+
+namespace {
+const int MEMORY_TO_BYTE = 1024;
+}  // namespace
+
+using common::PlatformResult;
+using common::ErrorCode;
+
+PlatformResult SysteminfoUtils::GetVconfInt(const char *key, int *value) {
+  if (0 == vconf_get_int(key, value)) {
+    LoggerD("value[%s]: %d", key, *value);
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+  const std::string error_msg = "Could not get " + std::string(key);
+  LoggerD("%s",error_msg.c_str());
+  return PlatformResult(ErrorCode::UNKNOWN_ERR, error_msg);
+}
+
+PlatformResult SysteminfoUtils::GetRuntimeInfoString(system_settings_key_e key, std::string* platform_string) {
+  char* platform_c_string;
+  int err = system_settings_get_value_string(key, &platform_c_string);
+  if (SYSTEM_SETTINGS_ERROR_NONE == err) {
+    if (nullptr != platform_c_string) {
+      *platform_string = platform_c_string;
+      free(platform_c_string);
+      return PlatformResult(ErrorCode::NO_ERROR);
+    }
+  }
+  const std::string error_msg = "Error when retrieving system setting information: "
+      + std::to_string(err);
+  LoggerE("%s", error_msg.c_str());
+  return PlatformResult(ErrorCode::UNKNOWN_ERR, error_msg);
+}
+
+PlatformResult SysteminfoUtils::CheckTelephonySupport() {
+  bool supported = false;
+  PlatformResult ret = SystemInfoDeviceCapability::GetValueBool(
+    "tizen.org/feature/network.telephony", &supported);
+  if (ret.IsError()) {
+    return ret;
+  }
+  if (!supported) {
+    LoggerD("Telephony is not supported on this device");
+    return PlatformResult(ErrorCode::NOT_SUPPORTED_ERR,
+        "Telephony is not supported on this device");
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SysteminfoUtils::CheckCameraFlashSupport() {
+  bool supported = false;
+  PlatformResult ret = SystemInfoDeviceCapability::GetValueBool(
+    "tizen.org/feature/camera.back.flash", &supported);
+  if (ret.IsError()) {
+    return ret;
+  }
+  if (!supported) {
+    LoggerD("Back-facing camera with a flash is not supported on this device");
+    return PlatformResult(ErrorCode::NOT_SUPPORTED_ERR,
+        "Back-facing camera with a flash is not supported on this device");
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SysteminfoUtils::CheckIfEthernetNetworkSupported() {
+  LoggerD("Entered");
+  connection_h connection_handle = nullptr;
+  connection_ethernet_state_e connection_state = CONNECTION_ETHERNET_STATE_DEACTIVATED;
+
+  int error = connection_create(&connection_handle);
+  if (CONNECTION_ERROR_NONE != error) {
+    std::string log_msg = "Cannot create connection: " + std::to_string(error);
+    LoggerE("%s", log_msg.c_str());
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, log_msg);
+  }
+  std::unique_ptr<std::remove_pointer<connection_h>::type, int (*)(connection_h)> connection_handle_ptr(
+    connection_handle, &connection_destroy);  // automatically release the memory
+
+  error = connection_get_ethernet_state(connection_handle, &connection_state);
+  if (CONNECTION_ERROR_NOT_SUPPORTED == error) {
+    std::string log_msg = "Cannot get ethernet connection state: Not supported";
+    LoggerE("%s", log_msg.c_str());
+    return PlatformResult(ErrorCode::NOT_SUPPORTED_ERR, log_msg);
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SysteminfoUtils::CheckBatterySupport() {
+  LoggerD("Entered");
+  bool supported = false;
+  PlatformResult ret = SystemInfoDeviceCapability::GetValueBool(
+    "http://tizen.org/feature/battery", &supported);
+  if (ret.IsError()) {
+    return ret;
+  }
+  if (!supported) {
+    LoggerD("Battery is not supported on this device");
+    return PlatformResult(ErrorCode::NOT_SUPPORTED_ERR,
+        "Battery is not supported on this device");
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SysteminfoUtils::CheckDeviceOrientationSupport() {
+  LoggerD("Entered");
+  bool supported = false;
+  PlatformResult ret = SystemInfoDeviceCapability::GetValueBool(
+    "http://tizen.org/feature/sensor.magnetometer", &supported);
+  if (ret.IsError()) {
+    return ret;
+  }
+  if (!supported) {
+    LoggerD("Device orientation is not supported on this device");
+    return PlatformResult(ErrorCode::NOT_SUPPORTED_ERR,
+        "Device orientation is not supported on this device");
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+
+PlatformResult SysteminfoUtils::GetTotalMemory(long long* result) {
+  LoggerD("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: " + std::to_string(ret);
+    LoggerE("%s", log_msg.c_str());
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, log_msg);
+  }
+
+  *result = static_cast<long long>(value*MEMORY_TO_BYTE);
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SysteminfoUtils::GetAvailableMemory(long long* result) {
+  LoggerD("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: " + std::to_string(ret);
+    LoggerE("%s", log_msg.c_str());
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, log_msg);
+  }
+
+  *result = static_cast<long long>(value*MEMORY_TO_BYTE);
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SysteminfoUtils::RegisterVconfCallback(const char *in_key, vconf_callback_fn cb,
+                                                          void* event_ptr) {
+  if (0 != vconf_notify_key_changed(in_key, cb, event_ptr)) {
+    LoggerE("Failed to register vconf callback: %s", in_key);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to register vconf callback");
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SysteminfoUtils::UnregisterVconfCallback(const char *in_key, vconf_callback_fn cb) {
+  if (0 != vconf_ignore_key_changed(in_key, cb)) {
+    LoggerE("Failed to unregister vconf callback: %s", in_key);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to unregister vconf callback");
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SysteminfoUtils::RegisterTapiChangeCallback(TapiHandle *handle,
+                                                           const char *noti_id,
+                                                           tapi_notification_cb callback,
+                                                           void *user_data) {
+  if (TAPI_API_SUCCESS != tel_register_noti_event(handle, noti_id, callback, user_data)) {
+    LoggerE("Failed to register tapi callback with key: %s", noti_id);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to register tapi callback");
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SysteminfoUtils::UnregisterTapiChangeCallback(TapiHandle *handle,
+                                                             const char *noti_id) {
+  if (TAPI_API_SUCCESS != tel_deregister_noti_event(handle, noti_id)) {
+    LoggerE("Failed to unregister tapi callback with key: %s", noti_id);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to unregister tapi callback");
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+} // namespace systeminfo
+} // namespace webapi
diff --git a/webWidgetTCT_device/src/systeminfo/systeminfo-utils.h b/webWidgetTCT_device/src/systeminfo/systeminfo-utils.h
new file mode 100755 (executable)
index 0000000..c8c5e59
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2015 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 WEBAPI_PLUGINS_SYSTEMINFO_SYSTEMINFO_UTILS_H__
+#define WEBAPI_PLUGINS_SYSTEMINFO_SYSTEMINFO_UTILS_H__
+
+#include <string>
+#include <system_settings.h>
+#include <vconf.h>
+#include <vconf-internal-keys.h>
+#include <ITapiSim.h>
+#include <TelNetwork.h>
+#include "common/picojson.h"
+#include "common/platform_result.h"
+#ifdef TIZEN_TV
+#  include "common/filesystem/filesystem_provider.h"
+#endif
+#ifdef TIZEN_TV_PRODUCT
+#  include "common/tvsapi_subscribe_helper.h"
+#endif
+#include "systeminfo/systeminfo_device_capability.h"
+
+namespace extension {
+namespace systeminfo {
+
+struct CpuInfo {
+  long long usr;
+  long long nice;
+  long long system;
+  long long idle;
+  double load;
+};
+
+class SysteminfoUtils {
+ public:
+  static common::PlatformResult GetVconfInt(const char *key, int *value);
+  static common::PlatformResult GetRuntimeInfoString(system_settings_key_e key,
+                                                     std::string* platform_string);
+  static common::PlatformResult CheckTelephonySupport();
+  static common::PlatformResult CheckCameraFlashSupport();
+  static common::PlatformResult CheckIfEthernetNetworkSupported();
+  static common::PlatformResult CheckBatterySupport();
+  static common::PlatformResult CheckDeviceOrientationSupport();
+
+  static common::PlatformResult GetTotalMemory(long long* result);
+  static common::PlatformResult GetAvailableMemory(long long* result);
+  static common::PlatformResult RegisterVconfCallback(const char *in_key, vconf_callback_fn cb,
+                                                            void* event_ptr);
+  static common::PlatformResult UnregisterVconfCallback(const char *in_key, vconf_callback_fn cb);
+  static common::PlatformResult RegisterTapiChangeCallback(TapiHandle *handle, const char *noti_id,
+                                                           tapi_notification_cb callback,
+                                                           void *user_data);
+  static common::PlatformResult UnregisterTapiChangeCallback(TapiHandle *handle,
+                                                             const char *noti_id);
+};
+
+typedef unsigned char byte;
+
+} // namespace systeminfo
+} // namespace webapi
+
+#endif // WEBAPI_PLUGINS_SYSTEMINFO_SYSTEMINFO_UTILS_H__
diff --git a/webWidgetTCT_device/src/systeminfo/systeminfo.gyp b/webWidgetTCT_device/src/systeminfo/systeminfo.gyp
new file mode 100755 (executable)
index 0000000..658ce4d
--- /dev/null
@@ -0,0 +1,61 @@
+{
+  'includes':[
+    '../common/common.gypi',
+  ],
+  'targets': [
+    {
+      'target_name': 'tizen_systeminfo',
+      'type': 'loadable_module',
+      'dependencies': [
+        '../common/common.gyp:tizen_common',
+      ],
+      'sources': [
+        'systeminfo_api.js',
+        'systeminfo_extension.cc',
+        'systeminfo_extension.h',
+        'systeminfo_instance.cc',
+        'systeminfo_instance.h',
+        'systeminfo-utils.cpp',
+        'systeminfo-utils.h',
+        'systeminfo_manager.cc',
+        'systeminfo_manager.h',
+        'systeminfo_device_capability.cc',
+        'systeminfo_device_capability.h',
+        'systeminfo_properties_manager.cc',
+        'systeminfo_properties_manager.h',
+        'systeminfo_sim_details_manager.cc',
+        'systeminfo_sim_details_manager.h',
+      ],
+      'includes': [
+        '../common/pkg-config.gypi',
+      ],
+      'conditions': [
+        ['tizen == 1', {
+          'variables': {
+            'packages': [
+            'ecore',
+            'vconf',
+            'glib-2.0',
+            'capi-system-info',
+            'capi-network-connection',
+            'capi-system-device',
+            'capi-system-system-settings',
+            'tapi',
+            'sensor',
+            ]
+          },
+        }],
+        ['tizen_is_emulator == 1', {
+          'defines': ['TIZEN_IS_EMULATOR'],
+        }],
+        ['tizen_tv_product == 1', {
+          'variables': {
+            'packages': [
+              'tvs-api',
+            ],
+          },
+        }],
+      ],
+    },
+  ],
+}
diff --git a/webWidgetTCT_device/src/systeminfo/systeminfo_api.js b/webWidgetTCT_device/src/systeminfo/systeminfo_api.js
new file mode 100755 (executable)
index 0000000..5cd7c9e
--- /dev/null
@@ -0,0 +1,1417 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+var validator_ = xwalk.utils.validator;
+var privilege_ = xwalk.utils.privilege;
+var types_ = validator_.Types;
+var T_ = xwalk.utils.type;
+var Converter_ = xwalk.utils.converter;
+var native_ = new xwalk.utils.NativeManager(extension);
+
+// index of default property for sim-related callbacks
+var defaultListenerIndex = 0;
+
+//enumeration SystemInfoPropertyId ////////////////////////////////////////////////////
+var SystemInfoPropertyId = {
+        BATTERY : 'BATTERY',
+        CPU : 'CPU',
+        STORAGE : 'STORAGE',
+        DISPLAY : 'DISPLAY',
+        DEVICE_ORIENTATION : 'DEVICE_ORIENTATION',
+        BUILD : 'BUILD',
+        LOCALE : 'LOCALE',
+        NETWORK : 'NETWORK',
+        WIFI_NETWORK : 'WIFI_NETWORK',
+        ETHERNET_NETWORK : 'ETHERNET_NETWORK',
+        CELLULAR_NETWORK : 'CELLULAR_NETWORK',
+        SIM : 'SIM',
+        PERIPHERAL : 'PERIPHERAL',
+        MEMORY : 'MEMORY',
+        VIDEOSOURCE : 'VIDEOSOURCE',
+        CAMERA_FLASH : 'CAMERA_FLASH'
+};
+
+//class SystemInfoDeviceCapability ////////////////////////////////////////////////////
+function SystemInfoDeviceCapability(data) {
+    Object.defineProperties(this, {
+        bluetooth : {
+            value : data.bluetooth,
+            writable : false,
+            enumerable : true
+        },
+        nfc : {
+            value : data.nfc,
+            writable : false,
+            enumerable : true
+        },
+        nfcReservedPush : {
+            value : data.nfcReservedPush,
+            writable : false,
+            enumerable : true
+        },
+        multiTouchCount : {
+            value : Converter_.toOctet(data.multiTouchCount),
+            writable : false,
+            enumerable : true
+        },
+        inputKeyboard : {
+            value : data.inputKeyboard,
+            writable : false,
+            enumerable : true
+        },
+        inputKeyboardLayout : {
+            value : data.inputKeyboardLayout,
+            writable : false,
+            enumerable : true
+        },
+        wifi : {
+            value : data.wifi,
+            writable : false,
+            enumerable : true
+        },
+        wifiDirect : {
+            value : data.wifiDirect,
+            writable : false,
+            enumerable : true
+        },
+        opengles : {
+            value : data.opengles,
+            writable : false,
+            enumerable : true
+        },
+        openglestextureFormat : {
+            value : data.openglestextureFormat,
+            writable : false,
+            enumerable : true
+        },
+        openglesVersion1_1 : {
+            value : data.openglesVersion1_1,
+            writable : false,
+            enumerable : true
+        },
+        openglesVersion2_0 : {
+            value : data.openglesVersion2_0,
+            writable : false,
+            enumerable : true
+        },
+        fmRadio : {
+            value : data.fmRadio,
+            writable : false,
+            enumerable : true
+        },
+        platformVersion : {
+            get : function() {
+                xwalk.utils.checkPrivilegeAccess(privilege_.SYSTEM);
+                return data.platformVersion;
+            },
+            set : function() {},
+            enumerable : true
+        },
+        webApiVersion : {
+            get : function() {
+                xwalk.utils.checkPrivilegeAccess(privilege_.SYSTEM);
+                return data.webApiVersion;
+            },
+            set : function() {},
+            enumerable : true
+        },
+        nativeApiVersion : {
+            get : function() {
+                xwalk.utils.checkPrivilegeAccess(privilege_.SYSTEM);
+                return data.nativeApiVersion;
+            },
+            set : function() {},
+            enumerable : true
+        },
+        platformName : {
+            value : data.platformName,
+            writable : false,
+            enumerable : true
+        },
+        camera : {
+            value : data.camera,
+            writable : false,
+            enumerable : true
+        },
+        cameraFront : {
+            value : data.cameraFront,
+            writable : false,
+            enumerable : true
+        },
+        cameraFrontFlash : {
+            value : data.cameraFrontFlash,
+            writable : false,
+            enumerable : true
+        },
+        cameraBack : {
+            value : data.cameraBack,
+            writable : false,
+            enumerable : true
+        },
+        cameraBackFlash : {
+            value : data.cameraBackFlash,
+            writable : false,
+            enumerable : true
+        },
+        location : {
+            value : data.location,
+            writable : false,
+            enumerable : true
+        },
+        locationGps : {
+            value : data.locationGps,
+            writable : false,
+            enumerable : true
+        },
+        locationWps : {
+            value : data.locationWps,
+            writable : false,
+            enumerable : true
+        },
+        microphone : {
+            value : data.microphone,
+            writable : false,
+            enumerable : true
+        },
+        usbHost : {
+            value : data.usbHost,
+            writable : false,
+            enumerable : true
+        },
+        usbAccessory : {
+            value : data.usbAccessory,
+            writable : false,
+            enumerable : true
+        },
+        screenOutputRca : {
+            value : data.screenOutputRca,
+            writable : false,
+            enumerable : true
+        },
+        screenOutputHdmi : {
+            value : data.screenOutputHdmi,
+            writable : false,
+            enumerable : true
+        },
+        platformCoreCpuArch : {
+            value : data.platformCoreCpuArch,
+            writable : false,
+            enumerable : true
+        },
+        platformCoreFpuArch : {
+            value : data.platformCoreFpuArch,
+            writable : false,
+            enumerable : true
+        },
+        sipVoip : {
+            value : data.sipVoip,
+            writable : false,
+            enumerable : true
+        },
+        duid : {
+            value : data.duid,
+            writable : false,
+            enumerable : true
+        },
+        speechRecognition : {
+            value : data.speechRecognition,
+            writable : false,
+            enumerable : true
+        },
+        speechSynthesis : {
+            value : data.speechSynthesis,
+            writable : false,
+            enumerable : true
+        },
+        accelerometer : {
+            value : data.accelerometer,
+            writable : false,
+            enumerable : true
+        },
+        accelerometerWakeup : {
+            value : data.accelerometerWakeup,
+            writable : false,
+            enumerable : true
+        },
+        barometer : {
+            value : data.barometer,
+            writable : false,
+            enumerable : true
+        },
+        barometerWakeup : {
+            value : data.barometerWakeup,
+            writable : false,
+            enumerable : true
+        },
+        gyroscope : {
+            value : data.gyroscope,
+            writable : false,
+            enumerable : true
+        },
+        gyroscopeWakeup : {
+            value : data.gyroscopeWakeup,
+            writable : false,
+            enumerable : true
+        },
+        magnetometer : {
+            value : data.magnetometer,
+            writable : false,
+            enumerable : true
+        },
+        magnetometerWakeup : {
+            value : data.magnetometerWakeup,
+            writable : false,
+            enumerable : true
+        },
+        photometer : {
+            value : data.photometer,
+            writable : false,
+            enumerable : true
+        },
+        photometerWakeup : {
+            value : data.photometerWakeup,
+            writable : false,
+            enumerable : true
+        },
+        proximity : {
+            value : data.proximity,
+            writable : false,
+            enumerable : true
+        },
+        proximityWakeup : {
+            value : data.proximityWakeup,
+            writable : false,
+            enumerable : true
+        },
+        tiltmeter : {
+            value : data.tiltmeter,
+            writable : false,
+            enumerable : true
+        },
+        tiltmeterWakeup : {
+            value : data.tiltmeterWakeup,
+            writable : false,
+            enumerable : true
+        },
+        dataEncryption : {
+            value : data.dataEncryption,
+            writable : false,
+            enumerable : true
+        },
+        graphicsAcceleration : {
+            value : data.graphicsAcceleration,
+            writable : false,
+            enumerable : true
+        },
+        push : {
+            value : data.push,
+            writable : false,
+            enumerable : true
+        },
+        telephony : {
+            value : data.telephony,
+            writable : false,
+            enumerable : true
+        },
+        telephonyMms : {
+            value : data.telephonyMms,
+            writable : false,
+            enumerable : true
+        },
+        telephonySms : {
+            value : data.telephonySms,
+            writable : false,
+            enumerable : true
+        },
+        screenSizeNormal : {
+            value : data.screenSizeNormal,
+            writable : false,
+            enumerable : true
+        },
+        screenSize480_800 : {
+            value : data.screenSize480_800,
+            writable : false,
+            enumerable : true
+        },
+        screenSize720_1280 : {
+            value : data.screenSize720_1280,
+            writable : false,
+            enumerable : true
+        },
+        autoRotation : {
+            value : data.autoRotation,
+            writable : false,
+            enumerable : true
+        },
+        shellAppWidget : {
+            value : data.shellAppWidget,
+            writable : false,
+            enumerable : true
+        },
+        visionImageRecognition : {
+            value : data.visionImageRecognition,
+            writable : false,
+            enumerable : true
+        },
+        visionQrcodeGeneration : {
+            value : data.visionQrcodeGeneration,
+            writable : false,
+            enumerable : true
+        },
+        visionQrcodeRecognition : {
+            value : data.visionQrcodeRecognition,
+            writable : false,
+            enumerable : true
+        },
+        visionFaceRecognition : {
+            value : data.visionFaceRecognition,
+            writable : false,
+            enumerable : true
+        },
+        secureElement : {
+            value : data.secureElement,
+            writable : false,
+            enumerable : true
+        },
+        nativeOspCompatible : {
+            value : data.nativeOspCompatible,
+            writable : false,
+            enumerable : true
+        },
+        profile : {
+            value : data.profile,
+            writable : false,
+            enumerable : true
+        }
+    });
+}
+
+//class SystemInfoBattery ////////////////////////////////////////////////////
+function SystemInfoBattery(data) {
+    Object.defineProperties(this, {
+        level : {
+            value : data.level,
+            writable : false,
+            enumerable : true
+        },
+        isCharging : {
+            value : data.isCharging,
+            writable : false,
+            enumerable : true
+        }
+    });
+}
+
+//class SystemInfoCpu ////////////////////////////////////////////////////
+function SystemInfoCpu(data) {
+    Object.defineProperties(this, {
+        load : {
+            value: data.load,
+            writable: false,
+            enumerable: true
+        }
+    });
+}
+
+//class SystemInfoStorageUnit ////////////////////////////////////////////////////
+function SystemInfoStorageUnit(data) {
+    Object.defineProperties(this, {
+        type : {
+            value: data.type,
+            writable: false,
+            enumerable: true
+        },
+        capacity : {
+            value: Converter_.toUnsignedLongLong(data.capacity),
+            writable: false,
+            enumerable: true
+        },
+        availableCapacity : {
+            value : Converter_.toUnsignedLongLong(data.availableCapacity),
+            writable : false,
+            enumerable : true
+        },
+        isRemovable : {
+            value : data.isRemovable,
+            writable : false,
+            enumerable : true
+        },
+        isRemoveable : {
+            value : data.isRemovable,
+            writable : false,
+            enumerable : true
+        }
+    });
+}
+
+//class SystemInfoStorage ////////////////////////////////////////////////////
+function SystemInfoStorage(data) {
+    var len = data.storages.length;
+    var storageArray = new Array(len);
+    for (var i = 0; i < len; ++i) {
+        storageArray[i] = new SystemInfoStorageUnit(data.storages[i]);
+    }
+    Object.defineProperties(this, {
+        units : {
+            value: storageArray,
+            writable: false,
+            enumerable: true
+        }
+    });
+}
+
+//class SystemInfoDisplay ////////////////////////////////////////////////////
+function SystemInfoDisplay(data) {
+    Object.defineProperties(this, {
+        resolutionWidth : {
+            value: Converter_.toUnsignedLong(data.resolutionWidth),
+            writable: false,
+            enumerable: true
+        },
+        resolutionHeight : {
+            value: Converter_.toUnsignedLong(data.resolutionHeight),
+            writable: false,
+            enumerable: true
+        },
+        dotsPerInchWidth : {
+            value: Converter_.toUnsignedLong(data.dotsPerInchWidth),
+            writable: false,
+            enumerable: true
+        },
+        dotsPerInchHeight : {
+            value: Converter_.toUnsignedLong(data.dotsPerInchHeight),
+            writable: false,
+            enumerable: true
+        },
+        physicalWidth : {
+            value: Number(data.physicalWidth),
+            writable: false,
+            enumerable: true
+        },
+        physicalHeight : {
+            value: Number(data.physicalHeight),
+            writable: false,
+            enumerable: true
+        },
+        brightness : {
+            value: Number(data.brightness),
+            writable: false,
+            enumerable: true
+        }
+    });
+}
+
+//class SystemInfoDeviceOrientation ////////////////////////////////////////////////////
+function SystemInfoDeviceOrientation(data) {
+    Object.defineProperties(this, {
+        status : {value: data.status, writable: false, enumerable: true},
+        isAutoRotation : {value: data.isAutoRotation, writable: false, enumerable: true}
+    });
+}
+
+//class SystemInfoBuild ////////////////////////////////////////////////////
+function SystemInfoBuild(data) {
+    Object.defineProperties(this, {
+        model : {value: data.model, writable: false, enumerable: true},
+        manufacturer : {value: data.manufacturer, writable: false, enumerable: true},
+        buildVersion : {value: data.buildVersion, writable: false, enumerable: true}
+    });
+}
+
+//class SystemInfoLocale ////////////////////////////////////////////////////
+function SystemInfoLocale(data) {
+    Object.defineProperties(this, {
+        language : {value: data.language, writable: false, enumerable: true},
+        country : {value: data.country, writable: false, enumerable: true}
+    });
+}
+//class SystemInfoNetwork ////////////////////////////////////////////////////
+function SystemInfoNetwork(data) {
+    Object.defineProperties(this, {
+        networkType : {value: data.networkType, writable: false, enumerable: true}
+    });
+}
+
+//class SystemInfoWifiNetwork ////////////////////////////////////////////////////
+function SystemInfoWifiNetwork(data) {
+    Object.defineProperties(this, {
+        status : {value: data.status, writable: false, enumerable: true},
+        ssid : {value: data.ssid, writable: false, enumerable: true},
+        ipAddress : {value: data.ipAddress, writable: false, enumerable: true},
+        ipv6Address : {value: data.ipv6Address, writable: false, enumerable: true},
+        macAddress : {value: data.macAddress, writable: false, enumerable: true},
+        signalStrength : {value: Number(data.signalStrength), writable: false, enumerable: true},
+        securityMode : {value: data.securityMode, writable: false, enumerable: true},
+        encryptionType : {value: data.encryptionType, writable: false, enumerable: true},
+        ipMode : {value: data.ipMode, writable: false, enumerable: true},
+        subnetMask : {value: data.subnetMask, writable: false, enumerable: true},
+        gateway : {value: data.gateway, writable: false, enumerable: true},
+        dns : {value: data.dns, writable: false, enumerable: true}
+    });
+}
+
+//class SystemInfoEthernetNetwork ////////////////////////////////////////////////////
+function SystemInfoEthernetNetwork(data) {
+    Object.defineProperties(this, {
+        cable : {value: data.cable, writable: false, enumerable: true},
+        status : {value: data.status, writable: false, enumerable: true},
+        ipAddress : {value: data.ipAddress, writable: false, enumerable: true},
+        ipv6Address : {value: data.ipv6Address, writable: false, enumerable: true},
+        macAddress : {value: data.macAddress, writable: false, enumerable: true},
+        ipMode : {value: data.ipMode, writable: false, enumerable: true},
+        subnetMask : {value: data.subnetMask, writable: false, enumerable: true},
+        gateway : {value: data.gateway, writable: false, enumerable: true},
+        dns : {value: data.dns, writable: false, enumerable: true}
+    });
+}
+
+//class SystemInfoCellularNetwork ////////////////////////////////////////////////////
+function SystemInfoCellularNetwork(data) {
+    Object.defineProperties(this, {
+        status : {value: data.status, writable: false, enumerable: true},
+        apn : {value: data.apn, writable: false, enumerable: true},
+        ipAddress : {value: data.ipAddress, writable: false, enumerable: true},
+        ipv6Address : {value: data.ipv6Address, writable: false, enumerable: true},
+        mcc : {value: Number(data.mcc), writable: false, enumerable: true},
+        mnc : {value: Number(data.mnc), writable: false, enumerable: true},
+        cellId : {value: Number(data.cellId), writable: false, enumerable: true},
+        lac : {value: Number(data.lac), writable: false, enumerable: true},
+        isRoaming : {value: data.isRoaming, writable: false, enumerable: true},
+        isFlightMode : {value: data.isFligthMode, writable: false, enumerable: true},
+        imei : {
+            get: function() {
+                xwalk.utils.checkPrivilegeAccess4Ver("2.3.1", privilege_.TELEPHONY, privilege_.SYSTEMMANAGER);
+                return data.imei;
+            },
+            set: function() {},
+            enumerable: true
+        }
+    });
+}
+
+//class SystemInfoSIM ////////////////////////////////////////////////////
+function SystemInfoSIM(data) {
+    Object.defineProperties(this, {
+        state : {
+            get: function() {
+                xwalk.utils.checkPrivilegeAccess(privilege_.SYSTEM);
+                return data.state;
+            },
+            set: function() {},
+            enumerable: true
+        },
+        operatorName : {
+            get: function() {
+                xwalk.utils.checkPrivilegeAccess(privilege_.SYSTEM);
+                return data.operatorName;
+            },
+            set: function() {},
+            enumerable: true
+        },
+        msisdn : {
+            get: function() {
+                xwalk.utils.checkPrivilegeAccess4Ver("2.3.1", privilege_.TELEPHONY, privilege_.SYSTEMMANAGER);
+                return data.msisdn;
+            },
+            set: function() {},
+            enumerable: true
+        },
+        iccid : {
+            get: function() {
+                xwalk.utils.checkPrivilegeAccess(privilege_.SYSTEM);
+                return data.iccid;
+            },
+            set: function() {},
+            enumerable: true
+        },
+        mcc : {
+            get: function() {
+                xwalk.utils.checkPrivilegeAccess(privilege_.SYSTEM);
+                return Number(data.mcc);
+            },
+            set: function() {},
+            enumerable: true
+        },
+        mnc : {
+            get: function() {
+                xwalk.utils.checkPrivilegeAccess(privilege_.SYSTEM);
+                return Number(data.mnc);
+            },
+            set: function() {},
+            enumerable: true
+        },
+        msin : {
+            get: function() {
+                xwalk.utils.checkPrivilegeAccess4Ver("2.3.1", privilege_.TELEPHONY, privilege_.SYSTEMMANAGER);
+                return data.msin;
+            },
+            set: function() {},
+            enumerable: true
+        },
+        spn : {
+            get: function() {
+                xwalk.utils.checkPrivilegeAccess(privilege_.SYSTEM);
+                return data.spn;
+            },
+            set: function() {},
+            enumerable: true
+        },
+    });
+}
+
+//class SystemInfoPeripheral ////////////////////////////////////////////////////
+function SystemInfoPeripheral(data) {
+    Object.defineProperties(this, {
+        isVideoOutputOn : {value: data.isVideoOutputOn, writable: false, enumerable: true}
+    });
+}
+
+//class SystemInfoMemory ////////////////////////////////////////////////////
+function SystemInfoMemory(data) {
+    Object.defineProperties(this, {
+        status : {value: data.state, writable: false, enumerable: true}
+    });
+}
+
+//class SystemInfoVideoSourceInfo ////////////////////////////////////////////////////
+function SystemInfoVideoSourceInfo(data) {
+    Object.defineProperties(this, {
+        type : {value: data.type, writable: false, enumerable: true},
+        number : {value: data.number, writable: false, enumerable: true}
+    });
+}
+
+//class SystemInfoVideoSource ////////////////////////////////////////////////////
+function SystemInfoVideoSource(data) {
+    Object.defineProperties(this, {
+        connected : {value: [], writable: false, enumerable: true},
+        disconnected : {value: [], writable: false, enumerable: true}
+    });
+    for(var i=0;i<data.connected.length;++i)
+    {
+        this.connected.push(new SystemInfoVideoSourceInfo(data.connected[i]));
+    }
+    for(var i=0;i<data.disconnected.length;++i)
+    {
+        this.disconnected.push(new SystemInfoVideoSourceInfo(data.disconnected[i]));
+    }
+}
+
+function SystemInfoCameraFlash(data) {
+  var getBrightness = function() {
+      xwalk.utils.checkPrivilegeAccess(privilege_.LED);
+
+      var result = native_.callSync('SystemInfo_getBrightness', {});
+      if (native_.isSuccess(result)) {
+        return Converter_.toLong(native_.getResultObject(result)) / this.levels;
+      }
+      return null;
+    };
+
+  var getLevels = function() {
+      xwalk.utils.checkPrivilegeAccess(privilege_.LED);
+
+      var result = native_.callSync('SystemInfo_getMaxBrightness', {});
+      if (native_.isSuccess(result)) {
+        return Converter_.toLong(native_.getResultObject(result));
+      }
+      return null;
+    };
+
+  Object.defineProperties(this, {
+        brightness : {set : function(){}, get: getBrightness, enumerable: true},
+        camera : {value: data.camera, enumerable: true},
+        levels : {get: getLevels, enumerable: true},
+    });
+}
+
+SystemInfoCameraFlash.prototype.setBrightness = function(brightness) {
+  xwalk.utils.checkPrivilegeAccess(privilege_.LED);
+
+  var args = validator_.validateArgs(arguments, [
+    {name: 'brightness', type: types_.DOUBLE}
+  ]);
+  if (args.brightness < 0 || args.brightness > 1)
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+                              'Value is not between 0 and 1');
+  args.brightness = args.brightness * this.levels;
+
+  var result = native_.callSync('SystemInfo_setBrightness', args);
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+  this.brightness = result;
+};
+
+//class SystemInfo ////////////////////////////////////////////////////
+var SystemInfo = function() {
+};
+
+SystemInfo.prototype.getCapabilities = function() {
+    var result = native_.callSync('SystemInfo_getCapabilities', {});
+    if (native_.isFailure(result)) {
+        throw native_.getErrorObject(result);
+    }
+    var devCap = new SystemInfoDeviceCapability(native_.getResultObject(result));
+    return devCap;
+};
+
+SystemInfo.prototype.getCapability = function() {
+    var args = validator_.validateArgs(arguments, [
+             {
+                 name : 'key',
+                 type : types_.STRING
+             }
+             ]);
+
+    var result = native_.callSync('SystemInfo_getCapability', {key: args.key});
+    if (native_.isFailure(result)) {
+        throw native_.getErrorObject(result);
+    }
+    var res = native_.getResultObject(result);
+    if (res.type === 'int') {
+        return Number(res.value);
+    } else {
+        return res.value;
+    }
+};
+
+
+var _createProperty = function (property, data) {
+    if (_propertyContainer[property]){
+        return new _propertyContainer[property].constructor(data);
+    } else {
+        throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR, 'Property with id: ' + property + ' is not supported.');
+    }
+};
+
+var _createPropertyArray = function (property, data) {
+    var jsonArray = data.array;
+    var propertyArray = [];
+    if (_propertyContainer[property]){
+        var arrayLength = jsonArray.length;
+        for (var i = 0; i < arrayLength; i++) {
+            propertyArray.push(new _propertyContainer[property].constructor(jsonArray[i]));
+        }
+    } else {
+        throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR, 'Property with id: ' + property + ' is not supported.');
+    }
+    return propertyArray;
+};
+
+
+var getPropertyFunction = function(cppLabel, objectCreateFunction) {
+    return function() {
+        if (arguments[0] === "CELLULAR_NETWORK") {
+            xwalk.utils.checkPrivilegeAccess4Ver("2.4", privilege_.TELEPHONY);
+        }
+
+        var args = validator_.validateArgs(arguments, [
+                 {
+                     name : 'property',
+                     type : types_.ENUM,
+                     values : T_.getValues(SystemInfoPropertyId)
+                 },
+                 {
+                     name : 'successCallback',
+                     type : types_.FUNCTION
+                 },
+                 {
+                     name : 'errorCallback',
+                     type : types_.FUNCTION,
+                     optional : true,
+                     nullable : true
+                 }
+                 ]);
+        var propObject = _propertyContainer[args.property];
+        if (!propObject) {
+            throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR, 'Property with id: ' + args.property + ' is not supported.');
+        }
+        var callback = function(result) {
+            if (native_.isFailure(result)) {
+                setTimeout(function() {
+                    native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+                }, 0);
+            } else {
+                var resultProp = objectCreateFunction(args.property, native_.getResultObject(result));
+                args.successCallback(resultProp);
+            }
+        };
+        native_.call(cppLabel, {property: args.property}, callback);
+    };
+}
+
+SystemInfo.prototype.getPropertyValue =
+    getPropertyFunction('SystemInfo_getPropertyValue', _createProperty);
+
+SystemInfo.prototype.getPropertyValueArray =
+    getPropertyFunction('SystemInfo_getPropertyValueArray', _createPropertyArray);
+
+
+//SystemInfo helpers ///////////////////////////////////////////////////
+var _batteryStr = SystemInfoPropertyId.BATTERY;
+var _cpuStr = SystemInfoPropertyId.CPU;
+var _storageStr = SystemInfoPropertyId.STORAGE;
+var _displayStr = SystemInfoPropertyId.DISPLAY;
+var _deviceOrientationStr = SystemInfoPropertyId.DEVICE_ORIENTATION;
+//var _buildStr = SystemInfoPropertyId.BUILD;
+var _localeStr = SystemInfoPropertyId.LOCALE;
+var _networkStr = SystemInfoPropertyId.NETWORK;
+var _wifiNetworkStr = SystemInfoPropertyId.WIFI_NETWORK;
+var _ethernetNetworkStr = SystemInfoPropertyId.ETHERNET_NETWORK;
+var _cellularNetworkStr = SystemInfoPropertyId.CELLULAR_NETWORK;
+var _simStr = SystemInfoPropertyId.SIM;
+var _peripheralStr = SystemInfoPropertyId.PERIPHERAL;
+var _memoryStr = SystemInfoPropertyId.MEMORY;
+var _videosourceStr = SystemInfoPropertyId.VIDEOSOURCE;
+var _cameraFlashStr = SystemInfoPropertyId.CAMERA_FLASH;
+
+var _nextId = 0;
+
+
+function _systeminfoBatteryListenerCallback(eventObj) {
+    var property = _batteryStr;
+    var callbacks = _propertyContainer[property].callbacks;
+
+    for (var watchId in callbacks) {
+        if (callbacks.hasOwnProperty(watchId)) {
+            var listener = callbacks[watchId];
+            var executeCall = (T_.isUndefined(listener.lowThreshold) ||
+                    (propObj.level <= listener.lowThreshold)) ||
+                    (T_.isUndefined(listener.highThreshold) ||
+                            (propObj.level >= listener.highThreshold));
+            var propObj = !listener.isArrayType ?
+                    _createProperty(property, eventObj.result.array[0]) :
+                        _createPropertyArray(property, eventObj.result);
+            if (executeCall) {
+                listener.callback(propObj);
+            }
+        }
+    }
+}
+
+function _systeminfoCpuListenerCallback(eventObj) {
+    var property = _cpuStr;
+    var callbacks = _propertyContainer[property].callbacks;
+
+    for (var watchId in callbacks) {
+        if (callbacks.hasOwnProperty(watchId)) {
+            var listener = callbacks[watchId];
+            var propObj = !listener.isArrayType ?
+                    _createProperty(property, eventObj.result.array[0]) :
+                        _createPropertyArray(property, eventObj.result);
+            var executeCall = (T_.isUndefined(listener.lowThreshold) ||
+                    (propObj.load <= listener.lowThreshold)) ||
+                    (T_.isUndefined(listener.highThreshold) ||
+                            (propObj.load >= listener.highThreshold));
+            if (executeCall) {
+                listener.callback(propObj);
+            }
+        }
+    }
+}
+
+function _systeminfoStorageListenerCallback(eventObj) {
+    var property = _storageStr;
+    var callbacks = _propertyContainer[property].callbacks;
+
+    for (var watchId in callbacks) {
+        if (callbacks.hasOwnProperty(watchId)) {
+            var listener = callbacks[watchId];
+            var propObj = !listener.isArrayType ?
+                    _createProperty(property, eventObj.result.array[0]) :
+                        _createPropertyArray(property, eventObj.result);
+            callbacks[watchId].callback(propObj);
+        }
+    }
+}
+
+function _systeminfoDisplayListenerCallback(eventObj) {
+    var property = _displayStr;
+    var callbacks = _propertyContainer[property].callbacks;
+
+    for (var watchId in callbacks) {
+        if (callbacks.hasOwnProperty(watchId)) {
+            var listener = callbacks[watchId];
+            var propObj = !listener.isArrayType ?
+                    _createProperty(property, eventObj.result.array[0]) :
+                        _createPropertyArray(property, eventObj.result);
+            var executeCall = (T_.isUndefined(listener.lowThreshold) ||
+                    (propObj.brightness <= listener.lowThreshold)) ||
+                    (T_.isUndefined(listener.highThreshold) ||
+                            (propObj.brightness >= listener.highThreshold));
+            if (executeCall) {
+                listener.callback(propObj);
+            }
+        }
+    }
+}
+
+function _systeminfoDeviceOrientationListenerCallback(eventObj) {
+    var property = _deviceOrientationStr;
+    var callbacks = _propertyContainer[property].callbacks;
+
+    for (var watchId in callbacks) {
+        if (callbacks.hasOwnProperty(watchId)) {
+            var listener = callbacks[watchId];
+            var propObj = !listener.isArrayType ?
+                    _createProperty(property, eventObj.result.array[0]) :
+                        _createPropertyArray(property, eventObj.result);
+            callbacks[watchId].callback(propObj);
+        }
+    }
+}
+
+function _systeminfoLocaleListenerCallback(eventObj) {
+    var property = _localeStr;
+    var callbacks = _propertyContainer[property].callbacks;
+
+    for (var watchId in callbacks) {
+        if (callbacks.hasOwnProperty(watchId)) {
+            var listener = callbacks[watchId];
+            var propObj = !listener.isArrayType ?
+                    _createProperty(property, eventObj.result.array[0]) :
+                        _createPropertyArray(property, eventObj.result);
+            callbacks[watchId].callback(propObj);
+        }
+    }
+}
+
+function _systeminfoNetworkListenerCallback(eventObj) {
+    var property = _networkStr;
+    var callbacks = _propertyContainer[property].callbacks;
+
+    for (var watchId in callbacks) {
+        if (callbacks.hasOwnProperty(watchId)) {
+            var listener = callbacks[watchId];
+            var propObj = !listener.isArrayType ?
+                    _createProperty(property, eventObj.result.array[0]) :
+                        _createPropertyArray(property, eventObj.result);
+            callbacks[watchId].callback(propObj);
+        }
+    }
+}
+
+function _systeminfoWifiNetworkListenerCallback(eventObj) {
+    var property = _wifiNetworkStr;
+    var callbacks = _propertyContainer[property].callbacks;
+
+    for (var watchId in callbacks) {
+        if (callbacks.hasOwnProperty(watchId)) {
+            var listener = callbacks[watchId];
+            var propObj = !listener.isArrayType ?
+                    _createProperty(property, eventObj.result.array[0]) :
+                        _createPropertyArray(property, eventObj.result);
+            callbacks[watchId].callback(propObj);
+        }
+    }
+}
+
+function _systeminfoEthernetNetworkListenerCallback(eventObj) {
+  var property = _ethernetNetworkStr;
+  var callbacks = _propertyContainer[property].callbacks;
+
+  for (var watchId in callbacks) {
+      if (callbacks.hasOwnProperty(watchId)) {
+          var listener = callbacks[watchId];
+          var propObj = !listener.isArrayType ?
+                  _createProperty(property, eventObj.result.array[0]) :
+                      _createPropertyArray(property, eventObj.result);
+          callbacks[watchId].callback(propObj);
+      }
+  }
+}
+
+function _systeminfoCellularNetworkListenerCallback(eventObj) {
+    var property = _cellularNetworkStr;
+    var callbacks = _propertyContainer[property].callbacks;
+
+    for (var watchId in callbacks) {
+        if (callbacks.hasOwnProperty(watchId)) {
+            var listener = callbacks[watchId];
+            if (!listener.isArrayType && eventObj.changedPropertyIndex != defaultListenerIndex) {
+                // if this is not arrayListener, ignore events of non-default SIM
+                return;
+            }
+
+            var propObj = !listener.isArrayType ?
+                    _createProperty(property, eventObj.result.array[0]) :
+                        _createPropertyArray(property, eventObj.result);
+            callbacks[watchId].callback(propObj);
+        }
+    }
+}
+
+function _systeminfoSimListenerCallback(eventObj) {
+    var property = _simStr;
+    var callbacks = _propertyContainer[property].callbacks;
+
+    for (var watchId in callbacks) {
+        if (callbacks.hasOwnProperty(watchId)) {
+            var listener = callbacks[watchId];
+            var propObj = !listener.isArrayType ?
+                    _createProperty(property, eventObj.result.array[0]) :
+                        _createPropertyArray(property, eventObj.result);
+            callbacks[watchId].callback(propObj);
+        }
+    }
+}
+
+function _systeminfoPeripheralListenerCallback(eventObj) {
+    var property = _peripheralStr;
+    var callbacks = _propertyContainer[property].callbacks;
+
+    for (var watchId in callbacks) {
+        if (callbacks.hasOwnProperty(watchId)) {
+            var listener = callbacks[watchId];
+            var propObj = !listener.isArrayType ?
+                    _createProperty(property, eventObj.result.array[0]) :
+                        _createPropertyArray(property, eventObj.result);
+            callbacks[watchId].callback(propObj);
+        }
+    }
+}
+
+function _systeminfoMemoryListenerCallback(eventObj) {
+    var property = _memoryStr;
+    var callbacks = _propertyContainer[property].callbacks;
+
+    for (var watchId in callbacks) {
+        if (callbacks.hasOwnProperty(watchId)) {
+            var listener = callbacks[watchId];
+            var propObj = !listener.isArrayType ?
+                    _createProperty(property, eventObj.result.array[0]) :
+                        _createPropertyArray(property, eventObj.result);
+            callbacks[watchId].callback(propObj);
+        }
+    }
+}
+
+function _systemInfoVideoSourceListenerCallback(eventObj) {
+    var property = _videosourceStr;
+    var callbacks = _propertyContainer[property].callbacks;
+
+    for (var watchId in callbacks) {
+        if (callbacks.hasOwnProperty(watchId)) {
+            var listener = callbacks[watchId];
+            var propObj = !listener.isArrayType ?
+                    _createProperty(property, eventObj.result.array[0]) :
+                        _createPropertyArray(property, eventObj.result);
+            callbacks[watchId].callback(propObj);
+        }
+    }
+}
+
+function  _systeminfoCameraFlashListenerCallback(eventObj) {
+    var property = _cameraFlashStr;
+    var callbacks = _propertyContainer[property].callbacks;
+
+    for (var watchId in callbacks) {
+        if (callbacks.hasOwnProperty(watchId)) {
+            var listener = callbacks[watchId];
+            var propObj = !listener.isArrayType ?
+                    _createProperty(property, eventObj.result.array[0]) :
+                        _createPropertyArray(property, eventObj.result);
+            callbacks[watchId].callback(propObj);
+        }
+    }
+}
+
+var _propertyContainer = {
+        'BATTERY' : {
+            callbacks : {},
+            constructor : SystemInfoBattery,
+            broadcastFunction : _systeminfoBatteryListenerCallback,
+            signalLabel : 'SystemInfoBatteryChangeBroadcast'
+        },
+        'CPU' : {
+            callbacks : {},
+            constructor : SystemInfoCpu,
+            broadcastFunction : _systeminfoCpuListenerCallback,
+            signalLabel : 'SystemInfoCpuChangeBroadcast'
+        },
+        'STORAGE' : {
+            callbacks : {},
+            constructor : SystemInfoStorage,
+            broadcastFunction : _systeminfoStorageListenerCallback,
+            signalLabel : 'SystemInfoStorageChangeBroadcast'
+        },
+        'DISPLAY' : {
+            callbacks : {},
+            constructor : SystemInfoDisplay,
+            broadcastFunction : _systeminfoDisplayListenerCallback,
+            signalLabel : 'SystemInfoDisplayChangeBroadcast'
+        },
+        'DEVICE_ORIENTATION' : {
+            callbacks : {},
+            constructor : SystemInfoDeviceOrientation,
+            broadcastFunction : _systeminfoDeviceOrientationListenerCallback,
+            signalLabel : 'SystemInfoDeviceOrientationChangeBroadcast'
+        },
+        'BUILD' : {
+            callbacks : {}, //adding callbacks for build is not possible
+            constructor : SystemInfoBuild,
+            broadcastFunction : function(){},
+            signalLabel : ''
+        },
+        'LOCALE' : {
+            callbacks : {},
+            constructor : SystemInfoLocale,
+            broadcastFunction : _systeminfoLocaleListenerCallback,
+            signalLabel : 'SystemInfoLocaleChangeBroadcast'
+        },
+        'NETWORK' : {
+            callbacks : {},
+            constructor : SystemInfoNetwork,
+            broadcastFunction : _systeminfoNetworkListenerCallback,
+            signalLabel : 'SystemInfoNetworkChangeBroadcast'
+        },
+        'WIFI_NETWORK' : {
+            callbacks : {},
+            constructor : SystemInfoWifiNetwork,
+            broadcastFunction : _systeminfoWifiNetworkListenerCallback,
+            signalLabel : 'SystemInfoWifiNetworkChangeBroadcast'
+        },
+        'ETHERNET_NETWORK' : {
+            callbacks : {},
+            constructor : SystemInfoEthernetNetwork,
+            broadcastFunction : _systeminfoEthernetNetworkListenerCallback,
+            signalLabel : 'SystemInfoEthernetNetworkChangeBroadcast'
+        },
+        'CELLULAR_NETWORK' : {
+            callbacks : {},
+            constructor : SystemInfoCellularNetwork,
+            broadcastFunction : _systeminfoCellularNetworkListenerCallback,
+            signalLabel : 'SystemInfoCellularNetworkChangeBroadcast'
+        },
+        'SIM' : {
+            callbacks : {},
+            constructor : SystemInfoSIM,
+            broadcastFunction : _systeminfoSimListenerCallback,
+            signalLabel : 'SystemInfoSimChangeBroadcast'
+        },
+        'PERIPHERAL' : {
+            callbacks : {},
+            constructor : SystemInfoPeripheral,
+            broadcastFunction : _systeminfoPeripheralListenerCallback,
+            signalLabel : 'SystemInfoPeripheralChangeBroadcast'
+        },
+        'MEMORY' : {
+            callbacks : {},
+            constructor : SystemInfoMemory,
+            broadcastFunction : _systeminfoMemoryListenerCallback,
+            signalLabel : 'SystemInfoMemoryChangeBroadcast'
+        },
+        'VIDEOSOURCE' : {
+            callbacks : {},
+            constructor : SystemInfoVideoSource,
+            broadcastFunction : _systemInfoVideoSourceListenerCallback,
+            signalLabel : 'SystemInfoVideoSourceChangeBroadcast'
+        },
+        'CAMERA_FLASH' : {
+            callbacks : {},
+            constructor : SystemInfoCameraFlash,
+            broadcastFunction : _systeminfoCameraFlashListenerCallback,
+            signalLabel : 'SystemInfoCameraFlashChangeBroadcast'
+    }
+};
+
+/// It common function to be called when listener would be triggered
+
+var _listenerFunction = function(msg) {
+    var propertyId = msg.propertyId;
+    if (propertyId) {
+        _propertyContainer[propertyId].broadcastFunction(msg);
+    } else {
+        console.log("No propertyId provided - ignoring");
+    }
+}
+native_.addListener("SysteminfoCommonListenerLabel", _listenerFunction);
+
+var _registerListener = function (property, listener, errorCallback) {
+    var watchId;
+    var result={};
+
+    var propObject = _propertyContainer[property];
+    if (!propObject) {
+        throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR, 'Property with id: ' + property + ' is not supported.');
+    }
+    var callbackBroadcastFunction = propObject.broadcastFunction;
+    var signalLabel = propObject.signalLabel;
+    var callbacksMap = propObject.callbacks;
+
+    var fail = false;
+    if (T_.isEmptyObject(callbacksMap)) {
+        //registration in C++ layer
+        result = native_.callSync(
+                'SystemInfo_addPropertyValueChangeListener',
+                {property: Converter_.toString(property)});
+        fail = native_.isFailure(result);
+        if (native_.isFailure(result)) {
+            setTimeout(function() {
+                native_.callIfPossible(errorCallback, native_.getErrorObject(result));
+            }, 0);
+        }
+    }
+    if (!fail){
+        watchId = ++_nextId;
+        callbacksMap[watchId] = listener;
+    }
+
+    return Converter_.toUnsignedLong(watchId);
+};
+
+var _identifyListener = function (watchId) {
+    for (var p in _propertyContainer) {
+        if (_propertyContainer[p].callbacks[watchId]) {
+            return p;
+        }
+    }
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR, 'Listener with id: ' + watchId + ' does not exist.');
+};
+
+var _unregisterListener = function (watchId, isTimeout) {
+    var property = {};
+    try {
+        property = _identifyListener(watchId);
+    } catch (e) {
+        // if it is "auto" timeout call it should not throw an exception
+        if (isTimeout) {
+            console.log('Listener was already deleted');
+            return;
+        }
+        throw e;
+    }
+
+    var propObject = _propertyContainer[property];
+    var result={};
+
+    var callbackBroadcastFunction = propObject.broadcastFunction;
+    var signalLabel = propObject.signalLabel;
+    var callbacksMap = propObject.callbacks;
+
+    delete callbacksMap[Number(watchId)];
+    if (T_.isEmptyObject(callbacksMap)) {
+        //unregistration in C++ layer
+        result = native_.callSync(
+                'SystemInfo_removePropertyValueChangeListener',
+                {property: Converter_.toString(property)});
+        if (native_.isFailure(result)) {
+            throw native_.getErrorObject(result);
+        }
+    }
+};
+
+var getListenerFunction = function (isArray) {
+    return function() {
+        if (arguments[0] === "CELLULAR_NETWORK") {
+            xwalk.utils.checkPrivilegeAccess4Ver("2.4", privilege_.TELEPHONY);
+        }
+        var args = validator_.validateArgs(arguments, [
+                 {
+                     name : 'property',
+                     type : types_.ENUM,
+                     values : T_.getValues(SystemInfoPropertyId)
+                 },
+                 {
+                     name : 'successCallback',
+                     type : types_.FUNCTION
+                 },
+                 {
+                     name : 'options',
+                     type : types_.DICTIONARY,
+                     optional : true,
+                     nullable : true
+                 },
+                 {
+                     name : 'errorCallback',
+                     type : types_.FUNCTION,
+                     optional : true,
+                     nullable : true
+                 }
+                 ]);
+
+        var listener = {
+                callback      : args.successCallback,
+                isArrayType     : isArray,
+                highThreshold : !T_.isNullOrUndefined(args.options) ?
+                        args.options.highThreshold : undefined,
+                lowThreshold  : !T_.isNullOrUndefined(args.options) ?
+                        args.options.lowThreshold : undefined
+        };
+        var watchId = _registerListener(args.property, listener, args.errorCallback);
+
+        var timeout = !T_.isNullOrUndefined(args.options) ? args.options.timeout : undefined;
+        if (!T_.isUndefined(timeout) ){
+            setTimeout(function(){_unregisterListener(watchId, true);}, timeout);
+        }
+
+        return watchId;
+    };
+};
+
+SystemInfo.prototype.addPropertyValueChangeListener = getListenerFunction(false);
+
+SystemInfo.prototype.addPropertyValueArrayChangeListener = getListenerFunction(true);
+
+SystemInfo.prototype.removePropertyValueChangeListener = function() {
+    var args = validator_.validateArgs(arguments, [
+             {
+                 name : 'watchId',
+                 type : types_.UNSIGNED_LONG
+             }
+             ]);
+
+    _unregisterListener(args.watchId, false);
+};
+
+SystemInfo.prototype.getTotalMemory = function() {
+    var result = native_.callSync('SystemInfo_getTotalMemory', {});
+    if (native_.isFailure(result)) {
+        throw native_.getErrorObject(result);
+    }
+    return native_.getResultObject(result).totalMemory;
+};
+
+SystemInfo.prototype.getAvailableMemory = function() {
+    var result = native_.callSync('SystemInfo_getAvailableMemory', {});
+    if (native_.isFailure(result)) {
+        throw native_.getErrorObject(result);
+    }
+    return native_.getResultObject(result).availableMemory;
+};
+
+SystemInfo.prototype.getCount = function() {
+    var args = validator_.validateArgs(arguments, [
+             {
+                 name : 'property',
+                 type : types_.ENUM,
+                 values : T_.getValues(SystemInfoPropertyId)
+             }
+             ]);
+
+    var result = native_.callSync('SystemInfo_getCount', {property: args.property});
+    if (native_.isFailure(result)) {
+        throw native_.getErrorObject(result);
+    }
+    var res = native_.getResultObject(result);
+    return Number(res.count);
+};
+
+SystemInfo.prototype._SystemInfoVideoSourceInfo = SystemInfoVideoSourceInfo;//expose to tv window
+
+//Exports
+exports = new SystemInfo();
diff --git a/webWidgetTCT_device/src/systeminfo/systeminfo_device_capability.cc b/webWidgetTCT_device/src/systeminfo/systeminfo_device_capability.cc
new file mode 100755 (executable)
index 0000000..bf5cd7f
--- /dev/null
@@ -0,0 +1,616 @@
+/*
+ * Copyright (c) 2015 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 "systeminfo_device_capability.h"
+
+#include <fstream>
+#include <system_info.h>
+
+#include "common/logger.h"
+
+// TODO:: hardcoded value, only for IsBluetoothAlwaysOn
+#define PROFILE_MOBILE 1
+
+namespace extension {
+namespace systeminfo {
+
+using common::PlatformResult;
+using common::ErrorCode;
+
+namespace {
+// device profile
+const char* kPlatformFull = "mobile-full";
+const char* kPlatformMobile = "mobile-web";
+const char* kPlatformWearable = "wearable";
+const char* kPlatformTv = "tv";
+
+const char* kProfileFull = "MOBILE_FULL";
+const char* kProfileMobile = "MOBILE_WEB";
+const char* kProfileWearable = "WEARABLE";
+const char* kProfileTv = "TV";
+//opengles
+const char* kOpenglesTextureDelimiter = "/";
+const char* kOpenglesTextureUtc = "utc";
+const char* kOpenglesTexturePtc = "ptc";
+const char* kOpenglesTextureEtc = "etc";
+const char* kOpenglesTexture3dc = "3dc";
+const char* kOpenglesTextureAtc = "atc";
+const char* kOpenglesTexturePvrtc = "pvrtc";
+//core cpu arch
+const char* kPlatformCoreDelimiter = " | ";
+const char* kPlatformCoreArmv6 = "armv6";
+const char* kPlatformCoreArmv7 = "armv7";
+const char* kPlatformCoreX86 = "x86";
+//core fpu arch
+const char* kPlatformCoreSse2 = "sse2";
+const char* kPlatformCoreSse3 = "sse3";
+const char* kPlatformCoreSsse3 = "ssse3";
+const char* kPlatformCoreVfpv2 = "vfpv2";
+const char* kPlatformCoreVfpv3 = "vfpv3";
+
+/*API feature*/
+/*Network feature*/
+const char* kTizenFeatureBluetoothAlwaysOn = "http://tizen.org/capability/network.bluetooth.always_on"; //TODO mobile/wearable: false, tv: true
+const char* kTizenFeatureOpenglesTextureFormat = "http://tizen.org/feature/opengles.texture_format";
+const char* kTizenFeatureCoreApiVersion = "http://tizen.org/feature/platform.core.api.version";
+const char* kTizenFeaturePlatfromCoreCpuArch = "http://tizen.org/feature/platform.core.cpu.arch";
+const char* kTizenFeaturePlatfromCoreFpuArch = "http://tizen.org/feature/platform.core.fpu.arch";
+/*profile feature*/
+const char* kTizenFeatureProfile = "http://tizen.org/feature/profile";
+/*Screen feature*/
+const char* kTizenFeatureScreen = "http://tizen.org/feature/screen";
+/*Sensor feature*/
+const char* kTizenFeatureCpuFrequency = "http://tizen.org/feature/platform.core.cpu.frequency";
+/*platform*/
+const char* kTizenFeaturePlatformNativeApiVersion = "tizen.org/feature/platform.native.api.version";
+const char* kTizenFeaturePlatformNativeOspCompatible = "tizen.org/feature/platform.native.osp_compatible";
+const char* kTizenFeaturePlatformVersionName = "http://tizen.org/feature/platform.version.name";
+} //namespace
+
+PlatformResult SystemInfoDeviceCapability::GetValueBool(const char *key, bool* value) {
+  bool platform_result = false;
+  int ret = system_info_get_platform_bool(key, &platform_result);
+  if (SYSTEM_INFO_ERROR_NONE != ret) {
+    ret = system_info_get_custom_bool(key, &platform_result);
+    if (SYSTEM_INFO_ERROR_NONE != ret) {
+      std::string log_msg = "Platform error while getting bool value: ";
+      log_msg += std::string(key) + " " + std::to_string(ret);
+      LoggerE("%s", log_msg.c_str());
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, log_msg);
+    }
+  }
+
+  *value = platform_result;
+  LoggerD("value[%s]: %s", key, *value ? "true" : "false");
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SystemInfoDeviceCapability::GetValueInt(const char *key, int* value) {
+  int platform_result = 0;
+  int ret = system_info_get_platform_int(key, &platform_result);
+  if (SYSTEM_INFO_ERROR_NONE != ret) {
+    ret = system_info_get_custom_int(key, &platform_result);
+    if (SYSTEM_INFO_ERROR_NONE != ret) {
+      std::string log_msg = "Platform error while getting int value: ";
+      log_msg += std::string(key) + " " + std::to_string(ret);
+      LoggerE("%s", log_msg.c_str());
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, log_msg);
+    }
+  }
+
+  *value = platform_result;
+  LoggerD("value[%s]: %d", key, *value);
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SystemInfoDeviceCapability::GetValueString(const char *key, std::string* str_value) {
+  char* value = nullptr;
+
+  int ret = system_info_get_platform_string(key, &value);
+  if (SYSTEM_INFO_ERROR_NONE != ret) {
+    ret = system_info_get_custom_string(key, &value);
+    if (SYSTEM_INFO_ERROR_NONE != ret) {
+      std::string log_msg = "Platform error while getting string value: ";
+      log_msg += std::string(key) + " " + std::to_string(ret);
+      LoggerE("%s", log_msg.c_str());
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, log_msg);
+    }
+  }
+
+  if (value != nullptr) {
+    *str_value = value;
+    free(value);
+    value = nullptr;
+  }
+
+  LoggerD("value[%s]: %s", key, str_value->c_str());
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+static PlatformResult CheckStringCapability(const std::string& key, std::string* value, bool* fetched) {
+  LoggerD("Entered CheckStringCapability");
+  *fetched = false;
+  if (kTizenFeatureOpenglesTextureFormat == key) {
+    PlatformResult ret = SystemInfoDeviceCapability::GetOpenglesTextureFormat(value);
+    if (ret.IsError()) {
+      return ret;
+    }
+  } else if (kTizenFeatureCoreApiVersion == key) {
+    *value = "2.3";
+  } else if (key == kTizenFeaturePlatfromCoreCpuArch) {
+    PlatformResult ret = SystemInfoDeviceCapability::GetPlatfomCoreCpuArch(value);
+    if (ret.IsError()) {
+      return ret;
+    }
+  } else if (kTizenFeaturePlatfromCoreFpuArch == key) {
+    PlatformResult ret = SystemInfoDeviceCapability::GetPlatfomCoreFpuArch(value);
+    if (ret.IsError()) {
+      return ret;
+    }
+  } else if (kTizenFeatureProfile == key) {
+    PlatformResult ret = SystemInfoDeviceCapability::GetProfile(value);
+    if (ret.IsError()) {
+      return ret;
+    }
+  } else if (kTizenFeaturePlatformNativeApiVersion == key) {
+    PlatformResult ret = SystemInfoDeviceCapability::GetNativeAPIVersion(value);
+    if (ret.IsError()) {
+      return ret;
+    }
+  } else if (kTizenFeaturePlatformVersionName == key) {
+    PlatformResult ret = SystemInfoDeviceCapability::GetPlatformVersionName(value);
+    if (ret.IsError()) {
+      return ret;
+    }
+  } else {
+    size_t prefix_len = strlen("http://");
+    if (key.length() <= prefix_len) {
+      return PlatformResult(ErrorCode::NOT_SUPPORTED_ERR, "Value for given key was not found");
+    }
+    PlatformResult ret = SystemInfoDeviceCapability::GetValueString(key.substr(prefix_len).c_str(), value);
+    if (ret.IsError()){
+      return PlatformResult(ErrorCode::NO_ERROR);
+    }
+  }
+  *fetched = true;
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+static PlatformResult CheckBoolCapability(const std::string& key, bool* bool_value, bool* fetched) {
+  LoggerD("Entered CheckBoolCapability");
+  *fetched = false;
+  if(kTizenFeatureBluetoothAlwaysOn == key) {
+    *bool_value = SystemInfoDeviceCapability::IsBluetoothAlwaysOn();
+    *fetched = true;
+  } else if (kTizenFeatureScreen == key) {
+    *bool_value = SystemInfoDeviceCapability::IsScreen();
+    *fetched = true;
+  } else if (kTizenFeaturePlatformNativeOspCompatible == key) {
+    PlatformResult ret = SystemInfoDeviceCapability::IsNativeOspCompatible(bool_value);
+    if (ret.IsError()) {
+      return ret;
+    }
+    *fetched = true;
+  } else {
+    size_t prefix_len = strlen("http://");
+    if (key.length() <= prefix_len) {
+      return PlatformResult(ErrorCode::NOT_SUPPORTED_ERR, "Value for given key was not found");
+    }
+    PlatformResult ret = SystemInfoDeviceCapability::GetValueBool(
+        key.substr(prefix_len).c_str(), bool_value);
+    if (ret.IsSuccess()) {
+      *fetched = true;
+    }
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+static PlatformResult CheckIntCapability(const std::string& key, std::string* value,
+                                         bool* fetched) {
+  LoggerD("Entered CheckIntCapability");
+  int result = 0;
+  if (key == kTizenFeatureCpuFrequency) {
+    PlatformResult ret = SystemInfoDeviceCapability::GetPlatformCoreCpuFrequency(&result);
+    if (ret.IsError()) {
+      *fetched = false;
+      return ret;
+    }
+  } else {
+    size_t prefix_len = strlen("http://");
+    if (key.length() <= prefix_len) {
+      return PlatformResult(ErrorCode::NOT_SUPPORTED_ERR, "Value for given key was not found");
+    }
+    PlatformResult ret = SystemInfoDeviceCapability::GetValueInt(
+        key.substr(prefix_len).c_str(), &result);
+    if (ret.IsError()) {
+      *fetched = false;
+      return PlatformResult(ErrorCode::NO_ERROR);
+    }
+  }
+  *value = std::to_string(result);
+  *fetched = true;
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SystemInfoDeviceCapability::GetCapability(const std::string& key,
+                                                          picojson::value* result) {
+  LoggerD("Entered");
+  picojson::object& result_obj = result->get<picojson::object>();
+
+  std::string value = "";
+  std::string type = "";
+  bool bool_value = false ;
+  bool is_fetched = false;
+
+  PlatformResult ret = CheckBoolCapability(key, &bool_value, &is_fetched);
+  if (ret.IsError()) {
+    return ret;
+  }
+  if (is_fetched) {
+    type = "bool";
+  } else {
+    ret = CheckIntCapability(key, &value, &is_fetched);
+    if (ret.IsError()) {
+      return ret;
+    }
+    if (is_fetched) {
+      type = "int";
+    } else {
+      ret = CheckStringCapability(key, &value, &is_fetched);
+      if (ret.IsError()) {
+        return ret;
+      }
+      if(is_fetched) {
+        type = "string";
+      }
+    }
+  }
+
+  if (type == "bool") {
+    result_obj.insert(std::make_pair("value", picojson::value(bool_value)));
+  } else if (type == "string" || type == "int") {
+    result_obj.insert(std::make_pair("value", picojson::value(value)));
+  } else {
+    LoggerD("Value for given key was not found");
+    return PlatformResult(ErrorCode::NOT_SUPPORTED_ERR, "Value for given key was not found");
+  }
+  result_obj.insert(std::make_pair("type", picojson::value(type)));
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SystemInfoDeviceCapability::IsInputKeyboardLayout(bool* result) {
+  std::string input_keyboard_layout = "";
+  PlatformResult ret = GetValueString("tizen.org/feature/input.keyboard.layout",
+                                      &input_keyboard_layout);
+  if (ret.IsError()) {
+    return ret;
+  }
+  bool input_keyboard = false;
+  ret = GetValueBool("tizen.org/feature/input.keyboard", &input_keyboard);
+  if (ret.IsError()) {
+    return ret;
+  }
+
+  // according to SystemInfo-DeviceCapabilities-dependency-table
+  // inputKeyboard   inputKeyboardLayout
+  //  O               O                   Possible
+  //  O               X                   Possible
+  //  X               X                   Possible
+  //  X               O                   Impossible
+
+  *result = input_keyboard ? !(input_keyboard_layout.empty()) : false;
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SystemInfoDeviceCapability::GetOpenglesTextureFormat(std::string* result) {
+  bool bool_result = false;
+  PlatformResult ret = GetValueBool("tizen.org/feature/opengles", &bool_result);
+  if (!bool_result) {
+    // this exception is converted to "Undefined" value in JS layer
+    std::string log_msg = "OpenGL-ES is not supported";
+    LoggerE("%s", log_msg.c_str());
+    return PlatformResult(ErrorCode::NOT_SUPPORTED_ERR, log_msg);
+  }
+  std::string texture_format = "";
+
+  ret = GetValueBool("tizen.org/feature/opengles.texture_format.utc", &bool_result);
+  if (ret.IsError()) {
+    return ret;
+  }
+  if (bool_result) {
+    texture_format += kOpenglesTextureUtc;
+  }
+
+  ret = GetValueBool("tizen.org/feature/opengles.texture_format.ptc", &bool_result);
+  if (ret.IsError()) {
+    return ret;
+  }
+  if (bool_result) {
+    if (!texture_format.empty()) {
+      texture_format += kOpenglesTextureDelimiter;
+    }
+    texture_format += kOpenglesTexturePtc;
+  }
+
+  ret = GetValueBool("tizen.org/feature/opengles.texture_format.etc", &bool_result);
+  if (ret.IsError()) {
+    return ret;
+  }
+  if (bool_result) {
+    if (!texture_format.empty()) {
+      texture_format += kOpenglesTextureDelimiter;
+    }
+    texture_format += kOpenglesTextureEtc;
+  }
+
+  ret = GetValueBool("tizen.org/feature/opengles.texture_format.3dc", &bool_result);
+  if (ret.IsError()) {
+    return ret;
+  }
+  if (bool_result) {
+    if (!texture_format.empty()) {
+      texture_format += kOpenglesTextureDelimiter;
+    }
+    texture_format += kOpenglesTexture3dc;
+  }
+
+  ret = GetValueBool("tizen.org/feature/opengles.texture_format.atc", &bool_result);
+  if (ret.IsError()) {
+    return ret;
+  }
+  if (bool_result) {
+    if (!texture_format.empty()) {
+      texture_format += kOpenglesTextureDelimiter;
+    }
+    texture_format += kOpenglesTextureAtc;
+  }
+
+  ret = GetValueBool("tizen.org/feature/opengles.texture_format.pvrtc", &bool_result);
+  if (ret.IsError()) {
+    return ret;
+  }
+  if (bool_result) {
+    if (!texture_format.empty()) {
+      texture_format += kOpenglesTextureDelimiter;
+    }
+    texture_format += kOpenglesTexturePvrtc;
+  }
+
+  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";
+    LoggerE("%s", log_msg.c_str());
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, log_msg);
+  }
+  *result = texture_format;
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SystemInfoDeviceCapability::GetPlatfomCoreCpuArch(std::string* return_value) {
+  std::string result;
+  bool bool_result = false;
+  PlatformResult ret = GetValueBool("tizen.org/feature/platform.core.cpu.arch.armv6", &bool_result);
+  if (ret.IsError()) {
+    return ret;
+  }
+  if (bool_result) {
+    result = kPlatformCoreArmv6;
+  }
+
+  ret = GetValueBool("tizen.org/feature/platform.core.cpu.arch.armv7", &bool_result);
+  if (ret.IsError()) {
+    return ret;
+  }
+  if (bool_result) {
+    if (!result.empty()) {
+      result += kPlatformCoreDelimiter;
+    }
+    result += kPlatformCoreArmv7;
+  }
+
+  ret = GetValueBool("tizen.org/feature/platform.core.cpu.arch.x86", &bool_result);
+  if (ret.IsError()) {
+    return ret;
+  }
+  if (bool_result) {
+    if (!result.empty()) {
+      result += kPlatformCoreDelimiter;
+    }
+    result += kPlatformCoreX86;
+  }
+
+  if (result.empty()) {
+    LoggerE("Platform error while retrieving platformCoreCpuArch: result is empty");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "platformCoreCpuArch result is empty");
+  }
+  *return_value = result;
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SystemInfoDeviceCapability::GetPlatfomCoreFpuArch(std::string* return_value) {
+  std::string result;
+  bool bool_result = false;
+  PlatformResult ret = GetValueBool("tizen.org/feature/platform.core.fpu.arch.sse2", &bool_result);
+  if (ret.IsError()) {
+    return ret;
+  }
+  if (bool_result) {
+    result = kPlatformCoreSse2;
+  }
+
+  ret = GetValueBool("tizen.org/feature/platform.core.fpu.arch.sse3", &bool_result);
+  if (ret.IsError()) {
+    return ret;
+  }
+  if (bool_result) {
+    if (!result.empty()) {
+      result += kPlatformCoreDelimiter;
+    }
+    result += kPlatformCoreSse3;
+  }
+
+  ret = GetValueBool("tizen.org/feature/platform.core.fpu.arch.ssse3", &bool_result);
+  if (ret.IsError()) {
+    return ret;
+  }
+  if (bool_result) {
+    if (!result.empty()) {
+      result += kPlatformCoreDelimiter;
+    }
+    result += kPlatformCoreSsse3;
+  }
+
+  ret = GetValueBool("tizen.org/feature/platform.core.fpu.arch.vfpv2", &bool_result);
+  if (ret.IsError()) {
+    return ret;
+  }
+  if (bool_result) {
+    if (!result.empty()) {
+      result += kPlatformCoreDelimiter;
+    }
+    result += kPlatformCoreVfpv2;
+  }
+
+  ret = GetValueBool("tizen.org/feature/platform.core.fpu.arch.vfpv3", &bool_result);
+  if (ret.IsError()) {
+    return ret;
+  }
+  if (bool_result) {
+    if (!result.empty()) {
+      result += kPlatformCoreDelimiter;
+    }
+    result += kPlatformCoreVfpv3;
+  }
+  if (result.empty()) {
+    LoggerE("Platform error while retrieving platformCoreFpuArch: result is empty");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "platformCoreFpuArch result is empty");
+  }
+  *return_value = result;
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SystemInfoDeviceCapability::GetProfile(std::string* return_value) {
+  std::string profile = "";
+  PlatformResult ret = GetValueString("tizen.org/feature/profile", &profile);
+  if (ret.IsError()) {
+    return ret;
+  }
+
+  *return_value = kProfileFull;
+  if ( kPlatformFull == profile ) {
+    *return_value = kProfileFull;
+  } else if ( kPlatformMobile == profile ) {
+    *return_value = kProfileMobile;
+  } else if ( kPlatformWearable == profile ) {
+    *return_value = kProfileWearable;
+  } else if ( kPlatformTv == profile) {
+    *return_value = kProfileTv;
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+bool SystemInfoDeviceCapability::IsBluetoothAlwaysOn() {
+#ifdef PROFILE_MOBILE_FULL
+  return false;
+#elif PROFILE_MOBILE
+  return false;
+#elif PROFILE_WEARABLE
+  return false;
+#elif PROFILE_TV
+  return true;
+#else
+  return false;
+#endif
+}
+
+bool SystemInfoDeviceCapability::IsScreen() {
+  return true;
+}
+
+PlatformResult SystemInfoDeviceCapability::GetPlatformCoreCpuFrequency(int* return_value) {
+  LoggerD("Entered");
+
+  std::string freq;
+  std::string file_name;
+
+#ifdef TIZEN_IS_EMULATOR
+  file_name = "/proc/cpuinfo";
+#else
+  file_name = "/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq";
+#endif
+
+  std::ifstream cpuinfo_freq(file_name);
+  if (!cpuinfo_freq.is_open()) {
+    LoggerE("Failed to get cpu frequency");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Unable to open file");
+  }
+
+#ifdef TIZEN_IS_EMULATOR
+  //get frequency value from cpuinfo file
+  //example entry for frequency looks like below
+  //cpu MHz   : 3392.046
+  std::size_t found;
+  do {
+    getline(cpuinfo_freq, freq);
+    found = freq.find("cpu MHz");
+  } while (std::string::npos == found && !cpuinfo_freq.eof());
+
+  found = freq.find(":");
+  if (std::string::npos != found) {
+    *return_value = std::stoi(freq.substr(found + 2));
+  }
+#else
+  getline(cpuinfo_freq, freq);
+  *return_value = std::stoi(freq) / 1000; // unit: MHz
+#endif
+
+  cpuinfo_freq.close();
+  LoggerD("cpu frequency : %d", *return_value);
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SystemInfoDeviceCapability::IsNativeOspCompatible(bool* result) {
+  LoggerD("Enter");
+#ifdef PROFILE_WEARABLE
+  *result = false;
+  return PlatformResult(ErrorCode::NO_ERROR);
+#else
+  return GetValueBool(kTizenFeaturePlatformNativeOspCompatible, result);
+#endif
+}
+
+PlatformResult SystemInfoDeviceCapability::GetNativeAPIVersion(std::string* return_value) {
+  LoggerD("Enter");
+#ifdef PROFILE_WEARABLE
+  *return_value = "";
+  return PlatformResult(ErrorCode::NO_ERROR);
+#else
+  return GetValueString(kTizenFeaturePlatformNativeApiVersion, return_value);
+#endif
+}
+
+PlatformResult SystemInfoDeviceCapability::GetPlatformVersionName(std::string* result) {
+  LoggerD("Enter");
+
+  //Because of lack of 'http://tizen.org/feature/platform.version.name'
+  //key on platform we use 'http://tizen.org/system/platform.name'.
+  return GetValueString("tizen.org/system/platform.name", result);
+}
+
+} // namespace systeminfo
+} // namespace webapi
diff --git a/webWidgetTCT_device/src/systeminfo/systeminfo_device_capability.h b/webWidgetTCT_device/src/systeminfo/systeminfo_device_capability.h
new file mode 100755 (executable)
index 0000000..8285e61
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2015 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 WEBAPI_PLUGINS_SYSTEMINFO_SYSTEMINFO_DEVICE_CAPABILITY_H__
+#define WEBAPI_PLUGINS_SYSTEMINFO_SYSTEMINFO_DEVICE_CAPABILITY_H__
+
+#include <string>
+#include "common/picojson.h"
+#include "common/platform_result.h"
+
+namespace extension {
+namespace systeminfo {
+
+class SystemInfoDeviceCapability {
+ public:
+  static common::PlatformResult GetCapability(const std::string& key, picojson::value* result);
+  static common::PlatformResult GetValueBool(const char *key, bool* value);
+  static common::PlatformResult GetValueInt(const char *key, int* value);
+  static common::PlatformResult GetValueString(const char *key, std::string* str_value);
+
+  static common::PlatformResult IsInputKeyboardLayout(bool* result);
+  static common::PlatformResult GetOpenglesTextureFormat(std::string* result);
+  static common::PlatformResult GetPlatfomCoreCpuArch(std::string* return_value);
+  static common::PlatformResult GetPlatfomCoreFpuArch(std::string* return_value);
+  static common::PlatformResult GetProfile(std::string* return_value);
+  static common::PlatformResult GetPlatformCoreCpuFrequency(int* return_value);
+  static common::PlatformResult IsNativeOspCompatible(bool* result);
+  static common::PlatformResult GetNativeAPIVersion(std::string* return_value);
+  static common::PlatformResult GetPlatformVersionName(std::string* result);
+  static bool IsBluetoothAlwaysOn();
+  static bool IsScreen();
+};
+
+} // namespace systeminfo
+} // namespace webapi
+
+#endif // WEBAPI_PLUGINS_SYSTEMINFO_SYSTEMINFO_DEVICE_CAPABILITY_H__
diff --git a/webWidgetTCT_device/src/systeminfo/systeminfo_extension.cc b/webWidgetTCT_device/src/systeminfo/systeminfo_extension.cc
new file mode 100755 (executable)
index 0000000..071b351
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2015 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 "systeminfo/systeminfo_extension.h"
+
+#include "systeminfo/systeminfo_instance.h"
+
+// This will be generated from systeminfo_api.js
+extern const char kSource_systeminfo_api[];
+
+common::Extension* CreateExtension() {
+  return new SysteminfoExtension;
+}
+
+SysteminfoExtension::SysteminfoExtension() {
+  SetExtensionName("tizen.systeminfo");
+  SetJavaScriptAPI(kSource_systeminfo_api);
+}
+
+SysteminfoExtension::~SysteminfoExtension() {}
+
+common::Instance* SysteminfoExtension::CreateInstance() {
+  return new extension::systeminfo::SysteminfoInstance();
+}
diff --git a/webWidgetTCT_device/src/systeminfo/systeminfo_extension.h b/webWidgetTCT_device/src/systeminfo/systeminfo_extension.h
new file mode 100755 (executable)
index 0000000..3e049de
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015 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 SYSTEMINFO_EXTENSION_H_
+#define SYSTEMINFO_EXTENSION_H_
+
+#include "common/extension.h"
+
+class SysteminfoExtension : public common::Extension {
+ public:
+  SysteminfoExtension();
+  virtual ~SysteminfoExtension();
+
+ private:
+  virtual common::Instance* CreateInstance();
+};
+
+#endif // SYSTEMINFO_EXTENSION_H_
+
diff --git a/webWidgetTCT_device/src/systeminfo/systeminfo_instance.cc b/webWidgetTCT_device/src/systeminfo/systeminfo_instance.cc
new file mode 100755 (executable)
index 0000000..9f4cad7
--- /dev/null
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2015 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 "systeminfo/systeminfo_instance.h"
+
+#include <device/led.h>
+#include <functional>
+#include <memory>
+
+#include "common/picojson.h"
+#include "common/logger.h"
+#include "common/platform_exception.h"
+#include "common/task-queue.h"
+
+#include "systeminfo-utils.h"
+#include "systeminfo_device_capability.h"
+
+namespace extension {
+namespace systeminfo {
+
+using common::PlatformResult;
+using common::ErrorCode;
+using common::TypeMismatchException;
+
+namespace {
+const std::string kPropertyIdString = "propertyId";
+const std::string kListenerIdString = "listenerId";
+
+#define CHECK_EXIST(args, name, out) \
+  if (!args.contains(name)) {\
+    ReportError(TypeMismatchException(name" is required argument"), out);\
+      return;\
+    }
+}
+
+SysteminfoInstance::SysteminfoInstance() : manager_(this) {
+  LoggerD("Enter");
+  using std::placeholders::_1;
+  using std::placeholders::_2;
+
+#define REGISTER_SYNC(c,x) \
+        RegisterSyncHandler(c, std::bind(&SysteminfoInstance::x, this, _1, _2));
+  REGISTER_SYNC("SystemInfo_getCapabilities", GetCapabilities);
+  REGISTER_SYNC("SystemInfo_getCapability", GetCapability);
+  REGISTER_SYNC("SystemInfo_addPropertyValueChangeListener", AddPropertyValueChangeListener);
+  REGISTER_SYNC("SystemInfo_removePropertyValueChangeListener", RemovePropertyValueChangeListener);
+  REGISTER_SYNC("SystemInfo_getTotalMemory", GetTotalMemory);
+  REGISTER_SYNC("SystemInfo_getAvailableMemory", GetAvailableMemory);
+  REGISTER_SYNC("SystemInfo_getCount", GetCount);
+  REGISTER_SYNC("SystemInfo_setBrightness", SetBrightness);
+  REGISTER_SYNC("SystemInfo_getBrightness", GetBrightness);
+  REGISTER_SYNC("SystemInfo_getMaxBrightness", GetMaxBrightness);
+
+#undef REGISTER_SYNC
+#define REGISTER_ASYNC(c,x) \
+        RegisterSyncHandler(c, std::bind(&SysteminfoInstance::x, this, _1, _2));
+  REGISTER_ASYNC("SystemInfo_getPropertyValue", GetPropertyValue);
+  REGISTER_ASYNC("SystemInfo_getPropertyValueArray", GetPropertyValueArray);
+#undef REGISTER_ASYNC
+}
+
+SysteminfoInstance::~SysteminfoInstance() {
+  LoggerD("Entered");
+}
+
+void SysteminfoInstance::GetCapabilities(const picojson::value& args, picojson::object& out) {
+  LoggerD("Enter");
+  manager_.GetCapabilities(args, &out);
+}
+
+void SysteminfoInstance::GetCapability(const picojson::value& args, picojson::object& out) {
+  LoggerD("Enter");
+  manager_.GetCapability(args, &out);
+}
+
+void SysteminfoInstance::GetPropertyValue(const picojson::value& args, picojson::object& out) {
+  LoggerD("Enter");
+  manager_.GetPropertyValue(args, &out);
+}
+
+void SysteminfoInstance::GetPropertyValueArray(const picojson::value& args, picojson::object& out) {
+  LoggerD("Enter");
+  manager_.GetPropertyValueArray(args, &out);
+}
+
+void SysteminfoInstance::AddPropertyValueChangeListener(const picojson::value& args, picojson::object& out) {
+  LoggerD("Enter");
+  manager_.AddPropertyValueChangeListener(args, &out);
+}
+
+void SysteminfoInstance::RemovePropertyValueChangeListener(const picojson::value& args, picojson::object& out) {
+  LoggerD("Enter");
+  manager_.RemovePropertyValueChangeListener(args, &out);
+}
+
+void SysteminfoInstance::GetTotalMemory(const picojson::value& args, picojson::object& out) {
+  LoggerD("Enter");
+  manager_.GetTotalMemory(args, &out);
+}
+
+void SysteminfoInstance::GetAvailableMemory(const picojson::value& args, picojson::object& out) {
+  LoggerD("Enter");
+  manager_.GetAvailableMemory(args, &out);
+}
+
+void SysteminfoInstance::GetCount(const picojson::value& args, picojson::object& out) {
+
+  LoggerD("Enter");
+  manager_.GetCount(args, &out);
+}
+
+void SysteminfoInstance::SetBrightness(const picojson::value& args, picojson::object& out) {
+  LoggerD("entered");
+
+  CHECK_EXIST(args, "brightness", out)
+
+  const double brightness = args.get("brightness").get<double>();
+  int result = device_flash_set_brightness(brightness);
+  if (result != DEVICE_ERROR_NONE) {
+    LoggerE("Error occured");
+    if (DEVICE_ERROR_INVALID_PARAMETER == result) {
+      ReportError(PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Error occured"), &out);
+    } else {
+      ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Error occured"), &out);
+    }
+    return;
+  }
+
+  ReportSuccess(out);
+}
+
+void SysteminfoInstance::GetBrightness(const picojson::value& args, picojson::object& out) {
+  LoggerD("entered");
+
+  int brightness = 0;
+  int result = device_flash_get_brightness(&brightness);
+  if (result != DEVICE_ERROR_NONE) {
+    LoggerE("Error occured");
+    ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Error occured"), &out);
+    return;
+  }
+
+  ReportSuccess(picojson::value(std::to_string(brightness)), out);
+}
+
+void SysteminfoInstance::GetMaxBrightness(const picojson::value& args, picojson::object& out) {
+  LoggerD("entered");
+
+  int brightness = 0;
+  int result = device_flash_get_max_brightness(&brightness);
+  if (result != DEVICE_ERROR_NONE) {
+    LoggerE("Error occured");
+    ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Not supported property"), &out);
+    return;
+  }
+  ReportSuccess(picojson::value(std::to_string(brightness)), out);
+}
+
+} // namespace systeminfo
+} // namespace extension
diff --git a/webWidgetTCT_device/src/systeminfo/systeminfo_instance.h b/webWidgetTCT_device/src/systeminfo/systeminfo_instance.h
new file mode 100755 (executable)
index 0000000..1a29194
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2015 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 SYSTEMINFO_INSTANCE_H_
+#define SYSTEMINFO_INSTANCE_H_
+
+#include "common/extension.h"
+#include "systeminfo/systeminfo_manager.h"
+
+namespace extension {
+namespace systeminfo {
+
+class SysteminfoInstance
+    : public common::ParsedInstance
+{
+ public:
+  SysteminfoInstance();
+  virtual ~SysteminfoInstance();
+ private:
+  void GetCapabilities(const picojson::value& args, picojson::object& out);
+  void GetCapability(const picojson::value& args, picojson::object& out);
+  void GetPropertyValue(const picojson::value& args, picojson::object& out);
+  void GetPropertyValueArray(const picojson::value& args, picojson::object& out);
+  void AddPropertyValueChangeListener(const picojson::value& args, picojson::object& out);
+  void RemovePropertyValueChangeListener(const picojson::value& args, picojson::object& out);
+  void GetMaxBrightness(const picojson::value& args, picojson::object& out);
+  void GetBrightness(const picojson::value& args, picojson::object& out);
+  void SetBrightness(const picojson::value& args, picojson::object& out);
+  void GetTotalMemory(const picojson::value& args, picojson::object& out);
+  void GetAvailableMemory(const picojson::value& args, picojson::object& out);
+  void GetCount(const picojson::value& args, picojson::object& out);
+
+  SysteminfoManager manager_;
+};
+
+} // namespace systeminfo
+} // namespace extension
+
+#endif // SYSTEMINFO_INSTANCE_H_
diff --git a/webWidgetTCT_device/src/systeminfo/systeminfo_manager.cc b/webWidgetTCT_device/src/systeminfo/systeminfo_manager.cc
new file mode 100755 (executable)
index 0000000..93bb919
--- /dev/null
@@ -0,0 +1,1436 @@
+/*
+ * Copyright (c) 2015 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 "systeminfo/systeminfo_manager.h"
+
+#include <functional>
+#include <memory>
+
+#ifdef TIZEN_TV
+#  ifdef TIZEN_TV_PRODUCT
+#    include <TVServiceAPI.h>
+#    include <SignalSubscriberDataType.h>
+#    include "common/video_source_types.h"
+#    include "filesystem/filesystem_manager.h"
+#    include "common/filesystem/filesystem_provider_capiusb.h"
+#    include "common/tvsapi_subscribe_helper.h"
+#  else
+#    include "common/filesystem/deviced.h"
+#  endif
+#endif
+
+
+#include <device.h>
+#include <wifi.h>
+#include <device/callback.h>
+#include <device/device-error.h>
+#include <sensor_internal.h>
+#include <wifi.h>
+
+#include "systeminfo/systeminfo_instance.h"
+#include "systeminfo/systeminfo_device_capability.h"
+#include "systeminfo/systeminfo-utils.h"
+#include "common/logger.h"
+#include "common/converter.h"
+#include "common/task-queue.h"
+
+using common::PlatformResult;
+using common::ErrorCode;
+using common::TypeMismatchException;
+using common::tools::ReportError;
+using common::tools::ReportSuccess;
+using common::Instance;
+using common::TaskQueue;
+
+#ifdef TIZEN_TV_PRODUCT
+using common::TvsSubscribeHelper;
+#endif
+
+namespace extension {
+namespace systeminfo {
+
+namespace {
+const int kDefaultPropertyCount = 1;
+const int BASE_GATHERING_INTERVAL = 100;
+const double kPropertyWatcherTime = 1;
+// index of default property for sim-related callbacks
+const int kDefaultListenerIndex = 0;
+
+const std::string kPropertyIdString = "propertyId";
+const std::string kListenerIdString = "listenerId";
+const std::string kChangedPropertyIndexString = "changedPropertyIndex";
+const std::string kListenerConstValue = "SysteminfoCommonListenerLabel";
+
+const std::string kPropertyIdBattery = "BATTERY";
+const std::string kPropertyIdCpu = "CPU";
+const std::string kPropertyIdStorage = "STORAGE";
+const std::string kPropertyIdDisplay = "DISPLAY";
+const std::string kPropertyIdDeviceOrientation = "DEVICE_ORIENTATION";
+const std::string kPropertyIdBuild = "BUILD";
+const std::string kPropertyIdLocale = "LOCALE";
+const std::string kPropertyIdNetwork = "NETWORK";
+const std::string kPropertyIdWifiNetwork = "WIFI_NETWORK";
+const std::string kPropertyIdEthernetNetwork = "ETHERNET_NETWORK";
+const std::string kPropertyIdCellularNetwork = "CELLULAR_NETWORK";
+const std::string kPropertyIdSim = "SIM";
+const std::string kPropertyIdPeripheral = "PERIPHERAL";
+const std::string kPropertyIdMemory= "MEMORY";
+const std::string kPropertyIdCameraFlash= "CAMERA_FLASH";
+const std::string kPropertyIdVideoSource= "VIDEOSOURCE";
+
+#define CHECK_EXIST(args, name, out) \
+  if (!args.contains(name)) {\
+    ReportError(TypeMismatchException(name" is required argument"), *out);\
+      return;\
+    }
+
+#define DEFAULT_REPORT_BOOL_CAPABILITY(str_name, feature_name) \
+  ret = SystemInfoDeviceCapability::GetValueBool(feature_name, &bool_value); \
+  if (ret.IsError()) { \
+    ReportError(ret, out); \
+    return; \
+  } \
+  result_obj.insert(std::make_pair(str_name, picojson::value(bool_value)));
+
+#define REPORT_BOOL_CAPABILITY(str_name, method) \
+  ret = method(&bool_value); \
+  if (ret.IsError()) { \
+    ReportError(ret, out); \
+    return; \
+  } \
+  result_obj.insert(std::make_pair(str_name, picojson::value(bool_value)));
+
+#define DEFAULT_REPORT_INT_CAPABILITY(str_name, feature_name) \
+  ret = SystemInfoDeviceCapability::GetValueInt(feature_name, &int_value); \
+  if (ret.IsError()) { \
+    ReportError(ret, out); \
+    return; \
+  } \
+  result_obj.insert(std::make_pair(str_name, picojson::value(std::to_string(int_value))));
+
+#define DEFAULT_REPORT_STRING_CAPABILITY(str_name, feature_name) \
+  ret = SystemInfoDeviceCapability::GetValueString(feature_name, &str_value); \
+  if (ret.IsError()) { \
+    ReportError(ret, out); \
+    return; \
+  } \
+  result_obj.insert(std::make_pair(str_name, picojson::value(str_value)));
+
+#define REPORT_STRING_CAPABILITY(str_name, method) \
+  ret = method(&str_value); \
+  if (ret.IsError()) { \
+    ReportError(ret, out); \
+    return; \
+  } \
+  result_obj.insert(std::make_pair(str_name, picojson::value(str_value)));
+
+//Callback static functions
+static void OnBatteryChangedCb(keynode_t* node, void* event_ptr) {
+  LoggerD("Enter");
+  SysteminfoManager* manager = static_cast<SysteminfoManager*>(event_ptr);
+  manager->CallListenerCallback(kPropertyIdBattery);
+}
+
+static gboolean OnCpuChangedCb(gpointer event_ptr) {
+  LoggerD("Enter");
+  SysteminfoManager* manager = static_cast<SysteminfoManager*>(event_ptr);
+  manager->CallCpuListenerCallback();
+  return G_SOURCE_CONTINUE;
+}
+
+static gboolean OnStorageChangedCb(gpointer event_ptr) {
+  LoggerD("Enter");
+  SysteminfoManager* manager = static_cast<SysteminfoManager*>(event_ptr);
+  manager->CallStorageListenerCallback();
+  return G_SOURCE_CONTINUE;
+}
+
+static void OnMmcChangedCb(keynode_t* node, void* event_ptr) {
+  LoggerD("Enter");
+  SysteminfoManager* manager = static_cast<SysteminfoManager*>(event_ptr);
+  manager->CallListenerCallback(kPropertyIdStorage);
+}
+
+static void OnDisplayChangedCb(keynode_t* node, void* event_ptr) {
+  LoggerD("Enter");
+  SysteminfoManager* manager = static_cast<SysteminfoManager*>(event_ptr);
+  manager->CallListenerCallback(kPropertyIdDisplay);
+}
+
+static void OnDeviceAutoRotationChangedCb(keynode_t* node, void* event_ptr) {
+  LoggerD("Enter");
+  SysteminfoManager* manager = static_cast<SysteminfoManager*>(event_ptr);
+  manager->CallListenerCallback(kPropertyIdDeviceOrientation);
+}
+
+static void OnDeviceOrientationChangedCb(sensor_t sensor, unsigned int event_type,
+                                  sensor_data_t *data, void *user_data) {
+  LoggerD("Enter");
+  SysteminfoManager* manager = static_cast<SysteminfoManager*>(user_data);
+  manager->CallListenerCallback(kPropertyIdDeviceOrientation);
+}
+
+static void OnLocaleChangedCb(system_settings_key_e key, void* event_ptr) {
+  LoggerD("Enter");
+  SysteminfoManager* manager = static_cast<SysteminfoManager*>(event_ptr);
+  manager->CallListenerCallback(kPropertyIdLocale);
+}
+
+static void OnNetworkChangedCb(connection_type_e type, void* event_ptr) {
+  LoggerD("Enter");
+  SysteminfoManager* manager = static_cast<SysteminfoManager*>(event_ptr);
+  manager->CallListenerCallback(kPropertyIdNetwork);
+}
+
+static void OnNetworkValueChangedCb(const char* ipv4_address,
+                             const char* ipv6_address, void* event_ptr) {
+  LoggerD("Enter");
+  SysteminfoManager* manager = static_cast<SysteminfoManager*>(event_ptr);
+  manager->CallListenerCallback(kPropertyIdWifiNetwork);
+  manager->CallListenerCallback(kPropertyIdEthernetNetwork);
+  manager->CallListenerCallback(kPropertyIdCellularNetwork);
+}
+
+static void OnCellularNetworkValueChangedCb(keynode_t *node, void *event_ptr) {
+  LoggerD("Enter");
+  SysteminfoManager* manager = static_cast<SysteminfoManager*>(event_ptr);
+  manager->CallListenerCallback(kPropertyIdCellularNetwork, kDefaultListenerIndex);
+}
+
+static void OnTapiValueChangedCb(TapiHandle *handle, const char *noti_id,
+                                 void *data, void *user_data) {
+  LoggerD("Enter");
+  LoggerD("Changed key: %s", noti_id);
+  SysteminfoManager* manager = static_cast<SysteminfoManager*>(user_data);
+  int index = manager->GetChangedTapiIndex(handle);
+  LoggerD("Changed SIM index is: %d", index);
+  manager->CallListenerCallback(kPropertyIdCellularNetwork, index);
+}
+
+static void OnPeripheralChangedCb(keynode_t* node, void* event_ptr) {
+  LoggerD("Enter");
+  SysteminfoManager* manager = static_cast<SysteminfoManager*>(event_ptr);
+  manager->CallListenerCallback(kPropertyIdPeripheral);
+}
+
+static void OnMemoryChangedCb(keynode_t* node, void* event_ptr) {
+  LoggerD("Enter");
+  SysteminfoManager* manager = static_cast<SysteminfoManager*>(event_ptr);
+  manager->CallListenerCallback(kPropertyIdMemory);
+}
+
+static void OnBrightnessChangedCb(device_callback_e type, void* value, void* user_data) {
+  LoggerD("Entered");
+  if (type == DEVICE_CALLBACK_FLASH_BRIGHTNESS) {
+    SysteminfoManager* manager = static_cast<SysteminfoManager*>(user_data);
+    manager->CallListenerCallback(kPropertyIdCameraFlash);
+  }
+}
+
+#ifdef TIZEN_TV_PRODUCT
+void OnVideoSourceChangedCb(void* event_ptr)
+{
+  LoggerD("Entered");
+  SysteminfoManager* manager = static_cast<SysteminfoManager*>(event_ptr);
+  manager->CallListenerCallback(kPropertyIdVideoSource);
+}
+#endif
+
+} //namespace
+
+SysteminfoManager::SysteminfoManager(SysteminfoInstance* instance)
+    : instance_(instance),
+      videoSourceInstance{nullptr},
+      prop_manager_(*this),
+      sensor_handle_(-1),
+      wifi_level_(WIFI_RSSI_LEVEL_0),
+      cpu_load_(0),
+      last_cpu_load_(0),
+      available_capacity_internal_(0),
+      last_available_capacity_internal_(0),
+      available_capacity_mmc_(0),
+      last_available_capacity_mmc_(0),
+      sim_count_(0),
+      tapi_handles_{nullptr},
+      cpu_event_id_(0),
+      storage_event_id_(0),
+      connection_handle_(nullptr) {
+        LoggerD("Entered");
+        InitCameraTypes();
+      }
+
+SysteminfoManager::~SysteminfoManager() {
+  LoggerD("Enter");
+  DisconnectSensor(sensor_handle_);
+
+  if (IsListenerRegistered(kPropertyIdBattery)) { UnregisterBatteryListener(); }
+  if (IsListenerRegistered(kPropertyIdCpu)) { UnregisterCpuListener(); }
+  if (IsListenerRegistered(kPropertyIdStorage)) { UnregisterStorageListener(); }
+  if (IsListenerRegistered(kPropertyIdDisplay)) { UnregisterDisplayListener(); }
+  if (IsListenerRegistered(kPropertyIdDeviceOrientation)) { UnregisterDeviceOrientationListener(); }
+  if (IsListenerRegistered(kPropertyIdLocale)) { UnregisterLocaleListener(); }
+  if (IsListenerRegistered(kPropertyIdNetwork)) { UnregisterNetworkListener(); }
+  if (IsListenerRegistered(kPropertyIdWifiNetwork)) { UnregisterWifiNetworkListener(); }
+  if (IsListenerRegistered(kPropertyIdEthernetNetwork)) { UnregisterEthernetNetworkListener(); }
+  if (IsListenerRegistered(kPropertyIdCellularNetwork)) { UnregisterCellularNetworkListener(); }
+  if (IsListenerRegistered(kPropertyIdPeripheral)) { UnregisterPeripheralListener(); }
+  if (IsListenerRegistered(kPropertyIdMemory)) { UnregisterMemoryListener(); }
+  if (IsListenerRegistered(kPropertyIdCameraFlash)) { UnregisterCameraFlashListener(); }
+#ifdef TIZEN_TV_PRODUCT
+  if (IsListenerRegistered(kPropertyIdVideoSource)) { UnregisterVideoSourceListener(); }
+#endif
+
+  unsigned int i = 0;
+  while(tapi_handles_[i]) {
+    tel_deinit(tapi_handles_[i]);
+    i++;
+  }
+}
+
+void SysteminfoManager::GetCapabilities(const picojson::value& args, picojson::object* out) {
+  LoggerD("Enter");
+  picojson::value result = picojson::value(picojson::object());
+  picojson::object& result_obj = result.get<picojson::object>();
+
+  bool bool_value = false;
+  int int_value = 0;
+  std::string str_value = "";
+  PlatformResult ret(ErrorCode::NO_ERROR);
+  DEFAULT_REPORT_BOOL_CAPABILITY("bluetooth", "tizen.org/feature/network.bluetooth")
+  DEFAULT_REPORT_BOOL_CAPABILITY("nfc", "tizen.org/feature/network.nfc")
+  DEFAULT_REPORT_BOOL_CAPABILITY("nfcReservedPush", "tizen.org/feature/network.nfc.reserved_push")
+  DEFAULT_REPORT_INT_CAPABILITY("multiTouchCount", "tizen.org/feature/multi_point_touch.point_count")
+  DEFAULT_REPORT_BOOL_CAPABILITY("inputKeyboard", "tizen.org/feature/input.keyboard")
+  REPORT_BOOL_CAPABILITY("inputKeyboardLayout", SystemInfoDeviceCapability::IsInputKeyboardLayout)
+  DEFAULT_REPORT_BOOL_CAPABILITY("wifi", "tizen.org/feature/network.wifi")
+  DEFAULT_REPORT_BOOL_CAPABILITY("wifiDirect", "tizen.org/feature/network.wifi.direct")
+  DEFAULT_REPORT_STRING_CAPABILITY("platformName", "tizen.org/system/platform.name")
+  DEFAULT_REPORT_STRING_CAPABILITY("platformVersion", "tizen.org/feature/platform.version")
+  DEFAULT_REPORT_STRING_CAPABILITY("webApiVersion", "tizen.org/feature/platform.web.api.version")
+  DEFAULT_REPORT_BOOL_CAPABILITY("fmRadio", "tizen.org/feature/fmradio")
+  DEFAULT_REPORT_BOOL_CAPABILITY("opengles", "tizen.org/feature/opengles")
+  DEFAULT_REPORT_BOOL_CAPABILITY("openglesVersion1_1", "tizen.org/feature/opengles.version.1_1")
+  DEFAULT_REPORT_BOOL_CAPABILITY("openglesVersion2_0", "tizen.org/feature/opengles.version.2_0")
+  REPORT_STRING_CAPABILITY("openglestextureFormat",
+                           SystemInfoDeviceCapability::GetOpenglesTextureFormat)
+  DEFAULT_REPORT_BOOL_CAPABILITY("speechRecognition", "tizen.org/feature/speech.recognition")
+  DEFAULT_REPORT_BOOL_CAPABILITY("speechSynthesis", "tizen.org/feature/speech.synthesis")
+  DEFAULT_REPORT_BOOL_CAPABILITY("accelerometer", "tizen.org/feature/sensor.accelerometer")
+  DEFAULT_REPORT_BOOL_CAPABILITY("accelerometerWakeup", "tizen.org/feature/sensor.accelerometer.wakeup")
+  DEFAULT_REPORT_BOOL_CAPABILITY("barometer", "tizen.org/feature/sensor.barometer")
+  DEFAULT_REPORT_BOOL_CAPABILITY("barometerWakeup", "tizen.org/feature/sensor.barometer.wakeup")
+  DEFAULT_REPORT_BOOL_CAPABILITY("gyroscope", "tizen.org/feature/sensor.gyroscope")
+  DEFAULT_REPORT_BOOL_CAPABILITY("gyroscopeWakeup", "tizen.org/feature/sensor.gyroscope.wakeup")
+  DEFAULT_REPORT_BOOL_CAPABILITY("camera", "tizen.org/feature/camera")
+  DEFAULT_REPORT_BOOL_CAPABILITY("cameraFront", "tizen.org/feature/camera.front")
+  DEFAULT_REPORT_BOOL_CAPABILITY("cameraFrontFlash", "tizen.org/feature/camera.front.flash")
+  DEFAULT_REPORT_BOOL_CAPABILITY("cameraBack", "tizen.org/feature/camera.back")
+  DEFAULT_REPORT_BOOL_CAPABILITY("cameraBackFlash", "tizen.org/feature/camera.back.flash")
+  DEFAULT_REPORT_BOOL_CAPABILITY("location", "tizen.org/feature/location")
+  DEFAULT_REPORT_BOOL_CAPABILITY("locationGps", "tizen.org/feature/location.gps")
+  DEFAULT_REPORT_BOOL_CAPABILITY("locationWps", "tizen.org/feature/location.wps")
+  DEFAULT_REPORT_BOOL_CAPABILITY("microphone", "tizen.org/feature/microphone")
+  DEFAULT_REPORT_BOOL_CAPABILITY("usbHost", "tizen.org/feature/usb.host")
+  DEFAULT_REPORT_BOOL_CAPABILITY("usbAccessory", "tizen.org/feature/usb.accessory")
+  DEFAULT_REPORT_BOOL_CAPABILITY("screenOutputRca", "tizen.org/feature/screen.output.rca")
+  DEFAULT_REPORT_BOOL_CAPABILITY("screenOutputHdmi", "tizen.org/feature/screen.output.hdmi")
+  DEFAULT_REPORT_BOOL_CAPABILITY("graphicsAcceleration", "tizen.org/feature/graphics.acceleration")
+  DEFAULT_REPORT_BOOL_CAPABILITY("push", "tizen.org/feature/network.push")
+  DEFAULT_REPORT_BOOL_CAPABILITY("telephony", "tizen.org/feature/network.telephony")
+  DEFAULT_REPORT_BOOL_CAPABILITY("telephonyMms", "tizen.org/feature/network.telephony.mms")
+  DEFAULT_REPORT_BOOL_CAPABILITY("telephonySms", "tizen.org/feature/network.telephony.sms")
+  REPORT_STRING_CAPABILITY("platformCoreCpuArch",
+                             SystemInfoDeviceCapability::GetPlatfomCoreCpuArch)
+  REPORT_STRING_CAPABILITY("platformCoreFpuArch",
+                             SystemInfoDeviceCapability::GetPlatfomCoreFpuArch)
+  DEFAULT_REPORT_BOOL_CAPABILITY("sipVoip", "tizen.org/feature/sip.voip")
+  DEFAULT_REPORT_BOOL_CAPABILITY("magnetometer", "tizen.org/feature/sensor.magnetometer")
+  DEFAULT_REPORT_BOOL_CAPABILITY("magnetometerWakeup", "tizen.org/feature/sensor.magnetometer.wakeup")
+  DEFAULT_REPORT_BOOL_CAPABILITY("photometer", "tizen.org/feature/sensor.photometer")
+  DEFAULT_REPORT_BOOL_CAPABILITY("photometerWakeup", "tizen.org/feature/sensor.photometer.wakeup")
+  DEFAULT_REPORT_BOOL_CAPABILITY("proximity", "tizen.org/feature/sensor.proximity")
+  DEFAULT_REPORT_BOOL_CAPABILITY("proximityWakeup", "tizen.org/feature/sensor.proximity.wakeup")
+  DEFAULT_REPORT_BOOL_CAPABILITY("tiltmeter", "tizen.org/feature/sensor.tiltmeter")
+  DEFAULT_REPORT_BOOL_CAPABILITY("tiltmeterWakeup", "tizen.org/feature/sensor.tiltmeter.wakeup")
+  DEFAULT_REPORT_BOOL_CAPABILITY("dataEncryption", "tizen.org/feature/database.encryption")
+  DEFAULT_REPORT_BOOL_CAPABILITY("autoRotation", "tizen.org/feature/screen.auto_rotation")
+  DEFAULT_REPORT_BOOL_CAPABILITY("visionImageRecognition", "tizen.org/feature/vision.image_recognition")
+  DEFAULT_REPORT_BOOL_CAPABILITY("visionQrcodeGeneration", "tizen.org/feature/vision.qrcode_generation")
+  DEFAULT_REPORT_BOOL_CAPABILITY("visionQrcodeRecognition", "tizen.org/feature/vision.qrcode_recognition")
+  DEFAULT_REPORT_BOOL_CAPABILITY("visionFaceRecognition", "tizen.org/feature/vision.face_recognition")
+  DEFAULT_REPORT_BOOL_CAPABILITY("secureElement", "tizen.org/feature/network.secure_element")
+  REPORT_STRING_CAPABILITY("profile", SystemInfoDeviceCapability::GetProfile)
+  DEFAULT_REPORT_STRING_CAPABILITY("nativeApiVersion", "tizen.org/feature/platform.native.api.version")
+  DEFAULT_REPORT_STRING_CAPABILITY("duid", "tizen.org/system/tizenid")
+  DEFAULT_REPORT_BOOL_CAPABILITY("screenSizeNormal", "tizen.org/feature/screen.size.normal")
+  DEFAULT_REPORT_BOOL_CAPABILITY("screenSize480_800", "tizen.org/feature/screen.size.normal.480.800")
+  DEFAULT_REPORT_BOOL_CAPABILITY("screenSize720_1280", "tizen.org/feature/screen.size.normal.720.1280")
+  DEFAULT_REPORT_BOOL_CAPABILITY("shellAppWidget", "tizen.org/feature/shell.appwidget")
+  DEFAULT_REPORT_BOOL_CAPABILITY("nativeOspCompatible", "tizen.org/feature/platform.native.osp_compatible")
+
+  ReportSuccess(result, *out);
+  LoggerD("Success");
+}
+
+void SysteminfoManager::GetCapability(const picojson::value& args, picojson::object* out) {
+  LoggerD("Enter");
+  CHECK_EXIST(args, "key", out)
+  const std::string& key = args.get("key").get<std::string>();
+  LoggerD("Getting capability with key: %s ", key.c_str());
+
+  picojson::value result = picojson::value(picojson::object());
+  PlatformResult ret = SystemInfoDeviceCapability::GetCapability(key, &result);
+  if (ret.IsSuccess()) {
+    ReportSuccess(result, *out);
+    LoggerD("Success");
+  } else {
+    ReportError(ret, out);
+  }
+}
+
+void SysteminfoManager::GetPropertyValue(const picojson::value& args, picojson::object* out) {
+  LoggerD("Enter");
+  CHECK_EXIST(args, "callbackId", out)
+  CHECK_EXIST(args, "property", out)
+  const double callback_id = args.get("callbackId").get<double>();
+  const std::string& prop_id = args.get("property").get<std::string>();
+  LoggerD("Getting property with id: %s ", prop_id.c_str());
+
+  auto get = [this, prop_id, callback_id](const std::shared_ptr<picojson::value>& response) -> void {
+    LoggerD("Getting");
+    picojson::value result = picojson::value(picojson::object());
+    PlatformResult ret = prop_manager_.GetPropertyValue(prop_id, false, &result);
+    if (ret.IsError()) {
+      ReportError(ret,&(response->get<picojson::object>()));
+      return;
+    }
+    ReportSuccess(result, response->get<picojson::object>());
+  };
+
+  auto get_response = [this, callback_id](const std::shared_ptr<picojson::value>& response) -> void {
+    LoggerD("Getting response");
+    picojson::object& obj = response->get<picojson::object>();
+    obj.insert(std::make_pair("callbackId", picojson::value{static_cast<double>(callback_id)}));
+    LoggerD("message: %s", response->serialize().c_str());
+    Instance::PostMessage(instance_, response->serialize().c_str());
+  };
+
+  auto data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+
+  TaskQueue::GetInstance().Queue<picojson::value>(get, get_response, data);
+}
+
+void SysteminfoManager::GetPropertyValueArray(const picojson::value& args, picojson::object* out) {
+  LoggerD("Enter");
+  CHECK_EXIST(args, "callbackId", out)
+  CHECK_EXIST(args, "property", out)
+  const double callback_id = args.get("callbackId").get<double>();
+  const std::string& prop_id = args.get("property").get<std::string>();
+  LoggerD("Getting property arrray with id: %s ", prop_id.c_str());
+
+  auto get = [this, prop_id, callback_id](const std::shared_ptr<picojson::value>& response) -> void {
+    LoggerD("Getting");
+    picojson::value result = picojson::value(picojson::object());
+
+    PlatformResult ret = prop_manager_.GetPropertyValue(prop_id, true, &result);
+    if (ret.IsError()) {
+      LoggerE("Failed: GetPropertyValue()");
+      ReportError(ret,&(response->get<picojson::object>()));
+      return;
+    }
+    ReportSuccess(result, response->get<picojson::object>());
+  };
+
+  auto get_response = [this, callback_id](const std::shared_ptr<picojson::value>& response) -> void {
+    LoggerD("Getting response");
+    picojson::object& obj = response->get<picojson::object>();
+    obj.insert(std::make_pair("callbackId", picojson::value(callback_id)));
+    Instance::PostMessage(instance_, response->serialize().c_str());
+  };
+
+  auto data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+
+  TaskQueue::GetInstance().Queue<picojson::value>(get, get_response, data);
+}
+
+void SysteminfoManager::GetTotalMemory(const picojson::value& args, picojson::object* out) {
+  LoggerD("Enter");
+  picojson::value result = picojson::value(picojson::object());
+  picojson::object& result_obj = result.get<picojson::object>();
+
+  long long return_value = 0;
+  PlatformResult ret = SysteminfoUtils::GetTotalMemory(&return_value);
+  if (ret.IsError()) {
+    LoggerD("Error");
+    ReportError(ret, out);
+    return;
+  }
+  result_obj.insert(std::make_pair("totalMemory",
+                                   picojson::value(static_cast<double>(return_value))));
+
+  ReportSuccess(result, *out);
+  LoggerD("Success");
+}
+
+void SysteminfoManager::GetAvailableMemory(const picojson::value& args, picojson::object* out) {
+  LoggerD("Enter");
+  picojson::value result = picojson::value(picojson::object());
+  picojson::object& result_obj = result.get<picojson::object>();
+
+  long long return_value = 0;
+  PlatformResult ret = SysteminfoUtils::GetAvailableMemory(&return_value);
+  if (ret.IsError()) {
+    LoggerD("Error");
+    ReportError(ret, out);
+    return;
+  }
+  result_obj.insert(std::make_pair("availableMemory",
+                                   picojson::value(static_cast<double>(return_value))));
+
+  ReportSuccess(result, *out);
+  LoggerD("Success");
+}
+
+void SysteminfoManager::GetCount(const picojson::value& args, picojson::object* out) {
+  LoggerD("Enter");
+  CHECK_EXIST(args, "property", out)
+  const std::string& property = args.get("property").get<std::string>();
+  LoggerD("Getting count of property with id: %s ", property.c_str());
+
+  picojson::value result = picojson::value(picojson::object());
+  picojson::object& result_obj = result.get<picojson::object>();
+  unsigned long count = 0;
+  PlatformResult ret = GetPropertyCount(property, &count);
+  if (ret.IsError()) {
+    LoggerE("Failed: GetCount()");
+    ReportError(ret, out);
+    return;
+  }
+  result_obj.insert(std::make_pair("count", picojson::value(static_cast<double>(count))));
+
+  ReportSuccess(result, *out);
+  LoggerD("Success");
+}
+
+void SysteminfoManager::AddPropertyValueChangeListener(const picojson::value& args,
+                                                       picojson::object* out) {
+  LoggerD("Enter");
+  // Check type of property for which listener should be registered
+  CHECK_EXIST(args, "property", out)
+  const std::string& property_name = args.get("property").get<std::string>();
+
+  PlatformResult ret(ErrorCode::NO_ERROR);
+  if (!IsListenerRegistered(property_name)){
+    LoggerD("Adding listener for property with id: %s ", property_name.c_str());
+    if (property_name == kPropertyIdBattery) {
+      ret = RegisterBatteryListener();
+    } else if (property_name == kPropertyIdCpu) {
+      ret = RegisterCpuListener();
+    } else if (property_name == kPropertyIdStorage) {
+      ret = RegisterStorageListener();
+    } else if (property_name == kPropertyIdDisplay) {
+      ret = RegisterDisplayListener();
+    } else if (property_name == kPropertyIdDeviceOrientation) {
+      ret = RegisterDeviceOrientationListener();
+    } else if (property_name == kPropertyIdBuild) {
+      LoggerW("BUILD property's value is a fixed value");
+      //should be accepted, but no registration is needed
+      ret = PlatformResult(ErrorCode::NOT_SUPPORTED_ERR, "BUILD property's value is a fixed value");
+    } else if (property_name == kPropertyIdLocale) {
+      ret = RegisterLocaleListener();
+    } else if (property_name == kPropertyIdNetwork) {
+      ret = RegisterNetworkListener();
+    } else if (property_name == kPropertyIdWifiNetwork) {
+      ret = RegisterWifiNetworkListener();
+    } else if (property_name == kPropertyIdEthernetNetwork) {
+      ret = RegisterEthernetNetworkListener();
+    } else if (property_name == kPropertyIdCellularNetwork) {
+      ret = RegisterCellularNetworkListener();
+    } else if (property_name == kPropertyIdSim) {
+      //SIM listeners are not supported by core API, so we just pass over
+      LoggerW("SIM listener is not supported by Core API - ignoring");
+    } else if (property_name == kPropertyIdPeripheral) {
+      ret = RegisterPeripheralListener();
+    } else if (property_name == kPropertyIdMemory) {
+      ret = RegisterMemoryListener();
+  #ifdef TIZEN_TV_PRODUCT
+    } else if (property_name == kPropertyIdVideoSource) {
+      ret = RegisterVideoSourceListener();
+  #endif
+    } else if (property_name == kPropertyIdCameraFlash) {
+      ret = RegisterCameraFlashListener();
+    } else {
+      LoggerE("Not supported property");
+      ret = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Not supported property");
+    }
+    if (ret.IsSuccess()) {
+      registered_listeners_.insert(property_name);
+    }
+  } else {
+    LoggerD("Adding listener for property with id: %s is not needed, already registered",
+            property_name.c_str());
+  }
+  if (ret.IsSuccess()) {
+    ReportSuccess(*out);
+    LoggerD("Success");
+    return;
+  }
+  LoggerD("Error");
+  ReportError(ret, out);
+}
+
+void SysteminfoManager::RemovePropertyValueChangeListener(const picojson::value& args,
+                                                          picojson::object* out) {
+  LoggerD("Enter");
+
+  // Check type of property for which listener should be removed
+  CHECK_EXIST(args, "property", out)
+  const std::string& property_name = args.get("property").get<std::string>();
+
+  PlatformResult ret(ErrorCode::NO_ERROR);
+  if (IsListenerRegistered(property_name)){
+    LoggerD("Removing listener for property with id: %s ", property_name.c_str());
+    registered_listeners_.erase(property_name);
+    if (property_name == kPropertyIdBattery) {
+      ret = UnregisterBatteryListener();
+    } else if (property_name == kPropertyIdCpu) {
+      ret = UnregisterCpuListener();
+    } else if (property_name == kPropertyIdStorage) {
+      ret = UnregisterStorageListener();
+    } else if (property_name == kPropertyIdDisplay) {
+      ret = UnregisterDisplayListener();
+    } else if (property_name == kPropertyIdDeviceOrientation) {
+      ret = UnregisterDeviceOrientationListener();
+    } else if (property_name == kPropertyIdBuild) {
+      LoggerW("BUILD property's value is a fixed value");
+      //should be accepted, but no unregistration is needed
+      //ret = PlatformResult(ErrorCode::NOT_SUPPORTED_ERR, "BUILD property's value is a fixed value");
+    } else if (property_name == kPropertyIdLocale) {
+      ret = UnregisterLocaleListener();
+    } else if (property_name == kPropertyIdNetwork) {
+      ret = UnregisterNetworkListener();
+    } else if (property_name == kPropertyIdWifiNetwork) {
+      ret = UnregisterWifiNetworkListener();
+    } else if (property_name == kPropertyIdEthernetNetwork) {
+      ret = UnregisterEthernetNetworkListener();
+    } else if (property_name == kPropertyIdCellularNetwork) {
+      ret = UnregisterCellularNetworkListener();
+    } else if (property_name == kPropertyIdSim) {
+      //SIM listeners are not supported by core API, so we just pass over
+      LoggerW("SIM listener is not supported by Core API - ignoring");
+    } else if (property_name == kPropertyIdPeripheral) {
+      ret = UnregisterPeripheralListener();
+    } else if (property_name == kPropertyIdMemory) {
+      ret = UnregisterMemoryListener();
+   #ifdef TIZEN_TV_PRODUCT
+     } else if (property_name == kPropertyIdVideoSource) {
+       ret = UnregisterVideoSourceListener();
+   #endif
+    } else if (property_name == kPropertyIdCameraFlash) {
+      ret = UnregisterCameraFlashListener();
+    } else {
+      LoggerE("Not supported property");
+      ret = PlatformResult(ErrorCode::INVALID_VALUES_ERR, "Not supported property");
+    }
+  } else {
+    LoggerD("Removing listener for property with id: %s is not needed, not registered",
+            property_name.c_str());
+  }
+  if (ret.IsSuccess()) {
+    ReportSuccess(*out);
+    LoggerD("Success");
+    return;
+  }
+  LoggerD("Error");
+  ReportError(ret, out);
+}
+
+#define CHECK_LISTENER_ERROR(method) \
+  ret = method; \
+  if (ret.IsError()) { \
+    return ret; \
+  }
+
+bool SysteminfoManager::IsIpChangeCallbackNotRegistered() {
+  LoggerD("Entered");
+  return !(IsListenerRegistered(kPropertyIdWifiNetwork) ||
+      IsListenerRegistered(kPropertyIdEthernetNetwork) ||
+      IsListenerRegistered(kPropertyIdCellularNetwork));
+}
+
+PlatformResult SysteminfoManager::RegisterIpChangeCallback() {
+  LoggerD("Entered");
+  connection_h handle;
+  PlatformResult ret(ErrorCode::NO_ERROR);
+  CHECK_LISTENER_ERROR(GetConnectionHandle(handle))
+  int error = connection_set_ip_address_changed_cb(handle,
+                                                   OnNetworkValueChangedCb,
+                                                   static_cast<void*>(this));
+  if (CONNECTION_ERROR_NONE != error) {
+    LoggerE("Failed to register ip change callback: %d", error);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Cannot register ip change callback");
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SysteminfoManager::UnregisterIpChangeCallback() {
+  LoggerD("Entered");
+  connection_h handle;
+  PlatformResult ret(ErrorCode::NO_ERROR);
+  CHECK_LISTENER_ERROR(GetConnectionHandle(handle))
+  int error = connection_unset_ip_address_changed_cb(handle);
+  if (CONNECTION_ERROR_NONE != error) {
+    LoggerE("Failed to unregister ip change callback: %d", error);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Cannot unregister ip change callback");
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SysteminfoManager::RegisterBatteryListener() {
+  LoggerD("Entered");
+  PlatformResult ret = PlatformResult(ErrorCode::NO_ERROR);
+  CHECK_LISTENER_ERROR(
+      SysteminfoUtils::RegisterVconfCallback(VCONFKEY_SYSMAN_BATTERY_CAPACITY,
+                                             OnBatteryChangedCb, this))
+  CHECK_LISTENER_ERROR(
+      SysteminfoUtils::RegisterVconfCallback(VCONFKEY_SYSMAN_BATTERY_CHARGE_NOW,
+                                             OnBatteryChangedCb, this))
+                                             LoggerD("Added callback for BATTERY");
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SysteminfoManager::UnregisterBatteryListener() {
+  LoggerD("Entered");
+  PlatformResult ret = PlatformResult(ErrorCode::NO_ERROR);
+  CHECK_LISTENER_ERROR(
+      SysteminfoUtils::UnregisterVconfCallback(VCONFKEY_SYSMAN_BATTERY_CAPACITY,
+                                               OnBatteryChangedCb))
+  CHECK_LISTENER_ERROR(
+      SysteminfoUtils::UnregisterVconfCallback(VCONFKEY_SYSMAN_BATTERY_CHARGE_NOW,
+                                               OnBatteryChangedCb))
+                                               LoggerD("Removed callback for BATTERY");
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SysteminfoManager::RegisterCpuListener() {
+  LoggerD("Entered");
+  cpu_event_id_ = g_timeout_add_seconds(kPropertyWatcherTime, OnCpuChangedCb, static_cast<void*>(this));
+  LoggerD("Added callback for CPU");
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SysteminfoManager::UnregisterCpuListener() {
+  LoggerD("Entered");
+  g_source_remove(cpu_event_id_);
+  cpu_event_id_ = 0;
+  LoggerD("Removed callback for CPU");
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SysteminfoManager::RegisterStorageListener() {
+  LoggerD("Entered");
+  PlatformResult ret = PlatformResult(ErrorCode::NO_ERROR);
+  CHECK_LISTENER_ERROR(
+      SysteminfoUtils::RegisterVconfCallback(VCONFKEY_SYSMAN_MMC_STATUS,
+                                             OnMmcChangedCb, this))
+
+  storage_event_id_ = g_timeout_add_seconds(kPropertyWatcherTime,
+                                             OnStorageChangedCb, static_cast<void*>(this));
+  LoggerD("Added callback for STORAGE");
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SysteminfoManager::UnregisterStorageListener() {
+  LoggerD("Entered");
+  PlatformResult ret = PlatformResult(ErrorCode::NO_ERROR);
+  CHECK_LISTENER_ERROR(
+      SysteminfoUtils::UnregisterVconfCallback(VCONFKEY_SYSMAN_MMC_STATUS, OnMmcChangedCb))
+
+  g_source_remove(storage_event_id_);
+  storage_event_id_ = 0;
+  LoggerD("Removed callback for STORAGE");
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SysteminfoManager::RegisterDisplayListener() {
+  LoggerD("Entered");
+  PlatformResult ret = PlatformResult(ErrorCode::NO_ERROR);
+  CHECK_LISTENER_ERROR(
+      SysteminfoUtils::RegisterVconfCallback(VCONFKEY_SETAPPL_LCD_BRIGHTNESS,
+                                             OnDisplayChangedCb, this))
+  LoggerD("Added callback for DISPLAY");
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SysteminfoManager::UnregisterDisplayListener() {
+  LoggerD("Entered");
+  PlatformResult ret = PlatformResult(ErrorCode::NO_ERROR);
+  CHECK_LISTENER_ERROR(
+      SysteminfoUtils::UnregisterVconfCallback(VCONFKEY_SETAPPL_LCD_BRIGHTNESS,
+                                               OnDisplayChangedCb))
+  LoggerD("Removed callback for DISPLAY");
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SysteminfoManager::RegisterDeviceOrientationListener() {
+  LoggerD("Entered");
+  PlatformResult ret = PlatformResult(ErrorCode::NO_ERROR);
+  CHECK_LISTENER_ERROR(
+      SysteminfoUtils::RegisterVconfCallback(VCONFKEY_SETAPPL_AUTO_ROTATE_SCREEN_BOOL,
+                                             OnDeviceAutoRotationChangedCb, this))
+
+  bool sensor_ret = sensord_register_event(GetSensorHandle(), AUTO_ROTATION_EVENT_CHANGE_STATE,
+                                           BASE_GATHERING_INTERVAL, 0,
+                                           OnDeviceOrientationChangedCb, this);
+  if (!sensor_ret) {
+    LoggerE("Failed to register orientation change event listener");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Failed to register orientation change event listener");
+  }
+
+  LoggerD("Added callback for DEVICE_ORIENTATION");
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SysteminfoManager::UnregisterDeviceOrientationListener() {
+  LoggerD("Entered");
+  PlatformResult ret = PlatformResult(ErrorCode::NO_ERROR);
+  CHECK_LISTENER_ERROR(
+      SysteminfoUtils::UnregisterVconfCallback(VCONFKEY_SETAPPL_AUTO_ROTATE_SCREEN_BOOL,
+                                               OnDeviceAutoRotationChangedCb))
+  bool sensor_ret = sensord_unregister_event(GetSensorHandle(), AUTO_ROTATION_EVENT_CHANGE_STATE);
+  if (!sensor_ret) {
+    LoggerE("Failed to unregister orientation change event listener");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to unregister"
+                          " orientation change event listener");
+  }
+
+  LoggerD("Removed callback for DEVICE_ORIENTATION");
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SysteminfoManager::RegisterLocaleListener() {
+  LoggerD("Entered");
+  if (SYSTEM_SETTINGS_ERROR_NONE !=
+      system_settings_set_changed_cb(SYSTEM_SETTINGS_KEY_LOCALE_COUNTRY,
+                                     OnLocaleChangedCb, static_cast<void*>(this)) ) {
+    LoggerE("Country change callback registration failed");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Country change callback registration failed");
+  }
+  if (SYSTEM_SETTINGS_ERROR_NONE !=
+      system_settings_set_changed_cb(SYSTEM_SETTINGS_KEY_LOCALE_LANGUAGE,
+                                     OnLocaleChangedCb, static_cast<void*>(this)) ) {
+    LoggerE("Language change callback registration failed");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Language change callback registration failed");
+  }
+  LoggerD("Added callback for LOCALE");
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SysteminfoManager::UnregisterLocaleListener() {
+  LoggerD("Entered");
+  if (SYSTEM_SETTINGS_ERROR_NONE !=
+      system_settings_unset_changed_cb(SYSTEM_SETTINGS_KEY_LOCALE_LANGUAGE) ) {
+    LoggerE("Unregistration of language change callback failed");
+  }
+  if (SYSTEM_SETTINGS_ERROR_NONE !=
+      system_settings_unset_changed_cb(SYSTEM_SETTINGS_KEY_LOCALE_COUNTRY) ) {
+    LoggerE("Unregistration of country change callback failed");
+  }
+  LoggerD("Removed callback for LOCALE");
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SysteminfoManager::RegisterNetworkListener() {
+  LoggerD("Entered");
+  connection_h handle;
+  PlatformResult ret(ErrorCode::NO_ERROR);
+  CHECK_LISTENER_ERROR(GetConnectionHandle(handle))
+  if (CONNECTION_ERROR_NONE !=
+      connection_set_type_changed_cb(handle, OnNetworkChangedCb, static_cast<void*>(this))) {
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Registration of listener failed");
+  }
+  LoggerD("Added callback for NETWORK");
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SysteminfoManager::UnregisterNetworkListener() {
+  LoggerD("Entered");
+  connection_h handle;
+  PlatformResult ret(ErrorCode::NO_ERROR);
+  CHECK_LISTENER_ERROR(GetConnectionHandle(handle))
+  if (CONNECTION_ERROR_NONE != connection_unset_type_changed_cb(handle)) {
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Unregistration of listener failed");
+  }
+  LoggerD("Removed callback for NETWORK");
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SysteminfoManager::RegisterWifiNetworkListener() {
+  LoggerD("Entered");
+
+  if (IsIpChangeCallbackNotRegistered()) {
+    PlatformResult ret = PlatformResult(ErrorCode::NO_ERROR);
+    CHECK_LISTENER_ERROR(RegisterIpChangeCallback());
+    LoggerD("Registered IP change listener");
+  } else {
+    LoggerD("No need to register IP listener on platform, already registered");
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SysteminfoManager::UnregisterWifiNetworkListener() {
+  LoggerD("Entered");
+  // if there is no other ip-relateded listeners left, unregister
+  if (IsIpChangeCallbackNotRegistered()) {
+    PlatformResult ret = PlatformResult(ErrorCode::NO_ERROR);
+    CHECK_LISTENER_ERROR(UnregisterIpChangeCallback());
+    LoggerD("Removed IP change listener");
+  } else {
+    LoggerD("Removed callback for WIFI_NETWORK, but IP change listener still works");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SysteminfoManager::RegisterEthernetNetworkListener() {
+  LoggerD("Entered");
+  PlatformResult ret = SysteminfoUtils::CheckIfEthernetNetworkSupported();
+  if (ret.IsError()){
+    return ret;
+  }
+
+  if (IsIpChangeCallbackNotRegistered()) {
+    PlatformResult ret = PlatformResult(ErrorCode::NO_ERROR);
+    CHECK_LISTENER_ERROR(RegisterIpChangeCallback());
+    LoggerD("Registered IP change listener");
+  } else {
+    LoggerD("No need to register IP listener on platform, already registered");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SysteminfoManager::UnregisterEthernetNetworkListener() {
+  LoggerD("Entered");
+
+  if (IsIpChangeCallbackNotRegistered()) {
+    PlatformResult ret = PlatformResult(ErrorCode::NO_ERROR);
+    CHECK_LISTENER_ERROR(UnregisterIpChangeCallback());
+    LoggerD("Removed IP change listener");
+  } else {
+    LoggerD("Removed callback for ETHERNET_NETWORK, but IP change listener still works");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SysteminfoManager::RegisterCellularNetworkListener() {
+  LoggerD("Entered");
+  PlatformResult ret = SysteminfoUtils::CheckTelephonySupport();
+  if (ret.IsError()) {
+      return ret;
+  }
+
+  if (IsIpChangeCallbackNotRegistered()) {
+    CHECK_LISTENER_ERROR(RegisterIpChangeCallback());
+    LoggerD("Registered IP change listener");
+  } else {
+    LoggerD("No need to register IP listener on platform, already registered");
+  }
+
+  if (!IsListenerRegistered(kPropertyIdCellularNetwork)) {
+    CHECK_LISTENER_ERROR(SysteminfoUtils::RegisterVconfCallback(
+        VCONFKEY_TELEPHONY_FLIGHT_MODE, OnCellularNetworkValueChangedCb, this))
+    int sim_count = GetSimCount();
+    TapiHandle **tapis = GetTapiHandles();
+    for (int i = 0; i < sim_count; ++i) {
+      CHECK_LISTENER_ERROR(SysteminfoUtils::RegisterTapiChangeCallback(
+          tapis[i], TAPI_PROP_NETWORK_CELLID, OnTapiValueChangedCb, this))
+      CHECK_LISTENER_ERROR(SysteminfoUtils::RegisterTapiChangeCallback(
+          tapis[i], TAPI_PROP_NETWORK_LAC, OnTapiValueChangedCb, this))
+      CHECK_LISTENER_ERROR(SysteminfoUtils::RegisterTapiChangeCallback(
+          tapis[i], TAPI_PROP_NETWORK_ROAMING_STATUS, OnTapiValueChangedCb, this))
+    }
+    LoggerD("Added callback for CELLULAR_NETWORK");
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SysteminfoManager::UnregisterCellularNetworkListener() {
+  LoggerD("Entered");
+
+  // if there is no other ip-relateded listeners left, unregister
+  if (!IsListenerRegistered(kPropertyIdCellularNetwork)) {
+    PlatformResult ret = PlatformResult(ErrorCode::NO_ERROR);
+    CHECK_LISTENER_ERROR(SysteminfoUtils::UnregisterVconfCallback(
+        VCONFKEY_TELEPHONY_FLIGHT_MODE, OnCellularNetworkValueChangedCb))
+    int sim_count = GetSimCount();
+    TapiHandle **tapis = GetTapiHandles();
+    for (int i = 0; i < sim_count; ++i) {
+      CHECK_LISTENER_ERROR(SysteminfoUtils::UnregisterTapiChangeCallback(
+          tapis[i], TAPI_PROP_NETWORK_CELLID))
+      CHECK_LISTENER_ERROR(SysteminfoUtils::UnregisterTapiChangeCallback(
+          tapis[i], TAPI_PROP_NETWORK_LAC))
+      CHECK_LISTENER_ERROR(SysteminfoUtils::UnregisterTapiChangeCallback(
+          tapis[i], TAPI_PROP_NETWORK_ROAMING_STATUS))
+    }
+  }
+
+  if (IsIpChangeCallbackNotRegistered()) {
+    PlatformResult ret = PlatformResult(ErrorCode::NO_ERROR);
+    CHECK_LISTENER_ERROR(UnregisterIpChangeCallback());
+    LoggerD("Removed IP change listener");
+  } else {
+    LoggerD("Removed callback for CELLULAR_NETWORK, but IP change listener still works");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SysteminfoManager::RegisterPeripheralListener() {
+  LoggerD("Entered");
+  PlatformResult ret = PlatformResult(ErrorCode::NO_ERROR);
+  int value = 0;
+/*  if (-1 != vconf_get_int(VCONFKEY_MIRACAST_WFD_SOURCE_STATUS, &value)) {
+    CHECK_LISTENER_ERROR(RegisterVconfCallback(VCONFKEY_MIRACAST_WFD_SOURCE_STATUS,
+                                               OnPeripheralChangedCb, instance))
+  }*/
+  if (-1 != vconf_get_int(VCONFKEY_SYSMAN_HDMI, &value)) {
+    CHECK_LISTENER_ERROR(SysteminfoUtils::RegisterVconfCallback(VCONFKEY_SYSMAN_HDMI,
+                                               OnPeripheralChangedCb, this))
+  }
+
+  LoggerD("Added callback for PERIPHERAL");
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SysteminfoManager::UnregisterPeripheralListener() {
+  LoggerD("Entered");
+  PlatformResult ret = PlatformResult(ErrorCode::NO_ERROR);
+  int value = 0;
+/*  if (-1 != vconf_get_int(VCONFKEY_MIRACAST_WFD_SOURCE_STATUS, &value)) {
+    CHECK_LISTENER_ERROR(SysteminfoUtils::UnregisterVconfCallback(VCONFKEY_MIRACAST_WFD_SOURCE_STATUS,
+                                                 OnPeripheralChangedCb))
+  }*/
+  if (-1 != vconf_get_int(VCONFKEY_SYSMAN_HDMI, &value)) {
+    CHECK_LISTENER_ERROR(SysteminfoUtils::UnregisterVconfCallback(VCONFKEY_SYSMAN_HDMI,
+                                                 OnPeripheralChangedCb))
+  }
+
+  LoggerD("Removed callback for PERIPHERAL");
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SysteminfoManager::RegisterMemoryListener() {
+  LoggerD("Entered");
+  PlatformResult ret = PlatformResult(ErrorCode::NO_ERROR);
+  int value = 0;
+  if (-1 != vconf_get_int(VCONFKEY_SYSMAN_LOW_MEMORY, &value)) {
+    CHECK_LISTENER_ERROR(SysteminfoUtils::RegisterVconfCallback(VCONFKEY_SYSMAN_LOW_MEMORY,
+                                                                OnMemoryChangedCb, this))
+  }
+  LoggerD("Added callback for MEMORY");
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SysteminfoManager::UnregisterMemoryListener() {
+  LoggerD("Entered");
+  PlatformResult ret = PlatformResult(ErrorCode::NO_ERROR);
+  int value = 0;
+  if (-1 != vconf_get_int(VCONFKEY_SYSMAN_LOW_MEMORY, &value)) {
+    CHECK_LISTENER_ERROR(SysteminfoUtils::UnregisterVconfCallback(VCONFKEY_SYSMAN_LOW_MEMORY,
+                                                                  OnMemoryChangedCb))
+  }
+  LoggerD("Removed callback for MEMORY");
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+#ifdef TIZEN_TV_PRODUCT
+void SysteminfoManager::OnSignal(ESignalType, TSSignalData)
+{
+  OnVideoSourceChangedCb(this);
+}
+
+PlatformResult SysteminfoManager::RegisterVideoSourceListener()
+{
+  auto sHelper = &(TvsSubscribeHelper::getInstance());
+  PlatformResult ret = sHelper->registerListener(SIGNAL_SOURCE_STATE_CHANGED, this);
+  if (ret.IsError()) {
+    return ret;
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SysteminfoManager::UnregisterVideoSourceListener()
+{
+  auto sHelper = &(TvsSubscribeHelper::getInstance());
+  sHelper->unregisterListener(SIGNAL_SOURCE_STATE_CHANGED, this);
+  return PlatformResult(ErrorCode::NO_ERROR);}
+#endif
+
+PlatformResult SysteminfoManager::RegisterCameraFlashListener() {
+  LoggerD("Entered");
+  if (DEVICE_ERROR_NONE != device_add_callback(DEVICE_CALLBACK_FLASH_BRIGHTNESS,
+                                               OnBrightnessChangedCb, this)) {
+    return PlatformResult(ErrorCode::UNKNOWN_ERR);
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SysteminfoManager::UnregisterCameraFlashListener() {
+  LoggerD("Entered");
+  PlatformResult ret = PlatformResult(ErrorCode::NO_ERROR);
+  if (DEVICE_ERROR_NONE != device_remove_callback(DEVICE_CALLBACK_FLASH_BRIGHTNESS,
+                                                  OnBrightnessChangedCb)) {
+    return PlatformResult(ErrorCode::UNKNOWN_ERR);
+  }
+  LoggerD("Removed callback for camera_flash");
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+void SysteminfoManager::SetBrightness(const picojson::value& args, picojson::object* out) {
+  LoggerD("entered");
+
+  CHECK_EXIST(args, "brightness", out)
+
+  const double brightness = args.get("brightness").get<double>();
+  int result = device_flash_set_brightness(brightness);
+  if (result != DEVICE_ERROR_NONE) {
+    LoggerE("Error occured");
+    ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Error occured"), out);
+    return;
+  }
+  ReportSuccess(*out);
+}
+
+void SysteminfoManager::GetBrightness(const picojson::value& args, picojson::object* out) {
+  LoggerD("entered");
+
+  int brightness = 0;
+  int result = device_flash_get_brightness(&brightness);
+  if (result != DEVICE_ERROR_NONE) {
+    LoggerE("Error occured");
+    ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Error occured"), out);
+    return;
+  }
+  ReportSuccess(picojson::value(std::to_string(brightness)), *out);
+}
+
+void SysteminfoManager::GetMaxBrightness(const picojson::value& args, picojson::object* out) {
+  LoggerD("entered");
+
+  int brightness = 0;
+  int result = device_flash_get_max_brightness(&brightness);
+  if (result != DEVICE_ERROR_NONE) {
+    LoggerE("Error occured");
+    ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Not supported property"), out);
+    return;
+  }
+  ReportSuccess(picojson::value(std::to_string(brightness)), *out);
+}
+
+PlatformResult SysteminfoManager::GetPropertyCount(const std::string& property,
+                                                   unsigned long* count) {
+  LoggerD("Enter");
+
+  if ("BATTERY" == property || "CPU" == property || "STORAGE" == property ||
+      "DISPLAY" == property || "DEVICE_ORIENTATION" == property ||
+      "BUILD" == property || "LOCALE" == property || "WIFI_NETWORK" == property ||
+      "PERIPHERAL" == property || "MEMORY" == property) {
+    *count = kDefaultPropertyCount;
+  } else if ("CELLULAR_NETWORK" == property || "SIM" == property || "NETWORK" == property) {
+    PlatformResult ret = SysteminfoUtils::CheckTelephonySupport();
+    if (ret.IsError()) {
+      *count = 0;
+    } else {
+      *count = GetSimCount();
+    }
+  } else if ("CAMERA_FLASH" == property) {
+    *count = GetCameraTypesCount();
+  } else if ("ETHERNET_NETWORK" == property) {
+    PlatformResult ret = SysteminfoUtils::CheckIfEthernetNetworkSupported();
+    if (ret.IsError()) {
+      *count = 0;
+    } else {
+      *count = kDefaultPropertyCount;
+    }
+  } else {
+    LoggerD("Property with given id is not supported");
+    return PlatformResult(ErrorCode::NOT_SUPPORTED_ERR, "Property with given id is not supported");
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+wifi_rssi_level_e SysteminfoManager::GetWifiLevel() {
+  LoggerD("Enter");
+  return wifi_level_;
+}
+
+void SysteminfoManager::SetWifiLevel(wifi_rssi_level_e level) {
+  LoggerD("Entered");
+  wifi_level_ = level;
+}
+
+int SysteminfoManager::GetSensorHandle() {
+  LoggerD("Enter");
+  std::lock_guard<std::mutex> lock(sensor_mutex_);
+  if (sensor_handle_ < 0) {
+    LoggerD("Connecting to sensor");
+    ConnectSensor(&sensor_handle_);
+  } else {
+    LoggerD("Sensor already connected");
+  }
+  return sensor_handle_;
+}
+
+PlatformResult SysteminfoManager::ConnectSensor(int* result) {
+  LoggerD("Entered");
+  sensor_t 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";
+    LoggerE("%s", log_msg.c_str());
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, log_msg);
+  }
+  bool ret = sensord_start(handle_orientation, 0);
+  if(!ret) {
+    sensord_disconnect(handle_orientation);
+    std::string log_msg = "Failed to start auto rotation sensor";
+    LoggerE("%s", log_msg.c_str());
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, log_msg);
+  }
+  LoggerD("Sensor starts successfully = %d", handle_orientation);
+  *result = handle_orientation;
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+void SysteminfoManager::DisconnectSensor(int handle_orientation) {
+  LoggerD("Enter");
+  if (handle_orientation >= 0) {
+    LoggerD("Entered");
+    bool state = sensord_stop(handle_orientation);
+    LoggerD("sensord_stop() returned state = %d", state);
+    state = sensord_disconnect(handle_orientation);
+    LoggerD("sensord_disconnect() returned state %d", state);
+  } else {
+    LoggerD("sensor already disconnected - no action needed");
+  }
+}
+
+void SysteminfoManager::SetCpuInfoLoad(double load) {
+  LoggerD("Enter");
+  cpu_load_ = load;
+}
+
+void SysteminfoManager::SetAvailableCapacityInternal(unsigned long long capacity) {
+  LoggerD("Entered");
+  available_capacity_internal_ = capacity;
+}
+
+void SysteminfoManager::SetAvailableCapacityMmc(unsigned long long capacity) {
+  LoggerD("Entered");
+  available_capacity_mmc_ = capacity;
+}
+
+int SysteminfoManager::GetSimCount() {
+  LoggerD("Entered");
+  InitTapiHandles();
+  return sim_count_;
+}
+
+void SysteminfoManager::InitTapiHandles() {
+  LoggerD("Entered");
+  std::lock_guard<std::mutex> lock(tapi_mutex_);
+  if (nullptr == tapi_handles_[0]){  //check if anything is in table
+    sim_count_ = 0;
+    char **cp_list = tel_get_cp_name_list();
+    if (nullptr != cp_list) {
+      while (cp_list[sim_count_]) {
+        tapi_handles_[sim_count_] = tel_init(cp_list[sim_count_]);
+        if (nullptr == tapi_handles_[sim_count_]) {
+          LoggerE("Failed to connect with tapi, handle is null");
+          break;
+        }
+        LoggerD("%d modem: %s", sim_count_, cp_list[sim_count_]);
+        sim_count_++;
+      }
+    } else {
+      LoggerE("Failed to get cp list");
+      sim_count_ = kTapiMaxHandle;
+    }
+    g_strfreev(cp_list);
+  }
+}
+
+TapiHandle* SysteminfoManager::GetTapiHandle() {
+  LoggerD("Entered");
+  InitTapiHandles();
+  return tapi_handles_[0];
+}
+
+TapiHandle** SysteminfoManager::GetTapiHandles() {
+  LoggerD("Enter");
+  InitTapiHandles();
+  return tapi_handles_;
+}
+
+int SysteminfoManager::GetChangedTapiIndex(TapiHandle* tapi) {
+  LoggerD("Enter");
+  TapiHandle** handles = GetTapiHandles();
+  for (int i = 0; i < sim_count_; ++i) {
+    if (handles[i] == tapi) {
+      return i;
+    }
+  }
+  return -1;
+}
+
+void SysteminfoManager::InitCameraTypes() {
+  LoggerD("Enter");
+  bool supported = false;
+  PlatformResult ret = SystemInfoDeviceCapability::GetValueBool(
+      "tizen.org/feature/camera.back.flash", &supported);
+  if (ret.IsSuccess()) {
+    if (supported) {
+      camera_types_.push_back("BACK");
+    }
+  }
+  ret = SystemInfoDeviceCapability::GetValueBool(
+      "tizen.org/feature/camera.front.flash", &supported);
+  if (ret.IsSuccess()) {
+    if (supported) {
+      camera_types_.push_back("FRONT");
+    }
+  }
+}
+
+std::string SysteminfoManager::GetCameraTypes(unsigned long index) {
+  LoggerD("Enter");
+  if (index >= camera_types_.size()) {
+    return "";
+  }
+  return camera_types_[index];
+}
+
+unsigned long SysteminfoManager::GetCameraTypesCount() {
+  LoggerD("Enter");
+  return camera_types_.size();
+}
+
+PlatformResult SysteminfoManager::GetConnectionHandle(connection_h& handle) {
+  LoggerD("Entered");
+  std::lock_guard<std::mutex> lock(connection_mutex_);
+  if (nullptr == connection_handle_) {
+    int error = connection_create(&connection_handle_);
+    if (CONNECTION_ERROR_NONE != error) {
+      LoggerE("Failed to create connection: %d", error);
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, "Cannot create connection");
+    }
+  }
+  handle = connection_handle_;
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+bool SysteminfoManager::IsListenerRegistered(const std::string& property_id) {
+  LoggerD("Entered");
+  return (registered_listeners_.find(property_id) != registered_listeners_.end());
+}
+
+void SysteminfoManager::PostListenerResponse(const std::string& property_id,
+                                     const picojson::value& result,
+                                     int property_index) {
+  LoggerD("Entered");
+  const std::shared_ptr<picojson::value>& response =
+      std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+  response->get<picojson::object>()[kPropertyIdString] = picojson::value(property_id);
+  response->get<picojson::object>()[kListenerIdString] = picojson::value(kListenerConstValue);
+  // Added pushing index of property to handle only default for signle-property listeners in js
+  response->get<picojson::object>()[kChangedPropertyIndexString] =
+      picojson::value(static_cast<double>(property_index));
+
+  ReportSuccess(result,response->get<picojson::object>());
+  Instance::PostMessage(instance_, response->serialize().c_str());
+}
+
+
+void SysteminfoManager::CallListenerCallback(const std::string& property_id,
+                                             int property_index) {
+  LoggerD("Enter");
+  if(IsListenerRegistered(property_id)) {
+    LoggerD("listener for %s property is registered, calling it", property_id.c_str());
+
+    picojson::value result = picojson::value(picojson::object());
+    PlatformResult ret = GetPropertiesManager().GetPropertyValue(
+        property_id, true, &result);
+    if (ret.IsSuccess()) {
+      PostListenerResponse(property_id, result, property_index);
+    }
+  } else {
+    LoggerD("listener for %s property is not registered, ignoring", property_id.c_str());
+  }
+}
+
+void SysteminfoManager::CallCpuListenerCallback() {
+  LoggerD("Enter");
+  std::string property_id = kPropertyIdCpu;
+  if(IsListenerRegistered(property_id)) {
+    LoggerD("listener for %s property is registered, calling it", property_id.c_str());
+    picojson::value result = picojson::value(picojson::object());
+    PlatformResult ret = GetPropertiesManager().GetPropertyValue(
+        property_id, true, &result);
+    if (ret.IsSuccess()) {
+      if (cpu_load_ == last_cpu_load_) {
+        LoggerD("Cpu load didn't change, ignoring");
+        return;
+      }
+      last_cpu_load_ = cpu_load_;
+      PostListenerResponse(property_id, result);
+    }
+  } else {
+    LoggerD("listener for %s property is not registered, ignoring", property_id.c_str());
+  }
+}
+
+void SysteminfoManager::CallStorageListenerCallback() {
+  LoggerD("Enter");
+  std::string property_id = kPropertyIdStorage;
+  if(IsListenerRegistered(property_id)) {
+    LoggerD("listener for %s property is registered, calling it", property_id.c_str());
+
+    picojson::value result = picojson::value(picojson::object());
+    PlatformResult ret = GetPropertiesManager().GetPropertyValue(
+        property_id, true, &result);
+    if (ret.IsSuccess()) {
+      // check if anything changed
+      if (available_capacity_internal_ == last_available_capacity_internal_ &&
+          available_capacity_mmc_ == last_available_capacity_mmc_) {
+        LoggerD("Storage state didn't change, ignoring");
+        return;
+      }
+      // refresh previous values
+      last_available_capacity_internal_ = available_capacity_internal_;
+      last_available_capacity_mmc_ = available_capacity_mmc_;
+
+      PostListenerResponse(property_id, result);
+    }
+  } else {
+    LoggerD("listener for %s property is not registered, ignoring", property_id.c_str());
+  }
+}
+
+}  // namespace systeminfo
+}  // namespace extension
diff --git a/webWidgetTCT_device/src/systeminfo/systeminfo_manager.h b/webWidgetTCT_device/src/systeminfo/systeminfo_manager.h
new file mode 100755 (executable)
index 0000000..ba038a2
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2015 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 WEBAPI_PLUGINS_SYSTEMINFO_SYSTEMINFO_MANAGER_H__
+#define WEBAPI_PLUGINS_SYSTEMINFO_SYSTEMINFO_MANAGER_H__
+
+#include <set>
+
+#include <wifi.h>
+#include <net_connection.h>
+
+#include "common/picojson.h"
+#include "common/platform_result.h"
+#include "systeminfo/systeminfo_properties_manager.h"
+#ifdef TIZEN_TV_PRODUCT
+#include "common/tvsapi_subscribe_helper.h"
+#endif
+
+namespace extension {
+namespace systeminfo {
+
+const int kTapiMaxHandle = 2;
+
+class SysteminfoInstance;
+
+#ifdef TIZEN_TV_PRODUCT
+class SysteminfoManager : private common::TvsSignalListener{
+#else
+class SysteminfoManager {
+#endif
+ public:
+  SysteminfoManager(SysteminfoInstance* instance);
+  ~SysteminfoManager();
+
+  void GetCapabilities(const picojson::value& args, picojson::object* out);
+  void GetCapability(const picojson::value& args, picojson::object* out);
+  void GetPropertyValue(const picojson::value& args, picojson::object* out);
+  void GetPropertyValueArray(const picojson::value& args, picojson::object* out);
+  void AddPropertyValueChangeListener(const picojson::value& args, picojson::object* out);
+  void RemovePropertyValueChangeListener(const picojson::value& args, picojson::object* out);
+  void GetMaxBrightness(const picojson::value& args, picojson::object* out);
+  void GetBrightness(const picojson::value& args, picojson::object* out);
+  void SetBrightness(const picojson::value& args, picojson::object* out);
+  void GetTotalMemory(const picojson::value& args, picojson::object* out);
+  void GetAvailableMemory(const picojson::value& args, picojson::object* out);
+  void GetCount(const picojson::value& args, picojson::object* out);
+
+  common::PlatformResult GetPropertyCount(const std::string& property, unsigned long* count);
+  wifi_rssi_level_e GetWifiLevel();
+  void SetWifiLevel(wifi_rssi_level_e level);
+  int GetSensorHandle();
+  TapiHandle* GetTapiHandle();
+  TapiHandle** GetTapiHandles();
+  int GetChangedTapiIndex(TapiHandle* tapi);
+  common::PlatformResult GetConnectionHandle(connection_h& handle);
+
+  SysteminfoInstance* GetInstance() { return instance_;};
+  SysteminfoPropertiesManager& GetPropertiesManager() { return prop_manager_;};
+
+  void SetCpuInfoLoad(double load);
+  void SetAvailableCapacityInternal(unsigned long long capacity);
+  void SetAvailableCapacityMmc(unsigned long long capacity);
+  std::string GetCameraTypes(unsigned long index);
+  unsigned long GetCameraTypesCount();
+
+  bool IsListenerRegistered(const std::string& property_id);
+  void CallListenerCallback(const std::string& property_id, int property_index = 0);
+  void CallCpuListenerCallback();
+  void CallStorageListenerCallback();
+ private:
+  void PostListenerResponse(const std::string& property_id, const picojson::value& result,
+                            int property_index = 0);
+  common::PlatformResult ConnectSensor(int* result);
+  void DisconnectSensor(int handle_orientation);
+  void InitTapiHandles();
+  void InitCameraTypes();
+  int GetSimCount();
+
+#ifdef TIZEN_TV_PRODUCT
+  void OnSignal(ESignalType, TSSignalData);
+#endif
+
+  bool IsIpChangeCallbackNotRegistered();
+  common::PlatformResult RegisterIpChangeCallback();
+  common::PlatformResult UnregisterIpChangeCallback();
+
+  common::PlatformResult RegisterBatteryListener();
+  common::PlatformResult UnregisterBatteryListener();
+  common::PlatformResult RegisterCpuListener();
+  common::PlatformResult UnregisterCpuListener();
+  common::PlatformResult RegisterStorageListener();
+  common::PlatformResult UnregisterStorageListener();
+  common::PlatformResult RegisterDisplayListener();
+  common::PlatformResult UnregisterDisplayListener();
+  common::PlatformResult RegisterDeviceOrientationListener();
+  common::PlatformResult UnregisterDeviceOrientationListener();
+  common::PlatformResult RegisterLocaleListener();
+  common::PlatformResult UnregisterLocaleListener();
+  common::PlatformResult RegisterNetworkListener();
+  common::PlatformResult UnregisterNetworkListener();
+  common::PlatformResult RegisterWifiNetworkListener();
+  common::PlatformResult UnregisterWifiNetworkListener();
+  common::PlatformResult RegisterEthernetNetworkListener();
+  common::PlatformResult UnregisterEthernetNetworkListener();
+  common::PlatformResult RegisterCellularNetworkListener();
+  common::PlatformResult UnregisterCellularNetworkListener();
+  common::PlatformResult RegisterPeripheralListener();
+  common::PlatformResult UnregisterPeripheralListener();
+  common::PlatformResult RegisterMemoryListener();
+  common::PlatformResult UnregisterMemoryListener();
+  common::PlatformResult RegisterCameraFlashListener();
+  common::PlatformResult UnregisterCameraFlashListener();
+
+#ifdef TIZEN_TV
+  common::PlatformResult RegisterVideoSourceListener();
+  common::PlatformResult UnregisterVideoSourceListener();
+#endif
+
+  SysteminfoInstance* instance_;
+  SysteminfoInstance* videoSourceInstance;
+  SysteminfoPropertiesManager prop_manager_;
+
+  //! Sensor handle for DeviceOrientation purposes
+  int sensor_handle_;
+  std::mutex sensor_mutex_;
+
+  std::vector<std::string> camera_types_;
+  wifi_rssi_level_e wifi_level_;
+  double cpu_load_;
+  double last_cpu_load_;
+  unsigned long long available_capacity_internal_;
+  unsigned long long last_available_capacity_internal_;
+  unsigned long long available_capacity_mmc_;
+  unsigned long long last_available_capacity_mmc_;
+
+  int sim_count_;
+  TapiHandle *tapi_handles_[kTapiMaxHandle+1];
+  std::mutex tapi_mutex_;
+
+  std::set<std::string> registered_listeners_;
+
+  guint cpu_event_id_;
+  guint storage_event_id_;
+
+  connection_h connection_handle_;
+  std::mutex connection_mutex_;
+
+};
+} // namespace systeminfo
+} // namespace webapi
+
+#endif // WEBAPI_PLUGINS_SYSTEMINFO_SYSTEMINFO_MANAGER_H__
diff --git a/webWidgetTCT_device/src/systeminfo/systeminfo_properties_manager.cc b/webWidgetTCT_device/src/systeminfo/systeminfo_properties_manager.cc
new file mode 100755 (executable)
index 0000000..3e56ab0
--- /dev/null
@@ -0,0 +1,1571 @@
+/*
+ * Copyright (c) 2015 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 "systeminfo/systeminfo_properties_manager.h"
+
+#include <memory>
+#include <wifi.h>
+
+#include <vconf.h>
+#include <vconf-internal-keys.h>
+#include <system_info.h>
+#include <sensor_internal.h>
+#include <system_settings.h>
+#include <net_connection.h>
+#include <sys/statfs.h>
+
+#include "systeminfo/systeminfo_manager.h"
+#include "systeminfo/systeminfo_device_capability.h"
+#include "common/scope_exit.h"
+#include "systeminfo/systeminfo-utils.h"
+#include "common/filesystem/storage.h"
+#ifdef TIZEN_TV
+#  ifdef TIZEN_TV_PRODUCT
+#    include <TVServiceAPI.h>
+#    include <SignalSubscriberDataType.h>
+#    include "common/video_source_types.h"
+#    include "filesystem/filesystem_manager.h"
+#    include "common/filesystem/filesystem_provider_capiusb.h"
+#  else
+#    include "common/filesystem/deviced.h"
+#  endif
+#endif
+
+namespace extension {
+namespace systeminfo {
+
+using common::PlatformResult;
+using common::ErrorCode;
+
+
+namespace {
+const std::string kMemoryStateNormal = "NORMAL";
+const std::string kMemoryStateWarinig = "WARNING";
+const double kDisplayInchToMillimeter = 2.54;
+//Battery
+const double kRemainingBatteryChargeMax = 100.0;
+const int kVconfErrorNone = 0;
+//Display
+const double kDisplayBrightnessDivideValue = 100;
+//Device Orientation
+const std::string kOrientationPortraitPrimary = "PORTRAIT_PRIMARY";
+const std::string kOrientationPortraitSecondary = "PORTRAIT_SECONDARY";
+const std::string kOrientationLandscapePrimary = "LANDSCAPE_PRIMARY";
+const std::string kOrientationLandscapeSecondary = "LANDSCAPE_SECONDARY";
+//Peripheral
+const std::string kVideoOutputString = "isVideoOutputOn";
+//Storage
+const char* kStorageInternalPath = "/opt/usr/media";
+const char* kStorageSdcardPath = "/opt/storage/sdcard";
+const std::string kPropertyIdStorage = "STORAGE";
+const std::string kTypeUnknown = "UNKNOWN";
+const std::string kTypeInternal = "INTERNAL";
+const std::string kTypeUsbDevice = "USB_DEVICE";
+const std::string kTypeUsbHost = "USB_HOST";
+const std::string kTypeMmc = "MMC";
+//Network
+enum NetworkType {
+  kNone,
+  kType2G,
+  kType2_5G,
+  kType3G,
+  kType4G,
+  kWifi,
+  kEthernet,
+  kUnknown
+};
+
+enum SecurityMode {
+  kNoneMode,
+  kWepMode,
+  kWpaPskMode,
+  kWpa2PskMode,
+  kEapMode
+};
+
+std::map<SecurityMode, std::string> NetworkSecurityModeMap = {
+  {kNoneMode, "NONE"},
+  {kWepMode, "WEP"},
+  {kWpaPskMode, "WPA_PSK"},
+  {kWpa2PskMode, "WPA2_PSK"},
+  {kEapMode, "EAP"}
+};
+
+enum EncryptionType {
+  kNoneType,
+  kWepType,
+  kTkipType,
+  kAesType,
+  kTkipAesMixedType
+};
+
+std::map<EncryptionType, std::string> NetworkEcryptionTypeMap = {
+  {kNoneType, "NONE"},
+  {kWepType, "WEP"},
+  {kTkipType, "TKIP"},
+  {kAesType, "AES"},
+  {kTkipAesMixedType, "TKIP_AES_MIXED"}
+};
+
+enum IpMode {
+  kNoneIpMode,
+  kStaticMode,
+  kDynamicMode,
+  kAutoMode,
+  kFixedMode
+};
+
+std::map<IpMode, std::string> NetworkIpModeMap = {
+  {kNoneIpMode, "NONE"},
+  {kStaticMode, "STATIC"},
+  {kDynamicMode, "DYNAMIC"},
+  {kAutoMode, "AUTO"},
+  {kFixedMode, "FIXED"},
+};
+
+const int kDnsOrder = 1;
+
+const char* kNetworkTypeNone = "NONE";
+const char* kNetworkType2G = "2G";
+const char* kNetworkType2_5G = "2.5G";
+const char* kNetworkType3G = "3G";
+const char* kNetworkType4G = "4G";
+const char* kNetworkTypeWifi = "WIFI";
+const char* kNetworkTypeEthernet = "ETHERNET";
+const char* kNetworkTypeUnknown = "UNKNOWN";
+//Wifi Network
+const std::string kWifiStatusOn = "ON";
+const std::string kWifiStatusOff = "OFF";
+const int kWifiSignalStrengthDivideValue = 100;
+//Cellular Network
+const unsigned short kMccDivider = 100;
+const char* kConnectionOff = "OFF";
+const char* kConnectionOn = "ON";
+}
+
+SysteminfoPropertiesManager::SysteminfoPropertiesManager(SysteminfoManager& manager)
+    : manager_(manager) {
+  LoggerD("Entered");
+}
+
+SysteminfoPropertiesManager::~SysteminfoPropertiesManager() {
+  LoggerD("Entered");
+}
+
+PlatformResult SysteminfoPropertiesManager::GetPropertyValue(const std::string& property,
+                                                             bool is_array_type,
+                                                             picojson::value* res) {
+  LoggerD("Entered getPropertyValue");
+
+  if (!is_array_type) {
+    picojson::object& res_obj = res->get<picojson::object>();
+    return ReportProperty(property, 0, &res_obj);
+  } else {
+    picojson::object& array_result_obj = res->get<picojson::object>();
+    picojson::array& array = array_result_obj.insert(
+        std::make_pair("array", picojson::value(picojson::array()))).
+            first->second.get<picojson::array>();
+
+    unsigned long property_count = 0;
+    PlatformResult ret = manager_.GetPropertyCount(property, &property_count);
+    if (ret.IsError()){
+      LoggerD("Property is not available");
+      return ret;
+    }
+    LoggerD("property name: %s", property.c_str());
+    LoggerD("available property count: %d", property_count);
+
+    for (size_t i = 0; i < property_count; i++) {
+      picojson::value result = picojson::value(picojson::object());
+      picojson::object& result_obj = result.get<picojson::object>();
+
+      PlatformResult ret = ReportProperty(property, i, &result_obj);
+      if (ret.IsError()){
+        return ret;
+      }
+      array.push_back(result);
+    }
+    if (property_count == 0) {
+      return PlatformResult(ErrorCode::NOT_SUPPORTED_ERR, "Property with given id is not supported");
+    }
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SysteminfoPropertiesManager::ReportProperty(const std::string& property, int index,
+                                               picojson::object* res_obj) {
+  LoggerD("Entered");
+  if ("BATTERY" == property){
+    return ReportBattery(res_obj);
+  } else if ("CPU" == property) {
+    return ReportCpu(res_obj);
+  } else if ("STORAGE" == property) {
+    return ReportStorage(res_obj);
+  } else if ("DISPLAY" == property) {
+    return ReportDisplay(res_obj);
+  } else if ("DEVICE_ORIENTATION" == property) {
+    return ReportDeviceOrientation(res_obj);
+  } else if ("BUILD" == property) {
+    return ReportBuild(res_obj);
+  } else if ("LOCALE" == property) {
+    return ReportLocale(res_obj);
+  } else if ("NETWORK" == property) {
+    return ReportNetwork(res_obj, index);
+  } else if ("WIFI_NETWORK" == property) {
+    return ReportWifiNetwork(res_obj);
+  } else if ("ETHERNET_NETWORK" == property) {
+    return ReportEthernetNetwork(res_obj);
+  } else if ("CELLULAR_NETWORK" == property) {
+    return ReportCellularNetwork(res_obj, index);
+  } else if ("SIM" == property) {
+    return ReportSim(res_obj, index);
+  } else if ("PERIPHERAL" == property) {
+    return ReportPeripheral(res_obj);
+  } else if ("MEMORY" == property) {
+    return ReportMemory(res_obj);
+  } else if ("CAMERA_FLASH" == property) {
+    return ReportCameraFlash(res_obj, index);
+#ifdef TIZEN_TV_PRODUCT
+  } else if ("VIDEOSOURCE" == property) {
+    return ReportVideoSource(res_obj);
+#endif
+  }
+  LoggerD("Property with given id is not supported");
+  return PlatformResult(ErrorCode::NOT_SUPPORTED_ERR, "Property with given id is not supported");
+}
+
+/// BATTERY
+PlatformResult SysteminfoPropertiesManager::ReportBattery(picojson::object* out) {
+  LoggerD("Entered");
+  PlatformResult supported = SysteminfoUtils::CheckBatterySupport();
+  if (supported.IsError()) {
+    return supported;
+  }
+
+  int value = 0;
+  int ret = vconf_get_int(VCONFKEY_SYSMAN_BATTERY_CAPACITY, &value);
+  if (kVconfErrorNone != ret) {
+    std::string log_msg = "Platform error while getting battery detail: ";
+    LoggerE("%s%d", log_msg.c_str(), ret);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, (log_msg + std::to_string(ret)));
+  }
+
+  out->insert(std::make_pair("level", picojson::value(static_cast<double>(value)/kRemainingBatteryChargeMax)));
+  value = 0;
+  ret = vconf_get_int(VCONFKEY_SYSMAN_BATTERY_CHARGE_NOW, &value);
+  if (kVconfErrorNone != ret) {
+    std::string log_msg =  "Platform error while getting battery charging: ";
+    LoggerE("%s%d",log_msg.c_str(), ret);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, (log_msg + std::to_string(ret)));
+  }
+  out->insert(std::make_pair("isCharging", picojson::value(0 != value)));
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+/// CPU
+PlatformResult SysteminfoPropertiesManager::ReportCpu(picojson::object* out) {
+  LoggerD("Entered");
+  static CpuInfo cpu_info;
+  FILE *fp = nullptr;
+  fp = fopen("/proc/stat", "r");
+  if (nullptr == fp) {
+    std::string error_msg("Can not open /proc/stat for reading");
+    LoggerE( "%s", error_msg.c_str() );
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, 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 ) * 100LL / total;
+      cpu_info.usr = usr;
+      cpu_info.system = system;
+      cpu_info.nice = nice;
+      cpu_info.idle = idle;
+      cpu_info.load = load;
+    } else {
+      LoggerW("Cannot calculate cpu load, previous value returned");
+      load = cpu_info.load;
+    }
+  } else {
+    std::string error_msg( "Could not read /proc/stat" );
+    LoggerE( "%s", error_msg.c_str() );
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, error_msg);
+  }
+
+  manager_.SetCpuInfoLoad(cpu_info.load);
+
+  load = 100 - load;
+  LoggerD("Cpu load : %f", load );
+  out->insert(std::make_pair("load", picojson::value(load / 100.0)));
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+/// DISPLAY
+PlatformResult SysteminfoPropertiesManager::ReportDisplay(picojson::object* out) {
+  LoggerD("Entered");
+  int screenWidth = 0;
+  int screenHeight = 0;
+  int dotsPerInchWidth = 0;
+  int dotsPerInchHeight = 0;
+  double physicalWidth = 0;
+  double physicalHeight = 0;
+  double scaledBrightness;
+
+  // FETCH RESOLUTION
+  if (SYSTEM_INFO_ERROR_NONE != system_info_get_platform_int(
+      "tizen.org/feature/screen.width", &screenWidth)) {
+    LoggerE("Cannot get value of screen width");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Cannot get value of screen width");
+  }
+  if (SYSTEM_INFO_ERROR_NONE != system_info_get_platform_int(
+      "tizen.org/feature/screen.height", &screenHeight)) {
+    LoggerE("Cannot get value of screen height");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Cannot get value of screen height");
+  }
+
+  //FETCH DOTS PER INCH
+  int dots_per_inch=0;
+  if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_int(
+      "tizen.org/feature/screen.dpi", &dots_per_inch)) {
+    dotsPerInchWidth = dots_per_inch;
+    dotsPerInchHeight = dots_per_inch;
+  } else {
+    LoggerE("Cannot get 'tizen.org/feature/screen.dpi' value");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "Cannot get 'tizen.org/feature/screen.dpi' value");
+  }
+
+  //FETCH PHYSICAL WIDTH
+  if (dotsPerInchWidth != 0 && screenWidth != 0) {
+    physicalWidth = (screenWidth / dotsPerInchWidth) * kDisplayInchToMillimeter;
+  } else {
+    std::string log_msg = "Failed to get physical screen width value";
+    LoggerE("%s, screenWidth : %d, dotsPerInchWidth: %d", log_msg.c_str(),
+         screenWidth, dotsPerInchWidth);
+  }
+
+  //FETCH PHYSICAL HEIGHT
+  if (dotsPerInchHeight != 0 && screenHeight != 0) {
+    physicalHeight = (screenHeight / dotsPerInchHeight) * kDisplayInchToMillimeter;
+  } else {
+    std::string log_msg = "Failed to get physical screen height value";
+    LoggerE("%s, screenHeight : %d, dotsPerInchHeight: %d", log_msg.c_str(),
+         screenHeight, dotsPerInchHeight);
+  }
+
+  //FETCH BRIGHTNESS
+  int brightness;
+  if (kVconfErrorNone == vconf_get_int(VCONFKEY_SETAPPL_LCD_BRIGHTNESS, &brightness)) {
+    scaledBrightness = static_cast<double>(brightness)/kDisplayBrightnessDivideValue;
+  } else {
+    LoggerE("Cannot get brightness value of display");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Cannot get brightness value of display");
+  }
+
+  out->insert(std::make_pair("resolutionWidth", picojson::value(std::to_string(screenWidth))));
+  out->insert(std::make_pair("resolutionHeight", picojson::value(std::to_string(screenHeight))));
+  out->insert(std::make_pair("dotsPerInchWidth", picojson::value(std::to_string(dotsPerInchWidth))));
+  out->insert(std::make_pair("dotsPerInchHeight", picojson::value(std::to_string(dotsPerInchHeight))));
+  out->insert(std::make_pair("physicalWidth", picojson::value(std::to_string(physicalWidth))));
+  out->insert(std::make_pair("physicalHeight", picojson::value(std::to_string(physicalHeight))));
+  out->insert(std::make_pair("brightness", picojson::value(scaledBrightness)));
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+/// DEVICE_ORIENTATION
+PlatformResult SysteminfoPropertiesManager::FetchIsAutoRotation(bool* result) {
+  LoggerD("Entered");
+  int is_auto_rotation = 0;
+
+  if ( 0 == vconf_get_bool(
+      VCONFKEY_SETAPPL_AUTO_ROTATE_SCREEN_BOOL, &is_auto_rotation)) {
+    if (is_auto_rotation) {
+      *result = true;
+    } else {
+      *result = false;
+    }
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+  else {
+    LoggerE("VCONFKEY_SETAPPL_AUTO_ROTATE_SCREEN_BOOL check failed");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                          "VCONFKEY_SETAPPL_AUTO_ROTATE_SCREEN_BOOL check failed");
+  }
+}
+
+PlatformResult SysteminfoPropertiesManager::FetchStatus(std::string* result) {
+  LoggerD("Entered");
+  int rotation = 0;
+  std::string status = kOrientationPortraitPrimary;
+
+  sensor_data_t data;
+  bool ret = sensord_get_data(manager_.GetSensorHandle(),
+                             AUTO_ROTATION_BASE_DATA_SET, &data);
+  if (ret) {
+    LoggerD("size of the data value array:%d", data.value_count);
+    if (data.value_count > 0 ) {
+      rotation = data.values[0];
+      LoggerD("rotation is: %d", rotation);
+    } else {
+      LoggerE("Failed to get data : the size of array is 0. Default rotation would be returned.");
+    }
+  } else {
+    LoggerE("Failed to get data(sensord_get_data). Default rotation would be returned.");
+  }
+
+
+  switch (rotation) {
+    case AUTO_ROTATION_DEGREE_UNKNOWN:
+    case AUTO_ROTATION_DEGREE_0:
+      LoggerD("AUTO_ROTATION_DEGREE_0");
+      status = kOrientationPortraitPrimary;
+      break;
+    case AUTO_ROTATION_DEGREE_90:
+      LoggerD("AUTO_ROTATION_DEGREE_90");
+      status = kOrientationLandscapePrimary;
+      break;
+    case AUTO_ROTATION_DEGREE_180:
+      LoggerD("AUTO_ROTATION_DEGREE_180");
+      status = kOrientationPortraitSecondary;
+      break;
+    case AUTO_ROTATION_DEGREE_270:
+      LoggerD("AUTO_ROTATION_DEGREE_270");
+      status = kOrientationLandscapeSecondary;
+      break;
+    default:
+      LoggerE("Received unexpected data: %u", rotation);
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, "Received unexpected data");
+  }
+  *result = status;
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SysteminfoPropertiesManager::ReportDeviceOrientation(picojson::object* out) {
+  LoggerD("Entered");
+  PlatformResult supported = SysteminfoUtils::CheckDeviceOrientationSupport();
+  if (supported.IsError()) {
+    return supported;
+  }
+
+  bool is_auto_rotation = false;
+  std::string status = "";
+
+  PlatformResult ret = FetchIsAutoRotation(&is_auto_rotation);
+  if (ret.IsError()) return ret;
+
+  ret = FetchStatus(&status);
+  if (ret.IsError()) return ret;
+
+  out->insert(std::make_pair("isAutoRotation", picojson::value(is_auto_rotation)));
+  out->insert(std::make_pair("status", picojson::value(status)));
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+/// BUILD
+PlatformResult SysteminfoPropertiesManager::ReportBuild(picojson::object* out) {
+  LoggerD("Entered");
+  std::string model = "";
+  PlatformResult ret = SystemInfoDeviceCapability::GetValueString(
+      "tizen.org/system/model_name", &model);
+  if (ret.IsError()) {
+    return ret;
+  }
+  std::string manufacturer = "";
+  ret = SystemInfoDeviceCapability::GetValueString(
+      "tizen.org/system/manufacturer", &manufacturer);
+  if (ret.IsError()) {
+    return ret;
+  }
+  std::string buildVersion = "";
+  ret = SystemInfoDeviceCapability::GetValueString(
+      "tizen.org/system/build.string", &buildVersion);
+  if (ret.IsError()) {
+    return ret;
+  }
+
+  out->insert(std::make_pair("model", picojson::value(model)));
+  out->insert(std::make_pair("manufacturer", picojson::value(manufacturer)));
+  out->insert(std::make_pair("buildVersion", picojson::value(buildVersion)));
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+/// LOCALE
+PlatformResult SysteminfoPropertiesManager::ReportLocale(picojson::object* out) {
+  LoggerD("Entered");
+  std::string str_language = "";
+  PlatformResult ret = SysteminfoUtils::GetRuntimeInfoString(
+      SYSTEM_SETTINGS_KEY_LOCALE_LANGUAGE, &str_language);
+  if (ret.IsError()) {
+    return ret;
+  }
+
+  std::string str_country = "";
+  ret = SysteminfoUtils::GetRuntimeInfoString(SYSTEM_SETTINGS_KEY_LOCALE_COUNTRY, &str_country);
+  if (ret.IsError()) {
+    return ret;
+  }
+
+  out->insert(std::make_pair("language", picojson::value(str_language)));
+  out->insert(std::make_pair("country", picojson::value(str_country)));
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+/// NETWORK
+static PlatformResult GetNetworkTypeString(NetworkType type, std::string& type_string) {
+  LoggerD("Entered");
+  switch (type) {
+    case kNone:
+      type_string = kNetworkTypeNone;
+      break;
+    case kType2G:
+      type_string = kNetworkType2G;
+      break;
+    case kType2_5G:
+      type_string = kNetworkType2_5G;
+      break;
+    case kType3G:
+      type_string = kNetworkType3G;
+      break;
+    case kType4G:
+      type_string = kNetworkType4G;
+      break;
+    case kWifi:
+      type_string = kNetworkTypeWifi;
+      break;
+    case kEthernet:
+      type_string = kNetworkTypeEthernet;
+      break;
+    case kUnknown:
+      type_string = kNetworkTypeUnknown;
+      break;
+    default:
+      LoggerE("Incorrect type: %d", type);
+      return PlatformResult(ErrorCode::TYPE_MISMATCH_ERR, "Incorrect type");
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SysteminfoPropertiesManager::ReportNetwork(picojson::object* out, unsigned long count) {
+  LoggerD("Entered with index property %d", count);
+  connection_h connection_handle = nullptr;
+  connection_type_e connection_type = CONNECTION_TYPE_DISCONNECTED;
+  int networkType = 0;
+  NetworkType type = kNone;
+
+  //connection must be created in every call, in other case error occurs
+  int error = connection_create(&connection_handle);
+  if (CONNECTION_ERROR_NONE != error) {
+    std::string log_msg = "Cannot create connection: " + std::to_string(error);
+    LoggerE("%s", log_msg.c_str());
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, log_msg);
+  }
+  std::unique_ptr<std::remove_pointer<connection_h>::type, int(*)(connection_h)>
+  connection_handle_ptr(connection_handle, &connection_destroy);
+  // automatically release the memory
+
+  error = connection_get_type(connection_handle, &connection_type);
+  if (CONNECTION_ERROR_NONE != error) {
+    std::string log_msg = "Cannot get connection type: " + std::to_string(error);
+    LoggerE("%s", log_msg.c_str());
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, log_msg);
+  }
+
+  switch (connection_type) {
+    case CONNECTION_TYPE_DISCONNECTED :
+      type = kNone;
+      break;
+    case CONNECTION_TYPE_WIFI :
+      type =  kWifi;
+      break;
+    case CONNECTION_TYPE_CELLULAR :
+      if (TAPI_API_SUCCESS == tel_get_property_int(manager_.GetTapiHandles()[count],
+                                                   TAPI_PROP_NETWORK_SERVICE_TYPE, &networkType)) {
+        if (networkType < TAPI_NETWORK_SERVICE_TYPE_2G) {
+          type =  kNone;
+        } else if (networkType == TAPI_NETWORK_SERVICE_TYPE_2G) {
+          type =  kType2G;
+        } else if (networkType == TAPI_NETWORK_SERVICE_TYPE_2_5G
+            || networkType == TAPI_NETWORK_SERVICE_TYPE_2_5G_EDGE) {
+          type =  kType2_5G;
+        } else if (networkType == TAPI_NETWORK_SERVICE_TYPE_3G
+            || networkType == TAPI_NETWORK_SERVICE_TYPE_HSDPA) {
+          type =  kType3G;
+        } else if (networkType == TAPI_NETWORK_SERVICE_TYPE_LTE) {
+          type =  kType4G;
+        } else {
+          type =  kNone;
+        }
+      }
+      break;
+    case CONNECTION_TYPE_ETHERNET :
+      type =  kEthernet;
+      break;
+    default:
+      LoggerE("Incorrect type: %d", connection_type);
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, "Incorrect type");
+  }
+  std::string type_str = "";
+  PlatformResult ret = GetNetworkTypeString(type, type_str);
+  if(ret.IsError()) {
+    return ret;
+  }
+  out->insert(std::make_pair("networkType", picojson::value(type_str)));
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+/// CELLULAR_NETWORK and ETHERNET_NETWORK
+static PlatformResult GetIpsFromProfile(connection_profile_h profile_handle, std::string* ip_addr_str,
+                             std::string* ipv6_addr_str){
+  LoggerD("Entered");
+  //getting ipv4 address
+  char* ip_addr = nullptr;
+  int error = connection_profile_get_ip_address(profile_handle,
+                                                CONNECTION_ADDRESS_FAMILY_IPV4,
+                                                &ip_addr);
+  if (CONNECTION_ERROR_NONE != error) {
+    LoggerE("Failed to get ip address: %d", error);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Cannot get ip address");
+  }
+  *ip_addr_str = ip_addr;
+  free(ip_addr);
+  //getting ipv6 address
+  ip_addr = nullptr;
+  error = connection_profile_get_ip_address(profile_handle,
+                                            CONNECTION_ADDRESS_FAMILY_IPV6,
+                                            &ip_addr);
+  if (CONNECTION_ERROR_NONE == error) {
+    *ipv6_addr_str = ip_addr;
+    free(ip_addr);
+  } else if (CONNECTION_ERROR_ADDRESS_FAMILY_NOT_SUPPORTED != error) {
+    //core api returns error -97 = CONNECTION_ERROR_ADDRESS_FAMILY_NOT_SUPPORTED
+    //it will be supported in the future. For now let's ignore this error
+    LoggerE("Failed to get ipv6 address: %d", error);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Cannot get ipv6 address");
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+static PlatformResult GetIps(connection_profile_h profile_handle, std::string* ip_addr_str,
+                   std::string* ipv6_addr_str){
+  //getting ipv4 address
+  char* ip_addr = nullptr;
+  int error = connection_profile_get_ip_address(profile_handle,
+                                                CONNECTION_ADDRESS_FAMILY_IPV4,
+                                                &ip_addr);
+  if (CONNECTION_ERROR_NONE != error) {
+    LoggerE("Failed to get ip address: %d", error);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Cannot get ip address");
+  }
+  *ip_addr_str = ip_addr;
+  free(ip_addr);
+
+  //getting ipv6 address
+  ip_addr = nullptr;
+  error = connection_profile_get_ip_address(profile_handle,
+                                            CONNECTION_ADDRESS_FAMILY_IPV6,
+                                            &ip_addr);
+  if (CONNECTION_ERROR_NONE == error) {
+    *ipv6_addr_str = ip_addr;
+    free(ip_addr);
+  } else if (CONNECTION_ERROR_ADDRESS_FAMILY_NOT_SUPPORTED != error) {
+    //core api returns error -97 = CONNECTION_ERROR_ADDRESS_FAMILY_NOT_SUPPORTED
+    //it will be supported in the future. For now let's ignore this error
+    LoggerE("Failed to get ipv6 address: %d", error);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Cannot get ipv6 address");
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+static PlatformResult GetIpConfigType(connection_profile_h profile, IpMode* ip_config_type) {
+  //ipv4 address family
+  connection_ip_config_type_e type;
+  int error = connection_profile_get_ip_config_type(profile,
+                                                  CONNECTION_ADDRESS_FAMILY_IPV4,
+                                                  &type);
+  if (CONNECTION_ERROR_NONE == error) {
+    switch (type) {
+      case CONNECTION_IP_CONFIG_TYPE_NONE :
+        *ip_config_type = kNoneIpMode;
+        break;
+      case CONNECTION_IP_CONFIG_TYPE_STATIC :
+        *ip_config_type =  kStaticMode;
+        break;
+      case CONNECTION_IP_CONFIG_TYPE_DYNAMIC :
+        *ip_config_type =  kDynamicMode;
+        break;
+      case CONNECTION_IP_CONFIG_TYPE_AUTO :
+        *ip_config_type =  kAutoMode;
+        break;
+      case CONNECTION_IP_CONFIG_TYPE_FIXED :
+        *ip_config_type =  kFixedMode;
+        break;
+      default:
+        LoggerE("Incorrect config type: %d", type);
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Incorrect config type");
+    }
+  }
+  else {
+    LoggerE("Failed to get ip config type: %d", error);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Cannot get ip config type");
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SysteminfoPropertiesManager::ReportWifiNetwork(picojson::object* out) {
+  LoggerD("Entered");
+
+  bool result_status = false;
+  std::string result_ssid;
+  std::string result_ip_address;
+  std::string result_ipv6_address;
+  std::string result_mac_address;
+  double result_signal_strength = 0;
+  std::string mode_str;
+  std::string encrypt_type;
+  std::string ip_mode;
+  std::string result_subnet_mask;
+  std::string result_gateway;
+  std::string result_dns;
+
+  connection_h connection_handle = nullptr;
+  connection_type_e connection_type = CONNECTION_TYPE_DISCONNECTED;
+  connection_profile_h profile_handle = nullptr;
+  EncryptionType type = kNoneType;
+  SecurityMode mode = kNoneMode;
+  IpMode ip_config_type = kNoneIpMode;
+
+  //connection must be created in every call, in other case error occurs
+  int error = connection_create(&connection_handle);
+  if (CONNECTION_ERROR_NONE != error) {
+    std::string log_msg = "Cannot create connection: " + std::to_string(error);
+    LoggerE("%s", log_msg.c_str());
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, log_msg);
+  }
+  std::unique_ptr<std::remove_pointer<connection_h>::type, int(*)(connection_h)>
+  connection_handle_ptr(connection_handle, &connection_destroy);
+  // automatically release the memory
+
+  char* mac = nullptr;
+  error = connection_get_mac_address(connection_handle, CONNECTION_TYPE_WIFI, &mac);
+  if (CONNECTION_ERROR_NONE == error && nullptr != mac) {
+    SLoggerD("MAC address fetched: %s", mac);
+    result_mac_address = mac;
+    free(mac);
+  } else {
+    std::string log_msg = "Failed to get mac address: " + std::to_string(error);
+    LoggerE("%s", log_msg.c_str());
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, log_msg);
+  }
+
+  error = connection_get_type(connection_handle, &connection_type);
+  if (CONNECTION_ERROR_NONE != error) {
+    std::string log_msg = "Cannot get connection type: " + std::to_string(error);
+    LoggerE("%s", log_msg.c_str());
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, log_msg);
+  }
+  if (CONNECTION_TYPE_WIFI == connection_type) {
+    result_status = true;
+    //gathering profile
+    error = connection_get_current_profile(connection_handle, &profile_handle);
+    if (CONNECTION_ERROR_NONE != error) {
+      std::string log_msg = "Cannot get connection profile: " + std::to_string(error);
+      LoggerE("%s", log_msg.c_str());
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, log_msg);
+    }
+    std::unique_ptr
+    <std::remove_pointer<connection_profile_h>::type, int(*)(connection_profile_h)>
+    profile_handle_ptr(profile_handle, &connection_profile_destroy);
+    // automatically release the memory
+
+    //gathering ssid
+    char* essid = nullptr;
+    error = connection_profile_get_wifi_essid(profile_handle, &essid);
+    if (CONNECTION_ERROR_NONE == error) {
+      result_ssid = essid;
+      free(essid);
+    }
+    else {
+      std::string log_msg = "Failed to get network ssid: " + std::to_string(error);
+      LoggerE("%s", log_msg.c_str());
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, log_msg);
+    }
+
+    //gathering ips
+    PlatformResult ret = GetIps(profile_handle, &result_ip_address, &result_ipv6_address);
+    if (ret.IsError()) {
+      return ret;
+    }
+
+    //gathering strength
+    int rssi = 0;
+    error = connection_profile_get_wifi_rssi(profile_handle, &rssi);
+    if (CONNECTION_ERROR_NONE == error) {
+      result_signal_strength = (double) rssi/kWifiSignalStrengthDivideValue;
+    }
+    else {
+      std::string log_msg = "Failed to get signal strength: " + std::to_string(error);
+      LoggerE("%s", log_msg.c_str());
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, log_msg);
+    }
+    //gathering security mode
+    connection_wifi_security_type_e security_mode = CONNECTION_WIFI_SECURITY_TYPE_NONE;
+    error = connection_profile_get_wifi_security_type(profile_handle, &security_mode);
+    if (CONNECTION_ERROR_NONE == error) {
+        switch (security_mode) {
+          case CONNECTION_WIFI_SECURITY_TYPE_NONE :
+            mode = kNoneMode;
+            break;
+          case CONNECTION_WIFI_SECURITY_TYPE_WEP :
+            mode =  kWepMode;
+            break;
+          case CONNECTION_WIFI_SECURITY_TYPE_WPA_PSK :
+            mode =  kWpaPskMode;
+            break;
+          case CONNECTION_WIFI_SECURITY_TYPE_WPA2_PSK :
+            mode =  kWpa2PskMode;
+            break;
+          case CONNECTION_WIFI_SECURITY_TYPE_EAP :
+            mode =  kEapMode;
+            break;
+          default:
+            LoggerE("Incorrect mode: %d", security_mode);
+            return PlatformResult(ErrorCode::UNKNOWN_ERR, "Incorrect mode");
+        }
+    }
+    else {
+      std::string log_msg = "Failed to get signal strength: " + std::to_string(error);
+      LoggerE("%s", log_msg.c_str());
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, log_msg);
+    }
+    //gathering encryption type
+    connection_wifi_encryption_type_e encryption_type = CONNECTION_WIFI_ENCRYPTION_TYPE_NONE;
+    error = connection_profile_get_wifi_encryption_type(profile_handle, &encryption_type);
+    if (CONNECTION_ERROR_NONE == error) {
+        switch (encryption_type) {
+          case CONNECTION_WIFI_ENCRYPTION_TYPE_NONE :
+            type = kNoneType;
+            break;
+          case CONNECTION_WIFI_ENCRYPTION_TYPE_WEP :
+            type =  kWepType;
+            break;
+          case CONNECTION_WIFI_ENCRYPTION_TYPE_TKIP :
+            type =  kTkipType;
+            break;
+          case CONNECTION_WIFI_ENCRYPTION_TYPE_AES :
+            type =  kAesType;
+            break;
+          case CONNECTION_WIFI_ENCRYPTION_TYPE_TKIP_AES_MIXED :
+            type =  kTkipAesMixedType;
+            break;
+          default:
+            LoggerE("Incorrect type: %d", encryption_type);
+            return PlatformResult(ErrorCode::UNKNOWN_ERR, "Incorrect type");
+        }
+    }
+    else {
+      std::string log_msg = "Failed to get signal strength: " + std::to_string(error);
+      LoggerE("%s", log_msg.c_str());
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, log_msg);
+    }
+    //gathering IP configuration mode
+    ret = GetIpConfigType(profile_handle, &ip_config_type);
+    if (ret.IsError()) {
+      return ret;
+    }
+
+    //gathering subnet mask
+    char* subnet_mask = nullptr;
+    error = connection_profile_get_subnet_mask(profile_handle, CONNECTION_ADDRESS_FAMILY_IPV4, &subnet_mask);
+    if (CONNECTION_ERROR_NONE == error) {
+      result_subnet_mask = subnet_mask;
+      free(subnet_mask);
+    }
+    else {
+      std::string log_msg = "Failed to get subnet mask: " + std::to_string(error);
+      LoggerE("%s", log_msg.c_str());
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, log_msg);
+    }
+
+    //gathering gateway
+    char* gateway = nullptr;
+    error = connection_profile_get_gateway_address(profile_handle, CONNECTION_ADDRESS_FAMILY_IPV4, &gateway);
+    if (CONNECTION_ERROR_NONE == error) {
+      result_gateway = gateway;
+      free(gateway);
+    }
+    else {
+      std::string log_msg = "Failed to get gateway: " + std::to_string(error);
+      LoggerE("%s", log_msg.c_str());
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, log_msg);
+    }
+
+    //gathering dns
+    char* dns = nullptr;
+    error = connection_profile_get_dns_address(profile_handle, kDnsOrder, CONNECTION_ADDRESS_FAMILY_IPV4, &dns);
+    if (CONNECTION_ERROR_NONE == error) {
+      result_dns = dns;
+      free(dns);
+    }
+    else {
+      std::string log_msg = "Failed to get gateway: " + std::to_string(error);
+      LoggerE("%s", log_msg.c_str());
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, log_msg);
+    }
+  }
+  else {
+    LoggerD("Connection type = %d. WIFI is disabled", connection_type);
+  }
+
+  mode_str = NetworkSecurityModeMap[mode];
+  encrypt_type = NetworkEcryptionTypeMap[type];
+  ip_mode = NetworkIpModeMap[ip_config_type];
+
+  out->insert(std::make_pair("status", picojson::value(result_status ? kWifiStatusOn : kWifiStatusOff)));
+  out->insert(std::make_pair("ssid", picojson::value(result_ssid)));
+  out->insert(std::make_pair("ipAddress", picojson::value(result_ip_address)));
+  out->insert(std::make_pair("ipv6Address", picojson::value(result_ipv6_address)));
+  out->insert(std::make_pair("macAddress", picojson::value(result_mac_address)));
+  out->insert(std::make_pair("signalStrength", picojson::value(std::to_string(result_signal_strength))));
+  out->insert(std::make_pair("securityMode", picojson::value(mode_str)));
+  out->insert(std::make_pair("encryptionType", picojson::value(encrypt_type)));
+  out->insert(std::make_pair("ipMode", picojson::value(ip_mode)));
+  out->insert(std::make_pair("subnetMask", picojson::value(result_subnet_mask)));
+  out->insert(std::make_pair("gateway", picojson::value(result_gateway)));
+  out->insert(std::make_pair("dns", picojson::value(result_dns)));
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+/// ETHERNET_NETWORK
+PlatformResult SysteminfoPropertiesManager::ReportEthernetNetwork(picojson::object* out) {
+  LoggerD("Entered");
+
+  std::string result_cable;
+  std::string result_status;
+  std::string result_ip_address;
+  std::string result_ipv6_address;
+  std::string result_mac_address;
+  std::string ip_mode;
+  std::string result_subnet_mask;
+  std::string result_gateway;
+  std::string result_dns;
+
+  connection_h connection_handle = nullptr;
+  connection_ethernet_state_e connection_state = CONNECTION_ETHERNET_STATE_DEACTIVATED;
+  connection_type_e connection_type = CONNECTION_TYPE_DISCONNECTED;
+  connection_profile_h profile_handle = nullptr;
+  IpMode ip_config_type = kNoneIpMode;
+
+  // connection must be created in every call, in other case error occurs
+  int error = connection_create(&connection_handle);
+  if (CONNECTION_ERROR_NONE != error) {
+    std::string log_msg = "Cannot create connection: " + std::to_string(error);
+    LoggerE("%s", log_msg.c_str());
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, log_msg);
+  }
+  std::unique_ptr<std::remove_pointer<connection_h>::type, int (*)(connection_h)> connection_handle_ptr(
+      connection_handle, &connection_destroy);  // automatically release the memory
+
+  error = connection_get_ethernet_state(connection_handle, &connection_state);
+  if (CONNECTION_ERROR_NONE != error) {
+    if (CONNECTION_ERROR_NOT_SUPPORTED == error) {
+      std::string log_msg = "Cannot get ethernet connection state: Not supported";
+      LoggerE("%s", log_msg.c_str());
+      return PlatformResult(ErrorCode::NOT_SUPPORTED_ERR, log_msg);
+    }
+    std::string log_msg = "Cannot get ethernet connection state: " + std::to_string(error);
+    LoggerE("%s", log_msg.c_str());
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, log_msg);
+  }
+
+  switch (connection_state) {
+    case CONNECTION_ETHERNET_STATE_DEACTIVATED:
+      result_status = "DEACTIVATED";
+      break;
+
+    case CONNECTION_ETHERNET_STATE_DISCONNECTED:
+      result_status = "DISCONNECTED";
+      break;
+
+    case CONNECTION_ETHERNET_STATE_CONNECTED:
+      result_status = "CONNECTED";
+      break;
+
+    default:
+      result_status = "UNKNOWN";
+      break;
+  }
+
+  connection_ethernet_cable_state_e cable_state = CONNECTION_ETHERNET_CABLE_DETACHED;
+  error = connection_get_ethernet_cable_state(connection_handle, &cable_state);
+  if (CONNECTION_ERROR_NONE != error) {
+    std::string log_msg = "Cannot get ethernet cable state: " + std::to_string(error);
+    LoggerE("%s", log_msg.c_str());
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, log_msg);
+  }
+
+  switch (cable_state) {
+    case CONNECTION_ETHERNET_CABLE_DETACHED:
+      result_cable = "DETACHED";
+      break;
+
+    case CONNECTION_ETHERNET_CABLE_ATTACHED:
+      result_cable = "ATTACHED";
+      break;
+
+    default:
+      result_cable = "UNKNOWN";
+      break;
+  }
+
+  char* mac = nullptr;
+  error = connection_get_mac_address(connection_handle, CONNECTION_TYPE_ETHERNET, &mac);
+  if (CONNECTION_ERROR_NONE == error && nullptr != mac) {
+    SLoggerD("MAC address fetched: %s", mac);
+    result_mac_address = mac;
+    free(mac);
+  } else {
+    std::string log_msg = "Failed to get mac address: " + std::to_string(error);
+    LoggerE("%s", log_msg.c_str());
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, log_msg);
+  }
+
+  error = connection_get_type(connection_handle, &connection_type);
+  if (CONNECTION_ERROR_NONE != error) {
+    std::string log_msg = "Cannot get connection type: " + std::to_string(error);
+    LoggerE("%s", log_msg.c_str());
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, log_msg);
+  }
+
+  if (CONNECTION_TYPE_ETHERNET == connection_type) {
+    //gathering profile
+    error = connection_get_current_profile(connection_handle, &profile_handle);
+    if (CONNECTION_ERROR_NONE != error) {
+      std::string log_msg = "Cannot get connection profile: " + std::to_string(error);
+      LoggerE("%s", log_msg.c_str());
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, log_msg);
+    }
+    std::unique_ptr<std::remove_pointer<connection_profile_h>::type,
+        int (*)(connection_profile_h)> profile_handle_ptr(
+        profile_handle, &connection_profile_destroy); // automatically release the memory
+
+    //gathering ips
+    PlatformResult ret = GetIps(profile_handle, &result_ip_address, &result_ipv6_address);
+    if (ret.IsError()) {
+      return ret;
+    }
+
+    //gathering IP configuration mode
+    ret = GetIpConfigType(profile_handle, &ip_config_type);
+    if (ret.IsError()) {
+      return ret;
+    }
+    //gathering subnet mask
+    char* subnet_mask = nullptr;
+    error = connection_profile_get_subnet_mask(profile_handle, CONNECTION_ADDRESS_FAMILY_IPV4, &subnet_mask);
+    if (CONNECTION_ERROR_NONE == error) {
+      result_subnet_mask = subnet_mask;
+      free(subnet_mask);
+    }
+    else {
+      std::string log_msg = "Failed to get subnet mask: " + std::to_string(error);
+      LoggerE("%s", log_msg.c_str());
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, log_msg);
+    }
+
+    //gathering gateway
+    char* gateway = nullptr;
+    error = connection_profile_get_gateway_address(profile_handle, CONNECTION_ADDRESS_FAMILY_IPV4, &gateway);
+    if (CONNECTION_ERROR_NONE == error) {
+      result_gateway = gateway;
+      free(gateway);
+    }
+    else {
+      std::string log_msg = "Failed to get gateway: " + std::to_string(error);
+      LoggerE("%s", log_msg.c_str());
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, log_msg);
+    }
+
+    //gathering dns
+    char* dns = nullptr;
+    error = connection_profile_get_dns_address(profile_handle, kDnsOrder, CONNECTION_ADDRESS_FAMILY_IPV4, &dns);
+    if (CONNECTION_ERROR_NONE == error) {
+      result_dns = dns;
+      free(dns);
+    }
+    else {
+      std::string log_msg = "Failed to get gateway: " + std::to_string(error);
+      LoggerE("%s", log_msg.c_str());
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, log_msg);
+    }
+  } else {
+    LoggerD("Connection type = %d. ETHERNET is disabled", connection_type);
+  }
+
+  ip_mode = NetworkIpModeMap[ip_config_type];
+
+  out->insert(std::make_pair("cable", picojson::value(result_cable)));
+  out->insert(std::make_pair("status", picojson::value(result_status)));
+  out->insert(std::make_pair("ipAddress", picojson::value(result_ip_address)));
+  out->insert(std::make_pair("ipv6Address", picojson::value(result_ipv6_address)));
+  out->insert(std::make_pair("macAddress", picojson::value(result_mac_address)));
+  out->insert(std::make_pair("ipMode", picojson::value(ip_mode)));
+  out->insert(std::make_pair("subnetMask", picojson::value(result_subnet_mask)));
+  out->insert(std::make_pair("gateway", picojson::value(result_gateway)));
+  out->insert(std::make_pair("dns", picojson::value(result_dns)));
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+static PlatformResult FetchBasicSimProperties(TapiHandle *tapi_handle,
+    unsigned short *result_mcc,
+    unsigned short *result_mnc,
+    unsigned short *result_cell_id,
+    unsigned short *result_lac,
+    bool *result_is_roaming,
+    bool *result_is_flight_mode) {
+  LoggerD("Entered");
+  int result_value = 0;
+  int tapi_res = TAPI_API_SUCCESS;
+  tapi_res = tel_get_property_int(tapi_handle, TAPI_PROP_NETWORK_PLMN, &result_value);
+  if (TAPI_API_SUCCESS != tapi_res) {
+    std::string error_msg = "Cannot get mcc value, error: " + std::to_string(tapi_res);
+    LoggerE("%s", error_msg.c_str());
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, error_msg);
+  }
+  *result_mcc = static_cast<unsigned short>(result_value) / kMccDivider;
+  *result_mnc = static_cast<unsigned short>(result_value) % kMccDivider;
+
+  tapi_res = tel_get_property_int(tapi_handle, TAPI_PROP_NETWORK_CELLID, &result_value);
+  if (TAPI_API_SUCCESS != tapi_res) {
+    std::string error_msg = "Cannot get cell_id value, error: " + std::to_string(tapi_res);
+    LoggerE("%s", error_msg.c_str());
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, error_msg);
+  }
+  *result_cell_id = static_cast<unsigned short>(result_value);
+
+  tapi_res = tel_get_property_int(tapi_handle, TAPI_PROP_NETWORK_LAC, &result_value);
+  if (TAPI_API_SUCCESS != tapi_res) {
+    std::string error_msg = "Cannot get lac value, error: " + std::to_string(tapi_res);
+    LoggerE("%s", error_msg.c_str());
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, error_msg);
+  }
+  *result_lac = static_cast<unsigned short>(result_value);
+
+  tapi_res = tel_get_property_int(tapi_handle, TAPI_PROP_NETWORK_ROAMING_STATUS, &result_value);
+  if (TAPI_API_SUCCESS != tapi_res) {
+    std::string error_msg = "Cannot get is_roaming value, error: " + std::to_string(tapi_res);
+    LoggerE("%s", error_msg.c_str());
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, error_msg);
+  }
+  *result_is_roaming = (0 != result_value) ? true : false;
+
+  if (0 != vconf_get_bool(VCONFKEY_TELEPHONY_FLIGHT_MODE, &result_value)) {
+    LoggerE("Cannot get is_flight_mode value");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Cannot get is_flight_mode value");
+  }
+  *result_is_flight_mode = (0 != result_value) ? true : false;
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+static PlatformResult FetchConnection(TapiHandle *tapi_handle, std::string* result_status,
+                            std::string* result_apn, std::string* result_ip_address,
+                            std::string* result_ipv6_address, std::string* result_imei) {
+  LoggerD("Entered");
+  connection_type_e connection_type = CONNECTION_TYPE_DISCONNECTED;
+  connection_profile_h profile_handle = nullptr;
+  connection_h connection_handle = nullptr;
+
+  //connection must be created in every call, in other case error occurs
+  int error = connection_create(&connection_handle);
+  if (CONNECTION_ERROR_NONE != error) {
+    std::string log_msg = "Cannot create connection: " + std::to_string(error);
+    LoggerE("%s", log_msg.c_str());
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, log_msg);
+  }
+  std::unique_ptr<std::remove_pointer<connection_h>::type, int(*)(connection_h)>
+  connection_handle_ptr(connection_handle, &connection_destroy);
+  // automatically release the memory
+
+  error = connection_get_type(connection_handle, &connection_type);
+  if (CONNECTION_ERROR_NONE != error) {
+    LoggerE("Failed to get connection type: %d", error);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Cannot get connection type");
+  }
+
+  char* apn = nullptr;
+  if (CONNECTION_TYPE_CELLULAR == connection_type) {
+    *result_status = kConnectionOn;
+
+    error = connection_get_current_profile(connection_handle,
+                                           &profile_handle);
+    std::unique_ptr
+    <std::remove_pointer<connection_profile_h>::type, int(*)(connection_profile_h)>
+    profile_handle_ptr(profile_handle, &connection_profile_destroy);
+    // automatically release the memory
+    if (CONNECTION_ERROR_NONE != error) {
+      LoggerE("Failed to get profile: %d", error);
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, "Cannot get profile");
+    }
+
+    error = connection_profile_get_cellular_apn(profile_handle, &apn);
+    if (CONNECTION_ERROR_NONE != error) {
+      LoggerE("Failed to get apn name: %d", error);
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, "Cannot get apn name");
+    }
+    *result_apn = apn;
+    free(apn);
+
+    PlatformResult ret = GetIpsFromProfile(profile_handle, result_ip_address,
+                                           result_ipv6_address);
+    if (ret.IsError()) {
+      return ret;
+    }
+  } else {
+    *result_status = kConnectionOff;
+
+    //According to previous implementation in case of error
+    //don't throw exception here
+    error = connection_get_default_cellular_service_profile(
+        connection_handle,
+        CONNECTION_CELLULAR_SERVICE_TYPE_INTERNET,
+        &profile_handle);
+    std::unique_ptr
+    <std::remove_pointer<connection_profile_h>::type, int(*)(connection_profile_h)>
+    profile_handle_ptr(profile_handle, &connection_profile_destroy);
+    // automatically release the memory
+    if (CONNECTION_ERROR_NONE == error) {
+      error = connection_profile_get_cellular_apn(profile_handle, &apn);
+      if (CONNECTION_ERROR_NONE == error) {
+        *result_apn = apn;
+        free(apn);
+      } else {
+        LoggerE("Failed to get default apn name: %d. Failing silently",
+             error);
+      }
+    } else {
+      LoggerE("Failed to get default profile: %d. Failing silently",
+           error);
+    }
+  }
+
+  char* imei = nullptr;
+  imei = tel_get_misc_me_imei_sync(tapi_handle);
+  if (nullptr != imei) {
+    *result_imei = imei;
+    free(imei);
+  } else {
+    LoggerE("Failed to get imei, nullptr pointer. Setting empty value.");
+    *result_imei = "";
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult SysteminfoPropertiesManager::ReportCellularNetwork(picojson::object* out,
+                                                                  unsigned long count) {
+  LoggerD("Entered with index property %d", count);
+  PlatformResult ret = SysteminfoUtils::CheckTelephonySupport();
+  if (ret.IsError()) {
+    return ret;
+  }
+  std::string result_status;
+  std::string result_apn;
+  std::string result_ip_address;
+  std::string result_ipv6_address;
+  unsigned short result_mcc;
+  unsigned short result_mnc;
+  unsigned short result_cell_id;
+  unsigned short result_lac;
+  bool result_is_roaming;
+  bool result_is_flight_mode;
+  std::string result_imei;
+
+  //gathering vconf-based values
+  ret = FetchBasicSimProperties(manager_.GetTapiHandles()[count], &result_mcc,
+                           &result_mnc, &result_cell_id, &result_lac,
+                           &result_is_roaming, &result_is_flight_mode);
+  if (ret.IsError()) {
+    return ret;
+  }
+  //gathering connection informations
+  ret = FetchConnection(manager_.GetTapiHandles()[count],
+                  &result_status, &result_apn, &result_ip_address, &result_ipv6_address,
+                  &result_imei);
+  if (ret.IsError()) {
+    return ret;
+  }
+
+  out->insert(std::make_pair("status", picojson::value(result_status)));
+  out->insert(std::make_pair("apn", picojson::value(result_apn)));
+  out->insert(std::make_pair("ipAddress", picojson::value(result_ip_address)));
+  out->insert(std::make_pair("ipv6Address", picojson::value(result_ipv6_address)));
+  out->insert(std::make_pair("mcc", picojson::value(std::to_string(result_mcc))));
+  out->insert(std::make_pair("mnc", picojson::value(std::to_string(result_mnc))));
+  out->insert(std::make_pair("cellId", picojson::value(std::to_string(result_cell_id))));
+  out->insert(std::make_pair("lac", picojson::value(std::to_string(result_lac))));
+  out->insert(std::make_pair("isRoaming", picojson::value(result_is_roaming)));
+  out->insert(std::make_pair("isFligthMode", picojson::value(result_is_flight_mode)));
+  out->insert(std::make_pair("imei", picojson::value(result_imei)));
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+/// SIM
+PlatformResult SysteminfoPropertiesManager::ReportSim(picojson::object* out, unsigned long count) {
+  LoggerD("Entered");
+  PlatformResult ret = SysteminfoUtils::CheckTelephonySupport();
+  if (ret.IsError()) {
+    return ret;
+  }
+  return sim_manager_.GatherSimInformation(
+      manager_.GetTapiHandles()[count], out);
+}
+
+/// PERIPHERAL
+PlatformResult SysteminfoPropertiesManager::ReportPeripheral(picojson::object* out) {
+  LoggerD("Entered");
+/*  int wireless_display_status = 0;
+  PlatformResult ret = GetVconfInt(VCONFKEY_MIRACAST_WFD_SOURCE_STATUS, &wireless_display_status);
+  if (ret.IsSuccess()) {
+    if (VCONFKEY_MIRACAST_WFD_SOURCE_ON == wireless_display_status) {
+      out.insert(std::make_pair(kVideoOutputString, picojson::value(true)));
+      return PlatformResult(ErrorCode::NO_ERROR);
+    }
+  }*/
+  int hdmi_status = 0;
+  PlatformResult ret = SysteminfoUtils::GetVconfInt(VCONFKEY_SYSMAN_HDMI, &hdmi_status);
+  if (ret.IsSuccess()) {
+    if (VCONFKEY_SYSMAN_HDMI_CONNECTED == hdmi_status) {
+      out->insert(std::make_pair(kVideoOutputString, picojson::value(true)));
+      return PlatformResult(ErrorCode::NO_ERROR);
+    }
+  }
+
+  out->insert(std::make_pair(kVideoOutputString, picojson::value(false)));
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+/// MEMORY
+PlatformResult SysteminfoPropertiesManager::ReportMemory(picojson::object* out) {
+  LoggerD("Entered");
+  std::string state = kMemoryStateNormal;
+  int status = 0;
+  PlatformResult ret = SysteminfoUtils::GetVconfInt(VCONFKEY_SYSMAN_LOW_MEMORY, &status);
+  if (ret.IsSuccess()) {
+    switch (status) {
+      case VCONFKEY_SYSMAN_LOW_MEMORY_SOFT_WARNING:
+      case VCONFKEY_SYSMAN_LOW_MEMORY_HARD_WARNING:
+        state = kMemoryStateWarinig;
+        break;
+      case VCONFKEY_SYSMAN_LOW_MEMORY_NORMAL:
+      default:
+        state = kMemoryStateNormal;
+    }
+  }
+
+  out->insert(std::make_pair("state", picojson::value(state)));
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+static void CreateStorageInfo(const std::string& type, struct statfs& fs, picojson::object* out) {
+  LoggerD("Entered");
+  out->insert(std::make_pair("type", picojson::value(type)));
+  out->insert(std::make_pair("capacity", picojson::value(std::to_string(
+      static_cast<unsigned long long>(fs.f_bsize) *
+      static_cast<unsigned long long>(fs.f_blocks)))));
+  out->insert(std::make_pair("availableCapacity", picojson::value(std::to_string(
+      static_cast<unsigned long long>(fs.f_bsize) *
+      static_cast<unsigned long long>(fs.f_bavail)))));
+  bool isRemovable = (type == kTypeInternal) ? false : true;
+  out->insert(std::make_pair("isRemovable", picojson::value(isRemovable)));
+}
+
+#ifdef TIZEN_TV
+#ifdef TIZEN_TV_PRODUCT
+PlatformResult SysteminfoPropertiesManager::ReportVideoSource(picojson::object* out) {
+
+  ISourceControl* pSourceControl;
+
+  picojson::array arrayConnected;
+  picojson::array arrayDisconnected;
+
+  int ret = TVServiceAPI::CreateSourceControl(PROFILE_TYPE_MAIN, 0, &pSourceControl);
+  if (0 != ret) {
+    LoggerE("Failed to create source control: %d", ret);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to create source control");
+  }
+
+  //Always add TV as connected
+  picojson::object obj;
+  VideoSourceTypes::SourceDesc desc;
+  std::string type_name;
+
+  ret = VideoSourceTypes::SourceDescFromESource(SOURCE_TYPE_TV,desc);
+  ret |= VideoSourceTypes::SourceTypeToName(desc.type,type_name);
+  if (ret)
+  {
+    LoggerE("Unknown source type: %d", ret);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown source type");
+  }
+
+  obj.insert(std::make_pair("type",picojson::value(type_name)));
+  obj.insert(std::make_pair("number",picojson::value( static_cast<double>(desc.number))));
+  arrayConnected.push_back(picojson::value(obj));
+
+  //Foreach starting from 2nd element
+  std::for_each(++VideoSourceTypes::getSourceMapTypeBeginIterator(),VideoSourceTypes::getSourceMapTypeEndIterator(),
+    [pSourceControl,&arrayConnected,&arrayDisconnected](std::pair< ESource, VideoSourceTypes::SourceDesc > _element)-> void
+    {
+      VideoSourceTypes::SourceDesc desc;
+      std::string type_name;
+      picojson::object obj;
+      int ret = VideoSourceTypes::SourceDescFromESource(_element.first,desc);
+      ret |= VideoSourceTypes::SourceTypeToName(desc.type,type_name);
+      if (ret)
+      {
+          LoggerE("Unknown source type: %d", ret);
+      }
+      obj.insert(std::make_pair("type",picojson::value(type_name)));
+      obj.insert(std::make_pair("number",picojson::value((double)desc.number)));
+      bool status = false;
+      if( pSourceControl->CheckExtSourcePlugged( (ESource)_element.first, status ) >0 ) {
+        if(status == true)
+        {
+          arrayConnected.push_back(picojson::value(obj));
+        }
+        else
+        {
+          arrayDisconnected.push_back(picojson::value(obj));
+        }
+    }
+    });
+
+  out->insert(std::make_pair("connected",picojson::value(arrayConnected)));
+  out->insert(std::make_pair("disconnected",picojson::value(arrayDisconnected)));
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+#endif
+
+
+PlatformResult SysteminfoPropertiesManager::ReportStorage(picojson::object* out) {
+  LoggerD("Enter");
+
+  picojson::value result = picojson::value(picojson::array());
+  picojson::array& array = result.get<picojson::array>();
+
+  struct statfs fs;
+
+#ifdef TIZEN_TV_PRODUCT
+  common::FilesystemProviderRef provider(common::FilesystemProviderCAPIUSB::Create());
+#else
+  common::FilesystemProviderRef provider(common::FilesystemProviderDeviced::Create());
+#endif
+
+  auto storages = provider.GetStorages();
+  LoggerD("Storages found %d", storages.size());
+  for( auto storage : storages) {
+    if( storage->state() == common::StorageState::kMounted) {
+      if( statfs(storage->path().c_str(), &fs ) < 0 ) {
+        LoggerE("Storage unit %s not detected", storage->name().c_str());
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "Storage unit not detected");
+      }
+      array.push_back(picojson::value(picojson::object()));
+      picojson::object& internal_obj = array.back().get<picojson::object>();
+
+      switch(storage->type()) {
+        case common::StorageType::kInternal: {
+          CreateStorageInfo(kTypeInternal, fs, &internal_obj);
+          break;
+        }
+        case common::StorageType::kExternal: {
+          CreateStorageInfo(kTypeUsbDevice, fs, &internal_obj);
+          break;
+        }
+      }
+      manager_.SetAvailableCapacityInternal(fs.f_bavail);
+    }
+  }
+
+  out->insert(std::make_pair("storages", picojson::value(result)));
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+#else
+
+PlatformResult SysteminfoPropertiesManager::ReportStorage(picojson::object* out) {
+  LoggerD("Enter");
+  int sdcardState = 0;
+  struct statfs fs;
+
+  picojson::value result = picojson::value(picojson::array());
+  picojson::array& array = result.get<picojson::array>();
+  array.push_back(picojson::value(picojson::object()));
+  picojson::object& internal_obj = array.back().get<picojson::object>();
+
+  if (statfs(kStorageInternalPath, &fs) < 0) {
+    LoggerE("There are no storage units detected");
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "There are no storage units detected");
+  }
+  CreateStorageInfo(kTypeInternal, fs, &internal_obj);
+  manager_.SetAvailableCapacityInternal(fs.f_bavail);
+
+  if (0 == vconf_get_int(VCONFKEY_SYSMAN_MMC_STATUS, &sdcardState)) {
+    if (VCONFKEY_SYSMAN_MMC_MOUNTED == sdcardState){
+      if (statfs(kStorageSdcardPath, &fs) < 0) {
+        LoggerE("MMC mounted, but not accessible");
+        return PlatformResult(ErrorCode::UNKNOWN_ERR, "MMC mounted, but not accessible");
+      }
+      array.push_back(picojson::value(picojson::object()));
+      picojson::object& external_obj = array.back().get<picojson::object>();
+      CreateStorageInfo(kTypeMmc, fs, &external_obj);
+      manager_.SetAvailableCapacityMmc(fs.f_bavail);
+    }
+  }
+
+  out->insert(std::make_pair("storages", picojson::value(result)));
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+#endif
+
+PlatformResult SysteminfoPropertiesManager::ReportCameraFlash(picojson::object* out,
+                                                              unsigned long index) {
+  LoggerD("Entered");
+  if (index < manager_.GetCameraTypesCount()) {
+    std::string camera = manager_.GetCameraTypes(index);
+    out->insert(std::make_pair("camera", picojson::value(camera)));
+  } else {
+    return PlatformResult(
+        ErrorCode::NOT_SUPPORTED_ERR,
+        "Camera is not supported on this device");
+  }
+
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+
+} // namespace systeminfo
+} // namespace webapi
diff --git a/webWidgetTCT_device/src/systeminfo/systeminfo_properties_manager.h b/webWidgetTCT_device/src/systeminfo/systeminfo_properties_manager.h
new file mode 100755 (executable)
index 0000000..6b6869a
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2015 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 WEBAPI_PLUGINS_SYSTEMINFO_SYSTEMINFO_PROPERTIES_MANAGER_H__
+#define WEBAPI_PLUGINS_SYSTEMINFO_SYSTEMINFO_PROPERTIES_MANAGER_H__
+
+#include <string>
+#include "common/picojson.h"
+#include "common/platform_result.h"
+#include "systeminfo/systeminfo_sim_details_manager.h"
+
+namespace extension {
+namespace systeminfo {
+
+class SysteminfoManager;
+
+class SysteminfoPropertiesManager {
+ public:
+  SysteminfoPropertiesManager(SysteminfoManager& manager);
+  ~SysteminfoPropertiesManager();
+
+  common::PlatformResult GetPropertyValue(
+      const std::string& prop, bool is_array_type, picojson::value* res);
+
+ private:
+  common::PlatformResult ReportProperty(const std::string& property, int index,
+                                               picojson::object* res_obj);
+  common::PlatformResult ReportBattery(picojson::object* out);
+  common::PlatformResult ReportCpu(picojson::object* out);
+  common::PlatformResult ReportDisplay(picojson::object* out);
+  common::PlatformResult ReportDeviceOrientation(picojson::object* out);
+  common::PlatformResult ReportBuild(picojson::object* out);
+  common::PlatformResult ReportLocale(picojson::object* out);
+  common::PlatformResult ReportNetwork(picojson::object* out, unsigned long count);
+  common::PlatformResult ReportWifiNetwork(picojson::object* out);
+  common::PlatformResult ReportEthernetNetwork(picojson::object* out);
+  common::PlatformResult ReportCellularNetwork(picojson::object* out, unsigned long count);
+  common::PlatformResult ReportSim(picojson::object* out, unsigned long count);
+  common::PlatformResult ReportPeripheral(picojson::object* out);
+  common::PlatformResult ReportCameraFlash(picojson::object* out, unsigned long count);
+  common::PlatformResult ReportMemory(picojson::object* out);
+  common::PlatformResult ReportStorage(picojson::object* out);
+#ifdef TIZEN_TV_PRODUCT
+  common::PlatformResult ReportVideoSource(picojson::object* out);
+#endif
+
+  common::PlatformResult FetchIsAutoRotation(bool* result);
+  common::PlatformResult FetchStatus(std::string* result);
+
+  SysteminfoManager& manager_;
+  SimDetailsManager sim_manager_;
+};
+
+} // namespace systeminfo
+} // namespace webapi
+
+#endif // WEBAPI_PLUGINS_SYSTEMINFO_SYSTEMINFO_PROPERTIES_MANAGER_H__
diff --git a/webWidgetTCT_device/src/systeminfo/systeminfo_sim_details_manager.cc b/webWidgetTCT_device/src/systeminfo/systeminfo_sim_details_manager.cc
new file mode 100755 (executable)
index 0000000..5493164
--- /dev/null
@@ -0,0 +1,293 @@
+/*
+ * Copyright (c) 2015 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 "systeminfo/systeminfo_sim_details_manager.h"
+
+#include "common/logger.h"
+
+namespace extension {
+namespace systeminfo {
+
+namespace {
+//Sim
+const char* kSimStatusAbsent = "ABSENT";
+const char* kSimStatusInitializing = "INITIALIZING";
+const char* kSimStatusReady = "READY";
+const char* kSimStatusPinRequired = "PIN_REQUIRED";
+const char* kSimStatusPukRequired = "PUK_REQUIRED";
+const char* kSimStatusSimLocked = "SIM_LOCKED";
+const char* kSimStatusNetworkLocked = "NETWORK_LOCKED";
+const char* kSimStatusUnknown = "UNKNOWN";
+
+void SimCphsValueCallback(TapiHandle */*handle*/, int result, void *data, void *user_data) {
+  LoggerD("Entered");
+  SimDetailsManager* sim_mgr = static_cast<SimDetailsManager*>(user_data);
+  TelSimAccessResult_t access_rt = static_cast<TelSimAccessResult_t>(result);
+  TelSimCphsNetName_t *cphs_info = static_cast<TelSimCphsNetName_t*>(data);
+
+  std::string result_operator;
+  if (TAPI_SIM_ACCESS_SUCCESS == access_rt) {
+    std::stringstream s;
+    s << cphs_info->full_name;
+    if (s.str().empty()) {
+      s << cphs_info->short_name;
+    }
+    result_operator = s.str();
+  } else {
+    LoggerW("Failed to retrieve cphs_info: %d", access_rt);
+  }
+  sim_mgr->set_operator_name(result_operator);
+  sim_mgr->TryReturn();
+}
+
+void SimMsisdnValueCallback(TapiHandle */*handle*/, int result, void *data, void *user_data) {
+  LoggerD("Entered");
+  SimDetailsManager* sim_mgr = static_cast<SimDetailsManager*>(user_data);
+  TelSimAccessResult_t access_rt = static_cast<TelSimAccessResult_t>(result);
+  TelSimMsisdnList_t *msisdn_info = static_cast<TelSimMsisdnList_t*>(data);
+
+  std::string result_msisdn;
+  if (TAPI_SIM_ACCESS_SUCCESS == access_rt) {
+    if (msisdn_info->count > 0) {
+      if (strlen(msisdn_info->list[0].num) > 0) {
+        result_msisdn = msisdn_info->list[0].num;
+      } else {
+        LoggerW("MSISDN number empty");
+      }
+    } else {
+      LoggerW("msisdn_info list empty");
+    }
+  } else {
+    LoggerW("Failed to retrieve msisdn_: %d", access_rt);
+  }
+
+  sim_mgr->set_msisdn(result_msisdn);
+  sim_mgr->TryReturn();
+}
+
+void SimSpnValueCallback(TapiHandle */*handle*/, int result, void *data, void *user_data) {
+  LoggerD("Entered");
+  SimDetailsManager* sim_mgr = static_cast<SimDetailsManager*>(user_data);
+  TelSimAccessResult_t access_rt = static_cast<TelSimAccessResult_t>(result);
+  TelSimSpn_t *spn_info = static_cast<TelSimSpn_t*>(data);
+
+  std::string result_spn;
+  if (TAPI_SIM_ACCESS_SUCCESS == access_rt) {
+    result_spn = (char *)spn_info->spn;
+  } else {
+    LoggerW("Failed to retrieve spn_: %d", access_rt);
+  }
+
+  sim_mgr->set_spn(result_spn);
+  sim_mgr->TryReturn();
+}
+} //namespace
+
+using common::PlatformResult;
+using common::ErrorCode;
+
+SimDetailsManager::SimDetailsManager():
+            mcc_(0),
+            mnc_(0),
+            operator_name_(""),
+            msin_(""),
+            state_(""),
+            msisdn_(""),
+            iccid_(""),
+            spn_(""),
+            sim_result_obj_(nullptr),
+            to_process_(0)
+{
+}
+
+PlatformResult SimDetailsManager::GatherSimInformation(TapiHandle* handle, picojson::object* out) {
+  LoggerD("Entered");
+  std::lock_guard<std::mutex> first_lock_sim(sim_info_mutex_);
+  ResetSimHolder(out);
+
+  FetchSimState(handle);
+  if (kSimStatusReady == state_) {
+    PlatformResult ret = FetchSimSyncProps(handle);
+    if (ret.IsError()) {
+      return ret;
+    }
+    {
+      //All props should be fetched synchronously, but sync function does not work
+      std::lock_guard<std::mutex> lock_to_process(sim_to_process_mutex_);
+      //would be deleted on } ending bracket
+      int result = tel_get_sim_cphs_netname(handle, SimCphsValueCallback, this);
+      if (TAPI_API_SUCCESS == result) {
+        ++to_process_;
+      } else {
+        LoggerE("Failed getting cphs netname: %d", result);
+      }
+
+      result = tel_get_sim_msisdn(handle, SimMsisdnValueCallback, this);
+      if (TAPI_API_SUCCESS == result) {
+        ++to_process_;
+      } else {
+        LoggerE("Failed getting msisdn: %d", result);
+      }
+
+      result = tel_get_sim_spn(handle, SimSpnValueCallback, this);
+      if (TAPI_API_SUCCESS == result) {
+        ++to_process_;
+      } else {
+        LoggerE("Failed getting spn: %d", result);
+      }
+    }
+    //prevent returning not filled result
+    std::lock_guard<std::mutex> lock_sim(sim_info_mutex_);
+    //result will come from callbacks
+    return PlatformResult(ErrorCode::NO_ERROR);
+  }
+  //if sim state is not READY return default values and don't wait for callbacks
+  TryReturn();
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+void SimDetailsManager::FetchSimState(TapiHandle *tapi_handle) {
+  LoggerD("Entered");
+  if (nullptr == tapi_handle) {
+    LoggerE("Tapi handle is null");
+    state_ = kSimStatusUnknown;
+  } else {
+    int card_changed = 0;
+    TelSimCardStatus_t sim_card_state;
+    int error = tel_get_sim_init_info(tapi_handle, &sim_card_state, &card_changed);
+    if (TAPI_API_SUCCESS == error) {
+      switch (sim_card_state) {
+        case TAPI_SIM_STATUS_CARD_NOT_PRESENT:
+        case TAPI_SIM_STATUS_CARD_REMOVED:
+          state_ = kSimStatusAbsent;
+          break;
+        case TAPI_SIM_STATUS_SIM_INITIALIZING:
+          state_ = kSimStatusInitializing;
+          break;
+        case TAPI_SIM_STATUS_SIM_INIT_COMPLETED:
+          state_ = kSimStatusReady;
+          break;
+        case TAPI_SIM_STATUS_SIM_PIN_REQUIRED:
+          state_ = kSimStatusPinRequired;
+          break;
+        case TAPI_SIM_STATUS_SIM_PUK_REQUIRED:
+          state_ = kSimStatusPukRequired;
+          break;
+        case TAPI_SIM_STATUS_SIM_LOCK_REQUIRED:
+        case TAPI_SIM_STATUS_CARD_BLOCKED:
+          state_ = kSimStatusSimLocked;
+          break;
+        case TAPI_SIM_STATUS_SIM_NCK_REQUIRED:
+        case TAPI_SIM_STATUS_SIM_NSCK_REQUIRED:
+          state_ = kSimStatusNetworkLocked;
+          break;
+        default:
+          state_ = kSimStatusUnknown;
+          break;
+      }
+    }
+  }
+}
+
+PlatformResult SimDetailsManager::FetchSimSyncProps(TapiHandle *tapi_handle) {
+  LoggerD("Entered");
+  TelSimImsiInfo_t imsi;
+  int error = tel_get_sim_imsi(tapi_handle, &imsi);
+  if (TAPI_API_SUCCESS == error) {
+    LoggerD("mcc: %s, mnc: %s, msin: %s", imsi.szMcc, imsi.szMnc, imsi.szMsin);
+    mcc_ = std::stoul(imsi.szMcc);
+    mnc_ = std::stoul(imsi.szMnc);
+    msin_ = imsi.szMsin;
+  }
+  else {
+    LoggerE("Failed to get sim imsi: %d", error);
+    return PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get sim imsi");
+  }
+
+  //TODO add code for iccid value fetching, when proper API would be ready
+  iccid_ = "";
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+void SimDetailsManager::ResetSimHolder(picojson::object* out) {
+  LoggerD("Entered");
+  sim_result_obj_ = out;
+  to_process_ = 0;
+  mcc_ = 0;
+  mnc_ = 0;
+  operator_name_ = "";
+  msin_ = "";
+  state_ = "";
+  msisdn_ = "";
+  iccid_ = "";
+  spn_ = "";
+}
+
+void SimDetailsManager::ReturnSimToJS() {
+  LoggerD("Entered");
+  if (nullptr != sim_result_obj_) {
+    sim_result_obj_->insert(std::make_pair("state", picojson::value(state_)));
+    sim_result_obj_->insert(std::make_pair("operatorName", picojson::value(operator_name_)));
+    sim_result_obj_->insert(std::make_pair("msisdn", picojson::value(msisdn_)));
+    sim_result_obj_->insert(std::make_pair("iccid", picojson::value(iccid_)));
+    sim_result_obj_->insert(std::make_pair("mcc", picojson::value(std::to_string(mcc_))));
+    sim_result_obj_->insert(std::make_pair("mnc", picojson::value(std::to_string(mnc_))));
+    sim_result_obj_->insert(std::make_pair("msin", picojson::value(msin_)));
+    sim_result_obj_->insert(std::make_pair("spn", picojson::value(spn_)));
+    //everything returned, clear pointer
+    sim_result_obj_ = nullptr;
+  } else {
+    LoggerE("No sim returned JSON object pointer is null");
+  }
+}
+
+void SimDetailsManager::TryReturn() {
+  LoggerD("Entered");
+  if (0 == to_process_){
+    LoggerD("Returning property to JS");
+    ReturnSimToJS();
+    sim_info_mutex_.unlock();
+  } else {
+    LoggerD("Not ready yet - waiting");
+  }
+}
+
+void SimDetailsManager::set_operator_name(const std::string& name) {
+  LoggerD("Entered");
+  std::lock_guard<std::mutex> lock(sim_to_process_mutex_);
+  operator_name_ = name;
+  --to_process_;
+  LoggerD("Operator name: %s", operator_name_.c_str());
+};
+
+void SimDetailsManager::set_msisdn(const std::string& msisdn) {
+  LoggerD("Entered");
+  std::lock_guard<std::mutex> lock(sim_to_process_mutex_);
+  this->msisdn_ = msisdn;
+  --to_process_;
+  LoggerD("MSISDN number: %s", this->msisdn_.c_str());
+};
+
+void SimDetailsManager::set_spn(const std::string& spn) {
+  LoggerD("Entered");
+  std::lock_guard<std::mutex> lock(sim_to_process_mutex_);
+  this->spn_ = spn;
+  --to_process_;
+  LoggerD("SPN value: %s", this->spn_.c_str());
+};
+
+} // namespace systeminfo
+} // namespace webapi
diff --git a/webWidgetTCT_device/src/systeminfo/systeminfo_sim_details_manager.h b/webWidgetTCT_device/src/systeminfo/systeminfo_sim_details_manager.h
new file mode 100755 (executable)
index 0000000..38def8f
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2015 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 WEBAPI_PLUGINS_SYSTEMINFO_SYSTEMINFO_SIM_DETAILS_MANAGER_H__
+#define WEBAPI_PLUGINS_SYSTEMINFO_SYSTEMINFO_SIM_DETAILS_MANAGER_H__
+
+#include <string>
+#include <mutex>
+
+#include <ITapiModem.h>
+#include <ITapiSim.h>
+
+#include "common/picojson.h"
+#include "common/platform_result.h"
+
+namespace extension {
+namespace systeminfo {
+
+class SimDetailsManager {
+ public:
+  SimDetailsManager();
+
+  common::PlatformResult GatherSimInformation(TapiHandle* handle, picojson::object* out);
+  long GetSimCount(TapiHandle **tapi_handle);
+  void TryReturn();
+
+  void set_operator_name(const std::string& name);
+  void set_msisdn(const std::string& msisdn);
+  void set_spn(const std::string& spn);
+
+ private:
+  void ResetSimHolder(picojson::object* out);
+  void FetchSimState(TapiHandle *tapi_handle);
+  common::PlatformResult FetchSimSyncProps(TapiHandle *tapi_handle);
+  void ReturnSimToJS();
+
+  unsigned short mcc_;
+  unsigned short mnc_;
+  std::string operator_name_;
+  std::string msin_;
+  std::string state_;
+  std::string msisdn_;
+  std::string iccid_;
+  std::string spn_;
+
+  picojson::object* sim_result_obj_;
+  unsigned short to_process_;
+  std::mutex sim_to_process_mutex_;
+  std::mutex sim_info_mutex_;
+};
+
+} // namespace systeminfo
+} // namespace webapi
+
+#endif // WEBAPI_PLUGINS_SYSTEMINFO_SYSTEMINFO_SIM_DETAILS_MANAGER_H__
diff --git a/webWidgetTCT_device/src/systemsetting/systemsetting.gyp b/webWidgetTCT_device/src/systemsetting/systemsetting.gyp
new file mode 100755 (executable)
index 0000000..815fed4
--- /dev/null
@@ -0,0 +1,31 @@
+{
+  'includes':[
+    '../common/common.gypi',
+  ],
+  'targets': [
+    {
+      'target_name': 'tizen_systemsetting',
+      'type': 'loadable_module',
+      'dependencies': [
+        '../common/common.gyp:tizen_common',
+      ],
+      'sources': [
+        'systemsetting_api.js',
+        'systemsetting_extension.cc',
+        'systemsetting_extension.h',
+        'systemsetting_instance.cc',
+        'systemsetting_instance.h',
+      ],
+      'conditions': [
+        ['tizen == 1', {
+          'variables': {
+            'packages': [
+              'capi-system-system-settings',
+              'vconf',
+            ]
+          },
+        }],
+      ],
+    },
+  ],
+}
diff --git a/webWidgetTCT_device/src/systemsetting/systemsetting_api.js b/webWidgetTCT_device/src/systemsetting/systemsetting_api.js
new file mode 100755 (executable)
index 0000000..464a33e
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+
+var validator_ = xwalk.utils.validator;
+var privilege_ = xwalk.utils.privilege;
+var type_ = xwalk.utils.type;
+var types_ = validator_.Types;
+var native_ = new xwalk.utils.NativeManager(extension);
+
+function throwException_(err) {
+    throw new WebAPIException(err.code, err.name, err.message);
+}
+
+function callSync_(msg) {
+    var ret = extension.internal.sendSyncMessage(JSON.stringify(msg));
+    var obj = JSON.parse(ret);
+    if (obj.error)
+        throwException_(obj.error);
+    return obj.result;
+}
+
+var SystemSettingTypeValues = ['HOME_SCREEN', 'LOCK_SCREEN', 'INCOMING_CALL', 'NOTIFICATION_EMAIL'];
+
+function SystemSettingManager() {
+}
+
+SystemSettingManager.prototype.getProperty = function() {
+    var args = validator_.validateArgs(arguments, [
+        { name: 'type', type: types_.ENUM, values: SystemSettingTypeValues },
+        { name: 'successCallback', type: types_.FUNCTION },
+        { name: 'errorCallback', type: types_.FUNCTION, optional: true, nullable: true }
+    ]);
+
+    var callback = function(result) {
+        if (native_.isFailure(result)) {
+            native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+        }
+        else {
+            args.successCallback(result.result.value);
+        }
+    }
+
+    var callArgs = {
+        type: args.type
+    };
+
+    native_.call('SystemSettingManager_getProperty', callArgs, callback);
+};
+
+SystemSettingManager.prototype.setProperty = function() {
+    xwalk.utils.checkPrivilegeAccess(privilege_.SETTING);
+
+    var args = validator_.validateArgs(arguments, [
+        { name: 'type', type: types_.ENUM, values: SystemSettingTypeValues },
+        { name: 'value', type: types_.STRING },
+        { name: 'successCallback', type: types_.FUNCTION },
+        { name: 'errorCallback', type: types_.FUNCTION, optional: true, nullable: true }
+    ]);
+
+    var callback = function(result) {
+        if (native_.isFailure(result)) {
+            native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+        }
+        else {
+            args.successCallback();
+        }
+    }
+
+    var callArgs = {
+        type: args.type,
+        value: args.value
+    };
+
+    native_.call('SystemSettingManager_setProperty', callArgs, callback);
+};
+
+// Exports
+exports = new SystemSettingManager();
+
diff --git a/webWidgetTCT_device/src/systemsetting/systemsetting_extension.cc b/webWidgetTCT_device/src/systemsetting/systemsetting_extension.cc
new file mode 100755 (executable)
index 0000000..d6c9008
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2015 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 "systemsetting/systemsetting_extension.h"
+
+#include "systemsetting/systemsetting_instance.h"
+
+// This will be generated from systemsetting_api.js
+extern const char kSource_systemsetting_api[];
+
+common::Extension* CreateExtension() {
+  return new SystemSettingExtension;
+}
+
+SystemSettingExtension::SystemSettingExtension() {
+  SetExtensionName("tizen.systemsetting");
+  SetJavaScriptAPI(kSource_systemsetting_api);
+}
+
+SystemSettingExtension::~SystemSettingExtension() {}
+
+common::Instance* SystemSettingExtension::CreateInstance() {
+  return new extension::systemsetting::SystemSettingInstance;
+}
diff --git a/webWidgetTCT_device/src/systemsetting/systemsetting_extension.h b/webWidgetTCT_device/src/systemsetting/systemsetting_extension.h
new file mode 100755 (executable)
index 0000000..a193b78
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015 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 SYSTEMSETTING_SYSTEMSETTING_EXTENSION_H_
+#define SYSTEMSETTING_SYSTEMSETTING_EXTENSION_H_
+
+#include "common/extension.h"
+
+class SystemSettingExtension : public common::Extension {
+ public:
+  SystemSettingExtension();
+  virtual ~SystemSettingExtension();
+
+ private:
+  virtual common::Instance* CreateInstance();
+};
+
+#endif // SYSTEMSETTING_SYSTEMSETTING_EXTENSION_H_
+
diff --git a/webWidgetTCT_device/src/systemsetting/systemsetting_instance.cc b/webWidgetTCT_device/src/systemsetting/systemsetting_instance.cc
new file mode 100755 (executable)
index 0000000..a3a9542
--- /dev/null
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) 2015 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 "systemsetting/systemsetting_instance.h"
+
+#include <memory>
+
+#include "common/logger.h"
+#include "common/picojson.h"
+#include "common/task-queue.h"
+#include "common/filesystem/filesystem_provider_storage.h"
+
+#include <system_settings.h>
+
+
+namespace extension {
+namespace systemsetting {
+
+namespace {
+const std::string SETTING_HOME_SCREEN = "HOME_SCREEN";
+const std::string SETTING_LOCK_SCREEN = "LOCK_SCREEN";
+const std::string SETTING_INCOMING_CALL = "INCOMING_CALL";
+const std::string SETTING_NOTIFICATION_EMAIL = "NOTIFICATION_EMAIL";
+}
+
+using namespace common;
+using namespace extension::systemsetting;
+
+SystemSettingInstance::SystemSettingInstance():
+    fs_provider_(common::FilesystemProviderStorage::Create())
+{
+  LoggerD("Enter");
+  using std::placeholders::_1;
+  using std::placeholders::_2;
+
+#define REGISTER(c,x) \
+    RegisterSyncHandler(c, std::bind(&SystemSettingInstance::x, this, _1, _2));
+
+  REGISTER("SystemSettingManager_getProperty", getProperty);
+  REGISTER("SystemSettingManager_setProperty", setProperty);
+
+#undef REGISTER
+}
+
+SystemSettingInstance::~SystemSettingInstance()
+{
+  LoggerD("Enter");
+}
+
+void SystemSettingInstance::getProperty(const picojson::value& args, picojson::object& out)
+{
+  LoggerD("Enter");
+  const double callback_id = args.get("callbackId").get<double>();
+
+  const std::string& type = args.get("type").get<std::string>();
+  LoggerD("Getting property type: %s ", type.c_str());
+
+  auto get = [this, type](const std::shared_ptr<picojson::value>& response) -> void {
+    LoggerD("Getting platform value");
+    picojson::value result = picojson::value(picojson::object());
+    PlatformResult status = getPlatformPropertyValue(type, &result);
+    if(status.IsSuccess()) {
+      ReportSuccess(result, response->get<picojson::object>());
+    } else {
+      LoggerE("Failed: getPlatformPropertyValue()");
+      ReportError(status, &response->get<picojson::object>());
+    }
+  };
+
+  auto get_response = [this, callback_id](const std::shared_ptr<picojson::value>& response) -> void {
+    LoggerD("Getting response");
+    picojson::object& obj = response->get<picojson::object>();
+    obj.insert(std::make_pair("callbackId", picojson::value(callback_id)));
+    Instance::PostMessage(this, response->serialize().c_str());
+  };
+
+  auto data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+
+  TaskQueue::GetInstance().Queue<picojson::value>(get, get_response, data);
+}
+
+PlatformResult SystemSettingInstance::getPlatformPropertyValue(
+    const std::string& settingType,
+    picojson::value* out) {
+  LoggerD("Enter");
+  picojson::object& result_obj = out->get<picojson::object>();
+
+  int ret = SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER;
+  char *value = NULL;
+  if (settingType == SETTING_HOME_SCREEN) {
+    ret = system_settings_get_value_string(
+        SYSTEM_SETTINGS_KEY_WALLPAPER_HOME_SCREEN, &value);
+  }
+  else if (settingType == SETTING_LOCK_SCREEN) {
+    ret = system_settings_get_value_string(
+        SYSTEM_SETTINGS_KEY_WALLPAPER_LOCK_SCREEN, &value);
+  }
+  else if (settingType == SETTING_INCOMING_CALL) {
+    ret = system_settings_get_value_string(
+        SYSTEM_SETTINGS_KEY_INCOMING_CALL_RINGTONE, &value);
+  }
+  else if (settingType == SETTING_NOTIFICATION_EMAIL) {
+    ret = system_settings_get_value_string(
+        SYSTEM_SETTINGS_KEY_EMAIL_ALERT_RINGTONE, &value);
+  }
+  // other values (not specified in the documentation) are handled in JS
+
+  switch (ret) {
+    case SYSTEM_SETTINGS_ERROR_NONE:
+      LoggerD("ret == SYSTEM_SETTINGS_ERROR_NONE");
+      result_obj.insert(std::make_pair("value", picojson::value(value ? value : "")));
+      free(value);
+      return PlatformResult(ErrorCode::NO_ERROR);
+    case SYSTEM_SETTINGS_ERROR_NOT_SUPPORTED:
+      LoggerD("ret == SYSTEM_SETTINGS_ERROR_NOT_SUPPORTED");
+      return PlatformResult(ErrorCode::NOT_SUPPORTED_ERR,
+                            "This property is not supported.");
+    default:
+      LoggerD("Other error");
+      return PlatformResult(ErrorCode::UNKNOWN_ERR);
+  }
+}
+
+void SystemSettingInstance::setProperty(const picojson::value& args, picojson::object& out)
+{
+  LoggerD("Enter");
+
+  const double callback_id = args.get("callbackId").get<double>();
+
+  const std::string& type = args.get("type").get<std::string>();
+  LoggerD("Type to set: %s ", type.c_str());
+
+  const std::string& value = args.get("value").get<std::string>();
+  LoggerD("Value to set: %s ", value.c_str());
+
+  auto get = [this, type, value, callback_id](const std::shared_ptr<picojson::value>& response) -> void {
+    LoggerD("Setting platform value");
+    std::string real_path = fs_provider_.GetRealPath(value);
+    PlatformResult status = setPlatformPropertyValue(type, real_path);
+    picojson::object& obj = response->get<picojson::object>();
+    if (status.IsSuccess()) {
+      ReportSuccess(obj);
+    } else {
+      LoggerE("Failed: setPlatformPropertyValue()");
+      ReportError(status, &obj);
+    }
+    obj.insert(std::make_pair("callbackId", picojson::value(callback_id)));
+    Instance::PostMessage(this, response->serialize().c_str());
+  };
+
+  auto data = std::shared_ptr<picojson::value>(new picojson::value(picojson::object()));
+
+  TaskQueue::GetInstance().Async<picojson::value>(get, data);
+}
+
+PlatformResult SystemSettingInstance::setPlatformPropertyValue(
+    const std::string& settingType,
+    const std::string& settingValue) {
+  LoggerD("Enter");
+  int ret = SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER;
+  if (settingType == SETTING_HOME_SCREEN) {
+    ret = system_settings_set_value_string(
+        SYSTEM_SETTINGS_KEY_WALLPAPER_HOME_SCREEN, settingValue.c_str());
+  }
+  else if (settingType == SETTING_LOCK_SCREEN) {
+    ret = system_settings_set_value_string(
+        SYSTEM_SETTINGS_KEY_WALLPAPER_LOCK_SCREEN, settingValue.c_str());
+  }
+  else if (settingType == SETTING_INCOMING_CALL) {
+    ret = system_settings_set_value_string(
+        SYSTEM_SETTINGS_KEY_INCOMING_CALL_RINGTONE, settingValue.c_str());
+  }
+  else if (settingType == SETTING_NOTIFICATION_EMAIL) {
+    ret = system_settings_set_value_string(
+        SYSTEM_SETTINGS_KEY_EMAIL_ALERT_RINGTONE, settingValue.c_str());
+  }
+  // other values (not specified in the documentation) are handled in JS
+
+  switch (ret) {
+    case SYSTEM_SETTINGS_ERROR_NONE:
+      LoggerD("ret == SYSTEM_SETTINGS_ERROR_NONE");
+      return PlatformResult(ErrorCode::NO_ERROR);
+    case SYSTEM_SETTINGS_ERROR_NOT_SUPPORTED:
+      LoggerD("ret == SYSTEM_SETTINGS_ERROR_NOT_SUPPORTED");
+      return PlatformResult(ErrorCode::NOT_SUPPORTED_ERR,
+                            "This property is not supported.");
+    case SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER:
+      LoggerD("ret == SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER");
+      return PlatformResult(ErrorCode::INVALID_VALUES_ERR,
+                            "Invalid parameter passed.");
+    default:
+      LoggerD("Other error");
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+                            "unknown error");
+  }
+}
+
+} // namespace systemsetting
+} // namespace extension
+
diff --git a/webWidgetTCT_device/src/systemsetting/systemsetting_instance.h b/webWidgetTCT_device/src/systemsetting/systemsetting_instance.h
new file mode 100755 (executable)
index 0000000..cbb84a1
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2015 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 SYSTEMSETTING_SYSTEMSETTING_INSTANCE_H_
+#define SYSTEMSETTING_SYSTEMSETTING_INSTANCE_H_
+
+#include "common/extension.h"
+#include "common/platform_result.h"
+
+namespace extension {
+namespace systemsetting {
+
+class SystemSettingInstance : public common::ParsedInstance
+{
+ public:
+  SystemSettingInstance();
+  virtual ~SystemSettingInstance();
+
+ private:
+  void getProperty(const picojson::value& args, picojson::object& out);
+  common::PlatformResult getPlatformPropertyValue(
+      const std::string& valueType,
+      picojson::value* out);
+
+  void setProperty(const picojson::value& args, picojson::object& out);
+  common::PlatformResult setPlatformPropertyValue(
+      const std::string& settingType,
+      const std::string& settingValue);
+
+  common::FilesystemProviderStorage& fs_provider_;
+};
+
+} // namespace systemsetting
+} // namespace extension
+
+#endif // SYSTEMSETTING_SYSTEMSETTING_INSTANCE_H_
diff --git a/webWidgetTCT_device/src/time/time.gyp b/webWidgetTCT_device/src/time/time.gyp
new file mode 100755 (executable)
index 0000000..a7a2d26
--- /dev/null
@@ -0,0 +1,31 @@
+{
+  'includes':[
+    '../common/common.gypi',
+  ],
+  'targets': [
+    {
+      'target_name': 'tizen_time',
+      'type': 'loadable_module',
+      'dependencies': [
+        '../common/common.gyp:tizen_common',
+      ],
+      'variables': {
+        'packages': [
+          'icu-i18n',
+        ],
+      },
+      'sources': [
+        'time_api.js',
+        'time_extension.cc',
+        'time_extension.h',
+        'time_instance.cc',
+        'time_instance.h',
+      ],
+      'conditions': [
+        [ 'tizen == 1', {
+            'variables': { 'packages': ['vconf'] },
+        }],
+      ],
+    },
+  ],
+}
diff --git a/webWidgetTCT_device/src/time/time_api.js b/webWidgetTCT_device/src/time/time_api.js
new file mode 100755 (executable)
index 0000000..d827480
--- /dev/null
@@ -0,0 +1,823 @@
+// Copyright (c) 2013 Intel Corporation. All rights reserved.
+// Copyright (c) 2015 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var _minuteInMilliseconds = 60 * 1000;
+var _hourInMilliseconds = _minuteInMilliseconds * 60;
+
+var utils_ = xwalk.utils;
+var validator_ = utils_.validator;
+var types_ = validator_.Types;
+var native_ = new utils_.NativeManager(extension);
+
+exports.getCurrentDateTime = function() {
+  return new tizen.TZDate();
+};
+
+exports.getLocalTimezone = function() {
+  var result = native_.callSync('Time_getLocalTimeZone');
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+
+  return native_.getResultObject(result);
+};
+
+var _availableTimezonesCache = [];
+
+exports.getAvailableTimezones = function() {
+  if (_availableTimezonesCache.length)
+    return _availableTimezonesCache;
+
+  var result = native_.callSync('Time_getAvailableTimeZones');
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+
+  _availableTimezonesCache = native_.getResultObject(result);
+  return _availableTimezonesCache;
+};
+
+exports.getDateFormat = function() {
+  var args = validator_.validateArgs(arguments, [{
+    name: 'shortformat',
+    type: types_.BOOLEAN,
+    optional: true,
+    nullable: true
+  }]);
+
+  if (!args.has.shortformat) {
+    args.shortformat = false;
+  }
+
+  var result = native_.callSync('Time_getDateFormat', {shortformat: args.shortformat});
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+  return native_.getResultObject(result);
+};
+
+exports.getTimeFormat = function() {
+  var result = native_.callSync('Time_getTimeFormat');
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+
+  return native_.getResultObject(result);
+};
+
+exports.isLeapYear = function(year) {
+  if (year === undefined)
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR);
+
+  return ((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0);
+};
+
+var _timeUtilDateTimeChangeListener;
+
+function _timeUtilDateTimeChangeListenerCallback() {
+  native_.callIfPossible(_timeUtilDateTimeChangeListener);
+}
+
+exports.setDateTimeChangeListener = function() {
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'changeCallback',
+      type: types_.FUNCTION
+    }
+  ]);
+  _timeUtilDateTimeChangeListener = args.changeCallback;
+  native_.addListener('DateTimeChangeListener',
+      _timeUtilDateTimeChangeListenerCallback);
+  var result = native_.callSync('Time_setDateTimeChangeListener', {});
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+};
+
+exports.unsetDateTimeChangeListener = function() {
+  native_.removeListener('DateTimeChangeListener',
+      _timeUtilDateTimeChangeListenerCallback);
+  var result = native_.callSync('Time_unsetDateTimeChangeListener', {});
+  _timeUtilDateTimeChangeListener = undefined;
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+};
+
+var _timeUtilTimezoneChangeListener;
+
+function _timeUtilTimezoneChangeListenerCallback() {
+  native_.callIfPossible(_timeUtilTimezoneChangeListener);
+}
+
+exports.setTimezoneChangeListener = function() {
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'changeCallback',
+      type: types_.FUNCTION
+    }
+  ]);
+
+  _timeUtilTimezoneChangeListener = args.changeCallback;
+  native_.addListener('TimezoneChangeListener',
+      _timeUtilTimezoneChangeListenerCallback);
+  var result = native_.callSync('Time_setTimezoneChangeListener', {});
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+};
+
+exports.unsetTimezoneChangeListener = function() {
+  native_.removeListener('TimezoneChangeListener',
+      _timeUtilTimezoneChangeListenerCallback);
+  var result = native_.callSync('Time_unsetTimezoneChangeListener', {});
+  _timeUtilTimezoneChangeListener = undefined;
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+};
+
+function _throwProperTizenException(e) {
+  if (e instanceof TypeError)
+    throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR);
+  else if (e instanceof RangeError)
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR);
+  else
+    throw new WebAPIException(WebAPIException.UNKNOWN_ERR);
+}
+
+var TimeDurationUnit = {
+  MSECS: 'MSECS',
+  SECS: 'SECS',
+  MINS: 'MINS',
+  HOURS: 'HOURS',
+  DAYS: 'DAYS'
+};
+
+tizen.TimeDuration = function(length, unit) {
+  validator_.isConstructorCall(this, tizen.TimeDuration);
+
+  var length_ = length !== null ? Math.floor(length) : 0;
+  var unit_ = Object.keys(TimeDurationUnit).indexOf(unit) >= 0 ? unit : TimeDurationUnit.MSECS;
+
+  Object.defineProperties(this, {
+    length: {
+      get: function() {
+        return length_;
+      },
+      set: function(v) {
+        if (v !== null) {
+          length_ = Math.floor(v);
+        }
+      },
+      enumerable: true
+    },
+    unit: {
+      get: function() {
+        return unit_;
+      },
+      set: function(v) {
+        if (Object.keys(TimeDurationUnit).indexOf(v) >= 0) {
+          unit_ = v;
+        }
+      },
+      enumerable: true
+    }
+  });
+};
+
+function makeMillisecondsDurationObject(length) {
+  var dayInMsecs = _hourInMilliseconds * 24;
+  length = Math.floor(length);
+
+  if ((length % dayInMsecs) === 0)
+    return new tizen.TimeDuration(length / dayInMsecs, TimeDurationUnit.DAYS);
+
+  return new tizen.TimeDuration(length, TimeDurationUnit.MSECS);
+}
+
+tizen.TimeDuration.prototype.getMilliseconds = function() {
+  var m;
+  switch (this.unit) {
+    case TimeDurationUnit.MSECS:
+      m = 1;
+      break;
+    case TimeDurationUnit.SECS:
+      m = 1000;
+      break;
+    case TimeDurationUnit.MINS:
+      m = 60 * 1000;
+      break;
+    case TimeDurationUnit.HOURS:
+      m = 3600 * 1000;
+      break;
+    case TimeDurationUnit.DAYS:
+      m = 86400 * 1000;
+      break;
+  }
+  return m * this.length;
+};
+
+tizen.TimeDuration.prototype.difference = function() {
+  var args = validator_.validateArgs(arguments, [{
+    name: 'other',
+    type: types_.PLATFORM_OBJECT,
+    values: tizen.TimeDuration
+  }]);
+
+  try {
+    return makeMillisecondsDurationObject(this.getMilliseconds() -
+                                          args.other.getMilliseconds());
+  } catch (e) {
+    _throwProperTizenException(e);
+  }
+};
+
+tizen.TimeDuration.prototype.equalsTo = function() {
+  var args = validator_.validateArgs(arguments, [{
+    name: 'other',
+    type: types_.PLATFORM_OBJECT,
+    values: tizen.TimeDuration
+  }]);
+
+  try {
+    return this.getMilliseconds() === args.other.getMilliseconds();
+  } catch (e) {
+    _throwProperTizenException(e);
+  }
+};
+
+tizen.TimeDuration.prototype.lessThan = function() {
+  var args = validator_.validateArgs(arguments, [{
+    name: 'other',
+    type: types_.PLATFORM_OBJECT,
+    values: tizen.TimeDuration
+  }]);
+
+  try {
+    return this.getMilliseconds() < args.other.getMilliseconds();
+  } catch (e) {
+    _throwProperTizenException(e);
+  }
+};
+
+tizen.TimeDuration.prototype.greaterThan = function() {
+  var args = validator_.validateArgs(arguments, [{
+    name: 'other',
+    type: types_.PLATFORM_OBJECT,
+    values: tizen.TimeDuration
+  }]);
+
+  try {
+    return this.getMilliseconds() > args.other.getMilliseconds();
+  } catch (e) {
+    _throwProperTizenException(e);
+  }
+};
+
+tizen.TimeDuration.prototype.toString = function() {
+  return this.length + ' ' + this.unit;
+};
+
+function getTimezoneOffset(_timezone, _timeInMs) {
+  var result = native_.callSync('Time_getTimeZoneOffset', {
+    timezone: _timezone,
+    value: _timeInMs
+  });
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+
+  return native_.getResultObject(result);
+}
+
+function getMsUTC(date, timezone) {
+  var ms_utc = Date.UTC(date.getUTCFullYear(),
+                        date.getUTCMonth(),
+                        date.getUTCDate(),
+                        date.getUTCHours(),
+                        date.getUTCMinutes(),
+                        date.getUTCSeconds(),
+                        date.getUTCMilliseconds());
+  if (arguments.length === 2) {
+    var result = native_.callSync('Time_getMsUTC', {
+      timezone: timezone,
+      value: ms_utc
+    });
+    if (native_.isFailure(result)) {
+      throw native_.getErrorObject(result);
+    }
+
+    ms_utc = native_.getResultObject(result);
+  }
+
+  return ms_utc;
+}
+
+tizen.TZDate = function(year, month, day, hours, minutes, seconds, milliseconds, timezone) {
+  validator_.isConstructorCall(this, tizen.TZDate);
+
+  if (timezone) {
+    if (tizen.time.getAvailableTimezones().indexOf(timezone) < 0) {
+      throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR);
+    }
+
+    this.timezone_ = timezone;
+  } else {
+    this.timezone_ = tizen.time.getLocalTimezone();
+  }
+
+  var hours = hours || 0;
+  var minutes = minutes || 0;
+  var seconds = seconds || 0;
+  var milliseconds = milliseconds || 0;
+
+  if (!arguments.length) {
+    this.date_ = new Date();
+  } else if (arguments.length === 1 || arguments.length === 2) {
+    if (arguments[0] instanceof Date) {
+      this.date_ = arguments[0];
+    } else {
+      this.date_ = new Date();
+    }
+    if (arguments[1]) {
+      if (tizen.time.getAvailableTimezones().indexOf(arguments[1]) < 0) {
+        throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR);
+      }
+      this.timezone_ = arguments[1];
+    }
+  } else {
+    this.date_ = {};
+    if (timezone) {
+      // If date is 31, setUTCMonth function reduce 30 days.
+      // It means that month isn't changed.
+      var d = new Date(2011, 10, 11, 4, 55, 54, 12);
+      d.setUTCFullYear(year);
+      d.setUTCMonth(month);
+      d.setUTCDate(day);
+      d.setUTCHours(hours);
+      d.setUTCMinutes(minutes);
+      d.setUTCSeconds(seconds);
+      d.setUTCMilliseconds(milliseconds);
+      this.date_ = new Date(getMsUTC(d, timezone));
+    } else {
+      this.date_ = new Date(year, month, day, hours, minutes, seconds, milliseconds);
+    }
+  }
+};
+
+tizen.TZDate.prototype.getDate = function() {
+  var d = this.addDuration(new tizen.TimeDuration(getTimezoneOffset(this.timezone_,
+                    getMsUTC(this.date_))));
+  return d.date_.getUTCDate();
+};
+
+tizen.TZDate.prototype.setDate = function() {
+  var args = validator_.validateArgs(arguments, [{
+    name: 'date',
+    type: types_.LONG
+  }]);
+
+  this.date_.setDate(args.date);
+};
+
+tizen.TZDate.prototype.getDay = function() {
+  return this.date_.getDay();
+};
+
+tizen.TZDate.prototype.getFullYear = function() {
+  return this.date_.getFullYear();
+};
+
+tizen.TZDate.prototype.setFullYear = function() {
+  var args = validator_.validateArgs(arguments, [{
+    name: 'year',
+    type: types_.LONG
+  }]);
+
+  this.date_.setFullYear(args.year);
+};
+
+tizen.TZDate.prototype.getHours = function() {
+  var d = this.addDuration(new tizen.TimeDuration(getTimezoneOffset(this.timezone_,
+                                           getMsUTC(this.date_))));
+  return d.date_.getUTCHours();
+};
+
+tizen.TZDate.prototype.setHours = function() {
+  var args = validator_.validateArgs(arguments, [{
+    name: 'hours',
+    type: types_.LONG
+  }]);
+
+  this.date_.setHours(args.hours);
+};
+
+tizen.TZDate.prototype.getMilliseconds = function() {
+  return this.date_.getMilliseconds();
+};
+
+tizen.TZDate.prototype.setMilliseconds = function() {
+  var args = validator_.validateArgs(arguments, [{
+    name: 'ms',
+    type: types_.LONG
+  }]);
+
+  this.date_.setMilliseconds(args.ms);
+};
+
+tizen.TZDate.prototype.getMonth = function() {
+  return this.date_.getMonth();
+};
+
+tizen.TZDate.prototype.setMonth = function() {
+  var args = validator_.validateArgs(arguments, [{
+    name: 'month',
+    type: types_.LONG
+  }]);
+
+  this.date_.setMonth(args.month);
+};
+
+tizen.TZDate.prototype.getMinutes = function() {
+  return this.date_.getMinutes();
+};
+
+tizen.TZDate.prototype.setMinutes = function() {
+  var args = validator_.validateArgs(arguments, [{
+    name: 'minutes',
+    type: types_.LONG
+  }]);
+
+  this.date_.setMinutes(args.minutes);
+};
+
+tizen.TZDate.prototype.getSeconds = function() {
+  return this.date_.getSeconds();
+};
+
+tizen.TZDate.prototype.setSeconds = function() {
+  var args = validator_.validateArgs(arguments, [{
+    name: 'seconds',
+    type: types_.LONG
+  }]);
+
+  this.date_.setSeconds(args.seconds);
+};
+
+tizen.TZDate.prototype.getUTCDate = function() {
+  return this.date_.getUTCDate();
+};
+
+tizen.TZDate.prototype.setUTCDate = function() {
+  var args = validator_.validateArgs(arguments, [{
+    name: 'date',
+    type: types_.LONG
+  }]);
+
+  this.date_.setUTCDate(args.date);
+};
+
+tizen.TZDate.prototype.getUTCDay = function() {
+  var d = this.addDuration(new tizen.TimeDuration(getTimezoneOffset(this.timezone_,
+                                         getMsUTC(this.date_)) * -1));
+  return d.getDay();
+};
+
+tizen.TZDate.prototype.getUTCFullYear = function() {
+  var d = this.addDuration(new tizen.TimeDuration(getTimezoneOffset(this.timezone_,
+                                          getMsUTC(this.date_)) * -1));
+  return d.getFullYear();
+};
+
+tizen.TZDate.prototype.setUTCFullYear = function() {
+  var args = validator_.validateArgs(arguments, [{
+    name: 'year',
+    type: types_.LONG
+  }]);
+
+  this.date_.setUTCFullYear(args.year);
+};
+
+tizen.TZDate.prototype.getUTCHours = function() {
+  return this.date_.getUTCHours();
+};
+
+tizen.TZDate.prototype.setUTCHours = function() {
+  var args = validator_.validateArgs(arguments, [{
+    name: 'hours',
+    type: types_.LONG
+  }]);
+
+  var offset_hours = getTimezoneOffset(this.timezone_, getMsUTC(this.date_)) /
+                     _hourInMilliseconds;
+  this.date_.setHours(args.hours + offset_hours);
+};
+
+tizen.TZDate.prototype.getUTCMilliseconds = function() {
+  var d = this.addDuration(new tizen.TimeDuration(getTimezoneOffset(this.timezone_,
+                                              getMsUTC(this.date_)) * -1));
+  return d.getMilliseconds();
+};
+
+tizen.TZDate.prototype.setUTCMilliseconds = function() {
+  var args = validator_.validateArgs(arguments, [{
+    name: 'ms',
+    type: types_.LONG
+  }]);
+
+  this.date_.setUTCMilliseconds(args.ms);
+};
+
+tizen.TZDate.prototype.getUTCMinutes = function() {
+  var d = this.addDuration(new tizen.TimeDuration(getTimezoneOffset(this.timezone_,
+                                             getMsUTC(this.date_)) * -1));
+  return d.getMinutes();
+};
+
+tizen.TZDate.prototype.setUTCMinutes = function() {
+  var args = validator_.validateArgs(arguments, [{
+    name: 'minutes',
+    type: types_.LONG
+  }]);
+
+  this.date_.setUTCMinutes(args.minutes);
+};
+
+tizen.TZDate.prototype.getUTCMonth = function() {
+  var d = this.addDuration(new tizen.TimeDuration(getTimezoneOffset(this.timezone_,
+                                           getMsUTC(this.date_)) * -1));
+  return d.getMonth();
+};
+
+tizen.TZDate.prototype.setUTCMonth = function() {
+  var args = validator_.validateArgs(arguments, [{
+    name: 'month',
+    type: types_.LONG
+  }]);
+
+  this.date_.setUTCMonth(args.month);
+};
+
+tizen.TZDate.prototype.getUTCSeconds = function() {
+  var d = this.addDuration(new tizen.TimeDuration(getTimezoneOffset(this.timezone_,
+                                         getMsUTC(this.date_)) * -1));
+  return d.getSeconds();
+};
+
+tizen.TZDate.prototype.setUTCSeconds = function() {
+  var args = validator_.validateArgs(arguments, [{
+    name: 'secs',
+    type: types_.LONG
+  }]);
+
+  this.date_.setUTCSeconds(args.secs);
+};
+
+tizen.TZDate.prototype.getTime = function() {
+  return this.date_.getTime();
+};
+
+tizen.TZDate.prototype.getTimezone = function() {
+  return this.timezone_;
+};
+
+tizen.TZDate.prototype.toTimezone = function() {
+  var args = validator_.validateArgs(arguments, [{
+    name: 'timezone',
+    type: types_.STRING
+  }]);
+
+  if (!args.timezone)
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR);
+
+  return new tizen.TZDate(new Date(this.date_.getTime()), args.timezone);
+};
+
+tizen.TZDate.prototype.toLocalTimezone = function() {
+  return this.toTimezone(tizen.time.getLocalTimezone());
+};
+
+tizen.TZDate.prototype.toUTC = function() {
+  return this.toTimezone('GMT');
+};
+
+tizen.TZDate.prototype.difference = function() {
+  var args = validator_.validateArgs(arguments, [{
+    name: 'other',
+    type: types_.PLATFORM_OBJECT,
+    values: tizen.TZDate
+  }]);
+
+  try {
+    return makeMillisecondsDurationObject(this.getTime() - args.other.getTime());
+  } catch (e) {
+    _throwProperTizenException(e);
+  }
+};
+
+tizen.TZDate.prototype.equalsTo = function() {
+  var args = validator_.validateArgs(arguments, [{
+    name: 'other',
+    type: types_.PLATFORM_OBJECT,
+    values: tizen.TZDate
+  }]);
+
+  try {
+    return this.getTime() === args.other.getTime();
+  } catch (e) {
+    _throwProperTizenException(e);
+  }
+};
+
+tizen.TZDate.prototype.earlierThan = function() {
+  var args = validator_.validateArgs(arguments, [{
+    name: 'other',
+    type: types_.PLATFORM_OBJECT,
+    values: tizen.TZDate
+  }]);
+
+  try {
+    return this.getTime() < args.other.getTime();
+  } catch (e) {
+    _throwProperTizenException(e);
+  }
+};
+
+tizen.TZDate.prototype.laterThan = function(other) {
+  var args = validator_.validateArgs(arguments, [{
+    name: 'other',
+    type: types_.PLATFORM_OBJECT,
+    values: tizen.TZDate
+  }]);
+
+  try {
+    return this.getTime() > args.other.getTime();
+  } catch (e) {
+    _throwProperTizenException(e);
+  }
+};
+
+tizen.TZDate.prototype.addDuration = function() {
+  var args = validator_.validateArgs(arguments, [{
+    name: 'duration',
+    type: types_.PLATFORM_OBJECT,
+    values: tizen.TimeDuration
+  }]);
+
+  try {
+    var date = new tizen.TZDate(new Date(this.date_.getTime()), this.timezone_);
+    date.setMilliseconds(args.duration.getMilliseconds() + date.getMilliseconds());
+    return date;
+  } catch (e) {
+    _throwProperTizenException(e);
+  }
+};
+
+tizen.TZDate.prototype.toLocaleDateString = function() {
+  var result = native_.callSync('Time_toDateString', {
+    timezone: this.timezone_,
+    value: this.date_.getTime(),
+    trans: '',
+    locale: true
+  });
+  if (native_.isFailure(result)) {
+    return '';
+  }
+
+  return native_.getResultObject(result);
+};
+
+tizen.TZDate.prototype.toLocaleTimeString = function() {
+  var result = native_.callSync('Time_toTimeString', {
+    timezone: this.timezone_,
+    value: this.date_.getTime(),
+    trans: '',
+    locale: true
+  });
+  if (native_.isFailure(result)) {
+    return '';
+  }
+
+  return native_.getResultObject(result);
+};
+
+tizen.TZDate.prototype.toLocaleString = function() {
+  var result = native_.callSync('Time_toString', {
+    timezone: this.timezone_,
+    value: this.date_.getTime(),
+    trans: '',
+    locale: true
+  });
+  if (native_.isFailure(result)) {
+    return '';
+  }
+
+  return native_.getResultObject(result);
+};
+
+tizen.TZDate.prototype.toDateString = function() {
+  var result = native_.callSync('Time_toDateString', {
+    timezone: this.timezone_,
+    value: this.date_.getTime(),
+    trans: '',
+    locale: false
+  });
+  if (native_.isFailure(result)) {
+    return '';
+  }
+
+  return native_.getResultObject(result);
+};
+
+tizen.TZDate.prototype.toTimeString = function() {
+  var result = native_.callSync('Time_toTimeString', {
+    timezone: this.timezone_,
+    value: this.date_.getTime(),
+    trans: '',
+    locale: false
+  });
+  if (native_.isFailure(result)) {
+    return '';
+  }
+
+  return native_.getResultObject(result);
+};
+
+tizen.TZDate.prototype.toString = function() {
+  var result = native_.callSync('Time_toString', {
+    timezone: this.timezone_,
+    value: this.date_.getTime(),
+    trans: '',
+    locale: false
+  });
+  if (native_.isFailure(result)) {
+    return '';
+  }
+
+  return native_.getResultObject(result);
+};
+
+tizen.TZDate.prototype.getTimezoneAbbreviation = function() {
+  var result = native_.callSync('Time_getTimeZoneAbbreviation', {
+    timezone: this.timezone_,
+    value: this.date_.getTime()
+  });
+  if (native_.isFailure(result)) {
+    return '';
+  }
+
+  return native_.getResultObject(result);
+};
+
+tizen.TZDate.prototype.secondsFromUTC = function() {
+  return this.date_.getTimezoneOffset() * 60;
+};
+
+tizen.TZDate.prototype.isDST = function() {
+  var result = native_.callSync('Time_isDST', {
+    timezone: this.timezone_,
+    value: getMsUTC(this.date_)
+  });
+  if (native_.isFailure(result)) {
+    return false;
+  }
+
+  return native_.getResultObject(result);
+};
+
+tizen.TZDate.prototype.getPreviousDSTTransition = function() {
+  var result = native_.callSync('Time_getDSTTransition', {
+    'timezone': this.timezone_,
+    'value': getMsUTC(this.date_),
+    'trans': 'NEXT_TRANSITION'
+  });
+  if (native_.isFailure(result)) {
+    return null;
+  }
+  var _result = native_.getResultObject(result);
+  if (result.error || _result === 0)
+    return null;
+
+  var utc_time = getMsUTC(new Date(_result), this.timezone_);
+  return new tizen.TZDate(new Date(utc_time)).toTimezone(this.timezone_);
+};
+
+tizen.TZDate.prototype.getNextDSTTransition = function() {
+  var result = native_.callSync('Time_getDSTTransition', {
+    timezone: this.timezone_,
+    value: getMsUTC(this.date_),
+    trans: 'PREV_TRANSITION'
+  });
+  if (native_.isFailure(result)) {
+    return null;
+  }
+  var _result = native_.getResultObject(result);
+  if (result.error || _result === 0)
+    return null;
+
+  var utc_time = getMsUTC(new Date(_result), this.timezone_);
+  return new tizen.TZDate(new Date(utc_time)).toTimezone(this.timezone_);
+};
diff --git a/webWidgetTCT_device/src/time/time_extension.cc b/webWidgetTCT_device/src/time/time_extension.cc
new file mode 100755 (executable)
index 0000000..de63827
--- /dev/null
@@ -0,0 +1,38 @@
+// Copyright (c) 2013 Intel Corporation. All rights reserved.
+// Copyright (c) 2015 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <common/logger.h>
+#include "time/time_extension.h"
+#include "time/time_instance.h"
+
+common::Extension* CreateExtension() {
+  LoggerD("Entered");
+  return new TimeExtension;
+}
+
+// This will be generated from time_api.js.
+extern const char kSource_time_api[];
+
+TimeExtension::TimeExtension() {
+  LoggerD("Entered");
+  SetExtensionName("tizen.time");
+  SetJavaScriptAPI(kSource_time_api);
+
+  const char* entry_points[] = {
+    "tizen.TZDate",
+    "tizen.TimeDuration",
+    NULL
+  };
+  SetExtraJSEntryPoints(entry_points);
+}
+
+TimeExtension::~TimeExtension() {
+  LoggerD("Entered");
+}
+
+common::Instance* TimeExtension::CreateInstance() {
+  LoggerD("Entered");
+  return new extension::time::TimeInstance();
+}
diff --git a/webWidgetTCT_device/src/time/time_extension.h b/webWidgetTCT_device/src/time/time_extension.h
new file mode 100755 (executable)
index 0000000..df8b8d4
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright (c) 2013 Intel Corporation. All rights reserved.
+// Copyright (c) 2015 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TIME_TIME_EXTENSION_H_
+#define TIME_TIME_EXTENSION_H_
+
+#include "common/extension.h"
+
+class TimeExtension : public common::Extension {
+ public:
+  TimeExtension();
+  virtual ~TimeExtension();
+
+ private:
+  // common::Extension implementation.
+  virtual common::Instance* CreateInstance();
+};
+
+#endif  // TIME_TIME_EXTENSION_H_
diff --git a/webWidgetTCT_device/src/time/time_instance.cc b/webWidgetTCT_device/src/time/time_instance.cc
new file mode 100755 (executable)
index 0000000..a669077
--- /dev/null
@@ -0,0 +1,775 @@
+// Copyright (c) 2013 Intel Corporation. All rights reserved.
+// Copyright (c) 2015 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "time/time_instance.h"
+#include "common/platform_exception.h"
+#include "common/logger.h"
+
+#if defined(TIZEN)
+#include <vconf.h>
+#endif
+
+#include <sstream>
+#include <memory>
+#include <cerrno>
+#include <unistd.h>
+
+#include "common/picojson.h"
+#include "common/platform_result.h"
+
+#include "unicode/timezone.h"
+#include "unicode/calendar.h"
+#include "unicode/vtzone.h"
+#include "unicode/tztrans.h"
+#include "unicode/smpdtfmt.h"
+#include "unicode/dtptngen.h"
+
+namespace extension {
+namespace time {
+
+using namespace common;
+
+enum ListenerType {
+  kTimeChange,
+  kTimezoneChange
+};
+
+namespace {
+
+const int _hourInMilliseconds = 3600000;
+const char kTimezoneListenerId[] = "TimezoneChangeListener";
+const char kDateTimeListenerId[] = "DateTimeChangeListener";
+
+}  // namespace
+
+TimeInstance::TimeInstance() {
+  using std::placeholders::_1;
+  using std::placeholders::_2;
+
+  LoggerD("Entered");
+
+#define REGISTER_SYNC(c, x) \
+  RegisterSyncHandler(c, std::bind(&TimeInstance::x, this, _1, _2));
+#define REGISTER_ASYNC(c, x) \
+  RegisterSyncHandler(c, std::bind(&TimeInstance::x, this, _1, _2));
+
+  REGISTER_SYNC("Time_getAvailableTimeZones", TimeGetAvailableTimeZones);
+  REGISTER_SYNC("Time_getDSTTransition", TimeGetDSTTransition);
+  REGISTER_SYNC("Time_getLocalTimeZone", TimeGetLocalTimeZone);
+  REGISTER_SYNC("Time_getTimeFormat", TimeGetTimeFormat);
+  REGISTER_SYNC("Time_getDateFormat", TimeGetDateFormat);
+  REGISTER_SYNC("Time_getTimeZoneOffset", TimeGetTimeZoneOffset);
+  REGISTER_SYNC("Time_getTimeZoneAbbreviation", TimeGetTimeZoneAbbreviation);
+  REGISTER_SYNC("Time_isDST", TimeIsDST);
+  REGISTER_SYNC("Time_toString", TimeToString);
+  REGISTER_SYNC("Time_toDateString", TimeToDateString);
+  REGISTER_SYNC("Time_toTimeString", TimeToTimeString);
+  REGISTER_SYNC("Time_setDateTimeChangeListener",
+                TimeSetDateTimeChangeListener);
+  REGISTER_SYNC("Time_unsetDateTimeChangeListener",
+                TimeUnsetDateTimeChangeListener);
+  REGISTER_SYNC("Time_setTimezoneChangeListener",
+                TimeSetTimezoneChangeListener);
+  REGISTER_SYNC("Time_unsetTimezoneChangeListener",
+                TimeUnsetTimezoneChangeListener);
+  REGISTER_SYNC("Time_getMsUTC", TimeGetMsUTC);
+
+#undef REGISTER_SYNC
+#undef REGISTER_ASYNC
+}
+
+static void OnTimeChangedCallback(keynode_t* /*node*/, void* user_data);
+static std::string GetDefaultTimezone();
+
+TimeInstance::~TimeInstance() {
+    LoggerD("Entered");
+}
+
+void TimeInstance::TimeGetLocalTimeZone(const JsonValue& /*args*/,
+                                        JsonObject& out) {
+  LoggerD("Entered");
+
+  UnicodeString local_timezone;
+  TimeZone* timezone = TimeZone::createDefault();
+  if (nullptr != timezone) {
+    timezone->getID(local_timezone);
+    delete timezone;
+
+    std::string localtz;
+    local_timezone.toUTF8String(localtz);
+
+    ReportSuccess(JsonValue(localtz), out);
+  } else {
+    ReportError(out);
+  }
+}
+
+void TimeInstance::TimeGetAvailableTimeZones(const JsonValue& /*args*/,
+                                             JsonObject& out) {
+  LoggerD("Entered");
+
+  UErrorCode ec = U_ZERO_ERROR;
+  std::unique_ptr<StringEnumeration> timezones(TimeZone::createEnumeration());
+  int32_t count = timezones->count(ec);
+  if (U_FAILURE(ec)) {
+    LoggerE("Failed to get timezones.");
+    ReportError(out);
+    return;
+  }
+
+  JsonArray a;
+  const char* timezone = NULL;
+  int i = 0;
+  do {
+    int32_t resultLen = 0;
+    timezone = timezones->next(&resultLen, ec);
+    if (U_SUCCESS(ec)) {
+      a.push_back(JsonValue(timezone));
+      i++;
+    }
+  } while (timezone && i < count);
+
+  ReportSuccess(JsonValue(a), out);
+}
+
+void TimeInstance::TimeGetTimeZoneOffset(const JsonValue& args,
+                                         JsonObject& out) {
+  LoggerD("Entered");
+
+  std::unique_ptr<UnicodeString> id(
+      new UnicodeString(args.get("timezone").to_str().c_str()));
+  if (id == NULL) {
+    LoggerE("Allocation error");
+    ReportError(out);
+    return;
+  }
+
+  UDate dateInMs = strtod(args.get("value").to_str().c_str(), NULL);
+  if (errno == ERANGE) {
+    LoggerE("Value out of range");
+    ReportError(out);
+    return;
+  }
+
+  UErrorCode ec = U_ZERO_ERROR;
+  std::unique_ptr<TimeZone> timezone(TimeZone::createTimeZone(*id));
+
+  int32_t rawOffset = 0;
+  int32_t dstOffset = 0;
+  timezone->getOffset(dateInMs, false, rawOffset, dstOffset, ec);
+  if (U_FAILURE(ec)) {
+    LoggerE("Failed to get timezone offset");
+    ReportError(out);
+    return;
+  }
+  std::stringstream offsetStr;
+  offsetStr << (rawOffset + dstOffset);
+  ReportSuccess(JsonValue(offsetStr.str()), out);
+}
+
+void TimeInstance::TimeGetTimeZoneAbbreviation(const JsonValue& args,
+                                               JsonObject& out) {
+  LoggerD("Entered");
+
+  std::unique_ptr<UnicodeString> id(
+      new UnicodeString(args.get("timezone").to_str().c_str()));
+  if (id == NULL) {
+    LoggerE("Allocation error");
+    ReportError(out);
+    return;
+  }
+
+  UDate dateInMs = strtod(args.get("value").to_str().c_str(), NULL);
+  if (errno == ERANGE) {
+    LoggerE("Value out of range");
+    ReportError(out);
+    return;
+  }
+
+  UErrorCode ec = U_ZERO_ERROR;
+  std::unique_ptr<TimeZone> timezone(TimeZone::createTimeZone(*id));
+  std::unique_ptr<Calendar> cal(Calendar::createInstance(*timezone, ec));
+  if (U_FAILURE(ec)) {
+    LoggerE("Failed to create Calendar instance");
+    ReportError(out);
+    return;
+  }
+
+  cal->setTime(dateInMs, ec);
+  if (U_FAILURE(ec)) {
+    LoggerE("Failed to set date");
+    ReportError(out);
+    return;
+  }
+
+  std::unique_ptr<DateFormat> fmt(
+      new SimpleDateFormat(UnicodeString("z"), Locale::getEnglish(), ec));
+  if (U_FAILURE(ec)) {
+    LoggerE("Failed to create format object");
+    ReportError(out);
+    return;
+  }
+
+  UnicodeString uAbbreviation;
+  fmt->setCalendar(*cal);
+  fmt->format(cal->getTime(ec), uAbbreviation);
+  if (U_FAILURE(ec)) {
+    LoggerE("Failed to format object");
+    ReportError(out);
+    return;
+  }
+
+  std::string abbreviation = "";
+  uAbbreviation.toUTF8String(abbreviation);
+
+  ReportSuccess(JsonValue(abbreviation), out);
+}
+
+void TimeInstance::TimeIsDST(const JsonValue& args, JsonObject& out) {
+  LoggerD("Entered");
+
+  std::unique_ptr<UnicodeString> id(
+      new UnicodeString(args.get("timezone").to_str().c_str()));
+  if (id == NULL) {
+    LoggerE("Allocation error");
+    ReportError(out);
+    return;
+  }
+
+  UDate dateInMs = strtod(args.get("value").to_str().c_str(), NULL);
+  if (errno == ERANGE) {
+    LoggerE("Value out of range");
+    ReportError(out);
+    return;
+  }
+
+  UErrorCode ec = U_ZERO_ERROR;
+  std::unique_ptr<TimeZone> timezone(TimeZone::createTimeZone(*id));
+
+  int32_t rawOffset = 0;
+  int32_t dstOffset = 0;
+  timezone->getOffset(dateInMs, false, rawOffset, dstOffset, ec);
+  if (U_FAILURE(ec)) {
+    LoggerE("Failed to get timezone offset");
+    ReportError(out);
+    return;
+  }
+  ReportSuccess(JsonValue{static_cast<bool>(dstOffset)}, out);
+}
+
+void TimeInstance::TimeGetDSTTransition(const JsonValue& args,
+                                        JsonObject& out) {
+  LoggerD("Entered");
+
+  std::unique_ptr<UnicodeString> id(
+      new UnicodeString(args.get("timezone").to_str().c_str()));
+  if (id == NULL) {
+    LoggerE("Allocation error");
+    ReportError(out);
+    return;
+  }
+
+  std::string trans = args.get("trans").to_str();
+  UDate dateInMs = strtod(args.get("value").to_str().c_str(), NULL);
+  if (errno == ERANGE) {
+    LoggerE("Value out of range");
+    ReportError(out);
+    return;
+  }
+
+  std::unique_ptr<VTimeZone> vtimezone(VTimeZone::createVTimeZoneByID(*id));
+
+  if (!vtimezone->useDaylightTime()) {
+    LoggerE("Failed to set DST");
+    ReportError(out);
+    return;
+  }
+
+  TimeZoneTransition tzTransition;
+  if (trans.compare("NEXT_TRANSITION") &&
+      vtimezone->getNextTransition(dateInMs, FALSE, tzTransition)) {
+    ReportSuccess(JsonValue{tzTransition.getTime()}, out);
+  } else if (vtimezone->getPreviousTransition(dateInMs, FALSE, tzTransition)) {
+    ReportSuccess(JsonValue{tzTransition.getTime()}, out);
+  } else {
+    LoggerE("Error while getting transition");
+    ReportError(out);
+  }
+}
+
+void TimeInstance::TimeToString(const JsonValue& args, JsonObject& out) {
+  JsonValue val;
+  LoggerD("Entered");
+
+  if (!this->toStringByFormat(args, val, TimeInstance::DATETIME_FORMAT)) {
+    LoggerE("Failed to convert to string");
+    ReportError(out);
+    return;
+  }
+
+  ReportSuccess(val, out);
+}
+
+void TimeInstance::TimeToDateString(const JsonValue& args, JsonObject& out) {
+  JsonValue val;
+  LoggerD("Entered");
+
+  if (!this->toStringByFormat(args, val, TimeInstance::DATE_FORMAT)) {
+    LoggerE("Failed to convert to string");
+    ReportError(out);
+    return;
+  }
+
+  ReportSuccess(val, out);
+}
+
+void TimeInstance::TimeToTimeString(const JsonValue& args, JsonObject& out) {
+  JsonValue val;
+  LoggerD("Entered");
+
+  if (!this->toStringByFormat(args, val, TimeInstance::TIME_FORMAT)) {
+    LoggerE("Failed to convert to string");
+    ReportError(out);
+    return;
+  }
+
+  ReportSuccess(val, out);
+}
+
+bool TimeInstance::toStringByFormat(const JsonValue& args, JsonValue& out,
+                                    DateTimeFormatType format) {
+  LoggerD("Entered");
+
+  std::unique_ptr<UnicodeString> id(
+      new UnicodeString(args.get("timezone").to_str().c_str()));
+  if (id == NULL) {
+    LoggerE("Allocation error");
+    return false;
+  }
+
+  bool bLocale = args.get("locale").evaluate_as_boolean();
+
+  UDate dateInMs = strtod(args.get("value").to_str().c_str(), NULL);
+  if (errno == ERANGE) {
+    LoggerE("Value out of range");
+    return false;
+  }
+
+  UErrorCode ec = U_ZERO_ERROR;
+  std::unique_ptr<TimeZone> timezone(TimeZone::createTimeZone(*id));
+  std::unique_ptr<Calendar> cal(Calendar::createInstance(*timezone, ec));
+  if (U_FAILURE(ec)) {
+    LoggerE("Failed to create Calendar instance");
+    return false;
+  }
+
+  cal->setTime(dateInMs, ec);
+  if (U_FAILURE(ec)) {
+    LoggerE("Failed to set time");
+    return false;
+  }
+
+  std::unique_ptr<DateFormat> fmt(new SimpleDateFormat(
+      getDateTimeFormat(format, bLocale),
+      (bLocale ? Locale::getDefault() : Locale::getEnglish()), ec));
+  if (U_FAILURE(ec)) {
+    LoggerE("Failed to create format object");
+    return false;
+  }
+
+  UnicodeString uResult;
+  fmt->setCalendar(*cal);
+  fmt->format(cal->getTime(ec), uResult);
+  if (U_FAILURE(ec)) {
+    LoggerE("Failed to format object");
+    return false;
+  }
+
+  std::string result = "";
+  uResult.toUTF8String(result);
+
+  out = JsonValue(result);
+  return true;
+}
+
+void TimeInstance::TimeGetTimeFormat(const JsonValue& /*args*/,
+                                     JsonObject& out) {
+  LoggerD("Entered");
+
+  UnicodeString timeFormat = getDateTimeFormat(TimeInstance::TIME_FORMAT, true);
+
+  timeFormat = timeFormat.findAndReplace("H", "h");
+  timeFormat = timeFormat.findAndReplace("a", "ap");
+
+  timeFormat = timeFormat.findAndReplace("hh", "h");
+  timeFormat = timeFormat.findAndReplace("mm", "m");
+  timeFormat = timeFormat.findAndReplace("ss", "s");
+
+  std::string result = "";
+  timeFormat.toUTF8String(result);
+
+  ReportSuccess(JsonValue(result), out);
+}
+
+void TimeInstance::TimeGetDateFormat(const JsonValue& args, JsonObject& out) {
+  LoggerD("Entered");
+
+  bool shortformat = args.get("shortformat").evaluate_as_boolean();
+  UnicodeString time_format =
+      getDateTimeFormat((shortformat ? DateTimeFormatType::DATE_SHORT_FORMAT
+                                     : DateTimeFormatType::DATE_FORMAT),
+                        true);
+
+  time_format = time_format.findAndReplace("E", "D");
+
+  if (time_format.indexOf("MMM") > 0) {
+    if (time_format.indexOf("MMMM") > 0) {
+      time_format = time_format.findAndReplace("MMMM", "M");
+    } else {
+      time_format = time_format.findAndReplace("MMM", "M");
+    }
+  } else {
+    time_format = time_format.findAndReplace("M", "m");
+  }
+
+  int i = 0;
+  while (i < time_format.length() - 1) {
+    if (time_format[i] == time_format[i + 1]) {
+      time_format.remove(i, 1);
+    } else {
+      ++i;
+    }
+  }
+
+  std::string result = "";
+  time_format.toUTF8String(result);
+  ReportSuccess(JsonValue(result), out);
+}
+
+Locale* TimeInstance::getDefaultLocale() {
+   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) - (p != nullptr ? strlen(p) : 0);
+   if (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 TimeInstance::getDateTimeFormat(DateTimeFormatType type,
+                                              bool bLocale) {
+  LoggerD("Entered");
+  LoggerD("bLocale %d", bLocale);
+
+  UErrorCode ec = U_ZERO_ERROR;
+  Locale *defaultLocale = getDefaultLocale();
+  std::unique_ptr<DateTimePatternGenerator> dateTimepattern(
+      DateTimePatternGenerator::createInstance(
+          ((bLocale && defaultLocale) ? *defaultLocale : Locale::getEnglish()), ec));
+
+  delete defaultLocale;
+
+  if (U_FAILURE(ec)) {
+    LoggerE("Failed to create Calendar instance");
+    return "";
+  }
+
+  UnicodeString pattern;
+  if (type == DATE_FORMAT) {
+    pattern = dateTimepattern->getBestPattern(UDAT_YEAR_MONTH_WEEKDAY_DAY, ec);
+  } else if (type == DATE_SHORT_FORMAT) {
+    pattern = dateTimepattern->getBestPattern(UDAT_YEAR_NUM_MONTH_DAY, ec);
+  } else {
+    std::string skeleton;
+    if (type != TIME_FORMAT) skeleton = UDAT_YEAR_MONTH_WEEKDAY_DAY;
+
+#if defined(TIZEN)
+    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;
+    }
+    if (VCONFKEY_TIME_FORMAT_12 == value) {
+      skeleton += "hhmmss";
+    } else {
+      skeleton += "HHmmss";
+    }
+#else
+    skeleton += "hhmmss";
+#endif
+
+    pattern = dateTimepattern->getBestPattern(
+        UnicodeString(skeleton.c_str()), ec);
+    if (U_FAILURE(ec)) {
+      LoggerE("Failed to get time pattern");
+      return "";
+    }
+
+    if (!bLocale) pattern += " 'GMT'Z v'";
+  }
+
+  return pattern;
+}
+
+/////////////////////////// TimeUtilListeners ////////////////////////////////
+
+class TimeUtilListeners {
+ public:
+  TimeUtilListeners();
+  ~TimeUtilListeners();
+
+  PlatformResult RegisterVconfCallback(ListenerType type, TimeInstance& instance);
+  PlatformResult UnregisterVconfCallback(ListenerType type);
+
+  std::string GetCurrentTimezone();
+  void SetCurrentTimezone(std::string& newTimezone);
+
+ private:
+  std::string current_timezone_;
+  bool is_time_listener_registered_;
+  bool is_timezone_listener_registered_;
+};
+
+TimeUtilListeners::TimeUtilListeners()
+    : current_timezone_(GetDefaultTimezone()),
+      is_time_listener_registered_(false),
+      is_timezone_listener_registered_(false) {
+  LoggerD("Entered");
+}
+
+TimeUtilListeners::~TimeUtilListeners() {
+  LoggerD("Entered");
+  if (is_time_listener_registered_ || is_timezone_listener_registered_) {
+    if (0 != vconf_ignore_key_changed(VCONFKEY_SYSTEM_TIME_CHANGED,
+                                      OnTimeChangedCallback)) {
+      LoggerE("Failed to unregister vconf callback");
+    }
+  }
+}
+
+PlatformResult TimeUtilListeners::RegisterVconfCallback(ListenerType type, TimeInstance& instance) {
+  LoggerD("Entered");
+
+  if (!is_time_listener_registered_ && !is_timezone_listener_registered_) {
+    LoggerD("registering listener on platform");
+    if (0 != vconf_notify_key_changed(VCONFKEY_SYSTEM_TIME_CHANGED,
+                                      OnTimeChangedCallback, static_cast<void*>(&instance))) {
+      LoggerE("Failed to register vconf callback");
+      return PlatformResult(ErrorCode::UNKNOWN_ERR,
+          "Failed to register vconf callback");
+    }
+  } else {
+    LoggerD("not registering listener on platform - already registered");
+  }
+  switch (type) {
+    case kTimeChange:
+      is_time_listener_registered_ = true;
+      LoggerD("time change listener registered");
+      break;
+    case kTimezoneChange:
+      is_timezone_listener_registered_ = true;
+      LoggerD("time zone change listener registered");
+      break;
+    default:
+      LoggerE("Unknown type of listener");
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown type of listener");
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult TimeUtilListeners::UnregisterVconfCallback(ListenerType type) {
+  LoggerD("Entered");
+
+  switch (type) {
+    case kTimeChange:
+      is_time_listener_registered_ = false;
+      LoggerD("time change listener unregistered");
+      break;
+    case kTimezoneChange:
+      is_timezone_listener_registered_ = false;
+      LoggerD("time zone change listener unregistered");
+      break;
+    default:
+      return PlatformResult(ErrorCode::UNKNOWN_ERR, "Unknown type of listener");
+  }
+  if (!is_time_listener_registered_ && !is_timezone_listener_registered_) {
+    LoggerD("unregistering listener on platform");
+    if (0 != vconf_ignore_key_changed(VCONFKEY_SYSTEM_TIME_CHANGED,
+                                      OnTimeChangedCallback)) {
+      LoggerE("Failed to unregister vconf callback");
+    }
+  }
+  return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+std::string TimeUtilListeners::GetCurrentTimezone() {
+  return current_timezone_;
+}
+
+void TimeUtilListeners::SetCurrentTimezone(std::string& newTimezone) {
+  current_timezone_ = newTimezone;
+}
+
+static std::string GetDefaultTimezone() {
+  LoggerD("Entered");
+
+  char buf[1024];
+  std::string result;
+  ssize_t len = readlink("/opt/etc/localtime", buf, sizeof(buf) - 1);
+  if (len != -1) {
+    buf[len] = '\0';
+  } else {
+    /* handle error condition */
+    LoggerE("Error while reading link - incorrect length");
+    return result;
+  }
+  result = std::string(buf + strlen("/usr/share/zoneinfo/"));
+
+  LoggerD("tzpath = %s", result.c_str());
+  return result;
+}
+
+/////////////////////////// TimeUtilListeners object ////////////////////////
+static TimeUtilListeners g_time_util_listeners_obj;
+
+static void PostMessage(const char* message, TimeInstance& instance) {
+  LoggerD("Entered");
+
+  JsonValue result{JsonObject{}};
+  JsonObject& result_obj = result.get<JsonObject>();
+  result_obj.insert(std::make_pair("listenerId", picojson::value(message)));
+  Instance::PostMessage(&instance, result.serialize().c_str());
+}
+
+static void OnTimeChangedCallback(keynode_t* /*node*/, void* user_data) {
+  LoggerD("Entered");
+
+  TimeInstance *that = static_cast<TimeInstance*>(user_data);
+  if (!that) {
+    LoggerE("instance is NULL");
+    return;
+  }
+
+  std::string defaultTimezone = GetDefaultTimezone();
+
+  if (g_time_util_listeners_obj.GetCurrentTimezone() != defaultTimezone) {
+    g_time_util_listeners_obj.SetCurrentTimezone(defaultTimezone);
+    PostMessage(kTimezoneListenerId, *that);
+  }
+  PostMessage(kDateTimeListenerId, *that);
+}
+
+void TimeInstance::TimeSetDateTimeChangeListener(const JsonValue& /*args*/,
+                                                 JsonObject& out) {
+  LoggerD("Entered");
+
+  PlatformResult result =
+      g_time_util_listeners_obj.RegisterVconfCallback(kTimeChange, *this);
+  if (result.IsError()) {
+    LoggerE("Error while registering vconf callback");
+    ReportError(result, &out);
+  }
+  else
+    ReportSuccess(out);
+}
+
+void TimeInstance::TimeUnsetDateTimeChangeListener(const JsonValue& /*args*/,
+                                                   JsonObject& out) {
+  LoggerD("Entered");
+
+  PlatformResult result =
+      g_time_util_listeners_obj.UnregisterVconfCallback(kTimeChange);
+  if (result.IsError()) {
+    LoggerE("Failed to unregister vconf callback");
+    ReportError(result, &out);
+  }
+  else
+    ReportSuccess(out);
+}
+
+void TimeInstance::TimeSetTimezoneChangeListener(const JsonValue& /*args*/,
+                                                 JsonObject& out) {
+  LoggerD("Entered");
+
+  PlatformResult result =
+      g_time_util_listeners_obj.RegisterVconfCallback(kTimezoneChange, *this);
+  if (result.IsError()) {
+    LoggerE("Failed to register vconf callback");
+    ReportError(result, &out);
+  }
+  else
+    ReportSuccess(out);
+}
+
+void TimeInstance::TimeUnsetTimezoneChangeListener(const JsonValue& /*args*/,
+                                                   JsonObject& out) {
+  LoggerD("Entered");
+
+  PlatformResult result =
+      g_time_util_listeners_obj.UnregisterVconfCallback(kTimezoneChange);
+  if (result.IsError()) {
+    LoggerE("Failed to unregister vconf callback");
+    ReportError(result, &out);
+  }
+  else
+    ReportSuccess(out);
+}
+
+void TimeInstance::TimeGetMsUTC(const JsonValue& args, JsonObject& out) {
+  LoggerD("Entered");
+
+  std::unique_ptr<UnicodeString> id(new UnicodeString(args.get("timezone").to_str().c_str()));
+  if (id == NULL) {
+    LoggerE("Allocation error");
+    ReportError(out);
+    return;
+  }
+  UDate dateInMs = strtod(args.get("value").to_str().c_str(), NULL);
+  if (errno == ERANGE) {
+    LoggerE("Value out of range");
+    ReportError(out);
+    return;
+  }
+
+  UErrorCode ec = U_ZERO_ERROR;
+  std::unique_ptr<TimeZone> timezone(TimeZone::createTimeZone(*id));
+
+  int32_t rawOffset = 0;
+  int32_t dstOffset = 0;
+  timezone->getOffset(dateInMs, true, rawOffset, dstOffset, ec);
+  if (U_FAILURE(ec)) {
+    LoggerE("Failed to get timezone offset");
+    ReportError(out);
+    return;
+  }
+
+  dateInMs -= (rawOffset + dstOffset);
+
+  ReportSuccess(JsonValue{static_cast<double>(dateInMs)}, out);
+}
+
+}  // namespace time
+}  // namespace extension
diff --git a/webWidgetTCT_device/src/time/time_instance.h b/webWidgetTCT_device/src/time/time_instance.h
new file mode 100755 (executable)
index 0000000..3c5ffa9
--- /dev/null
@@ -0,0 +1,61 @@
+// Copyright (c) 2013 Intel Corporation. All rights reserved.
+// Copyright (c) 2015 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TIME_TIME_INSTANCE_H_
+#define TIME_TIME_INSTANCE_H_
+
+#include "common/extension.h"
+#include "common/picojson.h"
+#include "unicode/unistr.h"
+
+#include <string>
+
+namespace extension {
+namespace time {
+
+typedef picojson::value JsonValue;
+typedef picojson::object JsonObject;
+typedef picojson::array JsonArray;
+typedef std::string JsonString;
+
+class TimeInstance : public common::ParsedInstance {
+ public:
+  TimeInstance();
+  virtual ~TimeInstance();
+
+ private:
+  enum DateTimeFormatType {
+    TIME_FORMAT,
+    DATE_FORMAT,
+    DATE_SHORT_FORMAT,
+    DATETIME_FORMAT
+  };
+
+  void TimeGetAvailableTimeZones(const JsonValue& args, JsonObject& out);
+  void TimeGetDSTTransition(const JsonValue& args, JsonObject& out);
+  void TimeGetLocalTimeZone(const JsonValue& args, JsonObject& out);
+  void TimeGetTimeFormat(const JsonValue& args, JsonObject& out);
+  void TimeGetDateFormat(const JsonValue& args, JsonObject& out);
+  void TimeGetTimeZoneOffset(const JsonValue& args, JsonObject& out);
+  void TimeGetTimeZoneAbbreviation(const JsonValue& args, JsonObject& out);
+  void TimeIsDST(const JsonValue& args, JsonObject& out);
+  void TimeToString(const JsonValue& args, JsonObject& out);
+  void TimeToDateString(const JsonValue& args, JsonObject& out);
+  void TimeToTimeString(const JsonValue& args, JsonObject& out);
+  void TimeSetDateTimeChangeListener(const JsonValue& args, JsonObject& out);
+  void TimeUnsetDateTimeChangeListener(const JsonValue& args, JsonObject& out);
+  void TimeSetTimezoneChangeListener(const JsonValue& args, JsonObject& out);
+  void TimeUnsetTimezoneChangeListener(const JsonValue& args, JsonObject& out);
+  void TimeGetMsUTC(const JsonValue& args, JsonObject& out);
+
+  Locale* getDefaultLocale();
+  UnicodeString getDateTimeFormat(DateTimeFormatType type, bool bLocale);
+  bool toStringByFormat(const JsonValue& args, JsonValue& out,
+                        DateTimeFormatType format);
+};
+}  // namespace time
+}  // namespace extension
+
+#endif  // TIME_TIME_INSTANCE_H_
diff --git a/webWidgetTCT_device/src/tizen-wrt.gyp b/webWidgetTCT_device/src/tizen-wrt.gyp
new file mode 100755 (executable)
index 0000000..38c2aa0
--- /dev/null
@@ -0,0 +1,335 @@
+{
+  'includes':[
+    'common/common.gypi',
+  ],
+
+  'targets': [
+    {
+      'target_name': 'build_all_tizen_extensions',
+      'type': 'none',
+      'dependencies': [
+        'tool/tool.gyp:*',
+        'common/common.gyp:*',
+        'tizen/tizen.gyp:*',
+        'utils/utils.gyp:*',
+      ],
+      'conditions': [
+        [
+          'tizen_feature_account_support==1', {
+            'dependencies': [
+              'account/account.gyp:*',
+            ],
+          },
+        ],
+        [
+          'tizen_feature_alarm_support==1', {
+            'dependencies': [
+              'alarm/alarm.gyp:*',
+            ],
+          },
+        ],
+        [
+          'tizen_feature_application_support==1', {
+            'dependencies': [
+              'application/application.gyp:*',
+            ],
+          },
+        ],
+        [
+          'tizen_feature_archive_support==1', {
+            'dependencies': [
+              'archive/archive.gyp:*'
+            ],
+          },
+        ],
+        [
+          'tizen_feature_badge_support==1', {
+            'dependencies': [
+              'badge/badge.gyp:*',
+            ],
+          },
+        ],
+        [
+          'tizen_feature_bluetooth_support==1', {
+            'dependencies': [
+              'bluetooth/bluetooth.gyp:*',
+            ],
+          },
+        ],
+        [
+          'tizen_feature_bookmark_support==1', {
+            'dependencies': [
+              'bookmark/bookmark.gyp:*',
+            ],
+          },
+        ],
+        [
+          'tizen_feature_calendar_support==1', {
+            'dependencies': [
+              'calendar/calendar.gyp:*',
+            ],
+          },
+        ],
+        [
+          'tizen_feature_callhistory_support==1', {
+            'dependencies': [
+              'callhistory/callhistory.gyp:*',
+            ],
+          },
+        ],
+        [
+          'tizen_feature_contact_support==1', {
+            'dependencies': [
+              'contact/contact.gyp:*',
+            ],
+          },
+        ],
+        [
+          'tizen_feature_content_support==1', {
+            'dependencies': [
+              'content/content.gyp:*',
+            ],
+          },
+        ],
+        [
+          'tizen_feature_datacontrol_support==1', {
+            'dependencies': [
+              'datacontrol/datacontrol.gyp:*',
+            ],
+          },
+        ],
+        [
+          'tizen_feature_datasync_support==1', {
+            'dependencies': [
+              'datasync/datasync.gyp:*',
+            ],
+          },
+        ],
+        [
+          'tizen_feature_download_support==1', {
+            'dependencies': [
+              'download/download.gyp:*',
+            ],
+          },
+        ],
+        [
+          'tizen_feature_exif_support==1', {
+            'dependencies': [
+              'exif/exif.gyp:*',
+            ],
+          },
+        ],
+        [
+          'tizen_feature_filesystem_support==1', {
+            'dependencies': [
+              'filesystem/filesystem.gyp:*',
+            ],
+          },
+        ],
+        [
+          'tizen_feature_fm_radio_support==1', {
+            'dependencies': [
+              'radio/radio.gyp:*',
+            ],
+          },
+        ],
+        [
+          'tizen_feature_key_manager_support==1', {
+            'dependencies': [
+              'keymanager/keymanager.gyp:*',
+            ],
+          },
+        ],
+        [
+          'tizen_feature_ham_support==1', {
+            'dependencies': [
+              'humanactivitymonitor/humanactivitymonitor.gyp:*',
+            ],
+          },
+        ],
+        [
+          'tizen_feature_media_controller_support==1', {
+            'dependencies': [
+              'mediacontroller/mediacontroller.gyp:*',
+            ],
+          },
+        ],
+        [
+          'tizen_feature_media_key_support==1', {
+            'dependencies': [
+              'mediakey/mediakey.gyp:*',
+            ],
+          },
+        ],
+        [
+          'tizen_feature_message_port_support==1', {
+            'dependencies': [
+              'messageport/messageport.gyp:*',
+            ],
+          },
+        ],
+        [
+          'tizen_feature_messaging_support==1', {
+            'dependencies': [
+              'messaging/messaging.gyp:*',
+            ],
+          },
+        ],
+        [
+          'tizen_feature_nbs_support==1', {
+            'dependencies': [
+              'networkbearerselection/networkbearerselection.gyp:*',
+            ],
+          },
+        ],
+        [
+          'tizen_feature_nfc_emulation_support==1', {
+            'dependencies': [
+              'nfc/nfc.gyp:*',
+            ],
+          },
+        ],
+        [
+          'tizen_feature_nfc_support==1', {
+            'dependencies': [
+              'nfc/nfc.gyp:*',
+            ],
+          },
+        ],
+        [
+          'tizen_feature_notification_support==1', {
+            'dependencies': [
+              'notification/notification.gyp:*',
+            ],
+          },
+        ],
+        [
+          'tizen_feature_package_support==1', {
+            'dependencies': [
+              'package/package.gyp:*',
+            ],
+          },
+        ],
+        [
+          'tizen_feature_power_support==1', {
+            'dependencies': [
+              'power/power.gyp:*',
+            ],
+          },
+        ],
+        [
+          'tizen_feature_push_support==1', {
+            'dependencies': [
+              'push/push.gyp:*',
+            ],
+          },
+        ],
+        [
+          'tizen_feature_se_support==1', {
+            'dependencies': [
+              'secureelement/secureelement.gyp:*',
+            ],
+          },
+        ],
+        [
+          'tizen_feature_sensor_support==1', {
+            'dependencies': [
+              'sensor/sensor.gyp:*',
+            ],
+          },
+        ],
+        [
+          'tizen_feature_smart_controller_support==1', {
+            'dependencies': [
+              'smartcontroller/smartcontroller.gyp:*',
+            ],
+          },
+        ],
+        [
+          'tizen_feature_sound_support==1', {
+            'dependencies': [
+              'sound/sound.gyp:*',
+            ],
+          },
+        ],
+        [
+          'tizen_feature_system_info_support==1', {
+            'dependencies': [
+              'systeminfo/systeminfo.gyp:*',
+            ],
+          },
+        ],
+        [
+          'tizen_feature_system_setting_support==1', {
+            'dependencies': [
+              'systemsetting/systemsetting.gyp:*',
+            ],
+          },
+        ],
+        [
+          'tizen_feature_time_support==1', {
+            'dependencies': [
+              'time/time.gyp:*',
+            ],
+          },
+        ],
+        [
+          'tizen_feature_tv_display_support==1', {
+            'dependencies': [
+              'tvdisplay/tvdisplay.gyp:*',
+            ],
+          },
+        ],
+        [
+          'tizen_feature_tvaudio_support==1', {
+            'dependencies': [
+              'tvaudio/tvaudio.gyp:*',
+            ],
+          },
+        ],
+        [
+          'tizen_feature_tvinfo_support==1', {
+            'dependencies': [
+              'tvinfo/tvinfo.gyp:*',
+            ],
+          },
+        ],
+        [
+          'tizen_feature_tvinputdevice_support==1', {
+            'dependencies': [
+              'tvinputdevice/tvinputdevice.gyp:*'
+            ],
+          },
+        ],
+        [
+          'tizen_feature_inputdevice_support==1', {
+            'dependencies': [
+              'inputdevice/inputdevice.gyp:*'
+            ],
+          },
+        ],
+        [
+          'tizen_feature_tvchannel_support==1', {
+            'dependencies': [
+              'tvchannel/tvchannel.gyp:*',
+            ],
+          },
+        ],
+        [
+          'tizen_feature_tvwindow_support==1', {
+            'dependencies': [
+              'tvwindow/tvwindow.gyp:*',
+            ],
+          },
+        ],
+        [
+          'tizen_feature_web_setting_support==1', {
+            'dependencies': [
+              'websetting/websetting.gyp:*',
+            ],
+          },
+        ],
+      ], # end conditions
+    },
+  ], # end targets
+}
diff --git a/webWidgetTCT_device/src/tizen/tizen.gyp b/webWidgetTCT_device/src/tizen/tizen.gyp
new file mode 100755 (executable)
index 0000000..df68e91
--- /dev/null
@@ -0,0 +1,20 @@
+{
+  'includes':[
+    '../common/common.gypi',
+  ],
+  'targets': [
+    {
+      'target_name': 'tizen',
+      'type': 'loadable_module',
+      'dependencies': [
+        '../common/common.gyp:tizen_common',
+      ],
+      'sources': [
+        'tizen.h',
+        'tizen_api.js',
+        'tizen_extension.cc',
+        'tizen_extension.h',
+      ],
+    },
+  ],
+}
diff --git a/webWidgetTCT_device/src/tizen/tizen.h b/webWidgetTCT_device/src/tizen/tizen.h
new file mode 100755 (executable)
index 0000000..5b600f1
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright (c) 2013 Intel Corporation. All rights reserved.
+// Copyright (c) 2015 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TIZEN_TIZEN_H_
+#define TIZEN_TIZEN_H_
+
+#define STR_MATCH_EXACTLY        "EXACTLY"
+#define STR_MATCH_FULLSTRING     "FULLSTRING"
+#define STR_MATCH_CONTAINS       "CONTAINS"
+#define STR_MATCH_STARTSWITH     "STARTSWITH"
+#define STR_MATCH_ENDSWITH       "ENDSWITH"
+#define STR_MATCH_EXISTS         "EXISTS"
+
+#define STR_SORT_ASC             "ASC"
+#define STR_SORT_DESC            "DESC"
+
+#define STR_FILTEROP_OR          "UNION"
+#define STR_FILTEROP_AND         "INTERSECTION"
+
+#endif  // TIZEN_TIZEN_H_
diff --git a/webWidgetTCT_device/src/tizen/tizen_api.js b/webWidgetTCT_device/src/tizen/tizen_api.js
new file mode 100755 (executable)
index 0000000..eaa502b
--- /dev/null
@@ -0,0 +1,475 @@
+// Copyright (c) 2013 Intel Corporation. All rights reserved.
+// Copyright (c) 2015 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Tizen API Specification:
+// https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/tizen.html
+
+
+// WebAPIException and WebAPIError definition moved to src/utils/utils_api.js
+// for compliance reasons. You can find more info there.
+
+
+/**
+ * Filter match flags.
+ * @enum {string}
+ */
+var FilterMatchFlag = {
+  EXACTLY: 'EXACTLY',
+  FULLSTRING: 'FULLSTRING',
+  CONTAINS: 'CONTAINS',
+  STARTSWITH: 'STARTSWITH',
+  ENDSWITH: 'ENDSWITH',
+  EXISTS: 'EXISTS'
+};
+
+
+/**
+ * An enumerator that indicates the sorting order.
+ * @enum {string}
+ */
+var SortModeOrder = {
+  ASC: 'ASC',
+  DESC: 'DESC'
+};
+
+
+/**
+ * An enumerator that indicates the type of composite filter.
+ * @enum {string}
+ */
+var CompositeFilterType = {
+  UNION: 'UNION',
+  INTERSECTION: 'INTERSECTION'
+};
+
+// Tizen Filters
+// either AttributeFilter, AttributeRangeFilter, or CompositeFilter
+function is_tizen_filter(f) {
+  return (f instanceof tizen.AttributeFilter) ||
+         (f instanceof tizen.AttributeRangeFilter) ||
+         (f instanceof tizen.CompositeFilter);
+}
+
+//Extract property by string
+function _extractProperty(obj, attributeName) {
+  var props = attributeName.split('.');
+  for (var i = 0; i < props.length; ++i) {
+    if (obj instanceof Array) {
+      var ret = [];
+      for (var j = 0; j < obj.length; ++j)
+      {
+        ret.push(_extractProperty(obj[j], props.slice(i).join('.')));
+      }
+      return ret;
+    }
+    if (!obj.hasOwnProperty(props[i])) {
+      if (i === props.length - 1) {
+        throw new WebAPIException('InvalidValuesError', 'Property "' + attributeName +
+                '" is not valid');
+      }
+      return null;
+    }
+    obj = obj[props[i]];
+  }
+  return obj;
+}
+
+
+/**
+ * This is a common interface used by different types of object filters.
+ */
+var AbstractFilter = function() {};
+
+
+/**
+ * Represents a set of filters.
+ */
+exports.AttributeFilter = function(attrName, matchFlag, matchValue) {
+
+  xwalk.utils.validator.isConstructorCall(this, exports.AttributeFilter);
+
+  var name_ = '';
+  var flag_ = 'EXACTLY';
+  var value_ = null;
+
+  function attributeNameSetter(name) {
+    name_ = String(name);
+  }
+
+  if (arguments.length > 0)
+    attributeNameSetter(attrName);
+
+  function matchFlagSetter(flag) {
+    if (Object.keys(FilterMatchFlag).indexOf(flag) >= 0)
+      flag_ = flag;
+  }
+
+  function matchValueSetter(value) {
+    value_ = value;
+  }
+
+  if (arguments.length > 2) {
+    matchFlagSetter(matchFlag);
+    matchValueSetter(matchValue);
+  } else if (arguments.length > 1) {
+    // if matchValue is not used then matchFlag is set to 'EXISTS'.
+    matchFlagSetter('EXISTS');
+  }
+
+  Object.defineProperties(this, {
+    attributeName: {
+      enumerable: true,
+      set: attributeNameSetter,
+      get: function() {
+        return name_;
+      }
+    },
+    matchFlag: {
+      enumerable: true,
+      set: matchFlagSetter,
+      get: function() {
+        return flag_;
+      }
+    },
+    matchValue: {
+      enumerable: true,
+      set: matchValueSetter,
+      get: function() {
+        return value_;
+      }
+    }
+  });
+};
+exports.AttributeFilter.prototype = new AbstractFilter();
+
+//TODO: Move filtering to native code
+exports.AttributeFilter.prototype._filter = function(element) {
+  var elemValue = _extractProperty(element, this.attributeName);
+
+  if (!(elemValue instanceof Array)) {
+    elemValue = [elemValue];
+  }
+
+  var ret = false;
+  for (var i = 0; i < elemValue.length; ++i) {
+    var elemValueStr = String(elemValue[i]);
+    var elemValueStrU = elemValueStr.toUpperCase();
+    var matchValueStr = String(this.matchValue);
+    var matchValueStrU = matchValueStr.toUpperCase();
+
+    switch (this.matchFlag) {
+      case 'EXACTLY':
+        ret = elemValue[i] === this.matchValue;
+        break;
+      case 'FULLSTRING':
+        ret = elemValueStrU === matchValueStrU;
+        break;
+      case 'CONTAINS':
+        ret = elemValueStrU.indexOf(matchValueStrU) > -1;
+        break;
+      case 'STARTSWITH':
+        ret = elemValueStrU.indexOf(matchValueStrU) === 0;
+        break;
+      case 'ENDSWITH':
+        ret = elemValueStrU.lastIndexOf(matchValueStrU) +
+                matchValueStrU.length === elemValueStrU.length;
+        break;
+      case 'EXISTS':
+        ret = elemValue[i] !== undefined;
+        break;
+    }
+    if (ret) {
+      return ret;
+    }
+  }
+  return ret;
+};
+exports.AttributeFilter.prototype.constructor = exports.AttributeFilter;
+
+
+/**
+ * Represents a filter based on an object attribute which has values that are
+ * within a particular range.
+ */
+exports.AttributeRangeFilter = function(attrName, start, end) {
+
+  xwalk.utils.validator.isConstructorCall(this, exports.AttributeRangeFilter);
+
+  var name_ = '';
+  var start_ = null;
+  var end_ = null;
+
+  function attributeNameSetter(name) {
+    name_ = String(name);
+  }
+
+  if (arguments.length > 0)
+    attributeNameSetter(attrName);
+
+  function initSetter(init) {
+    start_ = init;
+  }
+
+  if (arguments.length > 1)
+    initSetter(start);
+
+  function endSetter(end) {
+    end_ = end;
+  }
+
+  if (arguments.length > 2)
+    endSetter(end);
+
+  Object.defineProperties(this, {
+    attributeName: {
+      enumerable: true,
+      set: attributeNameSetter,
+      get: function() {
+        return name_;
+      }
+    },
+    initialValue: {
+      enumerable: true,
+      set: initSetter,
+      get: function() {
+        return start_;
+      }
+    },
+    endValue: {
+      enumerable: true,
+      set: endSetter,
+      get: function() {
+        return end_;
+      }
+    }
+  });
+};
+
+exports.AttributeRangeFilter.prototype = new AbstractFilter();
+
+//TODO: Move filtering to native code
+exports.AttributeRangeFilter.prototype._filter = function(element) {
+  var elemValue = _extractProperty(element, this.attributeName);
+
+  if (!(elemValue instanceof Array)) {
+    elemValue = [elemValue];
+  }
+
+  for (var i = 0; i < elemValue.length; ++i) {
+    var value = elemValue[i];
+
+    if ((this.initialValue !== undefined && this.initialValue !== null) &&
+            (this.endValue !== undefined && this.endValue !== null)) {
+      if (value instanceof tizen.TZDate) {
+        if (this.initialValue.earlierThan(value) && this.endValue.laterThan(value)) {
+          return true;
+        }
+      } else {
+        if (this.initialValue <= value && this.endValue > value) {
+          return true;
+        }
+      }
+    } else if ((this.initialValue !== undefined && this.initialValue !== null) &&
+            (this.endValue === undefined || this.endValue === null)) {
+      if (value instanceof tizen.TZDate) {
+        if (this.initialValue.earlierThan(value)) {
+          return true;
+        }
+      } else {
+        if (this.initialValue <= value) {
+          return true;
+        }
+      }
+    } else if ((this.initialValue === undefined || this.initialValue === null) &&
+            (this.endValue !== undefined && this.endValue !== null)) {
+      if (value instanceof tizen.TZDate) {
+        if (this.endValue.laterThan(value)) {
+          return true;
+        }
+      } else {
+        if (this.endValue > value) {
+          return true;
+        }
+      }
+    }
+  }
+  return false;
+};
+
+exports.AttributeRangeFilter.prototype.constructor = exports.AttributeRangeFilter;
+
+
+/**
+ * Represents a set of filters.
+ */
+exports.CompositeFilter = function(type, filters) {
+
+  xwalk.utils.validator.isConstructorCall(this, exports.CompositeFilter);
+
+  var filterTypes = Object.keys(CompositeFilterType);
+
+  var type_ = filterTypes[0];
+  var filters_ = [];
+
+  function typeSetter(filterType) {
+    if (filterTypes.indexOf(filterType) >= 0)
+      type_ = filterType;
+  }
+
+  if (arguments.length > 0)
+    typeSetter(type);
+
+  function filtersSetter(filterList) {
+    if (!(filterList instanceof Array))
+      return;
+
+    for (var i in filterList) {
+      var valid = (filterList[i] instanceof AbstractFilter);
+      if (!valid)
+        return;
+    }
+
+    filters_ = filterList.slice(0);
+  }
+
+  if (arguments.length > 1)
+    filtersSetter(filters);
+
+  Object.defineProperties(this, {
+    type: {
+      enumerable: true,
+      set: typeSetter,
+      get: function() {
+        return type_;
+      }
+    },
+    filters: {
+      enumerable: true,
+      set: filtersSetter,
+      get: function() {
+        return filters_;
+      }
+    }
+  });
+};
+
+exports.CompositeFilter.prototype = new AbstractFilter();
+
+//TODO: Move filtering to native code
+exports.CompositeFilter.prototype._filter = function(element) {
+  var filters = this.filters;
+  if (this.type === 'UNION') {
+    for (var i = 0; i < filters.length; ++i) {
+      if (filters[i]._filter(element)) {
+        return true;
+      }
+    }
+    return false;
+  } else if (this.type === 'INTERSECTION') {
+    if (filters.length === 0)
+      return false;
+    for (var i = 0; i < filters.length; ++i) {
+      if (!filters[i]._filter(element)) {
+        return false;
+      }
+    }
+    return true;
+  }
+};
+
+exports.CompositeFilter.prototype.constructor = exports.CompositeFilter;
+
+
+/**
+ * SortMode is a common interface used for sorting of queried data.
+ */
+exports.SortMode = function(attrName, order) {
+
+  xwalk.utils.validator.isConstructorCall(this, exports.SortMode);
+
+  var sortModeOrder = Object.keys(SortModeOrder);
+
+  var attributeName_ = '';
+  var order_ = 'ASC';
+
+  function nameSetter(name) {
+    attributeName_ = String(name);
+  }
+
+  if (arguments.length > 0)
+    nameSetter(attrName);
+
+  function orderSetter(sortOrder) {
+    if (sortModeOrder.indexOf(sortOrder) >= 0)
+      order_ = sortOrder;
+  }
+
+  if (arguments.length > 1)
+    orderSetter(order);
+
+  Object.defineProperties(this, {
+    attributeName: {
+      enumerable: true, set: nameSetter, get: function() {
+        return attributeName_;
+      }
+    },
+    order: {
+      enumerable: true, set: orderSetter, get: function() {
+        return order_;
+      }
+    }
+  });
+};
+exports.SortMode.prototype.constructor = exports.SortMode;
+
+
+/**
+ * Represents a point (latitude and longitude) in the map coordinate system.
+ */
+exports.SimpleCoordinates = function(lat, lng) {
+
+  xwalk.utils.validator.isConstructorCall(this, exports.SimpleCoordinates);
+
+  var latitude = 0;
+  var longitude = 0;
+
+  function latSetter(lat) {
+    var tmp = Number(lat);
+    if (!isNaN(tmp)) {
+      if (tmp > 90) tmp = 90;
+      else if (tmp < -90) tmp = -90;
+
+      latitude = tmp;
+    }
+  }
+
+  latSetter(lat);
+
+  function lonSetter(lon) {
+    var tmp = Number(lon);
+    if (!isNaN(tmp)) {
+      if (tmp > 180) tmp = 180;
+      else if (tmp < -180) tmp = -180;
+
+      longitude = tmp;
+    }
+  }
+
+  lonSetter(lng);
+
+  Object.defineProperties(this, {
+    latitude: {
+      enumerable: true, set: latSetter, get: function() {
+        return latitude;
+      }
+    },
+    longitude: {
+      enumerable: true, set: lonSetter, get: function() {
+        return longitude;
+      }
+    }
+  });
+};
+exports.SimpleCoordinates.prototype.constructor = exports.SimpleCoordinates;
diff --git a/webWidgetTCT_device/src/tizen/tizen_extension.cc b/webWidgetTCT_device/src/tizen/tizen_extension.cc
new file mode 100755 (executable)
index 0000000..1769984
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright (c) 2013 Intel Corporation. All rights reserved.
+// Copyright (c) 2015 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tizen/tizen_extension.h"
+
+// This will be generated from tizen_api.js.
+extern const char kSource_tizen_api[];
+
+common::Extension* CreateExtension() {
+  return new TizenExtension;
+}
+
+TizenExtension::TizenExtension() {
+  SetExtensionName("tizen");
+  SetJavaScriptAPI(kSource_tizen_api);
+}
+
+TizenExtension::~TizenExtension() {}
diff --git a/webWidgetTCT_device/src/tizen/tizen_extension.h b/webWidgetTCT_device/src/tizen/tizen_extension.h
new file mode 100755 (executable)
index 0000000..2a6228e
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright (c) 2013 Intel Corporation. All rights reserved.
+// Copyright (c) 2015 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TIZEN_TIZEN_EXTENSION_H_
+#define TIZEN_TIZEN_EXTENSION_H_
+
+#include "common/extension.h"
+
+class TizenExtension : public common::Extension {
+ public:
+  TizenExtension();
+  virtual ~TizenExtension();
+};
+
+#endif  // TIZEN_TIZEN_EXTENSION_H_
diff --git a/webWidgetTCT_device/src/tool/desc_gentool.cc b/webWidgetTCT_device/src/tool/desc_gentool.cc
new file mode 100755 (executable)
index 0000000..015cf89
--- /dev/null
@@ -0,0 +1,217 @@
+#include <iostream>
+#include <string>
+#include <vector>
+#include <map>
+#include <functional>
+
+#include <dlfcn.h>
+#include <dirent.h>
+#include <unistd.h>
+
+#include <common/extension.h>
+
+static std::string prefix_ = "libtizen";
+static std::string postfix_ = ".so";
+static std::string target_path_ = "/usr/lib/tizen-extensions-crosswalk/";
+static std::vector<std::string> apinamespaces = {"tizen", "xwalk"};
+
+typedef common::Extension *(*CreateExtensionFunc)(void);
+
+struct module_description {
+  std::string name;
+  std::string lib;
+  std::vector<std::string> entries;
+};
+
+
+static XW_Extension ext = 0;
+static std::map<XW_Extension, module_description> descriptions;
+
+#ifndef JSON_MINIFY
+  #define PRINT_TAB() std::cout << "\t"
+#else
+  #define PRINT_TAB()
+#endif 
+
+void print_json() {
+  std::cout << "[" << std::endl;
+  for (const auto& kv : descriptions) {
+    const module_description &desc = kv.second;
+
+    std::string::size_type n = desc.name.find('.');
+    std::string ns =
+        n == std::string::npos ? desc.name : desc.name.substr(0, n);
+
+    if (std::find(apinamespaces.begin(), apinamespaces.end(), ns) ==
+        apinamespaces.end()) {
+      continue;
+    }
+
+    PRINT_TAB();
+    std::cout << "{" << std::endl;
+    PRINT_TAB();
+    PRINT_TAB();
+    std::cout << "\"name\":\"" << desc.name << "\"," << std::endl;
+    PRINT_TAB();
+    PRINT_TAB();
+    std::cout << "\"lib\":\"" << desc.lib << "\"," << std::endl;
+    PRINT_TAB();
+    PRINT_TAB();
+    std::cout << "\"entry_points\": [";
+    for (std::vector<std::string>::size_type i=0; i<desc.entries.size(); i++) {
+      if (i != 0) {
+        std::cout << ",";
+      }
+      std::cout << "\"" << desc.entries[i] << "\"";
+    }
+    std::cout << "]" << std::endl;
+    PRINT_TAB();
+    std::cout << "}";
+    if (kv.first != ext) {
+      std::cout << ",";
+    }
+    std::cout << std::endl;
+  }
+  std::cout << "]" << std::endl;
+}
+
+const void* get_interface(const char* name) {
+  if (!strcmp(name, XW_CORE_INTERFACE_1)) {
+    static const XW_CoreInterface coreInterface1 = {
+      [](XW_Extension extension, const char* name) {
+        module_description *desc = &descriptions[extension];
+        desc->name = name;
+      },
+      [](XW_Extension extension, const char* api) {},
+      [](XW_Extension extension, XW_CreatedInstanceCallback created,
+         XW_DestroyedInstanceCallback destroyed) {},
+      [](XW_Extension extension, XW_ShutdownCallback shutdown_callback) {},
+      [](XW_Instance instance, void* data) {},
+      [](XW_Instance instance) -> void* { return nullptr; }
+      };
+    return &coreInterface1;
+  }
+
+  if (!strcmp(name, XW_INTERNAL_ENTRY_POINTS_INTERFACE_1)) {
+    static const XW_Internal_EntryPointsInterface entryPointsInterface1 = {
+      [](XW_Extension extension, const char** entries) {
+        module_description *desc = &descriptions[extension];
+        for (int i=0; entries[i]; i++) {
+          desc->entries.push_back(std::string(entries[i]));
+        }
+      }
+    };
+    return &entryPointsInterface1;
+  }
+  
+  if (!strcmp(name, XW_MESSAGING_INTERFACE_1)) {
+    static const XW_MessagingInterface_1 messagingInterface1 = {
+      [](XW_Extension extension, XW_HandleMessageCallback handle_message) {
+      },
+      [](XW_Instance instance, const char* message) {
+      }
+    };
+    return &messagingInterface1;
+  }
+
+  if (!strcmp(name, XW_INTERNAL_SYNC_MESSAGING_INTERFACE_1)) {
+    static const XW_Internal_SyncMessagingInterface syncMessagingInterface1 = {
+      [](XW_Extension extension, XW_HandleSyncMessageCallback handle_sync_msg) {
+      },
+      [](XW_Instance instance, const char* reply){
+      }
+    };
+    return &syncMessagingInterface1;
+  }
+
+  if (!strcmp(name, XW_INTERNAL_RUNTIME_INTERFACE_1)) {
+    static const XW_Internal_RuntimeInterface_1 runtimeInterface1 = {
+      [](XW_Extension extension, const char* key, char* value, size_t vlen) {
+      }
+    };
+    return &runtimeInterface1;
+  }
+
+  if (!strcmp(name, XW_INTERNAL_PERMISSIONS_INTERFACE_1)) {
+    static const XW_Internal_PermissionsInterface_1 permissionsInterface1 = {
+      [](XW_Extension extension, const char* api_name) -> int {
+        return XW_ERROR;
+      },
+      [](XW_Extension extension, const char* perm_table) -> int {
+        return XW_ERROR;
+      }
+    };
+    return &permissionsInterface1;
+  }
+
+  return NULL;
+}
+
+int main(int argc, char* argv[]) {
+  if (argc < 2) {
+    std::cerr << "Need tizen crosswalk path" << std::endl;
+    return -1;
+  }
+  std::string tce_path = argv[1];
+  
+  if (tce_path.empty()) {
+    std::cerr << "Invalid tizen crosswalk path" << std::endl;
+    return -1;
+  }
+
+  DIR * dir;
+  int status = 0;
+  struct dirent entry = {0};
+  struct dirent* result = nullptr;
+  if ((dir = opendir(tce_path.c_str())) != NULL) {
+    while ((status = readdir_r(dir, &entry, &result)) == 0 && result != nullptr) {
+      std::string fname = result->d_name;
+
+      if (fname.size() >= prefix_.size() + postfix_.size() &&
+          !fname.compare(0, prefix_.size(), prefix_) &&
+          !fname.compare(fname.size() - postfix_.size(), postfix_.size(),
+                        postfix_)) {
+        std::string so_path = tce_path + "/" + fname;
+        void *handle = dlopen(so_path.c_str(), RTLD_LAZY);
+        if (handle == NULL) {
+          std::cerr << "cannot open " << so_path << std::endl;
+          char* error = dlerror();
+          std::cerr << "Error >>" << ( (error == NULL) ? "NULL" : error) << std::endl;
+          return -1;
+        }
+
+        XW_Initialize_Func initialize = reinterpret_cast<XW_Initialize_Func>(
+                dlsym(handle, "XW_Initialize"));
+
+        if (!initialize) {
+          std::cerr << "Can not loading extension " << fname << std::endl;
+        } else {
+          ext++;
+          descriptions[ext] = module_description();
+          descriptions[ext].lib = target_path_ + fname;
+          int ret = initialize(ext, get_interface);
+          if (ret != XW_OK) {
+            std::cerr << "Error loading extension " << fname << std::endl;
+          }
+        }
+
+        // some Shared libraries have static finalizer.
+        // __attribute__((destructor)) this gcc extension makes finalizer.
+        // if close it, it can makes segfault.
+        // True, It's shared object's problem. but we can't fix it.
+        // so don't close it in only this tool. just finish process.
+        //
+        // dlclose(handle);
+      }
+    }
+    closedir(dir);
+
+    print_json();
+  } else {
+    std::cerr << "path not exist : " << tce_path << std::endl;
+    return -1;
+  }
+
+  // it would be need for ignore loaded libraries destructor
+  _exit(0);
+}
diff --git a/webWidgetTCT_device/src/tool/tool.gyp b/webWidgetTCT_device/src/tool/tool.gyp
new file mode 100755 (executable)
index 0000000..384c34c
--- /dev/null
@@ -0,0 +1,25 @@
+{
+    'target_defaults': {
+        'variables': {'packages': ['dlog']},
+        'includes': [
+            '../common/pkg-config.gypi'
+        ]
+    },
+    'targets' : [
+        {
+            'target_name': 'desc_gentool',
+            'cflags': [
+                '-std=c++0x',
+                '-Wall'
+            ],
+            'link_settings': {'libraries': [ '-ldl'], },
+            'include_dirs': [
+                '../'
+            ],
+            'type': 'executable',
+            'sources': [
+                'desc_gentool.cc'
+            ]
+        }
+    ]
+}
diff --git a/webWidgetTCT_device/src/tvaudio/tvaudio.gyp b/webWidgetTCT_device/src/tvaudio/tvaudio.gyp
new file mode 100755 (executable)
index 0000000..0fe7e7a
--- /dev/null
@@ -0,0 +1,39 @@
+{
+  'includes':[
+    '../common/common.gypi',
+  ],
+  'targets': [
+    {
+      'target_name': 'tizen_tvaudio',
+      'type': 'loadable_module',
+      'dependencies': [
+        '../common/common.gyp:tizen_common',
+      ],
+      'sources': [
+        'tvaudio_api.js',
+        'tvaudio_extension.cc',
+        'tvaudio_extension.h',
+        'tvaudio_instance.cc',
+        'tvaudio_instance.h',
+        'tvaudio_manager.cc',
+        'tvaudio_manager.h'
+      ],
+      'includes': [
+        '../common/pkg-config.gypi',
+      ],
+      'conditions': [
+        ['tizen == 1', {
+          'variables': {
+            'packages': [
+              'glib-2.0',
+              'libavoc',
+              'capi-media-audio-io',
+              'capi-media-sound-manager',
+              'capi-media-sound-manager-tv'
+            ]
+          },
+        }],
+      ],
+    },
+  ],
+}
diff --git a/webWidgetTCT_device/src/tvaudio/tvaudio_api.js b/webWidgetTCT_device/src/tvaudio/tvaudio_api.js
new file mode 100755 (executable)
index 0000000..42c76f2
--- /dev/null
@@ -0,0 +1,244 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+var native = new xwalk.utils.NativeManager(extension);
+var validator = xwalk.utils.validator;
+var types = validator.Types;
+
+
+/**
+ * @type {string}
+ * @const
+ */
+var VOLUME_CHANGE_LISTENER = 'VolumeChangeCallback';
+
+
+
+/**
+ * This class provides access to the API functionalities through
+ * the tizen.tvaudiocontrol interface.
+ * @constructor
+ */
+function AudioControlManager() {
+  if (!(this instanceof AudioControlManager)) {
+    throw new TypeError;
+  }
+}
+
+
+
+/**
+ * Turns on or off the silent mode.
+ * @param {!boolean} mute  The mute state
+ *     (true = turn on the silent mode, false = turn off the silent mode)
+ */
+
+AudioControlManager.prototype.setMute = function(mute) {
+  var args = validator.validateArgs(arguments, [
+    {name: 'mute', type: types.BOOLEAN}
+  ]);
+
+  var ret = native.callSync('AudioControlManager_setMute', {
+    mute: args.mute
+  });
+
+  if (native.isFailure(ret)) {
+    throw native.getErrorObject(ret);
+  }
+};
+
+
+/**
+ * Gets the mute state.
+ * @return {boolean} 'true' if sound is muted else 'false'
+ */
+AudioControlManager.prototype.isMute = function() {
+  var ret = native.callSync('AudioControlManager_isMute');
+
+  if (native.isFailure(ret)) {
+    throw native.getErrorObject(ret);
+  }
+
+  return native.getResultObject(ret);
+};
+
+
+/**
+ * Changes the volume level.
+ * @param {!number} volume The value of volume
+ *     (the available volume range is 0 ~ 100)
+ */
+AudioControlManager.prototype.setVolume = function(volume) {
+
+  var args = validator.validateArgs(arguments, [
+    {name: 'volume', type: types.UNSIGNED_LONG}
+  ]);
+
+  if (args.volume < 0 || args.volume > 100) {
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+        'Volume is out of range: ' + args.volume, 'InvalidValuesError');
+  }
+
+  if (arguments.length < 1) {
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+        'no volume argument: ' + arguments.length, 'InvalidValuesError');
+    }
+
+  var ret = native.callSync('AudioControlManager_setVolume', {
+    volume: args.volume
+  });
+
+  if (native.isFailure(ret)) {
+    throw native.getErrorObject(ret);
+  }
+};
+
+
+/**
+ * Increases the volume by 1 level.
+ */
+AudioControlManager.prototype.setVolumeUp = function() {
+  var ret = native.callSync('AudioControlManager_setVolumeUp');
+
+  if (native.isFailure(ret)) {
+    throw native.getErrorObject(ret);
+  }
+};
+
+
+/**
+ * Decreases the volume by 1 level.
+ */
+AudioControlManager.prototype.setVolumeDown = function() {
+  var ret = native.callSync('AudioControlManager_setVolumeDown');
+
+  if (native.isFailure(ret)) {
+    throw native.getErrorObject(ret);
+  }
+};
+
+
+/**
+ * Gets the current volume level.
+ * @return {number} The current volume (the volume range is 0 ~ 100)
+ */
+AudioControlManager.prototype.getVolume = function() {
+  var ret = native.callSync('AudioControlManager_getVolume');
+  if (native.isFailure(ret)) {
+    throw native.getErrorObject(ret);
+  }
+  return native.getResultObject(ret);
+};
+
+
+/**
+ * Registers a volume change callback for getting notified
+ * when TV volume has been changed.
+ *
+ * @param {!function} listener The method to invoke
+ *                    when the volume has been changed.
+ */
+AudioControlManager.prototype.setVolumeChangeListener = function(listener) {
+  var args = validator.validateArgs(arguments, [
+    {name: 'listener', type: types.FUNCTION}
+  ]);
+
+  native.removeListener(VOLUME_CHANGE_LISTENER);
+
+  var ret = native.callSync('AudioControlManager_setVolumeChangeListener');
+
+  if (native.isFailure(ret)) {
+    throw native.getErrorObject(ret);
+  }
+
+  native.addListener(VOLUME_CHANGE_LISTENER, function(msg) {
+    args.listener(msg.volume);
+  });
+};
+
+
+/**
+ * Unregisters the volume change callback for detecting the volume changes.
+ */
+AudioControlManager.prototype.unsetVolumeChangeListener = function() {
+    var ret = native.callSync('AudioControlManager_unsetVolumeChangeListener');
+
+    if (native.isFailure(ret)) {
+      throw native.getErrorObject(ret);
+    }
+
+  native.removeListener(VOLUME_CHANGE_LISTENER);
+};
+
+
+/**
+ * Gets the current audio output mode.
+ * @return {AudioOutputMode} The current audio output mode
+ */
+AudioControlManager.prototype.getOutputMode = function() {
+  var ret = native.callSync('AudioControlManager_getOutputMode');
+  if (native.isFailure(ret)) {
+    throw native.getErrorObject(ret);
+  }
+  return native.getResultObject(ret);
+};
+
+
+/**
+ * Allowed types of sound
+ * They should correspond to values in native layer and .pcm files
+ */
+var AudioBeepType = [
+  'MOVE', // indented use the same sound
+    'UP',
+    'DOWN',
+    'LEFT',
+    'RIGHT',
+    'PAGE_LEFT',
+    'PAGE_RIGHT',
+  'BACK',
+  'SELECT',
+  'CANCEL',
+  'WARNING',
+  'KEYPAD',
+  'KEYPAD_ENTER',
+  'KEYPAD_DEL',
+  'PREPARING'
+];
+Object.freeze(AudioBeepType);
+
+
+/**
+ * Plays one of specific sounds.
+ * @param {!AudioBeepType} beep The Sound to play.
+ */
+AudioControlManager.prototype.playSound = function(beep) {
+  var args = validator.validateArgs(arguments, [{
+    name: 'type',
+    type: validator.Types.ENUM,
+    values: AudioBeepType // AudioBeepType
+  }]);
+
+  var ret = native.callSync('AudioControlManager_playSound',
+                            {type: args.type});
+  if (native.isFailure(ret)) {
+    throw native.getErrorObject(ret);
+  }
+  return;
+};
+
+// Exports
+exports = new AudioControlManager();
diff --git a/webWidgetTCT_device/src/tvaudio/tvaudio_extension.cc b/webWidgetTCT_device/src/tvaudio/tvaudio_extension.cc
new file mode 100755 (executable)
index 0000000..1cf303b
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2015 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 "tvaudio/tvaudio_extension.h"
+#include "tvaudio/tvaudio_instance.h"
+
+// This will be generated from tvaudio_api.js
+extern const char kSource_tvaudio_api[];
+
+namespace extension {
+namespace tvaudio {
+
+TVAudioExtension::TVAudioExtension() {
+    SetExtensionName("tizen.tvaudiocontrol");
+    SetJavaScriptAPI(kSource_tvaudio_api);
+}
+
+TVAudioExtension::~TVAudioExtension() {}
+
+AudioControlManager& TVAudioExtension::manager() {
+    // Initialize API on first request
+    return AudioControlManager::getInstance();
+}
+
+common::Instance* TVAudioExtension::CreateInstance() {
+    return new TVAudioInstance;
+}
+
+}  // namespace tvaudio
+}  // namespace extension
+
+common::Extension* CreateExtension() {
+    return new extension::tvaudio::TVAudioExtension;
+}
diff --git a/webWidgetTCT_device/src/tvaudio/tvaudio_extension.h b/webWidgetTCT_device/src/tvaudio/tvaudio_extension.h
new file mode 100755 (executable)
index 0000000..a53e2dc
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2015 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 SRC_TVAUDIO_TVAUDIO_EXTENSION_H_
+#define SRC_TVAUDIO_TVAUDIO_EXTENSION_H_
+
+#include "common/extension.h"
+#include "tvaudio/tvaudio_manager.h"
+
+namespace extension {
+namespace tvaudio {
+
+class TVAudioExtension : public common::Extension {
+ public:
+    TVAudioExtension();
+    virtual ~TVAudioExtension();
+
+    AudioControlManager& manager();
+
+ private:
+    virtual common::Instance* CreateInstance();
+};
+
+}  // namespace tvaudio
+}  // namespace extension
+
+#endif  // SRC_TVAUDIO_TVAUDIO_EXTENSION_H_
+
diff --git a/webWidgetTCT_device/src/tvaudio/tvaudio_instance.cc b/webWidgetTCT_device/src/tvaudio/tvaudio_instance.cc
new file mode 100755 (executable)
index 0000000..61e7926
--- /dev/null
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2015 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 <functional>
+#include <map>
+#include <string>
+
+#include "common/picojson.h"
+#include "common/logger.h"
+#include "common/platform_exception.h"
+
+#include "tvaudio/tvaudio_instance.h"
+#include "tvaudio/tvaudio_manager.h"
+
+namespace extension {
+namespace tvaudio {
+
+namespace {
+const std::map<AudioOutputMode, std::string> AudioOutputModeMap = {
+    {PCM, "PCM"},
+    {DOLBY, "DOLBY"},
+    {DTS, "DTS"},
+    {AAC, "AAC"}
+};
+}  // namespace
+
+TVAudioInstance::TVAudioInstance() {
+    LoggerD("Enter");
+    using std::placeholders::_1;
+    using std::placeholders::_2;
+    #define REGISTER_SYNC(c, x) \
+      RegisterSyncHandler(c, std::bind(&TVAudioInstance::x, this, _1, _2));
+    REGISTER_SYNC("AudioControlManager_setMute", setMute);
+    REGISTER_SYNC("AudioControlManager_isMute", isMute);
+    REGISTER_SYNC("AudioControlManager_setVolume", setVolume);
+    REGISTER_SYNC("AudioControlManager_setVolumeUp", setVolumeUp);
+    REGISTER_SYNC("AudioControlManager_setVolumeDown", setVolumeDown);
+    REGISTER_SYNC("AudioControlManager_getVolume", getVolume);
+    REGISTER_SYNC("AudioControlManager_getOutputMode", getOutputMode);
+    REGISTER_SYNC("AudioControlManager_setVolumeChangeListener", setVolumeChangeListener);
+    REGISTER_SYNC("AudioControlManager_unsetVolumeChangeListener", unsetVolumeChangeListener);
+    REGISTER_SYNC("AudioControlManager_playSound", playSound);
+    #undef REGISTER_SYNC
+}
+
+TVAudioInstance::~TVAudioInstance() {
+    LoggerD("Enter");
+}
+
+void TVAudioInstance::setMute(const picojson::value& args,
+        picojson::object& out) {
+    LoggerD("Enter");
+    bool mute = args.get("mute").get<bool>();
+    common::PlatformResult result =
+            AudioControlManager::getInstance().setMute(mute);
+    if (result.IsError()) {
+        LoggerD("Error occured");
+        ReportError(result, &out);
+    } else {
+        picojson::value result;
+        ReportSuccess(result, out);
+    }
+}
+
+void TVAudioInstance::isMute(const picojson::value& args,
+        picojson::object& out) {
+    LoggerD("Enter");
+    bool mute;
+    common::PlatformResult result =
+            AudioControlManager::getInstance().isMute(mute);
+    if (result.IsError()) {
+        LoggerD("Error occured");
+        ReportError(result, &out);
+    } else
+        ReportSuccess(picojson::value(mute), out);
+}
+
+void TVAudioInstance::setVolume(const picojson::value& args,
+        picojson::object& out) {
+    LoggerD("Enter");
+    double volume = args.get("volume").get<double>();
+    common::PlatformResult result =
+            AudioControlManager::getInstance().setVolume(volume);
+    if (result.IsError()) {
+        LoggerD("Error occured");
+        ReportError(result, &out);
+    } else {
+        picojson::value result;
+        ReportSuccess(result, out);
+    }
+}
+
+void TVAudioInstance::setVolumeUp(const picojson::value& args,
+        picojson::object& out) {
+    LoggerD("Enter");
+    common::PlatformResult result =
+            AudioControlManager::getInstance().setVolumeUp();
+    if (result.IsError()) {
+        LoggerD("Error occured");
+        ReportError(result, &out);
+    } else {
+        picojson::value result;
+        ReportSuccess(result, out);
+    }
+}
+
+void TVAudioInstance::setVolumeDown(const picojson::value& args,
+        picojson::object& out) {
+    LoggerD("Enter");
+    common::PlatformResult result =
+            AudioControlManager::getInstance().setVolumeDown();
+    if (result.IsError()) {
+        LoggerD("Error occured");
+        ReportError(result, &out);
+    } else {
+        picojson::value result;
+        ReportSuccess(result, out);
+    }
+}
+
+void TVAudioInstance::getVolume(const picojson::value& args,
+        picojson::object& out) {
+    LoggerD("Enter");
+    u_int16_t volume;
+    common::PlatformResult result =
+            AudioControlManager::getInstance().getVolume(volume);
+    if (result.IsError()) {
+        LoggerD("Error occured");
+        ReportError(result, &out);
+    } else {
+        picojson::value result = picojson::value(static_cast<double>(volume));
+        ReportSuccess(result, out);
+    }
+}
+
+void TVAudioInstance::getOutputMode(const picojson::value& args,
+        picojson::object& out) {
+    LoggerD("Enter");
+    AudioOutputMode mode;
+    common::PlatformResult result =
+            AudioControlManager::getInstance().getOutputMode(mode);
+    if (result.IsError()) {
+        LoggerD("Error occured");
+        ReportError(result, &out);
+    } else if (AudioOutputModeMap.find(mode) == AudioOutputModeMap.end()) {
+        LoggerE("Unknown mode type: %d", mode);
+        ReportError(common::PlatformResult(common::ErrorCode::UNKNOWN_ERR,
+            "Uknown audio output mode"), &out);
+    } else {
+        ReportSuccess(picojson::value(AudioOutputModeMap.at(mode)), out);
+    }
+}
+
+void TVAudioInstance::setVolumeChangeListener(const picojson::value& args,
+        picojson::object& out) {
+    common::PlatformResult result =
+            AudioControlManager::getInstance().registerVolumeChangeListener(this);
+    if (result.IsError()) {
+        LoggerD("Error occured");
+        ReportError(result, &out);
+    } else {
+        picojson::value result;
+        ReportSuccess(result, out);
+    }
+}
+
+void TVAudioInstance::unsetVolumeChangeListener(const picojson::value& args,
+        picojson::object& out) {
+    AudioControlManager::getInstance().unregisterVolumeChangeListener();
+    ReportSuccess(out);
+}
+
+void TVAudioInstance::onVolumeChangeCallback(u_int16_t volume) {
+  LoggerD("Enter");
+    picojson::value event = picojson::value(picojson::object());
+    picojson::object& obj = event.get<picojson::object>();
+    obj["listenerId"] = picojson::value("VolumeChangeCallback");
+    obj["volume"] = picojson::value(static_cast<double>(volume));
+    Instance::PostMessage(this, event.serialize().c_str());
+}
+
+void TVAudioInstance::playSound(const picojson::value& args,
+        picojson::object& out) {
+    const std::string& type = args.get("type").to_str();
+    common::PlatformResult result =
+            AudioControlManager::getInstance().playSound(type);
+    if (result.IsError()) {
+        LoggerD("Error occured");
+        ReportError(result, &out);
+    } else {
+        picojson::value result;
+        ReportSuccess(result, out);
+    }
+}
+
+}  // namespace tvaudio
+}  // namespace extension
diff --git a/webWidgetTCT_device/src/tvaudio/tvaudio_instance.h b/webWidgetTCT_device/src/tvaudio/tvaudio_instance.h
new file mode 100755 (executable)
index 0000000..cf27c0d
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2015 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 SRC_TVAUDIO_TVAUDIO_INSTANCE_H_
+#define SRC_TVAUDIO_TVAUDIO_INSTANCE_H_
+
+#include "common/extension.h"
+
+#include "tvaudio/tvaudio_manager.h"
+
+namespace extension {
+namespace tvaudio {
+
+class TVAudioInstance :
+        public common::ParsedInstance,
+        public VolumeChangeListener {
+ public:
+    TVAudioInstance();
+    virtual ~TVAudioInstance();
+
+ private:
+    void setMute(const picojson::value& args, picojson::object& out);
+    void isMute(const picojson::value& args, picojson::object& out);
+    void setVolume(const picojson::value& args, picojson::object& out);
+    void setVolumeUp(const picojson::value& args, picojson::object& out);
+    void setVolumeDown(const picojson::value& args, picojson::object& out);
+    void getVolume(const picojson::value& args, picojson::object& out);
+    void getOutputMode(const picojson::value& args, picojson::object& out);
+    void setVolumeChangeListener(const picojson::value& args, picojson::object& out);
+    void unsetVolumeChangeListener(const picojson::value& args, picojson::object& out);
+    virtual void onVolumeChangeCallback(u_int16_t volume);
+    void playSound(const picojson::value& args, picojson::object& out);
+};
+
+}  // namespace tvaudio
+}  // namespace extension
+
+#endif  // SRC_TVAUDIO_TVAUDIO_INSTANCE_H_
diff --git a/webWidgetTCT_device/src/tvaudio/tvaudio_manager.cc b/webWidgetTCT_device/src/tvaudio/tvaudio_manager.cc
new file mode 100755 (executable)
index 0000000..a98a77f
--- /dev/null
@@ -0,0 +1,386 @@
+/*
+ * Copyright (c) 2015 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 "tvaudio/tvaudio_manager.h"
+
+#include <avoc.h>
+#include <avoc_defs.h>
+#include <audio_io.h>
+#include <sound_manager.h>
+#include <sound_manager_product.h>
+
+#include <fstream> // NOLINT (readability/streams)
+// this flag is no longer enforced in the newest cpplint.py
+
+#include <string>
+#include <vector>
+
+#include "common/logger.h"
+#include "common/platform_exception.h"
+
+
+namespace extension {
+namespace tvaudio {
+
+using common::UnknownException;
+using common::InvalidValuesException;
+using common::ErrorCode;
+
+namespace {
+const int AVOC_SUCCESS = 0;
+const u_int16_t VOLUME_STEP = 1;
+}
+
+VolumeChangeListener::~VolumeChangeListener() {
+    LoggerD("Enter");
+}
+
+AudioControlManager::AudioControlManager() :
+    m_volume_step(VOLUME_STEP),
+    m_volume_change_listener(NULL),
+    m_playThreadIdInit(false),
+    m_playThreadId(0) {
+    LoggerD("Enter");
+    m_playData.stopSound = false;
+}
+
+AudioControlManager::~AudioControlManager() {
+    LoggerD("Enter");
+}
+
+AudioControlManager& AudioControlManager::getInstance() {
+  static AudioControlManager instance;
+  return instance;
+}
+
+common::PlatformResult AudioControlManager::setMute(bool mute) {
+    LoggerD("Enter");
+    int ret = sound_manager_set_master_mute(mute);
+    if (SOUND_MANAGER_ERROR_NONE != ret) {
+        LoggerE("Failed to change mute state: %d (%s)", ret,
+                get_error_message(ret));
+        return common::PlatformResult(ErrorCode::UNKNOWN_ERR,
+            "Unknown error. Failed to change mute state");
+    }
+    return common::PlatformResult(ErrorCode::NO_ERROR);
+}
+
+common::PlatformResult AudioControlManager::isMute(bool &isMute) {
+    LoggerD("Enter");
+    int ret = sound_manager_get_master_mute(&isMute);
+    if (SOUND_MANAGER_ERROR_NONE != ret) {
+        LoggerE("Failed to get mute state: %d (%s)", ret,
+                get_error_message(ret));
+        return common::PlatformResult(ErrorCode::UNKNOWN_ERR,
+            "Unknown error. Failed to get mute state");
+    }
+    LoggerD("Mute state: %d", isMute);
+    return common::PlatformResult(ErrorCode::NO_ERROR);
+}
+
+common::PlatformResult AudioControlManager::setVolume(u_int16_t volume) {
+    LoggerD("Enter. Volume: %d", volume);
+    if (volume > 100) {
+        LoggerE("Invalid volume number");
+        return common::PlatformResult(ErrorCode::INVALID_VALUES_ERR,
+            "Invalid volume number");
+    }
+    int ret = sound_manager_set_master_volume(volume);
+    if (SOUND_MANAGER_ERROR_NONE != ret) {
+        LoggerE("Failed to set volume: %d (%s)", ret, get_error_message(ret));
+        return common::PlatformResult(ErrorCode::UNKNOWN_ERR,
+            "Unknown error. Failed to set volume");
+    }
+    return common::PlatformResult(ErrorCode::NO_ERROR);
+}
+
+common::PlatformResult AudioControlManager::setVolumeUp() {
+    LoggerD("Enter");
+    common::PlatformResult ret(ErrorCode::NO_ERROR);
+    u_int16_t currentVolume;
+    ret = getVolume(currentVolume);
+    if (ret.IsError())
+        return ret;
+    if (currentVolume < 100) {
+        ret = setVolume(currentVolume + m_volume_step <= 100 ?
+                currentVolume + m_volume_step : 100);
+        if (ret.IsError())
+            return ret;
+    }
+    bool muteState;
+    ret = isMute(muteState);
+    if (ret.IsError())
+        return ret;
+    if (muteState) {
+        return setMute(false);
+    }
+    return common::PlatformResult(ErrorCode::NO_ERROR);
+}
+
+common::PlatformResult AudioControlManager::setVolumeDown() {
+    LoggerD("Enter");
+    common::PlatformResult ret(ErrorCode::NO_ERROR);
+    u_int16_t currentVolume;
+    ret = getVolume(currentVolume);
+    if (ret.IsError())
+        return ret;
+    if (currentVolume > 0) {
+        ret = setVolume(currentVolume >= m_volume_step ?
+                currentVolume - m_volume_step : 0);
+        if (ret.IsError())
+            return ret;
+    }
+    bool muteState;
+    ret = isMute(muteState);
+    if (ret.IsError())
+        return ret;
+    if (muteState) {
+        return setMute(false);
+    }
+    return common::PlatformResult(ErrorCode::NO_ERROR);
+}
+
+common::PlatformResult AudioControlManager::getVolume(u_int16_t &volume) {
+    LoggerD("Enter");
+    int tempVolume;
+    int ret = sound_manager_get_master_volume(&tempVolume);
+    if (SOUND_MANAGER_ERROR_NONE != ret) {
+        LoggerE("Failed to get volume: %d (%s)", ret, get_error_message(ret));
+        return common::PlatformResult(ErrorCode::UNKNOWN_ERR,
+            "Unknown error. Failed to get volume");
+    }
+    volume = tempVolume;
+    LoggerD("Volume: %d", volume);
+    return common::PlatformResult(ErrorCode::NO_ERROR);
+}
+
+common::PlatformResult AudioControlManager::getOutputMode(AudioOutputMode &mode) {
+    LoggerD("Enter");
+    avoc_audio_format_e type;
+    int ret = avoc_get_audio_format(&type);
+    if (AVOC_SUCCESS != ret) {
+        LoggerE("Failed to get audio output type: %d (%s)", ret,
+                get_error_message(ret));
+        return common::PlatformResult(ErrorCode::UNKNOWN_ERR,
+            "Unknown error. Failed to get audio output type");
+    }
+    switch (type) {
+        case AVOC_AUDIO_FORMAT_PCM:
+            mode = AudioOutputMode::PCM;
+            break;
+        case AVOC_AUDIO_FORMAT_ES_DOLBY_DIGITAL:
+            mode = AudioOutputMode::DOLBY;
+            break;
+        case AVOC_AUDIO_FORMAT_ES_DTS:
+        case AVOC_AUDIO_FORMAT_NEO_ES_DTS:
+            mode = AudioOutputMode::DTS;
+            break;
+        case AVOC_AUDIO_FORMAT_ES_AAC:
+            mode = AudioOutputMode::AAC;
+            break;
+        default:
+            LoggerE("Unexpected audio output type: %d", type);
+            return common::PlatformResult(ErrorCode::UNKNOWN_ERR,
+                "Unexecpted audio output type");
+    }
+    return common::PlatformResult(ErrorCode::NO_ERROR);
+}
+
+common::PlatformResult AudioControlManager::registerVolumeChangeListener(
+            VolumeChangeListener* listener) {
+    LoggerD("Enter");
+    unregisterVolumeChangeListener();
+    int r = sound_manager_set_master_volume_changed_cb(
+            volumeChangeCallback, NULL);
+    if (SOUND_MANAGER_ERROR_NONE != r) {
+        LoggerE("Failed to add listener: %d (%s)", r, get_error_message(r));
+        return common::PlatformResult(ErrorCode::UNKNOWN_ERR,
+            "Failed to add listener");
+    }
+    m_volume_change_listener = listener;
+    LoggerD("Added listener");
+    return common::PlatformResult(ErrorCode::NO_ERROR);
+}
+
+common::PlatformResult AudioControlManager::unregisterVolumeChangeListener() {
+    LoggerD("Enter");
+    int r = sound_manager_unset_master_volume_changed_cb();
+    if (SOUND_MANAGER_ERROR_NONE != r) {
+        LoggerW("Failed to remove listener: %d (%s)", r, get_error_message(r));
+        return common::PlatformResult(ErrorCode::UNKNOWN_ERR,
+            "Failed to remove listener");
+    }
+    m_volume_change_listener = NULL;
+    return common::PlatformResult(ErrorCode::NO_ERROR);
+}
+
+void AudioControlManager::volumeChangeCallback(
+        unsigned int /*volume*/,
+        void* /*user_data*/) {
+    LoggerD("Enter");
+    if (!g_idle_add(onVolumeChange, NULL)) {
+        LoggerW("Failed to add to g_idle");
+    }
+}
+
+gboolean AudioControlManager::onVolumeChange(gpointer /*user_data*/) {
+    LoggerD("Enter");
+    if (!getInstance().m_volume_change_listener) {
+        LoggerD("Listener is null. Ignoring");
+        return G_SOURCE_REMOVE;
+    }
+    u_int16_t val;
+    common::PlatformResult ret = getInstance().getVolume(val);
+    if (ret.IsError()) {
+        LoggerE("Failed to retrieve volume level");
+    }
+    getInstance().m_volume_change_listener->onVolumeChangeCallback(val);
+    return G_SOURCE_REMOVE;
+}
+
+/**
+ * Play one of predefined sounds
+ *
+ * If sound is already played it is replaced by the new sound
+ */
+common::PlatformResult AudioControlManager::playSound(const std::string &type) {
+    LoggerD("Enter");
+    const auto beep = SoundMap.find(type);
+    if (beep == SoundMap.end()) {
+        return common::PlatformResult(ErrorCode::UNKNOWN_ERR,
+            "Unknown error. Unknown beep type: " + type);
+    }
+
+    if (m_playThreadIdInit) {
+        m_playData.stopSound = true;
+        pthread_join(m_playThreadId, NULL);
+        m_playData.stopSound = false;
+    }
+    pthread_attr_t attr;
+    pthread_attr_init(&attr);
+    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+
+    m_playData.beep_type = beep->first;
+    m_playData.filename = beep->second;
+
+    if (0 == pthread_create(&m_playThreadId, &attr, play, &m_playData )) {
+        m_playThreadIdInit = true;
+    } else {
+        LoggerE("Failed to create pthread");
+        return common::PlatformResult(ErrorCode::UNKNOWN_ERR,
+            "Failed to create pthread to play sound");
+    }
+    return common::PlatformResult(ErrorCode::NO_ERROR);
+}
+
+void* AudioControlManager::play(void* play_data) {
+    LoggerD("Enter");
+    PlayData* pData = static_cast<PlayData*>(play_data);
+
+    LoggerD("Beep type: %s", pData->beep_type.c_str());
+
+    const std::string& filename = pData->filename;
+    std::unique_ptr <std::vector <char>> pBuffer =
+            AudioControlManager::loadFile(filename);
+
+    audio_out_h handle;
+    int error = audio_out_create(SAMPLING_FREQ,
+                                AUDIO_CHANNEL_STEREO,
+                                AUDIO_SAMPLE_TYPE_S16_LE,
+                                SOUND_TYPE_NOTIFICATION,
+                                &handle);
+    if (AUDIO_IO_ERROR_NONE != error) {
+        LoggerE("Failed to open audio output: %d (%s)", error,
+                get_error_message(error));
+        return NULL;
+    }
+
+    error = audio_out_prepare(handle);
+    if (AUDIO_IO_ERROR_NONE != error) {
+        LoggerE("Failed to open audio output: %d (%s)", error,
+                get_error_message(error));
+        audio_out_destroy(handle);
+        return NULL;
+    }
+
+    int counter = 0;
+    int dataLeftSize = pBuffer->size();
+    while ((!pData->stopSound) && (dataLeftSize > 0)) {
+        if ((dataLeftSize - AudioControlManager::CHUNK) < 0) {
+            error = audio_out_write(handle,
+                                    &(*pBuffer)[counter],
+                                    dataLeftSize);
+            if (dataLeftSize != error) {
+                LoggerE("Failed to write to audio output: %d (%s)", error,
+                        get_error_message(error));
+                audio_out_destroy(handle);
+                return NULL;
+            }
+            break;
+        } else {
+            dataLeftSize = dataLeftSize - AudioControlManager::CHUNK;
+            error = audio_out_write(handle,
+                                    &(*pBuffer)[counter],
+                                    AudioControlManager::CHUNK);
+            if (AudioControlManager::CHUNK != error) {
+                LoggerE("Failed to write to audio output: %d (%s)", error,
+                        get_error_message(error));
+                audio_out_destroy(handle);
+                return NULL;
+            }
+        }
+        counter += AudioControlManager::CHUNK;
+    }  // while
+    audio_out_destroy(handle);
+    return NULL;
+}
+
+std::unique_ptr <std::vector<char>>
+AudioControlManager::loadFile(const std::string& filename) {
+    LoggerD("Enter");
+    std::unique_ptr<std::vector<char>> pBuffer(new std::vector<char>());
+    std::ifstream file(filename.c_str(),
+                    (std::ios::binary | std::ios::in | std::ios::ate));
+    if (!file.is_open()) {
+        LoggerE("Could not open file %s", filename.c_str());
+        return std::unique_ptr< std::vector<char>>();
+    }
+
+    std::ifstream::pos_type size = file.tellg();
+    if (size < 0) {
+        file.close();
+        LoggerE("Failed to open file %s - incorrect size", filename.c_str());
+        return std::unique_ptr<std::vector<char>>();
+    }
+
+    LoggerD("resizing");
+    pBuffer->resize(size);
+    LoggerD("resized");
+    file.seekg(0, std::ios::beg);
+    if (!file.read(&(*pBuffer)[0], size)) {
+        file.close();
+        LoggerE("Failed to read audio file %s", filename.c_str());
+        return std::unique_ptr <std::vector <char>>();
+    }
+    file.close();
+
+    LoggerD("Got buffer");
+    return pBuffer;
+}
+
+}  // namespace tvaudio
+}  // namespace extension
+
diff --git a/webWidgetTCT_device/src/tvaudio/tvaudio_manager.h b/webWidgetTCT_device/src/tvaudio/tvaudio_manager.h
new file mode 100755 (executable)
index 0000000..cb813eb
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2015 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 <glib.h>
+#include <atomic>
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+#ifndef SRC_TVAUDIO_TVAUDIO_MANAGER_H_
+#define SRC_TVAUDIO_TVAUDIO_MANAGER_H_
+
+
+#include <sys/types.h>
+#include "common/platform_result.h"
+
+namespace extension {
+namespace tvaudio {
+
+enum AudioOutputMode {
+    PCM = 0,
+    DOLBY,
+    DTS,
+    AAC
+};
+
+class VolumeChangeListener {
+ public:
+    virtual void onVolumeChangeCallback(u_int16_t volume) = 0;
+    virtual ~VolumeChangeListener();
+};
+
+class AudioControlManager {
+ public:
+    common::PlatformResult setMute(bool mute);
+    common::PlatformResult isMute(bool &isMute);
+    common::PlatformResult setVolume(u_int16_t volume);
+    common::PlatformResult setVolumeUp();
+    common::PlatformResult setVolumeDown();
+    common::PlatformResult playSound(const std::string &type);
+    common::PlatformResult getVolume(u_int16_t &volume);
+    common::PlatformResult getOutputMode(AudioOutputMode &mode);
+    common::PlatformResult registerVolumeChangeListener(VolumeChangeListener* listener);
+    common::PlatformResult unregisterVolumeChangeListener();
+    static void volumeChangeCallback(unsigned int volume, void* user_data);
+    static gboolean onVolumeChange(gpointer user_data);
+
+    // Non-copyable, -assignable, -movable
+    AudioControlManager(const AudioControlManager &) = delete;
+    AudioControlManager(AudioControlManager &&) = delete;
+    AudioControlManager& operator=(const AudioControlManager &) = delete;
+    AudioControlManager& operator=(AudioControlManager &&) = delete;
+
+    static AudioControlManager& getInstance();
+
+    virtual ~AudioControlManager();
+
+ private:
+    u_int16_t m_volume_step;
+    VolumeChangeListener* m_volume_change_listener;
+    AudioControlManager();
+
+    static const int CHUNK = 768;
+    static const int SAMPLING_FREQ = 44100;
+
+    static void* play(void* _args);
+
+    bool m_playThreadIdInit;
+    pthread_t m_playThreadId;
+
+    static std::unique_ptr<std::vector<char>>
+        loadFile(const std::string& filename);
+
+    //  key : sound file path
+    const std::map<const std::string, const std::string> SoundMap = {
+        {"MOVE",          "/opt/usr/share/settings/Ringtones/move.pcm"},
+        {"UP",            "/opt/usr/share/settings/Ringtones/move.pcm"},
+        {"DOWN",          "/opt/usr/share/settings/Ringtones/move.pcm"},
+        {"LEFT",          "/opt/usr/share/settings/Ringtones/move.pcm"},
+        {"RIGHT",         "/opt/usr/share/settings/Ringtones/move.pcm"},
+        {"PAGE_LEFT",     "/opt/usr/share/settings/Ringtones/move.pcm"},
+        {"PAGE_RIGHT",    "/opt/usr/share/settings/Ringtones/move.pcm"},
+
+        {"BACK",          "/opt/usr/share/settings/Ringtones/back.pcm"},
+        {"SELECT",        "/opt/usr/share/settings/Ringtones/select.pcm"},
+        {"CANCEL",        "/opt/usr/share/settings/Ringtones/cancel.pcm"},
+        {"WARNING",       "/opt/usr/share/settings/Ringtones/enter.pcm"},
+        {"KEYPAD",        "/opt/usr/share/settings/Ringtones/keypad.pcm"},
+        {"KEYPAD_ENTER",  "/opt/usr/share/settings/Ringtones/enter.pcm"},
+        {"KEYPAD_DEL",    "/opt/usr/share/settings/Ringtones/del.pcm"},
+        {"PREPARING",     "/opt/usr/share/settings/Ringtones/preparing.pcm"},
+    };
+    struct PlayData {
+        std::atomic<bool> stopSound;
+        std::string beep_type;
+        std::string filename;
+    };
+    PlayData m_playData;
+};
+
+}  // namespace tvaudio
+}  // namespace extension
+
+#endif  // SRC_TVAUDIO_TVAUDIO_MANAGER_H_
+
diff --git a/webWidgetTCT_device/src/tvchannel/channel_info.cc b/webWidgetTCT_device/src/tvchannel/channel_info.cc
new file mode 100755 (executable)
index 0000000..57d4901
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2015 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 "tvchannel/channel_info.h"
+#include <stdint.h>
+#include <string>
+#include <algorithm>
+#include "tvchannel/tvchannel_manager.h"
+#include "common/logger.h"
+
+namespace extension {
+namespace tvchannel {
+
+ChannelInfo::ChannelInfo() :
+    m_major(0), m_minor(0), m_channelName(""), m_programNumber(0), m_ptc(0),
+        m_lcn(0), m_sourceID(0), m_transportStreamID(0), m_originalNetworkID(0),
+        m_serviceName(""), m_serviceID(0) {
+}
+
+ChannelInfo::~ChannelInfo() {
+}
+
+void ChannelInfo::fromApiData(const TCServiceData &channelData) {
+    LoggerD("Enter");
+    m_ptc = channelData.Get<u_int16_t>(CHANNEL_NUMBER);
+    m_major = channelData.Get<u_int16_t>(MAJOR);
+    m_minor = channelData.Get<u_int16_t>(MINOR);
+    m_lcn = channelData.Get<u_int16_t>(LCN);
+    m_sourceID = channelData.Get<u_int16_t>(SOURCE_ID);
+    m_programNumber = channelData.Get<u_int16_t>(PROGRAM_NUMBER);
+    m_transportStreamID = channelData.Get<u_int16_t>(TRANSPORT_STREAM_ID);
+    m_originalNetworkID = channelData.Get<u_int16_t>(ORIGINAL_NETWORK_ID);
+    m_serviceID = channelData.Get < TCServiceId > (SERVICE_ID);
+
+    setChannelName(channelData);
+}
+
+int64_t ChannelInfo::getMajor() const {
+    return m_major;
+}
+
+void ChannelInfo::setMajor(int64_t major) {
+    m_major = major;
+}
+
+int64_t ChannelInfo::getMinor() const {
+    return m_minor;
+}
+
+void ChannelInfo::setMinor(int64_t minor) {
+    m_minor = minor;
+}
+
+std::string ChannelInfo::getChannelName() const {
+    return m_channelName;
+}
+
+void ChannelInfo::setChannelName(std::string channelName) {
+    m_channelName = channelName;
+}
+
+void ChannelInfo::setChannelName(const TCServiceData &channelData) {
+    LoggerD("Enter");
+    size_t len = channelData.GetLength(SERVICE_NAME);
+    if (len) {
+        LoggerD("ServiceName length %d", len);
+        size_t c_len = len * sizeof(t_wchar_t) / sizeof(char);
+        t_wchar_t svc_name[len + 1];
+        channelData.Get(SERVICE_NAME, svc_name);
+        char name[CHANNEL_NAME_MAX_SIZE];
+        std::fill(name, name + CHANNEL_NAME_MAX_SIZE, '\0');
+        TVChannelManager::ucs2utf8(name, sizeof(name),
+            reinterpret_cast<char *>(svc_name), c_len);
+        m_channelName = name;
+    } else {
+        m_channelName = "";
+    }
+}
+
+int64_t ChannelInfo::getProgramNumber() const {
+    return m_programNumber;
+}
+
+void ChannelInfo::setProgramNumber(int64_t programNumber) {
+    m_programNumber = programNumber;
+}
+
+int64_t ChannelInfo::getPtc() const {
+    return m_ptc;
+}
+
+void ChannelInfo::setPtc(int64_t ptc) {
+    m_ptc = ptc;
+}
+
+int64_t ChannelInfo::getLcn() const {
+    return m_lcn;
+}
+
+void ChannelInfo::setLcn(int64_t lcn) {
+    m_lcn = lcn;
+}
+
+int64_t ChannelInfo::getSourceID() const {
+    return m_sourceID;
+}
+
+void ChannelInfo::setSourceID(int64_t sourceID) {
+    m_sourceID = sourceID;
+}
+
+int64_t ChannelInfo::getTransportStreamID() const {
+    return m_transportStreamID;
+}
+
+void ChannelInfo::setTransportStreamID(int64_t transportStreamID) {
+    m_transportStreamID = transportStreamID;
+}
+
+int64_t ChannelInfo::getOriginalNetworkID() const {
+    return m_originalNetworkID;
+}
+
+void ChannelInfo::setOriginalNetworkID(int64_t originalNetworkID) {
+    m_originalNetworkID = originalNetworkID;
+}
+
+std::string ChannelInfo::getServiceName() const {
+    return getChannelName();
+}
+
+void ChannelInfo::setServiceName(std::string serviceName) {
+    setChannelName(serviceName);
+}
+
+void ChannelInfo::setServiceName(const TCServiceData &data) {
+    setChannelName(data);
+}
+
+TCServiceId ChannelInfo::getServiceID() const {
+    return m_serviceID;
+}
+
+void ChannelInfo::setServiceID(TCServiceId serviceID) {
+    m_serviceID = serviceID;
+}
+
+}  //  namespace tvchannel
+}  //  namespace extension
diff --git a/webWidgetTCT_device/src/tvchannel/channel_info.h b/webWidgetTCT_device/src/tvchannel/channel_info.h
new file mode 100755 (executable)
index 0000000..b8eecc2
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2015 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 SRC_TVCHANNEL_CHANNEL_INFO_H_
+#define SRC_TVCHANNEL_CHANNEL_INFO_H_
+
+#include <ServiceData.h>
+#include <string>
+#include "tvchannel/types.h"
+
+namespace extension {
+namespace tvchannel {
+
+class ChannelInfo {
+ public:
+    ChannelInfo();
+    virtual ~ChannelInfo();
+
+    void fromApiData(const TCServiceData &channelData);
+
+    int64_t getMajor() const;
+    void setMajor(int64_t major);
+
+    int64_t getMinor() const;
+    void setMinor(int64_t minor);
+
+    std::string getChannelName() const;
+    void setChannelName(std::string channelName);
+    void setChannelName(const TCServiceData &channelData);
+
+    int64_t getProgramNumber() const;
+    void setProgramNumber(int64_t programNumber);
+
+    int64_t getPtc() const;
+    void setPtc(int64_t ptc);
+
+    int64_t getLcn() const;
+    void setLcn(int64_t lcn);
+
+    int64_t getSourceID() const;
+    void setSourceID(int64_t sourceID);
+
+    int64_t getTransportStreamID() const;
+    void setTransportStreamID(int64_t transportStreamID);
+
+    int64_t getOriginalNetworkID() const;
+    void setOriginalNetworkID(int64_t originalNetworkID);
+
+    std::string getServiceName() const;
+    void setServiceName(std::string serviceName);
+    void setServiceName(const TCServiceData &channelData);
+
+    TCServiceId getServiceID() const;
+    void setServiceID(TCServiceId serviceID);
+
+ private:
+    int64_t m_major;
+    int64_t m_minor;
+    std::string m_channelName;
+    int64_t m_programNumber;
+    int64_t m_ptc;
+    int64_t m_lcn;
+    int64_t m_sourceID;
+    int64_t m_transportStreamID;
+    int64_t m_originalNetworkID;
+    std::string m_serviceName;
+    TCServiceId m_serviceID;
+
+    static const int CHANNEL_NAME_MAX_SIZE = 128;
+};
+
+}  //  namespace tvchannel
+}  //  namespace extension
+
+#endif  // SRC_TVCHANNEL_CHANNEL_INFO_H_
diff --git a/webWidgetTCT_device/src/tvchannel/criteria_filter.cc b/webWidgetTCT_device/src/tvchannel/criteria_filter.cc
new file mode 100755 (executable)
index 0000000..942d773
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2015 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 "tvchannel/criteria_filter.h"
+#include <common/logger.h>
+
+namespace extension {
+namespace tvchannel {
+
+CriteriaFilter::CriteriaFilter(EServiceMode _mode) :
+    m_mode(_mode) {
+}
+
+void CriteriaFilter::filterWhere(int32_t columnName,
+    const int32_t columnValue) {
+    if (m_mode == SERVICE_MODE_ATSC && columnName == ORIGINAL_NETWORK_ID) {
+        LoggerD("ORIGINAL_NETWORK_ID not supported");
+        return;
+    }
+    if ((m_mode == SERVICE_MODE_DVB || m_mode == SERVICE_MODE_DVBNT)
+        && (columnName == MINOR || columnName == SOURCE_ID)) {
+        LoggerD("%d not supported", columnName);
+        return;
+    }
+    if (m_mode == SERVICE_MODE_ISDB && columnName == SOURCE_ID) {
+        LoggerD("SOURCE_ID not supported");
+        return;
+    }
+
+    columnMap[columnName] = columnValue;
+}
+
+void CriteriaFilter::getFilteredCriteria(std::unique_ptr < TCCriteriaHelper > & _pCriteria) {
+    for (auto it = columnMap.begin(); it != columnMap.end(); ++it) {
+        _pCriteria->Where(it->first, it->second);
+    }
+}
+
+void CriteriaFilter::resetFilter() {
+    columnMap.clear();
+}
+
+}  //  namespace tvchannel
+}  //  namespace extension
diff --git a/webWidgetTCT_device/src/tvchannel/criteria_filter.h b/webWidgetTCT_device/src/tvchannel/criteria_filter.h
new file mode 100755 (executable)
index 0000000..7be9ab6
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2015 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 SRC_TVCHANNEL_CRITERIA_FILTER_H_
+#define SRC_TVCHANNEL_CRITERIA_FILTER_H_
+
+#include <ServiceNavigationDataType.h>
+#include <CriteriaHelper.h>
+#include <stdint.h>
+#include <map>
+#include <memory>
+
+namespace extension {
+namespace tvchannel {
+
+class CriteriaFilter {
+ public:
+    explicit CriteriaFilter(EServiceMode mode);
+    void filterWhere(int32_t columnName, const int32_t columnValue);
+    void getFilteredCriteria(std::unique_ptr < TCCriteriaHelper > & _pCriteria);
+    void resetFilter();
+ private:
+    EServiceMode m_mode;
+    std::map<int32_t, int32_t> columnMap;
+};
+
+}  //  namespace tvchannel
+}  //  namespace extension
+
+#endif  //  SRC_TVCHANNEL_CRITERIA_FILTER_H_
diff --git a/webWidgetTCT_device/src/tvchannel/program_info.cc b/webWidgetTCT_device/src/tvchannel/program_info.cc
new file mode 100755 (executable)
index 0000000..bedda5f
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2015 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 "tvchannel/program_info.h"
+#include "tvchannel/tvchannel_manager.h"
+#include "common/logger.h"
+#include <algorithm>
+
+namespace extension {
+namespace tvchannel {
+
+ProgramInfo::ProgramInfo() :
+m_title(""),
+m_startTime(0),
+m_duration(0),
+m_detailedDescription(""),
+m_language(""),
+m_rating("") {
+}
+
+ProgramInfo::~ProgramInfo() {
+}
+
+void ProgramInfo::fromApiData(const TCProgramData &data) {
+    LoggerD("Enter");
+    setTitle(data);
+    m_startTime = data.StartTime();
+    m_duration = data.EndTime() - m_startTime;
+    setDetailedDescription(data);
+    setLanguage(data);
+}
+
+std::string ProgramInfo::getTitle() const {
+    return m_title;
+}
+
+void ProgramInfo::setTitle(const TCProgramData &data) {
+    LoggerD("Enter");
+    try {
+        unsigned int len;
+        size_t c_len;
+
+        len = data.TitleLength();
+        if (len) {
+            LoggerD("Title length %d", len);
+            t_wchar_t title[len + 1];
+            TCProgramData copy = data;
+            copy.Title(title, &len);
+            c_len = len * sizeof (t_wchar_t) / sizeof (char);
+            char name[128];
+            std::fill(name, name + 128, 0);
+            TVChannelManager::ucs2utf8(name, (size_t)sizeof (name),
+                reinterpret_cast<char*>(title), c_len);
+            m_title = name;
+        } else {
+            m_title = "";
+        }
+    } catch (...) {
+        LoggerD("There is some problem on text encoding.");
+        m_title = "";
+    }
+}
+
+void ProgramInfo::setTitle(std::string title) {
+    m_title = title;
+}
+
+int64_t ProgramInfo::getStartTime() const {
+    return m_startTime;
+}
+
+double ProgramInfo::getStartTimeMs() const {
+    return static_cast<double> (m_startTime * 1000.0);
+}
+
+void ProgramInfo::setStartTime(int64_t startTime) {
+    m_startTime = startTime;
+}
+
+int64_t ProgramInfo::getDuration() const {
+    return m_duration;
+}
+
+void ProgramInfo::setDuration(int64_t duration) {
+    m_duration = duration;
+}
+
+std::string ProgramInfo::getDetailedDescription() const {
+    return m_detailedDescription;
+}
+
+void ProgramInfo::setDetailedDescription(std::string detailedDescription) {
+    m_detailedDescription = detailedDescription;
+}
+
+void ProgramInfo::setDetailedDescription(const TCProgramData &data) {
+    LoggerD("Enter");
+    try {
+        unsigned int len;
+        size_t c_len;
+
+        len = data.ExtendedTextLength();
+        LoggerD("Description length %d", len);
+        if (len) {
+            t_wchar_t description[len +1];
+            TCProgramData copy = data;
+            copy.ExtendedText(description, &len);
+
+            c_len = len * sizeof (t_wchar_t) / sizeof (char);
+            char name[TCProgramData::EExtendChannelTextLength
+                ::EXTEND_CHANNEL_TEXT_LENGTH];
+            std::fill(name, name + TCProgramData::EExtendChannelTextLength
+                ::EXTEND_CHANNEL_TEXT_LENGTH, 0);
+            TVChannelManager::ucs2utf8(name, (size_t)sizeof (name),
+                reinterpret_cast<char*>(description), c_len);
+            m_detailedDescription = name;
+        } else {
+            m_detailedDescription = "";
+        }
+    } catch (...) {
+        LoggerD("There is some problem on text encoding.");
+        m_detailedDescription = "";
+    }
+}
+
+std::string ProgramInfo::getLanguage() const {
+    return m_language;
+}
+
+void ProgramInfo::setLanguage(std::string language) {
+    m_language = language;
+}
+
+void ProgramInfo::setLanguage(const TCProgramData &data) {
+    // todo: convert language number to code?
+    m_language = std::to_string(data.Language());
+}
+
+std::string ProgramInfo::getRating() const {
+    return m_rating;
+}
+
+void ProgramInfo::setRating(std::string rating) {
+    m_rating = rating;
+}
+
+
+}  // namespace tvchannel
+}  // namespace extension
diff --git a/webWidgetTCT_device/src/tvchannel/program_info.h b/webWidgetTCT_device/src/tvchannel/program_info.h
new file mode 100755 (executable)
index 0000000..41aa1d8
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2015 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 SRC_TVCHANNEL_PROGRAM_INFO_H_
+#define SRC_TVCHANNEL_PROGRAM_INFO_H_
+
+#include <ProgramData.h>
+#include <string>
+
+#include "tvchannel/types.h"
+
+namespace extension {
+namespace tvchannel {
+
+class ProgramInfo {
+ public:
+    ProgramInfo();
+    virtual ~ProgramInfo();
+    void fromApiData(const TCProgramData &data);
+
+    std::string getTitle() const;
+    void setTitle(std::string title);
+    void setTitle(const TCProgramData &data);
+
+    int64_t getStartTime() const;
+    double getStartTimeMs() const;
+    void setStartTime(int64_t startTime);
+
+    int64_t getDuration() const;
+    void setDuration(int64_t duration);
+
+    std::string getDetailedDescription() const;
+    void setDetailedDescription(std::string detailedDescription);
+    void setDetailedDescription(const TCProgramData &data);
+
+    std::string getLanguage() const;
+    void setLanguage(std::string language);
+    void setLanguage(const TCProgramData &data);
+
+    std::string getRating() const;
+    void setRating(std::string rating);
+
+ private:
+    std::string m_title;
+    int64_t m_startTime;
+    int64_t m_duration;
+    std::string m_detailedDescription;
+    std::string m_language;
+    std::string m_rating;
+};
+
+}  // namespace tvchannel
+}  // namespace extension
+
+#endif  // SRC_TVCHANNEL_PROGRAM_INFO_H_
diff --git a/webWidgetTCT_device/src/tvchannel/tune_option.cc b/webWidgetTCT_device/src/tvchannel/tune_option.cc
new file mode 100755 (executable)
index 0000000..e81d9eb
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2015 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 "tvchannel/tune_option.h"
+#include <stdint.h>
+#include <common/logger.h>
+
+namespace extension {
+namespace tvchannel {
+
+TuneOption::TuneOption() {
+    initialize();
+}
+
+void TuneOption::initialize() {
+    m_ptc = 0;
+    m_major = 0;
+    m_minor = 0;
+    m_sourceID = 0;
+    m_programNumber = 0;
+    m_transportStreamID = 0;
+    m_originalNetworkID = 0;
+    m_ptc_is_set = false;
+    m_major_is_set = false;
+    m_minor_is_set = false;
+    m_sourceID_is_set = false;
+    m_programNumber_is_set = false;
+    m_transportStreamID_is_set = false;
+    m_originalNetworkID_is_set = false;
+}
+
+TuneOption::~TuneOption() {
+}
+
+TuneOption::TuneOption(picojson::object const& _tuneDict) {
+    LoggerD("Enter");
+    initialize();
+    picojson::object tuneDict = _tuneDict;
+    if (tuneDict.find("major") != tuneDict.end()) {
+        setMajor(std::stoll(tuneDict["major"].to_str()));
+    }
+    if (tuneDict.find("minor") != tuneDict.end()) {
+        setMinor(std::stoll(tuneDict["minor"].to_str()));
+    }
+    if (tuneDict.find("sourceID") != tuneDict.end()) {
+        setSourceID(std::stoll(tuneDict["sourceID"].to_str()));
+    }
+    if (tuneDict.find("programNumber") != tuneDict.end()) {
+        setProgramNumber(
+            std::stoll(tuneDict["programNumber"].to_str()));
+    }
+    if (tuneDict.find("transportStreamID") != tuneDict.end()) {
+        setTransportStreamID(
+            std::stoll(tuneDict["transportStreamID"].to_str()));
+    }
+    if (tuneDict.find("ptc") != tuneDict.end()) {
+        setPtc(std::stoll(tuneDict["ptc"].to_str()));
+    }
+    if (tuneDict.find("originalNetworkID") != tuneDict.end()) {
+        setOriginalNetworkID(
+            std::stoll(tuneDict["originalNetworkID"].to_str()));
+    }
+}
+
+int64_t TuneOption::getPtc() const {
+    return m_ptc;
+}
+
+bool TuneOption::isPtcSet() const {
+    return m_ptc_is_set;
+}
+
+void TuneOption::setPtc(int64_t ptc) {
+    m_ptc = ptc;
+    m_ptc_is_set = true;
+}
+
+int64_t TuneOption::getMajor() const {
+    return m_major;
+}
+
+bool TuneOption::isMajorSet() const {
+    return m_major_is_set;
+}
+
+void TuneOption::setMajor(int64_t major) {
+    m_major = major;
+    m_major_is_set = true;
+}
+
+int64_t TuneOption::getMinor() const {
+    return m_minor;
+}
+
+bool TuneOption::isMinorSet() const {
+    return m_minor_is_set;
+}
+
+void TuneOption::setMinor(int64_t minor) {
+    m_minor = minor;
+    m_minor_is_set = true;
+}
+
+int64_t TuneOption::getSourceID() const {
+    return m_sourceID;
+}
+
+bool TuneOption::isSourceIDSet() const {
+    return m_sourceID_is_set;
+}
+
+void TuneOption::setSourceID(int64_t sourceID) {
+    m_sourceID = sourceID;
+    m_sourceID_is_set = true;
+}
+
+int64_t TuneOption::getProgramNumber() const {
+    return m_programNumber;
+}
+
+bool TuneOption::isProgramNumberSet() const {
+    return m_programNumber_is_set;
+}
+
+void TuneOption::setProgramNumber(int64_t programNumber) {
+    m_programNumber = programNumber;
+    m_programNumber_is_set = true;
+}
+
+int64_t TuneOption::getTransportStreamID() const {
+    return m_transportStreamID;
+}
+
+bool TuneOption::isTransportStreamIDSet() const {
+    return m_transportStreamID_is_set;
+}
+
+void TuneOption::setTransportStreamID(int64_t transportStreamID) {
+    m_transportStreamID = transportStreamID;
+    m_transportStreamID_is_set = true;
+}
+
+int64_t TuneOption::getOriginalNetworkID() const {
+    return m_originalNetworkID;
+}
+
+bool TuneOption::isOriginalNetworkIDSet() const {
+    return m_originalNetworkID_is_set;
+}
+
+void TuneOption::setOriginalNetworkID(int64_t originalNetworkID) {
+    m_originalNetworkID = originalNetworkID;
+    m_originalNetworkID_is_set = true;
+}
+
+}  //  namespace tvchannel
+}  //  namespace extension
diff --git a/webWidgetTCT_device/src/tvchannel/tune_option.h b/webWidgetTCT_device/src/tvchannel/tune_option.h
new file mode 100755 (executable)
index 0000000..3241ddd
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2015 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 SRC_TVCHANNEL_TUNE_OPTION_H_
+#define SRC_TVCHANNEL_TUNE_OPTION_H_
+
+#include <memory>
+#include "common/picojson.h"
+#include "tvchannel/types.h"
+
+namespace extension {
+namespace tvchannel {
+
+class TuneOption {
+ public:
+    TuneOption();
+    virtual ~TuneOption();
+
+    explicit TuneOption(picojson::object const& _tuneDict);
+
+    int64_t getPtc() const;
+    bool isPtcSet() const;
+    void setPtc(int64_t ptc);
+
+    int64_t getMajor() const;
+    bool isMajorSet() const;
+    void setMajor(int64_t major);
+
+    int64_t getMinor() const;
+    bool isMinorSet() const;
+    void setMinor(int64_t minor);
+
+    int64_t getSourceID() const;
+    bool isSourceIDSet() const;
+    void setSourceID(int64_t sourceID);
+
+    int64_t getProgramNumber() const;
+    bool isProgramNumberSet() const;
+    void setProgramNumber(int64_t programNumber);
+
+    int64_t getTransportStreamID() const;
+    bool isTransportStreamIDSet() const;
+    void setTransportStreamID(int64_t transportStreamID);
+
+    int64_t getOriginalNetworkID() const;
+    bool isOriginalNetworkIDSet() const;
+    void setOriginalNetworkID(int64_t originalNetworkID);
+
+ private:
+    int64_t m_ptc;
+    int64_t m_major;
+    int64_t m_minor;
+    int64_t m_sourceID;
+    int64_t m_programNumber;
+    int64_t m_transportStreamID;
+    int64_t m_originalNetworkID;
+    bool m_ptc_is_set;
+    bool m_major_is_set;
+    bool m_minor_is_set;
+    bool m_sourceID_is_set;
+    bool m_programNumber_is_set;
+    bool m_transportStreamID_is_set;
+    bool m_originalNetworkID_is_set;
+    void initialize();
+};
+
+typedef std::shared_ptr<TuneOption> TuneOptionPtr;
+
+}  //  namespace tvchannel
+}  //  namespace extension
+
+#endif  //  SRC_TVCHANNEL_TUNE_OPTION_H_
diff --git a/webWidgetTCT_device/src/tvchannel/tvchannel.gyp b/webWidgetTCT_device/src/tvchannel/tvchannel.gyp
new file mode 100755 (executable)
index 0000000..233578d
--- /dev/null
@@ -0,0 +1,53 @@
+{
+  'includes':[
+    '../common/common.gypi',
+  ],
+  'targets': [
+    {
+      'target_name': 'tizen_tvchannel',
+      'type': 'loadable_module',
+      'variables': {
+        'packages': [
+          'tvs-api',
+        ],
+      },
+      'dependencies': [
+        '../common/common.gyp:tizen_common',
+        '../tizen/tizen.gyp:tizen',
+      ],
+      'includes': [
+        '../common/pkg-config.gypi',
+      ],
+      'conditions': [
+       ['tizen == 1', {
+        'variables': {
+            'packages': [
+             'tvs-api'
+            ],
+        },
+       },
+      ],
+      ],
+      'sources': [
+        'tvchannel_api.js',
+        'tvchannel_error.h',
+        'tvchannel_extension.cc',
+        'tvchannel_extension.h',
+        'tvchannel_instance.cc',
+        'tvchannel_instance.h',
+        'channel_info.cc',
+        'channel_info.h',
+        'program_info.cc',
+        'program_info.h',
+        'tvchannel_manager.h',
+        'tvchannel_manager.cc',
+        'types.h',
+        'types.cc',
+        'tune_option.h',
+        'tune_option.cc',
+        'criteria_filter.h',
+        'criteria_filter.cc'
+      ],
+    },
+  ],
+}
diff --git a/webWidgetTCT_device/src/tvchannel/tvchannel_api.js b/webWidgetTCT_device/src/tvchannel/tvchannel_api.js
new file mode 100755 (executable)
index 0000000..c4672f8
--- /dev/null
@@ -0,0 +1,681 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+var native = new xwalk.utils.NativeManager(extension);
+var validator = xwalk.utils.validator;
+var validatorType = xwalk.utils.type;
+
+
+/**
+ * An enumerator that defines window types.
+ * @enum {string}
+ */
+var WindowType = {
+  MAIN: 'MAIN'
+};
+
+
+/**
+ * An enumerator to indicate the tune mode.
+ * @enum {string}
+ */
+var TuneMode = {
+  ALL: 'ALL',
+  DIGITAL: 'DIGITAL',
+  ANALOG: 'ANALOG',
+  FAVORITE: 'FAVORITE'
+};
+
+function FavoriteList(data) {
+  Object.defineProperties(this, {
+    id: {
+      enumerable: true,
+      value: data.id
+    }
+  });
+}
+
+FavoriteList.prototype.addChannel = function(channel, successCallback, errorCallback) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.TV_CHANNEL);
+  var args = validator.validateArgs(arguments, [
+    {
+      name: 'channelInfo',
+      type: validator.Types.PLATFORM_OBJECT,
+      values: ChannelInfo
+    },
+    {
+      name: 'successCallback',
+      type: validator.Types.FUNCTION,
+      optional: false,
+      nullable: false
+    },
+    {
+      name: 'errorCallback',
+      type: validator.Types.FUNCTION,
+      optional: true,
+      nullable: true
+    }
+  ]);
+  native.call('TVChannelManager_UpdateFavorites', {
+    channelId: args.channelInfo._serviceId,
+    favoriteId: this.id,
+    addToList: true
+  }, function(msg) {
+    if (msg.error) {
+      if (validatorType.isFunction(args.errorCallback)) {
+        args.errorCallback(native.getErrorObject(msg));
+      }
+    } else {
+      args.successCallback();
+    }
+  });
+};
+
+FavoriteList.prototype.removeChannel = function(channel, successCallback, errorCallback) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.TV_CHANNEL);
+  var args = validator.validateArgs(arguments, [
+    {
+      name: 'channelInfo',
+      type: validator.Types.PLATFORM_OBJECT,
+      values: ChannelInfo
+    },
+    {
+      name: 'successCallback',
+      type: validator.Types.FUNCTION,
+      optional: false,
+      nullable: false
+    },
+    {
+      name: 'errorCallback',
+      type: validator.Types.FUNCTION,
+      optional: true,
+      nullable: true
+    }
+  ]);
+  native.call('TVChannelManager_UpdateFavorites', {
+    channelId: args.channelInfo._serviceId,
+    favoriteId: this.id,
+    addToList: false
+  }, function(msg) {
+    if (msg.error) {
+      if (validatorType.isFunction(args.errorCallback)) {
+        args.errorCallback(native.getErrorObject(msg));
+      }
+    } else {
+      args.successCallback();
+    }
+  });
+};
+
+FavoriteList.prototype.getChannels = function(successCallback, errorCallback, nStart, number) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.TV_CHANNEL);
+  var args = validator.validateArgs(arguments, [
+    {
+      name: 'successCallback',
+      type: validator.Types.FUNCTION,
+      optional: false,
+      nullable: false
+    },
+    {
+      name: 'errorCallback',
+      type: validator.Types.FUNCTION,
+      optional: true,
+      nullable: true
+    },
+    {
+      name: 'nStart',
+      optional: true,
+      nullable: true,
+      type: validator.Types.LONG
+    },
+    {
+      name: 'number',
+      optional: true,
+      nullable: true,
+      type: validator.Types.LONG
+    }
+  ]);
+  if (args.nStart < 0) {
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+      "nStart is lower than 0");
+  }
+  if (args.number < 0) {
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+      "number is lower than 0");
+  }
+  native.call('TVChannelManager_GetChannelListFavorite', {
+    favoriteId: this.id,
+    nStart: args.nStart,
+    number: args.number
+  }, function(msg) {
+    if (msg.error) {
+      if (validatorType.isFunction(args.errorCallback)) {
+        args.errorCallback(native.getErrorObject(msg));
+      }
+    } else {
+      args.successCallback(dictListToChannelList(msg.channelInfos));
+    }
+  });
+};
+
+/**
+ * An enumerator that defined signal states
+ * @enum {string}
+ */
+var SignalState = {
+  SIGNAL_STATE_OK: 'SIGNAL_STATE_OK',
+  SIGNAL_STATE_NO_SIGNAL: 'SIGNAL_STATE_NO_SIGNAL'
+};
+
+function ChannelInfo(dict) {
+  for (var key in dict) {
+    if (dict.hasOwnProperty(key)) {
+      Object.defineProperty(this, key, {
+        value: dict[key],
+        enumerable: true
+      });
+    }
+  }
+}
+
+function dictListToChannelList(list) {
+  var result = [],
+      i = 0,
+      il = list.length;
+  for (; i < il; ++i) {
+    result.push(new ChannelInfo(list[i]));
+  }
+  return result;
+}
+
+function ProgramInfo(dict) {
+  for (var key in dict) {
+    if (dict.hasOwnProperty(key)) {
+      Object.defineProperty(this, key, {
+        value: key === 'startTime' ? new tizen.TZDate(new Date(dict[key])) : dict[key],
+        enumerable: true
+      });
+    }
+  }
+}
+
+function dictListToProgramList(list) {
+  var result = [],
+      i = 0,
+      il = list.length;
+  for (; i < il; ++i) {
+    result.push(new ProgramInfo(list[i]));
+  }
+  return result;
+}
+
+function ListenerManager(native, listenerName) {
+  this.listeners = {};
+  this.nextId = 1;
+  native.addListener(listenerName, this.onListenerCalled.bind(this));
+}
+
+ListenerManager.prototype.onListenerCalled = function(msg) {
+  for (var key in this.listeners) {
+    if (this.listeners.hasOwnProperty(key)) {
+      this.listeners[key](msg);
+    }
+  }
+};
+
+ListenerManager.prototype.addListener = function(callback) {
+  var id = this.nextId;
+  this.listeners[id] = callback;
+  ++this.nextId;
+  return id;
+};
+
+ListenerManager.prototype.removeListener = function(watchId) {
+  if (this.listeners.hasOwnProperty(watchId)) {
+    delete this.listeners[watchId];
+  }
+};
+
+
+/**
+ * @const
+ * @type {string}
+ */
+var CHANNEL_CHANGE_LISTENER = 'ChannelChanged';
+
+var channelListener = new ListenerManager(native, CHANNEL_CHANGE_LISTENER);
+
+
+/**
+ * @const
+ * @type {string}
+ */
+var SIGNAL_STATE_LISTENER = 'SignalStateChanged';
+
+var signalStateListener = new ListenerManager(native, SIGNAL_STATE_LISTENER);
+
+/**
+ * @const
+ * @type {string}
+ */
+var PROGRAMINFO_LISTENER = 'ProgramInfoReceived';
+
+//TVChannelManager interface
+function TVChannelManager() {
+  if (!(this instanceof TVChannelManager)) {
+    throw new TypeError;
+  }
+}
+
+
+TVChannelManager.prototype.tune = function(tuneOption, successCallback, errorCallback, windowType) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.TV_CHANNEL);
+  var data = validator.validateArgs(arguments, [
+    {
+      name: 'tuneOption',
+      type: validator.Types.DICTIONARY
+    },
+    {
+      name: 'callback',
+      type: validator.Types.LISTENER,
+      values: ['onsuccess', 'onnosignal', 'onprograminforeceived']
+    },
+    {
+      name: 'errorCallback',
+      type: validator.Types.FUNCTION,
+      optional: true,
+      nullable: true
+    },
+    {
+      name: 'windowType',
+      optional: true,
+      nullable: true,
+      type: validator.Types.ENUM,
+      values: validatorType.getValues(WindowType)
+    }
+  ]);
+  native.addListener(PROGRAMINFO_LISTENER, function(msg) {
+    if (validatorType.isFunction(data.callback.onprograminforeceived)) {
+      data.callback.onprograminforeceived(new ProgramInfo(msg.program), msg.windowType);
+    }
+  });
+  native.call('TVChannelManager_tune', {
+    tuneOption: data.tuneOption,
+    windowType: data.windowType
+  }, function(msg) {
+    if (msg.error) {
+      if (validatorType.isFunction(data.errorCallback)) {
+        data.errorCallback(native.getErrorObject(msg));
+      }
+    } else if (msg.nosignal) {
+      if (validatorType.isFunction(data.callback.onnosignal)) {
+        data.callback.onnosignal();
+      }
+    } else if (msg.success) {
+      if (validatorType.isFunction(data.callback.onsuccess)) {
+        data.callback.onsuccess(new ChannelInfo(msg.channel), msg.windowType);
+      }
+    }
+  });
+};
+
+function tuneUpDown(args, methodName) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.TV_CHANNEL);
+  var data = validator.validateArgs(args, [
+    {
+      name: 'callback',
+      type: validator.Types.LISTENER,
+      values: ['onsuccess', 'onnosignal', 'onprograminforeceived']
+    },
+    {
+      name: 'errorCallback',
+      type: validator.Types.FUNCTION,
+      optional: true,
+      nullable: true
+    },
+    {
+      name: 'tuneMode',
+      optional: true,
+      nullable: true,
+      type: validator.Types.ENUM,
+      values: validatorType.getValues(TuneMode)
+    },
+    {
+      name: 'windowType',
+      optional: true,
+      nullable: true,
+      type: validator.Types.ENUM,
+      values: validatorType.getValues(WindowType)
+    }
+  ]);
+  native.addListener(PROGRAMINFO_LISTENER, function(msg) {
+    if (validatorType.isFunction(data.callback.onprograminforeceived)) {
+      data.callback.onprograminforeceived(new ProgramInfo(msg.program), msg.windowType);
+    }
+  });
+  native.call(methodName, {
+    tuneMode: data.tuneMode,
+    windowType: data.windowType
+  }, function(msg) {
+    if (msg.error) {
+      if (validatorType.isFunction(data.errorCallback)) {
+        data.errorCallback(native.getErrorObject(msg));
+      }
+    } else if (msg.nosignal) {
+      if (validatorType.isFunction(data.callback.onnosignal)) {
+        data.callback.onnosignal();
+      }
+    } else if (msg.success) {
+      if (validatorType.isFunction(data.callback.onsuccess)) {
+        data.callback.onsuccess(new ChannelInfo(msg.channel), msg.windowType);
+      }
+    }
+  });
+}
+
+TVChannelManager.prototype.tuneUp = function(callback, errorCallback, tuneMode, windowType) {
+  tuneUpDown(arguments, 'TVChannelManager_tuneUp');
+};
+
+TVChannelManager.prototype.tuneDown = function(successCallback,
+    errorCallback, tuneMode, windowType) {
+  tuneUpDown(arguments, 'TVChannelManager_tuneDown');
+};
+
+TVChannelManager.prototype.findChannel = function(major, minor, successCallback, errorCallback) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.TV_CHANNEL);
+  var args = validator.validateArgs(arguments, [
+    {
+      name: 'major',
+      optional: false,
+      nullable: false,
+      type: validator.Types.LONG
+    },
+    {
+      name: 'minor',
+      optional: false,
+      nullable: false,
+      type: validator.Types.LONG
+    },
+    {
+      name: 'successCallback',
+      type: validator.Types.FUNCTION,
+      optional: false,
+      nullable: false
+    },
+    {
+      name: 'errorCallback',
+      type: validator.Types.FUNCTION,
+      optional: true,
+      nullable: true
+    }
+  ]);
+  native.call('TVChannelManager_findChannel', {
+    major: args.major,
+    minor: args.minor
+  }, function(msg) {
+    if (msg.error) {
+      if (validatorType.isFunction(args.errorCallback)) {
+        args.errorCallback(native.getErrorObject(msg));
+      }
+    } else {
+      args.successCallback(dictListToChannelList(msg.channelInfos));
+    }
+  });
+};
+
+TVChannelManager.prototype.getChannelList = function(successCallback,
+    errorCallback, tuneMode, start, number) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.TV_CHANNEL);
+  var args = validator.validateArgs(arguments, [
+    {
+      name: 'successCallback',
+      type: validator.Types.FUNCTION,
+      optional: false,
+      nullable: false
+    },
+    {
+      name: 'errorCallback',
+      type: validator.Types.FUNCTION,
+      optional: true,
+      nullable: true
+    },
+    {
+      name: 'tuneMode',
+      optional: true,
+      nullable: true,
+      type: validator.Types.ENUM,
+      values: validatorType.getValues(TuneMode)
+    },
+    {
+      name: 'nStart',
+      optional: true,
+      nullable: true,
+      type: validator.Types.LONG
+    },
+    {
+      name: 'number',
+      optional: true,
+      nullable: true,
+      type: validator.Types.LONG
+    }
+  ]);
+  if (args.nStart < 0) {
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+      "nStart is lower than 0");
+  }
+  if (args.number < 0) {
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+      "number is lower than 0");
+  }
+  native.call('TVChannelManager_getChannelList', {
+    tuneMode: args.tuneMode,
+    nStart: args.nStart,
+    number: args.number
+  }, function(msg) {
+    if (msg.error) {
+      if (validatorType.isFunction(args.errorCallback)) {
+        args.errorCallback(native.getErrorObject(msg));
+      }
+    } else {
+      args.successCallback(dictListToChannelList(msg.channelInfos));
+    }
+  });
+};
+
+TVChannelManager.prototype.getCurrentChannel = function(windowType) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.TV_CHANNEL);
+  var args = validator.validateArgs(arguments, [
+    {
+      name: 'windowType',
+      optional: true,
+      nullable: true,
+      type: validator.Types.ENUM,
+      values: validatorType.getValues(WindowType)
+    }
+  ]);
+  var ret = native.callSync('TVChannelManager_getCurrentChannel', {
+    windowType: args.windowType ? args.windowType : WindowType.MAIN
+  });
+  if (native.isFailure(ret)) {
+    throw native.getErrorObject(ret);
+  }
+  return new ChannelInfo(native.getResultObject(ret));
+};
+
+TVChannelManager.prototype.getProgramList = function(channelInfo,
+    startTime, successCallback, errorCallback, duration) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.TV_CHANNEL);
+  var args = validator.validateArgs(arguments, [
+    {
+      name: 'channelInfo',
+      type: validator.Types.PLATFORM_OBJECT,
+      values: ChannelInfo
+    },
+    {
+      name: 'startTime',
+      type: validator.Types.PLATFORM_OBJECT,
+      values: tizen.TZDate
+    },
+    {
+      name: 'successCallback',
+      type: validator.Types.FUNCTION,
+      optional: false,
+      nullable: false
+    },
+    {
+      name: 'errorCallback',
+      type: validator.Types.FUNCTION,
+      optional: true,
+      nullable: true
+    },
+    {
+      name: 'duration',
+      optional: true,
+      nullable: true,
+      type: validator.Types.LONG
+    }
+  ]);
+  native.call('TVChannelManager_getProgramList', {
+    channelId: args.channelInfo._serviceId,
+    startTime: args.startTime.getTime(),
+    duration: args.duration
+  }, function(msg) {
+    if (msg.error) {
+      if (validatorType.isFunction(args.errorCallback)) {
+        args.errorCallback(native.getErrorObject(msg));
+      }
+    } else {
+      args.successCallback(dictListToProgramList(msg.programInfos));
+    }
+  });
+};
+
+TVChannelManager.prototype.getCurrentProgram = function(windowType) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.TV_CHANNEL);
+  var args = validator.validateArgs(arguments, [
+    {
+      name: 'windowType',
+      optional: true,
+      nullable: true,
+      type: validator.Types.ENUM,
+      values: validatorType.getValues(WindowType)
+    }
+  ]);
+  var ret = native.callSync('TVChannelManager_getCurrentProgram', {
+    windowType: args.windowType ? args.windowType : WindowType.MAIN
+  });
+  if (native.isFailure(ret)) {
+    throw native.getErrorObject(ret);
+  }
+  return new ProgramInfo(native.getResultObject(ret));
+};
+
+TVChannelManager.prototype.addChannelChangeListener = function(callback, windowType) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.TV_CHANNEL);
+  var args = validator.validateArgs(arguments, [
+    {
+      name: 'callback',
+      type: validator.Types.FUNCTION
+    },
+    {
+      name: 'windowType',
+      optional: true,
+      nullable: true,
+      type: validator.Types.ENUM,
+      values: validatorType.getValues(WindowType)
+    }
+  ]);
+
+  return channelListener.addListener(function(msg){
+    var channel = new ChannelInfo(msg.channel);
+    args.callback(channel, msg.windowType);
+  });
+};
+
+TVChannelManager.prototype.removeChannelChangeListener = function(listenerId) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.TV_CHANNEL);
+  channelListener.removeListener(listenerId);
+};
+
+TVChannelManager.prototype.addSignalStateChangeListener = function(callback) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.TV_CHANNEL);
+  var args = validator.validateArgs(arguments, [
+    {
+      name: 'callback',
+      type: validator.Types.FUNCTION
+    }
+    ]);
+
+  return signalStateListener.addListener(function(msg){
+      args.callback(msg.state)});
+};
+
+TVChannelManager.prototype.removeSignalStateChangeListener = function(listenerId) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.TV_CHANNEL);
+  signalStateListener.removeListener(listenerId);
+};
+
+TVChannelManager.prototype.addProgramChangeListener = function(successCallback, windowType) {
+  return undefined;
+};
+
+TVChannelManager.prototype.removeProgramChangeListener = function(listenerId) {
+  return undefined;
+};
+
+TVChannelManager.prototype.getNumOfAvailableTuner = function()
+    {
+  var ret = native.callSync('TVChannelManager_getNumOfAvailableTuner');
+  if (native.isFailure(ret)) {
+    throw native.getErrorObject(ret);
+  }
+  return native.getResultObject(ret);
+};
+
+TVChannelManager.prototype.getFavorites = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.TV_CHANNEL);
+  var ret = native.callSync('TVChannelManager_GetFavorites');
+  if (native.isFailure(ret)) {
+    throw native.getErrorObject(ret);
+  }
+  var items = [],
+      list = native.getResultObject(ret);
+  for (var i = 0, il = list.length; i < il; ++i) {
+    items.push(new FavoriteList(list[i]));
+  }
+  return items;
+};
+
+TVChannelManager.prototype.getBroadcastStandard = function(type) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.TV_CHANNEL);
+  var args = validator.validateArgs(arguments, [
+    {
+      name: 'type',
+      optional: true,
+      nullable: true,
+      type: validator.Types.ENUM,
+      values: Object.keys(WindowType)
+    }
+  ]);
+  var ret = native.callSync('TVChannelManager_GetBroadcastStandard', {});
+  if (native.isFailure(ret)) {
+    throw native.getErrorObject(ret);
+  }
+  return native.getResultObject(ret);
+};
+
+exports = new TVChannelManager();
diff --git a/webWidgetTCT_device/src/tvchannel/tvchannel_extension.cc b/webWidgetTCT_device/src/tvchannel/tvchannel_extension.cc
new file mode 100755 (executable)
index 0000000..56e4da9
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2015 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 "tvchannel/tvchannel_extension.h"
+#include "tvchannel/tvchannel_instance.h"
+
+// This will be generated from datasync_api.js.
+extern const char kSource_tvchannel_api[];
+
+TVChannelExtension::TVChannelExtension() {
+    SetExtensionName("tizen.tvchannel");
+    SetJavaScriptAPI(kSource_tvchannel_api);
+}
+
+TVChannelExtension::~TVChannelExtension() {
+}
+
+common::Instance* TVChannelExtension::CreateInstance() {
+    return new extension::tvchannel::TVChannelInstance();
+}
+
+// entry point
+common::Extension* CreateExtension() {
+    return new TVChannelExtension();
+}
+
diff --git a/webWidgetTCT_device/src/tvchannel/tvchannel_extension.h b/webWidgetTCT_device/src/tvchannel/tvchannel_extension.h
new file mode 100755 (executable)
index 0000000..fc336a8
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2015 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 SRC_TVCHANNEL_TVCHANNEL_EXTENSION_H_
+#define SRC_TVCHANNEL_TVCHANNEL_EXTENSION_H_
+
+#include "common/extension.h"
+
+class TVChannelExtension: public common::Extension {
+ public:
+    TVChannelExtension();
+    virtual ~TVChannelExtension();
+ private:
+    virtual common::Instance* CreateInstance();
+};
+
+#endif  // SRC_TVCHANNEL_TVCHANNEL_EXTENSION_H_
diff --git a/webWidgetTCT_device/src/tvchannel/tvchannel_instance.cc b/webWidgetTCT_device/src/tvchannel/tvchannel_instance.cc
new file mode 100755 (executable)
index 0000000..6691b8c
--- /dev/null
@@ -0,0 +1,792 @@
+/*
+ * Copyright (c) 2015 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 "tvchannel/tvchannel_instance.h"
+#include <functional>
+#include "common/logger.h"
+#include "tizen/tizen.h"
+#include "common/picojson.h"
+#include "common/tools.h"
+#include "tvchannel/channel_info.h"
+#include "tvchannel/program_info.h"
+#include "tvchannel/types.h"
+#include "common/task-queue.h"
+
+namespace extension {
+namespace tvchannel {
+
+using common::ErrorCode;
+using common::TaskQueue;
+
+TVChannelInstance::TVChannelInstance() :
+    m_pSubscriber(nullptr) {
+    using std::placeholders::_1;
+    using std::placeholders::_2;
+
+    #define REGISTER_ASYNC(c, func) \
+        RegisterSyncHandler(c, func);
+    #define REGISTER_SYNC(c, func) \
+        RegisterSyncHandler(c, func);
+
+    REGISTER_SYNC("TVChannelManager_GetFavorites",
+        std::bind(&TVChannelInstance::GetFavorites, this, _1, _2));
+    REGISTER_SYNC("TVChannelManager_UpdateFavorites",
+        std::bind(&TVChannelInstance::UpdateFavorites, this, _1, _2));
+    REGISTER_SYNC("TVChannelManager_GetChannelListFavorite",
+        std::bind(&TVChannelInstance::GetChannelListFavorite, this, _1, _2));
+    REGISTER_SYNC("TVChannelManager_getCurrentChannel",
+        std::bind(&TVChannelInstance::getCurrentChannel, this, _1, _2));
+    REGISTER_SYNC("TVChannelManager_getCurrentProgram",
+        std::bind(&TVChannelInstance::getCurrentProgram, this, _1, _2));
+    REGISTER_ASYNC("TVChannelManager_findChannel",
+        std::bind(&TVChannelInstance::findChannel, this, _1, _2));
+    REGISTER_ASYNC("TVChannelManager_getChannelList",
+        std::bind(&TVChannelInstance::getChannelList, this, _1, _2));
+    REGISTER_ASYNC("TVChannelManager_getProgramList",
+        std::bind(&TVChannelInstance::getProgramList, this, _1, _2));
+    REGISTER_ASYNC("TVChannelManager_GetBroadcastStandard",
+        std::bind(&TVChannelInstance::GetBroadcastStandard, this, _1, _2));
+    REGISTER_ASYNC("TVChannelManager_tune",
+        std::bind(&TVChannelInstance::tune, this, _1, _2));
+    REGISTER_ASYNC("TVChannelManager_tuneUp",
+        std::bind(&TVChannelInstance::tuneUp, this, _1, _2));
+    REGISTER_ASYNC("TVChannelManager_tuneDown",
+        std::bind(&TVChannelInstance::tuneDown, this, _1, _2));
+
+    #undef REGISTER_ASYNC
+    #undef REGISTER_SYNC
+
+    m_TVChannelManager = TVChannelManager::create();
+    if (m_TVChannelManager != nullptr) {
+        m_TVChannelManager->registerListener(this);
+    }
+}
+
+TVChannelInstance::~TVChannelInstance() {
+    LoggerD("Entered");
+    if (m_TVChannelManager != nullptr) {
+        m_TVChannelManager->unregisterListener();
+    }
+    delete m_TVChannelManager;
+}
+
+void TVChannelInstance::tune(picojson::value const& args,
+    picojson::object& out) {
+    LoggerD("Enter");
+    picojson::object tuneOption =
+        args.get("tuneOption").get<picojson::object>();
+    double callbackId = args.get("callbackId").get<double>();
+    std::string windowType;
+    if (args.contains("windowType")) {
+        windowType = args.get("windowType").get<std::string>();
+    } else {
+        windowType = "MAIN";
+    }
+
+    WindowType type;
+    common::PlatformResult retVal = stringToWindowType(windowType, type);
+    if (retVal.IsError()) {
+        ReportError(retVal, &out);
+        return;
+    }
+    std::shared_ptr<TVChannelManager::TuneData> pTuneData(
+        new TVChannelManager::TuneData(TuneOption(tuneOption),
+            type, callbackId));
+
+    std::function<void(std::shared_ptr<
+        TVChannelManager::TuneData> const&)> task = std::bind(
+            &TVChannelInstance::tuneTask, this, std::placeholders::_1);
+    std::function<void(std::shared_ptr<
+            TVChannelManager::TuneData> const&)> taskAfter = std::bind(
+                &TVChannelInstance::tuneTaskAfter, this, std::placeholders::_1);
+
+    common::TaskQueue::GetInstance().Queue<TVChannelManager::TuneData>(task,
+        taskAfter, pTuneData);
+
+    picojson::value v;
+    ReportSuccess(v, out);
+}
+
+void TVChannelInstance::tuneTaskAfter(
+    std::shared_ptr<TVChannelManager::TuneData> const& _tuneData) {
+    LoggerD("Enter");
+    if (_tuneData->error.IsError()) {
+        LoggerE("Failed to tune.");
+        picojson::value event = picojson::value(picojson::object());
+        picojson::object& obj = event.get<picojson::object>();
+        obj.insert(std::make_pair("callbackId", picojson::value(
+            _tuneData->callbackId)));
+        obj.insert(std::make_pair("error", _tuneData->error.ToJSON()));
+        Instance::PostMessage(this, event.serialize().c_str());
+    }
+}
+
+void TVChannelInstance::tuneTask(
+    std::shared_ptr<TVChannelManager::TuneData> const& _tuneData) {
+    LoggerD("Enter");
+    if (m_TVChannelManager != nullptr) {
+        m_TVChannelManager->tune(_tuneData);
+    } else {
+        _tuneData->error = common::PlatformResult(ErrorCode::UNKNOWN_ERR,
+            "Channel manager not initialized");
+    }
+}
+
+void TVChannelInstance::tuneUp(picojson::value const& args,
+    picojson::object& out) {
+    LoggerD("Enter");
+
+    NavigatorMode navMode;
+    if (args.contains("tuneMode")) {
+        common::PlatformResult err = stringToNavigatorMode(
+                args.get("tuneMode").get<std::string>(), navMode);
+        if (err.IsError()) {
+            ReportError(err, &out);
+            return;
+        }
+    } else {
+        navMode = NavigatorMode::ALL;
+    }
+
+    double callbackId = args.get("callbackId").get<double>();
+    std::string windowType;
+    if (args.contains("windowType")) {
+        windowType = args.get("windowType").get<std::string>();
+    } else {
+        windowType = "MAIN";
+    }
+
+    WindowType type;
+    common::PlatformResult retVal = stringToWindowType(windowType, type);
+    if (retVal.IsError()) {
+        ReportError(retVal, &out);
+        return;
+    }
+    std::shared_ptr<TVChannelManager::TuneData> pTuneData(
+        new TVChannelManager::TuneData(navMode,
+            type, callbackId));
+
+    std::function<void(std::shared_ptr<
+        TVChannelManager::TuneData> const&)> task = std::bind(
+            &TVChannelInstance::tuneUpTask, this, std::placeholders::_1);
+    std::function<void(std::shared_ptr<
+            TVChannelManager::TuneData> const&)> taskAfter = std::bind(
+                &TVChannelInstance::tuneTaskAfter, this, std::placeholders::_1);
+
+    common::TaskQueue::GetInstance().Queue<TVChannelManager::TuneData>(task,
+        taskAfter, pTuneData);
+
+    picojson::value v;
+    ReportSuccess(v, out);
+}
+
+void TVChannelInstance::tuneUpTask(
+    std::shared_ptr<TVChannelManager::TuneData> const& _tuneData) {
+    if (m_TVChannelManager != nullptr) {
+        m_TVChannelManager->tuneUp(_tuneData);
+    } else {
+        _tuneData->error = common::PlatformResult(ErrorCode::UNKNOWN_ERR,
+            "Channel manager not initialized");
+    }
+}
+
+void TVChannelInstance::tuneDown(picojson::value const& args,
+    picojson::object& out) {
+    LoggerD("Enter");
+
+    NavigatorMode navMode;
+    if (args.contains("tuneMode")) {
+        common::PlatformResult err = stringToNavigatorMode(
+                args.get("tuneMode").get<std::string>(), navMode);
+        if (err.IsError()) {
+            ReportError(err, &out);
+            return;
+        }
+    } else {
+        navMode = NavigatorMode::ALL;
+    }
+
+    double callbackId = args.get("callbackId").get<double>();
+    std::string windowType;
+    if (args.contains("windowType")) {
+        windowType = args.get("windowType").get<std::string>();
+    } else {
+        windowType = "MAIN";
+    }
+
+    WindowType type;
+    common::PlatformResult retVal = stringToWindowType(windowType, type);
+    if (retVal.IsError()) {
+        ReportError(retVal, &out);
+        return;
+    }
+    std::shared_ptr<TVChannelManager::TuneData> pTuneData(
+        new TVChannelManager::TuneData(navMode,
+            type, callbackId));
+
+    std::function<void(std::shared_ptr<
+        TVChannelManager::TuneData> const&)> task = std::bind(
+            &TVChannelInstance::tuneUpTask, this, std::placeholders::_1);
+    std::function<void(std::shared_ptr<
+            TVChannelManager::TuneData> const&)> taskAfter = std::bind(
+                &TVChannelInstance::tuneTaskAfter, this, std::placeholders::_1);
+
+    common::TaskQueue::GetInstance().Queue<TVChannelManager::TuneData>(task,
+        taskAfter, pTuneData);
+
+    picojson::value v;
+    ReportSuccess(v, out);
+}
+
+void TVChannelInstance::tuneDownTask(
+    std::shared_ptr<TVChannelManager::TuneData> const& _tuneData) {
+    if (m_TVChannelManager != nullptr) {
+        m_TVChannelManager->tuneDown(_tuneData);
+    } else {
+        _tuneData->error = common::PlatformResult(ErrorCode::UNKNOWN_ERR,
+            "Channel manager not initialized");
+    }
+}
+
+void TVChannelInstance::getCurrentChannel(picojson::value const& args,
+    picojson::object& out) {
+
+    std::unique_ptr<ChannelInfo> pChannel(new ChannelInfo());
+    common::PlatformResult error(ErrorCode::NO_ERROR);
+    WindowType type;
+    common::PlatformResult retVal = stringToWindowType(
+        args.get("windowType").get<std::string>(),
+        type);
+    if (retVal.IsError()) {
+        ReportError(retVal, &out);
+        return;
+    }
+    if (m_TVChannelManager != nullptr) {
+        error = m_TVChannelManager->getCurrentChannel(\
+            pChannel,
+            type);
+    } else {
+        error = common::PlatformResult(ErrorCode::UNKNOWN_ERR,
+            "Channel manager not initialized");
+    }
+    if (error.IsError()) {
+        ReportError(error, &out);
+    } else {
+        picojson::value v = channelInfoToJson(pChannel);
+        ReportSuccess(v, out);
+    }
+}
+
+picojson::value TVChannelInstance::channelInfoToJson(
+    const std::unique_ptr<ChannelInfo> &pChannel) {
+    picojson::value::object channel;
+    channel.insert(
+        std::make_pair("major",
+            picojson::value(static_cast<double>(pChannel->getMajor()))));
+    channel.insert(
+        std::make_pair("minor",
+            picojson::value(static_cast<double>(pChannel->getMinor()))));
+    channel.insert(
+        std::make_pair("channelName",
+            picojson::value(pChannel->getChannelName())));
+    channel.insert(
+        std::make_pair("programNumber",
+            picojson::value(
+                static_cast<double>(pChannel->getProgramNumber()))));
+    channel.insert(
+        std::make_pair("ptc",
+            picojson::value(static_cast<double>(pChannel->getPtc()))));
+    channel.insert(
+        std::make_pair("lcn",
+            picojson::value(static_cast<double>(pChannel->getLcn()))));
+    channel.insert(
+        std::make_pair("sourceID",
+            picojson::value(static_cast<double>(pChannel->getSourceID()))));
+    channel.insert(
+        std::make_pair("transportStreamID",
+            picojson::value(
+                static_cast<double>(pChannel->getTransportStreamID()))));
+    channel.insert(
+        std::make_pair("originalNetworkID",
+            picojson::value(
+                static_cast<double>(pChannel->getOriginalNetworkID()))));
+    channel.insert(
+        std::make_pair("serviceName",
+            picojson::value(pChannel->getServiceName())));
+    // internal property
+    channel.insert(
+        std::make_pair("_serviceId", 
+            picojson::value(std::to_string(pChannel->getServiceID()))));
+    return picojson::value(channel);
+}
+
+picojson::value TVChannelInstance::programInfoToJson(
+    const std::unique_ptr<ProgramInfo>& pInfo) {
+    picojson::value::object program;
+    program.insert(std::make_pair("title", picojson::value(pInfo->getTitle())));
+    program.insert(
+        std::make_pair("startTime",
+            picojson::value(static_cast<double>(pInfo->getStartTimeMs()))));
+    program.insert(
+        std::make_pair("duration",
+            picojson::value(static_cast<double>(pInfo->getDuration()))));
+    program.insert(
+        std::make_pair("detailedDescription",
+            picojson::value(pInfo->getDetailedDescription())));
+    program.insert(
+        std::make_pair("language", picojson::value(pInfo->getLanguage())));
+    program.insert(
+        std::make_pair("rating", picojson::value(pInfo->getRating())));
+
+    picojson::value result(program);
+    return result;
+}
+
+void TVChannelInstance::getCurrentProgram(const picojson::value& args,
+    picojson::object& out) {
+    std::unique_ptr<ProgramInfo> pInfo(new ProgramInfo());
+    WindowType type;
+    common::PlatformResult retVal = stringToWindowType(
+        args.get("windowType").get<std::string>(),
+        type);
+    if (retVal.IsError()) {
+        ReportError(retVal, &out);
+        return;
+    }
+    common::PlatformResult error(ErrorCode::NO_ERROR);
+    if (m_TVChannelManager != nullptr) {
+        error = m_TVChannelManager->getCurrentProgram(pInfo.get(),
+            type);
+    } else {
+        error = common::PlatformResult(ErrorCode::UNKNOWN_ERR,
+            "Channel manager not initialized");
+    }
+    if (error.IsError()) {
+        ReportError(error, &out);
+    } else {
+        ReportSuccess(programInfoToJson(pInfo), out);
+    }
+}
+
+void TVChannelInstance::onChannelChange(double callbackId) {
+    LoggerD("Enter");
+    if (m_TVChannelManager == nullptr) {
+        LoggerW("Channel manager not initialized");
+        return;
+    }
+    WindowType windowType;
+    common::PlatformResult retVal = stringToWindowType(
+        "MAIN",
+        windowType);
+    if (retVal.IsError()) {
+        LoggerW("Failed to get current channel");
+        return;
+    }
+
+    picojson::value::object dict;
+    std::unique_ptr<ChannelInfo> pChannel(new ChannelInfo());
+    retVal = m_TVChannelManager->getCurrentChannel(pChannel,
+                windowType);
+    if (retVal.IsError()) {
+        LoggerW("Failed to get current channel");
+        return;
+    }
+    dict["listenerId"] = picojson::value("ChannelChanged");
+    dict["channel"] = channelInfoToJson(pChannel);
+    dict["windowType"] = picojson::value("MAIN");
+    dict["success"] = picojson::value(true);
+    picojson::value resultListener(dict);
+    Instance::PostMessage(this, resultListener.serialize().c_str());
+    if (callbackId !=- 1) {
+        dict.erase("listenerId");
+        dict["callbackId"] = picojson::value(callbackId);
+        picojson::value resultCallback(dict);
+        Instance::PostMessage(this, resultCallback.serialize().c_str());
+    }
+}
+
+void TVChannelInstance::onEPGReceived(double callbackId) {
+    if (m_TVChannelManager == nullptr) {
+        LoggerW("Channel manager not initialized");
+        return;
+    }
+    common::PlatformResult retVal(ErrorCode::NO_ERROR);
+    picojson::value::object dict;
+    dict["listenerId"] = picojson::value("ProgramInfoReceived");
+    dict["windowType"] = picojson::value("MAIN");
+    std::unique_ptr<ProgramInfo> pInfo(new ProgramInfo());
+    retVal = m_TVChannelManager->getCurrentProgram(pInfo.get(), MAIN);
+    if (retVal.IsError()) {
+        LoggerW("Failed to get current program");
+        return;
+    }
+    dict["program"] = programInfoToJson(pInfo);
+    picojson::value result(dict);
+    Instance::PostMessage(this, result.serialize().c_str());
+}
+void TVChannelInstance::onNoSignal(double callbackId) {
+
+    picojson::value::object dict;
+    dict["windowType"] = picojson::value("MAIN");
+    dict["callbackId"] = picojson::value(callbackId);
+    dict["nosignal"] = picojson::value(true);
+    picojson::value result(dict);
+    Instance::PostMessage(this, result.serialize().c_str());
+}
+
+void TVChannelInstance::onSignalStateChange(bool ifSignalOK)
+{
+    picojson::value state;
+    state = ifSignalOK ? picojson::value("SIGNAL_STATE_OK")
+                     : picojson::value("SIGNAL_STATE_NO_SIGNAL");
+    picojson::value::object dict;
+    dict["state"]=state;
+    dict["listenerId"] = picojson::value("SignalStateChanged");
+    picojson::value result(dict);
+    Instance::PostMessage(this, result.serialize().c_str());
+}
+
+void TVChannelInstance::findChannel(const picojson::value& args,
+    picojson::object& out) {
+    LoggerD("Enter");
+    if (m_TVChannelManager == nullptr) {
+        common::PlatformResult error = common::PlatformResult(
+            ErrorCode::UNKNOWN_ERR,
+            "Channel manager not initialized");
+        ReportError(error, &out);
+        return;
+    }
+    std::function<void(std::shared_ptr<TVChannelManager::FindChannelData>)>
+        asyncWork = std::bind(
+            &TVChannelManager::findChannel,
+            m_TVChannelManager,
+            std::placeholders::_1);
+    std::function<void(std::shared_ptr<TVChannelManager::FindChannelData>)>
+        afterWork = std::bind(
+            &TVChannelInstance::findChannelResult,
+            this,
+            std::placeholders::_1);
+    std::shared_ptr<TVChannelManager::FindChannelData> data(
+        new TVChannelManager::FindChannelData());
+    data->major = std::stoi(args.get("major").to_str());
+    data->minor = std::stoi(args.get("minor").to_str());
+    data->callbackId = args.get("callbackId").get<double>();
+    TaskQueue::GetInstance().Queue<TVChannelManager::FindChannelData>(
+        asyncWork,
+        afterWork,
+        data);
+    picojson::value result;
+    ReportSuccess(result, out);
+}
+
+void TVChannelInstance::findChannelResult(
+    const std::shared_ptr<TVChannelManager::FindChannelData>& data) {
+    LoggerD("Enter");
+    picojson::value::object dict;
+    dict["callbackId"] = picojson::value(data->callbackId);
+    if (data->error.IsError()) {
+        dict["error"] = data->error.ToJSON();
+    } else {
+        picojson::value::array channels;
+        auto it = data->channels.begin();
+        for (; it != data->channels.end(); ++it) {
+            channels.push_back(channelInfoToJson(
+                std::unique_ptr<ChannelInfo>(*it)));
+        }
+        data->channels.clear();
+        dict["channelInfos"] = picojson::value(channels);
+    }
+    picojson::value result(dict);
+    Instance::PostMessage(this, result.serialize().c_str());
+}
+
+void TVChannelInstance::getChannelList(const picojson::value& args,
+    picojson::object& out) {
+    LoggerD("Enter");
+    if (m_TVChannelManager == nullptr) {
+        common::PlatformResult error = common::PlatformResult(
+            ErrorCode::UNKNOWN_ERR,
+            "Channel manager not initialized");
+        ReportError(error, &out);
+        return;
+    }
+    std::function<void(std::shared_ptr<TVChannelManager::GetChannelListData>)>
+        asyncWork = std::bind(
+            &TVChannelManager::getChannelList,
+            m_TVChannelManager,
+            std::placeholders::_1);
+    std::function<void(std::shared_ptr<TVChannelManager::GetChannelListData>)>
+        afterWork = std::bind(
+            &TVChannelInstance::getChannelListResult,
+            this,
+            std::placeholders::_1);
+    std::shared_ptr<TVChannelManager::GetChannelListData> data(
+        new TVChannelManager::GetChannelListData());
+    if (args.contains("tuneMode")) {
+        common::PlatformResult err = stringToNavigatorMode(
+                args.get("tuneMode").get<std::string>(), data->tuneMode);
+        if (err.IsError()) {
+            ReportError(err, &out);
+            return;
+        }
+    }
+    if (args.contains("nStart")) {
+        if (!args.get("nStart").is<picojson::null>()) {
+            data->nStart = std::stoi(args.get("nStart").to_str());
+            data->nStartSet = true;
+        }
+    }
+    if (args.contains("number")) {
+        if (!args.get("number").is<picojson::null>()) {
+            data->number = std::stoi(args.get("number").to_str());
+            data->numberSet = true;
+        }
+    }
+    data->callbackId = args.get("callbackId").get<double>();
+    TaskQueue::GetInstance().Queue<TVChannelManager::GetChannelListData>(
+        asyncWork,
+        afterWork,
+        data);
+    picojson::value result;
+    ReportSuccess(result, out);
+}
+
+void TVChannelInstance::getChannelListResult(
+    const std::shared_ptr<TVChannelManager::GetChannelListData>& data) {
+    picojson::value::object dict;
+    dict["callbackId"] = picojson::value(data->callbackId);
+    if (data->error.IsError()) {
+        dict["error"] = data->error.ToJSON();
+    } else {
+        picojson::value::array channels;
+        int32_t start = data->nStartSet ? data->nStart : 0;
+        int32_t number = data->numberSet ? data->number : data->channels.size();
+        int32_t i = 0;
+        auto it = data->channels.begin();
+        for (; it != data->channels.end(); ++it) {
+            // add only limited rows by start and number
+            if (i >= start && i < start + number) {
+                channels.push_back(channelInfoToJson(
+                    std::unique_ptr<ChannelInfo>(*it)));
+            } else {
+                delete *it;
+            }
+            ++i;
+        }
+        data->channels.clear();
+        dict["channelInfos"] = picojson::value(channels);
+    }
+    picojson::value result(dict);
+    Instance::PostMessage(this, result.serialize().c_str());
+}
+
+void TVChannelInstance::getProgramList(
+    const picojson::value& args, picojson::object& out) {
+    LoggerD("Enter");
+    if (m_TVChannelManager == nullptr) {
+        common::PlatformResult error = common::PlatformResult(
+            ErrorCode::UNKNOWN_ERR,
+            "Channel manager not initialized");
+        ReportError(error, &out);
+        return;
+    }
+    std::function<void(std::shared_ptr<TVChannelManager::GetProgramListData>)>
+        asyncWork = std::bind(
+            &TVChannelManager::getProgramList,
+            m_TVChannelManager,
+            std::placeholders::_1);
+    std::function<void(std::shared_ptr<TVChannelManager::GetProgramListData>)>
+        afterWork = std::bind(
+            &TVChannelInstance::getProgramListResult,
+            this,
+            std::placeholders::_1);
+    std::shared_ptr<TVChannelManager::GetProgramListData> data(
+        new TVChannelManager::GetProgramListData());
+    data->channelId = std::stoull(
+        args.get("channelId").to_str());
+    uint64_t startTime = std::stoull(args.get("startTime").to_str()) / 1000;
+    if (startTime > UINT32_MAX) {
+        data->startTime = UINT32_MAX;
+    } else {
+        data->startTime = startTime;
+    }
+    data->duration = UINT16_MAX;
+    if (args.contains("duration")) {
+        uint64_t duration = std::stoi(args.get("duration").to_str());
+        //duration is passed in hours, seconds are needed
+        if (duration * 3600 < UINT16_MAX) {
+            data->duration = duration * 3600;
+        }
+    }
+    data->callbackId = args.get("callbackId").get<double>();
+    TaskQueue::GetInstance().Queue<TVChannelManager::GetProgramListData>(
+        asyncWork,
+        afterWork,
+        data);
+    picojson::value result;
+    ReportSuccess(result, out);
+}
+
+void TVChannelInstance::getProgramListResult(
+    const std::shared_ptr<TVChannelManager::GetProgramListData>& data) {
+    picojson::value::object dict;
+    dict["callbackId"] = picojson::value(data->callbackId);
+    if (data->error.IsError()) {
+        dict["error"] = data->error.ToJSON();
+    } else {
+        picojson::value::array programs;
+        auto it = data->programs.begin();
+        for (; it != data->programs.end(); ++it) {
+            programs.push_back(programInfoToJson(
+                std::unique_ptr<ProgramInfo>(*it)));
+        }
+        data->programs.clear();
+        dict["programInfos"] = picojson::value(programs);
+    }
+    picojson::value result(dict);
+    Instance::PostMessage(this, result.serialize().c_str());
+}
+
+void TVChannelInstance::GetFavorites(const picojson::value& args,
+  picojson::object& out) {
+  LoggerD("Enter");
+
+  picojson::array items;
+  size_t num = m_TVChannelManager->GetFavoritesNumber();
+  // favorite ids start from 1
+  for (size_t i = 1; i <= num; ++i) {
+    picojson::object fav;
+    fav["id"] = picojson::value(static_cast<double>(i));
+    items.push_back(picojson::value(fav));
+  }
+  picojson::value result(items);
+  ReportSuccess(result, out);
+}
+
+void TVChannelInstance::UpdateFavorites(const picojson::value& args,
+  picojson::object& out) {
+  LoggerD("Enter");
+  if (m_TVChannelManager == nullptr) {
+    common::PlatformResult error = common::PlatformResult(
+        ErrorCode::UNKNOWN_ERR,
+        "Channel manager not initialized");
+    ReportError(error, &out);
+    return;
+  }
+  std::function<void(std::shared_ptr<TVChannelManager::UpdateFavoriteListData>)>
+    asyncWork = std::bind(
+        &TVChannelManager::UpdateFavoriteList,
+        m_TVChannelManager,
+        std::placeholders::_1);
+  std::function<void(std::shared_ptr<TVChannelManager::UpdateFavoriteListData>)>
+    afterWork = std::bind(
+        &TVChannelInstance::UpdateFavoritesAfter,
+        this,
+        std::placeholders::_1);
+  std::shared_ptr<TVChannelManager::UpdateFavoriteListData> data(
+    new TVChannelManager::UpdateFavoriteListData());
+  data->channelId = std::stoull(args.get("channelId").to_str());
+  data->favoriteId = std::stoi(args.get("favoriteId").to_str());
+  data->callbackId = std::stod(args.get("callbackId").to_str());
+  data->addToList = args.get("addToList").get<bool>();
+  TaskQueue::GetInstance().Queue<TVChannelManager::UpdateFavoriteListData>(
+    asyncWork,
+    afterWork,
+    data);
+  picojson::value result;
+  ReportSuccess(result, out);
+}
+
+void TVChannelInstance::UpdateFavoritesAfter(
+  const std::shared_ptr<TVChannelManager::UpdateFavoriteListData>& data) {
+  LoggerD("Enter");
+  picojson::value event = picojson::value(picojson::object());
+  picojson::object& obj = event.get<picojson::object>();
+  obj.insert(std::make_pair("callbackId", picojson::value(
+      data->callbackId)));
+  if (data->error.IsError()) {
+    LoggerE("Failed to update favorites");
+    common::tools::ReportError(data->error, &obj);
+  } else {
+    common::tools::ReportSuccess(obj);
+  }
+  Instance::PostMessage(this, event.serialize().c_str());
+}
+
+void TVChannelInstance::GetChannelListFavorite(const picojson::value& args,
+  picojson::object& out) {
+  LoggerD("Enter");
+  if (m_TVChannelManager == nullptr) {
+    common::PlatformResult error = common::PlatformResult(
+      ErrorCode::UNKNOWN_ERR,
+      "Channel manager not initialized");
+    ReportError(error, &out);
+    return;
+  }
+  std::function<void(std::shared_ptr<TVChannelManager::GetChannelListData>)>
+    asyncWork = std::bind(
+      &TVChannelManager::getChannelList,
+      m_TVChannelManager,
+      std::placeholders::_1);
+  std::function<void(std::shared_ptr<TVChannelManager::GetChannelListData>)>
+    afterWork = std::bind(
+      &TVChannelInstance::getChannelListResult,
+      this,
+      std::placeholders::_1);
+  std::shared_ptr<TVChannelManager::GetChannelListData> data(
+    new TVChannelManager::GetChannelListData());
+    data->tuneMode = NavigatorMode::ALL;
+  data->favoriteId = std::stoi(args.get("favoriteId").to_str());
+  if (args.contains("nStart")) {
+    if (!args.get("nStart").is<picojson::null>()) {
+      data->nStart = std::stoi(args.get("nStart").to_str());
+      data->nStartSet = true;
+    }
+  }
+  if (args.contains("number")) {
+    if (!args.get("number").is<picojson::null>()) {
+      data->number = std::stoi(args.get("number").to_str());
+      data->numberSet = true;
+    }
+  }
+  data->callbackId = std::stod(args.get("callbackId").to_str());
+  TaskQueue::GetInstance().Queue<TVChannelManager::GetChannelListData>(
+    asyncWork,
+    afterWork,
+    data);
+  picojson::value result;
+  ReportSuccess(result, out);
+}
+
+void TVChannelInstance::GetBroadcastStandard(const picojson::value& args,
+                                            picojson::object& out) {
+  LoggerD("Entered");
+  if (m_TVChannelManager == nullptr) {
+    common::PlatformResult error = common::PlatformResult(
+        ErrorCode::UNKNOWN_ERR, "Channel manager not initialized");
+    ReportError(error, &out);
+    return;
+  }
+  std::string serviceMode;
+  common::PlatformResult ret = m_TVChannelManager->GetBroadcastStandard(&serviceMode);
+  if (ret.IsError()) {
+    ReportError(ret, &out);
+    return;
+  }
+  ReportSuccess(picojson::value(serviceMode), out);
+}
+}  // namespace tvchannel
+}  // namespace extension
diff --git a/webWidgetTCT_device/src/tvchannel/tvchannel_instance.h b/webWidgetTCT_device/src/tvchannel/tvchannel_instance.h
new file mode 100755 (executable)
index 0000000..4117fed
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2015 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 SRC_TVCHANNEL_TVCHANNEL_INSTANCE_H_
+#define SRC_TVCHANNEL_TVCHANNEL_INSTANCE_H_
+
+#include <string>
+#include <memory>
+
+#include "common/extension.h"
+#include "common/platform_result.h"
+#include "common/picojson.h"
+#include "tvchannel/tvchannel_extension.h"
+#include "tvchannel/tvchannel_manager.h"
+
+namespace extension {
+namespace tvchannel {
+
+class TVChannelInstance:
+        public common::ParsedInstance,
+        public EventListener {
+ public:
+    TVChannelInstance();
+    virtual ~TVChannelInstance();
+
+ private:
+    //  not copiable, assignable
+    TVChannelInstance(TVChannelInstance const&) = delete;
+    TVChannelInstance& operator=(TVChannelInstance const&) = delete;
+
+    void getCurrentChannel(const picojson::value& args, picojson::object& out);
+    void getCurrentProgram(const picojson::value& args, picojson::object& out);
+    virtual void onChannelChange(double callbackId);
+    virtual void onEPGReceived(double callbackId);
+    virtual void onNoSignal(double callbackId);
+    virtual void onSignalStateChange(bool ifSignalOK);
+    void findChannel(const picojson::value& args, picojson::object& out);
+    void findChannelResult(
+        const std::shared_ptr<TVChannelManager::FindChannelData>& data);
+    void getChannelList(const picojson::value& args, picojson::object& out);
+    void getChannelListResult(
+        const std::shared_ptr<TVChannelManager::GetChannelListData>& data);
+    picojson::value channelInfoToJson(
+        const std::unique_ptr<ChannelInfo> &pChannel);
+    picojson::value programInfoToJson(
+        const std::unique_ptr<ProgramInfo> &pProgram);
+    void getProgramList(const picojson::value& args, picojson::object& out);
+    void getProgramListResult(
+        const std::shared_ptr<TVChannelManager::GetProgramListData>& data);
+    void tune(picojson::value const& args,
+        picojson::object& out);
+    void tuneUp(picojson::value const& args,
+        picojson::object& out);
+    void tuneDown(picojson::value const& args,
+        picojson::object& out);
+    void tuneTask(std::shared_ptr<
+        TVChannelManager::TuneData> const& _tuneData);
+    void tuneTaskAfter(
+        std::shared_ptr<TVChannelManager::TuneData> const& _pTuneData);
+    void tuneUpTask(std::shared_ptr<
+        TVChannelManager::TuneData> const& _tuneData);
+    void tuneDownTask(
+        std::shared_ptr<TVChannelManager::TuneData> const& _tuneData);
+    void GetFavorites(const picojson::value& args, picojson::object& out);
+    void UpdateFavorites(const picojson::value& args, picojson::object& out);
+    void UpdateFavoritesAfter(
+        std::shared_ptr<TVChannelManager::UpdateFavoriteListData> const& data);
+    void GetChannelListFavorite(const picojson::value& args, picojson::object& out);
+    void GetBroadcastStandard(const picojson::value& args, picojson::object& out);
+
+    ISignalSubscriber* m_pSubscriber;
+    TVChannelManager* m_TVChannelManager;
+};
+
+}  // namespace tvchannel
+}  // namespace extension
+
+#endif  // SRC_TVCHANNEL_TVCHANNEL_INSTANCE_H_
diff --git a/webWidgetTCT_device/src/tvchannel/tvchannel_manager.cc b/webWidgetTCT_device/src/tvchannel/tvchannel_manager.cc
new file mode 100755 (executable)
index 0000000..7520c36
--- /dev/null
@@ -0,0 +1,865 @@
+/*
+ * Copyright (c) 2015 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 "tvchannel/tvchannel_manager.h"
+#include <iconv.h>
+#include <stdint.h>
+#include <functional>
+#include <map>
+#include "tvchannel/channel_info.h"
+#include "tvchannel/program_info.h"
+#include "common/logger.h"
+#include "common/task-queue.h"
+#include <NavigationModeHelper.h>
+#include "tvchannel/criteria_filter.h"
+#include "tvchannel/tvchannel_instance.h"
+
+namespace extension {
+namespace tvchannel {
+
+using common::ErrorCode;
+using common::PlatformResult;
+
+TVChannelManager::TVChannelManager() :
+    m_listener(NULL) {
+    LoggerD("Enter");
+
+    ISourceControl* pSourceControl;
+    TVServiceAPI::CreateSourceControl(PROFILE_TYPE_MAIN, 0, &pSourceControl);
+    if(pSourceControl == nullptr) {
+        lastSourceState_ = SOURCE_STATE_NONE;
+        LoggerW("Failed to create tvs-api source control");
+    } else {
+        int ret = pSourceControl->GetSourceState(lastSourceState_);
+        if( ret <= 0) {
+          LoggerW("Failed to get source state from tvs-api source control");
+          lastSourceState_ = SOURCE_STATE_NONE;
+        }
+    }
+}
+
+TVChannelManager* TVChannelManager::create() {
+    LOGD("Enter");
+    TVChannelManager* TVchMgr = new TVChannelManager();
+    if (common::TvsSubscribeHelper::getInstance().getService() == nullptr) {
+        LoggerE("Failed to create tvs-api service");
+        delete TVchMgr;
+        return NULL;
+    }
+    return TVchMgr;
+}
+
+IService* TVChannelManager::getService() {
+    return common::TvsSubscribeHelper::getInstance().getService();
+}
+
+void TVChannelManager::tune(std::shared_ptr<TuneData> const& _pTuneData) {
+    LoggerD("Enter");
+    std::unique_lock<std::mutex> lock(tuneMutex);
+
+    WindowType windowType = _pTuneData->windowType;
+    TuneOption tuneOption = _pTuneData->tuneOption;
+
+    common::PlatformResult retVal(ErrorCode::NO_ERROR);
+    std::unique_ptr<ChannelInfo> pChannel(new ChannelInfo());
+    retVal = getCurrentChannel(pChannel, windowType);
+    if (retVal.IsError()) {
+        _pTuneData->error = retVal;
+        return;
+    }
+
+    TCServiceId currentServiceId = pChannel->getServiceID();
+
+    IServiceNavigation* serviceNavigation = nullptr;
+    retVal = getNavigation(&serviceNavigation, getProfile(windowType), SCREENID);
+    if (retVal.IsError()) {
+        _pTuneData->error = retVal;
+        return;
+    }
+
+    TSTvMode tvMode;
+    retVal = getTvMode(tvMode, serviceNavigation);
+    if (retVal.IsError()) {
+        _pTuneData->error = retVal;
+        return;
+    }
+
+    ENavigationMode naviMode = NAVIGATION_MODE_ALL;
+    std::unique_ptr < TCCriteriaHelper > pCriteria(new TCCriteriaHelper());
+    retVal = getBasicCriteria(pCriteria, tvMode, naviMode);
+    if (retVal.IsError()) {
+        _pTuneData->error = retVal;
+        return;
+    }
+
+    pCriteria->Fetch(SERVICE_ID);
+    pCriteria->Fetch(CHANNEL_TYPE);
+    pCriteria->Fetch(CHANNEL_NUMBER);
+
+    CriteriaFilter filter = CriteriaFilter(tvMode.serviceMode);
+
+    if (tuneOption.isMajorSet()) {
+        LoggerD("MAJOR: %lld", tuneOption.getMajor());
+        filter.filterWhere(MAJOR, static_cast<int>(tuneOption.getMajor()));
+    }
+    if (tuneOption.isMinorSet()) {
+        LoggerD("MINOR: %lld", tuneOption.getMinor());
+        filter.filterWhere(MINOR, static_cast<int>(tuneOption.getMinor()));
+    }
+    if (tuneOption.isPtcSet()) {
+        LoggerD("PTC: %lld", tuneOption.getPtc());
+        filter.filterWhere(CHANNEL_NUMBER,
+            static_cast<int>(tuneOption.getPtc()));
+    }
+    if (tuneOption.isOriginalNetworkIDSet()) {
+        LoggerD("ORIGINAL_NETWORK_ID: %lld", tuneOption.getOriginalNetworkID());
+        filter.filterWhere(ORIGINAL_NETWORK_ID,
+            static_cast<int>(tuneOption.getOriginalNetworkID()));
+    }
+    if (tuneOption.isProgramNumberSet()) {
+        LoggerD("PROGRAM_NUMBER: %lld", tuneOption.getProgramNumber());
+        filter.filterWhere(PROGRAM_NUMBER,
+            static_cast<int>(tuneOption.getProgramNumber()));
+    }
+    if (tuneOption.isSourceIDSet()) {
+        LoggerD("SOURCE_ID: %lld", tuneOption.getSourceID());
+        filter.filterWhere(SOURCE_ID,
+            static_cast<int>(tuneOption.getSourceID()));
+    }
+    if (tuneOption.isTransportStreamIDSet()) {
+        LoggerD("TRANSPORT_STREAM_ID: %lld", tuneOption.getTransportStreamID());
+        filter.filterWhere(TRANSPORT_STREAM_ID,
+            static_cast<int>(tuneOption.getTransportStreamID()));
+    }
+
+    filter.getFilteredCriteria(pCriteria);
+
+    TCServiceData foundService;
+    int ret = getService()->FindService(*pCriteria, foundService);
+    if (TV_SERVICE_API_METHOD_SUCCESS != ret) {
+        _pTuneData->error = PlatformResult(ErrorCode::NOT_FOUND_ERR,
+            "Failed to find channel");
+        return;
+    }
+
+    TCServiceId serviceId = foundService.Get < TCServiceId > (SERVICE_ID);
+
+    if (currentServiceId != serviceId) {
+        ret = serviceNavigation->SetService(serviceId);
+        if (TV_SERVICE_API_METHOD_SUCCESS != ret) {
+            LOGE("Failed to set selected channel: %d", ret);
+            _pTuneData->error = PlatformResult(ErrorCode::UNKNOWN_ERR,
+                "Failed to set selected channel");
+            return;
+        }
+        _pTuneData->serviceId = serviceId;
+        m_callbackTuneMap[serviceId] = _pTuneData->callbackId;
+    } else {
+        LoggerD("Selected the current channel. Calling tune and epg events");
+        common::TaskQueue::GetInstance().Async(std::bind(
+            &EventListener::onChannelChange, m_listener,
+            _pTuneData->callbackId));
+        m_callbackTuneMap[serviceId] = _pTuneData->callbackId;
+        broadcastEPGIfAvailable(serviceId, _pTuneData->callbackId);
+    }
+}
+
+ENavigationMode navigatorModeToENavigationMode(NavigatorMode mode) {
+    switch (mode) {
+        case DIGITAL:
+            return NAVIGATION_MODE_DIGITAL;
+        case ANALOG:
+            return NAVIGATION_MODE_ANALOG;
+        case FAVORITE:
+            return NAVIGATION_MODE_FAVORITES;
+        default:
+            return NAVIGATION_MODE_ALL;
+    }
+}
+
+void TVChannelManager::tuneUp(std::shared_ptr<TuneData> const& _pTuneData) {
+    LoggerD("Enter");
+    std::unique_lock<std::mutex> lock(tuneMutex);
+
+    WindowType windowType = _pTuneData->windowType;
+    common::PlatformResult retVal(ErrorCode::NO_ERROR);
+
+    std::unique_ptr<ChannelInfo> pChannel(new ChannelInfo());
+    retVal = getCurrentChannel(pChannel, windowType);
+    if (retVal.IsError()) {
+        _pTuneData->error = retVal;
+        return;
+    }
+
+    TCServiceId currentServiceId = pChannel->getServiceID();
+
+    IServiceNavigation* serviceNavigation = nullptr;
+    retVal = getNavigation(&serviceNavigation, getProfile(windowType), SCREENID);
+    if (retVal.IsError()) {
+        _pTuneData->error = retVal;
+        return;
+    }
+
+    TSTvMode tvMode;
+    retVal = getTvMode(tvMode, serviceNavigation);
+    if (retVal.IsError()) {
+        _pTuneData->error = retVal;
+        return;
+    }
+
+    ENavigationMode naviMode = navigatorModeToENavigationMode(
+        _pTuneData->navMode);
+
+    std::unique_ptr < TCCriteriaHelper > pCriteria(new TCCriteriaHelper());
+    retVal = getBasicCriteria(pCriteria, tvMode, naviMode);
+    if (retVal.IsError()) {
+        _pTuneData->error = retVal;
+        return;
+    }
+
+    pCriteria->Fetch(SERVICE_ID);
+    pCriteria->Fetch(SERVICE_NAME);
+    pCriteria->Fetch(CHANNEL_TYPE);
+    pCriteria->Fetch(CHANNEL_NUMBER);
+    TCServiceData previousService;
+
+    int ret = serviceNavigation->GetPreviousService(*pCriteria,
+            currentServiceId,
+            previousService);
+    if (TV_SERVICE_API_METHOD_SUCCESS != ret) {
+        LoggerE("Failed to find previous channel: %d", ret);
+        _pTuneData->error = PlatformResult(ErrorCode::NOT_FOUND_ERR,
+            "Failed to find previous channel");
+        return;
+    }
+    TCServiceId serviceId = previousService.Get<TCServiceId>(SERVICE_ID);
+
+    // if GetNextService's result is same with current service id,
+    // it means failure to find previous channel.
+    if (currentServiceId == serviceId) {
+        LoggerE("Failed to find previous channel: %d", ret);
+        _pTuneData->error = PlatformResult(ErrorCode::NOT_FOUND_ERR,
+            "Failed to find next channel");
+        return;
+    }
+
+    ret = serviceNavigation->SetService(serviceId);
+    if (TV_SERVICE_API_METHOD_SUCCESS != ret) {
+        LoggerE("Failed to set selected channel: %d", ret);
+        _pTuneData->error = PlatformResult(ErrorCode::UNKNOWN_ERR,
+            "Failed to set selected channel");
+    } else {
+        m_callbackTuneMap[serviceId] = _pTuneData->callbackId;
+    }
+}
+
+void TVChannelManager::tuneDown(std::shared_ptr<TuneData> const& _pTuneData) {
+    LoggerD("Enter");
+    std::unique_lock<std::mutex> lock(tuneMutex);
+
+    WindowType windowType = _pTuneData->windowType;
+    common::PlatformResult retVal(ErrorCode::NO_ERROR);
+
+    std::unique_ptr<ChannelInfo> pChannel(new ChannelInfo());
+    retVal = getCurrentChannel(pChannel, windowType);
+    if (retVal.IsError()) {
+        _pTuneData->error = retVal;
+        return;
+    }
+
+    TCServiceId currentServiceId = pChannel->getServiceID();
+
+    IServiceNavigation* serviceNavigation = nullptr;
+    retVal = getNavigation(&serviceNavigation, getProfile(windowType), SCREENID);
+    if (retVal.IsError()) {
+        _pTuneData->error = retVal;
+        return;
+    }
+
+    TSTvMode tvMode;
+    retVal = getTvMode(tvMode, serviceNavigation);
+    if (retVal.IsError()) {
+        _pTuneData->error = retVal;
+        return;
+    }
+
+    ENavigationMode naviMode = navigatorModeToENavigationMode(
+        _pTuneData->navMode);
+
+    std::unique_ptr < TCCriteriaHelper > pCriteria(new TCCriteriaHelper());
+    retVal = getBasicCriteria(pCriteria, tvMode, naviMode);
+    if (retVal.IsError()) {
+        _pTuneData->error = retVal;
+        return;
+    }
+
+    pCriteria->Fetch(SERVICE_ID);
+    pCriteria->Fetch(SERVICE_NAME);
+    pCriteria->Fetch(CHANNEL_TYPE);
+    pCriteria->Fetch(CHANNEL_NUMBER);
+    TCServiceData nextService;
+
+    int ret = serviceNavigation->GetNextService(*pCriteria,
+            currentServiceId,
+            nextService);
+    if (TV_SERVICE_API_METHOD_SUCCESS != ret) {
+        LoggerE("Failed to find previous channel: %d", ret);
+        _pTuneData->error = PlatformResult(ErrorCode::NOT_FOUND_ERR,
+            "Failed to find previous channel");
+        return;
+    }
+    TCServiceId serviceId = nextService.Get<TCServiceId>(SERVICE_ID);
+
+    // if GetNextService's result is same with current service id,
+    // it means failure to find previous channel.
+    if (currentServiceId == serviceId) {
+        LoggerE("Failed to find previous channel: %d", ret);
+        _pTuneData->error = PlatformResult(ErrorCode::NOT_FOUND_ERR,
+            "Failed to find previous channel");
+        return;
+    }
+
+    ret = serviceNavigation->SetService(serviceId);
+    if (TV_SERVICE_API_METHOD_SUCCESS != ret) {
+        LoggerE("Failed to set selected channel: %d", ret);
+        _pTuneData->error = PlatformResult(ErrorCode::NOT_FOUND_ERR,
+            "Failed to set selected channel");
+    } else {
+        m_callbackTuneMap[serviceId] = _pTuneData->callbackId;
+    }
+}
+
+common::PlatformResult TVChannelManager::getNavigation(IServiceNavigation** serviceNavigation, EProfile profileId,
+    u_int16_t screenId) {
+    LoggerD("Enter");
+    IServiceNavigation* navigation;
+    int ret = TVServiceAPI::CreateServiceNavigation(profileId, screenId,
+        &navigation);
+    if (TV_SERVICE_API_SUCCESS != ret) {
+        LoggerE("Failed to create service navigation: %d", ret);
+        return common::PlatformResult(ErrorCode::UNKNOWN_ERR,
+            "Failed to create service navigation");
+    }
+    *serviceNavigation = navigation;
+    return common::PlatformResult(ErrorCode::NO_ERROR);
+}
+
+common::PlatformResult TVChannelManager::getTvMode(TSTvMode& Mode, IServiceNavigation* pNavigation) {
+    LoggerD("Enter");
+    TSTvMode tvMode;
+    int ret = pNavigation->GetTvMode(tvMode);
+    if (TV_SERVICE_API_METHOD_SUCCESS != ret) {
+        LoggerE("Failed to get current tv mode: %d", ret);
+        return common::PlatformResult(ErrorCode::UNKNOWN_ERR,
+            "Failed to get current tv mode");
+    }
+    LoggerD("tvMode : antenna - %d, service - %d", tvMode.antennaMode,
+        tvMode.serviceMode);
+    Mode = tvMode;
+    return common::PlatformResult(ErrorCode::NO_ERROR);
+}
+
+common::PlatformResult TVChannelManager::getBasicCriteria(
+        std::unique_ptr<TCCriteriaHelper>& pCriteria, TSTvMode tvMode, ENavigationMode naviMode) {
+    LoggerD("Enter");
+    bool found = TCNavigationModeHelper::GetNavigationCriteria(tvMode, naviMode,
+        *pCriteria);
+    if (!found) {
+        LoggerE("Failed to create navigation criteria");
+        return common::PlatformResult(ErrorCode::UNKNOWN_ERR,
+            "Failed to create navigation criteria");
+    }
+    return common::PlatformResult(ErrorCode::NO_ERROR);
+}
+
+common::PlatformResult TVChannelManager::getCurrentServiceInfo(
+    TCServiceData& servData, IServiceNavigation* _pNavigation, TSTvMode _mode,
+    std::unique_ptr<TCCriteriaHelper> const& _pCriteria) {
+    LoggerD("Enter");
+    TCServiceData serviceData;
+    int ret = _pNavigation->GetCurrentServiceInfo(_mode, *_pCriteria,
+        serviceData);
+    if (TV_SERVICE_API_METHOD_SUCCESS != ret) {
+        LoggerE("Failed to get current service info: %d", ret);
+        return common::PlatformResult(ErrorCode::UNKNOWN_ERR,
+            "Failed to get current service info");
+    }
+    servData = serviceData;
+    return common::PlatformResult(ErrorCode::NO_ERROR);
+}
+
+common::PlatformResult TVChannelManager::getCurrentChannel(
+        std::unique_ptr<ChannelInfo>& pChannel, WindowType _windowType) {
+    LoggerD("Entered %d", _windowType);
+
+    std::unique_ptr < TCCriteriaHelper > pCriteria(new TCCriteriaHelper());
+    pCriteria->Fetch(SERVICE_ID);
+    pCriteria->Fetch(MAJOR);
+    pCriteria->Fetch(MINOR);
+    pCriteria->Fetch(PROGRAM_NUMBER);
+    pCriteria->Fetch(CHANNEL_NUMBER);
+    pCriteria->Fetch(CHANNEL_TYPE);
+    pCriteria->Fetch(SERVICE_NAME);
+    pCriteria->Fetch(SOURCE_ID);
+    pCriteria->Fetch(TRANSPORT_STREAM_ID);
+    pCriteria->Fetch(ORIGINAL_NETWORK_ID);
+    pCriteria->Fetch(LCN);
+
+    //  Navigation
+    common::PlatformResult retVal(ErrorCode::NO_ERROR);
+    IServiceNavigation* navigation = nullptr;
+    retVal = getNavigation(&navigation, getProfile(_windowType), SCREENID);
+    if (retVal.IsError()) {
+        return retVal;
+    }
+
+    TSTvMode tvMode;
+    retVal = getTvMode(tvMode, navigation);
+    if (retVal.IsError()) {
+        return retVal;
+    }
+
+    TCServiceData serviceData;
+    retVal = getCurrentServiceInfo(serviceData, navigation, tvMode, pCriteria);
+    if (retVal.IsError()) {
+        return retVal;
+    }
+    LoggerD("Current channel id: %llu",
+        serviceData.Get < TCServiceId > (SERVICE_ID));
+    LoggerD("Current channel number: %d",
+        serviceData.Get<u_int16_t>(CHANNEL_NUMBER));
+    pChannel->fromApiData(serviceData);
+    return common::PlatformResult(ErrorCode::NO_ERROR);
+}
+
+EProfile TVChannelManager::getProfile(WindowType windowType) {
+    LoggerD("Enter");
+    switch (windowType) {
+      case MAIN:
+        return PROFILE_TYPE_MAIN;
+// PIP is not supported - j.h.lim
+//      case PIP:
+//          return PROFILE_TYPE_PIP;
+      default:
+        LoggerE("Unsupported window type: %d", windowType);
+        return PROFILE_TYPE_UNKNOWN;
+    }
+}
+
+common::PlatformResult TVChannelManager::getCurrentChannelId(TCServiceId& service, WindowType _windowType) {
+    LoggerD("Enter");
+    //  Navigation
+    common::PlatformResult retVal(ErrorCode::NO_ERROR);
+    IServiceNavigation* navigation = nullptr;
+    retVal = getNavigation(&navigation, getProfile(_windowType), SCREENID);
+    if (retVal.IsError())
+        return retVal;
+
+    TSTvMode tvMode;
+    retVal = getTvMode(tvMode, navigation);
+    if (retVal.IsError()) {
+        return retVal;
+    }
+
+    std::unique_ptr < TCCriteriaHelper > pCriteria(new TCCriteriaHelper());
+    pCriteria->Fetch(SERVICE_ID);
+
+    TCServiceData serviceData;
+    retVal = getCurrentServiceInfo(serviceData, navigation, tvMode, pCriteria);
+    if (retVal.IsError()) {
+        return retVal;
+    }
+
+    service = serviceData.Get < TCServiceId > (SERVICE_ID);
+    return common::PlatformResult(ErrorCode::NO_ERROR);
+}
+
+common::PlatformResult TVChannelManager::getCurrentProgram(
+        ProgramInfo* program, WindowType _windowType) {
+    LoggerD("Enter");
+    common::PlatformResult retVal(ErrorCode::NO_ERROR);
+    IServiceGuide* guide;
+    int ret = TVServiceAPI::CreateServiceGuide(&guide);
+    if (TV_SERVICE_API_SUCCESS != ret) {
+        LoggerE("Failed to create service guide: %d", ret);
+        return common::PlatformResult(ErrorCode::UNKNOWN_ERR,
+            "Failed to create service guide");
+    }
+
+    TCProgramData programData;
+    TCServiceId service;
+    retVal = getCurrentChannelId(service, _windowType);
+    if (retVal.IsError()) {
+        return retVal;
+    }
+
+    ret = guide->GetPresentProgram(service, programData);
+    if (TV_SERVICE_API_METHOD_SUCCESS != ret) {
+        LoggerE("Failed to get current program: %d", ret);
+        return common::PlatformResult(ErrorCode::UNKNOWN_ERR,
+            "Failed to get current program");
+    }
+    program->fromApiData(programData);
+    return common::PlatformResult(ErrorCode::NO_ERROR);
+}
+
+void TVChannelManager::registerListener(EventListener* pListener) {
+    LoggerD("Enter");
+    m_listener = pListener;
+    auto& helper = common::TvsSubscribeHelper::getInstance();
+
+    helper.registerListener(SIGNAL_TUNE_SUCCESS, this);
+    helper.registerListener(SIGNAL_LOCK_SUCCESS, this);
+    helper.registerListener(SIGNAL_TUNER_LOCK_FAIL, this);
+    helper.registerListener(SIGNAL_EPG_COMPLETED, this);
+    helper.registerListener(SIGNAL_SOURCE_STATE_CHANGED, this);
+
+}
+
+void TVChannelManager::unregisterListener() {
+    LoggerD("Enter");
+    auto& helper = common::TvsSubscribeHelper::getInstance();
+
+    helper.unregisterListener(SIGNAL_TUNE_SUCCESS, this);
+    helper.unregisterListener(SIGNAL_LOCK_SUCCESS, this);
+    helper.unregisterListener(SIGNAL_TUNER_LOCK_FAIL, this);
+    helper.unregisterListener(SIGNAL_EPG_COMPLETED, this);
+    helper.unregisterListener(SIGNAL_SOURCE_STATE_CHANGED, this);
+    m_listener = NULL;
+}
+
+void TVChannelManager::broadcastEPGIfAvailable(TCServiceId ChannelId, double callbackID) {
+    LoggerD("Enter");
+    IServiceGuide* guide;
+    int ret = TVServiceAPI::CreateServiceGuide(&guide);
+    if (TV_SERVICE_API_SUCCESS != ret) {
+        LoggerW("Failed to create service guide: %d", ret);
+        return;
+    }
+    TCProgramData programData;
+    ret = guide->GetPresentProgram(ChannelId, programData);
+    if (TV_SERVICE_API_METHOD_SUCCESS == ret) {
+        if (!m_listener) {
+            LoggerW("Listener is empty, ignoring message");
+            return;
+        }
+        LoggerD("EPG data available, calling EPG completed for current channel");
+        //now broadcast fake event
+        common::TaskQueue::GetInstance().Async(std::bind(
+                &EventListener::onEPGReceived, m_listener,
+                callbackID));
+    } else {
+        LoggerD("EPG data not available yet, waiting for SIGNAL_EPG_COMPLETED");
+    }
+}
+
+void TVChannelManager::OnSignal(ESignalType type, TSSignalData data) {
+    LoggerD("Enter: %d", type);
+    if (!m_listener) {
+        LoggerE("Listener is empty, ignoring message");
+        return;
+    }
+
+    WindowType windowType;
+    common::PlatformResult retVal = stringToWindowType("MAIN", windowType);
+    if (retVal.IsError()) {
+        LOGE("Fail to get current channel id");
+        return;
+    }
+    TCServiceId pChannelId;
+    retVal = getCurrentChannelId(pChannelId, windowType);
+    if (retVal.IsError()) {
+        LOGE("Fail to get current channel id");
+        return;
+    }
+    double callbackID = -1;
+    auto it = m_callbackTuneMap.find(pChannelId);
+    if (it != m_callbackTuneMap.end()) {
+        callbackID = it->second;
+    }
+    LoggerD("CallbackID %f", callbackID);
+
+    switch (type) {
+    case SIGNAL_TUNE_SUCCESS:
+        m_listener->onChannelChange(callbackID);
+        broadcastEPGIfAvailable(pChannelId, callbackID);
+    break;
+    case SIGNAL_TUNER_LOCK_FAIL:
+        m_listener->onNoSignal(callbackID);
+        break;
+    case SIGNAL_EPG_COMPLETED:
+        m_listener->onEPGReceived(callbackID);
+        break;
+    case SIGNAL_SOURCE_STATE_CHANGED: {
+            ESourceState state = static_cast<ESourceState> (data.data.ll);
+            LoggerD("Signal source state changed. State: %lld", data.data.ll);
+            if (state != lastSourceState_) {
+                lastSourceState_ = state;
+                m_listener->onSignalStateChange(state == SOURCE_STATE_SIGNAL_OK);
+            }
+        }
+      break;
+    default:
+        LoggerW("Unrecognized event type");
+    }
+}
+
+void TVChannelManager::ucs2utf8(char *out, size_t out_len, char *in,
+    size_t in_len) {
+    iconv_t cd;
+    size_t r;
+
+    cd = iconv_open("UTF-8", "UCS-2BE");
+    if (cd == (iconv_t) - 1) {
+        LoggerE("Failed to open iconv");
+    }
+
+    r = iconv(cd, &in, &in_len, &out, &out_len);
+    if (r == (size_t) - 1) {
+        LoggerE("Failed convert string to utf8");
+    }
+
+    iconv_close(cd);
+}
+
+void TVChannelManager::findChannel(
+    const std::shared_ptr<FindChannelData>& data) {
+    LoggerD("Enter");
+    IServiceNavigation* navigation = nullptr;
+    common::PlatformResult retVal = getNavigation(&navigation, getProfile(WindowType::MAIN), SCREENID);
+    if (retVal.IsError()) {
+        data->error = PlatformResult(ErrorCode::UNKNOWN_ERR,
+            "Couldn't find channels");
+        return;
+    }
+
+    TSTvMode tvMode;
+    retVal = getTvMode(tvMode, navigation);
+
+    std::unique_ptr < TCCriteriaHelper > criteria(new TCCriteriaHelper());
+    retVal = getBasicCriteria(criteria, tvMode, NAVIGATION_MODE_ALL);
+
+    criteria->Fetch(SERVICE_ID);
+    criteria->Fetch(MAJOR);
+    criteria->Fetch(MINOR);
+    criteria->Fetch(PROGRAM_NUMBER);
+    criteria->Fetch(CHANNEL_NUMBER);
+    criteria->Fetch(CHANNEL_TYPE);
+    criteria->Fetch(SERVICE_NAME);
+    criteria->Fetch(SOURCE_ID);
+    criteria->Fetch(TRANSPORT_STREAM_ID);
+    criteria->Fetch(ORIGINAL_NETWORK_ID);
+    criteria->Fetch(LCN);
+
+    retVal = getTvMode(tvMode, navigation);
+
+    CriteriaFilter filter = CriteriaFilter(
+        tvMode.serviceMode);
+    filter.filterWhere(MAJOR, static_cast<int>(data->major));
+    filter.filterWhere(MINOR, static_cast<int>(data->minor));
+    filter.getFilteredCriteria(criteria);
+
+    std::list<TCServiceData*> resultServices;
+    int ret = getService()->FindServiceList(*criteria, resultServices);
+    if (TV_SERVICE_API_METHOD_FAILURE == ret) {
+        LoggerE("Failed to find channel: %d", ret);
+        data->error = PlatformResult(ErrorCode::NOT_FOUND_ERR,
+            "Failed to find channel");
+        return;
+    }
+    LoggerD("Found channels: %d", resultServices.size());
+    auto it = resultServices.begin();
+    for (; it != resultServices.end(); ++it) {
+        ChannelInfo *channelInfo = new ChannelInfo();
+        channelInfo->fromApiData(*(*it));
+        data->channels.push_back(channelInfo);
+        delete (*it);
+    }
+    resultServices.clear();
+}
+
+void TVChannelManager::getChannelList(
+    const std::shared_ptr<GetChannelListData>& data) {
+    LoggerD("Enter");
+    common::PlatformResult retVal(ErrorCode::NO_ERROR);
+    IServiceNavigation* navigation = nullptr;
+    retVal = getNavigation(&navigation, getProfile(WindowType::MAIN), SCREENID);
+    if (retVal.IsError()) {
+        data->error = retVal;
+        return;
+    }
+
+    ENavigationMode naviMode = NAVIGATION_MODE_ALL;
+    switch (data->tuneMode) {
+        case DIGITAL:
+            naviMode = NAVIGATION_MODE_DIGITAL;
+            break;
+        case ANALOG:
+            naviMode = NAVIGATION_MODE_ANALOG;
+            break;
+        case FAVORITE:
+            naviMode = NAVIGATION_MODE_FAVORITES;
+            break;
+        default:
+            naviMode = NAVIGATION_MODE_ALL;
+    }
+    TSTvMode tvMode;
+    retVal = getTvMode(tvMode, navigation);
+    if (retVal.IsError()) {
+        data->error = retVal;
+        return;
+    }
+
+    std::unique_ptr < TCCriteriaHelper > criteria(new TCCriteriaHelper());
+    retVal = getBasicCriteria(criteria, tvMode, naviMode);
+    if (retVal.IsError()) {
+        data->error = retVal;
+        return;
+    }
+
+    criteria->Fetch(SERVICE_ID);
+    criteria->Fetch(MAJOR);
+    criteria->Fetch(MINOR);
+    criteria->Fetch(PROGRAM_NUMBER);
+    criteria->Fetch(CHANNEL_NUMBER);
+    criteria->Fetch(CHANNEL_TYPE);
+    criteria->Fetch(SERVICE_NAME);
+    criteria->Fetch(SOURCE_ID);
+    criteria->Fetch(TRANSPORT_STREAM_ID);
+    criteria->Fetch(ORIGINAL_NETWORK_ID);
+    criteria->Fetch(LCN);
+    if (NAVIGATION_MODE_FAVORITES == naviMode) {
+        criteria->WhereNot(FAVORITE_ID, 0);
+    } else if (data->favoriteId > 0) {
+        LoggerD("List for favorite id: %d", data->favoriteId);
+        criteria->Where(FAVORITE_ID, data->favoriteId);
+    }
+
+    std::list<TCServiceData*> resultServices;
+    int ret = getService()->FindServiceList(*criteria, resultServices);
+    if (TV_SERVICE_API_METHOD_FAILURE == ret) {
+        LoggerE("Failed to find channels: %d", ret);
+        data->error = PlatformResult(ErrorCode::NOT_FOUND_ERR,
+            "Failed to find channel");
+        return;
+    }
+    LoggerD("Found channels: %d", resultServices.size());
+    auto it = resultServices.begin();
+    for (; it != resultServices.end(); ++it) {
+        ChannelInfo *channelInfo = new ChannelInfo();
+        channelInfo->fromApiData(*(*it));
+        data->channels.push_back(channelInfo);
+        delete (*it);
+    }
+    resultServices.clear();
+}
+
+void TVChannelManager::getProgramList(
+    const std::shared_ptr<GetProgramListData>& data) {
+    LoggerD("Enter");
+    IServiceGuide* guide;
+    int ret = TVServiceAPI::CreateServiceGuide(&guide);
+    if (TV_SERVICE_API_SUCCESS != ret) {
+        LoggerE("Failed to create service guide: %d", ret);
+        data->error = PlatformResult(ErrorCode::UNKNOWN_ERR,
+            "Failed to create service guide");
+        return;
+    }
+
+    std::map<unsigned int, TCProgramData*> programList;
+    LoggerD("Channel: %llu, Start time: %u, duration: %u", data->channelId,
+        data->startTime, data->duration);
+    ret = guide->GetProgramList(data->channelId,
+        data->startTime, data->duration, programList);
+    if (TV_SERVICE_API_METHOD_FAILURE == ret) {
+        LoggerE("Failed to get program list.");
+        data->error = PlatformResult(ErrorCode::NOT_FOUND_ERR,
+            "Failed to get program list.");
+        return;
+    }
+    LoggerD("Found programs: %d", programList.size());
+
+    auto it = programList.begin();
+    for (; it != programList.end(); ++it) {
+        ProgramInfo *programInfo = new ProgramInfo();
+        programInfo->fromApiData(*(it->second));
+        data->programs.push_back(programInfo);
+        delete it->second;
+    }
+    programList.clear();
+}
+
+int TVChannelManager::GetFavoritesNumber() {
+  // core api has no function to check how many favorite list/profiles is
+  // available. For now, we are sure that there are only 1-5
+  return 5;
+}
+
+void TVChannelManager::UpdateFavoriteList(
+  const std::shared_ptr<UpdateFavoriteListData>& data) {
+  LoggerD("Enter");
+  std::vector<std::pair<TCServiceId, bool>> update;
+  update.push_back(std::make_pair(data->channelId, data->addToList));
+  int ret = getService()->UpdateFavorites(update, data->favoriteId);
+  if (ret != TV_SERVICE_API_METHOD_SUCCESS) {
+    LoggerE("Failed to update favorites: %d", ret);
+    data->error = PlatformResult(ErrorCode::UNKNOWN_ERR,
+        "Failed to update favorite list");
+  }
+}
+
+common::PlatformResult TVChannelManager::GetBroadcastStandard(
+    std::string* serviceMode) {
+  LoggerD("Enter");
+  IServiceNavigation* pNavigation;
+  common::PlatformResult ret =
+      getNavigation(&pNavigation, PROFILE_TYPE_MAIN, SCREENID);
+  if (ret.IsError()) {
+    return ret;
+  }
+  TSTvMode tvMode;
+  ret = getTvMode(tvMode, pNavigation);
+  if (ret.IsError()) {
+    return ret;
+  }
+  switch (tvMode.serviceMode) {
+    case SERVICE_MODE_ATSC:
+      *serviceMode = "ATSC";
+      break;
+    case SERVICE_MODE_DVB:
+      *serviceMode = "DVB";
+      break;
+    case SERVICE_MODE_ISDB:
+      *serviceMode = "ISDB";
+      break;
+    case SERVICE_MODE_UNKNOWN: {
+      LoggerE("Unknown broadcast standard");
+      return common::PlatformResult(common::ErrorCode::UNKNOWN_ERR,
+                                    "Unknown broadcast standard");
+      }
+    default:
+      *serviceMode = "SATELLITE";
+  }
+  return common::PlatformResult(common::ErrorCode::NO_ERROR);
+}
+
+TVChannelManager::~TVChannelManager() {
+  LoggerD("Entered");
+}
+
+
+}  // namespace tvchannel
+}  // namespace extension
diff --git a/webWidgetTCT_device/src/tvchannel/tvchannel_manager.h b/webWidgetTCT_device/src/tvchannel/tvchannel_manager.h
new file mode 100755 (executable)
index 0000000..009298a
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 2015 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 SRC_TVCHANNEL_TVCHANNEL_MANAGER_H_
+#define SRC_TVCHANNEL_TVCHANNEL_MANAGER_H_
+
+#include <string>
+#include <memory>
+#include <mutex>
+#include <map>
+#include <list>
+#include <TVServiceAPI.h>
+#include <ServiceNavigationDataType.h>
+#include <NavigationModeHelper.h>
+#include "tvchannel/types.h"
+#include "tvchannel/tune_option.h"
+#include "common/platform_exception.h"
+#include "common/tvsapi_subscribe_helper.h"
+#include "common/platform_result.h"
+#include "tvchannel/program_info.h"
+
+namespace common {
+class PlatformException;
+}
+
+namespace extension {
+namespace tvchannel {
+
+class ChannelInfo;
+class ProgramInfo;
+//  TVServiceAPI static methods returns 0 on success
+static const int TV_SERVICE_API_SUCCESS = 0;
+//  TVServiceAPI object methods return 1 on success
+static const int TV_SERVICE_API_METHOD_SUCCESS = 1;
+//  TVServiceAPI object methods return -1 on failure
+static const int TV_SERVICE_API_METHOD_FAILURE = -1;
+//  You need to check error return in function/method docs and use correct
+//  constant
+
+class EventListener {
+ public:
+    virtual void onChannelChange(double callbackId) = 0;
+    virtual void onEPGReceived(double callbackId) = 0;
+    virtual void onNoSignal(double callbackId) = 0;
+    virtual void onSignalStateChange(bool ifSignalOk) = 0;
+    virtual ~EventListener() {
+    }
+};
+
+class TVChannelManager: public common::TvsSignalListener{
+ public:
+    struct TuneData {
+        TuneData(TuneOption _tuneOption, WindowType _windowType,
+            double _callbackId) :
+              navMode(NOT_DEFINED),
+              tuneOption(_tuneOption), windowType(_windowType),
+              callbackId(_callbackId), serviceId(0),
+              error(common::ErrorCode::NO_ERROR) {
+        }
+        TuneData(NavigatorMode _navMode, WindowType _windowType,
+                    double _callbackId) :
+                        navMode(_navMode), windowType(_windowType),
+                        callbackId(_callbackId), serviceId(0),
+                error(common::ErrorCode::NO_ERROR) {
+        }
+        NavigatorMode navMode;
+        TuneOption tuneOption;
+        WindowType windowType;
+        double callbackId;
+        u_int64_t serviceId;
+        common::PlatformResult error;
+    };
+
+    static TVChannelManager* create();
+    static void ucs2utf8(char *out, size_t out_len, char *in, size_t in_len);
+    void registerListener(EventListener* pListener);
+    void unregisterListener();
+    common::PlatformResult getCurrentChannel(std::unique_ptr<ChannelInfo>&, WindowType _windowType);
+    common::PlatformResult getCurrentProgram(ProgramInfo*, WindowType _windowType);
+
+    void tune(std::shared_ptr<TuneData> const& _pTuneData);
+    void tuneUp(std::shared_ptr<TuneData> const& _pTuneData);
+    void tuneDown(std::shared_ptr<TuneData> const& _pTuneData);
+
+    EProfile getProfile(WindowType windowType);
+    common::PlatformResult getNavigation(IServiceNavigation**, EProfile profileId, u_int16_t screenId);
+    common::PlatformResult getTvMode(TSTvMode&, IServiceNavigation* _pNavigation);
+    common::PlatformResult getBasicCriteria(std::unique_ptr<TCCriteriaHelper>&, TSTvMode tvMode,
+        ENavigationMode naviMode);
+    common::PlatformResult getCurrentServiceInfo(TCServiceData&, IServiceNavigation* _pNavigation,
+        TSTvMode _mode, std::unique_ptr<TCCriteriaHelper> const& _pCriteria);
+
+    IService* getService();
+
+    struct FindChannelData {
+        common::PlatformResult error;
+        int32_t major;
+        int32_t minor;
+        double callbackId;
+        std::list<ChannelInfo*> channels;
+        FindChannelData(): error(common::ErrorCode::NO_ERROR),
+            callbackId(0) {
+              minor = 0;
+              major = 0;
+            }
+    };
+
+    void findChannel(const std::shared_ptr<FindChannelData>& data);
+
+    struct GetChannelListData {
+        NavigatorMode tuneMode;
+        unsigned char favoriteId;
+        bool nStartSet;
+        bool numberSet;
+        common::PlatformResult error;
+        int32_t nStart;
+        int32_t number;
+        double callbackId;
+        std::list<ChannelInfo*> channels;
+
+        GetChannelListData() :
+            tuneMode(NOT_DEFINED),
+            favoriteId(0),
+            nStartSet(false),
+            numberSet(false),
+            error(common::ErrorCode::NO_ERROR),
+            nStart(0),
+            number(0),
+            callbackId(0) {
+        }
+    };
+
+    void getChannelList(const std::shared_ptr<GetChannelListData>& data);
+
+    struct GetProgramListData {
+        TCServiceId channelId;
+        u_int32_t startTime;
+        u_int32_t duration;
+        common::PlatformResult error;
+        double callbackId;
+        std::list<ProgramInfo*> programs;
+        GetProgramListData():
+          channelId(0),
+          startTime(0),
+          duration(0),
+          error(common::ErrorCode::NO_ERROR),
+          callbackId(0) {}
+    };
+
+    void getProgramList(const std::shared_ptr<GetProgramListData>& data);
+
+    int GetFavoritesNumber();
+
+    struct UpdateFavoriteListData {
+      common::PlatformResult error;
+      unsigned char favoriteId;
+      TCServiceId channelId;
+      double callbackId;
+      bool addToList;
+      UpdateFavoriteListData(): error(common::ErrorCode::NO_ERROR),
+          favoriteId(0),
+          channelId(0),
+          callbackId(0),
+          addToList(false) {}
+    };
+    void UpdateFavoriteList(const std::shared_ptr<UpdateFavoriteListData>& data);
+
+    common::PlatformResult GetBroadcastStandard(std::string* serviceMode);
+
+    ~TVChannelManager();
+
+ private:
+    EventListener* m_listener;
+    //  Not copyable, assignable, movable
+    TVChannelManager();
+    TVChannelManager(TVChannelManager const&) = delete;
+    void operator=(TVChannelManager const&) = delete;
+    TVChannelManager(TVChannelManager &&) = delete;
+
+    virtual void OnSignal(ESignalType type, TSSignalData data);
+    void broadcastEPGIfAvailable(TCServiceId ChannelId, double callbackID);
+
+    common::PlatformResult getCurrentChannelId(TCServiceId&, WindowType _windowType);
+    static const int SCREENID = 0;
+
+    std::mutex tuneMutex;
+    std::map<u_int64_t, double> m_callbackTuneMap;
+
+    ESourceState lastSourceState_;
+};
+
+}  // namespace tvchannel
+}  // namespace extension
+
+#endif  // SRC_TVCHANNEL_TVCHANNEL_MANAGER_H_
diff --git a/webWidgetTCT_device/src/tvchannel/types.cc b/webWidgetTCT_device/src/tvchannel/types.cc
new file mode 100755 (executable)
index 0000000..682d03c
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2015 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 "tvchannel/types.h"
+#include "common/logger.h"
+
+namespace extension {
+namespace tvchannel {
+
+const char* NAVIGATOR_MODE_ALL = "ALL";
+const char* NAVIGATOR_MODE_DIGITAL = "DIGITAL";
+const char* NAVIGATOR_MODE_ANALOG = "ANALOG";
+const char* NAVIGATOR_MODE_FAVORITE = "FAVORITE";
+
+common::PlatformResult stringToNavigatorMode(const std::string &mode,
+  NavigatorMode &outMode) {
+  common::PlatformResult result(common::ErrorCode::UNKNOWN_ERR,
+      "Unrecognized mode");
+  if (mode == NAVIGATOR_MODE_ALL) {
+    outMode = NavigatorMode::ALL;
+    result = common::PlatformResult(common::ErrorCode::NO_ERROR);
+  }
+  if (mode == NAVIGATOR_MODE_DIGITAL) {
+    outMode = NavigatorMode::DIGITAL;
+    result = common::PlatformResult(common::ErrorCode::NO_ERROR);
+  }
+  if (mode == NAVIGATOR_MODE_ANALOG) {
+    outMode = NavigatorMode::ANALOG;
+    result = common::PlatformResult(common::ErrorCode::NO_ERROR);
+  }
+  if (mode == NAVIGATOR_MODE_FAVORITE) {
+    outMode = NavigatorMode::FAVORITE;
+    result = common::PlatformResult(common::ErrorCode::NO_ERROR);
+  }
+  return result;
+}
+
+const char* TIZEN_TV_WINDOW_TYPE_MAIN = "MAIN";
+// PIP is not supported - j.h.lim
+// const char* TIZEN_TV_WINDOW_TYPE_PIP = "PIP";
+
+common::PlatformResult stringToWindowType(std::string type, WindowType &outType) {
+  if (type == TIZEN_TV_WINDOW_TYPE_MAIN) {
+    outType = MAIN;
+    return common::PlatformResult(common::ErrorCode::NO_ERROR);
+  } else {
+    LoggerE("Unrecognized window type: %s", type.c_str());
+    return common::PlatformResult(common::ErrorCode::UNKNOWN_ERR,
+        "Unrecognized window type");
+  }
+}
+
+}  //  namespace tvchannel
+}  //  namespace extension
+
diff --git a/webWidgetTCT_device/src/tvchannel/types.h b/webWidgetTCT_device/src/tvchannel/types.h
new file mode 100755 (executable)
index 0000000..a48ff40
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2015 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 SRC_TVCHANNEL_TYPES_H_
+#define SRC_TVCHANNEL_TYPES_H_
+
+#include <string>
+#include "common/platform_result.h"
+
+namespace extension {
+namespace tvchannel {
+
+enum NavigatorMode {
+    NOT_DEFINED,
+    ALL,
+    DIGITAL,
+    ANALOG,
+    FAVORITE
+};
+
+enum WindowType {
+    MAIN = 0,
+//  PIP is not supported - j.h.lim
+//  PIP
+};
+
+extern const char* TIZEN_TV_WINDOW_TYPE_MAIN;
+
+enum class SourceType {
+    TV,
+    AV,
+    SVIDEO,
+    COMP,
+    PC,
+    HDMI,
+    SCART,
+    DVI,
+    MEDIA,
+    IPTV,
+    UNKNOWN
+};
+
+extern const char* NAVIGATOR_MODE_ALL;
+extern const char* NAVIGATOR_MODE_DIGITAL;
+extern const char* NAVIGATOR_MODE_ANALOG;
+extern const char* NAVIGATOR_MODE_FAVORITE;
+
+common::PlatformResult stringToNavigatorMode(std::string const& mode,
+    NavigatorMode &outMode);
+common::PlatformResult stringToWindowType(std::string type, WindowType &outType);
+
+}  //  namespace tvchannel
+}  //  namespace extension
+
+#endif  // SRC_TVCHANNEL_TYPES_H_
diff --git a/webWidgetTCT_device/src/tvdisplay/tvdisplay.gyp b/webWidgetTCT_device/src/tvdisplay/tvdisplay.gyp
new file mode 100755 (executable)
index 0000000..d56c01a
--- /dev/null
@@ -0,0 +1,37 @@
+{
+  'includes':[
+    '../common/common.gypi',
+  ],
+  'targets': [
+    {
+      'target_name': 'tizen_tvdisplay',
+      'type': 'loadable_module',
+      'dependencies': [
+        '../common/common.gyp:tizen_common',
+      ],
+      'includes': [
+        '../common/pkg-config.gypi',
+      ],
+      'sources': [
+        'tvdisplay_api.js',
+        'tvdisplay_extension.cc',
+        'tvdisplay_extension.h',
+        'tvdisplay_instance.cc',
+        'tvdisplay_instance.h',
+      ],
+      'conditions': [
+        [
+          'tizen == 1',
+          {
+            'variables': {
+              'packages': [
+                'capi-system-info',
+                'vconf',
+              ]
+            },
+          },
+        ],
+      ],
+    },
+  ],
+}
diff --git a/webWidgetTCT_device/src/tvdisplay/tvdisplay_api.js b/webWidgetTCT_device/src/tvdisplay/tvdisplay_api.js
new file mode 100755 (executable)
index 0000000..5d160a1
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+/**
+ * @author m.wasowski2@samsung.com (Marcin Wasowski)
+ */
+
+function TVDisplay() {}
+
+var native = new xwalk.utils.NativeManager(extension);
+var validator = xwalk.utils.validator;
+var validatorTypes = xwalk.utils.validator.Types;
+
+var UNKNOWN_ERROR = 'UnknownError';
+
+
+/**
+ * Allowed values for is3DModeEnabled return value
+ * @type {Display3DModeState}
+ */
+var Display3DModeState = {
+  NOT_CONNECTED: 'NOT_CONNECTED',
+  NOT_SUPPORTED: 'NOT_SUPPORTED',
+  READY: 'READY'
+};
+Object.freeze(Display3DModeState);
+
+
+/**
+ * Check if 3D mode is enabled
+ * @return {Display3DModeState} mode String informing if 3D content
+ *                                   is supported and ready
+ */
+TVDisplay.prototype.is3DModeEnabled = function() {
+  var ret = native.callSync('TVDisplay_is3DModeEnabled', {});
+  if (native.isFailure(ret)) {
+    throw native.getErrorObject(ret);
+  }
+  return native.getResultObject(ret);
+};
+
+
+/**
+ *  Allowed values for 3D effect modes mapped to return values from C API
+ *
+ *  OFF - identifier for 3DEffect mode off
+ *  TOP_BOTTOM - Top-bottom: Left at top, right at bottom
+ *  SIDE_BY_SIDE - Top-bottom: Left at left side, right at right side
+ *  LINE_BY_LINE - Line-by-line: Left and right image interlaced by row
+ *  VERTICAL_STRIP - Vertical-strip: Left and right image
+ *                   interlaced by column
+ *  FRAME_SEQUENCE - Left and right image interlaced by frame
+ *  CHECKER_BD - Checkerboard (only for PC or game console sources)
+ *  FROM_2D_TO_3D - Left and right image computed from
+ *                  No-stereoscopic image
+*/
+var Display3DEffectMode = [
+  'OFF',
+  'TOP_BOTTOM',
+  'SIDE_BY_SIDE',
+  'LINE_BY_LINE',
+  'VERTICAL_STRIPE',
+  'FRAME_SEQUENCE',
+  'CHECKER_BD',
+  'FROM_2D_TO_3D'
+];
+Object.freeze(Display3DEffectMode);
+
+
+/**
+ * Get current 3D effect mode or 'OFF' if no 3D enabled
+ * @return {string} current mode name
+ */
+TVDisplay.prototype.get3DEffectMode = function() {
+  var ret = native.callSync('TVDisplay_get3DEffectMode', {});
+  if (native.isFailure(ret)) {
+    throw native.getErrorObject(ret);
+  }
+  var mode = Display3DEffectMode[native.getResultObject(ret)];
+  if (!mode) {
+    var error_msg = 'Unknown 3D effect mode (' + reply.result + ')';
+    throw new WebAPIException(0, error_msg, UNKNOWN_ERROR);
+  }
+  return mode;
+};
+
+
+/**
+ * Get list of supported 3D effects
+ *
+ * @param {!Mode3DEffectListSupportCallback} successCallback
+ * @param {?ErrorCallback} errorCallback
+ */
+TVDisplay.prototype.getSupported3DEffectModeList = function(
+    successCallback,
+    errorCallback) {
+
+  var successCallback = {
+    name: 'successCallback',
+    type: validatorTypes.FUNCTION,
+    optional: false,
+    nullable: false
+  };
+  var errorCallback = {
+    name: 'errorCallback',
+    type: validatorTypes.FUNCTION,
+    optional: true,
+    nullable: true
+  };
+
+  var args = validator.validateArgs(
+      arguments,
+      [successCallback, errorCallback]);
+
+  native.call(
+      'TVDisplay_getSupported3DEffectModeList',
+      {},
+      function(msg) {
+        if (msg && !msg.error) {
+          args.successCallback(msg.result);
+        } else if (msg && validatorTypes.isFunction(args.errorCallback)) {
+          args.errorCallback(native.getErrorObject(msg.error));
+        } else {
+          return;
+        }
+      }
+  );
+
+};
+
+
+exports = new TVDisplay();
diff --git a/webWidgetTCT_device/src/tvdisplay/tvdisplay_extension.cc b/webWidgetTCT_device/src/tvdisplay/tvdisplay_extension.cc
new file mode 100755 (executable)
index 0000000..e23e742
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2015 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 "tvdisplay/tvdisplay_extension.h"
+#include "tvdisplay/tvdisplay_instance.h"
+
+// This will be generated from tvdisplay_api.js.
+extern const char kSource_tvdisplay_api[];
+
+
+namespace extension {
+namespace tvdisplay {
+
+TVDisplayExtension::TVDisplayExtension() {
+    SetExtensionName("tizen.tvdisplaycontrol");
+    SetJavaScriptAPI(kSource_tvdisplay_api);
+}
+
+TVDisplayExtension::~TVDisplayExtension() {}
+
+common::Instance* TVDisplayExtension::CreateInstance() {
+    return new extension::tvdisplay::TVDisplayInstance();
+}
+
+}  // namespace tvdisplay
+}  // namespace extension
+
+// entry point
+common::Extension* CreateExtension() {
+  return new extension::tvdisplay::TVDisplayExtension();
+}
+
diff --git a/webWidgetTCT_device/src/tvdisplay/tvdisplay_extension.h b/webWidgetTCT_device/src/tvdisplay/tvdisplay_extension.h
new file mode 100755 (executable)
index 0000000..bd2792c
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2015 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 SRC_TVDISPLAY_TVDISPLAY_EXTENSION_H_
+#define SRC_TVDISPLAY_TVDISPLAY_EXTENSION_H_
+
+#include "common/extension.h"
+
+namespace extension {
+namespace tvdisplay {
+
+class TVDisplayExtension : public common::Extension {
+ public:
+    TVDisplayExtension();
+    virtual ~TVDisplayExtension();
+
+ private:
+    virtual common::Instance* CreateInstance();
+};
+
+}  // namespace tvdisplay
+}  // namespace extension
+
+#endif  // SRC_TVDISPLAY_TVDISPLAY_EXTENSION_H_
diff --git a/webWidgetTCT_device/src/tvdisplay/tvdisplay_instance.cc b/webWidgetTCT_device/src/tvdisplay/tvdisplay_instance.cc
new file mode 100755 (executable)
index 0000000..665766b
--- /dev/null
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2015 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 "tvdisplay/tvdisplay_instance.h"
+
+#include <vconf/vconf.h>
+#include <system_info.h>
+
+#include <common/logger.h>
+#include <common/platform_exception.h>
+#include <common/task-queue.h>
+
+#include <cstdio>
+#include <functional>
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+
+namespace {
+    const char* kError = "error";
+    const char* kResult = "result";
+    const char* kSuccess = "success";
+    const char* kID = "callbackId";
+
+    const int kVCONF_SUCCESS = 0;
+    const char* kVCONF_3D_MODE_KEY = "db/menu/picture/3d/3dmode";
+
+    const std::map<const int, const std::string> supported_3D_modes {
+        {SYSTEM_INFO_3D_MODE_OFF, "OFF"},
+        {SYSTEM_INFO_3D_MODE_TOP_BOTTOM, "TOP_BOTTOM"},
+        {SYSTEM_INFO_3D_MODE_SIDE_BY_SIDE, "SIDE_BY_SIDE"},
+        {SYSTEM_INFO_3D_MODE_CHECKER_BOARD, "CHECKER_BD"},
+        {SYSTEM_INFO_3D_MODE_LINE_BY_LINE, "LINE_BY_LINE"},
+        {SYSTEM_INFO_3D_MODE_VERTICAL_STRIPE, "VERTICAL_STRIPE"},
+        {SYSTEM_INFO_3D_MODE_FRAME_SEQUENTIAL, "FRAME_SEQUENCE"},
+        {SYSTEM_INFO_3D_MODE_2D_3D_CONVERSION, "FROM_2D_TO_3D"}
+    };
+
+    common::PlatformResult is_3D_enabled(bool &is_3D_supported) {
+        LOGD("Enter");
+        int is_supported = -1;
+        int ret = system_info_get_value_int(
+                SYSTEM_INFO_KEY_3D_SUPPORT,
+                &is_supported);
+
+        if (SYSTEM_INFO_ERROR_NONE != ret) {
+            LOGE("Failed to get 3d support: %d (%s)", ret, get_error_message(ret));
+            return common::PlatformResult(common::ErrorCode::UNKNOWN_ERR,
+            "Unknown error. While getting 3d mode details");
+        }
+
+        is_3D_supported = (is_supported == 1);
+        return common::PlatformResult(common::ErrorCode::NO_ERROR);
+    }
+}  // namespace
+
+namespace extension {
+namespace tvdisplay {
+
+TVDisplayInstance::TVDisplayInstance() {
+    using std::placeholders::_1;
+    using std::placeholders::_2;
+
+    #define REGISTER_ASYNC(c, func) \
+        RegisterSyncHandler(c, func);
+    #define REGISTER_SYNC(c, func) \
+        RegisterSyncHandler(c, func);
+
+    REGISTER_SYNC("TVDisplay_is3DModeEnabled",
+        std::bind(&TVDisplayInstance::Is3DModeEnabled, this, _1, _2));
+    REGISTER_SYNC("TVDisplay_get3DEffectMode",
+        std::bind(&TVDisplayInstance::Get3DEffectMode,this, _1, _2));
+    REGISTER_ASYNC("TVDisplay_getSupported3DEffectModeList",
+        std::bind(&TVDisplayInstance::GetSupported3DEffectModeList,
+                  this, _1, _2));
+
+    #undef REGISTER_ASYNC
+    #undef REGISTER_SYNC
+}
+
+TVDisplayInstance::~TVDisplayInstance() {}
+
+
+void TVDisplayInstance::Is3DModeEnabled(
+        const picojson::value& value,
+        picojson::object& out) {
+    LOGD("Enter");
+    picojson::value::object o;
+    std::string mode = "NOT_SUPPORTED";
+    bool is_3D_supported = false;
+    common::PlatformResult result = is_3D_enabled(is_3D_supported);
+    if (result.IsError()) {
+        LOGD("Error occured");
+        ReportError(result, &out);
+    } else {
+        if (is_3D_supported) {
+            mode = "READY";
+        }
+        LOGD("3D Mode is: %s", mode.c_str());
+        picojson::value result(mode);
+        ReportSuccess(result, out);
+    }
+}
+
+void TVDisplayInstance::Get3DEffectMode(
+        const picojson::value& value,
+        picojson::object& out) {
+    LOGD("Enter");
+
+    int mode = 0;
+    int ret = vconf_get_int(kVCONF_3D_MODE_KEY, &mode);
+
+    if (kVCONF_SUCCESS != ret) {
+        LOGE("Platform error while getting 3d mode details: %d (%s)", ret,
+                get_error_message(ret));
+        ReportError(common::UnknownException(
+                "Platform error while getting 3d mode details"), out);
+    }
+    ReportSuccess(picojson::value(mode * 1.0), out);
+}
+
+void TVDisplayInstance::GetSupported3DEffectModeList(
+        const picojson::value& value,
+        picojson::object& out) {
+    LOGD("Enter");
+
+    std::shared_ptr <picojson::value::object> reply
+            = std::shared_ptr <picojson::value::object>(
+                    new picojson::value::object());
+
+    (*reply)[kID] = value.get(kID);
+
+    std::function <void(std::shared_ptr <picojson::object> const&)> task =
+            std::bind(
+                    &TVDisplayInstance::GetSupported3DEffectModeListTask,
+                    this,
+                    std::placeholders::_1);
+    std::function <void(std::shared_ptr <picojson::object> const&) > taskAfter =
+            std::bind(
+                    &TVDisplayInstance::GetSupported3DEffectModeListTaskAfter,
+                    this,
+                    std::placeholders::_1);
+    common::TaskQueue::GetInstance()
+            .Queue <picojson::object>(
+                    task,
+                    taskAfter,
+                    reply);
+    ReportSuccess(out);
+}
+
+void TVDisplayInstance::GetSupported3DEffectModeListTask(
+        std::shared_ptr<picojson::object> const& data) {
+    LOGD("Enter");
+
+    picojson::object & reply = (*data);
+    std::vector <picojson::value> modes;
+    bool is_3D_supported = false;
+    common::PlatformResult res = is_3D_enabled(is_3D_supported);
+    if (res.IsError()) {
+        LOGD("Error occured");
+        reply[kError] = res.ToJSON();
+        return;
+    }
+    if (!is_3D_supported) {
+        LOGD("3D is disabled");
+        reply[kResult] = picojson::value(modes);
+        reply[kSuccess] = picojson::value(true);
+        return;
+    }
+    int flags = -1;
+    int result =  system_info_get_value_int(
+            SYSTEM_INFO_KEY_3D_EFFECT_MODE,
+            &flags);
+    if (SYSTEM_INFO_ERROR_NONE != result) {
+        LOGE("Fetching SYSTEM_INFO_KEY_3D_EFFECT_MODE failed: %d (%s)", result,
+                get_error_message(result));
+        res = common::PlatformResult(common::ErrorCode::UNKNOWN_ERR,
+                "Unknown error.");
+        reply[kError] = res.ToJSON();
+        return;
+    }
+
+    auto it = supported_3D_modes.begin();
+    for (; it != supported_3D_modes.end(); ++it) {
+        if (it->first & flags) {
+            modes.push_back(picojson::value(it->second));
+        }
+    }
+
+    if (flags & SYSTEM_INFO_3D_MODE_FRAME_PACKING) {
+        LOGD("There is no FRAME_PACKING mode in TIZEN");
+    }
+    if (flags & SYSTEM_INFO_3D_MODE_FRAME_DUAL) {
+        LOGD("There is no FRAME_DUAL mode in TIZEN");
+    }
+
+    reply[kResult] = picojson::value(modes);
+    reply[kSuccess] = picojson::value(true);
+}
+
+void TVDisplayInstance::GetSupported3DEffectModeListTaskAfter(
+        std::shared_ptr<picojson::object> const& data) {
+    LOGD("Enter");
+    picojson::value out(*data);
+    std::string serialized(out.serialize());
+    Instance::PostMessage(this, serialized.c_str());
+}
+
+}  // namespace tvdisplay
+}  // namespace extension
diff --git a/webWidgetTCT_device/src/tvdisplay/tvdisplay_instance.h b/webWidgetTCT_device/src/tvdisplay/tvdisplay_instance.h
new file mode 100755 (executable)
index 0000000..e8ea11a
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2015 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 SRC_TVDISPLAY_TVDISPLAY_INSTANCE_H_
+#define SRC_TVDISPLAY_TVDISPLAY_INSTANCE_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "common/extension.h"
+#include "common/picojson.h"
+#include "common/platform_result.h"
+
+namespace extension {
+namespace tvdisplay {
+
+class TVDisplayInstance : public common::ParsedInstance {
+ public:
+    TVDisplayInstance();
+    virtual ~TVDisplayInstance();
+
+ private:
+    void  Is3DModeEnabled(
+        const picojson::value& value,
+        picojson::object& out);
+
+    void Get3DEffectMode(
+        const picojson::value& value,
+        picojson::object& out);
+
+    void GetSupported3DEffectModeList(
+        const picojson::value& value,
+        picojson::object& out);
+
+    void GetSupported3DEffectModeListTask(
+        std::shared_ptr<picojson::object> const& data);
+
+    void GetSupported3DEffectModeListTaskAfter(
+        std::shared_ptr<picojson::object> const& data);
+
+ public:
+    static TVDisplayInstance* getInstance();
+};
+
+}  // namespace tvdisplay
+}  // namespace extension
+
+#endif  // SRC_TVDISPLAY_TVDISPLAY_INSTANCE_H_
diff --git a/webWidgetTCT_device/src/tvinfo/tvinfo.gyp b/webWidgetTCT_device/src/tvinfo/tvinfo.gyp
new file mode 100755 (executable)
index 0000000..3d2f2a1
--- /dev/null
@@ -0,0 +1,32 @@
+{
+  'includes':[
+    '../common/common.gypi',
+  ],
+  'targets': [
+    {
+      'target_name': 'tizen_tvinfo',
+      'type': 'loadable_module',
+      'dependencies': [
+        '../common/common.gyp:tizen_common',
+      ],
+      'sources': [
+        'tvinfo_api.js',
+        'tvinfo_extension.cc',
+        'tvinfo_extension.h',
+        'tvinfo_instance.cc',
+        'tvinfo_instance.h',
+        'tvinfo_manager.cc',
+        'tvinfo_manager.h',
+      ],
+      'conditions': [
+        ['tizen == 1', {
+          'variables': {
+            'packages': [
+              'vconf',
+            ]
+          },
+        }],
+      ],
+    },
+  ],
+}
diff --git a/webWidgetTCT_device/src/tvinfo/tvinfo_api.js b/webWidgetTCT_device/src/tvinfo/tvinfo_api.js
new file mode 100755 (executable)
index 0000000..fa836da
--- /dev/null
@@ -0,0 +1,194 @@
+// Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var native = new xwalk.utils.NativeManager(extension);
+var validator = xwalk.utils.validator;
+var validatorType = xwalk.utils.type;
+var converter = xwalk.utils.converter;
+
+var CaptionInfoKey = {
+  CAPTION_ONOFF_KEY: 'CAPTION_ONOFF_KEY',
+  CAPTION_MODE_KEY: 'CAPTION_MODE_KEY',
+  CAPTION_FONT_SIZE_KEY: 'CAPTION_FONT_SIZE_KEY',
+  CAPTION_FONT_STYLE_KEY: 'CAPTION_FONT_STYLE_KEY',
+  CAPTION_FONT_COLOR_KEY: 'CAPTION_FONT_COLOR_KEY',
+  CAPTION_FONT_OPACITY_KEY: 'CAPTION_FONT_OPACITY_KEY',
+  CAPTION_BG_COLOR_KEY: 'CAPTION_BG_COLOR_KEY',
+  CAPTION_BG_OPACITY_KEY: 'CAPTION_BG_OPACITY_KEY',
+  CAPTION_EDGE_TYPE_KEY: 'CAPTION_EDGE_TYPE_KEY',
+  CAPTION_EDGE_COLOR_KEY: 'CAPTION_EDGE_COLOR_KEY',
+  CAPTION_WINDOW_COLOR_KEY: 'CAPTION_WINDOW_COLOR_KEY',
+  CAPTION_WINDOW_OPACITY_KEY: 'CAPTION_WINDOW_OPACITY_KEY'
+};
+
+var CaptionState = {
+  CAPTION_OFF: 'CAPTION_OFF',
+  CAPTION_ON: 'CAPTION_ON'
+};
+
+var CaptionMode = {
+  CAPTION_MODE_DEFAULT: 'CAPTION_MODE_DEFAULT',
+  CAPTION_MODE_SERVICE1: 'CAPTION_MODE_SERVICE1',
+  CAPTION_MODE_SERVICE2: 'CAPTION_MODE_SERVICE2',
+  CAPTION_MODE_SERVICE3: 'CAPTION_MODE_SERVICE3',
+  CAPTION_MODE_SERVICE4: 'CAPTION_MODE_SERVICE4',
+  CAPTION_MODE_SERVICE5: 'CAPTION_MODE_SERVICE5',
+  CAPTION_MODE_SERVICE6: 'CAPTION_MODE_SERVICE6',
+  CAPTION_MODE_CC1: 'CAPTION_MODE_CC1',
+  CAPTION_MODE_CC2: 'CAPTION_MODE_CC2',
+  CAPTION_MODE_CC3: 'CAPTION_MODE_CC3',
+  CAPTION_MODE_CC4: 'CAPTION_MODE_CC4',
+  CAPTION_MODE_TEXT1: 'CAPTION_MODE_TEXT1',
+  CAPTION_MODE_TEXT2: 'CAPTION_MODE_TEXT2',
+  CAPTION_MODE_TEXT3: 'CAPTION_MODE_TEXT3',
+  CAPTION_MODE_TEXT4: 'CAPTION_MODE_TEXT4'
+};
+
+var CaptionFontSize = {
+  CAPTION_SIZE_DEFAULT: 'CAPTION_SIZE_DEFAULT',
+  CAPTION_SIZE_SMALL: 'CAPTION_SIZE_SMALL',
+  CAPTION_SIZE_STANDARD: 'CAPTION_SIZE_STANDARD',
+  CAPTION_SIZE_LARGE: 'CAPTION_SIZE_LARGE',
+  CAPTION_SIZE_EXTRA_LARGE: 'CAPTION_SIZE_EXTRA_LARGE'
+};
+
+var CaptionFontStyle = {
+  CAPTION_FONT_DEFAULT: 'CAPTION_FONT_DEFAULT',
+  CAPTION_FONT_STYLE0: 'CAPTION_FONT_STYLE0',
+  CAPTION_FONT_STYLE1: 'CAPTION_FONT_STYLE1',
+  CAPTION_FONT_STYLE2: 'CAPTION_FONT_STYLE2',
+  CAPTION_FONT_STYLE3: 'CAPTION_FONT_STYLE3',
+  CAPTION_FONT_STYLE4: 'CAPTION_FONT_STYLE4',
+  CAPTION_FONT_STYLE5: 'CAPTION_FONT_STYLE5',
+  CAPTION_FONT_STYLE6: 'CAPTION_FONT_STYLE6',
+  CAPTION_FONT_STYLE7: 'CAPTION_FONT_STYLE7'
+};
+
+var CaptionColor = {
+  CAPTION_COLOR_DEFAULT: 'CAPTION_COLOR_DEFAULT',
+  CAPTION_COLOR_WHITE: 'CAPTION_COLOR_WHITE',
+  CAPTION_COLOR_BLACK: 'CAPTION_COLOR_BLACK',
+  CAPTION_COLOR_RED: 'CAPTION_COLOR_RED',
+  CAPTION_COLOR_GREEN: 'CAPTION_COLOR_GREEN',
+  CAPTION_COLOR_BLUE: 'CAPTION_COLOR_BLUE',
+  CAPTION_COLOR_YELLOW: 'CAPTION_COLOR_YELLOW',
+  CAPTION_COLOR_MAGENTA: 'CAPTION_COLOR_MAGENTA',
+  CAPTION_COLOR_CYAN: 'CAPTION_COLOR_CYAN'
+};
+
+var CaptionOpacity = {
+  CAPTION_OPACITY_SOLID: 'CAPTION_OPACITY_SOLID',
+  CAPTION_OPACITY_FLASHING: 'CAPTION_OPACITY_FLASHING',
+  CAPTION_OPACITY_TRANSLUCENT: 'CAPTION_OPACITY_TRANSLUCENT',
+  CAPTION_OPACITY_TRANSPARENT: 'CAPTION_OPACITY_TRANSPARENT',
+  CAPTION_OPACITY_DEFAULT: 'CAPTION_OPACITY_DEFAULT'
+};
+var CaptionEdge = {
+  CAPTION_EDGE_NONE: 'CAPTION_EDGE_NONE',
+  CAPTION_EDGE_RAISED: 'CAPTION_EDGE_RAISED',
+  CAPTION_EDGE_DEPRESSED: 'CAPTION_EDGE_DEPRESSED',
+  CAPTION_EDGE_UNIFORM: 'CAPTION_EDGE_UNIFORM',
+  CAPTION_EDGE_DROP_SHADOWED: 'CAPTION_EDGE_DROP_SHADOWED'
+};
+
+function TVInfoManager() {
+  if (!(this instanceof TVInfoManager)) {
+    throw new TypeError;
+  }
+}
+
+TVInfoManager.prototype.getCaptionValue = function(key) {
+  // xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.TV_INFO);
+  var args = validator.validateArgs(arguments, [
+    {
+      name: 'key',
+      type: validator.Types.ENUM,
+      values: validatorType.getValues(CaptionInfoKey)
+    }
+  ]);
+  var ret =
+      native.callSync('TVInfoManager_GetCaptionValue', {'key' : args.key});
+  if (native.isFailure(ret)) {
+    throw native.getErrorObject(ret);
+  }
+  return native.getResultObject(ret);
+};
+
+function ListenerManager(native, listenerName) {
+  this.listeners = {};
+  native.addListener(listenerName, this.onListenerCalled.bind(this));
+}
+
+ListenerManager.prototype.onListenerCalled = function(msg) {
+  for (var key in this.listeners) {
+    if (this.listeners.hasOwnProperty(key)) {
+      this.listeners[key](msg);
+    }
+  }
+};
+
+ListenerManager.prototype.addListener = function(callback, watchId) {
+  this.listeners[watchId] = callback;
+  return watchId;
+};
+
+ListenerManager.prototype.removeListener = function(watchId) {
+  if (this.listeners.hasOwnProperty(watchId)) {
+    delete this.listeners[watchId];
+    return true;
+  }
+  return false;
+};
+
+/**
+ * @const
+ * @type {string}
+ */
+var CAPTION_VALUE_LISTENER = 'CaptionValueChanged';
+var captionValueListener = new ListenerManager(native, CAPTION_VALUE_LISTENER);
+
+TVInfoManager.prototype.addCaptionValueChangeListener =
+    function(key, callback) {
+  // xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.TV_INFO);
+  var args = validator.validateArgs(arguments, [
+    {
+      name : 'key',
+      type : validator.Types.ENUM,
+      values : validatorType.getValues(CaptionInfoKey)
+    },
+    {
+      name : 'callback',
+      type : validator.Types.FUNCTION
+    }
+  ]);
+  var ret = native.callSync('TVInfoManager_AddCaptionValueChangeListener',
+                            {'key' : key});
+  if (native.isFailure(ret)) {
+    throw native.getErrorObject(ret);
+  }
+  var id = native.getResultObject(ret);
+
+  return captionValueListener.addListener(function(msg) {
+      if (msg.key == args.key) {
+        args.callback(msg.key, msg.value);
+      }
+    }, id);
+};
+
+TVInfoManager.prototype.removeCaptionValueChangeListener =
+    function(listenerId) {
+  // xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.TV_INFO);
+  var args = validator.validateArgs(arguments, [
+    {
+      name : 'listenerId',
+      type : validator.Types.LONG,
+    }
+  ]);
+  if(captionValueListener.removeListener(args.listenerId)) {
+    native.callSync('TVInfoManager_RemoveCaptionValueChangeListener',
+                    {'id' : args.listenerId});
+  }
+};
+
+exports = new TVInfoManager();
diff --git a/webWidgetTCT_device/src/tvinfo/tvinfo_extension.cc b/webWidgetTCT_device/src/tvinfo/tvinfo_extension.cc
new file mode 100755 (executable)
index 0000000..ad4ce20
--- /dev/null
@@ -0,0 +1,25 @@
+// Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tvinfo/tvinfo_extension.h"
+
+#include "tvinfo/tvinfo_instance.h"
+
+// This will be generated from tvinfo_api.js
+extern const char kSource_tvinfo_api[];
+
+common::Extension* CreateExtension() {
+  return new TVInfoExtension();
+}
+
+TVInfoExtension::TVInfoExtension() {
+  SetExtensionName("tizen.tvinfo");
+  SetJavaScriptAPI(kSource_tvinfo_api);
+}
+
+TVInfoExtension::~TVInfoExtension() {}
+
+common::Instance* TVInfoExtension::CreateInstance() {
+  return new extension::tvinfo::TVInfoInstance();
+}
diff --git a/webWidgetTCT_device/src/tvinfo/tvinfo_extension.h b/webWidgetTCT_device/src/tvinfo/tvinfo_extension.h
new file mode 100755 (executable)
index 0000000..2235137
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TVINFO_TVINFO_EXTENSION_H_
+#define TVINFO_TVINFO_EXTENSION_H_
+
+#include "common/extension.h"
+
+class TVInfoExtension : public common::Extension {
+ public:
+  TVInfoExtension();
+  virtual ~TVInfoExtension();
+
+ private:
+  virtual common::Instance* CreateInstance();
+};
+
+#endif  // TVINFO_TVINFO_EXTENSION_H_
diff --git a/webWidgetTCT_device/src/tvinfo/tvinfo_instance.cc b/webWidgetTCT_device/src/tvinfo/tvinfo_instance.cc
new file mode 100755 (executable)
index 0000000..9266fb2
--- /dev/null
@@ -0,0 +1,101 @@
+// Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tvinfo/tvinfo_instance.h"
+
+#include <functional>
+#include <string>
+
+#include "common/logger.h"
+#include "common/picojson.h"
+#include "common/platform_result.h"
+
+namespace extension {
+namespace tvinfo {
+
+TVInfoInstance::TVInfoInstance() {
+  LoggerD("Enter");
+  using std::placeholders::_1;
+  using std::placeholders::_2;
+
+#define REGISTER_SYNC(c, x) \
+  RegisterSyncHandler(c, std::bind(&TVInfoInstance::x, this, _1, _2));
+
+  REGISTER_SYNC("TVInfoManager_GetCaptionValue", GetCaptionValue);
+  REGISTER_SYNC("TVInfoManager_AddCaptionValueChangeListener",
+                AddCaptionValueChangeListener);
+  REGISTER_SYNC("TVInfoManager_RemoveCaptionValueChangeListener",
+                RemoveCaptionValueChangeListener);
+#undef REGISTER_SYNC
+
+  manager_.RegisterListener(this);
+}
+
+void TVInfoInstance::GetCaptionValue(const picojson::value& args,
+                                     picojson::object& out) {
+  LoggerD("Enter");
+  std::string caption_info_key = args.get("key").get<std::string>();
+  std::string value;
+  common::PlatformResult res =
+      manager_.GetCaptionValue(caption_info_key, &value);
+  if (res.IsError()) {
+    LoggerE("Failed to get caption value");
+    ReportError(res, &out);
+    return;
+  }
+  ReportSuccess(picojson::value(value), out);
+}
+
+void TVInfoInstance::AddCaptionValueChangeListener(const picojson::value& args,
+                                                   picojson::object& out) {
+  LoggerD("Enter");
+  if (!args.contains("key")) {
+    LoggerE("Invalid args. Caption info key is required argument");
+    ReportError(
+        common::TypeMismatchException("Caption info key is required argument"),
+        out);
+    return;
+  }
+  const std::string key = args.get("key").get<std::string>();
+  int id;
+  common::PlatformResult result = manager_.AddChangeListener(key, &id);
+  if (result.IsError()) {
+    LoggerE("Failed");
+    ReportError(result, &out);
+    return;
+  }
+  ReportSuccess(picojson::value(static_cast<double>(id)), out);
+}
+void TVInfoInstance::RemoveCaptionValueChangeListener(
+    const picojson::value& args, picojson::object& out) {
+  LoggerD("Enter");
+  if (!args.contains("id")) {
+    LoggerE("Invalid args. Caption info id is required argument");
+    ReportError(
+        common::TypeMismatchException("Caption info id is required argument"),
+        out);
+    return;
+  }
+  const int id = static_cast<int>(args.get("id").get<double>());
+  common::PlatformResult result = manager_.RemoveChangeListener(id);
+  if (result.IsError()) {
+    LoggerE("Failed");
+    ReportError(result, &out);
+    return;
+  }
+  ReportSuccess(out);
+}
+void TVInfoInstance::OnCaptionValueChange(const std::string& value,
+                                          const std::string& key) {
+  LoggerD("Enter");
+  picojson::value::object dict;
+  dict["listenerId"] = picojson::value("CaptionValueChanged");
+  dict["value"] = picojson::value(value);
+  dict["key"] = picojson::value(key);
+  picojson::value res(dict);
+  Instance::PostMessage(this, res.serialize().c_str());
+}
+
+}  // namespace tvinfo
+}  // namespace extension
diff --git a/webWidgetTCT_device/src/tvinfo/tvinfo_instance.h b/webWidgetTCT_device/src/tvinfo/tvinfo_instance.h
new file mode 100755 (executable)
index 0000000..8cd0eb2
--- /dev/null
@@ -0,0 +1,37 @@
+// Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TVINFO_TVINFO_INSTANCE_H_
+#define TVINFO_TVINFO_INSTANCE_H_
+
+#include <string>
+
+#include "common/extension.h"
+#include "common/picojson.h"
+#include "common/platform_result.h"
+
+#include "tvinfo/tvinfo_manager.h"
+
+namespace extension {
+namespace tvinfo {
+
+class TVInfoInstance : public common::ParsedInstance, public EventListener {
+ public:
+  TVInfoInstance();
+  void GetCaptionValue(const picojson::value& args, picojson::object& out);
+  void AddCaptionValueChangeListener(const picojson::value& args,
+                               picojson::object& out);
+  void RemoveCaptionValueChangeListener(const picojson::value& args,
+                                  picojson::object& out);
+  virtual void OnCaptionValueChange(const std::string& value,
+                                    const std::string& key);
+
+ private:
+  TVInfoManager manager_;
+};
+
+}  // namespace tvinfo
+}  // namespace extension
+
+#endif  // TVINFO_TVINFO_INSTANCE_H_
diff --git a/webWidgetTCT_device/src/tvinfo/tvinfo_manager.cc b/webWidgetTCT_device/src/tvinfo/tvinfo_manager.cc
new file mode 100755 (executable)
index 0000000..40a4a14
--- /dev/null
@@ -0,0 +1,288 @@
+// Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tvinfo/tvinfo_manager.h"
+
+#include <vconf.h>
+
+#include <map>
+#include <string>
+#include <utility>
+
+#include "common/platform_result.h"
+
+namespace extension {
+namespace tvinfo {
+
+TVInfoManager::TVInfoManager() : listener_(nullptr), next_id(0) {
+  LoggerD("Enter");
+  if (vconf_key_map_inverse_.empty()) {
+    for (auto p : vconf_key_map_) {
+      vconf_key_map_inverse_.insert(std::make_pair(p.second, p.first));
+    }
+  }
+}
+TVInfoManager::~TVInfoManager() {
+  LoggerD("Enter");
+  for (auto it = id_map_.begin(); it != id_map_.end();) {
+    this->RemoveChangeListener((it++)->first);
+  }
+}
+common::PlatformResult TVInfoManager::GetCaptionValue(
+    const std::string& caption_info_key, std::string* value) {
+  LoggerD("Enter");
+  auto vconf_key_it = vconf_key_map_.find(caption_info_key);
+  if (vconf_key_it == vconf_key_map_.end()) {
+    LoggerE("Invalid caption info key, vconf key not found");
+    return common::PlatformResult(
+        common::ErrorCode::UNKNOWN_ERR,
+        "Invalid caption info key, vconf key not found");
+  }
+  int vconf_value = -1;
+  int ret = vconf_get_int(vconf_key_it->second.c_str(), &vconf_value);
+  if (ret != 0) {
+    LoggerE("Failed to get vconf value");
+    return common::PlatformResult(common::ErrorCode::UNKNOWN_ERR,
+                                  "Failed to get vconf value");
+  }
+  return VconfValueToString(caption_info_key, vconf_value, value);
+}
+
+void TVInfoManager::RegisterListener(EventListener* listener) {
+  LoggerD("Enter");
+  listener_ = listener;
+}
+
+void TVInfoManager::UnregisterListener() {
+  LoggerD("Enter");
+  listener_ = nullptr;
+}
+
+common::PlatformResult TVInfoManager::AddChangeListener(
+    const std::string& caption_info_key, int* id) {
+  LoggerD("Enter");
+
+  auto vconf_key_it = vconf_key_map_.find(caption_info_key);
+  if (vconf_key_it == vconf_key_map_.end()) {
+    LoggerE("Invalid caption info key, vconf key not found");
+    return common::PlatformResult(
+        common::ErrorCode::UNKNOWN_ERR,
+        "Invalid caption info key, vconf key not found");
+  }
+  const std::string& vconf_key = vconf_key_it->second;
+
+  auto key_counters_it = key_counters_map_.find(vconf_key);
+  if (key_counters_it == key_counters_map_.end() ||
+      key_counters_it->second == 0) {
+    int ret = vconf_notify_key_changed(vconf_key.c_str(),
+                                       VconfKeyChangeCallback, this);
+    if (ret != 0) {
+      LoggerE("Failed to add vconf key change callback");
+      return common::PlatformResult(common::ErrorCode::UNKNOWN_ERR,
+                                    "Failed to add vconf key change callback");
+    }
+    key_counters_map_[vconf_key] = 1;
+  } else {
+    ++(key_counters_it->second);
+  }
+
+  int new_id = next_id++;
+  id_map_[new_id] = vconf_key;
+  *id = new_id;
+  return common::PlatformResult(common::ErrorCode::NO_ERROR);
+}
+
+common::PlatformResult TVInfoManager::RemoveChangeListener(const int& id) {
+  LoggerD("Enter");
+  auto id_map_it = id_map_.find(id);
+  if (id_map_it == id_map_.end()) {
+    LoggerE("Listener id (%d) not found", id);
+    return common::PlatformResult(common::ErrorCode::UNKNOWN_ERR,
+                                  "Listener id not found");
+  }
+  std::string vconf_key = id_map_it->second;
+  id_map_.erase(id_map_it);
+  auto counters_it = key_counters_map_.find(vconf_key);
+  if (counters_it == key_counters_map_.end() || counters_it->second == 0) {
+    LoggerE("No listeners listening on the key");
+    return common::PlatformResult(common::ErrorCode::UNKNOWN_ERR,
+                                  "No listeners listening on the key");
+  }
+  --(counters_it->second);
+  if (counters_it->second == 0) {
+    int ret =
+        vconf_ignore_key_changed(vconf_key.c_str(), VconfKeyChangeCallback);
+    if (ret != 0) {
+      LoggerE("Failed to remove vconf key change callback");
+      return common::PlatformResult(
+          common::ErrorCode::UNKNOWN_ERR,
+          "Failed to remove vconf key change callback");
+    }
+  }
+  return common::PlatformResult(common::ErrorCode::NO_ERROR);
+}
+
+common::PlatformResult TVInfoManager::VconfValueToString(
+    const std::string& caption_info_key, const int& vconf_value,
+    std::string* value) {
+  auto caption_key_it = caption_key_map_.find(caption_info_key);
+  if (caption_key_it == caption_key_map_.end()) {
+    LoggerE("Invalid caption info key");
+    return common::PlatformResult(common::ErrorCode::UNKNOWN_ERR,
+                                  "Invalid caption info key");
+  }
+  auto caption_value_it = caption_key_it->second->find(vconf_value);
+  if (caption_value_it == caption_key_it->second->end()) {
+    LoggerE("Unsupported vconf int value: %d", vconf_value);
+    return common::PlatformResult(common::ErrorCode::UNKNOWN_ERR,
+                                  "Unsupported vconf int value");
+  }
+  *value = caption_value_it->second;
+  return common::PlatformResult(common::ErrorCode::NO_ERROR);
+}
+
+void TVInfoManager::VconfKeyChangeCallback(keynode_t* node, void* user_data) {
+  LoggerD("Enter");
+  TVInfoManager* self = static_cast<TVInfoManager*>(user_data);
+  if (self->listener_ == nullptr) {
+    LoggerW("No listener listening");
+    return;
+  }
+  int type = vconf_keynode_get_type(node);
+  if (type != VCONF_TYPE_INT) {
+    LoggerE("Invalid type of keynode: %d", type);
+    return;
+  }
+  int vconf_value = vconf_keynode_get_int(node);
+  std::string vconf_key = vconf_keynode_get_name(node);
+  auto vconf_key_inverse_it = vconf_key_map_inverse_.find(vconf_key);
+  if (vconf_key_inverse_it == vconf_key_map_inverse_.end()) {
+    LoggerE("Unsupported vconf key: %s", vconf_key.c_str());
+    return;
+  }
+  const std::string& key = vconf_key_inverse_it->second;
+  std::string value;
+  common::PlatformResult result = VconfValueToString(key, vconf_value, &value);
+  if (result.IsSuccess()) {
+    self->listener_->OnCaptionValueChange(value, key);
+  }
+}
+
+TVInfoManager::VconfKeyMapInverse TVInfoManager::vconf_key_map_inverse_ = {};
+
+const TVInfoManager::VconfKeyMap TVInfoManager::vconf_key_map_ = {
+  {"CAPTION_ONOFF_KEY",
+    "db/menu/caption/caption"},
+  {"CAPTION_MODE_KEY",
+    "db/menu/caption/captionmode"},
+  {"CAPTION_FONT_SIZE_KEY",
+    "db/menu/caption/digitalcaptionoptions/size"},
+  {"CAPTION_FONT_STYLE_KEY",
+    "db/menu/caption/digitalcaptionoptions/fontstyle"},
+  {"CAPTION_FONT_COLOR_KEY",
+    "db/menu/caption/digitalcaptionoptions/fontcolor"},
+  {"CAPTION_FONT_OPACITY_KEY",
+    "db/menu/caption/digitalcaptionoptions/fontopacity"},
+  {"CAPTION_BG_COLOR_KEY",
+    "db/menu/caption/digitalcaptionoptions/backgroundcolor"},
+  {"CAPTION_BG_OPACITY_KEY",
+    "db/menu/caption/digitalcaptionoptions/backgroundopacity"},
+  {"CAPTION_EDGE_TYPE_KEY",
+    "db/menu/caption/digitalcaptionoptions/edgetype"},
+  {"CAPTION_EDGE_COLOR_KEY",
+    "db/menu/caption/digitalcaptionoptions/edgecolor"},
+  {"CAPTION_WINDOW_COLOR_KEY",
+    "db/menu/caption/digitalcaptionoptions/windowcolor"},
+  {"CAPTION_WINDOW_OPACITY_KEY",
+    "db/menu/caption/digitalcaptionoptions/windowopacity"}
+};
+
+const TVInfoManager::CaptionValueMap TVInfoManager::caption_state_map_ = {
+  {0, "CAPTION_OFF"},
+  {1, "CAPTION_ON"}
+};
+
+const TVInfoManager::CaptionValueMap TVInfoManager::caption_mode_map_ = {
+  {0, "CAPTION_MODE_DEFAULT"},
+  {1, "CAPTION_MODE_SERVICE1"},
+  {2, "CAPTION_MODE_SERVICE2"},
+  {3, "CAPTION_MODE_SERVICE3"},
+  {4, "CAPTION_MODE_SERVICE4"},
+  {5, "CAPTION_MODE_SERVICE5"},
+  {6, "CAPTION_MODE_SERVICE6"},
+  {7, "CAPTION_MODE_CC1"},
+  {8, "CAPTION_MODE_CC2"},
+  {9, "CAPTION_MODE_CC3"},
+  {10, "CAPTION_MODE_CC4"},
+  {11, "CAPTION_MODE_TEXT1"},
+  {12, "CAPTION_MODE_TEXT2"},
+  {13, "CAPTION_MODE_TEXT3"},
+  {14, "CAPTION_MODE_TEXT4"}
+};
+
+const TVInfoManager::CaptionValueMap TVInfoManager::caption_font_size_map_ = {
+  {0, "CAPTION_SIZE_DEFAULT"},
+  {1, "CAPTION_SIZE_SMALL"},
+  {2, "CAPTION_SIZE_STANDARD"},
+  {3, "CAPTION_SIZE_LARGE"},
+  {4, "CAPTION_SIZE_EXTRA_LARGE"}
+};
+
+const TVInfoManager::CaptionValueMap TVInfoManager::caption_font_style_map_ = {
+  {0, "CAPTION_FONT_DEFAULT"},
+  {1, "CAPTION_FONT_STYLE0"},
+  {2, "CAPTION_FONT_STYLE1"},
+  {3, "CAPTION_FONT_STYLE2"},
+  {4, "CAPTION_FONT_STYLE3"},
+  {5, "CAPTION_FONT_STYLE4"},
+  {6, "CAPTION_FONT_STYLE5"},
+  {7, "CAPTION_FONT_STYLE6"},
+  {8, "CAPTION_FONT_STYLE7"}
+};
+
+const TVInfoManager::CaptionValueMap TVInfoManager::caption_color_map_ = {
+  {0, "CAPTION_COLOR_DEFAULT"},
+  {1, "CAPTION_COLOR_WHITE"},
+  {2, "CAPTION_COLOR_BLACK"},
+  {3, "CAPTION_COLOR_RED"},
+  {4, "CAPTION_COLOR_GREEN"},
+  {5, "CAPTION_COLOR_BLUE"},
+  {6, "CAPTION_COLOR_YELLOW"},
+  {7, "CAPTION_COLOR_MAGENTA"},
+  {8, "CAPTION_COLOR_CYAN"}
+};
+
+const TVInfoManager::CaptionValueMap TVInfoManager::caption_opacity_map_ = {
+  {0, "CAPTION_OPACITY_SOLID"},
+  {1, "CAPTION_OPACITY_FLASHING"},
+  {2, "CAPTION_OPACITY_TRANSLUCENT"},
+  {3, "CAPTION_OPACITY_TRANSPARENT"},
+  {4, "CAPTION_OPACITY_DEFAULT"}
+};
+
+const TVInfoManager::CaptionValueMap TVInfoManager::caption_edge_map_ = {
+  {0, "CAPTION_EDGE_NONE"},
+  {1, "CAPTION_EDGE_RAISED"},
+  {2, "CAPTION_EDGE_DEPRESSED"},
+  {3, "CAPTION_EDGE_UNIFORM"},
+  {4, "CAPTION_EDGE_DROP_SHADOWED"}
+};
+
+const TVInfoManager::CaptionInfoKeyMap TVInfoManager::caption_key_map_ = {
+  {"CAPTION_ONOFF_KEY", &caption_state_map_},
+  {"CAPTION_MODE_KEY", &caption_mode_map_},
+  {"CAPTION_FONT_SIZE_KEY", &caption_font_size_map_},
+  {"CAPTION_FONT_STYLE_KEY", &caption_font_style_map_},
+  {"CAPTION_FONT_COLOR_KEY", &caption_color_map_},
+  {"CAPTION_FONT_OPACITY_KEY", &caption_opacity_map_},
+  {"CAPTION_BG_COLOR_KEY", &caption_color_map_},
+  {"CAPTION_BG_OPACITY_KEY", &caption_opacity_map_},
+  {"CAPTION_EDGE_TYPE_KEY", &caption_edge_map_},
+  {"CAPTION_EDGE_COLOR_KEY", &caption_color_map_},
+  {"CAPTION_WINDOW_COLOR_KEY", &caption_color_map_},
+  {"CAPTION_WINDOW_OPACITY_KEY", &caption_opacity_map_}
+};
+
+}  // namespace tvinfo
+}  // namespace extension
diff --git a/webWidgetTCT_device/src/tvinfo/tvinfo_manager.h b/webWidgetTCT_device/src/tvinfo/tvinfo_manager.h
new file mode 100755 (executable)
index 0000000..621db9b
--- /dev/null
@@ -0,0 +1,73 @@
+// Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TVINFO_TVINFO_MANAGER_H_
+#define TVINFO_TVINFO_MANAGER_H_
+
+#include <vconf.h>
+
+#include <map>
+#include <string>
+
+#include "common/platform_result.h"
+
+namespace extension {
+namespace tvinfo {
+
+class EventListener {
+ public:
+  virtual void OnCaptionValueChange(const std::string& value,
+                                    const std::string& key) = 0;
+};
+
+class TVInfoManager {
+ public:
+  TVInfoManager();
+  ~TVInfoManager();
+  common::PlatformResult GetCaptionValue(const std::string& caption_info_key,
+                                         std::string* value);
+  void RegisterListener(EventListener* listener);
+  void UnregisterListener();
+  common::PlatformResult AddChangeListener(const std::string& caption_info_key,
+                                           int* id);
+  common::PlatformResult RemoveChangeListener(const int& id);
+
+ private:
+  // Not copyable, assignable, movable
+  TVInfoManager(TVInfoManager const&) = delete;
+  TVInfoManager(TVInfoManager&&) = delete;
+  TVInfoManager& operator=(TVInfoManager const&) = delete;
+  TVInfoManager& operator=(TVInfoManager&&) = delete;
+
+  static common::PlatformResult VconfValueToString(
+      const std::string& caption_info_key, const int& vconf_value,
+      std::string* value);
+
+  static void VconfKeyChangeCallback(keynode_t *node, void *user_data);
+  EventListener* listener_;
+
+  typedef const std::map<int, const std::string> CaptionValueMap;
+  typedef const std::map<const std::string, CaptionValueMap*> CaptionInfoKeyMap;
+  typedef const std::map<const std::string, const std::string> VconfKeyMap;
+  typedef std::map<std::string, std::string> VconfKeyMapInverse;
+  static VconfKeyMap vconf_key_map_;
+  static VconfKeyMapInverse vconf_key_map_inverse_;
+  static CaptionInfoKeyMap caption_key_map_;
+  static CaptionValueMap caption_state_map_;
+  static CaptionValueMap caption_mode_map_;
+  static CaptionValueMap caption_font_size_map_;
+  static CaptionValueMap caption_font_style_map_;
+  static CaptionValueMap caption_color_map_;
+  static CaptionValueMap caption_opacity_map_;
+  static CaptionValueMap caption_edge_map_;
+
+  int next_id;
+  std::map<int, std::string> id_map_;
+  std::map<std::string, int> key_counters_map_;
+};
+
+}  // namespace tvinfo
+}  // namespace extension
+
+#endif  // TVINFO_TVINFO_MANAGER_H_
diff --git a/webWidgetTCT_device/src/tvinputdevice/tvinputdevice.gyp b/webWidgetTCT_device/src/tvinputdevice/tvinputdevice.gyp
new file mode 100755 (executable)
index 0000000..9bd3ab0
--- /dev/null
@@ -0,0 +1,32 @@
+{
+  'includes':[
+    '../common/common.gypi',
+  ],
+  'targets': [
+    {
+      'target_name': 'tizen_tvinputdevice',
+      'type': 'loadable_module',
+      'dependencies': [
+        '../common/common.gyp:tizen_common',
+      ],
+      'sources': [
+        'tvinputdevice_api.js',
+        'tvinputdevice_extension.cc',
+        'tvinputdevice_extension.h',
+        'tvinputdevice_instance.cc',
+        'tvinputdevice_instance.h'
+      ],
+      'includes': [
+        '../common/pkg-config.gypi',
+      ],
+      'conditions': [
+        ['tizen == 1', {
+          'variables': {
+            'packages': [
+            ]
+          },
+        }],
+      ],
+    },
+  ],
+}
diff --git a/webWidgetTCT_device/src/tvinputdevice/tvinputdevice_api.js b/webWidgetTCT_device/src/tvinputdevice/tvinputdevice_api.js
new file mode 100755 (executable)
index 0000000..610a71b
--- /dev/null
@@ -0,0 +1,557 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+var native = new xwalk.utils.NativeManager(extension);
+var validator = xwalk.utils.validator;
+var types = validator.Types;
+
+var tvInputInit = false;
+var tvInputLevel = "0";
+
+var mandatoryMap = {
+  "ArrowLeft" : {
+    keyName : "Left",
+    keyCode : 37
+  },
+  "ArrowUp" : {
+    keyName : "Up",
+    keyCode : 38
+  },
+  "ArrowRight" : {
+    keyName : "Right",
+    keyCode : 39
+  },
+  "ArrowDown" : {
+    keyName : "Down",
+    keyCode : 40
+  },
+  "Enter" : {
+    keyName : "Return",
+    keyCode : 13
+  },
+  "Back" : {
+    keyName : "XF86Back",
+    keyCode : 10009
+  },
+};
+var productMap = {
+  "SmartHub": {
+    keyName: "XF86Home",
+    keyCode: 10071
+  },
+  "Power": {
+    keyName: "XF86PowerOff",
+    keyCode: 409
+  },
+};
+var map = {
+  "VolumeUp": {
+    keyName: "XF86AudioRaiseVolume",
+    keyCode: 447
+  },
+  "VolumeDown": {
+    keyName: "XF86AudioLowerVolume",
+    keyCode: 448
+  },
+  "VolumeMute": {
+    keyName: "XF86AudioMute",
+    keyCode: 449
+  },
+  "ChannelUp": {
+    keyName: "XF86RaiseChannel",
+    keyCode: 427
+  },
+  "ChannelDown": {
+    keyName: "XF86LowerChannel",
+    keyCode: 428
+  },
+  "ColorF0Red": {
+    keyName: "XF86Red",
+    keyCode: 403
+  },
+  "ColorF1Green": {
+    keyName: "XF86Green",
+    keyCode: 404
+  },
+  "ColorF2Yellow": {
+    keyName: "XF86Yellow",
+    keyCode: 405
+  },
+  "ColorF3Blue": {
+    keyName: "XF86Blue",
+    keyCode: 406
+  },
+  "Menu": {
+    keyName: "XF86SysMenu",
+    keyCode: 10133
+  },
+  "Tools": {
+    keyName: "XF86SimpleMenu",
+    keyCode: 10135
+  },
+  "Info": {
+    keyName: "XF86Info",
+    keyCode: 457
+  },
+  "Exit": {
+    keyName: "XF86Exit",
+    keyCode: 10182
+  },
+  "Search": {
+    keyName: "XF86Search",
+    keyCode: 10225
+  },
+  "Guide": {
+    keyName: "XF86ChannelGuide",
+    keyCode: 458
+  },
+  "MediaRewind": {
+    keyName: "XF86AudioRewind",
+    keyCode: 412
+  },
+  "MediaPause": {
+    keyName: "XF86AudioPause",
+    keyCode: 19
+  },
+  "MediaFastForward": {
+    keyName: "XF86AudioNext",
+    keyCode: 417
+  },
+  "MediaRecord": {
+    keyName: "XF86AudioRecord",
+    keyCode: 416
+  },
+  "MediaPlay": {
+    keyName: "XF86AudioPlay",
+    keyCode: 415
+  },
+  "MediaStop": {
+    keyName: "XF86AudioStop",
+    keyCode: 413
+  },
+  "MediaPlayPause": {
+    keyName: "XF86PlayBack",
+    keyCode: 10252
+  },
+  "MediaTrackPrevious": {
+    keyName: "XF86PreviousChapter",
+    keyCode: 10232
+  },
+  "MediaTrackNext": {
+    keyName: "XF86NextChapter",
+    keyCode: 10233
+  },
+  "Source": {
+    keyName: "XF86Display",
+    keyCode: 10072
+  },
+  "PictureSize": {
+    keyName: "XF86PictureSize",
+    keyCode: 10140
+  },
+  "PreviousChannel": {
+    keyName: "XF86PreviousChannel",
+    keyCode: 10190
+  },
+  "ChannelList": {
+    keyName: "XF86ChannelList",
+    keyCode: 10073
+  },
+  "E-Manual": {
+    keyName: "XF86EManual",
+    keyCode: 10146
+  },
+  "MTS": {
+    keyName: "XF86MTS",
+    keyCode: 10195
+  },
+  "3D": {
+    keyName: "XF863D",
+    keyCode: 10199
+  },
+  "Soccer": {
+    keyName: "XF86SoccerMode",
+    keyCode: 10228
+  },
+  "Caption": {
+    keyName: "XF86Caption",
+    keyCode: 10221
+  },
+  "Teletext": {
+    keyName: "XF86TTXMIX",
+    keyCode: 10200
+  },
+  "Extra": {
+    keyName: "XF86ExtraApp",
+    keyCode: 10253
+  },
+  "0": {
+    keyName: "0",
+    keyCode: 48
+  },
+  "1": {
+    keyName: "1",
+    keyCode: 49
+  },
+  "2": {
+    keyName: "2",
+    keyCode: 50
+  },
+  "3": {
+    keyName: "3",
+    keyCode: 51
+  },
+  "4": {
+    keyName: "4",
+    keyCode: 52
+  },
+  "5": {
+    keyName: "5",
+    keyCode: 53
+  },
+  "6": {
+    keyName: "6",
+    keyCode: 54
+  },
+  "7": {
+    keyName: "7",
+    keyCode: 55
+  },
+  "8": {
+    keyName: "8",
+    keyCode: 56
+  },
+  "9": {
+    keyName: "9",
+    keyCode: 57
+  },
+  "Minus": {
+    keyName: "minus",
+    keyCode: 189
+  },
+};
+
+
+function TVInputDeviceKey(dict) {
+  for (var key in dict) {
+    if (dict.hasOwnProperty(key)) {
+      Object.defineProperty(this, key, {
+        value: dict[key],
+        enumerable: true
+      });
+    }
+  }
+  Object.freeze(this);
+}
+
+
+/**
+ * This class provides access to the API functionalities through the tizen.tvinputdevice interface.
+ * @constructor
+ */
+function TVInputDeviceManager() {
+  if (!(this instanceof TVInputDeviceManager)) {
+    throw new TypeError;
+  }
+}
+
+/**
+ * Retrieves the list of keys can be registered with the registerKey() method.
+ * @return {array} Array of keys
+ */
+TVInputDeviceManager.prototype.getSupportedKeys = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.TV_INPUT_DEVICE);
+  var re = [];
+  for (var key in map) {
+    if (map.hasOwnProperty(key)) {
+      re.push(new TVInputDeviceKey({name: key, code: map[key].keyCode}));
+    }
+  }
+
+  if(tvInputInit == false){
+    var ret = native.sendRuntimeSyncMessage('tizen://api/inputdevice/getCertLevel');
+    if (ret === 'error') {
+        throw new WebAPIException(WebAPIException.UNKNOWN_ERR, 'UnknownError');
+    }else{
+        console.log("ret : "+ret);
+        tvInputLevel = ret;
+        tvInputInit = true;
+    }
+  }
+
+  if( (tvInputLevel === '2') || (tvInputLevel === '3') ){
+    console.log("added partner key");
+    for (var key in productMap) {
+      if (productMap.hasOwnProperty(key)) {
+          re.push(new TVInputDeviceKey({name: key, code: productMap[key].keyCode}));
+      }
+    }
+  }else{
+    console.log("public key ["+tvInputInit+" , "+tvInputLevel+"]");
+  }
+
+  return re;
+};
+
+
+/**
+ * Returns information about the key which has the given name.
+ * @param {!string} keyName  The key name
+ * @return {object} Key object
+ */
+TVInputDeviceManager.prototype.getKey = function(keyName) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.TV_INPUT_DEVICE);
+  var args = validator.validateArgs(arguments, [
+    {name: 'keyName', type: types.STRING}
+  ]);
+
+  if(tvInputInit == false){
+    var ret = native.sendRuntimeSyncMessage('tizen://api/inputdevice/getCertLevel');
+    if (ret === 'error') {
+        throw new WebAPIException(WebAPIException.UNKNOWN_ERR, 'UnknownError');
+    }else{
+        tvInputLevel = ret;
+        tvInputInit = true;
+    }
+  }
+
+  if (map[args.keyName]) {
+    return new TVInputDeviceKey( { name: args.keyName, code: map[args.keyName].keyCode } );
+  }else if (mandatoryMap[args.keyName]) {
+    return new TVInputDeviceKey( { name: args.keyName, code: mandatoryMap[args.keyName].keyCode } );
+  }else if(productMap[args.keyName]){
+    if( (tvInputLevel === '2') || (tvInputLevel === '3') ){
+        return new TVInputDeviceKey( { name: args.keyName, code: productMap[args.keyName].keyCode } );
+    }else{
+        console.log("public level");
+        throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,'Parameter "keyName" is invalid.');
+    }
+  }else {
+    throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,'Parameter "keyName" is invalid.');
+  }
+
+};
+
+
+/**
+ * Registers an input device key to receive DOM keyboard event when it is pressed or released.
+ * @param {!string} keyName  The key name
+ */
+TVInputDeviceManager.prototype.registerKey = function(keyName) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.TV_INPUT_DEVICE);
+  var args = validator.validateArgs(arguments, [
+    {name: 'keyName', type: types.STRING}
+  ]);
+
+  if(tvInputInit == false){
+    var ret = native.sendRuntimeSyncMessage('tizen://api/inputdevice/getCertLevel');
+    if (ret === 'error') {
+        throw new WebAPIException(WebAPIException.UNKNOWN_ERR, 'UnknownError');
+    }else{
+        tvInputLevel = ret;
+        tvInputInit = true;
+    }
+  }
+
+  if (productMap[args.keyName]){
+    if( (tvInputLevel === '2') || (tvInputLevel === '3') ){
+        console.log("register : "+args.keyName+" , "+tvInputLevel)
+        var ret = native.sendRuntimeSyncMessage('tizen://api/inputdevice/registerKey', productMap[args.keyName].keyName);
+        if (ret === 'error') {
+          throw new WebAPIException(WebAPIException.UNKNOWN_ERR, 'UnknownError');
+        }
+    }else{
+        console.log("register error : "+tvInputLevel);
+        throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR, 'Parameter "keyName" is invalid.');
+    }
+  }else if(map[args.keyName]){
+    var ret = native.sendRuntimeSyncMessage('tizen://api/inputdevice/registerKey', map[args.keyName].keyName);
+    if (ret === 'error') {
+        throw new WebAPIException(WebAPIException.UNKNOWN_ERR, 'UnknownError');
+    }
+  }else{
+      throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,'Parameter "keyName" is invalid.');
+  }
+
+};
+
+
+/**
+ * Unregisters an input device key.
+ * @param {!string} keyName  The key name
+ */
+TVInputDeviceManager.prototype.unregisterKey = function(keyName) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.TV_INPUT_DEVICE);
+  var args = validator.validateArgs(arguments, [
+    {name: 'keyName', type: types.STRING}
+  ]);
+
+  if(tvInputInit == false){
+    var ret = native.sendRuntimeSyncMessage('tizen://api/inputdevice/getCertLevel');
+    if (ret === 'error') {
+        throw new WebAPIException(WebAPIException.UNKNOWN_ERR, 'UnknownError');
+    }else{
+        tvInputLevel = ret;
+        tvInputInit = true;
+    }
+  }
+
+  if (productMap[args.keyName]){
+    if( (tvInputLevel === '2') || (tvInputLevel === '3') ){
+        var ret = native.sendRuntimeSyncMessage('tizen://api/inputdevice/unregisterKey', productMap[args.keyName].keyName);
+        if (ret === 'error') {
+          throw new WebAPIException(WebAPIException.UNKNOWN_ERR, 'UnknownError');
+        }
+    }else{
+        throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR, 'Parameter "keyName" is invalid.');
+    }
+  }else if(map[args.keyName]){
+      var ret = native.sendRuntimeSyncMessage('tizen://api/inputdevice/unregisterKey', map[args.keyName].keyName);
+      if (ret === 'error') {
+        throw new WebAPIException(WebAPIException.UNKNOWN_ERR, 'UnknownError');
+      }
+  }else{
+      throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,'Parameter "keyName" is invalid.');
+  }
+
+};
+
+TVInputDeviceManager.prototype.registerKeyBatch = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.TV_INPUT_DEVICE);
+  var args = validator.validateMethod(arguments, [
+  {
+    name: 'keyNames',
+    type: types.ARRAY,
+    values: types.STRING
+  },
+  {
+    name: 'successCallback',
+    type: types.FUNCTION,
+    optional: true,
+    nullable: true
+  },
+  {
+    name: 'errorCallback',
+    type: types.FUNCTION,
+    optional: true,
+    nullable: true
+  }
+  ]);
+
+  if(tvInputInit == false){
+    var ret = native.sendRuntimeSyncMessage('tizen://api/inputdevice/getCertLevel');
+    if (ret === 'error') {
+        throw new WebAPIException(WebAPIException.UNKNOWN_ERR, 'UnknownError');
+    }else{
+        tvInputLevel = ret;
+        tvInputInit = true;
+    }
+  }
+
+  console.log("register batch : "+args.keyNames.length);
+  var keysList = "";
+  for (var i = 0; i < args.keyNames.length; ++i) {
+
+    if (productMap[args.keyNames[i]]){
+        if( (tvInputLevel === '2') || (tvInputLevel === '3') ){
+            keysList += productMap[args.keyNames[i]].keyName + ((i < args.keyNames.length - 1) ? "," : "");
+        }else{
+            console.log("tvinput public");
+            throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR, WebAPIException.INVALID_VALUES_ERR,
+                                  'Invalid key name: "' + args.keyNames[i] + '"');
+        }
+    }else if(map[args.keyNames[i]]){
+        keysList += map[args.keyNames[i]].keyName + ((i < args.keyNames.length - 1) ? "," : "");
+    }else{
+        throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,'Parameter "keyName" is invalid.');
+    }
+
+  }
+
+  setTimeout(function() {
+    var ret = native.sendRuntimeSyncMessage('tizen://api/inputdevice/registerKeyBatch', keysList);
+    if (ret === 'error') {
+        native.callIfPossible(args.errorCallback, new WebAPIException(
+            WebAPIException.UNKNOWN_ERR, 'Failed to register keys.'));
+    } else {
+        native.callIfPossible(args.successCallback);
+    }
+  }.bind(this), 0);
+};
+
+TVInputDeviceManager.prototype.unregisterKeyBatch = function() {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.TV_INPUT_DEVICE);
+  var args = validator.validateMethod(arguments, [
+  {
+    name: 'keyNames',
+    type: types.ARRAY,
+    values: types.STRING
+  },
+  {
+    name: 'successCallback',
+    type: types.FUNCTION,
+    optional: true,
+    nullable: true
+  },
+  {
+    name: 'errorCallback',
+    type: types.FUNCTION,
+    optional: true,
+    nullable: true
+  }
+  ]);
+
+  if(tvInputInit == false){
+    var ret = native.sendRuntimeSyncMessage('tizen://api/inputdevice/getCertLevel');
+    if (ret === 'error') {
+        throw new WebAPIException(WebAPIException.UNKNOWN_ERR, 'UnknownError');
+    }else{
+        tvInputLevel = ret;
+        tvInputInit = true;
+    }
+  }
+
+  var keysList = "";
+  for (var i = 0; i < args.keyNames.length; ++i) {
+
+    if (productMap[args.keyNames[i]]){
+      if( (tvInputLevel === '2') || (tvInputLevel === '3') ){
+          keysList += productMap[args.keyNames[i]].keyName + ((i < args.keyNames.length - 1) ? "," : "");
+      }else{
+          console.log("public level");
+          throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR, WebAPIException.INVALID_VALUES_ERR,
+                                'Invalid key name: "' + args.keyNames[i] + '"');
+      }
+    }else if(map[args.keyNames[i]]){
+      keysList += map[args.keyNames[i]].keyName + ((i < args.keyNames.length - 1) ? "," : "");
+    }else{
+      throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,'Parameter "keyName" is invalid.');
+    }
+  }
+
+  setTimeout(function() {
+    var ret = native.sendRuntimeSyncMessage('tizen://api/inputdevice/unregisterKeyBatch', keysList);
+    if (ret === 'error') {
+      native.callIfPossible(args.errorCallback, new WebAPIException(
+          WebAPIException.UNKNOWN_ERR, 'Failed to unregister keys.'));
+    } else {
+      native.callIfPossible(args.successCallback);
+    }
+  }.bind(this), 0);
+};
+
+// Exports
+exports = new TVInputDeviceManager();
diff --git a/webWidgetTCT_device/src/tvinputdevice/tvinputdevice_extension.cc b/webWidgetTCT_device/src/tvinputdevice/tvinputdevice_extension.cc
new file mode 100755 (executable)
index 0000000..e007872
--- /dev/null
@@ -0,0 +1,30 @@
+// Copyright 2014 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "../tvinputdevice/tvinputdevice_extension.h"
+#include "../tvinputdevice/tvinputdevice_instance.h"
+
+// This will be generated from tvinputdevice_api.js
+extern const char kSource_tvinputdevice_api[];
+
+namespace extension {
+namespace tvinputdevice {
+
+TVInputDeviceExtension::TVInputDeviceExtension() {
+    SetExtensionName("tizen.tvinputdevice");
+    SetJavaScriptAPI(kSource_tvinputdevice_api);
+}
+
+TVInputDeviceExtension::~TVInputDeviceExtension() {}
+
+common::Instance* TVInputDeviceExtension::CreateInstance() {
+    return new TVInputDeviceInstance;
+}
+
+}  // namespace tvinputdevice
+}  // namespace extension
+
+common::Extension* CreateExtension() {
+    return new extension::tvinputdevice::TVInputDeviceExtension;
+}
diff --git a/webWidgetTCT_device/src/tvinputdevice/tvinputdevice_extension.h b/webWidgetTCT_device/src/tvinputdevice/tvinputdevice_extension.h
new file mode 100755 (executable)
index 0000000..8a633f1
--- /dev/null
@@ -0,0 +1,26 @@
+// Copyright 2014 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SRC_TVINPUTDEVICE_TVINPUTDEVICE_EXTENSION_H_
+#define SRC_TVINPUTDEVICE_TVINPUTDEVICE_EXTENSION_H_
+
+#include "common/extension.h"
+
+namespace extension {
+namespace tvinputdevice {
+
+class TVInputDeviceExtension : public common::Extension {
+ public:
+    TVInputDeviceExtension();
+    virtual ~TVInputDeviceExtension();
+
+ private:
+    virtual common::Instance* CreateInstance();
+};
+
+}  // namespace tvinputdevice
+}  // namespace extension
+
+#endif  // SRC_TVINPUTDEVICE_TVINPUTDEVICE_EXTENSION_H_
+
diff --git a/webWidgetTCT_device/src/tvinputdevice/tvinputdevice_instance.cc b/webWidgetTCT_device/src/tvinputdevice/tvinputdevice_instance.cc
new file mode 100755 (executable)
index 0000000..fe926ca
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2015 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 "../tvinputdevice/tvinputdevice_instance.h"
+#include "common/logger.h"
+
+
+namespace extension {
+namespace tvinputdevice {
+
+TVInputDeviceInstance::TVInputDeviceInstance() {
+    LOGD("Enter");
+}
+
+TVInputDeviceInstance::~TVInputDeviceInstance() {
+    LOGD("Enter");
+}
+
+}  // namespace tvinputdevice
+}  // namespace extension
diff --git a/webWidgetTCT_device/src/tvinputdevice/tvinputdevice_instance.h b/webWidgetTCT_device/src/tvinputdevice/tvinputdevice_instance.h
new file mode 100755 (executable)
index 0000000..d48248e
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2015 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 SRC_TVINPUTDEVICE_TVINPUTDEVICE_INSTANCE_H_
+#define SRC_TVINPUTDEVICE_TVINPUTDEVICE_INSTANCE_H_
+
+#include "common/picojson.h"
+#include "common/extension.h"
+
+
+namespace extension {
+namespace tvinputdevice {
+
+class TVInputDeviceInstance : public common::ParsedInstance {
+ public:
+    TVInputDeviceInstance();
+    virtual ~TVInputDeviceInstance();
+
+ private:
+};
+
+}  // namespace tvinputdevice
+}  // namespace extension
+
+#endif  // SRC_TVINPUTDEVICE_TVINPUTDEVICE_INSTANCE_H_
diff --git a/webWidgetTCT_device/src/tvwindow/tvwindow.gyp b/webWidgetTCT_device/src/tvwindow/tvwindow.gyp
new file mode 100755 (executable)
index 0000000..977ac7d
--- /dev/null
@@ -0,0 +1,33 @@
+{
+  'includes':[
+    '../common/common.gypi',
+  ],
+  'targets': [
+    {
+      'target_name': 'tizen_tvwindow',
+      'type': 'loadable_module',
+      'variables': {
+        'packages': [
+          'capi-system-info',
+          'tvs-api',
+        ],
+      },
+      'dependencies': [
+        '../common/common.gyp:tizen_common',
+        '../tizen/tizen.gyp:tizen',
+      ],
+      'includes': [
+        '../common/pkg-config.gypi',
+      ],
+      'sources': [
+        'tvwindow_api.js',
+        'tvwindow_extension.cc',
+        'tvwindow_extension.h',
+        'tvwindow_manager.cc',
+        'tvwindow_manager.h',
+        'tvwindow_instance.cc',
+        'tvwindow_instance.h',
+      ],
+    },
+  ],
+}
diff --git a/webWidgetTCT_device/src/tvwindow/tvwindow_api.js b/webWidgetTCT_device/src/tvwindow/tvwindow_api.js
new file mode 100755 (executable)
index 0000000..829e98f
--- /dev/null
@@ -0,0 +1,446 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+var native = new xwalk.utils.NativeManager(extension);
+var validator = xwalk.utils.validator;
+var WindowType = {
+  MAIN: 'MAIN'
+};
+var ZPosition = {
+  FRONT: 'FRONT',
+  BEHIND: 'BEHIND'
+}
+var MeasurementUnit = {
+  px: 'px',
+  '%': '%'
+};
+var percentRE = /^([0-9]+(.[0-9]+)?)%$/,
+    pxRE = /^([0-9]+)(px)?$/,
+    last_window_rect = null,
+    max_width, max_height;
+var showCallbacks = [];
+
+function VideoResolution(data) {
+  Object.defineProperties(this, {
+    width: {
+        value: data.width,
+        enumerable: true
+    },
+    height: {
+        value: data.height,
+        enumerable: true
+    },
+    frequency: {
+        value: data.frequency,
+        enumerable: true
+    },
+    aspectRatio: {
+        value: data.aspectRatio,
+        enumerable: true
+    }
+  });
+}
+
+function ListenerManager(native, listenerName) {
+  this.listeners = {};
+  this.nextId = 1;
+  native.addListener(listenerName, this.onListenerCalled.bind(this));
+}
+
+ListenerManager.prototype.onListenerCalled = function(data) {
+  for (var key in this.listeners) {
+    if (this.listeners.hasOwnProperty(key)) {
+      this.listeners[key](data);
+    }
+  }
+};
+
+ListenerManager.prototype.addListener = function(callback) {
+  var id = this.nextId;
+  this.listeners[id] = callback;
+  ++this.nextId;
+  return id;
+};
+
+ListenerManager.prototype.removeListener = function(watchId) {
+  if (this.listeners.hasOwnProperty(watchId)) {
+    delete this.listeners[watchId];
+  }
+};
+
+/**
+ * @const
+ * @type {string}
+ */
+var VIDEO_RESOLUTION_LISTENER = 'VideoResolutionChanged';
+
+var videoResolutionListener = new ListenerManager(native, VIDEO_RESOLUTION_LISTENER);
+
+/**
+ * @const
+ * @type {string}
+ */
+var WINDOW_ENABLED = 'WindowEnabled';
+
+native.addListener(WINDOW_ENABLED, function() {
+  showCallbacks.forEach(function(cb) {
+    cb();
+  });
+  showCallbacks.length = 0;
+});
+
+//TVWindowManager interface
+function TVWindowManager() {
+  if (!(this instanceof TVWindowManager)) {
+    throw new TypeError;
+  }
+  var ret = native.callSync('TVWindow_GetScreenDimension', {});
+  if (native.isFailure(ret)) {
+    throw native.getErrorObject(ret);
+  }
+  var result = native.getResultObject(ret);
+  max_width = result.width;
+  max_height = result.height;
+}
+
+
+TVWindowManager.prototype.getAvailableWindows = function(successCallback, errorCallback) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.TV_WINDOW);
+  var args = validator.validateArgs(arguments, [
+    {
+      name: 'successCallback',
+      type: validator.Types.FUNCTION
+    },
+    {
+      name: 'errorCallback',
+      type: validator.Types.FUNCTION,
+      optional: true,
+      nullable: true
+    }
+  ]);
+
+  setTimeout(function() {
+    args.successCallback(Object.keys(WindowType));
+  });
+};
+
+TVWindowManager.prototype.setSource = function(videosource, successCallback, errorCallback, type) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.TV_WINDOW);
+  var args = validator.validateArgs(arguments, [
+    {
+      name: 'videosource',
+      type: validator.Types.PLATFORM_OBJECT,
+      values: tizen.systeminfo._SystemInfoVideoSourceInfo
+    },
+    {
+      name: 'successCallback',
+      type: validator.Types.FUNCTION
+    },
+    {
+      name: 'errorCallback',
+      type: validator.Types.FUNCTION,
+      optional: true,
+      nullable: true
+    },
+    {
+      name: 'type',
+      optional: true,
+      nullable: true,
+      type: validator.Types.ENUM,
+      values: Object.keys(WindowType)
+    }
+  ]);
+
+  native.call('TVWindow_SetSource', {
+    videosource: args.videosource
+  }, function(msg) {
+    if (native.isFailure(msg)) {
+      if (type.isFunction(args.errorCallback)) {
+        args.errorCallback(native.getErrorObject(msg));
+      }
+    } else {
+      native.callIfPossible(args.successCallback,
+        new tizen.systeminfo._SystemInfoVideoSourceInfo(msg), WindowType.MAIN);
+    }
+  });
+};
+
+TVWindowManager.prototype.getSource = function(type) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.TV_WINDOW);
+  var args = validator.validateArgs(arguments, [
+    {
+      name: 'type',
+      optional: true,
+      nullable: true,
+      type: validator.Types.ENUM,
+      values: Object.keys(WindowType)
+    }
+  ]);
+  var ret = native.callSync('TVWindow_GetSource', {});
+  if (native.isFailure(ret)) {
+    throw native.getErrorObject(ret);
+  }
+  var data = native.getResultObject(ret);
+  return new tizen.systeminfo._SystemInfoVideoSourceInfo(data);
+};
+
+function getPx(val, max) {
+  var match;
+  match = val.toString().match(percentRE);
+  if (match) {
+    return Math.round(match[1] * max / 100);
+  }
+  match = val.toString().match(pxRE);
+  if (match) {
+      if (match[1] > max) {
+        throw new WebAPIException(WebAPIException.NOT_SUPPORTED_ERR,
+        "Given value is not supported: " + match[1]);
+      }
+      return match[1];
+  }
+  throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+        "Invalid rectangle value");
+}
+
+function convertToPixels(rect) {
+  var ret = [];
+  ret.push(getPx(rect[0], max_width));
+  ret.push(getPx(rect[1], max_height));
+  ret.push(getPx(rect[2], max_width));
+  ret.push(getPx(rect[3], max_height));
+  return ret;
+}
+
+TVWindowManager.prototype.show = function(successCallback, errorCallback, rectangle, type, zPosition) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.TV_WINDOW);
+  var args = validator.validateArgs(arguments, [
+    {
+      name: 'successCallback',
+      type: validator.Types.FUNCTION
+    },
+    {
+      name: 'errorCallback',
+      type: validator.Types.FUNCTION,
+      optional: true,
+      nullable: true
+    },
+    {
+      name: 'rectangle',
+      type: validator.Types.ARRAY,
+      optional: true,
+      nullable: true
+    },
+    {
+      name: 'type',
+      optional: true,
+      nullable: true,
+      type: validator.Types.ENUM,
+      values: Object.keys(WindowType)
+    },
+    {
+      name: 'zPosition',
+      optional: true,
+      nullable: true,
+      type: validator.Types.ENUM,
+      values: Object.keys(ZPosition)
+    }
+  ]);
+
+  var rect, px_rect;
+  if (Array.isArray(args.rectangle)) {
+    if (args.rectangle.length < 4) {
+      throw new WebAPIException(WebAPIException.INVALID_VALUES_ERR,
+        "Invalid rectangle vector size");
+    }
+    rect = args.rectangle;
+    px_rect = convertToPixels(rect);
+  } else if (last_window_rect) {
+    // set previous window size, copy previous array:
+    rect = last_window_rect.slice();
+    px_rect = convertToPixels(rect);
+  } else {
+    // window shown for first time, show full
+    rect = [0, 0, max_width, max_height];
+    px_rect = rect;
+  }
+
+  var position = args.zPosition;
+  if ((position === undefined) || !(position in ZPosition)) {
+    position = ZPosition.FRONT;
+  }
+
+  px_rect.push(position);
+
+  native.sendRuntimeAsyncMessage('tizen://tvwindow/reposition', px_rect.toString(), function(result) {
+    if (native.isFailure(result)) {
+      native.callIfPossible(args.errorCallback, native.getErrorObject(result));
+    } else {
+      native.sendRuntimeAsyncMessage('tizen://tvwindow/show', null, function(result) {
+        if (native.isFailure(result)) {
+          native.callIfPossible(args.errorCallback, native.getErrorObject(result));
+        } else {
+          var windowReady = function () {
+            last_window_rect = rect.slice();
+            args.successCallback(rect, WindowType.MAIN);
+          };
+          var ret = native.callSync('TVWindow_IsSourceActive', {});
+          if (native.isFailure(ret)) {
+            native.callIfPossible(args.errorCallback, native.getErrorObject(ret));
+          } else {
+            var windowActive = native.getResultObject(ret);
+            if (windowActive) {
+              windowReady();
+            } else {
+              showCallbacks.push(windowReady);
+            }
+          }
+        }
+      });
+    }
+  });
+};
+
+TVWindowManager.prototype.hide = function(successCallback, errorCallback, type) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.TV_WINDOW);
+  var args = validator.validateArgs(arguments, [
+    {
+      name: 'successCallback',
+      type: validator.Types.FUNCTION
+    },
+    {
+      name: 'errorCallback',
+      type: validator.Types.FUNCTION,
+      optional: true,
+      nullable: true
+    },
+    {
+      name: 'type',
+      optional: true,
+      nullable: true,
+      type: validator.Types.ENUM,
+      values: Object.keys(WindowType)
+    }
+  ]);
+
+  native.sendRuntimeAsyncMessage('tizen://tvwindow/hide', null, function(result) {
+    if (native.isFailure(result)) {
+      native.callIfPossible(args.errorCallback, native.getErrorObject(result));
+    } else {
+      native.callIfPossible(args.successCallback);
+    }
+  });
+};
+
+TVWindowManager.prototype.getRect = function(successCallback, errorCallback, unit, type) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.TV_WINDOW);
+  var args = validator.validateArgs(arguments, [
+    {
+      name: 'successCallback',
+      type: validator.Types.FUNCTION
+    },
+    {
+      name: 'errorCallback',
+      type: validator.Types.FUNCTION,
+      optional: true,
+      nullable: true
+    },
+    {
+      name: 'unit',
+      optional: true,
+      nullable: true,
+      type: validator.Types.ENUM,
+      values: Object.keys(MeasurementUnit)
+    },
+    {
+      name: 'type',
+      optional: true,
+      nullable: true,
+      type: validator.Types.ENUM,
+      values: Object.keys(WindowType)
+    }
+  ]);
+
+  setTimeout(function() {
+    var rect;
+    if (last_window_rect) {
+      rect = convertToPixels(last_window_rect);
+    } else {
+      rect = [0, 0, max_width, max_height];
+    }
+
+    if (!args.unit || args.unit === MeasurementUnit.px) {
+      //convert to px, default argument
+      rect = rect.map(function(val) {
+        return val + 'px';
+      });
+    } else {
+      //convert to %
+      rect = rect.map(function(val, indx) {
+        var max = indx % 2 === 0 ? max_width : max_height;
+        return Math.round(100.0 * val / max) + '%';
+      });
+    }
+    args.successCallback(rect, WindowType.MAIN);
+  });
+};
+
+TVWindowManager.prototype.getVideoResolution = function(type) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.TV_WINDOW);
+  var args = validator.validateArgs(arguments, [
+    {
+      name: 'type',
+      optional: true,
+      nullable: true,
+      type: validator.Types.ENUM,
+      values: Object.keys(WindowType)
+    }
+  ]);
+  var ret = native.callSync('TVWindow_GetVideoResolution', {});
+  if (native.isFailure(ret)) {
+    throw native.getErrorObject(ret);
+  }
+  var data = native.getResultObject(ret);
+  return new VideoResolution(data);
+};
+
+TVWindowManager.prototype.addVideoResolutionChangeListener = function(callback, type) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.TV_WINDOW);
+  var args = validator.validateArgs(arguments, [
+    {
+      name: 'callback',
+      type: validator.Types.FUNCTION
+    },
+    {
+      name: 'windowType',
+      optional: true,
+      nullable: true,
+      type: validator.Types.ENUM,
+      values: Object.keys(WindowType)
+    }
+  ]);
+
+  return videoResolutionListener.addListener(function(data) {
+    var res = new VideoResolution(data);
+    args.callback(res, data.type);
+  });
+};
+
+TVWindowManager.prototype.removeVideoResolutionChangeListener = function(listenerId) {
+  xwalk.utils.checkPrivilegeAccess(xwalk.utils.privilege.TV_WINDOW);
+  videoResolutionListener.removeListener(listenerId);
+};
+
+exports = new TVWindowManager();
diff --git a/webWidgetTCT_device/src/tvwindow/tvwindow_extension.cc b/webWidgetTCT_device/src/tvwindow/tvwindow_extension.cc
new file mode 100755 (executable)
index 0000000..1b662f1
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2015 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 "tvwindow/tvwindow_extension.h"
+#include "tvwindow/tvwindow_instance.h"
+
+// This will be generated from datasync_api.js.
+extern const char kSource_tvwindow_api[];
+
+namespace extension {
+namespace tvwindow {
+
+TVWindowExtension::TVWindowExtension() {
+  SetExtensionName("tizen.tvwindow");
+  SetJavaScriptAPI(kSource_tvwindow_api);
+}
+
+TVWindowExtension::~TVWindowExtension() {}
+
+TVWindowManager& TVWindowExtension::manager() {
+  // Initialize API on first request
+  return TVWindowManager::getInstance();
+}
+
+common::Instance* TVWindowExtension::CreateInstance() {
+  return new TVWindowInstance(*this);
+}
+
+}  // namespace tvwindow
+}  // namespace extension
+
+// entry point
+common::Extension* CreateExtension() {
+  return new extension::tvwindow::TVWindowExtension;
+}
diff --git a/webWidgetTCT_device/src/tvwindow/tvwindow_extension.h b/webWidgetTCT_device/src/tvwindow/tvwindow_extension.h
new file mode 100755 (executable)
index 0000000..398d46a
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2015 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 SRC_TVWINDOW_TVWINDOW_EXTENSION_H_
+#define SRC_TVWINDOW_TVWINDOW_EXTENSION_H_
+
+#include "common/extension.h"
+#include "tvwindow/tvwindow_manager.h"
+
+namespace extension {
+namespace tvwindow {
+
+class TVWindowExtension : public common::Extension {
+ public:
+  TVWindowExtension();
+  virtual ~TVWindowExtension();
+
+  TVWindowManager& manager();
+
+ private:
+  // common::Extension implementation.
+  virtual common::Instance* CreateInstance();
+};
+
+}  // namespace tvwindow
+}  // namespace extension
+
+#endif  // SRC_TVWINDOW_TVWINDOW_EXTENSION_H_
diff --git a/webWidgetTCT_device/src/tvwindow/tvwindow_instance.cc b/webWidgetTCT_device/src/tvwindow/tvwindow_instance.cc
new file mode 100755 (executable)
index 0000000..71484c8
--- /dev/null
@@ -0,0 +1,387 @@
+/*
+ * Copyright (c) 2015 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 "tvwindow/tvwindow_instance.h"
+#include "tvwindow/tvwindow_manager.h"
+#include "common/logger.h"
+#include "tizen/tizen.h"
+#include "common/picojson.h"
+#include "common/platform_result.h"
+#include "common/platform_exception.h"
+#include "common/video_source_types.h"
+#include "common/task-queue.h"
+
+#include <system_info.h>
+#include <TVServiceAPI.h>
+#include <algorithm>
+#include <memory>
+
+using namespace common;
+
+namespace extension {
+namespace tvwindow {
+
+bool TVWindowInstance::CheckExists(const picojson::value& args, std::string name, picojson::object& out,TVWindowInstance * inst)
+{
+  if (!args.contains(name))
+  {
+    std::string err = name+" is required argument";
+    inst->ReportError(TypeMismatchException(err), out);
+    return false;
+  }
+  return true;
+}
+
+
+TVWindowInstance::TVWindowInstance(TVWindowExtension const& extension):
+    m_tvsApiEnabled(false) {
+  LoggerD("Entered");
+  using std::placeholders::_1;
+  using std::placeholders::_2;
+
+  RegisterSyncHandler("TVWindow_GetScreenDimension",
+      std::bind(&TVWindowInstance::GetScreenDimension, this, _1, _2));
+  RegisterSyncHandler("TVWindow_IsSourceActive",
+      std::bind(&TVWindowInstance::IsSourceActive, this, _1, _2));
+  RegisterSyncHandler("TVWindow_GetSource",
+      std::bind(&TVWindowInstance::GetSource, this, _1, _2));
+  RegisterSyncHandler("TVWindow_SetSource",
+      std::bind(&TVWindowInstance::SetSource, this, _1, _2));
+  RegisterSyncHandler("TVWindow_GetVideoResolution",
+      std::bind(&TVWindowInstance::GetVideoResolution, this, _1, _2));
+  auto& helper = common::TvsSubscribeHelper::getInstance();
+  helper.registerListener(SIGNAL_TUNE_SUCCESS, this);
+  helper.registerListener(SIGNAL_TVS_ACTIVATE, this);
+  helper.registerListener(SIGNAL_RESOLUTION_CHANGED, this);
+}
+
+TVWindowInstance::~TVWindowInstance() {
+  LoggerD("Entered");
+  auto& helper = common::TvsSubscribeHelper::getInstance();
+  helper.unregisterListener(SIGNAL_TUNE_SUCCESS, this);
+  helper.unregisterListener(SIGNAL_TVS_ACTIVATE, this);
+  helper.unregisterListener(SIGNAL_RESOLUTION_CHANGED, this);
+}
+
+void TVWindowInstance::GetScreenDimension(const picojson::value& args,
+    picojson::object& out) {
+  LoggerD("Entered");
+
+  int max_width = 0;
+  if (system_info_get_value_int(SYSTEM_INFO_KEY_OSD_RESOLUTION_WIDTH,
+      &max_width) != SYSTEM_INFO_ERROR_NONE) {
+    common::PlatformResult res(common::ErrorCode::UNKNOWN_ERR,
+        "Failed to retrieve screen max width");
+    ReportError(res, &out);
+    return;
+  }
+  int max_height = 0;
+  if (system_info_get_value_int(SYSTEM_INFO_KEY_OSD_RESOLUTION_HEIGHT,
+      &max_height) != SYSTEM_INFO_ERROR_NONE) {
+    common::PlatformResult res(common::ErrorCode::UNKNOWN_ERR,
+        "Failed to retrieve screen max height");
+    ReportError(res, &out);
+    return;
+  }
+  picojson::value::object dict;
+  dict["width"] = picojson::value(static_cast<double>(max_width));
+  dict["height"] = picojson::value(static_cast<double>(max_height));
+  picojson::value result(dict);
+  ReportSuccess(result, out);
+}
+
+picojson::value EAspectratioTypeToJsonValue(EAspectratioType aspectratio) {
+  switch (aspectratio) {
+    case ASPECTRATIO_TYPE_100_100:
+      return picojson::value("ASPECT_RATIO_1x1");
+    case ASPECTRATIO_TYPE_300_400:
+      return picojson::value("ASPECT_RATIO_4x3");
+    case ASPECTRATIO_TYPE_900_1600:
+      return picojson::value("ASPECT_RATIO_16x9");
+    case ASPECTRATIO_TYPE_100_221:
+      return picojson::value("ASPECT_RATIO_221x100");
+      break;
+    default:
+      LoggerW("Unsupported aspect ratio: %d", aspectratio);
+      return picojson::value();
+  }
+}
+
+void TVWindowInstance::OnSignal(ESignalType type, TSSignalData data) {
+  LoggerD("Entered, signal: %d", type);
+
+  switch (type) {
+    case SIGNAL_TVS_ACTIVATE: {
+        auto& mgr = TVWindowManager::getInstance();
+        if (mgr.IsCurrentSourceTV() && !mgr.IsSourceActive()) {
+          LoggerD("Current source = TV, active = false");
+        } else {
+          LoggerD("tvs-api active");
+          m_tvsApiEnabled = true;
+          picojson::value::object dict;
+          dict["listenerId"] = picojson::value("WindowEnabled");
+          picojson::value res(dict);
+          Instance::PostMessage(this, res.serialize().c_str());
+        }
+      }
+      break;
+    case SIGNAL_TUNE_SUCCESS:
+        if (!m_tvsApiEnabled) {
+          LoggerD("tvs-api active");
+          m_tvsApiEnabled = true;
+          picojson::value::object dict;
+          dict["listenerId"] = picojson::value("WindowEnabled");
+          picojson::value res(dict);
+          Instance::PostMessage(this, res.serialize().c_str());
+        }
+      break;
+    case SIGNAL_RESOLUTION_CHANGED: {
+        TSResolution resolution;
+        common::PlatformResult ret =
+          TVWindowManager::getInstance().GetResolution(resolution);
+        if (ret.IsSuccess()) {
+          picojson::value::object dict;
+          dict["aspectRatio"] = EAspectratioTypeToJsonValue(resolution.aspectratio);
+          if (!dict["aspectRatio"].is<picojson::null>()) {
+            dict["width"] = picojson::value(static_cast<double>(
+              resolution.horizontal));
+            dict["height"] = picojson::value(static_cast<double>(
+              resolution.vertical));
+            dict["frequency"] = picojson::value(static_cast<double>(
+              resolution.frequency));
+            dict["type"] = picojson::value("MAIN");
+            dict["listenerId"] = picojson::value("VideoResolutionChanged");
+            picojson::value res(dict);
+            Instance::PostMessage(this, res.serialize().c_str());
+          }
+        }
+      }
+      break;
+    default:
+      LoggerW("Unrecognized signal type");
+  }
+}
+
+void TVWindowInstance::IsSourceActive(const picojson::value& args,
+    picojson::object& out) {
+  LoggerD("Entered");
+
+  auto& mgr = TVWindowManager::getInstance();
+  picojson::value result(mgr.IsSourceActive());
+  ReportSuccess(result, out);
+}
+
+void TVWindowInstance::GetSource(const picojson::value& args,
+    picojson::object& out) {
+  LoggerD("Entered");
+
+  using namespace VideoSourceTypes;
+
+  ISourceControl* pSourceControl;
+
+  int ret = TVServiceAPI::CreateSourceControl(PROFILE_TYPE_MAIN, 0, &pSourceControl);
+  if (0 != ret) {
+    LoggerE("Failed to create source control: %d", ret);
+    common::PlatformResult res(common::ErrorCode::UNKNOWN_ERR,
+           "Failed to create source control");
+    ReportError(res, &out);
+    return;
+  }
+
+  ESource src = SOURCE_TYPE_UNDEFINED;
+  ret = pSourceControl->GetCurrentSourceInfo(src);
+  if (1 != ret) {
+    LoggerE("Failed to get current source info: %d", ret);
+    common::PlatformResult res(common::ErrorCode::UNKNOWN_ERR,
+           "Failed to get current source info");
+    ReportError(res, &out);
+    return;
+  }
+
+  picojson::value::object dict;
+  SourceDesc desc;
+  std::string name;
+  ret = SourceDescFromESource(src,desc);
+  ret|= SourceTypeToName(desc.type,name);
+  if (ret) {
+    LoggerE("Unknown source type: %d", src);
+    common::PlatformResult res(common::ErrorCode::UNKNOWN_ERR,
+           "Unknown source type");
+    ReportError(res, &out);
+    return;
+ }
+
+  dict["type"] = picojson::value(name);
+  dict["number"] = picojson::value(static_cast<double>(desc.number));
+
+  picojson::value result(dict);
+  ReportSuccess(result, out);
+}
+
+void TVWindowInstance::SetSource(const picojson::value& args,
+    picojson::object& out) {
+  LoggerD("Entered");
+
+  CheckExists(args,"videosource",out,this);
+  CheckExists(args,"callbackId",out,this);
+
+  const std::string& videoSourceName = args.get("videosource").get("type").get<std::string>();
+  const unsigned long videoSourceNumber = std::stoul(args.get("videosource").get("number").to_str());
+  const double callback_id = args.get("callbackId").get<double>();
+
+  VideoSourceTypes::SourceType sourceType;
+
+  int ret = VideoSourceTypes::NameToSourceType(videoSourceName,sourceType);
+
+  if(ret)
+  {
+      LoggerE("Invalid source name");
+      ReportError(out);
+      return;
+  }
+
+  VideoSourceTypes::SourceDesc sourceDesc (sourceType,videoSourceNumber);
+  ESource sourceToSet = SOURCE_TYPE_UNDEFINED;
+
+  ret = VideoSourceTypes::ESourceFromSourceDesc(sourceDesc,sourceToSet);
+  if(ret || SOURCE_TYPE_UNDEFINED == sourceToSet)
+  {
+      LoggerE("Invalid source");
+      ReportError(out);
+      return;
+  }
+
+  auto set = std::bind(&TVWindowInstance::SetSourceWork, this, std::placeholders::_1, sourceToSet);
+  auto set_response = std::bind(&TVWindowInstance::SetSourceResponse, this, std::placeholders::_1, videoSourceName, videoSourceNumber, sourceToSet, callback_id);
+
+  TaskQueue::GetInstance().Queue<picojson::value> (set, set_response,
+      std::make_shared<picojson::value>(picojson::object()));
+
+  ReportSuccess(out);
+}
+
+void TVWindowInstance::SetSourceWork(const std::shared_ptr<picojson::value>& response, const ESource sourceToSet)
+{
+  LoggerD("Setting source");
+
+  ISourceControl* pSourceControl;
+  ESource currentSource = SOURCE_TYPE_UNDEFINED;
+
+
+  common::PlatformResult res = CreateSourceControl(&pSourceControl);
+  if(res.IsSuccess())
+  {
+      LoggerD("Current source");
+      int ret = pSourceControl->GetCurrentSourceInfo(currentSource);
+      if ( ret < 1 ) {
+          LoggerE("Failed to get current source info: %d", ret);
+      }
+
+      if(sourceToSet==currentSource)
+      {
+          LoggerD("Source already set");
+      }
+      else
+      {
+          LoggerD("Set function");
+          ret = pSourceControl->SetSource(sourceToSet);
+          if (ret < 1) {
+              LoggerE("Failed to set source: %d", ret);
+          }
+      }
+  }
+}
+
+void TVWindowInstance::SetSourceResponse(const std::shared_ptr<picojson::value>& response, const std::string& videoSourceName,
+                                         const unsigned long videoSourceNumber, const ESource sourceToSet, const double callback_id)
+{
+  LoggerD("Setting source response");
+
+  ISourceControl* pSourceControl;
+
+  picojson::object& obj = response->get<picojson::object>();
+
+  common::PlatformResult res = CreateSourceControl(&pSourceControl);
+  if(res.IsError())
+  {
+      ReportError(res, &obj);
+      Instance::PostMessage(this, response->serialize().c_str());
+      return;
+  }
+
+  ESource currentSource = SOURCE_TYPE_UNDEFINED;
+  int ret = pSourceControl->GetCurrentSourceInfo(currentSource);
+    if (ret <1 ) {
+      LoggerE("Failed to get current source info: %d", ret);
+    }
+
+    obj.insert(std::make_pair("type", picojson::value( videoSourceName )));
+    obj.insert(std::make_pair("number", picojson::value(static_cast<double>(videoSourceNumber))));
+    obj.insert(std::make_pair("callbackId", picojson::value{static_cast<double>(callback_id)}));
+
+  if(sourceToSet==currentSource)
+  {
+    ReportSuccess(obj);
+    Instance::PostMessage(this, response->serialize().c_str());
+  }
+  else
+  {
+      ReportError(common::PlatformResult(common::ErrorCode::UNKNOWN_ERR,"Failed to set source"), &obj);
+      Instance::PostMessage(this, response->serialize().c_str());
+  }
+}
+
+
+common::PlatformResult TVWindowInstance::CreateSourceControl(ISourceControl** pSourceControl)
+{
+  int ret = TVServiceAPI::CreateSourceControl(PROFILE_TYPE_MAIN, 0, pSourceControl);
+  if (0 != ret)
+  {
+      LoggerE("Failed to create source control: %d", ret);
+      return common::PlatformResult(common::ErrorCode::UNKNOWN_ERR,"Failed to set source");
+  }
+  return common::PlatformResult(common::ErrorCode::NO_ERROR, "");
+}
+
+void TVWindowInstance::GetVideoResolution(const picojson::value& args,
+  picojson::object& out) {
+  LoggerD("Entered");
+
+  TSResolution resolution;
+  common::PlatformResult ret =
+    TVWindowManager::getInstance().GetResolution(resolution);
+  if (ret.IsError()) {
+    ReportError(ret, &out);
+    return;
+  }
+  picojson::value::object dict;
+  dict["aspectRatio"] = EAspectratioTypeToJsonValue(resolution.aspectratio);
+  if (dict["aspectRatio"].is<picojson::null>()) {
+    common::PlatformResult error(common::ErrorCode::UNKNOWN_ERR,
+      "Unsupported aspect ratio");
+    ReportError(error, &out);
+    return;
+  }
+  dict["width"] = picojson::value(static_cast<double>(resolution.horizontal));
+  dict["height"] = picojson::value(static_cast<double>(resolution.vertical));
+  dict["frequency"] = picojson::value(static_cast<double>(resolution.frequency));
+  picojson::value result(dict);
+  ReportSuccess(result, out);
+}
+
+}  // namespace tvwindow
+}  // namespace extension
+
diff --git a/webWidgetTCT_device/src/tvwindow/tvwindow_instance.h b/webWidgetTCT_device/src/tvwindow/tvwindow_instance.h
new file mode 100755 (executable)
index 0000000..f3b19f9
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2015 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 SRC_TVWINDOW_TVWINDOW_INSTANCE_H_
+#define SRC_TVWINDOW_TVWINDOW_INSTANCE_H_
+
+#include <string>
+
+#include "common/extension.h"
+#include "common/picojson.h"
+#include "common/tvsapi_subscribe_helper.h"
+
+#include "tvwindow/tvwindow_extension.h"
+
+namespace extension {
+namespace tvwindow {
+
+class TVWindowInstance : public common::ParsedInstance,
+    public common::TvsSignalListener
+{
+ public:
+  explicit TVWindowInstance(TVWindowExtension const& extension);
+  virtual ~TVWindowInstance();
+
+ private:
+  void IsSourceActive(const picojson::value& args, picojson::object& out);
+  void GetScreenDimension(const picojson::value& args, picojson::object& out);
+  virtual void OnSignal(ESignalType type, TSSignalData data);
+  bool m_tvsApiEnabled;
+  void GetSource(const picojson::value& args, picojson::object& out);
+  void SetSource(const picojson::value& args,picojson::object& out);
+  bool CheckExists(const picojson::value& args, std::string name, picojson::object& out,TVWindowInstance * inst);
+  void SetSourceWork(const std::shared_ptr<picojson::value>& response, const ESource sourceToSet);
+  void SetSourceResponse(const std::shared_ptr<picojson::value>& response, const std::string& videoSourceName,
+                         const unsigned long videoSourceNumber, const ESource sourceToSet, const double callback_id);
+  common::PlatformResult CreateSourceControl(ISourceControl** pSourceControl);
+  void GetVideoResolution(const picojson::value& args, picojson::object& out);
+};
+
+
+}  // namespace tvwindow
+}  // namespace extension
+
+#endif  // SRC_TVWINDOW_TVWINDOW_INSTANCE_H_
diff --git a/webWidgetTCT_device/src/tvwindow/tvwindow_manager.cc b/webWidgetTCT_device/src/tvwindow/tvwindow_manager.cc
new file mode 100755 (executable)
index 0000000..d7d4210
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2015 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 <TVServiceAPI.h>
+#include "tvwindow/tvwindow_manager.h"
+
+namespace extension {
+namespace tvwindow {
+
+TVWindowManager::TVWindowManager() {
+  LoggerD("Enter");
+}
+
+TVWindowManager& TVWindowManager::getInstance() {
+  static TVWindowManager manager;
+  return manager;
+}
+
+bool TVWindowManager::IsCurrentSourceTV() {
+  ISourceControl* control;
+  int ret = TVServiceAPI::CreateSourceControl(PROFILE_TYPE_MAIN, DEFAULT_SCREEN_ID, &control);
+  if (ret != 0) {
+    LoggerW("Failed to retrieve source control");
+    return false;
+  }
+  ESource source = SOURCE_TYPE_UNDEFINED;
+  control->GetCurrentSourceInfo(source);
+  LoggerD("Current source: %d", source);
+  return source == SOURCE_TYPE_TV;
+}
+
+bool TVWindowManager::IsSourceActive() {
+  ISourceControl* control;
+  int ret = TVServiceAPI::CreateSourceControl(PROFILE_TYPE_MAIN, DEFAULT_SCREEN_ID, &control);
+  if (ret != 0) {
+    LoggerW("Failed to retrieve source control");
+    return false;
+  }
+  bool isActive = false;
+  control->IsActive(isActive);
+  LoggerD("Source active: %d", isActive);
+  return isActive;
+}
+
+common::PlatformResult TVWindowManager::GetResolution(TSResolution& resolution) {
+  LoggerD("Entered");
+
+  IAVControl* control;
+  int ret = TVServiceAPI::CreateAVControl(PROFILE_TYPE_MAIN, 0, &control);
+  if (ret != 0) {
+    LoggerE("Failed to create AV Control: %d", ret);
+    return common::PlatformResult(common::ErrorCode::UNKNOWN_ERR,
+        "Failed to get video resolution");
+  }
+
+  EResolution enumRes;
+  ret = control->GetResolution(enumRes, resolution);
+  if (ret != 0) {
+    LoggerE("Failed to get video resolution: %d", ret);
+    return common::PlatformResult(common::ErrorCode::UNKNOWN_ERR,
+        "Failed to get video resolution");
+  }
+  return common::PlatformResult(common::ErrorCode::NO_ERROR);
+}
+
+}  // namespace tvwindow
+}  // namespace extension
diff --git a/webWidgetTCT_device/src/tvwindow/tvwindow_manager.h b/webWidgetTCT_device/src/tvwindow/tvwindow_manager.h
new file mode 100755 (executable)
index 0000000..bee466d
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2015 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 SRC_TVWINDOW_TVWINDOW_MANAGER_H_
+#define SRC_TVWINDOW_TVWINDOW_MANAGER_H_
+
+#include "common/logger.h"
+#include "common/platform_result.h"
+#include <AVControlDataType.h>
+
+namespace extension {
+namespace tvwindow {
+
+class TVWindowManager {
+ public:
+  static TVWindowManager& getInstance();
+  bool IsCurrentSourceTV();
+  bool IsSourceActive();
+  common::PlatformResult GetResolution(TSResolution &resolution);
+ private:
+  TVWindowManager();
+  // Not copyable, assignable, movable
+  TVWindowManager(TVWindowManager const&);
+  void operator=(TVWindowManager const&);
+  TVWindowManager(TVWindowManager &&);
+};
+
+}  // namespace tvwindow
+}  // namespace extension
+
+#endif  // SRC_TVWINDOW_TVWINDOW_MANAGER_H_
diff --git a/webWidgetTCT_device/src/utils/utils.gyp b/webWidgetTCT_device/src/utils/utils.gyp
new file mode 100755 (executable)
index 0000000..8d6e16a
--- /dev/null
@@ -0,0 +1,33 @@
+{
+  'includes':[
+    '../common/common.gypi',
+  ],
+  'targets': [
+    {
+      'target_name': 'tizen_utils',
+      'type': 'loadable_module',
+      'dependencies': [
+        '../common/common.gyp:tizen_common',
+      ],
+      'sources': [
+        'utils_api.js',
+        'utils_extension.cc',
+        'utils_extension.h',
+        'utils_instance.cc',
+        'utils_instance.h',
+      ],
+      'conditions': [
+        ['tizen == 1', {
+          'variables': {
+            'packages': [
+              'capi-appfw-package-manager',
+              'capi-appfw-app-manager',
+              'pkgmgr-info',
+              'pkgmgr'
+            ]
+          },
+        }],
+      ],
+    },
+  ],
+}
diff --git a/webWidgetTCT_device/src/utils/utils_api.js b/webWidgetTCT_device/src/utils/utils_api.js
new file mode 100755 (executable)
index 0000000..49b753a
--- /dev/null
@@ -0,0 +1,1602 @@
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var _global = {};
+if (typeof window != 'undefined') {
+  _global = window;
+}
+else if (typeof global != 'undefiend') {
+  _global = global;
+}
+
+/**
+ * @deprecated Used only by validateArguments()
+ */
+var signature_to_type = {
+  'n': 'number',
+  'f': 'function',
+  'b': 'boolean',
+  's': 'string',
+  'o': 'object'
+};
+
+var DateConverter = function() {};
+
+DateConverter.prototype.toTZDate = function(v, isAllDay) {
+  if (typeof v === 'number') {
+    v = {
+      UTCTimestamp: v
+        };
+    isAllDay = false;
+  }
+
+  if (!(v instanceof _global.Object)) {
+    return v;
+  }
+
+  if (isAllDay) {
+    return new tizen.TZDate(v.year, v.month - 1, v.day,
+        null, null, null, null, v.timezone || null);
+  } else {
+    return new tizen.TZDate(new Date(v.UTCTimestamp * 1000), 'UTC').toLocalTimezone();
+  }
+};
+
+DateConverter.prototype.fromTZDate = function(v) {
+  if (!tizen.TZDate || !(v instanceof tizen.TZDate)) {
+    return v;
+  }
+
+  var timestamp = Date.UTC(v.date_.getUTCFullYear(),
+                           v.date_.getUTCMonth(),
+                           v.date_.getUTCDate(),
+                           v.date_.getUTCHours(),
+                           v.date_.getUTCMinutes(),
+                           v.date_.getUTCSeconds(),
+                           v.date_.getUTCMilliseconds()) / 1000;
+
+  return {
+    year: v.getFullYear(),
+    month: v.getMonth(),
+    day: v.getDate(),
+    timezone: v.getTimezone(),
+    UTCTimestamp: timestamp
+  };
+
+};
+
+var _dateConverter = new DateConverter();
+
+/** @constructor */
+function Utils() {
+  var privilege = {
+    ACCOUNT_READ: 'http://tizen.org/privilege/account.read',
+    ACCOUNT_WRITE: 'http://tizen.org/privilege/account.write',
+    ALARM: 'http://tizen.org/privilege/alarm',
+    APPLICATION_INFO: 'http://tizen.org/privilege/application.info',
+    APPLICATION_LAUNCH: 'http://tizen.org/privilege/application.launch',
+    APPMANAGER_CERTIFICATE: 'http://tizen.org/privilege/appmanager.certificate',
+    APPMANAGER_KILL: 'http://tizen.org/privilege/appmanager.kill',
+    BLUETOOTH_ADMIN: 'http://tizen.org/privilege/bluetooth.admin',
+    BLUETOOTH_GAP: 'http://tizen.org/privilege/bluetooth.gap',
+    BLUETOOTH_HEALTH: 'http://tizen.org/privilege/bluetooth.health',
+    BLUETOOTH_SPP: 'http://tizen.org/privilege/bluetooth.spp',
+    BLUETOOTHMANAGER: 'http://tizen.org/privilege/bluetoothmanager',
+    BLUETOOTH: 'http://tizen.org/privilege/bluetooth',
+    BOOKMARK_READ: 'http://tizen.org/privilege/bookmark.read',
+    BOOKMARK_WRITE: 'http://tizen.org/privilege/bookmark.write',
+    CALENDAR_READ: 'http://tizen.org/privilege/calendar.read',
+    CALENDAR_WRITE: 'http://tizen.org/privilege/calendar.write',
+    CALLHISTORY_READ: 'http://tizen.org/privilege/callhistory.read',
+    CALLHISTORY_WRITE: 'http://tizen.org/privilege/callhistory.write',
+    CONTACT_READ: 'http://tizen.org/privilege/contact.read',
+    CONTACT_WRITE: 'http://tizen.org/privilege/contact.write',
+    CONTENT_READ: 'http://tizen.org/privilege/content.read',
+    CONTENT_WRITE: 'http://tizen.org/privilege/content.write',
+    DATACONTROL_CONSUMER: 'http://tizen.org/privilege/datacontrol.consumer',
+    DATASYNC: 'http://tizen.org/privilege/datasync',
+    DOWNLOAD: 'http://tizen.org/privilege/download',
+    FILESYSTEM_READ: 'http://tizen.org/privilege/filesystem.read',
+    FILESYSTEM_WRITE: 'http://tizen.org/privilege/filesystem.write',
+    HEALTHINFO: 'http://tizen.org/privilege/healthinfo',
+    INTERNET: 'http://tizen.org/privilege/internet',
+    KEYMANAGER: 'http://tizen.org/privilege/keymanager',
+    LED: 'http://tizen.org/privilege/led',
+    LOCATION: 'http://tizen.org/privilege/location',
+    MEDIACONTROLLER_SERVER: 'http://tizen.org/privilege/mediacontroller.server',
+    MEDIACONTROLLER_CLIENT: 'http://tizen.org/privilege/mediacontroller.client',
+    MESSAGING_READ: 'http://tizen.org/privilege/messaging.read',
+    MESSAGING_WRITE: 'http://tizen.org/privilege/messaging.write',
+    NETWORKBEARERSELECTION: 'http://tizen.org/privilege/networkbearerselection',
+    NFC_ADMIN: 'http://tizen.org/privilege/nfc.admin',
+    NFC_CARDEMULATION: 'http://tizen.org/privilege/nfc.cardemulation',
+    NFC_COMMON: 'http://tizen.org/privilege/nfc.common',
+    NFC_P2P: 'http://tizen.org/privilege/nfc.p2p',
+    NFC_TAG: 'http://tizen.org/privilege/nfc.tag',
+    NOTIFICATION: 'http://tizen.org/privilege/notification',
+    PACKAGE_INFO: 'http://tizen.org/privilege/package.info',
+    PACKAGEMANAGER_INSTALL: 'http://tizen.org/privilege/packagemanager.install',
+    POWER: 'http://tizen.org/privilege/power',
+    PUSH: 'http://tizen.org/privilege/push',
+    SECUREELEMENT: 'http://tizen.org/privilege/secureelement',
+    SETTING: 'http://tizen.org/privilege/setting',
+    SYSTEM: 'http://tizen.org/privilege/system',
+    SYSTEMMANAGER: 'http://tizen.org/privilege/systemmanager',
+    TELEPHONY: 'http://tizen.org/privilege/telephony',
+    TV_CHANNEL: 'http://tizen.org/privilege/tv.channel',
+    TV_WINDOW: 'http://tizen.org/privilege/tv.window',
+    TV_INFO: 'http://tizen.org/privilege/tv.info',
+    VOLUME_SET: 'http://tizen.org/privilege/volume.set',
+    TV_INPUT_DEVICE: 'http://tizen.org/privilege/tv.inputdevice'
+  };
+  Object.freeze(privilege);
+
+  Object.defineProperty(this, 'privilege', {
+    value: privilege,
+    writable: false,
+    enumerable: true,
+    configurable: false
+  });
+}
+
+Utils.prototype.repackFilter = function(filter) {
+  if (filter instanceof tizen.AttributeFilter) {
+    return {
+      filterType: 'AttributeFilter',
+      attributeName: filter.attributeName,
+      matchFlag: filter.matchFlag,
+      matchValue: _dateConverter.fromTZDate(filter.matchValue)
+    };
+  }
+  if (filter instanceof tizen.AttributeRangeFilter) {
+    return {
+      filterType: 'AttributeRangeFilter',
+      attributeName: filter.attributeName,
+      initialValue: _dateConverter.fromTZDate(filter.initialValue),
+      endValue: _dateConverter.fromTZDate(filter.endValue)
+    };
+  }
+  if (filter instanceof tizen.CompositeFilter) {
+    var _f = [];
+    var filters = filter.filters;
+
+    for (var i = 0; i < filters.length; ++i) {
+      _f.push(this.repackFilter(filters[i]));
+    }
+
+    return {
+      filterType: 'CompositeFilter',
+      type: filter.type,
+      filters: _f
+    };
+  }
+
+  return null;
+};
+
+/**
+ * @deprecated You should use xwalk.utils.validator.validateMethod() instead.
+ */
+Utils.prototype.validateArguments = function(signature, args) {
+  var full_args = Array.prototype.slice.call(args);
+
+  // After '?' everything is optional.
+  var mandatory_len = signature.indexOf('?') === -1 ? signature.length : signature.indexOf('?');
+
+  if (full_args.length < mandatory_len)
+    return false;
+
+  // Mandatory arguments.
+  for (var i = 0; i < mandatory_len; i++) {
+    if (typeof full_args[i] !== signature_to_type[signature[i]] || full_args[i] === null)
+      return false;
+  }
+
+  // Optional args may be null.
+  for (var i = mandatory_len; i < full_args.length && i < signature.length - 1; i++) {
+    if (full_args[i] !== null && typeof full_args[i] !== signature_to_type[signature[i + 1]])
+      return false;
+  }
+
+  return true;
+};
+
+Utils.prototype.validateObject = function(object, signature, attributes) {
+  for (var i = 0; i < signature.length; i++) {
+    if (object.hasOwnProperty(attributes[i]) &&
+        typeof object[attributes[i]] !== signature_to_type[signature[i]]) {
+      return false;
+    }
+  }
+
+  return true;
+};
+
+Utils.prototype.getPkgApiVersion = function() {
+  var result = native_.callSync('Utils_getPkgApiVersion');
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+  return native_.getResultObject(result);
+};
+
+Utils.prototype.checkPrivilegeAccess = function(privilege) {
+  var result = native_.callSync('Utils_checkPrivilegeAccess', {
+    privilege : _toString(privilege),
+  });
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+};
+
+Utils.prototype.checkPrivilegeAccess4Ver = function(new_ver, new_priv, old_priv) {
+  var app_ver = this.getPkgApiVersion();
+
+  var arr_new_ver = new_ver.split(".");
+  var arr_app_ver = app_ver.split(".");
+  var num_new;
+  var num_app;
+  var sel = 0;
+
+  var i;
+  var length = Math.min(arr_new_ver.length, arr_app_ver.length);
+  for (i = 0; i < length; i++) {
+    num_new = parseInt(arr_new_ver[i]);
+    num_app = parseInt(arr_app_ver[i]);
+    if (num_app < num_new) {
+      sel = 1;
+      break;
+    } else if (num_app > num_new) {
+      sel = -1;
+      break;
+    }
+  }
+
+  if (sel == 0 && arr_new_ver.length > arr_app_ver.length) {
+    sel = 1;
+  }
+
+  if (sel != 1) {
+    this.checkPrivilegeAccess(new_priv);
+  } else if (old_priv != undefined) {
+    this.checkPrivilegeAccess(old_priv);
+  }
+}
+
+Utils.prototype.checkBackwardCompabilityPrivilegeAccess = function(current_privilege, previous_privilege) {
+  var result = native_.callSync('Utils_checkBackwardCompabilityPrivilegeAccess', {
+    current_privilege : _toString(current_privilege),
+    previous_privilege : _toString(previous_privilege),
+  });
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+};
+
+/////////////////////////////////////////////////////////////////////////////
+/** @constructor */
+var Type = function() {};
+
+Type.prototype.isBoolean = function(obj) {
+  return typeof obj === 'boolean';
+};
+
+Type.prototype.isObject = function(obj) {
+  return (null !== obj && typeof obj === 'object' && !this.isArray(obj));
+};
+
+Type.prototype.isArray = function(obj) {
+  return Array.isArray(obj);
+};
+
+Type.prototype.isFunction = function(obj) {
+  return typeof obj === 'function';
+};
+
+Type.prototype.isNumber = function(obj) {
+  return typeof obj === 'number';
+};
+
+Type.prototype.isString = function(obj) {
+  return typeof obj === 'string';
+};
+
+Type.prototype.isDate = function(obj) {
+  return obj instanceof Date;
+};
+
+Type.prototype.isNull = function(obj) {
+  return obj === null;
+};
+
+Type.prototype.isNullOrUndefined = function(obj) {
+  return (obj === null || obj === undefined);
+};
+
+Type.prototype.isUndefined = function(obj) {
+  return obj === void 0;
+};
+
+Type.prototype.isA = function(obj, type) {
+  var clas = Object.prototype.toString.call(obj).slice(8, -1);
+  return (obj !== undefined) && (obj !== null) && (clas === type);
+};
+
+Type.prototype.isEmptyObject = function(obj) {
+  for (var property in obj) {
+    if (obj.hasOwnProperty(property)) {
+      return false;
+    }
+  }
+  return true;
+};
+
+Type.prototype.hasProperty = function(obj, prop) {
+  return prop in obj;
+};
+
+Type.prototype.arrayContains = function(arr, value) {
+  return (arr.indexOf(value) > -1);
+};
+
+Type.prototype.getValues = function(obj) {
+  var ret = [];
+  for (var key in obj) {
+    if (obj.hasOwnProperty(key)) {
+      ret.push(obj[key]);
+    }
+  }
+  return ret;
+};
+
+var _type = new Type();
+
+
+
+/////////////////////////////////////////////////////////////////////////////
+/** @constructor */
+var Converter = function() {};
+
+function _nullableGeneric(func, nullable, val) {
+  if (_type.isNull(val) && nullable === true) {
+    return val;
+  } else {
+    return func.apply(null, [].slice.call(arguments, 2));
+  }
+}
+
+function _toBoolean(val) {
+  return Boolean(val);
+}
+
+Converter.prototype.toBoolean = function(val, nullable) {
+  return _nullableGeneric(_toBoolean, nullable, val);
+};
+
+function _toLong(val) {
+  var ret = parseInt(val, 10);
+  return isNaN(ret) ? (val === true ? 1 : 0) : ret;
+}
+
+Converter.prototype.toLong = function(val, nullable) {
+  return _nullableGeneric(_toLong, nullable, val);
+};
+
+function _toLongLong(val) {
+  // According to WebIDL specification this will not be a precise representation
+  // of requested val. We're converting the val to signed long and then pass it
+  // to C++ to get the value in required range.
+  return native_.getResultObject(native_.callSync('Utils_toLongLong', {
+    n : _toLong(val)
+  }));
+}
+
+Converter.prototype.toLongLong = function(val, nullable) {
+  return _nullableGeneric(_toLongLong, nullable, val);
+};
+
+function _toUnsignedLong(val) {
+  return _toLong(val) >>> 0;
+}
+
+Converter.prototype.toUnsignedLong = function(val, nullable) {
+  return _nullableGeneric(_toUnsignedLong, nullable, val);
+};
+
+function _toUnsignedLongLong(val) {
+  // According to WebIDL specification this will not be a precise representation
+  // of requested val. We're converting the val to signed long and then pass it
+  // to C++ to get the value in required range.
+  return native_.getResultObject(native_.callSync('Utils_toUnsignedLongLong', {
+    n : _toLong(val)
+  }));
+}
+
+Converter.prototype.toUnsignedLongLong = function(val, nullable) {
+  return _nullableGeneric(_toUnsignedLongLong, nullable, val);
+};
+
+function _toByte(val) {
+  return ((_toLong(val) + 128) & 0xFF) - 128;
+}
+
+Converter.prototype.toByte = function(val, nullable) {
+  return _nullableGeneric(_toByte, nullable, val);
+};
+
+function _toOctet(val) {
+  return _toLong(val) & 0xFF;
+}
+
+Converter.prototype.toOctet = function(val, nullable) {
+  return _nullableGeneric(_toOctet, nullable, val);
+};
+
+function _toDouble(val) {
+  var ret = Number(val);
+  if (isNaN(ret) || !isFinite(ret)) {
+    throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR,
+        'Cannot convert ' + String(val) + ' to double.');
+  }
+  return ret;
+}
+
+Converter.prototype.toDouble = function(val, nullable) {
+  return _nullableGeneric(_toDouble, nullable, val);
+};
+
+function _toString(val) {
+  return String(val);
+}
+
+Converter.prototype.toString = function(val, nullable) {
+  return _nullableGeneric(_toString, nullable, val);
+};
+
+function _toPlatformObject(val, types) {
+  var v;
+  var t;
+  if (_type.isArray(val)) {
+    v = val;
+  } else {
+    v = [val];
+  }
+
+  if (_type.isArray(types)) {
+    t = types;
+  } else {
+    t = [types];
+  }
+  var match = false;
+  for (var i = 0; i < t.length; ++i) {
+    for (var j = 0; j < v.length; ++j) {
+      match = match || (v[j] instanceof t[i]);
+    }
+  }
+  if (match) {
+    return val;
+  }
+
+  throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR,
+      'Cannot convert ' + String(val) + ' to ' + String(t[0].name) + '.');
+}
+
+Converter.prototype.toPlatformObject = function(val, types, nullable) {
+  return _nullableGeneric(_toPlatformObject, nullable, val, types);
+};
+
+function _toFunction(val) {
+  if (_type.isFunction(val)) {
+    return val;
+  }
+
+  throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR,
+      'Cannot convert ' + String(val) + ' to function.');
+}
+
+Converter.prototype.toFunction = function(val, nullable) {
+  return _nullableGeneric(_toFunction, nullable, val);
+};
+
+function _toArray(val) {
+  if (_type.isArray(val)) {
+    return val;
+  }
+
+  throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR,
+      'Cannot convert ' + String(val) + ' to array.');
+}
+
+Converter.prototype.toArray = function(val, nullable) {
+  return _nullableGeneric(_toArray, nullable, val);
+};
+
+function _toDictionary(val) {
+  if (_type.isObject(val) || _type.isFunction(val)) {
+    return val;
+  }
+
+  throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR,
+      'Cannot convert ' + String(val) + ' to dictionary.');
+}
+
+Converter.prototype.toDictionary = function(val, nullable) {
+  return _nullableGeneric(_toDictionary, nullable, val);
+};
+
+function _toEnum(val, e) {
+  var v = _toString(val);
+  if (_type.arrayContains(e, v)) {
+    return v;
+  }
+
+  throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR,
+      'Cannot convert ' + v + ' to enum.');
+}
+
+Converter.prototype.toEnum = function(val, e, nullable) {
+  return _nullableGeneric(_toEnum, nullable, val, e);
+};
+
+var _converter = new Converter();
+
+/////////////////////////////////////////////////////////////////////////////
+/** @constructor */
+var Validator = function() {
+  this.Types = {
+    BOOLEAN: 'BOOLEAN',
+    LONG: 'LONG',
+    LONG_LONG: 'LONG_LONG',
+    UNSIGNED_LONG: 'UNSIGNED_LONG',
+    UNSIGNED_LONG_LONG: 'UNSIGNED_LONG_LONG',
+    BYTE: 'BYTE',
+    OCTET: 'OCTET',
+    DOUBLE: 'DOUBLE',
+    STRING: 'STRING',
+    FUNCTION: 'FUNCTION',
+    DICTIONARY: 'DICTIONARY',
+    PLATFORM_OBJECT: 'PLATFORM_OBJECT',
+    LISTENER: 'LISTENER',
+    ARRAY: 'ARRAY',
+    ENUM: 'ENUM',
+    FILE_REFERENCE: 'FILE_REFERENCE'
+  };
+};
+
+
+/**
+ * Verifies if arguments passed to function are valid.
+ *
+ * Description of expected arguments.
+ * This is an array of objects, each object represents one argument.
+ * First object in this array describes first argument, second object describes second
+ * argument, and so on.
+ * Object describing an argument needs to have two properties:
+ *   - name - name of the argument,
+ *   - type - type of the argument, only values specified in Validator.Types are allowed.
+ * Other properties, which may appear:
+ *   - optional - if set to value which evaluates to true, argument is optional
+ *   - nullable - if set to to true, argument may be set to null
+ *   - values - required in case of some objects, value depends on type
+ *   - validator - function which accepts a single parameter and returns true or false;
+ *                 if this property is present, this function will be executed,
+ *                 argument converted to expected type is going to be passed to this function
+ *
+ * @param {Array} a - arguments of a method
+ * @param {Array} d - description of expected arguments
+ * @return {Object} which holds all available arguments.
+ * @throws TypeMismatchError if arguments are not valid
+ *
+ * @code
+ * [
+ *   {
+ *     name: 'first',
+ *     type: 'aType'
+ *   }
+ * ]
+ * @code
+ * [
+ *   {
+ *     name: 'first',
+ *     type: 'aType',
+ *     optional: true
+ *   }
+ * ]
+ * @code
+ * [
+ *   {
+ *     name: 'first',
+ *     type: 'aType',
+ *     nullable: true
+ *   }
+ * ]
+ * @code
+ * [
+ *   {
+ *     name: 'first',
+ *     type: 'aType',
+ *     optional: true,
+ *     nullable: true
+ *   }
+ * ]
+ * @code
+ * [
+ *   {
+ *     name: 'first',
+ *     type: Validator.Types.PLATFORM_OBJECT,
+ *     values: ApplicationControl // type of platform object
+ *   }
+ * ]
+ * @code
+ * [
+ *   {
+ *     name: 'first',
+ *     type: Validator.Types.PLATFORM_OBJECT,
+ *     values: [Alarm, AlarmRelative, AlarmAbsolute] // accepted types
+ *   }
+ * ]
+ * @code
+ * [
+ *   {
+ *     name: 'first',
+ *     type: Validator.Types.LISTENER,
+ *     values: ['onsuccess', 'onfailure'] // array of callbacks' names
+ *   }
+ * ]
+ * @code
+ * [
+ *   {
+ *     name: 'first',
+ *     type: Validator.Types.ARRAY,
+ *     values: ApplicationControlData // type of each element in array,
+ *                                    // tested with instanceof
+ *   }
+ * ]
+ * @code
+ * [
+ *   {
+ *     name: 'first',
+ *     type: Validator.Types.ARRAY,
+ *     values: Validator.Types.DOUBLE // converts elements, only primitive types are supported
+ *   }
+ * ]
+ * @code
+ * [
+ *   {
+ *     name: 'first',
+ *     type: Validator.Types.ENUM,
+ *     values: ['SCREEN_DIM', 'SCREEN_NORMAL', 'CPU_AWAKE'] // array of allowed values
+ *   }
+ * ]
+ */
+Validator.prototype.validateArgs = function(a, d) {
+  var args = {has: {}};
+
+  for (var i = 0; i < d.length; ++i) {
+    var name = d[i].name;
+    args.has[name] = (i < a.length);
+
+    var optional = d[i].optional;
+    var nullable = d[i].nullable;
+    var val = a[i];
+
+    if (args.has[name] || !optional) {
+      var type = d[i].type;
+      var values = d[i].values;
+
+      switch (type) {
+        case this.Types.BOOLEAN:
+          val = _converter.toBoolean(val, nullable);
+          break;
+
+        case this.Types.LONG:
+          val = _converter.toLong(val, nullable);
+          break;
+
+        case this.Types.LONG_LONG:
+          val = _converter.toLongLong(val, nullable);
+          break;
+
+        case this.Types.UNSIGNED_LONG:
+          val = _converter.toUnsignedLong(val, nullable);
+          break;
+
+        case this.Types.UNSIGNED_LONG_LONG:
+          val = _converter.toUnsignedLongLong(val, nullable);
+          break;
+
+        case this.Types.BYTE:
+          val = _converter.toByte(val, nullable);
+          break;
+
+        case this.Types.OCTET:
+          val = _converter.toOctet(val, nullable);
+          break;
+
+        case this.Types.DOUBLE:
+          val = _converter.toDouble(val, nullable);
+          break;
+
+        case this.Types.STRING:
+          val = _converter.toString(val, nullable);
+          break;
+
+        case this.Types.FUNCTION:
+          val = _converter.toFunction(val, nullable);
+          break;
+
+        case this.Types.DICTIONARY:
+          val = _converter.toDictionary(val, nullable);
+          break;
+
+        case this.Types.PLATFORM_OBJECT:
+          val = _converter.toPlatformObject(val, values, nullable);
+          break;
+
+        case this.Types.LISTENER:
+          if (_type.isNull(val)) {
+            if (!nullable) {
+              throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR,
+                  'Argument "' + name + '" cannot be null.');
+            }
+          } else {
+            if (!_type.isObject(val)) {
+              throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR,
+                  'Argument "' + name + '" should be an object.');
+            }
+            for (var ii = 0; ii < values.length; ++ii) {
+              if (_type.hasProperty(val, values[ii])) {
+                val[values[ii]] = _converter.toFunction(val[values[ii]], false);
+              }
+            }
+          }
+          break;
+
+        case this.Types.ARRAY:
+          val = _converter.toArray(val, nullable);
+          if (!_type.isNull(val) && values) {
+            var func;
+
+            switch (values) {
+              case this.Types.BOOLEAN:
+                func = _converter.toBoolean;
+                break;
+
+              case this.Types.LONG:
+                func = _converter.toLong;
+                break;
+
+              case this.Types.LONG_LONG:
+                func = _converter.toLongLong;
+                break;
+
+              case this.Types.UNSIGNED_LONG:
+                func = _converter.toUnsignedLong;
+                break;
+
+              case this.Types.UNSIGNED_LONG_LONG:
+                func = _converter.toUnsignedLongLong;
+                break;
+
+              case this.Types.BYTE:
+                func = _converter.toByte;
+                break;
+
+              case this.Types.OCTET:
+                func = _converter.toOctet;
+                break;
+
+              case this.Types.DOUBLE:
+                func = _converter.toDouble;
+                break;
+
+              case this.Types.STRING:
+                func = _converter.toString;
+                break;
+
+              default:
+                func = function(val) {
+                  if (!(val instanceof values)) {
+                    throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR,
+                        'Items of array "' + name + '" should be of type: ' + values + '.');
+                  }
+                  return val;
+                };
+            }
+
+            for (var j = 0; j < val.length; ++j) {
+              val[j] = func(val[j]);
+            }
+          }
+          break;
+
+        case this.Types.ENUM:
+          val = _converter.toEnum(val, values, nullable);
+          break;
+
+        case this.Types.FILE_REFERENCE:
+          if (_type.isObject(val) && 'File' === val.constructor.name && val.fullPath) {
+            val = val.fullPath;
+          }
+          val = _converter.toString(val, nullable);
+          break;
+
+        default:
+          throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR,
+              'Unknown type: "' + type + '".');
+      }
+
+      var _validator = d[i].validator;
+
+      if (_type.isFunction(_validator) && !_validator(val)) {
+        throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR,
+            'Argument "' + name + '" did not pass additional validation.');
+      }
+
+      args[name] = val;
+    }
+  }
+
+  return args;
+};
+
+
+/**
+ * @deprecated Use validateArgs() instead.
+ */
+Validator.prototype.validateMethod = function(a, d) {
+  return this.validateArgs(a, d);
+};
+
+
+/**
+ * Use this helper to ensure that constructor is invoked by "new" operator.
+ *
+ * @param {Object} obj
+ * @param {Function} instance
+ */
+Validator.prototype.isConstructorCall = function(obj, instance) {
+  if (!(obj instanceof instance) || obj._previouslyConstructed) {
+    // There is no TypeError exception in Tizen 2.3.0 API spec but it's required by current TCTs.
+    // For Tizen compliance it's wrapped into WebAPIException.
+    throw new WebAPIException('TypeError', 'Constructor cannot be called as function.');
+  }
+
+  Object.defineProperty(obj, '_previouslyConstructed', {
+    value: true,
+    writable: false,
+    enumerable: false
+  });
+};
+
+
+/**
+ * @deprecated Use isConstructorCall() instead.
+ */
+Validator.prototype.validateConstructorCall = function(obj, instance) {
+  this.isConstructorCall(obj, instance);
+};
+
+var _validator = new Validator();
+
+
+
+/////////////////////////////////////////////////////////////////////////////
+/** @constructor */
+var NativeManager = function(extension) {
+
+  /**
+   * @type {string}
+   * @const
+   */
+  this.CALLBACK_ID_KEY = 'callbackId';
+
+  /**
+   * @type {string}
+   * @const
+   */
+  this.LISTENER_ID_KEY = 'listenerId';
+
+  /**
+   * @type {Object}
+   * @private
+   */
+  var extension_ = extension;
+
+  /**
+   * @type {number}
+   * @private
+   */
+  var replyId_ = 0;
+
+  /**
+   * Map of async reply callbacks.
+   *
+   * @type {Object.<number, function>}
+   * @protected
+   */
+  this.callbacks_ = {};
+
+  /**
+   * Map of registered listeners.
+   *
+   * @type {Object.<string, function>}
+   * @protected
+   */
+  this.listeners_ = {};
+
+  _validator.isConstructorCall(this, NativeManager);
+
+  // TODO: Remove mockup if WRT implements sendRuntimeMessage
+  // This is temporary mockup!
+  extension.sendRuntimeMessage = extension.sendRuntimeMessage || function() {
+    console.error('Runtime did not implement extension.sendRuntimeMessage!');
+    throw new WebAPIException(WebAPIException.UNKNOWN_ERR,
+        'Runtime did not implement extension.sendRuntimeMessage!');
+  };
+
+  extension.sendRuntimeAsyncMessage = extension.sendRuntimeAsyncMessage || function() {
+    console.error('Runtime did not implement extension.sendRuntimeAsyncMessage!');
+    throw new WebAPIException(WebAPIException.UNKNOWN_ERR,
+        'Runtime did not implement extension.sendRuntimeAsyncMessage!');
+  };
+
+  extension.sendRuntimeSyncMessage = extension.sendRuntimeSyncMessage || function() {
+    console.error('Runtime did not implement extension.sendRuntimeSyncMessage!');
+    throw new WebAPIException(WebAPIException.UNKNOWN_ERR,
+        'Runtime did not implement extension.sendRuntimeSyncMessage!');
+  };
+
+  // check extension prototype
+  if (!extension || !extension.internal ||
+      !_type.isFunction(extension.postMessage) ||
+      !_type.isFunction(extension.internal.sendSyncMessage) ||
+      !_type.isFunction(extension.sendSyncData) ||
+      !_type.isFunction(extension.sendRuntimeMessage) ||
+      !_type.isFunction(extension.sendRuntimeAsyncMessage) ||
+      !_type.isFunction(extension.sendRuntimeSyncMessage) ||
+      !_type.isFunction(extension.setMessageListener)) {
+    throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR,
+                              'Wrong extension object passed');
+  }
+
+  Object.defineProperties(this, {
+    nextReplyId: {
+      get: function() {
+        return ++replyId_;
+      },
+      enumerable: false
+    },
+    extension: {
+      get: function() {
+        return extension_;
+      },
+      enumerable: true
+    }
+  });
+
+  extension_.setMessageListener(function(json) {
+    var msg = JSON.parse(json);
+    var id;
+
+    if (msg.hasOwnProperty(this.CALLBACK_ID_KEY)) {
+      id = msg[this.CALLBACK_ID_KEY];
+      delete msg[this.CALLBACK_ID_KEY];
+
+      if (!_type.isFunction(this.callbacks_[id])) {
+        console.error('Wrong callback identifier. Ignoring message.');
+        return;
+      }
+
+      var f = this.callbacks_[id];
+      setTimeout(function() {
+        try {
+          f(msg);
+        } catch (e) {
+          console.error('########## exception');
+          console.error(e);
+        }
+      }, 0);
+      delete this.callbacks_[id];
+
+      return;
+    }
+
+    if (msg.hasOwnProperty(this.LISTENER_ID_KEY)) {
+      id = msg[this.LISTENER_ID_KEY];
+      delete msg[this.LISTENER_ID_KEY];
+
+      if (!_type.isFunction(this.listeners_[id])) {
+        console.error('Wrong listener identifier ' + id + ' . Ignoring message.');
+        return;
+      }
+
+      var f = this.listeners_[id];
+      setTimeout(function() {
+        try {
+          f(msg);
+        } catch (e) {
+          console.error('########## exception');
+          console.error(e);
+        }
+      }, 0);
+
+      return;
+    }
+
+    console.error('Missing callback or listener identifier. Ignoring message.');
+
+  }.bind(this));
+};
+
+NativeManager.prototype.call = function(cmd, args, callback) {
+  args = args || {};
+
+  var replyId = this.nextReplyId;
+  args[this.CALLBACK_ID_KEY] = replyId;
+  this.callbacks_[replyId] = callback;
+
+  return this.callSync(cmd, args);
+};
+
+NativeManager.prototype.callData = function(cmd, args, chunk, callback) {
+  args = args || {};
+
+  var replyId = this.nextReplyId;
+  args[this.CALLBACK_ID_KEY] = replyId;
+  this.callbacks_[replyId] = callback;
+
+  return this.callSyncData(cmd, args, chunk);
+};
+
+NativeManager.prototype.callSync = function(cmd, args) {
+  var request = JSON.stringify({
+    cmd: cmd,
+    args: args || {}
+  });
+
+  return JSON.parse(this.extension.internal.sendSyncMessage(request));
+};
+
+NativeManager.prototype.callSyncData = function(cmd, args, type, chunk) {
+  if (!type) type = "string";
+  var request = JSON.stringify({
+    cmd: cmd,
+    args: args || {}
+  });
+  var response = this.extension.sendSyncData(request, chunk);
+  response.reply = JSON.parse(response.reply);
+  response.output = this.extension.receiveChunkData(response.chunk_id, type);
+  return response;
+};
+
+NativeManager.prototype.sendRuntimeMessage = function(msg, body) {
+  return this.extension.sendRuntimeMessage(msg, body || '');
+};
+
+NativeManager.prototype.sendRuntimeAsyncMessage = function(msg, body, callback) {
+  var handler = function(response) {
+    if (_type.isFunction(callback)) {
+      var result = {};
+      if ('success' === response.toLowerCase()) {
+        result.status = 'success';
+      } else {
+        result.status = 'error';
+        result.error = new WebAPIException(WebAPIException.UNKNOWN_ERR,
+                                           'Runtime message failure');
+      }
+      callback(result);
+    }
+  };
+  return this.extension.sendRuntimeAsyncMessage(msg, body || '', handler);
+};
+
+NativeManager.prototype.sendRuntimeSyncMessage = function(msg, body) {
+  return this.extension.sendRuntimeSyncMessage(msg, body || '');
+};
+
+NativeManager.prototype.addListener = function(name, callback) {
+  if (!_type.isString(name) || !name.length) {
+    throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR);
+  }
+
+  this.listeners_[name] = callback;
+};
+
+NativeManager.prototype.removeListener = function(name) {
+  if (this.listeners_.hasOwnProperty(name)) {
+    delete this.listeners_[name];
+  }
+};
+
+NativeManager.prototype.isListenerSet = function(name) {
+  return this.listeners_.hasOwnProperty(name);
+};
+
+NativeManager.prototype.isSuccess = function(result) {
+  return (result.status !== 'error');
+};
+
+NativeManager.prototype.isFailure = function(result) {
+  return !this.isSuccess(result);
+};
+
+NativeManager.prototype.getResultObject = function(result) {
+  return result.result;
+};
+
+NativeManager.prototype.getErrorObject = function(result) {
+  return new WebAPIException(result.error);
+};
+
+NativeManager.prototype.callIfPossible = function(callback) {
+  if (!_type.isNullOrUndefined(callback)) {
+    callback.apply(callback, [].slice.call(arguments, 1));
+  }
+};
+
+/*
+ *bridge is a two way communication interface
+ *Example usage:
+ *var bridge = new NativeBridge(extension);
+ *    To send sync method:
+ *    var result = bridge.sync({
+ *        cmd: 'my_cpp_function_symbol',
+ *        args: {
+ *            name: 'My name',
+ *            age: 28
+ *        }
+ *    });
+ *    console.log(result);
+ *
+ *    To send async method and handle response:
+ *    bridge.async({
+ *        cmd: 'my_cpp_function_symbol',
+ *        args: {
+ *            name: 'My name'
+ *        }
+ *    }).then({
+ *        success: function (data) {
+ *            var age = data.age;
+ *            args.successCallback(age);
+ *        },
+ *        error: function (e) {...},
+ *        someCallback: function (data) {...}
+ *    });
+ *bridge.async will add special param to passed data called cid
+ *that param need to be kept and returned with respons
+ *To determine which callback should be invoked, response should
+ *contain "action" param. Value of "action" param indicates name of
+ *triggered callback.
+ *Callbask are removed from listenr by defoult to prevent that behaviour
+ *param "keep" should be assigned to value true
+ *Example of c++ async response:
+ *    Simple succes with data:
+ *    {
+ *        cid: 23,
+ *        action: 'success',
+ *        args: {
+ *            age: 23
+ *        }
+ *    }
+ *    More complicated example:
+ *    {
+ *        cid: 23,
+ *        action: 'progress',
+ *        keep: true,
+ *        args: {
+ *            age: 23
+ *        }
+ *    }
+ */
+var NativeBridge = (function (extension, debug) {
+    debug = !!debug;
+    var Callbacks = (function () {
+        var _collection = {};
+        var _cid = 0;
+        var _next = function () {
+            return (_cid += 1);
+        };
+
+        var CallbackManager = function () {};
+
+        CallbackManager.prototype = {
+            add: function (/*callbacks, cid?*/) {
+                if (debug) console.log('bridge.CallbackManager.add');
+                var args = Array.prototype.slice.call(arguments);
+                var c = args.shift();
+                var cid = args.pop();
+                if (cid) {
+                    if (c !== null && typeof c === 'object') {
+                        for (var key in c) {
+                            if (c.hasOwnProperty(key)) _collection[cid][key] = c[key];
+                        }
+                    }
+                } else {
+                    cid = _next();
+                    _collection[cid] = c;
+                }
+                return cid;
+            },
+            remove: function (cid) {
+                if (debug)  console.log('bridge.CallbackManager.remove, cid: ' + cid);
+                if (_collection[cid]) delete _collection[cid];
+            },
+            call: function (cid, key, args, keep) {
+                if (debug) console.log('bridge.CallbackManager.call, cid: '+ cid + ', key: ' + key);
+                var callbacks = _collection[cid];
+                keep = !!keep;
+                if (callbacks) {
+                    var fn = callbacks[key];
+                    if (fn) {
+                        fn.apply(null, args);
+                        if (!keep) this.remove(cid)
+                    }
+                }
+            }
+        };
+
+        return {
+            getInstance: function () {
+                return this.instance || (this.instance = new CallbackManager);
+            }
+        };
+    })();
+
+
+    var Listeners = (function () {
+        var _listeners = {};
+        var _id = 0;
+        var _next = function () {
+            return (_id += 1);
+        };
+
+        var ListenerManager = function () {};
+
+        ListenerManager.prototype = {
+            add: function (l) {
+                if (debug) console.log('bridge.ListenerManager.add');
+                var id = _next();
+                _listeners[id] = l;
+                return id;
+            },
+            resolve: function (id, action, data, keep) {
+                if (debug) console.log('bridge.ListenerManager.resolve, id: ' + id + ', action: ' + action);
+                keep = !!keep;
+                var l = _listeners[id];
+                if (l) {
+                    var cm = Callbacks.getInstance();
+                    cm.call(l.cid, action, [data], keep);
+                }
+                return l;
+            },
+            remove: function (id) {
+                if (debug) console.log('bridge.ListenerManager.remove, id: ' + id);
+                var l = _listeners[id];
+                if (l) {
+                    var cm = Callbacks.getInstance();
+                    if (l.cid) cm.remove(l.cid);
+                    delete _listeners[id];
+                }
+            },
+            attach: function (id, key, value) {
+                if (_listeners[id]) {
+                    _listeners[id][key] = value;
+                    return true;
+                }
+                return false;
+            },
+            find: function (key, value) {
+                var result = [];
+                for (var p in _listeners) {
+                    if (_listeners.hasOwnProperty(p)) {
+                        var l = _listeners[p];
+                        if (l[key] === value) result.push({id: p, listener: l});
+                    }
+                }
+                return result;
+            }
+        }
+
+        return {
+            getInstance: function () {
+                return this.instance || (this.instance = new ListenerManager);
+            }
+        };
+    })();
+
+    var Listener = function () {
+        if (debug) console.log('bridge: Listener constructor');
+        this.cid = null;
+    };
+    Listener.prototype = {
+        then: function (c) {
+            if (debug) console.log('bridge.Listener.then');
+            var cm = Callbacks.getInstance();
+            this.cid = cm.add(c, this.cid);
+            return this;
+        }
+    };
+
+    var Bridge = function () {};
+    Bridge.prototype = {
+        sync: function (data) {
+            var json = JSON.stringify({
+              cmd: data.cmd,
+              args: data
+            });
+            if (debug) console.log('bridge.sync, json: ' + json);
+            var result = extension.internal.sendSyncMessage(json);
+            var obj = JSON.parse(result);
+            if (obj.error)
+                throw new WebAPIException(obj.code, obj.name, obj.message);
+            return obj.result;
+        },
+        async: function (data) {
+            var l = new Listener();
+            data.cid = Listeners.getInstance().add(l);
+            var json = JSON.stringify({
+                cmd: data.cmd,
+                args: data
+            });
+            if (debug) console.log('bridge.async, json: ' + json);
+            setTimeout(function () {
+                extension.postMessage(json);
+            });
+            return l;
+        },
+        listener: function (c) {
+            var l = (new Listener()).then(c);
+            var cid = Listeners.getInstance().add(l);
+            return cid;
+        },
+        attach: function (id, key, value) {
+            return Listeners.getInstance().attach(id, key, value);
+        },
+        find: function (key, value) {
+            return Listeners.getInstance().find(key, value);
+        },
+        remove: function (id) {
+            Listeners.getInstance().remove(id);
+        }
+    };
+
+    extension.setMessageListener(function (json) {
+        /*
+         *Expected response:
+         *{
+         *    cid: 23,                        // callback id
+         *    action: 'success',              // expected callback action
+         *    keep: false                     // optional param
+         *    args: {...}                     // data pased to callback
+         *}
+         */
+
+        if (debug) console.log('bridge.setMessageListener, json: ' + json);
+        var data = JSON.parse(json);
+        if (data.cid && data.action) {
+            setTimeout(function() {
+                Listeners.getInstance().resolve(data.cid, data.action, data.args, data.keep);
+            }, 0);
+        }
+    });
+
+    return new Bridge;
+});
+
+// WebAPIException and WebAPIError definition moved to Utils for compliance
+// reasons with blink-wrt environment.
+// In blink-wrt the original Tizen module is loaded, which is not providing exception constructor.
+// As modules needs exceptions internally so they are loaded here for now.
+// See http://168.219.209.56/gerrit/#/c/23472/ for more details.
+// In future exception definition could be moved back to Tizen module.
+function __isObject(object) {
+  return object instanceof _global.Object;
+}
+
+function __isUndefined(object) {
+  return object === void 0;
+}
+
+function __isNumber(object) {
+  return typeof object === 'number';
+}
+
+// WARNING! This list should be in sync with the equivalent enum
+// located at tizen.h. Remember to update tizen.h if you change
+// something here.
+var errors = {
+  NO_ERROR: 0,
+  UNKNOWN_ERR: -1,
+
+  INDEX_SIZE_ERR: 1,
+  DOMSTRING_SIZE_ERR: 2,
+  HIERARCHY_REQUEST_ERR: 3,
+  WRONG_DOCUMENT_ERR: 4,
+  INVALID_CHARACTER_ERR: 5,
+  NO_DATA_ALLOWED_ERR: 6,
+  NO_MODIFICATION_ALLOWED_ERR: 7,
+  NOT_FOUND_ERR: 8,
+  NOT_SUPPORTED_ERR: 9,
+  INUSE_ATTRIBUTE_ERR: 10,
+  INVALID_STATE_ERR: 11,
+  SYNTAX_ERR: 12,
+  INVALID_MODIFICATION_ERR: 13,
+  NAMESPACE_ERR: 14,
+  INVALID_ACCESS_ERR: 15,
+  VALIDATION_ERR: 16,
+  TYPE_MISMATCH_ERR: 17,
+  SECURITY_ERR: 18,
+  NETWORK_ERR: 19,
+  ABORT_ERR: 20,
+  URL_MISMATCH_ERR: 21,
+  QUOTA_EXCEEDED_ERR: 22,
+  TIMEOUT_ERR: 23,
+  INVALID_NODE_TYPE_ERR: 24,
+  DATA_CLONE_ERR: 25,
+
+  // Error codes for these errors are not really defined anywhere.
+  INVALID_VALUES_ERR: 100,
+  IO_ERR: 101,
+  PERMISSION_DENIED_ERR: 102,
+  SERVICE_NOT_AVAILABLE_ERR: 103,
+  DATABASE_ERR: 104,
+  VERIFICATION_ERR: 105
+};
+
+var code_to_name = {};
+code_to_name[errors['NO_ERROR']] = 'NoError';
+code_to_name[errors['UNKNOWN_ERR']] = 'UnknownError';
+code_to_name[errors['INDEX_SIZE_ERR']] = 'IndexSizeError';
+code_to_name[errors['DOMSTRING_SIZE_ERR']] = 'DOMStringSizeError';
+code_to_name[errors['HIERARCHY_REQUEST_ERR']] = 'HierarchyRequestError';
+code_to_name[errors['WRONG_DOCUMENT_ERR']] = 'WrongDocumentError';
+code_to_name[errors['INVALID_CHARACTER_ERR']] = 'InvalidCharacterError';
+code_to_name[errors['NO_DATA_ALLOWED_ERR']] = 'NoDataAllowedError';
+code_to_name[errors['NO_MODIFICATION_ALLOWED_ERR']] = 'NoModificationAllowedError';
+code_to_name[errors['NOT_FOUND_ERR']] = 'NotFoundError';
+code_to_name[errors['NOT_SUPPORTED_ERR']] = 'NotSupportedError';
+code_to_name[errors['INUSE_ATTRIBUTE_ERR']] = 'InuseAttributeError';
+code_to_name[errors['INVALID_STATE_ERR']] = 'InvalidStateError';
+code_to_name[errors['SYNTAX_ERR']] = 'SyntaxError';
+code_to_name[errors['INVALID_MODIFICATION_ERR']] = 'InvalidModificationError';
+code_to_name[errors['NAMESPACE_ERR']] = 'NamespaceError';
+code_to_name[errors['INVALID_ACCESS_ERR']] = 'InvalidAccessError';
+code_to_name[errors['VALIDATION_ERR']] = 'ValidationError';
+code_to_name[errors['TYPE_MISMATCH_ERR']] = 'TypeMismatchError';
+code_to_name[errors['SECURITY_ERR']] = 'SecurityError';
+code_to_name[errors['NETWORK_ERR']] = 'NetworkError';
+code_to_name[errors['ABORT_ERR']] = 'AbortError';
+code_to_name[errors['URL_MISMATCH_ERR']] = 'URLMismatchError';
+code_to_name[errors['QUOTA_EXCEEDED_ERR']] = 'QuotaExceededError';
+code_to_name[errors['TIMEOUT_ERR']] = 'TimeoutError';
+code_to_name[errors['INVALID_NODE_TYPE_ERR']] = 'InvalidNodeTypeError';
+code_to_name[errors['DATA_CLONE_ERR']] = 'DataCloneError';
+
+code_to_name[errors['INVALID_VALUES_ERR']] = 'InvalidValuesError';
+code_to_name[errors['IO_ERR']] = 'IOError';
+code_to_name[errors['PERMISSION_DENIED_ERR']] = 'PermissionDeniedError';
+code_to_name[errors['SERVICE_NOT_AVAILABLE_ERR']] = 'ServiceNotAvailableError';
+code_to_name[errors['DATABASE_ERR']] = 'DatabaseError';
+code_to_name[errors['VERIFICATION_ERR']] = 'VerificationError';
+
+var name_to_code = {};
+Object.keys(errors).forEach(function(key) {
+  name_to_code[code_to_name[errors[key]]] = errors[key];
+});
+
+
+/**
+ * Generic exception interface.
+ *
+ * @param {number} code 16-bit error code.
+ * @param {string} message An error message that describes the details of an encountered error.
+ * @param {string} name An error type.
+ */
+var WebAPIException = function(code, message, name) {
+  var code_ = 0;
+  var name_ = code_to_name[code];
+  var message_ = 'Unknown error';
+
+  switch (arguments.length) {
+    case 1:
+      var error = arguments[0];
+      if (__isObject(error)) {
+        code_ = error.code;
+        name_ = error.name;
+        message_ = error.message;
+        if (__isUndefined(code_) && !__isUndefined(name_))
+          code_ = name_to_code[name_];
+        if (__isUndefined(name_) && !__isUndefined(code_))
+          name_ = code_to_name[code_];
+      } else if (__isNumber(error)) {
+        // backward compatibility with crosswalk implementation
+        code_ = error;
+        name_ = code_to_name[code];
+        message_ = name_;
+      }
+      break;
+    case 2:
+      if (__isNumber(arguments[0])) {
+        code_ = arguments[0];
+        if (!__isUndefined(code_to_name[code_])) {
+          name_ = code_to_name[code_];
+        }
+      } else {
+        name_ = String(arguments[0]);
+        if (!__isUndefined(name_to_code[name_])) {
+          code_ = name_to_code[name_];
+        }
+      }
+      message_ = String(arguments[1]);
+      break;
+    case 3:
+      // backward compatibility with crosswalk implementation
+      code_ = Number(arguments[0]);
+      message_ = String(arguments[1]);
+      name_ = String(arguments[2]);
+      break;
+    default:
+      return;
+  }
+
+  if (code_ > errors.DATA_CLONE_ERR) {
+    code_ = 0;
+  }
+
+  // attributes
+  Object.defineProperties(this, {
+    code: {value: code_, writable: false, enumerable: true},
+    name: {value: name_, writable: false, enumerable: true},
+    message: {value: message_, writable: false, enumerable: true}
+  });
+
+  this.constructor.prototype.__proto__ = Error.prototype;
+  Error.captureStackTrace && Error.captureStackTrace(this, this.constructor); // V8-specific code
+};
+
+WebAPIException.prototype.toString = function() {
+  return this.name + ': ' + this.message;
+};
+
+
+var error_constants = {};
+for (var prop in errors) {
+  error_constants[prop] = {value: errors[prop], writable: false, enumerable: true};
+}
+Object.defineProperties(WebAPIException, error_constants);
+Object.defineProperties(WebAPIException.prototype, error_constants);
+
+
+// Export WebAPIException and WebAPIError into global scope.
+// For compliance reasons their constructors should not be exported in tizen namespace,
+// but should be available internally to allow throwing exceptions from modules.
+var scope;
+if (typeof window !== 'undefined') {
+  scope = window;
+} else if(typeof global !== 'undefined') {
+  scope = global;
+}
+scope = scope || {};
+scope.WebAPIException = WebAPIException;
+scope.WebAPIError = WebAPIException;
+
+Utils.prototype.dateConverter = _dateConverter;
+Utils.prototype.type = _type;
+Utils.prototype.converter = _converter;
+Utils.prototype.validator = _validator;
+Utils.prototype.NativeManager = NativeManager;
+Utils.prototype.NativeBridge = NativeBridge;
+
+var native_ = new NativeManager(extension);
+
+exports = new Utils();
+
+Object.freeze(Utils.prototype);
+Object.freeze(NativeManager.prototype);
+Object.freeze(NativeBridge.prototype);
+Object.freeze(exports);
diff --git a/webWidgetTCT_device/src/utils/utils_extension.cc b/webWidgetTCT_device/src/utils/utils_extension.cc
new file mode 100755 (executable)
index 0000000..9eae126
--- /dev/null
@@ -0,0 +1,31 @@
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "common/logger.h"
+#include "utils/utils_extension.h"
+#include "utils/utils_instance.h"
+
+// This will be generated from tizen_api.js.
+extern const char kSource_utils_api[];
+
+common::Extension* CreateExtension() {
+  LoggerD("Entered");
+  return new UtilsExtension;
+}
+
+UtilsExtension::UtilsExtension() {
+  LoggerD("Entered");
+  SetExtensionName("xwalk.utils");
+  SetJavaScriptAPI(kSource_utils_api);
+}
+
+UtilsExtension::~UtilsExtension() {
+  LoggerD("Entered");
+}
+
+common::Instance* UtilsExtension::CreateInstance() {
+  LoggerD("Entered");
+  return new extension::utils::UtilsInstance();
+}
diff --git a/webWidgetTCT_device/src/utils/utils_extension.h b/webWidgetTCT_device/src/utils/utils_extension.h
new file mode 100755 (executable)
index 0000000..1102e4b
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UTILS_UTILS_EXTENSION_H_
+#define UTILS_UTILS_EXTENSION_H_
+
+#include "common/extension.h"
+
+class UtilsExtension : public common::Extension {
+ public:
+  UtilsExtension();
+  virtual ~UtilsExtension();
+
+ private:
+  virtual common::Instance* CreateInstance();
+};
+
+#endif  // UTILS_UTILS_EXTENSION_H_
diff --git a/webWidgetTCT_device/src/utils/utils_instance.cc b/webWidgetTCT_device/src/utils/utils_instance.cc
new file mode 100755 (executable)
index 0000000..71d7aca
--- /dev/null
@@ -0,0 +1,173 @@
+// Copyright (c) 2013 Intel Corporation. All rights reserved.
+// Copyright (c) 2015 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <sys/types.h>
+#include <utility>
+#include <unistd.h>
+#include <app_manager.h>
+#include <pkgmgr-info.h>
+#include "common/scope_exit.h"
+#include "common/logger.h"
+#include "utils/utils_instance.h"
+
+using common::PlatformResult;
+using common::ErrorCode;
+
+namespace extension {
+namespace utils {
+
+UtilsInstance::UtilsInstance() {
+  using std::placeholders::_1;
+  using std::placeholders::_2;
+
+  LoggerD("Entered");
+#define REGISTER_SYNC(c, x) \
+  RegisterSyncHandler(c, std::bind(&UtilsInstance::x, this, _1, _2));
+#define REGISTER_ASYNC(c, x) \
+  RegisterSyncHandler(c, std::bind(&UtilsInstance::x, this, _1, _2));
+
+  REGISTER_SYNC("Utils_getPkgApiVersion", GetPkgApiVersion);
+  REGISTER_SYNC("Utils_checkPrivilegeAccess", CheckPrivilegeAccess);
+  REGISTER_SYNC("Utils_checkBackwardCompabilityPrivilegeAccess", CheckBackwardCompabilityPrivilegeAccess);
+  REGISTER_SYNC("Utils_toLongLong", ToLongLong);
+  REGISTER_SYNC("Utils_toUnsignedLongLong", ToUnsignedLongLong);
+
+#undef REGISTER_SYNC
+#undef REGISTER_ASYNC
+}
+
+void UtilsInstance::GetPkgApiVersion(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+
+  char* app_id = nullptr;
+  char* pkgid = nullptr;
+  app_info_h app_handle = nullptr;
+  pkgmgrinfo_pkginfo_h pkginfo_handle = nullptr;
+  char *api_version = nullptr;
+
+  SCOPE_EXIT {
+    if (app_id) {
+      free(app_id);
+    }
+    if (pkgid) {
+      free(pkgid);
+    }
+    if (app_handle) {
+      app_info_destroy(app_handle);
+    }
+    if (pkginfo_handle) {
+      pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_handle);
+    }
+  };
+
+  pid_t pid = getpid();
+  int ret = app_manager_get_app_id(pid, &app_id);
+  if (ret != APP_MANAGER_ERROR_NONE) {
+    LoggerE("Failed to get app id");
+    ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get app id"), &out);
+    return;
+  }
+
+  ret = app_info_create(app_id, &app_handle);
+  if (ret != APP_MANAGER_ERROR_NONE) {
+    LoggerE("Fail to get app info");
+    ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Fail to get app info"), &out);
+    return;
+  }
+
+  ret = app_info_get_package(app_handle, &pkgid);
+  if ((ret != APP_MANAGER_ERROR_NONE) || (pkgid == nullptr)) {
+    LoggerE("Fail to get pkg id");
+    ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Fail to get pkg id"), &out);
+    return;
+  }
+
+  ret = pkgmgrinfo_pkginfo_get_pkginfo(pkgid, &pkginfo_handle);
+  if (ret != PMINFO_R_OK) {
+    LoggerE("Fail to get pkginfo_h");
+    ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Fail to get pkginfo_h"), &out);
+    return;
+  }
+
+  ret = pkgmgrinfo_pkginfo_get_api_version(pkginfo_handle, &api_version);
+  if (ret != PMINFO_R_OK) {
+    LoggerE("Fail to get api version");
+    ReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Fail to get api version"), &out);
+    return;
+  }
+
+  ReportSuccess(picojson::value(api_version), out);
+}
+
+void UtilsInstance::CheckPrivilegeAccess(const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
+  const auto& privilege = args.get("privilege").to_str();
+  CHECK_PRIVILEGE_ACCESS(privilege, &out);
+  ReportSuccess(out);
+}
+
+void UtilsInstance::CheckBackwardCompabilityPrivilegeAccess(const picojson::value& args,
+                                                            picojson::object& out) {
+  LoggerD("Entered");
+  const auto& current_priv = args.get("current_privilege").to_str();
+  const auto& prev_priv = args.get("previous_privilege").to_str();
+
+  CHECK_BACKWARD_COMPABILITY_PRIVILEGE_ACCESS(current_priv, prev_priv, &out);
+  ReportSuccess(out);
+}
+
+namespace {
+
+template <typename T> int sgn(T val) {
+    return (T(0) < val) - (val < T(0));
+}
+
+const double kTwoPow63 = 9223372036854775808.0;
+const double kTwoPow64 = 18446744073709551616.0;
+
+}  // namespace
+
+void UtilsInstance::ToLongLong(const picojson::value& args,
+                               picojson::object& out) {
+  LoggerD("Entered");
+
+  const auto& n = args.get("n");
+  long long output = 0;
+
+  if (n.is<double>()) {
+    auto d = n.get<double>();
+    d = sgn<double>(d) * std::floor(std::fabs(d));
+    d = std::fmod(d, kTwoPow64);
+    if (d > kTwoPow63) {
+      d -= kTwoPow64;
+    }
+    output = static_cast<long long>(d);
+  }
+
+  ReportSuccess(picojson::value(static_cast<double>(output)), out);
+}
+
+void UtilsInstance::ToUnsignedLongLong(const picojson::value& args,
+                                       picojson::object& out) {
+  LoggerD("Entered");
+
+  const auto& n = args.get("n");
+  unsigned long long output = 0;
+
+  if (n.is<double>()) {
+    auto d = n.get<double>();
+    d = sgn<double>(d) * std::floor(std::fabs(d));
+    d = std::fmod(d, kTwoPow64);
+    if (d < 0.0) {
+      d += kTwoPow64;
+    }
+    output = static_cast<unsigned long long>(d);
+  }
+
+  ReportSuccess(picojson::value(static_cast<double>(output)), out);
+}
+
+}  // namespace utils
+}  // namespace extension
diff --git a/webWidgetTCT_device/src/utils/utils_instance.h b/webWidgetTCT_device/src/utils/utils_instance.h
new file mode 100755 (executable)
index 0000000..5c5e1d3
--- /dev/null
@@ -0,0 +1,30 @@
+// Copyright (c) 2013 Intel Corporation. All rights reserved.
+// Copyright (c) 2015 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UTILS_UTILS_INSTANCE_H_
+#define UTILS_UTILS_INSTANCE_H_
+
+#include "common/extension.h"
+
+namespace extension {
+namespace utils {
+
+class UtilsInstance : public common::ParsedInstance {
+ public:
+  UtilsInstance();
+  virtual ~UtilsInstance() {}
+
+ private:
+  void GetPkgApiVersion(const picojson::value& args, picojson::object& out);
+  void CheckPrivilegeAccess(const picojson::value& args, picojson::object& out);
+  void CheckBackwardCompabilityPrivilegeAccess(const picojson::value& args, picojson::object& out);
+
+  void ToLongLong(const picojson::value& args, picojson::object& out);
+  void ToUnsignedLongLong(const picojson::value& args, picojson::object& out);
+};
+}  // namespace utils
+}  // namespace extension
+
+#endif  // UTILS_UTILS_INSTANCE_H_
diff --git a/webWidgetTCT_device/src/websetting/websetting.gyp b/webWidgetTCT_device/src/websetting/websetting.gyp
new file mode 100755 (executable)
index 0000000..f65be42
--- /dev/null
@@ -0,0 +1,27 @@
+{
+  'includes':[
+    '../common/common.gypi',
+  ],
+  'targets': [
+    {
+      'target_name': 'tizen_websetting',
+      'type': 'loadable_module',
+      'dependencies': [
+        '../common/common.gyp:tizen_common',
+      ],
+      'sources': [
+        'websetting_api.js',
+        'websetting_extension.cc',
+        'websetting_extension.h',
+      ],
+      'includes': [
+        '../common/pkg-config.gypi',
+      ],
+      'variables': {
+        'packages': [
+          'glib-2.0',
+        ]
+      },
+    },
+  ],
+}
diff --git a/webWidgetTCT_device/src/websetting/websetting_api.js b/webWidgetTCT_device/src/websetting/websetting_api.js
new file mode 100755 (executable)
index 0000000..9607c62
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+var validator_ = xwalk.utils.validator;
+var native_ = new xwalk.utils.NativeManager(extension);
+
+exports.setUserAgentString = function() {
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'userAgent',
+      type: validator_.Types.STRING,
+      optional: false,
+      nullable: false
+    },
+    {
+      name: 'successCallback',
+      type: validator_.Types.FUNCTION,
+      optional: true,
+      nullable: true
+    },
+    {
+      name: 'errorCallback',
+      type: validator_.Types.FUNCTION,
+      optional: true,
+      nullable: true
+    }
+  ]);
+
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+    } else {
+      args.successCallback();
+    }
+  };
+
+  native_.sendRuntimeAsyncMessage('tizen://changeUA', args.userAgent, callback);
+};
+
+exports.removeAllCookies = function() {
+  var args = validator_.validateArgs(arguments, [
+    {
+      name: 'successCallback',
+      type: validator_.Types.FUNCTION,
+      optional: true,
+      nullable: true
+    },
+    {
+      name: 'errorCallback',
+      type: validator_.Types.FUNCTION,
+      optional: true,
+      nullable: true
+    }
+  ]);
+
+  var callback = function(result) {
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
+    } else {
+      args.successCallback();
+    }
+  };
+
+  native_.sendRuntimeAsyncMessage('tizen://deleteAllCookies', '', callback);
+};
diff --git a/webWidgetTCT_device/src/websetting/websetting_extension.cc b/webWidgetTCT_device/src/websetting/websetting_extension.cc
new file mode 100755 (executable)
index 0000000..a80bb84
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2015 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 "common/logger.h"
+#include "websetting/websetting_extension.h"
+
+extern const char kSource_websetting_api[];
+
+common::Extension* CreateExtension() {
+  return new WebSettingExtension();
+}
+
+WebSettingExtension::WebSettingExtension() {
+  LoggerD("Entered");
+  SetExtensionName("tizen.websetting");
+  SetJavaScriptAPI(kSource_websetting_api);
+}
+
+WebSettingExtension::~WebSettingExtension() {
+  LoggerD("Entered");
+}
+
+common::Instance* WebSettingExtension::CreateInstance() {
+  LoggerD("Entered");
+  return new common::ParsedInstance();
+}
diff --git a/webWidgetTCT_device/src/websetting/websetting_extension.h b/webWidgetTCT_device/src/websetting/websetting_extension.h
new file mode 100755 (executable)
index 0000000..00b40fe
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2015 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 WEBSETTING_WEBSETTING_EXTENSION_H_
+#define WEBSETTING_WEBSETTING_EXTENSION_H_
+
+#include "common/extension.h"
+
+class WebSettingExtension : public common::Extension {
+ public:
+  WebSettingExtension();
+  virtual ~WebSettingExtension();
+
+ private:
+  virtual common::Instance* CreateInstance();
+};
+
+#endif  // WEBSETTING_WEBSETTING_EXTENSION_H_
diff --git a/webWidgetTCT_device/test/common/loader.js b/webWidgetTCT_device/test/common/loader.js
new file mode 100755 (executable)
index 0000000..3ba1415
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+// remember to run webapi-plugins/tools/install-fake-app.sh first
+
+(function () {
+    'use strict';
+
+    function initialize() {
+        if (typeof (tizen) === 'undefined') {
+            console.log('Loading wrt-service');
+            process.argv[1] = '/opt/usr/apps/node/bin/node';
+            require('/usr/bin/wrt-service');
+            process.title = 'node';
+
+            // console
+            var parent = module.parent;
+            while (parent) {
+                if (parent.exports.repl) {
+                    parent.exports.repl.rli.output.columns = 150;
+                }
+                parent = parent.parent;
+            }
+        }
+    }
+
+    module.exports = initialize;
+})();
diff --git a/webWidgetTCT_device/test/fs b/webWidgetTCT_device/test/fs
new file mode 100755 (executable)
index 0000000..c5b049d
--- /dev/null
@@ -0,0 +1,9 @@
+var fs = {
+    appendFileSync : function(path, content) {
+        append(path, content);
+    },
+    readFileSync : function(path) {
+        read(path);
+    },
+};
+fs
diff --git a/webWidgetTCT_device/test/index.js b/webWidgetTCT_device/test/index.js
new file mode 100755 (executable)
index 0000000..23c9f82
--- /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.
+ */
+
+(function() {
+    load('/home/owner/share/wrt-service-tct/prerequisite.js');
+    requireTCT('./tct/tct.js')('alarm application datacontrol filesystem messageport package systeminfo');
+    //require('./utc/utc.js')('alarm application datacontrol filesystem messageport package systeminfo');
+})();
diff --git a/webWidgetTCT_device/test/prerequisite.js b/webWidgetTCT_device/test/prerequisite.js
new file mode 100755 (executable)
index 0000000..41fb146
--- /dev/null
@@ -0,0 +1,12 @@
+var __dirname = "/home/owner/share/wrt-service-tct/";
+var GLOBAL = this;
+var requireTCTHash = {};
+var module = {};
+function requireTCT(path) {
+    console.log("require " + path);
+    if (requireTCTHash[path] == undefined) {
+        var ret = load(__dirname + path);
+        requireTCTHash[path] = ret;
+    }
+    return requireTCTHash[path];
+}
diff --git a/webWidgetTCT_device/test/tct/common/testharness.css b/webWidgetTCT_device/test/tct/common/testharness.css
new file mode 100755 (executable)
index 0000000..365084f
--- /dev/null
@@ -0,0 +1,92 @@
+html {
+    font-family:DejaVu Sans, Bitstream Vera Sans, Arial, Sans;
+}
+
+#log .warning,
+#log .warning a {
+  color: black;
+  background: yellow;
+}
+
+#log .error,
+#log .error a {
+  color: white;
+  background: red;
+}
+
+#log pre {
+  border: 1px solid black;
+  padding: 1em;
+}
+
+section#summary {
+    margin-bottom:1em;
+}
+
+table#results {
+    border-collapse:collapse;
+    table-layout:fixed;
+    width:100%;
+}
+
+table#results th:first-child,
+table#results td:first-child {
+    width:4em;
+}
+
+table#results th:last-child,
+table#results td:last-child {
+    width:50%;
+}
+
+table#results.assertions th:last-child,
+table#results.assertions td:last-child {
+    width:35%;
+}
+
+table#results th {
+    padding:0;
+    padding-bottom:0.5em;
+    border-bottom:medium solid black;
+}
+
+table#results td {
+    padding:1em;
+    padding-bottom:0.5em;
+    border-bottom:thin solid black;
+}
+
+tr.pass > td:first-child {
+    color:green;
+}
+
+tr.fail > td:first-child {
+    color:red;
+}
+
+tr.timeout > td:first-child {
+    color:red;
+}
+
+tr.notrun > td:first-child {
+    color:blue;
+}
+
+.pass > td:first-child, .fail > td:first-child, .timeout > td:first-child, .notrun > td:first-child {
+    font-variant:small-caps;
+}
+
+table#results span {
+    display:block;
+}
+
+table#results span.expected {
+    font-family:DejaVu Sans Mono, Bitstream Vera Sans Mono, Monospace;
+    white-space:pre;
+}
+
+table#results span.actual {
+    font-family:DejaVu Sans Mono, Bitstream Vera Sans Mono, Monospace;
+    white-space:pre;
+}
+
diff --git a/webWidgetTCT_device/test/tct/common/testharness.js b/webWidgetTCT_device/test/tct/common/testharness.js
new file mode 100755 (executable)
index 0000000..697e495
--- /dev/null
@@ -0,0 +1,2180 @@
+/*
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+*/
+
+/*
+ * == Introduction ==
+ *
+ * This file provides a framework for writing testcases. It is intended to
+ * provide a convenient API for making common assertions, and to work both
+ * for testing synchronous and asynchronous DOM features in a way that
+ * promotes clear, robust, tests.
+ *
+ * == Basic Usage ==
+ *
+ * To use this file, import the script and the testharnessreport script into
+ * the test document:
+ * <script src="/resources/testharness.js"></script>
+ * <script src="/resources/testharnessreport.js"></script>
+ *
+ * Within each file one may define one or more tests. Each test is atomic
+ * in the sense that a single test has a single result (pass/fail/timeout).
+ * Within each test one may have a number of asserts. The test fails at the
+ * first failing assert, and the remainder of the test is (typically) not run.
+ *
+ * If the file containing the tests is a HTML file with an element of id "log"
+ * this will be populated with a table containing the test results after all
+ * the tests have run.
+ *
+ * NOTE: By default tests must be created before the load event fires. For ways
+ *       to create tests after the load event, see "Determining when all tests
+ *       are complete", below
+ *
+ * == Synchronous Tests ==
+ *
+ * To create a synchronous test use the test() function:
+ *
+ * test(test_function, name, properties)
+ *
+ * test_function is a function that contains the code to test. For example a
+ * trivial passing test would be:
+ *
+ * test(function() {assert_true(true)}, "assert_true with true")
+ *
+ * The function passed in is run in the test() call.
+ *
+ * properties is an object that overrides default test properties. The
+ * recognised properties are:
+ *    timeout - the test timeout in ms
+ *
+ * e.g.
+ * test(test_function, "Sample test", {timeout:1000})
+ *
+ * would run test_function with a timeout of 1s.
+ *
+ * Additionally, test-specific metadata can be passed in the properties. These
+ * are used when the individual test has different metadata from that stored
+ * in the <head>.
+ * The recognized metadata properties are:
+ *
+ *    help - The url of the part of the specification being tested
+ *
+ *    assert - A human readable description of what the test is attempting
+ *             to prove
+ *
+ *    author - Name and contact information for the author of the test in the
+ *             format: "Name <email_addr>" or "Name http://contact/url"
+ *
+ * == Asynchronous Tests ==
+ *
+ * Testing asynchronous features is somewhat more complex since the result of
+ * a test may depend on one or more events or other callbacks. The API provided
+ * for testing these features is indended to be rather low-level but hopefully
+ * applicable to many situations.
+ *
+ * To create a test, one starts by getting a Test object using async_test:
+ *
+ * async_test(name, properties)
+ *
+ * e.g.
+ * var t = async_test("Simple async test")
+ *
+ * Assertions can be added to the test by calling the step method of the test
+ * object with a function containing the test assertions:
+ *
+ * t.step(function() {assert_true(true)});
+ *
+ * When all the steps are complete, the done() method must be called:
+ *
+ * t.done();
+ *
+ * As a convenience, async_test can also takes a function as first argument.
+ * This function is called with the test object as both its `this` object and
+ * first argument. The above example can be rewritten as:
+ *
+ * async_test(function(t) {
+ *     object.some_event = function() {
+ *         t.step(function (){assert_true(true); t.done();});
+ *     };
+ * }, "Simple async test");
+ *
+ * which avoids cluttering the global scope with references to async
+ * tests instances.
+ *
+ * The properties argument is identical to that for test().
+ *
+ * In many cases it is convenient to run a step in response to an event or a
+ * callback. A convenient method of doing this is through the step_func method
+ * which returns a function that, when called runs a test step. For example
+ *
+ * object.some_event = t.step_func(function(e) {assert_true(e.a)});
+ *
+ * == Making assertions ==
+ *
+ * Functions for making assertions start assert_
+ * The best way to get a list is to look in this file for functions names
+ * matching that pattern. The general signature is
+ *
+ * assert_something(actual, expected, description)
+ *
+ * although not all assertions precisely match this pattern e.g. assert_true
+ * only takes actual and description as arguments.
+ *
+ * The description parameter is used to present more useful error messages when
+ * a test fails
+ *
+ * NOTE: All asserts must be located in a test() or a step of an async_test().
+ *       asserts outside these places won't be detected correctly by the harness
+ *       and may cause a file to stop testing.
+ *
+ * == Setup ==
+ *
+ * Sometimes tests require non-trivial setup that may fail. For this purpose
+ * there is a setup() function, that may be called with one or two arguments.
+ * The two argument version is:
+ *
+ * setup(func, properties)
+ *
+ * The one argument versions may omit either argument.
+ * func is a function to be run synchronously. setup() becomes a no-op once
+ * any tests have returned results. Properties are global properties of the test
+ * harness. Currently recognised properties are:
+ *
+ * timeout - The time in ms after which the harness should stop waiting for
+ *           tests to complete (this is different to the per-test timeout
+ *           because async tests do not start their timer until .step is called)
+ *
+ * explicit_done - Wait for an explicit call to done() before declaring all
+ *                 tests complete (see below)
+ *
+ * output_document - The document to which results should be logged. By default
+ *                   this is the current document but could be an ancestor
+ *                   document in some cases e.g. a SVG test loaded in an HTML
+ *                   wrapper
+ *
+ * explicit_timeout - disable file timeout; only stop waiting for results
+ *                    when the timeout() function is called (typically for
+ *                    use when integrating with some existing test framework
+ *                    that has its own timeout mechanism).
+ *
+ * == Determining when all tests are complete ==
+ *
+ * By default the test harness will assume there are no more results to come
+ * when:
+ * 1) There are no Test objects that have been created but not completed
+ * 2) The load event on the document has fired
+ *
+ * This behaviour can be overridden by setting the explicit_done property to
+ * true in a call to setup(). If explicit_done is true, the test harness will
+ * not assume it is done until the global done() function is called. Once done()
+ * is called, the two conditions above apply like normal.
+ *
+ * == Generating tests ==
+ *
+ * NOTE: this functionality may be removed
+ *
+ * There are scenarios in which is is desirable to create a large number of
+ * (synchronous) tests that are internally similar but vary in the parameters
+ * used. To make this easier, the generate_tests function allows a single
+ * function to be called with each set of parameters in a list:
+ *
+ * generate_tests(test_function, parameter_lists, properties)
+ *
+ * For example:
+ *
+ * generate_tests(assert_equals, [
+ *     ["Sum one and one", 1+1, 2],
+ *     ["Sum one and zero", 1+0, 1]
+ *     ])
+ *
+ * Is equivalent to:
+ *
+ * test(function() {assert_equals(1+1, 2)}, "Sum one and one")
+ * test(function() {assert_equals(1+0, 1)}, "Sum one and zero")
+ *
+ * Note that the first item in each parameter list corresponds to the name of
+ * the test.
+ *
+ * The properties argument is identical to that for test(). This may be a
+ * single object (used for all generated tests) or an array.
+ *
+ * == Callback API ==
+ *
+ * The framework provides callbacks corresponding to 3 events:
+ *
+ * start - happens when the first Test is created
+ * result - happens when a test result is recieved
+ * complete - happens when all results are recieved
+ *
+ * The page defining the tests may add callbacks for these events by calling
+ * the following methods:
+ *
+ *   add_start_callback(callback) - callback called with no arguments
+ *   add_result_callback(callback) - callback called with a test argument
+ *   add_completion_callback(callback) - callback called with an array of tests
+ *                                       and an status object
+ *
+ * tests have the following properties:
+ *   status: A status code. This can be compared to the PASS, FAIL, TIMEOUT and
+ *           NOTRUN properties on the test object
+ *   message: A message indicating the reason for failure. In the future this
+ *            will always be a string
+ *
+ *  The status object gives the overall status of the harness. It has the
+ *  following properties:
+ *    status: Can be compared to the OK, ERROR and TIMEOUT properties
+ *    message: An error message set when the status is ERROR
+ *
+ * == External API ==
+ *
+ * In order to collect the results of multiple pages containing tests, the test
+ * harness will, when loaded in a nested browsing context, attempt to call
+ * certain functions in each ancestor and opener browsing context:
+ *
+ * start - start_callback
+ * result - result_callback
+ * complete - completion_callback
+ *
+ * These are given the same arguments as the corresponding internal callbacks
+ * described above.
+ *
+ * == External API through cross-document messaging ==
+ *
+ * Where supported, the test harness will also send messages using
+ * cross-document messaging to each ancestor and opener browsing context. Since
+ * it uses the wildcard keyword (*), cross-origin communication is enabled and
+ * script on different origins can collect the results.
+ *
+ * This API follows similar conventions as those described above only slightly
+ * modified to accommodate message event API. Each message is sent by the harness
+ * is passed a single vanilla object, available as the `data` property of the
+ * event object. These objects are structures as follows:
+ *
+ * start - { type: "start" }
+ * result - { type: "result", test: Test }
+ * complete - { type: "complete", tests: [Test, ...], status: TestsStatus }
+ *
+ * == List of assertions ==
+ *
+ * assert_true(actual, description)
+ *   asserts that /actual/ is strictly true
+ *
+ * assert_false(actual, description)
+ *   asserts that /actual/ is strictly false
+ *
+ * assert_equals(actual, expected, description)
+ *   asserts that /actual/ is the same value as /expected/
+ *
+ * assert_not_equals(actual, expected, description)
+ *   asserts that /actual/ is a different value to /expected/. Yes, this means
+ *   that "expected" is a misnomer
+ *
+ * assert_in_array(actual, expected, description)
+ *   asserts that /expected/ is an Array, and /actual/ is equal to one of the
+ *   members -- expected.indexOf(actual) != -1
+ *
+ * assert_array_equals(actual, expected, description)
+ *   asserts that /actual/ and /expected/ have the same length and the value of
+ *   each indexed property in /actual/ is the strictly equal to the corresponding
+ *   property value in /expected/
+ *
+ * assert_approx_equals(actual, expected, epsilon, description)
+ *   asserts that /actual/ is a number within +/- /epsilon/ of /expected/
+ *
+ * assert_less_than(actual, expected, description)
+ *   asserts that /actual/ is a number less than /expected/
+ *
+ * assert_greater_than(actual, expected, description)
+ *   asserts that /actual/ is a number greater than /expected/
+ *
+ * assert_less_than_equal(actual, expected, description)
+ *   asserts that /actual/ is a number less than or equal to /expected/
+ *
+ * assert_greater_than_equal(actual, expected, description)
+ *   asserts that /actual/ is a number greater than or equal to /expected/
+ *
+ * assert_regexp_match(actual, expected, description)
+ *   asserts that /actual/ matches the regexp /expected/
+ *
+ * assert_class_string(object, class_name, description)
+ *   asserts that the class string of /object/ as returned in
+ *   Object.prototype.toString is equal to /class_name/.
+ *
+ * assert_own_property(object, property_name, description)
+ *   assert that object has own property property_name
+ *
+ * assert_inherits(object, property_name, description)
+ *   assert that object does not have an own property named property_name
+ *   but that property_name is present in the prototype chain for object
+ *
+ * assert_idl_attribute(object, attribute_name, description)
+ *   assert that an object that is an instance of some interface has the
+ *   attribute attribute_name following the conditions specified by WebIDL
+ *
+ * assert_readonly(object, property_name, description)
+ *   assert that property property_name on object is readonly
+ *
+ * assert_throws(code, func, description)
+ *   code - the expected exception:
+ *     o string: the thrown exception must be a DOMException with the given
+ *               name, e.g., "TimeoutError" (for compatibility with existing
+ *               tests, a constant is also supported, e.g., "TIMEOUT_ERR")
+ *     o object: the thrown exception must have a property called "name" that
+ *               matches code.name
+ *     o null:   allow any exception (in general, one of the options above
+ *               should be used)
+ *   func - a function that should throw
+ *
+ * assert_unreached(description)
+ *   asserts if called. Used to ensure that some codepath is *not* taken e.g.
+ *   an event does not fire.
+ *
+ * assert_any(assert_func, actual, expected_array, extra_arg_1, ... extra_arg_N)
+ *   asserts that one assert_func(actual, expected_array_N, extra_arg1, ..., extra_arg_N)
+ *   is true for some expected_array_N in expected_array. This only works for assert_func
+ *   with signature assert_func(actual, expected, args_1, ..., args_N). Note that tests
+ *   with multiple allowed pass conditions are bad practice unless the spec specifically
+ *   allows multiple behaviours. Test authors should not use this method simply to hide
+ *   UA bugs.
+ *
+ * assert_exists(object, property_name, description)
+ *   *** deprecated ***
+ *   asserts that object has an own property property_name
+ *
+ * assert_not_exists(object, property_name, description)
+ *   *** deprecated ***
+ *   assert that object does not have own property property_name
+ */
+
+(function ()
+{
+    var debug = false;
+    // default timeout is 5 seconds, test can override if needed
+    var settings = {
+      output:true,
+      timeout:20000,
+      test_timeout:10000
+    };
+/*
+    var xhtml_ns = "http://www.w3.org/1999/xhtml";
+
+    // script_prefix is used by Output.prototype.show_results() to figure out
+    // where to get testharness.css from.  It's enclosed in an extra closure to
+    // not pollute the library's namespace with variables like "src".
+    var script_prefix = null;
+    (function ()
+    {
+        var scripts = document.getElementsByTagName("script");
+        for (var i = 0; i < scripts.length; i++)
+        {
+            if (scripts[i].src)
+            {
+                var src = scripts[i].src;
+            }
+            else if (scripts[i].href)
+            {
+                //SVG case
+                var src = scripts[i].href.baseVal;
+            }
+            if (src && src.slice(src.length - "testharness.js".length) === "testharness.js")
+            {
+                script_prefix = src.slice(0, src.length - "testharness.js".length);
+                break;
+            }
+        }
+    })();
+*/
+    /*
+     * API functions
+     */
+
+    var name_counter = 0;
+    function next_default_name()
+    {
+        //Don't use document.title to work around an Opera bug in XHTML documents
+        var prefix = "Untitled";
+        var suffix = name_counter > 0 ? " " + name_counter : "";
+        name_counter++;
+        return prefix + suffix;
+    }
+
+    function test(func, name, properties)
+    {
+        var test_name = name ? name : next_default_name();
+        console.log('------------------------------------------------------------------------------');
+        console.log('Running synchronous test "' + test_name + '"');
+        console.log('------------------------------------------------------------------------------');
+        properties = properties ? properties : {};
+        var test_obj = new Test(test_name, properties);
+        test_obj.step(func);
+        if (test_obj.status === test_obj.NOTRUN) {
+            test_obj.done();
+        }
+    }
+
+    function async_test(func, name, properties)
+    {
+        if (typeof func !== "function") {
+            properties = name;
+            name = func;
+            func = null;
+        }
+        var test_name = name ? name : next_default_name();
+        console.log('------------------------------------------------------------------------------');
+        console.log('Running asynchronous test "' + test_name + '"');
+        console.log('------------------------------------------------------------------------------');
+        properties = properties ? properties : {};
+        var test_obj = new Test(test_name, properties);
+        if (func) {
+            test_obj.step(func, test_obj, test_obj);
+        }
+        return test_obj;
+    }
+
+    function setup(func_or_properties, maybe_properties)
+    {
+        var func = null;
+        var properties = {};
+        if (arguments.length === 2) {
+            func = func_or_properties;
+            properties = maybe_properties;
+        } else if (func_or_properties instanceof Function){
+            func = func_or_properties;
+        } else {
+            properties = func_or_properties;
+        }
+        tests.setup(func, properties);
+        output.setup(properties);
+    }
+
+    function done() {
+        tests.end_wait();
+    }
+
+    function generate_tests(func, args, properties) {
+        forEach(args, function(x, i)
+                {
+                    var name = x[0];
+                    test(function()
+                         {
+                             func.apply(this, x.slice(1));
+                         },
+                         name,
+                         Array.isArray(properties) ? properties[i] : properties);
+                });
+    }
+
+    function on_event(object, event, callback)
+    {
+      object.addEventListener(event, callback, false);
+    }
+
+    expose(test, 'test');
+    expose(async_test, 'async_test');
+    expose(generate_tests, 'generate_tests');
+    expose(setup, 'setup');
+    expose(done, 'done');
+    expose(on_event, 'on_event');
+
+    /*
+     * Return a string truncated to the given length, with ... added at the end
+     * if it was longer.
+     */
+    function truncate(s, len)
+    {
+        if (s.length > len) {
+            return s.substring(0, len - 3) + "...";
+        }
+        return s;
+    }
+
+    /*
+     * Convert a value to a nice, human-readable string
+     */
+    function format_value(val)
+    {
+        if (Array.isArray(val))
+        {
+            return "[" + val.map(format_value).join(", ") + "]";
+        }
+
+        switch (typeof val)
+        {
+        case "string":
+            val = val.replace("\\", "\\\\");
+            for (var i = 0; i < 32; i++)
+            {
+                var replace = "\\";
+                switch (i) {
+                case 0: replace += "0"; break;
+                case 1: replace += "x01"; break;
+                case 2: replace += "x02"; break;
+                case 3: replace += "x03"; break;
+                case 4: replace += "x04"; break;
+                case 5: replace += "x05"; break;
+                case 6: replace += "x06"; break;
+                case 7: replace += "x07"; break;
+                case 8: replace += "b"; break;
+                case 9: replace += "t"; break;
+                case 10: replace += "n"; break;
+                case 11: replace += "v"; break;
+                case 12: replace += "f"; break;
+                case 13: replace += "r"; break;
+                case 14: replace += "x0e"; break;
+                case 15: replace += "x0f"; break;
+                case 16: replace += "x10"; break;
+                case 17: replace += "x11"; break;
+                case 18: replace += "x12"; break;
+                case 19: replace += "x13"; break;
+                case 20: replace += "x14"; break;
+                case 21: replace += "x15"; break;
+                case 22: replace += "x16"; break;
+                case 23: replace += "x17"; break;
+                case 24: replace += "x18"; break;
+                case 25: replace += "x19"; break;
+                case 26: replace += "x1a"; break;
+                case 27: replace += "x1b"; break;
+                case 28: replace += "x1c"; break;
+                case 29: replace += "x1d"; break;
+                case 30: replace += "x1e"; break;
+                case 31: replace += "x1f"; break;
+                }
+                val = val.replace(RegExp(String.fromCharCode(i), "g"), replace);
+            }
+            return '"' + val.replace(/"/g, '\\"') + '"';
+        case "boolean":
+        case "undefined":
+            return String(val);
+        case "number":
+            // In JavaScript, -0 === 0 and String(-0) == "0", so we have to
+            // special-case.
+            if (val === -0 && 1/val === -Infinity)
+            {
+                return "-0";
+            }
+            return String(val);
+        case "object":
+            if (val === null)
+            {
+                return "null";
+            }
+
+            // Special-case Node objects, since those come up a lot in my tests.  I
+            // ignore namespaces.  I use duck-typing instead of instanceof, because
+            // instanceof doesn't work if the node is from another window (like an
+            // iframe's contentWindow):
+            // http://www.w3.org/Bugs/Public/show_bug.cgi?id=12295
+            if ("nodeType" in val
+            && "nodeName" in val
+            && "nodeValue" in val
+            && "childNodes" in val)
+            {
+                switch (val.nodeType)
+                {
+                case Node.ELEMENT_NODE:
+                    var ret = "<" + val.tagName.toLowerCase();
+                    for (var i = 0; i < val.attributes.length; i++)
+                    {
+                        ret += " " + val.attributes[i].name + '="' + val.attributes[i].value + '"';
+                    }
+                    ret += ">" + val.innerHTML + "</" + val.tagName.toLowerCase() + ">";
+                    return "Element node " + truncate(ret, 60);
+                case Node.TEXT_NODE:
+                    return 'Text node "' + truncate(val.data, 60) + '"';
+                case Node.PROCESSING_INSTRUCTION_NODE:
+                    return "ProcessingInstruction node with target " + format_value(truncate(val.target, 60)) + " and data " + format_value(truncate(val.data, 60));
+                case Node.COMMENT_NODE:
+                    return "Comment node <!--" + truncate(val.data, 60) + "-->";
+                case Node.DOCUMENT_NODE:
+                    return "Document node with " + val.childNodes.length + (val.childNodes.length == 1 ? " child" : " children");
+                case Node.DOCUMENT_TYPE_NODE:
+                    return "DocumentType node";
+                case Node.DOCUMENT_FRAGMENT_NODE:
+                    return "DocumentFragment node with " + val.childNodes.length + (val.childNodes.length == 1 ? " child" : " children");
+                default:
+                    return "Node object of unknown type";
+                }
+            }
+
+            // Fall through to default
+        default:
+            return typeof val + ' "' + truncate(String(val), 60) + '"';
+        }
+    }
+    expose(format_value, "format_value");
+
+    /*
+     * Assertions
+     */
+
+    function assert_true(actual, description)
+    {
+        assert(actual === true, "assert_true", description,
+                                "expected true got ${actual}", {actual:actual});
+    };
+    expose(assert_true, "assert_true");
+
+    function assert_false(actual, description)
+    {
+        assert(actual === false, "assert_false", description,
+                                 "expected false got ${actual}", {actual:actual});
+    };
+    expose(assert_false, "assert_false");
+
+    function same_value(x, y) {
+        if (y !== y)
+        {
+            //NaN case
+            return x !== x;
+        }
+        else if (x === 0 && y === 0) {
+            //Distinguish +0 and -0
+            return 1/x === 1/y;
+        }
+        else
+        {
+            //typical case
+            return x === y;
+        }
+    }
+
+    function assert_equals(actual, expected, description)
+    {
+         /*
+          * Test if two primitives are equal or two objects
+          * are the same object
+          */
+        if (typeof actual != typeof expected)
+        {
+            assert(false, "assert_equals", description,
+                          "expected (" + typeof expected + ") ${expected} but got (" + typeof actual + ") ${actual}",
+                          {expected:expected, actual:actual});
+            return;
+        }
+        assert(same_value(actual, expected), "assert_equals", description,
+                                             "expected ${expected} but got ${actual}",
+                                             {expected:expected, actual:actual});
+    };
+    expose(assert_equals, "assert_equals");
+
+    function assert_not_equals(actual, expected, description)
+    {
+         /*
+          * Test if two primitives are unequal or two objects
+          * are different objects
+          */
+        assert(!same_value(actual, expected), "assert_not_equals", description,
+                                              "got disallowed value ${actual}",
+                                              {actual:actual});
+    };
+    expose(assert_not_equals, "assert_not_equals");
+
+    function assert_in_array(actual, expected, description)
+    {
+        assert(expected.indexOf(actual) != -1, "assert_in_array", description,
+                                               "value ${actual} not in array ${expected}",
+                                               {actual:actual, expected:expected});
+    }
+    expose(assert_in_array, "assert_in_array");
+
+    function assert_object_equals(actual, expected, description)
+    {
+         //This needs to be improved a great deal
+         function check_equal(actual, expected, stack)
+         {
+             stack.push(actual);
+
+             var p;
+             for (p in actual)
+             {
+                 assert(expected.hasOwnProperty(p), "assert_object_equals", description,
+                                                    "unexpected property ${p}", {p:p});
+
+                 if (typeof actual[p] === "object" && actual[p] !== null)
+                 {
+                     if (stack.indexOf(actual[p]) === -1)
+                     {
+                         check_equal(actual[p], expected[p], stack);
+                     }
+                 }
+                 else
+                 {
+                     assert(same_value(actual[p], expected[p]), "assert_object_equals", description,
+                                                       "property ${p} expected ${expected} got ${actual}",
+                                                       {p:p, expected:expected, actual:actual});
+                 }
+             }
+             for (p in expected)
+             {
+                 assert(actual.hasOwnProperty(p),
+                        "assert_object_equals", description,
+                        "expected property ${p} missing", {p:p});
+             }
+             stack.pop();
+         }
+         check_equal(actual, expected, []);
+    };
+    expose(assert_object_equals, "assert_object_equals");
+
+    function assert_array_equals(actual, expected, description)
+    {
+        assert(actual.length === expected.length,
+               "assert_array_equals", description,
+               "lengths differ, expected ${expected} got ${actual}",
+               {expected:expected.length, actual:actual.length});
+
+        for (var i=0; i < actual.length; i++)
+        {
+            assert(actual.hasOwnProperty(i) === expected.hasOwnProperty(i),
+                   "assert_array_equals", description,
+                   "property ${i}, property expected to be $expected but was $actual",
+                   {i:i, expected:expected.hasOwnProperty(i) ? "present" : "missing",
+                   actual:actual.hasOwnProperty(i) ? "present" : "missing"});
+            assert(same_value(expected[i], actual[i]),
+                   "assert_array_equals", description,
+                   "property ${i}, expected ${expected} but got ${actual}",
+                   {i:i, expected:expected[i], actual:actual[i]});
+        }
+    }
+    expose(assert_array_equals, "assert_array_equals");
+
+    function assert_approx_equals(actual, expected, epsilon, description)
+    {
+        /*
+         * Test if two primitive numbers are equal withing +/- epsilon
+         */
+        assert(typeof actual === "number",
+               "assert_approx_equals", description,
+               "expected a number but got a ${type_actual}",
+               {type_actual:typeof actual});
+
+        assert(Math.abs(actual - expected) <= epsilon,
+               "assert_approx_equals", description,
+               "expected ${expected} +/- ${epsilon} but got ${actual}",
+               {expected:expected, actual:actual, epsilon:epsilon});
+    };
+    expose(assert_approx_equals, "assert_approx_equals");
+
+    function assert_less_than(actual, expected, description)
+    {
+        /*
+         * Test if a primitive number is less than another
+         */
+        assert(typeof actual === "number",
+               "assert_less_than", description,
+               "expected a number but got a ${type_actual}",
+               {type_actual:typeof actual});
+
+        assert(actual < expected,
+               "assert_less_than", description,
+               "expected a number less than ${expected} but got ${actual}",
+               {expected:expected, actual:actual});
+    };
+    expose(assert_less_than, "assert_less_than");
+
+    function assert_greater_than(actual, expected, description)
+    {
+        /*
+         * Test if a primitive number is greater than another
+         */
+        assert(typeof actual === "number",
+               "assert_greater_than", description,
+               "expected a number but got a ${type_actual}",
+               {type_actual:typeof actual});
+
+        assert(actual > expected,
+               "assert_greater_than", description,
+               "expected a number greater than ${expected} but got ${actual}",
+               {expected:expected, actual:actual});
+    };
+    expose(assert_greater_than, "assert_greater_than");
+
+    function assert_less_than_equal(actual, expected, description)
+    {
+        /*
+         * Test if a primitive number is less than or equal to another
+         */
+        assert(typeof actual === "number",
+               "assert_less_than_equal", description,
+               "expected a number but got a ${type_actual}",
+               {type_actual:typeof actual});
+
+        assert(actual <= expected,
+               "assert_less_than", description,
+               "expected a number less than or equal to ${expected} but got ${actual}",
+               {expected:expected, actual:actual});
+    };
+    expose(assert_less_than_equal, "assert_less_than_equal");
+
+    function assert_greater_than_equal(actual, expected, description)
+    {
+        /*
+         * Test if a primitive number is greater than or equal to another
+         */
+        assert(typeof actual === "number",
+               "assert_greater_than_equal", description,
+               "expected a number but got a ${type_actual}",
+               {type_actual:typeof actual});
+
+        assert(actual >= expected,
+               "assert_greater_than_equal", description,
+               "expected a number greater than or equal to ${expected} but got ${actual}",
+               {expected:expected, actual:actual});
+    };
+    expose(assert_greater_than_equal, "assert_greater_than_equal");
+
+    function assert_regexp_match(actual, expected, description) {
+        /*
+         * Test if a string (actual) matches a regexp (expected)
+         */
+        assert(expected.test(actual),
+               "assert_regexp_match", description,
+               "expected ${expected} but got ${actual}",
+               {expected:expected, actual:actual});
+    }
+    expose(assert_regexp_match, "assert_regexp_match");
+
+    function assert_class_string(object, class_string, description) {
+        assert_equals({}.toString.call(object), "[object " + class_string + "]",
+                      description);
+    }
+    expose(assert_class_string, "assert_class_string");
+
+
+    function _assert_own_property(name) {
+        return function(object, property_name, description)
+        {
+            assert(object.hasOwnProperty(property_name),
+                   name, description,
+                   "expected property ${p} missing", {p:property_name});
+        };
+    }
+    expose(_assert_own_property("assert_exists"), "assert_exists");
+    expose(_assert_own_property("assert_own_property"), "assert_own_property");
+
+    function assert_not_exists(object, property_name, description)
+    {
+        assert(!object.hasOwnProperty(property_name),
+               "assert_not_exists", description,
+               "unexpected property ${p} found", {p:property_name});
+    };
+    expose(assert_not_exists, "assert_not_exists");
+
+    function _assert_inherits(name) {
+        return function (object, property_name, description)
+        {
+            assert(typeof object === "object",
+                   name, description,
+                   "provided value is not an object");
+
+            assert("hasOwnProperty" in object,
+                   name, description,
+                   "provided value is an object but has no hasOwnProperty method");
+
+            assert(!object.hasOwnProperty(property_name),
+                   name, description,
+                   "property ${p} found on object expected in prototype chain",
+                   {p:property_name});
+
+            assert(property_name in object,
+                   name, description,
+                   "property ${p} not found in prototype chain",
+                   {p:property_name});
+        };
+    }
+    expose(_assert_inherits("assert_inherits"), "assert_inherits");
+    expose(_assert_inherits("assert_idl_attribute"), "assert_idl_attribute");
+
+    function assert_readonly(object, property_name, description)
+    {
+         var initial_value = object[property_name];
+         try {
+             //Note that this can have side effects in the case where
+             //the property has PutForwards
+             object[property_name] = initial_value + "a"; //XXX use some other value here?
+             assert(same_value(object[property_name], initial_value),
+                    "assert_readonly", description,
+                    "changing property ${p} succeeded",
+                    {p:property_name});
+         }
+         finally
+         {
+             object[property_name] = initial_value;
+         }
+    };
+    expose(assert_readonly, "assert_readonly");
+
+    function assert_throws(code, func, description)
+    {
+        try
+        {
+            func.call(this);
+            assert(false, "assert_throws", description,
+                   "${func} did not throw", {func:func});
+        }
+        catch(e)
+        {
+            if (e instanceof AssertionError) {
+                throw(e);
+            }
+            if (code === null)
+            {
+                return;
+            }
+            if (typeof code === "object")
+            {
+                assert(typeof e == "object" && "name" in e && e.name == code.name,
+                       "assert_throws", description,
+                       "${func} threw ${actual} (${actual_name}) expected ${expected} (${expected_name})",
+                                    {func:func, actual:e, actual_name:e.name,
+                                     expected:code,
+                                     expected_name:code.name});
+                return;
+            }
+
+            var code_name_map = {
+                INDEX_SIZE_ERR: 'IndexSizeError',
+                HIERARCHY_REQUEST_ERR: 'HierarchyRequestError',
+                WRONG_DOCUMENT_ERR: 'WrongDocumentError',
+                INVALID_CHARACTER_ERR: 'InvalidCharacterError',
+                NO_MODIFICATION_ALLOWED_ERR: 'NoModificationAllowedError',
+                NOT_FOUND_ERR: 'NotFoundError',
+                NOT_SUPPORTED_ERR: 'NotSupportedError',
+                INVALID_STATE_ERR: 'InvalidStateError',
+                SYNTAX_ERR: 'SyntaxError',
+                INVALID_MODIFICATION_ERR: 'InvalidModificationError',
+                NAMESPACE_ERR: 'NamespaceError',
+                INVALID_ACCESS_ERR: 'InvalidAccessError',
+                TYPE_MISMATCH_ERR: 'TypeMismatchError',
+                SECURITY_ERR: 'SecurityError',
+                NETWORK_ERR: 'NetworkError',
+                ABORT_ERR: 'AbortError',
+                URL_MISMATCH_ERR: 'URLMismatchError',
+                QUOTA_EXCEEDED_ERR: 'QuotaExceededError',
+                TIMEOUT_ERR: 'TimeoutError',
+                INVALID_NODE_TYPE_ERR: 'InvalidNodeTypeError',
+                DATA_CLONE_ERR: 'DataCloneError'
+            };
+
+            var name = code in code_name_map ? code_name_map[code] : code;
+
+            var name_code_map = {
+                IndexSizeError: 1,
+                HierarchyRequestError: 3,
+                WrongDocumentError: 4,
+                InvalidCharacterError: 5,
+                NoModificationAllowedError: 7,
+                NotFoundError: 8,
+                NotSupportedError: 9,
+                InvalidStateError: 11,
+                SyntaxError: 12,
+                InvalidModificationError: 13,
+                NamespaceError: 14,
+                InvalidAccessError: 15,
+                TypeMismatchError: 17,
+                SecurityError: 18,
+                NetworkError: 19,
+                AbortError: 20,
+                URLMismatchError: 21,
+                QuotaExceededError: 22,
+                TimeoutError: 23,
+                InvalidNodeTypeError: 24,
+                DataCloneError: 25,
+
+                UnknownError: 0,
+                ConstraintError: 0,
+                DataError: 0,
+                TransactionInactiveError: 0,
+                ReadOnlyError: 0,
+                VersionError: 0
+            };
+
+            if (!(name in name_code_map))
+            {
+                throw new AssertionError('Test bug: unrecognized DOMException code "' + code + '" passed to assert_throws()');
+            }
+
+            var required_props = { code: name_code_map[name] };
+
+            if (required_props.code === 0
+            || ("name" in e && e.name !== e.name.toUpperCase() && e.name !== "DOMException"))
+            {
+                // New style exception: also test the name property.
+                required_props.name = name;
+            }
+
+            //We'd like to test that e instanceof the appropriate interface,
+            //but we can't, because we don't know what window it was created
+            //in.  It might be an instanceof the appropriate interface on some
+            //unknown other window.  TODO: Work around this somehow?
+
+            assert(typeof e == "object",
+                   "assert_throws", description,
+                   "${func} threw ${e} with type ${type}, not an object",
+                   {func:func, e:e, type:typeof e});
+
+            for (var prop in required_props)
+            {
+                assert(typeof e == "object" && prop in e && e[prop] == required_props[prop],
+                       "assert_throws", description,
+                       "${func} threw ${e} that is not a DOMException " + code + ": property ${prop} is equal to ${actual}, expected ${expected}",
+                       {func:func, e:e, prop:prop, actual:e[prop], expected:required_props[prop]});
+            }
+        }
+    }
+    expose(assert_throws, "assert_throws");
+
+    function assert_unreached(description) {
+         assert(false, "assert_unreached", description,
+                "Reached unreachable code");
+    }
+    expose(assert_unreached, "assert_unreached");
+
+    function assert_any(assert_func, actual, expected_array)
+    {
+        var args = [].slice.call(arguments, 3)
+        var errors = []
+        var passed = false;
+        forEach(expected_array,
+                function(expected)
+                {
+                    try {
+                        assert_func.apply(this, [actual, expected].concat(args))
+                        passed = true;
+                    } catch(e) {
+                        errors.push(e.message);
+                    }
+                });
+        if (!passed) {
+            throw new AssertionError(errors.join("\n\n"));
+        }
+    }
+    expose(assert_any, "assert_any");
+
+    function Test(name, properties)
+    {
+        this.name = name;
+        this.status = this.NOTRUN;
+        this.timeout_id = null;
+        this.is_done = false;
+
+        this.properties = properties;
+        this.timeout_length = properties.timeout ? properties.timeout : settings.test_timeout;
+
+        this.message = null;
+
+        var this_obj = this;
+        this.steps = [];
+
+        tests.push(this);
+    }
+
+    Test.statuses = {
+        PASS:0,
+        FAIL:1,
+        TIMEOUT:2,
+        NOTRUN:3
+    };
+
+    Test.prototype = merge({}, Test.statuses);
+
+    Test.prototype.structured_clone = function()
+    {
+        if(!this._structured_clone)
+        {
+            var msg = this.message;
+            msg = msg ? String(msg) : msg;
+            this._structured_clone = merge({
+                name:String(this.name),
+                status:this.status,
+                message:msg
+            }, Test.statuses);
+        }
+        return this._structured_clone;
+    };
+
+    Test.prototype.step = function(func, this_obj)
+    {
+        //In case the test has already failed
+        if (this.status !== this.NOTRUN)
+        {
+          return;
+        }
+
+        tests.started = true;
+
+        if (this.timeout_id === null) {
+            this.set_timeout();
+        }
+
+        this.steps.push(func);
+
+        if (arguments.length === 1)
+        {
+            this_obj = this;
+        }
+
+        try
+        {
+            return func.apply(this_obj, Array.prototype.slice.call(arguments, 2));
+        }
+        catch(e)
+        {
+            //This can happen if something called synchronously invoked another
+            //step
+            if (this.status !== this.NOTRUN)
+            {
+                return;
+            }
+            this.status = this.FAIL;
+            this.message = (typeof e === "object" && e !== null) ? e.message : e;
+            if (typeof e.stack != "undefined" && typeof e.message == "string") {
+                //Try to make it more informative for some exceptions, at least
+                //in Gecko and WebKit.  This results in a stack dump instead of
+                //just errors like "Cannot read property 'parentNode' of null"
+                //or "root is null".  Makes it a lot longer, of course.
+                this.message += "(stack: {code}" + e.stack + "{/code})";
+            }
+            this.done();
+            if (debug && e.constructor !== AssertionError) {
+                throw e;
+            }
+        }
+    };
+
+    Test.prototype.step_func = function(func, this_obj)
+    {
+        var test_this = this;
+
+        if (arguments.length === 1)
+        {
+            this_obj = test_this;
+        }
+
+        return function()
+        {
+            test_this.step.apply(test_this, [func, this_obj].concat(
+                Array.prototype.slice.call(arguments)));
+        };
+    };
+
+    Test.prototype.step_func_done = function(func, this_obj)
+    {
+        var test_this = this;
+
+        if (arguments.length === 1)
+        {
+            this_obj = test_this;
+        }
+
+        return function()
+        {
+            test_this.step.apply(test_this, [func, this_obj].concat(
+                Array.prototype.slice.call(arguments)));
+            test_this.done();
+        };
+    };
+
+    Test.prototype.set_timeout = function()
+    {
+        var this_obj = this;
+        this.timeout_id = setTimeout(function()
+                                     {
+                                         this_obj.timeout();
+                                     }, this.timeout_length);
+    };
+
+    Test.prototype.timeout = function()
+    {
+        this.status = this.TIMEOUT;
+        this.timeout_id = null;
+        this.message = "Test timed out";
+        this.done();
+    };
+
+    Test.prototype.done = function()
+    {
+        if (this.is_done) {
+            return;
+        }
+        clearTimeout(this.timeout_id);
+        if (this.status === this.NOTRUN)
+        {
+            this.status = this.PASS;
+        }
+        this.is_done = true;
+        tests.result(this);
+    };
+
+
+    /*
+     * Harness
+     */
+
+    function TestsStatus()
+    {
+        this.status = null;
+        this.message = null;
+    }
+
+    TestsStatus.statuses = {
+        OK:0,
+        ERROR:1,
+        TIMEOUT:2
+    };
+
+    TestsStatus.prototype = merge({}, TestsStatus.statuses);
+
+    TestsStatus.prototype.structured_clone = function()
+    {
+        if(!this._structured_clone)
+        {
+            var msg = this.message;
+            msg = msg ? String(msg) : msg;
+            this._structured_clone = merge({
+                status:this.status,
+                message:msg
+            }, TestsStatus.statuses);
+        }
+        return this._structured_clone;
+    };
+
+    function Tests()
+    {
+        this.tests = [];
+        this.num_pending = 0;
+
+        this.phases = {
+            INITIAL:0,
+            SETUP:1,
+            HAVE_TESTS:2,
+            HAVE_RESULTS:3,
+            COMPLETE:4
+        };
+        this.phase = this.phases.INITIAL;
+
+        this.properties = {};
+
+//        //All tests can't be done until the load event fires
+        this.all_loaded = true;
+        this.wait_for_finish = true;
+        this.processing_callbacks = false;
+
+        this.timeout_length = settings.timeout;
+        this.timeout_id = null;
+
+        this.start_callbacks = [];
+        this.test_done_callbacks = [];
+        this.all_done_callbacks = [];
+
+        this.status = new TestsStatus();
+
+//        var this_obj = this;
+//
+//        on_event(window, "load",
+//                 function()
+//                 {
+//                     this_obj.all_loaded = true;
+//                     if (this_obj.all_done())
+//                     {
+//                         this_obj.complete();
+//                     }
+//                 });
+//
+//        this.set_timeout();
+    }
+
+    Tests.prototype.setup = function(func, properties)
+    {
+//        if (this.phase >= this.phases.HAVE_RESULTS)
+//        {
+//            return;
+//        }
+//        if (this.phase < this.phases.SETUP)
+//        {
+//            this.phase = this.phases.SETUP;
+//        }
+//
+//        for (var p in properties)
+//        {
+//            if (properties.hasOwnProperty(p))
+//            {
+//                this.properties[p] = properties[p];
+//            }
+//        }
+//
+//        if (properties.timeout)
+//        {
+//            this.timeout_length = properties.timeout;
+//        }
+//        if (properties.explicit_done)
+//        {
+//            this.wait_for_finish = true;
+//        }
+//        if (properties.explicit_timeout) {
+//            this.timeout_length = null;
+//        }
+//
+//        if (func)
+//        {
+//            try
+//            {
+//                func();
+//            } catch(e)
+//            {
+//                this.status.status = this.status.ERROR;
+//                this.status.message = e;
+//            };
+//        }
+//        this.set_timeout();
+    };
+
+    Tests.prototype.set_timeout = function()
+    {
+        var this_obj = this;
+        clearTimeout(this.timeout_id);
+        if (this.timeout_length !== null)
+        {
+            this.timeout_id = setTimeout(function() {
+                                             this_obj.timeout();
+                                         }, this.timeout_length);
+        }
+    };
+
+    Tests.prototype.timeout = function() {
+        this.status.status = this.status.TIMEOUT;
+        this.complete();
+    };
+
+    Tests.prototype.end_wait = function()
+    {
+        this.wait_for_finish = false;
+        if (this.all_done()) {
+            this.complete();
+        }
+    };
+
+    Tests.prototype.push = function(test)
+    {
+        if (this.phase < this.phases.HAVE_TESTS) {
+            this.start();
+        }
+        this.num_pending++;
+        this.tests.push(test);
+    };
+
+    Tests.prototype.all_done = function() {
+        return (this.all_loaded && this.num_pending === 0 &&
+                !this.wait_for_finish && !this.processing_callbacks);
+    };
+
+    Tests.prototype.start = function() {
+        this.phase = this.phases.HAVE_TESTS;
+        this.notify_start();
+    };
+
+    Tests.prototype.notify_start = function() {
+        var this_obj = this;
+        forEach (this.start_callbacks,
+                 function(callback)
+                 {
+                     callback(this_obj.properties);
+                 });
+        forEach_windows(
+                function(w, is_same_origin)
+                {
+                    if(is_same_origin && w.start_callback)
+                    {
+                        try
+                        {
+                            w.start_callback(this_obj.properties);
+                        }
+                        catch(e)
+                        {
+                            if (debug)
+                            {
+                                throw(e);
+                            }
+                        }
+                    }
+                    if (supports_post_message(w) && w !== self)
+                    {
+                        w.postMessage({
+                            type: "start",
+                            properties: this_obj.properties
+                        }, "*");
+                    }
+                });
+    };
+
+    Tests.prototype.result = function(test)
+    {
+        if (this.phase > this.phases.HAVE_RESULTS)
+        {
+            return;
+        }
+        this.phase = this.phases.HAVE_RESULTS;
+        this.num_pending--;
+        this.notify_result(test);
+    };
+
+    Tests.prototype.notify_result = function(test) {
+        var this_obj = this;
+        this.processing_callbacks = true;
+        forEach(this.test_done_callbacks,
+                function(callback)
+                {
+                    callback(test, this_obj);
+                });
+
+        forEach_windows(
+                function(w, is_same_origin)
+                {
+                    if(is_same_origin && w.result_callback)
+                    {
+                        try
+                        {
+                            w.result_callback(test);
+                        }
+                        catch(e)
+                        {
+                            if(debug) {
+                                throw e;
+                            }
+                        }
+                    }
+                    if (supports_post_message(w) && w !== self)
+                    {
+                        w.postMessage({
+                            type: "result",
+                            test: test.structured_clone()
+                        }, "*");
+                    }
+                });
+        this.processing_callbacks = false;
+        if (this_obj.all_done())
+        {
+            this_obj.complete();
+        }
+    };
+
+    Tests.prototype.complete = function() {
+        if (this.phase === this.phases.COMPLETE) {
+            return;
+        }
+        this.phase = this.phases.COMPLETE;
+        var this_obj = this;
+        this.tests.forEach(
+            function(x)
+            {
+                if(x.status === x.NOTRUN)
+                {
+                    this_obj.notify_result(x);
+                }
+            }
+        );
+        this.notify_complete();
+    };
+
+    Tests.prototype.notify_complete = function()
+    {
+        clearTimeout(this.timeout_id);
+        var this_obj = this;
+        var tests = map(this_obj.tests,
+                        function(test)
+                        {
+                            return test.structured_clone();
+                        });
+        if (this.status.status === null)
+        {
+            this.status.status = this.status.OK;
+        }
+
+        forEach (this.all_done_callbacks,
+                 function(callback)
+                 {
+                     callback(this_obj.tests, this_obj.status);
+                 });
+
+        forEach_windows(
+                function(w, is_same_origin)
+                {
+                    if(is_same_origin && w.completion_callback)
+                    {
+                        try
+                        {
+                            w.completion_callback(this_obj.tests, this_obj.status);
+                        }
+                        catch(e)
+                        {
+                            if (debug)
+                            {
+                                throw e;
+                            }
+                        }
+                    }
+                    if (supports_post_message(w) && w !== self)
+                    {
+                        w.postMessage({
+                            type: "complete",
+                            tests: tests,
+                            status: this_obj.status.structured_clone()
+                        }, "*");
+                    }
+                });
+    };
+
+    var tests = new Tests();
+
+    function timeout() {
+        if (tests.timeout_length === null)
+        {
+            tests.timeout();
+        }
+    }
+    expose(timeout, 'timeout');
+
+    function add_start_callback(callback) {
+        tests.start_callbacks.push(callback);
+    }
+
+    function add_result_callback(callback)
+    {
+        tests.test_done_callbacks.push(callback);
+    }
+
+    function add_completion_callback(callback)
+    {
+       tests.all_done_callbacks.push(callback);
+    }
+
+    expose(add_start_callback, 'add_start_callback');
+    expose(add_result_callback, 'add_result_callback');
+    expose(add_completion_callback, 'add_completion_callback');
+
+    /*
+     * Output listener
+    */
+
+    function Output() {
+      var startTime = new Date().toISOString().replace(/:/g, '-');
+      startTime = startTime.substr(0, startTime.indexOf('.'));
+
+      this.log_document = '/tmp/log-tct-' + startTime + '.log';
+      this.summary_document = '/tmp/summary-tct-' + startTime + '.html';
+      this.done_count = 0;
+      this.enabled = settings.output;
+      this.phase = this.INITIAL;
+      this.fs = requireTCT('fs');
+      console.log(this.fs);
+
+      console.log('Log will be saved to: ' + this.log_document);
+      console.log('Summary will be saved to: ' + this.summary_document);
+    }
+
+    Output.prototype.INITIAL = 0;
+    Output.prototype.STARTED = 1;
+    Output.prototype.HAVE_RESULTS = 2;
+    Output.prototype.COMPLETE = 3;
+
+    Output.prototype.setup = function(properties) {
+        if (this.phase > this.INITIAL) {
+            return;
+        }
+
+        //If output is disabled in testharnessreport.js the test shouldn't be
+        //able to override that
+        this.enabled = this.enabled && (properties.hasOwnProperty("output") ?
+                                        properties.output : settings.output);
+    };
+
+    Output.prototype.init = function(properties)
+    {
+        if (this.phase >= this.STARTED) {
+            return;
+        }
+        this.phase = this.STARTED;
+    };
+
+    Output.prototype.log = function(message)
+    {
+        console.log(message);
+        this.fs.appendFileSync(this.log_document, message + '\n');
+    };
+
+    Output.prototype.summary = function(message)
+    {
+        this.fs.appendFileSync(this.summary_document, message + '\n');
+    };
+
+    var status_text = {};
+    status_text[Test.prototype.PASS] = "Pass";
+    status_text[Test.prototype.FAIL] = "Fail";
+    status_text[Test.prototype.TIMEOUT] = "Timeout";
+    status_text[Test.prototype.NOTRUN] = "Not Run";
+
+    Output.prototype.show_status = function(test)
+    {
+        this.log('------------------------------------------------------------------------------');
+        this.log('Result of test "' + test.name + '": ' + status_text[test.status]);
+        this.log(test.message);
+        this.log('------------------------------------------------------------------------------');
+        if (this.phase < this.STARTED)
+        {
+            this.init();
+        }
+        if (!this.enabled)
+        {
+            return;
+        }
+        if (this.phase < this.HAVE_RESULTS)
+        {
+            this.phase = this.HAVE_RESULTS;
+        }
+        this.done_count++;
+
+        this.log("Running, " + this.done_count + " complete");
+    };
+
+    Output.prototype.show_results = function (tests, harness_status)
+    {
+        if (this.phase >= this.COMPLETE) {
+            return;
+        }
+        if (!this.enabled)
+        {
+            return;
+        }
+        this.phase = this.COMPLETE;
+
+        var status_number = {};
+        forEach(tests, function(test) {
+                    var status = status_text[test.status];
+                    if (status_number.hasOwnProperty(status))
+                    {
+                        status_number[status] += 1;
+                    } else {
+                        status_number[status] = 1;
+                    }
+                });
+
+        function status_class(status)
+        {
+            return status.replace(/\s/g, '').toLowerCase();
+        }
+
+        var summary_template = ["section", {"id":"summary"},
+                                ["h2", {}, "Summary"],
+                                ["p", {}, "Found ${num_tests} tests"],
+                                function(vars) {
+                                    var rv = [["div", {}]];
+                                    var i=0;
+                                    while (status_text.hasOwnProperty(i)) {
+                                        if (status_number.hasOwnProperty(status_text[i])) {
+                                            var status = status_text[i];
+                                            rv[0].push(["div", {"class":status_class(status)},
+                                                        ["label", {},
+                                                         status_number[status] + " " + status]]);
+                                        }
+                                        i++;
+                                    }
+                                    return rv;
+                                }];
+//        log.appendChild(render(summary_template, {num_tests:tests.length}, output_document));
+
+        // This use of innerHTML plus manual escaping is not recommended in
+        // general, but is necessary here for performance.  Using textContent
+        // on each individual <td> adds tens of seconds of execution time for
+        // large test suites (tens of thousands of tests).
+        function escape_html(s)
+        {
+            return s.replace(/\&/g, "&amp;")
+                .replace(/</g, "&lt;")
+                .replace(/"/g, "&quot;")
+                .replace(/'/g, "&#39;")
+                .replace(/{code}/g, "<pre>")
+                .replace(/{\/code}/g, "</pre>");
+        }
+
+        function has_assertions()
+        {
+            for (var i = 0; i < tests.length; i++) {
+                if (tests[i].properties.hasOwnProperty("assert")) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        function get_assertion(test)
+        {
+            if (test.properties.hasOwnProperty("assert")) {
+                if (Array.isArray(test.properties.assert)) {
+                    return test.properties.assert.join(' ');
+                }
+                return test.properties.assert;
+            }
+            return '';
+        }
+
+        var assertions = has_assertions();
+        var html = "<!DOCTYPE html><html><head><style type=\"text/css\">";
+        this.summary(html);
+        this.summary(this.fs.readFileSync(__dirname + 'tct/common/testharness.css'));
+        html = "</style></head><body><div id=\"log\">";
+        this.summary(html);
+        this.summary(render(summary_template, {num_tests:tests.length}));
+        html = "<h2>Details</h2><table id='results' " + (assertions ? "class='assertions'" : "" ) + ">"
+            + "<thead><tr><th>Result</th><th>Test Name</th>"
+            + (assertions ? "<th>Assertion</th>" : "")
+            + "<th>Message</th></tr></thead>"
+            + "<tbody>";
+        this.summary(html);
+        for (var i = 0; i < tests.length; i++) {
+            html = '<tr class="'
+                + escape_html(status_class(status_text[tests[i].status]))
+                + '"><td>'
+                + escape_html(status_text[tests[i].status])
+                + "</td><td>"
+                + escape_html(tests[i].name)
+                + "</td><td>"
+                + (assertions ? escape_html(get_assertion(tests[i])) + "</td><td>" : "")
+                + escape_html(tests[i].message ? tests[i].message : " ")
+                + "</td></tr>";
+            this.summary(html);
+        }
+        html = "</tbody></table></div></body></html>";
+        this.summary(html);
+    };
+
+    var output = new Output();
+    add_start_callback(function (properties) {output.init(properties);});
+    add_result_callback(function (test) {output.show_status(test);});
+    add_completion_callback(function (tests, harness_status) {output.show_results(tests, harness_status);});
+
+    /*
+     * Template code
+     *
+     * A template is just a javascript structure. An element is represented as:
+     *
+     * [tag_name, {attr_name:attr_value}, child1, child2]
+     *
+     * the children can either be strings (which act like text nodes), other templates or
+     * functions (see below)
+     *
+     * A text node is represented as
+     *
+     * ["{text}", value]
+     *
+     * String values have a simple substitution syntax; ${foo} represents a variable foo.
+     *
+     * It is possible to embed logic in templates by using a function in a place where a
+     * node would usually go. The function must either return part of a template or null.
+     *
+     * In cases where a set of nodes are required as output rather than a single node
+     * with children it is possible to just use a list
+     * [node1, node2, node3]
+     *
+     * Usage:
+     *
+     * render(template, substitutions) - take a template and an object mapping
+     * variable names to parameters and return either a DOM node or a list of DOM nodes
+     *
+     * substitute(template, substitutions) - take a template and variable mapping object,
+     * make the variable substitutions and return the substituted template
+     *
+     */
+
+    function is_single_node(template)
+    {
+        return typeof template[0] === "string";
+    }
+
+    function substitute(template, substitutions)
+    {
+        if (typeof template === "function") {
+            var replacement = template(substitutions);
+            if (replacement)
+            {
+                var rv = substitute(replacement, substitutions);
+                return rv;
+            }
+            else
+            {
+                return null;
+            }
+        }
+        else if (is_single_node(template))
+        {
+            return substitute_single(template, substitutions);
+        }
+        else
+        {
+            return filter(map(template, function(x) {
+                                  return substitute(x, substitutions);
+                              }), function(x) {return x !== null;});
+        }
+    }
+
+    function substitute_single(template, substitutions)
+    {
+        var substitution_re = /\${([^ }]*)}/g;
+
+        function do_substitution(input) {
+            var components = input.split(substitution_re);
+            var rv = [];
+            for (var i=0; i<components.length; i+=2)
+            {
+                rv.push(components[i]);
+                if (components[i+1])
+                {
+                    rv.push(String(substitutions[components[i+1]]));
+                }
+            }
+            return rv;
+        }
+
+        var rv = [];
+        rv.push(do_substitution(String(template[0])).join(""));
+
+        if (template[0] === "{text}") {
+            substitute_children(template.slice(1), rv);
+        } else {
+            substitute_attrs(template[1], rv);
+            substitute_children(template.slice(2), rv);
+        }
+
+        function substitute_attrs(attrs, rv)
+        {
+            rv[1] = {};
+            for (var name in template[1])
+            {
+                if (attrs.hasOwnProperty(name))
+                {
+                    var new_name = do_substitution(name).join("");
+                    var new_value = do_substitution(attrs[name]).join("");
+                    rv[1][new_name] = new_value;
+                };
+            }
+        }
+
+        function substitute_children(children, rv)
+        {
+            for (var i=0; i<children.length; i++)
+            {
+                if (children[i] instanceof Object) {
+                    var replacement = substitute(children[i], substitutions);
+                    if (replacement !== null)
+                    {
+                        if (is_single_node(replacement))
+                        {
+                            rv.push(replacement);
+                        }
+                        else
+                        {
+                            extend(rv, replacement);
+                        }
+                    }
+                }
+                else
+                {
+                    extend(rv, do_substitution(String(children[i])));
+                }
+            }
+            return rv;
+        }
+
+        return rv;
+    }
+
+ function make_dom_single(template)
+ {
+     if (template[0] === "{text}")
+     {
+         var element = "";
+         for (var i=1; i<template.length; i++)
+         {
+             element += template[i];
+         }
+     }
+     else
+     {
+         var element = "<" + template[0];
+         for (var name in template[1]) {
+             if (template[1].hasOwnProperty(name))
+             {
+                 element += " " + name + "=\"" + template[1][name] + "\"";
+             }
+         }
+         element += ">";
+         for (var i=2; i<template.length; i++)
+         {
+             if (template[i] instanceof Object)
+             {
+                 var sub_element = make_dom(template[i]);
+                 element += sub_element;
+             }
+             else
+             {
+                 element += template[i];
+             }
+         }
+         element += "</" + template[0] + ">";
+     }
+
+     return element;
+ }
+
+
+
+ function make_dom(template, substitutions)
+    {
+        if (is_single_node(template))
+        {
+            return make_dom_single(template);
+        }
+        else
+        {
+            return map(template, function(x) {
+                           return make_dom_single(x);
+                       });
+        }
+    }
+
+ function render(template, substitutions)
+    {
+        return make_dom(substitute(template, substitutions));
+    }
+
+    /*
+     * Utility funcions
+     */
+    function assert(expected_true, function_name, description, error, substitutions)
+    {
+        if (expected_true !== true)
+        {
+            throw new AssertionError(make_message(function_name, description,
+                                                  error, substitutions));
+        }
+    }
+
+    function AssertionError(message)
+    {
+        this.message = message;
+    }
+
+    function make_message(function_name, description, error, substitutions)
+    {
+        for (var p in substitutions) {
+            if (substitutions.hasOwnProperty(p)) {
+                substitutions[p] = format_value(substitutions[p]);
+            }
+        }
+        var node_form = substitute(["{text}", "${function_name}: ${description}" + error],
+                                   merge({function_name:function_name,
+                                          description:(description?description + " ":"")},
+                                          substitutions));
+        return node_form.slice(1).join("");
+    }
+
+    function filter(array, callable, thisObj) {
+        var rv = [];
+        for (var i=0; i<array.length; i++)
+        {
+            if (array.hasOwnProperty(i))
+            {
+                var pass = callable.call(thisObj, array[i], i, array);
+                if (pass) {
+                    rv.push(array[i]);
+                }
+            }
+        }
+        return rv;
+    }
+
+    function map(array, callable, thisObj)
+    {
+        var rv = [];
+        rv.length = array.length;
+        for (var i=0; i<array.length; i++)
+        {
+            if (array.hasOwnProperty(i))
+            {
+                rv[i] = callable.call(thisObj, array[i], i, array);
+            }
+        }
+        return rv;
+    }
+
+    function extend(array, items)
+    {
+        Array.prototype.push.apply(array, items);
+    }
+
+    function forEach (array, callback, thisObj)
+    {
+        for (var i=0; i<array.length; i++)
+        {
+            if (array.hasOwnProperty(i))
+            {
+                callback.call(thisObj, array[i], i, array);
+            }
+        }
+    }
+
+    function merge(a,b)
+    {
+        var rv = {};
+        var p;
+        for (p in a)
+        {
+            rv[p] = a[p];
+        }
+        for (p in b) {
+            rv[p] = b[p];
+        }
+        return rv;
+    }
+
+    function expose(object, name)
+    {
+        var components = name.split(".");
+        var target = GLOBAL;
+        for (var i=0; i<components.length - 1; i++)
+        {
+            if (!(components[i] in target))
+            {
+                target[components[i]] = {};
+            }
+            target = target[components[i]];
+        }
+        target[components[components.length - 1]] = object;
+    }
+
+    expose(expose, 'expose');
+
+    function forEach_windows(callback) {
+        // Iterate of the the windows [self ... top, opener]. The callback is passed
+        // two objects, the first one is the windows object itself, the second one
+        // is a boolean indicating whether or not its on the same origin as the
+        // current window.
+        /*var cache = forEach_windows.result_cache;
+        if (!cache) {
+            cache = [[self, true]];
+            var w = self;
+            var i = 0;
+            var so;
+            var origins = location.ancestorOrigins;
+            while (w != w.parent)
+            {
+                w = w.parent;
+                // In WebKit, calls to parent windows' properties that aren't on the same
+                // origin cause an error message to be displayed in the error console but
+                // don't throw an exception. This is a deviation from the current HTML5
+                // spec. See: https://bugs.webkit.org/show_bug.cgi?id=43504
+                // The problem with WebKit's behavior is that it pollutes the error console
+                // with error messages that can't be caught.
+                //
+                // This issue can be mitigated by relying on the (for now) proprietary
+                // `location.ancestorOrigins` property which returns an ordered list of
+                // the origins of enclosing windows. See:
+                // http://trac.webkit.org/changeset/113945.
+                if(origins) {
+                    so = (location.origin == origins[i]);
+                }
+                else
+                {
+                    so = is_same_origin(w);
+                }
+                cache.push([w, so]);
+                i++;
+            }
+            w = window.opener;
+            if(w)
+            {
+                // window.opener isn't included in the `location.ancestorOrigins` prop.
+                // We'll just have to deal with a simple check and an error msg on WebKit
+                // browsers in this case.
+                cache.push([w, is_same_origin(w)]);
+            }
+            forEach_windows.result_cache = cache;
+        }
+
+        forEach(cache,
+                function(a)
+                {
+                    callback.apply(null, a);
+                });*/
+    }
+
+    function is_same_origin(w) {
+        try {
+            'random_prop' in w;
+            return true;
+        } catch(e) {
+            return false;
+        }
+    }
+
+    function supports_post_message(w)
+    {
+        var supports;
+        var type;
+        // Given IE  implements postMessage across nested iframes but not across
+        // windows or tabs, you can't infer cross-origin communication from the presence
+        // of postMessage on the current window object only.
+        //
+        // Touching the postMessage prop on a window can throw if the window is
+        // not from the same origin AND post message is not supported in that
+        // browser. So just doing an existence test here won't do, you also need
+        // to wrap it in a try..cacth block.
+        try
+        {
+            type = typeof w.postMessage;
+            if (type === "function")
+            {
+                supports = true;
+            }
+            // IE8 supports postMessage, but implements it as a host object which
+            // returns "object" as its `typeof`.
+            else if (type === "object")
+            {
+                supports = true;
+            }
+            // This is the case where postMessage isn't supported AND accessing a
+            // window property across origins does NOT throw (e.g. old Safari browser).
+            else
+            {
+                supports = false;
+            }
+        }
+        catch(e) {
+            // This is the case where postMessage isn't supported AND accessing a
+            // window property across origins throws (e.g. old Firefox browser).
+            supports = false;
+        }
+        return supports;
+    }
+})();
+
+/*
+ *For blacklist
+ */
+
+function is_platform_supported(name)
+{
+    var ret = true;
+
+    if (not_support_list.indexOf(name) >= 0)
+        ret = false;
+
+    return ret;
+}
+
+// vim: set expandtab shiftwidth=4 tabstop=4:
diff --git a/webWidgetTCT_device/test/tct/common/unitcommon.js b/webWidgetTCT_device/test/tct/common/unitcommon.js
new file mode 100755 (executable)
index 0000000..368924c
--- /dev/null
@@ -0,0 +1,620 @@
+/*
+
+Copyright (c) 2013 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+
+
+Authors:
+
+ */
+
+
+MIN_BYTE = -128;
+MAX_BYTE = 127;
+MIN_OCTET = 0;
+MAX_OCTET = 255;
+MIN_SHORT = -32768;
+MAX_SHORT = 32767;
+MIN_UNSIGNED_SHORT = 0;
+MAX_UNSIGNED_SHORT = 65535;
+MIN_LONG = -2147483648;
+MAX_LONG = 2147483647;
+MIN_UNSIGNED_LONG = 0;
+MAX_UNSIGNED_LONG = 4294967295;
+MIN_LONG_LONG = -9223372036854775808;
+MAX_LONG_LONG = 9223372036854775807;
+MIN_UNSIGNED_LONG_LONG = 0;
+MAX_UNSIGNED_LONG_LONG = 18446744073709551615;
+
+TYPE_MISMATCH_EXCEPTION = {name: 'TypeMismatchError'};
+NOT_FOUND_EXCEPTION = {name: 'NotFoundError'};
+INVALID_VALUES_EXCEPTION = {name: 'InvalidValuesError'};
+UNKNOWN_EXCEPTION = {name: 'UnknownError'};
+IO_EXCEPTION = {name: 'IOError'};
+SECURITY_EXCEPTION = {name: 'SecurityError'};
+
+
+var _registered_types = {};
+
+function _resolve_registered_type(type) {
+    while (type in _registered_types) {
+        type = _registered_types[type];
+    }
+    return type;
+}
+
+/**
+ * Method checks extra argument for none argument method.
+ * The only check is that method will not throw an exception.
+ * Example usage:
+ * checkExtraArgument(tizen.notification, "removeAll");
+ *
+ * @param object object
+ * @param methodName string - name of the method
+ */
+function checkExtraArgument(object, methodName) {
+    var extraArgument = [
+        null,
+        undefined,
+        "Tizen",
+        1,
+        false,
+        ["one", "two"],
+        {argument: 1},
+        function () {}
+    ], i;
+
+    for (i = 0; i < extraArgument.length; i++) {
+        object[methodName](extraArgument[i]);
+    }
+}
+
+expose(checkExtraArgument, 'checkExtraArgument');
+
+/**
+ * Method to validate conversion for Domstrings.
+ * Example usage:
+ *
+ * var conversionArr = getDOMStringConversionArray(false);
+ *
+ * for(i = 0; i < conversionArr.length; i++){
+ *    alarmId = conversionArr[i];
+ *    assert_throws(NOT_FOUND_EXCEPTION, function(){
+ *        tAlarm = tizen.alarm.get(alarmId);
+ *    }, "NotFound exception should be thrown");
+ * }
+ *
+ *
+ * @param isOptional
+ * @returns array which contain various kind of value
+ *
+ */
+function getDOMStringConversionArray(isOptional) {
+    var typeArr = [false, true, NaN, 0, undefined, [1,2], {"a":1,"b":2}, function(){} ];
+    if (!isOptional) {
+        typeArr.push(null);
+    }
+    return typeArr;
+}
+
+/**
+ * Method to validate conversion.
+ * Example usage:
+ *   conversionTable = getTypeConversionExceptions("functionObject", true);
+ *   for(i = 0; i < conversionTable.length; i++) {
+ *       errorCallback = conversionTable[i][0];
+ *       exceptionName = conversionTable[i][1];
+ *
+ *       assert_throws({name : exceptionName},
+ *       function () {
+ *           tizen.systemsetting.setProperty("HOME_SCREEN",
+ *               propertyValue, successCallback, errorCallback);
+ *       }, exceptionName + " should be thrown - given incorrect errorCallback.");
+ *   }
+ *
+ * @param conversionType
+ * @param isOptional
+ * @returns table of tables which contain value (index 0) and exceptionName (index 1)
+ *
+ */
+function getTypeConversionExceptions(conversionType, isOptional) {
+    var exceptionName = "TypeMismatchError",
+        conversionTable;
+    switch (conversionType) {
+        case "enum":
+            conversionTable = [
+                [undefined, exceptionName],
+                [null, exceptionName],
+                [0, exceptionName],
+                [true, exceptionName],
+                ["dummyInvalidEnumValue", exceptionName],
+                [{ }, exceptionName]
+            ];
+            if (!isOptional) {
+                conversionTable.push([null, exceptionName]);
+            }
+            break;
+        case "double":
+            conversionTable = [
+                [undefined, exceptionName],
+                [NaN, exceptionName],
+                [Number.POSITIVE_INFINITY, exceptionName],
+                [Number.NEGATIVE_INFINITY, exceptionName],
+                ["TIZEN", exceptionName],
+                [{ name : "TIZEN" }, exceptionName],
+                [function () { }, exceptionName]
+            ];
+            break;
+        case "long":
+            conversionTable = [
+                [undefined, exceptionName],
+                ["TIZEN", exceptionName],
+                [{ name : "TIZEN" }, exceptionName],
+                [function () { }, exceptionName]
+            ];
+            break;
+        case "object":
+            conversionTable = [
+                [true, exceptionName],
+                [false, exceptionName],
+                [NaN, exceptionName],
+                [0, exceptionName],
+                ["", exceptionName],
+                ["TIZEN", exceptionName],
+                [undefined, exceptionName]
+            ];
+            if (!isOptional) {
+                conversionTable.push([null, exceptionName]);
+            }
+            break;
+        case "functionObject":
+            conversionTable = [
+                [true, exceptionName],
+                [false, exceptionName],
+                [NaN, exceptionName],
+                [0, exceptionName],
+                ["", exceptionName],
+                ["TIZEN", exceptionName],
+                [[], exceptionName],
+                [{ }, exceptionName],
+                [undefined, exceptionName]
+            ];
+            if (!isOptional) {
+                conversionTable.push([null, exceptionName]);
+            }
+            break;
+        case "array":
+            conversionTable = [
+                [true, exceptionName],
+                [false, exceptionName],
+                [NaN, exceptionName],
+                [0, exceptionName],
+                ["", exceptionName],
+                ["TIZEN", exceptionName],
+                [{ }, exceptionName],
+                [function () { }, exceptionName],
+                [undefined, exceptionName]
+            ];
+            if (!isOptional) {
+                conversionTable.push([null, exceptionName]);
+            }
+            break;
+        case "dictionary":
+            conversionTable = [
+                [true, exceptionName],
+                [false, exceptionName],
+                [NaN, exceptionName],
+                [0, exceptionName],
+                ["", exceptionName],
+                ["TIZEN", exceptionName],
+                [undefined, exceptionName]
+            ];
+            if (!isOptional) {
+                conversionTable.push([null, exceptionName]);
+            }
+            break;
+        default:
+            assert_unreached("Fix your test. Wrong conversionType '" + conversionType + "'.");
+    };
+
+    return conversionTable;
+}
+
+expose(getTypeConversionExceptions, 'getTypeConversionExceptions');
+
+
+function assert_type(obj, type, description) {
+    var org_type = type, prop_name, prop_type, prop_value;
+
+    type = _resolve_registered_type(type);
+
+    if (typeof (type) === 'string') {
+        type = type.toLowerCase();
+        switch (type) {
+            case 'object':
+            case 'string':
+            case 'number':
+            case 'function':
+            case 'boolean':
+            case 'undefined':
+            case 'xml':
+                assert_equals(typeof (obj), type, description);
+                break;
+            case 'null':
+                assert_true(obj === null, description);
+                break;
+            case 'array':
+                assert_true(Array.isArray(obj), description);
+                break;
+            case 'date':
+                assert_true(obj instanceof Date, description);
+                break;
+            case 'byte':
+                assert_equals(typeof (obj), 'number', description);
+                assert_greater_than_equal(obj, MIN_BYTE, description + " - value too low.");
+                assert_less_than_equal(obj, MAX_BYTE, description + " - value too high.");
+                assert_equals(Math.abs(obj % 1), 0, description + " - value is not an integer.");
+                break;
+            case 'octet':
+                assert_equals(typeof (obj), 'number', description);
+                assert_greater_than_equal(obj, MIN_OCTET, description + " - value too low.");
+                assert_less_than_equal(obj, MAX_OCTET, description + " - value too high.");
+                assert_equals(obj % 1, 0, description + " - value is not an integer.");
+                break;
+            case 'short':
+                assert_equals(typeof (obj), 'number', description);
+                assert_greater_than_equal(obj, MIN_SHORT, description + " - value too low.");
+                assert_less_than_equal(obj, MAX_SHORT, description + " - value too high.");
+                assert_equals(Math.abs(obj % 1), 0, description + " - value is not an integer.");
+                break;
+            case 'unsigned short':
+                assert_equals(typeof (obj), 'number', description);
+                assert_greater_than_equal(obj, MIN_UNSIGNED_SHORT, description + " - value too low.");
+                assert_less_than_equal(obj, MAX_UNSIGNED_SHORT, description + " - value too high.");
+                assert_equals(obj % 1, 0, description + " - value is not an integer.");
+                break;
+            case 'long':
+                assert_equals(typeof (obj), 'number', description);
+                assert_greater_than_equal(obj, MIN_LONG, description + " - value too low.");
+                assert_less_than_equal(obj, MAX_LONG, description + " - value too high.");
+                assert_equals(Math.abs(obj % 1), 0, description + " - value is not an integer.");
+                break;
+            case 'unsigned long':
+                assert_equals(typeof (obj), 'number', description);
+                assert_greater_than_equal(obj, MIN_UNSIGNED_LONG, description + " - value too low.");
+                assert_less_than_equal(obj, MAX_UNSIGNED_LONG, description + " - value too high.");
+                assert_equals(obj % 1, 0, description + " - value is not an integer.");
+                break;
+            case 'long long':
+                assert_equals(typeof (obj), 'number', description);
+                assert_greater_than_equal(obj, MIN_LONG_LONG, description + " - value too low.");
+                assert_less_than_equal(obj, MAX_LONG_LONG, description + " - value too high.");
+                assert_equals(Math.abs(obj % 1), 0, description + " - value is not an integer.");
+                break;
+            case 'unsigned long long':
+                assert_equals(typeof (obj), 'number', description);
+                assert_greater_than_equal(obj, MIN_UNSIGNED_LONG_LONG, description + " - value too low.");
+                assert_less_than_equal(obj, MAX_UNSIGNED_LONG_LONG, description + " - value too high.");
+                assert_equals(obj % 1, 0, description + " - value is not an integer.");
+                break;
+            case 'double':
+                assert_equals(typeof (obj), 'number', description);
+                break;
+            default:
+                assert_unreached('Fix your test. Wrong type \'' + org_type + '\'');
+        }
+    } else if (typeof (type) === 'function') {
+        assert_true(obj instanceof type, description);
+    } else if (typeof (type) === 'object') {
+        for (prop_name in type) {
+            prop_type = type[prop_name];
+            if (prop_type === 'function') {
+                assert_inherits(obj, prop_name);
+                assert_equals(typeof obj[prop_name], prop_type, 'Object should have method ' + prop_name);
+            } else {
+                assert_own_property(obj, prop_name);
+            }
+        }
+    } else {
+        assert_unreached('Fix your test. Wrong type ' + org_type);
+    }
+}
+
+expose(assert_type, 'assert_type');
+
+function register_type(alias, type_spec) {
+    _registered_types[alias] = type_spec;
+}
+
+expose(register_type, 'register_type');
+
+/**
+ * Method to check if attribute is const.
+ * Example usage:
+ * check_const(tizen.bluetooth.deviceMinor, 'TOY_DOLL', 0x03, 'number', 0x29B);
+ *
+ * @param obj  object to test which  has const attribute
+ * @param attributeName attribute name.
+ * @param expectedValue expected value of provided attribute name
+ * @param expectedType expected type of provided attribute name
+ * @param valueToAssign value to assign in order to check if attribute value can be modified
+ */
+function check_const(obj, attributeName, expectedValue, expectedType, valueToAssign) {
+    var tmp;
+    if (expectedValue === valueToAssign) {
+        assert_unreached("Fix your test. The same values given for "  + attributeName +
+            " in 'value' and 'valueToSet' arguments.");
+    }
+    if (typeof (attributeName) === "string") {
+        assert_true(attributeName in obj, "Name " + attributeName + " doesn't exist in provided object.");
+        assert_equals(obj[attributeName], expectedValue, "Value of " + attributeName + " is diffrent.");
+        if (typeof (expectedType) !== "undefined") {
+            if (expectedValue === null) {
+                assert_type(obj[attributeName], "object", "Type of " + attributeName + " is different.");
+            } else {
+                assert_type(obj[attributeName], expectedType, "Type of " + attributeName + " is different.");
+            }
+        } else {
+            assert_unreached("Fix your test. Wrong type " + expectedType);
+        }
+        tmp = obj[attributeName];
+        obj[attributeName] = valueToAssign;
+        assert_equals(obj[attributeName], tmp, attributeName + " can be modified.");
+    } else {
+        assert_unreached("Fix your test. Wrong type of name " + typeof (attributeName));
+    }
+}
+
+expose(check_const, 'check_const');
+
+/**
+ * Method to check if attribute is readonly.
+ * Example usage:
+ * check_readonly(statusNotification, "postedTime", null, 'object', new Date());
+ *
+ * @param obj  object to test which  has readonly attribute
+ * @param attributeName attribute name.
+ * @param expectedValue expected value of provided attribute name
+ * @param expectedType expected type of provided attribute name
+ * @param valueToAssign value to assign in order to check if attribute value can be modified
+ */
+function check_readonly(obj, attributeName, expectedValue, expectedType, valueToAssign) {
+    check_const(obj, attributeName, expectedValue, expectedType, valueToAssign);
+}
+
+expose(check_readonly, 'check_readonly');
+
+/**
+ * Method to check if attribute can be set to null.
+ * Example usage:
+ * check_not_nullable(syncInfo, "mode");
+ *
+ * @param obj object to test which has not nullable attribute
+ * @param attributeName attribute name.
+ */
+function check_not_nullable(obj, attributeName)
+{   var old_value = obj[attributeName];
+    obj[attributeName] = null;
+    assert_not_equals(obj[attributeName], null, "Attribute " + attributeName + " can be set to null.");
+    obj[attributeName] = old_value;
+}
+
+expose(check_not_nullable, 'check_not_nullable');
+
+/**
+ * Method to check NoInterfaceObject
+ * Example usage:
+ * check_no_interface_object("BluetoothAdapter")
+ *
+ * @param interfaceName interface name
+ */
+function check_no_interface_object(interfaceName) {
+    assert_throws({name: "TypeError"}, function () {
+        tizen[interfaceName]();
+    },"Wrong call as a function");
+    assert_throws({name: "TypeError"}, function () {
+        new tizen[interfaceName]();
+    },"Wrong call as a new function");
+    assert_throws({name: "TypeError"}, function () {
+        ({}) instanceof tizen[interfaceName];
+    },"instanceof exception");
+    assert_equals(tizen[interfaceName], undefined, interfaceName + " is not undefined.");
+}
+
+expose(check_no_interface_object, 'check_no_interface_object');
+
+
+/**
+ * Method to check Constructors
+ * Example usage:
+ * check_constructor("BluetoothAdapter")
+ *
+ * @param constructorName constructor name
+ */
+
+function check_constructor(constructorName) {
+    assert_true(constructorName in tizen, "No " + constructorName + " in tizen.");
+    assert_false({} instanceof tizen[constructorName],"Custom object is not instance of " + constructorName);
+    assert_throws({
+        name: "TypeError"
+    }, function () {
+        tizen[constructorName]();
+    }, "Constructor called as function.");
+}
+
+expose(check_constructor, 'check_constructor');
+
+/**
+ * Method to check if given method can be overridden in a given object - (TEMPORARY REMOVED).
+ * That method also checks if given method exists in a given object.
+ * Example usage:
+ * check_method_exists(tizen.notification, "get");
+ *
+ * @param obj object with method
+ * @param methodName name of the method to check.
+ */
+function check_method_exists(obj, methodName) {
+    assert_type(obj[methodName], 'function', "Method does not exist.");
+}
+
+expose(check_method_exists, 'check_method_exists');
+
+/**
+ * Method to check extensibility of given object.
+ * Method checks if new attribute and method can be added.
+ * Example usage:
+ * check_extensibility(tizen.notification);
+ *
+ * @param obj object to check
+ */
+function check_extensibility(obj) {
+    var dummyAttribute = "dummyAttributeValue", dummyMethodResult = "dummyMethodResultValue";
+    obj.newDummyMethod = function() {
+        return dummyMethodResult;
+    }
+    assert_equals(obj.newDummyMethod(), dummyMethodResult, "Incorrect result from added method.");
+
+    obj.newDummyAttribute = dummyAttribute;
+    assert_equals(obj.newDummyAttribute, dummyAttribute, "Incorrect result from added attribute.");
+}
+
+expose(check_extensibility, 'check_extensibility');
+
+/**
+ * Method to check if attribute can be modify.
+ * Example usage:
+ * check_attr(downloadRequest, "fileName", default_val, "string", "file_name.html");
+ *
+ * @param obj  object to test which has not readonly attribute
+ * @param attributeName attribute name.
+ * @param expectedValue expected value of provided attribute name
+ * @param expectedType expected type of provided attribute name
+ * @param valueToAssign value to assign in order to check if attribute value can be modified
+ */
+function check_attribute(obj, attributeName, expectedValue, expectedType, valueToAssign) {
+    if (expectedValue === valueToAssign) {
+        assert_unreached("Fix your test. The same values given for "  + attributeName +
+            " in 'value' and 'valueToSet' arguments.");
+    }
+    if (typeof (attributeName) === "string") {
+        assert_true(attributeName in obj, "Name " + attributeName + " doesn't exist in provided object.");
+        assert_equals(obj[attributeName], expectedValue, "Value of " + attributeName + " is diffrent.");
+        if (typeof (expectedType) !== "undefined") {
+            if (expectedValue === null) {
+                assert_type(obj[attributeName], "object", "Type of " + attributeName + " is different.");
+            } else {
+                assert_type(obj[attributeName], expectedType, "Type of " + attributeName + " is different.");
+            }
+        } else {
+            assert_unreached("Fix your test. Wrong type " + expectedType);
+        }
+        obj[attributeName] = valueToAssign;
+        assert_equals(obj[attributeName], valueToAssign, attributeName + " can be modified.");
+    } else {
+        assert_unreached("Fix your test. Wrong type of name " + typeof (attributeName));
+    }
+}
+
+expose(check_attribute, 'check_attribute');
+
+/**
+ * Method to check if whole array can be overwritten with an invalid value.
+ * Sample usage:
+ * check_invalid_array_assignments(message, "to", false);
+ *
+ * @param obj object which has the array as its property
+ * @param array name of the array to check
+ * @param isNullable indicates if the array can be null
+ */
+function check_invalid_array_assignments(obj, array, isNullable) {
+    var args = [undefined, true, false, NaN, 0, "TIZEN", {}, function () {}],
+        val = obj[array], i;
+
+    if (!isNullable) {
+        obj[array] = null;
+        assert_not_equals(obj[array], null, "Non-nullable array was set to null");
+        assert_type(obj[array], "array", "Non-nullable array type changed after assigning null");
+        assert_equals(obj[array].toString(), val.toString(), "Non-nullable array contents changed after assigning null");
+    }
+
+    for (i = 0 ; i < args.length ; i++) {
+        obj[array] = args[i];
+        assert_type(obj[array], "array", "Array type changed after assigning an invalid value");
+        assert_equals(obj[array].toString(), val.toString(), "Array contents changed after assigning an invalid value");
+    }
+}
+
+expose(check_invalid_array_assignments, 'check_invalid_array_assignments');
+
+/**
+ * Method to check if an object can be overwritten with an invalid value.
+ * Sample usage:
+ * check_invalid_object_assignments(message, "body", false);
+ *
+ * @param parentObj object which has the 'obj' object as its property
+ * @param obj name of the object to check
+ * @param isNullable indicates if the object can be null
+ */
+function check_invalid_obj_assignments(parentObj, obj, isNullable) {
+    var args = [undefined, true, false, NaN, 0, "TIZEN", function () {}],
+        val = parentObj[obj], i;
+
+    if (!isNullable) {
+        parentObj[obj] = null;
+        assert_equals(parentObj[obj], val, "Non-nullable obj was modified after assigning null");
+    }
+
+    for (i = 0 ; i < args.length ; i++) {
+        parentObj[obj] = args[i];
+        assert_equals(parentObj[obj], val, "The object was set to " + args[i]);
+    }
+}
+
+expose(check_invalid_obj_assignments, 'check_invalid_obj_assignments');
+
+/**
+ * Method to validate conversion for listeners.
+ * Example usage:
+ * incorrectListeners = getListenerConversionExceptions(["oninstalled", "onupdated", "onuninstalled"]);
+ * for(i = 0; i < incorrectListeners.length; i++) {
+ *     packageInformationEventCallback  = incorrectListeners[i][0];
+ *     exceptionName = incorrectListeners[i][1];
+ *     assert_throws({name : exceptionName},
+ *        function () {
+ *             tizen.package.setPackageInfoEventListener(packageInformationEventCallback);
+ *         }, exceptionName + " should be thrown - given incorrect successCallback.");
+ * }
+ *
+ *
+ * @param callbackNames Array with names
+ * @returns {Array} table of tables which contain incorrect listener (index 0) and exceptionName (index 1)
+ *
+ */
+function getListenerConversionExceptions(callbackNames) {
+    var result = [], conversionTable, i, j, listenerName;
+    conversionTable = getTypeConversionExceptions("functionObject", false);
+
+    for (i = 0; i < callbackNames.length; i++) {
+        for (j = 0; j < conversionTable.length; j++) {
+            listenerName = {};
+            listenerName[callbackNames[i]] = conversionTable[j][0];
+            result.push([listenerName, conversionTable[j][1]]);
+        }
+    }
+
+    return result;
+}
+
+expose(getListenerConversionExceptions, 'getListenerConversionExceptions');
\ No newline at end of file
diff --git a/webWidgetTCT_device/test/tct/tct.js b/webWidgetTCT_device/test/tct/tct.js
new file mode 100755 (executable)
index 0000000..9a60f5f
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+ * 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.
+ */
+
+(function() {
+    function runTests() {
+        // gather tests to run
+        var selectedTests = {};
+        for (var i = 0; i < arguments.length; ++i) {
+            var arg = arguments[i];
+            if (!(arg instanceof Array)) {
+                arg = String(arg).split(' ');
+            }
+            for (var j = 0; j < arg.length; ++j) {
+                selectedTests[arg[j].toLowerCase()] = '';
+            }
+        }
+
+        // load node.js modules
+        var fs = requireTCT('fs');
+
+        // checks if object is empty
+        function isEmptyObject(object) {
+            for (var prop in object) {
+                if (object.hasOwnProperty(prop)) {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        // constants
+        var testsDir = 'tct/tests/';
+        var testRegExp = /^Test(.*)\.js$/;
+        var testPrefix = 'Test';
+        var extension = '.js';
+
+        // find available tests
+        var availableTests = {};
+        //var testFiles = fs.readdirSync(testsDir);
+        var testFiles = [
+            "TestApplication.js",
+            "TestFilesystem.js",
+            //"TestMessagePort.js",
+            "TestSysteminfo.js",
+            "TestPreference.js",
+            //"TestSensor.js",
+            "TestAnimationTiming.js",
+            "TestPageVisibility.js",
+            "TestXMLHttpRequest.js",
+            //"TestMessagePort.js",
+            "TestEvent.js",
+            "TestCSS.js",
+            "TestDom.js",
+            "TestHtml.js",
+            "TestWidgetService.js",
+            "TestWebWidget.js"
+        ];
+
+        for (var ii = 0; ii < testFiles.length; ++ii) {
+            var match = testRegExp.exec(testFiles[ii]);
+            if (match) {
+                match = match[1];
+                availableTests[match.toLowerCase()] = match;
+            }
+        }
+
+        // if no tests are selected, run all
+        if (isEmptyObject(selectedTests)) {
+            selectedTests = availableTests;
+        }
+
+        // load tizen modules
+        /*if (typeof (tizen) === 'undefined') {
+            requireTCT('common/loader.js')();
+        }*/
+
+        // load test engine
+        requireTCT('tct/common/testharness.js');
+        requireTCT('tct/common/unitcommon.js');
+
+        // stores test cases
+        var testCases = [];
+        var stats = { modules : {}, tests : {} };
+
+        function add_test_case(m, f) {
+            if (!stats.modules[m]) {
+                stats.modules[m] = {};
+                stats.modules[m].all = 0;
+                stats.modules[m].pass = 0;
+                stats.modules[m].fail = 0;
+                stats.modules[m].timeout = 0;
+                stats.modules[m].notrun = 0;
+            }
+            ++stats.modules[m].all;
+            stats.tests[f.name] = m;
+            testCases.push(f);
+        }
+        expose(add_test_case, 'add_test_case');
+
+        // load tests
+        for (var test in selectedTests) {
+            if (availableTests[test]) {
+                console.log('Loading test: ' + availableTests[test]);
+                try {
+                    requireTCT(testsDir + testPrefix + availableTests[test] + extension);
+                } catch (e) {
+                    console.log('Failed to load: ' + availableTests[test]);
+                    console.log(e);
+                }
+            }
+        }
+
+        // handle test case
+        var currentTest = 0;
+
+        function onResult(test) {
+            if (test) {
+                // store statistics
+                var m = stats.tests[test.name];
+                switch (test.status) {
+                case 0:
+                    ++stats.modules[m].pass;
+                    break;
+                case 1:
+                    ++stats.modules[m].fail;
+                    break;
+                case 2:
+                    ++stats.modules[m].timeout;
+                    break;
+                case 3:
+                    ++stats.modules[m].notrun;
+                    break;
+                }
+            }
+
+            // launch next test case
+            if (currentTest < testCases.length) {
+                setTimeout(testCases[currentTest], 0);
+                ++currentTest;
+            } else {
+                done();
+            }
+        }
+        function onFinish() {
+            var total = 0;
+            var pass = 0;
+            var fail = 0;
+            var timeout = 0;
+            var notrun = 0;
+            console.log('============ Test suites:');
+            for (var m in stats.modules) {
+                if (stats.modules.hasOwnProperty(m)) {
+                    var s = stats.modules[m];
+                    var nr = s.all - s.pass - s.fail - s.timeout;
+                    console.log('[' + m + '] - ' + s.pass + ' passed, ' + s.fail + ' failed, ' + s.timeout + ' timed out, ' + nr + ' not run.');
+                    total += s.all;
+                    pass += s.pass;
+                    fail += s.fail;
+                    timeout += s.timeout;
+                    notrun += nr;
+                }
+            }
+            console.log('============ Summary:');
+            console.log('Test cases all: ' + total);
+            console.log('Test cases passed: ' + pass);
+            console.log('Test cases failed: ' + fail);
+            console.log('Test cases timed out: ' + timeout);
+            console.log('Test cases not run: ' + notrun);
+            // terminate process
+            // process.exit();
+        }
+
+        // register callbacks
+        add_result_callback(onResult);
+        add_completion_callback(onFinish);
+
+        // start testing
+        console.log('Running tests');
+        onResult();
+    }
+
+    if (!module.parent) {
+        // standalone script
+        //runTests(process.argv.slice(2));
+        runTests([
+                "Application",
+                "Filesystem",
+                "Systeminfo",
+                "Preference",
+                //"Sensor",
+                "AnimationTiming",
+                "PageVisibility",
+                "XMLHttpRequest",
+                "Event",
+                "CSS",
+                "Dom",
+                "Html",
+                "WidgetService",
+                "WebWidget",
+                ]);
+    } else {
+        module.exports = runTests;
+    }
+})();
+
diff --git a/webWidgetTCT_device/test/tct/tests/TestAlarm.js b/webWidgetTCT_device/test/tct/tests/TestAlarm.js
new file mode 100755 (executable)
index 0000000..0735339
--- /dev/null
@@ -0,0 +1,1530 @@
+/*
+ * Copyright (c) 2012 Intel Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * *Redistributions of works must retain the original copyright notice, this list
+ * of conditions and the following disclaimer.
+ * *Redistributions in binary form must reproduce the original copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * *Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this work without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors:
+ *         Jenny Cao <jenny.q.cao@intel.com>
+ *
+ *         Revision history:
+ *
+ */
+
+var UNKNOWN_ERR         = "UnknownError";
+var TYPE_MISMATCH_ERR   = "TypeMismatchError";
+var IO_ERR              = "IOError";
+var INVALID_VALUES_ERR  = "InvalidValuesError";
+var SECURITY_ERR        = "SecurityError";
+var NOT_FOUND_ERR       = "NotFoundError";
+var NOT_SUPPORT_ERR     = "NotSupportedError";
+
+var APPLICATION_ID = "testalar00.alarmTestApp";
+
+add_result_callback(function () {
+    try {
+        tizen.alarm.removeAll();
+    } catch (err) {
+        // do nothing in case removeAll throw an exception
+    }
+});
+
+function createAbsAlarm() {
+    var absAlarm1, date = new Date();
+    date.setFullYear(date.getFullYear() + 1);
+    absAlarm1 = new tizen.AlarmAbsolute(date);
+    return absAlarm1;
+}
+
+function createRelAlarm() {
+    var alarmRel1 = new tizen.AlarmRelative(3 * tizen.alarm.PERIOD_HOUR);
+    return alarmRel1;
+}
+
+function cleanAlarms() {
+    tizen.alarm.removeAll();
+}
+
+function AlarmAbsolute_constructor_date() {
+
+//==== TEST: AlarmAbsolute_constructor_date
+//==== LABEL Test whether the constructor with date parameter are supported
+//==== SPEC Tizen Web API:Application:Alarm:AlarmAbsolute:constructor C
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA CONSTRA CONSTRM
+
+test(function () {
+    var alarm, date = new Date();
+    date.setFullYear(date.getFullYear() + 1);
+    date.setMilliseconds(0);
+    alarm = new tizen.AlarmAbsolute(date);
+    assert_true(alarm instanceof tizen.AlarmAbsolute, "object was not created properly");
+    assert_equals(alarm.date.getTime(), date.getTime(), "date passed as constructor parameter is different than date in the object");
+}, 'AlarmAbsolute_constructor_date');
+
+}
+
+function AlarmAbsolute_constructor_date_daysOfTheWeek() {
+
+//==== TEST: AlarmAbsolute_constructor_date_daysOfTheWeek
+//==== LABEL Test whether the constructor with date parameter and day of the week parameter are supported
+//==== SPEC Tizen Web API:Application:Alarm:AlarmAbsolute:constructor C
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA CONSTRA CONSTRM
+
+test(function () {
+    var i, alarm, date = new Date(),
+        daysOfTheWeekPossibilities = ["MO", "TU", "WE", "TH", "FR", "SA", "SU"],
+        daysOfTheWeek = [];
+    date.setFullYear(date.getFullYear() + 1);
+    date.setMilliseconds(0);
+    for (i = 0; i < daysOfTheWeekPossibilities.length; i++) {
+        daysOfTheWeek.push(daysOfTheWeekPossibilities[i]);
+        alarm = new tizen.AlarmAbsolute(date, daysOfTheWeek);
+        assert_true(alarm instanceof tizen.AlarmAbsolute, "object was not created properly");
+        assert_equals(alarm.date.getTime(), date.getTime(), "date passed as constructor parameter is different than date in the object");
+        assert_array_equals(alarm.daysOfTheWeek, daysOfTheWeek,
+            "days of the week array passed as constructor parameter is different than days of the week array in the object");
+    }
+}, 'AlarmAbsolute_constructor_date_daysOfTheWeek');
+
+}
+
+function AlarmAbsolute_constructor_date_period() {
+
+//==== TEST: AlarmAbsolute_constructor_date_period
+//==== LABEL Test whether the constructor with date parameter and period parameter are supported
+//==== SPEC Tizen Web API:Application:Alarm:AlarmAbsolute:constructor C
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA CONSTRA CONSTRM
+
+test(function () {
+    var alarm, date = new Date(), period = 300;
+    date.setFullYear(date.getFullYear() + 1);
+    date.setMilliseconds(0);
+    alarm = new tizen.AlarmAbsolute(date, period);
+    assert_true(alarm instanceof tizen.AlarmAbsolute, "object was not created properly");
+    assert_equals(alarm.date.getTime(), date.getTime(), "date passed as constructor parameter is different than date in the object");
+    assert_array_equals(alarm.period, period, "period passed as constructor parameter is different than period in the object");
+}, 'AlarmAbsolute_constructor_date_period');
+
+}
+
+function AlarmAbsolute_date_attribute() {
+
+//==== TEST: AlarmAbsolute_date_attribute
+//==== LABEL Check AlarmAbsolute for date attribute
+//==== SPEC Tizen Web API:Application:Alarm:AlarmAbsolute:date A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var alarm, tmp, date = new Date();
+    date.setFullYear(date.getFullYear() + 1);
+    date.setMilliseconds(0);
+    alarm = new tizen.AlarmAbsolute(date);
+    assert_true("date" in alarm, "date doesn't exist in provided object.");
+    assert_type(alarm.date, "object", "type of date is different.");
+    assert_equals(alarm.date.getTime(), date.getTime(), "date passed as constructor parameter is different than date in the object");
+    tmp = alarm.date.getTime();
+    alarm.date.setSeconds(50, 0);
+    assert_equals(tmp, alarm.date.getTime(), "date can be modified");
+}, 'AlarmAbsolute_date_attribute');
+
+}
+
+function AlarmAbsolute_daysOfTheWeek_attribute() {
+
+//==== TEST: AlarmAbsolute_daysOfTheWeek_attribute
+//==== LABEL Check AlarmAbsolute for daysOfTheWeek attribute
+//==== SPEC Tizen Web API:Application:Alarm:AlarmAbsolute:daysOfTheWeek A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ARO ADV
+
+test(function () {
+    var alarm1, alarm2, tmp, date = new Date(), daysOfTheWeek = ["MO", "TU"];
+    date.setFullYear(date.getFullYear() + 1);
+    alarm1 = new tizen.AlarmAbsolute(date);
+    assert_array_equals(alarm1.daysOfTheWeek, [], "default value should be an empty array");
+    alarm2 = new tizen.AlarmAbsolute(date, daysOfTheWeek);
+    assert_true("daysOfTheWeek" in alarm2, "daysOfTheWeek doesn't exist in provided object.");
+    assert_type(alarm2.daysOfTheWeek, "array", "type of daysOfTheWeek is different.");
+    assert_array_equals(alarm2.daysOfTheWeek, daysOfTheWeek,
+        "daysOfTheWeek passed as constructor parameter is different than daysOfTheWeek in the object");
+    tmp = alarm2.daysOfTheWeek;
+    alarm2.daysOfTheWeek = ["WE", "TH", "FR"];
+    assert_array_equals(tmp, alarm2.daysOfTheWeek, "daysOfTheWeek can be modified");
+}, 'AlarmAbsolute_daysOfTheWeek_attribute');
+
+}
+
+function AlarmAbsolute_exist() {
+
+//==== TEST: AlarmAbsolute_exist
+//==== LABEL Check if AlarmAbsolute exist
+//==== SPEC Tizen Web API:Application:Alarm:AlarmAbsolute:constructor C
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA CONSTRF
+
+test(function () {
+    check_constructor("AlarmAbsolute");
+}, 'AlarmAbsolute_exist');
+
+}
+
+function AlarmAbsolute_extend() {
+
+//==== TEST: AlarmAbsolute_extend
+//==== LABEL Check if AlarmAbsolute possible extend
+//==== SPEC Tizen Web API:Application:Alarm:AlarmAbsolute:AlarmAbsolute U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA OBX
+
+test(function () {
+    var alarm = createAbsAlarm();
+    check_extensibility(alarm);
+}, 'AlarmAbsolute_extend');
+
+}
+
+function AlarmAbsolute_getNextScheduledDate() {
+
+//==== TEST: AlarmAbsolute_getNextScheduledDate
+//==== LABEL Check using getNextScheduledDate method
+//==== SPEC Tizen Web API:Application:Alarm:AlarmAbsolute:getNextScheduledDate M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MNA MR
+
+test(function () {
+    add_result_callback(function () {
+        try {
+            tizen.alarm.removeAll();
+        } catch (err) {
+            // do nothing in case removeAll throw an exception
+        }
+    });
+
+    var alarm, nextScheduledDate, myDate = new Date();
+    myDate.setFullYear(myDate.getFullYear() + 1);
+    myDate.setMilliseconds(0);
+    alarm = new tizen.AlarmAbsolute(myDate);
+    tizen.alarm.add(alarm, APPLICATION_ID);
+    nextScheduledDate = alarm.getNextScheduledDate();
+    assert_type(nextScheduledDate, "date", "type of the returned value is not a date");
+    assert_equals(nextScheduledDate.getTime(), myDate.getTime(), "the returned date is not the same which was added");
+    assert_equals(nextScheduledDate.getTime(), alarm.date.getTime(), "the returned date is not the same which is in the object");
+}, 'AlarmAbsolute_getNextScheduledDate');
+
+}
+
+function AlarmAbsolute_getNextScheduledDate_exist() {
+
+//==== TEST: AlarmAbsolute_getNextScheduledDate_exist
+//==== LABEL Check if method getNextScheduledDate exists
+//==== SPEC Tizen Web API:Application:Alarm:AlarmAbsolute:getNextScheduledDate M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    var alarm = createAbsAlarm();
+    check_method_exists(alarm, "getNextScheduledDate");
+}, 'AlarmAbsolute_getNextScheduledDate_exist');
+
+}
+
+function AlarmAbsolute_getNextScheduledDate_extra_argument() {
+
+//==== TEST: AlarmAbsolute_getNextScheduledDate_extra_argument
+//==== LABEL Check using getNextScheduledDate method with extra argument
+//==== SPEC Tizen Web API:Application:Alarm:AlarmAbsolute:getNextScheduledDate M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR MNAEX
+
+test(function () {
+    add_result_callback(function () {
+        try {
+            tizen.alarm.removeAll();
+        } catch (err) {
+            // do nothing in case removeAll throw an exception
+        }
+    });
+
+    var alarm, myDate = new Date();
+    myDate.setFullYear(myDate.getFullYear() + 1);
+    myDate.setMilliseconds(0);
+    alarm = new tizen.AlarmAbsolute(myDate);
+    tizen.alarm.add(alarm, APPLICATION_ID);
+    checkExtraArgument(alarm, "getNextScheduledDate");
+}, 'AlarmAbsolute_getNextScheduledDate_extra_argument');
+
+}
+
+function AlarmAbsolute_getNextScheduledDate_return_null() {
+
+//==== TEST: AlarmAbsolute_getNextScheduledDate_return_null
+//==== LABEL Check using getNextScheduledDate method for null return
+//==== SPEC Tizen Web API:Application:Alarm:AlarmAbsolute:getNextScheduledDate M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MNA MR
+
+test(function () {
+    add_result_callback(function () {
+        try {
+            tizen.alarm.removeAll();
+        } catch (err) {
+            // do nothing in case removeAll throw an exception
+        }
+    });
+
+    var alarm, nextScheduledDate, myDate = new Date();
+    myDate.setFullYear(myDate.getFullYear() - 1);
+    alarm = new tizen.AlarmAbsolute(myDate);
+    tizen.alarm.add(alarm, APPLICATION_ID);
+    nextScheduledDate = alarm.getNextScheduledDate();
+    assert_equals(nextScheduledDate, null, "nextScheduledDate do not returns null");
+}, 'AlarmAbsolute_getNextScheduledDate_return_null');
+
+}
+
+function AlarmAbsolute_period_attribute() {
+
+//==== TEST: AlarmAbsolute_period_attribute
+//==== LABEL Check AlarmAbsolute for period attribute
+//==== SPEC Tizen Web API:Application:Alarm:AlarmAbsolute:period A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ARO ADV
+
+test(function () {
+    var alarm1, alarm2, date = new Date(), period = 60;
+    date.setFullYear(date.getFullYear() + 1);
+    alarm1 = new tizen.AlarmAbsolute(date);
+    assert_true("period" in alarm1, "attribute period doesn't exist in provided object");
+    assert_type(alarm1.period, "null", "default value should be null");
+    alarm2 = new tizen.AlarmAbsolute(date, period);
+    check_readonly(alarm2, "period", alarm2.period, "number", 1);
+    assert_equals(alarm2.period, period, "period passed as constructor parameter is different than period in the object");
+}, 'AlarmAbsolute_period_attribute');
+
+}
+
+function AlarmManagerObject_notexist() {
+
+//==== TEST: AlarmManagerObject_notexist
+//==== LABEL Check if AlarmManagerObject not exist
+//==== SPEC Tizen Web API:Application:Alarm:AlarmManagerObject:AlarmManagerObject U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("AlarmManagerObject");
+}, 'AlarmManagerObject_notexist');
+
+}
+
+function AlarmManager_PERIOD_DAY_const() {
+
+//==== TEST: AlarmManager_PERIOD_DAY_const
+//==== LABEL Check if PERIOD_DAY is constant
+//==== SPEC Tizen Web API:Application:Alarm:AlarmManager:PERIOD_DAY A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== TEST_CRITERIA CONSTE CONSTT CONSTV CONSTRO
+
+test(function () {
+    check_const(tizen.alarm, "PERIOD_DAY", 86400, "number", 43200);
+}, 'AlarmManager_PERIOD_DAY_const');
+
+}
+
+function AlarmManager_PERIOD_HOUR_const() {
+
+//==== TEST: AlarmManager_PERIOD_HOUR_const
+//==== LABEL Check if PERIOD_HOUR is constant
+//==== SPEC Tizen Web API:Application:Alarm:AlarmManager:PERIOD_HOUR A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA CONSTE CONSTT CONSTV CONSTRO
+
+test(function () {
+    check_const(tizen.alarm, "PERIOD_HOUR", 3600, "number", 1300);
+}, 'AlarmManager_PERIOD_HOUR_const');
+
+}
+
+function AlarmManager_PERIOD_MINUTE_const() {
+
+//==== TEST: AlarmManager_PERIOD_MINUTE_const
+//==== LABEL Check if PERIOD_MINUTE is constant
+//==== SPEC Tizen Web API:Application:Alarm:AlarmManager:PERIOD_MINUTE A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA CONSTE CONSTT CONSTV CONSTRO
+
+test(function () {
+    check_const(tizen.alarm, "PERIOD_MINUTE", 60, "number", 120);
+}, 'AlarmManager_PERIOD_MINUTE_const');
+
+}
+
+function AlarmManager_PERIOD_WEEK_const() {
+
+//==== TEST: AlarmManager_PERIOD_WEEK_const
+//==== LABEL Check if PERIOD_WEEK is constant
+//==== SPEC Tizen Web API:Application:Alarm:AlarmManager:PERIOD_WEEK A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA CONSTE CONSTT CONSTV CONSTRO
+
+test(function () {
+    check_const(tizen.alarm, "PERIOD_WEEK", 604800, "number", 302400);
+}, 'AlarmManager_PERIOD_WEEK_const');
+
+}
+
+function AlarmManager_add_absolute_alarm() {
+
+//==== TEST: AlarmManager_add_absolute_alarm
+//==== LABEL Check using add method (with non-optional arguments) in AlarmManager interface to add absolute alarm
+//==== SPEC Tizen Web API:Application:Alarm:AlarmManager:add M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MAST MMINA MR
+
+test(function () {
+    add_result_callback(function () {
+        try {
+            tizen.alarm.removeAll();
+        } catch (err) {
+            // do nothing in case removeAll throw an exception
+        }
+    });
+
+    var alarm1, alarm2, retVal;
+    alarm1 = createAbsAlarm();
+    retVal = tizen.alarm.add(alarm1, APPLICATION_ID);
+    assert_type(retVal, "undefined", "method returned value");
+    assert_not_equals(alarm1.id, null, "object was not added properly");
+    alarm2 = tizen.alarm.get(alarm1.id);
+    assert_equals(alarm1.id, alarm2.id, "the object is not the same which was added");
+}, 'AlarmManager_add_absolute_alarm');
+
+}
+
+function AlarmManager_add_absolute_alarm_with_appControl() {
+
+//==== TEST: AlarmManager_add_absolute_alarm_with_appControl
+//==== LABEL Check using add method (with optional argument) in AlarmManager interface to add absolute alarm
+//==== SPEC Tizen Web API:Application:Alarm:AlarmManager:add M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MOA MR MAST
+
+test(function () {
+    add_result_callback(function () {
+        try {
+            tizen.alarm.removeAll();
+        } catch (err) {
+            // do nothing in case removeAll throw an exception
+        }
+    });
+
+    var alarm1, alarm2, appControl, returnVal;
+    alarm1 = createAbsAlarm();
+    appControl = new tizen.ApplicationControl("http://tizen.org/appcontrol/operation/view", "http://www.tizen.org");
+    returnVal = tizen.alarm.add(alarm1, APPLICATION_ID, appControl);
+    assert_type(returnVal, "undefined", "method returned value");
+    assert_not_equals(alarm1.id, null, "object was not added properly");
+    alarm2 = tizen.alarm.get(alarm1.id);
+    assert_equals(alarm1.id, alarm2.id, "the object is not the same which was added");
+}, 'AlarmManager_add_absolute_alarm_with_appControl');
+
+}
+
+function AlarmManager_add_alarm_TypeMismatch() {
+
+//==== TEST: AlarmManager_add_alarm_TypeMismatch
+//==== LABEL Check argument 'alarm' type conversion
+//==== SPEC Tizen Web API:Application:Alarm:AlarmManager:add M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+test(function () {
+    add_result_callback(function () {
+        try {
+            tizen.alarm.removeAll();
+        } catch (err) {
+            // do nothing in case removeAll throw an exception
+        }
+    });
+
+    var i, conversionTable = getTypeConversionExceptions("object");
+    for (i = 0; i < conversionTable.length; i++) {
+        assert_throws({name: conversionTable[i][1]}, function () {
+            tizen.alarm.add(conversionTable[i][0], APPLICATION_ID);
+        }, "exception should was thrown");
+    }
+}, 'AlarmManager_add_alarm_TypeMismatch');
+
+}
+
+function AlarmManager_add_appControl_TypeMismatch() {
+
+//==== TEST: AlarmManager_add_appControl_TypeMismatch
+//==== LABEL Check argument 'appControl' type conversion
+//==== SPEC Tizen Web API:Application:Alarm:AlarmManager:add M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+test(function () {
+    add_result_callback(function () {
+        try {
+            tizen.alarm.removeAll();
+        } catch (err) {
+            // do nothing in case removeAll throw an exception
+        }
+    });
+
+    var i, conversionTable = getTypeConversionExceptions("object", true),
+        alarm = createAbsAlarm();
+    for (i = 0; i < conversionTable.length; i++) {
+        assert_throws({name: conversionTable[i][1]}, function () {
+            tizen.alarm.add(alarm, APPLICATION_ID, conversionTable[i][0]);
+        }, "exception should was thrown");
+    }
+}, 'AlarmManager_add_appControl_TypeMismatch');
+
+}
+
+function AlarmManager_add_appControl_invalid() {
+
+//==== TEST: AlarmManager_add_appControl_invalid
+//==== LABEL Check if an exception was thrown when a wrong appControl was passed
+//==== SPEC Tizen Web API:Application:Alarm:AlarmManager:add M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MC
+
+test(function () {
+    add_result_callback(function () {
+        try {
+            tizen.alarm.removeAll();
+        } catch (err) {
+            // do nothing in case removeAll throw an exception
+        }
+    });
+
+    var absAlarm1 = createAbsAlarm();
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        tizen.alarm.add(absAlarm1, APPLICATION_ID, [12, 34]);
+    }, "TypeMismatchError exception should be thrown - given wrong appControl");
+}, 'AlarmManager_add_appControl_invalid');
+
+}
+
+function AlarmManager_add_appControl_invalid_obj() {
+
+//==== TEST: AlarmManager_add_appControl_invalid_obj
+//==== LABEL Check if an exception was thrown when a fake system object was passed
+//==== SPEC Tizen Web API:Application:Alarm:AlarmManager:add M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTO
+
+test(function () {
+    add_result_callback(function () {
+        try {
+            tizen.alarm.removeAll();
+        } catch (err) {
+            // do nothing in case removeAll throw an exception
+        }
+    });
+
+    var alarm, appControl;
+
+    alarm = createAbsAlarm();
+
+    appControl = {
+        operation: "http://tizen.org/appcontrol/operation/share",
+        uri: "share.html",
+        mime: "image/*",
+        category: "",
+        data: []
+    };
+
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        tizen.alarm.add(alarm, APPLICATION_ID, appControl);
+    }, "fake system object was pased but exception wasn't thrown");
+}, 'AlarmManager_add_appControl_invalid_obj');
+
+}
+
+function AlarmManager_add_exist() {
+
+//==== TEST: AlarmManager_add_exist
+//==== LABEL Check if method add exists
+//==== SPEC Tizen Web API:Application:Alarm:AlarmManager:add M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    check_method_exists(tizen.alarm, "add");
+}, 'AlarmManager_add_exist');
+
+}
+
+function AlarmManager_add_missarg() {
+
+//==== TEST: AlarmManager_add_missarg
+//==== LABEL Check with missing non-optional argument
+//==== SPEC Tizen Web API:Application:Alarm:AlarmManager:add M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MMA
+
+test(function () {
+    add_result_callback(function () {
+        try {
+            tizen.alarm.removeAll();
+        } catch (err) {
+            // do nothing in case removeAll throw an exception
+        }
+    });
+
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        tizen.alarm.add();
+    }, "Method was called without arguments but exception was not thrown");
+
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        tizen.alarm.add(undefined, APPLICATION_ID);
+    }, "Method was called without Alarm but exception was not thrown");
+}, 'AlarmManager_add_missarg');
+
+}
+
+function AlarmManager_add_relative_alarm() {
+
+//==== TEST: AlarmManager_add_relative_alarm
+//==== LABEL Check using add method (with non-optional arguments) in AlarmManager interface to add relative alarm
+//==== SPEC Tizen Web API:Application:Alarm:AlarmManager:add M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MMINA MR MAST
+
+test(function () {
+    add_result_callback(function () {
+        try {
+            tizen.alarm.removeAll();
+        } catch (err) {
+            // do nothing in case removeAll throw an exception
+        }
+    });
+
+    var alarm1 = createRelAlarm(), alarm2, retVal;
+    retVal = tizen.alarm.add(alarm1, APPLICATION_ID);
+    alarm2 = tizen.alarm.get(alarm1.id);
+    assert_type(retVal, "undefined", "method returned value");
+    assert_not_equals(alarm1.id, null, "object was not added properly");
+    assert_equals(alarm1.id, alarm2.id, "the object is not the same which was added");
+}, 'AlarmManager_add_relative_alarm');
+
+}
+
+function AlarmManager_add_relative_alarm_with_appControl() {
+
+//==== TEST: AlarmManager_add_relative_alarm_with_appControl
+//==== LABEL Check using add method (with optional argument) in AlarmManager interface to add relative alarm
+//==== SPEC Tizen Web API:Application:Alarm:AlarmManager:add M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MOA MR MAST
+
+test(function () {
+    add_result_callback(function () {
+        try {
+            tizen.alarm.removeAll();
+        } catch (err) {
+            // do nothing in case removeAll throw an exception
+        }
+    });
+
+    var alarm1, alarm2, appControl, returnVal;
+    alarm1 = createRelAlarm();
+    appControl = new tizen.ApplicationControl("http://tizen.org/appcontrol/operation/view", "http://www.tizen.org");
+    returnVal = tizen.alarm.add(alarm1, APPLICATION_ID, appControl);
+    assert_type(returnVal, "undefined", "method returned value");
+    assert_not_equals(alarm1.id, null, "object was not added properly");
+    alarm2 = tizen.alarm.get(alarm1.id);
+    assert_equals(alarm1.id, alarm2.id, "the object is not the same which was added");
+}, 'AlarmManager_add_relative_alarm_with_appControl');
+
+}
+
+function AlarmManager_extend() {
+
+//==== TEST: AlarmManager_extend
+//==== LABEL Check if AlarmManager possible extend
+//==== SPEC Tizen Web API:Application:Alarm:AlarmManager:AlarmManager U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA OBX
+
+test(function () {
+    check_extensibility(tizen.alarm);
+}, 'AlarmManager_extend');
+
+}
+
+function AlarmManager_get() {
+
+//==== TEST: AlarmManager_get
+//==== LABEL Check using get method in AlarmManager interface to get alarm
+//==== SPEC Tizen Web API:Application:Alarm:AlarmManager:get M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR MMINA
+
+test(function () {
+    add_result_callback(function () {
+        try {
+            tizen.alarm.removeAll();
+        } catch (err) {
+            // do nothing in case removeAll throw an exception
+        }
+    });
+
+    var alarm1, alarm2;
+    alarm1 = createAbsAlarm();
+    tizen.alarm.add(alarm1, APPLICATION_ID);
+    alarm2 = tizen.alarm.get(alarm1.id);
+    assert_true(alarm2 instanceof tizen.AlarmAbsolute, "object was not get properly");
+    assert_equals(alarm1.id, alarm2.id, "the object is not the same which was added");
+}, 'AlarmManager_get');
+
+}
+
+function AlarmManager_getAll() {
+
+//==== TEST: AlarmManager_getAll
+//==== LABEL Check using getAll method in AlarmManager interface to get all alarms
+//==== SPEC Tizen Web API:Application:Alarm:AlarmManager:getAll M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR MNA
+
+test(function () {
+    add_result_callback(function () {
+        try {
+            tizen.alarm.removeAll();
+        } catch (err) {
+            // do nothing in case removeAll throw an exception
+        }
+    });
+
+    var i, absAlarm, relAlarm, alarmAll = [];
+    cleanAlarms();
+    absAlarm = createAbsAlarm();
+    tizen.alarm.add(absAlarm, APPLICATION_ID);
+    relAlarm = createRelAlarm();
+    tizen.alarm.add(relAlarm, APPLICATION_ID);
+    alarmAll = tizen.alarm.getAll();
+    assert_equals(alarmAll.length, 2, "number of added alarms should be 2");
+    for (i = 0; i < alarmAll.length; i++) {
+        if (alarmAll[i] instanceof tizen.AlarmAbsolute) {
+            assert_equals(alarmAll[i].id, absAlarm.id, "object is not the same which was added");
+        } else if (alarmAll[i] instanceof tizen.AlarmRelative) {
+            assert_equals(alarmAll[i].id, relAlarm.id, "object is not the same which was added");
+        } else {
+            assert_unreached("object was not get properly");
+        }
+    }
+}, 'AlarmManager_getAll');
+
+}
+
+function AlarmManager_getAll_exist() {
+
+//==== TEST: AlarmManager_getAll_exist
+//==== LABEL Check if method getAll exists
+//==== SPEC Tizen Web API:Application:Alarm:AlarmManager:getAll M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    check_method_exists(tizen.alarm, "getAll");
+}, 'AlarmManager_getAll_exist');
+
+}
+
+function AlarmManager_getAll_extra_argument() {
+
+//==== TEST: AlarmManager_getAll_extra_argument
+//==== LABEL Check using getAll withe extra argument to get all alarms
+//==== SPEC Tizen Web API:Application:Alarm:AlarmManager:getAll M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MNAEX MR
+
+test(function () {
+    add_result_callback(function () {
+        try {
+            tizen.alarm.removeAll();
+        } catch (err) {
+            // do nothing in case removeAll throw an exception
+        }
+    });
+
+    var i, absAlarm, alarmAll = [], argumentsList = [null, undefined, "string", 1, false, ["one", "two"], {arg: 1}, function () {}];
+    cleanAlarms();
+    absAlarm = createAbsAlarm();
+    tizen.alarm.add(absAlarm, APPLICATION_ID);
+    for (i = 0; i < argumentsList.length; i++) {
+        alarmAll = tizen.alarm.getAll(argumentsList[i]);
+        assert_equals(alarmAll.length, 1, "number of added alarms should be 1");
+        assert_true(alarmAll[0] instanceof tizen.AlarmAbsolute, "object was not get properly");
+        assert_equals(alarmAll[0].id, absAlarm.id, "the first object is not the same which was added");
+        alarmAll = [];
+    }
+}, 'AlarmManager_getAll_extra_argument');
+
+}
+
+function AlarmManager_get_AlarmRelative() {
+
+//==== TEST: AlarmManager_get_AlarmRelative
+//==== LABEL Check using get method in AlarmManager interface to get AlarmRelative
+//==== SPEC Tizen Web API:Application:Alarm:AlarmManager:get M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MMINA MR
+
+test(function () {
+    add_result_callback(function () {
+        try {
+            tizen.alarm.removeAll();
+        } catch (err) {
+            // do nothing in case removeAll throw an exception
+        }
+    });
+
+    var alarm1, alarm2;
+    alarm1 = createRelAlarm();
+    tizen.alarm.add(alarm1, APPLICATION_ID);
+    alarm2 = tizen.alarm.get(alarm1.id);
+    assert_true(alarm2 instanceof tizen.AlarmRelative, "object was not get properly");
+    assert_equals(alarm1.id, alarm2.id, "the object is not the same which was added");
+}, 'AlarmManager_get_AlarmRelative');
+
+}
+
+function AlarmManager_get_exist() {
+
+//==== TEST: AlarmManager_get_exist
+//==== LABEL Check if method get exists
+//==== SPEC Tizen Web API:Application:Alarm:AlarmManager:get M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    check_method_exists(tizen.alarm, "get");
+}, 'AlarmManager_get_exist');
+
+}
+
+function AlarmManager_in_tizen() {
+
+//==== TEST: AlarmManager_in_tizen
+//==== LABEL Check if AlarmManager exist in tizen
+//==== SPEC Tizen Web API:Application:Alarm:AlarmManager:AlarmManager U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA OBME
+
+test(function () {
+    assert_true("alarm" in tizen, "no alarm in tizen");
+    check_readonly(tizen, "alarm", tizen.alarm, "object", "dummyValue");
+}, 'AlarmManager_in_tizen');
+
+}
+
+function AlarmManager_notexist() {
+
+//==== TEST: AlarmManager_notexist
+//==== LABEL Check if AlarmManager notexist
+//==== SPEC Tizen Web API:Application:Alarm:AlarmManager:AlarmManager U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("AlarmManager");
+}, 'AlarmManager_notexist');
+
+}
+
+function AlarmManager_removeAll() {
+
+//==== TEST: AlarmManager_removeAll
+//==== LABEL Check using removeAll method in AlarmManager interface to remove all alarms
+//==== SPEC Tizen Web API:Application:Alarm:AlarmManager:removeAll M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR MNA MNAST
+
+test(function (){
+    add_result_callback(function () {
+        try {
+            tizen.alarm.removeAll();
+        } catch (err) {
+            // do nothing in case removeAll throw an exception
+        }
+    });
+
+    var absAlarm, relAlarm, retVal, alarmAll = [];
+
+    tizen.alarm.removeAll();
+
+    absAlarm = createAbsAlarm();
+    tizen.alarm.add(absAlarm, APPLICATION_ID);
+
+    relAlarm = createRelAlarm();
+    tizen.alarm.add(relAlarm, APPLICATION_ID);
+
+    alarmAll = tizen.alarm.getAll();
+    assert_equals(alarmAll.length, 2 , "number of added alarms should be 2");
+
+    retVal = tizen.alarm.removeAll();
+    assert_type(retVal, "undefined", "method returned value");
+
+    assert_throws(NOT_FOUND_EXCEPTION, function () {
+        tizen.alarm.get(relAlarm.id);
+    }, "exception wasn't thrown");
+
+    assert_throws(NOT_FOUND_EXCEPTION, function () {
+        tizen.alarm.get(absAlarm.id);
+    }, "exception wasn't thrown");
+
+    alarmAll = tizen.alarm.getAll();
+    assert_equals(alarmAll.length, 0, "items not removed properly");
+}, 'AlarmManager_removeAll');
+
+}
+
+function AlarmManager_removeAll_exist() {
+
+//==== TEST: AlarmManager_removeAll_exist
+//==== LABEL Check if method removeAll exists
+//==== SPEC Tizen Web API:Application:Alarm:AlarmManager:removeAll M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    check_method_exists(tizen.alarm, "removeAll");
+}, 'AlarmManager_removeAll_exist');
+
+}
+
+function AlarmManager_removeAll_extra_argument() {
+
+//==== TEST: AlarmManager_removeAll_extra_argument
+//==== LABEL Check using removeAll with extra argument to remove all alarms
+//==== SPEC Tizen Web API:Application:Alarm:AlarmManager:removeAll M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MNAEX
+
+test(function (){
+    add_result_callback(function () {
+        try {
+            tizen.alarm.removeAll();
+        } catch (err) {
+            // do nothing in case removeAll throw an exception
+        }
+    });
+
+    var i, alarm, alarmAll, retVal, argumentsList = [null, undefined, "string", 1, false, ["one", "two"], {arg: 1}, function () {}];
+    tizen.alarm.removeAll();
+    alarm =  createAbsAlarm();
+    for (i = 0; i < argumentsList.length; i++) {
+        tizen.alarm.add(alarm, APPLICATION_ID);
+        alarmAll = tizen.alarm.getAll();
+        assert_equals(alarmAll.length, 1 , "number of added alarms should be 1");
+        retVal = tizen.alarm.removeAll(argumentsList[i]);
+        assert_type(retVal, "undefined", "method returned value");
+        assert_throws(NOT_FOUND_EXCEPTION, function () {
+            tizen.alarm.get(alarm.id);
+        }, "exception wasn't thrown");
+        alarmAll = tizen.alarm.getAll();
+        assert_equals(alarmAll.length, 0, "items not removed properly");
+    }
+}, 'AlarmManager_removeAll_extra_argument');
+
+}
+
+function AlarmManager_remove_absolute_alarm() {
+
+//==== TEST: AlarmManager_remove_absolute_alarm
+//==== LABEL Check using remove method in AlarmManager interface to remove absolute alarm
+//==== SPEC Tizen Web API:Application:Alarm:AlarmManager:remove M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR MMINA MAST
+
+test(function () {
+    add_result_callback(function () {
+        try {
+            tizen.alarm.removeAll();
+        } catch (err) {
+            // do nothing in case removeAll throw an exception
+        }
+    });
+
+    var alarm, retVal;
+    tizen.alarm.removeAll();
+    alarm = createAbsAlarm();
+    tizen.alarm.add(alarm, APPLICATION_ID);
+    retVal=tizen.alarm.remove(alarm.id);
+    assert_type(retVal, "undefined", "method returned value");
+    assert_throws(NOT_FOUND_EXCEPTION, function () {
+        tizen.alarm.get(alarm.id);
+    }, "exception wasn't thrown");
+    assert_equals(tizen.alarm.getAll().length, 0, "item not removed properly");
+}, 'AlarmManager_remove_absolute_alarm');
+
+}
+
+function AlarmManager_remove_exist() {
+
+//==== TEST: AlarmManager_remove_exist
+//==== LABEL Check if method remove exists
+//==== SPEC Tizen Web API:Application:Alarm:AlarmManager:remove M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    check_method_exists(tizen.alarm, "remove");
+}, 'AlarmManager_remove_exist');
+
+}
+
+function AlarmManager_remove_relative_alarm() {
+
+//==== TEST: AlarmManager_remove_relative_alarm
+//==== LABEL Check using remove method in AlarmManager interface to remove relative alarm
+//==== SPEC Tizen Web API:Application:Alarm:AlarmManager:remove M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR MMINA MAST
+
+test(function () {
+    add_result_callback(function () {
+        try {
+            tizen.alarm.removeAll();
+        } catch (err) {
+            // do nothing in case removeAll throw an exception
+        }
+    });
+
+    var alarm, retVal;
+    tizen.alarm.removeAll();
+    alarm = createRelAlarm();
+    tizen.alarm.add(alarm, APPLICATION_ID);
+    retVal=tizen.alarm.remove(alarm.id);
+    assert_type(retVal, "undefined", "method returned value");
+    assert_throws(NOT_FOUND_EXCEPTION, function () {
+        tizen.alarm.get(alarm.id);
+    }, "exception wasn't thrown");
+    assert_equals(tizen.alarm.getAll().length, 0, "item not removed properly");
+}, 'AlarmManager_remove_relative_alarm');
+
+}
+
+function AlarmRelative_constructor_delay() {
+
+//==== TEST: AlarmRelative_constructor_delay
+//==== LABEL Test whether the constructor with delay parameter are supported
+//==== SPEC Tizen Web API:Application:Alarm:AlarmRelative:constructor C
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA CONSTRA CONSTRM
+
+test(function () {
+    var alarm, delay = 3600;
+    alarm = new tizen.AlarmRelative(delay);
+    assert_true(alarm instanceof tizen.AlarmRelative, "object was not created properly");
+    assert_equals(alarm.delay, delay, "delay passed as constructor parameter is different than delay in the object");
+}, 'AlarmRelative_constructor_delay');
+
+}
+
+function AlarmRelative_constructor_delay_convert() {
+
+//==== TEST: AlarmRelative_constructor_delay_convert
+//==== LABEL Check conversion of delay parameter of AlarmRelative constructor
+//==== SPEC Tizen Web API:Application:Alarm:AlarmRelative:constructor C
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA CONSTRA CONSTRM
+
+test(function () {
+    var i, alarm1, alarm2, period = 300, delay = ["ABCD", null, undefined];
+    for (i = 0; i < delay.length; i++) {
+        alarm1 = new tizen.AlarmRelative(delay[i]);
+        assert_true(alarm1 instanceof tizen.AlarmRelative, "object was not created properly");
+        assert_equals(alarm1.delay, 0, "bad delay in the object");
+
+        alarm2 = new tizen.AlarmRelative(delay[i], period);
+        assert_true(alarm2 instanceof tizen.AlarmRelative, "object was not created properly");
+        assert_equals(alarm2.delay, 0, "bad delay in the object");
+    }
+}, 'AlarmRelative_constructor_delay_convert');
+
+}
+
+function AlarmRelative_constructor_delay_period() {
+
+//==== TEST: AlarmRelative_constructor_delay_period
+//==== LABEL Test whether the constructor with delay parameter and period parameter are supported
+//==== SPEC Tizen Web API:Application:Alarm:AlarmRelative:constructor C
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA CONSTRA  CONSTRM
+
+test(function () {
+    var alarm, delay = 3600, period = 300;
+    alarm = new tizen.AlarmRelative(delay, period);
+    assert_true(alarm instanceof tizen.AlarmRelative, "object was not created properly");
+    assert_equals(alarm.delay, delay, "delay passed as constructor parameter is different than delay in the object");
+    assert_equals(alarm.period, period, "period passed as constructor parameter is different than period in the object");
+}, 'AlarmRelative_constructor_delay_period');
+
+}
+
+function AlarmRelative_constructor_period_convert() {
+
+//==== TEST: AlarmRelative_constructor_period_convert
+//==== LABEL Check conversion of period parameter of AlarmRelative constructor
+//==== SPEC Tizen Web API:Application:Alarm:AlarmRelative:constructor C
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA CONSTRA CONSTRM
+
+test(function () {
+    var i, alarm, delay = 3600, period1 = [undefined, "ABCD"], period2 = null;
+
+    for (i = 0; i < period1.length; i++) {
+        alarm = new tizen.AlarmRelative(delay, period1[i]);
+        assert_true(alarm instanceof tizen.AlarmRelative, "object was not created properly");
+        assert_equals(alarm.period, 0, "bad period in the object");
+    }
+
+    alarm = new tizen.AlarmRelative(delay, period2);
+    assert_true(alarm instanceof tizen.AlarmRelative, "object was not created properly");
+    assert_type(alarm.period, "null", "wrong type of period variable");
+
+}, 'AlarmRelative_constructor_period_convert');
+
+}
+
+function AlarmRelative_delay_attribute() {
+
+//==== TEST: AlarmRelative_delay_attribute
+//==== LABEL Check delay attribute in AlarmRelative
+//==== SPEC Tizen Web API:Application:Alarm:AlarmRelative:delay A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var alarm, delay = 3600;
+    alarm = new tizen.AlarmRelative(delay);
+    assert_true("delay" in alarm, "attribute delay doesn't exist in provided object");
+    check_readonly(alarm, "delay", alarm.delay, "number", 7200);
+    assert_equals(alarm.delay, delay, "delay passed as constructor parameter is different than delay in the object");
+}, 'AlarmRelative_delay_attribute');
+
+}
+
+function AlarmRelative_exist() {
+
+//==== TEST: AlarmRelative_exist
+//==== LABEL Check if AlarmRelative exist
+//==== SPEC Tizen Web API:Application:Alarm:AlarmRelative:constructor C
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA CONSTRF
+
+test(function () {
+    check_constructor("AlarmRelative");
+}, 'AlarmRelative_exist');
+
+}
+
+function AlarmRelative_extend() {
+
+//==== TEST: AlarmRelative_extend
+//==== LABEL Check if AlarmRelative possible extend
+//==== SPEC Tizen Web API:Application:Alarm:AlarmRelative:AlarmRelative U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA OBX
+
+test(function () {
+    var alarm = createRelAlarm();
+    check_extensibility(alarm);
+}, 'AlarmRelative_extend');
+
+}
+
+function AlarmRelative_getRemainingSeconds() {
+
+//==== TEST: AlarmRelative_getRemainingSeconds
+//==== LABEL Check using getRemainingSeconds method
+//==== SPEC Tizen Web API:Application:Alarm:AlarmRelative:getRemainingSeconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR MNA
+
+test(function () {
+    add_result_callback(function () {
+        try {
+            tizen.alarm.removeAll();
+        } catch (err) {
+            // do nothing in case removeAll throw an exception
+        }
+    });
+
+    var alarm, remainingSeconds, delay = 3600;
+    alarm = new tizen.AlarmRelative(delay);
+    tizen.alarm.add(alarm, APPLICATION_ID);
+    remainingSeconds = alarm.getRemainingSeconds();
+    assert_type(remainingSeconds, "long", "type of the returned value is not a number");
+    assert_approx_equals(remainingSeconds, alarm.delay, 960, "the returned value is not properly");
+}, 'AlarmRelative_getRemainingSeconds');
+
+}
+
+function AlarmRelative_getRemainingSeconds_exist() {
+
+//==== TEST: AlarmRelative_getRemainingSeconds_exist
+//==== LABEL Check if method getRemainingSeconds exists
+//==== SPEC Tizen Web API:Application:Alarm:AlarmRelative:getRemainingSeconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    var alarm = createRelAlarm();
+    check_method_exists(alarm, "getRemainingSeconds");
+}, 'AlarmRelative_getRemainingSeconds_exist');
+
+}
+
+function AlarmRelative_getRemainingSeconds_extra_argument() {
+
+//==== TEST: AlarmRelative_getRemainingSeconds_extra_argument
+//==== LABEL Check using getRemainingSeconds with extra argument
+//==== SPEC Tizen Web API:Application:Alarm:AlarmRelative:getRemainingSeconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MNAEX MR
+
+test(function () {
+    add_result_callback(function () {
+        try {
+            tizen.alarm.removeAll();
+        } catch (err) {
+            // do nothing in case removeAll throw an exception
+        }
+    });
+
+    var i, alarm, remainingSeconds, delay = 3600,
+        argumentsList = [null, undefined, "string", 1, false, ["one", "two"], {arg: 1}, function () {}];
+    alarm = new tizen.AlarmRelative(delay);
+    tizen.alarm.add(alarm, APPLICATION_ID);
+    for (i = 0; i < argumentsList.length; i++) {
+        remainingSeconds = alarm.getRemainingSeconds(argumentsList[i]);
+        assert_type(remainingSeconds, "long", "type of the returned value is not a number");
+        assert_approx_equals(remainingSeconds, alarm.delay, 960, "the returned value is not properly");
+    }
+}, 'AlarmRelative_getRemainingSeconds_extra_argument');
+
+}
+
+function AlarmRelative_period_attribute() {
+
+//==== TEST: AlarmRelative_period_attribute
+//==== LABEL Check period attribute in AlarmRelative
+//==== SPEC Tizen Web API:Application:Alarm:AlarmRelative:period A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ARO ADV
+
+test(function () {
+    var alarm1, alarm2, delay = 3600, period = 60;
+    alarm1 = new tizen.AlarmRelative(delay);
+    assert_true("period" in alarm1, "attribute period doesn't exist in provided object");
+    assert_type(alarm1.period, "null", "default value should be null");
+    alarm2 = new tizen.AlarmRelative(delay, period);
+    check_readonly(alarm2, "period", alarm2.period, "number", 120);
+    assert_equals(alarm2.period, period, "period passed as constructor parameter is different than period in the object");
+}, 'AlarmRelative_period_attribute');
+
+}
+
+function Alarm_id_attribute_absolute_alarm() {
+
+//==== TEST: Alarm_id_attribute_absolute_alarm
+//==== LABEL Check Alarm.id attribute of AlarmAbsolute
+//==== SPEC Tizen Web API:Application:Alarm:Alarm:id A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    add_result_callback(function () {
+        try {
+            tizen.alarm.removeAll();
+        } catch (err) {
+            // do nothing in case removeAll throw an exception
+        }
+    });
+
+    var alarm, date = new Date();
+    date.setFullYear(date.getFullYear() + 1);
+    alarm = new tizen.AlarmAbsolute(date);
+    assert_true("id" in alarm, "attribute id doesn't exist in provided object");
+    assert_type(alarm.id, "null", "default value should be null");
+    tizen.alarm.add(alarm, APPLICATION_ID);
+    check_readonly(alarm, "id", alarm.id, "string", "dummyValue");
+}, 'Alarm_id_attribute_absolute_alarm');
+
+}
+
+function Alarm_id_attribute_relative_alarm() {
+
+//==== TEST: Alarm_id_attribute_relative_alarm
+//==== LABEL Check Alarm.id attribute of AlarmRelative
+//==== SPEC Tizen Web API:Application:Alarm:Alarm:id A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    add_result_callback(function () {
+        try {
+            tizen.alarm.removeAll();
+        } catch (err) {
+            // do nothing in case removeAll throw an exception
+        }
+    });
+
+    var alarm, delay = 3600;
+    alarm = new tizen.AlarmRelative(delay);
+    assert_true("id" in alarm, "attribute id doesn't exist in provided object");
+    assert_type(alarm.id, "null", "default value should be null");
+    tizen.alarm.add(alarm, APPLICATION_ID);
+    check_readonly(alarm, "id", alarm.id, "string", "dummyValue");
+}, 'Alarm_id_attribute_relative_alarm');
+
+}
+
+function Alarm_notexist() {
+
+//==== TEST: Alarm_notexist
+//==== LABEL Check if Alarm notexist
+//==== SPEC Tizen Web API:Application:Alarm:Alarm:Alarm U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("Alarm");
+}, 'Alarm_notexist');
+
+}
+
+function AlarmManager_get_id_invalid() {
+
+//==== TEST: AlarmManager_get_id_invalid
+//==== LABEL Check AlarmManager for get method using invalid values
+//==== SPEC Tizen Web API:Application:Alarm:AlarmManager:get M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== TEST_CRITERIA MC
+//==== PRIORITY P2
+
+test(function () {
+    var DOMStringConversionArray, i, id;
+    
+    DOMStringConversionArray = [true, false, NaN, undefined, ["element1", "element2"], {"a":1,"b":2}, function(){}];
+    for(i = 0; i < DOMStringConversionArray.length; i++){
+        id = DOMStringConversionArray[i];
+        assert_throws(INVALID_VALUES_EXCEPTION, function () {
+            tizen.alarm.get(id);
+        }, "Should throw InvalidValuesError exception");
+    }
+}, 'AlarmManager_get_id_invalid');
+
+}
+
+function AlarmManager_get_misarg() {
+
+//==== TEST AlarmManager_get_misarg
+//==== LABEL Check if get method is invoked with missing arguments
+//==== SPEC Tizen Web API:Application:Alarm:AlarmManager:get M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MMA
+
+test(function () {
+    var alarm1;
+
+    alarm1 = createAbsAlarm();
+    tizen.alarm.add(alarm1, APPLICATION_ID);
+    assert_throws(INVALID_VALUES_EXCEPTION, function () {
+        tizen.alarm.get();
+    }, "Should throw InvalidValuesError exception");
+}, 'AlarmManager_get_misarg');
+
+}
+
+function AlarmManager_remove_id_invalid() {
+
+//==== TEST AlarmManager_remove_id_invalid
+//==== LABEL Check if remove method is invoked with wrong parameters
+//==== SPEC Tizen Web API:Application:Alarm:AlarmManager:remove M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+test(function () {
+    var alarm1, conversionTable, i;
+
+    alarm1 = createAbsAlarm();
+    conversionTable = getTypeConversionExceptions("object");
+    for (i = 0; i < conversionTable.length; i++) {
+        assert_throws(INVALID_VALUES_EXCEPTION, function () {
+            tizen.alarm.remove(conversionTable[i][0]);
+        }, "Should throw InvalidValuesError exception");
+    }
+}, 'AlarmManager_remove_id_invalid');
+
+}
+
+function AlarmManager_remove_misarg() {
+
+//==== TEST AlarmManager_remove_misarg
+//==== LABEL Check if remove method is invoked with missing arguments
+//==== SPEC Tizen Web API:Application:Alarm:AlarmManager:remove M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/alarm.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MMA
+
+test(function () {
+    assert_throws(INVALID_VALUES_EXCEPTION, function () {
+        tizen.alarm.remove();
+    }, "Should throw InvalidValuesError exception");
+}, 'AlarmManager_remove_misarg');
+
+}
+
+
+var moduleName = "tct-alarm-tizen-tests";
+add_test_case(moduleName, AlarmAbsolute_constructor_date);
+add_test_case(moduleName, AlarmAbsolute_constructor_date_daysOfTheWeek);
+add_test_case(moduleName, AlarmAbsolute_constructor_date_period);
+add_test_case(moduleName, AlarmAbsolute_date_attribute);
+add_test_case(moduleName, AlarmAbsolute_daysOfTheWeek_attribute);
+add_test_case(moduleName, AlarmAbsolute_exist);
+add_test_case(moduleName, AlarmAbsolute_extend);
+add_test_case(moduleName, AlarmAbsolute_getNextScheduledDate);
+add_test_case(moduleName, AlarmAbsolute_getNextScheduledDate_exist);
+add_test_case(moduleName, AlarmAbsolute_getNextScheduledDate_extra_argument);
+add_test_case(moduleName, AlarmAbsolute_getNextScheduledDate_return_null);
+add_test_case(moduleName, AlarmAbsolute_period_attribute);
+add_test_case(moduleName, AlarmManagerObject_notexist);
+add_test_case(moduleName, AlarmManager_PERIOD_DAY_const);
+add_test_case(moduleName, AlarmManager_PERIOD_HOUR_const);
+add_test_case(moduleName, AlarmManager_PERIOD_MINUTE_const);
+add_test_case(moduleName, AlarmManager_PERIOD_WEEK_const);
+add_test_case(moduleName, AlarmManager_add_absolute_alarm);
+add_test_case(moduleName, AlarmManager_add_absolute_alarm_with_appControl);
+add_test_case(moduleName, AlarmManager_add_alarm_TypeMismatch);
+add_test_case(moduleName, AlarmManager_add_appControl_TypeMismatch);
+add_test_case(moduleName, AlarmManager_add_appControl_invalid);
+add_test_case(moduleName, AlarmManager_add_appControl_invalid_obj);
+add_test_case(moduleName, AlarmManager_add_exist);
+add_test_case(moduleName, AlarmManager_add_missarg);
+add_test_case(moduleName, AlarmManager_add_relative_alarm);
+add_test_case(moduleName, AlarmManager_add_relative_alarm_with_appControl);
+add_test_case(moduleName, AlarmManager_extend);
+add_test_case(moduleName, AlarmManager_get);
+add_test_case(moduleName, AlarmManager_getAll);
+add_test_case(moduleName, AlarmManager_getAll_exist);
+add_test_case(moduleName, AlarmManager_getAll_extra_argument);
+add_test_case(moduleName, AlarmManager_get_AlarmRelative);
+add_test_case(moduleName, AlarmManager_get_exist);
+add_test_case(moduleName, AlarmManager_in_tizen);
+add_test_case(moduleName, AlarmManager_notexist);
+add_test_case(moduleName, AlarmManager_removeAll);
+add_test_case(moduleName, AlarmManager_removeAll_exist);
+add_test_case(moduleName, AlarmManager_removeAll_extra_argument);
+add_test_case(moduleName, AlarmManager_remove_absolute_alarm);
+add_test_case(moduleName, AlarmManager_remove_exist);
+add_test_case(moduleName, AlarmManager_remove_relative_alarm);
+add_test_case(moduleName, AlarmRelative_constructor_delay);
+add_test_case(moduleName, AlarmRelative_constructor_delay_convert);
+add_test_case(moduleName, AlarmRelative_constructor_delay_period);
+add_test_case(moduleName, AlarmRelative_constructor_period_convert);
+add_test_case(moduleName, AlarmRelative_delay_attribute);
+add_test_case(moduleName, AlarmRelative_exist);
+add_test_case(moduleName, AlarmRelative_extend);
+add_test_case(moduleName, AlarmRelative_getRemainingSeconds);
+add_test_case(moduleName, AlarmRelative_getRemainingSeconds_exist);
+add_test_case(moduleName, AlarmRelative_getRemainingSeconds_extra_argument);
+add_test_case(moduleName, AlarmRelative_period_attribute);
+add_test_case(moduleName, Alarm_id_attribute_absolute_alarm);
+add_test_case(moduleName, Alarm_id_attribute_relative_alarm);
+add_test_case(moduleName, Alarm_notexist);
+add_test_case(moduleName, AlarmManager_get_id_invalid);
+add_test_case(moduleName, AlarmManager_get_misarg);
+add_test_case(moduleName, AlarmManager_remove_id_invalid);
+add_test_case(moduleName, AlarmManager_remove_misarg);
\ No newline at end of file
diff --git a/webWidgetTCT_device/test/tct/tests/TestAnimationTiming.js b/webWidgetTCT_device/test/tct/tests/TestAnimationTiming.js
new file mode 100755 (executable)
index 0000000..430378d
--- /dev/null
@@ -0,0 +1,228 @@
+/*
+ * Copyright (c) 2012 Intel Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * *Redistributions of works must retain the original copyright notice, this list
+ * of conditions and the following disclaimer.
+ * *Redistributions in binary form must reproduce the original copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * *Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this work without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors:
+ *
+ *        Yu, XiaoyanX <xiaoyanx.yu@intel.com>
+ *        HaoYunfen <yunfenx.hao@intel.com>
+ *        Cui, Jieqiong <jieqiongx.cui@intel.com>
+ */
+
+
+
+var TIMEOUT_AUTO_TEST = 30000;
+
+function AnimationTiming_WindowAnimationTiming_requestAnimationFrame_NeedParameter() {
+
+setup({timeout:500});
+        var t = async_test("AnimationTiming_WindowAnimationTiming_requestAnimationFrame_NeedParameter");
+        var reqAnimAPI =   window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.msRequestAnimationFrame || oRequestAnimationFrame;
+        var requestId = 0;
+        function animate(time) {
+           t.step(function() {
+                assert_not_equals(time,null);
+            });
+            t.done();
+        }
+
+        try{
+            animationStartTime = Date.now();
+            requestId =reqAnimAPI(animate);
+        }catch(e){
+            t.step(function() {
+                assert_true(false,"The browser does not support requestAnimationFrame method");
+            });
+            t.done();
+        }
+        alert("=====================================");
+        alert("Manual Test");
+        alert("Precondition: The screen should be switched on.");
+        alert("This TC tests whether the animation runs only when the screen is switched on");
+        alert("Instruction");
+        alert("(1) Press the reset button (bottom-right button),\n(2) turn around the dial to the right until you see 'Add widget' screen,\n(3) to the left until you see the stock watch face.");
+        alert("ps. If the dial does not response, press the reset button again, and repeat the steps.");
+    }
+function AnimationTiming_WindowAnimationTiming_cancelAnimationFrame_exist() {
+
+test(function () {
+    var reqAnimAPI = window.cancelAnimationFrame ||  window.webkitCancelRequestAnimationFrame || window.mozCancelAnimationFrame || window.msCancelAnimationFrame || window.oCancelAnimationFrame;
+            assert_true(reqAnimAPI !== undefined && reqAnimAPI != null,
+                "check if window.cancelAnimationFrame || window.webkitCancelRequestAnimationFrame || window.mozCancelAnimationFrame || window.msCancelAnimationFrame || window.oCancelAnimationFrame; is defined and not null");
+}, 'AnimationTiming_WindowAnimationTiming_cancelAnimationFrame_exist');
+
+}
+function AnimationTiming_WindowAnimationTiming_requestAnimationFrame_AcceptInlineScript() {
+
+setup({timeout:500});
+        var t = async_test("AnimationTiming_WindowAnimationTiming_requestAnimationFrame_AcceptInlineScript");
+        var reqAnimAPI =   window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.msRequestAnimationFrame || oRequestAnimationFrame;
+        t.step(function(){
+            var foo = t.step_func(function(){
+                t.done();
+            });
+            reqAnimAPI(foo);
+        });
+}
+
+function AnimationTiming_WindowAnimationTiming_requestAnimationFrame_hidden() {
+
+setup({timeout:500});
+        var t = async_test("AnimationTiming_WindowAnimationTiming_requestAnimationFrame_hidden");
+        var reqAnimAPI =   window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.msRequestAnimationFrame || oRequestAnimationFrame;
+        var cancelAnimAPI = window.cancelRequestAnimationFrame ||  window.webkitCancelRequestAnimationFrame || window.mozCancelAnimationFrame || window.msCancelAnimationFrame || window.oCancelAnimationFrame;;
+        var requestId = 0;
+        var hidden = document.hidden || document.webkitHidden || document.mozHidden|| document.msHidden;
+        function animate(time) {
+            t.step(function() {
+                assert_true(hidden, "expects hidden attribute is true");
+            });
+            t.done();
+        }
+        requestId =reqAnimAPI(animate);
+}
+function AnimationTiming_WindowAnimationTiming_requestAnimationFrame_ignoreOptionalArgs() {
+
+setup({timeout:500});
+        var t = async_test("AnimationTiming_WindowAnimationTiming_requestAnimationFrame_ignoreOptionalArgs");
+        var reqAnimAPI =   window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.msRequestAnimationFrame || oRequestAnimationFrame;
+        try{
+            reqAnimAPI(CallbackOptArgs, "foo");
+        }catch(e){
+            t.step(function() {
+                assert_true(false, "The browser does not support requestAnimationFrame method");
+            });
+            t.done();
+        }
+        function CallbackOptArgs(timestamp, arg){
+            t.step(function() {
+                assert_not_equals(timestamp,null, "expects callback to be invoked");
+            });
+            t.done();
+        }
+}
+function AnimationTiming_WindowAnimationTiming_requestAnimationFrame_invokeSecondCallback() {
+
+setup({timeout:500});
+        var t = async_test("AnimationTiming_WindowAnimationTiming_requestAnimationFrame_invokeSecondCallback");
+        var reqAnimAPI =   window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.msRequestAnimationFrame || oRequestAnimationFrame;
+        var callbackNumber = 0;
+        try{
+            reqAnimAPI(Callback1);
+            reqAnimAPI(Callback2);
+        }catch(e){
+            t.step(function() {
+                assert_true(false,"The browser does not support requestAnimationFrame method");
+            });
+            t.done();
+        }
+        function Callback1(timestamp) {
+           callbackNumber++;
+        }
+
+        function Callback2(timestamp) {
+            callbackNumber++;
+            t.step(function() {
+                assert_equals(callbackNumber, 2, "Check whether window.webkitRequestAnimationFrame can invoke second callback normally");
+            });
+            t.done();
+        }
+}
+
+function AnimationTiming_WindowAnimationTiming_requestAnimationFrame_exist() {
+
+test(function () {
+    var reqAnimAPI = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.msRequestAnimationFrame || oRequestAnimationFrame;
+        assert_true(reqAnimAPI !== undefined && reqAnimAPI != null,
+            reqAnimAPI+" check if window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.msRequestAnimationFrame || oRequestAnimationFrame is defined and not null");
+}, 'AnimationTiming_WindowAnimationTiming_requestAnimationFrame_exist');
+
+}
+
+// Adding TestPageVisibility.js
+// TCs in TestPageVisibility.js and TestAnimationTiming.js affect each other.
+var alert = console.log;
+function pagevisibility_DocumentVisibility_hidden_lockScreen() {
+
+            setTimeout(hiddenTest,2000);
+            var t=async_test("pagevisibility_DocumentVisibility_hidden_lockScreen");
+            function hiddenTest(){
+                var hidden = document.hidden || document.webkitHidden || document.mozHidden|| document.msHidden;
+                t.step(function(){
+                    assert_true(hidden,"expects hidden attribute is true");
+                    t.done();
+                });
+            }
+}
+
+function pagevisibility_DocumentVisibility_hidden_minimize() {
+
+            setTimeout(hiddenTest,2000);
+            var t=async_test("pagevisibility_DocumentVisibility_hidden_minimize");
+            function hiddenTest(){
+                var hidden = document.hidden || document.webkitHidden || document.mozHidden|| document.msHidden;
+                t.step(function() {
+                    assert_true(hidden,"expects hidden attribute is true");
+                    t.done();
+                });
+            }
+}
+function pagevisibility_DocumentVisibility_visibilitychange() {
+
+setup({timeout:300000});
+
+        var t = async_test('pagevisibility_DocumentVisibility_visibilitychange', {timeout: 300000});
+        var visibilityChange = document.visibilitychange || document.webkitvisibilitychange || document.mozvisibilitychange|| document.msvisibilitychange;
+                t.step(function() {
+                    document.addEventListener("visibilitychange", function() {
+                        t.done();
+                    }, false);
+                });
+                alert("=====================================");
+                alert("Manual Test");
+                alert("Precondition: The screen should be switched on.");
+                alert("Instruction");
+                alert("(1) turn around the dial to the right until you see 'Add widget' screen, and\n(2) to the left until you see the stock watch face.");
+                alert("ps. If the dial does not response, press the reset button again, and repeat the steps.");
+}
+
+
+// The following TCs requires the screen off
+// add_test_case(moduleName, AnimationTiming_WindowAnimationTiming_requestAnimationFrame_hidden);
+var moduleName = "tct-pagevisibility-w3c-tests";
+add_test_case(moduleName, pagevisibility_DocumentVisibility_hidden_lockScreen);
+add_test_case(moduleName, pagevisibility_DocumentVisibility_hidden_minimize);
+
+// The following TCs requires the screen on
+var moduleName = "tct-animationtiming-w3c-tests";
+add_test_case(moduleName, AnimationTiming_WindowAnimationTiming_requestAnimationFrame_NeedParameter);
+add_test_case(moduleName, AnimationTiming_WindowAnimationTiming_cancelAnimationFrame_exist);
+add_test_case(moduleName, AnimationTiming_WindowAnimationTiming_requestAnimationFrame_AcceptInlineScript);
+add_test_case(moduleName, AnimationTiming_WindowAnimationTiming_requestAnimationFrame_ignoreOptionalArgs);
+add_test_case(moduleName, AnimationTiming_WindowAnimationTiming_requestAnimationFrame_invokeSecondCallback);
+add_test_case(moduleName, AnimationTiming_WindowAnimationTiming_requestAnimationFrame_exist);
+
+var moduleName = "tct-pagevisibility-w3c-tests";
+add_test_case(moduleName, pagevisibility_DocumentVisibility_visibilitychange);
diff --git a/webWidgetTCT_device/test/tct/tests/TestApplication.js b/webWidgetTCT_device/test/tct/tests/TestApplication.js
new file mode 100755 (executable)
index 0000000..f95a820
--- /dev/null
@@ -0,0 +1,5512 @@
+/*
+Copyright (c) 2013 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Authors:
+        Krzysztof Lachacz <k.lachacz@samsung.com>
+        Mariusz Polasinski <m.polasinski@samsung.com>
+        Junghyuk Park <junghyuk.park@samsung.com>
+
+*/
+
+var alert = console.log;
+
+var METADATA_KEY = "meta-key";
+var METADATA_VALUE = "meta-value";
+var TCT_APPCONTROL_APPID_METADATA = {
+    testKey1: "testValue1",
+    testKey2: "testValue2"
+}
+
+var THIS_APP_ID = "Qny4t67cv7.DeviceAPI.f02";
+var INVALID_APP_ID = "api1appli0.WebAPITizenApplicationTestsInvalid";
+var APP_INFO_TEST_APP_ID = "api1appli3.TCTAppInfoEventTest";
+var APP_BROAD_TEST_APP_ID = "api1appli4.TCTbroadcastApp";
+
+var APP_BROAD_TEST_EVENT_NAME = "broadcast_event";
+var APP_BROAD_TEST_APP_NAME = "TCTbroadcastApp";
+
+var TCT_APPCONTROL_APPID = "api1appli1.TCTAppControl";
+var TCT_APPCONTROL_MOCK_APPID = "api1appli2.TCTAppControlMock";
+
+var TCT_APPCONTROL_LAUNCH_APPCONTROL_OPERATION = "http://tizen.org/appcontrol/operation/tct/launch";
+var TCT_APPCONTROL_LAUNCH_APPCONTROL_URI = "tct://launch_appcontrol.html";
+var TCT_APPCONTROL_LAUNCH_APPCONTROL_MIME = "text/html";
+var TCT_APPCONTROL_LAUNCH_APPCONTROL_MIME_INVALID = "invalid/invalid";
+
+var TCT_APPCONTROL_LAUNCH_APPCONTROL_EXPLICIT_OPERATION = "http://tizen.org/appcontrol/operation/tct/launch/explicit";
+var TCT_APPCONTROL_LAUNCH_APPCONTROL_EXPLICIT_URI = "tct://launch_appcontrol.html";
+var TCT_APPCONTROL_LAUNCH_APPCONTROL_EXPLICIT_MIME = "text/html";
+
+var TCT_APPCONTROL_REPLY_RESULT_OPERATION = "http://tizen.org/appcontrol/operation/tct/reply_result";
+var TCT_APPCONTROL_REPLY_RESULT_WITH_DATA_OPERATION = "http://tizen.org/appcontrol/operation/tct/reply_result/data";
+var TCT_APPCONTROL_REPLY_FAILURE_OPERATION = "http://tizen.org/appcontrol/operation/tct/reply_failure";
+
+var TCT_APPCONTROL_RUN_TEST_OPERATION = "http://tizen.org/appcontrol/operation/tct/run_test";
+var TCT_APPCONTROL_RUN_TEST_URI_PREFIX = "tct://";
+var TCT_APPCONTROL_RUN_TEST_MIME = "application/javascript";
+
+var TCT_APPCONTROL_EXIT_OPERATION = "http://tizen.org/appcontrol/operation/tct/exit";
+
+var TYPE_MISMATCH_ERR = {name: 'TypeMismatchError'};
+
+var TIMEOUT_AUTO_TEST = 30000;
+setup({timeout: TIMEOUT_AUTO_TEST});
+
+/**
+ * Function runs test in other application (TCTAppControl) and receives
+ * the results.
+ *
+ * @param testName name of the test
+ */
+function runTestAtTCTAppControl(testName) {
+    var t = async_test(testName, { timeout: TIMEOUT_AUTO_TEST }),
+    appControl, onreply, onerror, data;
+
+    setup_launch(t, TCT_APPCONTROL_APPID, function () {
+        appControl = new tizen.ApplicationControl(
+                        TCT_APPCONTROL_RUN_TEST_OPERATION,
+                        TCT_APPCONTROL_RUN_TEST_URI_PREFIX+testName,
+                        TCT_APPCONTROL_RUN_TEST_MIME);
+
+        onreply = {
+            onsuccess: t.step_func(function (dataArray) {
+                assert_true(dataArray.length == 2, "Unexpected dataArray");
+
+                for (data in dataArray) {
+                    if (dataArray[data].key === "status") {
+                        t.status = parseInt(dataArray[data].value[0]);
+                    } else if (dataArray[data].key === "message") {
+                        t.message = dataArray[data].value[0];
+                    } else {
+                        assert_unreached("Unexpected key in data");
+                        return;
+                    }
+                }
+
+                setTimeout(function(){
+                                       t.done();
+                               }, 3000);
+            }),
+            onfailure: t.step_func(function () {
+                assert_unreached("Unexpected onfailure");
+            })
+        };
+
+        onerror = t.step_func(function (error) {
+            assert_unreached("launchAppControl failure: " + error.message);
+        });
+
+        tizen.application.launchAppControl(appControl, null, null, onerror, onreply);
+    });
+}
+
+function setup_launch(t, appId, onready) {
+    t.step(function() {
+        onready = t.step_func(onready);
+      
+        tizen.application.getAppsContext(
+            t.step_func(function (contexts) {
+                for (var i in contexts) {
+                    if (contexts[i].appId === appId) {
+                        tizen.application.kill(contexts[i].id, onready, onready);
+                        return;
+                    }
+                }
+                onready();
+            }),
+            t.step_func(function (error) {
+                assert_unreached("setup_launch fails: " + error.name + " with message: " + error.message);
+            })
+        );  
+    });
+}
+
+function assert_launch(t, appId, onsuccess) {
+    var intervalId = setInterval(t.step_func(function() {
+        tizen.application.getAppsContext(
+            t.step_func(function (contexts) {
+                for (var i in contexts) {
+                    if (contexts[i].appId === appId) {
+                        clearInterval(intervalId);
+                        t.step_func(onsuccess)(contexts[i]);
+                        return;
+                    }
+                }
+            }),
+            t.step_func(function (error) {
+                assert_unreached("assert_launch fails: " + error.name + " with message: " + error.message);
+            })
+        );
+    }), 1000);
+}
+
+function assert_not_launch(t, appId, onsuccess) {
+    tizen.application.getAppsContext(
+        t.step_func(function (contexts) {
+            for (var i in contexts) {
+                if (contexts[i].appId === appId) {
+                    assert_unreached("assert_not_launch fails: "+appId+" has launched");
+                    return;
+                }
+            }
+            t.step_func(onsuccess)();
+        }),
+        t.step_func(function (error) {
+            assert_unreached("assert_not_launch fails: " + error.name + " with message: " + error.message);
+        })
+    );
+}
+
+function assert_kill(t, appId, onsuccess) {
+    var intervalId = setInterval(t.step_func(function() {
+        tizen.application.getAppsContext(
+            t.step_func(function (contexts) {
+                for (var i in contexts) {
+                    if (contexts[i].appId === appId) {
+                        return;
+                    }
+                }
+                clearInterval(intervalId);
+                t.step_func(onsuccess)();
+            }),
+            t.step_func(function (error) {
+                assert_unreached("assert_kill fails: " + error.name + " with message: " + error.message);
+            })
+        );
+    }), 1000);
+}
+
+function assert_not_kill(t, appId, onsuccess) {
+    tizen.application.getAppsContext(
+        t.step_func(function (contexts) {
+            for (var i in contexts) {
+                if (contexts[i].appId === appId) {
+                    t.step_func(onsuccess)();
+                    return;
+                }
+            }
+            assert_unreached("assert_not_kill fails: " + appId + " is not found");
+        }),
+        t.step_func(function (error) {
+            assert_unreached("assert_not_kill fails: " + error.name + " with message: " + error.message);
+        })
+    );
+}
+
+function assert_exit(t, appId, onsuccess) {
+    assert_kill(t, appId, onsuccess);
+}
+
+function ApplicationCertificate_extend() {
+
+//==== TEST: ApplicationCertificate_extend
+//==== LABEL Check if ApplicationCertificate possible extend
+//==== SPEC Tizen Web API:Application:Application:ApplicationCertificate:ApplicationCertificate U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA OBX
+
+test(function () {
+    var appCertificateArray = tizen.application.getAppCerts();
+    check_extensibility(appCertificateArray[0]);
+}, 'ApplicationCertificate_extend');
+
+}
+
+function ApplicationCertificate_notexist() {
+
+//==== TEST: ApplicationCertificate_notexist
+//==== LABEL Check if ApplicationCertificate notexist
+//==== SPEC Tizen Web API:Application:Application:ApplicationCertificate:ApplicationCertificate U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("ApplicationCertificate");
+}, 'ApplicationCertificate_notexist');
+
+}
+
+function ApplicationCertificate_type_attribute() {
+
+//==== TEST: ApplicationCertificate_type_attribute
+//==== LABEL Check attribute ApplicationCertificate::type existence and type
+//==== SPEC Tizen Web API:Application:Application:ApplicationCertificate:type A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var i, appCertificateArray = tizen.application.getAppCerts();
+    for (i = 0; i < appCertificateArray.length; i++) {
+        assert_true("type" in appCertificateArray[i], "type doesn't exist in provided object.");
+        check_readonly(appCertificateArray[i], "type", appCertificateArray[i].type, "string", "dummyValue");
+    }
+}, 'ApplicationCertificate_type_attribute');
+
+}
+
+function ApplicationCertificate_value_attribute() {
+
+//==== TEST: ApplicationCertificate_value_attribute
+//==== LABEL Check attribute ApplicationCertificate::value existence and type
+//==== SPEC Tizen Web API:Application:Application:ApplicationCertificate:value A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var i, appCertificateArray = tizen.application.getAppCerts();
+    for (i = 0; i < appCertificateArray.length; i++) {
+        assert_true("value" in appCertificateArray[i], "value doesn't exist in provided object.");
+        check_readonly(appCertificateArray[i], "value", appCertificateArray[i].value, "string", "dummyValue");
+    }
+}, 'ApplicationCertificate_value_attribute');
+
+}
+
+function ApplicationContextArraySuccessCallback_notexist() {
+
+//==== TEST: ApplicationContextArraySuccessCallback_notexist
+//==== LABEL Check if ApplicationContextArraySuccessCallback cannot be called as a function or in new expression
+//==== SPEC Tizen Web API:Application:Application:ApplicationContextArraySuccessCallback:ApplicationContextArraySuccessCallback U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA CBNIO
+
+test(function () {
+    check_no_interface_object("ApplicationContextArraySuccessCallback");
+}, 'ApplicationContextArraySuccessCallback_notexist');
+
+}
+
+function ApplicationContextArraySuccessCallback_onsuccess() {
+
+//==== TEST: ApplicationContextArraySuccessCallback_onsuccess
+//==== LABEL Check if ApplicationContextArraySuccessCallback onsuccess is called and if its arguments have proper type
+//==== ONLOAD_DELAY 30
+//==== SPEC: Tizen Web API:Application:Application:ApplicationContextArraySuccessCallback:onsuccess M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA CBOA CBT
+
+setup({timeout: 30000});
+
+var t = async_test('ApplicationContextArraySuccessCallback_onsuccess', {timeout: 30000}),
+    getSuccess, getError, context;
+
+t.step(function () {
+    getSuccess = t.step_func(function (contexts) {
+        assert_type(contexts, "array", "wrong type of invoked callback argument");
+        assert_true(contexts.length > 0, "contexts was not found");
+
+        context = contexts[0];
+        assert_true("id" in context, "context should have id property");
+        check_readonly(context, "id", context.id, "string", "dummy");
+        assert_true("appId" in context, "context should have appId property");
+        check_readonly(context, "appId", context.appId, "string", "dummy");
+
+        t.done();
+    });
+
+    getError = t.step_func(function (error) {
+        assert_unreached("getAppsContext() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    tizen.application.getAppsContext(getSuccess, getError);
+});
+
+}
+
+function ApplicationContext_appId_attribute() {
+
+//==== TEST: ApplicationContext_appId_attribute
+//==== LABEL Check attribute ApplicationContext::appId existence and type
+//==== SPEC Tizen Web API:Application:Application:ApplicationContext:appId A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var appContext = tizen.application.getAppContext(null);
+    assert_true("appId" in appContext, "id doesn't exist in provided object.");
+    check_readonly(appContext, "appId", appContext.appId, "string", 1);
+}, 'ApplicationContext_appId_attribute');
+
+}
+
+function ApplicationContext_extend() {
+
+//==== TEST: ApplicationContext_extend
+//==== LABEL Check if ApplicationContext possible extend
+//==== SPEC Tizen Web API:Application:Application:ApplicationContext:ApplicationContext U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA OBX
+
+test(function () {
+    var appContext = tizen.application.getAppContext(null);
+    check_extensibility(appContext);
+}, 'ApplicationContext_extend');
+
+}
+
+function ApplicationContext_id_attribute() {
+
+//==== TEST: ApplicationContext_id_attribute
+//==== LABEL Check attribute ApplicationContext::id existence and type
+//==== SPEC Tizen Web API:Application:Application:ApplicationContext:id A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var appContext = tizen.application.getAppContext(null);
+    assert_true("id" in appContext, "id doesn't exist in provided object.");
+    check_readonly(appContext, "id", appContext.id, "string", 1);
+}, 'ApplicationContext_id_attribute');
+
+}
+
+function ApplicationContext_notexist() {
+
+//==== TEST: ApplicationContext_notexist
+//==== LABEL Check if ApplicationContext notexist
+//==== SPEC Tizen Web API:Application:Application:ApplicationContext:ApplicationContext U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("ApplicationContext");
+}, 'ApplicationContext_notexist');
+
+}
+
+function ApplicationControlDataArrayReplyCallback_notexist() {
+
+//==== TEST: ApplicationControlDataArrayReplyCallback_notexist
+//==== LABEL Check if ApplicationControlDataArrayReplyCallback notexist
+//==== SPEC Tizen Web API:Application:Application:ApplicationControlDataArrayReplyCallback:ApplicationControlDataArrayReplyCallback U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA CBNIO
+
+test(function () {
+    check_no_interface_object("ApplicationControlDataArrayReplyCallback");
+}, 'ApplicationControlDataArrayReplyCallback_notexist');
+
+}
+
+function ApplicationControlDataArrayReplyCallback_onfailure() {
+
+//==== TEST: ApplicationControlDataArrayReplyCallback_onfailure
+//==== LABEL Check onfailure listener in ApplicationControlDataArrayReplyCallback
+//==== SPEC Tizen Web API:Application:Application:ApplicationControlDataArrayReplyCallback:onfailure M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA CBOA
+setup({timeout: 30000});
+
+var t = async_test('ApplicationControlDataArrayReplyCallback_onfailure', {timeout: 30000}),
+    launchError, appControl, replyCB;
+
+setup_launch(t, TCT_APPCONTROL_APPID, function () {
+    launchError = t.step_func(function (error) {
+        assert_unreached("launchAppControl() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    appControl = new tizen.ApplicationControl(TCT_APPCONTROL_REPLY_FAILURE_OPERATION);
+
+    replyCB = {
+        onsuccess: t.step_func(function () {
+            assert_unreached("onsuccess callback called");
+        }),
+        onfailure: t.step_func(function () {
+            setTimeout(function(){
+                               t.done();
+                       }, 3000);
+        })
+    };
+
+    tizen.application.launchAppControl(appControl, null, null, launchError, replyCB);
+});
+
+}
+
+function ApplicationControlDataArrayReplyCallback_onsuccess() {
+
+//==== TEST: ApplicationControlDataArrayReplyCallback_onsuccess
+//==== LABEL Check argument passed into method who is onsuccess listener in ApplicationControlDataArrayReplyCallback
+//==== SPEC Tizen Web API:Application:Application:ApplicationControlDataArrayReplyCallback:onsuccess M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA CBT CBOA
+
+setup({timeout: 30000});
+
+var t = async_test('ApplicationControlDataArrayReplyCallback_onsuccess', {timeout: 30000}),
+    launchError, dataSent, appControl, replyCB;
+
+function create_appcontrol_data(size) {
+    var dataArray = [], valueArray, key, value;
+
+    for (key=1; key <= size; key++) {
+        valueArray = [];
+        for (value=1; value <= key; value++) {
+            valueArray.push(value.toString());
+        }
+        dataArray.push(new tizen.ApplicationControlData(key.toString(), valueArray));
+    }
+
+    return dataArray;
+}
+
+function assert_appcontrol_data(t, dataReceived, dataExpected) {
+    t.step(function () {
+        var key, value, data, valueArray, sum, sumExpected;
+
+        assert_type(dataReceived, "array", "wrong type of argument");
+        assert_equals(dataReceived.length, dataExpected.length, "wrong length of data array");
+
+        for (key = 0; key < dataReceived.length; key++) {
+            data = dataReceived[key];
+            valueArray = data.value;
+
+            assert_true(data instanceof tizen.ApplicationControlData, "wrong type of array element");
+            assert_equals(valueArray.length, parseInt(data.key, 10), "wrong length of value array");
+
+            sum = 0;
+            sumExpected = 0;
+
+            for (value=0; value < valueArray.length; value++) {
+                sumExpected = sumExpected + value + 1;
+                sum += parseInt(valueArray[value], 10);
+            }
+
+            assert_equals(sum, sumExpected, "unexpected value array");
+        }
+    });
+}
+
+
+setup_launch(t, TCT_APPCONTROL_APPID, function () {
+    launchError = t.step_func(function (error) {
+        assert_unreached("launchAppControl() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    dataSent = create_appcontrol_data(8);
+
+    appControl = new tizen.ApplicationControl(
+                    TCT_APPCONTROL_REPLY_RESULT_WITH_DATA_OPERATION,
+                    null, null, null, dataSent);
+
+    replyCB = {
+        onsuccess: t.step_func(function (dataReceived) {
+            assert_appcontrol_data(t, dataReceived, dataSent);
+            setTimeout(function(){
+                               t.done();
+                       }, 3000);
+        }),
+        onfailure: t.step_func(function () {
+            assert_unreached("onfailure callback called");
+        })
+    };
+
+    tizen.application.launchAppControl(appControl, null, null, launchError, replyCB);
+});
+
+}
+
+function ApplicationControlData_constructor() {
+
+//==== TEST: ApplicationControlData_constructor
+//==== LABEL Check if ApplicationControlData constructor works
+//==== SPEC: Tizen Web API:Application:Application:ApplicationControlData:constructor C
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA CONSTRM CONSTRA
+
+test(function () {
+    var key = "image", value = ["photo.jpg"], appControlData;
+    appControlData = new tizen.ApplicationControlData(key, value);
+    assert_equals(appControlData.key, key, "key is different");
+    assert_equals(appControlData.value.length, value.length, "value is different");
+    assert_equals(appControlData.value[0], value[0], "value is different");
+}, 'ApplicationControlData_constructor');
+
+}
+
+function ApplicationControlData_exist() {
+
+//==== TEST: ApplicationControlData_exist
+//==== LABEL Check if ApplicationControlData exist and is a constructor
+//==== SPEC: Tizen Web API:Application:Application:ApplicationControlData:constructor C
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA CONSTRF
+
+test(function () {
+    check_constructor("ApplicationControlData");
+}, 'ApplicationControlData_exist');
+
+}
+
+function ApplicationControlData_extend() {
+
+//==== TEST: ApplicationControlData_extend
+//==== LABEL Check if ApplicationControlData can have new properties added
+//==== SPEC: Tizen Web API:Application:Application:ApplicationControlData:ApplicationControlData U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA OBX
+
+test(function () {
+    var key = "image", value = ["photo.jpg"], appControlData;
+    appControlData = new tizen.ApplicationControlData(key, value);
+    check_extensibility(appControlData);
+}, 'ApplicationControlData_extend');
+
+}
+
+function ApplicationControlData_key_attribute() {
+
+//==== TEST: ApplicationControlData_key_attribute
+//==== LABEL Check if ApplicationControlData have key attribute with proper type, writable, not null
+//==== SPEC: Tizen Web API:Application:Application:ApplicationControlData:key A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ASG AN
+
+test(function () {
+    var key = "image", newKey = "photo", value = ["photo.jpg"], appControlData;
+    appControlData = new tizen.ApplicationControlData(key, value);
+
+    assert_true("key" in appControlData, "ApplicationControlData should have key attribute");
+    check_attribute(appControlData, "key", appControlData.key, "string", "dummy");
+    appControlData.key = null;
+    assert_not_equals(appControlData.key, null, "can assign a null value");
+    appControlData.key = newKey;
+    assert_equals(appControlData.key, newKey, "can not assign a valid value");
+
+}, 'ApplicationControlData_key_attribute');
+
+}
+
+function ApplicationControlData_value_attribute() {
+
+//==== TEST: ApplicationControlData_value_attribute
+//==== LABEL Check if ApplicationControlData have value attribute with proper type, writable, not null
+//==== SPEC: Tizen Web API:Application:Application:ApplicationControlData:value A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT AN ASG
+
+test(function () {
+    var key = "image", value = ["photo.jpg"], appControlData, tmp;
+    appControlData = new tizen.ApplicationControlData(key, value);
+
+    assert_true("value" in appControlData, "ApplicationControlData should have value attribute");
+    assert_type(appControlData.value, "array", "value should be an array");
+    tmp = appControlData.value;
+    appControlData.value = null;
+    assert_equals(appControlData.value.length, tmp.length, "value is nullable");
+    appControlData.value = ["one", "two"];
+    assert_not_equals(appControlData.value.length, tmp.length, "value is readonly");
+
+}, 'ApplicationControlData_value_attribute');
+
+}
+
+function ApplicationControl_category_attribute() {
+
+//==== TEST: ApplicationControl_category_attribute
+//==== LABEL Check attribute ApplicationControl::category existence and type
+//==== SPEC Tizen Web API:Application:Application:ApplicationControl:category A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ASG
+
+test(function () {
+    var appControl1, appControl2, operation = "http://tizen.org/appcontrol/operation/share",
+        uri = "share.html", mime = "image/*", category = "dummyValue", newCategory = "dummyValue2";
+    appControl1 = new tizen.ApplicationControl(operation);
+    assert_true("category" in appControl1, "category doesn't exist in provided object.");
+    assert_type(appControl1.category, "null", "default value should be null");
+    appControl2 = new tizen.ApplicationControl(operation, uri, mime, category);
+    assert_type(appControl2.category, "string", "type of category is different");
+    assert_equals(appControl2.category, category, "category passed as constructor parameter is different than category in the object");
+    appControl2.category = newCategory;
+    assert_equals(appControl2.category, newCategory, "category can not be assigned a valid value");
+}, 'ApplicationControl_category_attribute');
+
+}
+
+function ApplicationControl_constructor() {
+
+//==== TEST: ApplicationControl_constructor
+//==== LABEL Test whether constructor with all arguments are supported
+//==== SPEC Tizen Web API:Application:Application:ApplicationControl:constructor C
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA CONSTRM CONSTRA
+
+test(function () {
+    var appControl, operation = "http://tizen.org/appcontrol/operation/share",
+        uri = "share.html", mime = "image/*", category = "dummyValue", i,
+        data = [new tizen.ApplicationControlData("images", ["imagedata1", "imagedata2"])];
+
+    appControl = new tizen.ApplicationControl(operation, uri, mime, category, data);
+    assert_true(appControl instanceof tizen.ApplicationControl, "object was not created properly");
+    assert_equals(appControl.operation, operation,
+        "the operation argument passed as constructor parameter is different than the operation attribute in the object");
+    assert_equals(appControl.uri, uri, "the uri argument passed as constructor parameter is different than the uri attribute in the object");
+    assert_equals(appControl.mime, mime, "the mime argument passed as constructor parameter is different than the mime attribute in the object");
+    assert_equals(appControl.category, category,
+        "the category argument passed as constructor parameter is different than the category attribute in the object");
+
+    for (i = 0; i < data[0].value.length; i++) {
+        assert_equals(appControl.data[0].value[i], data[0].value[i], "data passed as constructor parameter is different than data in the object");
+    }
+}, 'ApplicationControl_constructor');
+
+}
+
+function ApplicationControl_constructor_minargs() {
+
+//==== TEST: ApplicationControl_constructor_minargs
+//==== LABEL Test whether constructor with non-optional argument are supported
+//==== SPEC Tizen Web API:Application:Application:ApplicationControl:constructor C
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA CONSTRM CONSTRA
+
+test(function () {
+    var appControl, operation = "http://tizen.org/appcontrol/operation/share";
+
+    appControl = new tizen.ApplicationControl(operation);
+    assert_true(appControl instanceof tizen.ApplicationControl, "object was not created properly");
+    assert_equals(appControl.operation, operation,
+        "the operation argument passed as constructor parameter is different than the operation attribute in the object");
+
+}, 'ApplicationControl_constructor_minargs');
+
+}
+
+function ApplicationControl_data_attribute() {
+
+//==== TEST: ApplicationControl_data_attribute
+//==== LABEL Check attribute ApplicationControl::data existence and type
+//==== SPEC Tizen Web API:Application:Application:ApplicationControl:data A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT AN ASG
+
+test(function () {
+    var i, tmp, appControl1, appControl2, operation = "http://tizen.org/appcontrol/operation/share",
+        uri = "share.html", mime = "image/*", category = "dummyValue",
+        data = [new tizen.ApplicationControlData("images", ["imagedata1", "imagedata2"])],
+        newData = [new tizen.ApplicationControlData("images", ["imagedata3", "imagedata4"])];
+
+    appControl1 = new tizen.ApplicationControl(operation);
+    assert_true("data" in appControl1, "data doesn't exist in provided object.");
+    assert_array_equals(appControl1.data, [], "default value should be an empty array");
+    appControl2 = new tizen.ApplicationControl(operation, uri, mime, category, data);
+    assert_type(appControl2.data, "array", "type of data is different");
+    for (i = 0; i < appControl2.data[0].length; i++) {
+        assert_equals(appControl2.data[0].value[i], data[0].value[i], "data passed as constructor parameter is different than data in the object");
+    }
+    tmp = appControl2.data;
+    appControl2.data = null;
+    assert_not_equals(appControl2.data, null, "operation accept null");
+    appControl2.data = newData;
+    for (i = 0; i < appControl2.data[0].length; i++) {
+        assert_equals(appControl2.data[0].value[i], newData[0].value[i], "data can not be assigned a valid value");
+    }
+}, 'ApplicationControl_data_attribute');
+
+}
+
+function ApplicationControl_exist() {
+
+//==== TEST: ApplicationControl_exist
+//==== LABEL Check if ApplicationControl exist
+//==== SPEC Tizen Web API:Application:Application:ApplicationControl:constructor C
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA CONSTRF
+
+test(function () {
+    check_constructor("ApplicationControl");
+}, 'ApplicationControl_exist');
+
+}
+
+function ApplicationControl_extend() {
+
+//==== TEST: ApplicationControl_extend
+//==== LABEL Check if ApplicationControl possible extend
+//==== SPEC Tizen Web API:Application:Application:ApplicationControl:ApplicationControl U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA OBX
+
+test(function () {
+    var appControl = new tizen.ApplicationControl("http://tizen.org/appcontrol/operation/share");
+    check_extensibility(appControl);
+}, 'ApplicationControl_extend');
+
+}
+
+function ApplicationControl_mime_attribute() {
+
+//==== TEST: ApplicationControl_mime_attribute
+//==== LABEL Check attribute ApplicationControl::mime existence and type
+//==== SPEC Tizen Web API:Application:Application:ApplicationControl:mime A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ASG
+
+test(function () {
+    var appControl1, appControl2, operation = "http://tizen.org/appcontrol/operation/share",
+        uri = "share.html", mime = "image/*", newMime = "text/*";
+    appControl1 = new tizen.ApplicationControl(operation);
+    assert_true("mime" in appControl1, "mime doesn't exist in provided object.");
+    appControl2 = new tizen.ApplicationControl(operation, uri, mime);
+    assert_type(appControl2.mime, "string", "type of mime is different");
+    assert_equals(appControl2.mime, mime, "mime passed as constructor parameter is different than mime in the object");
+    appControl2.mime = newMime;
+    assert_equals(appControl2.mime, newMime, "mime can not be assigned a valid value");
+}, 'ApplicationControl_mime_attribute');
+
+}
+
+function ApplicationControl_operation_attribute() {
+
+//==== TEST: ApplicationControl_operation_attribute
+//==== LABEL Check attribute ApplicationControl::operation existence and type
+//==== SPEC Tizen Web API:Application:Application:ApplicationControl:operation A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ASG AN
+test(function () {
+    var appControl, operation = "http://tizen.org/appcontrol/operation/share", operationNewValue = "http://tizen.org/appcontrol/operation";
+    appControl = new tizen.ApplicationControl(operation);
+    assert_true("operation" in appControl, "operation doesn't exist in provided object.");
+    assert_type(appControl.operation, "string", "type of operation is different");
+    assert_equals(appControl.operation, operation, "operation passed as constructor parameter is different than operation in the object");
+    appControl.operation = null;
+    assert_not_equals(appControl.operation, null, "can assign a null value");
+    appControl.operation = operationNewValue;
+    assert_equals(appControl.operation, operationNewValue, "can not assign a valid value");
+}, 'ApplicationControl_operation_attribute');
+
+}
+
+function ApplicationControl_uri_attribute() {
+
+//==== TEST: ApplicationControl_uri_attribute
+//==== LABEL Check attribute ApplicationControl::uri existence and type
+//==== SPEC Tizen Web API:Application:Application:ApplicationControl:uri A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ASG
+test(function () {
+    var appControl1, appControl2, operation = "http://tizen.org/appcontrol/operation/share",
+        uri = "share.html", newUri = "share2.html";
+    appControl1 = new tizen.ApplicationControl(operation);
+    assert_true("uri" in appControl1, "uri doesn't exist in provided object.");
+    appControl2 = new tizen.ApplicationControl(operation, uri);
+    assert_type(appControl2.uri, "string", "type of uri is different");
+    assert_equals(appControl2.uri, uri, "uri passed as constructor parameter is different than uri in the object");
+    appControl2.uri = newUri;
+    assert_equals(appControl2.uri, newUri, "uri can not be assigned a valid value");
+}, 'ApplicationControl_uri_attribute');
+
+}
+
+function ApplicationInformationArraySuccessCallback_notexist() {
+
+//==== TEST: ApplicationInformationArraySuccessCallback_notexist
+//==== LABEL Check if ApplicationInformationArraySuccessCallback cannot be called as a function or in new expression
+//==== SPEC Tizen Web API:Application:Application:ApplicationInformationArraySuccessCallback:ApplicationInformationArraySuccessCallback U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA CBNIO
+
+test(function () {
+    check_no_interface_object("ApplicationInformationArraySuccessCallback");
+}, 'ApplicationInformationArraySuccessCallback_notexist');
+
+}
+
+function ApplicationInformationArraySuccessCallback_onsuccess() {
+
+//==== TEST: ApplicationInformationArraySuccessCallback_onsuccess
+//==== LABEL Check if ApplicationInformationArraySuccessCallback onsuccess is called and if its arguments have proper type
+//==== SPEC: Tizen Web API:Application:Application:ApplicationInformationArraySuccessCallback:onsuccess M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== ONLOAD_DELAY 90
+//==== TEST_CRITERIA CBT CBOA
+setup({timeout: 90000});
+
+var t = async_test('ApplicationInformationArraySuccessCallback_onsuccess', {timeout: 90000}),
+    getSuccess, getError;
+
+t.step(function () {
+    getSuccess = t.step_func(function (appInfo) {
+        assert_type(appInfo, "array", "type of the found value is not properly");
+        assert_true(appInfo.length > 0, "information was not found");
+        assert_true("id" in appInfo[0], "ApplicationInformation should have id property");
+        assert_true("name" in appInfo[0], "ApplicationInformation should have name property");
+        assert_true("iconPath" in appInfo[0], "ApplicationInformation should have iconPath property");
+        assert_true("version" in appInfo[0], "ApplicationInformation should have version property");
+        assert_true("show" in appInfo[0], "ApplicationInformation should have show property");
+        assert_true("categories" in appInfo[0], "ApplicationInformation should have categories property");
+        assert_true("installDate" in appInfo[0], "ApplicationInformation should have categories property");
+        assert_true("size" in appInfo[0], "ApplicationInformation should have size property");
+        assert_true("packageId" in appInfo[0], "ApplicationInformation should have packageId property");
+        t.done();
+    });
+
+    getError = t.step_func(function (error) {
+        assert_unreached("getAppsInfo() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    tizen.application.getAppsInfo(getSuccess, getError);
+});
+
+}
+
+function ApplicationInformationEventCallback_notexist() {
+
+//==== TEST: ApplicationInformationEventCallback_notexist
+//==== LABEL Check if ApplicationInformationEventCallback notexist
+//==== SPEC Tizen Web API:Application:Application:ApplicationInformationEventCallback:ApplicationInformationEventCallback U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA CBNIO
+
+test(function () {
+    check_no_interface_object("ApplicationInformationEventCallback");
+}, 'ApplicationInformationEventCallback_notexist');
+
+}
+
+function ApplicationInformation_categories_attribute() {
+
+//==== TEST: ApplicationInformation_categories_attribute
+//==== LABEL Check if ApplicationInformation have categories attribute with proper type, readonly, not null
+//==== SPEC: Tizen Web API:Application:Application:ApplicationInformation:categories A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== ONLOAD_DELAY 90
+//==== TEST_CRITERIA AE AT ARO
+setup({timeout: 90000});
+
+var t = async_test('ApplicationInformation_categories_attribute', {timeout: 90000}),
+    getSuccess, getError, info, tmp, i;
+
+t.step(function () {
+    getError = t.step_func(function (error) {
+        assert_unreached("getAppsInfo() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    getSuccess = t.step_func(function (informationArray) {
+        assert_true(informationArray.length > 0, "information was not found");
+
+        info = informationArray[0];
+        assert_true("categories" in info, "AplicationInformation should have categories attribute");
+        assert_type(info.categories, "array", "categories should be an array");
+        tmp = info.categories;
+        info.categories = ["one", "two"];
+        assert_equals(info.categories.length, tmp.length, "categories is not readonly");
+        for(i = 0; i < tmp.length; i++) {
+            assert_type(info.categories[i], "string", "categories items sould be a string");
+            assert_equals(info.categories[i], tmp[i], "categories is not readonly");
+        }
+
+        t.done();
+    });
+
+    tizen.application.getAppsInfo(getSuccess, getError);
+});
+
+}
+
+function ApplicationInformation_extend() {
+
+//==== TEST: ApplicationInformation_extend
+//==== LABEL Check if ApplicationInformation can have new properties added
+//==== SPEC: Tizen Web API:Application:Application:ApplicationInformation:ApplicationInformation U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P3
+//==== ONLOAD_DELAY 90
+//==== TEST_CRITERIA OBX
+setup({timeout: 90000});
+
+var t = async_test('ApplicationInformation_extend', {timeout: 90000}),
+    getSuccess, getError, info;
+
+t.step(function () {
+    getError = t.step_func(function (error) {
+        assert_unreached("getAppsInfo() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    getSuccess = t.step_func(function (informationArray) {
+        assert_true(informationArray.length > 0, "information was not found");
+
+        info = informationArray[0];
+        check_extensibility(info);
+
+        t.done();
+    });
+
+    tizen.application.getAppsInfo(getSuccess, getError);
+});
+
+}
+
+function ApplicationInformation_iconPath_attribute() {
+
+//==== TEST: ApplicationInformation_iconPath_attribute
+//==== LABEL Check if ApplicationInformation have iconPath attribute with proper type, readonly, not null
+//==== SPEC: Tizen Web API:Application:Application:ApplicationInformation:iconPath A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== ONLOAD_DELAY 90
+//==== TEST_CRITERIA AE AT ARO
+setup({timeout: 90000});
+
+var t = async_test('ApplicationInformation_iconPath_attribute', {timeout: 90000}),
+    getSuccess, getError, info;
+
+t.step(function () {
+    getError = t.step_func(function (error) {
+        assert_unreached("getAppsInfo() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    getSuccess = t.step_func(function (informationArray) {
+        assert_true(informationArray.length > 0, "information was not found");
+
+        info = informationArray[0];
+        assert_true("iconPath" in info, "AplicationInformation should have iconPath attribute");
+        check_readonly(info, "iconPath", info.iconPath, "string", "dummy");
+
+        t.done();
+    });
+
+    tizen.application.getAppsInfo(getSuccess, getError);
+});
+
+}
+
+function ApplicationInformation_id_attribute() {
+
+//==== TEST: ApplicationInformation_id_attribute
+//==== LABEL Check if ApplicationInformation have id attribute with proper type, readonly, not null
+//==== SPEC: Tizen Web API:Application:Application:ApplicationInformation:id A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== ONLOAD_DELAY 90
+//==== TEST_CRITERIA AE AT ARO
+setup({timeout: 90000});
+
+var t = async_test('ApplicationInformation_id_attribute', {timeout: 90000}),
+    getSuccess, getError, info;
+
+t.step(function () {
+    getError = t.step_func(function (error) {
+        assert_unreached("getAppsInfo() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    getSuccess = t.step_func(function (informationArray) {
+        assert_true(informationArray.length > 0, "information was not found");
+
+        info = informationArray[0];
+        assert_true("id" in info, "AplicationInformation should have id attribute");
+        check_readonly(info, "id", info.id, "string", "dummy");
+
+        t.done();
+    });
+
+    tizen.application.getAppsInfo(getSuccess, getError);
+});
+
+}
+
+function ApplicationInformation_installDate_attribute() {
+
+//==== TEST: ApplicationInformation_installDate_attribute
+//==== LABEL Check if ApplicationInformation have installDate attribute with proper type, readonly, not null
+//==== SPEC: Tizen Web API:Application:Application:ApplicationInformation:installDate A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== ONLOAD_DELAY 90
+//==== TEST_CRITERIA AE AT ARO
+setup({timeout: 90000});
+
+var t = async_test('ApplicationInformation_installDate_attribute', {timeout: 90000}),
+    getSuccess, getError, info, tmp;
+
+t.step(function () {
+    getError = t.step_func(function (error) {
+        assert_unreached("getAppsInfo() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    getSuccess = t.step_func(function (informationArray) {
+        assert_true(informationArray.length > 0, "information was not found");
+
+        info = informationArray[0];
+        assert_true("installDate" in info, "AplicationInformation should have installDate attribute");
+        assert_type(info.installDate, "date", "installDate should be a date");
+        tmp = info.installDate;
+        info.installDate = new Date();
+        assert_equals(info.installDate.getTime(), tmp.getTime(), "values are different");
+
+        t.done();
+    });
+
+    tizen.application.getAppsInfo(getSuccess, getError);
+});
+
+}
+
+function ApplicationInformation_name_attribute() {
+
+//==== TEST: ApplicationInformation_name_attribute
+//==== LABEL Check if ApplicationInformation have name attribute with proper type, readonly, not null
+//==== SPEC: Tizen Web API:Application:Application:ApplicationInformation:name A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== ONLOAD_DELAY 90
+//==== TEST_CRITERIA AE AT ARO
+setup({timeout: 90000});
+
+var t = async_test('ApplicationInformation_name_attribute', {timeout: 90000}),
+    getSuccess, getError, info;
+
+t.step(function () {
+    getError = t.step_func(function (error) {
+        assert_unreached("getAppsInfo() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    getSuccess = t.step_func(function (informationArray) {
+        assert_true(informationArray.length > 0, "information was not found");
+
+        info = informationArray[0];
+        assert_true("name" in info, "AplicationInformation should have name attribute");
+        check_readonly(info, "name", info.name, "string", "dummy");
+
+        t.done();
+    });
+
+    tizen.application.getAppsInfo(getSuccess, getError);
+});
+
+}
+
+function ApplicationInformation_notexist() {
+
+//==== TEST: ApplicationInformation_notexist
+//==== LABEL Check if ApplicationInformation cannot be called as a function or in new expression
+//==== SPEC Tizen Web API:Application:Application:ApplicationInformation:ApplicationInformation U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("ApplicationInformation");
+}, 'ApplicationInformation_notexist');
+
+}
+
+function ApplicationInformation_packageId_attribute() {
+
+//==== TEST: ApplicationInformation_packageId_attribute
+//==== LABEL Check if ApplicationInformation have packageId attribute with proper type, readonly, not null
+//==== SPEC: Tizen Web API:Application:Application:ApplicationInformation:packageId A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== ONLOAD_DELAY 90
+//==== TEST_CRITERIA AE AT ARO
+setup({timeout: 90000});
+
+var t = async_test('ApplicationInformation_packageId_attribute', {timeout: 90000}),
+    getSuccess, getError, info;
+
+t.step(function () {
+    getError = t.step_func(function (error) {
+        assert_unreached("getAppsInfo() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    getSuccess = t.step_func(function (informationArray) {
+        assert_true(informationArray.length > 0, "information was not found");
+
+        info = informationArray[0];
+        assert_true("packageId" in info, "AplicationInformation should have packageId attribute");
+        check_readonly(info, "packageId", info.packageId, "string", "dummy");
+
+        t.done();
+    });
+
+    tizen.application.getAppsInfo(getSuccess, getError);
+});
+
+}
+
+function ApplicationInformation_show_attribute() {
+
+//==== TEST: ApplicationInformation_show_attribute
+//==== LABEL Check if ApplicationInformation have show attribute with proper type, readonly, not null
+//==== SPEC: Tizen Web API:Application:Application:ApplicationInformation:show A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== ONLOAD_DELAY 90
+//==== TEST_CRITERIA AE AT ARO
+setup({timeout: 90000});
+
+var t = async_test('ApplicationInformation_show_attribute', {timeout: 90000}),
+    getSuccess, getError, info;
+
+t.step(function () {
+    getError = t.step_func(function (error) {
+        assert_unreached("getAppsInfo() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    getSuccess = t.step_func(function (informationArray) {
+        assert_true(informationArray.length > 0, "information was not found");
+
+        info = informationArray[0];
+        assert_true("show" in info, "AplicationInformation should have show attribute");
+        check_readonly(info, "show", info.show, "boolean", !info.show);
+
+        t.done();
+    });
+
+    tizen.application.getAppsInfo(getSuccess, getError);
+});
+
+}
+
+function ApplicationInformation_size_attribute() {
+
+//==== TEST: ApplicationInformation_size_attribute
+//==== LABEL Check if ApplicationInformation have size attribute with proper type, readonly, not null
+//==== SPEC: Tizen Web API:Application:Application:ApplicationInformation:size A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== ONLOAD_DELAY 90
+//==== TEST_CRITERIA AE AT ARO
+setup({timeout: 90000});
+
+var t = async_test('ApplicationInformation_size_attribute', {timeout: 90000}),
+    getSuccess, getError, info;
+
+t.step(function () {
+    getError = t.step_func(function (error) {
+        assert_unreached("getAppsInfo() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    getSuccess = t.step_func(function (informationArray) {
+        assert_true(informationArray.length > 0, "information was not found");
+
+        info = informationArray[0];
+        assert_true("size" in info, "AplicationInformation should have size attribute");
+        check_readonly(info, "size", info.size, "number", 2 + 3 * info.size / 2);
+
+        t.done();
+    });
+
+    tizen.application.getAppsInfo(getSuccess, getError);
+});
+
+}
+
+function ApplicationInformation_version_attribute() {
+
+//==== TEST: ApplicationInformation_version_attribute
+//==== LABEL Check if ApplicationInformation have version attribute with proper type, readonly, not null
+//==== SPEC: Tizen Web API:Application:Application:ApplicationInformation:version A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== ONLOAD_DELAY 90
+//==== TEST_CRITERIA AE AT ARO
+setup({timeout: 90000});
+
+var t = async_test('ApplicationInformation_version_attribute', {timeout: 90000}),
+    getSuccess, getError, info;
+
+t.step(function () {
+    getError = t.step_func(function (error) {
+        assert_unreached("getAppsInfo() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    getSuccess = t.step_func(function (informationArray) {
+        assert_true(informationArray.length > 0, "information was not found");
+
+        info = informationArray[0];
+        assert_true("version" in info, "AplicationInformation should have version attribute");
+        check_readonly(info, "version", info.version, "string", "dummy");
+
+        t.done();
+    });
+
+    tizen.application.getAppsInfo(getSuccess, getError);
+});
+
+}
+
+function ApplicationManagerObject_notexist() {
+
+//==== TEST: ApplicationManagerObject_notexist
+//==== LABEL Check if ApplicationManagerObject not exist
+//==== SPEC Tizen Web API:Application:Application:ApplicationManagerObject:ApplicationManagerObject U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("ApplicationManagerObject");
+}, 'ApplicationManagerObject_notexist');
+
+}
+
+function ApplicationManager_addAppInfoEventListener_eventCallback_TypeMismatch() {
+
+//==== TEST: ApplicationManager_addAppInfoEventListener_eventCallback_TypeMismatch
+//==== LABEL Check non-optional argument 'ApplicationInformationEventCallback' type conversion
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:addAppInfoEventListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+test(function () {
+    var i, conversionTable = getTypeConversionExceptions("object");
+
+    for (i = 0; i < conversionTable.length; i++) {
+        assert_throws({name: conversionTable[i][1]}, function () {
+            tizen.application.addAppInfoEventListener(conversionTable[i][0]);
+        }, "exception should be thrown");
+    }
+
+}, 'ApplicationManager_addAppInfoEventListener_eventCallback_TypeMismatch');
+
+}
+
+function ApplicationManager_addAppInfoEventListener_eventCallback_invalid_cb() {
+
+//==== TEST: ApplicationManager_addAppInfoEventListener_eventCallback_invalid_cb
+//==== LABEL Check if an exception was thrown when a fake callback was passed into addAppInfoEventListener method
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:addAppInfoEventListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTL
+
+test(function () {
+    var i, conversionTable = getListenerConversionExceptions(["oninstalled", "onupdated", "onuninstalled"]);
+
+    for (i = 0; i < conversionTable.length; i++) {
+        assert_throws({name: conversionTable[i][1]}, function () {
+            tizen.application.addAppInfoEventListener(conversionTable[i][0]);
+        }, "an exception should be thrown");
+    }
+
+}, 'ApplicationManager_addAppInfoEventListener_eventCallback_invalid_cb');
+
+}
+
+function ApplicationManager_addAppInfoEventListener_exist() {
+
+//==== TEST: ApplicationManager_addAppInfoEventListener_exist
+//==== LABEL Check if method addAppInfoEventListener exist
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:addAppInfoEventListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    check_method_exists(tizen.application, "addAppInfoEventListener");
+}, 'ApplicationManager_addAppInfoEventListener_exist');
+
+}
+
+function ApplicationManager_addAppInfoEventListener_missarg() {
+
+//==== TEST: ApplicationManager_addAppInfoEventListener_missarg
+//==== LABEL Check addAppInfoEventListener with missing non-optional ApplicationInformationEventCallback argument
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:addAppInfoEventListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MMA
+
+test(function () {
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        tizen.application.addAppInfoEventListener();
+    }, "method was called without ApplicationInformationEventCallback but exception was not thrown");
+}, 'ApplicationManager_addAppInfoEventListener_missarg');
+
+}
+
+function ApplicationManager_extend() {
+
+//==== TEST: ApplicationManager_extend
+//==== LABEL Check if ApplicationManager possible extend
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:ApplicationManager U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA OBX
+
+test(function () {
+    check_extensibility(tizen.application);
+}, 'ApplicationManager_extend');
+
+}
+
+function ApplicationManager_findAppControl() {
+
+//==== TEST: ApplicationManager_findAppControl
+//==== LABEL Check using findAppControl method (with non-optional arguments) in ApplicationManager interface to get ApplicationsInformation of applications can be launched with the given application control
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:findAppControl M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MMINA MR
+
+setup({timeout: 30000});
+
+var t = async_test('ApplicationManager_findAppControl', {timeout: 30000}), i, findSuccess, appControl, retVal = null;
+
+t.step(function () {
+    appControl = new tizen.ApplicationControl(
+        TCT_APPCONTROL_LAUNCH_APPCONTROL_EXPLICIT_OPERATION,
+        TCT_APPCONTROL_LAUNCH_APPCONTROL_EXPLICIT_URI,
+        TCT_APPCONTROL_LAUNCH_APPCONTROL_EXPLICIT_MIME
+    );
+
+    findSuccess = t.step_func(function (appInfos, appControl) {
+        assert_equals(retVal, undefined, "incorrect returned value");
+        assert_type(appInfos, "array", "incorrect type of the received value");
+        assert_equals(appInfos.length, 2, "incorrect length of the received array");
+        for (i = 0; i < appInfos.length; i++) {
+            assert_type(appInfos[i], "object", "type of the found value is not properly");
+            assert_true("id" in appInfos[i], "no id in returned value");
+            assert_true("name" in appInfos[i], "no name in returned value");
+            assert_true("iconPath" in appInfos[i], "no iconPath in returned value");
+            assert_true("version" in appInfos[i], "no version in returned value");
+            assert_true("show" in appInfos[i], "no show in returned value");
+            assert_true("categories" in appInfos[i], "no categories in returned value");
+            assert_true("installDate" in appInfos[i], "no installDate in returned value");
+            assert_true("size" in appInfos[i], "no size in returned value");
+            assert_true("packageId" in appInfos[i], "no packageId in returned value");
+            if ((appInfos[i].id !== TCT_APPCONTROL_APPID) && (appInfos[i].id !== TCT_APPCONTROL_MOCK_APPID)) {
+                assert_unreached("wrong Application was found");
+            }
+        }
+        assert_true(appControl instanceof tizen.ApplicationControl, "wrong ApplicationControl");
+        t.done();
+    });
+
+    retVal = tizen.application.findAppControl(appControl, findSuccess);
+});
+
+}
+
+function ApplicationManager_findAppControl_appControl_TypeMismatch() {
+
+//==== TEST: ApplicationManager_findAppControl_appControl_TypeMismatch
+//==== LABEL Check non-optional argument ApplicationControl (findAppControl method) type conversion
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:findAppControl M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test('ApplicationManager_findAppControl_appControl_TypeMismatch', {timeout: 30000}),
+    i, findSuccess, conversionTable = getTypeConversionExceptions("object");
+
+t.step(function () {
+    findSuccess = t.step_func(function () {
+        assert_unreached("this function should not be run");
+    });
+
+    for (i = 0; i < conversionTable.length; i++) {
+        assert_throws({name: conversionTable[i][1]}, function () {
+            tizen.application.findAppControl(conversionTable[i][0], findSuccess);
+        }, "exception should be thrown");
+    }
+
+    t.done();
+
+}, "ApplicationManager_findAppControl_appControl_TypeMismatch");
+
+}
+
+function ApplicationManager_findAppControl_appControl_invalid_obj() {
+
+//==== TEST: ApplicationManager_findAppControl_appControl_invalid_obj
+//==== LABEL Check if an exception was thrown when a fake object (ApplicationControl) was passed into findAppControl method
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:findAppControl M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTO
+
+setup({timeout: 30000});
+
+var t = async_test('ApplicationManager_findAppControl_appControl_invalid_obj', {timeout: 30000}), findSuccess, appControl;
+t.step(function () {
+    appControl = {
+        operation: TCT_APPCONTROL_LAUNCH_APPCONTROL_OPERATION,
+        uri: TCT_APPCONTROL_LAUNCH_APPCONTROL_URI,
+        mime: TCT_APPCONTROL_LAUNCH_APPCONTROL_MIME,
+        category: "/opt",
+        data: [new tizen.ApplicationControlData("key", ["value1", "value2"])]
+    };
+
+    findSuccess = t.step_func(function () {
+        assert_unreached("this function should not be run");
+    });
+
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        tizen.application.findAppControl(appControl, findSuccess);
+    }, "exception should be thrown");
+
+    t.done();
+}, "ApplicationManager_findAppControl_appControl_invalid_obj");
+
+}
+
+function ApplicationManager_findAppControl_errorCallback_TypeMismatch() {
+
+//==== TEST: ApplicationManager_findAppControl_errorCallback_TypeMismatch
+//==== LABEL Check optional argument errorCallback (findAppControl method) type conversion
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:findAppControl M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test('ApplicationManager_findAppControl_errorCallback_TypeMismatch', {timeout: 30000}),
+    i, findSuccess, conversionTable = getTypeConversionExceptions("functionObject", true), appControl;
+
+t.step(function () {
+    appControl = new tizen.ApplicationControl(
+        TCT_APPCONTROL_LAUNCH_APPCONTROL_OPERATION
+    );
+
+    findSuccess = t.step_func(function () {
+        assert_unreached("this function should not be run");
+    });
+
+    for (i = 0; i < conversionTable.length; i++) {
+        assert_throws({name: conversionTable[i][1]}, function () {
+            tizen.application.findAppControl(appControl, findSuccess, conversionTable[i][0]);
+        }, "exception should be thrown");
+    }
+
+    t.done();
+
+});
+
+}
+
+function ApplicationManager_findAppControl_errorCallback_invalid_cb() {
+
+//==== TEST: ApplicationManager_findAppControl_errorCallback_invalid_cb
+//==== LABEL Check if an exception was thrown when a fake callback (onerror) was passed into findAppControl method
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:findAppControl M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 30000});
+
+var t = async_test('ApplicationManager_findAppControl_errorCallback_invalid_cb', {timeout: 30000}),
+    findSuccess, findErrorFunc, findError, appControl;
+
+t.step(function () {
+    appControl = new tizen.ApplicationControl(
+        TCT_APPCONTROL_LAUNCH_APPCONTROL_OPERATION
+    );
+
+    findSuccess = t.step_func(function () {
+        assert_unreached("this function should not be run");
+    });
+
+    findErrorFunc = t.step_func(function (error) {
+        assert_unreached("findAppControl() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    findError = {
+        onerror: findErrorFunc
+    };
+
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        tizen.application.findAppControl(appControl, findSuccess, findError);
+    }, "exception should be thrown");
+
+    t.done();
+});
+
+}
+
+function ApplicationManager_findAppControl_exist() {
+
+//==== TEST: ApplicationManager_findAppControl_exist
+//==== LABEL Check if method findAppControl exist
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:findAppControl M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    check_method_exists(tizen.application, "findAppControl");
+}, 'ApplicationManager_findAppControl_exist');
+
+}
+
+function ApplicationManager_findAppControl_missarg() {
+
+//==== TEST: ApplicationManager_findAppControl_missarg
+//==== LABEL Check findAppControl with missing non-optional argument
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:findAppControl M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MMA
+
+test(function () {
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        tizen.application.findAppControl();
+    }, "Method was called without arguments but exception was not thrown");
+}, 'ApplicationManager_findAppControl_missarg');
+
+}
+
+function ApplicationManager_findAppControl_successCallback_TypeMismatch() {
+
+//==== TEST: ApplicationManager_findAppControl_successCallback_TypeMismatch
+//==== LABEL Check non-optional argument successCallback (findAppControl method) type conversion
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:findAppControl M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test('ApplicationManager_findAppControl_successCallback_TypeMismatch', {timeout: 30000}),
+    i, conversionTable = getTypeConversionExceptions("functionObject"), appControl;
+t.step(function () {
+    appControl = new tizen.ApplicationControl(
+        TCT_APPCONTROL_LAUNCH_APPCONTROL_OPERATION
+    );
+
+    for (i = 0; i < conversionTable.length; i++) {
+        assert_throws({name: conversionTable[i][1]}, function () {
+            tizen.application.findAppControl(appControl, conversionTable[i][0]);
+        }, "exception should be thrown");
+    }
+
+    t.done();
+
+}, "ApplicationManager_findAppControl_successCallback_TypeMismatch");
+
+}
+
+function ApplicationManager_findAppControl_successCallback_invalid_cb() {
+
+//==== TEST: ApplicationManager_findAppControl_successCallback_invalid_cb
+//==== LABEL Check if an exception was thrown when a fake callback (onSuccess) was passed into findAppControl method
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:findAppControl M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 30000});
+
+var t = async_test('ApplicationManager_findAppControl_successCallback_invalid_cb', {timeout: 30000}),
+    findSuccess, findSuccessFunc, appControl;
+
+t.step(function () {
+    appControl = new tizen.ApplicationControl(
+        TCT_APPCONTROL_LAUNCH_APPCONTROL_OPERATION
+    );
+
+    findSuccessFunc = t.step_func(function () {
+        assert_unreached("this function should not be used");
+    });
+
+    findSuccess = { onsuccess: findSuccessFunc };
+
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        tizen.application.findAppControl(appControl, findSuccess);
+    }, "exception should be thrown");
+
+    t.done();
+
+}, "ApplicationManager_findAppControl_successCallback_invalid_cb");
+
+}
+
+function ApplicationManager_findAppControl_successCallback_missarg() {
+
+//==== TEST: ApplicationManager_findAppControl_successCallback_missarg
+//==== LABEL Check findAppControl with missing non-optional successCallback argument
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:findAppControl M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MMA
+
+test(function () {
+    var appControl = new tizen.ApplicationControl(TCT_APPCONTROL_LAUNCH_APPCONTROL_OPERATION);
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        tizen.application.findAppControl(appControl);
+    }, "Method was called without successCallback but exception was not thrown");
+}, 'ApplicationManager_findAppControl_successCallback_missarg');
+
+}
+
+function ApplicationManager_findAppControl_with_errorCallback() {
+
+//==== TEST: ApplicationManager_findAppControl_with_errorCallback
+//==== LABEL Check using findAppControl method (with optional argument errorCallback) in ApplicationManager interface
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:findAppControl M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MOA
+
+setup({timeout: 30000});
+
+var t = async_test('ApplicationManager_findAppControl_with_errorCallback', {timeout: 30000}),
+    i, findSuccess, findError, appControl;
+
+t.step(function () {
+    appControl = new tizen.ApplicationControl(
+        TCT_APPCONTROL_LAUNCH_APPCONTROL_EXPLICIT_OPERATION,
+        TCT_APPCONTROL_LAUNCH_APPCONTROL_EXPLICIT_URI,
+        TCT_APPCONTROL_LAUNCH_APPCONTROL_EXPLICIT_MIME
+    );
+
+    findSuccess = t.step_func(function (appInfos, appControl) {
+        assert_type(appInfos, "array", "incorrect type of the received value");
+        assert_equals(appInfos.length, 2, "incorrect length of the received array");
+        for (i = 0; i < appInfos.length; i++) {
+            assert_type(appInfos[i], "object", "type of the found value is not properly");
+            assert_true("id" in appInfos[i], "no id in returned value");
+            assert_true("name" in appInfos[i], "no name in returned value");
+            assert_true("iconPath" in appInfos[i], "no iconPath in returned value");
+            assert_true("version" in appInfos[i], "no version in returned value");
+            assert_true("show" in appInfos[i], "no show in returned value");
+            assert_true("categories" in appInfos[i], "no categories in returned value");
+            assert_true("installDate" in appInfos[i], "no installDate in returned value");
+            assert_true("size" in appInfos[i], "no size in returned value");
+            assert_true("packageId" in appInfos[i], "no packageId in returned value");
+            if ((appInfos[i].id !== TCT_APPCONTROL_APPID) && (appInfos[i].id !== TCT_APPCONTROL_MOCK_APPID)) {
+                assert_unreached("wrong Application was found");
+            }
+        }
+        assert_true(appControl instanceof tizen.ApplicationControl, "wrong ApplicationControl");
+        t.done();
+    });
+
+    findError = t.step_func(function (error) {
+        assert_unreached("findAppControl() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    tizen.application.findAppControl(appControl, findSuccess, findError);
+
+});
+
+}
+
+function ApplicationManager_getAppCerts() {
+
+//==== TEST: ApplicationManager_getAppCerts
+//==== LABEL Check using getAppCerts method (with non-optional arguments) in ApplicationManager interface to get application certificates for current application
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:getAppCerts M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MMINA MR
+
+test(function () {
+    var i, appCerts = tizen.application.getAppCerts();
+    assert_type(appCerts, "array", "type of the found value is not properly");
+    assert_not_equals(appCerts.length, 0, "array length should be > 0");
+    for (i = 0; i < appCerts.length; i++) {
+        assert_type(appCerts[i], "object", "type of the element of the returned array is not properly");
+        assert_true("type" in appCerts[i], "no type in returned value");
+        assert_true("value" in appCerts[i], "no value in returned value");
+    }
+}, 'ApplicationManager_getAppCerts');
+
+}
+
+function ApplicationManager_getAppCerts_exist() {
+
+//==== TEST: ApplicationManager_getAppCerts_exist
+//==== LABEL Check if method getAppCerts exist
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:getAppCerts M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    check_method_exists(tizen.application, "getAppCerts");
+}, 'ApplicationManager_getAppCerts_exist');
+
+}
+
+function ApplicationManager_getAppCerts_with_id() {
+
+//==== TEST: ApplicationManager_getAppCerts_with_id
+//==== LABEL Check using getAppCerts method (with id argument) in ApplicationManager interface to get application certificates
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:getAppCerts M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MOA MR
+
+test(function () {
+    var i, appCerts = tizen.application.getAppCerts(THIS_APP_ID);
+    assert_type(appCerts, "array", "type of the found value is not properly");
+    assert_not_equals(appCerts.length, 0, "array length should be > 0");
+    for (i = 0; i < appCerts.length; i++) {
+        assert_type(appCerts[i], "object", "type of the element of the returned array is not properly");
+        assert_true("type" in appCerts[i], "no type in returned value");
+        assert_true("value" in appCerts[i], "no value in returned value");
+    }
+}, 'ApplicationManager_getAppCerts_with_id');
+
+}
+
+function ApplicationManager_getAppContext() {
+
+//==== TEST: ApplicationManager_getAppContext
+//==== LABEL Check using getAppContext method (with non-optional arguments) in ApplicationManager interface to get ApplicationContext of current application
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:getAppContext M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MMINA MR
+
+test(function () {
+    var appContext = tizen.application.getAppContext();
+    assert_type(appContext, "object", "type of the returned value is not properly");
+    assert_true("id" in appContext, "no id in returned value");
+    assert_true("appId" in appContext, "no appId in returned value");
+    assert_equals(appContext.appId, THIS_APP_ID, "wrong ApplicationContext was returned");
+}, 'ApplicationManager_getAppContext');
+
+}
+
+function ApplicationManager_getAppContext_exist() {
+
+//==== TEST: ApplicationManager_getAppContext_exist
+//==== LABEL Check if method getAppContext exist
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:getAppContext M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    check_method_exists(tizen.application, "getAppContext");
+}, 'ApplicationManager_getAppContext_exist');
+
+}
+
+function ApplicationManager_getAppContext_with_contextId() {
+
+//==== TEST: ApplicationManager_getAppContext_with_contextId
+//==== LABEL Check using getAppContext method (with optional argument contextId) in ApplicationManager interface to get ApplicationContext with given contextId
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:getAppContext M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MOA MR
+
+test(function () {
+    var appContext1, appContext2;
+
+    appContext1 = tizen.application.getAppContext();
+
+    appContext2 = tizen.application.getAppContext(appContext1.id);
+    assert_type(appContext2, "object", "type of the found first value is not properly");
+    assert_true("id" in appContext2, "no id in returned value");
+    assert_true("appId" in appContext2, "no appId in returned value");
+
+    assert_equals(appContext1.id, appContext2.id, "wrong ApplicationContext was found");
+    assert_equals(appContext1.appId, appContext2.appId, "wrong ApplicationContext was found");
+}, 'ApplicationManager_getAppContext_with_contextId');
+
+}
+
+function ApplicationManager_getAppInfo() {
+
+//==== TEST: ApplicationManager_getAppInfo
+//==== LABEL Check using getAppInfo method (with non-optional arguments) in ApplicationManager interface to get ApplicationInformation of current application
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:getAppInfo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MMINA MR
+
+test(function () {
+    var appInfo = tizen.application.getAppInfo();
+    assert_type(appInfo, "object", "type of the found value is not properly");
+    assert_true("id" in appInfo, "no id in returned value");
+    assert_true("name" in appInfo, "no name in returned value");
+    assert_true("iconPath" in appInfo, "no iconPath in returned value");
+    assert_true("version" in appInfo, "no version in returned value");
+    assert_true("show" in appInfo, "no show in returned value");
+    assert_true("categories" in appInfo, "no categories in returned value");
+    assert_true("installDate" in appInfo, "no installDate in returned value");
+    assert_true("size" in appInfo, "no size in returned value");
+    assert_true("packageId" in appInfo, "no packageId in returned value");
+    assert_equals(appInfo.id, THIS_APP_ID, "wrong ApplicationInformation was returned");
+}, 'ApplicationManager_getAppInfo');
+
+}
+
+function ApplicationManager_getAppInfo_exist() {
+
+//==== TEST: ApplicationManager_getAppInfo_exist
+//==== LABEL Check if method getAppInfo exist
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:getAppInfo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    check_method_exists(tizen.application, "getAppInfo");
+}, 'ApplicationManager_getAppInfo_exist');
+
+}
+
+function ApplicationManager_getAppInfo_with_id() {
+
+//==== TEST: ApplicationManager_getAppInfo_with_id
+//==== LABEL Check using getAppInfo method (with optional argument ApplicationId) in ApplicationManager interface to get ApplicationInformation with given ApplicationId
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:getAppInfo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MOA MR
+
+test(function () {
+    var i, appInfo1, appInfo2, requiredFields = ["id", "name", "iconPath", "version", "show", "categories", "installDate", "size", "packageId"];
+
+    appInfo1 = tizen.application.getAppInfo();
+
+    appInfo2 = tizen.application.getAppInfo(appInfo1.id);
+    assert_type(appInfo2, "object", "type of the returned value is not properly");
+    for (i = 0; i < requiredFields.length; i++) {
+        assert_true(requiredFields[i] in appInfo2, "no " + requiredFields[i] + " in returned value");
+    }
+
+    for (i = 0; i < requiredFields.length; i++) {
+        if (requiredFields[i] === "categories") {
+            assert_array_equals(appInfo1[requiredFields[i]], appInfo2[requiredFields[i]], "wrong ApplicationInformation was returned");
+        } else if (requiredFields[i] === "installDate") {
+            assert_equals(appInfo1[requiredFields[i]].getTime(), appInfo2[requiredFields[i]].getTime(), "wrong ApplicationInformation was returned");
+        } else {
+            assert_equals(appInfo1[requiredFields[i]], appInfo2[requiredFields[i]], "wrong ApplicationInformation was returned");
+        }
+    }
+
+}, 'ApplicationManager_getAppInfo_with_id');
+
+}
+
+function ApplicationManager_getAppMetaData() {
+
+//==== TEST: ApplicationManager_getAppMetaData
+//==== LABEL Check the method ApplicationManager::getAppMetaData() called without arguments
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:getAppMetaData M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== TEST_CRITERIA MMINA MR
+
+test(function () {
+    var appMetaData = tizen.application.getAppMetaData(null);
+
+    assert_type(appMetaData, "array", "type of the found value is not array (null argument)");
+    assert_equals(appMetaData.length, 1, "Incorrect number of metadata (null argument)");
+    assert_equals(appMetaData[0].key, METADATA_KEY, "Incorrect metadata key (null argument)");
+    assert_equals(appMetaData[0].value, METADATA_VALUE, "Incorrect metadata value (null argument)");
+
+    appMetaData = tizen.application.getAppMetaData();
+    assert_type(appMetaData, "array", "type of the found value is not array");
+    assert_equals(appMetaData.length, 1, "Incorrect number of metadata.");
+    assert_equals(appMetaData[0].key, METADATA_KEY, "Incorrect metadata key");
+    assert_equals(appMetaData[0].value, METADATA_VALUE, "Incorrect metadata value");
+}, 'ApplicationManager_getAppMetaData');
+
+}
+
+function ApplicationManager_getAppMetaData_exist() {
+
+//==== TEST: ApplicationManager_getAppMetaData_exist
+//==== LABEL Check if method ApplicationManager::getAppMetaData exists
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:getAppMetaData M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    check_method_exists(tizen.application, "getAppMetaData");
+}, 'ApplicationManager_getAppMetaData_exist');
+
+}
+
+function ApplicationManager_getAppMetaData_with_id() {
+
+//==== TEST: ApplicationManager_getAppMetaData_with_id
+//==== LABEL Check the method ApplicationManager::getAppMetaData() called with id argument
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:getAppMetaData M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== TEST_CRITERIA MOA MR
+
+test(function () {
+    var i, appMetaData = tizen.application.getAppMetaData(TCT_APPCONTROL_APPID), key;
+
+    assert_type(appMetaData, "array", "type of the found value is not array");
+    assert_equals(appMetaData.length, 2, "Incorrect number of metadata.");
+    for (i = 0; i < appMetaData.length; i++) {
+        assert_type(appMetaData[i], "object", "type of the element of the returned array is not properly");
+        assert_true("key" in appMetaData[i], "no type in returned value");
+        assert_true("value" in appMetaData[i], "no value in returned value");
+
+        key = appMetaData[i].key;
+        assert_own_property(TCT_APPCONTROL_APPID_METADATA, key, "Incorrect key");
+        assert_equals(appMetaData[i].value, TCT_APPCONTROL_APPID_METADATA[key], "Incorrect value");
+        delete TCT_APPCONTROL_APPID_METADATA[key];
+    }
+}, 'ApplicationManager_getAppMetaData_with_id');
+
+}
+
+function ApplicationManager_getAppSharedURI() {
+
+//==== TEST: ApplicationManager_getAppSharedURI
+//==== LABEL Check using getAppSharedURI method (with non-optional arguments) in ApplicationManager interface to get URI shared directory of current application
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:getAppSharedURI M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MMINA MR
+
+test(function () {
+    var sharedDir = tizen.application.getAppSharedURI();
+    assert_type(sharedDir, "string", "type of the found value is not properly");
+}, 'ApplicationManager_getAppSharedURI');
+
+}
+
+function ApplicationManager_getAppSharedURI_exist() {
+
+//==== TEST: ApplicationManager_getAppSharedURI_exist
+//==== LABEL Check if method getAppSharedURI exist
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:getAppSharedURI M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    check_method_exists(tizen.application, "getAppSharedURI");
+}, 'ApplicationManager_getAppSharedURI_exist');
+
+}
+
+function ApplicationManager_getAppSharedURI_with_id() {
+
+//==== TEST: ApplicationManager_getAppSharedURI_with_id
+//==== LABEL Check using getAppSharedURI method (with optional argument ApplicationId) in ApplicationManager interface to get URI shared directory of application with given ApplicationId
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:getAppSharedURI M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MOA MR
+
+test(function () {
+    var sharedDir = tizen.application.getAppSharedURI(TCT_APPCONTROL_APPID);
+    assert_type(sharedDir, "string", "type of the found value is not properly");
+}, 'ApplicationManager_getAppSharedURI_with_id');
+
+}
+
+function ApplicationManager_getAppsContext() {
+
+//==== TEST: ApplicationManager_getAppsContext
+//==== LABEL Check using getAppsContext method (with non-optional arguments) in ApplicationManager interface to get ApplicationsContext of applications that are currently running on a device
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:getAppsContext M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MMINA MR
+
+setup({timeout: 30000});
+
+var t = async_test('ApplicationManager_getAppsContext', {timeout: 30000}), getSuccess, i, foundCurrentApplication = false, retVal = null;
+
+t.step(function () {
+
+    getSuccess = t.step_func(function (appContextArray) {
+        assert_equals(retVal, undefined, "incorrect returned value");
+        assert_type(appContextArray , "array", "type of the found value is not properly");
+        for (i = 0; i < appContextArray.length; i++) {
+            assert_type(appContextArray[i], "object", "type of the found value is not properly");
+            assert_true("id" in appContextArray[i], "no id in returned value");
+            assert_true("appId" in appContextArray[i], "no appId in returned value");
+            if (appContextArray[i].appId === THIS_APP_ID) {
+                foundCurrentApplication = true;
+            }
+        }
+        if (!foundCurrentApplication) {
+            assert_unreached("current application context wasn't found");
+        }
+
+        t.done();
+    });
+
+    retVal = tizen.application.getAppsContext(getSuccess);
+
+});
+
+}
+
+function ApplicationManager_getAppsContext_errorCallback_TypeMismatch() {
+
+//==== TEST: ApplicationManager_getAppsContext_errorCallback_TypeMismatch
+//==== LABEL Check optional argument errorCallback (getAppsContext method) type conversion
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:getAppsContext M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test('ApplicationManager_getAppsContext_errorCallback_TypeMismatch', {timeout: 30000}), i, getCallback, conversionTable = getTypeConversionExceptions("functionObject",
+    true);
+t.step(function () {
+
+    getCallback = t.step_func(function () {
+        assert_unreached("this function should not be run");
+    });
+
+    for (i = 0; i < conversionTable.length; i++) {
+        assert_throws({name: conversionTable[i][1]}, function () {
+            tizen.application.getAppsContext(getCallback, conversionTable[i][0]);
+        }, "exception should be thrown");
+    }
+
+    t.done();
+
+});
+
+}
+
+function ApplicationManager_getAppsContext_errorCallback_invalid_cb() {
+
+//==== TEST: ApplicationManager_getAppsContext_errorCallback_invalid_cb
+//==== LABEL Check if an exception was thrown when a fake callback (onerror) was passed into getAppsContext method
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:getAppsContext M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 30000});
+
+var t = async_test('ApplicationManager_getAppsContext_errorCallback_invalid_cb', {timeout: 30000}), getSuccess, getError, getErrorFunc;
+t.step(function () {
+
+    getSuccess = t.step_func(function () {
+        assert_unreached("application should not be run");
+    });
+
+    getErrorFunc = t.step_func(function (error) {
+        assert_unreached("getAppsContext() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    getError = {
+        onerror: getErrorFunc
+    };
+
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        tizen.application.getAppsContext(getSuccess, getError);
+    }, "exception should be thrown");
+
+    t.done();
+
+});
+
+}
+
+function ApplicationManager_getAppsContext_exist() {
+
+//==== TEST: ApplicationManager_getAppsContext_exist
+//==== LABEL Check if method getAppsContext exists
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:getAppsContext M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    check_method_exists(tizen.application, "getAppsContext");
+}, 'ApplicationManager_getAppsContext_exist');
+
+}
+
+function ApplicationManager_getAppsContext_missarg() {
+
+//==== TEST: ApplicationManager_getAppsContext_missarg
+//==== LABEL GetAppsContext - check with missing non-optional argument
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:getAppsContext M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MMA
+
+test(function () {
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        tizen.application.getAppsContext();
+    }, "Method was called without arguments but exception was not thrown");
+}, 'ApplicationManager_getAppsContext_missarg');
+
+}
+
+function ApplicationManager_getAppsContext_successCallback_TypeMismatch() {
+
+//==== TEST: ApplicationManager_getAppsContext_successCallback_TypeMismatch
+//==== LABEL Check non-optional argument successCallback (getAppsContext method) type conversion
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:getAppsContext M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+test(function () {
+    var i, conversionTable = getTypeConversionExceptions("functionObject");
+    for (i = 0; i < conversionTable.length; i++) {
+        assert_throws({name: conversionTable[i][1]}, function () {
+            tizen.application.getAppsContext(conversionTable[i][0]);
+        }, "exception should be thrown");
+    }
+}, 'ApplicationManager_getAppsContext_successCallback_TypeMismatch');
+
+}
+
+function ApplicationManager_getAppsContext_successCallback_invalid_cb() {
+
+//==== TEST: ApplicationManager_getAppsContext_successCallback_invalid_cb
+//==== LABEL Check if an exception was thrown when a fake callback (onsuccess) was passed into getAppsContext method
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:getAppsContext M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 30000});
+
+var t = async_test('ApplicationManager_getAppsContext_successCallback_invalid_cb', {timeout: 30000}), getSuccess, getSuccessFunc;
+t.step(function () {
+
+    getSuccessFunc = t.step_func(function () {
+        assert_unreached("this function should not be used");
+    });
+
+    getSuccess = {
+        onsuccess: getSuccessFunc
+    };
+
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        tizen.application.getAppsContext(getSuccess);
+    }, "exception should be thrown");
+
+    t.done();
+
+});
+
+}
+
+function ApplicationManager_getAppsContext_with_errorCallback() {
+
+//==== TEST: ApplicationManager_getAppsContext_with_errorCallback
+//==== LABEL Check using getAppsContext method (with optional argument errorCallback) in ApplicationManager interface
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:getAppsContext M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MOA
+
+setup({timeout: 30000});
+
+var t = async_test('ApplicationManager_getAppsContext_with_errorCallback', {timeout: 30000}), getSuccess, getError, i, foundCurrentApplication = false;
+
+t.step(function () {
+
+    getSuccess = t.step_func(function (appContextArray) {
+        assert_type(appContextArray , "array", "type of the found value is not properly");
+        for (i = 0; i < appContextArray.length; i++) {
+            assert_type(appContextArray[i], "object", "type of the found value is not properly");
+            assert_true("id" in appContextArray[i], "no id in returned value");
+            assert_true("appId" in appContextArray[i], "no appId in returned value");
+            if (appContextArray[i].appId === THIS_APP_ID) {
+                foundCurrentApplication = true;
+            }
+        }
+        if (!foundCurrentApplication) {
+            assert_unreached("current application context wasn't found");
+        }
+        t.done();
+    });
+
+    getError = t.step_func(function (error) {
+        assert_unreached("getAppsContext() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    tizen.application.getAppsContext(getSuccess, getError);
+
+});
+
+}
+
+function ApplicationManager_getAppsInfo() {
+
+//==== TEST: ApplicationManager_getAppsInfo
+//==== LABEL Check using getAppsInfo method (with non-optional arguments) in ApplicationManager interface
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:getAppsInfo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== ONLOAD_DELAY 90
+//==== TEST_CRITERIA MMINA MR
+setup({timeout: 90000});
+
+var t=async_test('ApplicationManager_getAppsInfo', {timeout: 90000}), getSuccess, retVal = null;
+t.step(function () {
+
+    getSuccess = t.step_func(function (appInfo) {
+        assert_equals(retVal, undefined, "incorrect returned value");
+        assert_type(appInfo, "array", "type of the found value is not properly");
+        assert_true(appInfo.length > 0, "information was not found");
+        t.done();
+    });
+
+    retVal = tizen.application.getAppsInfo(getSuccess);
+});
+
+}
+
+function ApplicationManager_getAppsInfo_errorCallback_TypeMismatch() {
+
+//==== TEST: ApplicationManager_getAppsInfo_errorCallback_TypeMismatch
+//==== LABEL Check optional argument errorCallback (getAppsInfo method) type conversion
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:getAppsInfo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test('ApplicationManager_getAppsInfo_errorCallback_TypeMismatch', {timeout: 30000}), i, getSuccess, conversionTable = getTypeConversionExceptions("functionObject",
+    true);
+t.step(function () {
+
+    getSuccess = t.step_func(function () {
+        assert_unreached("this function should not be used");
+    });
+
+    for (i = 0; i < conversionTable.length; i++) {
+        assert_throws({name: conversionTable[i][1]}, function () {
+            tizen.application.getAppsInfo(getSuccess, conversionTable[i][0]);
+        }, "exception should be thrown");
+    }
+
+    t.done();
+
+});
+
+}
+
+function ApplicationManager_getAppsInfo_errorCallback_invalid_cb() {
+
+//==== TEST: ApplicationManager_getAppsInfo_errorCallback_invalid_cb
+//==== LABEL Check if an exception was thrown when a fake callback (onerror) was passed into getAppsInfo method
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:getAppsInfo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 30000});
+
+var t = async_test('ApplicationManager_getAppsInfo_errorCallback_invalid_cb', {timeout: 30000}), getSuccess, getError, getErrorFunc;
+t.step(function () {
+
+    getSuccess = t.step_func(function () {
+        assert_unreached("application should not be run");
+    });
+
+    getErrorFunc = t.step_func(function (error) {
+        assert_unreached("getAppsInfo() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    getError = {
+        onerror: getErrorFunc
+    };
+
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        tizen.application.getAppsInfo(getSuccess, getError);
+    }, "exception should be thrown");
+
+    t.done();
+
+});
+
+}
+
+function ApplicationManager_getAppsInfo_exist() {
+
+//==== TEST: ApplicationManager_getAppsInfo_exist
+//==== LABEL Check if method getAppsInfo exist
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:getAppsInfo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    check_method_exists(tizen.application, "getAppsInfo");
+}, 'ApplicationManager_getAppsInfo_exist');
+
+}
+
+function ApplicationManager_getAppsInfo_missarg() {
+
+//==== TEST: ApplicationManager_getAppsInfo_missarg
+//==== LABEL ApplicationManager.getAppsInfo - check with missing non-optional argument
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:getAppsInfo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MMA
+
+test(function () {
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        tizen.application.getAppsInfo();
+    }, "Method was called without arguments but exception was not thrown");
+}, 'ApplicationManager_getAppsInfo_missarg');
+
+}
+
+function ApplicationManager_getAppsInfo_successCallback_TypeMismatch() {
+
+//==== TEST: ApplicationManager_getAppsInfo_successCallback_TypeMismatch
+//==== LABEL Check non-optional argument successCallback (getAppsInfo method) type conversion
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:getAppsContext M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+test(function () {
+    var i, conversionTable = getTypeConversionExceptions("functionObject");
+    for (i = 0; i < conversionTable.length; i++) {
+        assert_throws({name: conversionTable[i][1]}, function () {
+            tizen.application.getAppsInfo(conversionTable[i][0]);
+        }, "exception should be thrown");
+    }
+}, 'ApplicationManager_getAppsInfo_successCallback_TypeMismatch');
+
+}
+
+function ApplicationManager_getAppsInfo_successCallback_invalid_cb() {
+
+//==== TEST: ApplicationManager_getAppsInfo_successCallback_invalid_cb
+//==== LABEL Check if an exception was thrown when a fake callback (onsuccess) was passed into getAppsInfo method
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:getAppsInfo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 30000});
+
+var t = async_test('ApplicationManager_getAppsInfo_successCallback_invalid_cb', {timeout: 30000}), getSuccess, getSuccessFunc;
+t.step(function () {
+
+    getSuccessFunc = t.step_func(function () {
+        assert_unreached("this function should not be used");
+    });
+
+    getSuccess = {
+        onsuccess: getSuccessFunc
+    };
+
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        tizen.application.getAppsInfo(getSuccess);
+    }, "exception should be thrown");
+
+    t.done();
+
+});
+
+}
+
+function ApplicationManager_getAppsInfo_with_errorCallback() {
+
+//==== TEST: ApplicationManager_getAppsInfo_with_errorCallback
+//==== LABEL Check using getAppsInfo method (with optional argument errorCallback) in ApplicationManager interface
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:getAppsInfo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== ONLOAD_DELAY 90
+//==== TEST_CRITERIA MOA
+setup({timeout: 90000});
+
+var t = async_test('ApplicationManager_getAppsInfo_with_errorCallback', {timeout: 90000}), getSuccess, getError;
+
+t.step(function () {
+
+    getSuccess = t.step_func(function (appInfo) {
+        assert_type(appInfo, "array", "type of the found value is not properly");
+        assert_true(appInfo.length > 0, "information was not found");
+        t.done();
+    });
+
+    getError = t.step_func(function (error) {
+        assert_unreached("getAppsInfo() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    tizen.application.getAppsInfo(getSuccess, getError);
+
+});
+
+}
+
+function ApplicationManager_getCurrentApplication() {
+
+//==== TEST: ApplicationManager_getCurrentApplication
+//==== LABEL Check using getCurrentApplication method in ApplicationManager interface to get current Application object
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:getCurrentApplication M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MNA MR
+
+test(function () {
+    var app = tizen.application.getCurrentApplication();
+    assert_type(app, "object", "type of the returned value is not properly");
+    assert_true("appInfo" in app, "no appInfo in returned value");
+    assert_true("contextId" in app, "no contextId in returned value");
+    assert_true("exit" in app, "no exit in returned value");
+    assert_true("hide" in app, "no hide in returned value");
+    assert_true("getRequestedAppControl" in app, "no getRequestedAppControl in returned value");
+}, 'ApplicationManager_getCurrentApplication');
+
+}
+
+function ApplicationManager_getCurrentApplication_exist() {
+
+//==== TEST: ApplicationManager_getCurrentApplication_exist
+//==== LABEL Check if method getCurrentApplication exist
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:getCurrentApplication M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    check_method_exists(tizen.application, "getCurrentApplication");
+}, 'ApplicationManager_getCurrentApplication_exist');
+
+}
+
+function ApplicationManager_getCurrentApplication_extra_argument() {
+
+//==== TEST: ApplicationManager_getCurrentApplication_extra_argument
+//==== LABEL Check using getCurrentApplication with extra argument to get current Application object
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:getCurrentApplication M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MNAEX
+
+test(function () {
+    checkExtraArgument(tizen.application, "getCurrentApplication");
+}, 'ApplicationManager_getCurrentApplication_extra_argument');
+
+}
+
+function ApplicationManager_in_tizen() {
+
+//==== TEST: ApplicationManager_in_tizen
+//==== LABEL Check if ApplicationManager exist in tizen
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:ApplicationManager U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA OBME
+
+test(function () {
+    assert_true("application" in tizen, "no ApplicationManager in tizen");
+    check_readonly(tizen, "application", tizen.application, "object", "dummyValue");
+}, 'ApplicationManager_in_tizen');
+
+}
+
+function ApplicationManager_kill() {
+
+//==== TEST: ApplicationManager_kill
+//==== LABEL Check using kill method (with non-optional arguments) in ApplicationManager interface
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:kill M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MMINA MAST MR
+setup({timeout: 30000});
+
+var t = async_test('ApplicationManager_kill', {timeout: 30000}),
+    launchSuccess, launchError, retVal = null;
+
+setup_launch(t, TCT_APPCONTROL_APPID, function () {
+    launchSuccess = t.step_func(function () {
+        assert_launch(t, TCT_APPCONTROL_APPID, function (context) {
+            retVal = tizen.application.kill(context.id);
+            assert_kill(t, TCT_APPCONTROL_APPID, function () {
+                assert_equals(retVal, undefined, "incorrect returned value");
+                setTimeout(function(){
+                                       t.done();
+                               }, 3000);
+            });
+        });
+    });
+
+    launchError = t.step_func(function (error) {
+        assert_unreached("launch fails: " + error.name + " with message: " + error.message);
+    });
+
+    tizen.application.launch(TCT_APPCONTROL_APPID, launchSuccess, launchError);
+});
+
+}
+
+function ApplicationManager_kill_errorCallback_TypeMismatch() {
+
+//==== TEST: ApplicationManager_kill_errorCallback_TypeMismatch
+//==== LABEL Check optional argument 'onError' (kill) type conversion
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:kill M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P2
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MC
+setup({timeout: 30000});
+
+var t = async_test('ApplicationManager_kill_errorCallback_TypeMismatch', {timeout: 30000}),
+    i, killSuccess, launchSuccess, launchError, conversionTable = getTypeConversionExceptions("functionObject", true);
+
+setup_launch(t, TCT_APPCONTROL_APPID, function () {
+    killSuccess = t.step_func(function () {
+        assert_unreached("This function should not be used");
+    });
+
+    launchSuccess = t.step_func(function () {
+        assert_launch(t, TCT_APPCONTROL_APPID, function (context) {
+            for (i = 0; i < conversionTable.length; i++) {
+                assert_throws({name: conversionTable[i][1]}, function () {
+                    tizen.application.kill(context.id, killSuccess, conversionTable[i][0]);
+                }, "exception should be thrown");
+            }
+
+            assert_not_kill(t, TCT_APPCONTROL_APPID, function () {
+                setTimeout(function(){
+                                       t.done();
+                               }, 3000);
+            });
+        });
+    });
+
+    launchError = t.step_func(function (error) {
+        assert_unreached("launch fails: " + error.name + " with message: " + error.message);
+    });
+
+    tizen.application.launch(TCT_APPCONTROL_APPID, launchSuccess, launchError);
+});
+
+}
+
+function ApplicationManager_kill_errorCallback_invalid_cb() {
+
+//==== TEST: ApplicationManager_kill_errorCallback_invalid_cb
+//==== LABEL Check if an exception was thrown when a fake callback (onError) was passed into kill method
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:kill M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P2
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MTCB
+setup({timeout: 30000});
+
+var t = async_test('ApplicationManager_kill_errorCallback_invalid_cb', {timeout: 30000}),
+    killSuccess, killError, killErrorFunc, launchSuccess, launchError;
+
+setup_launch(t, TCT_APPCONTROL_APPID, function () {
+
+    killSuccess = t.step_func(function () {
+        assert_unreached("This function (killSuccess) should not be used");
+    });
+
+    killErrorFunc = t.step_func(function (error) {
+        assert_unreached("kill() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    killError = { onsuccess: killErrorFunc };
+
+    launchSuccess = t.step_func(function () {
+        assert_launch(t, TCT_APPCONTROL_APPID, function (context) {
+            assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+                tizen.application.kill(context.id, killSuccess, killError);
+            }, "exception should be thrown");
+
+            assert_not_kill(t, TCT_APPCONTROL_APPID, function () {
+                setTimeout(function(){
+                                       t.done();
+                               }, 3000);
+            });
+        });
+    });
+
+    launchError = t.step_func(function (error) {
+        assert_unreached("launch fails: " + error.name + " with message: " + error.message);
+    });
+
+    tizen.application.launch(TCT_APPCONTROL_APPID, launchSuccess, launchError);
+});
+
+}
+
+function ApplicationManager_kill_exist() {
+
+//==== TEST: ApplicationManager_kill_exist
+//==== LABEL Check if method kill exist
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:kill M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    check_method_exists(tizen.application, "kill");
+}, 'ApplicationManager_kill_exist');
+
+}
+
+function ApplicationManager_kill_successCallback_TypeMismatch() {
+
+//==== TEST: ApplicationManager_kill_successCallback_TypeMismatch
+//==== LABEL Check optional argument 'onSuccess' (kill) type conversion
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:kill M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P2
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test('ApplicationManager_kill_successCallback_TypeMismatch', {timeout: 30000}),
+    i, launchSuccess, launchError,
+    conversionTable = getTypeConversionExceptions("functionObject", true);
+
+setup_launch(t, TCT_APPCONTROL_APPID, function () {
+
+    launchSuccess = t.step_func(function () {
+        assert_launch(t, TCT_APPCONTROL_APPID, function (context) {
+            for (i = 0; i < conversionTable.length; i++) {
+                assert_throws({name: conversionTable[i][1]}, function () {
+                    tizen.application.kill(context.id, conversionTable[i][0]);
+                }, "exception should be thrown");
+            }
+
+            assert_not_kill(t, TCT_APPCONTROL_APPID, function () {
+                setTimeout(function(){
+                                       t.done();
+                               }, 3000);
+            });
+        });
+    });
+
+    launchError = t.step_func(function (error) {
+        assert_unreached("launch fails: " + error.name + " with message: " + error.message);
+    });
+
+    tizen.application.launch(TCT_APPCONTROL_APPID, launchSuccess, launchError);
+});
+
+}
+
+function ApplicationManager_kill_successCallback_invalid_cb() {
+
+//==== TEST: ApplicationManager_kill_successCallback_invalid_cb
+//==== LABEL Check if an exception was thrown when a fake callback (onSuccess) was passed into kill method
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:kill M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P2
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 30000});
+
+var t = async_test('ApplicationManager_kill_successCallback_invalid_cb', {timeout: 30000}),
+    killSuccessFunc, killSuccess, launchSuccess, launchError;
+
+setup_launch(t, TCT_APPCONTROL_APPID, function () {
+    killSuccessFunc = t.step_func(function () {
+        assert_unreached("this function should not be used");
+    });
+
+    killSuccess = { onsuccess: killSuccessFunc };
+
+    launchSuccess = t.step_func(function () {
+        assert_launch(t, TCT_APPCONTROL_APPID, function (context) {
+            assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+                tizen.application.kill(context.id, killSuccess);
+            }, "exception should be thrown");
+
+            assert_not_kill(t, TCT_APPCONTROL_APPID, function () {
+                setTimeout(function(){
+                                       t.done();
+                               }, 3000);
+            });
+        });
+    });
+
+    launchError = t.step_func(function (error) {
+        assert_unreached("launch fails: " + error.name + " with message: " + error.message);
+    });
+
+    tizen.application.launch(TCT_APPCONTROL_APPID, launchSuccess, launchError);
+});
+
+}
+
+function ApplicationManager_kill_with_errorCallback() {
+
+//==== TEST: ApplicationManager_kill_with_errorCallback
+//==== LABEL Check using kill method (with optional argument errorCallback) in ApplicationManager interface
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:kill M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MERRCB
+
+setup({timeout: 30000});
+
+var t = async_test('ApplicationManager_kill_with_errorCallback', {timeout: 30000}),
+    killSuccess, killError, currentApplication;
+
+t.step(function () {
+    killSuccess = t.step_func(function () {
+        assert_unreached("This function should not be used");
+    });
+
+    killError = t.step_func(function (error) {
+        assert_equals(error.name, "InvalidValuesError", "InvalidValuesError must be thrown");
+        t.done();
+    });
+
+    currentApplication = tizen.application.getCurrentApplication();
+
+    tizen.application.kill(currentApplication.contextId, killSuccess, killError);
+});
+
+}
+
+function ApplicationManager_kill_with_successCallback() {
+
+//==== TEST: ApplicationManager_kill_with_successCallback
+//==== LABEL Check using kill method (with optional argument successCallback) in ApplicationManager interface
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:kill M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MOA MAST
+
+setup({timeout: 30000});
+
+var t = async_test('ApplicationManager_kill_with_successCallback', {timeout: 30000}),
+    killSuccess, launchSuccess, launchError;
+
+setup_launch(t, TCT_APPCONTROL_APPID, function () {
+    killSuccess = t.step_func(function () {
+        assert_kill(t, TCT_APPCONTROL_APPID, function () {
+            setTimeout(function(){
+                               t.done();
+                       }, 3000);
+        });
+    });
+
+    launchSuccess = t.step_func(function () {
+        assert_launch(t, TCT_APPCONTROL_APPID, function (context) {
+            tizen.application.kill(context.id, killSuccess);
+        });
+    });
+
+    launchError = t.step_func(function (error) {
+        assert_unreached("launch fails: " + error.name + " with message: " + error.message);
+    });
+
+    tizen.application.launch(TCT_APPCONTROL_APPID, launchSuccess, launchError);
+});
+
+}
+
+function ApplicationManager_launch() {
+
+//==== TEST: ApplicationManager_launch
+//==== LABEL Check using launch method (with non-optional arguments) in ApplicationManager interface
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:launch M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MMINA MAST MR
+setup({timeout: 30000});
+
+var t = async_test('ApplicationManager_launch', {timeout: 30000}), retVal = null;
+
+setup_launch(t, TCT_APPCONTROL_APPID, function () {
+    retVal = tizen.application.launch(TCT_APPCONTROL_APPID);
+
+    assert_launch(t, TCT_APPCONTROL_APPID, function () {
+        assert_equals(retVal, undefined, "incorrect returned value");
+        setTimeout(function(){
+                       t.done();
+               }, 3000);
+    });
+});
+
+}
+
+function ApplicationManager_launchAppControl_appControl_TypeMismatch() {
+
+//==== TEST: ApplicationManager_launchAppControl_appControl_TypeMismatch
+//==== LABEL Check non-optional argument ApplicationControl type conversion
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:launchAppControl M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P2
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test('ApplicationManager_launchAppControl_appControl_TypeMismatch', {timeout: 30000}),
+    i, conversionTable = getTypeConversionExceptions("object");
+
+setup_launch(t, TCT_APPCONTROL_APPID, function () {
+    for (i = 0; i < conversionTable.length; i++) {
+        assert_throws({name: conversionTable[i][1]}, function () {
+            tizen.application.launchAppControl(conversionTable[i][0]);
+        }, "exception should be thrown");
+    }
+
+    assert_not_launch(t, TCT_APPCONTROL_APPID, function () {
+        setTimeout(function(){
+                       t.done();
+               }, 3000);
+    });
+});
+
+}
+
+function ApplicationManager_launchAppControl_appControl_invalid_obj() {
+
+//==== TEST: ApplicationManager_launchAppControl_appControl_invalid_obj
+//==== LABEL Check if an exception was thrown when a fake object (ApplicationControl) was passed into launchAppControl method
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:launchAppControl M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P2
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MTO
+
+setup({timeout: 30000});
+
+var t = async_test('ApplicationManager_launchAppControl_appControl_invalid_obj', {timeout: 30000}), appControl;
+
+setup_launch(t, TCT_APPCONTROL_APPID, function () {
+
+    appControl = {
+        operation: TCT_APPCONTROL_LAUNCH_APPCONTROL_OPERATION,
+        uri: TCT_APPCONTROL_LAUNCH_APPCONTROL_URI,
+        mime: TCT_APPCONTROL_LAUNCH_APPCONTROL_MIME,
+        category: "",
+        data: []
+    };
+
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        tizen.application.launchAppControl(appControl);
+    }, "exception should be thrown");
+
+    assert_not_launch(t, TCT_APPCONTROL_APPID, function () {
+        setTimeout(function(){
+                       t.done();
+               }, 3000);
+    });
+});
+
+}
+
+function ApplicationManager_launchAppControl_errorCallback_TypeMismatch() {
+
+//==== TEST: ApplicationManager_launchAppControl_errorCallback_TypeMismatch
+//==== LABEL Check optional argument 'onError' (launchAppControl) type conversion
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:launchAppControl M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P2
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test('ApplicationManager_launchAppControl_errorCallback_TypeMismatch', {timeout: 30000}),
+    i, launchSuccess, appcontrol, conversionTable = getTypeConversionExceptions("functionObject", true);
+
+setup_launch(t, TCT_APPCONTROL_APPID, function () {
+    launchSuccess = t.step_func(function () {
+        assert_unreached("application should not be run");
+    });
+
+    appcontrol = new tizen.ApplicationControl(
+        TCT_APPCONTROL_LAUNCH_APPCONTROL_OPERATION
+    );
+
+    for (i = 0; i < conversionTable.length; i++) {
+        assert_throws({name: conversionTable[i][1]}, function () {
+            tizen.application.launchAppControl(appcontrol, null, launchSuccess, conversionTable[i][0]);
+        }, "exception should be thrown");
+    }
+
+    assert_not_launch(t, TCT_APPCONTROL_APPID, function () {
+        setTimeout(function(){
+                       t.done();
+               }, 3000);
+    });
+});
+
+}
+
+function ApplicationManager_launchAppControl_errorCallback_invalid_cb() {
+
+//==== TEST: ApplicationManager_launchAppControl_errorCallback_invalid_cb
+//==== LABEL Check if an exception was thrown when a fake callback (onError) was passed into launchAppControl method
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:launchAppControl M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P2
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 30000});
+
+var t = async_test('ApplicationManager_launchAppControl_errorCallback_invalid_cb', {timeout: 30000}),
+    launchSuccess, launchError, launchErrorFunc, appcontrol;
+
+setup_launch(t, TCT_APPCONTROL_APPID, function () {
+    launchSuccess = t.step_func(function () {
+        assert_unreached("application should not be run");
+    });
+
+    launchErrorFunc = t.step_func(function (error) {
+        assert_unreached("launchAppControl() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    launchError = {onerror: launchErrorFunc};
+
+    appcontrol = new tizen.ApplicationControl(
+        TCT_APPCONTROL_LAUNCH_APPCONTROL_OPERATION
+    );
+
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        tizen.application.launchAppControl(appcontrol, null, launchSuccess, launchError);
+    }, "exception should be thrown");
+
+    assert_not_launch(t, TCT_APPCONTROL_APPID, function () {
+        setTimeout(function(){
+                       t.done();
+               }, 3000);
+    });
+});
+
+}
+
+function ApplicationManager_launchAppControl_exist() {
+
+//==== TEST: ApplicationManager_launchAppControl_exist
+//==== LABEL Check if method launchAppControl exist
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:launchAppControl M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    check_method_exists(tizen.application, "launchAppControl");
+}, 'ApplicationManager_launchAppControl_exist');
+
+}
+
+function ApplicationManager_launchAppControl_missarg() {
+
+//==== TEST: ApplicationManager_launchAppControl_missarg
+//==== LABEL LaunchAppControl - check with missing non-optional argument
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:launchAppControl M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MMA
+
+test(function () {
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        tizen.application.launchAppControl();
+    }, "Method was called without arguments but exception was not thrown");
+}, 'ApplicationManager_launchAppControl_missarg');
+
+}
+
+function ApplicationManager_launchAppControl_replyCallback_TypeMismatch() {
+
+//==== TEST: ApplicationManager_launchAppControl_replyCallback_TypeMismatch
+//==== LABEL Check optional argument 'onReply' type conversion
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:launchAppControl M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P2
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test('ApplicationManager_launchAppControl_replyCallback_TypeMismatch', {timeout: 30000}),
+    i, launchSuccess, launchError, appcontrol, conversionTable = getTypeConversionExceptions("object", true);
+
+setup_launch(t, TCT_APPCONTROL_APPID, function () {
+    launchSuccess = t.step_func(function () {
+        assert_unreached("application should not be run");
+    });
+
+    launchError = t.step_func(function (error) {
+        assert_unreached("launchAppControl() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    appcontrol = new tizen.ApplicationControl(
+        TCT_APPCONTROL_LAUNCH_APPCONTROL_OPERATION
+    );
+
+    for (i = 0; i < conversionTable.length; i++) {
+        assert_throws({name: conversionTable[i][1]}, function () {
+            tizen.application.launchAppControl(appcontrol, null, launchSuccess, launchError, conversionTable[i][0]);
+        }, "exception should be thrown");
+    }
+
+    assert_not_launch(t, TCT_APPCONTROL_APPID, function () {
+        setTimeout(function(){
+                       t.done();
+               }, 3000);
+    });
+});
+
+}
+
+function ApplicationManager_launchAppControl_replyCallback_invalid_cb() {
+
+//==== TEST: ApplicationManager_launchAppControl_replyCallback_invalid_cb
+//==== LABEL Check if an exception was thrown when a fake callback (onReply) was passed into launchAppControl method
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:launchAppControl M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P2
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MTL
+
+setup({timeout: 30000});
+
+var t = async_test('ApplicationManager_launchAppControl_replyCallback_invalid_cb', {timeout: 30000}), i, launchSuccess, launchError, appcontrol, conversionTable;
+
+setup_launch(t, TCT_APPCONTROL_APPID, function () {
+
+    launchSuccess = t.step_func(function () {
+        assert_unreached("application should not be run");
+    });
+
+    launchError = t.step_func(function (error) {
+        assert_unreached("launchAppControl() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    appcontrol = new tizen.ApplicationControl(
+        TCT_APPCONTROL_LAUNCH_APPCONTROL_OPERATION
+    );
+
+    conversionTable = getListenerConversionExceptions(["onsuccess", "onfailure"]);
+
+    for (i = 0; i < conversionTable.length; i++) {
+        assert_throws({name: conversionTable[i][1]}, function () {
+            tizen.application.launchAppControl(appcontrol, null, launchSuccess, launchError, conversionTable[i][0]);
+        }, "exception should be thrown");
+    }
+
+    assert_not_launch(t, TCT_APPCONTROL_APPID, function () {
+        setTimeout(function(){
+                       t.done();
+               }, 3000);
+    });
+});
+
+}
+
+function ApplicationManager_launchAppControl_successCallback_TypeMismatch() {
+
+//==== TEST: ApplicationManager_launchAppControl_successCallback_TypeMismatch
+//==== LABEL Check optional argument 'onSuccess' (launchAppControl) type conversion
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:launchAppControl M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P2
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test('ApplicationManager_launchAppControl_successCallback_TypeMismatch', {timeout: 30000}),
+    i, appcontrol, conversionTable = getTypeConversionExceptions("functionObject", true);
+
+setup_launch(t, TCT_APPCONTROL_APPID, function () {
+    appcontrol = new tizen.ApplicationControl(
+        TCT_APPCONTROL_LAUNCH_APPCONTROL_OPERATION
+    );
+
+    for (i = 0; i < conversionTable.length; i++) {
+        assert_throws({name: conversionTable[i][1]}, function () {
+            tizen.application.launchAppControl(appcontrol, null, conversionTable[i][0]);
+        }, "exception should be thrown");
+    }
+
+    assert_not_launch(t, TCT_APPCONTROL_APPID, function () {
+        setTimeout(function(){
+                       t.done();
+               }, 3000);
+    });
+});
+
+}
+
+function ApplicationManager_launchAppControl_successCallback_invalid_cb() {
+
+//==== TEST: ApplicationManager_launchAppControl_successCallback_invalid_cb
+//==== LABEL Check if an exception was thrown when a fake callback (onSuccess) was passed into launchAppControl method
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:launchAppControl M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P2
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 30000});
+
+var t = async_test('ApplicationManager_launchAppControl_successCallback_invalid_cb', {timeout: 30000}), launchSuccess, launchSuccessFunc, appcontrol;
+
+setup_launch(t, TCT_APPCONTROL_APPID, function () {
+
+    launchSuccessFunc = t.step_func(function () {
+        assert_unreached("this function should not be used");
+    });
+
+    launchSuccess = { onsuccess: launchSuccessFunc };
+
+    appcontrol = new tizen.ApplicationControl(
+        TCT_APPCONTROL_LAUNCH_APPCONTROL_OPERATION
+    );
+
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        tizen.application.launchAppControl(appcontrol, null, launchSuccess);
+    }, "exception should be thrown");
+
+    assert_not_launch(t, TCT_APPCONTROL_APPID, function () {
+        setTimeout(function(){
+                       t.done();
+               }, 3000);
+    });
+});
+
+}
+
+function ApplicationManager_launchAppControl_with_appControl_operation() {
+
+//==== TEST: ApplicationManager_launchAppControl_with_appControl_operation
+//==== LABEL Check using launchAppControl method (with operation of ApplicationControl) in ApplicationManager interface
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:launchAppControl M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MMINA MAST
+
+setup({timeout: 30000});
+
+var t = async_test('ApplicationManager_launchAppControl_with_appControl_operation', {timeout: 30000}),
+    appcontrol;
+
+setup_launch(t, TCT_APPCONTROL_APPID, function () {
+    appcontrol = new tizen.ApplicationControl(
+        TCT_APPCONTROL_LAUNCH_APPCONTROL_OPERATION
+    );
+
+    tizen.application.launchAppControl(appcontrol);
+
+    assert_launch(t, TCT_APPCONTROL_APPID, function () {
+        setTimeout(function(){
+                       t.done();
+               }, 3000);
+    });
+});
+
+}
+
+function ApplicationManager_launchAppControl_with_appControl_operation_mime() {
+
+//==== TEST: ApplicationManager_launchAppControl_with_appControl_operation_mime
+//==== LABEL Check using launchAppControl method (with operation and MIME type of ApplicationControl) in ApplicationManager interface
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:launchAppControl M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MMINA MAST
+
+setup({timeout: 30000});
+
+var t = async_test('ApplicationManager_launchAppControl_with_appControl_operation_mime', {timeout: 30000}),
+    appcontrol;
+
+setup_launch(t, TCT_APPCONTROL_APPID, function () {
+    appcontrol = new tizen.ApplicationControl(
+        TCT_APPCONTROL_LAUNCH_APPCONTROL_OPERATION,
+        null,
+        TCT_APPCONTROL_LAUNCH_APPCONTROL_MIME
+    );
+
+    tizen.application.launchAppControl(appcontrol);
+
+    assert_launch(t, TCT_APPCONTROL_APPID, function () {
+        setTimeout(function(){
+                       t.done();
+               }, 3000);
+    });
+});
+
+}
+
+function ApplicationManager_launchAppControl_with_appControl_operation_uri() {
+
+//==== TEST: ApplicationManager_launchAppControl_with_appControl_operation_uri
+//==== LABEL Check using launchAppControl method (with operation and URI of ApplicationControl) in ApplicationManager interface
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:launchAppControl M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MMINA MAST
+
+setup({timeout: 30000});
+
+var t = async_test('ApplicationManager_launchAppControl_with_appControl_operation_uri', {timeout: 30000}),
+    appcontrol;
+
+setup_launch(t, TCT_APPCONTROL_APPID, function () {
+    appcontrol = new tizen.ApplicationControl(
+        TCT_APPCONTROL_LAUNCH_APPCONTROL_OPERATION,
+        TCT_APPCONTROL_LAUNCH_APPCONTROL_URI
+    );
+
+    tizen.application.launchAppControl(appcontrol);
+
+    assert_launch(t, TCT_APPCONTROL_APPID, function () {
+        setTimeout(function(){
+                       t.done();
+               }, 3000);
+    });
+});
+
+}
+
+function ApplicationManager_launchAppControl_with_appControl_operation_uri_mime() {
+
+//==== TEST: ApplicationManager_launchAppControl_with_appControl_operation_uri_mime
+//==== LABEL Check using launchAppControl method (with operation, URI and MIME type of ApplicationControl) in ApplicationManager interface
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:launchAppControl M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MMINA MAST
+
+setup({timeout: 30000});
+
+var t = async_test('ApplicationManager_launchAppControl_with_appControl_operation_uri_mime', {timeout: 30000}),
+    appcontrol;
+
+setup_launch(t, TCT_APPCONTROL_APPID, function () {
+    appcontrol = new tizen.ApplicationControl(
+        TCT_APPCONTROL_LAUNCH_APPCONTROL_OPERATION,
+        TCT_APPCONTROL_LAUNCH_APPCONTROL_URI,
+        TCT_APPCONTROL_LAUNCH_APPCONTROL_MIME
+    );
+
+    tizen.application.launchAppControl(appcontrol);
+
+    assert_launch(t, TCT_APPCONTROL_APPID, function () {
+        setTimeout(function(){
+                       t.done();
+               }, 3000);
+    });
+});
+
+}
+
+function ApplicationManager_launchAppControl_with_errorCallback() {
+
+//==== TEST: ApplicationManager_launchAppControl_with_errorCallback
+//==== LABEL Check using launchAppControl method (with optional argument errorCallback) in ApplicationManager interface
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:launchAppControl M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MERRCB
+
+setup({timeout: 30000});
+
+var t = async_test('ApplicationManager_launchAppControl_with_errorCallback', {timeout: 30000}),
+    launchSuccess, launchError, appcontrol;
+
+setup_launch(t, TCT_APPCONTROL_APPID, function () {
+    launchSuccess = t.step_func(function () {
+        assert_unreached("this function should not be used");
+    });
+
+    launchError = t.step_func(function () {
+        assert_not_launch(t, TCT_APPCONTROL_APPID, function () {
+            setTimeout(function(){
+                               t.done();
+                       }, 3000);
+        });
+    });
+
+    appcontrol = new tizen.ApplicationControl(
+        TCT_APPCONTROL_LAUNCH_APPCONTROL_OPERATION,
+        TCT_APPCONTROL_LAUNCH_APPCONTROL_URI,
+        TCT_APPCONTROL_LAUNCH_APPCONTROL_MIME_INVALID
+    );
+
+    tizen.application.launchAppControl(appcontrol, null, launchSuccess, launchError);
+});
+
+}
+
+function ApplicationManager_launchAppControl_with_id() {
+
+//==== TEST: ApplicationManager_launchAppControl_with_id
+//==== LABEL Check using launchAppControl method with explicit application ID in ApplicationManager interface
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:launchAppControl M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MOA MAST
+
+setup({timeout: 30000});
+
+var t = async_test('ApplicationManager_launchAppControl_with_id', {timeout: 30000}),
+    appcontrol;
+
+setup_launch(t, TCT_APPCONTROL_MOCK_APPID, function () {
+    setup_launch(t, TCT_APPCONTROL_APPID, function () {
+        appcontrol = new tizen.ApplicationControl(
+            TCT_APPCONTROL_LAUNCH_APPCONTROL_EXPLICIT_OPERATION,
+            TCT_APPCONTROL_LAUNCH_APPCONTROL_EXPLICIT_URI,
+            TCT_APPCONTROL_LAUNCH_APPCONTROL_EXPLICIT_MIME
+        );
+
+        tizen.application.launchAppControl(appcontrol, TCT_APPCONTROL_APPID);
+
+        assert_launch(t, TCT_APPCONTROL_APPID, function (context) {
+            assert_not_launch(t, TCT_APPCONTROL_MOCK_APPID, function () {
+                setTimeout(function(){
+                                       t.done();
+                               }, 3000);
+            });
+        });
+    });
+});
+
+}
+
+function ApplicationManager_launchAppControl_with_replyCallback() {
+
+//==== TEST: ApplicationManager_launchAppControl_with_replyCallback
+//==== LABEL Check using launchAppControl method (with optional argument replyCallback) in ApplicationManager interface
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:launchAppControl M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MOA
+
+setup({timeout: 30000});
+
+var t = async_test('ApplicationManager_launchAppControl_with_replyCallback', {timeout: 30000}),
+    replyCallback, launchError, appcontrol;
+
+setup_launch(t, TCT_APPCONTROL_APPID, function () {
+    replyCallback = {
+        onsuccess: t.step_func(function () {
+            setTimeout(function(){
+                               t.done();
+                       }, 3000);
+        }),
+        onfailure: t.step_func(function () {
+            assert_unreached("Unexpected onfailure");
+        })
+    };
+
+    launchError = t.step_func(function (error) {
+        assert_unreached("launch fails: " + error.name + " with message: " + error.message);
+    });
+
+    appcontrol = new tizen.ApplicationControl(
+        TCT_APPCONTROL_REPLY_RESULT_OPERATION
+    );
+
+    tizen.application.launchAppControl(appcontrol, null, null, launchError, replyCallback);
+});
+
+}
+
+function ApplicationManager_launchAppControl_with_successCallback() {
+
+//==== TEST: ApplicationManager_launchAppControl_with_successCallback
+//==== LABEL Check using launchAppControl method (with optional argument successCallback) in ApplicationManager interface
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:launchAppControl M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MOA MAST MR
+
+setup({timeout: 30000});
+
+var t = async_test('ApplicationManager_launchAppControl_with_successCallback', {timeout: 30000}),
+    launchSuccess, appcontrol, retVal = null;
+
+setup_launch(t, TCT_APPCONTROL_APPID, function () {
+    launchSuccess = t.step_func(function () {
+        assert_equals(retVal, undefined, "incorrect returned value");
+        assert_launch(t, TCT_APPCONTROL_APPID, function () {
+            setTimeout(function(){
+                               t.done();
+                       }, 3000);
+        });
+    });
+
+    appcontrol = new tizen.ApplicationControl(
+        TCT_APPCONTROL_LAUNCH_APPCONTROL_OPERATION
+    );
+
+    retVal = tizen.application.launchAppControl(appcontrol, null, launchSuccess);
+});
+
+}
+
+function ApplicationManager_launch_errorCallback_TypeMismatch() {
+
+//==== TEST: ApplicationManager_launch_errorCallback_TypeMismatch
+//==== LABEL Check optional argument 'onError' (launch) type conversion
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:launch M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P2
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test('ApplicationManager_launch_errorCallback_TypeMismatch', {timeout: 30000}),
+    i, launchSuccess, conversionTable = getTypeConversionExceptions("functionObject", true);
+
+setup_launch(t, TCT_APPCONTROL_APPID, function () {
+    launchSuccess = t.step_func(function () {
+        assert_unreached("application should not be run");
+    });
+
+    for (i = 0; i < conversionTable.length; i++) {
+        assert_throws({name: conversionTable[i][1]}, function () {
+            tizen.application.launch(TCT_APPCONTROL_APPID, launchSuccess, conversionTable[i][0]);
+        }, "exception should was thrown");
+    }
+
+    assert_not_launch(t, TCT_APPCONTROL_APPID, function () {
+        setTimeout(function(){
+                       t.done();
+               }, 3000);
+    });
+});
+
+}
+
+function ApplicationManager_launch_errorCallback_invalid_cb() {
+
+//==== TEST: ApplicationManager_launch_errorCallback_invalid_cb
+//==== LABEL Check if an exception was thrown when a fake callback (on error) was passed
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:launch M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P2
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 30000});
+
+var t = async_test('ApplicationManager_launch_errorCallback_invalid_cb', {timeout: 30000}),
+    launchSuccess, launchError, launchErrorFunc;
+
+setup_launch(t, TCT_APPCONTROL_APPID, function () {
+    launchSuccess = t.step_func(function () {
+        assert_unreached("application should not be run");
+    });
+
+    launchErrorFunc = t.step_func(function (error) {
+        assert_unreached("launch() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    launchError = {onerror: launchErrorFunc};
+
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        tizen.application.launch(TCT_APPCONTROL_APPID, launchSuccess, launchError);
+    }, "exception should be thrown");
+
+    assert_not_launch(t, TCT_APPCONTROL_APPID, function () {
+        setTimeout(function(){
+                       t.done();
+               }, 3000);
+    });
+});
+
+}
+
+function ApplicationManager_launch_exist() {
+
+//==== TEST: ApplicationManager_launch_exist
+//==== LABEL Check if method launch exist
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:launch M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    check_method_exists(tizen.application, "launch");
+}, 'ApplicationManager_launch_exist');
+
+}
+
+function ApplicationManager_launch_successCallback_TypeMismatch() {
+
+//==== TEST: ApplicationManager_launch_successCallback_TypeMismatch
+//==== LABEL Check optional argument 'onSuccess' (launch) type conversion
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:launch M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P2
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test('ApplicationManager_launch_successCallback_TypeMismatch', {timeout: 30000}),
+    i, conversionTable = getTypeConversionExceptions("functionObject", true);
+
+setup_launch(t, TCT_APPCONTROL_APPID, function () {
+    for (i = 0; i < conversionTable.length; i++) {
+        assert_throws({name: conversionTable[i][1]}, function () {
+            tizen.application.launch(TCT_APPCONTROL_APPID, conversionTable[i][0]);
+        }, "exception should be thrown");
+    }
+
+    assert_not_launch(t, TCT_APPCONTROL_APPID, function () {
+        setTimeout(function(){
+                       t.done();
+               }, 3000);
+    });
+});
+
+}
+
+function ApplicationManager_launch_successCallback_invalid_cb() {
+
+//==== TEST: ApplicationManager_launch_successCallback_invalid_cb
+//==== LABEL Check if an exception was thrown when a fake callback (on success) was passed
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:launch M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P2
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 30000});
+
+var t = async_test('ApplicationManager_launch_successCallback_invalid_cb', {timeout: 30000}),
+    launchSuccess, launchSuccessFunc;
+
+setup_launch(t, TCT_APPCONTROL_APPID, function () {
+    launchSuccessFunc = t.step_func(function () {
+        assert_unreached("this function should not be used");
+    });
+
+    launchSuccess = { onsuccess: launchSuccessFunc };
+
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        tizen.application.launch(TCT_APPCONTROL_APPID, launchSuccess);
+    }, "exception should be thrown");
+
+    assert_not_launch(t, TCT_APPCONTROL_APPID, function () {
+        setTimeout(function(){
+                       t.done();
+               }, 3000);
+    });
+});
+
+}
+
+function ApplicationManager_launch_with_errorCallback() {
+
+//==== TEST: ApplicationManager_launch_with_errorCallback
+//==== LABEL Check using launch method (with optional argument errorCallback) in ApplicationManager interface
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:launch M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MERRCB
+
+setup({timeout: 30000});
+
+var t = async_test('ApplicationManager_launch_with_errorCallback', {timeout: 30000}),
+    launchSuccess, launchError;
+
+setup_launch(t, TCT_APPCONTROL_APPID, function () {
+    launchSuccess = t.step_func(function () {
+        assert_unreached("this function should not be used");
+    });
+
+    launchError = t.step_func(function () {
+        setTimeout(function(){
+                       t.done();
+               }, 3000);
+    });
+
+    tizen.application.launch(INVALID_APP_ID, launchSuccess, launchError);
+});
+
+}
+
+function ApplicationManager_launch_with_successCallback() {
+
+//==== TEST: ApplicationManager_launch_with_successCallback
+//==== LABEL Check using launch method (with optional argument successCallback) in ApplicationManager interface
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:launch M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MOA MAST
+
+setup({timeout: 30000});
+
+var t = async_test('ApplicationManager_launch_with_successCallback', {timeout: 30000}),
+    launchSuccess;
+
+setup_launch(t, TCT_APPCONTROL_APPID, function () {
+    launchSuccess = t.step_func(function () {
+        assert_launch(t, TCT_APPCONTROL_APPID, function () {
+            setTimeout(function(){
+                               t.done();
+                       }, 3000);
+        });
+    });
+
+    tizen.application.launch(TCT_APPCONTROL_APPID, launchSuccess);
+});
+
+}
+
+function ApplicationManager_notexist() {
+
+//==== TEST: ApplicationManager_notexist
+//==== LABEL Check if ApplicationManager notexist
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:ApplicationManager U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("ApplicationManager");
+}, 'ApplicationManager_notexist');
+
+}
+
+function ApplicationManager_removeAppInfoEventListener() {
+
+//==== TEST: ApplicationManager_removeAppInfoEventListener
+//==== LABEL Check using removeAppInfoEventListener method (installation process) in ApplicationManager interface
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:removeAppInfoEventListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MMINA MR
+
+setup({timeout: 30000});
+
+var t = async_test('ApplicationManager_removeAppInfoEventListener', {timeout: 30000}), appEventCallback, watchId, retVal;
+t.step(function () {
+
+    appEventCallback = {
+        oninstalled: t.step_func(function () {
+            assert_unreached("This function (oninstalled) should not be used");
+        }),
+        onupdated: t.step_func(function () {
+            assert_unreached("This function (onupdated) should not be used");
+        }),
+        onuninstalled: t.step_func(function () {
+            assert_unreached("This function (onuninstalled) should not be used");
+        })
+    };
+
+    watchId = tizen.application.addAppInfoEventListener(appEventCallback);
+    assert_type(watchId, "long", "wrong listener ID");
+    retVal = tizen.application.removeAppInfoEventListener(watchId);
+    assert_type(retVal, "undefined", "this method should return nothing");
+    t.done();
+
+});
+
+}
+
+function ApplicationManager_removeAppInfoEventListener_exist() {
+
+//==== TEST: ApplicationManager_removeAppInfoEventListener_exist
+//==== LABEL Check if method removeAppInfoEventListener exist
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:removeAppInfoEventListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    check_method_exists(tizen.application, "removeAppInfoEventListener");
+}, 'ApplicationManager_removeAppInfoEventListener_exist');
+
+}
+
+function ApplicationMetaData_extend() {
+
+//==== TEST: ApplicationMetaData_extend
+//==== LABEL Check if ApplicationMetaData can have new properties added
+//==== SPEC: Tizen Web API:Application:Application:ApplicationMetaData:ApplicationMetaData U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA OBX
+
+test(function () {
+    var metadata;
+
+    metadata = tizen.application.getAppMetaData();
+    assert_equals(metadata.length, 1, "Incorrect number of metadata.");
+    check_extensibility(metadata[0]);
+
+}, 'ApplicationMetaData_extend');
+
+}
+
+function ApplicationMetaData_key_attribute() {
+
+//==== TEST: ApplicationMetaData_key_attribute
+//==== LABEL Check if ApplicationMetaData have key attribute with proper type, readonly, not null
+//==== SPEC: Tizen Web API:Application:Application:ApplicationMetaData:key A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var metadata;
+    metadata = tizen.application.getAppMetaData();
+
+    assert_type(metadata, "array", "getAppMetaData should return array");
+    assert_equals(metadata.length, 1, "Incorrect number of metadata.");
+
+    assert_true("key" in metadata[0], "AplicationInformation should have iconPath attribute");
+    check_readonly(metadata[0], "key", METADATA_KEY, "string", "dummy");
+}, 'ApplicationMetaData_key_attribute');
+
+}
+
+function ApplicationMetaData_notexist() {
+
+//==== TEST: ApplicationMetaData_notexist
+//==== LABEL Check if ApplicationMetaData cannot be called as a function or in new expression
+//==== SPEC Tizen Web API:Application:Application:ApplicationMetaData:ApplicationMetaData U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("ApplicationMetaData");
+}, 'ApplicationMetaData_notexist');
+
+}
+
+function ApplicationMetaData_value_attribute() {
+
+//==== TEST: ApplicationMetaData_value_attribute
+//==== LABEL Check if ApplicationMetaData have value attribute with proper type, readonly, not null
+//==== SPEC: Tizen Web API:Application:Application:ApplicationMetaData:value A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var metadata;
+    metadata = tizen.application.getAppMetaData();
+
+    assert_type(metadata, "array", "getAppMetaData should return array");
+    assert_equals(metadata.length, 1, "Incorrect number of metadata.");
+
+    assert_true("value" in metadata[0], "ApplicationMetaData should have value attribute");
+    check_readonly(metadata[0], "value", METADATA_VALUE, "string", "dummy");
+
+}, 'ApplicationMetaData_value_attribute');
+
+}
+
+function Application_ContextId_attribute() {
+
+//==== TEST: Application_ContextId_attribute
+//==== LABEL Check attribute Application::ContextId existence and type
+//==== SPEC Tizen Web API:Application:Application:Application:contextId A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var app = tizen.application.getCurrentApplication();
+    assert_true("contextId" in app, "contextId doesn't exist in provided object");
+    check_readonly(app, "contextId", app.contextId, "string", "dummyValue");
+}, 'Application_ContextId_attribute');
+
+}
+
+function Application_appInfo_attribute() {
+
+//==== TEST: Application_appInfo_attribute
+//==== LABEL Check attribute Application::appInfo existence and type
+//==== SPEC Tizen Web API:Application:Application:Application:appInfo A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ARO
+test(function () {
+    var app = tizen.application.getCurrentApplication();
+    assert_true("appInfo" in app, "appInfo doesn't exist in provided object");
+    assert_type(app.appInfo, "object", "unexpected type");
+    assert_true("id" in app.appInfo, "no id in ApplicationInformation");
+    assert_true("name" in app.appInfo, "no name in ApplicationInformation");
+    assert_true("iconPath" in app.appInfo, "no iconPath in ApplicationInformation");
+    assert_true("version" in app.appInfo, "no version in ApplicationInformation");
+    assert_true("show" in app.appInfo, "no show in ApplicationInformation");
+    assert_true("categories" in app.appInfo, "no categories in ApplicationInformation");
+    assert_true("installDate" in app.appInfo, "no installDate in ApplicationInformation");
+    assert_true("size" in app.appInfo, "no size in ApplicationInformation");
+    assert_true("packageId" in app.appInfo, "no packageId in ApplicationInformation");
+    assert_equals(app.appInfo.id, THIS_APP_ID, "wrong ApplicationInformation");
+    app.appInfo = tizen.application.getAppInfo(TCT_APPCONTROL_APPID);
+    assert_equals(app.appInfo.id, THIS_APP_ID, "ApplicationInformation can be modified");
+}, 'Application_appInfo_attribute');
+
+}
+
+function Application_exit() {
+
+//==== TEST: Application_exit
+//==== LABEL Check using exit method (with non-optional arguments) in Application interface
+//==== SPEC Tizen Web API:Application:Application:Application:exit M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MNA MNAST
+
+setup({timeout: 30000});
+
+var t = async_test('Application_exit', {timeout: 30000}),
+    timeout = 1000, replyCallback, launchError, appcontrol;
+
+setup_launch(t, TCT_APPCONTROL_APPID, function () {
+    replyCallback = {
+        onsuccess: t.step_func(function () {
+            setTimeout(function () {
+                assert_exit(t, TCT_APPCONTROL_APPID, function () {
+                    setTimeout(function(){
+                                               t.done();
+                                       }, 3000);
+                });
+            }, timeout);
+        }),
+        onfailure: t.step_func(function () {
+            assert_unreached("Unexpected onfailure");
+        })
+    };
+
+    launchError = t.step_func(function (error) {
+        assert_unreached("launch fails: " + error.name + " with message: " + error.message);
+    });
+
+    appcontrol = new tizen.ApplicationControl(
+        TCT_APPCONTROL_EXIT_OPERATION,
+        null,
+        null,
+        null,
+        [ new tizen.ApplicationControlData("timeout", [timeout.toString()])]
+    );
+
+    tizen.application.launchAppControl(appcontrol, null, null, launchError, replyCallback);
+});
+
+}
+
+function Application_exit_exist() {
+
+//==== TEST: Application_exit_exist
+//==== LABEL Check if method Application.exit exist
+//==== SPEC Tizen Web API:Application:Application:Application:exit M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    var app = tizen.application.getCurrentApplication();
+    check_method_exists(app, "exit");
+}, 'Application_exit_exist');
+
+}
+
+function Application_extend() {
+
+//==== TEST: Application_extend
+//==== LABEL Check if Application possible extend
+//==== SPEC Tizen Web API:Application:Application:Application:Application U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA OBX
+
+test(function () {
+    var app = tizen.application.getCurrentApplication();
+    check_extensibility(app);
+}, 'Application_extend');
+
+}
+
+function Application_getRequestedAppControl() {
+
+//==== TEST: Application_getRequestedAppControl
+//==== LABEL Check using getRequestedAppControl method (with non-optional arguments) in Application interface
+//==== SPEC Tizen Web API:Application:Application:Application:getRequestedAppControl M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MNA MR
+
+/**
+ * Function below only invokes test in TCTAppControl application.
+ * Actually tests are in support/TCTAppControl/tests directory.
+ */
+runTestAtTCTAppControl("Application_getRequestedAppControl");
+
+}
+
+function Application_getRequestedAppControl_exist() {
+
+//==== TEST: Application_getRequestedAppControl_exist
+//==== LABEL Check if method Application.getRequestedAppControl exist
+//==== SPEC Tizen Web API:Application:Application:Application:getRequestedAppControl M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    var app = tizen.application.getCurrentApplication();
+    check_method_exists(app, "getRequestedAppControl");
+}, 'Application_getRequestedAppControl_exist');
+
+}
+
+function Application_getRequestedAppControl_extra_argument() {
+
+//==== TEST: Application_getRequestedAppControl_extra_argument
+//==== LABEL Check using getRequestedAppControl method (with extra argument) in Application interface
+//==== SPEC Tizen Web API:Application:Application:Application:getRequestedAppControl M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MNAEX MR
+
+/**
+ * Function below only invokes test in TCTAppControl application.
+ * Actually tests are in support/TCTAppControl/tests directory.
+ */
+runTestAtTCTAppControl("Application_getRequestedAppControl_extra_argument");
+
+}
+
+function Application_hide() {
+
+//==== TEST: Application_hide
+//==== LABEL Check using hide method (with non-optional arguments) in Application interface
+//==== SPEC Tizen Web API:Application:Application:Application:hide M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MNA MR
+
+/**
+ * Function below only invokes test in TCTAppControl application.
+ * Actually tests are in support/TCTAppControl/tests directory.
+ */
+runTestAtTCTAppControl("Application_hide");
+
+}
+
+function Application_hide_exist() {
+
+//==== TEST: Application_hide_exist
+//==== LABEL Check if method Application.hide exist
+//==== SPEC Tizen Web API:Application:Application:Application:hide M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    var app = tizen.application.getCurrentApplication();
+    check_method_exists(app, "hide");
+}, 'Application_hide_exist');
+
+}
+
+function Application_hide_extra_argument() {
+
+//==== TEST: Application_hide_extra_argument
+//==== LABEL Check using hide method (with extra arguments) in Application interface
+//==== SPEC Tizen Web API:Application:Application:Application:hide M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MNAEX
+
+/**
+ * Function below only invokes test in TCTAppControl application.
+ * Actually tests are in support/TCTAppControl/tests directory.
+ */
+runTestAtTCTAppControl("Application_hide_extra_argument");
+
+}
+
+function Application_notexist() {
+
+//==== TEST: Application_notexist
+//==== LABEL Check if Application notexist
+//==== SPEC Tizen Web API:Application:Application:Application:Application U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("Application");
+}, 'Application_notexist');
+
+}
+
+function FindAppControlSuccessCallback_notexist() {
+
+//==== TEST: FindAppControlSuccessCallback_notexist
+//==== LABEL Check if FindAppControlSuccessCallback cannot be called as a function or in new expression
+//==== SPEC Tizen Web API:Application:Application:FindAppControlSuccessCallback:FindAppControlSuccessCallback U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA CBNIO
+
+test(function () {
+    check_no_interface_object("FindAppControlSuccessCallback");
+}, 'FindAppControlSuccessCallback_notexist');
+
+}
+
+function FindAppControlSuccessCallback_onsuccess() {
+
+//==== TEST: FindAppControlSuccessCallback_onsuccess
+//==== LABEL Check if FindAppControlSuccessCallback onsuccess is called and if its arguments have proper type
+//==== ONLOAD_DELAY 30
+//==== SPEC: Tizen Web API:Application:Application:FindAppControlSuccessCallback:onsuccess M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA CBOA CBT
+
+setup({timeout: 30000});
+
+var t = async_test('FindAppControlSuccessCallback_onsuccess', {timeout: 30000}),
+    findSuccess, findError, info, control, tmp, i;
+
+t.step(function () {
+    control = new tizen.ApplicationControl(
+        TCT_APPCONTROL_LAUNCH_APPCONTROL_OPERATION,
+        TCT_APPCONTROL_LAUNCH_APPCONTROL_URI,
+        TCT_APPCONTROL_LAUNCH_APPCONTROL_MIME
+    );
+
+    findSuccess = t.step_func(function (informationArray, appControl) {
+        assert_type(informationArray, "array", "wrong type of invoked callback argument");
+        assert_true(informationArray.length > 0, "informationArray was not found");
+
+        info = informationArray[0];
+        assert_true("id" in info, "ApplicationInformation should have id property");
+        check_readonly(info, "id", info.id, "string", "dummy");
+        assert_true("name" in info, "ApplicationInformation should have name property");
+        check_readonly(info, "name", info.name, "string", "dummy");
+        assert_true("iconPath" in info, "ApplicationInformation should have iconPath property");
+        check_readonly(info, "iconPath", info.iconPath, "string", "dummy");
+        assert_true("version" in info, "ApplicationInformation should have version property");
+        check_readonly(info, "version", info.version, "string", "dummy");
+        assert_true("show" in info, "ApplicationInformation should have show property");
+        check_readonly(info, "show", info.show, "boolean", !info.show);
+
+        assert_type(info.categories, "array", "categories should be an array");
+        tmp = info.categories;
+        info.categories = ["one", "two"];
+        assert_equals(info.categories.length, tmp.length, "categories is not readonly");
+        for(i = 0; i < tmp.length; i++) {
+            assert_type(info.categories[i], "string", "categories items sould be a string");
+            assert_equals(info.categories[i], tmp[i], "categories is not readonly");
+        }
+
+        assert_type(info.installDate, "date", "installDate should be a date");
+        tmp = info.installDate;
+        info.installDate = new Date();
+        assert_equals(info.installDate.getTime(), tmp.getTime(), "values are different");
+
+        assert_true("size" in info, "ApplicationInformation should have size property");
+        check_readonly(info, "size", info.size, "number", 2 + 3 * info.size / 2);
+        assert_true("packageId" in info, "ApplicationInformation should have packageId property");
+        check_readonly(info, "packageId", info.packageId, "string", "dummy");
+
+        assert_true("operation" in appControl, "ApplicationControl should have operation property");
+        check_attribute(appControl, "operation", appControl.operation, "string", "dummy");
+        assert_true("uri" in appControl, "ApplicationControl should have uri property");
+        check_attribute(appControl, "uri", appControl.uri, "string", "dummy");
+        assert_true("mime" in appControl, "ApplicationControl should have mime property");
+        check_attribute(appControl, "mime", appControl.mime, "string", "dummy");
+        assert_true("category" in appControl, "ApplicationControl should have category property");
+        check_attribute(appControl, "category", appControl.category, "string", "dummy");
+        assert_true("data" in appControl, "ApplicationControl should have data property");
+        assert_type(appControl.data, "array", "data in appControl has wrong type");
+
+        t.done();
+    });
+
+    findError = t.step_func(function (error) {
+        assert_unreached("errorCallback called:" + error.message);
+    });
+
+    tizen.application.findAppControl(control, findSuccess, findError);
+});
+
+}
+
+function RequestedApplicationControl_appControl_attribute() {
+
+//==== TEST: RequestedApplicationControl_appControl_attribute
+//==== LABEL Check if RequestedApplicationControl have appControl attribute with proper type, writable, not null
+//==== SPEC: Tizen Web API:Application:Application:RequestedApplicationControl:appControl A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA AE AT ARO
+
+/**
+ * Function below only invokes test in TCTAppControl application.
+ * Actually tests are in support/TCTAppControl/tests directory.
+ */
+runTestAtTCTAppControl("RequestedApplicationControl_appControl_attribute");
+
+}
+
+function RequestedApplicationControl_callerAppId_attribute() {
+
+//==== TEST: RequestedApplicationControl_callerAppId_attribute
+//==== LABEL Check if RequestedApplicationControl have callerAppId attribute with proper type, writable, not null
+//==== SPEC: Tizen Web API:Application:Application:RequestedApplicationControl:callerAppId A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA AE AT ARO
+
+/**
+ * Function below only invokes test in TCTAppControl application.
+ * Actually tests are in support/TCTAppControl/tests directory.
+ */
+runTestAtTCTAppControl("RequestedApplicationControl_callerAppId_attribute");
+
+}
+
+function RequestedApplicationControl_extend() {
+
+//==== TEST: RequestedApplicationControl_extend
+//==== LABEL Check if RequestedApplicationControl can have new properties added
+//==== SPEC: Tizen Web API:Application:Application:RequestedApplicationControl:RequestedApplicationControl U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P3
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA OBX
+
+/**
+ * Function below only invokes test in TCTAppControl application.
+ * Actually tests are in support/TCTAppControl/tests directory.
+ */
+runTestAtTCTAppControl("RequestedApplicationControl_extend");
+
+}
+
+function RequestedApplicationControl_notexist() {
+
+//==== TEST: RequestedApplicationControl_notexist
+//==== LABEL Check if RequestedApplicationControl cannot be called as a function or in new expression
+//==== SPEC Tizen Web API:Application:Application:RequestedApplicationControl:RequestedApplicationControl U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("RequestedApplicationControl");
+}, 'RequestedApplicationControl_notexist');
+
+}
+
+function RequestedApplicationControl_replyFailure() {
+//==== TEST: RequestedApplicationControl_replyFailure
+//==== LABEL Check if RequestedApplicationControl method replyFailure works properly
+//==== SPEC: Tizen Web API:Application:Application:RequestedApplicationControl:replyFailure M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MNA
+
+setup({timeout: 30000});
+
+var t = async_test('RequestedApplicationControl_replyFailure', {timeout: 30000}),
+    appControl, replyCallback, onError;
+
+setup_launch(t, TCT_APPCONTROL_APPID, function () {
+    appControl = new tizen.ApplicationControl(
+                        TCT_APPCONTROL_REPLY_FAILURE_OPERATION,
+                        null,
+                        null,
+                        null,
+                        [ new tizen.ApplicationControlData("testName", [ t.name ]) ]);
+
+    onError = t.step_func(function (err) {
+        assert_unreached("errorCallback called: " + err.message);
+    });
+
+    replyCallback = {
+        onsuccess: t.step_func(function () {
+            assert_unreached("onsuccess callback called");
+        }),
+
+        onfailure: t.step_func(function () {
+            setTimeout(function(){
+                               t.done();
+                       }, 3000);
+        })
+    };
+
+    tizen.application.launchAppControl(appControl, null, null, onError, replyCallback);
+});
+
+}
+
+function RequestedApplicationControl_replyFailure_exist() {
+
+//==== TEST: RequestedApplicationControl_replyFailure_exist
+//==== LABEL Check if replyFailure exists
+//==== SPEC: Tizen Web API:Application:Application:RequestedApplicationControl:replyFailure M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA ME
+
+/**
+ * Function below only invokes test in TCTAppControl application.
+ * Actually tests are in support/TCTAppControl/tests directory.
+ */
+runTestAtTCTAppControl("RequestedApplicationControl_replyFailure_exist");
+
+}
+
+function RequestedApplicationControl_replyFailure_extra_argument() {
+
+//==== TEST: RequestedApplicationControl_replyFailure_extra_argument
+//==== LABEL Check if replyFailure method can be invoked with extra argument
+//==== SPEC Tizen Web API:Application:Application:RequestedApplicationControl:replyFailure M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MNAEX
+
+setup({timeout: 30000});
+
+var t = async_test('RequestedApplicationControl_replyFailure_extra_argument', {timeout: 30000}),
+    appControl, replyCallback, onError;
+
+setup_launch(t, TCT_APPCONTROL_APPID, function () {
+    appControl = new tizen.ApplicationControl(
+                        TCT_APPCONTROL_REPLY_FAILURE_OPERATION,
+                        null,
+                        null,
+                        null,
+                        [ new tizen.ApplicationControlData("testName", [ t.name ]) ]);
+
+    onError = t.step_func(function (err) {
+        assert_unreached("errorCallback called: " + err.message);
+    });
+
+    replyCallback = {
+        onsuccess: t.step_func(function () {
+            assert_unreached("onsuccess callback called");
+        }),
+
+        onfailure: t.step_func(function () {
+            setTimeout(function(){
+                               t.done();
+                       }, 3000);
+        })
+    };
+
+    tizen.application.launchAppControl(appControl, null, null, onError, replyCallback);
+});
+
+}
+
+function RequestedApplicationControl_replyResult() {
+
+//==== TEST: RequestedApplicationControl_replyResult
+//==== LABEL Check if RequestedApplicationControl method replyResult works properly
+//==== SPEC: Tizen Web API:Application:Application:RequestedApplicationControl:replyResult M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MMINA
+
+setup({timeout: 30000});
+
+var t = async_test('RequestedApplicationControl_replyResult', {timeout: 30000}),
+    appControl, replyCallback, onerror;
+
+setup_launch(t, TCT_APPCONTROL_APPID, function () {
+    appControl = new tizen.ApplicationControl(TCT_APPCONTROL_REPLY_RESULT_OPERATION);
+
+    onerror = t.step_func(function (err) {
+        assert_unreached("errorCallback called: " + err.message);
+    });
+
+    replyCallback = {
+        onsuccess: t.step_func(function () {
+            setTimeout(function(){
+                               t.done();
+                       }, 3000);
+        }),
+
+        onfailure: t.step_func(function () {
+            assert_unreached("onfailure callback called");
+        })
+    };
+
+    tizen.application.launchAppControl(appControl, null, null, onerror, replyCallback);
+});
+
+}
+
+function RequestedApplicationControl_replyResult_data_TypeMismatch() {
+
+//==== TEST: RequestedApplicationControl_replyResult_data_TypeMismatch
+//==== LABEL Check if replyResult throws exception when data is incorrect
+//==== SPEC Tizen Web API:Application:Application:RequestedApplicationControl:replyResult M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P2
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MC
+
+/**
+ * Function below only invokes test in TCTAppControl application.
+ * Actually tests are in support/TCTAppControl/tests directory.
+ */
+runTestAtTCTAppControl("RequestedApplicationControl_replyResult_data_TypeMismatch");
+
+}
+
+function RequestedApplicationControl_replyResult_exist() {
+//==== TEST: RequestedApplicationControl_replyResult_exist
+//==== LABEL Check if replyResult exists
+//==== SPEC: Tizen Web API:Application:Application:RequestedApplicationControl:replyResult M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA ME
+
+/**
+ * Function below only invokes test in TCTAppControl application.
+ * Actually tests are in support/TCTAppControl/tests directory.
+ */
+runTestAtTCTAppControl("RequestedApplicationControl_replyResult_exist");
+
+}
+
+function RequestedApplicationControl_replyResult_with_data() {
+
+//==== TEST: RequestedApplicationControl_replyResult_with_data
+//==== LABEL Check if RequestedApplicationControl method replyCallback called with data param works properly
+//==== SPEC: Tizen Web API:Application:Application:RequestedApplicationControl:replyResult M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MOA MAST
+
+setup({timeout: 30000});
+
+var t = async_test('RequestedApplicationControl_replyResult_with_data', {timeout: 30000}),
+    appControl, replyCallback, onerror, sentData;
+
+setup_launch(t, TCT_APPCONTROL_APPID, function () {
+    sentData = new tizen.ApplicationControlData("key1", ["data1"]);
+
+    appControl = new tizen.ApplicationControl(TCT_APPCONTROL_REPLY_RESULT_WITH_DATA_OPERATION,
+                                                null,
+                                                null,
+                                                null,
+                                                [sentData]);
+
+    onerror = t.step_func(function (err) {
+        assert_unreached("errorCallback called: " + err.message);
+    });
+
+    replyCallback = {
+        onsuccess: t.step_func(function (data) {
+            assert_true(data.length > 0, "data was not sent");
+            assert_equals(data[0].key, sentData.key, "values sent and received are different");
+            assert_equals(data[0].value[0], sentData.value[0], "values sent and received are different");
+            setTimeout(function(){
+                               t.done();
+                       }, 3000);
+        }),
+
+        onfailure: t.step_func(function () {
+            assert_unreached("onfailure callback called");
+        })
+    };
+
+    tizen.application.launchAppControl(appControl, null, null, onerror, replyCallback);
+});
+
+}
+
+function ApplicationInformationEventCallback_oninstalled() {
+
+//==== TEST: ApplicationInformationEventCallback_oninstalled
+//==== LABEL Check argument passed into method which is oninstalled listener in ApplicationInformationEventCallback
+//==== SPEC Tizen Web API:Application:Application:ApplicationInformationEventCallback:oninstalled M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRE Make sure that TCTAppInfoEventTest1 application is not installed (uninstall it)
+//==== STEP Click run and install TCTAppInfoEventTest1.wgt application from My files app (Phone/Others directory).
+//==== EXPECT Pass
+//==== EXECUTION_TYPE manual
+//==== PRIORITY P1
+//==== TEST_CRITERIA CBT CBOA
+
+setup({timeout: 300000});
+
+var t = async_test('ApplicationInformationEventCallback_oninstalled', {timeout: 300000}), appEventCallback, watchId;
+
+t.step(function () {
+
+    appEventCallback = {
+        oninstalled: t.step_func(function (appInfo) {
+            assert_type(appInfo, "object", "wrong type of received value");
+            assert_true("id" in appInfo, "no id in returned value");
+            assert_true("name" in appInfo, "no name in returned value");
+            assert_true("iconPath" in appInfo, "no iconPath in returned value");
+            assert_true("version" in appInfo, "no version in returned value");
+            assert_true("show" in appInfo, "no show in returned value");
+            assert_true("categories" in appInfo, "no categories in returned value");
+            assert_true("installDate" in appInfo, "no installDate in returned value");
+            assert_true("size" in appInfo, "no size in returned value");
+            assert_true("packageId" in appInfo, "no packageId in returned value");
+            assert_equals(appInfo.id, APP_INFO_TEST_APP_ID, "wrong ApplicationInformation was returned");
+            t.done();
+        }),
+        onupdated: t.step_func(function () {
+            assert_unreached("This function (onupdated) should not be used");
+        }),
+        onuninstalled: t.step_func(function () {
+            assert_unreached("This function (onuninstalled) should not be used");
+        })
+    };
+
+    watchId = tizen.application.addAppInfoEventListener(appEventCallback);
+    assert_type(watchId, "long", "wrong listener ID");
+
+    alert("Install the appliction, command: pkgcmd -i -t wgt -q -p /home/owner/share/TCTAppInfoEventTest1.wgt");
+});
+
+}
+
+function ApplicationInformationEventCallback_onupdated() {
+
+//==== TEST: ApplicationInformationEventCallback_onupdated
+//==== LABEL Check argument passed into method which is onupdated listener in ApplicationInformationEventCallback
+//==== SPEC Tizen Web API:Application:Application:ApplicationInformationEventCallback:onupdated M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRE Make sure that TCTAppInfoEventTest1 application is installed (you can install it from My files app (Phone/Others directory)).
+//==== STEP Click run and install TCTAppInfoEventTest2.wgt application from My files app (Phone/Others directory).
+//==== EXPECT Pass
+//==== EXECUTION_TYPE manual
+//==== PRIORITY P1
+//==== TEST_CRITERIA CBT CBOA
+
+setup({timeout: 300000});
+
+var t = async_test('ApplicationInformationEventCallback_onupdated', {timeout: 300000}), appEventCallback, watchId;
+
+t.step(function () {
+
+    appEventCallback = {
+        oninstalled: t.step_func(function () {
+            assert_unreached("This function (oninstalled) should not be used");
+        }),
+        onupdated: t.step_func(function (appInfo) {
+            assert_type(appInfo, "object", "wrong type of received value");
+            assert_true("id" in appInfo, "no id in returned value");
+            assert_true("name" in appInfo, "no name in returned value");
+            assert_true("iconPath" in appInfo, "no iconPath in returned value");
+            assert_true("version" in appInfo, "no version in returned value");
+            assert_true("show" in appInfo, "no show in returned value");
+            assert_true("categories" in appInfo, "no categories in returned value");
+            assert_true("installDate" in appInfo, "no installDate in returned value");
+            assert_true("size" in appInfo, "no size in returned value");
+            assert_true("packageId" in appInfo, "no packageId in returned value");
+            assert_equals(appInfo.id, APP_INFO_TEST_APP_ID, "wrong ApplicationInformation was returned");
+            t.done();
+        }),
+        onuninstalled: t.step_func(function () {
+            assert_unreached("This function (onuninstalled) should not be used");
+        })
+    };
+
+    watchId = tizen.application.addAppInfoEventListener(appEventCallback);
+    assert_type(watchId, "long", "wrong listener ID");
+
+    alert("Install the appliction, command: pkgcmd -i -t wgt -q -p /home/owner/share/TCTAppInfoEventTest2.wgt");
+
+});
+
+}
+
+function ApplicationInformationEventCallback_onuninstalled() {
+
+//==== TEST: ApplicationInformationEventCallback_onuninstalled
+//==== LABEL Check argument passed into method which is onuninstalled listener in ApplicationInformationEventCallback
+//==== SPEC Tizen Web API:Application:Application:ApplicationInformationEventCallback:onuninstalled M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRE Make sure that TCTAppInfoEventTest1 application is installed (you can install it from My files app (Phone/Others directory)).
+//==== STEP Click run and uninstall TCTAppInfoEventTest1 application.
+//==== EXPECT Pass
+//==== EXECUTION_TYPE manual
+//==== PRIORITY P1
+//==== TEST_CRITERIA CBT CBOA
+
+setup({timeout: 300000});
+
+var t = async_test('ApplicationInformationEventCallback_onuninstalled', {timeout: 300000}), appEventCallback, watchId;
+
+t.step(function () {
+
+    appEventCallback = {
+        oninstalled: t.step_func(function () {
+            assert_unreached("This function (oninstalled) should not be used");
+        }),
+        onupdated: t.step_func(function () {
+            assert_unreached("This function (onupdated) should not be used");
+        }),
+        onuninstalled: t.step_func(function (appId) {
+            assert_type(appId, "string", "wrong type of received value");
+            assert_equals(appId, APP_INFO_TEST_APP_ID, "wrong ApplicationId was returned");
+            t.done();
+        })
+    };
+
+    watchId = tizen.application.addAppInfoEventListener(appEventCallback);
+    assert_type(watchId, "long", "wrong listener ID");
+
+    alert("Uninstall the appliction, command: pkgcmd -u -n api1appli3");
+});
+
+}
+
+function ApplicationManager_addAppInfoEventListener_oninstalled() {
+
+//==== TEST: ApplicationManager_addAppInfoEventListener_oninstalled
+//==== LABEL Check using addAppInfoEventListener method (installation process) in ApplicationManager interface
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:addAppInfoEventListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRE Make sure that TCTAppInfoEventTest1 application is not installed (uninstall it)
+//==== STEP Click run and install TCTAppInfoEventTest1.wgt application from My files app (Phone/Others directory).
+//==== EXPECT Pass
+//==== EXECUTION_TYPE manual
+//==== PRIORITY P1
+//==== TEST_CRITERIA MMINA MAST MR
+
+setup({timeout: 300000});
+
+var t = async_test('ApplicationManager_addAppInfoEventListener_oninstalled', {timeout: 300000}), appEventCallback, watchId;
+t.step(function () {
+
+    appEventCallback = {
+        oninstalled: t.step_func(function () {
+            t.done();
+        }),
+        onupdated: t.step_func(function () {
+            assert_unreached("This function (onupdated) should not be used");
+        }),
+        onuninstalled: t.step_func(function () {
+            assert_unreached("This function (onuninstalled) should not be used");
+        })
+    };
+
+    watchId = tizen.application.addAppInfoEventListener(appEventCallback);
+    assert_type(watchId, "long", "wrong listener ID");
+
+    alert("Install the appliction, command: pkgcmd -i -t wgt -q -p /home/owner/share/TCTAppInfoEventTest1.wgt");
+});
+
+}
+
+function ApplicationManager_addAppInfoEventListener_onupdated() {
+
+//==== TEST: ApplicationManager_addAppInfoEventListener_onupdated
+//==== LABEL Check using addAppInfoEventListener method (updating process) in ApplicationManager interface
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:addAppInfoEventListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRE Make sure that TCTAppInfoEventTest1 application is installed (you can install it from My files app (Phone/Others directory)).
+//==== STEP Click run and install TCTAppInfoEventTest2.wgt application from My files app (Phone/Others directory).
+//==== EXPECT Pass
+//==== EXECUTION_TYPE manual
+//==== PRIORITY P1
+//==== TEST_CRITERIA MMINA MAST MR
+
+setup({timeout: 300000});
+
+var t = async_test('ApplicationManager_addAppInfoEventListener_onupdated', {timeout: 300000}), appEventCallback, watchId;
+t.step(function () {
+
+    appEventCallback = {
+        oninstalled: t.step_func(function () {
+            assert_unreached("This function (oninstalled) should not be used");
+        }),
+        onupdated: t.step_func(function () {
+            t.done();
+        }),
+        onuninstalled: t.step_func(function () {
+            assert_unreached("This function (onuninstalled) should not be used");
+        })
+    };
+
+    watchId = tizen.application.addAppInfoEventListener(appEventCallback);
+    assert_type(watchId, "long", "wrong listener ID");
+
+    alert("Install the appliction, command: pkgcmd -i -t wgt -q -p /home/owner/share/TCTAppInfoEventTest2.wgt");
+});
+
+}
+
+function ApplicationManager_addAppInfoEventListener_onuninstalled() {
+
+//==== TEST: ApplicationManager_addAppInfoEventListener_onuninstalled
+//==== LABEL Check using addAppInfoEventListener method (deinstallation process) in ApplicationManager interface
+//==== SPEC Tizen Web API:Application:Application:ApplicationManager:addAppInfoEventListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRE Make sure that TCTAppInfoEventTest1 application is installed (you can install it from My files app (Phone/Others directory)).
+//==== STEP Click run and uninstall TCTAppInfoEventTest1 application.
+//==== EXPECT Pass
+//==== EXECUTION_TYPE manual
+//==== PRIORITY P1
+//==== TEST_CRITERIA MMINA MAST MR
+
+setup({timeout: 300000});
+
+var t = async_test('ApplicationManager_addAppInfoEventListener_onuninstalled', {timeout: 300000}), appEventCallback, watchId;
+t.step(function () {
+
+    appEventCallback = {
+        oninstalled: t.step_func(function () {
+            assert_unreached("This function (onupdated) should not be used");
+        }),
+        onupdated: t.step_func(function () {
+            assert_unreached("This function (onupdated) should not be used");
+        }),
+        onuninstalled: t.step_func(function () {
+            t.done();
+        })
+    };
+
+    watchId = tizen.application.addAppInfoEventListener(appEventCallback);
+    assert_type(watchId, "long", "wrong listener ID");
+
+    alert("Uninstall the appliction, command: pkgcmd -u -n api1appli3");
+});
+
+}
+
+function Application_addEventListener() {
+//==== TEST: Application_addEventListener
+//==== LABEL Check if method Application::addEventListener() successfully
+//==== SPEC Tizen Web API:TBD:Application:Application:addEventListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+setup({timeout: 90000});
+
+var t = async_test('Application_addEventListener', {timeout: 90000}), app, eventCallback, listenerId;
+
+setup_launch(t, APP_BROAD_TEST_APP_ID, function () {
+    eventCallback = t.step_func(function (name, data) {
+        app.removeEventListener(listenerId);
+        setTimeout(function(){
+                       t.done();
+               }, 3000);
+    });
+
+    app = tizen.application.getCurrentApplication();
+    try {
+        listenerId = app.addEventListener({"appId": APP_BROAD_TEST_APP_ID, "name": APP_BROAD_TEST_EVENT_NAME}, eventCallback);
+        assert_type(listenerId, "number", "addEventListener returns wrong value");
+    } catch (e) {
+        assert_unreached(e.name + ": " + e.message);
+    }
+    tizen.application.launch(APP_BROAD_TEST_APP_ID);
+});
+
+}
+
+function Application_addEventListener_callback_invalid_cb() {
+//==== TEST: Application_addEventListener_callback_invalid_cb
+//==== LABEL Check if addEventListener() throws exception with invalid callback
+//==== SPEC Tizen Web API:TBD:Application:Application:addEventListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTL
+
+test(function () {
+    var app = tizen.application.getCurrentApplication(), callback, i, incorrectListener, exceptionName;
+
+    incorrectListener = getListenerConversionExceptions(["onevent"]);
+    for(i = 0; i < incorrectListener.length; i++) {
+        callback = incorrectListener[i][0];
+        exceptionName = incorrectListener[i][1];
+
+        assert_throws({name: exceptionName}, function () {
+            app.addEventListener({"appId": app.appInfo.id, "name": APP_BROAD_TEST_APP_NAME}, callback);
+        }, exceptionName + " should be thrown - given incorrect callback.");
+    }
+}, 'Application_addEventListener_callback_invalid_cb');
+
+}
+
+function Application_addEventListener_eventCallback_TypeMismatch() {
+//==== TEST: Application_addEventListener_eventCallback_TypeMismatch
+//==== LABEL Check if Application::addEventListener throws exception when given wrong eventCallback
+//==== SPEC Tizen Web API:TBD:Application:Application:addEventListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+test(function () {
+    var app = tizen.application.getCurrentApplication(), i, badValues, value, exceptionName;
+
+    badValues = getTypeConversionExceptions("functionObject", false);
+    for (i = 0; i < badValues.length; i++) {
+        value = badValues[i][0];
+        exceptionName = badValues[i][1];
+        assert_throws({
+            name: exceptionName
+        }, function () {
+           app.addEventListener({"appId": app.appInfo.id, "name": APP_BROAD_TEST_APP_NAME}, value);
+           }, exceptionName + " exception should be thrown with an invalid name.");
+    }
+}, 'Application_addEventListener_eventCallback_TypeMismatch');
+
+}
+
+function Application_addEventListener_exist() {
+//==== TEST: Application_addEventListener_exist
+//==== LABEL Check if Application::addEventListener() method exists
+//==== SPEC Tizen Web API:TBD:Application:Application:addEventListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+var app;
+
+test(function () {
+    app = tizen.application.getCurrentApplication();
+    check_method_exists(app, "addEventListener");
+}, 'Application_addEventListener_exist');
+
+}
+
+function Application_addEventListener_misarg() {
+//==== TEST: Application_addEventListener_misarg
+//==== LABEL Check if Application.addEventListener() throws an exception without parameter
+//==== SPEC Tizen Web API:TBD:Application:Application:addEventListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MMA
+
+test(function () {
+    var app = tizen.application.getCurrentApplication();
+
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        app.addEventListener();
+    }, "Missing non-optional argument should throw an exception");
+}, 'Application_addEventListener_misarg');
+
+}
+
+function Application_addEventListener_name_TypeMismatch() {
+//==== TEST: Application_addEventListener_name_TypeMismatch
+//==== LABEL Check if Application::addEventListener throws exception when given wrong type of name
+//==== SPEC Tizen Web API:TBD:Application:Application:addEventListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 90000});
+
+var t = async_test('Application_addEventListener_name_TypeMismatch', {timeout: 90000}), app, i, badValues, value, exceptionName, eventCallback;
+
+t.step(function () {
+    app = tizen.application.getCurrentApplication();
+
+    eventCallback = t.step_func(function (name, data) {
+        assert_unreached("this callback should not be called");
+    });
+
+    badValues = getTypeConversionExceptions("object", false);
+    for (i = 0; i < badValues.length; i++) {
+        value = badValues[i][0];
+        exceptionName = badValues[i][1];
+        assert_throws({name: exceptionName}, function () {
+            app.addEventListener(value, eventCallback);
+        }, exceptionName + " exception should be thrown with an invalid name.");
+    }
+    t.done();
+});
+
+}
+
+function Application_broadcastEvent() {
+//==== TEST: Application_broadcastEvent
+//==== LABEL Check if method Application::broadcastEvent() successfully
+//==== SPEC Tizen Web API:TBD:Application:Application:broadcastEvent M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var app, myCustomData = {type: 'bar', value: 'val'}, result;
+
+    app = tizen.application.getCurrentApplication();
+    try {
+        result = app.broadcastEvent({"appId": app.appInfo.id, "name": APP_BROAD_TEST_EVENT_NAME}, myCustomData);
+        assert_type(result, "undefined", "fail to get return");
+    } catch (e) {
+        assert_unreached(e.name + ": " + e.message);
+    };
+}, 'Application_broadcastEvent');
+
+}
+
+function Application_broadcastEvent_data_TypeMismatch() {
+//==== TEST: Application_broadcastEvent_data_TypeMismatch
+//==== LABEL Check if Application::broadcastEvent throws exception when given wrong type of data
+//==== SPEC Tizen Web API:TBD:Application:Application:broadcastEvent M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+test(function () {
+    var app = tizen.application.getCurrentApplication(), i, badValues, value, exceptionName;
+
+    badValues = getTypeConversionExceptions("object", false);
+    for (i = 0; i < badValues.length; i++) {
+        value = badValues[i][0];
+        exceptionName = badValues[i][1];
+        assert_throws({name: exceptionName},
+            function () {
+                app.broadcastEvent({"appId": app.appInfo.id, "name": APP_BROAD_TEST_EVENT_NAME}, value);
+            }, exceptionName + " exception should be thrown with an invalid data.");
+    }
+}, 'Application_broadcastEvent_data_TypeMismatch');
+
+}
+
+function Application_broadcastEvent_exist() {
+//==== TEST: Application_broadcastEvent_exist
+//==== LABEL Check if Application::broadcastEvent() method exists
+//==== SPEC Tizen Web API:TBD:Application:Application:broadcastEvent M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    var app = tizen.application.getCurrentApplication();
+    check_method_exists(app, "broadcastEvent");
+}, 'Application_broadcastEvent_exist');
+
+}
+
+function Application_broadcastEvent_misarg() {
+//==== TEST: Application_broadcastEvent_misarg
+//==== LABEL Check if Application.broadcastEvent() throws an exception without parameter
+//==== SPEC Tizen Web API:TBD:Application:Application:broadcastEvent M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MMA
+
+test(function () {
+    var app = tizen.application.getCurrentApplication();
+
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        app.broadcastEvent();
+    }, "Missing non-optional argument should throw an exception");
+}, 'Application_broadcastEvent_misarg');
+
+}
+
+function Application_broadcastEvent_name_TypeMismatch() {
+//==== TEST: Application_broadcastEvent_name_TypeMismatch
+//==== LABEL Check if Application::broadcastEvent throws exception when given wrong type of name
+//==== SPEC Tizen Web API:TBD:Application:Application:broadcastEvent M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+test(function () {
+    var app = tizen.application.getCurrentApplication(), i, badValues, value, exceptionName, myCustomData = {type: 'bar', value: 'val'};
+
+    badValues = getTypeConversionExceptions("object", false);
+    for (i = 0; i < badValues.length; i++) {
+        value = badValues[i][0];
+        exceptionName = badValues[i][1];
+        assert_throws({
+            name: exceptionName
+            }, function () {
+                app.broadcastEvent(value, myCustomData);
+            }, exceptionName + " exception should be thrown with an invalid name.");
+    }
+}, 'Application_broadcastEvent_name_TypeMismatch');
+
+}
+
+function Application_broadcastTrustedEvent() {
+//==== TEST: Application_broadcastTrustedEvent
+//==== LABEL Check if method Application::broadcastTrustedEvent() successfully
+//==== SPEC Tizen Web API:TBD:Application:Application:broadcastTrustedEvent M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var app, myCustomData = {type: 'bar', value: 'val'}, returnValue;
+
+    app = tizen.application.getCurrentApplication();
+    try {
+        returnValue = app.broadcastTrustedEvent({"appId": app.appInfo.id, "name": APP_BROAD_TEST_EVENT_NAME}, myCustomData);
+        assert_type(returnValue, "undefined", "fail to get return");
+    } catch (e) {
+        assert_unreached(e.name + ": " + e.message);
+    };
+}, 'Application_broadcastTrustedEvent');
+
+}
+
+function Application_broadcastTrustedEvent_data_TypeMismatch() {
+//==== TEST: Application_broadcastTrustedEvent_data_TypeMismatch
+//==== LABEL Check if Application::broadcastTrustedEvent throws exception when given wrong type of data
+//==== SPEC Tizen Web API:TBD:Application:Application:broadcastTrustedEvent M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+test(function () {
+    var app = tizen.application.getCurrentApplication(), i, badValues, value, exceptionName;
+
+    badValues = getTypeConversionExceptions("object", false);
+    for (i = 0; i < badValues.length; i++) {
+        value = badValues[i][0];
+        exceptionName = badValues[i][1];
+        assert_throws({
+            name: exceptionName
+            }, function () {
+                app.broadcastTrustedEvent({"appId": app.appInfo.id, "name": APP_BROAD_TEST_EVENT_NAME}, value);
+            }, exceptionName + " exception should be thrown with an invalid data.");
+    }
+}, 'Application_broadcastTrustedEvent_data_TypeMismatch');
+
+}
+
+function Application_broadcastTrustedEvent_exist() {
+//==== TEST: Application_broadcastTrustedEvent_exist
+//==== LABEL Check if Application::broadcastTrustedEvent() method exists
+//==== SPEC Tizen Web API:TBD:Application:Application:broadcastTrustedEvent M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    var app = tizen.application.getCurrentApplication();
+    check_method_exists(app, "broadcastTrustedEvent");
+}, 'Application_broadcastTrustedEvent_exist');
+
+}
+
+function Application_broadcastTrustedEvent_misarg() {
+//==== TEST: Application_broadcastTrustedEvent_misarg
+//==== LABEL Check if Application.broadcastTrustedEvent() throws an exception without parameter
+//==== SPEC Tizen Web API:TBD:Application:Application:broadcastTrustedEvent M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MMA
+
+test(function () {
+    var app = tizen.application.getCurrentApplication();
+
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        app.broadcastTrustedEvent();
+    }, "Missing non-optional argument should throw an exception");
+}, 'Application_broadcastTrustedEvent_misarg');
+
+}
+
+function Application_broadcastTrustedEvent_name_TypeMismatch() {
+//==== TEST: Application_broadcastTrustedEvent_name_TypeMismatch
+//==== LABEL Check if Application::broadcastTrustedEvent throws exception when given wrong type of name
+//==== SPEC Tizen Web API:TBD:Application:Application:broadcastTrustedEvent M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+test(function () {
+    var app = tizen.application.getCurrentApplication(), i, badValues, value, exceptionName, myCustomData = {type: 'bar', value: 'val'};
+
+    badValues = getTypeConversionExceptions("object", false);
+    for (i = 0; i < badValues.length; i++) {
+        value = badValues[i][0];
+        exceptionName = badValues[i][1];
+        assert_throws({
+            name: exceptionName
+            }, function () {
+                app.broadcastTrustedEvent(value, myCustomData);
+            }, exceptionName + " exception should be thrown with an invalid name.");
+    }
+}, 'Application_broadcastTrustedEvent_name_TypeMismatch');
+
+}
+
+function Application_removeEventListener() {
+//==== TEST: Application_removeEventListener
+//==== LABEL Check if method Application::removeEventListener() successfully
+//==== SPEC Tizen Web API:TBD:Application:Application:removeEventListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+setup({timeout: 90000});
+
+var t = async_test('Application_removeEventListener', {timeout: 90000}), app, eventCallback, listenerId, returnValue;
+
+setup_launch(t, APP_BROAD_TEST_APP_ID, function () {
+    eventCallback = t.step_func(function (name, data) {
+        try {
+            returnValue = app.removeEventListener(listenerId);
+            assert_type(returnValue, "undefined", "removeEventListener returns wrong value");
+        } catch (e) {
+            assert_unreached(e.name + ": " + e.message);
+        }
+        setTimeout(function(){
+                       t.done();
+               }, 3000);
+    });
+
+    app = tizen.application.getCurrentApplication();
+    listenerId = app.addEventListener({"appId": APP_BROAD_TEST_APP_ID, "name": APP_BROAD_TEST_EVENT_NAME}, eventCallback);
+    tizen.application.launch(APP_BROAD_TEST_APP_ID);
+});
+
+}
+
+function Application_removeEventListener_exist() {
+//==== TEST: Application_removeEventListener_exist
+//==== LABEL Check if Application::removeEventListener() method exists
+//==== SPEC Tizen Web API:TBD:Application:Application:removeEventListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+var app;
+
+test(function () {
+    app = tizen.application.getCurrentApplication();
+    check_method_exists(app, "removeEventListener");
+}, 'Application_removeEventListener_exist');
+
+}
+
+function EventCallback_notexist() {
+//==== TEST: EventCallback_notexist
+//==== LABEL Check if interface EventCallback exists, it should not.
+//==== SPEC Tizen Web API:TBD:Application:EventCallback:EventCallback U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA CBNIO
+
+test(function () {
+    check_no_interface_object("EventCallback");
+}, 'EventCallback_notexist');
+
+}
+
+function EventCallback_onevent() {
+//==== TEST: EventCallback_onevent
+//==== LABEL Check if EventCallback ondetected is called and if its arguments have proper type
+//==== SPEC Tizen Web API:TBD:Application:EventCallback:onevent M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA CBOA CBT
+
+setup({timeout: 90000});
+
+var t = async_test('EventCallback_onevent', {timeout: 90000}), app, eventCallback, listenerId;
+
+setup_launch(t, APP_BROAD_TEST_APP_ID, function () {
+    eventCallback = t.step_func(function (name, data) {
+        assert_type(name, "object", "name isn't an object");
+        assert_type(data, "object", "data isn't an object");
+        assert_own_property(name, "name", "EventData does not own name property.");
+        app.removeEventListener(listenerId);
+        setTimeout(function(){
+                       t.done();
+               }, 3000);
+    });
+
+    app = tizen.application.getCurrentApplication();
+    listenerId = app.addEventListener({"appId": APP_BROAD_TEST_APP_ID, "name": APP_BROAD_TEST_EVENT_NAME}, eventCallback);
+    tizen.application.launch(APP_BROAD_TEST_APP_ID);
+});
+
+}
+
+function EventData_extend() {
+//==== TEST: EventData_extend
+//==== LABEL Check if instance of EventData can be extended with new property
+//==== SPEC Tizen Web API:TBD:Application:EventData:EventData U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA OBX
+
+setup({timeout: 90000});
+
+var t = async_test('EventData_extend', {timeout: 90000}), app, listener, listenerId;
+
+setup_launch(t, APP_BROAD_TEST_APP_ID, function () {
+    listener = t.step_func(function (name, data) {
+        check_extensibility(data);
+        app.removeEventListener(listenerId);
+        setTimeout(function(){
+                       t.done();
+               }, 3000);
+    });
+
+    app = tizen.application.getCurrentApplication();
+    listenerId = app.addEventListener({"appId": APP_BROAD_TEST_APP_ID, "name": APP_BROAD_TEST_EVENT_NAME}, listener);
+    tizen.application.launch(APP_BROAD_TEST_APP_ID);
+});
+
+}
+
+function EventData_notexist() {
+//==== TEST: EventData_notexist
+//==== LABEL Check if interface EventData exists, it should not.
+//==== SPEC Tizen Web API:TBD:Application:EventData:EventData U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("EventData");
+}, 'EventData_notexist');
+
+}
+
+function EventData_type_attribute() {
+//==== TEST: EventData_type_attribute
+//==== LABEL Check EventData type attribute
+//==== SPEC Tizen Web API:TBD:Application:EventData:type A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ASG AN
+
+setup({timeout: 90000});
+
+var t = async_test('EventData_type_attribute', {timeout: 90000}), app, eventCallback, listenerId;
+
+setup_launch(t, APP_BROAD_TEST_APP_ID, function () {
+    eventCallback = t.step_func(function (name, data) {        
+        check_attribute(data, "type", data.type, "String", "newvalue");
+        app.removeEventListener(listenerId);
+        setTimeout(function(){
+                       t.done();
+               }, 3000);
+    });
+
+    app = tizen.application.getCurrentApplication();
+    listenerId = app.addEventListener({"appId": APP_BROAD_TEST_APP_ID, "name": APP_BROAD_TEST_EVENT_NAME}, eventCallback);
+    tizen.application.launch(APP_BROAD_TEST_APP_ID);
+});
+
+}
+
+function EventData_value_attribute() {
+//==== TEST: EventData_value_attribute
+//==== LABEL Check EventData value attribute
+//==== SPEC Tizen Web API:TBD:Application:EventData:value A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/application.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ASG AN
+
+setup({timeout: 90000});
+
+var t = async_test('EventData_value_attribute', {timeout: 90000}), app, eventCallback, listenerId;
+
+setup_launch(t, APP_BROAD_TEST_APP_ID, function () {
+    eventCallback = t.step_func(function (name, data) {
+        check_attribute(data, "value", data.value, "String", "newvalue");
+        app.removeEventListener(listenerId);
+        setTimeout(function(){
+                       t.done();
+               }, 3000);
+    });
+
+    app = tizen.application.getCurrentApplication();
+
+    listenerId = app.addEventListener({"appId": APP_BROAD_TEST_APP_ID, "name": APP_BROAD_TEST_EVENT_NAME}, eventCallback);
+    tizen.application.launch(APP_BROAD_TEST_APP_ID);
+});
+
+}
+
+
+var moduleName = "tct-application-tizen-tests";
+add_test_case(moduleName, ApplicationCertificate_extend);
+add_test_case(moduleName, ApplicationCertificate_notexist);
+add_test_case(moduleName, ApplicationCertificate_type_attribute);
+add_test_case(moduleName, ApplicationCertificate_value_attribute);
+add_test_case(moduleName, ApplicationContextArraySuccessCallback_notexist);
+add_test_case(moduleName, ApplicationContextArraySuccessCallback_onsuccess);
+add_test_case(moduleName, ApplicationContext_appId_attribute);
+add_test_case(moduleName, ApplicationContext_extend);
+add_test_case(moduleName, ApplicationContext_id_attribute);
+add_test_case(moduleName, ApplicationContext_notexist);
+add_test_case(moduleName, ApplicationControlDataArrayReplyCallback_notexist);
+add_test_case(moduleName, ApplicationControlDataArrayReplyCallback_onfailure);
+add_test_case(moduleName, ApplicationControlDataArrayReplyCallback_onsuccess);
+add_test_case(moduleName, ApplicationControlData_constructor);
+add_test_case(moduleName, ApplicationControlData_exist);
+add_test_case(moduleName, ApplicationControlData_extend);
+add_test_case(moduleName, ApplicationControlData_key_attribute);
+add_test_case(moduleName, ApplicationControlData_value_attribute);
+add_test_case(moduleName, ApplicationControl_category_attribute);
+add_test_case(moduleName, ApplicationControl_constructor);
+add_test_case(moduleName, ApplicationControl_constructor_minargs);
+add_test_case(moduleName, ApplicationControl_data_attribute);
+add_test_case(moduleName, ApplicationControl_exist);
+add_test_case(moduleName, ApplicationControl_extend);
+add_test_case(moduleName, ApplicationControl_mime_attribute);
+add_test_case(moduleName, ApplicationControl_operation_attribute);
+add_test_case(moduleName, ApplicationControl_uri_attribute);
+add_test_case(moduleName, ApplicationInformationArraySuccessCallback_notexist);
+add_test_case(moduleName, ApplicationInformationArraySuccessCallback_onsuccess);
+add_test_case(moduleName, ApplicationInformationEventCallback_notexist);
+add_test_case(moduleName, ApplicationInformation_categories_attribute);
+add_test_case(moduleName, ApplicationInformation_extend);
+add_test_case(moduleName, ApplicationInformation_iconPath_attribute);
+add_test_case(moduleName, ApplicationInformation_id_attribute);
+add_test_case(moduleName, ApplicationInformation_installDate_attribute);
+add_test_case(moduleName, ApplicationInformation_name_attribute);
+add_test_case(moduleName, ApplicationInformation_notexist);
+add_test_case(moduleName, ApplicationInformation_packageId_attribute);
+add_test_case(moduleName, ApplicationInformation_show_attribute);
+add_test_case(moduleName, ApplicationInformation_size_attribute);
+add_test_case(moduleName, ApplicationInformation_version_attribute);
+add_test_case(moduleName, ApplicationManagerObject_notexist);
+add_test_case(moduleName, ApplicationManager_addAppInfoEventListener_eventCallback_TypeMismatch);
+add_test_case(moduleName, ApplicationManager_addAppInfoEventListener_eventCallback_invalid_cb);
+add_test_case(moduleName, ApplicationManager_addAppInfoEventListener_exist);
+add_test_case(moduleName, ApplicationManager_addAppInfoEventListener_missarg);
+add_test_case(moduleName, ApplicationManager_extend);
+add_test_case(moduleName, ApplicationManager_findAppControl);
+add_test_case(moduleName, ApplicationManager_findAppControl_appControl_TypeMismatch);
+add_test_case(moduleName, ApplicationManager_findAppControl_appControl_invalid_obj);
+add_test_case(moduleName, ApplicationManager_findAppControl_errorCallback_TypeMismatch);
+add_test_case(moduleName, ApplicationManager_findAppControl_errorCallback_invalid_cb);
+add_test_case(moduleName, ApplicationManager_findAppControl_exist);
+add_test_case(moduleName, ApplicationManager_findAppControl_missarg);
+add_test_case(moduleName, ApplicationManager_findAppControl_successCallback_TypeMismatch);
+add_test_case(moduleName, ApplicationManager_findAppControl_successCallback_invalid_cb);
+add_test_case(moduleName, ApplicationManager_findAppControl_successCallback_missarg);
+add_test_case(moduleName, ApplicationManager_findAppControl_with_errorCallback);
+add_test_case(moduleName, ApplicationManager_getAppCerts);
+add_test_case(moduleName, ApplicationManager_getAppCerts_exist);
+add_test_case(moduleName, ApplicationManager_getAppCerts_with_id);
+add_test_case(moduleName, ApplicationManager_getAppContext);
+add_test_case(moduleName, ApplicationManager_getAppContext_exist);
+add_test_case(moduleName, ApplicationManager_getAppContext_with_contextId);
+add_test_case(moduleName, ApplicationManager_getAppInfo);
+add_test_case(moduleName, ApplicationManager_getAppInfo_exist);
+add_test_case(moduleName, ApplicationManager_getAppInfo_with_id);
+//add_test_case(moduleName, ApplicationManager_getAppMetaData);
+add_test_case(moduleName, ApplicationManager_getAppMetaData_exist);
+add_test_case(moduleName, ApplicationManager_getAppMetaData_with_id);
+add_test_case(moduleName, ApplicationManager_getAppSharedURI);
+add_test_case(moduleName, ApplicationManager_getAppSharedURI_exist);
+add_test_case(moduleName, ApplicationManager_getAppSharedURI_with_id);
+add_test_case(moduleName, ApplicationManager_getAppsContext);
+add_test_case(moduleName, ApplicationManager_getAppsContext_errorCallback_TypeMismatch);
+add_test_case(moduleName, ApplicationManager_getAppsContext_errorCallback_invalid_cb);
+add_test_case(moduleName, ApplicationManager_getAppsContext_exist);
+add_test_case(moduleName, ApplicationManager_getAppsContext_missarg);
+add_test_case(moduleName, ApplicationManager_getAppsContext_successCallback_TypeMismatch);
+add_test_case(moduleName, ApplicationManager_getAppsContext_successCallback_invalid_cb);
+add_test_case(moduleName, ApplicationManager_getAppsContext_with_errorCallback);
+add_test_case(moduleName, ApplicationManager_getAppsInfo);
+add_test_case(moduleName, ApplicationManager_getAppsInfo_errorCallback_TypeMismatch);
+add_test_case(moduleName, ApplicationManager_getAppsInfo_errorCallback_invalid_cb);
+add_test_case(moduleName, ApplicationManager_getAppsInfo_exist);
+add_test_case(moduleName, ApplicationManager_getAppsInfo_missarg);
+add_test_case(moduleName, ApplicationManager_getAppsInfo_successCallback_TypeMismatch);
+add_test_case(moduleName, ApplicationManager_getAppsInfo_successCallback_invalid_cb);
+add_test_case(moduleName, ApplicationManager_getAppsInfo_with_errorCallback);
+add_test_case(moduleName, ApplicationManager_getCurrentApplication);
+add_test_case(moduleName, ApplicationManager_getCurrentApplication_exist);
+add_test_case(moduleName, ApplicationManager_getCurrentApplication_extra_argument);
+add_test_case(moduleName, ApplicationManager_in_tizen);
+add_test_case(moduleName, ApplicationManager_kill);
+add_test_case(moduleName, ApplicationManager_kill_errorCallback_TypeMismatch);
+add_test_case(moduleName, ApplicationManager_kill_errorCallback_invalid_cb);
+add_test_case(moduleName, ApplicationManager_kill_exist);
+add_test_case(moduleName, ApplicationManager_kill_successCallback_TypeMismatch);
+add_test_case(moduleName, ApplicationManager_kill_successCallback_invalid_cb);
+add_test_case(moduleName, ApplicationManager_kill_with_errorCallback);
+add_test_case(moduleName, ApplicationManager_kill_with_successCallback);
+add_test_case(moduleName, ApplicationManager_launch);
+add_test_case(moduleName, ApplicationManager_launchAppControl_appControl_TypeMismatch);
+add_test_case(moduleName, ApplicationManager_launchAppControl_appControl_invalid_obj);
+add_test_case(moduleName, ApplicationManager_launchAppControl_errorCallback_TypeMismatch);
+add_test_case(moduleName, ApplicationManager_launchAppControl_errorCallback_invalid_cb);
+add_test_case(moduleName, ApplicationManager_launchAppControl_exist);
+add_test_case(moduleName, ApplicationManager_launchAppControl_missarg);
+add_test_case(moduleName, ApplicationManager_launchAppControl_replyCallback_TypeMismatch);
+add_test_case(moduleName, ApplicationManager_launchAppControl_replyCallback_invalid_cb);
+add_test_case(moduleName, ApplicationManager_launchAppControl_successCallback_TypeMismatch);
+add_test_case(moduleName, ApplicationManager_launchAppControl_successCallback_invalid_cb);
+add_test_case(moduleName, ApplicationManager_launchAppControl_with_appControl_operation);
+add_test_case(moduleName, ApplicationManager_launchAppControl_with_appControl_operation_mime);
+add_test_case(moduleName, ApplicationManager_launchAppControl_with_appControl_operation_uri);
+add_test_case(moduleName, ApplicationManager_launchAppControl_with_appControl_operation_uri_mime);
+add_test_case(moduleName, ApplicationManager_launchAppControl_with_errorCallback);
+add_test_case(moduleName, ApplicationManager_launchAppControl_with_id);
+add_test_case(moduleName, ApplicationManager_launchAppControl_with_replyCallback);
+add_test_case(moduleName, ApplicationManager_launchAppControl_with_successCallback);
+add_test_case(moduleName, ApplicationManager_launch_errorCallback_TypeMismatch);
+add_test_case(moduleName, ApplicationManager_launch_errorCallback_invalid_cb);
+add_test_case(moduleName, ApplicationManager_launch_exist);
+add_test_case(moduleName, ApplicationManager_launch_successCallback_TypeMismatch);
+add_test_case(moduleName, ApplicationManager_launch_successCallback_invalid_cb);
+add_test_case(moduleName, ApplicationManager_launch_with_errorCallback);
+add_test_case(moduleName, ApplicationManager_launch_with_successCallback);
+add_test_case(moduleName, ApplicationManager_notexist);
+add_test_case(moduleName, ApplicationManager_removeAppInfoEventListener);
+add_test_case(moduleName, ApplicationManager_removeAppInfoEventListener_exist);
+//add_test_case(moduleName, ApplicationMetaData_extend);
+//add_test_case(moduleName, ApplicationMetaData_key_attribute);
+add_test_case(moduleName, ApplicationMetaData_notexist);
+//add_test_case(moduleName, ApplicationMetaData_value_attribute);
+add_test_case(moduleName, Application_ContextId_attribute);
+add_test_case(moduleName, Application_appInfo_attribute);
+add_test_case(moduleName, Application_exit);
+add_test_case(moduleName, Application_exit_exist);
+add_test_case(moduleName, Application_extend);
+add_test_case(moduleName, Application_getRequestedAppControl);
+add_test_case(moduleName, Application_getRequestedAppControl_exist);
+add_test_case(moduleName, Application_getRequestedAppControl_extra_argument);
+add_test_case(moduleName, Application_hide);
+add_test_case(moduleName, Application_hide_exist);
+add_test_case(moduleName, Application_hide_extra_argument);
+add_test_case(moduleName, Application_notexist);
+add_test_case(moduleName, FindAppControlSuccessCallback_notexist);
+add_test_case(moduleName, FindAppControlSuccessCallback_onsuccess);
+add_test_case(moduleName, RequestedApplicationControl_appControl_attribute);
+add_test_case(moduleName, RequestedApplicationControl_callerAppId_attribute);
+add_test_case(moduleName, RequestedApplicationControl_extend);
+add_test_case(moduleName, RequestedApplicationControl_notexist);
+add_test_case(moduleName, RequestedApplicationControl_replyFailure);
+add_test_case(moduleName, RequestedApplicationControl_replyFailure_exist);
+add_test_case(moduleName, RequestedApplicationControl_replyFailure_extra_argument);
+add_test_case(moduleName, RequestedApplicationControl_replyResult);
+add_test_case(moduleName, RequestedApplicationControl_replyResult_data_TypeMismatch);
+add_test_case(moduleName, RequestedApplicationControl_replyResult_exist);
+add_test_case(moduleName, RequestedApplicationControl_replyResult_with_data);
+/* not supported in tizen 2.3.1
+add_test_case(moduleName, Application_addEventListener);
+add_test_case(moduleName, Application_addEventListener_callback_invalid_cb);
+add_test_case(moduleName, Application_addEventListener_eventCallback_TypeMismatch);
+add_test_case(moduleName, Application_addEventListener_exist);
+add_test_case(moduleName, Application_addEventListener_misarg);
+add_test_case(moduleName, Application_addEventListener_name_TypeMismatch);
+add_test_case(moduleName, Application_broadcastEvent);
+add_test_case(moduleName, Application_broadcastEvent_data_TypeMismatch);
+add_test_case(moduleName, Application_broadcastEvent_exist);
+add_test_case(moduleName, Application_broadcastEvent_misarg);
+add_test_case(moduleName, Application_broadcastEvent_name_TypeMismatch);
+add_test_case(moduleName, Application_broadcastTrustedEvent);
+add_test_case(moduleName, Application_broadcastTrustedEvent_data_TypeMismatch);
+add_test_case(moduleName, Application_broadcastTrustedEvent_exist);
+add_test_case(moduleName, Application_broadcastTrustedEvent_misarg);
+add_test_case(moduleName, Application_broadcastTrustedEvent_name_TypeMismatch);
+add_test_case(moduleName, Application_removeEventListener);
+add_test_case(moduleName, Application_removeEventListener_exist);
+add_test_case(moduleName, EventCallback_notexist);
+add_test_case(moduleName, EventCallback_onevent);
+add_test_case(moduleName, EventData_extend);
+add_test_case(moduleName, EventData_notexist);
+add_test_case(moduleName, EventData_type_attribute);
+add_test_case(moduleName, EventData_value_attribute);
+*/
+
+add_test_case(moduleName, ApplicationInformationEventCallback_oninstalled);
+add_test_case(moduleName, ApplicationInformationEventCallback_onupdated);
+add_test_case(moduleName, ApplicationInformationEventCallback_onuninstalled);
+add_test_case(moduleName, ApplicationManager_addAppInfoEventListener_oninstalled);
+add_test_case(moduleName, ApplicationManager_addAppInfoEventListener_onupdated);
+add_test_case(moduleName, ApplicationManager_addAppInfoEventListener_onuninstalled);
diff --git a/webWidgetTCT_device/test/tct/tests/TestCSS.js b/webWidgetTCT_device/test/tct/tests/TestCSS.js
new file mode 100755 (executable)
index 0000000..3ec6f65
--- /dev/null
@@ -0,0 +1,1415 @@
+/*
+ * Copyright (c) 2012 Intel Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * *Redistributions of works must retain the original copyright notice, this list
+ * of conditions and the following disclaimer.
+ * *Redistributions in binary form must reproduce the original copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * *Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this work without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors:
+ *         Wei Ji <wei.ji@samsung.com>
+ *
+ *         Revision history:
+ *
+ */
+
+var UNKNOWN_ERR         = "UnknownError";
+var TYPE_MISMATCH_ERR   = "TypeMismatchError";
+var IO_ERR              = "IOError";
+var INVALID_VALUES_ERR  = "InvalidValuesError";
+var SECURITY_ERR        = "SecurityError";
+var NOT_FOUND_ERR       = "NotFoundError";
+var NOT_SUPPORT_ERR     = "NotSupportedError";
+
+var APPLICATION_ID = "testcss001.cssTestApp";
+
+var div = document.createElement("div");
+
+function hasStyle(name, styles) {
+    var arr = name.split("-");
+    var nameStr = arr[0];
+    for(i = 1; i < arr.length; i++) {
+        nameStr = nameStr + arr[i][0].toUpperCase() + arr[i].slice(1);
+    }
+    //name without prefix
+    if(nameStr in styles) {
+        return true;
+    }
+    //browser prefixes
+    var prefixes = ["ms", "Moz", "moz", "webkit", "O"];
+    //Uppercase first letter
+    nameStr = nameStr[0].toUpperCase() + nameStr.slice(1);
+    for (i in prefixes) {
+        //name with prefix
+        if ((prefixes[i] + nameStr) in styles) {
+            return true;
+        }
+    }
+    return false;
+}
+
+function Background_background() {
+    test(function () {
+        var p = document.getElementById("backgroundtest1");
+        assert_equals(p.style["backgroundColor"], "rgb(255, 0, 0)", "Background color should be rgb(255, 0, 0).");
+    }, 'Background_background');
+}
+
+function Background_background_color() {
+    test(function () {
+        var p = document.getElementById("backgroundtest2");
+        assert_equals(p.style["backgroundColor"], "rgb(0, 0, 0)", "Background color should be rgb(0, 0, 0).");
+    }, 'Background_background_color');
+}
+
+function Background_background_color_red() {
+    test(function () {
+        var p = document.getElementById("backgroundtest3");
+        assert_equals(p.style["backgroundColor"], "red", "Background color should be red.");
+    }, 'Background_background_color_red');
+}
+
+function Background_background_image() {
+    test(function () {
+        var p = document.getElementById("backgroundtest4");
+        assert_equals(p.style["backgroundImage"], "url(\"icon.png\")", "Background image should be url(\"icon.png\").");
+    }, 'Background_background_image');
+}
+
+function Background_background_image_none() {
+    test(function () {
+        var p = document.getElementById("backgroundtest5");
+        assert_equals(p.style["backgroundImage"], "none", "Background image should be none.");
+    }, 'Background_background_image_none');
+}
+
+function Background_background_repeat() {
+    test(function () {
+        var p = document.getElementById("backgroundtest6");
+        assert_equals(p.style["backgroundRepeat"], "repeat-x", "Background repeat should be repeat-x.");
+    }, 'Background_background_repeat');
+}
+
+function Background_background_repeat_repeat() {
+    test(function () {
+        var p = document.getElementById("backgroundtest7");
+        assert_equals(p.style["backgroundRepeat"], "repeat", "Background repeat should be repeat.");
+    }, 'Background_background_repeat_repeat');
+}
+
+function Background_background_repeat_repeat_y() {
+    test(function () {
+        var p = document.getElementById("backgroundtest8");
+        assert_equals(p.style["backgroundRepeat"], "repeat-y", "Background repeat should be repeat-y.");
+    }, 'Background_background_repeat_repeat_y');
+}
+
+function Background_background_repeat_no_repeat() {
+    test(function () {
+        var p = document.getElementById("backgroundtest9");
+        assert_equals(p.style["backgroundRepeat"], "no-repeat", "Background repeat should be no-repeat.");
+    }, 'Background_background_repeat_no_repeat');
+}
+
+function Background_background_size() {
+    test(function () {
+        var p = document.getElementById("backgroundtest10");
+        assert_equals(p.style["backgroundSize"], "100% 10px", "Background size should be 100% 10px.");
+    }, 'Background_background_size');
+}
+
+function Background_background_size_50pct_no_repeat_url_png() {
+    test(function () {
+        var p = document.getElementById("backgroundtest11");
+        assert_equals(p.style["backgroundSize"], "50%", "Background size should be 50%.");
+        assert_equals(p.style["backgroundRepeat"], "no-repeat", "Background repeat should be no-repeat.");
+        assert_equals(p.style["backgroundImage"], "url(\"icon.png\")", "Background image should be url(\"icon.png\").");
+    }, 'Background_background_size_50pct_no_repeat_url_png');
+}
+
+function Background_background_size_50pct_no_repeat_none() {
+    test(function () {
+        var p = document.getElementById("backgroundtest12");
+        assert_equals(p.style["backgroundSize"], "50%", "Background size should be 50%.");
+        assert_equals(p.style["backgroundRepeat"], "no-repeat", "Background repeat should be no-repeat.");
+        assert_equals(p.style["backgroundImage"], "none", "Background image should be none.");
+    }, 'Background_background_size_50pct_no_repeat_none');
+}
+
+function Background_background_size_50pct_repeat_none() {
+    test(function () {
+        var p = document.getElementById("backgroundtest13");
+        assert_equals(p.style["backgroundSize"], "50%", "Background size should be 50%.");
+        assert_equals(p.style["backgroundRepeat"], "repeat", "Background repeat should be repeat.");
+        assert_equals(p.style["backgroundImage"], "none", "Background image should be none.");
+    }, 'Background_background_size_50pct_repeat_none');
+}
+
+function Background_background_size_50pct_repeat_url_png() {
+    test(function () {
+        var p = document.getElementById("backgroundtest14");
+        assert_equals(p.style["backgroundSize"], "50%", "Background size should be 50%.");
+        assert_equals(p.style["backgroundRepeat"], "repeat", "Background repeat should be repeat.");
+        assert_equals(p.style["backgroundImage"], "url(\"icon.png\")", "Background image should be url(\"icon.png\").");
+    }, 'Background_background_size_50pct_repeat_url_png');
+}
+
+function Background_background_size_50pct_repeat_y_png() {
+    test(function () {
+        var p = document.getElementById("backgroundtest15");
+        assert_equals(p.style["backgroundSize"], "50%", "Background size should be 50%.");
+        assert_equals(p.style["backgroundRepeat"], "repeat-y", "Background repeat should be repeat-y.");
+        assert_equals(p.style["backgroundImage"], "url(\"icon.png\")", "Background image should be url(\"icon.png\").");
+    }, 'Background_background_size_50pct_repeat_y_png');
+}
+
+function Background_background_size_50pct_repeat_y_none() {
+    test(function () {
+        var p = document.getElementById("backgroundtest16");
+        assert_equals(p.style["backgroundSize"], "50%", "Background size should be 50%.");
+        assert_equals(p.style["backgroundRepeat"], "repeat-y", "Background repeat should be repeat-y.");
+        assert_equals(p.style["backgroundImage"], "none", "Background image should be none.");
+    }, 'Background_background_size_50pct_repeat_y_none');
+}
+
+function Background_background_size_50pct_repeat_x_png() {
+    test(function () {
+        var p = document.getElementById("backgroundtest17");
+        assert_equals(p.style["backgroundSize"], "50%", "Background size should be 50%.");
+        assert_equals(p.style["backgroundRepeat"], "repeat-x", "Background repeat should be repeat-x.");
+        assert_equals(p.style["backgroundImage"], "url(\"icon.png\")", "Background image should be url(\"icon.png\").");
+    }, 'Background_background_size_50pct_repeat_x_png');
+}
+
+function Background_background_size_50pct_repeat_x_none() {
+    test(function () {
+        var p = document.getElementById("backgroundtest18");
+        assert_equals(p.style["backgroundSize"], "50%", "Background size should be 50%.");
+        assert_equals(p.style["backgroundRepeat"], "repeat-x", "Background repeat should be repeat-x.");
+        assert_equals(p.style["backgroundImage"], "none", "Background image should be none.");
+    }, 'Background_background_size_50pct_repeat_x_none');
+}
+
+function Background_background_size_50px_70px_no_repeat_none() {
+    test(function () {
+        var p = document.getElementById("backgroundtest19");
+        assert_equals(p.style["backgroundSize"], "50px 70px", "Background size should be 50px 70px.");
+        assert_equals(p.style["backgroundRepeat"], "no-repeat", "Background repeat should be no-repeat.");
+        assert_equals(p.style["backgroundImage"], "none", "Background image should be none.");
+    }, 'Background_background_size_50px_70px_no_repeat_none');
+}
+
+function Background_background_size_50px_70px_no_repeat_png() {
+    test(function () {
+        var p = document.getElementById("backgroundtest20");
+        assert_equals(p.style["backgroundSize"], "50px 70px", "Background size should be 50px 70px.");
+        assert_equals(p.style["backgroundRepeat"], "no-repeat", "Background repeat should be no-repeat.");
+        assert_equals(p.style["backgroundImage"], "url(\"icon.png\")", "Background image should be url(\"icon.png\").");
+    }, 'Background_background_size_50px_70px_no_repeat_png');
+}
+
+function Background_background_size_50px_70px_repeat_none() {
+    test(function () {
+        var p = document.getElementById("backgroundtest21");
+        assert_equals(p.style["backgroundSize"], "50px 70px", "Background size should be 50px 70px.");
+        assert_equals(p.style["backgroundRepeat"], "repeat", "Background repeat should be repeat.");
+        assert_equals(p.style["backgroundImage"], "none", "Background image should be none.");
+    }, 'Background_background_size_50px_70px_repeat_none');
+}
+
+function Background_background_size_50px_70px_repeat_png() {
+    test(function () {
+        var p = document.getElementById("backgroundtest22");
+        assert_equals(p.style["backgroundSize"], "50px 70px", "Background size should be 50px 70px.");
+        assert_equals(p.style["backgroundRepeat"], "repeat", "Background repeat should be repeat.");
+        assert_equals(p.style["backgroundImage"], "url(\"icon.png\")", "Background image should be url(\"icon.png\").");
+    }, 'Background_background_size_50px_70px_repeat_png');
+}
+
+function Background_background_size_50px_70px_repeat_x_none() {
+    test(function () {
+        var p = document.getElementById("backgroundtest23");
+        assert_equals(p.style["backgroundSize"], "50px 70px", "Background size should be 50px 70px.");
+        assert_equals(p.style["backgroundRepeat"], "repeat-x", "Background repeat should be repeat-x.");
+        assert_equals(p.style["backgroundImage"], "none", "Background image should be none.");
+    }, 'Background_background_size_50px_70px_repeat_x_none');
+}
+
+function Background_background_size_50px_70px_repeat_x_png() {
+    test(function () {
+        var p = document.getElementById("backgroundtest24");
+        assert_equals(p.style["backgroundSize"], "50px 70px", "Background size should be 50px 70px.");
+        assert_equals(p.style["backgroundRepeat"], "repeat-x", "Background repeat should be repeat-x.");
+        assert_equals(p.style["backgroundImage"], "url(\"icon.png\")", "Background image should be url(\"icon.png\").");
+    }, 'Background_background_size_50px_70px_repeat_x_png');
+}
+
+function Background_background_size_50px_70px_repeat_y_none() {
+    test(function () {
+        var p = document.getElementById("backgroundtest25");
+        assert_equals(p.style["backgroundSize"], "50px 70px", "Background size should be 50px 70px.");
+        assert_equals(p.style["backgroundRepeat"], "repeat-y", "Background repeat should be repeat-y.");
+        assert_equals(p.style["backgroundImage"], "none", "Background image should be none.");
+    }, 'Background_background_size_50px_70px_repeat_y_none');
+}
+
+function Background_background_size_50px_70px_repeat_y_png() {
+    test(function () {
+        var p = document.getElementById("backgroundtest26");
+        assert_equals(p.style["backgroundSize"], "50px 70px", "Background size should be 50px 70px.");
+        assert_equals(p.style["backgroundRepeat"], "repeat-y", "Background repeat should be repeat-y.");
+        assert_equals(p.style["backgroundImage"], "url(\"icon.png\")", "Background image should be url(\"icon.png\").");
+    }, 'Background_background_size_50px_70px_repeat_y_png');
+}
+
+function Background_background_size_contain_no_repeat_none() {
+    test(function () {
+        var p = document.getElementById("backgroundtest27");
+        assert_equals(p.style["backgroundSize"], "contain", "Background size should be contain.");
+        assert_equals(p.style["backgroundRepeat"], "no-repeat", "Background repeat should be no-repeat.");
+        assert_equals(p.style["backgroundImage"], "none", "Background image should be none.");
+    }, 'Background_background_size_contain_no_repeat_none');
+}
+
+function Background_background_size_contain_no_repeat_png() {
+    test(function () {
+        var p = document.getElementById("backgroundtest28");
+        assert_equals(p.style["backgroundSize"], "contain", "Background size should be contain.");
+        assert_equals(p.style["backgroundRepeat"], "no-repeat", "Background repeat should be no-repeat.");
+        assert_equals(p.style["backgroundImage"], "url(\"icon.png\")", "Background image should be url(\"icon.png\").");
+    }, 'Background_background_size_contain_no_repeat_png');
+}
+
+function Background_background_size_contain_repeat_none() {
+    test(function () {
+        var p = document.getElementById("backgroundtest29");
+        assert_equals(p.style["backgroundSize"], "contain", "Background size should be contain.");
+        assert_equals(p.style["backgroundRepeat"], "repeat", "Background repeat should be repeat.");
+        assert_equals(p.style["backgroundImage"], "none", "Background image should be none.");
+    }, 'Background_background_size_contain_repeat_none');
+}
+
+function Background_background_size_contain_repeat_png() {
+    test(function () {
+        var p = document.getElementById("backgroundtest30");
+        assert_equals(p.style["backgroundSize"], "contain", "Background size should be contain.");
+        assert_equals(p.style["backgroundRepeat"], "repeat", "Background repeat should be repeat.");
+        assert_equals(p.style["backgroundImage"], "url(\"icon.png\")", "Background image should be url(\"icon.png\").");
+    }, 'Background_background_size_contain_repeat_png');
+}
+
+function Background_background_size_contain_repeat_y_none() {
+    test(function () {
+        var p = document.getElementById("backgroundtest31");
+        assert_equals(p.style["backgroundSize"], "contain", "Background size should be contain.");
+        assert_equals(p.style["backgroundRepeat"], "repeat-y", "Background repeat should be repeat-y.");
+        assert_equals(p.style["backgroundImage"], "none", "Background image should be none.");
+    }, 'Background_background_size_contain_repeat_y_none');
+}
+
+function Background_background_size_contain_repeat_y_png() {
+    test(function () {
+        var p = document.getElementById("backgroundtest32");
+        assert_equals(p.style["backgroundSize"], "contain", "Background size should be contain.");
+        assert_equals(p.style["backgroundRepeat"], "repeat-y", "Background repeat should be repeat-y.");
+        assert_equals(p.style["backgroundImage"], "url(\"icon.png\")", "Background image should be url(\"icon.png\").");
+    }, 'Background_background_size_contain_repeat_y_png');
+}
+
+function Background_background_size_cover_repeat_y_none() {
+    test(function () {
+        var p = document.getElementById("backgroundtest33");
+        assert_equals(p.style["backgroundSize"], "cover", "Background size should be cover.");
+        assert_equals(p.style["backgroundRepeat"], "repeat-y", "Background repeat should be repeat-y.");
+        assert_equals(p.style["backgroundImage"], "none", "Background image should be none.");
+    }, 'Background_background_size_cover_repeat_y_none');
+}
+
+function Background_background_size_cover_repeat_y_png() {
+    test(function () {
+        var p = document.getElementById("backgroundtest34");
+        assert_equals(p.style["backgroundSize"], "cover", "Background size should be cover.");
+        assert_equals(p.style["backgroundRepeat"], "repeat-y", "Background repeat should be repeat-y.");
+        assert_equals(p.style["backgroundImage"], "url(\"icon.png\")", "Background image should be url(\"icon.png\").");
+    }, 'Background_background_size_cover_repeat_y_png');
+}
+
+function Background_background_size_cover_repeat_x_none() {
+    test(function () {
+        var p = document.getElementById("backgroundtest35");
+        assert_equals(p.style["backgroundSize"], "cover", "Background size should be cover.");
+        assert_equals(p.style["backgroundRepeat"], "repeat-x", "Background repeat should be repeat-x.");
+        assert_equals(p.style["backgroundImage"], "none", "Background image should be none.");
+    }, 'Background_background_size_cover_repeat_x_none');
+}
+
+function Background_background_size_cover_repeat_x_png() {
+    test(function () {
+        var p = document.getElementById("backgroundtest36");
+        assert_equals(p.style["backgroundSize"], "cover", "Background size should be cover.");
+        assert_equals(p.style["backgroundRepeat"], "repeat-x", "Background repeat should be repeat-x.");
+        assert_equals(p.style["backgroundImage"], "url(\"icon.png\")", "Background image should be url(\"icon.png\").");
+    }, 'Background_background_size_cover_repeat_x_png');
+}
+
+function Background_background_size_cover_no_repeat_none() {
+    test(function () {
+        var p = document.getElementById("backgroundtest37");
+        assert_equals(p.style["backgroundSize"], "cover", "Background size should be cover.");
+        assert_equals(p.style["backgroundRepeat"], "no-repeat", "Background repeat should be no-repeat.");
+        assert_equals(p.style["backgroundImage"], "none", "Background image should be none.");
+    }, 'Background_background_size_cover_no_repeat_none');
+}
+
+function Background_background_size_cover_no_repeat_png() {
+    test(function () {
+        var p = document.getElementById("backgroundtest38");
+        assert_equals(p.style["backgroundSize"], "cover", "Background size should be cover.");
+        assert_equals(p.style["backgroundRepeat"], "no-repeat", "Background repeat should be no-repeat.");
+        assert_equals(p.style["backgroundImage"], "url(\"icon.png\")", "Background image should be url(\"icon.png\").");
+    }, 'Background_background_size_cover_no_repeat_png');
+}
+
+function Padding_padding() {
+    test(function () {
+        var p = document.getElementById("paddingtest1");
+        assert_equals(p.style["paddingTop"], "1px", "Padding top should be 1px.");
+        assert_equals(p.style["paddingRight"], "2px", "Padding right should be 2px.");
+        assert_equals(p.style["paddingBottom"], "3px", "Padding bottom should be 3px.");
+        assert_equals(p.style["paddingLeft"], "4px", "Padding left should be 4px.");
+    }, 'Padding_padding');
+}
+
+function Padding_padding_bottom_length() {
+    test(function () {
+        var p = document.getElementById("paddingtest2");
+        assert_equals(p.style["paddingBottom"], "1px", "Padding bottom should be 1px.");
+    }, 'Padding_padding_bottom_length');
+}
+
+function Padding_padding_left_length() {
+    test(function () {
+        var p = document.getElementById("paddingtest2");
+        assert_equals(p.style["paddingLeft"], "2px", "Padding left should be 2px.");
+    }, 'Padding_padding_left_length');
+}
+
+function Padding_padding_right_length() {
+    test(function () {
+        var p = document.getElementById("paddingtest2");
+        assert_equals(p.style["paddingRight"], "3px", "Padding right should be 3px.");
+    }, 'Padding_padding_right_length');
+}
+
+function Padding_padding_top_length() {
+    test(function () {
+        var p = document.getElementById("paddingtest2");
+        assert_equals(p.style["paddingTop"], "4px", "Padding top should be 4px.");
+    }, 'Padding_padding_top_length');
+}
+
+function Padding_padding_bottom_percentage() {
+    test(function () {
+        var p = document.getElementById("paddingtest3");
+        assert_equals(p.style["paddingBottom"], "10%", "Padding bottom should be 10%.");
+    }, 'Padding_padding_bottom_percentage');
+}
+
+function Padding_padding_left_percentage() {
+    test(function () {
+        var p = document.getElementById("paddingtest3");
+        assert_equals(p.style["paddingLeft"], "20%", "Padding left should be 20%.");
+    }, 'Padding_padding_left_percentage');
+}
+
+function Padding_padding_right_percentage() {
+    test(function () {
+        var p = document.getElementById("paddingtest3");
+        assert_equals(p.style["paddingRight"], "30%", "Padding right should be 30%.");
+    }, 'Padding_padding_right_percentage');
+}
+
+function Padding_padding_top_percentage() {
+    test(function () {
+        var p = document.getElementById("paddingtest3");
+        assert_equals(p.style["paddingTop"], "40%", "Padding top should be 40%.");
+    }, 'Padding_padding_top_percentage');
+}
+
+function Display_display_block() {
+    test(function () {
+        var p = document.getElementById("displaytest1");
+        assert_equals(p.style["display"], "block", "Display should be block.");
+    }, 'Display_display_block');
+}
+
+function Display_visibility_visible() {
+    test(function () {
+        var p = document.getElementById("displaytest1");
+        assert_equals(p.style["visibility"], "visible", "Visibility should be visible.");
+    }, 'Display_visibility_visible');
+}
+
+function Display_display_inline() {
+    test(function () {
+        var p = document.getElementById("displaytest2");
+        assert_equals(p.style["display"], "inline", "Display should be inline.");
+    }, 'Display_display_inline');
+}
+
+function Display_visibility_hidden() {
+    test(function () {
+        var p = document.getElementById("displaytest2");
+        assert_equals(p.style["visibility"], "hidden", "Visibility should be hidden.");
+    }, 'Display_visibility_hidden');
+}
+
+function Positioning_position_static() {
+    test(function () {
+        var p = document.getElementById("positiontest1");
+        assert_equals(p.style["position"], "static", "Position should be static.");
+    }, 'Positioning_position_static');
+}
+
+function Positioning_z_index() {
+    test(function () {
+        var p = document.getElementById("positiontest1");
+        assert_equals(p.style["zIndex"], "auto", "Z-index should be auto.");
+    }, 'Positioning_z_index');
+}
+
+function Positioning_width_length() {
+    test(function () {
+        var p = document.getElementById("positiontest1");
+        assert_equals(p.style["width"], "20px", "Width should be 20px.");
+    }, 'Positioning_width_length');
+}
+
+function Positioning_height_length() {
+    test(function () {
+        var p = document.getElementById("positiontest1");
+        assert_equals(p.style["height"], "30px", "Height should be 30px.");
+    }, 'Positioning_height_length');
+}
+
+function Positioning_top_length() {
+    test(function () {
+        var p = document.getElementById("positiontest2");
+        assert_equals(p.style["top"], "1px", "Top should be 1px.");
+    }, 'Positioning_top_length');
+}
+
+function Positioning_right_length() {
+    test(function () {
+        var p = document.getElementById("positiontest2");
+        assert_equals(p.style["right"], "2px", "Right should be 2px.");
+    }, 'Positioning_right_length');
+}
+
+function Positioning_bottom_length() {
+    test(function () {
+        var p = document.getElementById("positiontest3");
+        assert_equals(p.style["bottom"], "3px", "Bottom should be 3px.");
+    }, 'Positioning_bottom_length');
+}
+
+function Positioning_left_length() {
+    test(function () {
+        var p = document.getElementById("positiontest3");
+        assert_equals(p.style["left"], "4px", "Left should be 4px.");
+    }, 'Positioning_left_length');
+}
+
+function Positioning_direction() {
+    test(function () {
+        var p = document.getElementById("positiontest4");
+        assert_equals(p.style["direction"], "ltr", "Direction should be ltr.");
+    }, 'Positioning_direction');
+}
+
+function Positioning_vertical_align() {
+    test(function () {
+        var p = document.getElementById("positiontest4");
+        assert_equals(p.style["verticalAlign"], "baseline", "Vertical align should be baseline.");
+    }, 'Positioning_vertical_align');
+}
+
+function Positioning_overflow() {
+    test(function () {
+        var p = document.getElementById("positiontest4");
+        assert_equals(p.style["overflow"], "visible", "overflow should be visible.");
+    }, 'Positioning_overflow');
+}
+
+function Positioning_line_height() {
+    test(function () {
+        var p = document.getElementById("positiontest5");
+        assert_equals(p.style["lineHeight"], "2px", "Line height should be 2px.");
+    }, 'Positioning_line_height');
+}
+
+function Margin_margin() {
+    test(function () {
+        var p = document.getElementById("margintest1");
+        assert_equals(p.style["marginTop"], "1px", "Margin top should be 1px.");
+        assert_equals(p.style["marginRight"], "2px", "Margin right should be 2px.");
+        assert_equals(p.style["marginBottom"], "3px", "Margin bottom should be 3px.");
+        assert_equals(p.style["marginLeft"], "4px", "Margin left should be 4px.");
+    }, 'Margin_margin');
+}
+
+function Margin_margin_bottom_length() {
+    test(function () {
+        var p = document.getElementById("margintest2");
+        assert_equals(p.style["marginBottom"], "1px", "Margin bottom should be 1px.");
+    }, 'Margin_margin_bottom_length');
+}
+
+function Margin_margin_left_length() {
+    test(function () {
+        var p = document.getElementById("margintest2");
+        assert_equals(p.style["marginLeft"], "2px", "Margin left should be 2px.");
+    }, 'Margin_margin_left_length');
+}
+
+function Margin_margin_right_length() {
+    test(function () {
+        var p = document.getElementById("margintest2");
+        assert_equals(p.style["marginRight"], "3px", "Margin right should be 3px.");
+    }, 'Margin_margin_right_length');
+}
+
+function Margin_margin_top_length() {
+    test(function () {
+        var p = document.getElementById("margintest2");
+        assert_equals(p.style["marginTop"], "4px", "Margin top should be 4px.");
+    }, 'Margin_margin_top_length');
+}
+
+function Color_color() {
+    test(function () {
+        var p = document.getElementById("colortest1");
+        assert_equals(p.style["color"], "red", "color should be red.");
+    }, 'Color_color');
+}
+
+function Color_opacity() {
+    test(function () {
+        var p = document.getElementById("colortest1");
+        assert_equals(p.style["opacity"], "0.3", "Opacity should be 0.3.");
+    }, 'Color_opacity');
+}
+
+function Text_text_align() {
+    test(function () {
+        var p = document.getElementById("texttest1");
+        assert_equals(p.style["textAlign"], "left", "Text align should be left.");
+    }, 'Text_text_align');
+}
+
+function Text_text_decoration() {
+    test(function () {
+        var p = document.getElementById("texttest1");
+        assert_equals(p.style["textDecoration"], "none", "Text decoration should be none.");
+    }, 'Text_text_decoration');
+}
+
+function Transform_transform() {
+    test(function () {
+        var p = document.getElementById("transformtest1");
+        assert_equals(p.style["transform"], "none", "transform should be none.");
+    }, 'Transform_transform');
+}
+
+function Transform_transform_origin() {
+    test(function () {
+        var p = document.getElementById("transformtest1");
+        assert_equals(p.style["transformOrigin"], "center center 0px", "transform origin should be center center.");
+    }, 'Transform_transform_origin');
+}
+
+function Font_font_style() {
+    test(function () {
+        var p = document.getElementById("fonttest1");
+        assert_equals(p.style["fontStyle"], "oblique", "Font style should be oblique.");
+    }, 'Font_font_style');
+}
+
+function Font_font_size() {
+    test(function () {
+        var p = document.getElementById("fonttest1");
+        assert_equals(p.style["fontSize"], "16px", "Font size should be 16px.");
+    }, 'Font_font_size');
+}
+
+function Font_font_weight() {
+    test(function () {
+        var p = document.getElementById("fonttest1");
+        assert_equals(p.style["fontWeight"], "normal", "Font weight should be normal.");
+    }, 'Font_font_weight');
+}
+
+function Border_bottom_style_solid() {
+    test(function () {
+        var p = document.getElementById("bordertest1");
+        assert_equals(p.style["borderBottomStyle"], "solid", "border bottom style should be solid.");
+    }, 'Border_bottom_style_solid');
+}
+
+function Border_bottom_style_none() {
+    test(function () {
+        var p = document.getElementById("bordertest2");
+        assert_equals(p.style["borderBottomStyle"], "none", "border bottom style should be none.");
+    }, 'Border_bottom_style_none');
+}
+
+function Border_color() {
+    test(function () {
+        var p = document.getElementById("bordertest3");
+        assert_equals(p.style["borderColor"], "rgb(0, 0, 0)", "borderColor should be rgb(0, 0, 0).");
+    }, 'Border_color');
+}
+
+function Border_top_color() {
+    test(function () {
+        var p = document.getElementById("bordertest4");
+        assert_equals(p.style["borderTopColor"], "rgb(85, 85, 85)", "border top Color should be rgb(85, 85, 85).");
+    }, 'Border_top_color');
+}
+
+function Border_right_color() {
+    test(function () {
+        var p = document.getElementById("bordertest5");
+        assert_equals(p.style["borderRightColor"], "rgb(85, 85, 85)", "border right Color should be rgb(85, 85, 85).");
+    }, 'Border_right_color');
+}
+
+function Border_bottom_color() {
+    test(function () {
+        var p = document.getElementById("bordertest6");
+        assert_equals(p.style["borderBottomColor"], "rgb(85, 85, 85)", "border bottom Color should be rgb(85, 85, 85).");
+    }, 'Border_bottom_color');
+}
+
+function Border_left_color() {
+    test(function () {
+        var p = document.getElementById("bordertest7");
+        assert_equals(p.style["borderLeftColor"], "rgb(85, 85, 85)", "border left Color should be rgb(85, 85, 85).");
+    }, 'Border_left_color');
+}
+
+function Border_style() {
+    test(function () {
+        var p = document.getElementById("bordertest8");
+        assert_equals(p.style["borderStyle"], "solid", "border style should be solid.");
+    }, 'Border_style');
+}
+
+function Border_top_style() {
+    test(function () {
+        var p = document.getElementById("bordertest9");
+        assert_equals(p.style["borderTopStyle"], "solid", "border top style should be solid.");
+    }, 'Border_top_style');
+}
+
+function Border_top_style_solid() {
+    test(function () {
+        var p = document.getElementById("bordertest10");
+        assert_equals(p.style["borderTopStyle"], "solid", "border top style should be solid.");
+    }, 'Border_top_style_solid');
+}
+
+function Border_top_style_none() {
+    test(function () {
+        var p = document.getElementById("bordertest11");
+        assert_equals(p.style["borderTopStyle"], "none", "border top style should be none.");
+    }, 'Border_top_style_none');
+}
+
+function Border_right_style() {
+    test(function () {
+        var p = document.getElementById("bordertest12");
+        assert_equals(p.style["borderRightStyle"], "solid", "border right style should be solid.");
+    }, 'Border_right_style');
+}
+
+function Border_right_style_solid() {
+    test(function () {
+        var p = document.getElementById("bordertest13");
+        assert_equals(p.style["borderRightStyle"], "solid", "border right style should be solid.");
+    }, 'Border_right_style_solid');
+}
+
+function Border_right_style_none() {
+    test(function () {
+        var p = document.getElementById("bordertest14");
+        assert_equals(p.style["borderRightStyle"], "none", "border right style should be none.");
+    }, 'Border_right_style_none');
+}
+
+function Border_left_style() {
+    test(function () {
+        var p = document.getElementById("bordertest15");
+        assert_equals(p.style["borderLeftStyle"], "solid", "border left style should be solid.");
+    }, 'Border_left_style');
+}
+
+function Border_left_style_solid() {
+    test(function () {
+        var p = document.getElementById("bordertest16");
+        assert_equals(p.style["borderLeftStyle"], "solid", "border left style should be solid.");
+    }, 'Border_left_style_solid');
+}
+
+function Border_left_style_none() {
+    test(function () {
+        var p = document.getElementById("bordertest17");
+        assert_equals(p.style["borderLeftStyle"], "none", "border left style should be none.");
+    }, 'Border_left_style_none');
+}
+
+function Border_width() {
+    test(function () {
+        var p = document.getElementById("bordertest18");
+        assert_equals(p.style["borderWidth"], "50px", "border width should be 50px.");
+    }, 'Border_width');
+}
+
+function Border_top_width() {
+    test(function () {
+        var p = document.getElementById("bordertest19");
+        assert_equals(p.style["borderTopWidth"], "50px", "border top width should be 50px.");
+    }, 'Border_top_width');
+}
+
+function Border_border() {
+    test(function () {
+        var p = document.getElementById("bordertest3");
+        assert_equals(p.style["border"], "8px solid rgb(0, 0, 0)", "Border should be 8px solid rgb(0, 0, 0).");
+    }, 'Border_border');
+}
+
+function Border_border_top() {
+    test(function () {
+        var p = document.getElementById("bordertest20");
+        assert_equals(p.style["borderTop"], "10px none black", "Border top should be 10px none black.");
+    }, 'Border_border_top');
+}
+
+function Border_border_right() {
+    test(function () {
+        var p = document.getElementById("bordertest20");
+        assert_equals(p.style["borderRight"], "20px none red", "Border right should be 20px none red.");
+    }, 'Border_border_right');
+}
+
+function Border_border_bottom() {
+    test(function () {
+        var p = document.getElementById("bordertest20");
+        assert_equals(p.style["borderBottom"], "30px none blue", "Border bottom should be 30px none blue.");
+    }, 'Border_border_bottom');
+}
+
+function Border_border_left() {
+    test(function () {
+        var p = document.getElementById("bordertest20");
+        assert_equals(p.style["borderLeft"], "40px none green", "Border left should be 40px none green.");
+    }, 'Border_border_left');
+}
+
+function Border_border_right_width() {
+    test(function () {
+        var p = document.getElementById("bordertest21");
+        assert_equals(p.style["borderRightWidth"], "2px", "Border right width should be 2px.");
+    }, 'Border_border_right_width');
+}
+
+function Border_border_bottom_width() {
+    test(function () {
+        var p = document.getElementById("bordertest21");
+        assert_equals(p.style["borderBottomWidth"], "3px", "Border bottom width should be 3px.");
+    }, 'Border_border_bottom_width');
+}
+
+function Border_border_left_width() {
+    test(function () {
+        var p = document.getElementById("bordertest21");
+        assert_equals(p.style["borderLeftWidth"], "4px", "Border left width should be 4px.");
+    }, 'Border_border_left_width');
+}
+
+function Border_border_image_source() {
+    test(function () {
+        var p = document.getElementById("bordertest22");
+        assert_equals(p.style["borderImageSource"], "url(\"icon.png\")", "Border image source should be url(\"icon.png\").");
+    }, 'Border_border_image_source');
+}
+
+function Border_border_image_slice() {
+    test(function () {
+        var p = document.getElementById("bordertest22");
+        assert_equals(p.style["borderImageSlice"], "1", "Border image slice should be 1.");
+    }, 'Border_border_image_slice');
+}
+
+function Border_border_image_width() {
+    test(function () {
+        var p = document.getElementById("bordertest22");
+        assert_equals(p.style["borderImageWidth"], "2px", "Border image width should be 2px.");
+    }, 'Border_border_image_width');
+}
+
+function margin_property_exist() {
+    test(function () {
+        assert_true(hasStyle("margin", div.style), "The margin property exists");
+    }, 'margin_property_exist');
+}
+
+function margin_bottom_property_exist() {
+    test(function () {
+        assert_true(hasStyle("margin-bottom", div.style), "The margin-bottom property exists");
+    }, 'margin_bottom_property_exist');
+}
+
+function margin_left_property_exist() {
+    test(function () {
+        assert_true(hasStyle("margin-left", div.style), "The margin-left property exists");
+    }, 'margin_left_property_exist');
+}
+
+function margin_right_property_exist() {
+    test(function () {
+        assert_true(hasStyle("margin-right", div.style), "The margin-bottom property exists");
+    }, 'margin_right_property_exist');
+}
+
+function margin_top_property_exist() {
+    test(function () {
+        assert_true(hasStyle("margin-top", div.style), "The margin-top property exists");
+    }, 'margin_top_property_exist');
+}
+
+function padding_property_exist() {
+    test(function () {
+        assert_true(hasStyle("padding", div.style), "The padding property exists");
+    }, 'padding_property_exist');
+}
+
+function padding_bottom_property_exist() {
+    test(function () {
+        assert_true(hasStyle("padding-bottom", div.style), "The padding-bottom property exists");
+    }, 'padding_bottom_property_exist');
+}
+
+function padding_left_property_exist() {
+    test(function () {
+        assert_true(hasStyle("padding-left", div.style), "The padding-left property exists");
+    }, 'padding_left_property_exist');
+}
+
+function padding_right_property_exist() {
+    test(function () {
+        assert_true(hasStyle("padding-right", div.style), "The padding-bottom property exists");
+    }, 'padding_right_property_exist');
+}
+
+function padding_top_property_exist() {
+    test(function () {
+        assert_true(hasStyle("padding-top", div.style), "The padding-top property exists");
+    }, 'padding_top_property_exist');
+}
+
+function border_property_exist() {
+    test(function () {
+        assert_true(hasStyle("border", div.style), "The border property exists");
+    }, 'border_property_exist');
+}
+
+function border_top_property_exist() {
+    test(function () {
+        assert_true(hasStyle("border-top", div.style), "The border-top property exists");
+    }, 'border_top_property_exist');
+}
+
+function border_right_property_exist() {
+    test(function () {
+        assert_true(hasStyle("border-right", div.style), "The border-right property exists");
+    }, 'border_right_property_exist');
+}
+
+function border_bottom_property_exist() {
+    test(function () {
+        assert_true(hasStyle("border-bottom", div.style), "The border-bottom property exists");
+    }, 'border_bottom_property_exist');
+}
+
+function border_left_property_exist() {
+    test(function () {
+        assert_true(hasStyle("border-left", div.style), "The border-left property exists");
+    }, 'border_left_property_exist');
+}
+
+function border_color_property_exist() {
+    test(function () {
+        assert_true(hasStyle("border-color", div.style), "The border-color property exists");
+    }, 'border_color_property_exist');
+}
+
+function border_top_color_property_exist() {
+    test(function () {
+        assert_true(hasStyle("border-top-color", div.style), "The border-top-color property exists");
+    }, 'border_top_color_property_exist');
+}
+
+function border_right_color_property_exist() {
+    test(function () {
+        assert_true(hasStyle("border-right-color", div.style), "The border-right-color property exists");
+    }, 'border_right_color_property_exist');
+}
+
+function border_bottom_color_property_exist() {
+    test(function () {
+        assert_true(hasStyle("border-bottom-color", div.style), "The border-bottom-color property exists");
+    }, 'border_bottom_color_property_exist');
+}
+
+function border_left_color_property_exist() {
+    test(function () {
+        assert_true(hasStyle("border-left-color", div.style), "The border-left-color property exists");
+    }, 'border_left_color_property_exist');
+}
+
+function border_style_property_exist() {
+    test(function () {
+        assert_true(hasStyle("border-style", div.style), "The border-style property exists");
+    }, 'border_style_property_exist');
+}
+
+function border_top_style_property_exist() {
+    test(function () {
+        assert_true(hasStyle("border-top-style", div.style), "The border-top-style property exists");
+    }, 'border_top_style_property_exist');
+}
+
+function border_right_style_property_exist() {
+    test(function () {
+        assert_true(hasStyle("border-right-style", div.style), "The border-right-style property exists");
+    }, 'border_right_style_property_exist');
+}
+
+function border_bottom_style_property_exist() {
+    test(function () {
+        assert_true(hasStyle("border-bottom-style", div.style), "The border-bottom-style property exists");
+    }, 'border_bottom_style_property_exist');
+}
+
+function border_left_style_property_exist() {
+    test(function () {
+        assert_true(hasStyle("border-left-style", div.style), "The border-left-style property exists");
+    }, 'border_left_style_property_exist');
+}
+
+function border_width_property_exist() {
+    test(function () {
+        assert_true(hasStyle("border-width", div.style), "The border-width property exists");
+    }, 'border_width_property_exist');
+}
+
+function border_top_width_property_exist() {
+    test(function () {
+        assert_true(hasStyle("border-top-width", div.style), "The border-top-width property exists");
+    }, 'border_top_width_property_exist');
+}
+
+function border_right_width_property_exist() {
+    test(function () {
+        assert_true(hasStyle("border-right-width", div.style), "The border-right-width property exists");
+    }, 'border_right_width_property_exist');
+}
+
+function border_bottom_width_property_exist() {
+    test(function () {
+        assert_true(hasStyle("border-bottom-width", div.style), "The border-bottom-width property exists");
+    }, 'border_bottom_width_property_exist');
+}
+
+function border_left_width_property_exist() {
+    test(function () {
+        assert_true(hasStyle("border-left-width", div.style), "The border-left-width property exists");
+    }, 'border_left_width_property_exist');
+}
+
+function border_image_source_property_exist() {
+    test(function () {
+        assert_true(hasStyle("border-image-source", div.style), "The border-image-source property exists");
+    }, 'border_image_source_property_exist');
+}
+
+function border_image_slice_property_exist() {
+    test(function () {
+        assert_true(hasStyle("border-image-slice", div.style), "The border-image-slice property exists");
+    }, 'border_image_slice_property_exist');
+}
+
+function border_image_width_property_exist() {
+    test(function () {
+        assert_true(hasStyle("border-image-width", div.style), "The border-image-width property exists");
+    }, 'border_image_width_property_exist');
+}
+
+function display_property_exist() {
+    test(function () {
+        assert_true(hasStyle("display", div.style), "The display property exists");
+    }, 'display_property_exist');
+}
+
+function visibility_property_exist() {
+    test(function () {
+        assert_true(hasStyle("visibility", div.style), "The visibility property exists");
+    }, 'visibility_property_exist');
+}
+
+function position_property_exist() {
+    test(function () {
+        assert_true(hasStyle("position", div.style), "The position property exists");
+    }, 'position_property_exist');
+}
+
+function top_property_exist() {
+    test(function () {
+        assert_true(hasStyle("top", div.style), "The top property exists");
+    }, 'top_property_exist');
+}
+
+function right_property_exist() {
+    test(function () {
+        assert_true(hasStyle("right", div.style), "The right property exists");
+    }, 'right_property_exist');
+}
+
+function bottom_property_exist() {
+    test(function () {
+        assert_true(hasStyle("bottom", div.style), "The bottom property exists");
+    }, 'bottom_property_exist');
+}
+
+function left_property_exist() {
+    test(function () {
+        assert_true(hasStyle("left", div.style), "The left property exists");
+    }, 'left_property_exist');
+}
+
+function z_index_property_exist() {
+    test(function () {
+        assert_true(hasStyle("z-index", div.style), "The z-index property exists");
+    }, 'z_index_property_exist');
+}
+
+function direction_property_exist() {
+    test(function () {
+        assert_true(hasStyle("direction", div.style), "The direction property exists");
+    }, 'direction_property_exist');
+}
+
+function width_property_exist() {
+    test(function () {
+        assert_true(hasStyle("width", div.style), "The width property exists");
+    }, 'width_property_exist');
+}
+
+function height_property_exist() {
+    test(function () {
+        assert_true(hasStyle("height", div.style), "The height property exists");
+    }, 'height_property_exist');
+}
+
+function vertical_align_property_exist() {
+    test(function () {
+        assert_true(hasStyle("vertical-align", div.style), "The vertical-align property exists");
+    }, 'vertical_align_property_exist');
+}
+
+function line_height_property_exist() {
+    test(function () {
+        assert_true(hasStyle("line-height", div.style), "The line-height property exists");
+    }, 'line_height_property_exist');
+}
+
+function overflow_property_exist() {
+    test(function () {
+        assert_true(hasStyle("overflow", div.style), "The overflow property exists");
+    }, 'overflow_property_exist');
+}
+
+function color_property_exist() {
+    test(function () {
+        assert_true(hasStyle("color", div.style), "The color property exists");
+    }, 'color_property_exist');
+}
+
+function opacity_property_exist() {
+    test(function () {
+        assert_true(hasStyle("opacity", div.style), "The opacity property exists");
+    }, 'opacity_property_exist');
+}
+
+function background_property_exist() {
+    test(function () {
+        assert_true(hasStyle("background", div.style), "The background property exists");
+    }, 'background_property_exist');
+}
+
+function background_color_property_exist() {
+    test(function () {
+        assert_true(hasStyle("background-color", div.style), "The background-color property exists");
+    }, 'background_color_property_exist');
+}
+
+function background_image_property_exist() {
+    test(function () {
+        assert_true(hasStyle("background-image", div.style), "The background-image property exists");
+    }, 'background_image_property_exist');
+}
+
+function background_repeat_property_exist() {
+    test(function () {
+        assert_true(hasStyle("background-repeat", div.style), "The background-repeat property exists");
+    }, 'background_repeat_property_exist');
+}
+
+function background_size_property_exist() {
+    test(function () {
+        assert_true(hasStyle("background-size", div.style), "The background-size property exists");
+    }, 'background_size_property_exist');
+}
+
+function font_style_property_exist() {
+    test(function () {
+        assert_true(hasStyle("font-style", div.style), "The font-style property exists");
+    }, 'font_style_property_exist');
+}
+
+function font_weight_property_exist() {
+    test(function () {
+        assert_true(hasStyle("font-weight", div.style), "The font-weight property exists");
+    }, 'font_weight_property_exist');
+}
+
+function font_size_property_exist() {
+    test(function () {
+        assert_true(hasStyle("font-size", div.style), "The font-size property exists");
+    }, 'font_size_property_exist');
+}
+
+function text_align_property_exist() {
+    test(function () {
+        assert_true(hasStyle("text-align", div.style), "The text-align property exists");
+    }, 'text_align_property_exist');
+}
+
+function text_decoration_property_exist() {
+    test(function () {
+        assert_true(hasStyle("text-decoration", div.style), "The text-decoration property exists");
+    }, 'text_decoration_property_exist');
+}
+
+function transform_property_exist() {
+    test(function () {
+        assert_true(hasStyle("transform", div.style), "The transform property exists");
+    }, 'transform_property_exist');
+}
+
+function transform_origin_property_exist() {
+    test(function () {
+        assert_true(hasStyle("transform-origin", div.style), "The transform-origin property exists");
+    }, 'transform_origin_property_exist');
+}
+
+
+var moduleName = "tct-css-tests";
+add_test_case(moduleName, Background_background);
+add_test_case(moduleName, Background_background_color);
+add_test_case(moduleName, Background_background_color_red);
+add_test_case(moduleName, Background_background_image);
+add_test_case(moduleName, Background_background_image_none);
+add_test_case(moduleName, Background_background_repeat);
+add_test_case(moduleName, Background_background_repeat_repeat);
+add_test_case(moduleName, Background_background_repeat_repeat_y);
+add_test_case(moduleName, Background_background_repeat_no_repeat);
+add_test_case(moduleName, Background_background_size);
+add_test_case(moduleName, Background_background_size_50pct_no_repeat_url_png);
+add_test_case(moduleName, Background_background_size_50pct_no_repeat_none);
+add_test_case(moduleName, Background_background_size_50pct_repeat_none);
+add_test_case(moduleName, Background_background_size_50pct_repeat_url_png);
+add_test_case(moduleName, Background_background_size_50pct_repeat_y_png);
+add_test_case(moduleName, Background_background_size_50pct_repeat_y_none);
+add_test_case(moduleName, Background_background_size_50pct_repeat_x_png);
+add_test_case(moduleName, Background_background_size_50pct_repeat_x_none);
+add_test_case(moduleName, Background_background_size_50px_70px_no_repeat_none);
+add_test_case(moduleName, Background_background_size_50px_70px_no_repeat_png);
+add_test_case(moduleName, Background_background_size_50px_70px_repeat_none);
+add_test_case(moduleName, Background_background_size_50px_70px_repeat_png);
+add_test_case(moduleName, Background_background_size_50px_70px_repeat_x_none);
+add_test_case(moduleName, Background_background_size_50px_70px_repeat_x_png);
+add_test_case(moduleName, Background_background_size_50px_70px_repeat_y_none);
+add_test_case(moduleName, Background_background_size_50px_70px_repeat_y_png);
+add_test_case(moduleName, Background_background_size_contain_no_repeat_none);
+add_test_case(moduleName, Background_background_size_contain_no_repeat_png);
+add_test_case(moduleName, Background_background_size_contain_repeat_none);
+add_test_case(moduleName, Background_background_size_contain_repeat_png);
+add_test_case(moduleName, Background_background_size_contain_repeat_y_none);
+add_test_case(moduleName, Background_background_size_contain_repeat_y_png);
+add_test_case(moduleName, Background_background_size_cover_repeat_y_none);
+add_test_case(moduleName, Background_background_size_cover_repeat_y_png);
+add_test_case(moduleName, Background_background_size_cover_repeat_x_none);
+add_test_case(moduleName, Background_background_size_cover_repeat_x_png);
+add_test_case(moduleName, Background_background_size_cover_no_repeat_none);
+add_test_case(moduleName, Background_background_size_cover_no_repeat_png);
+add_test_case(moduleName, Padding_padding);
+add_test_case(moduleName, Padding_padding_bottom_length);
+add_test_case(moduleName, Padding_padding_left_length);
+add_test_case(moduleName, Padding_padding_right_length);
+add_test_case(moduleName, Padding_padding_top_length);
+add_test_case(moduleName, Padding_padding_bottom_percentage);
+add_test_case(moduleName, Padding_padding_left_percentage);
+add_test_case(moduleName, Padding_padding_right_percentage);
+add_test_case(moduleName, Padding_padding_top_percentage);
+add_test_case(moduleName, Display_display_block);
+add_test_case(moduleName, Display_visibility_visible);
+add_test_case(moduleName, Display_display_inline);
+add_test_case(moduleName, Display_visibility_hidden);
+add_test_case(moduleName, Positioning_position_static);
+add_test_case(moduleName, Positioning_z_index);
+add_test_case(moduleName, Positioning_width_length);
+add_test_case(moduleName, Positioning_height_length);
+add_test_case(moduleName, Positioning_top_length);
+add_test_case(moduleName, Positioning_right_length);
+add_test_case(moduleName, Positioning_bottom_length);
+add_test_case(moduleName, Positioning_left_length);
+add_test_case(moduleName, Positioning_direction);
+add_test_case(moduleName, Positioning_vertical_align);
+add_test_case(moduleName, Positioning_overflow);
+add_test_case(moduleName, Positioning_line_height);
+add_test_case(moduleName, Margin_margin);
+add_test_case(moduleName, Margin_margin_bottom_length);
+add_test_case(moduleName, Margin_margin_left_length);
+add_test_case(moduleName, Margin_margin_right_length);
+add_test_case(moduleName, Margin_margin_top_length);
+add_test_case(moduleName, Color_color);
+add_test_case(moduleName, Color_opacity);
+add_test_case(moduleName, Text_text_align);
+add_test_case(moduleName, Text_text_decoration);
+add_test_case(moduleName, Transform_transform);
+add_test_case(moduleName, Transform_transform_origin);
+add_test_case(moduleName, Font_font_style);
+add_test_case(moduleName, Font_font_size);
+add_test_case(moduleName, Font_font_weight);
+add_test_case(moduleName, Border_bottom_style_solid);
+add_test_case(moduleName, Border_bottom_style_none);
+add_test_case(moduleName, Border_color);
+add_test_case(moduleName, Border_top_color);
+add_test_case(moduleName, Border_right_color);
+add_test_case(moduleName, Border_bottom_color);
+add_test_case(moduleName, Border_left_color);
+add_test_case(moduleName, Border_style);
+add_test_case(moduleName, Border_top_style);
+add_test_case(moduleName, Border_top_style_solid);
+add_test_case(moduleName, Border_top_style_none);
+add_test_case(moduleName, Border_right_style);
+add_test_case(moduleName, Border_right_style_solid);
+add_test_case(moduleName, Border_right_style_none);
+add_test_case(moduleName, Border_left_style);
+add_test_case(moduleName, Border_left_style_solid);
+add_test_case(moduleName, Border_left_style_none);
+add_test_case(moduleName, Border_width);
+add_test_case(moduleName, Border_top_width);
+add_test_case(moduleName, Border_border);
+add_test_case(moduleName, Border_border_top);
+add_test_case(moduleName, Border_border_right);
+add_test_case(moduleName, Border_border_bottom);
+add_test_case(moduleName, Border_border_left);
+add_test_case(moduleName, Border_border_right_width);
+add_test_case(moduleName, Border_border_bottom_width);
+add_test_case(moduleName, Border_border_left_width);
+add_test_case(moduleName, Border_border_image_source);
+add_test_case(moduleName, Border_border_image_slice);
+add_test_case(moduleName, Border_border_image_width);
+add_test_case(moduleName, margin_property_exist);
+add_test_case(moduleName, margin_bottom_property_exist);
+add_test_case(moduleName, margin_left_property_exist);
+add_test_case(moduleName, margin_right_property_exist);
+add_test_case(moduleName, margin_top_property_exist);
+add_test_case(moduleName, padding_property_exist);
+add_test_case(moduleName, padding_bottom_property_exist);
+add_test_case(moduleName, padding_left_property_exist);
+add_test_case(moduleName, padding_right_property_exist);
+add_test_case(moduleName, padding_top_property_exist);
+add_test_case(moduleName, border_property_exist);
+add_test_case(moduleName, border_top_property_exist);
+add_test_case(moduleName, border_right_property_exist);
+add_test_case(moduleName, border_bottom_property_exist);
+add_test_case(moduleName, border_left_property_exist);
+add_test_case(moduleName, border_color_property_exist);
+add_test_case(moduleName, border_top_color_property_exist);
+add_test_case(moduleName, border_right_color_property_exist);
+add_test_case(moduleName, border_bottom_color_property_exist);
+add_test_case(moduleName, border_left_color_property_exist);
+add_test_case(moduleName, border_style_property_exist);
+add_test_case(moduleName, border_top_style_property_exist);
+add_test_case(moduleName, border_right_style_property_exist);
+add_test_case(moduleName, border_bottom_style_property_exist);
+add_test_case(moduleName, border_left_style_property_exist);
+add_test_case(moduleName, border_width_property_exist);
+add_test_case(moduleName, border_top_width_property_exist);
+add_test_case(moduleName, border_right_width_property_exist);
+add_test_case(moduleName, border_bottom_width_property_exist);
+add_test_case(moduleName, border_left_width_property_exist);
+add_test_case(moduleName, border_image_source_property_exist);
+add_test_case(moduleName, border_image_slice_property_exist);
+add_test_case(moduleName, border_image_width_property_exist);
+add_test_case(moduleName, display_property_exist);
+add_test_case(moduleName, visibility_property_exist);
+add_test_case(moduleName, position_property_exist);
+add_test_case(moduleName, top_property_exist);
+add_test_case(moduleName, right_property_exist);
+add_test_case(moduleName, bottom_property_exist);
+add_test_case(moduleName, left_property_exist);
+add_test_case(moduleName, z_index_property_exist);
+add_test_case(moduleName, direction_property_exist);
+add_test_case(moduleName, width_property_exist);
+add_test_case(moduleName, height_property_exist);
+add_test_case(moduleName, vertical_align_property_exist);
+add_test_case(moduleName, line_height_property_exist);
+add_test_case(moduleName, overflow_property_exist);
+add_test_case(moduleName, color_property_exist);
+add_test_case(moduleName, opacity_property_exist);
+add_test_case(moduleName, background_property_exist);
+add_test_case(moduleName, background_color_property_exist);
+add_test_case(moduleName, background_image_property_exist);
+add_test_case(moduleName, background_repeat_property_exist);
+add_test_case(moduleName, background_size_property_exist);
+add_test_case(moduleName, font_style_property_exist);
+add_test_case(moduleName, font_weight_property_exist);
+add_test_case(moduleName, font_size_property_exist);
+add_test_case(moduleName, text_align_property_exist);
+add_test_case(moduleName, text_decoration_property_exist);
+add_test_case(moduleName, transform_property_exist);
+add_test_case(moduleName, transform_origin_property_exist);
\ No newline at end of file
diff --git a/webWidgetTCT_device/test/tct/tests/TestContent.js b/webWidgetTCT_device/test/tct/tests/TestContent.js
new file mode 100755 (executable)
index 0000000..57786c2
--- /dev/null
@@ -0,0 +1,9773 @@
+/*
+
+Copyright (c) 2013 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+
+
+Authors:
+        Krzysztof Lachacz <k.lachacz@samsung.com>
+        Junghyuk Park <junghyuk.park@samsung.com>
+*/
+
+var TIMEOUT_ASYNC_TEST = 30000;
+setup({timeout: TIMEOUT_ASYNC_TEST});
+
+var SHARED_STORAGE_PATH = "/home/owner/share";
+var TEST_CONTENT_DIR_PATH = "/home/owner/share/tct-content-tizen-tests/";
+
+var TEST_CONTENT_IMAGES = [
+    "tct-content-tizen-tests_image_default.jpg",
+    "tct-content-tizen-tests_image_geolocation.jpg",
+    "tct-content-tizen-tests_image_orientation_1.jpg",
+    "tct-content-tizen-tests_image_orientation_2.jpg",
+    "tct-content-tizen-tests_image_orientation_3.jpg",
+    "tct-content-tizen-tests_image_orientation_4.jpg",
+    "tct-content-tizen-tests_image_orientation_5.jpg",
+    "tct-content-tizen-tests_image_orientation_6.jpg",
+    "tct-content-tizen-tests_image_orientation_7.jpg",
+    "tct-content-tizen-tests_image_orientation_8.jpg"
+]
+
+var TEST_CONTENT_AUDIOS = [
+    "tct-content-tizen-tests_audio_default.mp3",
+    "tct-content-tizen-tests_audio_lyrics.mp3",
+    "tct-content-tizen-tests_audio_no_tag.mp3"
+]
+
+var TEST_CONTENT_VIDEOS = [
+    "tct-content-tizen-tests_video.mp4",
+    "tct-content-tizen-tests_video_tagged.mp4"
+]
+
+function setup_contents(async_test, onscaned) {
+    var contents = [];
+    contents = contents.concat(TEST_CONTENT_IMAGES);
+    contents = contents.concat(TEST_CONTENT_AUDIOS);
+    contents = contents.concat(TEST_CONTENT_VIDEOS);
+
+    function scanFiles(files, oncompleted) {
+        var file = files.shift();
+
+        tizen.content.scanFile(
+            "file://"+TEST_CONTENT_DIR_PATH+file,
+            async_test.step_func(function (content) {
+                if (files.length) {
+                    scanFiles(files, oncompleted);
+                } else {
+                    oncompleted();
+                }
+            }),
+            async_test.step_func(function (error) {
+                assert_unreached("setup_contents fails: " + error.name + " with message: " + error.message);
+            })
+        );
+    }
+
+    scanFiles(contents, onscaned);
+}
+
+function check_content_object(content) {
+    assert_type(content.editableAttributes, "array", "editableAttributes should be an array");
+    assert_type(content.id, "string", "id should be a string");
+    assert_type(content.name, "string", "name shoud be a string");
+    assert_type(content.type, "string", "type should be a string");
+    assert_type(content.mimeType, "string", "mimeType should be a string");
+    assert_type(content.title, "string", "title should be a string");
+    assert_type(content.contentURI, "string", "contentURI should be a string");
+    assert_type(content.size, "number", "size should be a number");
+    assert_type(content.rating, "number", "rating should be a number");
+    if(content.thumbnailURIs !== null) {
+        assert_type(content.thumbnailURIs, "array", "thumbnailURIs should be an array");
+    }
+    if(content.releaseDate !== null) {
+        assert_type(content.releaseDate, "date", "releaseDate should be a date");
+    }
+    if(content.modifiedDate !== null) {
+        assert_type(content.modifiedDate, "date", "modifiedDate should be a date");
+    }
+    if(content.description !== null) {
+        assert_type(content.description, "string", "description should be a string");
+    }
+}
+
+function prepare_file_for_scan(addedImagePath, onCopySuccess, t) {
+    var onCopyError = t.step_func(function (error) {
+        assert_unreached("Failed to copy a file to " + addedImagePath + " with message: " + error.message);
+    });
+
+    var copyContentFile = t.step_func(function () {
+        tizen.filesystem.resolve(
+            "file://" + TEST_CONTENT_DIR_PATH,
+            function (contentDirectory){
+                contentDirectory.copyTo(TEST_CONTENT_DIR_PATH + TEST_CONTENT_IMAGES[0], addedImagePath, true, onCopySuccess, onCopyError);
+            },
+            function (error) {
+                assert_unreached("Failed to resolve a directory: " + error.message);
+            },
+            "r"
+        );
+    });
+
+    var onDeleteSuccess = t.step_func(function () {
+        tizen.content.scanFile("file://" + addedImagePath, function (){
+            copyContentFile();
+        });
+    });
+
+    var onDeleteError = t.step_func(function () {
+        copyContentFile();
+    });
+
+    tizen.filesystem.resolve(
+        "file://" + SHARED_STORAGE_PATH,
+        function (directory){
+            var sharedDirectory = directory;
+            sharedDirectory.deleteFile(addedImagePath, onDeleteSuccess, onDeleteError);
+        },
+        function (error) {
+            assert_unreached("Failed to resolve a directory: " + error.message);
+        },
+        "rw"
+    );
+}
+
+function randomString(len) {
+    len = len || 32;
+    var $chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678';
+    var maxPos = $chars.length;
+    var pwd = '';
+    var i;
+    for (i = 0; i < len; i++) {
+        pwd += $chars.charAt(Math.floor(Math.random() * maxPos));
+    }
+    return pwd;
+}
+
+function ContentManagerObject_content_exist() {
+//==== TEST: ContentManagerObject_content_exist
+//==== LABEL Check if content attribute exists
+//==== SPEC Tizen Web API:Content:Content:ContentManager:ContentManager U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA OBME
+test(function () {
+    assert_true("content" in tizen, "ContentManagerObject should have content attribute");
+}, 'ContentManagerObject_content_exist');
+
+}
+
+function ContentManager_updateBatch_exist() {
+//==== TEST: ContentManager_updateBatch_exist
+//==== LABEL Check if updateBatch exists
+//==== SPEC Tizen Web API:Content:Content:ContentManager:updateBatch M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA ME
+test(function () {
+    assert_true("updateBatch" in tizen.content, "ContentManager should have updateBatch method");
+    check_method_exists(tizen.content, "updateBatch");
+}, 'ContentManager_updateBatch_exist');
+
+}
+
+function ContentManager_update_exist() {
+//==== TEST: ContentManager_update_exist
+//==== LABEL Check if update exists
+//==== SPEC Tizen Web API:Content:Content:ContentManager:update M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA ME
+test(function () {
+    assert_true("update" in tizen.content, "ContentManager should have update method");
+    check_method_exists(tizen.content, "update");
+}, 'ContentManager_update_exist');
+
+}
+
+function ContentManager_getDirectories_exist() {
+//==== TEST: ContentManager_getDirectories_exist
+//==== LABEL Check if getDirectories method exists
+//==== SPEC Tizen Web API:Content:Content:ContentManager:getDirectories M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA ME
+test(function () {
+    assert_true("getDirectories" in tizen.content, "ContentManager has getDirectories method");
+    check_method_exists(tizen.content, "getDirectories");
+}, 'ContentManager_getDirectories_exist');
+
+}
+
+function ContentManager_find_exist() {
+//==== TEST: ContentManager_find_exist
+//==== LABEL Check if find exists
+//==== SPEC Tizen Web API:Content:Content:ContentManager:find M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA ME
+test(function () {
+    assert_true("find" in tizen.content, "ContentManager should have find method");
+    check_method_exists(tizen.content, "find");
+}, 'ContentManager_find_exist');
+
+}
+
+function ContentManager_find() {
+//==== TEST: ContentManager_find
+//==== LABEL Check if ContentManager find method with optional error callback is invoked properly
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentManager:find M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA MOA MR
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_find', {timeout: 30000}),
+    successCallback, errorCallback, retVal = null;
+
+t.step(function () {
+    successCallback = t.step_func(function (contents) {
+        assert_equals(retVal, undefined, "find should return undefined");
+        t.done();
+    });
+
+    errorCallback = t.step_func(function (error) {
+        assert_unreached("Find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    retVal = tizen.content.find(successCallback, errorCallback);
+});
+
+}
+
+function ContentManager_getDirectories() {
+//==== TEST: ContentManager_getDirectories
+//==== LABEL Check if ContentManager getDirectories method with only non-optional arguments is invoked properly
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentManager:getDirectories M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA MMINA MR
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_getDirectories', {timeout: 30000}),
+    successCallback, returnedValue = null;
+
+t.step(function () {
+    successCallback = t.step_func(function (directories) {
+        assert_type(directories, "array", "directories should be an array");
+        assert_greater_than(directories.length, 0, "directories item is not found");
+        assert_equals(returnedValue, undefined,
+            "getDirectories should return undefined.");
+        t.done();
+    });
+
+    returnedValue = tizen.content.getDirectories(successCallback);
+});
+
+}
+
+function ContentManager_update() {
+//==== TEST: ContentManager_update
+//==== LABEL Check if update() method works properly
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentManager:update M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA MAST MMINA MR
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_update', {timeout: 30000}),
+    expected, updated = null, returnedValue = null,
+    successCallback, errorCallback, onSuccess, onError, i;
+
+setup_contents(t, t.step_func(function () {
+    onSuccess = t.step_func(function (contents) {
+        assert_equals(contents.length, 1, "updated media item should be found.");
+        assert_equals(contents[0].rating, expected, "rating should be updated.");
+        assert_equals(returnedValue, undefined,
+            "update should return undefined.");
+        t.done();
+    });
+
+    onError = t.step_func(function (error) {
+        assert_unreached("find has an error: " + error.name + " with message: " + error.message);
+    });
+
+    successCallback = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0 , "Media item should be found.");
+        for (i = 0; i < contents.length; i++) {
+            if (contents[i].editableAttributes.indexOf("rating") >= 0) {
+                updated = contents[i];
+                break;
+            }
+        }
+        assert_not_equals(updated, null, "File with editable 'rating' attribute not found");
+
+        expected = (updated.rating + 1) % 10;
+        updated.rating = expected;
+        returnedValue = tizen.content.update(updated);
+        tizen.content.find(onSuccess, onError, null, new tizen.AttributeFilter("id", "EXACTLY", updated.id));
+    });
+    errorCallback = t.step_func(function (error) {
+        assert_unreached("find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.find(successCallback, errorCallback, null);
+}));
+
+}
+
+function ContentManager_updateBatch() {
+//==== TEST: ContentManager_updateBatch
+//==== LABEL Check if updateBatch() method works properly
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentManager:updateBatch M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA MAST MOA MR
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_updateBatch', {timeout: 30000}), updated = [], expected = {}, i, returnedValue = null,
+    findAfterEditSuccess, findAfterEditError, updateError, findSuccess, findError,
+    filter;
+
+setup_contents(t, t.step_func(function () {
+    findAfterEditSuccess = t.step_func(function (contents) {
+        assert_equals(returnedValue, undefined,
+            "updateBatch should return undefined.");
+        assert_type(contents, "array", "contents should be an array");
+        assert_equals(contents.length, 2, "Media items after edit not found");
+        assert_equals(contents[0].rating, expected[contents[0].id], "rating should be changed");
+        assert_equals(contents[1].rating, expected[contents[1].id], "rating should be changed");
+        t.done();
+    });
+
+    findAfterEditError = t.step_func(function (error) {
+        assert_unreached("find() (after updateBatch()) error callback was invoked: " +
+            error.name + " msg: " + error.message);
+    });
+
+    updateError = t.step_func(function (error) {
+        assert_unreached("updateBatch() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    findSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 1, "Media item should be found.");
+        for (i = 0; i < contents.length; i++) {
+            if (contents[i].editableAttributes.indexOf("rating") >= 0) {
+                updated.push(contents[i]);
+            }
+        }
+        assert_greater_than(contents.length, 1,
+            "At least two media items with editable 'rating' attribute are needed");
+
+        updated[0].rating = (updated[0].rating + 1) % 10;
+        expected[updated[0].id] =  updated[0].rating;
+
+        updated[1].rating = (updated[1].rating + 1) % 10;
+        expected[updated[1].id] =  updated[1].rating;
+
+        returnedValue = tizen.content.updateBatch(updated, function () {
+            filter = new tizen.CompositeFilter("UNION", [
+                new tizen.AttributeFilter("id", "EXACTLY", updated[0].id),
+                new tizen.AttributeFilter("id", "EXACTLY", updated[1].id)
+            ]);
+
+            tizen.content.find(findAfterEditSuccess, findAfterEditError, null, filter);
+        }, updateError);
+    });
+
+    findError = t.step_func(function (error) {
+        assert_unreached("find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.find(findSuccess, findError);
+}));
+
+}
+
+function Content_type_AUDIO() {
+//==== TEST: Content_type_AUDIO
+//==== LABEL Check if Content type value is AUDIO for find method with filter AUDIO
+//==== PRIORITY P3
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:Content:Content U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA
+
+setup({timeout: 30000});
+
+var t = async_test('Content_type_AUDIO', {timeout: 30000}),
+    filter = new tizen.AttributeFilter("type", "EXACTLY", "AUDIO"),
+    onSuccess, onError, expected = "AUDIO";
+
+setup_contents(t, t.step_func(function () {
+    onSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "media item is not found");
+
+        assert_equals(contents[0].type, expected, "type value shpuld be AUDIO");
+        t.done();
+    });
+
+    onError = t.step_func(function (error) {
+        assert_unreached("Find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.find(onSuccess, onError, null, filter);
+}));
+
+}
+
+function ContentManager_update_description() {
+//==== TEST: ContentManager_update_description
+//==== LABEL Check if update() properly updates description attribute of first found item
+//==== PRIORITY P1
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentManager:update M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA MAST MMINA
+
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_update_description', {timeout: 30000}),
+    successCallback, errorCallback, onSuccess,
+    expected = Math.random().toFixed(10),
+    filter = new tizen.AttributeFilter("description", "EXACTLY", expected),
+    typeFilter = new tizen.AttributeFilter("type", "EXACTLY", "IMAGE"),
+    updated = null, i;
+
+setup_contents(t, t.step_func(function () {
+    successCallback = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "Media item should be found.");
+
+        for(i = 0; i < contents.length; i ++) {
+            if (contents[i].editableAttributes.indexOf("description") >= 0) {
+                contents[i].description = expected;
+                updated = contents[i];
+            }
+        }
+
+        if (updated === null) {
+            assert_unreached("Files do not contain editable 'description' attribute");
+        }
+
+        updated.description = expected;
+        tizen.content.update(updated);
+        tizen.content.find(onSuccess, errorCallback, null, filter);
+    });
+
+    errorCallback = t.step_func(function (error) {
+        assert_unreached("find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    onSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "Media item should be found.");
+        assert_equals(contents[0].description, expected, "update content description");
+        t.done();
+    });
+
+    tizen.content.find(successCallback, errorCallback, null, typeFilter);
+}));
+
+}
+
+function ContentManager_updateBatch_description() {
+//==== TEST: ContentManager_updateBatch_description
+//==== LABEL Check if updateBatch() method updates properly description of found content
+//==== PRIORITY P1
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentManager:updateBatch M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA MAST MOA
+
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_updateBatch_description', {timeout: 30000}),
+    successCallback, errorCallback, onSuccess, onError, successCB,
+    expected = Math.random().toFixed(10),
+    desFilter = new tizen.AttributeFilter("description", "EXACTLY", expected),
+    findFilter = new tizen.AttributeFilter("type", "EXACTLY", "IMAGE"),
+    compFilter = new tizen.CompositeFilter("INTERSECTION", [findFilter, desFilter]),
+    updated = [], i;
+
+setup_contents(t, t.step_func(function () {
+
+    successCB = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_equals(contents.length, 1, "Media item should be found.");
+        assert_equals(contents[0].description, expected, "update contents description");
+        t.done();
+    });
+
+    onSuccess = t.step_func(function () {
+        tizen.content.find(successCB, errorCallback, null, compFilter);
+    });
+    onError = t.step_func(function (error) {
+        assert_unreached("updateBatch() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    successCallback = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "Media item should be found.");
+
+        for(i = 0; i < contents.length; i++) {
+            if (contents[i].editableAttributes.indexOf("description") >= 0) {
+                contents[i].description = expected;
+                updated.push(contents[i]);
+                break;
+            }
+        }
+
+        if (updated.length === 0) {
+            assert_unreached("File does not contain editable 'description' attribute");
+        }
+
+        tizen.content.updateBatch(updated, onSuccess, onError);
+    });
+    errorCallback = t.step_func(function (error) {
+        assert_unreached("find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.find(successCallback, errorCallback, null, findFilter);
+}));
+
+}
+
+function Content_type_IMAGE() {
+//==== TEST: Content_type_IMAGE
+//==== LABEL Check if Content type value is IMAGE for find method with filter IMAGE
+//==== PRIORITY P3
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:Content:Content U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA
+
+setup({timeout: 30000});
+
+var t = async_test('Content_type_IMAGE', {timeout: 30000}),
+    filter = new tizen.AttributeFilter("type", "EXACTLY", "IMAGE"),
+    onSuccess, onError, expected = "IMAGE";
+
+setup_contents(t, t.step_func(function () {
+    onSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "media item is not found");
+
+        assert_equals(contents[0].type, expected, "type value should be IMAGE");
+        t.done();
+    });
+
+    onError = t.step_func(function (error) {
+        assert_unreached("Find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.find(onSuccess, onError, null, filter);
+}));
+
+}
+
+function Content_type_VIDEO() {
+//==== TEST: Content_type_VIDEO
+//==== LABEL Check if Content type value is VIDEO for find method with filter VIDEO
+//==== PRIORITY P3
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:Content:Content U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA
+
+setup({timeout: 30000});
+
+var t = async_test('Content_type_VIDEO', {timeout: 30000}),
+    filter = new tizen.AttributeFilter("type", "EXACTLY", "VIDEO"),
+    onSuccess, onError, expected = "VIDEO";
+
+setup_contents(t, t.step_func(function () {
+    onSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "media item is not found");
+
+        assert_equals(contents[0].type, expected, "type value should be VIDEO");
+        t.done();
+    });
+
+    onError = t.step_func(function (error) {
+        assert_unreached("Find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.find(onSuccess, onError, null, filter);
+}));
+
+}
+
+function ContentManager_find_nullableArgs() {
+//==== TEST: ContentManager_find_nullableArgs
+//==== LABEL Check if Content find method performs successCallback when all optional arguments are null
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentManager:find M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA MMINA
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_find_nullableArgs', {timeout: 30000}),
+    successCallback;
+
+t.step(function () {
+    successCallback = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "media item is not found");
+
+        t.done();
+    });
+
+    tizen.content.find(successCallback, null, null, null, null, null, null);
+});
+
+}
+
+function VideoContent_notexist() {
+//==== TEST: VideoContent_notexist
+//==== LABEL Check if VideoContent cannot be called in new expression and as a function or in new expression
+//==== PRIORITY P3
+//==== SPEC Tizen Web API:Content:Content:VideoContent:VideoContent U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA NIO
+test(function () {
+    check_no_interface_object("VideoContent");
+}, 'VideoContent_notexist');
+
+}
+
+function Content_notexist() {
+//==== TEST: Content_notexist
+//==== LABEL Check if Content cannot be called in new expression and as a function or in new expression
+//==== PRIORITY P3
+//==== SPEC Tizen Web API:Content:Content:Content:Content U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA NIO
+test(function () {
+    check_no_interface_object("Content");
+}, 'Content_notexist');
+
+}
+
+function ImageContent_notexist() {
+//==== TEST: ImageContent_notexist
+//==== LABEL Check if ImageContent cannot be called in new expression and as a function or in new expression
+//==== PRIORITY P3
+//==== SPEC Tizen Web API:Content:Content:ImageContent:ImageContent U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA NIO
+test(function () {
+    check_no_interface_object("ImageContent");
+}, 'ImageContent_notexist');
+
+}
+
+function ContentDirectoryArraySuccessCallback_notexist() {
+//==== TEST: ContentDirectoryArraySuccessCallback_notexist
+//==== LABEL Check if ContentDirectoryArraySuccessCallback cannot be called in new expression and as a function or in new expression
+//==== PRIORITY P3
+//==== SPEC Tizen Web API:Content:Content:ContentDirectoryArraySuccessCallback:ContentDirectoryArraySuccessCallback U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA CBNIO
+test(function () {
+    check_no_interface_object("ContentDirectoryArraySuccessCallback");
+}, 'ContentDirectoryArraySuccessCallback_notexist');
+
+}
+
+function ContentScanSuccessCallback_notexist() {
+//==== TEST: ContentScanSuccessCallback_notexist
+//==== LABEL Check if ContentScanSuccessCallback cannot be called in new expression and as a function or in new expression
+//==== PRIORITY P3
+//==== SPEC Tizen Web API:Content:Content:ContentScanSuccessCallback:ContentScanSuccessCallback U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA CBNIO
+test(function () {
+    check_no_interface_object("ContentScanSuccessCallback");
+}, 'ContentScanSuccessCallback_notexist');
+
+}
+
+function ContentManager_notexist() {
+//==== TEST: ContentManager_notexist
+//==== LABEL Check if ContentManager cannot be called in new expression and as a function or in new expression
+//==== PRIORITY P3
+//==== SPEC Tizen Web API:Content:Content:ContentManager:ContentManager U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA NIO
+test(function () {
+    check_no_interface_object("ContentManager");
+}, 'ContentManager_notexist');
+
+}
+
+function ContentManager_extend() {
+//==== TEST: ContentManager_extend
+//==== LABEL Check if content object can have new properties added
+//==== PRIORITY P3
+//==== SPEC Tizen Web API:Content:Content:ContentManager:ContentManager U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA OBX
+test(function () {
+    check_extensibility(tizen.content);
+}, 'ContentManager_extend');
+
+}
+
+function ContentManager_update_missarg() {
+//==== TEST: ContentManager_update_missarg
+//==== LABEL Check if update method called with missing non-optional argument throws an exception
+//==== SPEC Tizen Web API:Content:Content:ContentManager:update M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA MMA
+test(function () {
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        tizen.content.update();
+    }, "update() invoked without non-optional arguments.");
+}, 'ContentManager_update_missarg');
+
+}
+
+function ContentManager_update_content_TypeMismatch() {
+//==== TEST: ContentManager_update_content_TypeMismatch
+//==== LABEL Check if update throws exception when content is incorrect
+//==== PRIORITY: P2
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentManager:update M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA MC
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_update_content_TypeMismatch', {timeout: 30000}),
+    exceptionName = "TypeMismatchError", conversionTable, i, content;
+
+t.step(function () {
+    conversionTable = getTypeConversionExceptions("object", false);
+
+    for(i = 0; i < conversionTable.length; i++) {
+        content = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+
+        assert_throws({name: exceptionName},
+            function () {
+                tizen.content.update(content);
+            }, "update() invoked with incorrect content.");
+    }
+
+    t.done();
+});
+
+}
+
+function ContentManager_updateBatch_missarg() {
+//==== TEST: ContentManager_updateBatch_missarg
+//==== LABEL Check if updateBatch method called with missing non-optional argument throws an exception
+//==== SPEC Tizen Web API:Content:Content:ContentManager:updateBatch M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA MMA
+test(function () {
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        tizen.content.updateBatch();
+    }, "UpdateBatch was invoked without non-optional argumenents");
+}, 'ContentManager_updateBatch_missarg');
+
+}
+
+function ContentManager_updateBatch_contents_TypeMismatch() {
+//==== TEST: ContentManager_updateBatch_contents_TypeMismatch
+//==== LABEL Check if updateBatch throws exception when contents is incorrect
+//==== PRIORITY: P2
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentManager:updateBatch M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA MC
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_updateBatch_contents_TypeMismatch', {timeout: 30000}),
+    exceptionName = "TypeMismatchError", conversionTable, i, contents;
+
+t.step(function () {
+    conversionTable = getTypeConversionExceptions("array", false);
+
+    for(i = 0; i < conversionTable.length; i++) {
+        contents = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+
+        assert_throws({name: exceptionName},
+            function () {
+                tizen.content.update(contents);
+            }, "Given incorrect contents.");
+    }
+
+    t.done();
+});
+
+}
+
+function ContentManager_updateBatch_successCallback_TypeMismatch() {
+//==== TEST: ContentManager_updateBatch_successCallback_TypeMismatch
+//==== LABEL Check if updateBatch throws exception when successCallback is incorrect
+//==== PRIORITY: P2
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentManager:updateBatch M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA MC
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_updateBatch_successCallback_TypeMismatch', {timeout: 30000}),
+    conversionTable, successCallback, exceptionName, i;
+
+t.step(function () {
+    conversionTable = getTypeConversionExceptions("functionObject", true);
+
+    for(i = 0; i < conversionTable.length; i++) {
+        successCallback = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+
+        assert_throws({name: exceptionName},
+            function () {
+                tizen.content.updateBatch([], successCallback);
+            }, "Given incorrect successCallback.");
+    }
+
+    t.done();
+});
+
+}
+
+function ContentManager_updateBatch_successCallback_invalid_cb() {
+//==== TEST: ContentManager_updateBatch_successCallback_invalid_cb
+//==== LABEL Check if updateBatch throws exception when success callback is invalid
+//==== PRIORITY: P2
+//==== SPEC Tizen Web API:Content:Content:ContentManager:updateBatch M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA MTCB
+test(function () {
+    var exceptionName = "TypeMismatchError", incorrectCallback;
+
+    incorrectCallback = {
+        onsuccess: function (items) {
+            assert_unreached("Invalid successCallback invoked.");
+        }
+    };
+
+    assert_throws({name: exceptionName},
+        function () {
+            tizen.content.updateBatch([], incorrectCallback);
+        }, "Given invalid successCallback.");
+
+}, 'ContentManager_updateBatch_successCallback_invalid_cb');
+
+}
+
+function ContentManager_updateBatch_errorCallback_TypeMismatch() {
+//==== TEST: ContentManager_updateBatch_errorCallback_TypeMismatch
+//==== LABEL Check if updateBatch throws exception when errorCallback is incorrect
+//==== PRIORITY: P2
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentManager:updateBatch M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA MC
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_updateBatch_errorCallback_TypeMismatch', {timeout: 30000}),
+    conversionTable, successCallback, errorCallback, exceptionName, i;
+
+t.step(function () {
+    successCallback = t.step_func(function () {
+        assert_unreached("updateBatch() success callback should not be invoked.");
+    });
+
+    conversionTable = getTypeConversionExceptions("functionObject", true);
+    for(i = 0; i < conversionTable.length; i++) {
+        errorCallback = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+
+        assert_throws({name: exceptionName},
+            function () {
+                tizen.content.updateBatch([], successCallback, errorCallback);
+            }, "Given incorrect errorCallback.");
+    }
+
+    t.done();
+});
+
+}
+
+function ContentManager_updateBatch_errorCallback_invalid_cb() {
+//==== TEST: ContentManager_updateBatch_errorCallback_invalid_cb
+//==== LABEL Check if updateBatch throws exception when errorCallback is invalid
+//==== PRIORITY: P2
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentManager:updateBatch M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA MTCB
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_updateBatch_errorCallback_invalid_cb', {timeout: 30000}),
+    exceptionName = "TypeMismatchError", successCallback, incorrectCallback;
+
+t.step(function () {
+
+    incorrectCallback = {
+        onerror: t.step_func(function (error) {
+            assert_unreached("Invalid errorCallback invoked:" + error.name + " msg: " + error.message);
+        })
+    };
+
+    successCallback = t.step_func(function () {
+        assert_unreached("updateBatch() success callback should not be invoked.");
+    });
+
+    assert_throws({name: exceptionName},
+        function () {
+            tizen.content.updateBatch([], successCallback, incorrectCallback);
+        }, "Given incorrect errorCallback.");
+
+    t.done();
+});
+
+}
+
+function ContentManager_getDirectories_missarg() {
+//==== TEST: ContentManager_getDirectories_missarg
+//==== LABEL Check if getDirectories method called with missing non-optional argument throws an exception
+//==== SPEC Tizen Web API:Content:Content:ContentManager:getDirectories M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA MMA
+test(function () {
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        tizen.content.getDirectories();
+    }, "Invoked without non-optional arguments.");
+}, 'ContentManager_getDirectories_missarg');
+
+}
+
+function ContentManager_getDirectories_successCallback_invalid_cb() {
+//==== TEST: ContentManager_getDirectories_successCallback_invalid_cb
+//==== LABEL Check if getDirectories throws exception when success callback is incorrect
+//==== PRIORITY: P2
+//==== SPEC Tizen Web API:Content:Content:ContentManager:getDirectories M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA MTCB
+test(function () {
+    var exceptionName = "TypeMismatchError", incorrectCallback;
+
+    incorrectCallback = {
+        onsuccess: function (items) {
+            assert_unreached("Invalid getDirectories() success callback invoked.");
+        }
+    };
+
+    assert_throws({name: exceptionName},
+        function () {
+            tizen.content.getDirectories(incorrectCallback);
+        }, "Given incorrect successCallback.");
+
+}, 'ContentManager_getDirectories_successCallback_invalid_cb');
+
+}
+
+function ContentManager_getDirectories_successCallback_TypeMismatch() {
+//==== TEST: ContentManager_getDirectories_successCallback_TypeMismatch
+//==== LABEL Check if getDirectories throws exception when successCallback is invalid
+//==== PRIORITY: P2
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentManager:getDirectories M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA MC
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_getDirectories_successCallback_TypeMismatch', {timeout: 30000}),
+    conversionTable, successCallback, exceptionName, i;
+
+t.step(function () {
+    conversionTable = getTypeConversionExceptions("functionObject", true);
+
+    for(i = 0; i < conversionTable.length; i++) {
+        successCallback = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+
+        assert_throws({name: exceptionName},
+            function () {
+                tizen.content.getDirectories(successCallback);
+            }, "Given incorrect successCallback.");
+    }
+
+    t.done();
+});
+
+}
+
+function ContentManager_getDirectories_errorCallback_TypeMismatch() {
+//==== TEST: ContentManager_getDirectories_errorCallback_TypeMismatch
+//==== LABEL Check if getDirectories throws exception when errorCallback is incorrect
+//==== PRIORITY: P2
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentManager:getDirectories M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA MC
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_getDirectories_errorCallback_TypeMismatch', {timeout: 30000}),
+    conversionTable, successCallback, errorCallback, exceptionName, i;
+
+t.step(function () {
+    conversionTable = getTypeConversionExceptions("functionObject", true);
+
+    successCallback = t.step_func(function () {
+        assert_unreached("getDirectories() success callback should not be invoked.");
+    });
+
+    for(i = 0; i < conversionTable.length; i++) {
+        errorCallback = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+
+        assert_throws({name: exceptionName},
+            function () {
+                tizen.content.getDirectories(successCallback, errorCallback);
+            }, "Given incorrect errorCallback.");
+    }
+
+    t.done();
+});
+
+}
+
+function ContentManager_getDirectories_errorCallback_invalid_cb() {
+//==== TEST: ContentManager_getDirectories_errorCallback_invalid_cb
+//==== LABEL Check if getDirectories throws exception when errorCallback is invalid
+//==== PRIORITY: P2
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentManager:getDirectories M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA MTCB
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_getDirectories_errorCallback_invalid_cb', {timeout: 30000}),
+    exceptionName = "TypeMismatchError", successCallback, incorrectCallback;
+
+t.step(function () {
+
+    incorrectCallback = {
+        onerror: t.step_func(function (error) {
+            assert_unreached("Invalid getDirectories() error callback invoked:" + error.name + ": " + error.message);
+        })
+    };
+
+    successCallback = t.step_func(function () {
+        assert_unreached("getDirectories() success callback should not be invoked.");
+    });
+
+    assert_throws({name: exceptionName},
+        function () {
+            tizen.content.getDirectories(successCallback, incorrectCallback);
+        }, "Given invalid errorCallback.");
+
+    t.done();
+});
+
+}
+
+function ContentManager_find_missarg() {
+//==== TEST: ContentManager_find_missarg
+//==== LABEL Check if find method called with missing non-optional argument throws an exception
+//==== SPEC Tizen Web API:Content:Content:ContentManager:find M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA MMA
+test(function () {
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        tizen.content.find();
+    }, "Invoked with non-optional arguments.");
+}, 'ContentManager_find_missarg');
+
+}
+
+function ContentManager_find_successCallback_TypeMismatch() {
+//==== TEST: ContentManager_find_successCallback_TypeMismatch
+//==== LABEL Check if find throws exception when successCallback is incorrect
+//==== PRIORITY: P2
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentManager:find M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA MC
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_find_successCallback_TypeMismatch', {timeout: 30000}),
+    conversionTable, successCallback, exceptionName, i;
+
+t.step(function () {
+    conversionTable = getTypeConversionExceptions("functionObject", true);
+
+    for(i = 0; i < conversionTable.length; i++) {
+        successCallback = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+
+        assert_throws({name: exceptionName},
+            function () {
+                tizen.content.find(successCallback);
+            }, "Given incorrect success callback.");
+    }
+
+    t.done();
+});
+
+}
+
+function ContentManager_find_successCallback_invalid_cb() {
+//==== TEST: ContentManager_find_successCallback_invalid_cb
+//==== LABEL Check if find throws exception when success callback is invalid
+//==== PRIORITY: P2
+//==== SPEC Tizen Web API:Content:Content:ContentManager:find M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA MTCB
+test(function () {
+    var exceptionName = "TypeMismatchError", incorrectCallback;
+
+    incorrectCallback = {
+        onsuccess: function (items) {
+            assert_unreached("Invalid success callback invoked.");
+        }
+    };
+
+    assert_throws({name: exceptionName},
+        function () {
+            tizen.content.find(incorrectCallback);
+        }, "Given invalid successCallback.");
+
+}, 'ContentManager_find_successCallback_invalid_cb');
+
+}
+
+function ContentManager_find_errorCallback_TypeMismatch() {
+//==== TEST: ContentManager_find_errorCallback_TypeMismatch
+//==== LABEL Check if find throws exception when errorCallback is incorrect
+//==== PRIORITY: P2
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentManager:find M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA MC
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_find_errorCallback_TypeMismatch', {timeout: 30000}),
+    conversionTable, successCallback, errorCallback, exceptionName, i;
+
+t.step(function () {
+    conversionTable = getTypeConversionExceptions("functionObject", true);
+
+    successCallback = t.step_func(function () {
+        assert_unreached("find() success callback should not be invoked.");
+    });
+
+    for(i = 0; i < conversionTable.length; i++) {
+        errorCallback = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+
+        assert_throws({name: exceptionName},
+            function () {
+                tizen.content.find(successCallback, errorCallback);
+            }, "Given incorrect error callback.");
+    }
+
+    t.done();
+});
+
+}
+
+function ContentManager_find_errorCallback_invalid_cb() {
+//==== TEST: ContentManager_find_errorCallback_invalid_cb
+//==== LABEL Check if find throws exception when errorCallback is invalid
+//==== PRIORITY: P2
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentManager:find M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA MTCB
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_find_errorCallback_invalid_cb', {timeout: 30000}),
+    exceptionName = "TypeMismatchError", successCallback, incorrectCallback;
+
+t.step(function () {
+
+    incorrectCallback = {
+        onerror: t.step_func(function (error) {
+            assert_unreached("Invalid error callback invoked:" + error.name + ": " + error.message);
+        })
+    };
+
+    successCallback = t.step_func(function () {
+        assert_unreached("find() success callback should not be invoked.");
+    });
+
+    assert_throws({name: exceptionName},
+        function () {
+            tizen.content.find(successCallback, incorrectCallback);
+        }, "Given incorrect errorCallback.");
+
+    t.done();
+});
+
+}
+
+function ContentManager_scanFile_exist() {
+//==== TEST: ContentManager_scanFile_exist
+//==== LABEL Check if scanFile method exists
+//==== SPEC Tizen Web API:Content:Content:ContentManager:scanFile M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA ME
+test(function () {
+    assert_true("scanFile" in tizen.content, "ContentManager should have scanFile method");
+    check_method_exists(tizen.content, "scanFile");
+}, 'ContentManager_scanFile_exist');
+
+}
+
+function ContentManager_scanFile_successCallback_TypeMismatch() {
+//==== TEST: ContentManager_scanFile_successCallback_TypeMismatch
+//==== LABEL Check if scanFile throws exception when successCallback is invalid
+//==== PRIORITY: P2
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentManager:scanFile M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA MC
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_scanFile_successCallback_TypeMismatch', {timeout: 30000}),
+    conversionTable, successCallback, exceptionName, i;
+
+t.step(function () {
+    conversionTable = getTypeConversionExceptions("functionObject", true);
+
+    for(i = 0; i < conversionTable.length; i++) {
+        successCallback = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+
+        assert_throws({name: exceptionName},
+            function () {
+                tizen.content.scanFile("", successCallback);
+            }, "Given invalid successCallback.");
+    }
+
+    t.done();
+});
+
+}
+
+function ContentManager_scanFile_successCallback_invalid_cb() {
+//==== TEST: ContentManager_scanFile_successCallback_invalid_cb
+//==== LABEL Check if scanFile throws exception when success callback is incorrect
+//==== PRIORITY: P2
+//==== SPEC Tizen Web API:Content:Content:ContentManager:scanFile M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA MTCB
+test(function () {
+    var exceptionName = "TypeMismatchError", incorrectCallback;
+
+    incorrectCallback = {
+        onsuccess: function (items) {
+            assert_unreached("Invalid scanFile() success callback invoked.");
+        }
+    };
+
+    assert_throws({name: exceptionName},
+        function () {
+            tizen.content.scanFile("", incorrectCallback);
+        }, "Given incorrect successCallback.");
+
+}, 'ContentManager_scanFile_successCallback_invalid_cb');
+
+}
+
+function ContentManager_scanFile_errorCallback_TypeMismatch() {
+//==== TEST: ContentManager_scanFile_errorCallback_TypeMismatch
+//==== LABEL Check if scanFile throws exception when errorCallback is invalid
+//==== PRIORITY: P2
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentManager:scanFile M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA MC
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_scanFile_errorCallback_TypeMismatch', {timeout: 30000}),
+    conversionTable, successCallback, errorCallback, exceptionName, i;
+
+t.step(function () {
+    conversionTable = getTypeConversionExceptions("functionObject", true);
+
+    successCallback = t.step_func(function () {
+        assert_unreached("scanFile() success callback should not be invoked.");
+    });
+
+    for(i = 0; i < conversionTable.length; i++) {
+        errorCallback = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+
+        assert_throws({name: exceptionName},
+            function () {
+                tizen.content.scanFile(successCallback, errorCallback);
+            }, "Given invalid errorCallback.");
+    }
+
+    t.done();
+});
+
+}
+
+function ContentManager_scanFile_errorCallback_invalid_cb() {
+//==== TEST: ContentManager_scanFile_errorCallback_invalid_cb
+//==== LABEL Check if scanFile throws exception when errorCallback is incorrect
+//==== PRIORITY: P2
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentManager:scanFile M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA MTCB
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_scanFile_errorCallback_invalid_cb', {timeout: 30000}),
+    exceptionName = "TypeMismatchError", successCallback, incorrectCallback;
+
+t.step(function () {
+
+    incorrectCallback = {
+        onerror: t.step_func(function (error) {
+            assert_unreached("Invalid scanFile() errorCallback invoked:" + error.name + ": " + error.message);
+        })
+    };
+
+    successCallback = t.step_func(function () {
+        assert_unreached("scanFile() success callback should not be invoked.");
+    });
+
+    assert_throws({name: exceptionName},
+        function () {
+            tizen.content.scanFile(successCallback, incorrectCallback);
+        }, "Given incorrect errorCallback.");
+
+    t.done();
+});
+
+}
+
+function ContentManager_setChangeListener_exist() {
+//==== TEST: ContentManager_setChangeListener_exist
+//==== LABEL Check if setChangeListener exists
+//==== SPEC Tizen Web API:Content:Content:ContentManager:setChangeListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA ME
+test(function () {
+    assert_true("setChangeListener" in tizen.content,
+        "ContentManager should have setChangeListener method");
+    check_method_exists(tizen.content, "setChangeListener");
+}, 'ContentManager_setChangeListener_exist');
+
+}
+
+function ContentArraySuccessCallback_notexist() {
+//==== TEST: ContentArraySuccessCallback_notexist
+//==== LABEL Check if ContentArraySuccessCallback cannot be called in new expression and as a function or in new expression
+//==== PRIORITY P3
+//==== SPEC Tizen Web API:Content:Content:ContentArraySuccessCallback:ContentArraySuccessCallback U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA CBNIO
+test(function () {
+    check_no_interface_object("ContentArraySuccessCallback");
+}, 'ContentArraySuccessCallback_notexist');
+
+}
+
+function ContentDirectory_notexist() {
+//==== TEST: ContentDirectory_notexist
+//==== LABEL Check if ContentDirectory cannot be called in new expression and as a function or in new expression
+//==== PRIORITY P3
+//==== SPEC Tizen Web API:Content:Content:ContentDirectory:ContentDirectory U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA NIO
+test(function () {
+    check_no_interface_object("ContentDirectory");
+}, 'ContentDirectory_notexist');
+
+}
+
+function ContentChangeCallback_notexist() {
+//==== TEST: ContentChangeCallback_notexist
+//==== LABEL Check if ContentChangeCallback cannot be called in new expression and as a function or in new expression
+//==== PRIORITY P3
+//==== SPEC Tizen Web API:Content:Content:ContentChangeCallback:ContentChangeCallback U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA CBNIO
+test(function () {
+    check_no_interface_object("ContentChangeCallback");
+}, 'ContentChangeCallback_notexist');
+
+}
+
+function AudioContentLyrics_notexist() {
+//==== TEST: AudioContentLyrics_notexist
+//==== LABEL Check if AudioContentLyrics cannot be called in new expression and as a function or in new expression
+//==== PRIORITY P3
+//==== SPEC Tizen Web API:Content:Content:AudioContentLyrics:AudioContentLyrics U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA NIO
+test(function () {
+    check_no_interface_object("AudioContentLyrics");
+}, 'AudioContentLyrics_notexist');
+
+}
+
+function AudioContent_notexist() {
+//==== TEST: AudioContent_notexist
+//==== LABEL Check if AudioContent cannot be called in new expression and as a function or in new expression
+//==== PRIORITY P3
+//==== SPEC Tizen Web API:Content:Content:AudioContent:AudioContent U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA NIO
+test(function () {
+    check_no_interface_object("AudioContent");
+}, 'AudioContent_notexist');
+
+}
+
+function ContentManager_setChangeListener_missarg() {
+//==== TEST: ContentManager_setChangeListener_missarg
+//==== LABEL Check if setChangeListener method called with missing non-optional argument throws an exception
+//==== SPEC Tizen Web API:Content:Content:ContentManager:setChangeListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA MMA
+test(function () {
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        tizen.content.setChangeListener();
+    }, "Invoked without non-optional arguments.");
+}, 'ContentManager_setChangeListener_missarg');
+
+}
+
+function ContentManager_setChangeListener_changeCallback_TypeMismatch() {
+//==== TEST: ContentManager_setChangeListener_changeCallback_TypeMismatch
+//==== LABEL Check if setChangeListener throws exception when changeCallback is incorrect
+//==== PRIORITY: P2
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentManager:setChangeListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA MC
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_setChangeListener_changeCallback_TypeMismatch', {timeout: 30000}),
+    conversionTable, changeCallback, exceptionName, i;
+
+t.step(function () {
+    conversionTable = getTypeConversionExceptions("object", false);
+
+    for(i = 0; i < conversionTable.length; i++) {
+        changeCallback = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+
+        assert_throws({name: exceptionName},
+            function () {
+                tizen.content.setChangeListener(changeCallback);
+            }, "Given incorrect changeCallback.");
+    }
+    t.done();
+});
+
+}
+
+function ContentManager_setChangeListener_changeCallback_invalid_cb() {
+//==== TEST: ContentManager_setChangeListener_changeCallback_invalid_cb
+//==== LABEL Check if setChangeListener throws exception when changeCallback is invalid listener
+//==== PRIORITY: P2
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentManager:setChangeListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA MTL
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_setChangeListener_changeCallback_invalid_cb', {timeout: 30000}),
+    exceptionName, incorrectListeners, i, changeCallback;
+
+t.step(function () {
+    incorrectListeners = getListenerConversionExceptions(["oncontentadded",
+        "oncontentupdated", "oncontentremoved"]);
+    for(i = 0; i < incorrectListeners.length; i++) {
+        changeCallback  = incorrectListeners[i][0];
+        exceptionName = incorrectListeners[i][1];
+        assert_throws({name: exceptionName},
+            function () {
+                tizen.content.setChangeListener(changeCallback);
+            }, "Given invalid changeCallback.");
+    }
+    t.done();
+});
+
+}
+
+function ContentManager_unsetChangeListener_exist() {
+//==== TEST: ContentManager_unsetChangeListener_exist
+//==== LABEL Check if unsetChangeListener exists
+//==== SPEC Tizen Web API:Content:Content:ContentManager:unsetChangeListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA ME
+test(function () {
+    assert_true("unsetChangeListener" in tizen.content,
+        "ContentManager should have unsetChangeListener method");
+    check_method_exists(tizen.content, "unsetChangeListener");
+}, 'ContentManager_unsetChangeListener_exist');
+
+}
+
+function ImageContent_extend() {
+//==== TEST: ImageContent_extend
+//==== LABEL Check if ImageContent can have new properties added
+//==== PRIORITY P3
+//==== ONLOAD_DELAY 30
+//==== SPEC: Tizen Web API:Content:Content:ImageContent:ImageContent U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA OBX
+setup({timeout: 30000});
+
+var t = async_test('ImageContent_extend', {timeout: 30000}),
+    filter, onSuccess, onError, content;
+
+setup_contents(t, t.step_func(function () {
+    filter = new tizen.AttributeFilter("type", "EXACTLY", "IMAGE");
+
+    onError = t.step_func(function (error) {
+        assert_unreached("Find() Error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    onSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "media item is not found");
+
+        content = contents[0];
+        check_extensibility(content);
+        t.done();
+    });
+
+    tizen.content.find(onSuccess, onError, null, filter);
+}));
+
+}
+
+function ImageContent_geolocation_attribute() {
+//==== TEST: ImageContent_geolocation_attribute
+//==== LABEL Check if ImageContent have geolocation attribute with proper type and is writeable
+//==== ONLOAD_DELAY 30
+//==== SPEC: Tizen Web API:Content:Content:ImageContent:geolocation A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA AE AT ASG
+setup({timeout: 30000});
+
+var t = async_test('ImageContent_geolocation_attribute', {timeout: 30000}),
+    onSuccess, onError, filter, geolocation, i, geolocationExist = false;
+
+setup_contents(t, t.step_func(function () {
+    filter = new tizen.AttributeFilter("type", "EXACTLY", "IMAGE");
+
+    onError = t.step_func(function (error) {
+        assert_unreached("Find() Error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    onSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "media item is not found");
+
+        for(i = 0; i < contents.length; i++) {
+            assert_own_property(contents[i], "geolocation",
+                "Content does not own modifiedDate property.");
+
+            geolocation = new tizen.SimpleCoordinates(5, 5);
+            if (contents[i].geolocation !== null) {
+                assert_true(contents[i].geolocation instanceof tizen.SimpleCoordinates,
+                    "SoundContent.geolocation should be an instance of SimpleCoordinates");
+                if (contents[i].geolocation.latitude === 5) {
+                    geolocation.latitude = 6;
+                }
+                if (contents[i].geolocation.longitude === 5) {
+                    geolocation.longitude = 6;
+                }
+                geolocationExist = true;
+            }
+            contents[i].geolocation = geolocation;
+
+            assert_equals(contents[i].geolocation.latitude, geolocation.latitude,
+                "Value of SoundContent.geolocation.latitude should be updated.");
+            assert_equals(contents[i].geolocation.longitude, geolocation.longitude,
+                "Value of SoundContent.geolocation.latitude should be updated.");
+        }
+        assert_true(geolocationExist, "Image with geolocation doesn't exist.");
+
+        t.done();
+    });
+
+    tizen.content.find(onSuccess, onError, null, filter);
+}));
+
+}
+
+function ImageContent_width_attribute() {
+//==== TEST: ImageContent_width_attribute
+//==== LABEL Check if ImageContent have width attribute with proper type, and is readonly
+//==== ONLOAD_DELAY 30
+//==== SPEC: Tizen Web API:Content:Content:ImageContent:width A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA AE AT ARO
+setup({timeout: 30000});
+
+var t = async_test('ImageContent_width_attribute', {timeout: 30000}),
+    onSuccess, onError, filter, content;
+
+setup_contents(t, t.step_func(function () {
+    filter = new tizen.AttributeFilter("type", "EXACTLY", "IMAGE");
+
+    onError = t.step_func(function (error) {
+        assert_unreached("Find() Error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    onSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "media item is not found");
+
+        content = contents[0];
+        check_readonly(content, "width", content.width, "number", 100);
+
+        t.done();
+    });
+
+    tizen.content.find(onSuccess, onError, null, filter);
+}));
+
+}
+
+function ImageContent_height_attribute() {
+//==== TEST: ImageContent_height_attribute
+//==== LABEL Check if ImageContent have height attribute with proper type and is readonly
+//==== ONLOAD_DELAY 30
+//==== SPEC: Tizen Web API:Content:Content:ImageContent:height A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA AE AT ARO
+setup({timeout: 30000});
+
+var t = async_test('ImageContent_height_attribute', {timeout: 30000}),
+    onSuccess, onError, filter, content;
+
+setup_contents(t, t.step_func(function () {
+    filter = new tizen.AttributeFilter("type", "EXACTLY", "IMAGE");
+
+    onError = t.step_func(function (error) {
+        assert_unreached("Find() Error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    onSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "media item is not found");
+
+        content = contents[0];
+        check_readonly(content, "height", content.height, "number", 100);
+
+        t.done();
+    });
+
+    tizen.content.find(onSuccess, onError, null, filter);
+}));
+
+}
+
+function ImageContent_orientation_attribute() {
+//==== TEST: ImageContent_orientation_attribute
+//==== LABEL Check if ImageContent have orientation attribute with proper type is writeable and not nullable
+//==== ONLOAD_DELAY 30
+//==== SPEC: Tizen Web API:Content:Content:ImageContent:orientation A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA AE AT ASG AN
+setup({timeout: 30000});
+
+var t = async_test('ImageContent_orientation_attribute', {timeout: 30000}),
+    onSuccess, onError, filter, i, newValue,
+    imageContentOrientation = [
+        "NORMAL", "FLIP_HORIZONTAL", "ROTATE_180", "FLIP_VERTICAL", "TRANSPOSE", "ROTATE_90", "TRANSVERSE", "ROTATE_270"
+    ];
+
+setup_contents(t, t.step_func(function () {
+    filter = new tizen.AttributeFilter("type", "EXACTLY", "IMAGE");
+
+    onError = t.step_func(function (error) {
+        assert_unreached("Find() Error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    onSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "media item is not found");
+
+        for(i = 0; i < contents.length; i++) {
+            newValue = imageContentOrientation[(imageContentOrientation.indexOf(contents[i].orientation) + 1) % imageContentOrientation.length];
+            check_attribute(contents[i], "orientation", contents[i].orientation, "string", newValue);
+            assert_in_array(contents[i].orientation, imageContentOrientation, "invalid enum value");
+            contents[i].orientation = null;
+            assert_equals(contents[i].orientation, newValue,
+                "ImageContent.orientation should not accept null as value.");
+        }
+
+        t.done();
+    });
+
+    tizen.content.find(onSuccess, onError, null, filter);
+}));
+
+}
+
+function ContentDirectoryArraySuccessCallback_onsuccess() {
+//==== TEST: ContentDirectoryArraySuccessCallback_onsuccess
+//==== LABEL Check if ContentDirectoryArraySuccessCallback onsuccess is called and if its arguments have proper type
+//==== ONLOAD_DELAY 30
+//==== SPEC: Tizen Web API:Content:Content:ContentDirectoryArraySuccessCallback:onsuccess M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA CBT CBOA
+setup({timeout: 30000});
+
+var t = async_test('ContentDirectoryArraySuccessCallback_onsuccess', {timeout: 30000}),
+    onSuccess, onError, directory;
+
+t.step(function () {
+    onSuccess = t.step_func(function (directories) {
+        assert_type(directories, "array", "directories should be an array");
+        assert_greater_than(directories.length, 0, "directories were not found");
+
+        directory = directories[0];
+        assert_type(directory.id, "string", "id should be a string");
+        assert_type(directory.directoryURI, "string", "directoryURI should be a string");
+        assert_type(directory.title, "string", "title should be a string");
+        assert_type(directory.storageType, "string", "storageType should be a string");
+
+        if(directories.modifiedDate !== null) {
+            assert_type(directory.modifiedDate, "date", "modifiedDate should be a date");
+        }
+
+        t.done();
+    });
+    onError = t.step_func(function (error) {
+        assert_unreached("getDirectories() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.getDirectories(onSuccess, onError);
+});
+
+}
+
+function ContentScanSuccessCallback_onsuccess() {
+//==== TEST: ContentScanSuccessCallback_onsuccess
+//==== LABEL Check if ContentScanSuccessCallback onsuccess is called and if its arguments have proper type
+//==== ONLOAD_DELAY 30
+//==== SPEC: Tizen Web API:Content:Content:ContentScanSuccessCallback:onsuccess M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA CBOA CBT
+setup({timeout: 30000});
+
+var t = async_test('ContentScanSuccessCallback_onsuccess', {timeout: 30000}),
+    onSuccess, onError, onSuccessCB, onErrorCB;
+
+t.step(function () {
+    onErrorCB = t.step_func(function (error) {
+        assert_unreached("Find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    onSuccessCB = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "media item is not found");
+
+        onSuccess = t.step_func(function (directoryURI) {
+            assert_type(directoryURI, "string", "directoryURI should be a string");
+            t.done();
+        });
+
+        onError = t.step_func(function (error) {
+            assert_unreached("scanFile error callback was invoked: " + error.name + " msg: " + error.message);
+        });
+
+        tizen.content.scanFile(contents[0].contentURI, onSuccess, onError);
+    });
+
+    tizen.content.find(onSuccessCB, onErrorCB);
+});
+
+}
+
+function Content_extend() {
+//==== TEST: Content_extend
+//==== LABEL Check if Content can have new properties added
+//==== PRIORITY P3
+//==== ONLOAD_DELAY 30
+//==== SPEC: Tizen Web API:Content:Content:Content:Content U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA OBX
+setup({timeout: 30000});
+
+var t = async_test('Content_extend', {timeout: 30000}),
+    onSuccess, onError, content;
+
+setup_contents(t, t.step_func(function () {
+    onError = t.step_func(function (error) {
+        assert_unreached("Find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    onSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "media item is not found");
+
+        content = contents[0];
+        check_extensibility(content);
+        t.done();
+    });
+
+    tizen.content.find(onSuccess, onError);
+}));
+
+}
+
+function Content_editableAttributes_attribute() {
+//==== TEST: Content_editableAttributes_attribute
+//==== LABEL Check if Content have editableAttributes attribute with proper type and is readonly
+//==== ONLOAD_DELAY 30
+//==== SPEC: Tizen Web API:Content:Content:Content:editableAttributes A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA AE AT ARO
+setup({timeout: 30000});
+
+var t = async_test('Content_editableAttributes_attribute', {timeout: 30000}),
+    onSuccess, onError, beforeValues, i, editableExist = false;
+
+setup_contents(t, t.step_func(function () {
+    onError = t.step_func(function (error) {
+        assert_unreached("Find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    onSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "media item is not found");
+
+        for(i = 0; i < contents.length; i++) {
+            assert_own_property(contents[i], "editableAttributes",
+                "Content does not own editableAttributes property.");
+
+            if (contents[i].editableAttributes) {
+                assert_type(contents[i].editableAttributes, "array",
+                    "Content.editableAttributes should be an array");
+                assert_type(contents[i].editableAttributes[0], "string",
+                    "Content.editableAttributes should be a string.");
+
+                beforeValues = contents[i].editableAttributes;
+                contents[i].editableAttributes = ["anotherNeweditableAttributes"];
+                assert_equals(contents[i].editableAttributes.length, beforeValues.length,
+                    "Content.editableAttributes should be readonly");
+                assert_array_equals(contents[i].editableAttributes, beforeValues,
+                    "Content.editableAttributes should be readonly");
+                editableExist = true;
+            }
+        }
+        assert_true(editableExist, "There is no content having editable attributes.");
+
+        t.done();
+    });
+
+    tizen.content.find(onSuccess, onError);
+}));
+
+}
+
+function Content_id_attribute() {
+//==== TEST: Content_id_attribute
+//==== LABEL Check if Content have id attribute with proper type, and is readonly
+//==== ONLOAD_DELAY 30
+//==== SPEC: Tizen Web API:Content:Content:Content:id A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA AE AT ARO
+setup({timeout: 30000});
+
+var t = async_test('Content_id_attribute', {timeout: 30000}),
+    onSuccess, onError, content;
+
+setup_contents(t, t.step_func(function () {
+    onError = t.step_func(function (error) {
+        assert_unreached("Find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    onSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "media item is not found");
+
+        content = contents[0];
+        check_readonly(content, "id", content.id, "string", "dummy");
+
+        t.done();
+    });
+
+    tizen.content.find(onSuccess, onError);
+}));
+
+}
+
+function Content_name_attribute() {
+//==== TEST: Content_name_attribute
+//==== LABEL Check if Content have name attribute with proper type is writeable and not nullable
+//==== ONLOAD_DELAY 30
+//==== SPEC: Tizen Web API:Content:Content:Content:name A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA AE AT ASG AN
+setup({timeout: 30000});
+
+var t = async_test('Content_name_attribute', {timeout: 30000}),
+    onSuccess, onError, i, nameAtt;
+
+setup_contents(t, t.step_func(function () {
+    onError = t.step_func(function (error) {
+        assert_unreached("Find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    onSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "media item is not found");
+
+        for(i = 0; i < contents.length; i++) {
+            nameAtt = contents[i].name;
+            check_attribute(contents[i], "name", contents[i].name, "string", "dummy");
+
+            check_not_nullable(contents[i], "name");
+
+            contents[i].name = nameAtt;
+        }
+        t.done();
+    });
+
+    tizen.content.find(onSuccess, onError);
+}));
+
+}
+
+function Content_type_attribute() {
+//==== TEST: Content_type_attribute
+//==== LABEL Check if Content have type attribute with proper type and is readonly
+//==== ONLOAD_DELAY 30
+//==== SPEC: Tizen Web API:Content:Content:Content:type A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA AE AT ARO
+setup({timeout: 30000});
+
+var t = async_test('Content_type_attribute', {timeout: 30000}),
+    onSuccess, onError, content;
+
+setup_contents(t, t.step_func(function () {
+    onError = t.step_func(function (error) {
+        assert_unreached("Find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    onSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "media item is not found");
+
+        content = contents[0];
+        check_readonly(content, "type", content.type, "string", "dummy");
+
+        t.done();
+    });
+
+    tizen.content.find(onSuccess, onError);
+}));
+
+}
+
+function Content_mimeType_attribute() {
+//==== TEST: Content_mimeType_attribute
+//==== LABEL Check if Content have mimeType attribute with proper mimeType, and is readonly
+//==== ONLOAD_DELAY 30
+//==== SPEC: Tizen Web API:Content:Content:Content:mimeType A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA AE AT ARO
+setup({timeout: 30000});
+
+var t = async_test('Content_mimeType_attribute', {timeout: 30000}),
+    onSuccess, onError, content;
+
+setup_contents(t, t.step_func(function () {
+    onError = t.step_func(function (error) {
+        assert_unreached("Find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    onSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "media item is not found");
+
+        content = contents[0];
+        check_readonly(content, "mimeType", content.mimeType, "string", "dummy");
+
+        t.done();
+    });
+
+    tizen.content.find(onSuccess, onError);
+}));
+
+}
+
+function Content_title_attribute() {
+//==== TEST: Content_title_attribute
+//==== LABEL Check if Content have title attribute with proper type and is readonly
+//==== ONLOAD_DELAY 30
+//==== SPEC: Tizen Web API:Content:Content:Content:title A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA AE AT ARO
+setup({timeout: 30000});
+
+var t = async_test('Content_title_attribute', {timeout: 30000}),
+    onSuccess, onError, content;
+
+setup_contents(t, t.step_func(function () {
+    onError = t.step_func(function (error) {
+        assert_unreached("Find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    onSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "media item is not found");
+
+        content = contents[0];
+        check_readonly(content, "title", content.title, "string", "dummy");
+
+        t.done();
+    });
+
+    tizen.content.find(onSuccess, onError);
+}));
+
+}
+
+function Content_contentURI_attribute() {
+//==== TEST: Content_contentURI_attribute
+//==== LABEL Check if Content have contentURI attribute with proper contentURI and is readonly
+//==== ONLOAD_DELAY 30
+//==== SPEC: Tizen Web API:Content:Content:Content:contentURI A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA AE AT ARO
+setup({timeout: 30000});
+
+var t = async_test('Content_contentURI_attribute', {timeout: 30000}),
+    onSuccess, onError, content;
+
+setup_contents(t, t.step_func(function () {
+    onError = t.step_func(function (error) {
+        assert_unreached("Find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    onSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "media item is not found");
+
+        content = contents[0];
+        check_readonly(content, "contentURI", content.contentURI, "string", "dummy");
+
+        t.done();
+    });
+
+    tizen.content.find(onSuccess, onError);
+}));
+
+}
+
+function Content_thumbnailURIs_attribute() {
+//==== TEST: Content_thumbnailURIs_attribute
+//==== LABEL Check if Content have thumbnailURIs attribute with proper type and is readonly
+//==== ONLOAD_DELAY 30
+//==== SPEC: Tizen Web API:Content:Content:Content:thumbnailURIs A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA AE AT ARO
+setup({timeout: 30000});
+
+var t = async_test('Content_thumbnailURIs_attribute', {timeout: 30000}),
+    onSuccess, onError, beforeValues, filter, i;
+
+setup_contents(t, t.step_func(function () {
+    onError = t.step_func(function (error) {
+        assert_unreached("Find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    onSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "media item is not found");
+
+        for(i = 0; i < contents.length; i++) {
+            assert_own_property(contents[i], "thumbnailURIs",
+                "Content does not own thumbnailURIs property.");
+            assert_type(contents[i].thumbnailURIs, "array",
+                "content.thumbnailURIs should be an array");
+
+            assert_type(contents[i].thumbnailURIs[0], "string",
+                "Content.thumbnailURIs should be a string.");
+
+            beforeValues = contents[i].thumbnailURIs;
+            if (contents[i].thumbnailURIs[0] === "newThumbnailURIs") {
+                contents[i].thumbnailURIs = ["anotherNewThumbnailURIs"];
+            } else {
+                contents[i].thumbnailURIs = ["newThumbnailURIs"];
+            }
+            assert_equals(contents[i].thumbnailURIs.length, beforeValues.length,
+                "Content.thumbnailURIs should be readonly");
+            assert_array_equals(contents[i].thumbnailURIs, beforeValues,
+                "Content.thumbnailURIs should be readonly");
+        }
+        t.done();
+    });
+
+    filter = new tizen.AttributeFilter("thumbnailURIs", "EXISTS");
+    tizen.content.find(onSuccess, onError, null, filter);
+}));
+
+}
+
+function Content_releaseDate_attribute() {
+//==== TEST: Content_releaseDate_attribute
+//==== LABEL Check if Content have releaseDate attribute with proper type and is readonly
+//==== ONLOAD_DELAY 30
+//==== SPEC: Tizen Web API:Content:Content:Content:releaseDate A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA AE AT ARO
+setup({timeout: 30000});
+
+var t = async_test('Content_releaseDate_attribute', {timeout: 30000}),
+    onSuccess, onError, i, beforeValue, releaseDateExist = false;
+
+setup_contents(t, t.step_func(function () {
+    onError = t.step_func(function (error) {
+        assert_unreached("Find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    onSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "media item is not found");
+
+        for(i = 0; i < contents.length; i++) {
+            assert_own_property(contents[i], "releaseDate",
+                "Content does not own releaseDate property.");
+
+            if(contents[i].releaseDate !== null) {
+                assert_type(contents[i].releaseDate, "date", "releaseDate should be a date");
+                beforeValue = contents[i].releaseDate;
+                contents[i].releaseDate = new Date();
+                assert_equals(contents[i].releaseDate.getTime(), beforeValue.getTime(),
+                    "Content.releaseDate should be readonly.");
+                releaseDateExist = true;
+            } else {
+                assert_type(contents[i].releaseDate, null,
+                    "Attribute releaseDate in Content should be null.");
+            }
+        }
+        assert_true(releaseDateExist, "Did not found attribute releaseDate of AudioContent set to Date.");
+
+        t.done();
+    });
+
+    tizen.content.find(onSuccess, onError);
+}));
+
+}
+
+function Content_modifiedDate_attribute() {
+//==== TEST: Content_modifiedDate_attribute
+//==== LABEL Check if Content have modifiedDate attribute with proper type and is readolny
+//==== ONLOAD_DELAY 30
+//==== SPEC: Tizen Web API:Content:Content:Content:modifiedDate A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA AE AT ARO
+setup({timeout: 30000});
+
+var t = async_test('Content_modifiedDate_attribute', {timeout: 30000}),
+    onSuccess, onError, beforeValue, i, modifiedDateExist = false;
+
+setup_contents(t, t.step_func(function () {
+    onError = t.step_func(function (error) {
+        assert_unreached("Find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    onSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "media item is not found");
+
+        for(i = 0; i < contents.length; i++) {
+            assert_own_property(contents[i], "modifiedDate",
+                "Content does not own modifiedDate property.");
+
+            if(contents[i].modifiedDate !== null) {
+                assert_type(contents[i].modifiedDate, "date", "modifiedDate should be a date");
+                beforeValue = contents[i].modifiedDate;
+                contents[i].modifiedDate = new Date();
+                assert_equals(contents[i].modifiedDate.getTime(), beforeValue.getTime(),
+                    "Content.modifiedDate should be readonly");
+                modifiedDateExist = true;
+            }
+        }
+        assert_true(modifiedDateExist, "There is no not null modifiedDate in Content.");
+
+        t.done();
+    });
+
+    tizen.content.find(onSuccess, onError);
+}));
+
+}
+
+function Content_size_attribute() {
+//==== TEST: Content_size_attribute
+//==== LABEL Check if Content have size attribute with proper type and is readonly
+//==== ONLOAD_DELAY 30
+//==== SPEC: Tizen Web API:Content:Content:Content:size A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//  Check if Content have size attribute with proper type, nullable
+//==== TEST_CRITERIA AE AT ARO
+setup({timeout: 30000});
+
+var t = async_test('Content_size_attribute', {timeout: 30000}),
+    onSuccess, onError, content;
+
+setup_contents(t, t.step_func(function () {
+    onError = t.step_func(function (error) {
+        assert_unreached("Find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    onSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "media item is not found");
+
+        content = contents[0];
+        check_readonly(content, "size", content.size, "number", 0);
+
+        t.done();
+    });
+
+    tizen.content.find(onSuccess, onError);
+}));
+
+}
+
+function Content_description_attribute() {
+//==== TEST: Content_description_attribute
+//==== LABEL Check if Content have description attribute with proper type and is writeable
+//==== ONLOAD_DELAY 30
+//==== SPEC: Tizen Web API:Content:Content:Content:description A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA AE AT ASG
+setup({timeout: 30000});
+
+var t = async_test('Content_description_attribute', {timeout: 30000}),
+    onSuccess, onError, content;
+
+setup_contents(t, t.step_func(function () {
+    onError = t.step_func(function (error) {
+        assert_unreached("Find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    onSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "media item is not found");
+
+        content = contents[0];
+        if(content.description !== null) {
+            check_attribute(content, "description", content.description, "string", "dummy");
+        }
+
+        t.done();
+    });
+
+    tizen.content.find(onSuccess, onError);
+}));
+
+}
+
+function Content_rating_attribute() {
+//==== TEST: Content_rating_attribute
+//==== LABEL Check if Content have rating attribute with proper type, range, is writeable and not nullable
+//==== ONLOAD_DELAY 30
+//==== SPEC: Tizen Web API:Content:Content:Content:rating A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA AE AT ASG AN AVL
+setup({timeout: 30000});
+
+var t = async_test('Content_rating_attribute', {timeout: 30000}),
+    onSuccess, onError, i, newValue = 3;
+
+setup_contents(t, t.step_func(function () {
+    onError = t.step_func(function (error) {
+        assert_unreached("Find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    onSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "media item is not found");
+
+        for(i = 0; i < contents.length; i++) {
+            if(contents[i].rating === newValue ) {
+                newValue++;
+            }
+            check_attribute(contents[i], "rating", contents[i].rating, "unsigned long",
+                newValue);
+
+            contents[i].rating = 11;
+            assert_equals(contents[i].rating, newValue,
+                "Content.rating should not have value greater than 10.");
+
+            contents[i].rating = -1;
+            assert_equals(contents[i].rating, newValue,
+                "Content.rating should not have value less than 0.");
+
+            contents[i].rating = null;
+            assert_not_equals(contents[i].rating, null,
+                "Content.rating should not accept null as value.");
+        }
+        t.done();
+    });
+
+    tizen.content.find(onSuccess, onError);
+}));
+
+}
+
+function ContentManager_find_with_errorCallback() {
+//==== TEST: ContentManager_find_with_errorCallback
+//==== LABEL Check if find called with optional errorCallback is properly invoked
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentManager:find M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA MOA
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_find_with_errorCallback', {timeout: 30000}),
+    successCallback, errorCallback;
+
+t.step(function () {
+    successCallback = t.step_func(function (contents) {
+        t.done();
+    });
+
+    errorCallback = t.step_func(function (error) {
+        assert_unreached("Find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.find(successCallback, errorCallback);
+});
+
+}
+
+function ContentManager_find_with_directoryId() {
+//==== TEST: ContentManager_find_with_directoryId
+//==== LABEL Check if find called with optional directoryId is properly invoked
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentManager:find M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA MOA
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_find_with_directoryId', {timeout: 30000}),
+    getDirectoriesSuccess, getDirectoriesError, findSuccess, findError, directoryId;
+
+setup_contents(t, t.step_func(function () {
+
+    findSuccess = t.step_func(function (contents) {
+        t.done();
+    });
+
+    findError = t.step_func(function (error) {
+        assert_unreached("Find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+    getDirectoriesSuccess = t.step_func(function (directories) {
+        assert_type(directories, "array", "directories should be an array");
+        assert_greater_than(directories.length, 0, "directories item is not found");
+
+        directoryId = directories[0].id;
+        tizen.content.find(findSuccess, findError, directoryId);
+    });
+
+    getDirectoriesError = t.step_func(function (error) {
+        assert_unreached("getDirectories() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.getDirectories(getDirectoriesSuccess, getDirectoriesError);
+}));
+
+}
+
+function ContentManager_find_with_filter() {
+//==== TEST: ContentManager_find_with_filter
+//==== LABEL Check if find called with optional filter is properly invoked
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentManager:find M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA MOA
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_find_with_filter', {timeout: 30000}),
+    successCallback, errorCallback, filter;
+
+t.step(function () {
+    successCallback = t.step_func(function (contents) {
+        t.done();
+    });
+
+    errorCallback = t.step_func(function (error) {
+        assert_unreached("Find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    filter = new tizen.AttributeFilter("type", "EXACTLY", "IMAGE");
+    tizen.content.find(successCallback, errorCallback, null, filter);
+});
+
+}
+
+function ContentManager_find_with_sortMode() {
+//==== TEST: ContentManager_find_with_sortMode
+//==== LABEL Check if find called with optional sortMode is properly invoked
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentManager:find M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA MOA
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_find_with_sortMode', {timeout: 30000}),
+    successCallback, errorCallback, sortMode;
+
+t.step(function () {
+    successCallback = t.step_func(function (contents) {
+        t.done();
+    });
+
+    errorCallback = t.step_func(function (error) {
+        assert_unreached("Find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    sortMode = new tizen.SortMode("name", "ASC");
+    tizen.content.find(successCallback, errorCallback, null, null, sortMode);
+});
+
+}
+
+function ContentManager_find_with_count() {
+//==== TEST: ContentManager_find_with_count
+//==== LABEL Check if find called with optional count is properly invoked
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentManager:find M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA MOA
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_find_with_count', {timeout: 30000}),
+    successCallback, errorCallback, count = 1;
+
+t.step(function () {
+    successCallback = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_equals(contents.length, count, "unexpected result");
+
+        t.done();
+    });
+
+    errorCallback = t.step_func(function (error) {
+        assert_unreached("Find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.find(successCallback, errorCallback, null, null, null, count);
+});
+
+}
+
+function ContentManager_find_with_offset() {
+//==== TEST: ContentManager_find_with_offset
+//==== LABEL Check if find called with optional offset is properly invoked
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentManager:find M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA MOA
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_find_with_offset', {timeout: 30000}),
+    successCallback, errorCallback, offset;
+
+t.step(function () {
+    successCallback = t.step_func(function (contents) {
+        t.done();
+    });
+
+    errorCallback = t.step_func(function (error) {
+        assert_unreached("Find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.find(successCallback, errorCallback, null, null, null, 1, offset);
+});
+
+}
+
+function ContentManager_getDirectories_with_errorCallback() {
+//==== TEST: ContentManager_getDirectories_with_errorCallback
+//==== LABEL Check if getDirectories called with optional errorCallback is invoked properly
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentManager:getDirectories M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA MOA MR
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_getDirectories_with_errorCallback', {timeout: 30000}),
+    successCallback, errorCallback, returnedValue = null;
+
+t.step(function () {
+    errorCallback = t.step_func(function (error) {
+        assert_unreached("getDirectories() error callback was invoked:" + error.name + ": " + error.message);
+    });
+
+    successCallback = t.step_func(function (directories) {
+        assert_equals(returnedValue, undefined,
+            "getDirectories should return undefined.");
+        t.done();
+    });
+
+    returnedValue = tizen.content.getDirectories(successCallback, errorCallback);
+});
+
+}
+
+function ContentManager_find_filter_TypeMismatch() {
+//==== TEST: ContentManager_find_filter_TypeMismatch
+//==== LABEL Check if find throws exception when filter is incorrect
+//==== PRIORITY: P2
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentManager:find M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA MC
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_find_filter_TypeMismatch', {timeout: 30000}),
+    successCallback, errorCallback, filter, i, conversionTable, exceptionName;
+
+t.step(function () {
+    successCallback = t.step_func(function (contents) {
+        assert_unreached("find() success callback should not be invoked.");
+    });
+
+    errorCallback = t.step_func(function (error) {
+        assert_unreached("find() error callback should not be invoked: " + error.name + ": " + error.message);
+    });
+
+    conversionTable = getTypeConversionExceptions("object", true);
+
+    for(i = 0; i < conversionTable.length; i++) {
+        filter = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+
+        assert_throws({name: exceptionName},
+            function () {
+                tizen.content.find(successCallback, errorCallback, null, filter);
+            }, "Given invalid filter");
+    }
+
+    t.done();
+});
+
+}
+
+function ContentManager_find_sortMode_TypeMismatch() {
+//==== TEST: ContentManager_find_sortMode_TypeMismatch
+//==== LABEL Check if find throws exception when sortMode is incorrect
+//==== PRIORITY: P2
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentManager:find M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA MC
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_find_sortMode_TypeMismatch', {timeout: 30000}),
+    successCallback, errorCallback, sortMode, i, conversionTable, exceptionName;
+
+t.step(function () {
+    successCallback = t.step_func(function (contents) {
+        assert_unreached("find() success callback should not be invoked.");
+    });
+
+    errorCallback = t.step_func(function (error) {
+        assert_unreached("find() error callback should not be invoked: " + error.name + ": " + error.message);
+    });
+
+    conversionTable = getTypeConversionExceptions("object", true);
+
+    for(i = 0; i < conversionTable.length; i++) {
+        sortMode = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+
+        assert_throws({name: exceptionName},
+            function () {
+                tizen.content.find(successCallback, errorCallback, null, null, sortMode);
+            }, "Given incorrect sortMode");
+    }
+
+    t.done();
+});
+
+}
+
+function ContentManager_find_sortMode_invalid_obj() {
+//==== TEST: ContentManager_find_sortMode_invalid_obj
+//==== LABEL Check if find throws exception when sortMode is a simple object
+//==== PRIORITY: P2
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentManager:find M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA MTO
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_find_sortMode_invalid_obj', {timeout: 30000}),
+    exceptionName = "TypeMismatchError", successCallback, errorCallback, sortMode;
+
+t.step(function () {
+    successCallback = t.step_func(function () {
+        assert_unreached("find() success callback should not be invoked.");
+    });
+
+    errorCallback = t.step_func(function (error) {
+        assert_unreached("find() error callback should not be invoked: " + error.name + ": " + error.message);
+    });
+
+    sortMode = {
+        attributeName: "name",
+        order: "ASC"
+    };
+
+    assert_throws({name: exceptionName},
+        function () {
+            tizen.content.find(successCallback, errorCallback, null, null, sortMode);
+        }, "Given incorrect sortMode.");
+
+    t.done();
+});
+
+}
+
+function ContentManager_unsetChangeListener_extra_argument() {
+//==== TEST: ContentManager_unsetChangeListener_extra_argument
+//==== LABEL Check if unsetChangeListener method can be invoked with extra argument
+//==== SPEC Tizen Web API:Content:Content:ContentManager:unsetChangeListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA MNAEX
+test(function () {
+    checkExtraArgument(tizen.content, "unsetChangeListener");
+}, 'ContentManager_unsetChangeListener_extra_argument');
+
+}
+
+function ContentArraySuccessCallback_onsuccess() {
+//==== TEST: ContentArraySuccessCallback_onsuccess
+//==== LABEL Check if ContentArraySuccessCallback onsuccess is called and if its arguments have proper type
+//==== ONLOAD_DELAY 30
+//==== SPEC: Tizen Web API:Content:Content:ContentArraySuccessCallback:onsuccess M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA CBT CBOA
+setup({timeout: 30000});
+
+var t = async_test('ContentArraySuccessCallback_onsuccess', {timeout: 30000}),
+    onSuccess, onError, content;
+
+setup_contents(t, t.step_func(function () {
+    onSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_true(contents.length > 0, "media item is not found");
+
+        content = contents[0];
+        check_content_object(content);
+        t.done();
+    });
+
+    onError = t.step_func(function (error) {
+        assert_unreached("Find() errorCallback called: " + error.name + " with message: " + error.message);
+    });
+
+    tizen.content.find(onSuccess, onError);
+}));
+
+}
+
+function ContentManager_scanFile() {
+//==== TEST: ContentManager_scanFile
+//==== LABEL Check if scanFile methods works properly
+//==== ONLOAD_DELAY 30
+//==== SPEC: Tizen Web API:Content:Content:ContentManager:scanFile M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA MMINA MAST MR
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_scanFile', {timeout: 30000}), returnedValue = null,
+    addedImagePath=SHARED_STORAGE_PATH + "/ContentChangeCallback_oncontentadded.png", changeCallback, onCopySuccess;
+
+setup_contents(t, t.step_func(function () {
+    //cleanup after TC
+    add_result_callback(function () {
+        try {
+            tizen.content.unsetChangeListener();
+        } catch (err) {}
+    });
+
+    changeCallback = {
+        oncontentadded: t.step_func(function (content) {
+            assert_equals(content.contentURI, "file://" + addedImagePath, "Invalid content passed");
+            assert_equals(returnedValue, undefined, "scanFile should return undefined.");
+
+            t.done();
+        })
+    };
+
+    onCopySuccess = t.step_func(function () {
+        tizen.content.setChangeListener(changeCallback);
+        returnedValue = tizen.content.scanFile("file://" + addedImagePath, null,
+            function (error) {
+                assert_unreached("Failed to scan a file: " + addedImagePath + " with message: " + error.message);
+            }
+        );
+    });
+
+    prepare_file_for_scan(addedImagePath, onCopySuccess, t);
+}));
+
+}
+
+function ContentManager_scanFile_with_errorCallback() {
+//==== TEST: ContentManager_scanFile_with_errorCallback
+//==== LABEL Check if scanFile called with optional errorCallback is invoked properly
+//==== ONLOAD_DELAY 30
+//==== SPEC: Tizen Web API:Content:Content:ContentManager:scanFile M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA MOA MR
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_scanFile_with_errorCallback', {timeout: 30000}),
+    findSuccess, findError, scanSuccess, scanError, returnedValue = null;
+
+setup_contents(t, t.step_func(function () {
+
+    scanError = t.step_func(function (error) {
+        assert_unreached("scanFile() error callback ivoked: " + error.name + " msg: " + error.message);
+    });
+    scanSuccess = t.step_func(function (directoryURI) {
+        assert_equals(returnedValue, undefined,
+            "update should return undefined.");
+        t.done();
+    });
+
+    findError = t.step_func(function (error) {
+        assert_unreached("find() error callback invoked: " + error.name + " msg: " + error.message);
+    });
+    findSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "media item is not found");
+
+        returnedValue = tizen.content.scanFile(contents[0].contentURI, scanSuccess, scanError);
+    });
+
+    tizen.content.find(findSuccess, findError);
+}));
+
+}
+
+function ContentManager_scanFile_with_successCallback() {
+//==== TEST: ContentManager_scanFile_with_successCallback
+//==== LABEL Check if scanFile called with optional successCallback is invoked properly
+//==== ONLOAD_DELAY 30
+//==== SPEC: Tizen Web API:Content:Content:ContentManager:scanFile M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA MOA MR
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_scanFile_with_successCallback', {timeout: 30000}),
+    findSuccess, findError, scanSuccess, returnedValue = null;
+
+setup_contents(t, t.step_func(function () {
+
+    scanSuccess = t.step_func(function (directoryURI) {
+        assert_equals(returnedValue, undefined,
+            "update should return undefined.");
+        t.done();
+    });
+
+    findError = t.step_func(function (error) {
+        assert_unreached("find() error callback invoked: " + error.name + " msg: " + error.message);
+    });
+    findSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "media item is not found");
+
+        returnedValue = tizen.content.scanFile(contents[0].contentURI, scanSuccess);
+    });
+
+    tizen.content.find(findSuccess, findError);
+}));
+
+}
+
+function ContentManager_unsetChangeListener() {
+//==== TEST: ContentManager_unsetChangeListener
+//==== LABEL Check if unsetChangeListener method called with non-optional arguments does what it should
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentManager:unsetChangeListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA MNA MNAST MR
+
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_unsetChangeListener', {timeout: 30000}), onSuccess, onError, retVal = null,
+    changeCallback, filter, description = "changeCallback";
+t.step(function () {
+    changeCallback= {
+        oncontentadded: t.step_func(function (content) {
+            assert_unreached("Listener oncontentadded invoked.");
+        }),
+        oncontentupdated: t.step_func(function (content) {
+            assert_unreached("Listener oncontentupdated invoked.");
+        }),
+        oncontentremoved: t.step_func(function (id) {
+            assert_unreached("Listener oncontentremoved invoked.");
+        })
+    };
+    onSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "media item is not found");
+
+        contents[0].description = description;
+        tizen.content.update(contents[0]);
+    });
+    onError = t.step_func(function (error) {
+        assert_unreached("find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.setChangeListener(changeCallback);
+    retVal = tizen.content.unsetChangeListener();
+    assert_equals(retVal, undefined, "unsetChangeListener should not return anything");
+
+    filter = new tizen.AttributeFilter("description", "EXISTS");
+    tizen.content.find(onSuccess, onError, null, filter);
+
+    setTimeout(t.step_func(function () {
+        t.done();
+    }), 500);
+});
+
+}
+
+function VideoContent_extend() {
+//==== TEST: VideoContent_extend
+//==== LABEL Check if VideoContent can have new properties added
+//==== PRIORITY P3
+//==== ONLOAD_DELAY 30
+//==== SPEC: Tizen Web API:Content:Content:VideoContent:VideoContent U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA OBX
+setup({timeout: 30000});
+
+var t = async_test('VideoContent_extend', {timeout: 30000}),
+    onSuccess, onError, filter, content;
+
+setup_contents(t, t.step_func(function () {
+    filter = new tizen.AttributeFilter("type", "EXACTLY", "VIDEO");
+
+    onError = t.step_func(function (error) {
+        assert_unreached("Find() Error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    onSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "media item is not found");
+
+        content = contents[0];
+        check_extensibility(content);
+        t.done();
+    });
+
+    tizen.content.find(onSuccess, onError, null, filter);
+}));
+
+}
+
+function VideoContent_geolocation_attribute() {
+//==== TEST: VideoContent_geolocation_attribute
+//==== LABEL Check if VideoContent have geolocation attribute with proper type and is writeable
+//==== ONLOAD_DELAY 30
+//==== SPEC: Tizen Web API:Content:Content:VideoContent:geolocation A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA AE AT ASG
+setup({timeout: 30000});
+
+var t = async_test('VideoContent_geolocation_attribute', {timeout: 30000}),
+    onSuccess, onError, filter, geolocation, i;
+
+setup_contents(t, t.step_func(function () {
+    filter = new tizen.AttributeFilter("type", "EXACTLY", "VIDEO");
+
+    onError = t.step_func(function (error) {
+        assert_unreached("Find() Error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    onSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "media item is not found");
+
+        for(i = 0; i < contents.length; i++) {
+            assert_own_property(contents[i], "geolocation",
+                "Content does not own modifiedDate property.");
+
+            geolocation = new tizen.SimpleCoordinates(5, 5);
+            if (contents[i].geolocation !== null) {
+                assert_true(contents[i].geolocation instanceof tizen.SimpleCoordinates,
+                    "VideoContent.geolocation should be an instance of SimpleCoordinates");
+                if (contents[i].geolocation.latitude === 5) {
+                    geolocation.latitude = 6;
+                }
+                if (contents[i].geolocation.longitude === 5) {
+                    geolocation.longitude = 6;
+                }
+            }
+            contents[i].geolocation = geolocation;
+
+            assert_equals(contents[i].geolocation.latitude, geolocation.latitude,
+                "Value of VideoContent.geolocation.latitude should be updated.");
+            assert_equals(contents[i].geolocation.longitude, geolocation.longitude,
+                "Value of VideoContent.geolocation.latitude should be updated.");
+        }
+        t.done();
+    });
+
+    tizen.content.find(onSuccess, onError, null, filter);
+}));
+
+}
+
+function VideoContent_height_attribute() {
+//==== TEST: VideoContent_height_attribute
+//==== LABEL Check if VideoContent have height attribute with proper type and is readonly
+//==== ONLOAD_DELAY 30
+//==== SPEC: Tizen Web API:Content:Content:VideoContent:height A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA AE AT ARO
+setup({timeout: 30000});
+
+var t = async_test('VideoContent_height_attribute', {timeout: 30000}),
+    onSuccess, onError, filter, content;
+
+setup_contents(t, t.step_func(function () {
+    filter = new tizen.AttributeFilter("type", "EXACTLY", "VIDEO");
+
+    onError = t.step_func(function (error) {
+        assert_unreached("Find() Error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    onSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "media item is not found");
+
+        content = contents[0];
+        check_readonly(content, "height", content.height, "number", 100);
+
+        t.done();
+    });
+
+    tizen.content.find(onSuccess, onError, null, filter);
+}));
+
+}
+
+function VideoContent_width_attribute() {
+//==== TEST: VideoContent_width_attribute
+//==== LABEL Check if VideoContent have width attribute with proper type and is readonly
+//==== ONLOAD_DELAY 30
+//==== SPEC: Tizen Web API:Content:Content:VideoContent:width A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA AE AT ARO
+setup({timeout: 30000});
+
+var t = async_test('VideoContent_width_attribute', {timeout: 30000}),
+    onSuccess, onError, filter, content;
+
+setup_contents(t, t.step_func(function () {
+    filter = new tizen.AttributeFilter("type", "EXACTLY", "VIDEO");
+
+    onError = t.step_func(function (error) {
+        assert_unreached("Find() Error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    onSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "media item is not found");
+
+        content = contents[0];
+        check_readonly(content, "width", content.width, "number", 100);
+
+        t.done();
+    });
+
+    tizen.content.find(onSuccess, onError, null, filter);
+}));
+
+}
+
+function VideoContent_duration_attribute() {
+//==== TEST: VideoContent_duration_attribute
+//==== LABEL Check if VideoContent have duration attribute with proper type and is readonly
+//==== ONLOAD_DELAY 30
+//==== SPEC: Tizen Web API:Content:Content:VideoContent:duration A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA AE AT ARO
+setup({timeout: 30000});
+
+var t = async_test('VideoContent_duration_attribute', {timeout: 30000}),
+    onSuccess, onError, filter, content;
+
+setup_contents(t, t.step_func(function () {
+    filter = new tizen.AttributeFilter("type", "EXACTLY", "VIDEO");
+
+    onError = t.step_func(function (error) {
+        assert_unreached("Find() Error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    onSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "media item is not found");
+
+        content = contents[0];
+        check_readonly(content, "duration", content.duration, "number", 100);
+
+        t.done();
+    });
+
+    tizen.content.find(onSuccess, onError, null, filter);
+}));
+
+}
+
+function VideoContent_album_attribute() {
+//==== TEST: VideoContent_album_attribute
+//==== LABEL Check if VideoContent have album attribute with proper type and is readonly
+//==== ONLOAD_DELAY 30
+//==== SPEC: Tizen Web API:Content:Content:VideoContent:album A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA AE AT ARO
+setup({timeout: 30000});
+
+var t = async_test('VideoContent_album_attribute', {timeout: 30000}),
+    onSuccess, onError, filter, content;
+
+setup_contents(t, t.step_func(function () {
+    filter = new tizen.AttributeFilter("type", "EXACTLY", "VIDEO");
+
+    onError = t.step_func(function (error) {
+        assert_unreached("Find() Error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    onSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "media item is not found");
+
+        content = contents[0];
+        if(content.album !== null) {
+            check_readonly(content, "album", content.album, "string", "MyAlbum");
+        }
+
+        t.done();
+    });
+
+    tizen.content.find(onSuccess, onError, null, filter);
+}));
+
+}
+
+function VideoContent_artists_attribute() {
+//==== TEST: VideoContent_artists_attribute
+//==== LABEL Check if VideoContent have artists attribute with proper type and is readonly
+//==== ONLOAD_DELAY 30
+//==== SPEC: Tizen Web API:Content:Content:VideoContent:artists A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA AE AT ARO
+setup({timeout: 30000});
+
+var t = async_test('VideoContent_artists_attribute', {timeout: 30000}), onSuccess, onError, beforeValues, i, artistExist = false,
+    filter = new tizen.AttributeFilter("type", "EXACTLY", "VIDEO");
+
+setup_contents(t, t.step_func(function () {
+
+    onError = t.step_func(function (error) {
+        assert_unreached("Find() Error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    onSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "media item is not found");
+
+        for(i = 0; i < contents.length; i++) {
+            assert_own_property(contents[i], "artists",
+                "VideoContent does not own artists property.");
+            if (contents[i].artists) {
+                assert_type(contents[i].artists, "array", "artists should be an array");
+                assert_type(contents[i].artists[0], "string", "artists item should be a string");
+
+                beforeValues = contents[i].artists;
+                if (contents[i].artists[0] === "newArtist") {
+                    contents[i].artists = ["anotherNewArtist"];
+                } else {
+                    contents[i].artists = ["newArtist"];
+                }
+                assert_equals(contents[i].artists.length, beforeValues.length, "artists is not readonly");
+                assert_array_equals(contents[i].artists, beforeValues, "artists is not readonly");
+                artistExist = true;
+
+            } else {
+                assert_type(contents[i].artists, null,
+                    "VideoContent.artists should be null.");
+            }
+        }
+        assert_true(artistExist, "Did not found attribute artists of VideoContent set to array.");
+
+        t.done();
+    });
+
+    tizen.content.find(onSuccess, onError, null, filter);
+}));
+
+}
+
+function ContentChangeCallback_oncontentadded() {
+//==== TEST: ContentChangeCallback_oncontentadded
+//==== LABEL Check if ContentChangeCallback oncontentadded is called and if its arguments have proper type
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentChangeCallback:oncontentadded M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA CBT CBOA
+setup({timeout: 30000});
+
+var t = async_test('ContentChangeCallback_oncontentadded', {timeout: 30000}), changeCallback, onCopySuccess,
+        addedImagePath=SHARED_STORAGE_PATH + "/ContentChangeCallback_oncontentadded.png";
+
+t.step(function () {
+    //cleanup after TC
+    add_result_callback(function () {
+        try {
+            tizen.content.unsetChangeListener();
+        } catch (err) {}
+    });
+
+    changeCallback = {
+        oncontentadded: t.step_func(function (content) {
+            assert_equals(content.contentURI, "file://" + addedImagePath, "Invalid content passed");
+            check_content_object(content);
+
+            t.done();
+        })
+    };
+
+    onCopySuccess = t.step_func(function () {
+        tizen.content.setChangeListener(changeCallback);
+        tizen.content.scanFile("file://" + addedImagePath, null,
+            function (error) {
+                assert_unreached("Failed to scan a file: " + addedImagePath + " with message: " + error.message);
+            }
+        );
+    });
+
+    prepare_file_for_scan(addedImagePath, onCopySuccess, t);
+});
+
+}
+
+function ContentChangeCallback_oncontentremoved() {
+//==== TEST: ContentChangeCallback_oncontentremoved
+//==== LABEL Check if ContentChangeCallback oncontentremoved is called and if its arguments have proper type
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentChangeCallback:oncontentremoved M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA CBT CBOA
+setup({timeout: 30000});
+
+var t = async_test('ContentChangeCallback_oncontentremoved', {timeout: 30000}),
+    contentDirectory, sharedDirectory, addedImagePath=SHARED_STORAGE_PATH + "/ContentChangeCallback_oncontentremoved.png",
+    addedContent, changeCallback, onCopySuccess, onCopyError, onDeleteSuccess, onDeleteError,
+    onScanSuccess, onScanError;
+
+add_result_callback(function (result) {
+    sharedDirectory.deleteFile(addedImagePath);
+});
+
+t.step(function () {
+    //cleanup after TC
+    add_result_callback(function () {
+        try {
+            tizen.content.unsetChangeListener();
+        } catch (err) {}
+    });
+
+    changeCallback = {
+        oncontentadded: t.step_func(function (content) {
+            addedContent = content;
+        }),
+        oncontentremoved: t.step_func(function (id) {
+            assert_equals(id, addedContent.id, "Invalid content ID passed");
+
+            t.done();
+        })
+    };
+
+    onDeleteSuccess = t.step_func(function () {
+        tizen.content.scanFile("file://" + addedImagePath);
+    });
+
+    onDeleteError = t.step_func(function () {
+        assert_unreached("Failed to delete a file: " + addedImagePath);
+    });
+
+    onScanSuccess = t.step_func(function () {
+        tizen.filesystem.resolve(
+            "file://" + SHARED_STORAGE_PATH,
+            function (directory) {
+                sharedDirectory = directory;
+                sharedDirectory.deleteFile(addedImagePath, onDeleteSuccess, onDeleteError);
+            },
+            function (error) {
+                assert_unreached("Failed to resolve a directory with message" + error.message);
+            },
+            "rw"
+        );
+    });
+
+    onScanError = t.step_func(function () {
+        assert_unreached("Failed to scan a file: " + addedImagePath);
+    });
+
+    onCopySuccess = t.step_func(function () {
+        tizen.content.scanFile("file://"+addedImagePath, onScanSuccess, onScanError);
+    });
+
+    onCopyError = t.step_func(function () {
+        assert_unreached("Failed to copy a file to " + addedImagePath);
+    });
+
+    tizen.content.setChangeListener(changeCallback);
+
+    tizen.filesystem.resolve(
+        "file://" + TEST_CONTENT_DIR_PATH,
+        function (directory) {
+            contentDirectory = directory;
+            contentDirectory.copyTo(TEST_CONTENT_DIR_PATH + TEST_CONTENT_IMAGES[0], addedImagePath, true, onCopySuccess, onCopyError);
+        },
+        function (error) {
+            assert_unreached("Failed to resolve a directory with message" + error.message);
+        },
+        "r"
+    );
+});
+
+}
+
+function ContentChangeCallback_oncontentupdated() {
+//==== TEST: ContentChangeCallback_oncontentupdated
+//==== LABEL Check if ContentChangeCallback oncontentupdated is called and if its arguments have proper type
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentChangeCallback:oncontentupdated M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA CBT CBOA
+setup({timeout: 30000});
+
+var t = async_test('ContentChangeCallback_oncontentupdated', {timeout: 30000}),
+    changeCallback, testDescription = "TEST DESCRIPTION", onSuccess, onError;
+
+t.step(function () {
+    //cleanup after TC
+    add_result_callback(function () {
+        try {
+            tizen.content.unsetChangeListener();
+        } catch (err) {}
+    });
+
+    changeCallback = {
+        oncontentupdated: t.step_func(function (content) {
+            assert_type(content, "object", "content should be an object");
+            assert_equals(content.description, testDescription, "description should be updated");
+            check_content_object(content);
+
+            t.done();
+        })
+    };
+
+    onSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "media item is not found");
+        contents[0].description = testDescription;
+        tizen.content.update(contents[0]);
+    });
+    onError = t.step_func(function (error) {
+        assert_unreached("Find() Error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.setChangeListener(changeCallback);
+    tizen.content.find(onSuccess, onError);
+});
+
+}
+
+function ContentManager_updateBatch_with_errorCallback() {
+//==== TEST: ContentManager_updateBatch_with_errorCallback
+//==== LABEL Check if updateBatch called with optional errorCallback is invoked properly
+//==== ONLOAD_DELAY 30
+//==== SPEC: Tizen Web API:Content:Content:ContentManager:updateBatch M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA MOA MR
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_updateBatch_with_errorCallback', {timeout: 30000}),
+    findSuccess, findError, updateBatchSuccess, updateBatchError, content,
+    returnedValue = null;
+
+setup_contents(t, t.step_func(function () {
+
+    updateBatchSuccess = t.step_func(function (directoryURI) {
+        assert_equals(returnedValue, undefined,
+            "updateBatch should return undefined.");
+        t.done();
+    });
+    updateBatchError = t.step_func(function (error) {
+        assert_unreached("updateBatch errorCallback called: " + error.name + " with message: " + error.message);
+    });
+
+    findSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "Media item should be found.");
+
+        content = contents[0];
+        if (content.editableAttributes.indexOf("rating") === 5) {
+            content.rating = 6;
+        } else {
+            content.rating = 5;
+        }
+
+        returnedValue = tizen.content.updateBatch([content], updateBatchSuccess, updateBatchError);
+    });
+    findError = t.step_func(function (error) {
+        assert_unreached("find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.find(findSuccess, findError);
+}));
+
+}
+
+function ContentManager_updateBatch_with_successCallback() {
+//==== TEST: ContentManager_updateBatch_with_successCallback
+//==== LABEL Check if updateBatch called with optional successCallback is invoked properly
+//==== ONLOAD_DELAY 30
+//==== SPEC: Tizen Web API:Content:Content:ContentManager:updateBatch M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA MOA MR
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_updateBatch_with_successCallback', {timeout: 30000}),
+    findSuccess, findError, updateBatchSuccess, content, returnedValue = null, i;
+
+setup_contents(t, t.step_func(function () {
+
+    updateBatchSuccess = t.step_func(function (directoryURI) {
+        assert_equals(returnedValue, undefined,
+            "updateBatch should return undefined.");
+        t.done();
+    });
+
+    findSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "Media item should be found.");
+
+        for (i = 0; i < contents.length; i++) {
+            content = contents[i];
+            if (content.editableAttributes.indexOf("rating") >= 0) {
+                if (content.rating === 5) {
+                    content.rating = 6;
+                } else {
+                    content.rating = 5;
+                }
+            }
+        }
+
+        returnedValue = tizen.content.updateBatch([content], updateBatchSuccess);
+    });
+    findError = t.step_func(function (error) {
+        assert_unreached("find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.find(findSuccess, findError);
+}));
+
+}
+
+function AudioContent_album_attribute() {
+//==== TEST: AudioContent_album_attribute
+//==== LABEL Check if AudioContent have album attribute with proper type and is readonly
+//==== ONLOAD_DELAY 30
+//==== SPEC: Tizen Web API:Content:Content:AudioContent:album A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA AE AT ARO
+setup({timeout: 30000});
+
+var t = async_test('AudioContent_album_attribute', {timeout: 30000}),
+    onSuccess, onError, filter, content;
+
+setup_contents(t, t.step_func(function () {
+    filter = new tizen.AttributeFilter("type", "EXACTLY", "AUDIO");
+
+    onError = t.step_func(function (error) {
+        assert_unreached("Find() Error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    onSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "media item is not found");
+
+        content = contents[0];
+        if(content.album !== null) {
+            check_readonly(content, "album", content.album, "string", "MyAlbum");
+            t.done();
+        }
+
+        assert_unreached("There are no media items with album property.");
+    });
+
+    tizen.content.find(onSuccess, onError, null, filter);
+}));
+
+}
+
+function AudioContent_artists_attribute() {
+//==== TEST: AudioContent_artists_attribute
+//==== LABEL Check if AudioContent have artists attribute with proper type and is readonly
+//==== ONLOAD_DELAY 30
+//==== SPEC: Tizen Web API:Content:Content:AudioContent:artists A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA AE AT ARO
+setup({timeout: 30000});
+
+var t = async_test('AudioContent_artists_attribute', {timeout: 30000}), onSuccess, onError, i, beforeValues, artistExist = false,
+    filter = new tizen.AttributeFilter("type", "EXACTLY", "AUDIO");
+
+setup_contents(t, t.step_func(function () {
+
+    onError = t.step_func(function (error) {
+        assert_unreached("Find() Error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    onSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "media item is not found");
+
+        for(i = 0; i < contents.length; i++) {
+            assert_own_property(contents[i], "artists",
+                "AudioContent does not own artists property.");
+
+            if (contents[i].artists) {
+                assert_type(contents[i].artists, "array", "artists should be an array");
+                assert_type(contents[i].artists[0], "string", "artists items should be a string");
+
+                beforeValues = contents[i].artists;
+                if (contents[i].artists[0] === "newArtist") {
+                    contents[i].artists = ["anotherNewArtist"];
+                } else {
+                    contents[i].artists = ["newArtist"];
+                }
+                assert_equals(contents[i].artists.length, beforeValues.length, "artists is not readonly");
+                assert_array_equals(contents[i].artists, beforeValues, "artists is not readonly");
+                artistExist = true;
+            } else {
+                assert_type(contents[i].artists, null,
+                    "AudioContent.artists should be null.");
+            }
+        }
+        assert_true(artistExist, "Did not found attribute artists of AudioContent set to array.");
+
+        t.done();
+    });
+
+    tizen.content.find(onSuccess, onError, null, filter);
+}));
+
+}
+
+function AudioContent_bitrate_attribute() {
+//==== TEST: AudioContent_bitrate_attribute
+//==== LABEL Check if AudioContent have bitrate attribute with proper type, readonly
+//==== ONLOAD_DELAY 30
+//==== SPEC: Tizen Web API:Content:Content:AudioContent:bitrate A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA AE AT ARO
+setup({timeout: 30000});
+
+var t = async_test('AudioContent_bitrate_attribute', {timeout: 30000}),
+    onSuccess, onError, filter, i;
+
+setup_contents(t, t.step_func(function () {
+    filter = new tizen.AttributeFilter("type", "EXACTLY", "AUDIO");
+
+    onError = t.step_func(function (error) {
+        assert_unreached("Find() Error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    onSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "media item is not found");
+
+        for(i = 0; i < contents.length; i++) {
+            check_readonly(contents[i], "bitrate", contents[i].bitrate, "unsigned long",
+                contents[i].bitrate + 1);
+        }
+        t.done();
+    });
+
+    tizen.content.find(onSuccess, onError, null, filter);
+}));
+
+}
+
+function AudioContent_duration_attribute() {
+//==== TEST: AudioContent_duration_attribute
+//==== LABEL Check if AudioContent have duration attribute with proper type and is readonly
+//==== ONLOAD_DELAY 30
+//==== SPEC: Tizen Web API:Content:Content:AudioContent:duration A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA AE AT ARO
+setup({timeout: 30000});
+
+var t = async_test('AudioContent_duration_attribute', {timeout: 30000}),
+    onSuccess, onError, filter, content;
+
+setup_contents(t, t.step_func(function () {
+    filter = new tizen.AttributeFilter("type", "EXACTLY", "AUDIO");
+
+    onError = t.step_func(function (error) {
+        assert_unreached("Find() Error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    onSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "media item is not found");
+
+        content = contents[0];
+        check_readonly(content, "duration", content.duration, "number", 100);
+
+        t.done();
+    });
+
+    tizen.content.find(onSuccess, onError, null, filter);
+}));
+
+}
+
+function AudioContent_extend() {
+//==== TEST: AudioContent_extend
+//==== LABEL Check if AudioContent can have new properties added
+//==== PRIORITY P3
+//==== ONLOAD_DELAY 30
+//==== SPEC: Tizen Web API:Content:Content:AudioContent:AudioContent U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA OBX
+setup({timeout: 30000});
+
+var t = async_test('AudioContent_extend', {timeout: 30000}),
+    onSuccess, onError, filter, content;
+
+setup_contents(t, t.step_func(function () {
+    filter = new tizen.AttributeFilter("type", "EXACTLY", "AUDIO");
+
+    onError = t.step_func(function (error) {
+        assert_unreached("Find() Error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    onSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "media item is not found");
+
+        content = contents[0];
+        check_extensibility(content);
+        t.done();
+    });
+
+    tizen.content.find(onSuccess, onError, null, filter);
+}));
+
+}
+
+function AudioContent_trackNumber_attribute() {
+//==== TEST: AudioContent_trackNumber_attribute
+//==== LABEL Check if AudioContent have trackNumber attribute with proper type, readonly, nullable
+//==== ONLOAD_DELAY 30
+//==== SPEC: Tizen Web API:Content:Content:AudioContent:trackNumber A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA AE AT ARO
+setup({timeout: 30000});
+
+var t = async_test('AudioContent_trackNumber_attribute', {timeout: 30000}),
+    onSuccess, onError, filter, content;
+
+setup_contents(t, t.step_func(function () {
+    filter = new tizen.AttributeFilter("type", "EXACTLY", "AUDIO");
+
+    onError = t.step_func(function (error) {
+        assert_unreached("Find() Error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    onSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "media item is not found");
+
+        content = contents[0];
+        if(content.trackNumber !== null) {
+            check_readonly(content, "trackNumber", content.trackNumber, "number", 100);
+            t.done();
+        }
+
+        assert_unreached("There are no media items with track number property.");
+    });
+
+    tizen.content.find(onSuccess, onError, null, filter);
+}));
+
+}
+
+function AudioContent_genres_attribute() {
+//==== TEST: AudioContent_genres_attribute
+//==== LABEL Check if AudioContent have genres attribute with proper type, readonly
+//==== ONLOAD_DELAY 30
+//==== SPEC: Tizen Web API:Content:Content:AudioContent:genres A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA AE AT ARO
+setup({timeout: 30000});
+
+var t = async_test('AudioContent_genres_attribute', {timeout: 30000}), onSuccess, onError, i, beforeValues, genreExist = false,
+    filter, filter1, filter2;
+
+setup_contents(t, t.step_func(function () {
+
+    onError = t.step_func(function (error) {
+        assert_unreached("Find() Error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    onSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "media item is not found");
+
+        for(i = 0; i < contents.length; i++) {
+            assert_own_property(contents[i], "genres",
+                "AudioContent does not own genres property. i =" + i + " TYPE= " + contents[i].type);
+
+            if (contents[i].genres) {
+                assert_type(contents[i].genres, "array", "genres should be an array");
+                assert_type(contents[i].genres[0], "string",
+                    "genres items should be a string");
+
+                beforeValues = contents[i].genres;
+                if (contents[i].genres[0] === "newGenre") {
+                    contents[i].genres = ["anotherNewGenre"];
+                } else {
+                    contents[i].genres = ["newGenre"];
+                }
+                assert_equals(contents[i].genres.length, beforeValues.length, "genres is not readonly");
+                assert_array_equals(contents[i].genres, beforeValues, "genres is not readonly");
+                genreExist = true;
+            } else {
+                assert_type(contents[i].genres, null,
+                    "AudioContent.genres should be null.");
+            }
+        }
+        assert_true(genreExist, "Did not found attribute genres of AudioContent set to array.");
+
+        t.done();
+    });
+
+    filter1 = new tizen.AttributeFilter("type", "EXACTLY", "AUDIO"),
+    filter2 = new tizen.AttributeFilter("genres", "EXISTS"),
+    filter = new tizen.CompositeFilter("INTERSECTION", [filter1, filter2]);
+
+    tizen.content.find(onSuccess, onError, null, filter);
+}));
+
+}
+
+function AudioContent_composers_attribute() {
+//==== TEST: AudioContent_composers_attribute
+//==== LABEL Check if AudioContent have composers attribute with proper type and is readonly
+//==== ONLOAD_DELAY 30
+//==== SPEC: Tizen Web API:Content:Content:AudioContent:composers A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA AE AT ARO
+setup({timeout: 30000});
+
+var t = async_test('AudioContent_composers_attribute', {timeout: 30000}),
+    onSuccess, onError, filter, i, beforeValues, composerExist = false;
+
+setup_contents(t, t.step_func(function () {
+    filter = new tizen.AttributeFilter("type", "EXACTLY", "AUDIO");
+
+    onError = t.step_func(function (error) {
+        assert_unreached("Find() Error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    onSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "media item is not found");
+
+        for(i = 0; i < contents.length; i++) {
+            assert_own_property(contents[i], "composers",
+                "AudioContent does not own composers property.");
+
+            if (contents[i].composers) {
+                assert_type(contents[i].composers, "array", "composers should be an array");
+                assert_type(contents[i].composers[0], "string",
+                    "composers items should be a string");
+
+                beforeValues = contents[i].composers;
+                if (contents[i].composers[0] === "newComposer") {
+                    contents[i].composers = ["anotherNewComposer"];
+                } else {
+                    contents[i].composers = ["newComposer"];
+                }
+                assert_equals(contents[i].composers.length, beforeValues.length, "composers is not readonly");
+                assert_array_equals(contents[i].composers, beforeValues, "composers is not readonly");
+                composerExist = true;
+            } else {
+                assert_type(contents[i].composers, null,
+                    "AudioContent.composers should be null.");
+            }
+        }
+        assert_true(composerExist, "Did not found attribute composers of AudioContent set to array.");
+
+        t.done();
+    });
+
+    tizen.content.find(onSuccess, onError, null, filter);
+}));
+
+}
+
+function AudioContent_copyright_attribute() {
+//==== TEST: AudioContent_copyright_attribute
+//==== LABEL Check if AudioContent have copyright attribute with proper type and is readonly
+//==== ONLOAD_DELAY 30
+//==== SPEC: Tizen Web API:Content:Content:AudioContent:copyright A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA AE AT ARO
+setup({timeout: 30000});
+
+var t = async_test('AudioContent_copyright_attribute', {timeout: 30000}),
+    onSuccess, onError, filter, content;
+
+setup_contents(t, t.step_func(function () {
+    filter = new tizen.AttributeFilter("type", "EXACTLY", "AUDIO");
+
+    onError = t.step_func(function (error) {
+        assert_unreached("Find() Error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    onSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "media item is not found");
+
+        content = contents[0];
+        if(content.copyright !== null) {
+            check_readonly(content, "copyright", content.copyright, "string", "MyRights");
+        }
+
+        t.done();
+    });
+
+    tizen.content.find(onSuccess, onError, null, filter);
+}));
+
+}
+
+function AudioContent_lyrics_attribute() {
+//==== TEST: AudioContent_lyrics_attribute
+//==== LABEL Check if AudioContent have lyrics attribute with proper type and is readonly
+//==== ONLOAD_DELAY 30
+//==== SPEC: Tizen Web API:Content:Content:AudioContent:lyrics A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA AE AT ARO
+setup({timeout: 30000});
+
+var t = async_test('AudioContent_lyrics_attribute', {timeout: 30000}),
+    onSuccess, onError, filter, tmp, i;
+
+setup_contents(t, t.step_func(function () {
+    filter = new tizen.AttributeFilter("type", "EXACTLY", "AUDIO");
+
+    onError = t.step_func(function (error) {
+        assert_unreached("Find() Error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    onSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "media item is not found");
+
+        for(i = 0; i < contents.length; i++) {
+            if (contents[i].lyrics) {
+                assert_own_property(contents[i], "lyrics",
+                    "AudioContent does not own composers property.");
+                assert_own_property(contents[i].lyrics, "type",
+                    "AudioContent.lyrics does not own type property.");
+                assert_type(contents[i].lyrics.type, "string",
+                    "AudioContent.lyrics.type should be a string.");
+                assert_own_property(contents[i].lyrics, "timestamps",
+                    "AudioContent.lyrics does not own timestamps property.");
+                assert_own_property(contents[i].lyrics, "texts",
+                    "AudioContent does not own texts property.");
+                assert_type(contents[i].lyrics.texts, "array",
+                    "AudioContent.lyrics.texts should be an array.");
+
+                tmp = contents[i].lyrics;
+                contents[i].lyrics = undefined;
+                assert_not_equals(contents[i].lyrics, undefined, "lyrics should be readonly");
+                assert_equals(contents[i].lyrics.type, tmp.type, "lyrics should be readonly");
+
+                if (contents[i].lyrics.timestamps) {
+                    assert_equals(contents[i].lyrics.timestamps.length, tmp.timestamps.length, "lyrics should be readonly");
+                }
+
+                assert_equals(contents[i].lyrics.texts.length, tmp.texts.length, "lyrics should be readonly");
+                t.done();
+            }
+        }
+
+        assert_unreached("There are no media items with lyrics");
+    });
+
+    tizen.content.find(onSuccess, onError, null, filter);
+}));
+
+}
+
+function AudioContentLyrics_extend() {
+//==== TEST: AudioContentLyrics_extend
+//==== LABEL Check if AudioContentLyrics can have new properties added
+//==== PRIORITY P3
+//==== ONLOAD_DELAY 30
+//==== SPEC: Tizen Web API:Content:Content:AudioContentLyrics:AudioContentLyrics U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA OBX
+setup({timeout: 30000});
+
+var t = async_test('AudioContentLyrics_extend', {timeout: 30000}),
+    onSuccess, onError, filter, lyrics, haveLyrics = false, i;
+
+setup_contents(t, t.step_func(function () {
+    filter = new tizen.AttributeFilter("type", "EXACTLY", "AUDIO");
+
+    onError = t.step_func(function (error) {
+        assert_unreached("Find() Error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    onSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "media item is not found");
+
+        for(i = 0; i < contents.length; i++) {
+            if(contents[i].lyrics) {
+                haveLyrics = true;
+                lyrics = contents[i].lyrics;
+                check_extensibility(lyrics);
+            }
+        }
+
+        assert_true(haveLyrics, "there are no media items with lyrics");
+
+        t.done();
+    });
+
+    tizen.content.find(onSuccess, onError, null, filter);
+}));
+
+}
+
+function AudioContentLyrics_type_attribute() {
+//==== TEST: AudioContentLyrics_type_attribute
+//==== LABEL Check if AudioContentLyrics have type attribute with proper type and is readonly
+//==== ONLOAD_DELAY 30
+//==== SPEC: Tizen Web API:Content:Content:AudioContentLyrics:type A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA AE AT ARO
+setup({timeout: 30000});
+
+var t = async_test('AudioContentLyrics_type_attribute', {timeout: 30000}),
+    onSuccess, onError, filter, haveLyrics = false, i;
+
+setup_contents(t, t.step_func(function () {
+    filter = new tizen.AttributeFilter("type", "EXACTLY", "AUDIO");
+
+    onError = t.step_func(function (error) {
+        assert_unreached("Find() Error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    onSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "media item is not found");
+
+        for(i = 0; i < contents.length; i++) {
+            if(contents[i].lyrics) {
+                haveLyrics = true;
+                check_readonly(contents[i].lyrics, "type", contents[i].lyrics.type, "string", "dummy");
+                assert_in_array(contents[i].lyrics.type, ["SYNCHRONIZED", "UNSYNCHRONIZED"], "invalid enum value");
+            }
+        }
+
+        assert_true(haveLyrics, "there are no media items with lyrics");
+
+        t.done();
+    });
+
+    tizen.content.find(onSuccess, onError, null, filter);
+}));
+
+}
+
+function AudioContentLyrics_timestamps_attribute() {
+//==== TEST: AudioContentLyrics_timestamps_attribute
+//==== LABEL Check if AudioContentLyrics have timestamps attribute with proper type and is readonly
+//==== ONLOAD_DELAY 30
+//==== SPEC: Tizen Web API:Content:Content:AudioContentLyrics:timestamps A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA AE AT ARO
+setup({timeout: 30000});
+
+var t = async_test('AudioContentLyrics_timestamps_attribute', {timeout: 30000}),
+    onSuccess, onError, filter, beforeValues, i;
+
+setup_contents(t, t.step_func(function () {
+    filter = new tizen.AttributeFilter("type", "EXACTLY", "AUDIO");
+
+    onError = t.step_func(function (error) {
+        assert_unreached("Find() Error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    onSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "media item is not found");
+
+        for(i = 0; i < contents.length; i++) {
+            if(contents[i].lyrics) {
+                assert_own_property(contents[i].lyrics, "timestamps",
+                    "AudioContent.lyrics does not own timestamps property.");
+
+                if(contents[i].lyrics.type === "UNSYNCHRONIZED") {
+                    assert_equals(contents[i].lyrics.timestamps, undefined,
+                        "lyrics.timestamps should be undefined when lyrics are unsynchronized");
+                } else {
+                    assert_type(contents[i].lyrics.timestamps, "array",
+                        "AudioContent.lyrics.timestamps should be an array");
+                    assert_greater_than(contents[i].lyrics.timestamps.length, 0,
+                        "AudioContent.lyrics.timestamps should not be empty.");
+                    assert_type(contents[i].lyrics.timestamps[0], "unsigned long",
+                        "AudioContent.lyrics.timestamps should be a string.");
+
+                    beforeValues = contents[i].lyrics.timestamps;
+                    contents[i].lyrics.timestamps = [100, -20];
+                    assert_equals(contents[i].lyrics.timestamps.length, beforeValues.length,
+                        "AudioContent.lyrics.timestamps should be readonly");
+                    assert_array_equals(contents[i].lyrics.timestamps, beforeValues,
+                        "AudioContent.lyrics.timestamps should be readonly");
+                }
+                t.done();
+            }
+        }
+        assert_unreached("There are no media items with lyrics");
+    });
+
+    tizen.content.find(onSuccess, onError, null, filter);
+}));
+
+}
+
+function AudioContentLyrics_texts_attribute() {
+//==== TEST: AudioContentLyrics_texts_attribute
+//==== LABEL Check if AudioContentLyrics have texts attribute with proper type and is readonly
+//==== ONLOAD_DELAY 30
+//==== SPEC: Tizen Web API:Content:Content:AudioContentLyrics:texts A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA AE AT ARO
+setup({timeout: 30000});
+
+var t = async_test('AudioContentLyrics_texts_attribute', {timeout: 30000}),
+    onSuccess, onError, filter, beforeValues, i, lyricsExist = false;
+
+setup_contents(t, t.step_func(function () {
+    filter = new tizen.AttributeFilter("type", "EXACTLY", "AUDIO");
+
+    onError = t.step_func(function (error) {
+        assert_unreached("Find() Error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    onSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "media item is not found");
+
+        for(i = 0; i < contents.length; i++) {
+            if(contents[i].lyrics) {
+                assert_own_property(contents[i].lyrics, "texts",
+                    "AudioContent does not own texts property.");
+                assert_type(contents[i].lyrics.texts, "array",
+                    "AudioContent.lyrics.texts should be an array.");
+                assert_greater_than(contents[i].lyrics.texts.length, 0,
+                    "AudioContent.lyrics.texts should not be empty.");
+
+                if(contents[i].lyrics.type === "UNSYNCHRONIZED") {
+                    assert_equals(contents[i].lyrics.texts.length, 1,
+                        "lyrics.texts should have 1 item when lyrics are unsynchronized");
+                }
+                assert_type(contents[i].lyrics.texts[0], "string",
+                    "lyrics.texts should be a string.");
+
+                beforeValues = contents[i].lyrics.texts;
+                contents[i].lyrics.texts = ["text1", "text2"];
+                assert_array_equals(contents[i].lyrics.texts, beforeValues,
+                    "lyrics.texts is not readonly");
+                lyricsExist = true;
+            } else {
+                assert_type(contents[i].lyrics, null,
+                    "Attribute lyrics in AudioContent should be null.");
+            }
+        }
+        assert_true(lyricsExist, "Did not found attribute lyrics of AudioContent set to AudioContentLyrics.");
+
+        t.done();
+    });
+
+    tizen.content.find(onSuccess, onError, null, filter);
+}));
+
+}
+
+function ContentDirectory_extend() {
+//==== TEST: ContentDirectory_extend
+//==== LABEL Check if ContentDirectory can have new properties added
+//==== PRIORITY P3
+//==== ONLOAD_DELAY 30
+//==== SPEC: Tizen Web API:Content:Content:ContentDirectory:ContentDirectory U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA OBX
+setup({timeout: 30000});
+
+var t = async_test('ContentDirectory_extend', {timeout: 30000}),
+    onSuccess, onError, directory;
+
+t.step(function () {
+    onError = t.step_func(function (error) {
+        assert_unreached("getDirectories() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    onSuccess = t.step_func(function (directories) {
+        assert_type(directories, "array", "directories should be an array");
+        assert_greater_than(directories.length, 0, "directories were not found");
+
+        directory = directories[0];
+        check_extensibility(directory);
+        t.done();
+    });
+
+    tizen.content.getDirectories(onSuccess, onError);
+});
+
+}
+
+function ContentDirectory_id_attribute() {
+//==== TEST: ContentDirectory_id_attribute
+//==== LABEL Check if ContentDirectory have id attribute with proper type, and is readonly
+//==== ONLOAD_DELAY 30
+//==== SPEC: Tizen Web API:Content:Content:ContentDirectory:id A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA AE AT ARO
+setup({timeout: 30000});
+
+var t = async_test('ContentDirectory_id_attribute', {timeout: 30000}),
+    onSuccess, onError, directory;
+
+t.step(function () {
+    onError = t.step_func(function (error) {
+        assert_unreached("getDirectories() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    onSuccess = t.step_func(function (directories) {
+        assert_type(directories, "array", "directories should be an array");
+        assert_greater_than(directories.length, 0, "directories were not found");
+
+        directory = directories[0];
+        check_readonly(directory, "id", directory.id, "string", "dummy");
+
+        t.done();
+    });
+
+    tizen.content.getDirectories(onSuccess, onError);
+});
+
+}
+
+function ContentDirectory_directoryURI_attribute() {
+//==== TEST: ContentDirectory_directoryURI_attribute
+//==== LABEL Check if ContentDirectory have directoryURI attribute with proper type and is readonly
+//==== ONLOAD_DELAY 30
+//==== SPEC: Tizen Web API:Content:Content:ContentDirectory:directoryURI A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA AE AT ARO
+setup({timeout: 30000});
+
+var t = async_test('ContentDirectory_directoryURI_attribute', {timeout: 30000}),
+    onSuccess, onError, directory;
+
+t.step(function () {
+    onError = t.step_func(function (error) {
+        assert_unreached("getDirectories() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    onSuccess = t.step_func(function (directories) {
+        assert_type(directories, "array", "directories should be an array");
+        assert_greater_than(directories.length, 0, "directories were not found");
+
+        directory = directories[0];
+        check_readonly(directory, "directoryURI", directory.directoryURI, "string", "dummy");
+
+        t.done();
+    });
+
+    tizen.content.getDirectories(onSuccess, onError);
+});
+
+}
+
+function ContentDirectory_title_attribute() {
+//==== TEST: ContentDirectory_title_attribute
+//==== LABEL Check if ContentDirectory have title attribute with proper type, readonly, not null
+//==== ONLOAD_DELAY 30
+//==== SPEC: Tizen Web API:Content:Content:ContentDirectory:title A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA AE AT ARO
+setup({timeout: 30000});
+
+var t = async_test('ContentDirectory_title_attribute', {timeout: 30000}),
+    onSuccess, onError, directory;
+
+t.step(function () {
+    onError = t.step_func(function (error) {
+        assert_unreached("getDirectories() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    onSuccess = t.step_func(function (directories) {
+        assert_type(directories, "array", "directories should be an array");
+        assert_greater_than(directories.length, 0, "directories were not found");
+
+        directory = directories[0];
+        check_readonly(directory, "title", directory.title, "string", "dummy");
+        t.done();
+    });
+
+    tizen.content.getDirectories(onSuccess, onError);
+});
+
+}
+
+function ContentDirectory_modifiedDate_attribute() {
+//==== TEST: ContentDirectory_modifiedDate_attribute
+//==== LABEL Check if ContentDirectory have modifiedDate attribute with proper type and is readonly
+//==== ONLOAD_DELAY 30
+//==== SPEC: Tizen Web API:Content:Content:ContentDirectory:modifiedDate A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA AE AT ARO
+setup({timeout: 30000});
+
+var t = async_test('ContentDirectory_modifiedDate_attribute', {timeout: 30000}),
+    onSuccess, onError, beforeValues, i, modifiedDateExist = false;
+
+t.step(function () {
+    onError = t.step_func(function (error) {
+        assert_unreached("getDirectories() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    onSuccess = t.step_func(function (directories) {
+        assert_type(directories, "array", "directories should be an array");
+        assert_greater_than(directories.length, 0, "directories were not found");
+
+        for(i = 0; i < directories.length; i++) {
+            assert_own_property(directories[i], "modifiedDate",
+                "Content does not own modifiedDate property.");
+
+            if(directories[i].modifiedDate !== null) {
+                assert_type(directories[i].modifiedDate, "date",
+                    "ContentDirectory.modifiedDate should be a date");
+                beforeValues = directories[i].modifiedDate;
+                directories[i].modifiedDate = new Date();
+                assert_equals(directories[i].modifiedDate.getTime(),
+                    beforeValues.getTime(), "modified date should be readonly");
+                modifiedDateExist = true;
+            }
+        }
+        assert_true(modifiedDateExist, "There is no folder having modification date.");
+
+        t.done();
+    });
+
+    tizen.content.getDirectories(onSuccess, onError);
+});
+
+}
+
+function ContentDirectory_storageType_attribute() {
+//==== TEST: ContentDirectory_storageType_attribute
+//==== LABEL Check if ContentDirectory have storageType attribute with proper type, readonly, not null
+//==== ONLOAD_DELAY 30
+//==== SPEC: Tizen Web API:Content:Content:ContentDirectory:storageType A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA AE AT ARO
+setup({timeout: 30000});
+
+var t = async_test('ContentDirectory_storageType_attribute', {timeout: 30000}),
+    onSuccess, onError, directory;
+
+t.step(function () {
+    onError = t.step_func(function (error) {
+        assert_unreached("getDirectories() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    onSuccess = t.step_func(function (directories) {
+        assert_type(directories, "array", "directories should be an array");
+        assert_greater_than(directories.length, 0, "directories were not found");
+
+        directory = directories[0];
+        check_readonly(directory, "storageType", directory.storageType, "string", "dummy");
+        assert_in_array(directory.storageType, ["INTERNAL", "EXTERNAL"], "invalid enum value");
+        t.done();
+    });
+
+    tizen.content.getDirectories(onSuccess, onError);
+});
+
+}
+
+function ContentManager_update_name() {
+//==== TEST: ContentManager_update_name
+//==== LABEL Check if update() properly updates name attribute of first found item
+//==== PRIORITY P1
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentManager:update M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA MAST MMINA
+
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_update_name', {timeout: 30000}),
+    successCallback, errorCallback, onSuccess, expected, updated = null, i,
+    filter, typeFilter = new tizen.AttributeFilter("type", "EXACTLY", "IMAGE");
+
+
+setup_contents(t, t.step_func(function () {
+
+    onSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_equals(contents.length, 1, "Updated image item should be found");
+        assert_equals(contents[0].name, expected, "name attribute should be updated");
+        t.done();
+    });
+
+    errorCallback = t.step_func(function (error) {
+        assert_unreached("Find() error callback invoked: " + error.name + " with message: " + error.message);
+    });
+    successCallback = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "Image item should be found");
+
+        for(i = 0; i < contents.length; i ++) {
+            if (contents[i].editableAttributes.indexOf("name") >= 0) {
+                updated = contents[i];
+                break;
+            }
+        }
+        assert_not_equals(updated, null, "Image should contain editable 'name' attribute.");
+
+        updated.name += "updated";
+        expected = updated.name;
+        tizen.content.update(updated);
+
+        filter = new tizen.AttributeFilter("id", "EXACTLY", updated.id);
+        tizen.content.find(onSuccess, errorCallback, null, filter);
+    });
+    tizen.content.find(successCallback, errorCallback, null, typeFilter);
+}));
+
+}
+
+function ContentManager_update_video_geolocation() {
+//==== TEST: ContentManager_update_video_geolocation
+//==== LABEL Check if update() properly updates geolocation attribute of first found video item
+//==== PRIORITY P1
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentManager:update M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA MAST MMINA
+
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_update_video_geolocation', {timeout: 30000}),
+    successCallback, errorCallback, onSuccess, expected, updated = null, i,
+    filter, typeFilter = new tizen.AttributeFilter("type", "EXACTLY", "VIDEO");
+
+setup_contents(t, t.step_func(function () {
+
+    onSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_equals(contents.length, 1, "Updated video item should be found");
+
+        assert_equals(contents[0].geolocation.latitude, expected.latitude,
+            "geolocation latitude attribute should be updated");
+        assert_equals(contents[0].geolocation.longitude, expected.longitude,
+            "geolocation longitude attribute should be updated");
+        t.done();
+    });
+
+    errorCallback = t.step_func(function (error) {
+        assert_unreached("Find() error callback invoked: " + error.name + " with message: " + error.message);
+    });
+    successCallback = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "Video item should be found");
+
+        for(i = 0; i < contents.length; i ++) {
+            if (contents[i].editableAttributes.indexOf("geolocation") >= 0) {
+                updated = contents[i];
+                break;
+            }
+        }
+        assert_not_equals(updated, null, "Video should contain editable 'geolocation' attribute.");
+
+        if (updated.geolocation !== null) {
+            if (updated.geolocation.latitude === 5) {
+                updated.geolocation.latitude = 6;
+            } else {
+                updated.geolocation.latitude = 5;
+            }
+            if (updated.geolocation.longitude === 5) {
+                updated.geolocation.longitude = 6;
+            } else {
+                updated.geolocation.longitude = 5;
+            }
+        } else {
+            updated.geolocation = new tizen.SimpleCoordinates(5.555, 5.555);
+        }
+        expected = updated.geolocation;
+        tizen.content.update(updated);
+
+        filter = new tizen.AttributeFilter("id", "EXACTLY", updated.id);
+        tizen.content.find(onSuccess, errorCallback, null, filter);
+    });
+    tizen.content.find(successCallback, errorCallback, null, typeFilter);
+}));
+
+}
+
+function ContentManager_update_image_geolocation() {
+//==== TEST: ContentManager_update_image_geolocation
+//==== LABEL Check if update() properly updates geolocation attribute of first found image item
+//==== PRIORITY P1
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentManager:update M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA MAST MMINA
+
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_update_image_geolocation', {timeout: 30000}),
+    successCallback, errorCallback, onSuccess, expected, updated = null, i,
+    filter, typeFilter = new tizen.AttributeFilter("type", "EXACTLY", "IMAGE");
+
+setup_contents(t, t.step_func(function () {
+
+    onSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_equals(contents.length, 1, "Updated image item should be found");
+        assert_equals(contents[0].geolocation.latitude, expected.latitude,
+            "geolocation latitude attribute should be updated");
+        assert_equals(contents[0].geolocation.longitude, expected.longitude,
+            "geolocation longitude attribute should be updated");
+        t.done();
+    });
+
+    errorCallback = t.step_func(function (error) {
+        assert_unreached("Find() error callback invoked: " + error.name + " with message: " + error.message);
+    });
+    successCallback = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "Image item should be found");
+
+        for(i = 0; i < contents.length; i++) {
+            if (contents[i].editableAttributes.indexOf("geolocation") >= 0) {
+                updated = contents[i];
+                break;
+            }
+        }
+        assert_not_equals(updated, null, "Image should contain editable 'geolocation' attribute.");
+
+        if (updated.geolocation !== null) {
+            if (updated.geolocation.latitude === 5) {
+                updated.geolocation.latitude = 6;
+            } else {
+                updated.geolocation.latitude = 5;
+            }
+            if (updated.geolocation.longitude === 5) {
+                updated.geolocation.longitude = 6;
+            } else {
+                updated.geolocation.longitude = 5;
+            }
+        } else {
+            updated.geolocation = new tizen.SimpleCoordinates(5.555, 5.555);
+        }
+        expected = updated.geolocation;
+        tizen.content.update(updated);
+
+        filter = new tizen.AttributeFilter("id", "EXACTLY", updated.id);
+        tizen.content.find(onSuccess, errorCallback, null, filter);
+    });
+    tizen.content.find(successCallback, errorCallback, null, typeFilter);
+}));
+
+}
+
+function ContentManager_update_image_orientation() {
+//==== TEST: ContentManager_update_image_orientation
+//==== LABEL Check if update() properly updates orientation attribute of first found image item
+//==== PRIORITY P1
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentManager:update M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA MAST MMINA
+
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_update_image_orientation', {timeout: 30000}),
+    successCallback, errorCallback, onSuccess, updated = null, i,
+    expected, filter, typeFilter = new tizen.AttributeFilter("type", "EXACTLY", "IMAGE");
+
+setup_contents(t, t.step_func(function () {
+
+    onSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_equals(contents.length, 1, "Updated image item should be found");
+        assert_equals(contents[0].orientation, expected, "orientation attribute should be updated");
+        t.done();
+    });
+
+    errorCallback = t.step_func(function (error) {
+        assert_unreached("Find() error callback invoked: " + error.name + " with message: " + error.message);
+    });
+    successCallback = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "Image item should be found");
+
+        for(i = 0; i < contents.length; i++) {
+            if (contents[i].editableAttributes.indexOf("orientation") >= 0) {
+                updated = contents[i];
+                break;
+            }
+        }
+
+        assert_not_equals(updated, null, "Image should contain editable 'orientation' attribute.");
+
+        if (updated.orientation === "NORMAL") {
+            updated.orientation = "FLIP_HORIZONTAL";
+        } else {
+            updated.orientation = "NORMAL";
+        }
+        expected = updated.orientation;
+        tizen.content.update(updated);
+
+        filter = new tizen.AttributeFilter("id", "EXACTLY", updated.id);
+        tizen.content.find(onSuccess, errorCallback, null, filter);
+    });
+    tizen.content.find(successCallback, errorCallback, null, typeFilter);
+}));
+
+}
+
+function ContentManager_updateBatch_name() {
+//==== TEST: ContentManager_updateBatch_name
+//==== LABEL Check if updateBatch() properly updates name attributes of multiple image items
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentManager:updateBatch M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA MAST MOA
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_updateBatch_name', {timeout: 30000}), updated = [], expected = {}, i, findAfterEditSuccess,
+    findAfterEditError, updateError, findSuccess, findError, filter;
+
+setup_contents(t, t.step_func(function () {
+    findAfterEditSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_equals(contents.length, 2, "Media items after edit not found");
+        assert_equals(contents[0].name, expected[contents[0].id], "name should be changed");
+        assert_equals(contents[1].name, expected[contents[1].id ], "name should be changed");
+        t.done();
+    });
+
+    findAfterEditError = t.step_func(function (error) {
+        assert_unreached("find() (after updateBatch()) error callback invoked: " + error.name + ", message: " + error.message);
+    });
+
+    updateError = t.step_func(function (error) {
+        assert_unreached("updateBatch() error callback invoked: " + error.name + ", message: " + error.message);
+    });
+
+    findSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 1, "At least two media items are needed");
+
+        for (i = 0; i < contents.length; i++) {
+            if (contents[i].editableAttributes.indexOf("name") >= 0) {
+                updated.push(contents[i]);
+            }
+        }
+
+        assert_greater_than(contents.length, 1,
+            "At least two media items with editable 'name' attribute are needed");
+
+        updated[0].name += "update";
+        expected[updated[0].id] =  updated[0].name;
+
+        updated[1].name += "update";
+        expected[updated[1].id] =  updated[1].name;
+
+        tizen.content.updateBatch(updated, function () {
+            filter = new tizen.CompositeFilter("UNION", [
+                new tizen.AttributeFilter("id", "EXACTLY", updated[0].id),
+                new tizen.AttributeFilter("id", "EXACTLY", updated[1].id)
+            ]);
+
+            tizen.content.find(findAfterEditSuccess, findAfterEditError, null, filter);
+        }, updateError);
+    });
+
+    findError = t.step_func(function (error) {
+        assert_unreached("find() error callback invoked: " + error.name + ", message: " + error.message);
+    });
+
+    tizen.content.find(findSuccess, findError);
+}));
+
+}
+
+function ContentManager_updateBatch_video_geolocation() {
+//==== TEST: ContentManager_updateBatch_video_geolocation
+//==== LABEL Check if updateBatch() properly updates name attributes of multiple video items
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentManager:updateBatch M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA MAST MOA
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_updateBatch_video_geolocation', {timeout: 30000}), updated = [], expected = {}, i, findAfterEditSuccess,
+    findAfterEditError, updateError, findSuccess, findError, typeFilter, filter;
+
+setup_contents(t, t.step_func(function () {
+    findAfterEditSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_equals(contents.length, 1, "Media item after edit should be found");
+
+        assert_equals(contents[0].geolocation.latitude, expected[contents[0].id].latitude, "latitude should be changed");
+        assert_equals(contents[0].geolocation.longitude, expected[contents[0].id].longitude, "longitude should be changed");
+
+        t.done();
+    });
+
+    findAfterEditError = t.step_func(function (error) {
+        assert_unreached("find() (after updateBatch()) error callback invoked: " + error.name + ", message: " + error.message);
+    });
+
+    updateError = t.step_func(function (error) {
+        assert_unreached("updateBatch() error callback invoked: " + error.name + ", message: " + error.message);
+    });
+
+    findSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "At least one media items is needed");
+
+        for (i = 0; i < contents.length; i++) {
+            if (contents[i].editableAttributes.indexOf("geolocation") >= 0) {
+                updated.push(contents[i]);
+                break;
+            }
+        }
+        assert_greater_than(contents.length, 0, "At least one media item with editable 'geolocation' attribute is needed");
+
+        if (updated[0].geolocation !== null) {
+            if (updated[0].geolocation.latitude === 5) {
+                updated[0].geolocation.latitude = 6;
+            } else {
+                updated[0].geolocation.latitude = 5;
+            }
+            if (updated[0].geolocation.longitude === 5) {
+                updated[0].geolocation.longitude = 6;
+            } else {
+                updated[0].geolocation.longitude = 5;
+            }
+        } else {
+            updated[0].geolocation = new tizen.SimpleCoordinates(5.555, 5.555);
+        }
+        expected[updated[0].id] = updated[0].geolocation;
+
+        tizen.content.updateBatch(updated, function () {
+            filter = new tizen.AttributeFilter("id", "EXACTLY", updated[0].id);
+            tizen.content.find(findAfterEditSuccess, findAfterEditError, null, filter);
+        }, updateError);
+    });
+
+    findError = t.step_func(function (error) {
+        assert_unreached("find() error callback invoked: " + error.name + ", message: " + error.message);
+    });
+
+    typeFilter = new tizen.AttributeFilter("type", "EXACTLY", "VIDEO");
+    tizen.content.find(findSuccess, findError, null, typeFilter);
+}));
+
+}
+
+function ContentManager_updateBatch_image_geolocation() {
+//==== TEST: ContentManager_updateBatch_image_geolocation
+//==== LABEL Check if updateBatch() properly updates geolocation attributes of multiple image items
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentManager:updateBatch M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA MAST MOA
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_updateBatch_image_geolocation', {timeout: 30000}), updated = [], expected = {}, i, findAfterEditSuccess,
+    findAfterEditError, updateError, findSuccess, findError, typeFilter, filter;
+
+setup_contents(t, t.step_func(function () {
+    findAfterEditSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_equals(contents.length, 2, "Media items after edit should be found.");
+
+        assert_equals(contents[0].geolocation.latitude, expected[contents[0].id].latitude, "latitude should be changed");
+        assert_equals(contents[0].geolocation.longitude, expected[contents[0].id].longitude, "longitude should be changed");
+        assert_equals(contents[1].geolocation.latitude, expected[contents[1].id].latitude, "latitude should be changed");
+        assert_equals(contents[1].geolocation.longitude, expected[contents[1].id].longitude, "longitude should be changed");
+        t.done();
+    });
+
+    findAfterEditError = t.step_func(function (error) {
+        assert_unreached("find() (after updateBatch()) error callback invoked: " + error.name + ", message: " + error.message);
+    });
+
+    updateError = t.step_func(function (error) {
+        assert_unreached("updateBatch() error callback invoked: " + error.name + ", message: " + error.message);
+    });
+
+    findSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 1, "At least two images should be found.");
+
+        for (i = 0; i < contents.length; i++) {
+            if (contents[i].editableAttributes.indexOf("geolocation") >= 0) {
+                updated.push(contents[i]);
+            }
+        }
+        assert_greater_than(contents.length, 1, "At least two images with editable 'geolocation' attribute are needed");
+
+        if (updated[0].geolocation !== null) {
+            if (updated[0].geolocation.latitude === 5) {
+                updated[0].geolocation.latitude = 6;
+            } else {
+                updated[0].geolocation.latitude = 5;
+            }
+            if (updated[0].geolocation.longitude === 5) {
+                updated[0].geolocation.longitude = 6;
+            } else {
+                updated[0].geolocation.longitude = 5;
+            }
+        } else {
+            updated[0].geolocation = new tizen.SimpleCoordinates(5.555, 5.55555);
+        }
+        expected[updated[0].id] =  updated[0].geolocation;
+
+        if (updated[1].geolocation !== null) {
+            if (contents[1].geolocation.latitude === 5) {
+                contents[1].geolocation.latitude = 6;
+            } else {
+                contents[1].geolocation.latitude = 5;
+            }
+            if (contents[1].geolocation.longitude === 5) {
+                contents[1].geolocation.longitude = 6;
+            } else {
+                contents[1].geolocation.longitude = 5;
+            }
+        } else {
+            updated[1].geolocation = new tizen.SimpleCoordinates(5.555, 5.555);
+        }
+        expected[updated[1].id] =  updated[1].geolocation;
+
+        tizen.content.updateBatch(updated, function () {
+            filter = new tizen.CompositeFilter("UNION", [
+                new tizen.AttributeFilter("id", "EXACTLY", updated[0].id),
+                new tizen.AttributeFilter("id", "EXACTLY", updated[1].id)
+            ]);
+
+            tizen.content.find(findAfterEditSuccess, findAfterEditError, null, filter);
+        }, updateError);
+    });
+    findError = t.step_func(function (error) {
+        assert_unreached("find() error callback invoked: " + error.name + ", message: " + error.message);
+    });
+
+    typeFilter = new tizen.AttributeFilter("type", "EXACTLY", "IMAGE");
+    tizen.content.find(findSuccess, findError, null, typeFilter);
+}));
+
+}
+
+function ContentManager_updateBatch_image_orientation() {
+//==== TEST: ContentManager_updateBatch_image_orientation
+//==== LABEL Check if updateBatch() properly updates orientation attributes of multiple image items
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentManager:updateBatch M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA MAST MOA
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_updateBatch_image_orientation', {timeout: 30000}), updated = [], expected = {}, i, findAfterEditSuccess,
+    findAfterEditError, updateError, findSuccess, findError, filter;
+
+setup_contents(t, t.step_func(function () {
+
+    findAfterEditSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_equals(contents.length, 2, "Media items after edit should br found");
+        assert_equals(contents[0].orientation, expected[contents[0].id], "orientation should be changed");
+        assert_equals(contents[1].orientation, expected[contents[1].id ], "orientation should be changed");
+        t.done();
+    });
+
+    findAfterEditError = t.step_func(function (error) {
+        assert_unreached("find() (after updateBatch()) error callback invoked: " + error.name + ", message: " + error.message);
+    });
+
+    updateError = t.step_func(function (error) {
+        assert_unreached("updateBatch() error callback invoked: " + error.name + ", message: " + error.message);
+    });
+
+    findSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 1, "At least two images should be found.");
+        for (i = 0; i < contents.length; i++) {
+            if (contents[i].editableAttributes.indexOf("orientation") >= 0) {
+                updated.push(contents[i]);
+            }
+        }
+
+        assert_greater_than(contents.length, 1,
+            "At least two media items with editable 'orientation' attribute are needed");
+
+        if (updated[0].orientation === "NORMAL") {
+            updated[0].orientation = "FLIP_HORIZONTAL";
+        } else {
+            updated[0].orientation = "NORMAL";
+        }
+        expected[updated[0].id] =  updated[0].orientation;
+
+        if (updated[1].orientation === "NORMAL") {
+            updated[1].orientation = "FLIP_HORIZONTAL";
+        } else {
+            updated[1].orientation = "NORMAL";
+        }
+        expected[updated[1].id] =  updated[1].orientation;
+
+        tizen.content.updateBatch(updated, function () {
+            filter = new tizen.CompositeFilter("UNION", [
+                new tizen.AttributeFilter("id", "EXACTLY", updated[0].id),
+                new tizen.AttributeFilter("id", "EXACTLY", updated[1].id)
+            ]);
+
+            tizen.content.find(findAfterEditSuccess, findAfterEditError, null, filter);
+        }, updateError);
+    });
+
+    findError = t.step_func(function (error) {
+        assert_unreached("find() error callback invoked: " + error.name + ", message: " + error.message);
+    });
+
+    tizen.content.find(findSuccess, findError);
+}));
+
+}
+
+function ContentManager_setChangeListener() {
+//==== TEST: ContentManager_setChangeListener
+//==== LABEL Check if setChangeListener method works properly
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentManager:setChangeListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA MMINA MAST MR
+
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_setChangeListener', {timeout: 30000}), onSuccess, onError,
+    changeCallback, returnedValue = null, filter, description = "changeCallback_"+ new Date().getTime();
+t.step(function () {
+    //cleanup after TC
+    add_result_callback(function () {
+        try {
+            tizen.content.unsetChangeListener();
+        } catch (err) {}
+    });
+
+    changeCallback = {
+        oncontentadded: t.step_func(function (content) {
+
+        }),
+        oncontentupdated: t.step_func(function (content) {
+            assert_equals(content.description, description,
+                "updated content has wrong value.");
+            assert_equals(returnedValue, undefined,
+                "setChangeListener should return undefined.");
+
+            t.done();
+        }),
+        oncontentremoved: t.step_func(function (id) {
+
+        })
+    };
+    onSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "media item is not found");
+
+        contents[0].description = description;
+        tizen.content.update(contents[0]);
+    });
+    onError = t.step_func(function (error) {
+        assert_unreached("find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+    returnedValue = tizen.content.setChangeListener(changeCallback);
+    filter = new tizen.AttributeFilter("description", "EXISTS");
+    tizen.content.find(onSuccess, onError, null, filter);
+});
+
+}
+
+function ContentManager_updateBatch_without_callback() {
+//==== TEST: ContentManager_updateBatch_without_callback
+//==== LABEL Check if updateBatch called without callback is invoked properly
+//==== ONLOAD_DELAY 30
+//==== SPEC: Tizen Web API:Content:Content:ContentManager:updateBatch M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA MMINA MR
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_updateBatch_without_callback', {timeout: 30000}),
+    findSuccess, findError, content, returnedValue = null;
+
+setup_contents(t, t.step_func(function () {
+    findError = t.step_func(function (error) {
+        assert_unreached("find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    findSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "Media item should be found.");
+
+        content = contents[0];
+        if (content.editableAttributes.indexOf("rating") === 5) {
+            content.rating = 6;
+        } else {
+            content.rating = 5;
+        }
+
+        returnedValue = tizen.content.updateBatch([content]);
+        assert_equals(returnedValue, undefined,
+            "updateBatch should return undefined.");
+        t.done();
+    });
+
+    tizen.content.find(findSuccess, findError);
+}));
+
+}
+
+function ContentManagerObject_notexist() {
+//==== TEST: ContentManagerObject_notexist
+//==== LABEL Check if ContentManagerObject cannot be called in new expression
+//==== PRIORITY P3
+//==== SPEC Tizen Web API:Content:Content:ContentManagerObject:ContentManagerObject U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== TEST_CRITERIA NIO
+test(function () {
+    check_no_interface_object("ContentManagerObject");
+}, 'ContentManagerObject_notexist');
+
+}
+
+function ContentManager_find_filter_attribute_invalid() {
+//==== TEST: ContentManager_find_filter_attribute_invalid
+//==== LABEL Check if find throws exception when filter is a simple object
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentManager:find M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTO
+
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_find_filter_attribute_invalid', {timeout: 30000}), successCallback, errorCallback, filter;
+
+t.step(function () {
+    successCallback = t.step_func(function (contents) {
+        assert_unreached("find() success callback should not be invoked.");
+    });
+
+    errorCallback = t.step_func(function (error) {
+        assert_unreached("find() error callback should not be invoked: " + error.name + ": " + error.message);
+    });
+
+    filter = {
+        attributeName: "type",
+        matchFlag: "EXACTLY",
+        matchValue: "IMAGE"
+    };
+
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+            tizen.content.find(successCallback, errorCallback, null, filter);
+        }, "Given incorrect filter.");
+    t.done();
+});
+
+}
+
+function ContentScanSuccessCallback_onsuccess_contentURI() {
+//==== TEST: ContentScanSuccessCallback_onsuccess_contentURI
+//==== LABEL Check contentURI in ContentScanSuccessCallback onsuccess
+//==== ONLOAD_DELAY 30
+//==== SPEC: Tizen Web API:Content:Content:ContentScanSuccessCallback:onsuccess M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY: P1
+//==== TEST_CRITERIA CBOA
+
+setup({timeout: 30000});
+
+var t = async_test('ContentScanSuccessCallback_onsuccess_contentURI', {timeout: 30000}), onSuccess, onError, onSuccessCB, onErrorCB;
+
+t.step(function () {
+    onErrorCB = t.step_func(function (error) {
+        assert_unreached("Find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    onSuccessCB = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "media item is not found");
+
+        onSuccess = t.step_func(function (directoryURI) {
+            assert_equals(directoryURI, contents[0].contentURI, "Invalid content directoryURI passed");
+            t.done();
+        });
+
+        onError = t.step_func(function (error) {
+            assert_unreached("scanFile error callback was invoked: " + error.name + " msg: " + error.message);
+        });
+
+        tizen.content.scanFile(contents[0].contentURI, onSuccess, onError);
+    });
+
+    tizen.content.find(onSuccessCB, onErrorCB);
+});
+
+}
+
+function ContentChangeCallback_oncontentremoved_id_type() {
+//==== TEST: ContentChangeCallback_oncontentremoved_id_type
+//==== LABEL Check if ContentChangeCallback oncontentremoved is called and if its arguments have proper type
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentChangeCallback:oncontentremoved M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY: P1
+//==== TEST_CRITERIA CBOA
+
+setup({timeout: 30000});
+
+var t = async_test('ContentChangeCallback_oncontentremoved_id_type', {timeout: 30000}),
+    contentDirectory, sharedDirectory, addedImagePath = SHARED_STORAGE_PATH + "/ContentChangeCallback_oncontentremoved.png",
+    addedContent, changeCallback, onCopySuccess, onCopyError, onDeleteSuccess, onDeleteError,
+    onScanSuccess, onScanError;
+
+add_result_callback(function (result) {
+    sharedDirectory.deleteFile(addedImagePath);
+});
+
+t.step(function () {
+    //cleanup after TC
+    add_result_callback(function () {
+        try {
+            tizen.content.unsetChangeListener();
+        } catch (err) {}
+    });
+
+    changeCallback = {
+        oncontentadded: t.step_func(function (content) {
+            addedContent = content;
+        }),
+        oncontentremoved: t.step_func(function (id) {
+            assert_type(id, "string", "Content ID should be a string");
+            t.done();
+        })
+    };
+
+    onDeleteSuccess = t.step_func(function () {
+        tizen.content.scanFile("file://" + addedImagePath);
+    });
+
+    onDeleteError = t.step_func(function () {
+        assert_unreached("Failed to delete a file: " + addedImagePath);
+    });
+
+    onScanSuccess = t.step_func(function () {
+        tizen.filesystem.resolve(
+            "file://" + SHARED_STORAGE_PATH,
+            function (directory) {
+                sharedDirectory = directory;
+                sharedDirectory.deleteFile(addedImagePath, onDeleteSuccess, onDeleteError);
+            },
+            function (error) {
+                assert_unreached("Failed to resolve a directory with message" + error.message);
+            },
+            "rw"
+        );
+    });
+
+    onScanError = t.step_func(function () {
+        assert_unreached("Failed to scan a file: " + addedImagePath);
+    });
+
+    onCopySuccess = t.step_func(function () {
+        tizen.content.scanFile("file://"+addedImagePath, onScanSuccess, onScanError);
+    });
+
+    onCopyError = t.step_func(function () {
+        assert_unreached("Failed to copy a file to " + addedImagePath);
+    });
+
+    tizen.content.setChangeListener(changeCallback);
+    tizen.filesystem.resolve(
+        "file://" + TEST_CONTENT_DIR_PATH,
+        function (directory) {
+            contentDirectory = directory;
+            contentDirectory.copyTo(TEST_CONTENT_DIR_PATH + TEST_CONTENT_IMAGES[0], addedImagePath, true, onCopySuccess, onCopyError);
+        },
+        function (error) {
+            assert_unreached("Failed to resolve a directory with message" + error.message);
+        },
+        "r"
+    );
+});
+
+}
+
+function Content_in_tizen() {
+//==== TEST: Content_in_tizen
+//==== LABEL Check if content exists in tizen.
+//==== SPEC Web API:Content:Content:Content:Content U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA OBME
+
+test(function () {
+    assert_true("content" in tizen, "No content in tizen.")
+    check_readonly(tizen, "content", tizen.content, "object", "dummyValue");
+}, 'Content_in_tizen');
+
+}
+
+function ContentManager_createPlaylist_exist() {
+//==== TEST: ContentManager_createPlaylist_exist
+//==== LABEL Check if createPlaylist exists
+//==== SPEC Tizen Web API:Content:Content:ContentManager:createPlaylist M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    assert_true("createPlaylist" in tizen.content, "ContentManager should have createPlaylist method");
+    check_method_exists(tizen.content, "createPlaylist");
+}, 'ContentManager_createPlaylist_exist');
+
+}
+
+function ContentManager_createPlaylist() {
+//==== TEST: ContentManager_createPlaylist
+//==== LABEL Check if ContentManager createPlaylist method without optional arguments works properly
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentManager:createPlaylist M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MMINA MR
+
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_createPlaylist', {timeout: 30000}),
+    createSuccess, removePlaylistSuccess, removePlaylistFail, retVal = null;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        assert_equals(retVal, undefined, "createPlaylist should return undefined");
+        tizen.content.removePlaylist(playlist.id, removePlaylistSuccess, removePlaylistFail);
+    });
+
+    retVal = tizen.content.createPlaylist(randomString(5), createSuccess);
+});
+
+}
+
+function ContentManager_createPlaylist_misarg() {
+//==== TEST: ContentManager_createPlaylist_misarg
+//==== LABEL Check if createPlaylist method called with missing non-optional argument throws an exception
+//==== SPEC Tizen Web API:Content:Content:ContentManager:createPlaylist M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MMA
+
+test(function () {
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        tizen.content.createPlaylist("newPlaylist");
+    }, "Invoked with non-optional arguments.");
+}, 'ContentManager_createPlaylist_misarg');
+
+}
+
+function ContentManager_createPlaylist_successCallback_TypeMismatch() {
+//==== TEST: ContentManager_createPlaylist_successCallback_TypeMismatch
+//==== LABEL Check if createPlaylist throws exception when successCallback is incorrect
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentManager:createPlaylist M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_createPlaylist_successCallback_TypeMismatch', {timeout: 30000}), conversionTable, successCallback, errorCallback, exceptionName, i;
+
+t.step(function () {
+    conversionTable = getTypeConversionExceptions("functionObject", true);
+
+    errorCallback = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    for (i = 0; i < conversionTable.length; i++) {
+        successCallback = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+        assert_throws({name: exceptionName},
+            function () {
+                tizen.content.createPlaylist("My new playlist", successCallback, errorCallback);
+            }, "Given incorrect success callback.");
+    }
+
+    t.done();
+});
+
+}
+
+function ContentManager_createPlaylist_successCallback_invalid_cb() {
+//==== TEST: ContentManager_createPlaylist_successCallback_invalid_cb
+//==== LABEL Check if createPlaylist throws exception when success callback is invalid
+//==== SPEC Tizen Web API:Content:Content:ContentManager:createPlaylist M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTCB
+
+test(function () {
+    var incorrectCallback;
+
+    incorrectCallback = {
+        onsuccess: function (playlist) {
+            assert_unreached("Invalid success callback invoked.");
+        }
+    };
+
+    assert_throws(TYPE_MISMATCH_EXCEPTION,
+        function () {
+            tizen.content.createPlaylist("newplaylist", incorrectCallback);
+        }, "Given invalid successCallback.");
+
+}, 'ContentManager_createPlaylist_successCallback_invalid_cb');
+
+}
+
+function ContentManager_createPlaylist_errorCallback_invoked() {
+//==== TEST: ContentManager_createPlaylist_errorCallback_invoked
+//==== LABEL Check if ContentManager createPlaylist method with invalid arguments would invoke errorCallback
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentManager:createPlaylist M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MERRCB
+
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_createPlaylist_errorCallback_invoked', {timeout: 30000}), createSuccess, createFail;
+
+t.step(function () {
+    createSuccess = t.step_func(function (playlist) {
+        assert_unreached("createPlaylist() success callback unreachable");
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_equals(error.name, "InvalidValuesError", "Incorrect error name");
+        assert_type(error.message, "string", "Error message is not a string");
+        assert_not_equals(error.message, "","Error message is empty");
+        t.done();
+    });
+
+    tizen.content.createPlaylist("", createSuccess, createFail);
+});
+
+}
+
+function ContentManager_createPlaylist_errorCallback_TypeMismatch() {
+//==== TEST: ContentManager_createPlaylist_errorCallback_TypeMismatch
+//==== LABEL Check if createPlaylist throws exception when errorCallback is incorrect
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentManager:createPlaylist M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_createPlaylist_errorCallback_TypeMismatch', {timeout: 30000}), conversionTable, successCallback, errorCallback, exceptionName, i;
+
+t.step(function () {
+    conversionTable = getTypeConversionExceptions("functionObject", true);
+
+    successCallback = t.step_func(function (playlist) {
+        assert_unreached("createPlaylist() success callback should not be invoked.");
+    });
+
+    for (i = 0; i < conversionTable.length; i++) {
+        errorCallback = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+        assert_throws({name: exceptionName},
+            function () {
+                tizen.content.createPlaylist("My new playlist", successCallback, errorCallback);
+            }, "Given incorrect error callback.");
+    }
+
+    t.done();
+});
+
+}
+
+function ContentManager_createPlaylist_errorCallback_invalid_cb() {
+//==== TEST: ContentManager_createPlaylist_errorCallback_invalid_cb
+//==== LABEL Check if createPlaylist throws exception when errorCallback is invalid
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentManager:createPlaylist M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_createPlaylist_errorCallback_invalid_cb', {timeout: 30000}), successCallback, incorrectCallback;
+
+t.step(function () {
+    incorrectCallback = {
+        onerror: t.step_func(function (error) {
+            assert_unreached("Invalid error callback invoked:" + error.name + ": " + error.message);
+        })
+    };
+
+    successCallback = t.step_func(function (playlist) {
+        assert_unreached("createPlaylist() success callback should not be invoked.");
+    });
+
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        tizen.content.createPlaylist("newplaylist", successCallback, incorrectCallback);
+    }, "Given incorrect errorCallback.");
+
+    t.done();
+});
+
+}
+
+function ContentManager_createPlaylist_noarg() {
+//==== TEST: ContentManager_createPlaylist_noarg
+//==== LABEL Check if createPlaylist method called with missing non-optional argument throws an exception
+//==== SPEC Tizen Web API:Content:Content:ContentManager:createPlaylist M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MMA
+
+test(function () {
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        tizen.content.createPlaylist();
+    }, "Invoked with non-optional arguments.");
+}, 'ContentManager_createPlaylist_noarg');
+
+}
+
+function ContentManager_createPlaylist_sourcePlaylist_TypeMismatch() {
+//==== TEST: ContentManager_createPlaylist_sourcePlaylist_TypeMismatch
+//==== LABEL Check if createPlaylist throws exception when sourcePlaylist is incorrect
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentManager:createPlaylist M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_createPlaylist_sourcePlaylist_TypeMismatch', {timeout: 30000}), conversionTable, successCallback, errorCallback, exceptionName, i, sourcePlaylist;
+
+t.step(function () {
+    conversionTable = getTypeConversionExceptions("object", true);
+
+    successCallback = t.step_func(function (playlist) {
+        assert_unreached("createPlaylist() success callback should not be invoked.");
+    });
+
+    errorCallback = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback should not be invoked.");
+    });
+
+    for (i = 0; i < conversionTable.length; i++) {
+        sourcePlaylist = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+        assert_throws({name: exceptionName},
+            function () {
+                tizen.content.createPlaylist("My new playlist", successCallback, errorCallback, sourcePlaylist);
+            }, "Given incorrect error callback.");
+    }
+
+    t.done();
+});
+
+}
+
+function ContentManager_getPlaylists() {
+//==== TEST: ContentManager_getPlaylists
+//==== LABEL Check if ContentManager getPlaylists method without optional error callback works properly
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentManager:getPlaylists M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MMINA MR
+
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_getPlaylists', {timeout: 30000}), successCallback, createSuccess, createFail, gPlaylist, removePlaylistSuccess, retVal = null;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    successCallback = t.step_func(function (playlists) {
+        assert_equals(retVal, undefined, "getPlaylists should return undefined");
+        tizen.content.removePlaylist(gPlaylist.id, removePlaylistSuccess);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        gPlaylist = playlist;
+        retVal = tizen.content.getPlaylists(successCallback);
+    });
+
+    createFail = t.step_func(function (error) {
+       assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function ContentManager_getPlaylists_exist() {
+//==== TEST: ContentManager_getPlaylists_exist
+//==== LABEL Check if getPlaylists exists
+//==== SPEC Tizen Web API:Content:Content:ContentManager:getPlaylists M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    assert_true("getPlaylists" in tizen.content, "ContentManager should have getPlaylists method");
+    check_method_exists(tizen.content, "getPlaylists");
+}, 'ContentManager_getPlaylists_exist');
+
+}
+
+function ContentManager_getPlaylists_misarg() {
+//==== TEST: ContentManager_getPlaylists_misarg
+//==== LABEL Check if getPlaylists method called with missing non-optional argument throws an exception
+//==== SPEC Tizen Web API:Content:Content:ContentManager:getPlaylists M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MMA
+
+test(function () {
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        tizen.content.getPlaylists();
+    }, "Invoked with non-optional arguments.");
+}, 'ContentManager_getPlaylists_misarg');
+
+}
+
+function ContentManager_getPlaylists_with_errorCallback() {
+//==== TEST: ContentManager_getPlaylists_with_errorCallback
+//==== LABEL Check if ContentManager getPlaylists method with optional error callback is invoked properly
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentManager:getPlaylists M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MOA MR
+
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_getPlaylists_with_errorCallback', {timeout: 30000}), successCallback, errorCallback, createSuccess, createFail, removePlaylistSuccess, gPlaylist, retVal = null;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    successCallback = t.step_func(function (playlists) {
+        assert_equals(retVal, undefined, "getPlaylists should return undefined");
+        tizen.content.removePlaylist(gPlaylist.id, removePlaylistSuccess);
+    });
+
+    errorCallback = t.step_func(function (error) {
+        assert_unreached("getPlaylists() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        gPlaylist = playlist;
+        retVal = tizen.content.getPlaylists(successCallback, errorCallback);
+    });
+
+    createFail = t.step_func(function (error) {
+       assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function ContentManager_getPlaylists_errorCallback_TypeMismatch() {
+//==== TEST: ContentManager_getPlaylists_errorCallback_TypeMismatch
+//==== LABEL Check if getPlaylists throws exception when errorCallback is incorrect
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentManager:getPlaylists M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_getPlaylists_errorCallback_TypeMismatch', {timeout: 30000}), conversionTable, successCallback, errorCallback, exceptionName, i;
+
+t.step(function () {
+    conversionTable = getTypeConversionExceptions("functionObject", true);
+
+    successCallback = t.step_func(function () {
+        assert_unreached("getPlaylists() success callback should not be invoked.");
+    });
+
+    for (i = 0; i < conversionTable.length; i++) {
+        errorCallback = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+        assert_throws({name: exceptionName},
+            function () {
+                tizen.content.getPlaylists(successCallback, errorCallback);
+            }, "Given incorrect error callback.");
+    }
+
+    t.done();
+});
+
+}
+
+function ContentManager_getPlaylists_errorCallback_invalid_cb() {
+//==== TEST: ContentManager_getPlaylists_errorCallback_invalid_cb
+//==== LABEL Check if getPlaylists throws exception when errorCallback is invalid
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentManager:getPlaylists M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_getPlaylists_errorCallback_invalid_cb', {timeout: 30000}), successCallback, incorrectCallback;
+
+t.step(function () {
+
+    incorrectCallback = {
+        onerror: t.step_func(function (error) {
+            assert_unreached("Invalid error callback invoked:" + error.name + ": " + error.message);
+        })
+    };
+
+    successCallback = t.step_func(function () {
+        assert_unreached("getPlaylists() success callback should not be invoked.");
+    });
+
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        tizen.content.getPlaylists(successCallback, incorrectCallback);
+    }, "Given incorrect errorCallback.");
+
+    t.done();
+});
+
+}
+
+function ContentManager_getPlaylists_successCallback_TypeMismatch() {
+//==== TEST: ContentManager_getPlaylists_successCallback_TypeMismatch
+//==== LABEL Check if getPlaylists throws exception when successCallback is incorrect
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentManager:getPlaylists M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_getPlaylists_successCallback_TypeMismatch', {timeout: 30000}), conversionTable, successCallback, errorCallback, exceptionName, i;
+
+t.step(function () {
+    conversionTable = getTypeConversionExceptions("functionObject", true);
+
+    errorCallback = t.step_func(function (error) {
+        assert_unreached("getPlaylists() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    for (i = 0; i < conversionTable.length; i++) {
+        successCallback = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+        assert_throws({name: exceptionName},
+            function () {
+                tizen.content.getPlaylists(successCallback, errorCallback);
+            }, "Given incorrect success callback.");
+    }
+
+    t.done();
+});
+
+}
+
+function ContentManager_getPlaylists_successCallback_invalid_cb() {
+//==== TEST: ContentManager_getPlaylists_successCallback_invalid_cb
+//==== LABEL Check if getPlaylists throws exception when success callback is invalid
+//==== SPEC Tizen Web API:Content:Content:ContentManager:getPlaylists M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTCB
+
+test(function () {
+    var incorrectCallback;
+
+    incorrectCallback = {
+        onsuccess: function (playlists) {
+            assert_unreached("Invalid success callback invoked.");
+        }
+    };
+
+    assert_throws(TYPE_MISMATCH_EXCEPTION,
+        function () {
+            tizen.content.getPlaylists(incorrectCallback);
+        }, "Given invalid successCallback.");
+
+}, 'ContentManager_getPlaylists_successCallback_invalid_cb');
+
+}
+
+function ContentManager_removePlaylist_exist() {
+//==== TEST: ContentManager_removePlaylist_exist
+//==== LABEL Check if removePlaylist exists
+//==== SPEC Tizen Web API:Content:Content:ContentManager:removePlaylist M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    assert_true("removePlaylist" in tizen.content, "ContentManager should have removePlaylist method");
+    check_method_exists(tizen.content, "removePlaylist");
+}, 'ContentManager_removePlaylist_exist');
+
+}
+
+function ContentManager_removePlaylist() {
+//==== TEST: ContentManager_removePlaylist
+//==== LABEL Check if ContentManager removePlaylist method without optional arguments works properly
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentManager:removePlaylist M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MMINA MR
+
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_removePlaylist', {timeout: 30000}),
+    createSuccess, createFail, removePlaylistSuccess, retVal = null;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        assert_equals(retVal, undefined, "removePlaylist should return undefined");
+        t.done();
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        retVal = tizen.content.removePlaylist(playlist.id, removePlaylistSuccess);
+    });
+
+    createFail = t.step_func(function (error) {
+       assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function ContentManager_removePlaylist_with_errorCallback() {
+//==== TEST: ContentManager_removePlaylist_with_errorCallback
+//==== LABEL Check if ContentManager removePlaylist method with optional arguments works properly
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentManager:removePlaylist M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MOA MAST
+
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_removePlaylist_with_errorCallback', {timeout: 30000}),
+    createSuccess, createFail, successCallback, errorCallback, removePlaylistSuccess, removePlaylistFail, successCb, errorCb,
+    beforelength = 0, afterlength = 0, id;
+
+t.step(function () {
+    successCb = t.step_func(function (playlists) {
+        afterlength = playlists.length;
+        assert_less_than(afterlength, beforelength, "length shoulddecrease");
+        assert_equals(afterlength, beforelength-1, "length should decrease");
+        t.done();
+    });
+
+    errorCb = t.step_func(function (error) {
+        assert_unreached("getPlaylists() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    removePlaylistSuccess = t.step_func(function () {
+        tizen.content.getPlaylists(successCb, errorCb);
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    successCallback = t.step_func(function (playlists) {
+        beforelength = playlists.length;
+        tizen.content.removePlaylist(id, removePlaylistSuccess, removePlaylistFail);
+    });
+
+    errorCallback = t.step_func(function (error) {
+        assert_unreached("getPlaylists() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        id = playlist.id;
+        tizen.content.getPlaylists(successCallback, errorCallback);
+    });
+
+    createFail = t.step_func(function (error) {
+       assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function ContentManager_removePlaylist_errorCallback_TypeMismatch() {
+//==== TEST: ContentManager_removePlaylist_errorCallback_TypeMismatch
+//==== LABEL Check if removePlaylist throws exception when successCallback is incorrect
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentManager:removePlaylist M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_removePlaylist_errorCallback_TypeMismatch', {timeout: 30000}),
+    createSuccess, createFail, exceptionName, conversionTable, i, successCallback, errorCallback, removePlaylistSuccess, removePlaylistFail;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    successCallback = t.step_func(function () {
+        assert_unreached("removePlaylist() success callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        conversionTable = getTypeConversionExceptions("functionObject", true);
+
+        for (i = 0; i < conversionTable.length; i++) {
+            errorCallback = conversionTable[i][0];
+            exceptionName = conversionTable[i][1];
+            assert_throws({name: exceptionName},
+                function () {
+                    tizen.content.removePlaylist(playlist.id, successCallback, errorCallback);
+            }, "Given incorrect success callback.");
+        }
+        tizen.content.removePlaylist(playlist.id, removePlaylistSuccess, removePlaylistFail)
+    });
+
+    createFail = t.step_func(function (error) {
+       assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function ContentManager_removePlaylist_errorCallback_invalid_cb() {
+//==== TEST: ContentManager_removePlaylist_errorCallback_invalid_cb
+//==== LABEL Check if removePlaylist throws exception when errorCallback is invalid
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:ContentManager:removePlaylist M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_removePlaylist_errorCallback_invalid_cb', {timeout: 30000}),
+    createSuccess, createFail, incorrectCallback, successCallback, removePlaylistSuccess, removePlaylistFail;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    incorrectCallback = {
+        onerror: function (error) {
+             assert_unreached("Invalid errorCallback invoked:" + error.name + " msg: " + error.message);
+        }
+    };
+
+    successCallback = t.step_func(function () {
+       assert_unreached("removePlaylist() success callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+            tizen.content.removePlaylist(playlist.id, successCallback, incorrectCallback);
+        }, "Given incorrect errorCallback.");
+        tizen.content.removePlaylist(playlist.id, removePlaylistSuccess, removePlaylistFail)
+    });
+
+    createFail = t.step_func(function (error) {
+       assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function ContentManager_removePlaylist_successCallback_TypeMismatch() {
+//==== TEST: ContentManager_removePlaylist_successCallback_TypeMismatch
+//==== LABEL Check if removePlaylist throws exception when success callback is invalid
+//==== SPEC Tizen Web API:Content:Content:ContentManager:removePlaylist M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_removePlaylist_successCallback_TypeMismatch', {timeout: 30000}),
+    createSuccess, createFail, exceptionName, conversionTable, i, successCallback, errorCallback, removePlaylistSuccess, removePlaylistFail;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    errorCallback = t.step_func(function (error) {
+        assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        conversionTable = getTypeConversionExceptions("functionObject", true);
+        for (i = 0; i < conversionTable.length; i++) {
+            successCallback = conversionTable[i][0];
+            exceptionName = conversionTable[i][1];
+            assert_throws({name: exceptionName},
+                function () {
+                    tizen.content.removePlaylist(playlist.id, successCallback, errorCallback);
+            }, "Given incorrect success callback.");
+        }
+        tizen.content.removePlaylist(playlist.id, removePlaylistSuccess, removePlaylistFail)
+    });
+
+    createFail = t.step_func(function (error) {
+       assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function ContentManager_removePlaylist_successCallback_invalid_cb() {
+//==== TEST: ContentManager_removePlaylist_successCallback_invalid_cb
+//==== LABEL Check if createPlaylist throws exception when successCallback is invalid
+//==== SPEC Tizen Web API:Content:Content:ContentManager:removePlaylist M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 30000});
+
+var t = async_test('ContentManager_removePlaylist_successCallback_invalid_cb', {timeout: 30000}),
+    createSuccess, createFail, incorrectCallback, removePlaylistSuccess, removePlaylistFail;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    incorrectCallback = {
+        onsuccess: function () {
+            assert_unreached("Invalid successCallback invoked.");
+        }
+    };
+
+    createSuccess = t.step_func(function (playlist) {
+        assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+            tizen.content.removePlaylist(playlist.id, incorrectCallback);
+        }, "Given incorrect successCallback.");
+        tizen.content.removePlaylist(playlist.id, removePlaylistSuccess, removePlaylistFail)
+    });
+
+    createFail = t.step_func(function (error) {
+       assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function Playlist_extend() {
+//==== TEST: Playlist_extend
+//==== LABEL Check if interface Playlist can have new properties
+//==== SPEC Tizen Web API:Content:Content:Playlist:Playlist U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA OBX
+
+setup({timeout: 30000});
+
+var t = async_test('Playlist_extend', {timeout: 30000}), createSuccess, createFail, removePlaylistSuccess, removePlaylistFail;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+        assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        check_extensibility(playlist);
+        tizen.content.removePlaylist(playlist.id, removePlaylistSuccess, removePlaylistFail);
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function Playlist_notexist() {
+//==== TEST: Playlist_notexist
+//==== LABEL Check if interface Playlist exists, it should not
+//==== SPEC Tizen Web API:Content:Content:Playlist:Playlist U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("Playlist");
+}, 'Playlist_notexist');
+
+}
+
+function Playlist_id_attribute() {
+//==== TEST: Playlist_id_attribute
+//==== LABEL Check if Playlist have id attribute with proper type and is readonly
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:Playlist:id A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ARO
+
+setup({timeout: 30000});
+
+var t = async_test('Playlist_id_attribute', {timeout: 30000}),
+    createSuccess, createFail, removePlaylistSuccess, removePlaylistFail;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+        assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        assert_own_property(playlist, "id", "playlist does not own id property.");
+        assert_type(playlist.id, "string", "id should be an string");
+        check_readonly(playlist, "id", playlist.id, "string", playlist.id + "abc");
+        tizen.content.removePlaylist(playlist.id, removePlaylistSuccess, removePlaylistFail);
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function Playlist_name_attribute() {
+//==== TEST: Playlist_name_attribute
+//==== LABEL Check if Playlist have name attribute with proper type
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:Playlist:name A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ASG AN
+
+setup({timeout: 30000});
+
+var t = async_test('Playlist_name_attribute', {timeout: 30000}),
+    createSuccess, createFail, removePlaylistSuccess, removePlaylistFail;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+        assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        assert_own_property(playlist, "name", "playlist does not own name property.");
+        assert_type(playlist.name, "string", "name should be an string");
+        check_attribute(playlist, "name", playlist.name, "string", playlist.name + "abc");
+        check_not_nullable(playlist, "name");
+        tizen.content.removePlaylist(playlist.id, removePlaylistSuccess, removePlaylistFail);
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function Playlist_numberOfTracks_attribute() {
+//==== TEST: Playlist_numberOfTracks_attribute
+//==== LABEL Check if Playlist have numberOfTracks attribute with proper type and is readonly
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:Playlist:numberOfTracks A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ARO
+
+setup({timeout: 30000});
+
+var t = async_test('Playlist_numberOfTracks_attribute', {timeout: 30000}),
+    createSuccess, createFail, removePlaylistSuccess, removePlaylistFail;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+        assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        assert_own_property(playlist, "numberOfTracks", "playlist does not own numberOfTracks property.");
+        assert_type(playlist.numberOfTracks, "long", "numberOfTracks should be an long");
+        check_readonly(playlist, "numberOfTracks", playlist.numberOfTracks, "long", playlist.numberOfTracks + 1);
+        tizen.content.removePlaylist(playlist.id, removePlaylistSuccess, removePlaylistFail);
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function Playlist_thumbnailURI_attribute() {
+//==== TEST: Playlist_thumbnailURI_attribute
+//==== LABEL Check if Playlist have thumbnailURI attribute with proper type
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:Playlist:thumbnailURI A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ASG ADV
+
+setup({timeout: 30000});
+
+var t = async_test('Playlist_thumbnailURI_attribute', {timeout: 30000}),
+    createSuccess, createFail, removePlaylistSuccess, removePlaylistFail;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+        assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        assert_own_property(playlist, "thumbnailURI", "playlist does not own thumbnailURI property.");
+        assert_equals(playlist.thumbnailURI, null, "playlist.thumbnailURI should be null by default.");
+        tizen.content.removePlaylist(playlist.id, removePlaylistSuccess, removePlaylistFail);
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function Playlist_add_exist() {
+//==== TEST: Playlist_add_exist
+//==== LABEL Check if add exists
+//==== SPEC Tizen Web API:Content:Content:Playlist:add M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+setup({timeout: 30000});
+
+var t = async_test('Playlist_add_exist', {timeout: 30000}),
+    createSuccess, createFail, removePlaylistSuccess, removePlaylistFail;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        assert_true("add" in playlist, "Playlist should have add method");
+        check_method_exists(playlist, "add");
+        tizen.content.removePlaylist(playlist.id, removePlaylistSuccess, removePlaylistFail);
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function Playlist_add() {
+//==== TEST: Playlist_add
+//==== LABEL Check if Playlist add method works properly
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:Playlist:add M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR MAST
+
+setup({timeout: 30000});
+
+var t = async_test('Playlist_add', {timeout: 30000}),
+    findSuccess, findFail, createSuccess, createFail,
+    removePlaylistSuccess, removePlaylistFail, gPlaylist, successCallback, errorCallback, i, retVal = null;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    successCallback = t.step_func(function (items) {
+        assert_equals(retVal, undefined, "add should return undefined");
+        assert_not_equals(items, 0, "items should not be 0");
+        tizen.content.removePlaylist(gPlaylist.id, removePlaylistSuccess, removePlaylistFail);
+    });
+
+    errorCallback = t.step_func(function (error) {
+       assert_unreached("get() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    findSuccess = t.step_func(function (contents) {
+        if (contents.length > 0) {
+            retVal = gPlaylist.add(contents[0]);
+        }
+        gPlaylist.get(successCallback, errorCallback);
+    });
+
+    findFail = t.step_func(function (error) {
+        assert_unreached("find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        gPlaylist = playlist;
+        tizen.content.find(findSuccess, findFail, null, new tizen.AttributeFilter("type", "EXACTLY", "AUDIO"));
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function Playlist_add_misarg() {
+//==== TEST: Playlist_add_misarg
+//==== LABEL Check if add method called with missing non-optional argument throws an exception
+//==== SPEC Tizen Web API:Content:Content:Playlist:add M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MMA
+
+setup({timeout: 30000});
+
+var t = async_test('Playlist_add_misarg', {timeout: 30000}),
+    createSuccess, createFail, removePlaylistSuccess, removePlaylistFail;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+            playlist.add();
+        }, "Invoked with non-optional arguments.");
+        tizen.content.removePlaylist(playlist.id, removePlaylistSuccess, removePlaylistFail);
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function Playlist_add_item_TypeMismatch() {
+//==== TEST: Playlist_add_item_TypeMismatch
+//==== LABEL Check if add throws exception when content is incorrect
+//==== SPEC Tizen Web API:Content:Content:Playlist:add M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test('Playlist_add_item_TypeMismatch', {timeout: 30000}),
+    createSuccess, createFail, conversionTable, item, exceptionName, i, removePlaylistSuccess, removePlaylistFail;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        conversionTable = getTypeConversionExceptions("object", false);
+        for (i = 0; i < conversionTable.length; i++) {
+            item = conversionTable[i][0];
+            exceptionName = conversionTable[i][1];
+            assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+                playlist.add(item);
+            }, "Invoked with non-optional arguments.");
+        }
+        tizen.content.removePlaylist(playlist.id, removePlaylistSuccess, removePlaylistFail);
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function Playlist_addBatch_exist() {
+//==== TEST: Playlist_addBatch_exist
+//==== LABEL Check if addBatch exists
+//==== SPEC Tizen Web API:Content:Content:Playlist:addBatch M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+setup({timeout: 30000});
+
+var t = async_test('Playlist_add_item_TypeMismatch', {timeout: 30000}),
+    createSuccess, createFail, removePlaylistSuccess, removePlaylistFail;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        assert_true("addBatch" in playlist, "Playlist should have addBatch method");
+        check_method_exists(playlist, "addBatch");
+        tizen.content.removePlaylist(playlist.id, removePlaylistSuccess, removePlaylistFail);
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function Playlist_addBatch() {
+//==== TEST: Playlist_addBatch
+//==== LABEL Check if Playlist addBatch method works properly
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:Playlist:addBatch M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR MAST MMINA
+
+setup({timeout: 30000});
+
+var t = async_test('Playlist_addBatch', {timeout: 30000}),
+    findSuccess, findFail, createSuccess, createFail, removePlaylistSuccess, removePlaylistFail, successCallback, errorCallback, gPlaylist ,retVal = null;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    successCallback = t.step_func(function (items) {
+        assert_equals(retVal, undefined, "addBatch should return undefined");
+        assert_not_equals(items, 0, "items should not be 0");
+        tizen.content.removePlaylist(gPlaylist.id, removePlaylistSuccess, removePlaylistFail);
+    });
+
+    errorCallback = t.step_func(function (error) {
+       assert_unreached("get() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    findSuccess = t.step_func(function (contents) {
+        if (contents.length > 2) {
+            retVal = gPlaylist.addBatch([contents[0], contents[1]]);
+        }
+        gPlaylist.get(successCallback, errorCallback);
+    });
+
+    findFail = t.step_func(function (error) {
+        assert_unreached("find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        gPlaylist = playlist;
+        tizen.content.find(findSuccess, findFail, null, new tizen.AttributeFilter("type", "EXACTLY", "AUDIO"));
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function Playlist_addBatch_misarg() {
+//==== TEST: Playlist_addBatch_misarg
+//==== LABEL Check if addBatch method called with missing non-optional argument throws an exception
+//==== SPEC Tizen Web API:Content:Content:Playlist:addBatch M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MMA
+
+setup({timeout: 30000});
+
+var t = async_test('Playlist_addBatch_misarg', {timeout: 30000}),
+    createSuccess, createFail, removePlaylistSuccess, removePlaylistFail;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+            playlist.addBatch();
+        }, "Invoked with non-optional arguments.");
+        tizen.content.removePlaylist(playlist.id, removePlaylistSuccess, removePlaylistFail);
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function Playlist_addBatch_items_TypeMismatch() {
+//==== TEST: Playlist_addBatch_items_TypeMismatch
+//==== LABEL Check if addBatch throws exception when content is incorrect
+//==== SPEC Tizen Web API:Content:Content:Playlist:addBatch M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test('Playlist_addBatch_items_TypeMismatch', {timeout: 30000}),
+    createSuccess, createFail, conversionTable, item, i, removePlaylistSuccess, removePlaylistFail;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        conversionTable = getTypeConversionExceptions("object", false);
+        for (i = 0; i < conversionTable.length; i++) {
+            item = conversionTable[i][0];
+            assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+                playlist.addBatch(item);
+            }, "Invoked with non-optional arguments.");
+        }
+        tizen.content.removePlaylist(playlist.id, removePlaylistSuccess, removePlaylistFail);
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function Playlist_addBatch_with_errorCallback() {
+//==== TEST: Playlist_addBatch_with_errorCallback
+//==== LABEL Check if Playlist addBatch method works properly with all optional arguments
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:Playlist:addBatch M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MOA
+
+setup({timeout: 30000});
+
+var t = async_test('Playlist_addBatch_with_errorCallback', {timeout: 30000}),
+    findSuccess, findFail, createSuccess, createFail, successCallback, errorCallback,
+    removePlaylistSuccess, removePlaylistFail, gPlaylist;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    successCallback = t.step_func(function () {
+        tizen.content.removePlaylist(gPlaylist.id, removePlaylistSuccess, removePlaylistFail);
+    });
+
+    errorCallback = t.step_func(function (error) {
+        assert_unreached("addBatch() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    findSuccess = t.step_func(function (contents) {
+        if (contents.length > 2) {
+            gPlaylist.addBatch([contents[0], contents[1]], successCallback, errorCallback);
+        }
+    });
+
+    findFail = t.step_func(function (error) {
+        assert_unreached("find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        gPlaylist = playlist;
+        tizen.content.find(findSuccess, findFail, null, new tizen.AttributeFilter("type", "EXACTLY", "AUDIO"));
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function Playlist_addBatch_errorCallback_TypeMismatch() {
+//==== TEST: Playlist_addBatch_errorCallback_TypeMismatch
+//==== LABEL Check if Playlist addBatch method throws exception when errorCallback is incorrect
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:Playlist:addBatch M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test('Playlist_addBatch_errorCallback_TypeMismatch', {timeout: 30000}),
+    findSuccess, findFail, createSuccess, createFail, successCallback, errorCallback, conversionTable, i, exceptionName,
+    removePlaylistSuccess, removePlaylistFail, gPlaylist;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    successCallback = t.step_func(function () {
+         assert_unreached("addBatch() success callback should not be invoked.");
+    });
+
+    findSuccess = t.step_func(function (contents) {
+        if (contents.length > 2) {
+            conversionTable = getTypeConversionExceptions("functionObject", true);
+            for (i = 0; i < conversionTable.length; i++) {
+                errorCallback = conversionTable[i][0];
+                exceptionName = conversionTable[i][1];
+                assert_throws({name: exceptionName},
+                    function () {
+                        gPlaylist.addBatch([contents[0], contents[1]], successCallback, errorCallback);
+                    }, "Given incorrect errorCallback.");
+            }
+        }
+        tizen.content.removePlaylist(gPlaylist.id, removePlaylistSuccess, removePlaylistFail);
+    });
+
+    findFail = t.step_func(function (error) {
+        assert_unreached("find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        gPlaylist = playlist;
+        tizen.content.find(findSuccess, findFail, null, new tizen.AttributeFilter("type", "EXACTLY", "AUDIO"));
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function Playlist_addBatch_errorCallback_invalid_cb() {
+//==== TEST: Playlist_addBatch_errorCallback_invalid_cb
+//==== LABEL Check if Playlist addBatch method throws exception when errorCallback is invalid
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:Playlist:addBatch M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 30000});
+
+var t = async_test('Playlist_addBatch_errorCallback_invalid_cb', {timeout: 30000}),
+    findSuccess, findFail, createSuccess, createFail, successCallback, incorrectCallback,
+    removePlaylistSuccess, removePlaylistFail, gPlaylist;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    incorrectCallback = {
+        onerror: function (error) {
+             assert_unreached("Invalid errorCallback invoked:" + error.name + " msg: " + error.message);
+        }
+    };
+
+    successCallback = t.step_func(function () {
+         assert_unreached("addBatch() success callback should not be invoked.");
+    });
+
+    findSuccess = t.step_func(function (contents) {
+        if (contents.length > 2) {
+            assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+                gPlaylist.addBatch([contents[0], contents[1]], successCallback, incorrectCallback);
+            }, "Given incorrect errorCallback.");
+        }
+        tizen.content.removePlaylist(gPlaylist.id, removePlaylistSuccess, removePlaylistFail);
+    });
+
+    findFail = t.step_func(function (error) {
+        assert_unreached("find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        gPlaylist = playlist;
+        tizen.content.find(findSuccess, findFail, null, new tizen.AttributeFilter("type", "EXACTLY", "AUDIO"));
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function Playlist_addBatch_successCallback_TypeMismatch() {
+//==== TEST: Playlist_addBatch_successCallback_TypeMismatch
+//==== LABEL Check if Playlist addBatch method throws exception when successCallback is incorrect
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:Playlist:addBatch M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test('Playlist_addBatch_successCallback_TypeMismatch', {timeout: 30000}),
+    findSuccess, findFail, createSuccess, createFail, successCallback, errorCallback, conversionTable, i, exceptionName,
+    removePlaylistSuccess, removePlaylistFail, gPlaylist;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    errorCallback = t.step_func(function () {
+         assert_unreached("addBatch() error callback should not be invoked.");
+    });
+
+    findSuccess = t.step_func(function (contents) {
+        if (contents.length > 2) {
+            conversionTable = getTypeConversionExceptions("functionObject", true);
+            for (i = 0; i < conversionTable.length; i++) {
+                successCallback = conversionTable[i][0];
+                exceptionName = conversionTable[i][1];
+                assert_throws({name: exceptionName},
+                    function () {
+                        gPlaylist.addBatch([contents[0], contents[1]], successCallback, errorCallback);
+                    }, "Given incorrect successCallback.");
+            }
+        }
+        tizen.content.removePlaylist(gPlaylist.id, removePlaylistSuccess, removePlaylistFail);
+    });
+
+    findFail = t.step_func(function (error) {
+        assert_unreached("find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        gPlaylist = playlist;
+        tizen.content.find(findSuccess, findFail, null, new tizen.AttributeFilter("type", "EXACTLY", "AUDIO"));
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function Playlist_addBatch_successCallback_invalid_cb() {
+//==== TEST: Playlist_addBatch_successCallback_invalid_cb
+//==== LABEL Check if Playlist addBatch method throws exception when successCallback is invalid
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:Playlist:addBatch M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 30000});
+
+var t = async_test('Playlist_addBatch_successCallback_invalid_cb', {timeout: 30000}),
+    findSuccess, findFail, createSuccess, createFail, incorrectCallback,
+    removePlaylistSuccess, removePlaylistFail, gPlaylist;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    incorrectCallback = {
+        onsuccess: function () {
+            assert_unreached("Invalid successCallback invoked.");
+        }
+    };
+
+    findSuccess = t.step_func(function (contents) {
+        if (contents.length > 2) {
+            assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+                gPlaylist.addBatch([contents[0], contents[1]], incorrectCallback);
+            }, "Given incorrect successCallback.");
+        }
+        tizen.content.removePlaylist(gPlaylist.id, removePlaylistSuccess, removePlaylistFail);
+    });
+
+    findFail = t.step_func(function (error) {
+        assert_unreached("find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        gPlaylist = playlist;
+        tizen.content.find(findSuccess, findFail, null, new tizen.AttributeFilter("type", "EXACTLY", "AUDIO"));
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function Playlist_get_exist() {
+//==== TEST: Playlist_get_exist
+//==== LABEL Check if get exists
+//==== SPEC Tizen Web API:Content:Content:Playlist:get M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+setup({timeout: 30000});
+
+var t = async_test('Playlist_get_exist', {timeout: 30000}),
+    createSuccess, createFail, removePlaylistSuccess, removePlaylistFail;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        assert_true("get" in playlist, "Playlist should have get method");
+        check_method_exists(playlist, "get");
+        tizen.content.removePlaylist(playlist.id, removePlaylistSuccess, removePlaylistFail);
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function Playlist_get() {
+//==== TEST: Playlist_get
+//==== LABEL Check if Playlist get method works properly
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:Playlist:get M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR MMINA
+
+setup({timeout: 30000});
+
+var t = async_test('Playlist_get', {timeout: 30000}),
+    findSuccess, findFail, createSuccess, createFail, successCallback,
+    removePlaylistSuccess, removePlaylistFail, gPlaylist, retVal = null;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    successCallback = t.step_func(function (items) {
+        assert_equals(retVal, undefined, "get should return undefined");
+        tizen.content.removePlaylist(gPlaylist.id, removePlaylistSuccess, removePlaylistFail);
+    });
+
+    findSuccess = t.step_func(function (contents) {
+        if (contents.length > 0) {
+            gPlaylist.add(contents[0]);
+            retVal = gPlaylist.get(successCallback);
+        }
+    });
+
+    findFail = t.step_func(function (error) {
+        assert_unreached("find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        gPlaylist = playlist;
+        tizen.content.find(findSuccess, findFail, null, new tizen.AttributeFilter("type", "EXACTLY", "AUDIO"));
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function Playlist_get_misarg() {
+//==== TEST: Playlist_get_misarg
+//==== LABEL Check if get method called with missing non-optional argument throws an exception
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:Playlist:get M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MMA
+
+setup({timeout: 30000});
+
+var t = async_test('Playlist_get_misarg', {timeout: 30000}),
+    findSuccess, findFail, createSuccess, createFail, removePlaylistSuccess, removePlaylistFail, gPlaylist;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    findSuccess = t.step_func(function (contents) {
+        if (contents.length > 0) {
+            gPlaylist.add(contents[0]);
+            assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+                gPlaylist.get();
+            }, "Invoked with non-optional arguments.");
+        tizen.content.removePlaylist(gPlaylist.id, removePlaylistSuccess, removePlaylistFail);
+        }
+    });
+
+    findFail = t.step_func(function (error) {
+        assert_unreached("find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        gPlaylist = playlist;
+        tizen.content.find(findSuccess, findFail, null, new tizen.AttributeFilter("type", "EXACTLY", "AUDIO"));
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function Playlist_get_with_offset() {
+//==== TEST: Playlist_get_with_offset
+//==== LABEL Check if Playlist get method works properly with all optional arguments
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:Playlist:get M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MOA
+
+setup({timeout: 30000});
+
+var t = async_test('Playlist_get_with_offset', {timeout: 30000}),
+    findSuccess, findFail, createSuccess, createFail, successCallback, errorCallback, count = 1, offset = 1,
+    removePlaylistSuccess, removePlaylistFail, gPlaylist;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    successCallback = t.step_func(function (items) {
+        tizen.content.removePlaylist(gPlaylist.id, removePlaylistSuccess, removePlaylistFail);
+    });
+
+    errorCallback = t.step_func(function (error) {
+        assert_unreached("get() error callback unreachable");
+    });
+
+    findSuccess = t.step_func(function (contents) {
+        if (contents.length > 0) {
+            gPlaylist.add(contents[0]);
+            gPlaylist.get(successCallback, errorCallback, count, offset);
+        }
+    });
+
+    findFail = t.step_func(function (error) {
+        assert_unreached("find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        gPlaylist = playlist;
+        tizen.content.find(findSuccess, findFail, null, new tizen.AttributeFilter("type", "EXACTLY", "AUDIO"));
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function Playlist_get_successCallback_TypeMismatch() {
+//==== TEST: Playlist_get_successCallback_TypeMismatch
+//==== LABEL Check if Playlist get method throws exception when successCallback is incorrect
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:Playlist:get M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test('Playlist_get_successCallback_TypeMismatch', {timeout: 30000}),
+    findSuccess, findFail, createSuccess, createFail, successCallback, errorCallback, conversionTable, i, exceptionName,
+    removePlaylistSuccess, removePlaylistFail, gPlaylist;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    errorCallback = t.step_func(function (error) {
+         assert_unreached("get() error callback should not be invoked.");
+    });
+
+    findSuccess = t.step_func(function (contents) {
+        if (contents.length > 0) {
+            gPlaylist.add(contents[0]);
+            conversionTable = getTypeConversionExceptions("functionObject", true);
+            for (i = 0; i < conversionTable.length; i++) {
+                successCallback = conversionTable[i][0];
+                exceptionName = conversionTable[i][1];
+                assert_throws({name: exceptionName},
+                    function () {
+                        gPlaylist.get(successCallback, errorCallback);
+                    }, "Given incorrect successCallback.");
+            }
+            tizen.content.removePlaylist(gPlaylist.id, removePlaylistSuccess, removePlaylistFail);
+        }
+    });
+
+    findFail = t.step_func(function (error) {
+        assert_unreached("find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        gPlaylist = playlist;
+        tizen.content.find(findSuccess, findFail, null, new tizen.AttributeFilter("type", "EXACTLY", "AUDIO"));
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function Playlist_get_successCallback_invalid_cb() {
+//==== TEST: Playlist_get_successCallback_invalid_cb
+//==== LABEL Check if Playlist get method throws exception when successCallback is invalid
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:Playlist:get M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 30000});
+
+var t = async_test('Playlist_get_successCallback_invalid_cb', {timeout: 30000}),
+    findSuccess, findFail, createSuccess, createFail, incorrectCallback,
+    removePlaylistSuccess, removePlaylistFail, gPlaylist;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    incorrectCallback = {
+        onsuccess: function (items) {
+            assert_unreached("Invalid successCallback invoked.");
+        }
+    };
+
+    findSuccess = t.step_func(function (contents) {
+        if (contents.length > 0) {
+            gPlaylist.add(contents[0]);
+            assert_throws(TYPE_MISMATCH_EXCEPTION,
+                function () {
+                    gPlaylist.get(incorrectCallback);
+                }, "Given incorrect successCallback.");
+            tizen.content.removePlaylist(gPlaylist.id, removePlaylistSuccess, removePlaylistFail);
+        }
+    });
+
+    findFail = t.step_func(function (error) {
+        assert_unreached("find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        gPlaylist = playlist;
+        tizen.content.find(findSuccess, findFail, null, new tizen.AttributeFilter("type", "EXACTLY", "AUDIO"));
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function Playlist_get_errorCallback_TypeMismatch() {
+//==== TEST: Playlist_get_errorCallback_TypeMismatch
+//==== LABEL Check if Playlist get method throws exception when errorCallback is incorrect
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:Playlist:get M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test('Playlist_get_errorCallback_TypeMismatch', {timeout: 30000}),
+    findSuccess, findFail, createSuccess, createFail, successCallback, errorCallback, conversionTable, i, exceptionName,
+    removePlaylistSuccess, removePlaylistFail, gPlaylist;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    successCallback = t.step_func(function () {
+         assert_unreached("get() success callback should not be invoked.");
+    });
+
+    findSuccess = t.step_func(function (contents) {
+        if (contents.length > 0) {
+            gPlaylist.add(contents[0]);
+            conversionTable = getTypeConversionExceptions("functionObject", true);
+            for (i = 0; i < conversionTable.length; i++) {
+                errorCallback = conversionTable[i][0];
+                exceptionName = conversionTable[i][1];
+                assert_throws({name: exceptionName},
+                    function () {
+                        gPlaylist.get(successCallback, errorCallback);
+                    }, "Given incorrect errorCallback.");
+            }
+            tizen.content.removePlaylist(gPlaylist.id, removePlaylistSuccess, removePlaylistFail);
+        }
+    });
+
+    findFail = t.step_func(function (error) {
+        assert_unreached("find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        gPlaylist = playlist;
+        tizen.content.find(findSuccess, findFail, null, new tizen.AttributeFilter("type", "EXACTLY", "AUDIO"));
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function Playlist_get_errorCallback_invalid_cb() {
+//==== TEST: Playlist_get_errorCallback_invalid_cb
+//==== LABEL Check if Playlist get method throws exception when errorCallback is incorrect
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:Playlist:get M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 30000});
+
+var t = async_test('Playlist_get_errorCallback_invalid_cb', {timeout: 30000}),
+    findSuccess, findFail, createSuccess, createFail, successCallback, incorrectCallback,
+    removePlaylistSuccess, removePlaylistFail, gPlaylist;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    incorrectCallback = {
+        onerror: t.step_func(function (error) {
+            assert_unreached("Invalid errorCallback invoked:" + error.name + " msg: " + error.message);
+        })
+    };
+
+    successCallback = t.step_func(function () {
+         assert_unreached("get() success callback should not be invoked.");
+    });
+
+    findSuccess = t.step_func(function (contents) {
+        if (contents.length > 0) {
+            gPlaylist.add(contents[0]);
+            assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+                gPlaylist.get(successCallback, incorrectCallback);
+            }, "Given incorrect errorCallback.");
+            tizen.content.removePlaylist(gPlaylist.id, removePlaylistSuccess, removePlaylistFail);
+        }
+    });
+
+    findFail = t.step_func(function (error) {
+        assert_unreached("find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        gPlaylist = playlist;
+        tizen.content.find(findSuccess, findFail, null, new tizen.AttributeFilter("type", "EXACTLY", "AUDIO"));
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function Playlist_get_errorCallback_invoked() {
+//==== TEST: Playlist_get_errorCallback_invoked
+//==== LABEL Check if Playlist get method with invalid arguments would invoke errorCallback
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:Playlist:get M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MERRCB
+
+setup({timeout: 30000});
+
+var t = async_test('Playlist_get_errorCallback_invoked', {timeout: 30000}),
+    findSuccess, findFail, createSuccess, createFail, successCallback, errorCallback, count = 1, offset = -1,
+    removePlaylistSuccess, removePlaylistFail, gPlaylist;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    successCallback = t.step_func(function (items) {
+        assert_unreached("get() success callback unreachable");
+    });
+
+    errorCallback = t.step_func(function (error) {
+        assert_equals(error.name, "InvalidValuesError", "Incorrect error name");
+        assert_type(error.message, "string", "Error message is not a string");
+        assert_not_equals(error.message, "","Error message is empty");
+        tizen.content.removePlaylist(gPlaylist.id, removePlaylistSuccess, removePlaylistFail);
+    });
+
+    findSuccess = t.step_func(function (contents) {
+        if (contents.length > 0) {
+            gPlaylist.add(contents[0]);
+            gPlaylist.get(successCallback, errorCallback, count, offset);
+        }
+    });
+
+    findFail = t.step_func(function (error) {
+        assert_unreached("find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        gPlaylist = playlist;
+        tizen.content.find(findSuccess, findFail, null, new tizen.AttributeFilter("type", "EXACTLY", "AUDIO"));
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function Playlist_setOrder_exist() {
+//==== TEST: Playlist_setOrder_exist
+//==== LABEL Check if setOrder exists
+//==== SPEC Tizen Web API:Content:Content:Playlist:setOrder M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+setup({timeout: 30000});
+
+var t = async_test('Playlist_setOrder_exist', {timeout: 30000}),
+    createSuccess, createFail, removePlaylistSuccess, removePlaylistFail;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        assert_true("setOrder" in playlist, "Playlist should have setOrder method");
+        check_method_exists(playlist, "setOrder");
+        tizen.content.removePlaylist(playlist.id, removePlaylistSuccess, removePlaylistFail);
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function Playlist_setOrder() {
+//==== TEST: Playlist_setOrder
+//==== LABEL Check if Playlist setOrder method works properly
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:Playlist:setOrder M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR MMINA MAST
+
+setup({timeout: 30000});
+
+var t = async_test('Playlist_setOrder', {timeout: 30000}),
+    findSuccess, findFail, createSuccess, createFail, getsuccessCallback, geterrorCallback, addSuccess, addFail,
+    setOrderSuccess, get2successCallback, get2errorCallback, removePlaylistSuccess, removePlaylistFail, gPlaylist, gItems, gExpectedOrder, retVal = null;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    get2successCallback = t.step_func(function (items) {
+        assert_equals(items[0].content.name, gItems[items.length-1].content.name, "name should be the same");
+        tizen.content.removePlaylist(gPlaylist.id, removePlaylistSuccess, removePlaylistFail);
+    });
+
+    get2errorCallback = t.step_func(function (error) {
+        assert_unreached("get() error callback unreachable(after set order)");
+    });
+
+    setOrderSuccess = t.step_func(function () {
+        assert_equals(retVal, undefined, "setOrder should return undefined");
+        gPlaylist.get(get2successCallback, get2errorCallback);
+    });
+
+    getsuccessCallback = t.step_func(function (items) {
+        gItems = items;
+        gExpectedOrder = gItems.slice(0);
+        gExpectedOrder.reverse();
+        retVal = gPlaylist.setOrder(gExpectedOrder, setOrderSuccess);
+    });
+
+    geterrorCallback = t.step_func(function (error) {
+        assert_unreached("get() error callback unreachable");
+    });
+
+    addSuccess = t.step_func(function () {
+        gPlaylist.get(getsuccessCallback, geterrorCallback);
+    });
+
+    addFail = t.step_func(function (error) {
+        assert_unreached("addBatch() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    findSuccess = t.step_func(function (contents) {
+        if (contents.length > 2) {
+            gPlaylist.addBatch([contents[0], contents[1]], addSuccess, addFail);
+        }
+    });
+
+    findFail = t.step_func(function (error) {
+        assert_unreached("find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        gPlaylist = playlist;
+        tizen.content.find(findSuccess, findFail, null, new tizen.AttributeFilter("type", "EXACTLY", "AUDIO"));
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function Playlist_setOrder_noarg() {
+//==== TEST: Playlist_setOrder_noarg
+//==== LABEL Check if setOrder method called with missing non-optional argument throws an exception
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:Playlist:setOrder M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MMA
+
+setup({timeout: 30000});
+
+var t = async_test('Playlist_setOrder_noarg', {timeout: 30000}),
+    findSuccess, findFail, createSuccess, createFail, getsuccessCallback, geterrorCallback, addSuccess, addFail,
+    removePlaylistSuccess, removePlaylistFail, gPlaylist, gItems, gExpectedOrder;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    getsuccessCallback = t.step_func(function (items) {
+        gItems = items;
+        gExpectedOrder = gItems.slice(0);
+        gExpectedOrder.reverse();
+        assert_throws(TYPE_MISMATCH_EXCEPTION,
+            function () {
+                gPlaylist.setOrder();
+            }, "missing non-optional argument should throw an exception");
+        tizen.content.removePlaylist(gPlaylist.id, removePlaylistSuccess, removePlaylistFail);
+    });
+
+    geterrorCallback = t.step_func(function (error) {
+        assert_unreached("get() error callback unreachable");
+    });
+
+    addSuccess = t.step_func(function () {
+        gPlaylist.get(getsuccessCallback, geterrorCallback);
+    });
+
+    addFail = t.step_func(function (error) {
+        assert_unreached("addBatch() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    findSuccess = t.step_func(function (contents) {
+        if (contents.length > 2) {
+            gPlaylist.addBatch([contents[0], contents[1]], addSuccess, addFail);
+        }
+    });
+
+    findFail = t.step_func(function (error) {
+        assert_unreached("find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        gPlaylist = playlist;
+        tizen.content.find(findSuccess, findFail, null, new tizen.AttributeFilter("type", "EXACTLY", "AUDIO"));
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function Playlist_setOrder_with_errorCallback() {
+//==== TEST: Playlist_setOrder_with_errorCallback
+//==== LABEL Check if Playlist setOrder method works properly with all optional arguments
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:Playlist:setOrder M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MOA MAST
+
+setup({timeout: 30000});
+
+var t = async_test('Playlist_setOrder_with_errorCallback', {timeout: 30000}),
+    findSuccess, findFail, createSuccess, createFail, getsuccessCallback, geterrorCallback, addSuccess, addFail,
+    setOrderSuccess, setOrderFail, get2successCallback, get2errorCallback, removePlaylistSuccess, removePlaylistFail, gPlaylist, gItems, gExpectedOrder;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    get2successCallback = t.step_func(function (items) {
+        assert_equals(items[0].content.name, gItems[items.length-1].content.name, "name should be the same");
+        tizen.content.removePlaylist(gPlaylist.id, removePlaylistSuccess, removePlaylistFail);
+    });
+
+    get2errorCallback = t.step_func(function (error) {
+        assert_unreached("get() error callback unreachable(after set order)");
+    });
+
+    setOrderSuccess = t.step_func(function () {
+        gPlaylist.get(get2successCallback, get2errorCallback);
+    });
+
+    setOrderFail = t.step_func(function (error) {
+        assert_unreached("setOrder() error callback unreachable");
+    });
+
+    getsuccessCallback = t.step_func(function (items) {
+        gItems = items;
+        gExpectedOrder = gItems.slice(0);
+        gExpectedOrder.reverse();
+        gPlaylist.setOrder(gExpectedOrder, setOrderSuccess, setOrderFail);
+    });
+
+    geterrorCallback = t.step_func(function (error) {
+        assert_unreached("get() error callback unreachable");
+    });
+
+    addSuccess = t.step_func(function () {
+        gPlaylist.get(getsuccessCallback, geterrorCallback);
+    });
+
+    addFail = t.step_func(function (error) {
+        assert_unreached("addBatch() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    findSuccess = t.step_func(function (contents) {
+        if (contents.length > 2) {
+            gPlaylist.addBatch([contents[0], contents[1]], addSuccess, addFail);
+        }
+    });
+
+    findFail = t.step_func(function (error) {
+        assert_unreached("find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        gPlaylist = playlist;
+        tizen.content.find(findSuccess, findFail, null, new tizen.AttributeFilter("type", "EXACTLY", "AUDIO"));
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function Playlist_setOrder_items_TypeMismatch() {
+//==== TEST: Playlist_setOrder_items_TypeMismatch
+//==== LABEL Check if Playlist get method throws exception when items is incorrect
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:Playlist:setOrder M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test('Playlist_setOrder_items_TypeMismatch', {timeout: 30000}),
+    findSuccess, findFail, createSuccess, createFail, getsuccessCallback, geterrorCallback, addSuccess, addFail, conversionTable, i, exceptionName,
+    removePlaylistSuccess, removePlaylistFail, gPlaylist;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    getsuccessCallback = t.step_func(function (items) {
+        conversionTable = getTypeConversionExceptions("array", true);
+        for (i = 0; i < conversionTable.length; i++) {
+            items = conversionTable[i][0];
+            exceptionName = conversionTable[i][1];
+            assert_throws({name: exceptionName},
+                function () {
+                        gPlaylist.setOrder(items);
+                }, "Given incorrect items.");
+        }
+        tizen.content.removePlaylist(gPlaylist.id, removePlaylistSuccess, removePlaylistFail);
+    });
+
+    geterrorCallback = t.step_func(function (error) {
+        assert_unreached("get() error callback unreachable");
+    });
+
+    addSuccess = t.step_func(function () {
+        gPlaylist.get(getsuccessCallback, geterrorCallback);
+    });
+
+    addFail = t.step_func(function (error) {
+        assert_unreached("addBatch() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    findSuccess = t.step_func(function (contents) {
+        if (contents.length > 2) {
+            gPlaylist.addBatch([contents[0], contents[1]], addSuccess, addFail);
+        }
+    });
+
+    findFail = t.step_func(function (error) {
+        assert_unreached("find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        gPlaylist = playlist;
+        tizen.content.find(findSuccess, findFail, null, new tizen.AttributeFilter("type", "EXACTLY", "AUDIO"));
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function Playlist_setOrder_successCallback_TypeMismatch() {
+//==== TEST: Playlist_setOrder_successCallback_TypeMismatch
+//==== LABEL Check if Playlist get method throws exception when successCallback is incorrect
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:Playlist:setOrder M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test('Playlist_setOrder_successCallback_TypeMismatch', {timeout: 30000}),
+    findSuccess, findFail, createSuccess, createFail, getsuccessCallback, geterrorCallback, addSuccess, addFail, conversionTable, i, exceptionName,
+    setOrderSuccess, removePlaylistSuccess, removePlaylistFail, gPlaylist, gItems, gExpectedOrder;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    getsuccessCallback = t.step_func(function (items) {
+        gItems = items;
+        gExpectedOrder = gItems.slice(0);
+        gExpectedOrder.reverse();
+        conversionTable = getTypeConversionExceptions("functionObject", true);
+        for (i = 0; i < conversionTable.length; i++) {
+            setOrderSuccess = conversionTable[i][0];
+            exceptionName = conversionTable[i][1];
+            assert_throws({name: exceptionName},
+                function () {
+                    gPlaylist.setOrder(gExpectedOrder, setOrderSuccess);
+                }, "Given incorrect errorCallback.");
+        }
+        tizen.content.removePlaylist(gPlaylist.id, removePlaylistSuccess, removePlaylistFail);
+    });
+
+    geterrorCallback = t.step_func(function (error) {
+        assert_unreached("get() error callback unreachable");
+    });
+
+    addSuccess = t.step_func(function () {
+        gPlaylist.get(getsuccessCallback, geterrorCallback);
+    });
+
+    addFail = t.step_func(function (error) {
+        assert_unreached("addBatch() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    findSuccess = t.step_func(function (contents) {
+        if (contents.length > 2) {
+            gPlaylist.addBatch([contents[0], contents[1]], addSuccess, addFail);
+        }
+    });
+
+    findFail = t.step_func(function (error) {
+        assert_unreached("find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        gPlaylist = playlist;
+        tizen.content.find(findSuccess, findFail, null, new tizen.AttributeFilter("type", "EXACTLY", "AUDIO"));
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function Playlist_setOrder_successCallback_invalid_cb() {
+//==== TEST: Playlist_setOrder_successCallback_invalid_cb
+//==== LABEL Check if Playlist get method throws exception when successCallback is invalid
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:Playlist:setOrder M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 30000});
+
+var t = async_test('Playlist_setOrder_successCallback_invalid_cb', {timeout: 30000}),
+    findSuccess, findFail, createSuccess, createFail, getsuccessCallback, geterrorCallback, addSuccess, addFail,
+    incorrectCallback, removePlaylistSuccess, removePlaylistFail, gPlaylist, gItems, gExpectedOrder;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    incorrectCallback = {
+        onsuccess: function () {
+            assert_unreached("Invalid successCallback invoked.");
+        }
+    };
+
+    getsuccessCallback = t.step_func(function (items) {
+        gItems = items;
+        gExpectedOrder = gItems.slice(0);
+        gExpectedOrder.reverse();
+        assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+            gPlaylist.setOrder(gExpectedOrder, incorrectCallback);
+        }, "Given incorrect successCallback.");
+        tizen.content.removePlaylist(gPlaylist.id, removePlaylistSuccess, removePlaylistFail);
+    });
+
+    geterrorCallback = t.step_func(function (error) {
+        assert_unreached("get() error callback unreachable");
+    });
+
+    addSuccess = t.step_func(function () {
+        gPlaylist.get(getsuccessCallback, geterrorCallback);
+    });
+
+    addFail = t.step_func(function (error) {
+        assert_unreached("addBatch() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    findSuccess = t.step_func(function (contents) {
+        if (contents.length > 2) {
+            gPlaylist.addBatch([contents[0], contents[1]], addSuccess, addFail);
+        }
+    });
+
+    findFail = t.step_func(function (error) {
+        assert_unreached("find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        gPlaylist = playlist;
+        tizen.content.find(findSuccess, findFail, null, new tizen.AttributeFilter("type", "EXACTLY", "AUDIO"));
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function Playlist_setOrder_errorCallback_TypeMismatch() {
+//==== TEST: Playlist_setOrder_errorCallback_TypeMismatch
+//==== LABEL Check if Playlist get method throws exception when errorCallback is incorrect
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:Playlist:setOrder M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test('Playlist_setOrder_errorCallback_TypeMismatch', {timeout: 30000}),
+    findSuccess, findFail, createSuccess, createFail, getsuccessCallback, geterrorCallback, addSuccess, addFail, conversionTable, i, exceptionName,
+    setOrderSuccess, setOrderFail, removePlaylistSuccess, removePlaylistFail, gPlaylist, gItems, gExpectedOrder;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    setOrderSuccess = t.step_func(function () {
+        assert_unreached("setOrder() success callback unreachable");
+    });
+
+    getsuccessCallback = t.step_func(function (items) {
+        gItems = items;
+        gExpectedOrder = gItems.slice(0);
+        gExpectedOrder.reverse();
+        conversionTable = getTypeConversionExceptions("functionObject", true);
+        for (i = 0; i < conversionTable.length; i++) {
+            setOrderFail = conversionTable[i][0];
+            exceptionName = conversionTable[i][1];
+            assert_throws({name: exceptionName},
+                function () {
+                    gPlaylist.setOrder(gExpectedOrder, setOrderSuccess, setOrderFail);
+                }, "Given incorrect errorCallback.");
+        }
+       tizen.content.removePlaylist(gPlaylist.id, removePlaylistSuccess, removePlaylistFail);
+    });
+
+    geterrorCallback = t.step_func(function (error) {
+        assert_unreached("get() error callback unreachable");
+    });
+
+    addSuccess = t.step_func(function () {
+        gPlaylist.get(getsuccessCallback, geterrorCallback);
+    });
+
+    addFail = t.step_func(function (error) {
+        assert_unreached("addBatch() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    findSuccess = t.step_func(function (contents) {
+        if (contents.length > 2) {
+            gPlaylist.addBatch([contents[0], contents[1]], addSuccess, addFail);
+        }
+    });
+
+    findFail = t.step_func(function (error) {
+        assert_unreached("find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        gPlaylist = playlist;
+        tizen.content.find(findSuccess, findFail, null, new tizen.AttributeFilter("type", "EXACTLY", "AUDIO"));
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function Playlist_setOrder_errorCallback_invalid_cb() {
+//==== TEST: Playlist_setOrder_errorCallback_invalid_cb
+//==== LABEL Check if Playlist get method throws exception when errorCallback is invalid
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:Playlist:setOrder M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 30000});
+
+var t = async_test('Playlist_setOrder_errorCallback_invalid_cb', {timeout: 30000}),
+    findSuccess, findFail, createSuccess, createFail, getsuccessCallback, geterrorCallback, addSuccess, addFail, conversionTable,
+    setOrderSuccess, incorrectCallback, removePlaylistSuccess, removePlaylistFail, gPlaylist, gItems, gExpectedOrder, i, j;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    setOrderSuccess = t.step_func(function () {
+        assert_unreached("setOrder() success callback unreachable");
+    });
+
+    incorrectCallback = {
+        onsuccess: function (error) {
+             assert_unreached("Invalid errorCallback invoked:" + error.name + " msg: " + error.message);
+        }
+    };
+
+    getsuccessCallback = t.step_func(function (items) {
+        gItems = items;
+        gExpectedOrder = gItems.slice(0);
+        gExpectedOrder.reverse();
+        assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+            gPlaylist.setOrder(gExpectedOrder, setOrderSuccess, incorrectCallback);
+        }, "Given incorrect errorCallback.");
+        tizen.content.removePlaylist(gPlaylist.id, removePlaylistSuccess, removePlaylistFail);
+    });
+
+    geterrorCallback = t.step_func(function (error) {
+        assert_unreached("get() error callback unreachable");
+    });
+
+    addSuccess = t.step_func(function () {
+        gPlaylist.get(getsuccessCallback, geterrorCallback);
+    });
+
+    addFail = t.step_func(function (error) {
+        assert_unreached("addBatch() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    findSuccess = t.step_func(function (contents) {
+        if (contents.length > 2) {
+            gPlaylist.addBatch([contents[0], contents[1]], addSuccess, addFail);
+        }
+    });
+
+    findFail = t.step_func(function (error) {
+        assert_unreached("find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        gPlaylist = playlist;
+        tizen.content.find(findSuccess, findFail, null, new tizen.AttributeFilter("type", "EXACTLY", "AUDIO"));
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function Playlist_setOrder_errorCallback_invoked() {
+//==== TEST: Playlist_setOrder_errorCallback_invoked
+//==== LABEL Check if ContentManager setOrder method with invalid arguments would invoke errorCallback
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:Playlist:setOrder M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MERRCB
+
+setup({timeout: 30000});
+
+var t = async_test('Playlist_setOrder_errorCallback_invoked', {timeout: 30000}),
+    findSuccess, findFail, createSuccess, createFail, getsuccessCallback, geterrorCallback, addSuccess, addFail,
+    setOrderSuccess, setOrderFail, removePlaylistSuccess, removePlaylistFail, gPlaylist, gExpectedOrder;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    setOrderSuccess = t.step_func(function () {
+        assert_unreached("setOrder() success callback unreachable(after set order)");
+    });
+
+    setOrderFail = t.step_func(function (error) {
+        assert_equals(error.name, "InvalidValuesError", "Incorrect error name");
+        assert_type(error.message, "string", "Error message is not a string");
+        assert_not_equals(error.message, "","Error message is empty");
+        tizen.content.removePlaylist(gPlaylist.id, removePlaylistSuccess, removePlaylistFail);
+    });
+
+    getsuccessCallback = t.step_func(function (items) {
+        gExpectedOrder = items.slice(items.length);
+        gExpectedOrder.reverse();
+        gPlaylist.setOrder(gExpectedOrder, setOrderSuccess, setOrderFail);
+    });
+
+    geterrorCallback = t.step_func(function (error) {
+        assert_unreached("get() error callback unreachable");
+    });
+
+    addSuccess = t.step_func(function () {
+        gPlaylist.get(getsuccessCallback, geterrorCallback);
+    });
+
+    addFail = t.step_func(function (error) {
+        assert_unreached("addBatch() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    findSuccess = t.step_func(function (contents) {
+        if (contents.length > 2) {
+            gPlaylist.addBatch([contents[0], contents[1]], addSuccess, addFail);
+        }
+    });
+
+    findFail = t.step_func(function (error) {
+        assert_unreached("find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        gPlaylist = playlist;
+        tizen.content.find(findSuccess, findFail, null, new tizen.AttributeFilter("type", "EXACTLY", "AUDIO"));
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function Playlist_move() {
+//==== TEST: Playlist_move
+//==== LABEL Check if Playlist move method works properly without optional arguments
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:Playlist:move M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR MMINA
+
+setup({timeout: 30000});
+
+var t = async_test('Playlist_move', {timeout: 30000}),
+    findSuccess, findFail, createSuccess, createFail, successCallback, errorCallback, addsuccessCallback, adderrorCallback,
+    moveSuccess, removePlaylistSuccess, removePlaylistFail, gPlaylist, retVal = null;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    moveSuccess = t.step_func(function () {
+        assert_equals(retVal, undefined, "move should return undefined");
+        tizen.content.removePlaylist(gPlaylist.id, removePlaylistSuccess, removePlaylistFail);
+    });
+
+    successCallback = t.step_func(function (items) {
+        retVal = gPlaylist.move(items[1], -1, moveSuccess);
+    });
+
+    errorCallback = t.step_func(function (error) {
+        assert_unreached("get() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    addsuccessCallback = t.step_func(function () {
+        gPlaylist.get(successCallback, errorCallback);
+    });
+
+    adderrorCallback = t.step_func(function (error) {
+        assert_unreached("addBatch() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    findSuccess = t.step_func(function (contents) {
+        if (contents.length > 2) {
+            gPlaylist.addBatch([contents[0], contents[1]], addsuccessCallback, adderrorCallback);
+        }
+    });
+
+    findFail = t.step_func(function (error) {
+        assert_unreached("find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        gPlaylist = playlist;
+        tizen.content.find(findSuccess, findFail, null, new tizen.AttributeFilter("type", "EXACTLY", "AUDIO"));
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function Playlist_move_exist() {
+//==== TEST: Playlist_move_exist
+//==== LABEL Check if move exists
+//==== SPEC Tizen Web API:Content:Content:Playlist:move M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+setup({timeout: 30000});
+
+var t = async_test('Playlist_move_exist', {timeout: 30000}),
+    createSuccess, createFail, removePlaylistSuccess, removePlaylistFail;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        assert_true("move" in playlist, "Playlist should have move method");
+        check_method_exists(playlist, "move");
+        tizen.content.removePlaylist(playlist.id, removePlaylistSuccess, removePlaylistFail);
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function Playlist_move_noarg() {
+//==== TEST: Playlist_move_noarg
+//==== LABEL Check if move method called with missing non-optional argument throws an exception
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:Playlist:move M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MMA
+
+setup({timeout: 30000});
+
+var t = async_test('Playlist_move_noarg', {timeout: 30000}),
+    findSuccess, findFail, createSuccess, createFail, successCallback, errorCallback, addsuccessCallback, adderrorCallback,
+    removePlaylistSuccess, removePlaylistFail, gPlaylist;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    successCallback = t.step_func(function (items) {
+        assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+            gPlaylist.move();
+        }, "miss argument");
+        tizen.content.removePlaylist(gPlaylist.id, removePlaylistSuccess, removePlaylistFail);
+    });
+
+    errorCallback = t.step_func(function (error) {
+        assert_unreached("get() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    addsuccessCallback = t.step_func(function () {
+        gPlaylist.get(successCallback, errorCallback);
+    });
+
+    adderrorCallback = t.step_func(function (error) {
+        assert_unreached("addBatch() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    findSuccess = t.step_func(function (contents) {
+        if (contents.length > 2) {
+            gPlaylist.addBatch([contents[0], contents[1]], addsuccessCallback, adderrorCallback);
+        }
+    });
+
+    findFail = t.step_func(function (error) {
+        assert_unreached("find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        gPlaylist = playlist;
+        tizen.content.find(findSuccess, findFail, null, new tizen.AttributeFilter("type", "EXACTLY", "AUDIO"));
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function Playlist_move_errorCallback_invalid_cb() {
+//==== TEST: Playlist_move_errorCallback_invalid_cb
+//==== LABEL Check if Playlist move method throws exception when errorCallback is invalid
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:Playlist:move M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 30000});
+
+var t = async_test('Playlist_move_errorCallback_invalid_cb', {timeout: 30000}),
+    findSuccess, findFail, createSuccess, createFail, successCallback, errorCallback, addsuccessCallback, adderrorCallback,
+    moveSuccess, incorrectCallback, removePlaylistSuccess, removePlaylistFail, gPlaylist;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    moveSuccess = t.step_func(function () {
+        assert_unreached("move() success callback should not be invoked.");
+    });
+
+    incorrectCallback = {
+        onsuccess: function (error) {
+             assert_unreached("Invalid errorCallback invoked:" + error.name + " msg: " + error.message);
+        }
+    };
+
+    successCallback = t.step_func(function (items) {
+        assert_throws(TYPE_MISMATCH_EXCEPTION,
+            function () {
+                gPlaylist.move(items[1], -1, moveSuccess, incorrectCallback);
+            }, "Given incorrect errorCallback.");
+        tizen.content.removePlaylist(gPlaylist.id, removePlaylistSuccess, removePlaylistFail);
+    });
+
+    errorCallback = t.step_func(function (error) {
+        assert_unreached("get() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    addsuccessCallback = t.step_func(function () {
+        gPlaylist.get(successCallback, errorCallback);
+    });
+
+    adderrorCallback = t.step_func(function (error) {
+        assert_unreached("addBatch() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    findSuccess = t.step_func(function (contents) {
+        if (contents.length > 2) {
+            gPlaylist.addBatch([contents[0], contents[1]], addsuccessCallback, adderrorCallback);
+        }
+    });
+
+    findFail = t.step_func(function (error) {
+        assert_unreached("find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        gPlaylist = playlist;
+        tizen.content.find(findSuccess, findFail, null, new tizen.AttributeFilter("type", "EXACTLY", "AUDIO"));
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function Playlist_move_errorCallback_TypeMismatch() {
+//==== TEST: Playlist_move_errorCallback_TypeMismatch
+//==== LABEL Check if Playlist move method throws exception when errorCallback is incorrect
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:Playlist:move M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test('Playlist_move_errorCallback_TypeMismatch', {timeout: 30000}),
+    findSuccess, findFail, createSuccess, createFail, successCallback, errorCallback, addsuccessCallback, adderrorCallback,
+    moveSuccess, moveFail, removePlaylistSuccess, removePlaylistFail, gPlaylist, conversionTable, i, exceptionName;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    moveSuccess = t.step_func(function () {
+        assert_unreached("move() success callback should not be invoked.");
+    });
+
+    successCallback = t.step_func(function (items) {
+        conversionTable = getTypeConversionExceptions("functionObject", true);
+        for (i = 0; i < conversionTable.length; i++) {
+            moveFail = conversionTable[i][0];
+            exceptionName = conversionTable[i][1];
+            assert_throws({name: exceptionName},
+                function () {
+                    gPlaylist.move(items[1], -1, moveSuccess, moveFail);
+                }, "Given incorrect errorCallback.");
+        }
+        tizen.content.removePlaylist(gPlaylist.id, removePlaylistSuccess, removePlaylistFail);
+    });
+
+    errorCallback = t.step_func(function (error) {
+        assert_unreached("get() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    addsuccessCallback = t.step_func(function () {
+        gPlaylist.get(successCallback, errorCallback);
+    });
+
+    adderrorCallback = t.step_func(function (error) {
+        assert_unreached("addBatch() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    findSuccess = t.step_func(function (contents) {
+        if (contents.length > 2) {
+            gPlaylist.addBatch([contents[0], contents[1]], addsuccessCallback, adderrorCallback);
+        }
+    });
+
+    findFail = t.step_func(function (error) {
+        assert_unreached("find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        gPlaylist = playlist;
+        tizen.content.find(findSuccess, findFail, null, new tizen.AttributeFilter("type", "EXACTLY", "AUDIO"));
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function Playlist_move_item_TypeMismatch() {
+//==== TEST: Playlist_move_item_TypeMismatch
+//==== LABEL Check if Playlist move method throws exception when item is incorrect
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:Playlist:move M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test('Playlist_move_item_TypeMismatch', {timeout: 30000}),
+    findSuccess, findFail, createSuccess, createFail, successCallback, errorCallback, addsuccessCallback, adderrorCallback,
+    moveSuccess, moveFail, removePlaylistSuccess, removePlaylistFail, gPlaylist, conversionTable, i, exceptionName;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    moveSuccess = t.step_func(function () {
+        assert_unreached("move() success callback should not be invoked.");
+    });
+
+    moveFail = t.step_func(function (error) {
+        assert_unreached("move() error callback should not be invoked.");
+    });
+
+    successCallback = t.step_func(function (items) {
+        conversionTable = getTypeConversionExceptions("object", true);
+        for (i = 0; i < conversionTable.length; i++) {
+            items = conversionTable[i][0];
+            exceptionName = conversionTable[i][1];
+            assert_throws({name: exceptionName},
+                function () {
+                    gPlaylist.move(items, -1, moveSuccess, moveFail);
+                }, "Given incorrect errorCallback.");
+        }
+        tizen.content.removePlaylist(gPlaylist.id, removePlaylistSuccess, removePlaylistFail);
+    });
+
+    errorCallback = t.step_func(function (error) {
+        assert_unreached("get() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    addsuccessCallback = t.step_func(function () {
+        gPlaylist.get(successCallback, errorCallback);
+    });
+
+    adderrorCallback = t.step_func(function (error) {
+        assert_unreached("addBatch() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    findSuccess = t.step_func(function (contents) {
+        if (contents.length > 2) {
+            gPlaylist.addBatch([contents[0], contents[1]], addsuccessCallback, adderrorCallback);
+        }
+    });
+
+    findFail = t.step_func(function (error) {
+        assert_unreached("find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        gPlaylist = playlist;
+        tizen.content.find(findSuccess, findFail, null, new tizen.AttributeFilter("type", "EXACTLY", "AUDIO"));
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function Playlist_move_successCallback_invalid_cb() {
+//==== TEST: Playlist_move_successCallback_invalid_cb
+//==== LABEL Check if Playlist move method throws exception when successCallback is invalid
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:Playlist:move M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 30000});
+
+var t = async_test('Playlist_move_successCallback_invalid_cb', {timeout: 30000}),
+    findSuccess, findFail, createSuccess, createFail, successCallback, errorCallback, addsuccessCallback, adderrorCallback,
+    moveFail, incorrectCallback, removePlaylistSuccess, removePlaylistFail, gPlaylist;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    moveFail = t.step_func(function (error) {
+        assert_unreached("move() error callback should not be invoked.");
+    });
+
+    incorrectCallback = {
+        onsuccess: function (error) {
+             assert_unreached("Invalid errorCallback invoked:" + error.name + " msg: " + error.message);
+        }
+    };
+
+    successCallback = t.step_func(function (items) {
+        assert_throws(TYPE_MISMATCH_EXCEPTION,
+            function () {
+                gPlaylist.move(items[1], -1, incorrectCallback, moveFail);
+            }, "Given incorrect errorCallback.");
+        tizen.content.removePlaylist(gPlaylist.id, removePlaylistSuccess, removePlaylistFail);
+    });
+
+    errorCallback = t.step_func(function (error) {
+        assert_unreached("get() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    addsuccessCallback = t.step_func(function () {
+        gPlaylist.get(successCallback, errorCallback);
+    });
+
+    adderrorCallback = t.step_func(function (error) {
+        assert_unreached("addBatch() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    findSuccess = t.step_func(function (contents) {
+        if (contents.length > 2) {
+            gPlaylist.addBatch([contents[0], contents[1]], addsuccessCallback, adderrorCallback);
+        }
+    });
+
+    findFail = t.step_func(function (error) {
+        assert_unreached("find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        gPlaylist = playlist;
+        tizen.content.find(findSuccess, findFail, null, new tizen.AttributeFilter("type", "EXACTLY", "AUDIO"));
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function Playlist_move_successCallback_TypeMismatch() {
+//==== TEST: Playlist_move_successCallback_TypeMismatch
+//==== LABEL Check if Playlist move method throws exception when successCallback is incorrect
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:Playlist:move M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test('Playlist_move_successCallback_TypeMismatch', {timeout: 30000}),
+    findSuccess, findFail, createSuccess, createFail, successCallback, errorCallback, addsuccessCallback, adderrorCallback,
+    moveSuccess, moveFail, removePlaylistSuccess, removePlaylistFail, gPlaylist, conversionTable, i, exceptionName;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    moveFail = t.step_func(function (error) {
+        assert_unreached("move() error callback should not be invoked.");
+    });
+
+    successCallback = t.step_func(function (items) {
+        conversionTable = getTypeConversionExceptions("functionObject", true);
+        for (i = 0; i < conversionTable.length; i++) {
+            moveSuccess = conversionTable[i][0];
+            exceptionName = conversionTable[i][1];
+            assert_throws({name: exceptionName},
+                function () {
+                    gPlaylist.move(items[1], -1, moveSuccess, moveFail);
+                }, "Given incorrect errorCallback.");
+        }
+        tizen.content.removePlaylist(gPlaylist.id, removePlaylistSuccess, removePlaylistFail);
+    });
+
+    errorCallback = t.step_func(function (error) {
+        assert_unreached("get() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    addsuccessCallback = t.step_func(function () {
+        gPlaylist.get(successCallback, errorCallback);
+    });
+
+    adderrorCallback = t.step_func(function (error) {
+        assert_unreached("addBatch() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    findSuccess = t.step_func(function (contents) {
+        if (contents.length > 2) {
+            gPlaylist.addBatch([contents[0], contents[1]], addsuccessCallback, adderrorCallback);
+        }
+    });
+
+    findFail = t.step_func(function (error) {
+        assert_unreached("find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        gPlaylist = playlist;
+        tizen.content.find(findSuccess, findFail, null, new tizen.AttributeFilter("type", "EXACTLY", "AUDIO"));
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function Playlist_remove_exist() {
+//==== TEST: Playlist_remove_exist
+//==== LABEL Check if remove exists
+//==== SPEC Tizen Web API:Content:Content:Playlist:remove M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+setup({timeout: 30000});
+
+var t = async_test('Playlist_remove_exist', {timeout: 30000}),
+    createSuccess, createFail, removePlaylistSuccess, removePlaylistFail;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        assert_true("remove" in playlist, "Playlist should have remove method");
+        check_method_exists(playlist, "remove");
+        tizen.content.removePlaylist(playlist.id, removePlaylistSuccess, removePlaylistFail);
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function Playlist_remove() {
+//==== TEST: Playlist_remove
+//==== LABEL Check if Playlist remove method works properly
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:Playlist:remove M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR MAST
+
+setup({timeout: 30000});
+
+var t = async_test('Playlist_remove', {timeout: 30000}),
+    findSuccess, findFail, createSuccess, createFail, getSuccess, getFail, get2Success, get2Fail,
+    removePlaylistSuccess, removePlaylistFail, gPlaylist, beforelenght, afterlength, retVal = null;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    get2Success = t.step_func(function (items) {
+        assert_equals(retVal, undefined, "remove should return undefined");
+        afterlength = items.length;
+        assert_less_than(afterlength, beforelenght, "length should be decrease");
+        tizen.content.removePlaylist(gPlaylist.id, removePlaylistSuccess, removePlaylistFail);
+    });
+
+    get2Fail = t.step_func(function (error) {
+        assert_unreached("get() error callback(after remove) was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    getSuccess = t.step_func(function (items) {
+        beforelenght = items.length;
+        retVal = gPlaylist.remove(items[0]);
+        gPlaylist.get(get2Success, get2Fail);
+    });
+
+    getFail = t.step_func(function (error) {
+        assert_unreached("get() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    findSuccess = t.step_func(function (contents) {
+        if (contents.length > 0) {
+            gPlaylist.add(contents[0]);
+            gPlaylist.get(getSuccess, getFail);
+        }
+    });
+
+    findFail = t.step_func(function (error) {
+        assert_unreached("find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        gPlaylist = playlist;
+        tizen.content.find(findSuccess, findFail, null, new tizen.AttributeFilter("type", "EXACTLY", "AUDIO"));
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function Playlist_remove_item_TypeMismatch() {
+//==== TEST: Playlist_remove_item_TypeMismatch
+//==== LABEL Check if remove throws exception when item is incorrect
+//==== SPEC Tizen Web API:Content:Content:Playlist:remove M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test('Playlist_remove_item_TypeMismatch', {timeout: 30000}),
+    createSuccess, createFail, conversionTable, item, exceptionName, i, removePlaylistSuccess, removePlaylistFail;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        conversionTable = getTypeConversionExceptions("object", false);
+        for (i = 0; i < conversionTable.length; i++) {
+            item = conversionTable[i][0];
+            exceptionName = conversionTable[i][1];
+            assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+                playlist.remove(item);
+            }, "Invoked with non-optional arguments.");
+        }
+        tizen.content.removePlaylist(playlist.id, removePlaylistSuccess, removePlaylistFail);
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function Playlist_remove_noarg() {
+//==== TEST: Playlist_remove_noarg
+//==== LABEL Check if remove method called with missing non-optional argument throws an exception
+//==== SPEC Tizen Web API:Content:Content:Playlist:remove M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MMA
+
+setup({timeout: 30000});
+
+var t = async_test('Playlist_remove_noarg', {timeout: 30000}),
+    createSuccess, createFail, removePlaylistSuccess, removePlaylistFail;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+            playlist.remove();
+        }, "Invoked with non-optional arguments.");
+        tizen.content.removePlaylist(playlist.id, removePlaylistSuccess, removePlaylistFail);
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function Playlist_removeBatch_exist() {
+//==== TEST: Playlist_removeBatch_exist
+//==== LABEL Check if removeBatch exists
+//==== SPEC Tizen Web API:Content:Content:Playlist:removeBatch M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+setup({timeout: 30000});
+
+var t = async_test('Playlist_removeBatch_exist', {timeout: 30000}),
+    createSuccess, createFail, removePlaylistSuccess, removePlaylistFail;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        assert_true("removeBatch" in playlist, "Playlist should have removeBatch method");
+        check_method_exists(playlist, "removeBatch");
+        tizen.content.removePlaylist(playlist.id, removePlaylistSuccess, removePlaylistFail);
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function Playlist_removeBatch_errorCallback_invalid_cb() {
+//==== TEST: Playlist_removeBatch_errorCallback_invalid_cb
+//==== LABEL Check if Playlist removeBatch method throws exception when errorCallback is invalid
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:Playlist:removeBatch M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 30000});
+
+var t = async_test('Playlist_removeBatch_errorCallback_invalid_cb', {timeout: 30000}),
+    findSuccess, findFail, createSuccess, createFail, addsuccessCallback, adderrorCallback, successCallback, incorrectCallback,
+    removePlaylistSuccess, removePlaylistFail, getSuccess, getFail, gPlaylist;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    incorrectCallback = {
+        onerror: t.step_func(function (error) {
+            assert_unreached("Invalid errorCallback invoked:" + error.name + " msg: " + error.message);
+        })
+    };
+
+    successCallback = t.step_func(function () {
+         assert_unreached("removeBatch() success callback should not be invoked.");
+    });
+
+    getSuccess = t.step_func(function (items) {
+        assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+            gPlaylist.removeBatch([items[0], items[1]], successCallback, incorrectCallback);
+        }, "Given incorrect errorCallback.");
+        tizen.content.removePlaylist(gPlaylist.id, removePlaylistSuccess, removePlaylistFail);
+    });
+
+    getFail = t.step_func(function (error) {
+        assert_unreached("get() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    addsuccessCallback = t.step_func(function () {
+        gPlaylist.get(getSuccess, getFail);
+    });
+
+    adderrorCallback = t.step_func(function (error) {
+        assert_unreached("addBatch() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    findSuccess = t.step_func(function (contents) {
+        if (contents.length > 2) {
+            gPlaylist.addBatch([contents[0], contents[1]], addsuccessCallback, adderrorCallback);
+        }
+    });
+
+    findFail = t.step_func(function (error) {
+        assert_unreached("find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        gPlaylist = playlist;
+        tizen.content.find(findSuccess, findFail, null, new tizen.AttributeFilter("type", "EXACTLY", "AUDIO"));
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function Playlist_removeBatch_errorCallback_TypeMismatch() {
+//==== TEST: Playlist_removeBatch_errorCallback_TypeMismatch
+//==== LABEL Check if Playlist removeBatch method throws exception when errorCallback is incorrect
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:Playlist:removeBatch M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test('Playlist_removeBatch_errorCallback_TypeMismatch', {timeout: 30000}),
+    findSuccess, findFail, createSuccess, createFail, addsuccessCallback, adderrorCallback, successCallback, errorCallback,
+    removePlaylistSuccess, removePlaylistFail, getSuccess, getFail, gPlaylist, conversionTable, i, exceptionName;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    successCallback = t.step_func(function () {
+         assert_unreached("removeBatch() success callback should not be invoked.");
+    });
+
+    getSuccess = t.step_func(function (items) {
+        conversionTable = getTypeConversionExceptions("functionObject", true);
+        for (i = 0; i < conversionTable.length; i++) {
+            errorCallback = conversionTable[i][0];
+            exceptionName = conversionTable[i][1];
+            assert_throws({name: exceptionName},
+                function () {
+                    gPlaylist.removeBatch([items[0], items[1]], successCallback, errorCallback);
+                }, "Given incorrect errorCallback.");
+        }
+        tizen.content.removePlaylist(gPlaylist.id, removePlaylistSuccess, removePlaylistFail);
+    });
+
+    getFail = t.step_func(function (error) {
+        assert_unreached("get() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    addsuccessCallback = t.step_func(function () {
+        gPlaylist.get(getSuccess, getFail);
+    });
+
+    adderrorCallback = t.step_func(function (error) {
+        assert_unreached("addBatch() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    findSuccess = t.step_func(function (contents) {
+        if (contents.length > 2) {
+            gPlaylist.addBatch([contents[0], contents[1]], addsuccessCallback, adderrorCallback);
+        }
+    });
+
+    findFail = t.step_func(function (error) {
+        assert_unreached("find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        gPlaylist = playlist;
+        tizen.content.find(findSuccess, findFail, null, new tizen.AttributeFilter("type", "EXACTLY", "AUDIO"));
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function Playlist_removeBatch_items_TypeMismatch() {
+//==== TEST: Playlist_removeBatch_items_TypeMismatch
+//==== LABEL Check if removeBatch throws exception when content is incorrect
+//==== SPEC Tizen Web API:Content:Content:Playlist:removeBatch M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test('Playlist_removeBatch_items_TypeMismatch', {timeout: 30000}),
+    createSuccess, createFail, conversionTable, item, exceptionName, i, removePlaylistSuccess, removePlaylistFail;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        conversionTable = getTypeConversionExceptions("object", false);
+        for (i = 0; i < conversionTable.length; i++) {
+            item = conversionTable[i][0];
+            exceptionName = conversionTable[i][1];
+            assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+                playlist.removeBatch(item);
+            }, "Invoked with non-optional arguments.");
+        }
+        tizen.content.removePlaylist(playlist.id, removePlaylistSuccess, removePlaylistFail);
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function Playlist_removeBatch_noarg() {
+//==== TEST: Playlist_removeBatch_noarg
+//==== LABEL Check if removeBatch method called with missing non-optional argument throws an exception
+//==== SPEC Tizen Web API:Content:Content:Playlist:removeBatch M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MMA
+
+setup({timeout: 30000});
+
+var t = async_test('Playlist_removeBatch_noarg', {timeout: 30000}),
+    createSuccess, createFail, removePlaylistSuccess, removePlaylistFail;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+            playlist.removeBatch();
+        }, "Invoked with non-optional arguments.");
+        tizen.content.removePlaylist(playlist.id, removePlaylistSuccess, removePlaylistFail);
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function Playlist_removeBatch_successCallback_invalid_cb() {
+//==== TEST: Playlist_removeBatch_successCallback_invalid_cb
+//==== LABEL Check if Playlist removeBatch method throws exception when successCallback is invalid
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:Playlist:removeBatch M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 30000});
+
+var t = async_test('Playlist_removeBatch_successCallback_invalid_cb', {timeout: 30000}),
+    findSuccess, findFail, createSuccess, createFail, addsuccessCallback, adderrorCallback, errorCallback, incorrectCallback,
+    removePlaylistSuccess, removePlaylistFail, getSuccess, getFail, gPlaylist;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    incorrectCallback = {
+        onsuccess: function () {
+             assert_unreached("Invalid successCallback invoked:" + error.name + " msg: " + error.message);
+        }
+    };
+
+    errorCallback = t.step_func(function () {
+         assert_unreached("removeBatch() error callback should not be invoked.");
+    });
+
+    getSuccess = t.step_func(function (items) {
+        assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+            gPlaylist.removeBatch([items[0], items[1]], incorrectCallback, errorCallback);
+        }, "Given incorrect errorCallback.");
+        tizen.content.removePlaylist(gPlaylist.id, removePlaylistSuccess, removePlaylistFail);
+    });
+
+    getFail = t.step_func(function (error) {
+        assert_unreached("get() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    addsuccessCallback = t.step_func(function () {
+        gPlaylist.get(getSuccess, getFail);
+    });
+
+    adderrorCallback = t.step_func(function (error) {
+        assert_unreached("addBatch() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    findSuccess = t.step_func(function (contents) {
+        if (contents.length > 2) {
+            gPlaylist.addBatch([contents[0], contents[1]], addsuccessCallback, adderrorCallback);
+        }
+    });
+
+    findFail = t.step_func(function (error) {
+        assert_unreached("find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        gPlaylist = playlist;
+        tizen.content.find(findSuccess, findFail, null, new tizen.AttributeFilter("type", "EXACTLY", "AUDIO"));
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function Playlist_removeBatch_successCallback_TypeMismatch() {
+//==== TEST: Playlist_removeBatch_successCallback_TypeMismatch
+//==== LABEL Check if Playlist removeBatch method throws exception when successCallback is incorrect
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:Playlist:removeBatch M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test('Playlist_removeBatch_successCallback_TypeMismatch', {timeout: 30000}),
+    findSuccess, findFail, createSuccess, createFail, addsuccessCallback, adderrorCallback, successCallback, errorCallback,
+    removePlaylistSuccess, removePlaylistFail, getSuccess, getFail, gPlaylist, conversionTable, i, exceptionName;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    errorCallback = t.step_func(function () {
+         assert_unreached("removeBatch() success callback should not be invoked.");
+    });
+
+    getSuccess = t.step_func(function (items) {
+        conversionTable = getTypeConversionExceptions("functionObject", true);
+        for (i = 0; i < conversionTable.length; i++) {
+            successCallback = conversionTable[i][0];
+            exceptionName = conversionTable[i][1];
+            assert_throws({name: exceptionName},
+                function () {
+                    gPlaylist.removeBatch([items[0], items[1]], successCallback, errorCallback);
+                }, "Given incorrect successCallback.");
+        }
+        tizen.content.removePlaylist(gPlaylist.id, removePlaylistSuccess, removePlaylistFail);
+    });
+
+    getFail = t.step_func(function (error) {
+        assert_unreached("get() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    addsuccessCallback = t.step_func(function () {
+        gPlaylist.get(getSuccess, getFail);
+    });
+
+    adderrorCallback = t.step_func(function (error) {
+        assert_unreached("addBatch() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    findSuccess = t.step_func(function (contents) {
+        if (contents.length > 2) {
+            gPlaylist.addBatch([contents[0], contents[1]], addsuccessCallback, adderrorCallback);
+        }
+    });
+
+    findFail = t.step_func(function (error) {
+        assert_unreached("find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        gPlaylist = playlist;
+        tizen.content.find(findSuccess, findFail, null, new tizen.AttributeFilter("type", "EXACTLY", "AUDIO"));
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function Playlist_removeBatch_with_errorCallback() {
+//==== TEST: Playlist_removeBatch_with_errorCallback
+//==== LABEL Check if Playlist removeBatch method works properly with all optional arguments
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:Playlist:removeBatch M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MOA
+
+setup({timeout: 30000});
+
+var t = async_test('Playlist_removeBatch_with_errorCallback', {timeout: 30000}),
+    findSuccess, findFail, createSuccess, createFail, addsuccessCallback, adderrorCallback, getSuccess, getFail, successCallback, errorCallback,
+    removePlaylistSuccess, removePlaylistFail, gPlaylist;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    successCallback = t.step_func(function () {
+        tizen.content.removePlaylist(gPlaylist.id, removePlaylistSuccess, removePlaylistFail);
+    });
+
+    errorCallback = t.step_func(function (error) {
+        assert_unreached("removeBatch() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    getSuccess = t.step_func(function (items) {
+        gPlaylist.removeBatch([items[0], items[1]], successCallback, errorCallback);
+    });
+
+    getFail = t.step_func(function (error) {
+        assert_unreached("get() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    addsuccessCallback = t.step_func(function () {
+        gPlaylist.get(getSuccess, getFail);
+    });
+
+    adderrorCallback = t.step_func(function (error) {
+        assert_unreached("addBatch() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    findSuccess = t.step_func(function (contents) {
+        if (contents.length > 2) {
+            gPlaylist.addBatch([contents[0], contents[1]], addsuccessCallback, adderrorCallback);
+        }
+    });
+
+    findFail = t.step_func(function (error) {
+        assert_unreached("find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        gPlaylist = playlist;
+        tizen.content.find(findSuccess, findFail, null, new tizen.AttributeFilter("type", "EXACTLY", "AUDIO"));
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function PlaylistArraySuccessCallback_notexist() {
+//==== TEST: PlaylistArraySuccessCallback_notexist
+//==== LABEL Check if interface PlaylistArraySuccessCallback exists,it should not
+//==== SPEC Tizen Web API:Content:Content:PlaylistArraySuccessCallback:PlaylistArraySuccessCallback U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA CBNIO
+
+test(function () {
+    check_no_interface_object("PlaylistArraySuccessCallback");
+}, 'PlaylistArraySuccessCallback_notexist');
+
+}
+
+function PlaylistArraySuccessCallback_onsuccess() {
+//==== TEST: PlaylistArraySuccessCallback_onsuccess
+//==== LABEL Check if PlaylistArraySuccessCallback onsuccess is called and if its arguments have proper type
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:PlaylistArraySuccessCallback:onsuccess M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA CBT CBOA
+
+setup({timeout: 30000});
+
+var t = async_test('PlaylistArraySuccessCallback_onsuccess', {timeout: 30000}), successCallback, errorCallback, createSuccess, createFail, removePlaylistSuccess, gPlaylist, retVal = null;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    successCallback = t.step_func(function (playlists) {
+        assert_equals(retVal, undefined, "getPlaylists should return undefined");
+        assert_type(playlists, "array", "playlists should be an array");
+        assert_type(playlists[0], "object", "Incorrect type.");
+        assert_type(playlists[0].id, "string", "id type check");
+        assert_type(playlists[0].name, "string", "name type check");
+        assert_type(playlists[0].numberOfTracks, "long", "numberOfTracks type check");
+        assert_equals(playlists[0].thumbnailURI, null, "thumbnailURI type check"); 
+        tizen.content.removePlaylist(gPlaylist.id, removePlaylistSuccess);
+    });
+
+    errorCallback = t.step_func(function (error) {
+        assert_unreached("getPlaylists() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        gPlaylist = playlist;
+        retVal = tizen.content.getPlaylists(successCallback, errorCallback);
+    });
+
+    createFail = t.step_func(function (error) {
+       assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function PlaylistItemArraySuccessCallback_notexist() {
+//==== TEST:PlaylistItemArraySuccessCallback_notexist
+//==== LABEL Check if interface PlaylistItemArraySuccessCallback exists,it should not
+//==== SPEC Tizen Web API:Content:Content:PlaylistItemArraySuccessCallback:PlaylistItemArraySuccessCallback U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA CBNIO
+
+test(function () {
+    check_no_interface_object("PlaylistItemArraySuccessCallback");
+}, 'PlaylistItemArraySuccessCallback_notexist');
+
+}
+
+function PlaylistItemArraySuccessCallback_onsuccess() {
+//==== TEST: PlaylistItemArraySuccessCallback_onsuccess
+//==== LABEL Check if PlaylistItemArraySuccessCallback onsuccess is called and if its arguments have proper type
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:PlaylistItemArraySuccessCallback:onsuccess M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA CBT CBOA
+
+setup({timeout: 90000});
+
+var t = async_test('PlaylistItemArraySuccessCallback_onsuccess', {timeout: 90000}),
+    findSuccess, findFail, createSuccess, createFail, onSuccess, onError,
+    removePlaylistSuccess, removePlaylistFail, gPlaylist;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    onSuccess = t.step_func(function (items) {
+        assert_type(items, "array", "items should be an array");
+        assert_type(items[0].content, "object", "content type check");
+        tizen.content.removePlaylist(gPlaylist.id, removePlaylistSuccess, removePlaylistFail);
+    });
+
+    onError = t.step_func(function (error) {
+        assert_unreached("get() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    findSuccess = t.step_func(function (contents) {
+        if (contents.length > 0) {
+            gPlaylist.add(contents[0]);
+            gPlaylist.get(onSuccess, onError);
+        }
+    });
+
+    findFail = t.step_func(function (error) {
+        assert_unreached("find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        gPlaylist = playlist;
+        tizen.content.find(findSuccess, findFail, null, new tizen.AttributeFilter("type", "EXACTLY", "AUDIO"));
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function PlaylistSuccessCallback_notexist() {
+//==== TEST: PlaylistSuccessCallback_notexist
+//==== LABEL Check if interface PlaylistSuccessCallback exists,it should not
+//==== SPEC Tizen Web API:Content:Content:PlaylistSuccessCallback:PlaylistSuccessCallback U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA CBNIO
+
+test(function () {
+    check_no_interface_object("PlaylistSuccessCallback");
+}, 'PlaylistSuccessCallback_notexist');
+
+}
+
+function PlaylistSuccessCallback_onsuccess() {
+//==== TEST: PlaylistSuccessCallback_onsuccess
+//==== LABEL Check if PlaylistSuccessCallback onsuccess is called and if its arguments have proper type
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:PlaylistSuccessCallback:PlaylistSuccessCallback U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA CBT CBOA
+
+setup({timeout: 30000});
+
+var t = async_test('PlaylistSuccessCallback_onsuccess', {timeout: 30000}),
+    onSuccess, onError, removePlaylistSuccess;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    onSuccess = t.step_func(function (playlist) {
+        assert_not_equals(playlist , null, "Argument should not be null.");
+        assert_type(playlist, "object", "Incorrect type.");
+        assert_type(playlist.id, "string", "id type check");
+        assert_type(playlist.name, "string", "name type check");
+        assert_type(playlist.numberOfTracks, "long", "numberOfTracks type check");
+        assert_equals(playlist.thumbnailURI, null, "thumbnailURI type check"); 
+        tizen.content.removePlaylist(playlist.id, removePlaylistSuccess);
+    });
+
+    onError = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), onSuccess, onError);
+});
+
+}
+
+function PlaylistItem_notexist() {
+//==== TEST: PlaylistItem_notexist
+//==== LABEL Check if interface PlaylistItem exists,it should not
+//==== SPEC Tizen Web API:Content:Content:PlaylistItem:PlaylistItem U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("PlaylistItem");
+}, 'PlaylistItem_notexist');
+
+}
+
+function PlaylistItem_extend() {
+//==== TEST: PlaylistItem_extend
+//==== LABEL Check if interface PlaylistItem can have new properties
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Content:Content:PlaylistItem:PlaylistItem U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA OBX
+
+setup({timeout: 30000});
+
+var t = async_test('PlaylistItem_extend', {timeout: 30000}),
+    findSuccess, findFail, createSuccess, createFail, successCallback, errorCallback,
+    removePlaylistSuccess, removePlaylistFail, gPlaylist;
+
+t.step(function () {
+    removePlaylistSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    removePlaylistFail = t.step_func(function (error) {
+       assert_unreached("removePlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    successCallback = t.step_func(function (items) {
+        assert_greater_than(items.length, 0 ,"Playlist items is not found");
+        check_extensibility(items);
+        tizen.content.removePlaylist(gPlaylist.id, removePlaylistSuccess, removePlaylistFail);
+    });
+
+    errorCallback = t.step_func(function (error) {
+       assert_unreached("get() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    findSuccess = t.step_func(function (contents) {
+        if (contents.length > 0) {
+            gPlaylist.add(contents[0]);
+            gPlaylist.get(successCallback, errorCallback);
+        }
+    });
+
+    findFail = t.step_func(function (error) {
+        assert_unreached("find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    createSuccess = t.step_func(function (playlist) {
+        gPlaylist = playlist;
+        tizen.content.find(findSuccess, findFail, null, new tizen.AttributeFilter("type", "EXACTLY", "AUDIO"));
+    });
+
+    createFail = t.step_func(function (error) {
+        assert_unreached("createPlaylist() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    tizen.content.createPlaylist(randomString(5), createSuccess, createFail);
+});
+
+}
+
+function Content_isFavorite_attribute() {
+//==== TEST: Content_isFavorite_attribute
+//==== LABEL Check if Content have isFavorite attribute with proper type and is writeable and not nullable
+//==== ONLOAD_DELAY 30
+//==== SPEC: Tizen Web API:Content:Content:Content:isFavorite A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/content.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ASG AN
+
+setup({timeout: 30000});
+
+var t = async_test('Content_isFavorite_attribute', {timeout: 30000}), onSuccess, onError, content;
+
+setup_contents(t, t.step_func(function () {
+    onError = t.step_func(function (error) {
+        assert_unreached("Find() error callback was invoked: " + error.name + " msg: " + error.message);
+    });
+
+    onSuccess = t.step_func(function (contents) {
+        assert_type(contents, "array", "contents should be an array");
+        assert_greater_than(contents.length, 0, "media item is not found");
+
+        content = contents[0];
+        if (content.isFavorite !== null) {
+            check_attribute(content, "isFavorite", content.isFavorite, "boolean", true);
+            content.isFavorite = null;
+            assert_not_equals(content.isFavorite, null, "Content.isFavorite should not accept null as value.");
+        }
+
+        t.done();
+    });
+
+    tizen.content.find(onSuccess, onError);
+}));
+
+}
+
+
+var moduleName = "tct-content-tizen-tests";
+add_test_case(moduleName, ContentManagerObject_content_exist);
+add_test_case(moduleName, ContentManager_updateBatch_exist);
+add_test_case(moduleName, ContentManager_update_exist);
+add_test_case(moduleName, ContentManager_getDirectories_exist);
+add_test_case(moduleName, ContentManager_find_exist);
+add_test_case(moduleName, ContentManager_find);
+add_test_case(moduleName, ContentManager_getDirectories);
+add_test_case(moduleName, ContentManager_update);
+add_test_case(moduleName, ContentManager_updateBatch);
+add_test_case(moduleName, Content_type_AUDIO);
+add_test_case(moduleName, ContentManager_update_description);
+add_test_case(moduleName, ContentManager_updateBatch_description);
+add_test_case(moduleName, Content_type_IMAGE);
+add_test_case(moduleName, Content_type_VIDEO);
+add_test_case(moduleName, ContentManager_find_nullableArgs);
+add_test_case(moduleName, VideoContent_notexist);
+add_test_case(moduleName, Content_notexist);
+add_test_case(moduleName, ImageContent_notexist);
+add_test_case(moduleName, ContentDirectoryArraySuccessCallback_notexist);
+add_test_case(moduleName, ContentScanSuccessCallback_notexist);
+add_test_case(moduleName, ContentManager_notexist);
+add_test_case(moduleName, ContentManager_extend);
+add_test_case(moduleName, ContentManager_update_missarg);
+add_test_case(moduleName, ContentManager_update_content_TypeMismatch);
+add_test_case(moduleName, ContentManager_updateBatch_missarg);
+add_test_case(moduleName, ContentManager_updateBatch_contents_TypeMismatch);
+add_test_case(moduleName, ContentManager_updateBatch_successCallback_TypeMismatch);
+add_test_case(moduleName, ContentManager_updateBatch_successCallback_invalid_cb);
+add_test_case(moduleName, ContentManager_updateBatch_errorCallback_TypeMismatch);
+add_test_case(moduleName, ContentManager_updateBatch_errorCallback_invalid_cb);
+add_test_case(moduleName, ContentManager_getDirectories_missarg);
+add_test_case(moduleName, ContentManager_getDirectories_successCallback_invalid_cb);
+add_test_case(moduleName, ContentManager_getDirectories_successCallback_TypeMismatch);
+add_test_case(moduleName, ContentManager_getDirectories_errorCallback_TypeMismatch);
+add_test_case(moduleName, ContentManager_getDirectories_errorCallback_invalid_cb);
+add_test_case(moduleName, ContentManager_find_missarg);
+add_test_case(moduleName, ContentManager_find_successCallback_TypeMismatch);
+add_test_case(moduleName, ContentManager_find_successCallback_invalid_cb);
+add_test_case(moduleName, ContentManager_find_errorCallback_TypeMismatch);
+add_test_case(moduleName, ContentManager_find_errorCallback_invalid_cb);
+add_test_case(moduleName, ContentManager_scanFile_exist);
+add_test_case(moduleName, ContentManager_scanFile_successCallback_TypeMismatch);
+add_test_case(moduleName, ContentManager_scanFile_successCallback_invalid_cb);
+add_test_case(moduleName, ContentManager_scanFile_errorCallback_TypeMismatch);
+add_test_case(moduleName, ContentManager_scanFile_errorCallback_invalid_cb);
+add_test_case(moduleName, ContentManager_setChangeListener_exist);
+add_test_case(moduleName, ContentArraySuccessCallback_notexist);
+add_test_case(moduleName, ContentDirectory_notexist);
+add_test_case(moduleName, ContentChangeCallback_notexist);
+add_test_case(moduleName, AudioContentLyrics_notexist);
+add_test_case(moduleName, AudioContent_notexist);
+add_test_case(moduleName, ContentManager_setChangeListener_missarg);
+add_test_case(moduleName, ContentManager_setChangeListener_changeCallback_TypeMismatch);
+add_test_case(moduleName, ContentManager_setChangeListener_changeCallback_invalid_cb);
+add_test_case(moduleName, ContentManager_unsetChangeListener_exist);
+add_test_case(moduleName, ImageContent_extend);
+add_test_case(moduleName, ImageContent_geolocation_attribute);
+add_test_case(moduleName, ImageContent_width_attribute);
+add_test_case(moduleName, ImageContent_height_attribute);
+add_test_case(moduleName, ImageContent_orientation_attribute);
+add_test_case(moduleName, ContentDirectoryArraySuccessCallback_onsuccess);
+add_test_case(moduleName, ContentScanSuccessCallback_onsuccess);
+add_test_case(moduleName, Content_extend);
+add_test_case(moduleName, Content_editableAttributes_attribute);
+add_test_case(moduleName, Content_id_attribute);
+add_test_case(moduleName, Content_name_attribute);
+add_test_case(moduleName, Content_type_attribute);
+add_test_case(moduleName, Content_mimeType_attribute);
+add_test_case(moduleName, Content_title_attribute);
+add_test_case(moduleName, Content_contentURI_attribute);
+add_test_case(moduleName, Content_thumbnailURIs_attribute);
+add_test_case(moduleName, Content_releaseDate_attribute);
+add_test_case(moduleName, Content_modifiedDate_attribute);
+add_test_case(moduleName, Content_size_attribute);
+add_test_case(moduleName, Content_description_attribute);
+add_test_case(moduleName, Content_rating_attribute);
+add_test_case(moduleName, ContentManager_find_with_errorCallback);
+add_test_case(moduleName, ContentManager_find_with_directoryId);
+add_test_case(moduleName, ContentManager_find_with_filter);
+add_test_case(moduleName, ContentManager_find_with_sortMode);
+add_test_case(moduleName, ContentManager_find_with_count);
+//add_test_case(moduleName, ContentManager_find_with_offset);
+add_test_case(moduleName, ContentManager_getDirectories_with_errorCallback);
+add_test_case(moduleName, ContentManager_find_filter_TypeMismatch);
+add_test_case(moduleName, ContentManager_find_sortMode_TypeMismatch);
+add_test_case(moduleName, ContentManager_find_sortMode_invalid_obj);
+add_test_case(moduleName, ContentManager_unsetChangeListener_extra_argument);
+add_test_case(moduleName, ContentArraySuccessCallback_onsuccess);
+add_test_case(moduleName, ContentManager_scanFile);
+add_test_case(moduleName, ContentManager_scanFile_with_errorCallback);
+add_test_case(moduleName, ContentManager_scanFile_with_successCallback);
+add_test_case(moduleName, ContentManager_unsetChangeListener);
+add_test_case(moduleName, VideoContent_extend);
+add_test_case(moduleName, VideoContent_geolocation_attribute);
+add_test_case(moduleName, VideoContent_height_attribute);
+add_test_case(moduleName, VideoContent_width_attribute);
+add_test_case(moduleName, VideoContent_duration_attribute);
+add_test_case(moduleName, VideoContent_album_attribute);
+add_test_case(moduleName, VideoContent_artists_attribute);
+add_test_case(moduleName, ContentChangeCallback_oncontentadded);
+add_test_case(moduleName, ContentChangeCallback_oncontentremoved);
+add_test_case(moduleName, ContentChangeCallback_oncontentupdated);
+add_test_case(moduleName, ContentManager_updateBatch_with_errorCallback);
+add_test_case(moduleName, ContentManager_updateBatch_with_successCallback);
+add_test_case(moduleName, AudioContent_album_attribute);
+add_test_case(moduleName, AudioContent_artists_attribute);
+add_test_case(moduleName, AudioContent_bitrate_attribute);
+add_test_case(moduleName, AudioContent_duration_attribute);
+add_test_case(moduleName, AudioContent_extend);
+add_test_case(moduleName, AudioContent_trackNumber_attribute);
+add_test_case(moduleName, AudioContent_genres_attribute);
+add_test_case(moduleName, AudioContent_composers_attribute);
+add_test_case(moduleName, AudioContent_copyright_attribute);
+add_test_case(moduleName, AudioContent_lyrics_attribute);
+add_test_case(moduleName, AudioContentLyrics_extend);
+add_test_case(moduleName, AudioContentLyrics_type_attribute);
+add_test_case(moduleName, AudioContentLyrics_timestamps_attribute);
+add_test_case(moduleName, AudioContentLyrics_texts_attribute);
+add_test_case(moduleName, ContentDirectory_extend);
+add_test_case(moduleName, ContentDirectory_id_attribute);
+add_test_case(moduleName, ContentDirectory_directoryURI_attribute);
+add_test_case(moduleName, ContentDirectory_title_attribute);
+add_test_case(moduleName, ContentDirectory_modifiedDate_attribute);
+add_test_case(moduleName, ContentDirectory_storageType_attribute);
+add_test_case(moduleName, ContentManager_update_name);
+add_test_case(moduleName, ContentManager_update_video_geolocation);
+add_test_case(moduleName, ContentManager_update_image_geolocation);
+add_test_case(moduleName, ContentManager_update_image_orientation);
+add_test_case(moduleName, ContentManager_updateBatch_name);
+add_test_case(moduleName, ContentManager_updateBatch_video_geolocation);
+add_test_case(moduleName, ContentManager_updateBatch_image_geolocation);
+add_test_case(moduleName, ContentManager_updateBatch_image_orientation);
+add_test_case(moduleName, ContentManager_setChangeListener);
+add_test_case(moduleName, ContentManager_updateBatch_without_callback);
+add_test_case(moduleName, ContentManagerObject_notexist);
+add_test_case(moduleName, ContentManager_find_filter_attribute_invalid);
+add_test_case(moduleName, ContentScanSuccessCallback_onsuccess_contentURI);
+add_test_case(moduleName, ContentChangeCallback_oncontentremoved_id_type);
+add_test_case(moduleName, Content_in_tizen);
+add_test_case(moduleName, ContentManager_createPlaylist_exist);
+add_test_case(moduleName, ContentManager_createPlaylist);
+add_test_case(moduleName, ContentManager_createPlaylist_misarg);
+add_test_case(moduleName, ContentManager_createPlaylist_successCallback_TypeMismatch);
+add_test_case(moduleName, ContentManager_createPlaylist_successCallback_invalid_cb);
+add_test_case(moduleName, ContentManager_createPlaylist_errorCallback_invoked);
+add_test_case(moduleName, ContentManager_createPlaylist_errorCallback_TypeMismatch);
+add_test_case(moduleName, ContentManager_createPlaylist_errorCallback_invalid_cb);
+add_test_case(moduleName, ContentManager_createPlaylist_noarg);
+add_test_case(moduleName, ContentManager_createPlaylist_sourcePlaylist_TypeMismatch);
+add_test_case(moduleName, ContentManager_getPlaylists);
+add_test_case(moduleName, ContentManager_getPlaylists_exist);
+add_test_case(moduleName, ContentManager_getPlaylists_misarg);
+add_test_case(moduleName, ContentManager_getPlaylists_with_errorCallback);
+add_test_case(moduleName, ContentManager_getPlaylists_errorCallback_TypeMismatch);
+add_test_case(moduleName, ContentManager_getPlaylists_errorCallback_invalid_cb);
+add_test_case(moduleName, ContentManager_getPlaylists_successCallback_TypeMismatch);
+add_test_case(moduleName, ContentManager_getPlaylists_successCallback_invalid_cb);
+add_test_case(moduleName, ContentManager_removePlaylist_exist);
+add_test_case(moduleName, ContentManager_removePlaylist);
+add_test_case(moduleName, ContentManager_removePlaylist_with_errorCallback);
+add_test_case(moduleName, ContentManager_removePlaylist_errorCallback_TypeMismatch);
+add_test_case(moduleName, ContentManager_removePlaylist_errorCallback_invalid_cb);
+add_test_case(moduleName, ContentManager_removePlaylist_successCallback_TypeMismatch);
+add_test_case(moduleName, ContentManager_removePlaylist_successCallback_invalid_cb);
+add_test_case(moduleName, Playlist_extend);
+add_test_case(moduleName, Playlist_notexist);
+add_test_case(moduleName, Playlist_id_attribute);
+add_test_case(moduleName, Playlist_name_attribute);
+add_test_case(moduleName, Playlist_numberOfTracks_attribute);
+add_test_case(moduleName, Playlist_thumbnailURI_attribute);
+add_test_case(moduleName, Playlist_add_exist);
+add_test_case(moduleName, Playlist_add);
+add_test_case(moduleName, Playlist_add_misarg);
+add_test_case(moduleName, Playlist_add_item_TypeMismatch);
+add_test_case(moduleName, Playlist_addBatch_exist);
+add_test_case(moduleName, Playlist_addBatch);
+add_test_case(moduleName, Playlist_addBatch_misarg);
+add_test_case(moduleName, Playlist_addBatch_items_TypeMismatch);
+add_test_case(moduleName, Playlist_addBatch_with_errorCallback);
+add_test_case(moduleName, Playlist_addBatch_errorCallback_TypeMismatch);
+add_test_case(moduleName, Playlist_addBatch_errorCallback_invalid_cb);
+add_test_case(moduleName, Playlist_addBatch_successCallback_TypeMismatch);
+add_test_case(moduleName, Playlist_addBatch_successCallback_invalid_cb);
+add_test_case(moduleName, Playlist_get_exist);
+add_test_case(moduleName, Playlist_get);
+add_test_case(moduleName, Playlist_get_misarg);
+add_test_case(moduleName, Playlist_get_with_offset);
+add_test_case(moduleName, Playlist_get_successCallback_TypeMismatch);
+add_test_case(moduleName, Playlist_get_successCallback_invalid_cb);
+add_test_case(moduleName, Playlist_get_errorCallback_TypeMismatch);
+add_test_case(moduleName, Playlist_get_errorCallback_invalid_cb);
+add_test_case(moduleName, Playlist_get_errorCallback_invoked);
+add_test_case(moduleName, Playlist_setOrder_exist);
+add_test_case(moduleName, Playlist_setOrder);
+add_test_case(moduleName, Playlist_setOrder_noarg);
+add_test_case(moduleName, Playlist_setOrder_with_errorCallback);
+add_test_case(moduleName, Playlist_setOrder_items_TypeMismatch);
+add_test_case(moduleName, Playlist_setOrder_successCallback_TypeMismatch);
+add_test_case(moduleName, Playlist_setOrder_successCallback_invalid_cb);
+add_test_case(moduleName, Playlist_setOrder_errorCallback_TypeMismatch);
+add_test_case(moduleName, Playlist_setOrder_errorCallback_invalid_cb);
+add_test_case(moduleName, Playlist_setOrder_errorCallback_invoked);
+add_test_case(moduleName, Playlist_move);
+add_test_case(moduleName, Playlist_move_exist);
+add_test_case(moduleName, Playlist_move_noarg);
+add_test_case(moduleName, Playlist_move_errorCallback_invalid_cb);
+add_test_case(moduleName, Playlist_move_errorCallback_TypeMismatch);
+add_test_case(moduleName, Playlist_move_item_TypeMismatch);
+add_test_case(moduleName, Playlist_move_successCallback_invalid_cb);
+add_test_case(moduleName, Playlist_move_successCallback_TypeMismatch);
+add_test_case(moduleName, Playlist_remove_exist);
+add_test_case(moduleName, Playlist_remove);
+add_test_case(moduleName, Playlist_remove_item_TypeMismatch);
+add_test_case(moduleName, Playlist_remove_noarg);
+add_test_case(moduleName, Playlist_removeBatch_exist);
+add_test_case(moduleName, Playlist_removeBatch_errorCallback_invalid_cb);
+add_test_case(moduleName, Playlist_removeBatch_errorCallback_TypeMismatch);
+add_test_case(moduleName, Playlist_removeBatch_items_TypeMismatch);
+add_test_case(moduleName, Playlist_removeBatch_noarg);
+add_test_case(moduleName, Playlist_removeBatch_successCallback_invalid_cb);
+add_test_case(moduleName, Playlist_removeBatch_successCallback_TypeMismatch);
+add_test_case(moduleName, Playlist_removeBatch_with_errorCallback);
+add_test_case(moduleName, PlaylistArraySuccessCallback_notexist);
+add_test_case(moduleName, PlaylistArraySuccessCallback_onsuccess);
+add_test_case(moduleName, PlaylistItemArraySuccessCallback_notexist);
+add_test_case(moduleName, PlaylistItemArraySuccessCallback_onsuccess);
+add_test_case(moduleName, PlaylistSuccessCallback_notexist);
+add_test_case(moduleName, PlaylistSuccessCallback_onsuccess);
+add_test_case(moduleName, PlaylistItem_notexist);
+add_test_case(moduleName, PlaylistItem_extend);
+add_test_case(moduleName, Content_isFavorite_attribute);
diff --git a/webWidgetTCT_device/test/tct/tests/TestDataControl.js b/webWidgetTCT_device/test/tct/tests/TestDataControl.js
new file mode 100755 (executable)
index 0000000..85e8510
--- /dev/null
@@ -0,0 +1,4150 @@
+/*
+
+Copyright (c) 2013 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+
+
+Authors:
+
+*/
+
+var PROVIDER_ID = "http://tizen.org/datacontrol/provider/DictionaryDataControlProvider";
+var DATA_ID = "Dictionary";
+var TYPE_SQL = "SQL";
+var TYPE_MAP = "MAP";
+
+function generateGlobalReqId() {
+    return new Date().getTime() % 1e8;
+}
+
+function DataControlConsumerObject_dataId_attribute() {
+//==== TEST: DataControlConsumerObject_dataId_attribute
+//==== LABEL Check if attribute dataId of DataControlConsumerObject exists, has type DOMString and is readonly
+//==== SPEC Tizen Web API:TBD:Datacontrol:DataControlConsumerObject:dataId A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== TEST_CRITERIA AE AT ARO
+//==== PRIORITY P1
+
+test(function () {
+    var globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_SQL);
+
+    assert_own_property(globalDataControl, "dataId" , "DataControlConsumerObject does not own dataId property.");
+    check_readonly(globalDataControl, "dataId", DATA_ID, "String", DATA_ID + "Tizen");
+}, 'DataControlConsumerObject_dataId_attribute');
+
+}
+
+function DataControlConsumerObject_extend() {
+//==== TEST: DataControlConsumerObject_extend
+//==== PRIORITY P3
+//==== LABEL Test whether the object DataControlConsumerObject can have new properties added
+//==== SPEC Tizen Web API:TBD:Datacontrol:DataControlConsumerObject:DataControlConsumerObject U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== TEST_CRITERIA OBX
+
+test(function () {
+    var globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_SQL);
+    check_extensibility(globalDataControl);
+}, 'DataControlConsumerObject_extend');
+
+}
+
+function DataControlConsumerObject_notexist() {
+//==== TEST: DataControlConsumerObject_notexist
+//==== PRIORITY P3
+//==== LABEL Check if interface DataControlConsumerObject exists, it should not
+//==== SPEC Tizen Web API:TBD:Datacontrol:DataControlConsumerObject:DataControlConsumerObject U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("DataControlConsumerObject");
+}, 'DataControlConsumerObject_notexist');
+
+}
+
+function DataControlConsumerObject_providerId_attribute() {
+//==== TEST: DataControlConsumerObject_providerId_attribute
+//==== LABEL Check if attribute providerId of DataControlConsumerObject exists, has type DOMString and is readonly
+//==== SPEC Tizen Web API:TBD:Datacontrol:DataControlConsumerObject:providerId A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== TEST_CRITERIA AE AT ARO
+//==== PRIORITY P1
+
+test(function () {
+    var globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_SQL);
+
+    assert_own_property(globalDataControl, "providerId" , "DataControlConsumerObject does not own providerId property.");
+    check_readonly(globalDataControl, "providerId", PROVIDER_ID, "String", PROVIDER_ID + "Tizen");
+}, 'DataControlConsumerObject_providerId_attribute');
+
+}
+
+function DataControlConsumerObject_type_attribute() {
+//==== TEST: DataControlConsumerObject_type_attribute
+//==== LABEL Check if attribute type of DataControlConsumerObject exists, has type DataType and is readonly
+//==== SPEC Tizen Web API:TBD:Datacontrol:DataControlConsumerObject:type A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== TEST_CRITERIA AE AT ARO
+//==== PRIORITY P1
+
+test(function () {
+    var globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_SQL);
+
+    assert_own_property(globalDataControl, "type" , "DataControlConsumerObject does not own type property.");
+    check_readonly(globalDataControl, "type", TYPE_SQL, "String", TYPE_SQL + "Tizen");
+}, 'DataControlConsumerObject_type_attribute');
+
+}
+
+function DataControlErrorCallback_notexist() {
+//==== TEST: DataControlErrorCallback_notexist
+//==== PRIORITY P3
+//==== LABEL Check if interface DataControlErrorCallback exists, it should not
+//==== SPEC Tizen Web API:TBD:Datacontrol:DataControlErrorCallback:DataControlErrorCallback U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== TEST_CRITERIA CBNIO
+
+test(function () {
+    check_no_interface_object("DataControlErrorCallback");
+}, 'DataControlErrorCallback_notexist');
+
+}
+
+function DataControlErrorCallback_onerror() {
+//==== TEST DataControlErrorCallback_onerror
+//==== LABEL Check if DataControlErrorCallback onerror method is invoked
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:TBD:Datacontrol:DataControlErrorCallback:onerror U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== TEST_CRITERIA CBOA CBT
+
+setup({timeout: 30000});
+
+var t = async_test('DataControlErrorCallback_onerror', {timeout: 30000}), globalDataControl, currentDate, insertSuccess, insertError, rowData,
+    rowDataUpdate, updateSuccess, updateError, returnedValue = null, descriptionUpdated, keyUpdated;
+
+t.step(function () {
+
+    keyUpdated = currentDate + "_update";
+    descriptionUpdated = currentDate + "_desc_update";
+    currentDate = new Date().getTime().toString();
+    rowData = {
+        columns: ["WORD", "WORD_DESC"],
+        values: ["'" + currentDate + "'", "'" + currentDate + "_desc'"]
+    };
+
+    rowDataUpdate = {
+        columns: ["tizen", "WORD_DESC"],
+        values: ["'" + keyUpdated + "'", "'" + descriptionUpdated + "'"]
+    };
+
+    updateSuccess = t.step_func(function (reqId) {
+        assert_equals(returnedValue, undefined, "Incorrect returned value");
+    });
+
+    updateError = t.step_func(function (reqId, error) {
+        assert_equals(reqId, 2, "incorrect reqId");
+        t.done();
+    });
+
+    insertSuccess = t.step_func(function (reqId, insertRowId) {
+        returnedValue = globalDataControl.update(2, rowDataUpdate,
+            rowData.columns[0] + "=" + rowData.values[0], updateSuccess, updateError);
+    });
+
+    insertError = t.step_func(function (reqId, error) {
+        assert_unreached("insert() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_SQL);
+    globalDataControl.insert(1, rowData, insertSuccess, insertError);
+});
+
+}
+
+function DataControlGetValueSuccessCallback_notexist() {
+//==== TEST: DataControlGetValueSuccessCallback_notexist
+//==== PRIORITY P3
+//==== LABEL Check if interface DataControlGetValueSuccessCallback exists, it should not
+//==== SPEC Tizen Web API:TBD:Datacontrol:DataControlGetValueSuccessCallback:DataControlGetValueSuccessCallback U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== TEST_CRITERIA CBNIO
+
+test(function () {
+    check_no_interface_object("DataControlGetValueSuccessCallback");
+}, 'DataControlGetValueSuccessCallback_notexist');
+
+}
+
+function DataControlGetValueSuccessCallback_onsuccess() {
+//==== TEST: DataControlGetValueSuccessCallback_onsuccess
+//==== PRIORITY P3
+//==== LABEL Check if callback is called and if its arguments have proper type - DataControlGetValueSuccessCallback.onsuccess
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:TBD:Datacontrol:DataControlGetValueSuccessCallback:onsuccess U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== TEST_CRITERIA CBOA CBT
+
+setup({timeout: 30000});
+
+var t = async_test('DataControlGetValueSuccessCallback_onsuccess', {timeout: 30000}),
+    globalDataControl, globalReqId = generateGlobalReqId(),
+    currentDate = new Date().getTime().toString(), key =  currentDate, value = currentDate + "value",
+    getSuccess, getError, addSuccess, addError;
+
+t.step(function () {
+    getSuccess = t.step_func(function (values, reqId) {
+        assert_equals(reqId, globalReqId, "Incorrect request id");
+        assert_type(values, "array", "Not an array");
+        assert_equals(values.length, 1, "Incorrect number of values");
+        assert_equals(values[0], value, "Incorrect value");
+        t.done();
+    });
+
+    getError = t.step_func(function (reqId, error) {
+        assert_unreached("getValue() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    addSuccess = t.step_func(function (reqId) {
+        assert_equals(reqId, globalReqId, "Incorrect request id");
+        globalReqId++;
+        globalDataControl.getValue(globalReqId, key, getSuccess, getError);
+    });
+
+    addError = t.step_func(function (reqId, error) {
+        assert_unreached("addValue() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_MAP);
+    globalDataControl.addValue(globalReqId, key, value, addSuccess, addError);
+});
+
+}
+
+function DataControlInsertSuccessCallback_notexist() {
+//==== TEST: DataControlInsertSuccessCallback_notexist
+//==== PRIORITY P3
+//==== LABEL Check if interface DataControlInsertSuccessCallback exists, it should not
+//==== SPEC Tizen Web API:TBD:Datacontrol:DataControlInsertSuccessCallback:DataControlInsertSuccessCallback U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== TEST_CRITERIA CBNIO
+
+test(function () {
+    check_no_interface_object("DataControlInsertSuccessCallback");
+}, 'DataControlInsertSuccessCallback_notexist');
+
+}
+
+function DataControlInsertSuccessCallback_onsuccess() {
+//==== TEST: DataControlInsertSuccessCallback_onsuccess
+//==== PRIORITY P3
+//==== LABEL Check if callback is called and if its arguments have proper type - DataControlInsertSuccessCallback
+//==== SPEC Tizen Web API:TBD:Datacontrol:DataControlInsertSuccessCallback:onsuccess U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA CBOA CBT
+
+setup({timeout: 30000});
+
+var t = async_test('DataControlInsertSuccessCallback_onsuccess', {timeout: 30000}), globalDataControl, globalReqId = generateGlobalReqId(),
+    currentDate = new Date().getTime().toString(), insertError, insertSuccess, rowData;
+t.step(function () {
+
+    rowData = {
+        columns: ["WORD", "WORD_DESC"],
+        values: ["'" + currentDate + "'", "'" + currentDate + "_desc'"]
+    };
+
+    insertSuccess = t.step_func(function (reqId, insertRowId) {
+        assert_equals(reqId, globalReqId, "Incorrect request id");
+        assert_type(reqId, "unsigned long", "reqId is not unsigned long");
+        assert_type(insertRowId, "long", "insertRowId is not long.");
+        t.done();
+    });
+
+    insertError = t.step_func(function (reqId, error) {
+        assert_unreached("insert() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_SQL);
+    globalDataControl.insert(globalReqId, rowData, insertSuccess, insertError);
+});
+
+}
+
+function DataControlManagerObject_notexist() {
+//==== TEST: DataControlManagerObject_notexist
+//==== PRIORITY P3
+//==== LABEL Check if interface DataControlManagerObject exists, it should not
+//==== SPEC Tizen Web API:TBD:Datacontrol:DataControlManagerObject:DataControlManagerObject U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("DataControlManagerObject");
+}, 'DataControlManager_extend');
+
+}
+
+function DataControlManager_extend() {
+//==== TEST: DataControlManager_extend
+//==== PRIORITY P3
+//==== LABEL Test whether the object DataControlManager can have new properties added
+//==== SPEC Tizen Web API:TBD:Datacontrol:DataControlManager:DataControlManager U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== TEST_CRITERIA OBX
+
+test(function () {
+    check_extensibility(tizen.datacontrol);
+}, 'DataControlManager_extend');
+
+}
+
+function DataControlManager_getDataControlConsumer_MAP() {
+//==== TEST: DataControlManager_getDataControlConsumer_MAP
+//==== LABEL Check DataControlManager.getDataControlConsumer returns valid object - MAP
+//==== SPEC Tizen Web API:TBD:Datacontrol:DataControlManager:getDataControlConsumer M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== TEST_CRITERIA MMINA MR
+//==== PRIORITY P1
+
+test(function () {
+    var globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_MAP);
+
+    assert_type(globalDataControl, "object", "Not an object");
+    assert_equals(globalDataControl.type, TYPE_MAP, "Incorrect type");
+    assert_equals(globalDataControl.providerId, PROVIDER_ID, "Incorrect providerId");
+    assert_equals(globalDataControl.dataId, DATA_ID, "Incorrect dataId");
+
+    assert_type(globalDataControl.addValue, "function", "addValue is not a function");
+    assert_type(globalDataControl.removeValue, "function", "removeValue is not a function");
+    assert_type(globalDataControl.getValue, "function", "getValue is not a function");
+    assert_type(globalDataControl.updateValue, "function", "updateValue is not a function");
+
+}, 'DataControlManager_getDataControlConsumer_MAP');
+
+}
+
+function DataControlManager_getDataControlConsumer_SQL() {
+//==== TEST: DataControlManager_getDataControlConsumer_SQL
+//==== LABEL Check DataControlManager.getDataControlConsumer returns valid object - SQL
+//==== SPEC Tizen Web API:TBD:Datacontrol:DataControlManager:getDataControlConsumer M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== TEST_CRITERIA MMINA MR
+//==== PRIORITY P1
+
+test(function () {
+    var globalDataControl;
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_SQL);
+
+    assert_type(globalDataControl, "object", "Not an object");
+    assert_equals(globalDataControl.type, TYPE_SQL, "Incorrect type");
+    assert_equals(globalDataControl.providerId, PROVIDER_ID, "Incorrect providerId");
+    assert_equals(globalDataControl.dataId, DATA_ID, "Incorrect dataId");
+
+    assert_type(globalDataControl.insert, "function", "insert is not a function");
+    assert_type(globalDataControl.update, "function", "update is not a function");
+    assert_type(globalDataControl.remove, "function", "remove is not a function");
+    assert_type(globalDataControl.select, "function", "select is not a function");
+
+}, 'DataControlManager_getDataControlConsumer_SQL');
+
+}
+
+function DataControlManager_getDataControlConsumer_exist() {
+//==== TEST: DataControlManager_getDataControlConsumer_exist
+//==== LABEL Check if method getDataControlConsumer of DataControlManager exists
+//==== SPEC Tizen Web API:TBD:Datacontrol:DataControlManager:getDataControlConsumer M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== TEST_CRITERIA ME
+//==== PRIORITY P1
+
+test(function () {
+    assert_true("getDataControlConsumer" in tizen.datacontrol, "No getDataControlConsumer method in tizen.datacontrol");
+    check_method_exists(tizen.datacontrol, "getDataControlConsumer");
+}, 'DataControlManager_getDataControlConsumer_exist');
+
+}
+
+function DataControlManager_getDataControlConsumer_missarg() {
+//==== TEST: DataControlManager_getDataControlConsumer_missarg
+//==== LABEL Check with missing non-optional argument - getDataControlConsumer
+//==== SPEC Tizen Web API:TBD:Datacontrol:DataControlManager:getDataControlConsumer M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== TEST_CRITERIA MMA
+//==== PRIORITY P1
+
+test(function () {
+    var exceptionName = "TypeMismatchError";
+
+    assert_throws({name: exceptionName}, function () {
+        tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID);
+    }, exceptionName + " should be thrown - missing type");
+
+}, 'DataControlManager_getDataControlConsumer_missarg');
+
+}
+
+function DataControlManager_getDataControlConsumer_noarg() {
+//==== TEST: DataControlManager_getDataControlConsumer_noarg
+//==== LABEL Check if getDataControlConsumer method can be invoked with no arguments
+//==== PRIORITY: P2
+//==== SPEC Tizen Web API:Application:DataControl:DataControlManager:getDataControlConsumer M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.2.1/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== TEST_CRITERIA MMA
+
+test(function () {
+    var globalDataConsumer;
+
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        globalDataConsumer = tizen.datacontrol.getDataControlConsumer();
+    }, TYPE_MISMATCH_EXCEPTION + " should be thrown - given no parameter. ");
+}, 'DataControlManager_getDataControlConsumer_noarg');
+
+}
+
+function DataControlManager_getDataControlConsumer_type_TypeMismatch() {
+//==== TEST: DataControlManager_getDataControlConsumer_type_TypeMismatch
+//==== LABEL Check argument type conversions exception - getDataControlConsumer
+//==== PRIORITY: P2
+//==== SPEC Tizen Web API:TBD:Datacontrol:DataControlManager:getDataControlConsumer M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== TEST_CRITERIA MC
+
+test(function () {
+    var conversionTable, i, exceptionName, invalidType;
+
+    conversionTable = getTypeConversionExceptions("enum", true);
+
+    for(i = 0; i < conversionTable.length; i++) {
+        invalidType  = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+
+        assert_throws({name: exceptionName}, function () {
+            tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, invalidType);
+        }, exceptionName + " should be thrown - missing success callback");
+    }
+
+}, 'DataControlManager_getDataControlConsumer_type_TypeMismatch');
+
+}
+
+function DataControlManager_in_tizen() {
+//==== TEST: DataControlManager_in_tizen
+//==== PRIORITY P3
+//==== LABEL Check if datacontrol exists in tizen
+//==== SPEC Tizen Web API:TBD:Datacontrol:DataControlManager:DataControlManager U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== TEST_CRITERIA OBME
+
+test(function () {
+    assert_true("datacontrol" in tizen, "No datacontrol in tizen.");
+    check_readonly(tizen, "datacontrol", tizen.datacontrol, "object", "dummyValue");
+}, 'DataControlManager_in_tizen');
+
+}
+
+function DataControlManager_notexist() {
+//==== TEST: DataControlManager_notexist
+//==== PRIORITY P3
+//==== LABEL Check if interface DataControlManager exists, it should not
+//==== SPEC Tizen Web API:TBD:Datacontrol:DataControlManager:DataControlManager U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("DataControlManager");
+}, 'DataControlManager_notexist');
+
+}
+
+function DataControlSelectSuccessCallback_notexist() {
+//==== TEST: DataControlSelectSuccessCallback_notexist
+//==== PRIORITY P3
+//==== LABEL Check if interface DataControlSelectSuccessCallback exists, it should not
+//==== SPEC Tizen Web API:TBD:Datacontrol:DataControlSelectSuccessCallback:DataControlSelectSuccessCallback U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== TEST_CRITERIA CBNIO
+
+test(function () {
+    check_no_interface_object("DataControlSelectSuccessCallback");
+}, 'DataControlSelectSuccessCallback_notexist');
+
+}
+
+function DataControlSelectSuccessCallback_onsuccess() {
+//==== TEST: DataControlSelectSuccessCallback_onsuccess
+//==== PRIORITY P3
+//==== LABEL Check if callback is called and if its arguments have proper type - DataControlSelectSuccessCallback
+//==== SPEC Tizen Web API:TBD:Datacontrol:DataControlSelectSuccessCallback:onsuccess U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA CBOA CBT
+
+setup({timeout: 30000});
+
+var t = async_test('DataControlSelectSuccessCallback_onsuccess', {timeout: 30000}), globalDataControl, globalReqId = generateGlobalReqId(),
+    currentDate = new Date().getTime().toString(), selectError, insertSuccess, insertError, selectSuccess, i, insertedData = {},
+    rowData, description = currentDate + "_desc", descriptionToSet = "'" + description + "'", columnsToSet = ["WORD",
+    "WORD_DESC"], numberOfElements = 5, key, wordColumnValue, wordDescColumnValue, insertCounter = 0;
+t.step(function () {
+
+    selectSuccess = t.step_func(function (rows, reqId) {
+        assert_equals(reqId, globalReqId, "incorrect request id");
+        assert_equals(rows.length, numberOfElements, "Incorrect number of rows.");
+        for (i = 0; i < rows.length; i++) {
+            assert_array_equals(rows[i].columns, columnsToSet, "Incorrect column names");
+            wordColumnValue = rows[i].values[0];
+            wordDescColumnValue = rows[i].values[1];
+            assert_own_property(insertedData, wordColumnValue, "Incorrect value for WORD columns");
+            assert_equals(wordDescColumnValue, insertedData[wordColumnValue], "Incorrect value for WORD_DESC column");
+            delete insertedData[wordColumnValue];
+        }
+        t.done();
+    });
+
+    selectError = t.step_func(function (reqId, error) {
+        assert_unreached("select() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    insertSuccess = t.step_func(function (reqId, insertRowId) {
+        globalReqId++;
+        insertCounter++;
+        //check to execute appropriate number of inserts before selecting
+        if (insertCounter <= numberOfElements) {
+            rowData = {};
+            rowData.columns = columnsToSet;
+            key = currentDate + globalReqId;
+            rowData.values = ["'" + key + "'", descriptionToSet];
+
+            insertedData[key] = description;
+
+            globalDataControl.insert(globalReqId, rowData, insertSuccess, insertError);
+        } else {
+            globalDataControl.select(globalReqId, columnsToSet,
+                columnsToSet[1] + "=" + descriptionToSet, selectSuccess, selectError);
+        }
+    });
+
+    insertError = t.step_func(function (reqId, error) {
+        assert_unreached("insert() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_SQL);
+    insertSuccess();
+});
+
+}
+
+function DataControlSuccessCallback_notexist() {
+//==== TEST: DataControlSuccessCallback_notexist
+//==== PRIORITY P3
+//==== LABEL Check if interface DataControlSuccessCallback exists, it should not
+//==== SPEC Tizen Web API:TBD:Datacontrol:DataControlSuccessCallback:DataControlSuccessCallback U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== TEST_CRITERIA CBNIO
+
+test(function () {
+    check_no_interface_object("DataControlSuccessCallback");
+}, 'DataControlSuccessCallback_notexist');
+
+}
+
+function DataControlSuccessCallback_onsuccess_MAP() {
+//==== TEST: DataControlSuccessCallback_onsuccess_MAP
+//==== PRIORITY P3
+//==== LABEL Check if callback is called and if its arguments have proper type - MAP
+//==== SPEC Tizen Web API:TBD:Datacontrol:DataControlSuccessCallback:onsuccess U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA CBOA CBT
+
+setup({timeout: 30000});
+
+var t = async_test('DataControlSuccessCallback_onsuccess_MAP', {timeout: 30000}),
+    globalDataControl, globalReqId = generateGlobalReqId(),
+    currentDate = new Date().getTime().toString(), key =  currentDate, value = currentDate + "value",
+    addSuccess, addError;
+
+t.step(function () {
+
+    addSuccess = t.step_func(function (reqId) {
+        assert_equals(reqId, globalReqId, "Incorrect request id");
+        t.done();
+    });
+
+    addError = t.step_func(function (reqId, error) {
+        assert_unreached("addValue() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_MAP);
+    globalDataControl.addValue(globalReqId, key, value, addSuccess, addError);
+});
+
+}
+
+function DataControlSuccessCallback_onsuccess_SQL() {
+//==== TEST: DataControlSuccessCallback_onsuccess_SQL
+//==== PRIORITY P3
+//==== LABEL Check if callback is called and if its arguments have proper type - SQL
+//==== SPEC Tizen Web API:TBD:Datacontrol:DataControlSuccessCallback:onsuccess U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA CBOA CBT
+
+setup({timeout: 30000});
+
+var t = async_test('DataControlSuccessCallback_onsuccess_SQL', {timeout: 30000}), globalDataControl, globalReqId = generateGlobalReqId(),
+    currentDate = new Date().getTime().toString(), insertSuccess, insertError, rowData, removeSuccess, removeError;
+t.step(function () {
+
+    rowData = {
+        columns: ["WORD", "WORD_DESC"],
+        values: ["'" + currentDate + "'", "'" + currentDate + "_desc'"]
+    };
+
+
+    removeSuccess = t.step_func(function (reqId) {
+        assert_equals(reqId, globalReqId, "Incorrect requestId.");
+        t.done();
+    });
+
+    removeError = t.step_func(function (reqId, error) {
+        assert_unreached("remove() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    insertSuccess = t.step_func(function (reqId, insertRowId) {
+        globalReqId++;
+        globalDataControl.remove(globalReqId,
+            rowData.columns[0] + "=" + rowData.values[0], removeSuccess, removeError);
+    });
+
+    insertError = t.step_func(function (reqId, error) {
+        assert_unreached("insert() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_SQL);
+    globalDataControl.insert(globalReqId, rowData, insertSuccess, insertError);
+});
+
+}
+
+function MappedDataControlConsumer_addValue() {
+//==== TEST: MappedDataControlConsumer_addValue
+//==== LABEL Check if addValue method called with non-optional arguments does what it should
+//==== SPEC Tizen Web API:TBD:Datacontrol:MappedDataControlConsumer:addValue M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== TEST_CRITERIA MR MMINA
+//==== PRIORITY P1
+
+var dataConsumer, globalReqId = generateGlobalReqId(),
+    currentDate = new Date().getTime().toString(), value = "samsung", returnedValue;
+
+test(function () {
+    dataConsumer = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_MAP);
+
+    returnedValue = dataConsumer.addValue(globalReqId, currentDate, value);
+    assert_equals(returnedValue, undefined, "Incorrect returned value");
+
+}, 'MappedDataControlConsumer_addValue');
+
+}
+
+function MappedDataControlConsumer_addValue_errorCallback_TypeMismatch() {
+//==== TEST: MappedDataControlConsumer_addValue_errorCallback_TypeMismatch
+//==== LABEL Check type conversions for errorCallback argument of MappedDataControlConsumer.addValue method
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:TBD:Datacontrol:MappedDataControlConsumer:addValue M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test('MappedDataControlConsumer_addValue_errorCallback_TypeMismatch', {timeout: 30000}),
+    conversionTable, successCallback, errorCallback, exceptionName, i, globalReqId = generateGlobalReqId(),
+    dataConsumer = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_MAP),
+    currentDate = new Date().getTime().toString(), value = "samsung";
+
+t.step(function () {
+    successCallback = t.step_func(function (reqId) {
+        assert_unreached("addValue() success callback invoked");
+    });
+
+    conversionTable = getTypeConversionExceptions("functionObject", true);
+
+    for(i = 0; i < conversionTable.length; i++) {
+        errorCallback = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+
+        assert_throws({name: exceptionName}, function () {
+            dataConsumer.addValue(globalReqId, currentDate, value, errorCallback);
+        }, exceptionName + " should be thrown. Given - " + errorCallback);
+    }
+
+    t.done();
+});
+
+}
+
+function MappedDataControlConsumer_addValue_errorCallback_invalid_cb() {
+//==== TEST: MappedDataControlConsumer_addValue_errorCallback_invalid_cb
+//==== LABEL Check if MappedDataControlConsumer.addValue method throws exception when errorCallback is invalid
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:TBD:Datacontrol:MappedDataControlConsumer:addValue M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 30000});
+
+var t = async_test('MappedDataControlConsumer_addValue_errorCallback_invalid_cb', {timeout: 30000}),
+    successCallback, invalidCallback, exceptionName = "TypeMismatchError", globalReqId = generateGlobalReqId(),
+    dataConsumer = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_MAP),
+    currentDate = new Date().getTime().toString(), value = "samsung";
+
+t.step(function () {
+    successCallback = t.step_func(function (reqId) {
+        assert_unreached("addValue() success callback invoked");
+    });
+
+    invalidCallback = {
+        onerror: t.step_func(function (reqId, error) {
+            assert_unreached("addValue() invalid error callback invoked");
+        })
+    };
+
+    assert_throws({name: exceptionName}, function () {
+        dataConsumer.addValue(globalReqId, currentDate, value, successCallback, invalidCallback);
+    }, exceptionName + " should be thrown");
+
+    t.done();
+});
+
+}
+
+function MappedDataControlConsumer_addValue_exist() {
+//==== TEST: MappedDataControlConsumer_addValue_exist
+//==== LABEL Check if method addValue of MappedDataControlConsumer exists
+//==== SPEC Tizen Web API:TBD:Datacontrol:MappedDataControlConsumer:addValue M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== TEST_CRITERIA ME
+//==== PRIORITY P1
+
+test(function () {
+    var globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_MAP);
+    assert_true("addValue" in globalDataControl, "No addValue method in globalDataControl");
+    check_method_exists(globalDataControl, "addValue");
+}, 'MappedDataControlConsumer_addValue_exist');
+
+}
+
+function MappedDataControlConsumer_addValue_successCallback_TypeMismatch() {
+//==== TEST: MappedDataControlConsumer_addValue_successCallback_TypeMismatch
+//==== LABEL Check type conversions for successCallback argument of MappedDataControlConsumer.addValue method
+//==== PRIORITY: P2
+//==== SPEC Tizen Web API:TBD:Datacontrol:MappedDataControlConsumer:addValue M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== TEST_CRITERIA MC
+
+test(function () {
+    var conversionTable, successCallback, exceptionName, i, globalReqId = generateGlobalReqId(),
+        dataConsumer = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_MAP),
+        currentDate = new Date().getTime().toString(), value = "samsung";
+
+    conversionTable = getTypeConversionExceptions("functionObject", true);
+
+    for(i = 0; i < conversionTable.length; i++) {
+        successCallback = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+
+        assert_throws({name: exceptionName},
+            function () {
+                dataConsumer.addValue(globalReqId, currentDate, value, successCallback);
+            }, exceptionName + " should be thrown. Given - " + successCallback);
+    }
+}, 'MappedDataControlConsumer_addValue_successCallback_TypeMismatch');
+
+}
+
+function MappedDataControlConsumer_addValue_successCallback_invalid_cb() {
+//==== TEST: MappedDataControlConsumer_addValue_successCallback_invalid_cb
+//==== LABEL Check if MappedDataControlConsumer.addValue method throws exception when successCallback is invalid
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:TBD:Datacontrol:MappedDataControlConsumer:addValue M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 30000});
+
+var t = async_test('MappedDataControlConsumer_addValue_successCallback_invalid_cb', {timeout: 30000}),
+    invalidCallback, exceptionName = "TypeMismatchError", globalReqId = generateGlobalReqId(),
+    dataConsumer = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_MAP),
+    currentDate = new Date().getTime().toString(), value = "samsung";
+
+t.step(function () {
+    invalidCallback = {
+        onsuccess: t.step_func(function (reqId) {
+            assert_unreached("addValue() invalid success callback invoked");
+        })
+    };
+
+    assert_throws({name: exceptionName},
+        function () {
+            dataConsumer.addValue(globalReqId, currentDate, value, invalidCallback);
+        }, exceptionName + " should be thrown");
+
+    t.done();
+});
+
+}
+
+function MappedDataControlConsumer_addValue_with_errorCallback() {
+//==== TEST: MappedDataControlConsumer_addValue_with_errorCallback
+//==== LABEL Check if addValue method called with optional errorCallback does what it should
+//==== SPEC Tizen Web API:TBD:Datacontrol:MappedDataControlConsumer:addValue M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MR MOA MAST
+//==== PRIORITY P1
+
+setup({timeout: 30000});
+
+var t = async_test('MappedDataControlConsumer_addValue_with_errorCallback', {timeout: 30000}),
+    getSuccessCallback, getErrorCallback, dataConsumer, globalReqId = generateGlobalReqId(),
+    currentDate = new Date().getTime().toString(), value = "samsung", returnedValue = null,
+    addSuccessCallback, addErrorCallback;
+
+t.step(function () {
+    dataConsumer = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_MAP);
+
+    getSuccessCallback = t.step_func(function (values, reqId) {
+        assert_equals(values.length, 1, "Length is incorrect");
+        assert_equals(values[0], value, "value is not set");
+        t.done();
+    });
+
+    getErrorCallback = t.step_func(function (reqId, error) {
+        assert_unreached("getValue() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    addSuccessCallback = t.step_func(function (reqId) {
+        assert_equals(returnedValue, undefined, "Incorrect returned value");
+        assert_equals(reqId, globalReqId, "Incorrect request id");
+        globalReqId++;
+        dataConsumer.getValue(globalReqId, currentDate, getSuccessCallback, getErrorCallback);
+    });
+
+    addErrorCallback = t.step_func(function (reqId, error) {
+        assert_unreached("addValue() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    returnedValue = dataConsumer.addValue(globalReqId, currentDate, value, addSuccessCallback, addErrorCallback);
+});
+
+}
+
+function MappedDataControlConsumer_addValue_with_successCallback() {
+//==== TEST: MappedDataControlConsumer_addValue_with_successCallback
+//==== LABEL Check if addValue method called with optional successCallback does what it should
+//==== SPEC Tizen Web API:TBD:Datacontrol:MappedDataControlConsumer:addValue M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MR MOA MAST
+//==== PRIORITY P1
+
+setup({timeout: 30000});
+
+var t = async_test('MappedDataControlConsumer_addValue_with_successCallback', {timeout: 30000}),
+    addSuccessCallback, getSuccessCallback, getErrorCallback, dataConsumer, globalReqId = generateGlobalReqId(),
+    currentDate = new Date().getTime().toString(), value = "samsung", returnedValue = null;
+
+t.step(function () {
+    dataConsumer = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_MAP);
+
+    getSuccessCallback = t.step_func(function (values, reqId) {
+        assert_equals(values.length, 1, "Length is incorrect");
+        assert_equals(values[0], value, "value is not set");
+        t.done();
+    });
+
+    getErrorCallback = t.step_func(function (reqId, error) {
+        assert_unreached("getValue() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    addSuccessCallback = t.step_func(function (reqId) {
+        assert_equals(returnedValue, undefined, "Incorrect returned value");
+        assert_equals(reqId, globalReqId, "Incorrect request id");
+        globalReqId++;
+        dataConsumer.getValue(globalReqId, currentDate, getSuccessCallback, getErrorCallback);
+    });
+    returnedValue = dataConsumer.addValue(globalReqId, currentDate, value, addSuccessCallback);
+});
+
+}
+
+function MappedDataControlConsumer_extend() {
+//==== TEST: MappedDataControlConsumer_extend
+//==== PRIORITY P3
+//==== LABEL Check if MappedDataControlConsumer can have new properties added
+//==== SPEC Tizen Web API:TBD:Datacontrol:MappedDataControlConsumer:MappedDataControlConsumer U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== TEST_CRITERIA OBX
+
+test(function () {
+    var globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_MAP);
+    check_extensibility(globalDataControl);
+}, 'MappedDataControlConsumer_extend');
+
+}
+
+function MappedDataControlConsumer_getValue() {
+//==== TEST: MappedDataControlConsumer_getValue
+//==== LABEL Check if MappedDataControlConsumer.getValue method works properly
+//==== SPEC Tizen Web API:TBD:Datacontrol:MappedDataControlConsumer:getValue M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MOA MR
+//==== PRIORITY P1
+
+setup({timeout: 30000});
+
+var t = async_test('MappedDataControlConsumer_getValue', {timeout: 30000}),
+    globalDataControl, globalReqId = generateGlobalReqId(),
+    currentDate = new Date().getTime().toString(), key =  currentDate, value = currentDate + "value",
+    getSuccess, getError, addSuccess, addError, returnedValue = null;
+
+t.step(function () {
+    getSuccess = t.step_func(function (values, reqId) {
+        assert_equals(returnedValue, undefined, "Incorrect returned value");
+        assert_equals(reqId, globalReqId, "Incorrect request id");
+        assert_type(values, "array", "Not an array");
+        assert_equals(values.length, 1, "Incorrect number of values");
+        assert_equals(values[0], value, "Incorrect value");
+        t.done();
+    });
+
+    getError = t.step_func(function (reqId, error) {
+        assert_unreached("getValue() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    addSuccess = t.step_func(function (reqId) {
+        assert_equals(reqId, globalReqId, "Incorrect request id");
+        globalReqId++;
+        returnedValue = globalDataControl.getValue(globalReqId, key, getSuccess, getError);
+    });
+
+    addError = t.step_func(function (reqId, error) {
+        assert_unreached("addValue() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_MAP);
+    globalDataControl.addValue(globalReqId, key, value, addSuccess, addError);
+});
+
+}
+
+function MappedDataControlConsumer_getValue_errorCallback_TypeMismatch() {
+//==== TEST: MappedDataControlConsumer_getValue_errorCallback_TypeMismatch
+//==== LABEL Check type conversions for errorCallback argument of MappedDataControlConsumer.getValue method
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:TBD:Datacontrol:MappedDataControlConsumer:getValue M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test('MappedDataControlConsumer_getValue_errorCallback_TypeMismatch', {timeout: 30000}),
+    conversionTable, successCallback, errorCallback, exceptionName, i, globalReqId = generateGlobalReqId(),
+    dataConsumer = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_MAP),
+    currentDate = new Date().getTime().toString();
+
+t.step(function () {
+    successCallback = t.step_func(function (values, reqId) {
+        assert_unreached("getValue() success callback invoked");
+    });
+
+    conversionTable = getTypeConversionExceptions("functionObject", true);
+
+    for(i = 0; i < conversionTable.length; i++) {
+        errorCallback = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+
+        assert_throws({name: exceptionName},
+            function () {
+                dataConsumer.getValue(globalReqId, currentDate, successCallback, errorCallback);
+            }, exceptionName + " should be thrown. Given - " + errorCallback);
+    }
+
+    t.done();
+});
+
+}
+
+function MappedDataControlConsumer_getValue_errorCallback_invalid_cb() {
+//==== TEST: MappedDataControlConsumer_getValue_errorCallback_invalid_cb
+//==== LABEL Check if MappedDataControlConsumer.getValue method throws exception when errorCallback is invalid
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:TBD:Datacontrol:MappedDataControlConsumer:getValue M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 30000});
+
+var t = async_test('MappedDataControlConsumer_getValue_errorCallback_invalid_cb', {timeout: 30000}),
+    successCallback, invalidCallback, exceptionName = "TypeMismatchError", globalReqId = generateGlobalReqId(),
+    dataConsumer = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_MAP),
+    currentDate = new Date().getTime().toString();
+
+t.step(function () {
+    successCallback = t.step_func(function (values, reqId) {
+        assert_unreached("getValue() success callback invoked");
+    });
+
+    invalidCallback = {
+        onerror: t.step_func(function (reqId, error) {
+            assert_unreached("getValue() invalid error callback invoked");
+        })
+    };
+
+    assert_throws({name: exceptionName},
+        function () {
+            dataConsumer.getValue(globalReqId, currentDate, successCallback, invalidCallback);
+        }, exceptionName + " should be thrown.");
+
+    t.done();
+});
+
+}
+
+function MappedDataControlConsumer_getValue_errorCallback_invoked() {
+//==== TEST: MappedDataControlConsumer_getValue_errorCallback_invoked
+//==== LABEL Check exception in error callback of getValue method
+//==== SPEC Tizen Web API:TBD:Datacontrol:MappedDataControlConsumer:getValue M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P2
+//==== TEST_CRITERIA MERRCB
+
+setup({timeout: 30000});
+
+var t = async_test('MappedDataControlConsumer_getValue_errorCallback_invoked', {timeout: 30000}), dataConsumer, globalReqId = generateGlobalReqId(),
+    addSuccessCallback, addErrorCallback, getValueSuccessCB, errorcb;
+
+t.step(function () {
+
+    errorcb = t.step_func(function (reqId, error) {     
+        assert_equals(error.name, "NotFoundError", "incorrect error code");
+        t.done();
+    });
+
+    getValueSuccessCB = t.step_func(function (reqId) {
+        assert_unreached("getValue() errorcallback");
+    });
+
+    addSuccessCallback = t.step_func(function (reqId) {
+        globalReqId++;
+        dataConsumer.getValue(globalReqId, "android", getValueSuccessCB, errorcb);
+    });
+
+    addErrorCallback = t.step_func(function (reqId, error) {
+        assert_unreached("addValue() errorcallback");
+    });
+
+    dataConsumer = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_MAP);
+    dataConsumer.addValue(globalReqId, "tizen", "samsung", addSuccessCallback, addErrorCallback);
+});
+
+}
+
+function MappedDataControlConsumer_getValue_exist() {
+//==== TEST: MappedDataControlConsumer_getValue_exist
+//==== LABEL Check if method getValue of MappedDataControlConsumer exists
+//==== SPEC Tizen Web API:TBD:Datacontrol:MappedDataControlConsumer:getValue M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== TEST_CRITERIA ME
+//==== PRIORITY P1
+
+test(function () {
+    var globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_MAP);
+    assert_true("getValue" in globalDataControl, "No getValue method in globalDataControl");
+    check_method_exists(globalDataControl, "getValue");
+}, 'MappedDataControlConsumer_getValue_exist');
+
+}
+
+function MappedDataControlConsumer_getValue_missarg() {
+//==== TEST: MappedDataControlConsumer_getValue_missarg
+//==== LABEL Check with missing non-optional argument - MappedDataControlConsumer.getValue
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:TBD:Datacontrol:MappedDataControlConsumer:getValue M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== TEST_CRITERIA MMA
+//==== PRIORITY P1
+
+setup({timeout: 30000});
+
+var t = async_test('MappedDataControlConsumer_getValue_missarg', {timeout: 30000}),
+    globalDataControl, globalReqId = generateGlobalReqId(),
+    currentDate = new Date().getTime().toString(), key =  currentDate, value = currentDate + "value",
+    addSuccess, addError, exceptionName = "TypeMismatchError";
+
+t.step(function () {
+
+    addSuccess = t.step_func(function (reqId) {
+        assert_equals(reqId, globalReqId, "incorrect request id");
+        globalReqId++;
+        assert_throws({name: exceptionName}, function () {
+            globalDataControl.getValue(globalReqId, key);
+        }, exceptionName + " should be thrown - missing success callback");
+        t.done();
+    });
+
+    addError = t.step_func(function (reqId, error) {
+        assert_unreached("addValue() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_MAP);
+    globalDataControl.addValue(globalReqId, key, value, addSuccess, addError);
+});
+
+}
+
+function MappedDataControlConsumer_getValue_noarg() {
+//==== TEST: MappedDataControlConsumer_getValue_noarg
+//==== LABEL Check with no argument - MappedDataControlConsumer::getValue
+//==== PRIORITY: P2
+//==== SPEC Tizen Web API:Application:Datacontrol:MappedDataControlConsumer:getValue M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.2.1/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== TEST_CRITERIA MMA
+
+setup({timeout: 90000});
+var t = async_test('MappedDataControlConsumer_getValue_noarg', {timeout: 90000}), globalDataControl, globalReqId, currentDate, key, value, addSuccess, addError;
+
+t.step(function () {
+    currentDate = new Date().getTime().toString();
+    globalReqId = generateGlobalReqId();
+    key = currentDate;
+    value = currentDate + "value";
+
+    addSuccess = t.step_func(function (reqId) {
+        globalReqId++;
+        assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+            globalDataControl.getValue();
+        }, TYPE_MISMATCH_EXCEPTION + " should throw exception - no argument. ");
+        t.done();
+    });
+
+    addError = t.step_func(function (reqId, error) {
+        assert_unreached(" addValue() error callback: name:  " + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_MAP);
+    globalDataControl.addValue(globalReqId, key, value, addSuccess, addError);
+});
+
+}
+
+function MappedDataControlConsumer_getValue_successCallback_TypeMismatch() {
+//==== TEST: MappedDataControlConsumer_getValue_successCallback_TypeMismatch
+//==== LABEL Check type conversions for successCallback argument of MappedDataControlConsumer.getValue method
+//==== SPEC Tizen Web API:TBD:Datacontrol:MappedDataControlConsumer:getValue M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+test(function () {
+    var conversionTable, successCallback, exceptionName, i, globalReqId = generateGlobalReqId(),
+        dataConsumer = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_MAP),
+        currentDate = new Date().getTime().toString();
+
+    conversionTable = getTypeConversionExceptions("functionObject", true);
+
+    for(i = 0; i < conversionTable.length; i++) {
+        successCallback = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+
+        assert_throws({name: exceptionName},
+            function () {
+                dataConsumer.getValue(globalReqId, currentDate, successCallback);
+            }, exceptionName + " should be thrown. Given - " + successCallback);
+    }
+}, 'MappedDataControlConsumer_getValue_successCallback_TypeMismatch');
+
+}
+
+function MappedDataControlConsumer_getValue_successCallback_invalid_cb() {
+//==== TEST: MappedDataControlConsumer_getValue_successCallback_invalid_cb
+//==== LABEL Check if MappedDataControlConsumer.getValue method throws exception when successCallback is invalid
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:TBD:Datacontrol:MappedDataControlConsumer:getValue M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 30000});
+
+var t = async_test('MappedDataControlConsumer_getValue_successCallback_invalid_cb', {timeout: 30000}),
+    invalidCallback, exceptionName = "TypeMismatchError", globalReqId = generateGlobalReqId(),
+    dataConsumer = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_MAP),
+    currentDate = new Date().getTime().toString();
+
+t.step(function () {
+    invalidCallback = {
+        onsuccess: t.step_func(function (values, reqId) {
+            assert_unreached("getValue() invalid success callback invoked");
+        })
+    };
+
+    assert_throws({name: exceptionName}, function () {
+        dataConsumer.getValue(globalReqId, currentDate, invalidCallback);
+    }, exceptionName + " should be thrown");
+
+    t.done();
+});
+
+}
+
+function MappedDataControlConsumer_getValue_without_errorCallback() {
+//==== TEST: MappedDataControlConsumer_getValue_without_errorCallback
+//==== LABEL Check MappedDataControlConsumer.getValue method without errorCallback
+//==== SPEC Tizen Web API:TBD:Datacontrol:MappedDataControlConsumer:getValue M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MMINA MR
+//==== PRIORITY P1
+
+setup({timeout: 30000});
+
+var t = async_test('MappedDataControlConsumer_getValue_without_errorCallback', {timeout: 30000}),
+    globalDataControl, globalReqId = generateGlobalReqId(),
+    currentDate = new Date().getTime().toString(), key =  currentDate, value = currentDate + "value",
+    getSuccess, addSuccess, addError, returnedValue = null;
+
+t.step(function () {
+    getSuccess = t.step_func(function (values, reqId) {
+        assert_equals(returnedValue, undefined, "Incorrect returned value");
+        assert_equals(reqId, globalReqId, "Incorrect request id");
+        assert_type(values, "array", "Not an array");
+        assert_equals(values.length, 1, "Incorrect number of values");
+        assert_equals(values[0], value, "Incorrect value");
+        t.done();
+    });
+
+    addSuccess = t.step_func(function (reqId) {
+        assert_equals(reqId, globalReqId, "Incorrect request id");
+        globalReqId++;
+        returnedValue = globalDataControl.getValue(globalReqId, key, getSuccess);
+    });
+
+    addError = t.step_func(function (reqId, error) {
+        assert_unreached("addValue() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_MAP);
+    globalDataControl.addValue(globalReqId, key, value, addSuccess, addError);
+});
+
+}
+
+function MappedDataControlConsumer_notexist() {
+//==== TEST: MappedDataControlConsumer_notexist
+//==== PRIORITY P3
+//==== LABEL Check if interface MappedDataControlConsumer exists, it should not
+//==== SPEC Tizen Web API:TBD:Datacontrol:MappedDataControlConsumer:MappedDataControlConsumer U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("MappedDataControlConsumer");
+}, 'MappedDataControlConsumer_notexist');
+
+}
+
+function MappedDataControlConsumer_removeValue() {
+//==== TEST: MappedDataControlConsumer_removeValue
+//==== LABEL Check if MappedDataControlConsumer.removeValue method works properly
+//==== SPEC Tizen Web API:TBD:Datacontrol:MappedDataControlConsumer:removeValue M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MR MOA MAST
+//==== PRIORITY P1
+
+setup({timeout: 30000});
+
+var t = async_test('MappedDataControlConsumer_removeValue', {timeout: 30000}),
+    globalDataControl, globalReqId = generateGlobalReqId(),
+    currentDate = new Date().getTime().toString(), key =  currentDate, value = currentDate + "value",
+    getSuccess, getError, addSuccess, addError, removeSuccess, removeError, returnedValue = null;
+
+t.step(function () {
+    getSuccess = t.step_func(function (values, reqId) {
+        assert_unreached("getValue() success callback invoked");
+    });
+
+    getError = t.step_func(function (reqId, error) {
+        assert_equals(reqId, globalReqId, "Incorrect request id.");
+        assert_equals(error.name, "NotFoundError", "incorrect exception name.");
+        t.done();
+    });
+
+    removeSuccess = t.step_func(function (reqId) {
+        assert_equals(returnedValue, undefined, "Incorrect returned value");
+        assert_equals(reqId, globalReqId, "Incorrect request id");
+        globalReqId++;
+        globalDataControl.getValue(globalReqId, key, getSuccess, getError);
+    });
+
+    removeError = t.step_func(function (reqId, error) {
+        assert_unreached("removeValue() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    addSuccess = t.step_func(function (reqId) {
+        assert_equals(reqId, globalReqId, "Incorrect request id");
+        globalReqId++;
+        returnedValue = globalDataControl.removeValue(globalReqId, key, value, removeSuccess, removeError);
+    });
+
+    addError = t.step_func(function (reqId, error) {
+        assert_unreached("addValue() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_MAP);
+    globalDataControl.addValue(globalReqId, key, value, addSuccess, addError);
+});
+
+}
+
+function MappedDataControlConsumer_removeValue_errorCallback_TypeMismatch() {
+//==== TEST: MappedDataControlConsumer_removeValue_errorCallback_TypeMismatch
+//==== LABEL Check type conversions for errorCallback argument of MappedDataControlConsumer.removeValue method
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:TBD:Datacontrol:MappedDataControlConsumer:removeValue M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test('MappedDataControlConsumer_removeValue_errorCallback_invalid_cb', {timeout: 30000}),
+    conversionTable, successCallback, errorCallback, exceptionName, i, globalReqId = generateGlobalReqId(),
+    dataConsumer = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_MAP),
+    currentDate = new Date().getTime().toString(), value = "samsung";
+
+t.step(function () {
+    successCallback = t.step_func(function (reqId) {
+        assert_unreached("removeValue() success callback invoked with reqId = " + reqId);
+    });
+
+    conversionTable = getTypeConversionExceptions("functionObject", true);
+
+    for(i = 0; i < conversionTable.length; i++) {
+        errorCallback = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+
+        assert_throws({name: exceptionName},
+            function () {
+                dataConsumer.removeValue(globalReqId, currentDate, value, successCallback, errorCallback);
+            }, exceptionName + " should be thrown. Given - " + errorCallback);
+    }
+
+    t.done();
+});
+
+}
+
+function MappedDataControlConsumer_removeValue_errorCallback_invalid_cb() {
+//==== TEST: MappedDataControlConsumer_removeValue_errorCallback_invalid_cb
+//==== LABEL Check if MappedDataControlConsumer.removeValue method throws exception when errorCallback is invalid
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:TBD:Datacontrol:MappedDataControlConsumer:removeValue M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 30000});
+
+var t = async_test('MappedDataControlConsumer_removeValue_errorCallback_invalid_cb', {timeout: 30000}),
+    successCallback, invalidCallback, exceptionName = "TypeMismatchError", globalReqId = generateGlobalReqId(),
+    dataConsumer = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_MAP),
+    currentDate = new Date().getTime().toString(), value = "samsung";
+
+t.step(function () {
+    successCallback = t.step_func(function (reqId) {
+        assert_unreached("removeValue() success callback invoked with reqId = " + reqId);
+    });
+
+    invalidCallback = {
+        onerror: t.step_func(function () {
+            assert_unreached("removeValue() invalid error callback invoked");
+        })
+    };
+
+    assert_throws({name: exceptionName},
+        function () {
+            dataConsumer.removeValue(globalReqId, currentDate, value, successCallback, invalidCallback);
+        }, exceptionName + " should be thrown.");
+
+    t.done();
+});
+
+}
+
+function MappedDataControlConsumer_removeValue_errorCallback_invoked() {
+//==== TEST: MappedDataControlConsumer_removeValue_errorCallback_invoked
+//==== LABEL Check exception in error callback of removeValue method
+//==== SPEC Tizen Web API:TBD:Datacontrol:MappedDataControlConsumer:removeValue M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P2
+//==== TEST_CRITERIA MERRCB
+
+setup({timeout: 30000});
+
+var t = async_test('MappedDataControlConsumer_removeValue_errorCallback_invoked', {timeout: 30000}), dataConsumer, globalReqId = generateGlobalReqId(),
+    addSuccessCallback, addErrorCallback, removeSuccessCallback, removeErrorCallback;
+
+t.step(function () {
+
+    removeErrorCallback = t.step_func(function (reqId, error) {
+        assert_equals(error.name, "NotFoundError", "incorrect error code");
+        t.done();
+    });
+
+    removeSuccessCallback = t.step_func(function (reqId) {
+        assert_unreached("removeValue() error callback");
+    });
+
+    addSuccessCallback = t.step_func(function (reqId) {
+        globalReqId++;
+        dataConsumer.removeValue(globalReqId, "android", "intel", removeSuccessCallback, removeErrorCallback);
+    });
+
+    addErrorCallback = t.step_func(function (reqId, error) {
+        assert_unreached("addValue() error callback");
+    });
+
+    dataConsumer = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_MAP);
+    dataConsumer.addValue(globalReqId, "tizen", "samsung", addSuccessCallback, addErrorCallback);
+});
+
+}
+
+function MappedDataControlConsumer_removeValue_exist() {
+//==== TEST: MappedDataControlConsumer_removeValue_exist
+//==== LABEL Check if method removeValue of MappedDataControlConsumer exists
+//==== SPEC Tizen Web API:TBD:Datacontrol:MappedDataControlConsumer:removeValue M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== TEST_CRITERIA ME
+//==== PRIORITY P1
+
+test(function () {
+    var globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_MAP);
+    assert_true("removeValue" in globalDataControl, "No removeValue method in globalDataControl");
+    check_method_exists(globalDataControl, "removeValue");
+}, 'MappedDataControlConsumer_removeValue_exist');
+
+}
+
+function MappedDataControlConsumer_removeValue_missarg() {
+//==== TEST: MappedDataControlConsumer_removeValue_missarg
+//==== LABEL Check with missing non-optional argument - MappedDataControlConsumer.removeValue
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:TBD:Datacontrol:MappedDataControlConsumer:removeValue M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== TEST_CRITERIA MMA
+//==== PRIORITY P1
+
+setup({timeout: 30000});
+
+var t = async_test('MappedDataControlConsumer_removeValue_missarg', {timeout: 30000}),
+    globalDataControl, globalReqId = generateGlobalReqId(),
+    currentDate = new Date().getTime().toString(), key =  currentDate, value = currentDate + "value", exceptionName = "TypeMismatchError",
+    addSuccess, addError;
+
+t.step(function () {
+
+    addSuccess = t.step_func(function (reqId) {
+        assert_equals(reqId, globalReqId, "incorrect request id");
+        globalReqId++;
+        assert_throws({name: exceptionName},
+        function () {
+            globalDataControl.removeValue(globalReqId, key, value);
+        }, exceptionName + " should be thrown - missing success callback.");
+        t.done();
+    });
+
+    addError = t.step_func(function (reqId, error) {
+        assert_unreached("addValue() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_MAP);
+    globalDataControl.addValue(globalReqId, key, value, addSuccess, addError);
+});
+
+}
+
+function MappedDataControlConsumer_removeValue_noarg() {
+//==== TEST: MappedDataControlConsumer_removeValue_noarg
+//==== LABEL Check with no argument - MappedDataControlConsumer::removeValue
+//==== PRIORITY: P2
+//==== SPEC Tizen Web API:Application:Datacontrol:MappedDataControlConsumer:removeValue M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.2.1/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== TEST_CRITERIA MMA
+
+setup({timeout: 90000});
+
+var t = async_test('MappedDataControlConsumer_removeValue_noarg', {timeout: 90000}), globalDataControl, globalReqId, currentDate, key, value, addSuccess, addError;
+
+t.step(function () {
+    globalReqId = generateGlobalReqId();
+    currentDate = new Date().getTime().toString();
+    key = currentDate;
+    value = currentDate + "value";
+
+    addSuccess = t.step_func(function (reqId) {
+        globalReqId++;
+        assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+            globalDataControl.removeValue();
+        }, TYPE_MISMATCH_EXCEPTION + " should throw exception - no argument. ");
+        t.done();
+    });
+
+    addError = t.step_func(function (reqId, error) {
+        assert_unreached(" addValue() error callback: name: " + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_MAP);
+    globalDataControl.addValue(globalReqId, key, value, addSuccess, addError);
+});
+
+}
+
+function MappedDataControlConsumer_removeValue_successCallback_TypeMismatch() {
+//==== TEST: MappedDataControlConsumer_removeValue_successCallback_TypeMismatch
+//==== LABEL Check type conversions for successCallback argument of MappedDataControlConsumer.removeValue method
+//==== SPEC Tizen Web API:TBD:Datacontrol:MappedDataControlConsumer:removeValue M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+test(function () {
+    var conversionTable, successCallback, exceptionName, i, globalReqId = generateGlobalReqId(),
+        dataConsumer = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_MAP),
+        currentDate = new Date().getTime().toString(), value = "samsung";
+
+    conversionTable = getTypeConversionExceptions("functionObject", true);
+
+    for(i = 0; i < conversionTable.length; i++) {
+        successCallback = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+
+        assert_throws({name: exceptionName},
+            function () {
+                dataConsumer.removeValue(globalReqId, currentDate, value, successCallback);
+            }, exceptionName + " should be thrown. Given - " + successCallback);
+    }
+}, 'MappedDataControlConsumer_removeValue_successCallback_TypeMismatch');
+
+}
+
+function MappedDataControlConsumer_removeValue_successCallback_invalid_cb() {
+//==== TEST: MappedDataControlConsumer_removeValue_successCallback_invalid_cb
+//==== LABEL Check if MappedDataControlConsumer.removeValue method throws exception when successCallback is invalid
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:TBD:Datacontrol:MappedDataControlConsumer:removeValue M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 30000});
+
+var t = async_test('MappedDataControlConsumer_removeValue_successCallback_invalid_cb', {timeout: 30000}),
+    invalidCallback, exceptionName = "TypeMismatchError", globalReqId = generateGlobalReqId(),
+    dataConsumer = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_MAP),
+    currentDate = new Date().getTime().toString(), value = "samsung";
+
+t.step(function () {
+    invalidCallback = {
+        onsuccess: t.step_func(function (reqId) {
+            assert_unreached("removeValue() invalid success callback invoked");
+        })
+    };
+
+    assert_throws({name: exceptionName},
+        function () {
+            dataConsumer.removeValue(globalReqId, currentDate, value, invalidCallback);
+        }, exceptionName + " should be thrown.");
+
+    t.done();
+});
+
+}
+
+function MappedDataControlConsumer_removeValue_without_errorCallback() {
+//==== TEST: MappedDataControlConsumer_removeValue_without_errorCallback
+//==== LABEL Check MappedDataControlConsumer.removeValue method without errorCallback
+//==== SPEC Tizen Web API:TBD:Datacontrol:MappedDataControlConsumer:removeValue M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MR MMINA MAST
+//==== PRIORITY P1
+
+setup({timeout: 30000});
+
+var t = async_test('MappedDataControlConsumer_removeValue_without_errorCallback', {timeout: 30000}),
+    globalDataControl, globalReqId = generateGlobalReqId(),
+    currentDate = new Date().getTime().toString(), key =  currentDate, value = currentDate + "value",
+    getSuccess, getError, addSuccess, addError, removeSuccess, returnedValue = null;
+
+t.step(function () {
+    getSuccess = t.step_func(function (values, reqId) {
+        assert_unreached("getValue() success callback invoked");
+    });
+
+    getError = t.step_func(function (reqId, error) {
+        assert_equals(reqId, globalReqId, "incorrect request id.");
+        assert_equals(error.name, "NotFoundError", "incorrect exception name.");
+        t.done();
+    });
+
+    removeSuccess = t.step_func(function (reqId) {
+        assert_equals(returnedValue, undefined, "Incorrect returned value");
+        assert_equals(reqId, globalReqId, "Incorrect request id");
+        globalReqId++;
+        globalDataControl.getValue(globalReqId, key, getSuccess, getError);
+    });
+
+    addSuccess = t.step_func(function (reqId) {
+        assert_equals(reqId, globalReqId, "Incorrect request id");
+        globalReqId++;
+        returnedValue = globalDataControl.removeValue(globalReqId, key, value, removeSuccess);
+    });
+
+    addError = t.step_func(function (reqId, error) {
+        assert_unreached("addValue() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_MAP);
+    globalDataControl.addValue(globalReqId, key, value, addSuccess, addError);
+});
+
+}
+
+function MappedDataControlConsumer_updateValue() {
+//==== TEST: MappedDataControlConsumer_updateValue
+//==== LABEL Check if MappedDataControlConsumer.updateValue method works properly
+//==== SPEC Tizen Web API:TBD:Datacontrol:MappedDataControlConsumer:updateValue M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MR MAST MOA
+//==== PRIORITY P1
+
+setup({timeout: 30000});
+
+var t = async_test('MappedDataControlConsumer_updateValue', {timeout: 30000}),
+    globalDataControl, globalReqId = generateGlobalReqId(),
+    currentDate = new Date().getTime().toString(), key =  currentDate, value = currentDate + "value",
+    getSuccess, getError, addSuccess, addError, updatedValue = currentDate + "updatedValue",
+    updateSuccess, updateError, returnedValue = null;
+
+t.step(function () {
+    getSuccess = t.step_func(function (values, reqId) {
+        assert_equals(reqId, globalReqId, "Incorrect request id");
+        assert_type(values, "array", "Not an array");
+        assert_equals(values.length, 1, "Incorrect number of values");
+        assert_equals(values[0], updatedValue, "Incorrect value");
+        t.done();
+    });
+
+    getError = t.step_func(function (reqId, error) {
+        assert_unreached("getValue() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    updateSuccess = t.step_func(function (reqId) {
+        assert_equals(returnedValue, undefined, "Incorrect returned value");
+        assert_equals(reqId, globalReqId, "Incorrect request id");
+        globalReqId++;
+        globalDataControl.getValue(globalReqId, key, getSuccess, getError);
+    });
+
+    updateError = t.step_func(function (reqId, error) {
+        assert_unreached("getValue() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    addSuccess = t.step_func(function (reqId) {
+        assert_equals(reqId, globalReqId, "Incorrect request id");
+        globalReqId++;
+        returnedValue = globalDataControl.updateValue(globalReqId, key, value, updatedValue, updateSuccess, updateError);
+    });
+
+    addError = t.step_func(function (reqId, error) {
+        assert_unreached("addValue() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_MAP);
+    globalDataControl.addValue(globalReqId, key, value, addSuccess, addError);
+});
+
+}
+
+function MappedDataControlConsumer_updateValue_errorCallback_TypeMismatch() {
+//==== TEST: MappedDataControlConsumer_updateValue_errorCallback_TypeMismatch
+//==== LABEL Check type conversions for errorCallback argument of MappedDataControlConsumer.updateValue method
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:TBD:Datacontrol:MappedDataControlConsumer:updateValue M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test('MappedDataControlConsumer_updateValue_errorCallback_TypeMismatch', {timeout: 30000}), i, globalDataControl,
+    globalReqId = generateGlobalReqId(), currentDate = new Date().getTime().toString(), updateSuccess, updatedValue = currentDate + "updatedValue",
+    key =  currentDate, value = currentDate + "value", addSuccess, addError, conversionTable = getTypeConversionExceptions("functionObject",
+    true);
+t.step(function () {
+
+    updateSuccess = t.step_func(function () {
+        assert_unreached("updateValue() success callback invoked");
+    });
+
+    addSuccess = t.step_func(function () {
+        for (i = 0; i < conversionTable.length; i++) {
+            globalReqId++;
+            assert_throws({name: conversionTable[i][1]}, function () {
+                globalDataControl.updateValue(globalReqId, key, value, updatedValue, updateSuccess, conversionTable[i][0]);
+            }, "exception should be thrown. Given - " + conversionTable[i][0]);
+        }
+        t.done();
+    });
+
+    addError = t.step_func(function (reqId, error) {
+        assert_unreached("addValue() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_MAP);
+    globalDataControl.addValue(globalReqId, key, value, addSuccess, addError);
+});
+
+}
+
+function MappedDataControlConsumer_updateValue_errorCallback_invalid_cb() {
+//==== TEST: MappedDataControlConsumer_updateValue_errorCallback_invalid_cb
+//==== LABEL Check if MappedDataControlConsumer.updateValue method throws exception when errorCallback is invalid
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:TBD:Datacontrol:MappedDataControlConsumer:updateValue M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 30000});
+
+var t = async_test('MappedDataControlConsumer_updateValue_errorCallback_invalid_cb', {timeout: 30000}), globalDataControl,
+    globalReqId = generateGlobalReqId(), currentDate = new Date().getTime().toString(), updateSuccess, updatedValue = currentDate + "updatedValue",
+    key =  currentDate, value = currentDate + "value", addSuccess, addError, invalidCallback;
+t.step(function () {
+
+    invalidCallback = {
+        onerror: t.step_func(function (reqId, error) {
+            assert_unreached("updateValue() invalid error callback invoked");
+        })
+    };
+
+    updateSuccess = t.step_func(function () {
+        assert_unreached("updateValue() success callback invoked");
+    });
+
+    addSuccess = t.step_func(function () {
+        assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+            globalDataControl.updateValue(globalReqId, key, value, updatedValue, updateSuccess, invalidCallback);
+        }, "exception should be thrown");
+        t.done();
+    });
+
+    addError = t.step_func(function (reqId, error) {
+        assert_unreached("addValue() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_MAP);
+    globalDataControl.addValue(globalReqId, key, value, addSuccess, addError);
+});
+
+}
+
+function MappedDataControlConsumer_updateValue_errorCallback_invoked() {
+//==== TEST: MappedDataControlConsumer_updateValue_errorCallback_invoked
+//==== LABEL Check exception in error callback of updateValue method
+//==== SPEC Tizen Web API:TBD:Datacontrol:MappedDataControlConsumer:updateValue M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P2
+//==== TEST_CRITERIA MERRCB
+
+setup({timeout: 30000});
+
+var t = async_test('MappedDataControlConsumer_updateValue_errorCallback_invoked', {timeout: 30000}), dataConsumer, globalReqId = generateGlobalReqId(),
+    addSuccessCallback, addErrorCallback, updateValueErrorcb, updateValueSuccesscb;
+
+t.step(function () {
+
+    updateValueErrorcb = t.step_func(function (reqId, error) {
+        assert_equals(error.name, "NotFoundError", "incorrect error code");
+        t.done();
+    });
+
+    updateValueSuccesscb = t.step_func(function (reqId) {
+        assert_unreached("updateValue() success callback");
+    });
+
+    addSuccessCallback = t.step_func(function (reqId) {
+        globalReqId++;
+        dataConsumer.updateValue(globalReqId, "android", "sony", "intel", updateValueSuccesscb, updateValueErrorcb);
+    });
+
+    addErrorCallback = t.step_func(function (reqId, error) {
+        assert_unreached("addValue() error callback");
+    });
+
+    dataConsumer = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_MAP);
+    dataConsumer.addValue(globalReqId, "tizen", "samsung", addSuccessCallback, addErrorCallback);
+});
+
+}
+
+function MappedDataControlConsumer_updateValue_exist() {
+//==== TEST: MappedDataControlConsumer_updateValue_exist
+//==== LABEL Check if method updateValue of MappedDataControlConsumer exists
+//==== SPEC Tizen Web API:TBD:Datacontrol:MappedDataControlConsumer:updateValue M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== TEST_CRITERIA ME
+//==== PRIORITY P1
+
+test(function () {
+    var globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_MAP);
+    assert_true("updateValue" in globalDataControl, "No updateValue method in globalDataControl");
+    check_method_exists(globalDataControl, "updateValue");
+}, 'MappedDataControlConsumer_updateValue_exist');
+
+
+}
+
+function MappedDataControlConsumer_updateValue_missarg() {
+//==== TEST: MappedDataControlConsumer_updateValue_missarg
+//==== LABEL Check with missing non-optional argument - MappedDataControlConsumer_updateValue
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:TBD:Datacontrol:MappedDataControlConsumer:updateValue M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== TEST_CRITERIA MMA
+//==== PRIORITY P1
+
+setup({timeout: 30000});
+
+var t = async_test('MappedDataControlConsumer_updateValue_missarg'),
+    globalDataControl, globalReqId = generateGlobalReqId(),
+    currentDate = new Date().getTime().toString(), key =  currentDate, value = currentDate + "value",
+    addSuccess, addError, updatedValue = currentDate + "updatedValue", exceptionName = "TypeMismatchError";
+
+t.step(function () {
+
+    addSuccess = t.step_func(function (reqId) {
+        assert_equals(reqId, globalReqId, "incorrect request id");
+        globalReqId++;
+        assert_throws({name: exceptionName},
+            function () {
+                globalDataControl.updateValue(globalReqId, key, value, updatedValue);
+            }, exceptionName + " should be thrown - missing success callback");
+        t.done();
+    });
+
+    addError = t.step_func(function (reqId, error) {
+        assert_unreached("addValue() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_MAP);
+    globalDataControl.addValue(globalReqId, key, value, addSuccess, addError);
+});
+
+}
+
+function MappedDataControlConsumer_updateValue_noarg() {
+//==== TEST: MappedDataControlConsumer_updateValue_noarg
+//==== LABEL Check with no argument - MappedDataControlConsumer::updateValue
+//==== PRIORITY: P2
+//==== SPEC Tizen Web API:Application:Datacontrol:MappedDataControlConsumer:updateValue M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.2.1/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== TEST_CRITERIA MMA
+
+setup({timeout: 90000});
+
+var t = async_test('MappedDataControlConsumer_updateValue_noarg', {timeout: 90000}), globalDataControl, globalReqId, currentDate, key, value, addSuccess, addError;
+
+t.step(function () {
+    globalReqId = generateGlobalReqId();
+    currentDate = new Date().getTime().toString();
+    key = currentDate;
+    value = currentDate + "value";
+
+    addSuccess = t.step_func(function (reqId) {
+        globalReqId++;
+        assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+            globalDataControl.updateValue();
+        }, TYPE_MISMATCH_EXCEPTION + " should throw exception - no argument. ");
+        t.done();
+    });
+    addError = t.step_func(function (reqId, error) {
+        assert_unreached("addValue() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_MAP);
+    globalDataControl.addValue(globalReqId, key, value, addSuccess, addError);
+});
+
+}
+
+function MappedDataControlConsumer_updateValue_successCallback_TypeMismatch() {
+//==== TEST: MappedDataControlConsumer_updateValue_successCallback_TypeMismatch
+//==== LABEL Check type conversions for successCallback argument of MappedDataControlConsumer.updateValue method
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:TBD:Datacontrol:MappedDataControlConsumer:updateValue M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test('MappedDataControlConsumer_updateValue_successCallback_TypeMismatch', {timeout: 30000}), i, globalDataControl,
+    globalReqId = generateGlobalReqId(), currentDate = new Date().getTime().toString(), updatedValue = currentDate + "updatedValue",
+    key =  currentDate, value = currentDate + "value", addSuccess, addError, conversionTable = getTypeConversionExceptions("functionObject");
+t.step(function () {
+
+    addSuccess = t.step_func(function () {
+        for (i = 0; i < conversionTable.length; i++) {
+            globalReqId++;
+            assert_throws({name: conversionTable[i][1]}, function () {
+                globalDataControl.updateValue(globalReqId, key, value, updatedValue, conversionTable[i][0]);
+            }, "exception should be thrown. Given - " + conversionTable[i][0]);
+        }
+        t.done();
+    });
+
+    addError = t.step_func(function (reqId, error) {
+        assert_unreached("addValue() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_MAP);
+    globalDataControl.addValue(globalReqId, key, value, addSuccess, addError);
+});
+
+}
+
+function MappedDataControlConsumer_updateValue_successCallback_invalid_cb() {
+//==== TEST: MappedDataControlConsumer_updateValue_successCallback_invalid_cb
+//==== LABEL Check if MappedDataControlConsumer.updateValue method throws exception when successCallback is invalid
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:TBD:Datacontrol:MappedDataControlConsumer:updateValue M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 30000});
+
+var t = async_test('MappedDataControlConsumer_updateValue_successCallback_invalid_cb', {timeout: 30000}), globalDataControl,
+    globalReqId = generateGlobalReqId(), currentDate = new Date().getTime().toString(), updatedValue = currentDate + "updatedValue",
+    key =  currentDate, value = currentDate + "value", addSuccess, addError, invalidCallback;
+t.step(function () {
+
+    invalidCallback = {
+        onsuccess: t.step_func(function () {
+            assert_unreached("Invalid success callback invoked");
+        })
+    };
+
+    addSuccess = t.step_func(function () {
+        assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+            globalDataControl.updateValue(globalReqId, key, value, updatedValue, invalidCallback);
+        }, "exception should be thrown");
+        t.done();
+    });
+
+    addError = t.step_func(function (reqId, error) {
+        assert_unreached("addValue() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_MAP);
+    globalDataControl.addValue(globalReqId, key, value, addSuccess, addError);
+});
+
+}
+
+function MappedDataControlConsumer_updateValue_without_errorCallback() {
+//==== TEST: MappedDataControlConsumer_updateValue_without_errorCallback
+//==== LABEL Check MappedDataControlConsumer.updateValue method without errorCallback
+//==== SPEC Tizen Web API:TBD:Datacontrol:MappedDataControlConsumer:updateValue M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MR MAST MMINA
+//==== PRIORITY P1
+
+setup({timeout: 30000});
+
+var t = async_test('MappedDataControlConsumer_updateValue_without_errorCallback', {timeout: 30000}),
+    globalDataControl, globalReqId = generateGlobalReqId(),
+    currentDate = new Date().getTime().toString(), key =  currentDate, value = currentDate + "value",
+    getSuccess, getError, addSuccess, addError, updatedValue = currentDate + "updatedValue",
+    updateSuccess, returnedValue = null;
+
+t.step(function () {
+    getSuccess = t.step_func(function (values, reqId) {
+        assert_equals(reqId, globalReqId, "Incorrect request id");
+        assert_type(values, "array", "Not an array");
+        assert_equals(values.length, 1, "Incorrect number of values");
+        assert_equals(values[0], updatedValue, "Incorrect value");
+        t.done();
+    });
+
+    getError = t.step_func(function (reqId, error) {
+        assert_unreached("getValue() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    updateSuccess = t.step_func(function (reqId) {
+        assert_equals(returnedValue, undefined, "Incorrect returned value");
+        assert_equals(reqId, globalReqId, "Incorrect request id");
+        globalReqId++;
+        globalDataControl.getValue(globalReqId, key, getSuccess, getError);
+    });
+
+    addSuccess = t.step_func(function (reqId) {
+        assert_equals(reqId, globalReqId, "Incorrect request id");
+        globalReqId++;
+        returnedValue = globalDataControl.updateValue(globalReqId, key, value, updatedValue, updateSuccess);
+    });
+
+    addError = t.step_func(function (reqId, error) {
+        assert_unreached("addValue() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_MAP);
+    globalDataControl.addValue(globalReqId, key, value, addSuccess, addError);
+});
+
+}
+
+function SQLDataControlConsumer_extend() {
+//==== TEST: SQLDataControlConsumer_extend
+//==== PRIORITY P3
+//==== LABEL Test whether the object SQLDataControlConsumer can have new properties added
+//==== SPEC Tizen Web API:TBD:Datacontrol:SQLDataControlConsumer:SQLDataControlConsumer U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== TEST_CRITERIA OBX
+
+test(function () {
+    var globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_SQL);
+    check_extensibility(globalDataControl);
+}, 'SQLDataControlConsumer_extend');
+
+}
+
+function SQLDataControlConsumer_insert() {
+//==== TEST: SQLDataControlConsumer_insert
+//==== LABEL Check if SQLDataControlConsumer.insert method works properly
+//==== SPEC Tizen Web API:TBD:Datacontrol:SQLDataControlConsumer:insert M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MR MOA MAST
+//==== PRIORITY P1
+
+setup({timeout: 30000});
+
+var t = async_test('SQLDataControlConsumer_insert', {timeout: 30000}), globalDataControl, globalReqId = generateGlobalReqId(),
+    currentDate = new Date().getTime().toString(), selectError, insertSuccess, insertError, selectSuccess, rowData,
+    returnedValue = null, descriptionToSet = currentDate + "_desc";
+t.step(function () {
+
+    rowData = {
+        columns: ["WORD", "WORD_DESC"],
+        values: ["'" + currentDate + "'", "'" + descriptionToSet + "'"]
+    };
+
+    selectSuccess = t.step_func(function (rows, reqId) {
+        assert_equals(rows.length, 1, "Incorrect number of rows.");
+        assert_array_equals(rows[0].columns, rowData.columns, "Incorrect columns");
+        assert_array_equals(rows[0].values, [currentDate, descriptionToSet], "Incorrect values");
+        t.done();
+    });
+
+    selectError = t.step_func(function (reqId, error) {
+        assert_unreached("select() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    insertSuccess = t.step_func(function (reqId, insertRowId) {
+        assert_equals(returnedValue, undefined, "Incorrect returned value");
+        assert_equals(reqId, globalReqId, "incorrect request id");
+        assert_type(reqId, "unsigned long", "reqId is not unsigned long");
+        assert_type(insertRowId, "long", "insertRowId is not long.");
+
+        globalReqId++;
+        globalDataControl.select(globalReqId, rowData.columns,
+            rowData.columns[0] + "=" + rowData.values[0], selectSuccess, selectError);
+    });
+
+    insertError = t.step_func(function (reqId, error) {
+        assert_unreached("insert() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_SQL);
+    returnedValue = globalDataControl.insert(globalReqId, rowData, insertSuccess, insertError);
+});
+
+}
+
+function SQLDataControlConsumer_insert_errorCallback_TypeMismatch() {
+//==== TEST: SQLDataControlConsumer_insert_errorCallback_TypeMismatch
+//==== LABEL Check type conversions for errorCallback argument of SQLDataControlConsumer.insert method
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:TBD:Datacontrol:SQLDataControlConsumer:insert M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test('SQLDataControlConsumer_insert_errorCallback_TypeMismatch', {timeout: 30000}), i, globalDataControl,
+    globalReqId = generateGlobalReqId(), currentDate = new Date().getTime().toString(), rowData, insertSuccess,
+    conversionTable = getTypeConversionExceptions("functionObject", true);
+t.step(function () {
+
+    rowData = {
+        columns: ["WORD", "WORD_DESC"],
+        values: ["'" + currentDate + "'", "'" + currentDate + "_desc'"]
+    };
+
+    insertSuccess = t.step_func(function () {
+        assert_unreached("insert() success callback invoked");
+    });
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_SQL);
+
+    for (i = 0; i < conversionTable.length; i++) {
+        assert_throws({name: conversionTable[i][1]}, function () {
+            globalDataControl.insert(globalReqId, rowData, insertSuccess, conversionTable[i][0]);
+        }, "exception should be thrown. Given - " + conversionTable[i][0]);
+        globalReqId++;
+    }
+
+    t.done();
+});
+
+}
+
+function SQLDataControlConsumer_insert_errorCallback_invalid_cb() {
+//==== TEST: SQLDataControlConsumer_insert_errorCallback_invalid_cb
+//==== LABEL Check if SQLDataControlConsumer.insert method throws exception when errorCallback is invalid
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:TBD:Datacontrol:SQLDataControlConsumer:insert M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 30000});
+
+var t = async_test('SQLDataControlConsumer_insert_errorCallback_invalid_cb', {timeout: 30000}), globalDataControl,
+    globalReqId = generateGlobalReqId(), currentDate = new Date().getTime().toString(), rowData, insertSuccess,
+    invalidCallback;
+t.step(function () {
+
+    rowData = {
+        columns: ["WORD", "WORD_DESC"],
+        values: ["'" + currentDate + "'", "'" + currentDate + "_desc'"]
+    };
+
+    insertSuccess = t.step_func(function () {
+        assert_unreached("insert() success callback invoked");
+    });
+
+    invalidCallback = {
+        onerror: t.step_func(function (reqId, error) {
+            assert_unreached("insert() invalid error callback invoked");
+        })
+    };
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_SQL);
+
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        globalDataControl.insert(globalReqId, rowData, insertSuccess, invalidCallback);
+    }, "exception should be thrown");
+
+    t.done();
+});
+
+}
+
+function SQLDataControlConsumer_insert_exist() {
+//==== TEST: SQLDataControlConsumer_insert_exist
+//==== LABEL Check if method insert of SQLDataControlConsumer exists
+//==== SPEC Tizen Web API:TBD:Datacontrol:SQLDataControlConsumer:insert M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== TEST_CRITERIA ME
+//==== PRIORITY P1
+
+test(function () {
+    var globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_SQL);
+    assert_true("insert" in globalDataControl, "No insert method in globalDataControl");
+    check_method_exists(globalDataControl, "insert");
+}, 'SQLDataControlConsumer_insert_exist');
+
+}
+
+function SQLDataControlConsumer_insert_insertionData_TypeMismatch() {
+//==== TEST: SQLDataControlConsumer_insert_insertionData_TypeMismatch
+//==== LABEL Check type conversions for insertionData argument of SQLDataControlConsumer.insert method
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:TBD:Datacontrol:SQLDataControlConsumer:insert M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test('SQLDataControlConsumer_insert_insertionData_TypeMismatch', {timeout: 30000}), i, globalDataControl,
+    globalReqId = generateGlobalReqId(), insertSuccess, conversionTable = getTypeConversionExceptions("dictionary", false);
+t.step(function () {
+
+    insertSuccess = t.step_func(function () {
+        assert_unreached("insert() success callback invoked");
+    });
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_SQL);
+
+    for (i = 0; i < conversionTable.length; i++) {
+        assert_throws({name: conversionTable[i][1]}, function () {
+            globalDataControl.insert(globalReqId, conversionTable[i][0], insertSuccess);
+        }, "exception should be thrown");
+        globalReqId++;
+    }
+
+    t.done();
+});
+
+}
+
+function SQLDataControlConsumer_insert_missarg() {
+//==== TEST: SQLDataControlConsumer_insert_missarg
+//==== LABEL Check with missing non-optional argument - SQLDataControlConsumer.insert
+//==== SPEC Tizen Web API:TBD:Datacontrol:SQLDataControlConsumer:insert M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== TEST_CRITERIA MMA
+//==== PRIORITY P1
+
+test(function () {
+    var globalDataControl, globalReqId = generateGlobalReqId(), exceptionName = "TypeMismatchError";
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_SQL);
+
+    assert_throws({name: exceptionName},
+        function () {
+            globalDataControl.insert(globalReqId);
+        }, exceptionName + " should be thrown - missing RowData object.");
+
+}, 'SQLDataControlConsumer_insert_missarg');
+
+}
+
+function SQLDataControlConsumer_insert_noarg() {
+//==== TEST: SQLDataControlConsumer_insert_noarg
+//==== LABEL Check with no argument - SQLDataControlConsumer::insert
+//==== PRIORITY: P2
+//==== SPEC Tizen Web API:Application:Datacontrol:SQLDataControlConsumer:insert M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.2.1/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== TEST_CRITERIA MMA
+
+test(function () {
+    var globalSQLConsumer, globalReqId = generateGlobalReqId();
+
+    globalSQLConsumer = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_SQL);
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        globalSQLConsumer.insert();
+    }, TYPE_MISMATCH_EXCEPTION + " should be thrown - no argument.");
+}, 'SQLDataControlConsumer_insert_noarg');
+
+}
+
+function SQLDataControlConsumer_insert_successCallback_TypeMismatch() {
+//==== TEST: SQLDataControlConsumer_insert_successCallback_TypeMismatch
+//==== LABEL Check type conversions for successCallback argument of SQLDataControlConsumer.insert method
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:TBD:Datacontrol:SQLDataControlConsumer:insert M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test('SQLDataControlConsumer_insert_successCallback_TypeMismatch', {timeout: 30000}), i, rowData, globalDataControl,
+    globalReqId = generateGlobalReqId(), currentDate = new Date().getTime().toString(),
+    conversionTable = getTypeConversionExceptions("functionObject", true);
+t.step(function () {
+
+    rowData = {
+        columns: ["WORD", "WORD_DESC"],
+        values: ["'" + currentDate + "'", "'" + currentDate + "_desc'"]
+    };
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_SQL);
+
+    for (i = 0; i < conversionTable.length; i++) {
+        assert_throws({name: conversionTable[i][1]}, function () {
+            globalDataControl.insert(globalReqId, rowData, conversionTable[i][0]);
+        }, "exception should be thrown. Given - " + conversionTable[i][0]);
+        globalReqId++;
+    }
+
+    t.done();
+});
+
+}
+
+function SQLDataControlConsumer_insert_successCallback_invalid_cb() {
+//==== TEST: SQLDataControlConsumer_insert_successCallback_invalid_cb
+//==== LABEL Check if SQLDataControlConsumer.insert method throws exception when successCallback is invalid
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:TBD:Datacontrol:SQLDataControlConsumer:insert M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 30000});
+
+var t = async_test('SQLDataControlConsumer_insert_successCallback_invalid_cb', {timeout: 30000}), rowData, globalDataControl,
+    globalReqId = generateGlobalReqId(), invalidCallback, currentDate = new Date().getTime().toString();
+t.step(function () {
+
+    rowData = {
+        columns: ["WORD", "WORD_DESC"],
+        values: ["'" + currentDate + "'", "'" + currentDate + "_desc'"]
+    };
+
+    invalidCallback = {
+        onsuccess: t.step_func(function () {
+            assert_unreached("insert() invalid success callback invoked");
+        })
+    };
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_SQL);
+
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        globalDataControl.insert(globalReqId, rowData, invalidCallback);
+    }, "exception should be thrown");
+
+    t.done();
+});
+
+}
+
+function SQLDataControlConsumer_insert_without_errorCallback() {
+//==== TEST: SQLDataControlConsumer_insert_without_errorCallback
+//==== LABEL Check SQLDataControlConsumer.insert method without errorCallback
+//==== SPEC Tizen Web API:TBD:Datacontrol:SQLDataControlConsumer:insert M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MR MOA MAST
+//==== PRIORITY P1
+
+setup({timeout: 30000});
+
+var t = async_test('SQLDataControlConsumer_insert_without_errorCallback', {timeout: 30000}), globalDataControl,
+    globalReqId = generateGlobalReqId(), currentDate = new Date().getTime().toString(), selectError, insertSuccess,
+    selectSuccess, rowData, returnedValue = null, descriptionToSet = currentDate + "_desc";
+t.step(function () {
+
+    rowData = {
+        columns: ["WORD", "WORD_DESC"],
+        values: ["'" + currentDate + "'", "'" + descriptionToSet + "'"]
+    };
+
+    selectSuccess = t.step_func(function (rows, reqId) {
+        assert_equals(rows.length, 1, "Incorrect number of rows.");
+        assert_array_equals(rows[0].columns, rowData.columns, "Incorrect columns");
+        assert_array_equals(rows[0].values, [currentDate, descriptionToSet], "Incorrect values");
+        t.done();
+    });
+
+    selectError = t.step_func(function (reqId, error) {
+        assert_unreached("select() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    insertSuccess = t.step_func(function (reqId, insertRowId) {
+        assert_equals(returnedValue, undefined, "Incorrect returned value");
+        assert_equals(reqId, globalReqId, "incorrect request id");
+        assert_type(reqId, "unsigned long", "reqId is not unsigned long");
+        assert_type(insertRowId, "long", "insertRowId is not long.");
+
+        globalReqId++;
+        globalDataControl.select(globalReqId, rowData.columns,
+            rowData.columns[0] + "=" + rowData.values[0], selectSuccess, selectError);
+    });
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_SQL);
+    returnedValue = globalDataControl.insert(globalReqId, rowData, insertSuccess);
+});
+
+}
+
+function SQLDataControlConsumer_insert_without_successCallback() {
+//==== TEST: SQLDataControlConsumer_insert_without_successCallback
+//==== LABEL Check SQLDataControlConsumer.insert method without successCallback
+//==== SPEC Tizen Web API:TBD:Datacontrol:SQLDataControlConsumer:insert M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== TEST_CRITERIA MR MMINA
+//==== PRIORITY P1
+
+test(function () {
+    var globalDataControl, globalReqId = generateGlobalReqId(), currentDate = new Date().getTime().toString(),
+        rowData, returnedValue;
+
+    rowData = {
+        columns: ["WORD", "WORD_DESC"],
+        values: ["'" + currentDate + "'", "'" + currentDate + "_desc'"]
+    };
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_SQL);
+    returnedValue = globalDataControl.insert(globalReqId, rowData);
+    assert_equals(returnedValue, undefined, "Incorrect returned value");
+
+}, 'SQLDataControlConsumer_insert_without_successCallback');
+
+}
+
+function SQLDataControlConsumer_notexist() {
+//==== TEST: SQLDataControlConsumer_notexist
+//==== PRIORITY P3
+//==== LABEL Check if interface SQLDataControlConsumer exists, it should not
+//==== SPEC Tizen Web API:TBD:Datacontrol:SQLDataControlConsumer:SQLDataControlConsumer U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("SQLDataControlConsumer");
+}, 'SQLDataControlConsumer_notexist');
+
+}
+
+function SQLDataControlConsumer_remove() {
+//==== TEST: SQLDataControlConsumer_remove
+//==== LABEL Check if SQLDataControlConsumer.remove method works properly
+//==== SPEC Tizen Web API:TBD:Datacontrol:SQLDataControlConsumer:remove M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MR MAST MOA
+//==== PRIORITY P1
+
+setup({timeout: 30000});
+
+var t = async_test('SQLDataControlConsumer_remove', {timeout: 30000}), globalDataControl, globalReqId = generateGlobalReqId(),
+    currentDate = new Date().getTime().toString(), selectError, insertSuccess, insertError, selectSuccess, rowData,
+    removeSuccess, removeError, returnedValue = null, columnsToSet = ["WORD", "WORD_DESC"], description = currentDate + "_desc",
+    descriptionToSet = "'" + description + "'", rowDataToRemove = {}, rowDataToSelect = {}, keyToRemove = currentDate + 1,
+    keyToSelect = currentDate + 2, insertCounter = 1;
+t.step(function () {
+
+    rowData = {
+        columns: ["WORD", "WORD_DESC"],
+        values: ["'" + currentDate + "'", "'" + currentDate + "_desc'"]
+    };
+
+    selectSuccess = t.step_func(function (rows, reqId) {
+        assert_equals(reqId, globalReqId, "incorrect request id");
+        assert_equals(rows.length, 1, "Incorrect number of rows.");
+        assert_array_equals(rows[0].columns, columnsToSet, "Incorrect column names");
+        assert_array_equals(rows[0].values, [keyToSelect, description], "Incorrect values");
+        t.done();
+    });
+
+    selectError = t.step_func(function (reqId, error) {
+        assert_unreached("select() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+
+    removeSuccess = t.step_func(function (reqId) {
+        assert_equals(returnedValue, undefined, "Incorrect returned value");
+        assert_equals(reqId, globalReqId, "Incorrect requestId.");
+        globalReqId++;
+        globalDataControl.select(globalReqId, rowData.columns,
+            columnsToSet[1] + "=" + descriptionToSet, selectSuccess, selectError);
+    });
+
+    removeError = t.step_func(function (reqId, error) {
+        assert_unreached("remove() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    insertSuccess = t.step_func(function (reqId, insertRowId) {
+        globalReqId++;
+        insertCounter++;
+        //check to execute appropriate number of inserts before removing
+        if (insertCounter <= 2) {
+            rowDataToSelect.columns = columnsToSet;
+            rowDataToSelect.values = ["'" + keyToSelect + "'", descriptionToSet];
+            globalDataControl.insert(globalReqId, rowDataToSelect, insertSuccess, insertError);
+        } else {
+            returnedValue = globalDataControl.remove(globalReqId,
+                columnsToSet[0] + "=" + rowDataToRemove.values[0], removeSuccess, removeError);
+        }
+    });
+
+    insertError = t.step_func(function (reqId, error) {
+        assert_unreached("insert() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_SQL);
+
+    rowDataToRemove.columns = columnsToSet;
+    rowDataToRemove.values = ["'" + keyToRemove + "'", descriptionToSet];
+    globalReqId++;
+    globalDataControl.insert(globalReqId, rowDataToRemove, insertSuccess, insertError);
+});
+
+}
+
+function SQLDataControlConsumer_remove_errorCallback_TypeMismatch() {
+//==== TEST: SQLDataControlConsumer_remove_errorCallback_TypeMismatch
+//==== LABEL Check type conversions for errorCallback argument of SQLDataControlConsumer.remove method
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:TBD:Datacontrol:SQLDataControlConsumer:remove M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test('SQLDataControlConsumer_remove_errorCallback_TypeMismatch', {timeout: 30000}), i, globalDataControl,
+    globalReqId = generateGlobalReqId(), currentDate = new Date().getTime().toString(), removeSuccess, rowData,
+    insertSuccess, insertError, conversionTable = getTypeConversionExceptions("functionObject", true);
+t.step(function () {
+
+    rowData = {
+        columns: ["WORD", "WORD_DESC"],
+        values: ["'" + currentDate + "'", "'" + currentDate + "_desc'"]
+    };
+
+    removeSuccess = t.step_func(function (reqId) {
+        assert_unreached("remove() success callback invoked");
+    });
+
+    insertSuccess = t.step_func(function (reqId, insertRowId) {
+        for (i = 0; i < conversionTable.length; i++) {
+            globalReqId++;
+            assert_throws({name: conversionTable[i][1]}, function () {
+                globalDataControl.remove(globalReqId,
+                    rowData.columns[0] + "=" + rowData.values[0], removeSuccess, conversionTable[i][0]);
+            }, "exception should be thrown. Given - " + conversionTable[i][0]);
+        }
+        t.done();
+    });
+
+    insertError = t.step_func(function (reqId, error) {
+        assert_unreached("insert() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_SQL);
+    globalDataControl.insert(globalReqId, rowData, insertSuccess, insertError);
+});
+
+}
+
+function SQLDataControlConsumer_remove_errorCallback_invalid_cb() {
+//==== TEST: SQLDataControlConsumer_remove_errorCallback_invalid_cb
+//==== LABEL Check if SQLDataControlConsumer.remove method throws exception when errorCallback is invalid
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:TBD:Datacontrol:SQLDataControlConsumer:remove M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 30000});
+
+var t = async_test('SQLDataControlConsumer_remove_errorCallback_invalid_cb', {timeout: 30000}), globalDataControl,
+    globalReqId = generateGlobalReqId(), currentDate = new Date().getTime().toString(), rowData, insertSuccess,
+    insertError, removeSuccess, invalidCallback;
+t.step(function () {
+
+    rowData = {
+        columns: ["WORD", "WORD_DESC"],
+        values: ["'" + currentDate + "'", "'" + currentDate + "_desc'"]
+    };
+
+    invalidCallback = {
+        onerror: t.step_func(function (reqId, error) {
+            assert_unreached("remove() invalid error callback invoked");
+        })
+    };
+
+    removeSuccess = t.step_func(function () {
+        assert_unreached("remove() success callback invoked");
+    });
+
+    insertSuccess = t.step_func(function () {
+        assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+            globalDataControl.remove(globalReqId,
+                rowData.columns[0] + "=" + rowData.values[0], removeSuccess, invalidCallback);
+        }, "exception should be thrown");
+        t.done();
+    });
+
+    insertError = t.step_func(function (reqId, error) {
+        assert_unreached("insert() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_SQL);
+    globalDataControl.insert(globalReqId, rowData, insertSuccess, insertError);
+});
+
+}
+
+function SQLDataControlConsumer_remove_errorCallback_invoked() {
+//==== TEST: SQLDataControlConsumer_remove_errorCallback_invoked
+//==== LABEL Check exception in error callback of remove method
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:TBD:Datacontrol:SQLDataControlConsumer:remove M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== TEST_CRITERIA MERRCB
+
+setup({timeout: 30000});
+
+var t = async_test('SQLDataControlConsumer_remove_errorCallback_invoked', {timeout: 30000}), globalDataControl, globalReqId = generateGlobalReqId(),
+    currentDate, insertSuccess, insertError, rowData;
+
+t.step(function () {
+    currentDate = new Date().getTime().toString();
+    rowData = {
+        columns: ["WORD", "WORD_DESC"],
+        values: ["'" + currentDate + "'", "'" + currentDate + "_desc'"]
+    };
+
+    removeSuccess = t.step_func(function (rows, reqId) {
+        assert_unreached("remove() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    removeError = t.step_func(function (reqId, error) {
+        assert_equals(error.code, 0, "incorrect error code");
+        t.done();
+    });
+
+    insertSuccess = t.step_func(function (reqId, insertRowId) {
+        globalReqId++;
+        globalDataControl.remove(globalReqId, "tizen='123'", removeSuccess, removeError);
+    });
+
+    insertError = t.step_func(function (reqId, error) {
+        assert_unreached("insert() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_SQL);
+    globalDataControl.insert(globalReqId, rowData, insertSuccess, insertError);
+});
+
+}
+
+function SQLDataControlConsumer_remove_exist() {
+//==== TEST: SQLDataControlConsumer_remove_exist
+//==== LABEL Check if method remove of SQLDataControlConsumer exists
+//==== SPEC Tizen Web API:TBD:Datacontrol:SQLDataControlConsumer:remove M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== TEST_CRITERIA ME
+//==== PRIORITY P1
+
+test(function () {
+    var globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_SQL);
+    assert_true("remove" in globalDataControl, "No remove method in globalDataControl");
+    check_method_exists(globalDataControl, "remove");
+}, 'SQLDataControlConsumer_remove_exist');
+
+}
+
+function SQLDataControlConsumer_remove_successCallback_TypeMismatch() {
+//==== TEST: SQLDataControlConsumer_remove_successCallback_TypeMismatch
+//==== LABEL Check type conversions for successCallback argument of SQLDataControlConsumer.remove method
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:TBD:Datacontrol:SQLDataControlConsumer:remove M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test('SQLDataControlConsumer_remove_successCallback_TypeMismatch', {timeout: 30000}), i, globalDataControl,
+    globalReqId = generateGlobalReqId(), currentDate = new Date().getTime().toString(), rowData, insertSuccess,
+    insertError, conversionTable = getTypeConversionExceptions("functionObject", true);
+t.step(function () {
+
+    rowData = {
+        columns: ["WORD", "WORD_DESC"],
+        values: ["'" + currentDate + "'", "'" + currentDate + "_desc'"]
+    };
+
+    insertSuccess = t.step_func(function (reqId, insertRowId) {
+        for (i = 0; i < conversionTable.length; i++) {
+            globalReqId++;
+            assert_throws({name: conversionTable[i][1]}, function () {
+                globalDataControl.remove(globalReqId,
+                    rowData.columns[0] + "=" + rowData.values[0], conversionTable[i][0]);
+            }, "exception should be thrown. Given - " + conversionTable[i][0]);
+        }
+        t.done();
+    });
+
+    insertError = t.step_func(function (reqId, error) {
+        assert_unreached("insert() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_SQL);
+    globalDataControl.insert(globalReqId, rowData, insertSuccess, insertError);
+});
+
+}
+
+function SQLDataControlConsumer_remove_successCallback_invalid_cb() {
+//==== TEST: SQLDataControlConsumer_remove_successCallback_invalid_cb
+//==== LABEL Check if SQLDataControlConsumer.remove method throws exception when successCallback is invalid
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:TBD:Datacontrol:SQLDataControlConsumer:remove M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 30000});
+
+var t = async_test('SQLDataControlConsumer_remove_successCallback_invalid_cb', {timeout: 30000}), globalDataControl,
+    globalReqId = generateGlobalReqId(), currentDate = new Date().getTime().toString(), rowData, insertSuccess,
+    insertError, invalidCallback;
+t.step(function () {
+
+    rowData = {
+        columns: ["WORD", "WORD_DESC"],
+        values: ["'" + currentDate + "'", "'" + currentDate + "_desc'"]
+    };
+
+    invalidCallback = {
+        onsuccess: t.step_func(function () {
+            assert_unreached("remove() invalid success callback invoked");
+        })
+    };
+
+    insertSuccess = t.step_func(function () {
+        assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+            globalDataControl.remove(globalReqId,
+                rowData.columns[0] + "=" + rowData.values[0], invalidCallback);
+        }, "exception should be thrown");
+        t.done();
+    });
+
+    insertError = t.step_func(function (reqId, error) {
+        assert_unreached("insert() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_SQL);
+    globalDataControl.insert(globalReqId, rowData, insertSuccess, insertError);
+});
+
+}
+
+function SQLDataControlConsumer_remove_without_errorCallback() {
+//==== TEST: SQLDataControlConsumer_remove_without_errorCallback
+//==== LABEL Check SQLDataControlConsumer.remove method without errorCallback
+//==== SPEC Tizen Web API:TBD:Datacontrol:SQLDataControlConsumer:remove M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MR MAST MOA
+//==== PRIORITY P1
+
+setup({timeout: 30000});
+
+var t = async_test('SQLDataControlConsumer_remove_without_errorCallback', {timeout: 30000}), globalDataControl,
+    globalReqId = generateGlobalReqId(), currentDate = new Date().getTime().toString(), selectError, insertSuccess,
+    insertError, selectSuccess, rowData, removeSuccess, returnedValue = null,
+    columnsToSet = ["WORD", "WORD_DESC"], description = currentDate + "_desc",
+    descriptionToSet = "'" + description + "'", rowDataToRemove = {}, rowDataToSelect = {}, keyToRemove = currentDate + 1,
+    keyToSelect = currentDate + 2, insertCounter = 1;
+t.step(function () {
+
+    rowData = {
+        columns: ["WORD", "WORD_DESC"],
+        values: ["'" + currentDate + "'", "'" + currentDate + "_desc'"]
+    };
+
+    selectSuccess = t.step_func(function (rows, reqId) {
+        assert_equals(reqId, globalReqId, "incorrect request id");
+        assert_equals(rows.length, 1, "Incorrect number of rows.");
+        assert_array_equals(rows[0].columns, columnsToSet, "Incorrect column names");
+        assert_array_equals(rows[0].values, [keyToSelect, description], "Incorrect values");
+        t.done();
+    });
+
+    selectError = t.step_func(function (reqId, error) {
+        assert_unreached("select() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+
+    removeSuccess = t.step_func(function (reqId) {
+        assert_equals(returnedValue, undefined, "Incorrect returned value");
+        assert_equals(reqId, globalReqId, "Incorrect requestId.");
+        globalReqId++;
+        globalDataControl.select(globalReqId, rowData.columns,
+            columnsToSet[1] + "=" + descriptionToSet, selectSuccess, selectError);
+    });
+
+    insertSuccess = t.step_func(function (reqId, insertRowId) {
+        globalReqId++;
+        insertCounter++;
+        //check to execute appropriate number of inserts before removing
+        if (insertCounter <= 2) {
+            rowDataToSelect.columns = columnsToSet;
+            rowDataToSelect.values = ["'" + keyToSelect + "'", descriptionToSet];
+            globalDataControl.insert(globalReqId, rowDataToSelect, insertSuccess, insertError);
+        } else {
+            returnedValue = globalDataControl.remove(globalReqId,
+                columnsToSet[0] + "=" + rowDataToRemove.values[0], removeSuccess);
+        }
+    });
+
+    insertError = t.step_func(function (reqId, error) {
+        assert_unreached("insert() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_SQL);
+
+    rowDataToRemove.columns = columnsToSet;
+    rowDataToRemove.values = ["'" + keyToRemove + "'", descriptionToSet];
+    globalReqId++;
+    globalDataControl.insert(globalReqId, rowDataToRemove, insertSuccess, insertError);
+});
+
+}
+
+function SQLDataControlConsumer_remove_without_successCallback() {
+//==== TEST: SQLDataControlConsumer_remove_without_successCallback
+//==== LABEL Check SQLDataControlConsumer.remove method without successCallback
+//==== SPEC Tizen Web API:TBD:Datacontrol:SQLDataControlConsumer:remove M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MR MMINA
+//==== PRIORITY P1
+
+setup({timeout: 30000});
+
+var t = async_test('SQLDataControlConsumer_remove_without_successCallback', {timeout: 30000}), globalDataControl,
+    globalReqId = generateGlobalReqId(), currentDate = new Date().getTime().toString(), insertSuccess, insertError,
+    rowData, returnedValue = null;
+t.step(function () {
+
+    rowData = {
+        columns: ["WORD", "WORD_DESC"],
+        values: ["'" + currentDate + "'", "'" + currentDate + "_desc'"]
+    };
+
+    insertSuccess = t.step_func(function (reqId, insertRowId) {
+        globalReqId++;
+        returnedValue = globalDataControl.remove(globalReqId,
+            rowData.columns[0] + "=" + rowData.values[0]);
+        assert_equals(returnedValue, undefined, "Incorrect returned value");
+        t.done();
+    });
+
+    insertError = t.step_func(function (reqId, error) {
+        assert_unreached("insert() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_SQL);
+    globalDataControl.insert(globalReqId, rowData, insertSuccess, insertError);
+});
+
+}
+
+function SQLDataControlConsumer_select() {
+//==== TEST: SQLDataControlConsumer_select
+//==== LABEL Check with non-optional arguments SQLDataControlConsumer.select method
+//==== SPEC Tizen Web API:TBD:Datacontrol:SQLDataControlConsumer:select M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MR MOA
+//==== PRIORITY P1
+
+setup({timeout: 30000});
+
+var t = async_test('SQLDataControlConsumer_select', {timeout: 30000}), globalDataControl, globalReqId = generateGlobalReqId(),
+    currentDate = new Date().getTime().toString(), selectError, insertSuccess, insertError, selectSuccess, i,
+    returnedValue = null, insertedData = {}, rowData, description = currentDate + "_desc",
+    descriptionToSet = "'" + description + "'", columnsToSet = ["WORD", "WORD_DESC"], numberOfElements = 2,
+    key, wordColumnValue, wordDescColumnValue, insertCounter = 0;
+t.step(function () {
+
+    selectSuccess = t.step_func(function (rows, reqId) {
+        assert_equals(returnedValue, undefined, "Incorrect returned value");
+        assert_equals(reqId, globalReqId, "Incorrect request id");
+        assert_equals(rows.length, numberOfElements, "Incorrect number of rows.");
+        for (i = 0; i < rows.length; i++) {
+            assert_array_equals(rows[i].columns, columnsToSet, "Incorrect column names");
+            wordColumnValue = rows[i].values[0];
+            wordDescColumnValue = rows[i].values[1];
+            assert_own_property(insertedData, wordColumnValue, "Incorrect value for WORD columns");
+            assert_equals(wordDescColumnValue, insertedData[wordColumnValue], "Incorrect value for WORD_DESC column");
+            delete insertedData[wordColumnValue];
+        }
+        t.done();
+    });
+
+    selectError = t.step_func(function (reqId, error) {
+        assert_unreached("select() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    insertSuccess = t.step_func(function (reqId, insertRowId) {
+        globalReqId++;
+        insertCounter++;
+        //check to execute appropriate number of inserts before selecting
+        if (insertCounter <= numberOfElements) {
+            rowData = {};
+            rowData.columns = columnsToSet;
+            key = currentDate + globalReqId;
+            rowData.values = ["'" + key + "'", descriptionToSet];
+
+            insertedData[key] = description;
+
+            globalDataControl.insert(globalReqId, rowData, insertSuccess, insertError);
+        } else {
+            returnedValue = globalDataControl.select(globalReqId, columnsToSet,
+                columnsToSet[1] + "=" + descriptionToSet, selectSuccess, selectError, 1, 2);
+        }
+    });
+
+    insertError = t.step_func(function (reqId, error) {
+        assert_unreached("insert() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_SQL);
+    insertSuccess();
+});
+
+}
+
+function SQLDataControlConsumer_select_columns_TypeMismatch() {
+//==== TEST: SQLDataControlConsumer_select_columns_TypeMismatch
+//==== LABEL Check type conversions for columns argument of SQLDataControlConsumer.select method
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:TBD:Datacontrol:SQLDataControlConsumer:select M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test('SQLDataControlConsumer_select_columns_TypeMismatch', {timeout: 30000}), i, globalDataControl, globalReqId = generateGlobalReqId(),
+    currentDate = new Date().getTime().toString(), rowData, insertSuccess, selectSuccess, insertError,
+    conversionTable = getTypeConversionExceptions("array", false);
+t.step(function () {
+
+    rowData = {
+        columns: ["WORD", "WORD_DESC"],
+        values: ["'" + currentDate + "'", "'" + currentDate + "_desc'"]
+    };
+
+    selectSuccess = t.step_func(function () {
+        assert_unreached("select() success callback invoked");
+    });
+
+    insertSuccess = t.step_func(function (reqId, insertRowId) {
+        for (i = 0; i < conversionTable.length; i++) {
+            globalReqId++;
+            assert_throws({name: conversionTable[i][1]}, function () {
+                globalDataControl.select(globalReqId, conversionTable[i][0],
+                    rowData.columns[0] + "=" + rowData.values[0], selectSuccess);
+            }, "exception should be thrown");
+        }
+        t.done();
+    });
+
+    insertError = t.step_func(function (reqId, error) {
+        assert_unreached("insert() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_SQL);
+    globalDataControl.insert(globalReqId, rowData, insertSuccess, insertError);
+});
+
+}
+
+function SQLDataControlConsumer_select_errorCallback_TypeMismatch() {
+//==== TEST: SQLDataControlConsumer_select_errorCallback_TypeMismatch
+//==== LABEL Check type conversions for errorCallback argument of SQLDataControlConsumer.select method
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:TBD:Datacontrol:SQLDataControlConsumer:select M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test('SQLDataControlConsumer_select_errorCallback_TypeMismatch', {timeout: 30000}), i, globalDataControl,
+    globalReqId = generateGlobalReqId(), currentDate = new Date().getTime().toString(), rowData, selectSuccess,
+    insertSuccess, insertError, conversionTable = getTypeConversionExceptions("functionObject", true);
+t.step(function () {
+
+    rowData = {
+        columns: ["WORD", "WORD_DESC"],
+        values: ["'" + currentDate + "'", "'" + currentDate + "_desc'"]
+    };
+
+    selectSuccess = t.step_func(function () {
+        assert_unreached("select() success callback invoked");
+    });
+
+    insertSuccess = t.step_func(function (reqId, insertRowId) {
+        for (i = 0; i < conversionTable.length; i++) {
+            globalReqId++;
+            assert_throws({name: conversionTable[i][1]}, function () {
+                globalDataControl.select(globalReqId, rowData.columns,
+                    rowData.columns[0] + "=" + rowData.values[0], selectSuccess, conversionTable[i][0]);
+            }, "exception should be thrown. Given - " + conversionTable[i][0]);
+        }
+        t.done();
+    });
+
+    insertError = t.step_func(function (reqId, error) {
+        assert_unreached("insert() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_SQL);
+    globalDataControl.insert(globalReqId, rowData, insertSuccess, insertError);
+});
+
+}
+
+function SQLDataControlConsumer_select_errorCallback_invalid_cb() {
+//==== TEST: SQLDataControlConsumer_select_errorCallback_invalid_cb
+//==== LABEL Check if SQLDataControlConsumer.select method throws exception when errorCallback is invalid
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:TBD:Datacontrol:SQLDataControlConsumer:select M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 30000});
+
+var t = async_test('SQLDataControlConsumer_select_errorCallback_invalid_cb', {timeout: 30000}), globalDataControl,
+    globalReqId = generateGlobalReqId(), currentDate = new Date().getTime().toString(), rowData, insertSuccess,
+    insertError, selectSuccess, invalidCallback;
+t.step(function () {
+
+    rowData = {
+        columns: ["WORD", "WORD_DESC"],
+        values: ["'" + currentDate + "'", "'" + currentDate + "_desc'"]
+    };
+
+    selectSuccess = t.step_func(function () {
+        assert_unreached("select() success callback invoked");
+    });
+
+    invalidCallback = {
+        onerror: t.step_func(function (reqId, error) {
+            assert_unreached("select() invalid error callback invoked");
+        })
+    };
+
+    insertSuccess = t.step_func(function () {
+        assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+            globalDataControl.select(globalReqId, rowData.columns,
+                rowData.columns[0] + "=" + rowData.values[0], selectSuccess, invalidCallback);
+        }, "exception should be thrown");
+        t.done();
+    });
+
+    insertError = t.step_func(function (reqId, error) {
+        assert_unreached("insert() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_SQL);
+    globalDataControl.insert(globalReqId, rowData, insertSuccess, insertError);
+});
+
+}
+
+function SQLDataControlConsumer_select_errorCallback_invoked() {
+//==== TEST SQLDataControlConsumer_select_errorCallback_invoked
+//==== LABEL Check exception in error callback of select method
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:TBD:Datacontrol:SQLDataControlConsumer:select M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== TEST_CRITERIA MERRCB
+
+setup({timeout: 30000});
+
+var t = async_test('SQLDataControlConsumer_select_exist', {timeout: 30000}), globalDataControl, globalReqId = generateGlobalReqId(), currentDate, selectError, insertSuccess, insertError, selectSuccess,
+    rowData, description, descriptionToSet;
+
+t.step(function () {
+
+    currentDate = new Date().getTime().toString();
+    descriptionToSet = "'" + description + "'";
+    columnsToSet = ["tizen", "123"];
+    description = currentDate + "_desc";
+    rowData = {
+        columns: ["WORD", "WORD_DESC"],
+        values: ["'" + currentDate + "'", "'" + currentDate + "_desc'"]
+    };
+
+    selectSuccess = t.step_func(function (rows, reqId) {
+        assert_unreached("select() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    selectError = t.step_func(function (reqId, error) {
+        assert_equals(error.code, 0, "incorrect error code");
+        t.done();
+    });
+
+    insertSuccess = t.step_func(function (reqId, insertRowId) {
+        globalReqId++;
+        globalDataControl.select(globalReqId, columnsToSet, columnsToSet[1] + "=" + descriptionToSet, selectSuccess, selectError, 2, 2);
+    });
+
+    insertError = t.step_func(function (reqId, error) {
+        assert_unreached("insert() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_SQL);
+    globalDataControl.insert(globalReqId, rowData, insertSuccess, insertError);
+});
+
+}
+
+function SQLDataControlConsumer_select_exist() {
+//==== TEST: SQLDataControlConsumer_select_exist
+//==== LABEL Check if method select of SQLDataControlConsumer exists
+//==== SPEC Tizen Web API:TBD:Datacontrol:SQLDataControlConsumer:select M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== TEST_CRITERIA ME
+//==== PRIORITY P1
+
+test(function () {
+    var globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_SQL);
+    assert_true("select" in globalDataControl, "No select method in globalDataControl");
+    check_method_exists(globalDataControl, "select");
+}, 'SQLDataControlConsumer_select_exist');
+
+}
+
+function SQLDataControlConsumer_select_missarg() {
+//==== TEST: SQLDataControlConsumer_select_missarg
+//==== LABEL Check with missing non-optional argument - select
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:TBD:Datacontrol:SQLDataControlConsumer:select M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== TEST_CRITERIA MMA
+//==== PRIORITY P1
+
+setup({timeout: 30000});
+
+var t = async_test('SQLDataControlConsumer_select_missarg', {timeout: 30000}), globalDataControl, globalReqId = generateGlobalReqId(),
+    currentDate = new Date().getTime().toString(), insertSuccess, insertError, rowData, exceptionName = "TypeMismatchError";
+t.step(function () {
+
+    rowData = {
+        columns: ["WORD", "WORD_DESC"],
+        values: ["'" + currentDate + "'", "'" + currentDate + "_desc'"]
+    };
+
+    insertSuccess = t.step_func(function (reqId, insertRowId) {
+        globalReqId++;
+        assert_throws({name: exceptionName},
+            function () {
+                globalDataControl.select(globalReqId);
+            }, exceptionName + " should be thrown - missing columns");
+        t.done();
+    });
+
+    insertError = t.step_func(function (reqId, error) {
+        assert_unreached("insert() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_SQL);
+    globalDataControl.insert(globalReqId, rowData, insertSuccess, insertError);
+});
+
+}
+
+function SQLDataControlConsumer_select_noarg() {
+//==== TEST: SQLDataControlConsumer_select_noarg
+//==== LABEL Check with no argument - SQLDataControlConsumer::select
+//==== PRIORITY: P2
+//==== SPEC Tizen Web API:Application:Datacontrol:SQLDataControlConsumer:select M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.2.1/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== TEST_CRITERIA MMA
+
+test(function () {
+    var globalDataControl, globalReqId = generateGlobalReqId();
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_SQL);
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        globalDataControl.select();
+    }, TYPE_MISMATCH_EXCEPTION + " should throw exception - no argument.");
+}, 'SQLDataControlConsumer_select_noarg');
+
+}
+
+function SQLDataControlConsumer_select_successCallback_TypeMismatch() {
+//==== TEST: SQLDataControlConsumer_select_successCallback_TypeMismatch
+//==== LABEL Check type conversions for successCallback argument of SQLDataControlConsumer.select method
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:TBD:Datacontrol:SQLDataControlConsumer:select M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test('SQLDataControlConsumer_select_successCallback_TypeMismatch', {timeout: 30000}), i, globalDataControl,
+    globalReqId = generateGlobalReqId(), currentDate = new Date().getTime().toString(), rowData, insertSuccess,
+    insertError, conversionTable = getTypeConversionExceptions("functionObject");
+t.step(function () {
+
+    rowData = {
+        columns: ["WORD", "WORD_DESC"],
+        values: ["'" + currentDate + "'", "'" + currentDate + "_desc'"]
+    };
+
+    insertSuccess = t.step_func(function (reqId, insertRowId) {
+        for (i = 0; i < conversionTable.length; i++) {
+            globalReqId++;
+            assert_throws({name: conversionTable[i][1]}, function () {
+                globalDataControl.select(globalReqId, rowData.columns,
+                    rowData.columns[0] + "=" + rowData.values[0], conversionTable[i][0]);
+            }, "exception should be thrown. Given - " + conversionTable[i][0]);
+        }
+        t.done();
+    });
+
+    insertError = t.step_func(function (reqId, error) {
+        assert_unreached("insert() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_SQL);
+    globalDataControl.insert(globalReqId, rowData, insertSuccess, insertError);
+});
+
+}
+
+function SQLDataControlConsumer_select_successCallback_invalid_cb() {
+//==== TEST: SQLDataControlConsumer_select_successCallback_invalid_cb
+//==== LABEL Check if SQLDataControlConsumer.select method throws exception when successCallback is invalid
+//==== SPEC Tizen Web API:TBD:Datacontrol:SQLDataControlConsumer:select M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== PRIORITY P2
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MTCB
+setup({timeout: 30000});
+
+var t = async_test('SQLDataControlConsumer_select_successCallback_invalid_cb', {timeout: 30000}),
+    globalDataControl, globalReqId = generateGlobalReqId(), currentDate = new Date().getTime().toString(), rowData,
+    insertSuccess, insertError, invalidCallback;
+t.step(function () {
+
+    rowData = {
+        columns: ["WORD", "WORD_DESC"],
+        values: ["'" + currentDate + "'", "'" + currentDate + "_desc'"]
+    };
+
+    invalidCallback = {
+        onsuccess: t.step_func(function () {
+            assert_unreached("select() invalid success callback invoked");
+        })
+    };
+
+    insertSuccess = t.step_func(function () {
+        assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+            globalDataControl.select(globalReqId, rowData.columns,
+                rowData.columns[0] + "=" + rowData.values[0], invalidCallback);
+        }, "exception should be thrown");
+        t.done();
+    });
+
+    insertError = t.step_func(function (reqId, error) {
+        assert_unreached("insert() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_SQL);
+    globalDataControl.insert(globalReqId, rowData, insertSuccess, insertError);
+});
+
+}
+
+function SQLDataControlConsumer_select_without_errorCallback() {
+//==== TEST: SQLDataControlConsumer_select_without_errorCallback
+//==== LABEL Check SQLDataControlConsumer.select method without errorCallback
+//==== SPEC Tizen Web API:TBD:Datacontrol:SQLDataControlConsumer:select M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MR MMINA
+//==== PRIORITY P1
+
+setup({timeout: 30000});
+
+var t = async_test('SQLDataControlConsumer_select_without_errorCallback', {timeout: 30000}), globalDataControl,
+    globalReqId = generateGlobalReqId(), currentDate = new Date().getTime().toString(), insertSuccess, insertError,
+    selectSuccess, i, returnedValue = null, insertedData = {}, rowData, description = currentDate + "_desc",
+    descriptionToSet = "'" + description + "'", columnsToSet = ["WORD", "WORD_DESC"], numberOfElements = 5,
+    key, wordColumnValue, wordDescColumnValue, insertCounter = 0;
+t.step(function () {
+
+    selectSuccess = t.step_func(function (rows, reqId) {
+        assert_equals(returnedValue, undefined, "Incorrect returned value");
+        assert_equals(reqId, globalReqId, "Incorrect request id");
+        assert_equals(rows.length, numberOfElements, "Incorrect number of rows.");
+        for (i = 0; i < rows.length; i++) {
+            assert_array_equals(rows[i].columns, columnsToSet, "Incorrect column names");
+            wordColumnValue = rows[i].values[0];
+            wordDescColumnValue = rows[i].values[1];
+            assert_own_property(insertedData, wordColumnValue, "Incorrect value for WORD columns");
+            assert_equals(wordDescColumnValue, insertedData[wordColumnValue], "Incorrect value for WORD_DESC column");
+            delete insertedData[wordColumnValue];
+        }
+        t.done();
+    });
+
+    insertSuccess = t.step_func(function (reqId, insertRowId) {
+        globalReqId++;
+        insertCounter++;
+        //check to execute appropriate number of inserts before selecting
+        if (insertCounter <= numberOfElements) {
+            rowData = {};
+            rowData.columns = columnsToSet;
+            key = currentDate + globalReqId;
+            rowData.values = ["'" + key + "'", descriptionToSet];
+
+            insertedData[key] = description;
+
+            globalDataControl.insert(globalReqId, rowData, insertSuccess, insertError);
+        } else {
+            returnedValue = globalDataControl.select(globalReqId, columnsToSet,
+                columnsToSet[1] + "=" + descriptionToSet, selectSuccess);
+        }
+    });
+
+    insertError = t.step_func(function (reqId, error) {
+        assert_unreached("insert() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_SQL);
+    insertSuccess();
+});
+
+}
+
+function SQLDataControlConsumer_select_without_maxNumberPerPage() {
+//==== TEST: SQLDataControlConsumer_select_without_maxNumberPerPage
+//==== LABEL Check SQLDataControlConsumer.select method without maxNumberPerPage
+//==== SPEC Tizen Web API:TBD:Datacontrol:SQLDataControlConsumer:select M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MR MOA
+//==== PRIORITY P1
+
+setup({timeout: 30000});
+
+var t = async_test('SQLDataControlConsumer_select_without_maxNumberPerPage', {timeout: 30000}), globalDataControl,
+    globalReqId = generateGlobalReqId(), currentDate = new Date().getTime().toString(), selectError, insertSuccess,
+    insertError, selectSuccess, i, returnedValue = null, insertedData = {}, rowData, description = currentDate + "_desc",
+    descriptionToSet = "'" + description + "'", columnsToSet = ["WORD", "WORD_DESC"], numberOfElements = 5, key,
+    wordColumnValue, wordDescColumnValue, insertCounter = 0;
+t.step(function () {
+
+
+    selectSuccess = t.step_func(function (rows, reqId) {
+        assert_equals(returnedValue, undefined, "Incorrect returned value");
+        assert_equals(reqId, globalReqId, "Incorrect request id");
+        assert_equals(rows.length, numberOfElements, "Incorrect number of rows.");
+        for (i = 0; i < rows.length; i++) {
+            assert_array_equals(rows[i].columns, columnsToSet, "Incorrect column names");
+            wordColumnValue = rows[i].values[0];
+            wordDescColumnValue = rows[i].values[1];
+            assert_own_property(insertedData, wordColumnValue, "Incorrect value for WORD columns");
+            assert_equals(wordDescColumnValue, insertedData[wordColumnValue], "Incorrect value for WORD_DESC column");
+            delete insertedData[wordColumnValue];
+        }
+        t.done();
+    });
+
+    selectError = t.step_func(function (reqId, error) {
+        assert_unreached("select() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    insertSuccess = t.step_func(function (reqId, insertRowId) {
+        globalReqId++;
+        insertCounter++;
+        //check to execute appropriate number of inserts before selecting
+        if (insertCounter <= numberOfElements) {
+            rowData = {};
+            rowData.columns = columnsToSet;
+            key = currentDate + globalReqId;
+            rowData.values = ["'" + key + "'", descriptionToSet];
+
+            insertedData[key] = description;
+
+            globalDataControl.insert(globalReqId, rowData, insertSuccess, insertError);
+        } else {
+            returnedValue = globalDataControl.select(globalReqId, columnsToSet,
+                columnsToSet[1] + "=" + descriptionToSet, selectSuccess, selectError, 1);
+        }
+    });
+
+    insertError = t.step_func(function (reqId, error) {
+        assert_unreached("insert() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_SQL);
+    insertSuccess();
+});
+
+}
+
+function SQLDataControlConsumer_select_without_page() {
+//==== TEST: SQLDataControlConsumer_select_without_page
+//==== LABEL Check SQLDataControlConsumer.select method without page
+//==== SPEC Tizen Web API:TBD:Datacontrol:SQLDataControlConsumer:select M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MR MOA
+//==== PRIORITY P1
+
+setup({timeout: 30000});
+
+var t = async_test('SQLDataControlConsumer_select_without_page', {timeout: 30000}), globalDataControl, globalReqId = generateGlobalReqId(),
+    currentDate = new Date().getTime().toString(), selectError, insertSuccess, insertError, selectSuccess, i, returnedValue = null,
+    insertedData = {}, rowData, description = currentDate + "_desc", descriptionToSet = "'" + description + "'",
+    columnsToSet = ["WORD", "WORD_DESC"], numberOfElements = 5, key, wordColumnValue, wordDescColumnValue, insertCounter = 0;
+t.step(function () {
+
+    selectSuccess = t.step_func(function (rows, reqId) {
+        assert_equals(returnedValue, undefined, "Incorrect returned value");
+        assert_equals(reqId, globalReqId, "Incorrect request id");
+        assert_equals(rows.length, numberOfElements, "Incorrect number of rows.");
+        for (i = 0; i < rows.length; i++) {
+            assert_array_equals(rows[i].columns, columnsToSet, "Incorrect column names");
+            wordColumnValue = rows[i].values[0];
+            wordDescColumnValue = rows[i].values[1];
+            assert_own_property(insertedData, wordColumnValue, "Incorrect value for WORD columns");
+            assert_equals(wordDescColumnValue, insertedData[wordColumnValue], "Incorrect value for WORD_DESC column");
+            delete insertedData[wordColumnValue];
+        }
+        t.done();
+    });
+
+    selectError = t.step_func(function (reqId, error) {
+        assert_unreached("select() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    insertSuccess = t.step_func(function (reqId, insertRowId) {
+        globalReqId++;
+        insertCounter++;
+        //check to execute appropriate number of inserts before selecting
+        if (insertCounter <= numberOfElements) {
+            rowData = {};
+            rowData.columns = columnsToSet;
+            key = currentDate + globalReqId;
+            rowData.values = ["'" + key + "'", descriptionToSet];
+
+            insertedData[key] = description;
+
+            globalDataControl.insert(globalReqId, rowData, insertSuccess, insertError);
+        } else {
+            returnedValue = globalDataControl.select(globalReqId, columnsToSet,
+                columnsToSet[1] + "=" + descriptionToSet, selectSuccess, selectError);
+        }
+    });
+
+    insertError = t.step_func(function (reqId, error) {
+        assert_unreached("insert() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_SQL);
+    insertSuccess();
+});
+
+}
+
+function SQLDataControlConsumer_update() {
+//==== TEST: SQLDataControlConsumer_update
+//==== LABEL Check if SQLDataControlConsumer.update method works properly
+//==== SPEC Tizen Web API:TBD:Datacontrol:SQLDataControlConsumer:update M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MR MAST MOA
+//==== PRIORITY P1
+
+setup({timeout: 30000});
+
+var t = async_test('SQLDataControlConsumer_update', {timeout: 30000}), globalDataControl, globalReqId = generateGlobalReqId(),
+    currentDate = new Date().getTime().toString(), selectError, insertSuccess, insertError, selectSuccess, rowData,
+    rowDataUpdate, updateSuccess, updateError, returnedValue = null, descriptionUpdated = currentDate + "_desc_update",
+    keyUpdated = currentDate + "_update";
+t.step(function () {
+
+    rowData = {
+        columns: ["WORD", "WORD_DESC"],
+        values: ["'" + currentDate + "'", "'" + currentDate + "_desc'"]
+    };
+
+    rowDataUpdate = {
+        columns: ["WORD", "WORD_DESC"],
+        values: ["'" + keyUpdated + "'", "'" + descriptionUpdated + "'"]
+    };
+
+    selectSuccess = t.step_func(function (rows, reqId) {
+        assert_equals(rows.length, 1, "Incorrect number of rows.");
+        assert_array_equals(rows[0].columns, rowDataUpdate.columns, "Incorrect columns");
+        assert_array_equals(rows[0].values, [keyUpdated, descriptionUpdated], "Incorrect values");
+        t.done();
+    });
+
+    selectError = t.step_func(function (reqId, error) {
+        assert_unreached("select() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+
+    updateSuccess = t.step_func(function (reqId) {
+        assert_equals(returnedValue, undefined, "Incorrect returned value");
+        assert_equals(reqId, globalReqId, "Incorrect requestId.");
+        globalReqId++;
+        globalDataControl.select(globalReqId, rowDataUpdate.columns,
+            rowDataUpdate.columns[0] + "=" + rowDataUpdate.values[0], selectSuccess, selectError);
+    });
+
+    updateError = t.step_func(function (reqId, error) {
+        assert_unreached("update() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    insertSuccess = t.step_func(function (reqId, insertRowId) {
+        globalReqId++;
+        returnedValue = globalDataControl.update(globalReqId, rowDataUpdate,
+            rowData.columns[0] + "=" + rowData.values[0], updateSuccess, updateError);
+    });
+
+    insertError = t.step_func(function (reqId, error) {
+        assert_unreached("insert() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_SQL);
+    globalDataControl.insert(globalReqId, rowData, insertSuccess, insertError);
+});
+
+}
+
+function SQLDataControlConsumer_update_errorCallback_TypeMismatch() {
+//==== TEST: SQLDataControlConsumer_update_errorCallback_TypeMismatch
+//==== LABEL Check type conversions for errorCallback argument of SQLDataControlConsumer.update method
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:TBD:Datacontrol:SQLDataControlConsumer:update M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test('SQLDataControlConsumer_update_errorCallback_TypeMismatch', {timeout: 30000}), i, globalDataControl,
+    globalReqId = generateGlobalReqId(), currentDate = new Date().getTime().toString(), rowData, rowDataUpdate,
+    insertSuccess, updateSuccess, insertError, conversionTable = getTypeConversionExceptions("functionObject",
+    true);
+t.step(function () {
+
+    rowData = {
+        columns: ["WORD", "WORD_DESC"],
+        values: ["'" + currentDate + "'", "'" + currentDate + "_desc'"]
+    };
+
+    rowDataUpdate = {
+        columns: ["WORD", "WORD_DESC"],
+        values: ["'" + currentDate + "_update'", "'" + currentDate + "_desc_update'"]
+    };
+
+    updateSuccess = t.step_func(function () {
+        assert_unreached("update() success callback invoked");
+    });
+
+    insertSuccess = t.step_func(function (reqId, insertRowId) {
+        for (i = 0; i < conversionTable.length; i++) {
+            globalReqId++;
+            assert_throws({name: conversionTable[i][1]}, function () {
+                globalDataControl.update(globalReqId, rowDataUpdate,
+                    rowData.columns[0] + "=" + rowData.values[0], updateSuccess, conversionTable[i][0]);
+            }, "exception should be thrown. Given - " + conversionTable[i][0]);
+        }
+        t.done();
+    });
+
+    insertError = t.step_func(function (reqId, error) {
+        assert_unreached("insert() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_SQL);
+    globalDataControl.insert(globalReqId, rowData, insertSuccess, insertError);
+});
+
+}
+
+function SQLDataControlConsumer_update_errorCallback_invalid_cb() {
+//==== TEST: SQLDataControlConsumer_update_errorCallback_invalid_cb
+//==== LABEL Check if SQLDataControlConsumer.update method throws exception when errorCallback is invalid
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:TBD:Datacontrol:SQLDataControlConsumer:update M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 30000});
+
+var t = async_test('SQLDataControlConsumer_update_errorCallback_invalid_cb', {timeout: 30000}), globalDataControl,
+    globalReqId = generateGlobalReqId(), currentDate = new Date().getTime().toString(), rowData, rowDataUpdate,
+    insertSuccess, updateSuccess, insertError, invalidCallback;
+t.step(function () {
+
+    rowData = {
+        columns: ["WORD", "WORD_DESC"],
+        values: ["'" + currentDate + "'", "'" + currentDate + "_desc'"]
+    };
+
+    rowDataUpdate = {
+        columns: ["WORD", "WORD_DESC"],
+        values: ["'" + currentDate + "_update'", "'" + currentDate + "_desc_update'"]
+    };
+
+    updateSuccess = t.step_func(function () {
+        assert_unreached("update() success callback invoked");
+    });
+
+    invalidCallback = {
+        onerror: t.step_func(function (reqId, error) {
+            assert_unreached("update() invalid error callback invoked");
+        })
+    };
+
+    insertSuccess = t.step_func(function (reqId, insertRowId) {
+        globalReqId++;
+        assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+            globalDataControl.update(globalReqId, rowDataUpdate,
+                rowData.columns[0] + "=" + rowData.values[0], updateSuccess, invalidCallback);
+        }, "exception should be thrown");
+        t.done();
+    });
+
+    insertError = t.step_func(function (reqId, error) {
+        assert_unreached("insert() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_SQL);
+    globalDataControl.insert(globalReqId, rowData, insertSuccess, insertError);
+});
+
+}
+
+function SQLDataControlConsumer_update_errorCallback_invoked() {
+//==== TEST: SQLDataControlConsumer_update_errorCallback_invoked
+//==== LABEL Check exception in error callback of update method
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:TBD:Datacontrol:SQLDataControlConsumer:update M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== TEST_CRITERIA MERRCB
+
+setup({timeout: 30000});
+
+var t = async_test('SQLDataControlConsumer_update_errorCallback_invoked', {timeout: 30000}), globalDataControl, currentDate, insertSuccess, insertError, rowData,
+    rowDataUpdate, updateSuccess, updateError, returnedValue = null, descriptionUpdated, keyUpdated;
+
+t.step(function () {
+
+    keyUpdated = currentDate + "_update";
+    descriptionUpdated = currentDate + "_desc_update";
+    currentDate = new Date().getTime().toString();
+    rowData = {
+        columns: ["WORD", "WORD_DESC"],
+        values: ["'" + currentDate + "'", "'" + currentDate + "_desc'"]
+    };
+
+    rowDataUpdate = {
+        columns: ["tizen", "WORD_DESC"],
+        values: ["'" + keyUpdated + "'", "'" + descriptionUpdated + "'"]
+    };
+
+    updateSuccess = t.step_func(function (reqId) {
+        assert_equals(returnedValue, undefined, "Incorrect returned value");
+    });
+
+    updateError = t.step_func(function (reqId, error) {
+        assert_equals(error.code, 0, "incorrect error code");
+        t.done();
+    });
+
+    insertSuccess = t.step_func(function (reqId, insertRowId) {
+        returnedValue = globalDataControl.update(2, rowDataUpdate,
+            rowData.columns[0] + "=" + rowData.values[0], updateSuccess, updateError);
+    });
+
+    insertError = t.step_func(function (reqId, error) {
+        assert_unreached("insert() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_SQL);
+    globalDataControl.insert(1, rowData, insertSuccess, insertError);
+});
+
+}
+
+function SQLDataControlConsumer_update_exist() {
+//==== TEST: SQLDataControlConsumer_update_exist
+//==== LABEL Check if method update of SQLDataControlConsumer exists
+//==== SPEC Tizen Web API:TBD:Datacontrol:SQLDataControlConsumer:update M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== TEST_CRITERIA ME
+//==== PRIORITY P1
+
+test(function () {
+    var globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_SQL);
+    assert_true("update" in globalDataControl, "No update method in globalDataControl");
+    check_method_exists(globalDataControl, "update");
+}, 'SQLDataControlConsumer_update_exist');
+
+}
+
+function SQLDataControlConsumer_update_missarg() {
+//==== TEST: SQLDataControlConsumer_update_missarg
+//==== LABEL Check with missing non-optional argument - SQLDataControlConsumer.update
+//==== SPEC Tizen Web API:TBD:Datacontrol:SQLDataControlConsumer:update M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MMA
+//==== PRIORITY P1
+
+setup({timeout: 30000});
+
+var t = async_test('SQLDataControlConsumer_update_missarg', {timeout: 30000}), globalDataControl, globalReqId = generateGlobalReqId(),
+    currentDate = new Date().getTime().toString(), insertSuccess, insertError, rowData, exceptionName = "TypeMismatchError";
+t.step(function () {
+
+    rowData = {
+        columns: ["WORD", "WORD_DESC"],
+        values: ["'" + currentDate + "'", "'" + currentDate + "_desc'"]
+    };
+
+    insertSuccess = t.step_func(function (reqId, insertRowId) {
+        globalReqId++;
+        assert_throws({name: exceptionName}, function () {
+            globalDataControl.update(globalReqId);
+        }, exceptionName + " should be thrown - missing RowData object");
+
+        t.done();
+    });
+
+    insertError = t.step_func(function (reqId, error) {
+        assert_unreached("insert() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_SQL);
+    globalDataControl.insert(globalReqId, rowData, insertSuccess, insertError);
+});
+
+}
+
+function SQLDataControlConsumer_update_noarg() {
+//==== TEST: SQLDataControlConsumer_update_noarg
+//==== LABEL Check with no argument - SQLDataControlConsumer::update
+//==== PRIORITY: P2
+//==== SPEC Tizen Web API:Application:Datacontrol:SQLDataControlConsumer:update M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.2.1/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== TEST_CRITERIA MMA
+
+test(function () {
+    var globalDataControl, globalReqId = generateGlobalReqId();
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_SQL);
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        globalDataControl.update();
+    }, TYPE_MISMATCH_EXCEPTION + " should throw exception - no argument.");
+}, 'SQLDataControlConsumer_update_noarg');
+
+}
+
+function SQLDataControlConsumer_update_successCallback_TypeMismatch() {
+//==== TEST: SQLDataControlConsumer_update_successCallback_TypeMismatch
+//==== LABEL Check type conversions for successCallback argument of SQLDataControlConsumer.update method
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:TBD:Datacontrol:SQLDataControlConsumer:update M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test('SQLDataControlConsumer_update_successCallback_TypeMismatch', {timeout: 30000}), i, globalDataControl,
+    globalReqId = generateGlobalReqId(), currentDate = new Date().getTime().toString(), rowData, insertSuccess,
+    insertError, conversionTable = getTypeConversionExceptions("functionObject", true), rowDataUpdate;
+t.step(function () {
+
+    rowData = {
+        columns: ["WORD", "WORD_DESC"],
+        values: ["'" + currentDate + "'", "'" + currentDate + "_desc'"]
+    };
+
+    rowDataUpdate = {
+        columns: ["WORD", "WORD_DESC"],
+        values: ["'" + currentDate + "_update'", "'" + currentDate + "_desc_update'"]
+    };
+
+    insertSuccess = t.step_func(function (reqId, insertRowId) {
+        for (i = 0; i < conversionTable.length; i++) {
+            globalReqId++;
+            assert_throws({name: conversionTable[i][1]}, function () {
+                globalDataControl.update(globalReqId, rowDataUpdate,
+                    rowData.columns[0] + "=" + rowData.values[0], conversionTable[i][0]);
+            }, "exception should be thrown. Given - " + conversionTable[i][0]);
+        }
+        t.done();
+    });
+
+    insertError = t.step_func(function (reqId, error) {
+        assert_unreached("insert() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_SQL);
+    globalDataControl.insert(globalReqId, rowData, insertSuccess, insertError);
+});
+
+}
+
+function SQLDataControlConsumer_update_successCallback_invalid_cb() {
+//==== TEST: SQLDataControlConsumer_update_successCallback_invalid_cb
+//==== LABEL Check if SQLDataControlConsumer.update method throws exception when successCallback is invalid
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:TBD:Datacontrol:SQLDataControlConsumer:update M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 30000});
+
+var t = async_test('SQLDataControlConsumer_update_successCallback_invalid_cb', {timeout: 30000}), globalDataControl,
+    globalReqId = generateGlobalReqId(), currentDate = new Date().getTime().toString(), rowData, rowDataUpdate,
+    insertSuccess, insertError, invalidCallback;
+t.step(function () {
+
+    rowData = {
+        columns: ["WORD", "WORD_DESC"],
+        values: ["'" + currentDate + "'", "'" + currentDate + "_desc'"]
+    };
+
+    rowDataUpdate = {
+        columns: ["WORD", "WORD_DESC"],
+        values: ["'" + currentDate + "_update'", "'" + currentDate + "_desc_update'"]
+    };
+
+    invalidCallback = {
+        onsuccess: t.step_func(function () {
+            assert_unreached("update() invalid success callback invoked");
+        })
+    };
+
+    insertSuccess = t.step_func(function (reqId, insertRowId) {
+        assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+            globalDataControl.update(globalReqId, rowDataUpdate,
+                rowData.columns[0] + "=" + rowData.values[0], invalidCallback);
+        }, "exception should be thrown");
+        t.done();
+    });
+
+    insertError = t.step_func(function (reqId, error) {
+        assert_unreached("insert() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_SQL);
+    globalDataControl.insert(globalReqId, rowData, insertSuccess, insertError);
+});
+
+}
+
+function SQLDataControlConsumer_update_updateData_TypeMismatch() {
+//==== TEST: SQLDataControlConsumer_update_updateData_TypeMismatch
+//==== LABEL Check type conversions for updateData argument of SQLDataControlConsumer.update method
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:TBD:Datacontrol:SQLDataControlConsumer:update M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test('SQLDataControlConsumer_update_updateData_TypeMismatch', {timeout: 30000}), i, globalDataControl,
+    globalReqId = generateGlobalReqId(), currentDate = new Date().getTime().toString(), rowData, insertSuccess,
+    updateSuccess, insertError, conversionTable = getTypeConversionExceptions("dictionary", false);
+t.step(function () {
+
+    rowData = {
+        columns: ["WORD", "WORD_DESC"],
+        values: ["'" + currentDate + "'", "'" + currentDate + "_desc'"]
+    };
+
+    updateSuccess = t.step_func(function () {
+        assert_unreached("update() success callback invoked");
+    });
+
+    insertSuccess = t.step_func(function (reqId, insertRowId) {
+        for (i = 0; i < conversionTable.length; i++) {
+            globalReqId++;
+            assert_throws({name: conversionTable[i][1]}, function () {
+                globalDataControl.update(globalReqId, conversionTable[i][0],
+                    rowData.columns[0] + "=" + rowData.values[0], updateSuccess);
+            }, "exception should be thrown");
+        }
+        t.done();
+    });
+
+    insertError = t.step_func(function (reqId, error) {
+        assert_unreached("insert() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_SQL);
+    globalDataControl.insert(globalReqId, rowData, insertSuccess, insertError);
+});
+
+}
+
+function SQLDataControlConsumer_update_without_errorCallback() {
+//==== TEST: SQLDataControlConsumer_update_without_errorCallback
+//==== LABEL Check SQLDataControlConsumer.update method without errorCallback
+//==== SPEC Tizen Web API:TBD:Datacontrol:SQLDataControlConsumer:update M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MR MAST MOA
+//==== PRIORITY P1
+
+setup({timeout: 30000});
+
+var t = async_test('SQLDataControlConsumer_update_without_errorCallback', {timeout: 30000}), globalDataControl,
+    globalReqId = generateGlobalReqId(), currentDate = new Date().getTime().toString(), selectError, insertSuccess,
+    insertError, selectSuccess, rowData, rowDataUpdate, updateSuccess, returnedValue = null,
+    descriptionUpdated = currentDate + "_desc_update", keyUpdated = currentDate + "_update";
+t.step(function () {
+
+    rowData = {
+        columns: ["WORD", "WORD_DESC"],
+        values: ["'" + currentDate + "'", "'" + currentDate + "_desc'"]
+    };
+
+    rowDataUpdate = {
+        columns: ["WORD", "WORD_DESC"],
+        values: ["'" + keyUpdated + "'", "'" + descriptionUpdated + "'"]
+    };
+
+    selectSuccess = t.step_func(function (rows, reqId) {
+        assert_equals(rows.length, 1, "Incorrect number of rows.");
+        assert_array_equals(rows[0].columns, rowDataUpdate.columns, "Incorrect columns");
+        assert_array_equals(rows[0].values, [keyUpdated, descriptionUpdated], "Incorrect values");
+        t.done();
+    });
+
+    selectError = t.step_func(function (reqId, error) {
+        assert_unreached("select() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+
+    updateSuccess = t.step_func(function (reqId) {
+        assert_equals(returnedValue, undefined, "Incorrect returned value");
+        assert_equals(reqId, globalReqId, "Incorrect requestId.");
+        globalReqId++;
+        globalDataControl.select(globalReqId, rowDataUpdate.columns,
+            rowDataUpdate.columns[0] + "=" + rowDataUpdate.values[0], selectSuccess, selectError);
+    });
+
+    insertSuccess = t.step_func(function (reqId, insertRowId) {
+        globalReqId++;
+        returnedValue = globalDataControl.update(globalReqId, rowDataUpdate,
+            rowData.columns[0] + "=" + rowData.values[0], updateSuccess);
+    });
+
+    insertError = t.step_func(function (reqId, error) {
+        assert_unreached("insert() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_SQL);
+    globalDataControl.insert(globalReqId, rowData, insertSuccess, insertError);
+});
+
+}
+
+function SQLDataControlConsumer_update_without_successCallback() {
+//==== TEST: SQLDataControlConsumer_update_without_successCallback
+//==== LABEL Check SQLDataControlConsumer.update method without successCallback
+//==== SPEC Tizen Web API:TBD:Datacontrol:SQLDataControlConsumer:update M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/datacontrol.html
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MR MMINA
+//==== PRIORITY P1
+
+setup({timeout: 30000});
+
+var t = async_test('SQLDataControlConsumer_update_without_successCallback', {timeout: 30000}), globalDataControl,
+    globalReqId = generateGlobalReqId(), currentDate = new Date().getTime().toString(), insertSuccess, insertError,
+    rowData, rowDataUpdate, returnedValue = null;
+t.step(function () {
+
+    rowData = {
+        columns: ["WORD", "WORD_DESC"],
+        values: ["'" + currentDate + "'", "'" + currentDate + "_desc'"]
+    };
+
+    rowDataUpdate = {
+        columns: ["WORD", "WORD_DESC"],
+        values: ["'" + currentDate + "_update'", "'" + currentDate + "_desc_update'"]
+    };
+
+    insertSuccess = t.step_func(function (reqId, insertRowId) {
+        globalReqId++;
+        returnedValue = globalDataControl.update(globalReqId, rowDataUpdate,
+            rowData.columns[0] + "=" + rowData.values[0]);
+        assert_equals(returnedValue, undefined, "Incorrect returned value");
+        t.done();
+    });
+
+    insertError = t.step_func(function (reqId, error) {
+        assert_unreached("insert() error callback: name:" + error.name + ", msg:" + error.message + " for reqId: " + reqId);
+    });
+
+    globalDataControl = tizen.datacontrol.getDataControlConsumer(PROVIDER_ID, DATA_ID, TYPE_SQL);
+    globalDataControl.insert(globalReqId, rowData, insertSuccess, insertError);
+});
+
+}
+
+
+var moduleName = "tct-datacontrol-tizen-tests";
+add_test_case(moduleName, DataControlConsumerObject_dataId_attribute);
+add_test_case(moduleName, DataControlConsumerObject_extend);
+add_test_case(moduleName, DataControlConsumerObject_notexist);
+add_test_case(moduleName, DataControlConsumerObject_providerId_attribute);
+add_test_case(moduleName, DataControlConsumerObject_type_attribute);
+add_test_case(moduleName, DataControlErrorCallback_notexist);
+add_test_case(moduleName, DataControlErrorCallback_onerror);
+add_test_case(moduleName, DataControlGetValueSuccessCallback_notexist);
+add_test_case(moduleName, DataControlGetValueSuccessCallback_onsuccess);
+add_test_case(moduleName, DataControlInsertSuccessCallback_notexist);
+add_test_case(moduleName, DataControlInsertSuccessCallback_onsuccess);
+add_test_case(moduleName, DataControlManagerObject_notexist);
+add_test_case(moduleName, DataControlManager_extend);
+add_test_case(moduleName, DataControlManager_getDataControlConsumer_MAP);
+add_test_case(moduleName, DataControlManager_getDataControlConsumer_SQL);
+add_test_case(moduleName, DataControlManager_getDataControlConsumer_exist);
+add_test_case(moduleName, DataControlManager_getDataControlConsumer_missarg);
+add_test_case(moduleName, DataControlManager_getDataControlConsumer_noarg);
+add_test_case(moduleName, DataControlManager_getDataControlConsumer_type_TypeMismatch);
+add_test_case(moduleName, DataControlManager_in_tizen);
+add_test_case(moduleName, DataControlManager_notexist);
+add_test_case(moduleName, DataControlSelectSuccessCallback_notexist);
+add_test_case(moduleName, DataControlSelectSuccessCallback_onsuccess);
+add_test_case(moduleName, DataControlSuccessCallback_notexist);
+add_test_case(moduleName, DataControlSuccessCallback_onsuccess_MAP);
+add_test_case(moduleName, DataControlSuccessCallback_onsuccess_SQL);
+add_test_case(moduleName, MappedDataControlConsumer_addValue);
+add_test_case(moduleName, MappedDataControlConsumer_addValue_errorCallback_TypeMismatch);
+add_test_case(moduleName, MappedDataControlConsumer_addValue_errorCallback_invalid_cb);
+add_test_case(moduleName, MappedDataControlConsumer_addValue_exist);
+add_test_case(moduleName, MappedDataControlConsumer_addValue_successCallback_TypeMismatch);
+add_test_case(moduleName, MappedDataControlConsumer_addValue_successCallback_invalid_cb);
+add_test_case(moduleName, MappedDataControlConsumer_addValue_with_errorCallback);
+add_test_case(moduleName, MappedDataControlConsumer_addValue_with_successCallback);
+add_test_case(moduleName, MappedDataControlConsumer_extend);
+add_test_case(moduleName, MappedDataControlConsumer_getValue);
+add_test_case(moduleName, MappedDataControlConsumer_getValue_errorCallback_TypeMismatch);
+add_test_case(moduleName, MappedDataControlConsumer_getValue_errorCallback_invalid_cb);
+add_test_case(moduleName, MappedDataControlConsumer_getValue_errorCallback_invoked);
+add_test_case(moduleName, MappedDataControlConsumer_getValue_exist);
+add_test_case(moduleName, MappedDataControlConsumer_getValue_missarg);
+add_test_case(moduleName, MappedDataControlConsumer_getValue_noarg);
+add_test_case(moduleName, MappedDataControlConsumer_getValue_successCallback_TypeMismatch);
+add_test_case(moduleName, MappedDataControlConsumer_getValue_successCallback_invalid_cb);
+add_test_case(moduleName, MappedDataControlConsumer_getValue_without_errorCallback);
+add_test_case(moduleName, MappedDataControlConsumer_notexist);
+add_test_case(moduleName, MappedDataControlConsumer_removeValue);
+add_test_case(moduleName, MappedDataControlConsumer_removeValue_errorCallback_TypeMismatch);
+add_test_case(moduleName, MappedDataControlConsumer_removeValue_errorCallback_invalid_cb);
+add_test_case(moduleName, MappedDataControlConsumer_removeValue_errorCallback_invoked);
+add_test_case(moduleName, MappedDataControlConsumer_removeValue_exist);
+add_test_case(moduleName, MappedDataControlConsumer_removeValue_missarg);
+add_test_case(moduleName, MappedDataControlConsumer_removeValue_noarg);
+add_test_case(moduleName, MappedDataControlConsumer_removeValue_successCallback_TypeMismatch);
+add_test_case(moduleName, MappedDataControlConsumer_removeValue_successCallback_invalid_cb);
+add_test_case(moduleName, MappedDataControlConsumer_removeValue_without_errorCallback);
+add_test_case(moduleName, MappedDataControlConsumer_updateValue);
+add_test_case(moduleName, MappedDataControlConsumer_updateValue_errorCallback_TypeMismatch);
+add_test_case(moduleName, MappedDataControlConsumer_updateValue_errorCallback_invalid_cb);
+add_test_case(moduleName, MappedDataControlConsumer_updateValue_errorCallback_invoked);
+add_test_case(moduleName, MappedDataControlConsumer_updateValue_exist);
+add_test_case(moduleName, MappedDataControlConsumer_updateValue_missarg);
+add_test_case(moduleName, MappedDataControlConsumer_updateValue_noarg);
+add_test_case(moduleName, MappedDataControlConsumer_updateValue_successCallback_TypeMismatch);
+add_test_case(moduleName, MappedDataControlConsumer_updateValue_successCallback_invalid_cb);
+add_test_case(moduleName, MappedDataControlConsumer_updateValue_without_errorCallback);
+add_test_case(moduleName, SQLDataControlConsumer_extend);
+add_test_case(moduleName, SQLDataControlConsumer_insert);
+add_test_case(moduleName, SQLDataControlConsumer_insert_errorCallback_TypeMismatch);
+add_test_case(moduleName, SQLDataControlConsumer_insert_errorCallback_invalid_cb);
+add_test_case(moduleName, SQLDataControlConsumer_insert_exist);
+add_test_case(moduleName, SQLDataControlConsumer_insert_insertionData_TypeMismatch);
+add_test_case(moduleName, SQLDataControlConsumer_insert_missarg);
+add_test_case(moduleName, SQLDataControlConsumer_insert_noarg);
+add_test_case(moduleName, SQLDataControlConsumer_insert_successCallback_TypeMismatch);
+add_test_case(moduleName, SQLDataControlConsumer_insert_successCallback_invalid_cb);
+add_test_case(moduleName, SQLDataControlConsumer_insert_without_errorCallback);
+add_test_case(moduleName, SQLDataControlConsumer_insert_without_successCallback);
+add_test_case(moduleName, SQLDataControlConsumer_notexist);
+add_test_case(moduleName, SQLDataControlConsumer_remove);
+add_test_case(moduleName, SQLDataControlConsumer_remove_errorCallback_TypeMismatch);
+add_test_case(moduleName, SQLDataControlConsumer_remove_errorCallback_invalid_cb);
+add_test_case(moduleName, SQLDataControlConsumer_remove_errorCallback_invoked);
+add_test_case(moduleName, SQLDataControlConsumer_remove_exist);
+add_test_case(moduleName, SQLDataControlConsumer_remove_successCallback_TypeMismatch);
+add_test_case(moduleName, SQLDataControlConsumer_remove_successCallback_invalid_cb);
+add_test_case(moduleName, SQLDataControlConsumer_remove_without_errorCallback);
+add_test_case(moduleName, SQLDataControlConsumer_remove_without_successCallback);
+add_test_case(moduleName, SQLDataControlConsumer_select);
+add_test_case(moduleName, SQLDataControlConsumer_select_columns_TypeMismatch);
+add_test_case(moduleName, SQLDataControlConsumer_select_errorCallback_TypeMismatch);
+add_test_case(moduleName, SQLDataControlConsumer_select_errorCallback_invalid_cb);
+add_test_case(moduleName, SQLDataControlConsumer_select_errorCallback_invoked);
+add_test_case(moduleName, SQLDataControlConsumer_select_exist);
+add_test_case(moduleName, SQLDataControlConsumer_select_missarg);
+add_test_case(moduleName, SQLDataControlConsumer_select_noarg);
+add_test_case(moduleName, SQLDataControlConsumer_select_successCallback_TypeMismatch);
+add_test_case(moduleName, SQLDataControlConsumer_select_successCallback_invalid_cb);
+add_test_case(moduleName, SQLDataControlConsumer_select_without_errorCallback);
+add_test_case(moduleName, SQLDataControlConsumer_select_without_maxNumberPerPage);
+add_test_case(moduleName, SQLDataControlConsumer_select_without_page);
+add_test_case(moduleName, SQLDataControlConsumer_update);
+add_test_case(moduleName, SQLDataControlConsumer_update_errorCallback_TypeMismatch);
+add_test_case(moduleName, SQLDataControlConsumer_update_errorCallback_invalid_cb);
+add_test_case(moduleName, SQLDataControlConsumer_update_errorCallback_invoked);
+add_test_case(moduleName, SQLDataControlConsumer_update_exist);
+add_test_case(moduleName, SQLDataControlConsumer_update_missarg);
+add_test_case(moduleName, SQLDataControlConsumer_update_noarg);
+add_test_case(moduleName, SQLDataControlConsumer_update_successCallback_TypeMismatch);
+add_test_case(moduleName, SQLDataControlConsumer_update_successCallback_invalid_cb);
+add_test_case(moduleName, SQLDataControlConsumer_update_updateData_TypeMismatch);
+add_test_case(moduleName, SQLDataControlConsumer_update_without_errorCallback);
+add_test_case(moduleName, SQLDataControlConsumer_update_without_successCallback);
diff --git a/webWidgetTCT_device/test/tct/tests/TestDom.js b/webWidgetTCT_device/test/tct/tests/TestDom.js
new file mode 100755 (executable)
index 0000000..1d51011
--- /dev/null
@@ -0,0 +1,1441 @@
+/*
+Copyright (c) 2016 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Authors:
+        Mengli Zhang <mengli.zhang@samsung.com>
+        Lei Tang <lei312.tang@samsung.com>
+
+*/
+var doc = document.body;
+var alert = console.log;
+function toASCIIUppercase(str) {
+  var diff = "a".charCodeAt(0) - "A".charCodeAt(0);
+  var res = "";
+  for (var i = 0; i < str.length; ++i) {
+    if ("a" <= str[i] && str[i] <= "z") {
+      res += String.fromCharCode(str.charCodeAt(i) - diff);
+    } else {
+      res += str[i];
+    }
+  }
+  return res;
+}
+
+function assert_equal_node(nodeA, nodeB) {
+  assert_equals(nodeB.nodeType, nodeA.nodeType, "nodeType");
+  assert_equals(nodeB.nodeName, nodeA.nodeName, "nodeName");
+
+  if (nodeA.nodeType === Node.ELEMENT_NODE) {
+    assert_equals(nodeB.prefix, nodeA.prefix);
+    assert_equals(nodeB.namespaceURI, nodeA.namespaceURI);
+    assert_equals(nodeB.localName, nodeA.localName);
+    assert_equals(nodeB.tagName, nodeA.tagName);
+    assert_not_equals(nodeB.attributes != nodeA.attributes);
+    assert_equals(nodeB.attributes.length, nodeA.attributes.length);
+    for (var i = 0, il = nodeA.attributes.length; i < il; ++i) {
+      assert_not_equals(nodeB.attributes[i], nodeA.attributes[i]);
+      assert_equals(nodeB.attributes[i].name, nodeA.attributes[i].name);
+      assert_equals(nodeB.attributes[i].prefix, nodeA.attributes[i].prefix);
+      assert_equals(nodeB.attributes[i].namespaceURI, nodeA.attributes[i].namespaceURI);
+      assert_equals(nodeB.attributes[i].value, nodeA.attributes[i].value);
+    }
+  }
+}
+
+function check_copy(orig, copy, type) {
+    assert_not_equals(orig, copy);
+    assert_equal_node(orig, copy);
+    assert_true(orig instanceof type, "Should be type");
+    assert_true(copy instanceof type, "Should be type");
+}
+
+function NonElementParentNode_getElementById() {
+
+//==== TEST: NonElementParentNode_getElementById
+//==== LABEL Check getElementById method
+//==== SPEC
+//==== SPEC_URL https://www.w3.org/TR/domcore/#interface-nonelementparentnode
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function() {
+    var TEST_ID = "test4-should-not-exist";
+    var e = document.createElement('div');
+    e.setAttribute("id", TEST_ID);
+    assert_equals(document.getElementById(TEST_ID), null, "getElementById method should be null");
+    document.body.appendChild(e);
+    assert_equals(document.getElementById(TEST_ID), e, "getElementById method should be the appended element");
+}, 'NonElementParentNode_getElementById');
+
+}
+
+function NonDocumentTypeChildNode_previousElementSibling_attribute() {
+
+//==== TEST: NonDocumentTypeChildNode_previousElementSibling_attribute
+//==== LABEL Check previousElementSibling attribute is object type
+//==== SPEC
+//==== SPEC_URL https://www.w3.org/TR/domcore/#interface-nondocumenttypechildnode
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT
+
+test(function() {
+    var TEST_ID = "test4-should-not-exist";
+    var e = document.createElement('div');
+    e.setAttribute("id", TEST_ID);
+    document.body.appendChild(e);
+    var lec = document.getElementById(TEST_ID);
+    var pes = lec.previousElementSibling;
+    assert_true(!!pes)
+    assert_equals(pes.nodeType, 1, "should be 1")
+    assert_equals(pes.getAttribute("id"), null, "previousElementSibling attribute should be null");
+}, 'NonDocumentTypeChildNode_previousElementSibling_attribute');
+
+}
+
+function NonDocumentTypeChildNode_nextElementSibling_attribute() {
+
+//==== TEST: NonDocumentTypeChildNode_nextElementSibling_attribute
+//==== LABEL Check nextElementSibling attribute is object type
+//==== SPEC
+//==== SPEC_URL https://www.w3.org/TR/domcore/#interface-nondocumenttypechildnode
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT
+
+test(function() {
+    var TEST_ID = "test4-should-not-exist";
+    var e = document.createElement('div');
+    e.setAttribute("id", TEST_ID);
+    document.body.appendChild(e);
+    var lec = document.getElementById(TEST_ID);
+    var nes = lec.nextElementSibling;
+    assert_true(!!nes);
+    assert_equals(nes.nodeType, 1, "pnextElementSibling attribute nodeType should be 1");
+    assert_equals(nes.getAttribute("id"), "test4-should-not-exist");
+}, 'NonDocumentTypeChildNode_nextElementSibling_attribute');
+
+}
+
+function ChildNode_remove_exist() {
+
+//==== TEST: ChildNode_remove_exist
+//==== LABEL Check remove method id exist
+//==== SPEC
+//==== SPEC_URL https://www.w3.org/TR/domcore/#childnode
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function() {
+    var node = document.createElement("div");
+    assert_true("remove" in node);
+    assert_equals(typeof node.remove, "function", "remove method should be function");
+    assert_equals(node.remove.length, 0);
+}, 'ChildNode_remove_exist');
+
+}
+
+function ChildNode_remove_extar_argument() {
+
+//==== TEST: ChildNode_remove_extar_argument
+//==== LABEL Check using remove() method with extra argument
+//==== SPEC
+//==== SPEC_URL https://www.w3.org/TR/domcore/#childnode
+//==== PRIORITY p1
+//==== TEST_CRITERIA MNAEX
+
+test(function() {
+    var node = document.createElement("div");
+    checkExtraArgument(node, "remove");
+}, 'ChildNode_remove_extar_argument');
+
+}
+
+function HTMLCollection_length_attribute() {
+
+//==== TEST: HTMLCollection_length_attribute
+//==== LABEL Make sure browsers throw when getting .length on some random object whose proto is an HTMLCollection
+//==== SPEC
+//==== SPEC_URL https://www.w3.org/TR/domcore/#htmlcollection
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ARO
+
+test(function() {
+    var obj = document.getElementsByTagName("div");
+    check_readonly(obj, "length", obj.length, "number", obj.length+1);
+}, 'HTMLCollection_length_attribute');
+
+}
+
+function HTMLCollection_namedItem() {
+
+//==== TEST: HTMLCollection_namedItem
+//==== LABEL HTMLCollection and empty names
+//==== SPEC
+//==== SPEC_URL https://www.w3.org/TR/domcore/#htmlcollection
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT
+
+test(function() {
+    var c = document.getElementsByClassName("a");
+    assert_false("" in c, "Empty string should not be in the collection.");
+    assert_equals(c[""], undefined, "Named getter should return undefined for empty string.");
+    assert_equals(c.namedItem(""), null, "namedItem should return null for empty string.");
+}, 'HTMLCollection_namedItem');
+
+}
+
+function HTMLCollection_item() {
+
+//==== TEST: HTMLCollection_item
+//==== LABEL HTMLCollection and empty names
+//==== SPEC
+//==== SPEC_URL https://www.w3.org/TR/domcore/#htmlcollection
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function() {
+    var collection = document.getElementsByTagName("foo");
+    assert_equals(collection.item(4294967293), null);
+    assert_equals(collection.item(4294967294), null);
+    assert_equals(collection.item(4294967295), null);
+}, 'HTMLCollection_item');
+
+}
+
+function Node_nodeName_attribute() {
+
+//==== TEST: Node_nodeName_attribute
+//==== LABEL For Text nodes, nodeName should return \"#text\".
+//==== SPEC
+//==== SPEC_URL https://www.w3.org/TR/domcore/#interface-node
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT
+
+test(function() {
+    assert_equals(document.createTextNode("foo").nodeName, "#text")
+}, 'Node_nodeName_attribute');
+
+}
+
+function Node_nodeValue_attribute() {
+
+//==== TEST: Node_nodeValue_attribute
+//==== LABEL For Text nodes, nodeName should return \"#text\".
+//==== SPEC
+//==== SPEC_URL https://www.w3.org/TR/domcore/#interface-node
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT
+
+test(function() {
+    var the_text = document.createTextNode("A span!");
+    assert_equals(the_text.nodeValue, "A span!");
+    assert_equals(the_text.data, "A span!");
+    the_text.nodeValue = "test again";
+    assert_equals(the_text.nodeValue, "test again");
+    assert_equals(the_text.data, "test again");
+    the_text.nodeValue = null;
+    assert_equals(the_text.nodeValue, "");
+    assert_equals(the_text.data, "");
+}, 'Node_nodeValue_attribute');
+
+}
+
+function Node_textContent_attribute() {
+
+//==== TEST: Node_textContent_attribute
+//==== LABEL For an empty Element, textContent should be the empty string
+//==== SPEC
+//==== SPEC_URL https://www.w3.org/TR/domcore/#interface-node
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT
+
+test(function() {
+    var documents, doctypes, element;
+
+    setup(function() {
+        documents = [
+           [document, "parser"],
+           [document.implementation.createDocument("", "test", null), "createDocument"],
+           [document.implementation.createHTMLDocument("title"), "createHTMLDocument"],
+        ]
+        doctypes = [
+           [document.doctype, "parser"],
+           [document.implementation.createDocumentType("x", "", ""), "script"],
+        ]
+    })
+
+    element = document.createElement("div")
+    assert_equals(element.textContent, "")
+}, 'Node_textContent_attribute');
+
+}
+
+function Node_parentNode_attribute() {
+
+//==== TEST: Node_parentNode_attribute
+//==== LABEL Check parentNode attribute
+//==== SPEC
+//==== SPEC_URL https://www.w3.org/TR/domcore/#interface-node
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT
+
+test(function() {
+    var el = document.createElement("div");
+    assert_equals(el.parentNode, null);
+    document.body.appendChild(el);
+    assert_equals(el.parentNode, document.body);
+}, 'Node_parentNode_attribute');
+
+}
+
+function Node_childNodes_attribute() {
+
+//==== TEST: Node_childNodes_attribute
+//==== LABEL Check childNodes attribute
+//==== SPEC
+//==== SPEC_URL https://www.w3.org/TR/domcore/#interface-node
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT
+
+test(function() {
+    var element = document.createElement("p");
+    assert_equals(element.childNodes, element.childNodes);
+}, 'Node_childNodes_attribute');
+
+}
+
+function Node_cloneNode() {
+
+//==== TEST: Node_cloneNode
+//==== LABEL Check cloneNode method
+//==== SPEC
+//==== SPEC_URL https://www.w3.org/TR/domcore/#interface-node
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT
+
+test(function() {
+    var el = document.createElement("foo");
+    el.setAttribute("a", "b");
+    el.setAttribute("c", "d");
+    var c = el.cloneNode();
+    check_copy(el, c, Element);
+}, 'Node_cloneNode');
+
+}
+
+function Node_isEqualNode() {
+
+//==== TEST: Node_isEqualNode
+//==== LABEL Check isEqualNode method
+//==== SPEC
+//==== SPEC_URL https://www.w3.org/TR/domcore/#interface-node
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT
+
+test(function() {
+    var text1 = document.createTextNode("data");
+    var text2 = document.createTextNode("data");
+    var text3 = document.createTextNode("data2");
+
+    assert_true(text1.isEqualNode(text1), "self-comparison");
+    assert_true(text1.isEqualNode(text2), "same properties");
+    assert_false(text1.isEqualNode(text3), "different data");
+}, 'Node_isEqualNode');
+
+}
+
+
+function Node_contains() {
+
+//==== TEST: Node_contains
+//==== LABEL
+//==== SPEC
+//==== SPEC_URL https://www.w3.org/TR/domcore/#interface-node
+//==== PRIORITY P0
+//==== TEST_CRITERIA
+/*
+"use strict";
+
+testNodes.forEach(function(referenceName) {
+  var reference = eval(referenceName);
+
+  test(function() {
+    assert_false(reference.contains(null));
+  }, 'Node_contains');
+
+  testNodes.forEach(function(otherName) {
+    var other = eval(otherName);
+    test(function() {
+      var ancestor = other;
+      while (ancestor && ancestor !== reference) {
+        ancestor = ancestor.parentNode;
+      }
+      if (ancestor === reference) {
+        assert_true(reference.contains(other));
+      } else {
+        assert_false(reference.contains(other));
+      }
+    }, referenceName + ".compareDocumentPosition(" + otherName + ")");
+  });
+});
+
+testDiv.parentNode.removeChild(testDiv);
+
+test(function() {
+
+
+
+}, 'Node_contains');
+*/
+}
+
+function Element_classList_exists() {
+
+//==== TEST: Element_classList_exists
+//==== LABEL Check if the Element has classList attribute exists
+//==== SPEC
+//==== SPEC_URL http://www.w3.org/TR/2011/WD-html5-20110525/elements.html#dom-classlist
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function (){
+    assert_true("classList" in document.documentElement);
+}, "Element_classList_exists");
+}
+
+function ParentNode_exits() {
+
+//==== TEST: ParentNode_exits
+//==== LABEL Check if the document has parentNode interface exists and returnValue
+//==== SPEC
+//==== SPEC_URL http://www.w3.org/TR/domcore/#interface-parentnode
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function (){
+    assert_true("parentNode" in document);
+    assert_equals(document.parentNode, null);
+},"ParentNode_exits");
+}
+
+function ParentNode_children() {
+
+//==== TEST: ParentNode_children
+//==== LABEL Check if the parentNode has children attribute
+//==== SPEC
+//==== SPEC_URL http://www.w3.org/TR/domcore/#interface-parentnode
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT
+
+test(function (){
+    var e1 = document.createElement("div");
+    var e2 = document.body.appendChild(e1);
+    assert_true("parentNode" in e2);
+    assert_equals(e2.parentnode, undefined);
+},"ParentNode_children");
+}
+
+function ParentNode_firstElementChild() {
+
+//==== TEST: ParentNode_firstElementChild
+//==== LABEL Check if the parentNode has firstElementChild attribute exists
+//==== SPEC
+//==== SPEC_URL http://www.w3.org/TR/domcore/#interface-parentnode
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT
+
+test(function() {
+    var e1 = document.createElement("div");
+    var e2 = document.createElement("div");
+    e1.appendChild(e2);
+    var fec = e1.firstElementChild;
+    assert_type(fec, "object", "firstElementChild attribute should object type");
+    assert_equals(fec.nodeType, 1, "firstElementChild attribute noteType is equal 1");
+},"ParentNode_firstElementChild");
+
+}
+
+function ParentNode_lastElementChild() {
+
+//==== TEST: ParentNode_lastElementChild
+//==== LABEL Check if the parentNode has lastElementChild attribute exists
+//==== SPEC
+//==== SPEC_URL http://www.w3.org/TR/domcore/#interface-parentnode
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT
+
+test(function() {
+    var e1 = document.createElement("div");
+    var e2 = document.createElement("div");
+    e1.appendChild(e2);
+    var fec = e1.lastElementChild;
+    assert_type(fec, "object", "lastElementChild attribute should object type");
+    assert_equals(fec.nodeType, 1, "lastElementChild attribute noteType is equal 1");
+},"ParentNode_lastElementChild");
+
+}
+
+function ParentNode_childElementCount() {
+
+//==== TEST: ParentNode_childElementCount
+//==== LABEL Check if the parentNode has childElementCount attribute exists
+//==== SPEC
+//==== SPEC_URL http://www.w3.org/TR/domcore/#interface-parentnode
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT
+
+test(function() {
+    var e1 = document.createElement("div");
+    var e2 = document.createElement("div");
+    e1.appendChild(e2);
+    var fec = e1.childElementCount;
+    assert_type(fec, "long", "childElementCount attribute should long type");
+},"ParentNode_childElementCount");
+
+}
+
+function Node_insertBefore() {
+
+//==== TEST: Node_insertBefore
+//==== LABEL Check insertBefore method
+//==== SPEC
+//==== SPEC_URL http://www.w3.org/TR/domcore/#interface-node
+//==== PRIORITY P0
+//==== TEST_CRITERIA AE AT
+
+test(function() {
+    var a = document.createElement("div");
+    var b = document.createElement("div");
+    var c = document.createElement("div");
+    assert_throws("NotFoundError", function() {
+        a.insertBefore(b, c);
+    });
+}, 'Node_insertBefore');
+
+}
+
+function Node_appendChild() {
+
+//==== TEST: Node_appendChild
+//==== LABEL Check appendChild method
+//==== SPEC
+//==== SPEC_URL http://www.w3.org/TR/domcore/#interface-node
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT
+
+test(function() {
+    var e1 = document.createElement("div");
+    var e2 = document.createElement("div");
+    var node = e1.appendChild(e2);
+    assert_type(node, "object", "appendChild should object type");
+  }, 'Node_appendChild');
+
+}
+
+function Node_replaceChild() {
+
+//==== TEST: Node_replaceChild
+//==== LABEL Check replaceChild method
+//==== SPEC
+//==== SPEC_URL http://www.w3.org/TR/domcore/#interface-node
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT
+
+test(function() {
+    var a = document.createElement("div");
+    assert_throws(new TypeError(), function() {
+        a.replaceChild(null, null);
+    });
+
+    var b = document.createElement("div");
+    assert_throws(new TypeError(), function() {
+        a.replaceChild(b, null);
+    });
+
+    assert_throws(new TypeError(), function() {
+        a.replaceChild(null, b);
+    });
+}, 'Node_replaceChild');
+
+}
+
+function Node_removeChild() {
+
+//==== TEST: Node_removeChild
+//==== LABEL Check removeChild method
+//==== SPEC
+//==== SPEC_URL http://www.w3.org/TR/domcore/#interface-node
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT
+
+test(function() {
+    assert_throws(new TypeError(), function() { document.body.removeChild(null) })
+    assert_throws(new TypeError(), function() { document.body.removeChild({'a':'b'}) })
+}, 'Node_removeChild');
+
+}
+
+function Document_doctype() {
+
+//==== TEST: Document_doctype
+//==== LABEL Check doctype attribute
+//==== SPEC
+//==== SPEC_URL https://www.w3.org/TR/domcore/#document
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT
+
+test(function() {
+  assert_true("doctype" in document);
+  assert_type(document.doctype, "object", "doctype attribute should be object type");
+}, 'Document_doctype');
+
+}
+
+function Document_documentElement() {
+
+//==== TEST: Document_documentElement
+//==== LABEL Check documentElement attribute
+//==== SPEC
+//==== SPEC_URL https://www.w3.org/TR/domcore/#document
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT
+
+test(function() {
+    assert_type(document.documentElement, "object", "documentElement attribute should be object type");
+    assert_equals(document.documentElement.nodeName, "HTML", "documentElement attribute is equals HTML");
+}, 'Document_documentElement');
+
+}
+
+function Document_contentType() {
+
+//==== TEST: Document_contentType
+//==== LABEL Check contentType attribute
+//==== SPEC
+//==== SPEC_URL https://www.w3.org/TR/domcore/#document
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT
+
+test(function() {
+    assert_equals(document.contentType, "text/html", "contentType attribute is equals text/html");
+}, 'Document_contentType');
+
+}
+
+function Document_characterSet() {
+
+//==== TEST: Document_characterSet
+//==== LABEL Check characterSet attribute
+//==== SPEC
+//==== SPEC_URL https://www.w3.org/TR/domcore/#document
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT
+
+test(function() {
+    document.createElement("div");
+    assert_type(document.characterSet, "string", "documentElement attribute should be string type");
+    assert_equals(document.characterSet, "UTF-8", "contentType attribute should be UTF-8");
+}, 'Document_characterSet');
+
+}
+
+function Document_compatMode() {
+
+//==== TEST: Document_compatMode
+//==== LABEL Check compatMode attribute
+//==== SPEC
+//==== SPEC_URL https://www.w3.org/TR/domcore/#document
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT
+
+test(function() {
+    document.createElement("div");
+    assert_type(document.compatMode, "string", "documentElement attribute should be string type");
+    assert_equals(document.compatMode, "CSS1Compat", "contentType attribute should be CSS1Compat");
+}, 'Document_compatMode');
+
+}
+
+function Document_getElementsByTagName() {
+
+//==== TEST: Document_getElementsByTagName
+//==== LABEL Check getElementsByTagName method is exist
+//==== SPEC
+//==== SPEC_URL https://www.w3.org/TR/domcore/#document
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function() {
+    assert_false(document.getElementsByTagName("html") instanceof NodeList,
+        "Should not return a NodeList");
+    assert_true(document.getElementsByTagName("html") instanceof HTMLCollection,
+        "Should return an HTMLCollection");
+}, 'Document_getElementsByTagName');
+
+}
+
+function Document_getElementsByClassName() {
+
+//==== TEST: Document_getElementsByClassName
+//==== LABEL Check getElementsByClassName method
+//==== SPEC
+//==== SPEC_URL https://www.w3.org/TR/domcore/#document
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function() {
+    var testElements = document.getElementsByClassName('test');
+    assert_type(testElements, "object", "getElementsByClassName method should be object type");
+    assert_equals(testElements[""], undefined, "Named getter should return undefined for empty string.");
+}, 'Document_getElementsByClassName');
+
+}
+
+function Document_createElement() {
+
+//==== TEST: Document_createElement
+//==== LABEL Check createElement method
+//==== SPEC
+//==== SPEC_URL https://www.w3.org/TR/domcore/#document
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function() {
+    var elt = document.createElement("elt");
+    var HTMLNS = "http://www.w3.org/1999/xhtml";
+    assert_true(elt instanceof Element);
+    assert_true(elt instanceof Node);
+    assert_equals(elt.localName, "elt");
+    assert_equals(elt.tagName, toASCIIUppercase("elt"));
+    assert_equals(elt.namespaceURI, HTMLNS);
+}, 'Document_createElement');
+
+}
+
+function Document_createElement_exist() {
+
+//==== TEST: Document_createElement_exist
+//==== LABEL Check createElement method is exist
+//==== SPEC
+//==== SPEC_URL https://www.w3.org/TR/domcore/#document
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function() {
+    assert_true("createElement" in document);
+    assert_equals(typeof document.createElement, "function", "createElement method returnValue is function");
+    assert_equals(document.createElement.length, 1, "createElement method length is equals 1");
+}, 'Document_createElement_exist');
+
+}
+
+function Document_createTextNode() {
+
+//==== TEST: Document_createTextNode
+//==== LABEL Check createTextNode method
+//==== SPEC
+//==== SPEC_URL https://www.w3.org/TR/domcore/#document
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function() {
+    var textnode = document.createTextNode("textnode");
+    assert_true(textnode instanceof Node);
+}, 'Document_createTextNode');
+
+}
+
+function Document_createTextNode_exist() {
+
+//==== TEST: Document_createTextNode_exist
+//==== LABEL Check createTextNode method is exist
+//==== SPEC
+//==== SPEC_URL https://www.w3.org/TR/domcore/#document
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function() {
+    assert_true("createTextNode" in document);
+    assert_equals(typeof document.createTextNode, "function", "createTextNode method returnValue is function");
+    assert_equals(document.createTextNode.length, 1, "createTextNode method length is equals 1");
+}, 'Document_createTextNode_exist');
+
+}
+
+function Document_createComment() {
+
+//==== TEST: Document_createComment
+//==== LABEL Check createComment method
+//==== SPEC
+//==== SPEC_URL https://www.w3.org/TR/domcore/#document
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function() {
+    var comment = document.createComment("comment");
+    assert_true(comment instanceof Node);
+}, 'Document_createComment');
+
+}
+
+function Document_createComment_exist() {
+
+//==== TEST: Document_createComment_exist
+//==== LABEL Check createComment method is exist
+//==== SPEC
+//==== SPEC_URL https://www.w3.org/TR/domcore/#document
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function() {
+    assert_true("createComment" in document);
+    assert_equals(typeof document.createComment, "function", "createComment method returnValue is function");
+    assert_equals(document.createComment.length, 1, "createComment method length is equals 1");
+}, 'Document_createComment_exist');
+
+}
+
+function DocumentType_name_attribute() {
+
+//==== TEST: DocumentType_name_attribute
+//==== LABEL Check name attribute is Domstring type
+//==== SPEC
+//==== SPEC_URL http://www.w3.org/TR/domcore/#interface-documenttype
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ARO
+
+test(function() {
+    check_readonly(DocumentType, "name", DocumentType.name, "string", DocumentType.name+1);
+}, 'DocumentType_name_attribute');
+
+}
+
+function NodeList_length_attribute() {
+
+//==== TEST: NodeList_length_attribute
+//==== LABEL Check length attribute is long type
+//==== SPEC
+//==== SPEC_URL http://www.w3.org/TR/domcore/#nodelist
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ARO
+
+test(function() {
+    var node = document.getElementsByTagName("*");
+    check_readonly(node, "length", node.length, "number", node.length+1);
+}, 'NodeList_length_attribute');
+
+}
+
+function NodeList_item() {
+
+//==== TEST: NodeList_item
+//==== LABEL Check item method
+//==== SPEC
+//==== SPEC_URL http://www.w3.org/TR/domcore/#nodelist
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function() {
+    var collection = document.getElementsByTagName("foo");
+    assert_equals(collection.item(4294967293), null, "item method returnValue should be null");
+}, 'NodeList_item');
+
+}
+
+function Element_localName() {
+
+//==== TEST: Element_localName
+//==== LABEL Check if the Element has localName attribute
+//==== SPEC
+//==== SPEC_URL http://www.w3.org/TR/domcore/#interface-element
+//==== PRIORITY P0
+//==== TEST_CRITERIA AE AT ARO
+
+test(function (){
+    check_readonly(document.documentElement, "localName", document.documentElement.localName, null, "div");
+}, "Element_localName");
+}
+
+function Element_tagName() {
+
+//==== TEST: Element_tagName
+//==== LABEL Check if the Element has tagName attribute
+//==== SPEC
+//==== SPEC_URL http://www.w3.org/TR/domcore/#interface-element
+//==== PRIORITY P0
+//==== TEST_CRITERIA AE AT ARO
+
+test(function (){
+    check_readonly(document.documentElement, "tagName", document.documentElement.tagName, null, "div");
+}, "Element_tagName");
+}
+
+function Element_id() {
+
+//==== TEST: Element_id
+//==== LABEL Check if the Element has id attribute
+//==== SPEC
+//==== SPEC_URL http://www.w3.org/TR/domcore/#interface-element
+//==== PRIORITY P0
+//==== TEST_CRITERIA AE AT ASG
+
+test(function() {
+    var e1 = document.createElement("p");
+    assert_true("id" in e1, "Id attribute should exist");
+    assert_type(e1.id, "string", "id attribute should return string type");
+    assert_equals(e1.id, "", "id attribute should return correctly value");
+    e1.id = "id";
+    assert_equals(e1.id, "id", "id attribute is writeable");
+},"Element_id");
+}
+
+function Element_className() {
+
+//==== TEST: Element_className
+//==== LABEL Check if the Element has className attribute
+//==== SPEC
+//==== SPEC_URL http://www.w3.org/TR/domcore/#interface-element
+//==== PRIORITY P0
+//==== TEST_CRITERIA AE AT ASG
+
+test(function() {
+    var e1;
+    e1 = document.createElement("p");
+    assert_true("className" in e1, "className attribute should exist");
+    assert_type(e1.className, "string", "className attribute should return string type");
+    assert_equals(e1.className, "", "className attribute should return correctly value");
+    e1.className = "className";
+    assert_equals(e1.className, "className", "className attribute is writeable");
+},"Element_className");
+}
+
+function Element_classList() {
+
+//==== TEST: Element_classList
+//==== LABEL Check if the Element has classList attribute exists
+//==== SPEC
+//==== SPEC_URL http://www.w3.org/TR/domcore/#interface-element
+//==== PRIORITY P0
+//==== TEST_CRITERIA AE AT ARO
+
+test(function (){
+    var e1;
+    e1 = document.createElement("p");
+    e1.className = "test";
+    assert_true("classList" in e1, "classList attribute is exist");
+    assert_type(e1.classList, "object", "classList attribute should return object type");
+    e1.classList = [];
+    assert_not_equals(e1.classList, [], "classList attribute is readonly");
+}, "Element_classList");
+}
+
+function Element_attributes() {
+
+//==== TEST: Element_attributes
+//==== LABEL Check if the Element has attributes attribute exists
+//==== SPEC
+//==== SPEC_URL http://www.w3.org/TR/domcore/#interface-element
+//==== PRIORITY P0
+//==== TEST_CRITERIA AE AT ARO
+
+test(function (){
+    var e1;
+    e1 = document.createElement("p");
+    e1.className = "test";
+    assert_true("attributes" in e1, "attributes attribute is exist");
+    assert_type(e1.attributes, "object", "attributes attribute should return object type");
+    e1.classList = [];
+    assert_not_equals(e1.attributes, [], "attributes attribute is readonly");
+}, "Element_attributes");
+}
+
+function Element_getAttribute() {
+
+//==== TEST: Element_getAttribute
+//==== LABEL Check if the getAttribute method work properly
+//==== SPEC
+//==== SPEC_URL http://www.w3.org/TR/domcore/#interface-element
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME MR
+
+test(function (){
+    var e1, att;
+    e1 = document.createElement("div");
+    e1.setAttribute("style", "color");
+    check_method_exists(e1, "getAttribute");
+    att = e1.getAttribute("style");
+    assert_equals(att, "color", "getAttribute method should work properly");
+}, "Element_getAttribute");
+}
+
+function Element_setAttribute() {
+
+//==== TEST: Element_setAttribute
+//==== LABEL Check if the setAttribute method work properly
+//==== SPEC
+//==== SPEC_URL http://www.w3.org/TR/domcore/#interface-element
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME MR
+
+test(function (){
+    var e1, att;
+    e1 = document.createElement("div");
+    check_method_exists(e1, "setAttribute");
+    att = e1.setAttribute("style", "board");
+    assert_equals(e1.getAttribute("style"), "board", "setAttribute method should work properly");
+}, "Element_setAttribute");
+}
+
+function Element_removeAttribute() {
+
+//==== TEST: Element_removeAttribute
+//==== LABEL Check if the removeAttribute method work properly
+//==== SPEC
+//==== SPEC_URL http://www.w3.org/TR/domcore/#interface-element
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME MR
+
+test(function (){
+    var e1, returnedValue;
+    e1 = document.createElement("div");
+    e1.setAttribute("style", "color");
+    check_method_exists(e1, "removeAttribute");
+    returnedValue = e1.removeAttribute("style");
+    assert_equals(returnedValue, undefined, "removeAttribute method  should return undefined");
+}, "Element_removeAttribute");
+}
+
+function Element_hasAttribute() {
+
+//==== TEST: Element_hasAttribute
+//==== LABEL Check if the removeAttribute method work properly
+//==== SPEC
+//==== SPEC_URL http://www.w3.org/TR/domcore/#interface-element
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME MR
+
+test(function (){
+    var e1, returnedValue;
+    e1 = document.createElement("div");
+    e1.setAttribute("target", "_red");
+    check_method_exists(e1, "hasAttribute");
+    returnedValue = e1.hasAttribute("target");
+    assert_equals(returnedValue, true, "hasAttribute method  should return boolean");
+}, "Element_hasAttribute");
+}
+
+function Element_getElementsByTagName() {
+
+//==== TEST: Element_getElementsByTagName
+//==== LABEL Check if the getElementsByTagName method work properly
+//==== SPEC
+//==== SPEC_URL http://www.w3.org/TR/domcore/#interface-element
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME MR
+
+test(function (){
+    var e1, returnedValue;
+    e1 = document.createElement("div");
+    check_method_exists(e1, "getElementsByTagName");
+    returnedValue = e1.getElementsByTagName("div");
+    assert_type(returnedValue, "object", "getElementsByTagName method should return object type");
+}, "Element_getElementsByTagName");
+}
+
+function Element_getElementsByClassName() {
+
+//==== TEST: Element_getElementsByClassName
+//==== LABEL Check if the getElementsByClassName method work properly
+//==== SPEC
+//==== SPEC_URL http://www.w3.org/TR/domcore/#interface-element
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME MR
+
+test(function (){
+    var e1, returnedValue;
+    e1 = document.createElement("div");
+    e1.setAttribute("class", "test_className");
+    check_method_exists(e1, "getElementsByClassName");
+    returnedValue = e1.getElementsByTagName("test_className");
+    assert_type(returnedValue, "object", "getElementsByTagName method should return object type");
+}, "Element_getElementsByClassName");
+}
+
+function Attr_name() {
+
+//==== TEST: Attr_name
+//==== LABEL Check if the Attr has name attribute exists
+//==== SPEC
+//==== SPEC_URL http://www.w3.org/TR/domcore/#interface-element
+//==== PRIORITY P0
+//==== TEST_CRITERIA AE AT ARO
+
+test(function (){
+    var e1 = document.createElement("div");
+    e1.setAttribute("class", "test_Name");
+    check_readonly(e1.attributes[0], "name", e1.attributes[0].name, "string", "div");
+}, "Attr_name");
+}
+
+function Attr_value() {
+
+//==== TEST: Attr_value
+//==== LABEL Check if the Attr has value attribute exists
+//==== SPEC
+//==== SPEC_URL http://www.w3.org/TR/domcore/#interface-element
+//==== PRIORITY P0
+//==== TEST_CRITERIA AE AT ASG
+
+test(function (){
+    var e1 = document.createElement("div");
+    e1.setAttribute("class", "test_Value");
+    check_attribute(e1.attributes[0], "value", "test_Value", "string", "Value");
+}, "Attr_value");
+}
+
+function Attr_specified() {
+
+//==== TEST: Attr_specified
+//==== LABEL Check if the Attr has specified attribute exists
+//==== SPEC
+//==== SPEC_URL http://www.w3.org/TR/domcore/#interface-element
+//==== PRIORITY P0
+//==== TEST_CRITERIA AE AT ARO
+
+test(function (){
+    var e1 = document.createElement("div");
+    e1.setAttribute("class", "test_Value");
+    check_readonly(e1.attributes[0], "specified", true, "boolean", false);
+}, "Attr_specified");
+}
+
+function CharacterData_data() {
+
+//==== TEST: CharacterData_data
+//==== LABEL Check if the CharacterData has data attribute exists
+//==== SPEC
+//==== SPEC_URL http://www.w3.org/TR/domcore/#interface-element
+//==== PRIORITY P0
+//==== TEST_CRITERIA AE AT ARO
+
+test(function (){
+    var node = document.createTextNode("test");
+    check_attribute(node, "data", "test", "string", "modify");
+  }, "CharacterData_data");
+}
+
+function CharacterData_length() {
+
+//==== TEST: CharacterData_length
+//==== LABEL Check if the CharacterData has length attribute exists
+//==== SPEC
+//==== SPEC_URL http://www.w3.org/TR/domcore/#interface-element
+//==== PRIORITY P0
+//==== TEST_CRITERIA AE AT ARO
+
+test(function (){
+    var node = document.createTextNode("test");
+    check_readonly(node, "length", 4, "number", 19);
+  }, "CharacterData_length");
+}
+
+function Text_wholeText() {
+
+//==== TEST: Text_wholeText
+//==== LABEL Check if the Text has wholeText attribute exists
+//==== SPEC
+//==== SPEC_URL http://www.w3.org/TR/domcore/#interface-element
+//==== PRIORITY P0
+//==== TEST_CRITERIA AE AT ARO
+
+test(function (){
+    var node = document.createTextNode("test");
+    check_readonly(node, "wholeText", "test", "string", "modify");
+  }, "Text_wholeText");
+}
+
+function comment_Comment() {
+
+//==== TEST: comment_Comment
+//==== LABEL Check if the Comment method in comment is working properly
+//==== SPEC
+//==== SPEC_URL http://www.w3.org/TR/domcore/#interface-element
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME MR
+
+test(function (){
+  var comment = new Comment("test");
+  assert_type(comment, "object", "comment constructor should return object");
+  }, "comment_Comment");
+}
+
+function DOMTokenList_length() {
+
+//==== TEST: DOMTokenList_length
+//==== LABEL Check if the DOMTokenList has length attribute exists
+//==== SPEC
+//==== SPEC_URL http://www.w3.org/TR/domcore/#interface-element
+//==== PRIORITY P0
+//==== TEST_CRITERIA AE AT ARO
+
+test(function() {
+  var e1 = document.createElement("span");
+  e1.setAttribute("class", "   a  a b ");
+  check_readonly(e1.classList, "length", 2, "number", 5);
+  assert_equals(String(document.createElement("span").classList), "",
+                "String(classList) should return the empty list for an undefined class attribute");
+  assert_equals(e1.getAttribute("class"), "   a  a b ",
+                "getAttribute should return the literal value");
+  assert_equals(e1.className, "   a  a b ",
+                "className should return the literal value");
+  assert_equals(String(e1.classList), "   a  a b ",
+                "String(classList) should return the literal value");
+  assert_equals(e1.classList.toString(), "   a  a b ",
+                "classList.toString() should return the literal value");
+  assert_class_string(e1.classList, "DOMTokenList");
+}, "DOMTokenList_length");
+}
+
+function DOMTokenList_item() {
+
+//==== TEST: DOMTokenList_item
+//==== LABEL Check if the item method in DOMTokenList is working properly
+//==== SPEC
+//==== SPEC_URL http://www.w3.org/TR/domcore/#interface-element
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME MR
+
+test(function() {
+    var e1 = document.createElement("div");
+    e1.setAttribute("class", "myclass1 myclass2");
+    check_method_exists(e1.classList, "item");
+    assert_equals(e1.classList.item(1),  "myclass2", "item method retuen the correctly value");
+}, "DOMTokenList_item");
+}
+
+function DOMTokenList_contains() {
+
+//==== TEST: DOMTokenList_contains
+//==== LABEL Check if the contains method in DOMTokenList is working properly
+//==== SPEC
+//==== SPEC_URL http://www.w3.org/TR/domcore/#interface-element
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME MR
+
+test(function() {
+    var e1 = document.createElement("div");
+    e1.setAttribute("class", "myclass1 myclass2");
+    check_method_exists(e1.classList, "contains");
+    assert_true(e1.classList.contains("myclass2"), "contains method returnvalue should boolean type");
+}, "DOMTokenList_contains");
+}
+
+
+function DOMTokenList_add() {
+
+//==== TEST: DOMTokenList_add
+//==== LABEL Check if the add method in DOMTokenList is working properly
+//==== SPEC
+//==== SPEC_URL http://www.w3.org/TR/domcore/#interface-element
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME MR
+
+test(function() {
+    var e1, returnedValue;
+    e1 = document.createElement("div");
+    e1.setAttribute("class", "myclass1 myclass2");
+    check_method_exists(e1.classList, "add");
+    returnedValue = e1.classList.add("myclass3");
+    assert_equals(returnedValue, undefined, "add method should return undefined");
+    assert_true(e1.classList.contains("myclass3"), "add method is working properly");
+}, "DOMTokenList_add");
+}
+
+function DOMTokenList_remove() {
+
+//==== TEST: DOMTokenList_remove
+//==== LABEL Check if the remove method in DOMTokenList is working properly
+//==== SPEC
+//==== SPEC_URL http://www.w3.org/TR/domcore/#interface-element
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME MR
+
+test(function() {
+    var e1, returnedValue;
+    e1 = document.createElement("div");
+    e1.setAttribute("class", "myclass1 myclass2");
+    check_method_exists(e1.classList, "contains");
+    returnedValue = e1.classList.remove("myclass2");
+    assert_equals(returnedValue, undefined, "remove method should return undefined");
+    assert_false(e1.classList.contains("myclass2"), "remove method is working properly");
+}, "DOMTokenList_remove");
+}
+
+function DOMTokenList_toggle() {
+
+//==== TEST: DOMTokenList_toggle
+//==== LABEL Check if the toggle method in DOMTokenList is working properly
+//==== SPEC
+//==== SPEC_URL http://www.w3.org/TR/domcore/#interface-element
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME MR
+
+test(function() {
+    var e1 = document.createElement("div");
+    e1.setAttribute("class", "myclass1 myclass2");
+    assert_true(
+        e1.classList.toggle("myclass3") && e1.classList.contains("myclass3") &&
+        !e1.classList.toggle("myclass3") && !e1.classList.contains("myclass3"),
+    "toggle method shoud work properly");
+}, "DOMTokenList_toggle");
+}
+
+function window_Window() {
+
+//==== TEST: window_Window
+//==== LABEL Check if the window has window attribute exists
+//==== SPEC
+//==== SPEC_URL http://www.w3.org/TR/domcore/#interface-element
+//==== PRIORITY P0
+//==== TEST_CRITERIA AE AT ARO
+
+test(function() {
+    assert_true("window" in window, "window should has Window attribute");
+    assert_type(window.window, "object", "The window attribute should object type");
+    window.window = null;
+    assert_not_equals(window.window, null, "window attribute is readonly");
+}, "window_Window");
+}
+
+function window_document() {
+
+//==== TEST: window_document
+//==== LABEL Check if the window has document attribute exists
+//==== SPEC
+//==== SPEC_URL http://www.w3.org/TR/domcore/#interface-element
+//==== PRIORITY P0
+//==== TEST_CRITERIA AE AT ARO
+
+test(function() {
+    assert_true("document" in window, "document should has document attribute");
+    assert_type(window.document, "object", "The document attribute should object type");
+    window.document = null;
+    assert_not_equals(window.document, null, "document attribute is readonly");
+}, "window_document");
+}
+
+function window_innerHeight() {
+
+//==== TEST: window_innerHeight
+//==== LABEL Check if the window has innerHeight attribute exists
+//==== SPEC
+//==== SPEC_URL http://www.w3.org/TR/domcore/#interface-element
+//==== PRIORITY P0
+//==== TEST_CRITERIA AE AT ARO
+
+test(function() {
+    assert_true("innerHeight" in window, "document should has innerHeight attribute");
+    assert_type(window.innerHeight, "number", "The innerHeight attribute should object type");
+    window.innerHeight = "9%";
+    assert_not_equals(window.innerHeight, "9", "innerHeight attribute is readonly");
+}, "window_innerHeight");
+}
+
+function window_innerWidth() {
+
+//==== TEST: window_innerWidth
+//==== LABEL Check if the window has innerWidth attribute exists
+//==== SPEC
+//==== SPEC_URL http://www.w3.org/TR/domcore/#interface-element
+//==== PRIORITY P0
+//==== TEST_CRITERIA AE AT ARO
+
+test(function() {
+    assert_true("innerWidth" in window, "document should has innerWidth attribute");
+    assert_type(window.innerWidth, "number", "The innerWidth attribute should object type");
+    window.innerWidth = "9&";
+    assert_not_equals(window.innerWidth, "9", "innerWidth attribute is readonly");
+}, "window_innerWidth");
+}
+
+var moduleName = "tct-dom-w3c-tests";
+add_test_case(moduleName, NonElementParentNode_getElementById);
+add_test_case(moduleName, ChildNode_remove_extar_argument);
+add_test_case(moduleName, ChildNode_remove_exist);
+add_test_case(moduleName, NonDocumentTypeChildNode_previousElementSibling_attribute);
+add_test_case(moduleName, NonDocumentTypeChildNode_nextElementSibling_attribute);
+add_test_case(moduleName, HTMLCollection_length_attribute);
+add_test_case(moduleName, HTMLCollection_namedItem);
+add_test_case(moduleName, HTMLCollection_item);
+add_test_case(moduleName, Node_nodeName_attribute);
+add_test_case(moduleName, Node_nodeValue_attribute);
+add_test_case(moduleName, Node_textContent_attribute);
+add_test_case(moduleName, Node_parentNode_attribute);
+add_test_case(moduleName, Node_childNodes_attribute);
+add_test_case(moduleName, Node_cloneNode);
+add_test_case(moduleName, Node_isEqualNode);
+add_test_case(moduleName, Element_classList_exists);
+add_test_case(moduleName, ParentNode_exits);
+add_test_case(moduleName, ParentNode_children);
+add_test_case(moduleName, ParentNode_firstElementChild);
+add_test_case(moduleName, ParentNode_lastElementChild);
+add_test_case(moduleName, ParentNode_childElementCount);
+add_test_case(moduleName, Node_insertBefore);
+add_test_case(moduleName, Node_appendChild);
+add_test_case(moduleName, Node_replaceChild);
+add_test_case(moduleName, Node_removeChild);
+add_test_case(moduleName, Document_doctype);
+add_test_case(moduleName, Document_documentElement);
+add_test_case(moduleName, Document_contentType);
+add_test_case(moduleName, Document_characterSet);
+add_test_case(moduleName, Document_compatMode);
+add_test_case(moduleName, Document_getElementsByTagName);
+add_test_case(moduleName, Document_getElementsByClassName);
+add_test_case(moduleName, Document_createElement);
+add_test_case(moduleName, Document_createElement_exist);
+add_test_case(moduleName, Document_createTextNode);
+add_test_case(moduleName, Document_createTextNode_exist);
+add_test_case(moduleName, Document_createComment);
+add_test_case(moduleName, Document_createComment_exist);
+add_test_case(moduleName, DocumentType_name_attribute);
+add_test_case(moduleName, NodeList_length_attribute);
+add_test_case(moduleName, NodeList_item);
+add_test_case(moduleName, Element_localName);
+add_test_case(moduleName, Element_tagName);
+add_test_case(moduleName, Element_id);
+add_test_case(moduleName, Element_className);
+add_test_case(moduleName, Element_classList);
+add_test_case(moduleName, Element_attributes);
+add_test_case(moduleName, Element_getAttribute);
+add_test_case(moduleName, Element_setAttribute);
+add_test_case(moduleName, Element_removeAttribute);
+add_test_case(moduleName, Element_hasAttribute);
+add_test_case(moduleName, Element_getElementsByTagName);
+add_test_case(moduleName, Element_getElementsByClassName);
+add_test_case(moduleName, Attr_name);
+add_test_case(moduleName, Attr_value);
+add_test_case(moduleName, Attr_specified);
+add_test_case(moduleName, CharacterData_data);
+add_test_case(moduleName, CharacterData_length);
+add_test_case(moduleName, Text_wholeText);
+add_test_case(moduleName, comment_Comment);
+add_test_case(moduleName, DOMTokenList_length);
+add_test_case(moduleName, DOMTokenList_item);
+add_test_case(moduleName, DOMTokenList_contains);
+add_test_case(moduleName, DOMTokenList_add);
+add_test_case(moduleName, DOMTokenList_remove);
+add_test_case(moduleName, DOMTokenList_toggle);
+add_test_case(moduleName, window_Window);
+add_test_case(moduleName, window_innerHeight);
+add_test_case(moduleName, window_innerWidth);
diff --git a/webWidgetTCT_device/test/tct/tests/TestEvent.js b/webWidgetTCT_device/test/tct/tests/TestEvent.js
new file mode 100755 (executable)
index 0000000..cc9778b
--- /dev/null
@@ -0,0 +1,652 @@
+/*
+*
+*Copyright (c) 2016 Samsung Electronics Co., Ltd.
+*
+*Licensed under the Apache License, Version 2.0 (the License);
+*you may not use this file except in compliance with the License.
+*You may obtain a copy of the License at
+*
+*    http://www.apache.org/licenses/LICENSE-2.0
+*
+*Unless required by applicable law or agreed to in writing, software
+*distributed under the License is distributed on an "AS IS" BASIS,
+*WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*See the License for the specific language governing permissions and
+*limitations under the License.
+*
+*Authors:
+*        Zhongyuan Yuan <zy123.yuan@samsung.com>
+*
+*/
+
+var ev = new Event("");
+
+function Event_eventHandler_attribute_onload() {
+//==== TEST: Event_eventHandler_attribute_onload
+//==== LABEL Test whether the eventHandler attribute onload exists, has currect type.
+//==== SPEC Tizen webwidget:DOMEvent:onload A
+//==== SPEC_URL https://www.w3.org/TR/domcore/#interface-event
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT
+test(function () {
+    ["html", "head", "link", "meta", "style", "body", "p", "div", "span", "br", "img", "script"].forEach(function(arg) {
+        var element = document.createElement(arg);
+        assert_true("onload" in element, element +" object");
+        assert_type(element.onload, "object", element +".onload");
+    });
+}, "Event_eventHandler_attribute_onload");
+
+}
+
+function Event_eventHandler_attribute_onclick() {
+//==== TEST: Event_eventHandler_attribute_onclick
+//==== LABEL Test whether the eventHandler attribute onclick exists, has currect type.
+//==== SPEC Tizen webwidget:DOMEvent:onload A
+//==== SPEC_URL https://www.w3.org/TR/domcore/#interface-event
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT
+test(function () {
+    ["html", "head", "link", "meta", "style", "body", "p", "div", "span", "br", "img", "script"].forEach(function(arg) {
+        var element = document.createElement(arg);
+        assert_true("onclick" in element, element +" object");
+        assert_type(element.onclick, "object", element +".onload");
+    });
+}, "Event_eventHandler_attribute_onclick");
+
+}
+
+
+function Event_constants_NONE() {
+//==== TEST: Event_constants_NONE
+//==== LABEL Test whether the constants NONE of DOM event is correct.
+//==== SPEC Tizen webwidget:DOMEvent:Constant A
+//==== SPEC_URL https://www.w3.org/TR/domcore/#interface-event
+//==== PRIORITY P1
+//==== TEST_CRITERIA CONSTE CONSTT CONSTV CONSTRO
+test(function () {
+    check_const(ev, "NONE", 0, "number", 100);
+}, "Event_constants_NONE");
+
+}
+
+function Event_constants_NONE() {
+//==== TEST: Event_constants_NONE
+//==== LABEL Test whether the constants NONE of DOM event is correct.
+//==== SPEC Tizen webwidget:DOMEvent:Constant A
+//==== SPEC_URL https://www.w3.org/TR/domcore/#interface-event
+//==== PRIORITY P1
+//==== TEST_CRITERIA CONSTE CONSTT CONSTV CONSTRO
+test(function () {
+    check_const(ev, "NONE", 0, "number", 100);
+}, "Event_constants_NONE");
+
+}
+
+function Event_constants_CAPTURING_PHASE() {
+//==== TEST: Event_constants_CAPTURING_PHASE
+//==== LABEL Test whether the constants CAPTURING_PHASE of DOM event is correct.
+//==== SPEC Tizen webwidget:DOMEvent:Constant A
+//==== SPEC_URL https://www.w3.org/TR/domcore/#interface-event
+//==== PRIORITY P1
+//==== TEST_CRITERIA CONSTE CONSTT CONSTV CONSTRO
+test(function () {
+    check_const(ev, "CAPTURING_PHASE", 1, "number", 100);
+}, "Event_constants_CAPTURING_PHASE");
+
+}
+
+function Event_constants_AT_TARGET() {
+//==== TEST: Event_constants_AT_TARGET
+//==== LABEL Test whether the constants AT_TARGET of DOM event is correct.
+//==== SPEC Tizen webwidget:DOMEvent:Constant:AT_TARGET A
+//==== SPEC_URL https://www.w3.org/TR/domcore/#interface-event
+//==== PRIORITY P1
+//==== TEST_CRITERIA CONSTE CONSTT CONSTV CONSTRO
+test(function () {
+    check_const(ev, "AT_TARGET", 2, "number", 100);
+}, "Event_constants_AT_TARGET");
+
+}
+
+function Event_constants_BUBBLING_PHASE() {
+//==== TEST: Event_constants_BUBBLING_PHASE
+//==== LABEL Test whether the constants BUBBLING_PHASE of DOM event is correct.
+//==== SPEC Tizen webwidget:DOMEvent:Constant:BUBBLING_PHASE A
+//==== SPEC_URL https://www.w3.org/TR/domcore/#interface-event
+//==== PRIORITY P1
+//==== TEST_CRITERIA CONSTE CONSTT CONSTV CONSTRO
+test(function () {
+    check_const(ev, "BUBBLING_PHASE", 3, "number", 100);
+}, "Event_constants_BUBBLING_PHASE");
+
+}
+
+function Event_event_exist() {
+//==== TEST: Event_event_exist
+//==== LABEL Test whether the event construct exist.
+//==== SPEC Tizen webwidget:DOMEvent:Event:constructor C
+//==== SPEC_URL https://www.w3.org/TR/domcore/#interface-event
+//==== PRIORITY P1
+//==== TEST_CRITERIA CONSTRF
+test(function () {
+    assert_true(typeof Event == "function", "event constructor not exist");
+}, "Event_event_exist");
+
+}
+
+function Event_event_extend() {
+//==== TEST: Event_event_extend
+//==== LABEL Test whether the event object is extendable.
+//==== SPEC Tizen webwidget:DOMEvent:Event U
+//==== SPEC_URL https://www.w3.org/TR/domcore/#interface-event
+//==== PRIORITY P3
+//==== TEST_CRITERIA OBX
+test(function () {
+    check_extensibility(ev);
+}, "Event_event_extend");
+
+}
+
+function Event_event_constructor() {
+//==== TEST: Event_event_constructor
+//==== LABEL Check various arguments for Event() constructor.
+//==== SPEC Tizen webwidget:DOMEvent:Event:constructor C
+//==== SPEC_URL https://www.w3.org/TR/domcore/#interface-event
+//==== PRIORITY P1
+//==== TEST_CRITERIA CONSTRA CONSTRM
+test(function () {
+    var eventInit = { bubbles: true, cancelable: true};
+    ev1 = new Event("foo", eventInit);
+    assert_type(ev1.type, "string", "Incorrect type of type.");
+    assert_equals(ev1.type, "foo", "Incorrect value of type");
+    assert_type(ev1.bubbles, "boolean", "Incorrect type of bubbles.");
+    assert_equals(ev1.bubbles, true, "Incorrect value of bubbles");
+    assert_type(ev1.cancelable, "boolean", "Incorrect type of cancelable.");
+    assert_equals(ev1.cancelable, true, "Incorrect value of cancelable");
+}, "Event_event_constructor");
+
+}
+
+function Event_attribute_bubbles() {
+//==== TEST: Event_attribute_bubbles
+//==== LABEL Test whether the attribute bubbles of DOM event exists, has currect type and is readonly
+//==== SPEC Tizen webwidget:DOMEvent:bubbles A
+//==== SPEC_URL https://www.w3.org/TR/domcore/#interface-event
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE, AT, ARO
+test(function () {
+    check_readonly(ev, "bubbles", ev.bubbles, "boolean", !ev.bubbles);
+}, "Event_attribute_bubbles");
+
+}
+
+function Event_attribute_cancelable() {
+//==== TEST: Event_attribute_cancelable
+//==== LABEL Test whether the attribute cancelable of DOM event exists, has currect type and is readonly
+//==== SPEC Tizen webwidget:DOMEvent:cancelable A
+//==== SPEC_URL https://www.w3.org/TR/domcore/#interface-event
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE, AT, ARO
+test(function () {
+    check_readonly(ev, "cancelable", ev.cancelable, "boolean", !ev.cancelable);
+}, "Event_attribute_cancelable");
+
+}
+
+function Event_attribute_currentTarget() {
+//==== TEST: Event_attribute_currentTarget
+//==== LABEL Test whether the attribute currentTarget of DOM event exists, has currect type and is readonly
+//==== SPEC Tizen webwidget:DOMEvent:currentTarget A
+//==== SPEC_URL https://www.w3.org/TR/domcore/#interface-event
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE, AT, ARO
+test(function () {
+    check_readonly(ev, "currentTarget", ev.currentTarget, "object", {});
+}, "Event_attribute_currentTarget");
+
+}
+
+function Event_attribute_eventPhase() {
+//==== TEST: Event_attribute_eventPhase
+//==== LABEL Test whether the attribute eventPhase of DOM event exists, has currect type and is readonly
+//==== SPEC Tizen webwidget:DOMEvent:eventPhase A
+//==== SPEC_URL https://www.w3.org/TR/domcore/#interface-event
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE, AT, ARO
+test(function () {
+    check_readonly(ev, "eventPhase", ev.eventPhase, "number", 100);
+}, "Event_attribute_eventPhase");
+
+}
+
+function Event_attribute_target() {
+//==== TEST: Event_attribute_target
+//==== LABEL Test whether the attribute target of DOM event exists, has currect type and is readonly
+//==== SPEC Tizen webwidget:DOMEvent:target A
+//==== SPEC_URL https://www.w3.org/TR/domcore/#interface-event
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE, AT, ARO
+test(function () {
+    check_readonly(ev, "target", ev.target, "object", {});
+}, "Event_attribute_target");
+
+}
+
+function Event_attribute_timeStamp() {
+//==== TEST: Event_attribute_timeStamp
+//==== LABEL Test whether the attribute timeStamp of DOM event exists, has currect type and is readonly
+//==== SPEC Tizen webwidget:DOMEvent:timeStamp A
+//==== SPEC_URL https://www.w3.org/TR/domcore/#interface-event
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE, AT, ARO
+test(function () {
+    check_readonly(ev, "timeStamp", ev.timeStamp, "number", 1);
+}, "Event_attribute_timeStamp");
+
+}
+
+function Event_attribute_type() {
+//==== TEST: Event_attribute_type
+//==== LABEL Test whether the attribute type of DOM event exists, has currect type and is readonly
+//==== SPEC Tizen webwidget:DOMEvent:type A
+//==== SPEC_URL https://www.w3.org/TR/domcore/#interface-event
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE, AT, ARO
+test(function () {
+    check_readonly(ev, "type", ev.type, "string", "a");
+}, "Event_attribute_type");
+
+}
+
+function Event_attribute_defaultPrevented() {
+//==== TEST: Event_attribute_defaultPrevented
+//==== LABEL Test whether the attribute defaultPrevented of DOM event exists, has currect type and is readonly
+//==== SPEC Tizen webwidget:DOMEvent:defaultPrevented A
+//==== SPEC_URL https://www.w3.org/TR/domcore/#interface-event
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE, AT, ARO
+test(function () {
+    check_readonly(ev, "defaultPrevented", ev.defaultPrevented, "boolean", !ev.defaultPrevented);
+}, "Event_attribute_defaultPrevented");
+
+}
+
+function Event_method_preventDefault_exist() {
+//==== TEST: Event_method_preventDefault_exist
+//==== LABEL Test whether the method preventDefault of DOM event exists.
+//==== SPEC Tizen webwidget:DOMEvent:preventDefault M
+//==== SPEC_URL https://www.w3.org/TR/domcore/#interface-event
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+test(function () {
+    check_method_exists(ev, "preventDefault");
+}, "Event_method_preventDefault_exist");
+
+}
+
+function Event_method_preventDefault() {
+//==== TEST: Event_method_preventDefault
+//==== LABEL Test whether the method preventDefault works properly and has correct return value.
+//==== SPEC Tizen webwidget:DOMEvent:preventDefault M
+//==== SPEC_URL https://www.w3.org/TR/domcore/#interface-event
+//==== PRIORITY P1
+//==== TEST_CRITERIA MNAST MR
+test(function () {
+    var eventInit = { bubbles: true, cancelable: true};
+    var ev1 = new Event("foo", eventInit);
+    var retVal = ev1.preventDefault();
+    assert_equals(ev1.defaultPrevented, true, "Incorrect returned value");
+    assert_equals(retVal, undefined, "Incorrect returned value");
+}, "Event_method_preventDefault");
+
+}
+
+function Event_method_preventDefault_extra_argument() {
+//==== TEST: Event_method_preventDefault_extra_argument
+//==== LABEL Check using preventDefault method with extra argument.
+//==== SPEC Tizen webwidget:DOMEvent:preventDefault M
+//==== SPEC_URL https://www.w3.org/TR/domcore/#interface-event
+//==== PRIORITY P1
+//==== TEST_CRITERIA MNAEX
+test(function () {
+    checkExtraArgument(ev, "preventDefault");
+}, "Event_method_preventDefault_extra_argument");
+
+}
+
+function Event_method_stopPropagation_exist() {
+//==== TEST: Event_method_stopPropagation_exist
+//==== LABEL Test whether the method stopPropagation of DOM event exists.
+//==== SPEC Tizen webwidget:DOMEvent:stopPropagation M
+//==== SPEC_URL https://www.w3.org/TR/domcore/#interface-event
+//==== PRIORITY P1
+//==== TEST_CRITERIA ME MR
+test(function () {
+    var retVal = ev.stopPropagation();
+    check_method_exists(ev, "stopPropagation");
+    assert_equals(retVal, undefined, "Incorrect returned value");
+}, "Event_method_stopPropagation_exist");
+
+}
+
+function Event_method_stopPropagation_extra_argument() {
+//==== TEST: Event_method_stopPropagation_extra_argument
+//==== LABEL Check using stopPropagation method with extra argument.
+//==== SPEC Tizen webwidget:DOMEvent:stopPropagation M
+//==== SPEC_URL https://www.w3.org/TR/domcore/#interface-event
+//==== PRIORITY P1
+//==== TEST_CRITERIA MNAEX
+test(function () {
+    checkExtraArgument(ev, "stopPropagation");
+}, "Event_method_stopPropagation_extra_argument");
+
+}
+
+function Event_method_stopImmediatePropagation_exist() {
+//==== TEST: Event_method_stopImmediatePropagation_exist
+//==== LABEL Test whether the method stopImmediatePropagation of DOM event exists.
+//==== SPEC Tizen webwidget:DOMEvent:stopImmediatePropagation M
+//==== SPEC_URL https://www.w3.org/TR/domcore/#interface-event
+//==== PRIORITY P1
+//==== TEST_CRITERIA ME MR
+test(function () {
+    var retVal = ev.stopImmediatePropagation();
+    check_method_exists(ev, "stopImmediatePropagation");
+    assert_equals(retVal, undefined, "Incorrect returned value");
+}, "Event_method_stopImmediatePropagation_exist");
+
+}
+
+function Event_method_stopImmediatePropagation_extra_argument() {
+//==== TEST: Event_method_stopImmediatePropagation_extra_argument
+//==== LABEL Check using stopImmediatePropagation method with extra argument.
+//==== SPEC Tizen webwidget:DOMEvent:stopImmediatePropagation M
+//==== SPEC_URL https://www.w3.org/TR/domcore/#interface-event
+//==== PRIORITY P1
+//==== TEST_CRITERIA MNAEX
+test(function () {
+    checkExtraArgument(ev, "stopImmediatePropagation");
+}, "Event_method_stopImmediatePropagation_extra_argument");
+
+}
+
+function EventTarget_addEventListener_exist() {
+//==== TEST: EventTarget_addEventListener_exist
+//==== LABEL Test whether the method addEventListener exists
+//==== SPEC Tizen webwidget:DOMEvent:EventTarget:addEventListener M
+//==== SPEC_URL https://www.w3.org/TR/domcore/#interface-event
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+test(function () {
+    check_method_exists(document, "addEventListener");
+}, "EventTarget_addEventListener_exist");
+
+}
+
+function EventTarget_addEventListener() {
+//==== TEST: EventTarget_addEventListener
+//==== LABEL Test whether the method addEventListener works properly and return value is correct
+//==== SPEC Tizen webwidget:DOMEvent:EventTarget:addEventListener M
+//==== SPEC_URL https://www.w3.org/TR/domcore/#interface-event
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR MNA
+test(function () {
+    assert_equals(document.addEventListener("x", null, false), undefined);
+    assert_equals(document.addEventListener("x", null, true), undefined);
+    assert_equals(document.addEventListener("x", null), undefined);
+}, "EventTarget_addEventListener");
+
+}
+
+function EventTarget_addEventListener_misarg() {
+//==== TEST: EventTarget_addEventListener_misarg
+//==== LABEL Test whether the method addEventListener throws exception when argument is missing
+//==== SPEC Tizen webwidget:DOMEvent:EventTarget:addEventListener M
+//==== SPEC_URL https://www.w3.org/TR/domcore/#interface-event
+//==== PRIORITY P2
+//==== TEST_CRITERIA MMA
+test(function () {
+    try{
+        document.addEventListener();
+        assert_unreached("Not throw exception");
+    }catch(e){
+    }
+}, "EventTarget_addEventListener_misarg");
+
+}
+
+function EventTarget_removeEventListener_exist() {
+//==== TEST: EventTarget_removeEventListener_exist
+//==== LABEL Test whether the method removeEventListener exists
+//==== SPEC Tizen webwidget:DOMEvent:EventTarget:removeEventListener M
+//==== SPEC_URL https://www.w3.org/TR/domcore/#interface-event
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+test(function () {
+    check_method_exists(document, "removeEventListener");
+}, "EventTarget_removeEventListener_exist");
+
+}
+
+function EventTarget_removeEventListener() {
+//==== TEST: EventTarget_removeEventListener
+//==== LABEL Test whether the method removeEventListener works properly and return value is correct
+//==== SPEC Tizen webwidget:DOMEvent:EventTarget:removeEventListener M
+//==== SPEC_URL https://www.w3.org/TR/domcore/#interface-event
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR MNA
+test(function () {
+    assert_equals(document.removeEventListener("x", null, false), undefined);
+    assert_equals(document.removeEventListener("x", null, true), undefined);
+    assert_equals(document.removeEventListener("x", null), undefined);
+}, "EventTarget_removeEventListener");
+
+}
+
+function EventTarget_removeEventListener_misarg() {
+//==== TEST: EventTarget_removeEventListener_misarg
+//==== LABEL Test whether the method removeEventListener throws exception when argument is missing
+//==== SPEC Tizen webwidget:DOMEvent:EventTarget:removeEventListener M
+//==== SPEC_URL https://www.w3.org/TR/domcore/#interface-event
+//==== PRIORITY P2
+//==== TEST_CRITERIA MMA
+test(function () {
+    try{
+        document.removeEventListener();
+        assert_unreached("Not throw exception");
+    }catch(e){
+    }
+}, "EventTarget_removeEventListener_misarg");
+
+}
+
+function EventTarget_dispatchEvent_exist() {
+//==== TEST: EventTarget_dispatchEvent_exist
+//==== LABEL Test whether the method dispatchEvent exists
+//==== SPEC Tizen webwidget:DOMEvent:EventTarget:dispatchEvent M
+//==== SPEC_URL https://www.w3.org/TR/domcore/#interface-event
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+test(function () {
+    check_method_exists(document, "dispatchEvent");
+}, "EventTarget_dispatchEvent_exist");
+
+}
+
+function EventTarget_dispatchEvent_misarg() {
+//==== TEST: EventTarget_dispatchEvent_misarg
+//==== LABEL Test whether the method dispatchEvent throws exception when argument is missing
+//==== SPEC Tizen webwidget:DOMEvent:EventTarget:dispatchEvent M
+//==== SPEC_URL https://www.w3.org/TR/domcore/#interface-event
+//==== PRIORITY P2
+//==== TEST_CRITERIA MMA
+test(function () {
+    try{
+        document.dispatchEvent();
+        assert_unreached("Not throw exception");
+    }catch(e){
+    }
+}, "EventTarget_dispatchEvent_misarg");
+
+}
+
+function EventTarget_dispatchEvent() {
+//==== TEST: EventTarget_dispatchEvent
+//==== LABEL Test whether the method dispatchEvent works properly and return value is correct
+//==== SPEC Tizen webwidget:DOMEvent:EventTarget:dispatchEvent M
+//==== SPEC_URL https://www.w3.org/TR/domcore/#interface-event
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR MAST
+
+var t = async_test("EventTarget_dispatchEvent", {timeout: 90000}), results, outerb, middleb, innerb, retVal;
+
+t.step(function () {
+    results = [];
+    outerb = document.createElement("p");
+    middleb = outerb.appendChild(document.createElement("p"));
+    innerb = middleb.appendChild(document.createElement("p"));
+    outerb.addEventListener("x", t.step_func(function() {
+        middleb.addEventListener("x", t.step_func(function() {
+            results.push("middle")
+        }), true)
+        results.push("outer")
+    }), true);
+    retVal = innerb.dispatchEvent(new Event("x"));
+    assert_equals(retVal, true, "invalid return value");
+    assert_array_equals(results, ["outer", "middle"]);
+    t.done();
+});
+
+}
+
+function ProgressEvent_exist() {
+//==== TEST: ProgressEvent_exist
+//==== LABEL Test whether the ProgressEvent construct exist.
+//==== SPEC Tizen webwidget:DOMEvent:ProgressEvent:constructor C
+//==== SPEC_URL https://www.w3.org/TR/domcore/#interface-event
+//==== PRIORITY P1
+//==== TEST_CRITERIA CONSTRF
+test(function () {
+    assert_true(typeof ProgressEvent == "function", "ProgressEvent constructor not exist");
+}, "ProgressEvent_exist");
+
+}
+
+function ProgressEvent_extend() {
+//==== TEST: ProgressEvent_extend
+//==== LABEL Test whether the ProgressEvent object is extendable.
+//==== SPEC Tizen webwidget:DOMEvent:ProgressEvent U
+//==== SPEC_URL https://www.w3.org/TR/domcore/#interface-event
+//==== PRIORITY P3
+//==== TEST_CRITERIA OBX
+test(function () {
+    var proEv = new ProgressEvent("");
+    check_extensibility(proEv);
+}, "ProgressEvent_extend");
+
+}
+
+function ProgressEvent_constructor() {
+//==== TEST: ProgressEvent_constructor
+//==== LABEL Check various arguments for ProgressEvent() constructor.
+//==== SPEC Tizen webwidget:DOMEvent:Event:ProgressEvent C
+//==== SPEC_URL https://www.w3.org/TR/domcore/#interface-event
+//==== PRIORITY P1
+//==== TEST_CRITERIA CONSTRA CONSTRM
+test(function () {
+    var progressEventInit = { lengthComputable: true, loaded: 1, total: 1 };
+    ev1 = new ProgressEvent("foo", progressEventInit);
+    assert_type(ev1.type, "string", "Incorrect type of type");
+    assert_equals(ev1.type, "foo", "Incorrect value of type");
+    assert_type(ev1.lengthComputable, "boolean", "Incorrect type of lengthComputable");
+    assert_equals(ev1.lengthComputable, true, "Incorrect value of lengthComputable");
+    assert_type(ev1.loaded, "number", "Incorrect type of loaded");
+    assert_equals(ev1.loaded, 1, "Incorrect value of loaded");
+    assert_type(ev1.total, "number", "Incorrect type of total");
+    assert_equals(ev1.total, 1, "Incorrect value of total");
+}, "ProgressEvent_constructor");
+
+}
+
+function ProgressEvent_attribute_lengthComputable() {
+//==== TEST: ProgressEvent_attribute_lengthComputable
+//==== LABEL Test whether the attribute lengthComputable of ProgressEvent exists, has currect type and is readonly
+//==== SPEC Tizen webwidget:DOMEvent:ProgressEvent:lengthComputable A
+//==== SPEC_URL https://www.w3.org/TR/domcore/#interface-event
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE, AT, ARO
+test(function () {
+    var proEv = new ProgressEvent("");
+    check_readonly(proEv, "lengthComputable", proEv.lengthComputable, "boolean", !proEv.lengthComputable);
+}, "ProgressEvent_attribute_lengthComputable");
+
+}
+
+function ProgressEvent_attribute_loaded() {
+//==== TEST: ProgressEvent_attribute_loaded
+//==== LABEL Test whether the attribute loaded of ProgressEvent exists, has currect type and is readonly
+//==== SPEC Tizen webwidget:DOMEvent:ProgressEvent:loaded A
+//==== SPEC_URL https://www.w3.org/TR/domcore/#interface-event
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE, AT, ARO
+test(function () {
+    var proEv = new ProgressEvent("");
+    check_readonly(proEv, "loaded", proEv.loaded, "number", !proEv.loaded);
+}, "ProgressEvent_attribute_loaded");
+
+}
+
+function ProgressEvent_attribute_total() {
+//==== TEST: ProgressEvent_attribute_total
+//==== LABEL Test whether the attribute total of ProgressEvent exists, has currect type and is readonly
+//==== SPEC Tizen webwidget:DOMEvent:ProgressEvent:total A
+//==== SPEC_URL https://www.w3.org/TR/domcore/#interface-event
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE, AT, ARO
+test(function () {
+    var proEv = new ProgressEvent("");
+    check_readonly(proEv, "total", proEv.total, "number", !proEv.total);
+}, "ProgressEvent_attribute_total");
+
+}
+
+var moduleName = "tct-event-w3c-tests";
+add_test_case(moduleName, Event_eventHandler_attribute_onload);
+add_test_case(moduleName, Event_eventHandler_attribute_onclick);
+add_test_case(moduleName, Event_constants_NONE);
+add_test_case(moduleName, Event_constants_CAPTURING_PHASE);
+add_test_case(moduleName, Event_constants_AT_TARGET);
+add_test_case(moduleName, Event_constants_BUBBLING_PHASE);
+add_test_case(moduleName, Event_event_exist);
+add_test_case(moduleName, Event_event_extend);
+add_test_case(moduleName, Event_event_constructor);
+add_test_case(moduleName, Event_attribute_bubbles);
+add_test_case(moduleName, Event_attribute_cancelable);
+add_test_case(moduleName, Event_attribute_currentTarget);
+add_test_case(moduleName, Event_attribute_eventPhase);
+add_test_case(moduleName, Event_attribute_target);
+add_test_case(moduleName, Event_attribute_timeStamp);
+add_test_case(moduleName, Event_attribute_type);
+add_test_case(moduleName, Event_attribute_defaultPrevented);
+add_test_case(moduleName, Event_method_preventDefault);
+add_test_case(moduleName, Event_method_preventDefault_exist);
+add_test_case(moduleName, Event_method_preventDefault_extra_argument);
+add_test_case(moduleName, Event_method_stopPropagation_exist);
+add_test_case(moduleName, Event_method_stopPropagation_extra_argument);
+add_test_case(moduleName, Event_method_stopImmediatePropagation_exist);
+add_test_case(moduleName, Event_method_stopImmediatePropagation_extra_argument);
+add_test_case(moduleName, EventTarget_addEventListener_exist);
+add_test_case(moduleName, EventTarget_addEventListener_misarg);
+add_test_case(moduleName, EventTarget_addEventListener);
+add_test_case(moduleName, EventTarget_removeEventListener_exist);
+add_test_case(moduleName, EventTarget_removeEventListener_misarg);
+add_test_case(moduleName, EventTarget_removeEventListener);
+add_test_case(moduleName, EventTarget_dispatchEvent_exist);
+add_test_case(moduleName, EventTarget_dispatchEvent_misarg);
+add_test_case(moduleName, EventTarget_dispatchEvent);
+add_test_case(moduleName, ProgressEvent_exist);
+add_test_case(moduleName, ProgressEvent_extend);
+add_test_case(moduleName, ProgressEvent_constructor);
+add_test_case(moduleName, ProgressEvent_attribute_lengthComputable);
+add_test_case(moduleName, ProgressEvent_attribute_loaded);
+add_test_case(moduleName, ProgressEvent_attribute_total);
diff --git a/webWidgetTCT_device/test/tct/tests/TestFilesystem.js b/webWidgetTCT_device/test/tct/tests/TestFilesystem.js
new file mode 100755 (executable)
index 0000000..34d9b18
--- /dev/null
@@ -0,0 +1,10722 @@
+/*
+
+Copyright (c) 2013 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+
+
+Authors:
+
+
+
+*/
+
+var TEST_ROOT_LOCATION = "downloads";
+
+var FILE_AND_DIR_NAME_PREFIX = "tizen_WebAPI_test_";
+var UNKNOWN_ERR              = "UnknownError";
+var TYPE_MISMATCH_ERR        = "TypeMismatchError";
+var IO_ERR                   = "IOError";
+var INVALID_VALUES_ERR       = "InvalidValuesError";
+var SECURITY_ERR             = "SecurityError";
+var NOT_FOUND_ERR            = "NotFoundError";
+
+var globalCounter = 1;
+
+function isFileObject(obj) {
+    return true;
+}
+
+function isFile(obj) {
+    return (isFileObject(obj) && !obj.isDirectory);
+}
+
+function isDir(obj) {
+    return (isFileObject(obj) && obj.isDirectory);
+}
+
+function isFilestream(obj) {
+    return true;
+}
+
+function deleteDirectory(parent, dir) {
+    function onError(err) {
+        assert_false("deleteDirectory() [" + err.name + "]", "directory wasn't deleted");
+    }
+
+    function onSuccess() {
+    }
+    parent.deleteDirectory(dir.fullPath, true, onSuccess, onError);
+}
+
+function deleteFile(parent, file) {
+    function onError(err) {
+        assert_false("deleteFile [" + err.name + "]", "file wasn't deleted");
+    }
+
+    function onSuccess() {
+    }
+    parent.deleteFile(file.fullPath, onSuccess, onError);
+}
+
+function resolve_root_location(handler) {
+    function on_resolve_error(err) {
+        assert_false("resolve error: [" + err.name + "]", "error during resolving the root location");
+    }
+
+    function on_resolve_success(file) {
+        assert_true(isFileObject(file), "resolve()");
+        handler(file);
+    }
+    tizen.filesystem.resolve(TEST_ROOT_LOCATION, on_resolve_success, on_resolve_error);
+}
+
+function getFileName(fileName) {
+    return FILE_AND_DIR_NAME_PREFIX + "_" + fileName;
+}
+
+function getDirName(dirName) {
+    return FILE_AND_DIR_NAME_PREFIX + "_" + dirName;
+}
+
+function createFileForParent(parent) {
+    var result = parent.createFile(getFileName());
+    assert_true(isFile(result), "createFile");
+    return result;
+}
+
+function createDirForParent(parent) {
+    var result = parent.createDirectory(getDirName());
+    assert_true(isDir(result), "createDirectory()");
+    return result;
+}
+
+function deleteFileAndDone(test, file) {
+    if(file === undefined) {
+        throw new Error("deleteFileAndDone: file is undefined");
+    }
+    if(file.parent === null){
+        throw new Error("deleteFileAndDone: parent directory is null");
+    }
+    file.parent.deleteFile(file.fullPath,
+        test.step_func(function() {
+            test.done();
+        }),
+        test.step_func(function(err) {
+            assert_unreached("deleteFileAndDone: delete onError " + err.message);
+        }));
+}
+
+function prepareForTesting(test, successCallback) {
+    var i, j, toRemoveCounter = 0, dirCounter = 0, deleteSuccess, deleteError,
+        resolveSuccess, resolveError, listFilesSuccess, listFilesError,
+        filterRegExp = new RegExp("^" + FILE_AND_DIR_NAME_PREFIX),
+        rootDirectories = ["documents", "images", "music", "videos", "downloads"];
+
+    deleteError = test.step_func(function (error) {
+        assert_unreached("delete() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    deleteSuccess = test.step_func(function () {
+        if (--toRemoveCounter === 0) {
+            test.step_func(successCallback)();
+        }
+    });
+
+    listFilesSuccess = test.step_func(function (files) {
+        dirCounter++;
+        for (j = 0; j < files.length; j++) {
+            if (files[j].name.search(filterRegExp) > -1) {
+                toRemoveCounter++;
+                if (files[j].isDirectory) {
+                    files[j].parent.deleteDirectory(files[j].fullPath, true, deleteSuccess, deleteError);
+                } else {
+                    files[j].parent.deleteFile(files[j].fullPath, deleteSuccess, deleteError);
+                }
+            }
+        }
+        if ((dirCounter === rootDirectories.length) && (toRemoveCounter === 0)) {
+            test.step_func(successCallback)();
+        }
+    });
+
+    listFilesError = test.step_func(function (error) {
+        assert_unreached("listFiles() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    resolveSuccess = test.step_func(function (dir) {
+        dir.listFiles(listFilesSuccess, listFilesError);
+    });
+
+    resolveError = test.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    for (i =0; i < rootDirectories.length; i++) {
+        tizen.filesystem.resolve(rootDirectories[i], resolveSuccess, resolveError, "rw");
+    }
+}
+
+function checkOwnProperties(fileHandle) {
+    var i, len, fileProperties = ["parent", "readOnly", "isFile", "isDirectory", "created", "modified", "path",
+                                  "name", "fullPath", "fileSize", "length"];
+    for (i = 0, len = fileProperties.length; i < len; i++) {
+        assert_own_property(fileHandle, fileProperties[i], "object does not have its own " + fileProperties[i] + " property");
+    }
+}
+
+function FileArraySuccessCallback_notexist() {
+//==== TEST: FileArraySuccessCallback_notexist
+//==== LABEL Interface FileArraySuccessCallback should not be accessible
+//==== PRIORITY: P3
+//==== SPEC Tizen Web API:IO:Filesystem:FileArraySuccessCallback:FileArraySuccessCallback U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA CBNIO
+test(function () {
+    check_no_interface_object("FileArraySuccessCallback");
+}, 'FileArraySuccessCallback_notexist');
+
+}
+
+function FileArraySuccessCallback_onsuccess() {
+
+//==== TEST: FileArraySuccessCallback_onsuccess
+//==== LABEL Test whether FileArraySuccessCallback::onsuccess is called with valid argument
+//==== PRIORITY: P1
+//==== SPEC Tizen Web API:IO:Filesystem:FileArraySuccessCallback:onsuccess M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA CBOA CBT
+
+var t = async_test('FileArraySuccessCallback_onsuccess'),
+    resolveSuccess, resolveError, listSuccess, i, fsTestFileName, foundValue = false;
+
+t.step(function () {
+    fsTestFileName = getFileName("filesystem");
+
+    listSuccess = t.step_func(function (files) {
+        assert_type(files, "array", "incorrect received value");
+        assert_greater_than(files.length, 0, "incorrect received array");
+        for (i = 0; i < files.length; i++) {
+            assert_type(files[i], "object", "incorrect received array element");
+            checkOwnProperties(files[i]);
+            if ((files[i].name === fsTestFileName) && (files[i].isFile === true)) {
+                foundValue = true;
+            }
+        }
+        assert_true(foundValue, "new file not found");
+        t.done();
+    });
+    resolveSuccess = t.step_func(function (dir) {
+        dir.createFile(fsTestFileName);
+        dir.listFiles(listSuccess);
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function FileStreamSuccessCallback_notexist() {
+//==== TEST: FileStreamSuccessCallback_notexist
+//==== LABEL Interface FileStreamSuccessCallback should not be accessible
+//==== PRIORITY: P3
+//==== SPEC Tizen Web API:IO:Filesystem:FileStreamSuccessCallback:FileStreamSuccessCallback U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA CBNIO
+test(function () {
+    check_no_interface_object("FileStreamSuccessCallback");
+}, 'FileStreamSuccessCallback_notexist');
+
+}
+
+function FileStreamSuccessCallback_onsuccess() {
+//==== TEST: FileStreamSuccessCallback_onsuccess
+//==== LABEL Test whether FileStreamSuccessCallback::onsuccess is called with argument of proper type
+//==== PRIORITY: P1
+//==== SPEC Tizen Web API:IO:Filesystem:FileStreamSuccessCallback:onsuccess M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA CBOA CBT
+var t = async_test('FileStreamSuccessCallback_onsuccess'),
+    resolveSuccess, resolveError, file, openStreamSuccess,
+    fsTestFileName = getFileName("filesystem.txt");
+
+t.step(function () {
+    openStreamSuccess = t.step_func(function (fs) {
+        assert_type(fs, "object", "fs isn't an object");
+        assert_own_property(fs, "eof", "fs doesn't have eof property");
+        assert_own_property(fs, "position", "fs doesn't have eof property");
+        assert_own_property(fs, "bytesAvailable", "fs doesn't have eof property");
+        fs.close();
+        t.done();
+    });
+    resolveSuccess = t.step_func(function (dir) {
+        file = dir.createFile(fsTestFileName);
+        file.openStream("r", openStreamSuccess);
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t,
+        function () {
+            tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+        }
+    );
+});
+
+}
+
+function FileStream_bytesAvailable_attribute() {
+//==== TEST: FileStream_bytesAvailable_attribute
+//==== PRIORITY P1
+//==== LABEL Check if FileStream::bytesAvailable attribute exist, is of proper type
+//==== SPEC Tizen Web API:IO:Filesystem:FileStream:bytesAvailable A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA AE ARO AT
+var t = async_test('FileStream_bytesAvailable_attribute'),
+    resolveSuccess, resolveError, openStreamSuccess, openStreamError, file,
+    testStr = "1234", fsTestFileName = getFileName("existFile01.txt");
+
+t.step(function () {
+    openStreamSuccess = t.step_func(function (fs) {
+        fs.write(testStr);
+        fs.position = 0;
+        assert_true("bytesAvailable" in fs, "bytesAvailable doesn't exist");
+        check_readonly(fs, "bytesAvailable", fs.bytesAvailable, "long", fs.bytesAvailable + 2);
+        fs.close();
+        t.done();
+    });
+    openStreamError = t.step_func(function (error) {
+        assert_unreached("openStream() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        file = dir.createFile(fsTestFileName);
+        file.openStream("rw", openStreamSuccess, openStreamError);
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t,
+        function () {
+            tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+        }
+    );
+});
+
+}
+
+function FileStream_close() {
+//==== TEST: FileStream_close
+//==== PRIORITY P2
+//==== LABEL Check if FileStream::close() method works
+//==== SPEC Tizen Web API:IO:Filesystem:FileStream:close M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MNA MR MNAST
+var t = async_test('FileStream_close'),
+    fsTestFileName = getFileName("closeFile.txt"), retVal = null,
+    resolveSuccess, resolveError, openStreamSuccess, openStreamError, file;
+
+t.step(function () {
+    openStreamSuccess = t.step_func(function (fs) {
+        fs.write("abcdefg");
+        retVal = fs.close();
+        assert_equals(retVal, undefined, "incorrect returned value close()");
+        assert_throws(IO_EXCEPTION, function () {
+                fs.read(2);
+            });
+        t.done();
+    });
+    openStreamError = t.step_func(function (error) {
+        assert_unreached("openStream() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        file = dir.createFile(fsTestFileName);
+        file.openStream("rw", openStreamSuccess, openStreamError);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t,
+        function () {
+            tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+        }
+    );
+});
+
+}
+
+function FileStream_close_exist() {
+//==== TEST: FileStream_close_exist
+//==== LABEL Check if FileStream::close() method exists
+//==== PRIORITY P0
+//==== SPEC Tizen Web API:IO:Filesystem:FileStream:close M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA ME
+var t = async_test('FileStream_close_exist'),
+    fsTestFileName = getFileName("existFile04.txt"),
+    resolveSuccess, resolveError, openStreamSuccess, openStreamError, file;
+
+t.step(function (){
+
+    openStreamSuccess = t.step_func(function (fs) {
+        assert_true("close" in fs, "No close method in FileStream");
+        check_method_exists(fs, "close");
+        fs.close();
+        t.done();
+    });
+    openStreamError = t.step_func(function (error) {
+        assert_unreached("openStream() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        file = dir.createFile(fsTestFileName);
+        file.openStream("rw", openStreamSuccess, openStreamError);
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t,
+        function () {
+            tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+        }
+    );
+});
+
+}
+
+function FileStream_close_extra_argument() {
+//==== TEST: FileStream_close_extra_argument
+//==== LABEL Check if FileStream::close() method can be called with extra arguments
+//==== SPEC Tizen Web API:IO:Filesystem:FileStream:close M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MNAEX
+
+var t = async_test('FileStream_close_extra_argument'),
+    fsTestFileName = getFileName("TestFile.txt"),
+    resolveSuccess, resolveError, file, openStreamSuccess, openStreamError;
+t.step(function () {
+    openStreamSuccess = t.step_func(function (stream) {
+        checkExtraArgument(stream, "close");
+        t.done();
+    });
+    openStreamError = t.step_func(function (error) {
+        assert_unreached("openStream() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        file = dir.createFile(fsTestFileName);
+        file.openStream("rw", openStreamSuccess);
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t,
+        function () {
+            tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+        }
+    );
+});
+
+}
+
+function FileStream_eof_attribute() {
+//==== TEST: FileStream_eof_attribute
+//==== PRIORITY P1
+//==== LABEL Check if FileStream::eof attribute exists, is Boolean
+//==== SPEC Tizen Web API:IO:Filesystem:FileStream:eof A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA AE ARO AT
+var t = async_test('FileStream_eof_attribute'),
+    fsTestFileName = getFileName("existFile02.txt"),
+    resolveSuccess, resolveError, openStreamSuccess, openStreamError, file;
+t.step(function () {
+    openStreamSuccess = t.step_func(function (fs) {
+        assert_true("eof" in fs, "eof doesn't exist");
+        check_readonly(fs, "eof", false, "boolean", true);
+        fs.close();
+        t.done();
+    });
+    openStreamError = t.step_func(function (error) {
+        assert_unreached("openStream() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        file = dir.createFile(fsTestFileName);
+        file.openStream("rw", openStreamSuccess, openStreamError);
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t,
+        function () {
+            tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+        }
+    );
+});
+
+}
+
+function FileStream_extend() {
+//==== TEST: FileStream_extend
+//==== LABEL Test whether instance of FileStream can be extended with new attribute
+//==== PRIORITY: P3
+//==== SPEC Tizen Web API:IO:Filesystem:FileStream:FileStream U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA OBX
+var t = async_test('FileStream_extend'),
+    fsTestFileName = getFileName("closeFile.txt"),
+    resolveSuccess, resolveError, openStreamSuccess, openStreamError, file;
+
+t.step(function (){
+    openStreamSuccess = t.step_func(function (fs) {
+        check_extensibility(fs);
+        fs.close();
+        t.done();
+    });
+    openStreamError = t.step_func(function (error) {
+        assert_unreached("openStream() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        file = dir.createFile(fsTestFileName);
+        file.openStream("rw", openStreamSuccess, openStreamError);
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t,
+        function () {
+            tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+        }
+    );
+});
+
+}
+
+function FileStream_notexist() {
+//==== TEST: FileStream_notexist
+//==== LABEL Interface FileStream should not be accessible
+//==== PRIORITY: P3
+//==== SPEC Tizen Web API:IO:Filesystem:FileStream:FileStream U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA NIO
+test(function () {
+    check_no_interface_object("FileStream");
+}, 'FileStream_notexist');
+
+}
+
+function FileStream_position_attribute() {
+//==== TEST: FileStream_position_attribute
+//==== PRIORITY P2
+//==== LABEL Check if FileStream::position attribute exists, is of proper type, can be changed
+//==== SPEC Tizen Web API:IO:Filesystem:FileStream:position A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA AE AT ASG AN
+var t = async_test('FileStream_position_attribute'),
+    fsTestFileName = getFileName("existFile0.txt"),
+    resolveSuccess, resolveError, openStreamSuccess, openStreamError, file;
+t.step(function () {
+    openStreamSuccess = t.step_func(function (fs) {
+        assert_own_property(fs, "position", "this FileStream doesn't have own position property");
+        assert_type(fs.position, "long", "incorrect type of position");
+        assert_equals(fs.position, 0, "incorrect default position");
+        fs.write("abcdefg");
+        assert_equals(fs.position, 7, "incorrect default position after write");
+        fs.position = 2;
+        assert_equals(fs.position, 2, "can't change the position");
+        check_not_nullable(fs, "position");
+        fs.close();
+        t.done();
+    });
+    openStreamError = t.step_func(function (error) {
+        assert_unreached("openStream() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        file = dir.createFile(fsTestFileName);
+        file.openStream("rw", openStreamSuccess, openStreamError);
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t,
+        function () {
+            tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+        }
+    );
+});
+
+}
+
+function FileStream_read() {
+//==== TEST: FileStream_read
+//==== LABEL Check if FileStream::read() method works properly
+//==== PRIORITY: P1
+//==== SPEC Tizen Web API:IO:Filesystem:FileStream:read M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MMINA MR
+var t = async_test('FileStream_read'),
+    fsTestFileName = getFileName("filesystem01.txt"),
+    resolveSuccess, resolveError, openStreamError, openStreamSuccess,
+    openStreamReadSuccess, file, expected = "abcde", text;
+
+t.step(function (){
+    openStreamReadSuccess = t.step_func(function (fs) {
+        text = fs.read(5);
+        fs.close();
+        assert_equals(text, expected, "read fs failed, read '" + text + "', expected '" + expected + "'");
+        t.done();
+    });
+
+    openStreamSuccess = t.step_func(function (fs) {
+        fs.write("abcdefg");
+        fs.close();
+        file.openStream("r", openStreamReadSuccess, openStreamError);
+    });
+    openStreamError = t.step_func(function (error) {
+        assert_unreached("openStream() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        file = dir.createFile(fsTestFileName);
+        file.openStream("w", openStreamSuccess, openStreamError);
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t,
+        function () {
+            tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+        }
+    );
+});
+
+}
+
+function FileStream_readBase64() {
+//==== TEST: FileStream_readBase64
+//==== LABEL Check if FileStream::readBase64() method works
+//==== PRIORITY: P1
+//==== SPEC Tizen Web API:IO:Filesystem:FileStream:readBase64 M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MMINA MR
+var t = async_test('FileStream_readBase64'),
+    fsTestFileName = getFileName("readBaseFile.txt"),
+    resolveSuccess, resolveError, openStreamError, openStreamSuccess,
+    openStreamReadSuccess, file, expected = "YWJjZGVmZw==", base64;
+
+t.step(function (){
+
+    openStreamReadSuccess = t.step_func(function (fs) {
+        base64 = fs.readBase64(256);
+        fs.close();
+        assert_equals(base64, expected, "read fs failed, read " + base64 + ", expected " + expected);
+        t.done();
+    });
+
+    openStreamSuccess = t.step_func(function (fs) {
+        fs.write("abcdefg");
+        fs.close();
+        file.openStream("r", openStreamReadSuccess, openStreamError);
+    });
+    openStreamError = t.step_func(function (error) {
+        assert_unreached("openStream() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        file = dir.createFile(fsTestFileName);
+        file.openStream("w", openStreamSuccess, openStreamError);
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t,
+        function () {
+            tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+        }
+    );
+});
+
+}
+
+function FileStream_readBase64_exist() {
+//==== TEST: FileStream_readBase64_exist
+//==== LABEL Check if FileStream::readBase64() method exists
+//==== PRIORITY P0
+//==== SPEC Tizen Web API:IO:Filesystem:FileStream:readBase64 M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA ME
+var t = async_test('FileStream_readBase64_exist'),
+    fsTestFileName = getFileName("existFile07.txt"),
+    resolveSuccess, resolveError, openStreamSuccess, openStreamError, file;
+
+t.step(function (){
+    openStreamSuccess = t.step_func(function (fs) {
+        assert_true("readBase64" in fs, "readBase64 exists");
+        fs.close();
+        t.done();
+    });
+    openStreamError = t.step_func(function (error) {
+        assert_unreached("openStream() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        file = dir.createFile(fsTestFileName);
+        file.openStream("rw", openStreamSuccess, openStreamError);
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t,
+        function () {
+            tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+        }
+    );
+});
+
+}
+
+function FileStream_readBase64_without_r_permission() {
+
+//==== TEST: FileStream_readBase64_without_r_permission
+//==== LABEL Check if FileStream::readBase64() throws exception when reading from a file opened in 'w' mode
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:FileStream:readBase64 M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA
+
+var t = async_test('FileStream_readBase64_without_r_permission'), testFile,
+    fsTestFileName = getFileName("readBase64WithoutR.txt"), resolveSuccess,
+    resolveError, openStreamSuccess, openStreamError, expected = "IOError";
+
+t.step(function () {
+
+    openStreamSuccess = t.step_func(function (fs) {
+        assert_throws({name: expected}, function () {
+            fs.readBase64(256);
+        }, expected + "exception should be thrown");
+        fs.close();
+        t.done();
+    });
+    openStreamError = t.step_func(function (error) {
+        assert_unreached("openStream() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        testFile = dir.createFile(fsTestFileName);
+        testFile.openStream("w", openStreamSuccess, openStreamError, "UTF-8");
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t,
+        function () {
+            tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+        }
+    );
+});
+
+}
+
+function FileStream_readBase64_writeFile() {
+//==== TEST: FileStream_readBase64_writeFile
+//==== LABEL Check if you can create a new file, write content to it, and then read the content of the file as base64
+//==== PRIORITY P3
+//==== SPEC Tizen Web API:IO:Filesystem:FileStream:FileStream U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA
+
+var t = async_test('FileStream_readBase64_writeFile'),
+    fsTestFileName = getFileName("fileSystem-File03.txt"),
+    resolveSuccess, resolveError, openStreamError, openStreamSuccess,
+    openStreamReadSuccess, file, expected = "YWJjZGVmZw==", base64;
+
+t.step(function (){
+    openStreamReadSuccess = t.step_func(function (fs) {
+        base64 = fs.readBase64(256);
+        fs.close();
+        assert_equals(base64, expected, "read fs failed, read " + base64 + ", expected " + expected);
+        t.done();
+    });
+
+    openStreamSuccess = t.step_func(function (fs) {
+        fs.write("abcdefg");
+        fs.close();
+        file.openStream("r", openStreamReadSuccess, openStreamError, "UTF-8");
+    });
+
+    openStreamError = t.step_func(function (error) {
+        assert_unreached("openStream() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        file = dir.createFile(fsTestFileName);
+        file.openStream("rw", openStreamSuccess, openStreamError, "UTF-8");
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t,
+        function () {
+            tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+        }
+    );
+});
+
+}
+
+function FileStream_readBytes() {
+//==== TEST: FileStream_readBytes
+//==== LABEL Check if FileStream::readBytes() method works properly
+//==== PRIORITY: P1
+//==== SPEC Tizen Web API:IO:Filesystem:FileStream:readBytes M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MMINA MR
+var t = async_test('FileStream_readBytes'), i,
+    fsTestFileName = getFileName("readBytesFile.txt"), stringToWrite = "1234567",
+    resolveSuccess, resolveError, openStreamSuccess, openStreamError, len,
+    openStreamReadSuccess, file, bytes;
+
+t.step(function () {
+    openStreamReadSuccess = t.step_func(function (fs) {
+        bytes = fs.readBytes(256);
+        fs.close();
+        assert_type(bytes, "array", "incorrect read type");
+        assert_equals(bytes.length, stringToWrite.length, "read fs failed, read " + bytes.length + ", expected " + stringToWrite.length);
+        for (i = 0, len = bytes.length; i < len; i++) {
+            assert_equals(bytes[i], stringToWrite.charCodeAt(i), "incorrect read value");
+        }
+        t.done();
+    });
+
+    openStreamSuccess = t.step_func(function (fs) {
+        fs.write(stringToWrite);
+        fs.close();
+        file.openStream("r", openStreamReadSuccess, openStreamError);
+    });
+    openStreamError = t.step_func(function (error) {
+        assert_unreached("openStream() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        file = dir.createFile(fsTestFileName);
+        file.openStream("w", openStreamSuccess, openStreamError);
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t,
+        function () {
+            tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+        }
+    );
+});
+
+}
+
+function FileStream_readBytes_exist() {
+//==== TEST: FileStream_readBytes_exist
+//==== LABEL Check if FileStream::readBytes() method exists
+//==== PRIORITY P0
+//==== SPEC Tizen Web API:IO:Filesystem:FileStream:readBytes M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA ME
+var t = async_test('FileStream_readBytes_exist'),
+    fsTestFileName = getFileName("existFile06.txt"),
+    resolveSuccess, resolveError, openStreamSuccess, openStreamError, file;
+
+t.step(function (){
+    openStreamSuccess = t.step_func(function (fs) {
+        assert_true("readBytes" in fs, "readBytes exists");
+        fs.close();
+        t.done();
+    });
+    openStreamError = t.step_func(function (error) {
+        assert_unreached("openStream() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        file = dir.createFile(fsTestFileName);
+        file.openStream("rw", openStreamSuccess, openStreamError);
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t,
+        function () {
+            tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+        }
+    );
+});
+
+}
+
+function FileStream_readBytes_without_r_permission() {
+
+//==== TEST: FileStream_readBytes_without_r_permission
+//==== LABEL Check if FileStream::readBytes() throws exception when reading from a file opened in 'w' mode
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:FileStream:readBytes M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA
+
+var t = async_test('FileStream_readBytes_without_r_permission'), testFile,
+    fsTestFileName = getFileName("readBytesWithoutR.txt"),
+    resolveSuccess, resolveError, openStreamSuccess,
+    openStreamError, expected = "IOError";
+
+t.step(function () {
+    openStreamSuccess = t.step_func(function (fs) {
+        assert_throws({name: expected}, function () {
+            fs.readBytes(2);
+        }, expected + "exception should be thrown");
+        fs.close();
+        t.done();
+    });
+    openStreamError = t.step_func(function (error) {
+        assert_unreached("openStream() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        testFile = dir.createFile(fsTestFileName);
+        testFile.openStream("w", openStreamSuccess, openStreamError, "UTF-8");
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t,
+        function () {
+            tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+        }
+    );
+});
+
+}
+
+function FileStream_readBytes_writeFile() {
+//==== TEST: FileStream_readBytes_writeFile
+//==== LABEL Check if you can create a new file, write content to it, and then read the content of the file as a byte array
+//==== PRIORITY P3
+//==== SPEC Tizen Web API:IO:Filesystem:FileStream:FileStream U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA
+
+var t = async_test('FileStream_readBytes_writeFile'),
+    fsTestFileName = getFileName("fileSystem-File04.txt"),
+    resolveSuccess, resolveError, openStreamError, openStreamSuccess,
+    openStreamReadSuccess, file, expected = 7, bytes;
+
+t.step(function (){
+    openStreamReadSuccess = t.step_func(function (fs) {
+        bytes = fs.readBytes(256);
+        fs.close();
+        assert_equals(bytes.length, expected, "read fs failed, read " + bytes.length + ", expected " + expected);
+        t.done();
+    });
+
+    openStreamSuccess = t.step_func(function (fs) {
+        fs.write("abcdefg");
+        fs.close();
+        file.openStream("r", openStreamReadSuccess, openStreamError, "UTF-8");
+    });
+    openStreamError = t.step_func(function (error) {
+        assert_unreached("openStream() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        file = dir.createFile(fsTestFileName);
+        file.openStream("rw", openStreamSuccess, openStreamError, "UTF-8");
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t,
+        function () {
+            tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+        }
+    );
+});
+
+}
+
+function FileStream_read_exist() {
+//==== TEST: FileStream_read_exist
+//==== LABEL Check if FileStream::read() method exists
+//==== PRIORITY P0
+//==== SPEC Tizen Web API:IO:Filesystem:FileStream:read M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA ME
+var t = async_test('FileStream_read_exist'),
+    fsTestFileName = getFileName("existFile05.txt"),
+    resolveSuccess, resolveError, openStreamSuccess, openStreamError, file;
+
+t.step(function (){
+    openStreamSuccess = t.step_func(function (fs) {
+        assert_true("read" in fs, "read exists");
+        fs.close();
+        t.done();
+    });
+    openStreamError = t.step_func(function (error) {
+        assert_unreached("openStream() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        file = dir.createFile(fsTestFileName);
+        file.openStream("rw", openStreamSuccess, openStreamError);
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t,
+        function () {
+            tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+        }
+    );
+});
+
+}
+
+function FileStream_read_without_r_permission() {
+
+//==== TEST: FileStream_read_without_r_permission
+//==== LABEL Check if FileStream::read() throws exception when reading from a file opened in 'w' mode
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:FileStream:read M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA
+
+var t = async_test('FileStream_read_without_r_permission'),
+    fsTestFileName = getFileName("write03.txt"), expected = "IOError", testFile,
+    resolveSuccess, resolveError, openStreamSuccess, openStreamError;
+t.step(function () {
+    openStreamSuccess = t.step_func(function (fs) {
+        assert_throws({name: expected}, function () {
+            fs.read(fs.bytesAvailable);
+        }, expected + " exception should be thrown");
+        fs.close();
+        t.done();
+    });
+    openStreamError = t.step_func(function (error) {
+        assert_unreached("openStream() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        testFile = dir.createFile(fsTestFileName);
+        testFile.openStream("w", openStreamSuccess, openStreamError, "UTF-8");
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t,
+        function () {
+            tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+        }
+    );
+});
+
+}
+
+function FileStream_read_writeFile() {
+//==== TEST: FileStream_read_writeFile
+//==== LABEL Check if you can create a new file, write content to it, and then read the content of the file
+//==== PRIORITY P3
+//==== SPEC Tizen Web API:IO:Filesystem:FileStream:FileStream U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA
+
+var t = async_test('FileStream_read_writeFile'),
+    resolveSuccess, resolveError, openStreamError, openStreamSuccess,
+    openStreamRSuccess, file, expected = "test write method", text,
+    fsTestFileName = getFileName("fileSystem-File05.txt");
+
+t.step(function (){
+    openStreamRSuccess = t.step_func(function (fs) {
+        text = fs.read(expected.length);
+        fs.close();
+        assert_equals(text, expected, "read fs failed, read '" + text + "', expected '" + expected + "'");
+        t.done();
+    });
+
+    openStreamSuccess = t.step_func(function (fs) {
+        fs.write(expected);
+        fs.close();
+        file.openStream("r", openStreamRSuccess, openStreamError, "UTF-8");
+    });
+    openStreamError = t.step_func(function (error) {
+        assert_unreached("openStream() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        file = dir.createFile(fsTestFileName);
+        file.openStream("rw", openStreamSuccess, openStreamError, "UTF-8");
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t,
+        function () {
+            tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+        }
+    );
+});
+
+}
+
+function FileStream_write() {
+//==== TEST: FileStream_write
+//==== LABEL Check if FileStream::write() method works properly
+//==== PRIORITY: P1
+//==== SPEC Tizen Web API:IO:Filesystem:FileStream:write M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MAST MMINA MR
+
+var t = async_test('FileStream_write'),
+    resolveSuccess, resolveError, openStreamRSuccess, openStreamWSuccess,
+    openStreamError, file, text, testString = "abcde", retVal = null,
+    fsTestFileName = getFileName("GoodFile.txt");
+
+t.step(function () {
+    openStreamRSuccess = t.step_func(function (fs) {
+        text = fs.read(testString.length);
+        fs.close();
+        assert_equals(text, testString, "Invalid characters read");
+        t.done();
+    });
+    openStreamWSuccess = t.step_func(function (fs) {
+        retVal = fs.write(testString);
+        fs.close();
+        assert_equals(retVal, undefined, "incorrect returned value from write()");
+        file.openStream("r", openStreamRSuccess, openStreamError, "UTF-8");
+    });
+    openStreamError = t.step_func(function (error) {
+        assert_unreached("openStream() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        file = dir.createFile(fsTestFileName);
+        file.openStream("w", openStreamWSuccess, openStreamError, "UTF-8");
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t,
+        function () {
+            tizen.filesystem.resolve("images", resolveSuccess, resolveError, "rw");
+        }
+    );
+});
+
+}
+
+function FileStream_writeBase64() {
+//==== TEST: FileStream_writeBase64
+//==== LABEL Check if FileStream::writeBase64() method works properly
+//==== SPEC Tizen Web API:IO:Filesystem:FileStream:writeBase64 M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MAST MMINA MR
+var t = async_test('FileStream_writeBase64'),
+    resolveSuccess, resolveError, openStreamWSuccess, openStreamRSuccess, retVal = null,
+    openStreamError, file, base64String = "YWJjZGVmZw==", expected = "abcdefg",
+    readString, fsTestFileName = getFileName("readBaseFile.txt");
+
+t.step(function () {
+    openStreamRSuccess = t.step_func(function (fs) {
+        readString = fs.read(expected.length);
+        fs.close();
+        assert_equals(readString, expected, "Incorrect bytes.");
+        t.done();
+    });
+    openStreamWSuccess = t.step_func(function (fs) {
+        retVal = fs.writeBase64(base64String);
+        assert_equals(retVal, undefined, "incorrect returned value from writeBase64()");
+        fs.close();
+        file.openStream("r", openStreamRSuccess, openStreamError);
+    });
+    openStreamError = t.step_func(function (error) {
+        assert_unreached("openStream() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        file = dir.createFile(fsTestFileName);
+        file.openStream("w", openStreamWSuccess, openStreamError);
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t,
+        function () {
+            tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+        }
+    );
+});
+
+}
+
+function FileStream_writeBase64_exist() {
+//==== TEST: FileStream_writeBase64_exist
+//==== LABEL Check if FileStream::writeBase64() method exists
+//==== PRIORITY P0
+//==== SPEC Tizen Web API:IO:Filesystem:FileStream:writeBase64 M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA ME
+var t = async_test('FileStream_writeBase64_exist'),
+    resolveSuccess, resolveError, openStreamSuccess, openStreamError, file,
+    fsTestFileName = getFileName("readBaseFile.txt");
+
+t.step(function (){
+    openStreamSuccess = t.step_func(function (fs) {
+        assert_true("writeBase64" in fs, "writeBase64 exists");
+        fs.close();
+        t.done();
+    });
+    openStreamError = t.step_func(function (error) {
+        assert_unreached("openStream() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        file = dir.createFile(fsTestFileName);
+        file.openStream("rw", openStreamSuccess, openStreamError);
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t,
+        function () {
+            tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+        }
+    );
+});
+
+}
+
+function FileStream_writeBase64_without_w_permission() {
+//==== TEST: FileStream_writeBase64_without_w_permission
+//==== LABEL Check if FileStream::writeBase64() throws exception when writing to a file opened in 'r' mode
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:FileStream:writeBase64 M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA
+
+var resolveSuccess, resolveError, openStreamSuccess, openStreamError, file,
+    expected = "IOError",  base = "YWJjZGVmZw==",
+    t = async_test('FileStream_writeBase64_without_w_permission'),
+    fsTestFileName = getFileName("write11.txt");
+
+t.step(function (){
+    openStreamSuccess = t.step_func(function (fs) {
+        assert_throws({name: expected}, function () {
+            fs.writeBase64(base);
+        }, expected + " exception should be thrown");
+        fs.close();
+        t.done();
+    });
+    openStreamError = t.step_func(function (error) {
+        assert_unreached("openStream() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        file = dir.createFile(fsTestFileName);
+        file.openStream("r", openStreamSuccess, openStreamError, "UTF-8");
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t,
+        function () {
+            tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+        }
+    );
+});
+
+}
+
+function FileStream_writeBytes() {
+//==== TEST: FileStream_writeBytes
+//==== LABEL Check if FileStream::writeBytes() method works properly
+//==== SPEC Tizen Web API:IO:Filesystem:FileStream:writeBytes M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MAST MMINA MR
+
+var t = async_test('FileStream_writeBytes'),
+    resolveSuccess, resolveError, openStreamWithWSuccess, openStreamWithRSuccess,
+    openStreamError, file, bytes, testString = [1, 2, 3, 4, 5, 6, 7], retVal = null,
+    fsTestFileName = getFileName("writeBytes.txt");
+
+t.step(function () {
+    openStreamWithRSuccess = t.step_func(function (fs) {
+        bytes = fs.readBytes(file.fileSize);
+        fs.close();
+        assert_array_equals(bytes, testString, "Invalid bytes read");
+        t.done();
+    });
+
+    openStreamWithWSuccess = t.step_func(function (fs) {
+        retVal = fs.writeBytes(testString);
+        assert_equals(retVal, undefined, "incorrect returned value from writeBytes()");
+        fs.close();
+        file.openStream("r", openStreamWithRSuccess, openStreamError);
+    });
+    openStreamError = t.step_func(function (error) {
+        assert_unreached("openStream() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        file = dir.createFile(fsTestFileName);
+        file.openStream("w", openStreamWithWSuccess, openStreamError);
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t,
+        function () {
+            tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+        }
+    );
+});
+
+}
+
+function FileStream_writeBytes_byteData_TypeMismatch() {
+//==== TEST: FileStream_writeBytes_byteData_TypeMismatch
+//==== LABEL Check if FileStream::writeBytes() throws exception for wrong type of byteData
+//==== PRIORITY: P2
+//==== SPEC Tizen Web API:IO:Filesystem:FileStream:writeBytes M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MC
+
+var t = async_test('FileStream_writeBytes_byteData_TypeMismatch'),
+    resolveSuccess, resolveError, openStreamSuccess, openStreamError,
+    file, conversionTable, bytes, i, exceptionName = "TypeMismatchError",
+    fsTestFileName = getFileName("readBytesFiletest3.txt");
+
+t.step(function (){
+    openStreamSuccess = t.step_func(function (fs) {
+        conversionTable = getTypeConversionExceptions("array", false);
+        for (i = 0; i < conversionTable.length; i++) {
+            bytes = conversionTable[i][0];
+            exceptionName = conversionTable[i][1];
+
+            assert_throws({name: exceptionName}, function () {
+                fs.writeBytes(bytes);
+            }, exceptionName + " should be thrown - given incorrect byteData.");
+        }
+        fs.close();
+        t.done();
+    });
+    openStreamError = t.step_func(function (error) {
+        assert_unreached("openStream() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        file = dir.createFile(fsTestFileName);
+        file.openStream("w", openStreamSuccess, openStreamError);
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t,
+        function () {
+            tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+        }
+    );
+});
+
+}
+
+function FileStream_writeBytes_exist() {
+//==== TEST: FileStream_writeBytes_exist
+//==== LABEL Check if FileStream::writeBytes() method exists
+//==== PRIORITY P0
+//==== SPEC Tizen Web API:IO:Filesystem:FileStream:writeBytes M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA ME
+
+var t = async_test('FileStream_writeBytes_exist'),
+    resolveSuccess, resolveError, openStreamSuccess, openStreamError, file,
+    fsTestFileName = getFileName("existFile09.txt");
+
+t.step(function (){
+    openStreamSuccess = t.step_func(function (fs) {
+        assert_true("writeBytes" in fs, "writeBytes exists");
+        fs.close();
+        t.done();
+    });
+    openStreamError = t.step_func(function (error) {
+        assert_unreached("openStream() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        file = dir.createFile(fsTestFileName);
+        file.openStream("rw", openStreamSuccess, openStreamError);
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t,
+        function () {
+            tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+        }
+    );
+});
+
+}
+
+function FileStream_writeBytes_missarg() {
+//==== TEST: FileStream_writeBytes_missarg
+//==== LABEL Check if FileStream::writeBytes() method throws exception for missing mandatory argument
+//==== SPEC Tizen Web API:IO:Filesystem:FileStream:writeBytes M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MMA
+
+var t = async_test('FileStream_writeBytes_missarg'),
+    resolveSuccess, resolveError, openStreamSuccess, openStreamError, file,
+    expected = "TypeMismatchError",
+    fsTestFileName = getFileName("readBytesFiletest2.txt");
+
+t.step(function (){
+    openStreamSuccess = t.step_func(function (fs) {
+        assert_throws({name: expected}, function () {
+            fs.writeBytes();
+        }, expected + " exception should be thrown");
+        fs.close();
+        t.done();
+    });
+    openStreamError = t.step_func(function (error) {
+        assert_unreached("openStream() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        file = dir.createFile(fsTestFileName);
+        file.openStream("w", openStreamSuccess, openStreamError);
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t,
+        function () {
+            tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+        }
+    );
+});
+
+}
+
+function FileStream_writeBytes_with_additional_null_parameter() {
+
+//==== TEST: FileStream_writeBytes_with_additional_null_parameter
+//==== LABEL Check if FileStream::writeBytes() method properly writes the specified bytes to file
+//==== SPEC Tizen Web API:IO:Filesystem:FileStream:writeBytes M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MAST
+var t = async_test('FileStream_writeBytes_with_additional_null_parameter'),
+    file, resolveSuccess, resolveError, openStreamWriteSuccess,
+    openStreamError, openStreamReadSuccess, testString = [1, 2, 3, 4, 5, 6, 7],
+    readString, fsTestFileName = getFileName("readBytesFileTestNull.txt");
+
+t.step(function () {
+    openStreamReadSuccess = t.step_func(function (stream) {
+        readString = stream.readBytes(testString.length, null);
+        stream.close();
+        assert_type(readString, "array", "type read from file");
+        assert_equals(readString.toString(), testString.toString(), "string read from file");
+        t.done();
+    });
+
+    openStreamWriteSuccess = t.step_func(function (stream) {
+        stream.writeBytes(testString, null);
+        stream.close();
+        file.openStream("r", openStreamReadSuccess, openStreamError, "UTF-8");
+    });
+    openStreamError = t.step_func(function (error) {
+        assert_unreached("openStream() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        file = dir.createFile(fsTestFileName);
+        file.openStream("w", openStreamWriteSuccess, openStreamError, "UTF-8");
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t,
+        function () {
+            tizen.filesystem.resolve(TEST_ROOT_LOCATION, resolveSuccess, resolveError);
+        }
+    );
+});
+
+}
+
+function FileStream_writeBytes_without_w_permission() {
+//==== TEST: FileStream_writeBytes_without_w_permission
+//==== LABEL Check if FileStream::writeBytes() throws exception when writing to a file opened in 'r' mode
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:FileStream:writeBytes M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA
+
+var t = async_test('FileStream_writeBytes_without_w_permission'),
+    resolveSuccess, resolveError, openStreamSuccess, openStreamError, file,
+    bytes = new Array(104, 101, 108), expected = "IOError",
+    fsTestFileName = getFileName("writeBytesWOPerm.txt");
+
+t.step(function (){
+    openStreamSuccess = t.step_func(function (fs) {
+        assert_throws({name: expected}, function () {
+            fs.writeBytes(bytes);
+        }, expected + " exception should be thrown");
+        fs.close();
+        t.done();
+    });
+    openStreamError = t.step_func(function (error) {
+        assert_unreached("openStream() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        file = dir.createFile(fsTestFileName);
+        file.openStream("r", openStreamSuccess, openStreamError, "UTF-8");
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t,
+        function () {
+            tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+        }
+    );
+});
+
+}
+
+function FileStream_write_exist() {
+//==== TEST: FileStream_write_exist
+//==== LABEL Check if FileStream::write() method exists
+//==== PRIORITY P0
+//==== SPEC Tizen Web API:IO:Filesystem:FileStream:write M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA ME
+
+var t = async_test('FileStream_write_exist'),
+    fsTestFileName = getFileName("existFile08.txt"),
+    resolveSuccess, resolveError, openStreamSuccess, openStreamError, file;
+
+t.step(function () {
+    openStreamSuccess = t.step_func(function (fs) {
+        assert_true("write" in fs, "write exists");
+        fs.close();
+        t.done();
+    });
+    openStreamError = t.step_func(function (error) {
+        assert_unreached("openStream() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        file = dir.createFile(fsTestFileName);
+        file.openStream("rw", openStreamSuccess, openStreamError);
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t,
+        function () {
+            tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+        }
+    );
+});
+
+}
+
+function FileStream_write_without_w_permission() {
+
+//==== TEST: FileStream_write_without_w_permission
+//==== LABEL Check if FileStream::write() throws exception when writing to a file opened in 'r' mode
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:FileStream:write M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA
+
+var t = async_test('FileStream_write_without_w_permission'),
+    fsTestFileName = getFileName("write09.txt"),
+    resolveSuccess, resolveError, openStreamSuccess, openStreamError, file,
+    expected = "IOError";
+
+t.step(function (){
+    openStreamSuccess = t.step_func(function (fs) {
+        assert_throws({name: expected}, function () {
+            fs.write("test");
+        }, expected + " exception should be thrown");
+        fs.close();
+        t.done();
+    });
+    openStreamError = t.step_func(function (error) {
+        assert_unreached("openStream() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        file = dir.createFile(fsTestFileName);
+        file.openStream("r", openStreamSuccess, openStreamError, "UTF-8");
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t,
+        function () {
+            tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+        }
+    );
+});
+
+}
+
+function FileStringSuccessCallback_notexist() {
+//==== TEST: FileStringSuccessCallback_notexist
+//==== LABEL Interface FileStringSuccessCallback should not be accessible
+//==== PRIORITY: P3
+//==== SPEC Tizen Web API:IO:Filesystem:FileStringSuccessCallback:FileStringSuccessCallback U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA CBNIO
+test(function () {
+    check_no_interface_object("FileStringSuccessCallback");
+}, 'FileStringSuccessCallback_notexist');
+
+}
+
+function FileStringSuccessCallback_onsuccess() {
+//==== TEST: FileStringSuccessCallback_onsuccess
+//==== LABEL Test whether FileStringSuccessCallback::onsuccess is called with valid argument
+//==== PRIORITY: P1
+//==== SPEC Tizen Web API:IO:Filesystem:FileStringSuccessCallback:onsuccess M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA CBOA CBT
+var t = async_test('FileStringSuccessCallback_onsuccess'), stringToWrite = "HelloWorld",
+    resolveSuccess, resolveError, readAsTextSuccess, openStreamSuccess, file,
+    fsTestFileName = getFileName("filesystem.txt");
+
+t.step(function () {
+    readAsTextSuccess = t.step_func(function (fileStr) {
+        assert_type(fileStr, "string", "incorrect type of passed argument");
+        assert_equals(fileStr, stringToWrite, "incorrect value of passed argument");
+        t.done();
+    });
+    openStreamSuccess = t.step_func(function (fs) {
+        fs.write(stringToWrite);
+        fs.close();
+        file.readAsText(readAsTextSuccess);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        file = dir.createFile(fsTestFileName);
+        file.openStream("w", openStreamSuccess);
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t,
+        function () {
+            tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+        }
+    );
+});
+
+}
+
+function FileSuccessCallback_notexist() {
+//==== TEST: FileSuccessCallback_notexist
+//==== LABEL Interface FileSuccessCallback should not be accessible
+//==== PRIORITY: P3
+//==== SPEC Tizen Web API:IO:Filesystem:FileSuccessCallback:FileSuccessCallback U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA CBNIO
+test(function () {
+    check_no_interface_object("FileSuccessCallback");
+}, 'FileSuccessCallback_notexist');
+
+}
+
+function FileSuccessCallback_onsuccess() {
+
+//==== TEST: FileSuccessCallback_onsuccess
+//==== LABEL Test whether FileSuccessCallback::onsuccess is called with valid argument
+//==== PRIORITY: P1
+//==== SPEC Tizen Web API:IO:Filesystem:FileSuccessCallback:onsuccess M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA CBOA CBT
+
+var t = async_test('FileSuccessCallback_onsuccess'),
+    resolveSuccess, resolveError;
+
+t.step(function () {
+    resolveSuccess = t.step_func(function (dir) {
+        assert_type(dir, "object", "incorrect received argument");
+        checkOwnProperties(dir);
+        assert_equals(dir.path, "images", "incorrect received File object");
+        t.done();
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    tizen.filesystem.resolve("images", resolveSuccess, resolveError, "rw");
+});
+
+}
+
+function FileSystemManagerObject_notexist() {
+
+//==== TEST: FileSystemManagerObject_notexist
+//==== LABEL Interface FileSystemManagerObject should not be accessible
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManagerObject:FileSystemManagerObject U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("FileSystemManagerObject");
+}, 'FileSystemManagerObject_notexist');
+
+}
+
+function FileSystemManager_addStorageStateChangeListener() {
+//==== TEST: FileSystemManager_addStorageStateChangeListener
+//==== LABEL Check if FileSystemManager::addStorageStateChangeListener() method can be called
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:addStorageStateChangeListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MMINA MR
+
+var t = async_test('FileSystemManager_addStorageStateChangeListener'),
+    successCallback, retValue = null;
+t.step(function () {
+    successCallback = t.step_func(function (storages) {
+        assert_type(retValue, "long", "addStorageStateChangeListener returns wrong value");
+
+        t.done();
+    });
+
+    retValue = tizen.filesystem.addStorageStateChangeListener(successCallback);
+});
+
+}
+
+function FileSystemManager_addStorageStateChangeListener_exist() {
+//==== TEST: FileSystemManager_addStorageStateChangeListener_exist
+//==== LABEL Check if FileSystemManager::addStorageStateChangeListener() method exists
+//==== PRIORITY P0
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:addStorageStateChangeListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA ME
+
+test(function () {
+    assert_true("addStorageStateChangeListener" in tizen.filesystem,
+        "No addStorageStateChangeListener method in tizen.filesystem");
+    check_method_exists(tizen.filesystem, "addStorageStateChangeListener");
+}, 'FileSystemManager_addStorageStateChangeListener_exist');
+
+}
+
+function FileSystemManager_addStorageStateChangeListener_missarg() {
+//==== TEST: FileSystemManager_addStorageStateChangeListener_missarg
+//==== PRIORITY P2
+//==== LABEL Check if FileSystemManager::addStorageStateChangeListener() method throws exception for missing mandatory argument
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:addStorageStateChangeListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MMA
+
+test(function () {
+    assert_throws(TYPE_MISMATCH_EXCEPTION,
+        function () {
+            tizen.filesystem.addStorageStateChangeListener();
+        }, "Method should throw an exception");
+}, 'FileSystemManager_addStorageStateChangeListener_missarg');
+
+}
+
+function FileSystemManager_addStorageStateChangeListener_onerror_TypeMismatch() {
+//==== TEST: FileSystemManager_addStorageStateChangeListener_onerror_TypeMismatch
+//==== PRIORITY P2
+//==== LABEL Check if FileSystemManager::addStorageStateChangeListener() throws exception for wrong type of onerror
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:addStorageStateChangeListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MC
+
+var t = async_test('FileSystemManager_addStorageStateChangeListener_onerror_TypeMismatch'), i,
+    onSuccess, onError, exceptionName, conversionTable;
+t.step(function () {
+    onSuccess = t.step_func(function (storage) {
+        assert_unreached("Shouldn't be invoked");
+    });
+    conversionTable = getTypeConversionExceptions("functionObject", true);
+    for(i = 0; i < conversionTable.length; i++) {
+        onError = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+
+        assert_throws({name: exceptionName},
+        function () {
+            tizen.filesystem.addStorageStateChangeListener(onSuccess, onError);
+        }, exceptionName + " should be thrown - given incorrect errorCallback #"+ onError +"#");
+    }
+    t.done();
+});
+
+}
+
+function FileSystemManager_addStorageStateChangeListener_onerror_invalid_cb() {
+//==== TEST: FileSystemManager_addStorageStateChangeListener_onerror_invalid_cb
+//==== PRIORITY P2
+//==== LABEL Check if FileSystemManager::addStorageStateChangeListener() throws exception for wrong onerror
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:addStorageStateChangeListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MTCB
+
+var t = async_test('FileSystemManager_addStorageStateChangeListener_onerror_invalid_cb'),
+    incorrectCallback, onSuccess;
+t.step(function () {
+    onSuccess = t.step_func(function (storage) {
+        assert_unreached("onSuccess callback invoked");
+    });
+    incorrectCallback = {
+        onerror: t.step_func(function (){
+            assert_unreached("invalid callback invoked");
+        })
+    };
+    assert_throws(TYPE_MISMATCH_EXCEPTION,
+        function () {
+            tizen.filesystem.addStorageStateChangeListener(onSuccess, incorrectCallback);
+        }, "given incorrect errorCallback");
+    t.done();
+});
+
+}
+
+function FileSystemManager_addStorageStateChangeListener_onsuccess_TypeMismatch() {
+//==== TEST: FileSystemManager_addStorageStateChangeListener_onsuccess_TypeMismatch
+//==== PRIORITY P2
+//==== LABEL Check if FileSystemManager::addStorageStateChangeListener() throws exception for wrong type of onsuccess
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:addStorageStateChangeListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MC
+
+var t = async_test('FileSystemManager_addStorageStateChangeListener_onsuccess_TypeMismatch'),
+    i, onSuccess, exceptionName, conversionTable;
+t.step(function () {
+    conversionTable = getTypeConversionExceptions("functionObject", false);
+    for(i = 0; i < conversionTable.length; i++) {
+        onSuccess = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+
+        assert_throws({name: exceptionName},
+            function () {
+                tizen.filesystem.addStorageStateChangeListener(onSuccess);
+            }, exceptionName + " should be thrown - given incorrect onSuccess.");
+    }
+    t.done();
+});
+
+}
+
+function FileSystemManager_addStorageStateChangeListener_onsuccess_invalid_cb() {
+//==== TEST: FileSystemManager_addStorageStateChangeListener_onsuccess_invalid_cb
+//==== PRIORITY P2
+//==== LABEL Check if FileSystemManager::addStorageStateChangeListener() throws exception for wrong onsuccess
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:addStorageStateChangeListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MTCB
+
+var t = async_test('FileSystemManager_addStorageStateChangeListener_onsuccess_invalid_cb'),
+    incorrectCallback;
+
+t.step(function () {
+    incorrectCallback = {
+        onsuccess: t.step_func(function (){
+            assert_unreached("Invalid callback invoked: ");
+        })
+    };
+    assert_throws(TYPE_MISMATCH_EXCEPTION,
+        function () {
+            tizen.filesystem.addStorageStateChangeListener(incorrectCallback);
+        }, "given incorrect error callback");
+    t.done();
+});
+
+}
+
+function FileSystemManager_addStorageStateChangeListener_with_onerror() {
+//==== TEST: FileSystemManager_addStorageStateChangeListener_with_onerror
+//==== PRIORITY P1
+//==== LABEL Check if FileSystemManager::addStorageStateChangeListener() can be called with onerror
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:addStorageStateChangeListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MOA
+
+var t = async_test('FileSystemManager_addStorageStateChangeListener_with_onerror'),
+    onError, successCallback;
+t.step(function (){
+    onError = t.step_func(function (error) {
+        assert_unreached("Error: " + error.message);
+    });
+    successCallback = t.step_func(function (storages) {
+        t.done();
+    });
+
+    tizen.filesystem.addStorageStateChangeListener(successCallback, onError);
+});
+
+}
+
+function FileSystemManager_addStorageStateChangeListener_without_arguments() {
+//==== TEST: FileSystemManager_addStorageStateChangeListener_without_arguments
+//==== PRIORITY P2
+//==== LABEL Check if FileSystemManager::addStorageStateChangeListener() throws exception for missing mandatory argument
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:addStorageStateChangeListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MMA
+
+test(function () {
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        tizen.filesystem.addStorageStateChangeListener();
+    });
+}, 'FileSystemManager_addStorageStateChangeListener_without_arguments');
+
+}
+
+function FileSystemManager_extend() {
+//==== TEST: FileSystemManager_extend
+//==== PRIORITY P3
+//==== LABEL Check if instance of FileSystemManager can be extended with new property
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:FileSystemManager U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA OBX
+
+test(function () {
+    check_extensibility(tizen.filesystem);
+}, 'FileSystemManager_extend');
+
+}
+
+function FileSystemManager_getStorage() {
+//==== TEST: FileSystemManager_getStorage
+//==== PRIORITY P1
+//==== LABEL Check if FileSystemManager::getStorage() calls onsuccess callback
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:getStorage M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MMINA MR
+
+var t = async_test('FileSystemManager_getStorage'),
+    onSuccess, onError, successCallback, retValue = null;
+t.step(function () {
+    onSuccess = t.step_func(function (storage) {
+        assert_equals(retValue, undefined, "getStorage returns wrong value");
+        t.done();
+    });
+    successCallback = t.step_func(function (storages) {
+        assert_true(storages.length > 0, "list the available storages");
+        retValue = tizen.filesystem.getStorage(storages[0].label, onSuccess);
+    });
+    onError = t.step_func(function (error) {
+        assert_unreached("Error: " + error.message);
+    });
+    tizen.filesystem.listStorages(successCallback, onError);
+});
+
+}
+
+function FileSystemManager_getStorage_exist() {
+//==== TEST: FileSystemManager_getStorage_exist
+//==== LABEL Check if FileSystemManager::getStorage() method exists
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:getStorage M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA ME
+
+test(function () {
+    assert_true("getStorage" in tizen.filesystem, "No getStorage method in tizen.filesystem");
+    check_method_exists(tizen.filesystem, "getStorage");
+}, 'FileSystemManager_getStorage_exist');
+
+}
+
+function FileSystemManager_getStorage_missarg() {
+//==== TEST: FileSystemManager_getStorage_missarg
+//==== PRIORITY P2
+//==== LABEL Check if FileSystemManager::getStorage() throws exception for missing mandatory argument
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:getStorage M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MMA
+
+test(function () {
+    assert_throws(TYPE_MISMATCH_EXCEPTION,
+        function () {
+            tizen.filesystem.getStorage();
+        }, "Method should throw an exception");
+}, 'FileSystemManager_getStorage_missarg');
+
+}
+
+function FileSystemManager_getStorage_onerror_TypeMismatch() {
+//==== TEST: FileSystemManager_getStorage_onerror_TypeMismatch
+//==== PRIORITY P2
+//==== LABEL Check if FileSystemManager::getStorage() throws exception for wrong type of onerror
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:getStorage M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MC
+
+var t = async_test('FileSystemManager_getStorage_onerror_TypeMismatch'), i,
+    getStorageSuccess, getStorageError, exceptionName,
+    listStoragesSuccess, listStoragesError, conversionTable;
+
+t.step(function () {
+    conversionTable = getTypeConversionExceptions("functionObject", true);
+    getStorageSuccess = t.step_func(function (storage) {
+        assert_unreached("getStorage success callback invoked.");
+    });
+    listStoragesSuccess = t.step_func(function (storages) {
+        for(i = 0; i < conversionTable.length; i++) {
+            getStorageError = conversionTable[i][0];
+            exceptionName = conversionTable[i][1];
+
+            assert_throws({name: exceptionName},
+                function () {
+                    tizen.filesystem.getStorage(storages[0].label, getStorageSuccess, getStorageError);
+                }, exceptionName + " should be thrown - given incorrect errorCallback.");
+        }
+        t.done();
+    });
+    listStoragesError = t.step_func(function (error) {
+        assert_unreached("listStorages() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    tizen.filesystem.listStorages(listStoragesSuccess, listStoragesError);
+});
+
+}
+
+function FileSystemManager_getStorage_onerror_invalid_cb() {
+//==== TEST: FileSystemManager_getStorage_onerror_invalid_cb
+//==== PRIORITY P2
+//==== LABEL Check if FileSystemManager::getStorage() throws exception for wrong onerror
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:getStorage M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MTCB
+
+var t = async_test('FileSystemManager_getStorage_onerror_invalid_cb'),
+    getStorageIncorrect, getStorageSuccess,
+    listStoragesSuccess, listStoragesError;
+
+t.step(function () {
+    getStorageSuccess = t.step_func(function (storage) {
+        assert_unreached("getStorage success callback invoked.");
+    });
+    getStorageIncorrect = {
+        onerror: t.step_func(function (){
+            assert_unreached("Invalid callback invoked: ");
+        })
+    };
+    listStoragesError = t.step_func(function (error) {
+        assert_unreached("listStorages() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+    listStoragesSuccess = t.step_func(function (storages) {
+        assert_throws(TYPE_MISMATCH_EXCEPTION,
+            function () {
+                tizen.filesystem.getStorage(storages[0].label, getStorageSuccess, getStorageIncorrect);
+            }, "given incorrect errorCallback");
+        t.done();
+    });
+
+    tizen.filesystem.listStorages(listStoragesSuccess, listStoragesError);
+});
+
+}
+
+function FileSystemManager_getStorage_onsuccess_TypeMismatch() {
+//==== TEST: FileSystemManager_getStorage_onsuccess_TypeMismatch
+//==== PRIORITY P2
+//==== LABEL Check if FileSystemManager::getStorage() throws exception for wrong type of onsuccess
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:getStorage M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MC
+
+var t = async_test('FileSystemManager_getStorage_onsuccess_TypeMismatch'), i,
+    listStoragesSuccess, listStoragesError, exceptionName,
+    getStorageSuccess, conversionTable;
+
+t.step(function () {
+    conversionTable = getTypeConversionExceptions("functionObject", false);
+    listStoragesSuccess = t.step_func(function (storages) {
+        for(i = 0; i < conversionTable.length; i++) {
+            getStorageSuccess = conversionTable[i][0];
+            exceptionName = conversionTable[i][1];
+
+            assert_throws({name: exceptionName},
+                function () {
+                    tizen.filesystem.getStorage(storages[0].label, getStorageSuccess);
+                }, exceptionName + " should be thrown - given incorrect onSuccess.");
+        }
+        t.done();
+    });
+    listStoragesError = t.step_func(function (error) {
+        assert_unreached("listStorages() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    tizen.filesystem.listStorages(listStoragesSuccess, listStoragesError);
+});
+
+}
+
+function FileSystemManager_getStorage_onsuccess_invalid_cb() {
+//==== TEST: FileSystemManager_getStorage_onsuccess_invalid_cb
+//==== PRIORITY P2
+//==== LABEL Check if FileSystemManager::getStorage() throws exception for wrong onsuccess
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:getStorage M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MTCB
+
+var t = async_test('FileSystemManager_getStorage_onsuccess_invalid_cb'),
+    getStorageIncorrect, listStoragesError,
+    listStoragesSuccess;
+
+t.step(function () {
+    getStorageIncorrect = {
+        onsuccess: t.step_func(function (){
+            assert_unreached("Invalid callback invoked: ");
+        })
+    };
+
+    listStoragesSuccess = t.step_func(function (storages) {
+        assert_throws(TYPE_MISMATCH_EXCEPTION,
+            function () {
+                tizen.filesystem.getStorage(storages[0].label, getStorageIncorrect);
+            }, "given incorrect error callback");
+        t.done();
+    });
+    listStoragesError = t.step_func(function (error) {
+        assert_unreached("listStorages() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    tizen.filesystem.listStorages(listStoragesSuccess, listStoragesError);
+});
+
+}
+
+function FileSystemManager_getStorage_with_nonexist_label() {
+//==== TEST: FileSystemManager_getStorage_with_nonexist_label
+//==== LABEL Check if FileSystemManager::getStorage() throws an exception when storage with given label does not exist
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:getStorage M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MERRCB
+
+var t = async_test('FileSystemManager_getStorage_with_nonexist_label'),
+    onSuccess, onError, expected = "NotFoundError";
+
+t.step(function (){
+    onSuccess = t.step_func(function (storages) {
+        assert_unreached("should throw an exception");
+    });
+
+    onError = t.step_func(function (error) {
+        assert_equals(error.name, expected, "should throw an exception");
+        t.done();
+    });
+
+    tizen.filesystem.getStorage("MMC", onSuccess, onError);
+});
+
+}
+
+function FileSystemManager_getStorage_with_onerror() {
+//==== TEST: FileSystemManager_getStorage_with_onerror
+//==== PRIORITY P1
+//==== LABEL Check if FileSystemManager::getStorage() can be called with onerror callback
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:getStorage M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MOA
+
+var t = async_test('FileSystemManager_getStorage_with_onerror'),
+    getStorageSuccess, getStorageError, listStoragesSuccess, listStoragesError;
+t.step(function (){
+    getStorageSuccess = t.step_func(function (storage) {
+        t.done();
+    });
+    getStorageError = t.step_func(function (error) {
+        assert_unreached("getStorage() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    listStoragesSuccess = t.step_func(function (storages) {
+        assert_true(storages.length > 0, "list the available storages");
+        tizen.filesystem.getStorage(storages[0].label, getStorageSuccess, getStorageError);
+    });
+    listStoragesError = t.step_func(function (error) {
+        assert_unreached("listStorages() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    tizen.filesystem.listStorages(listStoragesSuccess, listStoragesError);
+});
+
+}
+
+function FileSystemManager_in_tizen() {
+
+//==== TEST: FileSystemManager_in_tizen
+//==== LABEL Check if tizen namespace contains filesystem
+//==== PRIORITY: P3
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:FileSystemManager U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA OBME
+
+test(function () {
+    assert_true("filesystem" in tizen, "No FileSystemManager in tizen.");
+    check_readonly(tizen, "filesystem", tizen.filesystem, "object", "dummyValue");
+}, 'FileSystemManager_in_tizen');
+
+}
+
+function FileSystemManager_listStorages() {
+//==== TEST: FileSystemManager_listStorages
+//==== PRIORITY P1
+//==== LABEL Check if FileSystemManager::listStorages() method works
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:listStorages M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MMINA MR
+
+var t = async_test('FileSystemManager_listStorages'),
+    onSuccess, retValue = null;
+t.step(function () {
+    onSuccess = t.step_func(function (storages) {
+        assert_true(storages.length > 0, "list the available storages");
+        assert_equals(retValue, undefined, "listStorages returns wrong value");
+
+        t.done();
+    });
+
+    retValue = tizen.filesystem.listStorages(onSuccess);
+});
+
+}
+
+function FileSystemManager_listStorages_exist() {
+//==== TEST: FileSystemManager_listStorages_exist
+//==== LABEL Check if FileSystemManager::listStorages() method exists
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:listStorages M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA ME
+
+test(function () {
+    assert_true("listStorages" in tizen.filesystem, "No listStorages method in tizen.filesystem");
+    check_method_exists(tizen.filesystem, "listStorages");
+}, 'FileSystemManager_listStorages_exist');
+
+}
+
+function FileSystemManager_listStorages_missarg() {
+//==== TEST: FileSystemManager_listStorages_missarg
+//==== PRIORITY P2
+//==== LABEL Check if FileSystemManager::listStorages() throws exception for missing mandatory argument
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:listStorages M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MMA
+
+test(function () {
+    assert_throws(TYPE_MISMATCH_EXCEPTION,
+        function () {
+            tizen.filesystem.listStorages();
+        }, "Method should throw an exception");
+}, 'FileSystemManager_listStorages_missarg');
+
+}
+
+function FileSystemManager_listStorages_onerror_TypeMismatch() {
+//==== TEST: FileSystemManager_listStorages_onerror_TypeMismatch
+//==== PRIORITY P2
+//==== LABEL Check if FileSystemManager::listStorages() method throws exception for wrong type of onerror
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:listStorages M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MC
+
+var t = async_test('FileSystemManager_listStorages_onerror_TypeMismatch'), i,
+    listStoragesSuccess, exceptionName, listStoragesSuccess, listStoragesError,
+    conversionTable;
+
+t.step(function () {
+    conversionTable = getTypeConversionExceptions("functionObject", true);
+
+    listStoragesSuccess = t.step_func(function (storages) {
+        assert_unreached("listStorages() success callback should not be invoked");
+    });
+    for(i = 0; i < conversionTable.length; i++) {
+        listStoragesError = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+
+        assert_throws({name: exceptionName},
+            function () {
+                tizen.filesystem.listStorages(listStoragesSuccess, listStoragesError);
+            }, exceptionName + " should be thrown - given incorrect errorCallback.");
+    }
+    t.done();
+});
+
+}
+
+function FileSystemManager_listStorages_onerror_invalid_cb() {
+//==== TEST: FileSystemManager_listStorages_onerror_invalid_cb
+//==== PRIORITY P2
+//==== LABEL Check if FileSystemManager::listStorages() method throws exception for wrong onerror
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:listStorages M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MTCB
+
+var t = async_test('FileSystemManager_listStorages_onerror_invalid_cb'),
+    listStoragesIncorrect, listStoragesSuccess;
+
+t.step(function () {
+
+    listStoragesSuccess = t.step_func(function (storages) {
+        assert_unreached("this function should not be invoked");
+    });
+
+    listStoragesIncorrect = {
+        onerror: t.step_func(function (){
+            assert_unreached("Invalid callback invoked: ");
+        })
+    };
+    assert_throws(TYPE_MISMATCH_EXCEPTION,
+        function () {
+            tizen.filesystem.listStorages(listStoragesSuccess, listStoragesIncorrect);
+        }, "given incorrect errorCallback");
+    t.done();
+});
+
+}
+
+function FileSystemManager_listStorages_onsuccess_TypeMismatch() {
+//==== TEST: FileSystemManager_listStorages_onsuccess_TypeMismatch
+//==== PRIORITY P2
+//==== LABEL Check if FileSystemManager::listStorages() method throws exception for wrong type of onsuccess
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:listStorages M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MC
+
+var t = async_test('FileSystemManager_listStorages_onsuccess_TypeMismatch'), i,
+    exceptionName, listStoragesSuccess, listStoragesError, conversionTable;
+
+t.step(function () {
+    conversionTable = getTypeConversionExceptions("functionObject", false);
+
+    listStoragesError = t.step_func(function (error) {
+        assert_unreached("listStorages() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    for(i = 0; i < conversionTable.length; i++) {
+        listStoragesSuccess = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+
+        assert_throws({name: exceptionName},
+            function () {
+                tizen.filesystem.listStorages(listStoragesSuccess, listStoragesError);
+            }, exceptionName + " should be thrown - given incorrect onSuccess callback.");
+    }
+    t.done();
+});
+
+}
+
+function FileSystemManager_listStorages_onsuccess_invalid_cb() {
+//==== TEST: FileSystemManager_listStorages_onsuccess_invalid_cb
+//==== PRIORITY P2
+//==== LABEL Check if FileSystemManager::listStorages() method throws exception for wrong onsuccess
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:listStorages M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MTCB
+
+var t = async_test('FileSystemManager_listStorages_onsuccess_invalid_cb'),
+    listStoragesIncorrect;
+
+t.step(function () {
+
+    listStoragesIncorrect = {
+        onsuccess: t.step_func(function (){
+            assert_unreached("Invalid callback invoked: ");
+        })
+    };
+    assert_throws(TYPE_MISMATCH_EXCEPTION,
+        function () {
+            tizen.filesystem.listStorages(listStoragesIncorrect);
+        }, "given incorrect error callback");
+    t.done();
+});
+
+}
+
+function FileSystemManager_listStorages_storages_retrieve() {
+
+//==== TEST: FileSystemManager_listStorages_storages_retrieve
+//==== LABEL Check if FileSystemManager::listStorages() method properly retrieves the available storages on the device
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:listStorages M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MOA
+var t = async_test('FileSystemManager_listStorages_storages_retrieve'),
+    onSuccess, onError, labels;
+
+t.step(function () {
+    onSuccess = t.step_func(function (storages) {
+        labels = storages.map(function (item) {
+            return item.label;
+        });
+        assert_true(labels.indexOf("documents") > -1, "includes 'documents'");
+        assert_true(labels.indexOf("images") > -1, "includes 'images'");
+        assert_true(labels.indexOf("music") > -1, "includes 'music'");
+        assert_true(labels.indexOf("videos") > -1, "includes 'videos'");
+        assert_true(labels.indexOf("downloads") > -1, "includes 'downloads'");
+        assert_true(labels.indexOf("wgt-package") > -1, "includes 'wgt-package'");
+        assert_true(labels.indexOf("wgt-private") > -1, "includes 'wgt-private'");
+        assert_true(labels.indexOf("wgt-private-tmp") > -1, "includes 'wgt-private-tmp'");
+
+        t.done();
+    });
+    onError = t.step_func(function (error) {
+        assert_unreached("listStorages() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+    tizen.filesystem.listStorages(onSuccess, onError);
+});
+
+}
+
+function FileSystemManager_listStorages_with_invalid_error_callbacks() {
+
+//==== TEST: FileSystemManager_listStorages_with_invalid_error_callbacks
+//==== LABEL Check if FileSystemManager::listStorages() method throws exception for wrong type of onerror (literals)
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:listStorages M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MC
+var t = async_test('FileSystemManager_listStorages_with_invalid_error_callbacks'),
+    invalidTypeParams = [123, "abc", true, {}], getStorageSuccess, i;
+t.step(function () {
+    getStorageSuccess = t.step_func(function (storages) {
+        assert_unreached("Unexpected getStorageSuccess");
+    });
+
+    for (i = 0; i < invalidTypeParams.length; i++) {
+        assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+            tizen.filesystem.listStorages(
+                getStorageSuccess,
+                invalidTypeParams[i]
+            );
+        });
+    }
+    t.done();
+});
+
+}
+
+function FileSystemManager_listStorages_with_onerror() {
+
+//==== TEST: FileSystemManager_listStorages_with_onerror
+//==== PRIORITY P1
+//==== LABEL Check if FileSystemManager::listStorages() can be called with onerror argument
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:listStorages M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MOA MR
+
+var t = async_test('FileSystemManager_listStorages_with_onerror'),
+    listStoragesSuccess, listStoragesError, retValue = null;
+
+t.step(function () {
+
+    listStoragesSuccess = t.step_func(function (storages) {
+        assert_type(storages, "array", "incorrect type of the received argument");
+        assert_true(storages.length > 0, "incorrect received argument");
+        assert_equals(retValue, undefined, "listStorages returns wrong value");
+        t.done();
+    });
+
+    listStoragesError = t.step_func(function (error) {
+        assert_unreached("listStorages() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    retValue = tizen.filesystem.listStorages(listStoragesSuccess, listStoragesError);
+});
+
+}
+
+function FileSystemManager_listStorages_without_arguments() {
+//==== TEST: FileSystemManager_listStorages_without_arguments
+//==== LABEL Check if FileSystemManager::listStorages() method throws exception for missing mandatory argument
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:listStorages M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MMA
+
+test(function () {
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        tizen.filesystem.listStorages();
+    });
+}, 'FileSystemManager_listStorages_without_arguments');
+
+}
+
+function FileSystemManager_listStorages_works_correctly() {
+
+//==== TEST: FileSystemManager_listStorages_works_correctly
+//==== LABEL Check if FileSystemManager::listStorages() method invokes onsuccess callback
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:listStorages M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MOA
+var t = async_test('FileSystemManager_listStorages_works_correctly'),
+    listStoragesSuccess, listStoragesError;
+
+t.step(function () {
+    listStoragesSuccess = t.step_func(function (storages) {
+        assert_type(storages, "array", "storages");
+        assert_true(storages.length > 0, "storages.length > 0");
+        t.done();
+    });
+    listStoragesError = t.step_func(function (error) {
+        assert_unreached("listStorages() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    tizen.filesystem.listStorages(listStoragesSuccess, listStoragesError);
+});
+
+}
+
+function FileSystemManager_maxPathLength_attribute() {
+
+//==== TEST: FileSystemManager_maxPathLength_attribute
+//==== PRIORITY P1
+//==== LABEL Check if FileSystemManager::maxPathLength attribute exists
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:maxPathLength A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var maxLength = tizen.filesystem.maxPathLength;
+    assert_true("maxPathLength" in tizen.filesystem, "attribute doesn't exist");
+    check_readonly(tizen.filesystem, "maxPathLength", maxLength, "long", maxLength - 5);
+}, 'FileSystemManager_maxPathLength_attribute');
+
+}
+
+function FileSystemManager_notexist() {
+//==== TEST: FileSystemManager_notexist
+//==== PRIORITY P3
+//==== LABEL Interface FileSystemManager should not be accessible
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:FileSystemManager U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("FileSystemManager");
+}, 'FileSystemManager_notexist');
+
+}
+
+function FileSystemManager_removeStorageStateChangeListener() {
+//==== TEST: FileSystemManager_removeStorageStateChangeListener
+//==== LABEL Check if FileSystemManager::removeStorageStateChangeListener() method works with only mandatory arguments
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:removeStorageStateChangeListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MMINA MR
+
+var t = async_test('FileSystemManager_removeStorageStateChangeListener'),
+    successCallback, watch, retValue = null;
+
+t.step(function () {
+    successCallback = t.step_func(function (storages) {
+        retValue = tizen.filesystem.removeStorageStateChangeListener(watch);
+        assert_equals(retValue, undefined, "removeStorageStateChangeListener returns wrong value");
+
+        t.done();
+    });
+
+    watch = tizen.filesystem.addStorageStateChangeListener(successCallback);
+});
+
+}
+
+function FileSystemManager_removeStorageStateChangeListener_exist() {
+//==== TEST: FileSystemManager_removeStorageStateChangeListener_exist
+//==== LABEL Check if FileSystemManager::removeStorageStateChangeListener() method exists
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:removeStorageStateChangeListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA ME
+
+test(function () {
+    assert_true("removeStorageStateChangeListener" in tizen.filesystem,
+        "No removeStorageStateChangeListener method in tizen.filesystem");
+    check_method_exists(tizen.filesystem,
+        "removeStorageStateChangeListener");
+}, 'FileSystemManager_removeStorageStateChangeListener_exist');
+
+}
+
+function FileSystemManager_removeStorageStateChangeListener_works_correctly() {
+
+//==== TEST: FileSystemManager_removeStorageStateChangeListener_works_correctly
+//==== LABEL Check if FileSystemManager::removeStorageStateChangeListener() method can be called with valid watchId
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:removeStorageStateChangeListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MMINA
+test(function () {
+    var watchId;
+
+    watchId = tizen.filesystem.addStorageStateChangeListener(function (storage) {});
+    tizen.filesystem.removeStorageStateChangeListener(watchId);
+
+}, 'FileSystemManager_removeStorageStateChangeListener_works_correctly');
+
+}
+
+function FileSystemManager_resolve() {
+
+//==== TEST: FileSystemManager_resolve
+//==== PRIORITY P1
+//==== LABEL Check if FileSystemManager::resolve() method can be called with only mandatory argument
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:resolve M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MMINA MR
+
+var t = async_test('FileSystemManager_resolve'),
+    resolveSuccess, retValue = null;
+t.step(function () {
+    resolveSuccess = t.step_func(function (storage) {
+        assert_not_equals(storage, null, "Null check");
+        assert_equals(retValue, undefined, "resolve returns wrong value");
+
+        t.done();
+    });
+
+    retValue = tizen.filesystem.resolve("documents", resolveSuccess);
+});
+
+}
+
+function FileSystemManager_resolve_documents() {
+//==== TEST: FileSystemManager_resolve_documents
+//==== LABEL Check if FileSystemManager::resolve() method works for Documents virtual root
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:resolve M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MOA
+
+
+var resolveSuccess, resolveError, expected = "documents",
+    t = async_test('FileSystemManager_resolve_documents');
+
+t.step(function () {
+    resolveSuccess = t.step_func(function (dir) {
+        assert_equals(dir.path, expected, "resolve documents to a file handle");
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+});
+
+}
+
+function FileSystemManager_resolve_downloads() {
+//==== TEST: FileSystemManager_resolve_downloads
+//==== LABEL Check if FileSystemManager::resolve() method works for Downloads virtual root
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:resolve M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MOA
+
+
+var resolveSuccess, resolveError, expected = "downloads",
+    t = async_test('FileSystemManager_resolve_downloads');
+
+t.step(function () {
+    resolveSuccess = t.step_func(function (dir) {
+        assert_equals(dir.path , expected, "resolve downloads to a file handle");
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    tizen.filesystem.resolve("downloads", resolveSuccess, resolveError, "rw");
+});
+
+}
+
+function FileSystemManager_resolve_error_invoked() {
+
+//==== TEST: FileSystemManager_resolve_error_invoked
+//==== PRIORITY P2
+//==== LABEL Check if FileSystemManager::resolve() method reports NotFoundError by onerror for wrong value of location argument (absolute)
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:resolve M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MOA MERRCB
+
+var t = async_test('FileSystemManager_resolve_error_invoked'),
+    resolveSuccess, resolveError;
+t.step(function () {
+    resolveSuccess = t.step_func(function (dir) {
+        assert_unreached("this function shouldn't be invoked");
+    });
+    resolveError = t.step_func(function (error) {
+        assert_equals(error.name, "NotFoundError", "incorrect error was thrown");
+        t.done();
+    });
+
+    tizen.filesystem.resolve("/notExistingDirectory", resolveSuccess, resolveError);
+});
+
+}
+
+function FileSystemManager_resolve_exist() {
+
+//==== TEST: FileSystemManager_resolve_exist
+//==== PRIORITY P0
+//==== LABEL Check if FileSystemManager::resolve() method exists
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:resolve M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA ME
+
+test(function () {
+    assert_true("resolve" in tizen.filesystem, "FileSystemManager has resolve method");
+    check_method_exists(tizen.filesystem, "resolve");
+}, 'FileSystemManager_resolve_exist');
+
+}
+
+function FileSystemManager_resolve_images() {
+
+//==== TEST: FileSystemManager_resolve_images
+//==== LABEL Check if FileSystemManager::resolve() method works for Images virtual root
+//==== SPEC: Tizen Web API:IO:Filesystem:FileSystemManager:resolve M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MOA
+
+var resolveSuccess, resolveError, expected = "images",
+    t = async_test('FileSystemManager_resolve_images');
+
+t.step(function (){
+    resolveSuccess = t.step_func(function (dir) {
+        assert_equals(dir.path, expected, "resolve images to a file handle");
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    tizen.filesystem.resolve("images", resolveSuccess, resolveError, "rw");
+});
+
+}
+
+function FileSystemManager_resolve_missarg() {
+
+//==== TEST: FileSystemManager_resolve_missarg
+//==== LABEL Check if FileSystemManager::resolve() throws exception for missing mandatory argument
+//==== PRIORITY P0
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:resolve M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MMA
+
+test(function () {
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        tizen.filesystem.resolve();
+    }, "Method should throw an exception");
+}, 'FileSystemManager_resolve_missarg');
+
+}
+
+function FileSystemManager_resolve_mode_TypeMismatch() {
+
+//==== TEST: FileSystemManager_resolve_mode_TypeMismatch
+//==== PRIORITY P2
+//==== LABEL Check if FileSystemManager::resolve() method throws exception for wrong value of mode argument
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:resolve M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MC
+
+var t = async_test('FileSystemManager_resolve_mode_TypeMismatch'),
+    conversionTable, resolveSuccess, resolveError, mode, exceptionName, i;
+
+t.step(function () {
+    resolveSuccess = t.step_func(function (dir) {
+        assert_unreached("resolveSuccess was invoked");
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    conversionTable = getTypeConversionExceptions("enum", true);
+    for (i = 0; i < conversionTable.length; i++) {
+        mode = conversionTable[i][0];
+        //mode is nullable parameter so null should not throw (skip this case
+        if (mode === null){
+            continue;
+        }
+        exceptionName = conversionTable[i][1];
+
+        assert_throws({name: exceptionName},
+            function () {
+                tizen.filesystem.resolve("images", resolveSuccess, resolveError, mode);
+            }, exceptionName + " should be thrown - given incorrect errorCallback.");
+    }
+    t.done();
+});
+
+}
+
+function FileSystemManager_resolve_mode_a() {
+//==== TEST: FileSystemManager_resolve_mode_a
+//==== LABEL Check if FileSystemManager::resolve() method works for Documents virtual root and mode 'a'
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:resolve M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MOA
+
+
+var resolveSuccess, resolveError, expected = "documents",
+    t = async_test('FileSystemManager_resolve_mode_a');
+
+t.step(function (){
+    resolveSuccess = t.step_func(function (dir) {
+        assert_equals(dir.path, expected, "resolve a location with 'a' mode");
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "a");
+});
+
+}
+
+function FileSystemManager_resolve_mode_r() {
+//==== TEST: FileSystemManager_resolve_mode_r
+//==== LABEL Check if FileSystemManager::resolve() method works for Documents virtual root and mode 'r'
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:resolve M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MOA
+
+
+var resolveSuccess, resolveError, expected = "documents",
+    t = async_test('FileSystemManager_resolve_mode_r');
+
+t.step(function (){
+    resolveSuccess = t.step_func(function (dir) {
+        assert_equals(dir.path , expected, "resolve a location with an mode r");
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "r");
+});
+
+}
+
+function FileSystemManager_resolve_mode_w() {
+//==== TEST: FileSystemManager_resolve_mode_w
+//==== LABEL Check if FileSystemManager::resolve() method works for Documents virtual root and mode 'w'
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:resolve M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MOA
+
+
+var resolveSuccess, resolveError, expected = "documents",
+    t = async_test('FileSystemManager_resolve_mode_w');
+
+t.step(function (){
+    resolveSuccess = t.step_func(function (dir) {
+        assert_equals(dir.path , expected, "resolve a location with an mode w");
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "w");
+});
+
+}
+
+function FileSystemManager_resolve_music() {
+//==== TEST: FileSystemManager_resolve_music
+//==== LABEL Check if FileSystemManager::resolve() method works for Music virtual root
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:resolve M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MOA
+
+
+var resolveSuccess, resolveError, expected = "music",
+    t = async_test('FileSystemManager_resolve_music');
+
+t.step(function (){
+    resolveSuccess = t.step_func(function (dir) {
+        assert_equals(dir.path , expected, "resolve music to a file handle");
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    tizen.filesystem.resolve("music", resolveSuccess, resolveError, "rw");
+});
+
+}
+
+function FileSystemManager_resolve_onerror_TypeMismatch() {
+
+//==== TEST: FileSystemManager_resolve_onerror_TypeMismatch
+//==== PRIORITY P2
+//==== LABEL Check if FileSystemManager::resolve() method throws exception for wrong type of onerror
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:resolve M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MC
+
+var t = async_test('FileSystemManager_resolve_onerror_TypeMismatch'), i,
+    resolveSuccess, resolveError, exceptionName, conversionTable;
+t.step(function () {
+    conversionTable = getTypeConversionExceptions("functionObject", true);
+
+    resolveSuccess = t.step_func(function (dir) {
+        assert_unreached("this function shouldn't be invoked");
+    });
+
+    for(i = 0; i < conversionTable.length; i++) {
+        resolveError = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+
+        assert_throws({name: exceptionName},
+            function () {
+                tizen.filesystem.resolve("images", resolveSuccess, resolveError);
+            }, exceptionName + " should be thrown - given incorrect errorCallback.");
+    }
+    t.done();
+});
+
+}
+
+function FileSystemManager_resolve_onerror_invalid_cb() {
+
+//==== TEST: FileSystemManager_resolve_onerror_invalid_cb
+//==== PRIORITY P2
+//==== LABEL Check if FileSystemManager::resolve() method throws exception for wrong onerror
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:resolve M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MTCB
+
+var t = async_test('FileSystemManager_resolve_onerror_invalid_cb'),
+    resolveError, resolveSuccess, conversionTable;
+
+t.step(function () {
+    conversionTable = getTypeConversionExceptions("functionObject", true);
+    resolveSuccess = t.step_func(function (storage) {
+    });
+    resolveError = {
+        onerror: t.step_func(function (){
+            assert_unreached("Invalid callback invoked: ");
+        })
+    };
+    assert_throws(TYPE_MISMATCH_EXCEPTION,
+        function () {
+            tizen.filesystem.resolve("images", resolveSuccess, resolveError, "rw");
+        }, "given incorrect errorCallback");
+    t.done();
+});
+
+}
+
+function FileSystemManager_resolve_onsuccess_TypeMismatch() {
+
+//==== TEST: FileSystemManager_resolve_onsuccess_TypeMismatch
+//==== PRIORITY P2
+//==== LABEL Check if FileSystemManager::resolve() method throws exception for wrong type of onsuccess
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:resolve M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MC
+
+var t = async_test('FileSystemManager_resolve_onsuccess_TypeMismatch'), i,
+    resolveSuccess, resolveError, exceptionName, conversionTable;
+
+t.step(function () {
+    conversionTable = getTypeConversionExceptions("functionObject", false);
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    for (i = 0; i < conversionTable.length; i++) {
+        resolveSuccess = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+
+        assert_throws({name: exceptionName},
+            function () {
+                tizen.filesystem.resolve("documents", resolveSuccess, resolveError);
+            }, exceptionName + " should be thrown - given incorrect onSuccess.");
+    }
+    t.done();
+});
+
+}
+
+function FileSystemManager_resolve_onsuccess_invalid_cb() {
+
+//==== TEST: FileSystemManager_resolve_onsuccess_invalid_cb
+//==== PRIORITY P2
+//==== LABEL Check if FileSystemManager::resolve() method throws exception for wrong onsuccess
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:resolve M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MTCB
+
+var t = async_test('FileSystemManager_resolve_onsuccess_invalid_cb'),
+    resolveSuccess, resolveError;
+
+t.step(function () {
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    resolveSuccess = {
+        onsuccess: t.step_func(function (){
+            assert_unreached("Invalid callback invoked: ");
+        })
+    };
+
+    assert_throws(TYPE_MISMATCH_EXCEPTION,
+        function () {
+            tizen.filesystem.resolve("documents", resolveSuccess, resolveError);
+        }, "given incorrect error callback");
+    t.done();
+});
+
+}
+
+function FileSystemManager_resolve_ringtones() {
+
+//==== TEST: FileSystemManager_resolve_ringtones
+//==== LABEL Check if FileSystemManager::resolve() method works for Ringtones virtual root
+//==== SPEC: Tizen Web API:IO:Filesystem:FileSystemManager:resolve M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MOA
+
+var resolveSuccess, resolveError, expected = "ringtones",
+    t = async_test('FileSystemManager_resolve_ringtones');
+
+t.step(function (){
+    resolveSuccess = t.step_func(function (dir) {
+        assert_equals(dir.path, expected, "resolve ringtones to a file handle");
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    tizen.filesystem.resolve("ringtones", resolveSuccess, resolveError, "r");
+});
+
+}
+
+function FileSystemManager_resolve_ringtones_invalid_mode_a() {
+//==== TEST: FileSystemManager_resolve_ringtones_invalid_mode_a
+//==== LABEL Check if FileSystemManager::resolve() method reports InvalidValuesError when resolving Ringtones directory with mode 'a'
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:resolve M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA
+
+var resolveSuccess, resolveError,
+    t = async_test('FileSystemManager_resolve_ringtones_invalid_mode_a');
+
+t.step(function () {
+    resolveSuccess = t.step_func(function (dir) {
+        assert_unreached("this function shouldn't be invoked");
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_equals(error.name, "InvalidValuesError", "error.name");
+        t.done();
+    });
+
+    tizen.filesystem.resolve("ringtones", resolveSuccess, resolveError, "a");
+
+});
+
+}
+
+function FileSystemManager_resolve_ringtones_invalid_mode_rw() {
+//==== TEST: FileSystemManager_resolve_ringtones_invalid_mode_rw
+//==== LABEL Check if FileSystemManager::resolve() method reports InvalidValuesError when resolving Ringtones directory with mode 'rw'
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:resolve M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA
+
+var resolveSuccess, resolveError,
+    t = async_test('FileSystemManager_resolve_ringtones_invalid_mode_rw');
+
+t.step(function () {
+    resolveSuccess = t.step_func(function (dir) {
+        assert_unreached("this function shouldn't be invoked");
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_equals(error.name, "InvalidValuesError", "error.name");
+        t.done();
+    });
+
+    tizen.filesystem.resolve("ringtones", resolveSuccess, resolveError, "rw");
+
+});
+
+}
+
+function FileSystemManager_resolve_ringtones_invalid_mode_w() {
+//==== TEST: FileSystemManager_resolve_ringtones_invalid_mode_w
+//==== LABEL Check if FileSystemManager::resolve() method reports InvalidValuesError when resolving Ringtones directory with mode 'w'
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:resolve M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA
+
+var resolveSuccess, resolveError,
+    t = async_test('FileSystemManager_resolve_ringtones_invalid_mode_w');
+
+t.step(function () {
+    resolveSuccess = t.step_func(function (dir) {
+        assert_unreached("this function shouldn't be invoked");
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_equals(error.name, "InvalidValuesError", "error.name");
+        t.done();
+    });
+
+    tizen.filesystem.resolve("ringtones", resolveSuccess, resolveError, "w");
+
+});
+
+}
+
+function FileSystemManager_resolve_videos() {
+//==== TEST: FileSystemManager_resolve_videos
+//==== LABEL Check if FileSystemManager::resolve() method works for Videos virtual root
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:resolve M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MOA
+
+
+var expected = "videos", resolveSuccess, resolveError,
+    t = async_test('FileSystemManager_resolve_videos');
+
+t.step(function (){
+    resolveSuccess = t.step_func(function (dir) {
+        assert_equals(dir.path , expected, "resolve videos to a file handle");
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    tizen.filesystem.resolve("videos", resolveSuccess, resolveError, "rw");
+});
+
+}
+
+function FileSystemManager_resolve_wgt_package_invalid_mode_a() {
+//==== TEST: FileSystemManager_resolve_wgt-package_invalid_mode_a
+//==== LABEL Check if FileSystemManager::resolve() method reports InvalidValuesError when resolving 'wgt-package' directory with mode 'a'
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:resolve M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA
+
+var resolveSuccess, resolveError,
+    t = async_test('FileSystemManager_resolve_wgt_package_invalid_mode_a');
+
+t.step(function () {
+    resolveSuccess = t.step_func(function (dir) {
+        assert_unreached("this function shouldn't be invoked");
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_equals(error.name, "InvalidValuesError", "error.name");
+        t.done();
+    });
+
+    tizen.filesystem.resolve("wgt-package", resolveSuccess, resolveError, "a");
+
+});
+
+}
+
+function FileSystemManager_resolve_wgt_package_invalid_mode_rw() {
+//==== TEST: FileSystemManager_resolve_wgt-package_invalid_mode_rw
+//==== LABEL Check if FileSystemManager::resolve() method reports InvalidValuesError when resolving 'wgt-package' directory with mode 'rw'
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:resolve M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA
+
+var resolveSuccess, resolveError,
+    t = async_test('FileSystemManager_resolve_wgt_package_invalid_mode_rw');
+
+t.step(function () {
+    resolveSuccess = t.step_func(function (dir) {
+        assert_unreached("this function shouldn't be invoked");
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_equals(error.name, "InvalidValuesError", "error.name");
+        t.done();
+    });
+
+    tizen.filesystem.resolve("wgt-package", resolveSuccess, resolveError, "rw");
+
+});
+
+}
+
+function FileSystemManager_resolve_wgt_package_invalid_mode_w() {
+//==== TEST: FileSystemManager_resolve_wgt-package_invalid_mode_w
+//==== LABEL Check if FileSystemManager::resolve() method reports InvalidValuesError when resolving 'wgt-package' directory with mode 'w'
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:resolve M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA
+
+var resolveSuccess, resolveError,
+    t = async_test('FileSystemManager_resolve_wgt_package_invalid_mode_w');
+
+t.step(function () {
+    resolveSuccess = t.step_func(function (dir) {
+        assert_unreached("this function shouldn't be invoked");
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_equals(error.name, "InvalidValuesError", "error.name");
+        t.done();
+    });
+
+    tizen.filesystem.resolve("wgt-package", resolveSuccess, resolveError, "w");
+
+});
+
+}
+
+function FileSystemManager_resolve_wgt_package() {
+
+//==== TEST: FileSystemManager_resolve_wgt_package
+//==== LABEL Check if FileSystemManager::resolve() method works for 'wgt-package' virtual root
+//==== SPEC: Tizen Web API:IO:Filesystem:FileSystemManager:resolve M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MOA
+
+var resolveSuccess, resolveError, expected = "wgt-package",
+    t = async_test('FileSystemManager_resolve_wgt_package');
+
+t.step(function (){
+    resolveSuccess = t.step_func(function (dir) {
+        assert_equals(dir.path, expected, "resolve wgt-package to a file handle");
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    tizen.filesystem.resolve("wgt-package", resolveSuccess, resolveError, "r");
+});
+
+}
+
+function FileSystemManager_resolve_wgt_private() {
+
+//==== TEST: FileSystemManager_resolve_wgt_private
+//==== LABEL Check if FileSystemManager::resolve() method works for 'wgt-private' virtual root
+//==== SPEC: Tizen Web API:IO:Filesystem:FileSystemManager:resolve M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MOA
+
+var resolveSuccess, resolveError, expected = "wgt-private",
+    t = async_test('FileSystemManager_resolve_wgt_private');
+
+t.step(function (){
+    resolveSuccess = t.step_func(function (dir) {
+        assert_equals(dir.path, expected, "resolve wgt-private to a file handle");
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    tizen.filesystem.resolve("wgt-private", resolveSuccess, resolveError, "rw");
+});
+
+}
+
+function FileSystemManager_resolve_wgt_private_tmp() {
+
+//==== TEST: FileSystemManager_resolve_wgt_private_tmp
+//==== LABEL Check if FileSystemManager::resolve() method works for 'wgt-private-tmp' virtual root
+//==== SPEC: Tizen Web API:IO:Filesystem:FileSystemManager:resolve M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MOA
+
+var resolveSuccess, resolveError, expected = "wgt-private-tmp",
+    t = async_test('FileSystemManager_resolve_wgt_private_tmp');
+
+t.step(function (){
+    resolveSuccess = t.step_func(function (dir) {
+        assert_equals(dir.path, expected, "resolve wgt-private-tmp to a file handle");
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    tizen.filesystem.resolve("wgt-private-tmp", resolveSuccess, resolveError, "rw");
+});
+
+}
+
+function FileSystemManager_resolve_with_mode() {
+
+//==== TEST: FileSystemManager_resolve_with_mode
+//==== PRIORITY P1
+//==== LABEL Check if FileSystemManager::resolve() method works for Images virtual root with mode 'rw'
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:resolve M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MOA
+
+var t = async_test('FileSystemManager_resolve_with_mode'),
+    resolveSuccess, resolveError, expected;
+t.step(function () {
+    resolveSuccess = t.step_func(function (dir) {
+        expected="images";
+        assert_equals(dir.path, expected, "resolve a location to a file handle");
+        t.done();
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    tizen.filesystem.resolve("images", resolveSuccess, resolveError, "rw");
+});
+
+}
+
+function FileSystemManager_resolve_with_onerror() {
+
+//==== TEST: FileSystemManager_resolve_with_onerror
+//==== PRIORITY P2
+//==== LABEL Check if FileSystemManager::resolve() method can be called with onerror argument
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:resolve M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MOA
+
+var t = async_test('FileSystemManager_resolve_with_onerror'),
+    resolveSuccess, resolveError;
+t.step(function (){
+    resolveSuccess = t.step_func(function (storage) {
+        t.done();
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    tizen.filesystem.resolve("images", resolveSuccess, resolveError);
+});
+
+}
+
+function FileSystemManager_resolve_works_correctly() {
+
+//==== TEST: FileSystemManager_resolve_works_correctly
+//==== LABEL Check if FileSystemManager::resolve() method works for Documents and onsuccess is invoked with proper argument
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:resolve M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MOA
+
+var t = async_test('FileSystemManager_resolve_works_correctly'),
+    resolveSuccess, resolveError;
+
+t.step(function () {
+    resolveSuccess = t.step_func(function (dir) {
+        assert_true("parent" in dir, "parent don't exist in object");
+        assert_type(dir.parent, "null", "parent should be null");
+        assert_true("readOnly" in dir, "readOnly don't exist in object");
+        assert_false(dir.readOnly, "value of readOnly should be equal to false");
+        assert_true("isDirectory" in dir, "isDirectory don't exist in object");
+        assert_true(dir.isDirectory, "value of isDirectory should be equal to true");
+        assert_true("isFile" in dir, "isFile don't exist in object");
+        assert_false(dir.isFile, "value of isFile should be equal to true");
+        assert_true("created" in dir, "created don't exist in object");
+        assert_true("modified" in dir, "modified don't exist in object");
+        assert_true("name" in dir, "name don't exist in object");
+        assert_equals(dir.name, "", "value of name should be equal to empty string");
+        assert_true("path" in dir, "path don't exist in object");
+        assert_equals(dir.path, "documents", "value of path should be equal to string 'documents'");
+        assert_true("fullPath" in dir, "fullPath don't exist in object");
+        assert_equals(dir.fullPath, "documents", "value of fullPath should be equal to string 'documents'");
+        assert_true("fileSize" in dir, "fileSize don't exist in object");
+        assert_type(dir.fileSize, "undefined", "fileSize should be undefined");
+        assert_true("length" in dir, "length don't exist in object");
+        assert_type(dir.length, "long", "type of length should be number");
+        assert_true(dir.length >= 0, "value of length should be >= 0");
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    tizen.filesystem.resolve("documents", resolveSuccess, resolveError);
+});
+
+}
+
+function FileSystemStorageArraySuccessCallback_notexist() {
+//==== TEST: FileSystemStorageArraySuccessCallback_notexist
+//==== LABEL Interface FileSystemStorageArraySuccessCallback should not be accessible
+//==== PRIORITY: P3
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemStorageArraySuccessCallback:FileSystemStorageArraySuccessCallback U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA CBNIO
+test(function () {
+    check_no_interface_object("FileSystemStorageArraySuccessCallback");
+}, 'FileSystemStorageArraySuccessCallback_notexist');
+
+}
+
+function FileSystemStorageArraySuccessCallback_onsuccess() {
+
+//==== TEST: FileSystemStorageArraySuccessCallback_onsuccess
+//==== LABEL Test whether FileSystemStorageArraySuccessCallback::onsuccess is called with valid argument
+//==== PRIORITY: P1
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemStorageArraySuccessCallback:onsuccess M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA CBOA CBT
+
+var t = async_test('FileSystemStorageArraySuccessCallback_onsuccess'),
+    listStoragesSuccess, listStoragesError, i;
+t.step(function () {
+    listStoragesSuccess = t.step_func(function (storages) {
+        assert_type(storages, "Array", "wrong argument");
+        assert_true(storages.length > 0, "no available storage");
+        for (i = 0; i < storages.length; i++) {
+            assert_type(storages[i], "object", "wrong element of the argument");
+            assert_true("label" in storages[i], "label don't exist in object");
+            assert_true("type" in storages[i], "type don't exist in object");
+            assert_true("state" in storages[i], "state don't exist in object");
+        }
+        t.done();
+    });
+    listStoragesError = t.step_func(function (error) {
+        assert_unreached("listStorages() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    tizen.filesystem.listStorages(listStoragesSuccess, listStoragesError);
+});
+
+}
+
+function FileSystemStorageSuccessCallback_notexist() {
+//==== TEST: FileSystemStorageSuccessCallback_notexist
+//==== LABEL Interface FileSystemStorageSuccessCallback should not be accessible
+//==== PRIORITY: P3
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemStorageSuccessCallback:FileSystemStorageSuccessCallback U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA CBNIO
+test(function () {
+    check_no_interface_object("FileSystemStorageSuccessCallback");
+}, 'FileSystemStorageSuccessCallback_notexist');
+
+}
+
+function FileSystemStorageSuccessCallback_onsuccess() {
+
+//==== TEST: FileSystemStorageSuccessCallback_onsuccess
+//==== LABEL Test whether FileSystemStorageSuccessCallback::onsuccess is called with valid argument
+//==== PRIORITY: P1
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemStorageSuccessCallback:onsuccess M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA CBOA CBT
+
+var t = async_test('FileSystemStorageSuccessCallback_onsuccess'),
+    listStoragesSuccess, listStoragesError, getStorageSuccess;
+
+t.step(function () {
+    getStorageSuccess = t.step_func(function (storage) {
+        assert_type(storage, "object", "wrong argument");
+        assert_true("label" in storage, "label don't exist in object");
+        assert_true("type" in storage, "type don't exist in object");
+        assert_true("state" in storage, "state don't exist in object");
+        t.done();
+    });
+
+    listStoragesSuccess = t.step_func(function (storages) {
+        tizen.filesystem.getStorage(storages[0].label, getStorageSuccess);
+    });
+
+    listStoragesError = t.step_func(function (error) {
+        assert_unreached("listStorages() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    tizen.filesystem.listStorages(listStoragesSuccess, listStoragesError);
+});
+
+}
+
+function FileSystemStorage_extend() {
+
+//==== TEST: FileSystemStorage_extend
+//==== LABEL Check if instance of FileSystemStorage object can be extended with new attribute
+//==== PRIORITY: P3
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemStorage:FileSystemStorage U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA OBX
+
+var t = async_test('FileSystemStorage_extend'), listStoragesSuccess;
+
+t.step(function () {
+    listStoragesSuccess = t.step_func(function (storages) {
+        assert_true(storages.length > 0, "No available storage");
+        check_extensibility(storages[0]);
+        t.done();
+    });
+
+    tizen.filesystem.listStorages(listStoragesSuccess);
+});
+
+}
+
+function FileSystemStorage_label_attribute() {
+
+//==== TEST: FileSystemStorage_label_attribute
+//==== LABEL Check if FileSystemStorage::label attribute exists, has type DOMString and is readonly
+//==== SPEC: Tizen Web API:IO:Filesystem:FileSystemStorage:label A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA AE AT ARO
+
+var t = async_test('FileSystemStorage_label_attribute'), listStoragesSuccess;
+t.step(function () {
+    listStoragesSuccess = t.step_func(function (storages) {
+        assert_true(storages.length > 0, "No available storage");
+        assert_true("label" in storages[0], "label not in FileSystemStorage");
+        check_readonly(storages[0], "label", storages[0].label, "string", storages[0].label + "dummyValue");
+        t.done();
+    });
+
+    tizen.filesystem.listStorages(listStoragesSuccess);
+});
+
+}
+
+function FileSystemStorage_notexist() {
+//==== TEST: FileSystemStorage_notexist
+//==== LABEL Interface FileSystemStorage should not be accessible
+//==== PRIORITY: P3
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemStorage:FileSystemStorage U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA NIO
+test(function () {
+    check_no_interface_object("FileSystemStorage");
+}, 'FileSystemStorage_notexist');
+
+}
+
+function FileSystemStorage_state_attribute() {
+
+//==== TEST: FileSystemStorage_state_attribute
+//==== LABEL Check if FileSystemStorage::state attribute exists, has type FileSystemStorageState and is readonly
+//==== SPEC: Tizen Web API:IO:Filesystem:FileSystemStorage:state A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA AE AT ARO
+
+var t = async_test('FileSystemStorage_state_attribute'), listStoragesSuccess, valueToAssign;
+
+t.step(function () {
+    listStoragesSuccess = t.step_func(function (storages) {
+        assert_true(storages.length > 0, "No available storage");
+        assert_true("state" in storages[0], "state not in FileSystemStorage");
+        assert_in_array(storages[0].state, ["MOUNTED", "REMOVED", "UNMOUNTABLE"], "incorrect value of state");
+        if (storages[0].state === "MOUNTED") {
+            valueToAssign = "REMOVED";
+        } else if (storages[0].state === "REMOVED") {
+            valueToAssign = "UNMOUNTABLE";
+        } else {
+            valueToAssign = "MOUNTED";
+        }
+        check_readonly(storages[0], "state", storages[0].state, "string", valueToAssign);
+        t.done();
+    });
+
+    tizen.filesystem.listStorages(listStoragesSuccess);
+});
+
+}
+
+function FileSystemStorage_type_attribute() {
+
+//==== TEST: FileSystemStorage_type_attribute
+//==== LABEL Check if FileSystemStorage::type attribute exists, has type FileSystemStorageType and is readonly
+//==== SPEC: Tizen Web API:IO:Filesystem:FileSystemStorage:type A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA AE AT ARO
+
+var t = async_test('FileSystemStorage_type_attribute'), listStoragesSuccess, valueToAssign;
+
+t.step(function () {
+    listStoragesSuccess = t.step_func(function (storages) {
+        assert_true(storages.length > 0, "No available storage");
+        assert_true("type" in storages[0], "type not in FileSystemStorage");
+        assert_in_array(storages[0].type, ["INTERNAL", "EXTERNAL"], "incorrect value of type");
+        if (storages[0].type === "INTERNAL") {
+            valueToAssign = "EXTERNAL";
+        } else {
+            valueToAssign = "INTERNAL";
+        }
+        check_readonly(storages[0], "type", storages[0].type, "string", valueToAssign);
+        t.done();
+    });
+
+    tizen.filesystem.listStorages(listStoragesSuccess);
+});
+
+}
+
+function File_copyTo() {
+//==== TEST: File_copyTo
+//==== LABEL Check if File::copyTo() method ends successfully (copy file from documents/ to images/)
+//==== SPEC: Tizen Web API:IO:Filesystem:File:copyTo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MMINA
+
+var t = async_test('File_copyTo'), resolveSuccess, resolveError, fsTestFile, fsTestFileName;
+
+t.step(function (){
+    fsTestFileName =  getFileName("filesystem.txt");
+
+    resolveSuccess = t.step_func(function (dir) {
+        fsTestFile = dir.createFile(fsTestFileName);
+        dir.copyTo(fsTestFile.fullPath, "images/" + fsTestFile.name, true);
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+
+});
+
+}
+
+function File_copyTo_dir_overwrite_false() {
+//==== TEST: File_copyTo_dir_overwrite_false
+//==== LABEL Check if error callback is invoked when copy a directory to another location where directory of that name already exists (overwrite is false)
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:File:copyTo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MERRCB
+
+
+var resolveSuccess, resolveError, copySuccess, copyError, fsTestDir1, fsTestDirName1, fsTestSubDir1, fsTestSubDirName1,
+    fsTestDir2, fsTestDirName2, fsTestSubDir2, expected = "IOError",
+    t = async_test('File_copyTo_dir_overwrite_false');
+
+t.step(function () {
+    fsTestDirName1 = getDirName("filesystem1");
+    fsTestSubDirName1 = getDirName("filesystem1sub");
+    fsTestDirName2 = getDirName("filesystem2");
+
+    copySuccess = t.step_func(function () {
+        assert_unreached("copySuccess callback shouldn't be invoked");
+    });
+
+    copyError = t.step_func(function (error) {
+        assert_equals(error.name, expected, "wrong error type");
+        t.done();
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        fsTestDir1 = dir.createDirectory(fsTestDirName1);
+        fsTestSubDir1 = fsTestDir1.createDirectory(fsTestSubDirName1);
+        fsTestDir2 = dir.createDirectory(fsTestDirName2);
+        fsTestSubDir2 = fsTestDir2.createDirectory(fsTestSubDirName1);
+        fsTestDir1.copyTo(fsTestSubDir1.fullPath, fsTestSubDir2.path, false, copySuccess, copyError);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_copyTo_dir_overwrite_true() {
+//==== TEST: File_copyTo_dir_overwrite_true
+//==== LABEL Check if you can copy a directory to another location where directory of that name already exists (overwrite is true)
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:File:copyTo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MOA
+
+
+var resolveSuccess, resolveError, copySuccess, fsTestDir1, fsTestDirName1, fsTestSubDir1, fsTestSubDirName1,
+    fsTestDir2, fsTestDirName2, fsTestSubDir2, copyError,
+    t = async_test('File_copyTo_dir_overwrite_true');
+
+t.step(function () {
+    fsTestDirName1 = getDirName("filesystem1");
+    fsTestSubDirName1 = getDirName("filesystem1sub");
+    fsTestDirName2 = getDirName("filesystem2");
+
+    copySuccess = t.step_func(function () {
+        t.done();
+    });
+
+    copyError = t.step_func(function (error) {
+        assert_unreached("copyTo() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        fsTestDir1 = dir.createDirectory(fsTestDirName1);
+        fsTestSubDir1 = fsTestDir1.createDirectory(fsTestSubDirName1);
+        fsTestDir2 = dir.createDirectory(fsTestDirName2);
+        fsTestSubDir2 = fsTestDir2.createDirectory(fsTestSubDirName1);
+        fsTestDir1.copyTo(fsTestSubDir1.fullPath, fsTestSubDir2.path, true, copySuccess, copyError);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_copyTo_dir_samedir_samename_overwrite_false() {
+//==== TEST: File_copyTo_dir_samedir_samename_overwrite_false
+//==== LABEL Check if error callback is invoked when copy directory dir1/subdir1 into dir1/ (overwrite is false)
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:File:copyTo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MERRCB
+
+
+var resolveSuccess, resolveError, copySuccess, copyError, fsTestDir1, fsTestDirName1, fsTestSubDir1,
+    fsTestSubDirName1, expected = "IOError",
+    t = async_test('File_copyTo_dir_samedir_samename_overwrite_false');
+
+t.step(function () {
+    fsTestDirName1 = getDirName("filesystem1");
+    fsTestSubDirName1 = getDirName("filesystem1sub");
+
+    copySuccess = t.step_func(function () {
+        assert_unreached("copySuccess callback shouldn't be invoked");
+    });
+
+    copyError = t.step_func(function (error) {
+        assert_equals(error.name, expected, "wrong error type");
+        t.done();
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        fsTestDir1 = dir.createDirectory(fsTestDirName1);
+        fsTestSubDir1 = fsTestDir1.createDirectory(fsTestSubDirName1);
+        fsTestDir1.copyTo(fsTestSubDir1.fullPath, fsTestSubDir1.path, false, copySuccess, copyError);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_copyTo_dir_samedir_samename_overwrite_true() {
+//==== TEST: File_copyTo_dir_samedir_samename_overwrite_true
+//==== LABEL Check if error callback is invoked when copy directory dir1/subdir1 into dir1/ (overwrite is true)
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:File:copyTo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MERRCB
+
+
+var resolveSuccess, resolveError, copySuccess, fsTestDir1, fsTestDirName1, fsTestSubDir1, fsTestSubDirName1,
+    t = async_test('File_copyTo_dir_samedir_samename_overwrite_true'), copyError, expectedError = "IOError";
+
+t.step(function () {
+    fsTestDirName1 = getDirName("filesystem1");
+    fsTestSubDirName1 = getDirName("filesystem1sub");
+
+    copySuccess = t.step_func(function () {
+        assert_unreached("copySuccess callback shouldn't be invoked");
+    });
+
+    copyError = t.step_func(function (error) {
+        assert_equals(error.name, expectedError, "wrong error type");
+        t.done();
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        fsTestDir1 = dir.createDirectory(fsTestDirName1);
+        fsTestSubDir1 = fsTestDir1.createDirectory(fsTestSubDirName1);
+        fsTestDir1.copyTo(fsTestSubDir1.fullPath, fsTestSubDir1.path, true, copySuccess, copyError);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_copyTo_exist() {
+
+//==== TEST: File_copyTo_exist
+//==== LABEL Check if File::copyTo() method exists
+//==== PRIORITY P0
+//==== SPEC Tizen Web API:IO:Filesystem:File:copyTo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA ME
+
+var t = async_test('File_copyTo_exist'), resolveSuccess, resolveError;
+
+t.step(function () {
+    resolveSuccess = t.step_func(function (dir) {
+        assert_true("copyTo" in dir, "method copyTo exists");
+        check_method_exists(dir, "copyTo");
+        t.done();
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+
+});
+
+}
+
+function File_copyTo_file_overwrite_false() {
+//==== TEST: File_copyTo_file_overwrite_false
+//==== LABEL Check if error callback is invoked when copy a file to another directory where a file of that name already exists (overwrite is false)
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:File:copyTo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MERRCB
+
+var t = async_test('File_copyTo_file_overwrite_false'), expected = "IOError",
+    resolveSuccess, resolveError, copySuccess, copyError, fsTestFile, fsTestFileName, fsTestDir,
+    fsTestDirName, fsTestSubDir1, fsTestSubDirName1, fsTestSubDir2, fsTestSubDirName2;
+
+t.step(function () {
+    fsTestDirName = getFileName("filesystem");
+    fsTestSubDirName1 = getFileName("filesystem1sub");
+    fsTestSubDirName2 = getFileName("filesystem2sub");
+    fsTestFileName =  getFileName("filesystem.txt");
+
+    copySuccess = t.step_func(function () {
+        assert_unreached("copySuccess callback shouldn't be invoked");
+    });
+
+    copyError = t.step_func(function (error) {
+        assert_equals(error.name, expected, "wrong error type");
+        t.done();
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        fsTestDir = dir.createDirectory(fsTestDirName);
+        fsTestSubDir1 = fsTestDir.createDirectory(fsTestSubDirName1);
+        fsTestSubDir2 = fsTestDir.createDirectory(fsTestSubDirName2);
+        fsTestFile = fsTestSubDir1.createFile(fsTestFileName);
+        fsTestSubDir2.createFile(fsTestFileName);
+        fsTestSubDir1.copyTo(fsTestFile.fullPath, fsTestSubDir2.fullPath, false, copySuccess, copyError);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_copyTo_file_overwrite_true() {
+//==== TEST: File_copyTo_file_overwrite_true
+//==== LABEL Check if you can copy a file to another directory where a file of that name already exists (overwrite is true)
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:File:copyTo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MOA
+
+var t = async_test('File_copyTo_file_overwrite_true'),
+    resolveSuccess, resolveError, copySuccess, fsTestFile, fsTestFileName, fsTestDir, copyError,
+    fsTestDirName, fsTestSubDir1, fsTestSubDirName1, fsTestSubDir2, fsTestSubDirName2;
+
+t.step(function () {
+    fsTestDirName = getFileName("filesystem");
+    fsTestSubDirName1 = getFileName("filesystem1sub");
+    fsTestSubDirName2 = getFileName("filesystem2sub");
+    fsTestFileName =  getFileName("filesystem.txt");
+
+    copySuccess = t.step_func(function () {
+        t.done();
+    });
+
+    copyError = t.step_func(function (error) {
+        assert_unreached("copyTo() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        fsTestDir = dir.createDirectory(fsTestDirName);
+        fsTestSubDir1 = fsTestDir.createDirectory(fsTestSubDirName1);
+        fsTestSubDir2 = fsTestDir.createDirectory(fsTestSubDirName2);
+        fsTestFile = fsTestSubDir1.createFile(fsTestFileName);
+        fsTestSubDir2.createFile(fsTestFileName);
+        fsTestSubDir1.copyTo(fsTestFile.fullPath, fsTestSubDir2.fullPath, true, copySuccess, copyError);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_copyTo_file_samedir_samename_overwrite_false() {
+//==== TEST: File_copyTo_file_samedir_samename_overwrite_false
+//==== LABEL Check if error callback is invoked when copy a file to the same location (overwrite is false)
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:File:copyTo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MERRCB
+
+
+var t = async_test('File_copyTo_file_samedir_samename_overwrite_false'), expectedError = "IOError",
+    resolveSuccess, resolveError, copySuccess, copyError, fsTestFile, fsTestFileName, fsTestDir, fsTestDirName;
+
+t.step(function () {
+    fsTestDirName = getFileName("filesystem");
+    fsTestFileName =  getFileName("filesystem.txt");
+
+    copySuccess = t.step_func(function () {
+        assert_unreached("copySuccess callback shouldn't be invoked");
+    });
+
+    copyError = t.step_func(function (error) {
+        assert_equals(error.name, expectedError, "wrong error type");
+        t.done();
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        fsTestDir = dir.createDirectory(fsTestDirName);
+        fsTestFile = fsTestDir.createFile(fsTestFileName);
+        fsTestDir.copyTo(fsTestFile.fullPath, fsTestFile.fullPath, false, copySuccess, copyError);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_copyTo_file_samedir_samename_overwrite_true() {
+//==== TEST: File_copyTo_file_samedir_samename_overwrite_true
+//==== LABEL Check if error callback is invoked when copy a file to the same location (overwrite is true)
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:File:copyTo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MERRCB
+
+var t = async_test('File_copyTo_file_samedir_samename_overwrite_true'), resolveSuccess, copyError,
+    resolveError, copySuccess, fsTestFile, fsTestFileName, fsTestDir, fsTestDirName, expectedError = "IOError";
+
+t.step(function () {
+    fsTestDirName = getFileName("filesystem");
+    fsTestFileName =  getFileName("filesystem.txt");
+
+    copySuccess = t.step_func(function () {
+        assert_unreached("copySuccess callback shouldn't be invoked");
+    });
+
+    copyError = t.step_func(function (error) {
+        assert_equals(error.name, expectedError, "wrong error type");
+        t.done();
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        fsTestDir = dir.createDirectory(fsTestDirName);
+        fsTestFile = fsTestDir.createFile(fsTestFileName);
+        fsTestDir.copyTo(fsTestFile.fullPath, fsTestFile.path, true, copySuccess, copyError);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_copyTo_onerror_TypeMismatch() {
+
+//==== TEST: File_copyTo_onerror_TypeMismatch
+//==== LABEL Check if File::copyTo() throws exception when type of errorCallback is wrong
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:IO:Filesystem:File:copyTo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MC
+
+var t = async_test('File_copyTo_onerror_TypeMismatch'),
+    resolveSuccess, resolveError, conversionTable, copyError, i, copySuccess, fsTestFileName,
+    exceptionName = "TypeMismatchError";
+
+t.step(function () {
+    fsTestFileName =  getFileName("filesystem.txt");
+
+    copySuccess = t.step_func(function () {
+        assert_unreached("successCalback should not be called");
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        conversionTable = getTypeConversionExceptions("functionObject", true);
+        for (i = 0; i < conversionTable.length; i++) {
+            copyError = conversionTable[i][0];
+            exceptionName = conversionTable[i][1];
+
+            assert_throws({name: exceptionName},
+                function () {
+                    dir.copyTo(fsTestFileName, "images", true, copySuccess, copyError);
+                }, exceptionName + " should be thrown - given incorrect errorCallback.");
+        }
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_copyTo_onerror_invalid_cb() {
+
+//==== TEST: File_copyTo_onerror_invalid_cb
+//==== LABEL Check if File::copyTo() throws exception for wrong errorCallback
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:IO:Filesystem:File:copyTo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MTCB
+
+var t = async_test('File_copyTo_onerror_invalid_cb'), resolveSuccess, resolveError,
+    copySuccess, copyError, fsTestFileName;
+
+t.step(function () {
+    fsTestFileName =  getFileName("filesystem.txt");
+
+    copyError = {
+        onerror: t.step_func(function () {
+            assert_unreached("Invalid callback invoked: ");
+        })
+    };
+
+    copySuccess = t.step_func(function () {
+        assert_unreached("successCallback should not be called");
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        assert_throws(TYPE_MISMATCH_EXCEPTION,
+            function () {
+                dir.copyTo(fsTestFileName, "images", true, copySuccess, copyError);
+            }, "given incorrect errorCallback");
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_copyTo_onsuccess_TypeMismatch() {
+
+//==== TEST: File_copyTo_onsuccess_TypeMismatch
+//==== LABEL Check if File::copyTo() throws exception when type of successCallback is wrong
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:IO:Filesystem:File:copyTo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MC
+
+var t = async_test('File_copyTo_onsuccess_TypeMismatch'), copySuccess,
+    resolveSuccess, resolveError, conversionTable, i, exceptionName = "TypeMismatchError", fsTestFile, fsTestFileName;
+
+t.step(function (){
+    fsTestFileName =  getFileName("filesystem.txt");
+
+    resolveSuccess = t.step_func(function (dir) {
+        fsTestFile = dir.createFile(fsTestFileName);
+        conversionTable = getTypeConversionExceptions("functionObject", true);
+        for (i = 0; i < conversionTable.length; i++) {
+            copySuccess = conversionTable[i][0];
+            exceptionName = conversionTable[i][1];
+
+            assert_throws({name: exceptionName},
+                function () {
+                    dir.copyTo(fsTestFile.fullPath, "images", true, copySuccess);
+                }, exceptionName + " should be thrown - given incorrect successCallback.");
+        }
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+
+});
+
+}
+
+function File_copyTo_onsuccess_invalid_cb() {
+
+//==== TEST: File_copyTo_onsuccess_invalid_cb
+//==== LABEL Check if File::copyTo() throws exception for wrong successCallback
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:IO:Filesystem:File:copyTo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MTCB
+
+var t = async_test('File_copyTo_onsuccess_invalid_cb'),
+    resolveSuccess, resolveError, copySuccess, fsTestFile, fsTestFileName;
+
+t.step(function (){
+    fsTestFileName =  getFileName("filesystem.txt");
+
+    copySuccess = {
+        onsuccess: t.step_func(function () {
+            assert_unreached("Invalid callback invoked");
+        })
+    };
+
+    resolveSuccess = t.step_func(function (dir) {
+        fsTestFile = dir.createFile(fsTestFileName);
+        assert_throws(TYPE_MISMATCH_EXCEPTION,
+            function () {
+                dir.copyTo(fsTestFile.fullPath, "images", true, copySuccess);
+            }, "given incorrect successCallback");
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_copyTo_with_file_handle() {
+//==== TEST: File_copyTo_with_file_handle
+//==== LABEL Check if File::copyTo() calls errorCallback when called for object representing file, not a directory
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:File:copyTo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MERRCB
+
+var resolveSuccess, resolveError, copySuccess, copyError, fsTestFile, fsTestFileName, fsTestDir, fsTestDirName,
+    expectedError ="IOError", t = async_test('File_copyTo_with_file_handle');
+
+t.step(function () {
+    fsTestDirName = getFileName("filesystem");
+    fsTestFileName = getFileName("filesystem.txt");
+
+    copySuccess = t.step_func(function () {
+        assert_unreached("copySuccess callback shouldn't be invoked");
+    });
+
+    copyError = t.step_func(function (error) {
+        assert_equals(error.name, expectedError, "wrong error type");
+        t.done();
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        fsTestDir = dir.createDirectory(fsTestDirName);
+        fsTestFile = dir.createFile(fsTestFileName);
+        fsTestFile.copyTo(fsTestFile.fullPath, fsTestDir.fullPath, true, copySuccess, copyError);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+
+});
+
+}
+
+function File_copyTo_with_null_success_and_error_callbacks() {
+
+//==== TEST: File_copyTo_with_null_success_and_error_callbacks
+//==== LABEL Check if File::copyTo() can be invoked with null successCallback and errorCallback
+//==== SPEC Tizen Web API:IO:Filesystem:File:copyTo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MMINA
+
+var t = async_test('File_copyTo_with_null_success_and_error_callbacks'), resolveSuccess, resolveError, fsTestFile, fsTestFileName1, fsTestFileName2,
+    copyPath;
+
+t.step(function () {
+
+    fsTestFileName1 =  getFileName("filesystem1.txt");
+    fsTestFileName2 =  getFileName("filesystem2.txt");
+
+    resolveSuccess = t.step_func(function (dir) {
+        fsTestFile = dir.createFile(fsTestFileName1);
+        copyPath = dir.fullPath + "/" + fsTestFileName2;
+        dir.copyTo(fsTestFile.fullPath, copyPath, false, null, null);
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve(TEST_ROOT_LOCATION, resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_copyTo_with_onerror() {
+
+//==== TEST: File_copyTo_with_onerror
+//==== LABEL Check if File::copyTo() calls errorCallback (nonexisting originFilePath)
+//==== SPEC: Tizen Web API:IO:Filesystem:File:copyTo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MOA
+
+var t = async_test('File_copyTo_with_onerror'),
+    resolveSuccess, resolveError, copyToSuccess, copyToError, fsTestFileName;
+
+t.step(function (){
+    fsTestFileName =  getFileName("notexistingfile.txt");
+
+    copyToError = t.step_func(function () {
+        t.done();
+    });
+
+    copyToSuccess = t.step_func(function () {
+        assert_unreached("copyToError callback should be called");
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        dir.copyTo(fsTestFileName, "images/" + fsTestFileName, true, copyToSuccess, copyToError);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+
+});
+
+}
+
+function File_copyTo_with_onsuccess() {
+
+//==== TEST: File_copyTo_with_onsuccess
+//==== LABEL Check if File::copyTo() with onSuccess creates a file copy
+//==== SPEC: Tizen Web API:IO:Filesystem:File:copyTo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MAST MR
+
+var t = async_test('File_copyTo_with_onsuccess'), resolveSuccess, resolveError, resolveSuccess2, resolveError2,
+    fsTestFileName, fsTestFile, copyToSuccess, retVal = null;
+
+t.step(function () {
+    fsTestFileName =  getFileName("filesystem.txt");
+
+    resolveSuccess2 = t.step_func(function (dir) {
+        fsTestFile = dir.resolve(fsTestFileName);
+        assert_equals(fsTestFile.name, fsTestFileName, "file wasn't copied properly");
+        assert_true(fsTestFile.isFile, "file wasn't copied properly");
+        t.done();
+    });
+
+    resolveError2 = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    copyToSuccess = t.step_func(function () {
+        assert_equals(retVal, undefined, "incorrect returned value");
+        tizen.filesystem.resolve("images", resolveSuccess2, resolveError2, "rw");
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        fsTestFile = dir.createFile(fsTestFileName);
+        retVal = dir.copyTo(fsTestFile.fullPath, "images/" + fsTestFile.name, true, copyToSuccess);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+
+});
+
+}
+
+function File_copyTo_writeFile_newName() {
+//==== TEST: File_copyTo_writeFile_newName
+//==== LABEL Check if you can create a new empty file, write content into it, then request a copy of it (different name, same directory)
+//==== SPEC Tizen Web API:IO:Filesystem:File:copyTo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MOA
+
+
+var resolveSuccess, resolveError, copySuccess, copyError, openStreamSuccess, openStreamError,
+    fsTestFileName, fsTestFileName2, fsTestFile, fsTestDirName, fsTestDir,
+    t = async_test('File_copyTo_writeFile_newName');
+
+t.step(function () {
+    fsTestFileName = getFileName("filesystem.txt");
+    fsTestFileName2 = getFileName("filesystem2.txt");
+    fsTestDirName = getDirName("filesystem");
+
+    copyError = t.step_func(function (error) {
+        assert_unreached("copyTo() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    copySuccess = t.step_func(function () {
+        t.done();
+    });
+
+    openStreamError = t.step_func(function (error) {
+        assert_unreached("openStream() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    openStreamSuccess = t.step_func(function (fs) {
+        fs.write("test");
+        fs.close();
+        fsTestDir.copyTo(fsTestFile.fullPath, fsTestDir.fullPath + "/" + fsTestFileName2, true, copySuccess, copyError);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        fsTestDir = dir.createDirectory(fsTestDirName);
+        fsTestFile = fsTestDir.createFile(fsTestFileName);
+        fsTestFile.openStream("rw", openStreamSuccess, openStreamError, "UTF-8");
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+
+});
+
+}
+
+function File_copyTo_writeFile_overwrite_false() {
+//==== TEST: File_copyTo_writeFile_overwrite_false
+//==== LABEL Check if when create a new empty file, write content into it, then request a copy of it over existing file invokes errorCallback (overwrite=false)
+//==== SPEC Tizen Web API:IO:Filesystem:File:copyTo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MERRCB
+
+
+var t = async_test('File_copyTo_writeFile_overwrite_false'), resolveSuccess, resolveError,
+    openStreamSuccess, openStreamError, copyToSuccess, copyToError, fsTestFileName,
+    fsTestFile, fsTestDirName, fsTestDir, expectedError = "IOError", mainDir;
+
+t.step(function () {
+    fsTestFileName = getFileName("filesystem.txt");
+    fsTestDirName = getDirName("filesystem");
+
+    copyToSuccess = t.step_func(function () {
+        assert_unreached("copyToSuccess callback shouldn't be invoked");
+    });
+
+    copyToError = t.step_func(function (error) {
+        assert_equals(error.name, expectedError, "wrong error type");
+        t.done();
+    });
+
+    openStreamSuccess = t.step_func(function (fs) {
+        fs.write("test");
+        fs.close();
+        mainDir.copyTo(fsTestFile.fullPath, fsTestDir.fullPath + "/" + fsTestFile.name, false, copyToSuccess, copyToError);
+    });
+
+    openStreamError = t.step_func(function (error) {
+        assert_unreached("openStream() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        mainDir = dir;
+        fsTestFile = dir.createFile(fsTestFileName);
+        fsTestDir = dir.createDirectory(fsTestDirName);
+        fsTestDir.createFile(fsTestFileName);
+        fsTestFile.openStream("rw", openStreamSuccess, openStreamError, "UTF-8");
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+
+});
+
+}
+
+function File_copyTo_writeFile_subdir() {
+//==== TEST: File_copyTo_writeFile_subdir
+//==== LABEL Check if you can create a new empty file, write content into it, then request a copy of it (different name, different directory)
+//==== SPEC Tizen Web API:IO:Filesystem:File:copyTo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MOA
+
+
+var resolveSuccess, resolveError, openStreamSuccess, openStreamError, copySuccess, copyError, fsTestFileName, fsTestFile,
+    fsTestDir, fsTestDirName, fsTestSubDir, fsTestSubDirName, t = async_test('File_copyTo_writeFile_subdir');
+
+t.step(function () {
+    fsTestFileName = getFileName("filesystem.txt");
+    fsTestDirName = getDirName("filesystem");
+    fsTestSubDirName = getDirName("filesystemSub");
+
+    copySuccess = t.step_func(function () {
+        t.done();
+    });
+
+    copyError = t.step_func(function (error) {
+        assert_unreached("copyTo() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    openStreamSuccess = t.step_func(function (fs) {
+        fs.write("test");
+        fs.close();
+        fsTestDir.copyTo(fsTestFile.fullPath, fsTestSubDir.fullPath + "/" + fsTestFile.name, true, copySuccess, copyError);
+    });
+
+    openStreamError = t.step_func(function (error) {
+        assert_unreached("openStream() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        fsTestDir = dir.createDirectory(fsTestDirName);
+        fsTestSubDir = fsTestDir.createDirectory(fsTestSubDirName);
+        fsTestFile = fsTestDir.createFile(fsTestFileName);
+        fsTestFile.openStream("rw", openStreamSuccess, openStreamError, "UTF-8");
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+
+});
+
+}
+
+function File_createDirectory() {
+
+//==== TEST: File_createDirectory
+//==== LABEL Check if File::createDirectory() method
+//==== SPEC: Tizen Web API:IO:Filesystem:File:createDirectory M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MAST MMINA MR
+
+var t = async_test('File_createDirectory'),
+    resolveSuccess, resolveError, fsTestDir, fsTestDirName;
+
+t.step(function () {
+    fsTestDirName = getDirName("filesystem");
+
+    resolveSuccess = t.step_func(function (dir) {
+        fsTestDir = dir.createDirectory(fsTestDirName);
+        assert_type(fsTestDir, "object", "directory wasn't created properly");
+        checkOwnProperties(fsTestDir);
+        assert_equals(fsTestDir.name, fsTestDirName, "directory wasn't created properly");
+        assert_true(fsTestDir.isDirectory, "directory wasn't created properly");
+        fsTestDir = dir.resolve(fsTestDirName);
+        assert_equals(fsTestDir.name, fsTestDirName, "directory wasn't created properly");
+        assert_true(fsTestDir.isDirectory, "directory wasn't created properly");
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+
+});
+
+}
+
+function File_createDirectory_exist() {
+
+//==== TEST: File_createDirectory_exist
+//==== LABEL Check if File::createDirectory() method exists
+//==== PRIORITY P0
+//==== SPEC Tizen Web API:IO:Filesystem:File:createDirectory M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA ME
+
+var t = async_test('File_createDirectory_exist'),
+    resolveSuccess, resolveError;
+
+t.step(function () {
+    resolveSuccess = t.step_func(function (dir) {
+        assert_true("createDirectory" in dir, "method createDirectory exists");
+        check_method_exists(dir, "createDirectory");
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("Error: " + error.message);
+    });
+
+    tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+});
+
+}
+
+function File_createDirectory_level2() {
+//==== TEST: File_createDirectory_level2
+//==== LABEL Check if File::createDirectory() works for non-existing intermediate directory (creates 2 levels of directories)
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:File:createDirectory M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MAST
+
+var t = async_test('File_createDirectory_level2'), resolveSuccess, resolveError, listFilesSuccess, listFilesError, documentsDir,
+    fsTestDir, fsTestDirName, fsTestSubDir, fsTestSubDirName;
+
+t.step(function (){
+
+    fsTestDirName = getDirName("filesystem");
+    fsTestSubDirName = getDirName("filesystemSub");
+
+    listFilesSuccess = t.step_func(function (files) {
+        assert_true(files.length === 1, "Subdirectory not found.");
+        assert_equals(files[0].name, fsTestSubDirName, "Unexpected subdirectory name: " + files[0].name);
+        t.done();
+    });
+
+    listFilesError = t.step_func(function (error) {
+        assert_unreached("listFiles() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        documentsDir = dir;
+        fsTestSubDir = dir.createDirectory(fsTestDirName + "/" + fsTestSubDirName);
+        fsTestDir = dir.resolve(fsTestDirName);
+        fsTestDir.listFiles(listFilesSuccess, listFilesError);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+
+});
+
+}
+
+function File_createFile() {
+
+//==== TEST: File_createFile
+//==== LABEL Check if File::createFile() method works properly
+//==== SPEC: Tizen Web API:IO:Filesystem:File:createFile M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MAST MMINA MR
+
+var t = async_test('File_createFile'),
+    resolveSuccess, resolveError, fsTestFileName, fsTestFile;
+
+t.step(function () {
+    fsTestFileName =  getFileName("filesystem.txt");
+
+    resolveSuccess = t.step_func(function (dir) {
+        fsTestFile = dir.createFile(fsTestFileName);
+        assert_type(fsTestFile, "object", "file wasn't created properly");
+        checkOwnProperties(fsTestFile);
+        assert_equals(fsTestFile.name, fsTestFileName, "file wasn't created properly");
+        assert_true(fsTestFile.isFile, "file wasn't created properly");
+        fsTestFile = dir.resolve(fsTestFileName);
+        assert_equals(fsTestFile.name, fsTestFileName, "file wasn't created properly");
+        assert_true(fsTestFile.isFile, "file wasn't created properly");
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+
+});
+
+}
+
+function File_createFile_exist() {
+
+//==== TEST: File_createFile_exist
+//==== LABEL Check if File::createFile() method exists
+//==== PRIORITY P0
+//==== SPEC Tizen Web API:IO:Filesystem:File:createFile M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA ME
+
+var t = async_test('File_createFile_exist'),
+    resolveSuccess, resolveError;
+
+t.step(function (){
+    resolveSuccess = t.step_func(function (dir) {
+        assert_true("createFile" in dir, "method createFile exists");
+        check_method_exists(dir, "createFile");
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+});
+
+}
+
+function File_createFile_existing_file() {
+
+//==== TEST: File_createFile_existing_file
+//==== LABEL Check if File::createFile() throws exception when the file already exists
+//==== SPEC Tizen Web API:IO:Filesystem:File:createFile M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MMINA MAST
+
+var t = async_test('File_createFile_existing_file'), expected = "IOError",
+    resolveSuccess, resolveError, fsTestFileName;
+
+t.step(function () {
+    fsTestFileName = getFileName("filesystem");
+
+    resolveSuccess = t.step_func(function (dir) {
+        dir.createFile(fsTestFileName);
+        assert_throws({name: expected}, function () {
+                dir.createFile(fsTestFileName);
+            }, expected + " should be thrown");
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+
+});
+
+}
+
+function File_created_attribute() {
+
+//==== TEST: File_created_attribute
+//==== LABEL Check if File::created attribute exists, has type Date and is readonly
+//==== SPEC: Tizen Web API:IO:Filesystem:File:created A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA AE AT ARO
+
+var t = async_test('File_created_attribute'),
+    resolveSuccess, resolveError, fsTestFileName, fsTestFile, date, tmp;
+
+t.step(function (){
+    fsTestFileName =  getFileName("filesystem.txt");
+
+    resolveSuccess = t.step_func(function (dir) {
+        date = new Date();
+        fsTestFile = dir.createFile(fsTestFileName);
+        assert_own_property(fsTestFile, "created", "File does not own created property.");
+        assert_true("created" in fsTestFile, "attribute created doesn't exist in provided object.");
+        assert_type(fsTestFile.created, "Date", "Type of created is different.");
+        tmp = fsTestFile.created;
+        fsTestFile.created = new Date();
+        assert_equals(tmp.getTime(), fsTestFile.created.getTime(), "created can be modified.");
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+
+});
+
+}
+
+function File_deleteDirectory() {
+
+//==== TEST: File_deleteDirectory
+//==== LABEL Check if File::deleteDirectory() method can be called
+//==== SPEC: Tizen Web API:IO:Filesystem:File:deleteDirectory M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MMINA
+
+var t = async_test('File_deleteDirectory'), resolveSuccess, resolveError, fsTestDirName, fsTestDir;
+
+t.step(function (){
+
+    fsTestDirName =  getDirName("filesystem");
+
+    resolveSuccess = t.step_func(function (dir) {
+        fsTestDir = dir.createDirectory(fsTestDirName);
+        dir.deleteDirectory(fsTestDir.fullPath, true);
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+
+});
+
+}
+
+function File_deleteDirectory_createDir_documents() {
+//==== TEST: File_deleteDirectory_createDir_documents
+//==== LABEL Check if File::createDirectory() creates a new directory in Documents and File::deleteDirectory() removes it
+//==== SPEC Tizen Web API:IO:Filesystem:File:deleteDirectory M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MOA
+
+var fsTestDirName, fsTestDir, resolveSuccess, resolveError, deleteSuccess, deleteError, documentsDir,
+    t = async_test('File_deleteDirectory_createDir_documents');
+
+t.step(function (){
+    fsTestDirName =  getDirName("filesystem");
+
+    deleteSuccess = t.step_func(function () {
+        assert_throws(NOT_FOUND_EXCEPTION, function () {
+            documentsDir.resolve(fsTestDirName);
+        }, "directory wasn't deleted properly");
+        t.done();
+    });
+
+    deleteError = t.step_func(function (error) {
+        assert_unreached("deleteDirectory() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        documentsDir = dir;
+        fsTestDir = dir.createDirectory(fsTestDirName);
+        dir.deleteDirectory(fsTestDir.fullPath, true, deleteSuccess, deleteError);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_deleteDirectory_createDir_downloads() {
+//==== TEST: File_deleteDirectory_createDir_downloads
+//==== LABEL Check if File::createDirectory() creates a new directory in Downloads and File::deleteDirectory() removes it
+//==== SPEC Tizen Web API:IO:Filesystem:File:deleteDirectory M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MOA
+
+
+var fsTestDirName, fsTestDir, resolveSuccess, resolveError, deleteSuccess, deleteError, downloadsDir,
+    t = async_test('File_deleteDirectory_createDir_downloads');
+
+t.step(function (){
+    fsTestDirName =  getDirName("filesystem");
+
+    deleteSuccess = t.step_func(function () {
+        assert_throws(NOT_FOUND_EXCEPTION, function () {
+            downloadsDir.resolve(fsTestDirName);
+        }, "directory wasn't deleted properly");
+        t.done();
+    });
+
+    deleteError = t.step_func(function (error) {
+        assert_unreached("deleteDirectory() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        downloadsDir = dir;
+        fsTestDir = dir.createDirectory(fsTestDirName);
+        dir.deleteDirectory(fsTestDir.fullPath, true, deleteSuccess, deleteError);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("downloads", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_deleteDirectory_createDir_images() {
+//==== TEST: File_deleteDirectory_createDir_images
+//==== LABEL Check if File::createDirectory() creates a new directory in Images and File::deleteDirectory() removes it
+//==== PRIORITY P1
+//==== SPEC Tizen Web API:IO:Filesystem:File:deleteDirectory M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MOA
+
+
+var fsTestDirName, fsTestDir, resolveSuccess, resolveError, deleteSuccess, deleteError, imagesDir,
+    t = async_test('File_deleteDirectory_createDir_images');
+
+t.step(function (){
+    fsTestDirName =  getDirName("filesystem");
+
+    deleteSuccess = t.step_func(function () {
+        assert_throws(NOT_FOUND_EXCEPTION, function () {
+            imagesDir.resolve(fsTestDirName);
+        }, "directory wasn't deleted properly");
+        t.done();
+    });
+
+    deleteError = t.step_func(function (error) {
+        assert_unreached("deleteDirectory() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        imagesDir = dir;
+        fsTestDir = dir.createDirectory(fsTestDirName);
+        dir.deleteDirectory(fsTestDir.fullPath, true, deleteSuccess, deleteError);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("images", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_deleteDirectory_createDir_music() {
+//==== TEST: File_deleteDirectory_createDir_music
+//==== LABEL Check if File::createDirectory() creates a new directory in Music and File::deleteDirectory() removes it
+//==== PRIORITY P1
+//==== SPEC Tizen Web API:IO:Filesystem:File:deleteDirectory M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MOA
+
+
+var fsTestDirName, fsTestDir, resolveSuccess, resolveError, deleteSuccess, deleteError, musicDir,
+    t = async_test('File_deleteDirectory_createDir_music');
+
+t.step(function (){
+    fsTestDirName =  getDirName("filesystem");
+
+    deleteSuccess = t.step_func(function () {
+        assert_throws(NOT_FOUND_EXCEPTION, function () {
+            musicDir.resolve(fsTestDirName);
+        }, "directory wasn't deleted properly");
+        t.done();
+    });
+
+    deleteError = t.step_func(function (error) {
+        assert_unreached("deleteDirectory() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        musicDir = dir;
+        fsTestDir = dir.createDirectory(fsTestDirName);
+        dir.deleteDirectory(fsTestDir.fullPath, true, deleteSuccess, deleteError);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("music", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_deleteDirectory_createDir_videos() {
+//==== TEST: File_deleteDirectory_createDir_videos
+//==== LABEL Check if File::createDirectory() creates a new directory in Videos and File::deleteDirectory() removes it
+//==== PRIORITY P1
+//==== SPEC Tizen Web API:IO:Filesystem:File:deleteDirectory M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MOA
+
+var fsTestDirName, fsTestDir, resolveSuccess, resolveError, deleteSuccess, deleteError, videosDir,
+    t = async_test('File_deleteDirectory_createDir_videos');
+
+t.step(function (){
+    fsTestDirName =  getDirName("filesystem");
+
+    deleteSuccess = t.step_func(function () {
+        assert_throws(NOT_FOUND_EXCEPTION, function () {
+            videosDir.resolve(fsTestDirName);
+        }, "directory wasn't deleted properly");
+        t.done();
+    });
+
+    deleteError = t.step_func(function (error) {
+        assert_unreached("deleteDirectory() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        videosDir = dir;
+        fsTestDir = dir.createDirectory(fsTestDirName);
+        dir.deleteDirectory(fsTestDir.fullPath, true, deleteSuccess, deleteError);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("videos", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_deleteDirectory_exist() {
+
+//==== TEST: File_deleteDirectory_exist
+//==== LABEL Check if File::deleteDirectory() method exists
+//==== PRIORITY P0
+//==== SPEC Tizen Web API:IO:Filesystem:File:deleteDirectory M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA ME
+
+var t = async_test('File_deleteDirectory_exist'),
+    resolveSuccess, resolveError;
+
+t.step(function () {
+    resolveSuccess = t.step_func(function (dir) {
+        assert_true("deleteDirectory" in dir, "method deleteDirectory exists");
+        check_method_exists(dir, "deleteDirectory");
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+});
+
+}
+
+function File_deleteDirectory_onerror_TypeMismatch() {
+
+//==== TEST: File_deleteDirectory_onerror_TypeMismatch
+//==== LABEL Check if File::deleteDirectory() throws exception for wrong type of onerror
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:IO:Filesystem:File:deleteDirectory M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MC
+
+var t = async_test('File_deleteDirectory_onerror_TypeMismatch'),
+    resolveSuccess, resolveError, conversionTable, deleteError, i, deleteSuccess, fsTestDirName, fsTestDir,
+    exceptionName = "TypeMismatchError";
+
+t.step(function () {
+    fsTestDirName =  getDirName("filesystem");
+
+    deleteSuccess = t.step_func(function () {
+        assert_unreached("successCalback should not be called");
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        fsTestDir = dir.createDirectory(fsTestDirName);
+        conversionTable = getTypeConversionExceptions("functionObject", true);
+        for (i = 0; i < conversionTable.length; i++) {
+            deleteError = conversionTable[i][0];
+            exceptionName = conversionTable[i][1];
+
+            assert_throws({name: exceptionName},
+                function () {
+                    dir.deleteDirectory(fsTestDir.fullPath, deleteSuccess, deleteError);
+                }, exceptionName + " should be thrown - given incorrect errorCallback.");
+        }
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+
+});
+
+}
+
+function File_deleteDirectory_onerror_invalid_cb() {
+
+//==== TEST: File_deleteDirectory_onerror_invalid_cb
+//==== LABEL Check if File::deleteDirectory() throws exception for wrong onerror
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:IO:Filesystem:File:deleteDirectory M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MTCB
+
+var t = async_test('File_deleteDirectory_onerror_invalid_cb'),
+    resolveSuccess, resolveError, deleteDirectorySuccess, deleteDirectoryError, fsTestDirName, fsTestDir;
+
+t.step(function () {
+    fsTestDirName =  getDirName("filesystem");
+
+    deleteDirectoryError = {
+        onerror: t.step_func(function () {
+            assert_unreached("Invalid callback invoked: ");
+        })
+    };
+
+    deleteDirectorySuccess = t.step_func(function () {
+        assert_unreached("deleteDirectorySuccess should not be called");
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        fsTestDir = dir.createDirectory(fsTestDirName);
+        assert_throws(TYPE_MISMATCH_EXCEPTION,
+            function () {
+                dir.deleteDirectory(fsTestDir.fullPath, deleteDirectorySuccess, deleteDirectoryError);
+            }, "given incorrect errorCallback");
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+
+});
+
+}
+
+function File_deleteDirectory_onsuccess_TypeMismatch() {
+
+//==== TEST: File_deleteDirectory_onsuccess_TypeMismatch
+//==== LABEL Check if File::deleteDirectory() throws exception for wrong type of onsuccess
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:IO:Filesystem:File:deleteDirectory M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MC
+
+var t = async_test('File_deleteDirectory_onsuccess_TypeMismatch'), deleteSuccess,
+    resolveSuccess, resolveError, conversionTable, i, exceptionName = "TypeMismatchError", fsTestDirName, fsTestDir;
+
+t.step(function (){
+    fsTestDirName =  getDirName("filesystem");
+
+    resolveSuccess = t.step_func(function (dir) {
+        fsTestDir = dir.createDirectory(fsTestDirName);
+        conversionTable = getTypeConversionExceptions("functionObject", true);
+        for (i = 0; i < conversionTable.length; i++) {
+            deleteSuccess = conversionTable[i][0];
+            exceptionName = conversionTable[i][1];
+
+            assert_throws({name: exceptionName},
+                function () {
+                    dir.deleteDirectory(fsTestDir.fullPath, false, deleteSuccess);
+                }, exceptionName + " should be thrown - given incorrect successCallback.");
+        }
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+
+});
+
+}
+
+function File_deleteDirectory_onsuccess_invalid_cb() {
+
+//==== TEST: File_deleteDirectory_onsuccess_invalid_cb
+//==== LABEL Check if File::deleteDirectory() throws exception for wrong onsuccess
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:IO:Filesystem:File:deleteDirectory M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MTCB
+
+var t = async_test('File_deleteDirectory_onsuccess_invalid_cb'),
+    resolveSuccess, resolveError, deleteSuccess, fsTestDirName, fsTestDir;
+
+t.step(function (){
+    fsTestDirName =  getDirName("filesystem");
+
+    deleteSuccess = {
+        onsuccess: t.step_func(function () {
+            assert_unreached("Invalid callback invoked: ");
+        })
+    };
+
+    resolveSuccess = t.step_func(function (dir) {
+        fsTestDir = dir.createDirectory(fsTestDirName);
+        assert_throws(TYPE_MISMATCH_EXCEPTION,
+            function () {
+                dir.deleteDirectory(fsTestDir.fullPath, false, deleteSuccess);
+            }, "given incorrect successCallback");
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+
+});
+
+}
+
+function File_deleteDirectory_with_empty_path() {
+
+//==== TEST: File_deleteDirectory_with_empty_path
+//==== LABEL Check if File::deleteDirectory() calls errorCallback when given directoryPath is empty
+//==== SPEC Tizen Web API:IO:Filesystem:File:deleteDirectory M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MERRCB
+
+var t = async_test('File_deleteDirectory_with_empty_path'), resolveError, resolveSuccess, deleteDirectoryError, deleteDirectorySuccess,
+    expected = "NotFoundError";
+
+t.step(function () {
+
+    deleteDirectorySuccess = t.step_func(function () {
+        assert_unreached("deleteDirectorySuccess: deleteDirectory() should invoke error callback");
+    });
+
+    deleteDirectoryError = t.step_func(function (error) {
+        assert_equals(error.name, expected, "expect throw an exception");
+        t.done();
+    });
+
+    resolveSuccess = t.step_func(function (root) {
+        root.deleteDirectory("", false, deleteDirectorySuccess, deleteDirectoryError);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve_root_location() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    tizen.filesystem.resolve(TEST_ROOT_LOCATION, resolveSuccess, resolveError);
+});
+
+}
+
+function File_deleteDirectory_with_file_handle() {
+//==== TEST: File_deleteDirectory_with_file_handle
+//==== LABEL Check if File::deleteDirectory() calls errorCallback when called on File object representing file, not a directory
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:File:deleteDirectory M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MERRCB
+
+
+var resolveSuccess, resolveError, deleteSuccess, deleteError, fsTestFileName, fsTestFile, documentsDir,
+    expected = "InvalidValuesError", t = async_test('File_deleteDirectory_with_file_handle');
+
+t.step(function (){
+    fsTestFileName =  getFileName("filesystem.txt");
+
+    deleteSuccess = t.step_func(function () {
+        assert_unreached("delete a dir with file handle should throw an exception");
+    });
+
+    deleteError = t.step_func(function (error) {
+        fsTestFile = documentsDir.resolve(fsTestFileName);
+        assert_equals(fsTestFile.name, fsTestFileName, "file was deleted");
+        assert_true(fsTestFile.isFile, "file was deleted");
+        assert_equals(error.name, expected, "expect throw an exception");
+        t.done();
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        documentsDir = dir;
+        fsTestFile = dir.createFile(fsTestFileName);
+        dir.deleteDirectory(fsTestFile.fullPath, true, deleteSuccess, deleteError);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+
+});
+
+}
+
+function File_deleteDirectory_with_null_callbacks() {
+
+//==== TEST: File_deleteDirectory_with_null_callbacks
+//==== LABEL Check if File::deleteDirectory() method can be called with null onsuccess and onerror
+//==== SPEC Tizen Web API:IO:Filesystem:File:deleteDirectory M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MMINA
+
+var t = async_test('File_deleteDirectory_with_null_callbacks'), resolveSuccess, resolveError, fsTestDirName, fsTestDir;
+t.step(function () {
+
+    fsTestDirName =  getDirName("filesystem");
+
+    resolveSuccess = t.step_func(function (dir) {
+        fsTestDir = dir.createDirectory(fsTestDirName);
+        dir.deleteDirectory(fsTestDir.fullPath, true, null, null);
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve(TEST_ROOT_LOCATION, resolveSuccess, resolveError, "rw");
+    });
+
+});
+
+}
+
+function File_deleteDirectory_with_onerror() {
+
+//==== TEST: File_deleteDirectory_with_onerror
+//==== LABEL Check if File::deleteDirectory() method calls onerror properly (when removing non-existing directory)
+//==== SPEC: Tizen Web API:IO:Filesystem:File:deleteDirectory M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MERRCB
+
+var resolveSuccess, resolveError, deleteDirectorySuccess, deleteDirectoryError, fsTestDirName,
+    expected = "NotFoundError", t = async_test('File_deleteDirectory_with_onerror');
+
+t.step(function () {
+    fsTestDirName =  getDirName("filesystemNoExist");
+
+    deleteDirectorySuccess = t.step_func(function () {
+        assert_unreached("deleteDirectorySuccess: deleteDirectoryError should be invoked");
+    });
+
+    deleteDirectoryError = t.step_func(function (error) {
+        assert_equals(error.name, expected, "expect throw an exception");
+        t.done();
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        dir.deleteDirectory(fsTestDirName, true, deleteDirectorySuccess, deleteDirectoryError);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+
+});
+
+}
+
+function File_deleteDirectory_with_onsuccess() {
+
+//==== TEST: File_deleteDirectory_with_onsuccess
+//==== LABEL Check if File::deleteDirectory() method with onsuccess optional argument works properly
+//==== SPEC: Tizen Web API:IO:Filesystem:File:deleteDirectory M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MAST MR
+
+var t = async_test('File_deleteDirectory_with_onsuccess'), retVal = null,
+    resolveSuccess, resolveError, deleteSuccess, deleteError, fsTestDirName, fsTestDir, documentsDir;
+
+t.step(function () {
+    fsTestDirName =  getDirName("filesystem");
+
+    deleteSuccess = t.step_func(function () {
+        assert_equals(retVal, undefined, "incorrect returned value");
+        assert_throws(NOT_FOUND_EXCEPTION, function () {
+            documentsDir.resolve(fsTestDirName);
+        }, "directory wasn't deleted properly");
+        t.done();
+    });
+
+    deleteError = t.step_func(function (error) {
+        assert_unreached("deleteDirectory() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        documentsDir = dir;
+        fsTestDir = dir.createDirectory(fsTestDirName);
+        retVal = dir.deleteDirectory(fsTestDir.fullPath, true, deleteSuccess, deleteError);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+
+});
+
+}
+
+function File_deleteFile() {
+
+//==== TEST: File_deleteFile
+//==== LABEL Check if File::deleteFile() method works properly
+//==== SPEC: Tizen Web API:IO:Filesystem:File:deleteFile M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MAST MR
+
+var t = async_test('File_deleteFile'), fsTestFileName, fsTestFile, i, retVal = null,
+    resolveSuccess, resolveError, listFilesSuccess, listFilesError, documentsDir, deleteSuccess;
+t.step(function () {
+    fsTestFileName = getFileName("filesystem.txt");
+
+    listFilesSuccess = t.step_func(function (files) {
+        for (i = 0; i < files.length; i++) {
+            if (files[i].name === fsTestFileName) {
+                assert_unreached("File deletion failed");
+            }
+        }
+        t.done();
+    });
+
+    listFilesError = t.step_func(function (error) {
+        assert_unreached("listFiles() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    deleteSuccess = t.step_func(function () {
+        assert_equals(retVal, undefined, "incorrect returned value");
+        documentsDir.listFiles(listFilesSuccess, listFilesError);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        documentsDir = dir;
+        fsTestFile = dir.createFile(fsTestFileName);
+        retVal = dir.deleteFile(fsTestFile.fullPath, deleteSuccess);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_deleteFile_copyFile_downloads() {
+//==== TEST: File_deleteFile_copyFile_downloads
+//==== LABEL Check if you can create a new file in Document, copy it into Downloads, then request removing it
+//==== SPEC Tizen Web API:IO:Filesystem:File:deleteFile M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MOA
+
+
+var t = async_test('File_deleteFile_copyFile_downloads'), fsTestFileName, fsTestFile,
+    documentsDir, resolveSuccess, resolveError, copyToSuccess, copyToError,
+    deleteFileSuccess, deleteFileError;
+
+t.step(function () {
+    fsTestFileName = getFileName("fileSystem-File01.txt");
+
+    deleteFileSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    deleteFileError = t.step_func(function (error) {
+        assert_unreached("deleteFile() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    copyToSuccess = t.step_func(function () {
+        documentsDir.deleteFile(fsTestFile.fullPath, deleteFileSuccess, deleteFileError);
+    });
+
+    copyToError = t.step_func(function (error) {
+        assert_unreached("copyTo() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        documentsDir = dir;
+        fsTestFile = dir.createFile(fsTestFileName);
+        dir.copyTo(fsTestFile.fullPath, "downloads/", true, copyToSuccess, copyToError);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_deleteFile_copyFile_images() {
+//==== TEST: File_deleteFile_copyFile_images
+//==== LABEL Check if you can create a new file in Images, copy it into Downloads, then request removing it
+//==== SPEC Tizen Web API:IO:Filesystem:File:deleteFile M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MOA
+
+
+var t = async_test('File_deleteFile_copyFile_images'), fsTestFileName, fsTestFile,
+    documentsDir, resolveSuccess, resolveError, copyToSuccess, copyToError,
+    deleteFileSuccess, deleteFileError;
+
+t.step(function () {
+    fsTestFileName = getFileName("fileSystem-File01.png");
+
+    deleteFileSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    deleteFileError = t.step_func(function (error) {
+        assert_unreached("deleteFile() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    copyToSuccess = t.step_func(function () {
+        documentsDir.deleteFile(fsTestFile.fullPath, deleteFileSuccess, deleteFileError);
+    });
+
+    copyToError = t.step_func(function (error) {
+        assert_unreached("copyTo() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        documentsDir = dir;
+        fsTestFile = dir.createFile(fsTestFileName);
+        dir.copyTo(fsTestFile.fullPath, "downloads/", true, copyToSuccess, copyToError);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("images", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_deleteFile_copyFile_music() {
+//==== TEST: File_deleteFile_copyFile_music
+//==== LABEL Check if you can create a new file in Music, copy it into Downloads, then request removing it
+//==== SPEC Tizen Web API:IO:Filesystem:File:deleteFile M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MOA
+
+
+var t = async_test('File_deleteFile_copyFile_music'), fsTestFileName, fsTestFile,
+    documentsDir, resolveSuccess, resolveError, copyToSuccess, copyToError,
+    deleteFileSuccess, deleteFileError;
+
+t.step(function () {
+    fsTestFileName = getFileName("fileSystem-File01.mp3");
+
+    deleteFileSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    deleteFileError = t.step_func(function (error) {
+        assert_unreached("deleteFile() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    copyToSuccess = t.step_func(function () {
+        documentsDir.deleteFile(fsTestFile.fullPath, deleteFileSuccess, deleteFileError);
+    });
+
+    copyToError = t.step_func(function (error) {
+        assert_unreached("copyTo() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        documentsDir = dir;
+        fsTestFile = dir.createFile(fsTestFileName);
+        dir.copyTo(fsTestFile.fullPath, "downloads/", true, copyToSuccess, copyToError);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("music", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_deleteFile_copyFile_videos() {
+//==== TEST: File_deleteFile_copyFile_videos
+//==== LABEL Check if you can create a new file in Video, copy it into Downloads, then request removing it
+//==== SPEC Tizen Web API:IO:Filesystem:File:deleteFile M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MOA
+
+
+var t = async_test('File_deleteFile_copyFile_videos'), fsTestFileName, fsTestFile,
+    documentsDir, resolveSuccess, resolveError, copyToSuccess, copyToError,
+    deleteFileSuccess, deleteFileError;
+
+t.step(function () {
+    fsTestFileName = getFileName("fileSystem-File01.mp3");
+
+    deleteFileSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    deleteFileError = t.step_func(function (error) {
+        assert_unreached("deleteFile() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    copyToSuccess = t.step_func(function () {
+        documentsDir.deleteFile(fsTestFile.fullPath, deleteFileSuccess, deleteFileError);
+    });
+
+    copyToError = t.step_func(function (error) {
+        assert_unreached("copyTo() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        documentsDir = dir;
+        fsTestFile = dir.createFile(fsTestFileName);
+        dir.copyTo(fsTestFile.fullPath, "downloads/", true, copyToSuccess, copyToError);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("videos", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_deleteFile_createFile() {
+//==== TEST: File_deleteFile_createFile
+//==== LABEL Check if you can create a new file in Documents, copy it into Downloads, then request removing it
+//==== SPEC Tizen Web API:IO:Filesystem:File:deleteFile M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MOA
+
+
+var t = async_test('File_deleteFile_createFile'), fsTestFileName, fsTestFile,
+    resolveSuccess, resolveError, deleteFileSuccess, deleteFileError;
+
+t.step(function () {
+    fsTestFileName = getFileName("filesystem.txt");
+
+    deleteFileSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    deleteFileError = t.step_func(function (error) {
+        assert_unreached("deleteFile() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        fsTestFile = dir.createFile(fsTestFileName);
+        dir.deleteFile(fsTestFile.fullPath, deleteFileSuccess, deleteFileError);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_deleteFile_exist() {
+
+//==== TEST: File_deleteFile_exist
+//==== LABEL Check if File::deleteFile() method exists
+//==== PRIORITY P0
+//==== SPEC Tizen Web API:IO:Filesystem:File:deleteFile M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA ME
+
+var t = async_test('File_deleteFile_exist'),
+    resolveSuccess, resolveError;
+
+t.step(function (){
+    resolveSuccess = t.step_func(function (dir) {
+        assert_true("deleteFile" in dir, "method deleteFile exists");
+        check_method_exists(dir, "deleteFile");
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+});
+
+}
+
+function File_deleteFile_listDocumentsFiles() {
+//==== TEST: File_deleteFile_listDocumentsFiles
+//==== LABEL Check if you can create directories and file in Documents, list them, then request deleting the directory and the file
+//==== SPEC Tizen Web API:IO:Filesystem:File:deleteFile M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MOA
+
+
+var t = async_test('File_deleteFile_listDocumentsFiles'), fsTestDirName1, documentsDir,
+    fsTestDirName2, fsTestFileName, fsTestDir1, fsTestDir2, deleteDirError, deleteDirSuccess,
+    fsTestFile, resolveSuccess, resolveError, listFilesSuccess, listFilesError,
+    deleteFileSuccess, deleteFileError;
+
+t.step(function () {
+    fsTestDirName1 = getFileName("filesystem");
+    fsTestDirName2 = getFileName("inside");
+    fsTestFileName = getFileName("filesystem.txt");
+
+    deleteFileSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    deleteFileError = t.step_func(function (error) {
+        assert_unreached("deleteFile() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    deleteDirSuccess = t.step_func(function () {
+        fsTestDir1.deleteFile(fsTestFile.fullPath, deleteFileSuccess, deleteFileError);
+    });
+
+    deleteDirError = t.step_func(function (error) {
+        assert_unreached("deleteDir() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    listFilesSuccess = t.step_func(function (files) {
+        assert_true(files.length > 0, "Files not found");
+        fsTestDir1.deleteDirectory(fsTestDir2.fullPath, true, deleteDirSuccess, deleteDirError);
+    });
+
+    listFilesError = t.step_func(function (error) {
+        assert_unreached("listFiles() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        documentsDir = dir;
+        fsTestDir1 = dir.createDirectory(fsTestDirName1);
+        fsTestFile = fsTestDir1.createFile(fsTestFileName);
+        fsTestDir2 = fsTestDir1.createDirectory(fsTestDirName2);
+        fsTestDir1.listFiles(listFilesSuccess, listFilesError);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_deleteFile_listDownloadsFiles() {
+//==== TEST: File_deleteFile_listDownloadsFiles
+//==== LABEL Check if you can create directories and file in Downloads, list them, then request deleting the directory and the file
+//==== SPEC Tizen Web API:IO:Filesystem:File:deleteFile M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MOA
+
+
+var t = async_test('File_deleteFile_listDownloadsFiles'), fsTestDirName1, documentsDir,
+    fsTestDirName2, fsTestFileName, fsTestDir1, fsTestDir2, deleteDirError, deleteDirSuccess,
+    fsTestFile, resolveSuccess, resolveError, listFilesSuccess, listFilesError,
+    deleteFileSuccess, deleteFileError;
+
+t.step(function () {
+    fsTestDirName1 = getFileName("filesystem");
+    fsTestDirName2 = getFileName("inside");
+    fsTestFileName = getFileName("filesystem.txt");
+
+    deleteFileSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    deleteFileError = t.step_func(function (error) {
+        assert_unreached("deleteFile() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    deleteDirSuccess = t.step_func(function () {
+        fsTestDir1.deleteFile(fsTestFile.fullPath, deleteFileSuccess, deleteFileError);
+    });
+
+    deleteDirError = t.step_func(function (error) {
+        assert_unreached("deleteDir() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    listFilesSuccess = t.step_func(function (files) {
+        assert_true(files.length > 0, "Files not found");
+        fsTestDir1.deleteDirectory(fsTestDir2.fullPath, true, deleteDirSuccess, deleteDirError);
+    });
+
+    listFilesError = t.step_func(function (error) {
+        assert_unreached("listFiles() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        documentsDir = dir;
+        fsTestDir1 = dir.createDirectory(fsTestDirName1);
+        fsTestFile = fsTestDir1.createFile(fsTestFileName);
+        fsTestDir2 = fsTestDir1.createDirectory(fsTestDirName2);
+        fsTestDir1.listFiles(listFilesSuccess, listFilesError);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("downloads", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_deleteFile_listImagsFiles() {
+
+//==== TEST: File_deleteFile_listImagsFiles
+//==== LABEL Check if you can create directories and file in Images, list them, then request deleting the directory and the file
+//==== SPEC Tizen Web API:IO:Filesystem:File:deleteFile M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MOA
+
+
+var t = async_test('File_deleteFile_listImagsFiles'), fsTestDirName1, documentsDir,
+    fsTestDirName2, fsTestFileName, fsTestDir1, fsTestDir2, deleteDirError, deleteDirSuccess,
+    fsTestFile, resolveSuccess, resolveError, listFilesSuccess, listFilesError,
+    deleteFileSuccess, deleteFileError;
+
+t.step(function () {
+    fsTestDirName1 = getDirName("filesystem");
+    fsTestDirName2 = getDirName("inside");
+    fsTestFileName = getFileName("filesystem.txt");
+
+    deleteFileSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    deleteFileError = t.step_func(function (error) {
+        assert_unreached("deleteFile() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    deleteDirSuccess = t.step_func(function () {
+        fsTestDir1.deleteFile(fsTestFile.fullPath, deleteFileSuccess, deleteFileError);
+    });
+
+    deleteDirError = t.step_func(function (error) {
+        assert_unreached("deleteDir() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    listFilesSuccess = t.step_func(function (files) {
+        assert_true(files.length > 0, "Files not found");
+        fsTestDir1.deleteDirectory(fsTestDir2.fullPath, true, deleteDirSuccess, deleteDirError);
+    });
+
+    listFilesError = t.step_func(function (error) {
+        assert_unreached("listFiles() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        documentsDir = dir;
+        fsTestDir1 = dir.createDirectory(fsTestDirName1);
+        fsTestFile = fsTestDir1.createFile(fsTestFileName);
+        fsTestDir2 = fsTestDir1.createDirectory(fsTestDirName2);
+        fsTestDir1.listFiles(listFilesSuccess, listFilesError);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("images", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_deleteFile_listMusicFiles() {
+//==== TEST: File_deleteFile_listMusicFiles
+//==== LABEL Check if you can create directories and file in Music, list them, then request deleting the directory and the file
+//==== SPEC Tizen Web API:IO:Filesystem:File:deleteFile M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MOA
+
+
+var t = async_test('File_deleteFile_listMusicFiles'), fsTestDirName1, documentsDir,
+    fsTestDirName2, fsTestFileName, fsTestDir1, fsTestDir2, deleteDirError, deleteDirSuccess,
+    fsTestFile, resolveSuccess, resolveError, listFilesSuccess, listFilesError,
+    deleteFileSuccess, deleteFileError;
+
+t.step(function () {
+    fsTestDirName1 = getFileName("filesystem");
+    fsTestDirName2 = getFileName("inside");
+    fsTestFileName = getFileName("filesystem.txt");
+
+    deleteFileSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    deleteFileError = t.step_func(function (error) {
+        assert_unreached("deleteFile() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    deleteDirSuccess = t.step_func(function () {
+        fsTestDir1.deleteFile(fsTestFile.fullPath, deleteFileSuccess, deleteFileError);
+    });
+
+    deleteDirError = t.step_func(function (error) {
+        assert_unreached("deleteDir() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    listFilesSuccess = t.step_func(function (files) {
+        assert_true(files.length > 0, "Files not found");
+        fsTestDir1.deleteDirectory(fsTestDir2.fullPath, true, deleteDirSuccess, deleteDirError);
+    });
+
+    listFilesError = t.step_func(function (error) {
+        assert_unreached("listFiles() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        documentsDir = dir;
+        fsTestDir1 = dir.createDirectory(fsTestDirName1);
+        fsTestFile = fsTestDir1.createFile(fsTestFileName);
+        fsTestDir2 = fsTestDir1.createDirectory(fsTestDirName2);
+        fsTestDir1.listFiles(listFilesSuccess, listFilesError);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("music", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_deleteFile_listVideosfiles() {
+//==== TEST: File_deleteFile_listVideosfiles
+//==== LABEL Check if you can create directories and file in Videos, list them, then request deleting the directory and the file
+//==== SPEC Tizen Web API:IO:Filesystem:File:deleteFile M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MOA
+
+
+var t = async_test('File_deleteFile_listVideosfiles'), fsTestDirName1, documentsDir,
+    fsTestDirName2, fsTestFileName, fsTestDir1, fsTestDir2, deleteDirError, deleteDirSuccess,
+    fsTestFile, resolveSuccess, resolveError, listFilesSuccess, listFilesError,
+    deleteFileSuccess, deleteFileError;
+
+t.step(function () {
+    fsTestDirName1 = getFileName("filesystem");
+    fsTestDirName2 = getFileName("inside");
+    fsTestFileName = getFileName("filesystem.txt");
+
+    deleteFileSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    deleteFileError = t.step_func(function (error) {
+        assert_unreached("deleteFile() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    deleteDirSuccess = t.step_func(function () {
+        fsTestDir1.deleteFile(fsTestFile.fullPath, deleteFileSuccess, deleteFileError);
+    });
+
+    deleteDirError = t.step_func(function (error) {
+        assert_unreached("deleteDir() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    listFilesSuccess = t.step_func(function (files) {
+        assert_true(files.length > 0, "Files not found");
+        fsTestDir1.deleteDirectory(fsTestDir2.fullPath, true, deleteDirSuccess, deleteDirError);
+    });
+
+    listFilesError = t.step_func(function (error) {
+        assert_unreached("listFiles() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        documentsDir = dir;
+        fsTestDir1 = dir.createDirectory(fsTestDirName1);
+        fsTestFile = fsTestDir1.createFile(fsTestFileName);
+        fsTestDir2 = fsTestDir1.createDirectory(fsTestDirName2);
+        fsTestDir1.listFiles(listFilesSuccess, listFilesError);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("videos", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_deleteFile_onerror_TypeMismatch() {
+
+//==== TEST: File_deleteFile_onerror_TypeMismatch
+//==== LABEL Check if File::deleteFile() throws exception for wrong type of onerror
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:IO:Filesystem:File:deleteFile M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MC
+
+var t = async_test('File_deleteFile_onerror_TypeMismatch'),
+    resolveSuccess, resolveError, conversionTable, deleteFileError, i, deleteFileSuccess,
+    exceptionName = "TypeMismatchError";
+
+t.step(function () {
+    deleteFileSuccess = t.step_func(function () {
+        assert_unreached("successCalback should not be called");
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        conversionTable = getTypeConversionExceptions("functionObject", true);
+        for (i = 0; i < conversionTable.length; i++) {
+            deleteFileError = conversionTable[i][0];
+            exceptionName = conversionTable[i][1];
+
+            assert_throws({name: exceptionName},
+                function () {
+                    dir.deleteFile("verybadfile.txt", deleteFileSuccess, deleteFileError);
+                }, exceptionName + " should be thrown - given incorrect errorCallback.");
+        }
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+});
+
+}
+
+function File_deleteFile_onerror_invalid_cb() {
+
+//==== TEST: File_deleteFile_onerror_invalid_cb
+//==== LABEL Check if File::deleteFile() throws exception for wrong onerror
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:IO:Filesystem:File:deleteFile M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MTCB
+
+var t = async_test('File_deleteFile_onerror_invalid_cb'), fsTestFileName, fsTestFile,
+    resolveSuccess, resolveError, deleteFileSuccess, deleteFileError;
+
+t.step(function () {
+    fsTestFileName = getFileName("filesystem.txt");
+
+    deleteFileError = {
+        onerror: t.step_func(function () {
+            assert_unreached("Invalid callback invoked: ");
+        })
+    };
+    deleteFileSuccess = t.step_func(function () {
+        assert_unreached("successCallback should not be called");
+    });
+    resolveSuccess = t.step_func(function (dir) {
+        fsTestFile = dir.createDirectory(fsTestFileName);
+        assert_throws(TYPE_MISMATCH_EXCEPTION,
+            function () {
+                dir.deleteFile(fsTestFile.fullPath, deleteFileSuccess, deleteFileError);
+            }, "given incorrect errorCallback");
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_deleteFile_onsuccess_TypeMismatch() {
+
+//==== TEST: File_deleteFile_onsuccess_TypeMismatch
+//==== LABEL Check if File::deleteFile() throws exception for wrong type of onsuccess
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:IO:Filesystem:File:deleteFile M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MC
+
+var t = async_test('File_deleteFile_onsuccess_TypeMismatch'), deleteFileSuccess, fsTestFileName,
+    resolveSuccess, resolveError, conversionTable, i, exceptionName = "TypeMismatchError", fsTestFile;
+
+t.step(function () {
+    fsTestFileName = getFileName("filesystem.txt");
+
+    resolveSuccess = t.step_func(function (dir) {
+        fsTestFile = dir.createFile(fsTestFileName);
+        conversionTable = getTypeConversionExceptions("functionObject", true);
+        for (i = 0; i < conversionTable.length; i++) {
+            deleteFileSuccess = conversionTable[i][0];
+            exceptionName = conversionTable[i][1];
+
+            assert_throws({name: exceptionName},
+                function () {
+                    dir.deleteFile(fsTestFile.fullPath, deleteFileSuccess);
+                }, exceptionName + " should be thrown - given incorrect successCallback.");
+        }
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_deleteFile_onsuccess_invalid_cb() {
+
+//==== TEST: File_deleteFile_onsuccess_invalid_cb
+//==== LABEL Check if File::deleteFile() throws exception for wrong onsuccess
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:IO:Filesystem:File:deleteFile M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MTCB
+
+var t = async_test('File_deleteFile_onsuccess_invalid_cb'), fsTestFileName, fsTestFile,
+    resolveSuccess, resolveError, deleteFileSuccess;
+
+t.step(function () {
+    fsTestFileName = getFileName("filesystem.txt");
+
+    deleteFileSuccess = {
+        onsuccess: t.step_func(function () {
+            assert_unreached("Invalid callback invoked: ");
+        })
+    };
+
+    resolveSuccess = t.step_func(function (dir) {
+        fsTestFile = dir.createFile(fsTestFileName);
+        assert_throws(TYPE_MISMATCH_EXCEPTION,
+            function () {
+                dir.deleteFile(fsTestFile.fullPath, deleteFileSuccess);
+            }, "given incorrect successCallback");
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_deleteFile_with_dir_handle() {
+
+//==== TEST: File_deleteFile_with_dir_handle
+//==== LABEL Check if File::deleteFile() calls errorCallback when called on File object representing file, not a directory
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:File:deleteFile M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MERRCB
+
+
+var t = async_test('File_deleteFile_with_dir_handle'), fsTestDirName, fsTestDir,
+    resolveSuccess, resolveError, deleteFileSuccess, deleteFileError, expected = "InvalidValuesError",
+    documentsDir;
+
+t.step(function () {
+    fsTestDirName = getFileName("filesystem");
+
+    deleteFileSuccess = t.step_func(function () {
+        assert_unreached("There is no exception thrown when delete a file with file handle");
+    });
+
+    deleteFileError = t.step_func(function (error) {
+        assert_equals(error.name, expected, "expect throw an exception");
+        t.done();
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        documentsDir = dir;
+        fsTestDir= dir.createDirectory(fsTestDirName);
+        dir.deleteFile(fsTestDir.fullPath, deleteFileSuccess, deleteFileError);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_deleteFile_with_nonexist() {
+
+//==== TEST: File_deleteFile_with_nonexist
+//==== LABEL Check if File::deleteFile() calls errorCallback when given filePath does not exist
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:File:deleteFile M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MERRCB
+
+
+var expected = "NotFoundError", t = async_test('File_deleteFile_with_nonexist'),
+    resolveSuccess, resolveError, deleteFileSuccess, deleteFileError, fsTestFileName;
+
+t.step(function () {
+    fsTestFileName = getFileName("noExistFile.txt");
+
+    deleteFileSuccess = t.step_func(function () {
+        assert_unreached("This function should not be invoked");
+    });
+
+    deleteFileError = t.step_func(function (error) {
+        assert_equals(error.name, expected, "should throw an exception");
+        t.done();
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        dir.deleteFile("documents/" + fsTestFileName, deleteFileSuccess, deleteFileError);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+
+});
+
+}
+
+function File_deleteFile_with_onerror() {
+
+//==== TEST: File_deleteFile_with_onerror
+//==== LABEL Check if File::deleteFile() method calls errorCallback properly (when removing non-existing file)
+//==== SPEC: Tizen Web API:IO:Filesystem:File:deleteFile M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MERRCB
+
+var t = async_test('File_deleteFile_with_onerror'),
+    resolveSuccess, resolveError, deleteFileError, deleteFileSuccess, fsTestFileName;
+
+t.step(function () {
+    fsTestFileName = getFileName("noExistFile.txt");
+
+    deleteFileError = t.step_func(function () {
+        t.done();
+    });
+    deleteFileSuccess = t.step_func(function () {
+        assert_unreached("onerroroptional callback should be called");
+    });
+    resolveSuccess = t.step_func(function (dir) {
+        dir.deleteFile("documents/" + fsTestFileName, deleteFileSuccess, deleteFileError);
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+
+});
+
+}
+
+function File_deleteFile_with_onsuccess() {
+
+//==== TEST: File_deleteFile_with_onsuccess
+//==== LABEL Check if File::deleteFile() method calls given onsuccess callback
+//==== SPEC: Tizen Web API:IO:Filesystem:File:deleteFile M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MOA
+
+var t = async_test('File_deleteFile_with_onsuccess'), fsTestFileName, fsTestFile,
+    resolveSuccess, resolveError, deleteFileSuccess;
+
+t.step(function () {
+    fsTestFileName = getFileName("filesystem.txt");
+
+    deleteFileSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        fsTestFile = dir.createFile(fsTestFileName);
+        try {
+            dir.deleteFile(fsTestFile.fullPath, deleteFileSuccess);
+        } catch (e) {
+            assert_unreached("deleteFile() exeption: name: " + e.name + ", msg: " + e.message);
+        }
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_deleteFile_with_vaild_callbacks() {
+
+//==== TEST: File_deleteFile_with_vaild_callbacks
+//==== LABEL Check if File::deleteFile() can be called with onsuccess and onerror
+//==== SPEC Tizen Web API:IO:Filesystem:File:deleteFile M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MOA
+
+var t = async_test('File_deleteFile_with_vaild_callbacks'),
+    deleteFileSuccess, deleteFileError, documentsDir,
+    resolveSuccess, resolveError, fsTestFileName, fsTestFile;
+
+t.step(function () {
+    fsTestFileName = getFileName("filesystem.txt");
+
+    deleteFileSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    deleteFileError = t.step_func(function (error) {
+        assert_unreached("delete() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        documentsDir = dir;
+        fsTestFile = dir.createFile(fsTestFileName);
+        dir.deleteFile(fsTestFile.fullPath, deleteFileSuccess, deleteFileError);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_deleteFile_with_valid_filePath() {
+
+//==== TEST: File_deleteFile_with_valid_filePath
+//==== LABEL Check if File::deleteFile() method can be called without onsuccess
+//==== SPEC Tizen Web API:IO:Filesystem:File:deleteFile M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MMINA
+
+var t = async_test('File_deleteFile_with_valid_filePath'), fsTestFileName, fsTestFile,
+    resolveSuccess, resolveError;
+
+t.step(function () {
+    fsTestFileName = getFileName("filesystem.txt");
+
+    resolveSuccess = t.step_func(function (dir) {
+        fsTestFile = dir.createFile(fsTestFileName);
+        dir.deleteFile(fsTestFile.fullPath);
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_extend() {
+
+//==== TEST: File_extend
+//==== LABEL Check if instance of File can be extended with new property
+//==== PRIORITY: P3
+//==== SPEC Tizen Web API:IO:Filesystem:File:File U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA OBX
+
+var t = async_test('File_extend'),
+    resolveSuccess, resolveError;
+
+t.step(function () {
+    resolveSuccess = t.step_func(function (dir) {
+        check_extensibility(dir);
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+});
+
+}
+
+function File_fileSize_attribute() {
+
+//==== TEST: File_fileSize_attribute
+//==== LABEL Check if File::fileSize attribute exists, has type Number and is readonly
+//==== SPEC: Tizen Web API:IO:Filesystem:File:fileSize A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA AE AT ARO
+
+var t = async_test('File_fileSize_attribute'), fsTestFileName, fsTestFile,
+    resolveSuccess, resolveError;
+
+t.step(function () {
+    fsTestFileName = getFileName("filesystem.txt");
+
+    resolveSuccess = t.step_func(function (dir) {
+        fsTestFile = dir.createFile(fsTestFileName);
+        assert_own_property(fsTestFile, "fileSize", "File does not own fileSize property.");
+        check_readonly(fsTestFile, "fileSize", 0, "unsigned long long", fsTestFile.fileSize + 512);
+        assert_equals(dir.fileSize, undefined, "fileSize of directory should be undefined");
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_fullPath_attribute() {
+
+//==== TEST: File_fullPath_attribute
+//==== LABEL Check if File::fullPath attribute exists, has type DOMString and is readonly
+//==== SPEC: Tizen Web API:IO:Filesystem:File:fullPath A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA AE AT ARO
+
+var t = async_test('File_fullPath_attribute'), fsTestFileName, fsTestFile,
+    resolveSuccess, resolveError;
+
+t.step(function () {
+    fsTestFileName = getFileName("filesystem.txt");
+
+    resolveSuccess = t.step_func(function (dir) {
+        fsTestFile = dir.createFile(fsTestFileName);
+        assert_own_property(fsTestFile, "fullPath", "File does not own fullPath property.");
+        check_readonly(fsTestFile, "fullPath", fsTestFile.fullPath, "string", "images");
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_isDirectory_attribute() {
+
+//==== TEST: File_isDirectory_attribute
+//==== LABEL Check if File::isDirectory attribute exists, has type Boolean and is readonly
+//==== SPEC: Tizen Web API:IO:Filesystem:File:isDirectory A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA AE AT ARO
+
+var t = async_test('File_isDirectory_attribute'),
+    resolveSuccess, resolveError;
+
+t.step(function () {
+    resolveSuccess = t.step_func(function (dir) {
+        assert_own_property(dir, "isDirectory", "File does not own isDirectory property.");
+        check_readonly(dir, "isDirectory", true, "boolean", false);
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+});
+
+}
+
+function File_isFile_attribute() {
+
+//==== TEST: File_isFile_attribute
+//==== LABEL Check if File::isFile attribute exists, has type Boolean and is readonly
+//==== SPEC: Tizen Web API:IO:Filesystem:File:isFile A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA AE AT ARO
+
+var t = async_test('File_isFile_attribute'),
+    resolveSuccess, resolveError;
+
+t.step(function () {
+    resolveSuccess = t.step_func(function (dir) {
+        assert_own_property(dir, "isFile", "File does not own isFile property.");
+        check_readonly(dir, "isFile", false, "boolean", true);
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+});
+
+}
+
+function File_length_attribute() {
+
+//==== TEST: File_length_attribute
+//==== LABEL Check if File::length attribute exists, has type Number and is readonly
+//==== SPEC: Tizen Web API:IO:Filesystem:File:length A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA AE AT ARO
+
+var t = async_test('File_length_attribute'), fsTestFileName =  getFileName("filesystem.txt"),
+    resolveSuccess, resolveError, fsTestFile;
+
+t.step(function () {
+    resolveSuccess = t.step_func(function (dir) {
+        assert_own_property(dir, "length", "File does not own length property.");
+        check_readonly(dir, "length", dir.length, "long", dir.length + 10);
+        fsTestFile = dir.createFile(fsTestFileName);
+        assert_equals(fsTestFile.length, undefined, "length of file should be undefined");
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_listFiles() {
+
+//==== TEST: File_listFiles
+//==== LABEL Check if File::listFiles() method works properly
+//==== SPEC: Tizen Web API:IO:Filesystem:File:listFiles M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MMINA MR
+
+var t = async_test('File_listFiles'),
+    resolveSuccess, resolveError, listFilesSuccess, retVal=null;
+t.step(function () {
+    listFilesSuccess = t.step_func(function (files) {
+        assert_type(files, "array", "files should be array");
+        assert_equals(retVal, undefined, "incorrect returned value");
+        t.done();
+    });
+    resolveSuccess = t.step_func(function (dir) {
+        retVal = dir.listFiles(listFilesSuccess);
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+});
+
+}
+
+function File_listFiles_createFiles() {
+
+//==== TEST: File_listFiles_createFiles
+//==== LABEL Check if you can create a new directory and then list files in this directory
+//==== SPEC Tizen Web API:IO:Filesystem:File:listFiles M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MOA
+
+
+var t = async_test('File_listFiles_createFiles'),
+    resolveSuccess, resolveError, listFilesSuccess, listFilesError,
+    fsTestDirName, fsTestDir, documentsDir, fsTestFileName1, fsTestFileName2;
+
+t.step(function () {
+    fsTestDirName = getDirName("filesystem");
+    fsTestFileName1 = getFileName("filesystem1.txt");
+    fsTestFileName2 = getFileName("filesystem2.txt");
+
+    listFilesSuccess = t.step_func(function (files) {
+        assert_equals(files.length, 2, "list files");
+        t.done();
+    });
+    listFilesError = t.step_func(function (error) {
+        assert_unreached("listFiles() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        documentsDir = dir;
+        fsTestDir = dir.createDirectory(fsTestDirName);
+        fsTestDir.createFile(fsTestFileName1);
+        fsTestDir.createFile(fsTestFileName2);
+        fsTestDir.listFiles(listFilesSuccess, listFilesError);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_listFiles_exist() {
+
+//==== TEST: File_listFiles_exist
+//==== LABEL Check if File::listFiles() method exists
+//==== PRIORITY P0
+//==== SPEC Tizen Web API:IO:Filesystem:File:listFiles M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA ME
+
+var t = async_test('File_listFiles_exist'), resolveSuccess, resolveError;
+
+t.step(function () {
+    resolveSuccess = t.step_func(function (dir) {
+        assert_true("listFiles" in dir, "method listFiles exists");
+        check_method_exists(dir, "listFiles");
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+});
+
+}
+
+function File_listFiles_filter_TypeMismatch() {
+
+//==== TEST: File_listFiles_filter_TypeMismatch
+//==== LABEL Check if File::listFiles() method throws exception for wrong type of filter
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:IO:Filesystem:File:listFiles M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MC
+
+var t = async_test('File_listFiles_filter_TypeMismatch'), listFilesSuccess,
+    resolveSuccess, resolveError, conversionTable, i, exceptionName = "TypeMismatchError",
+    filter;
+
+t.step(function () {
+    listFilesSuccess = t.step_func(function () {});
+    resolveSuccess = t.step_func(function (dir) {
+        conversionTable = getTypeConversionExceptions("object", true);
+        for (i = 0; i < conversionTable.length; i++) {
+            filter = conversionTable[i][0];
+            exceptionName = conversionTable[i][1];
+
+            assert_throws({
+                    name: exceptionName
+                }, function () {
+                    dir.listFiles(listFilesSuccess, null, filter);
+                }, exceptionName + " should be thrown - given incorrect filter.");
+        }
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+});
+
+}
+
+function File_listFiles_filter_empty() {
+
+//==== TEST: File_listFiles_filter_empty
+//==== LABEL Check if File::listFiles() can be called with empty object as filter argument
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:File:listFiles M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MTD
+
+var t = async_test('File_listFiles_filter_empty'), resolveSuccess, resolveError,
+    listFilesSuccess, listFilesError;
+
+t.step(function () {
+
+    listFilesSuccess = t.step_func(function (files) {
+        t.done();
+    });
+
+    listFilesError = t.step_func(function (error) {
+        assert_unreached("listFiles() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        dir.listFiles(listFilesSuccess, listFilesError, {});
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+});
+
+}
+
+function File_listFiles_missarg() {
+
+//==== TEST: File_listFiles_missarg
+//==== PRIORITY: P2
+//==== LABEL Check if File::listFiles() with missing mandatory argument throws exception
+//==== SPEC: Tizen Web API:IO:Filesystem:File:listFiles M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MMA
+
+var t = async_test('File_listFiles_missarg'), resolveSuccess, resolveError;
+t.step(function () {
+    resolveSuccess = t.step_func(function (dir) {
+        assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+                dir.listFiles();
+            });
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+});
+
+}
+
+function File_listFiles_onerror_TypeMismatch() {
+
+//==== TEST: File_listFiles_onerror_TypeMismatch
+//==== LABEL Check if File::listFiles() throws exception for wrong type of onerror
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:IO:Filesystem:File:listFiles M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MC
+
+var t = async_test('File_listFiles_onerror_TypeMismatch'),
+    resolveSuccess, resolveError, conversionTable, listFilesError, i, fsTestFileName,
+    fsTestFile, listFilesSuccess, exceptionName = "TypeMismatchError";
+
+t.step(function () {
+    fsTestFileName = getFileName("filesystem.txt");
+
+    listFilesSuccess = t.step_func(function () {
+        assert_unreached("successCalback should not be called");
+    });
+    resolveSuccess = t.step_func(function (dir) {
+        conversionTable = getTypeConversionExceptions("functionObject", true);
+        fsTestFile = dir.createFile(fsTestFileName);
+        for (i = 0; i < conversionTable.length; i++) {
+            listFilesError = conversionTable[i][0];
+            exceptionName = conversionTable[i][1];
+
+            assert_throws({name: exceptionName},
+                function () {
+                    fsTestFile.listFiles(listFilesSuccess, listFilesError);
+                }, exceptionName + " should be thrown - given incorrect errorCallback.");
+        }
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_listFiles_onerror_invalid_cb() {
+
+//==== TEST: File_listFiles_onerror_invalid_cb
+//==== LABEL Check if File::listFiles() throws exception for wrong onerror
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:IO:Filesystem:File:listFiles M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MTCB
+
+var t = async_test('File_listFiles_onerror_invalid_cb'), fsTestFileName, fsTestFile,
+    resolveSuccess, resolveError, listFilesSuccess, listFilesError;
+t.step(function () {
+    fsTestFileName = getFileName("filesystem.txt");
+
+    listFilesError = {
+        onerror: t.step_func(function () {
+            assert_unreached("invalid errorCallback should not be called");
+        })
+    };
+    listFilesSuccess = t.step_func(function () {
+        assert_unreached("successCallback should not be called");
+    });
+    resolveSuccess = t.step_func(function (dir) {
+        fsTestFile = dir.createFile(fsTestFileName);
+        assert_throws(TYPE_MISMATCH_EXCEPTION,
+            function () {
+                fsTestFile.listFiles(listFilesSuccess, listFilesError);
+            }, "given incorrect errorCallback");
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_listFiles_onsuccess_TypeMismatch() {
+
+//==== TEST: File_listFiles_onsuccess_TypeMismatch
+//==== LABEL Check if File::listFiles() throws exception for wrong type of onsuccess
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:IO:Filesystem:File:listFiles M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MC
+
+var t = async_test('File_listFiles_onsuccess_TypeMismatch'), listFilesSuccess,
+    resolveSuccess, resolveError, conversionTable, i, exceptionName = "TypeMismatchError";
+
+t.step(function () {
+    resolveSuccess = t.step_func(function (dir) {
+        conversionTable = getTypeConversionExceptions("functionObject", false);
+        for (i = 0; i < conversionTable.length; i++) {
+            listFilesSuccess = conversionTable[i][0];
+            exceptionName = conversionTable[i][1];
+
+            assert_throws({
+                    name: exceptionName
+                }, function () {
+                    dir.listFiles(listFilesSuccess);
+                }, exceptionName + " should be thrown - given incorrect successCallback.");
+        }
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+});
+
+}
+
+function File_listFiles_onsuccess_invalid_cb() {
+
+//==== TEST: File_listFiles_onsuccess_invalid_cb
+//==== LABEL Check if File::listFiles() throws exception for wrong onsuccess
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:IO:Filesystem:File:listFiles M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MTCB
+
+var t = async_test('File_listFiles_onsuccess_invalid_cb'),
+    resolveSuccess, resolveError, listFilesSuccess;
+
+t.step(function () {
+    listFilesSuccess = {
+        onsuccess: t.step_func(function () {
+            assert_unreached("Invalid callback invoked: ");
+        })
+    };
+
+    resolveSuccess = t.step_func(function (dir) {
+        assert_throws(TYPE_MISMATCH_EXCEPTION,
+            function () {
+                dir.listFiles(listFilesSuccess);
+            }, "given incorrect successCallback");
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+});
+
+}
+
+function File_listFiles_with_file_handle() {
+
+//==== TEST: File_listFiles_with_file_handle
+//==== LABEL Check if File::listFiles() calls errorCallback when called on File object representing file, not a directory
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:File:listFiles M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MERRCB
+
+
+var resolveSuccess, resolveError, listFilesSuccess, listFilesError, fsTestFileName, fsTestFile,
+    documentsDir, t = async_test('File_listFiles_with_file_handle'), expected = "IOError";
+
+t.step(function () {
+    fsTestFileName = getFileName("filesystem.txt");
+
+    listFilesSuccess = t.step_func(function () {
+        assert_unreached("There is no exception thrown when listFiles with a file handle");
+    });
+
+    listFilesError = t.step_func(function (error) {
+        assert_equals(error.name, expected, "expect thrown an exception");
+        t.done();
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        documentsDir = dir;
+        fsTestFile = dir.createFile(fsTestFileName);
+        fsTestFile.listFiles(listFilesSuccess, listFilesError);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_listFiles_with_filter() {
+
+//==== TEST: File_listFiles_with_filter
+//==== LABEL Check if File::listFiles() works with filter argument
+//==== PRIORITY P1
+//==== SPEC Tizen Web API:IO:Filesystem:File:listFiles M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MOA
+
+
+var filesFilter, listFilesError, resolveSuccess, resolveError, listFilesSuccess, documentsDir,
+    fsTestFileName, fsTestFile, filesRegExp = new RegExp("^" + FILE_AND_DIR_NAME_PREFIX),
+    t = async_test('File_listFiles_with_filter');
+
+t.step(function () {
+    fsTestFileName = getFileName("filesystem.txt");
+    filesFilter = {name: FILE_AND_DIR_NAME_PREFIX + "%"};
+
+    listFilesSuccess = t.step_func(function (files) {
+        assert_true(files.length > 0 , "file wasn't found");
+        assert_regexp_match(files[0].name, filesRegExp, "bad file was found");
+        t.done();
+    });
+
+    listFilesError = t.step_func(function (error) {
+        assert_unreached("listFiles() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        documentsDir = dir;
+        fsTestFile = dir.createFile(fsTestFileName);
+        dir.listFiles(listFilesSuccess, listFilesError, filesFilter);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_listFiles_with_onerror() {
+
+//==== TEST: File_listFiles_with_onerror
+//==== LABEL Check if File::listFiles() calls errorCallback (listing files of a file)
+//==== SPEC: Tizen Web API:IO:Filesystem:File:listFiles M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MERRCB
+
+var t = async_test('File_listFiles_with_onerror'),
+    resolveSuccess, resolveError, listFilesSuccess, listFilesError, fsTestFileName, fsTestFile;
+
+t.step(function () {
+    fsTestFileName = getFileName("filesystem.txt");
+
+    listFilesError = t.step_func(function () {
+        t.done();
+    });
+
+    listFilesSuccess = t.step_func(function (files) {
+        assert_unreached("listFilesSuccess:  listFilesError should be invoked");
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        fsTestFile = dir.createFile(fsTestFileName);
+        fsTestFile.listFiles(listFilesSuccess, listFilesError);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_listFiles_with_valid_successCallback() {
+
+//==== TEST: File_listFiles_with_valid_successCallback
+//==== LABEL Check if File::listFiles() call onsuccess callback
+//==== SPEC Tizen Web API:IO:Filesystem:File:listFiles M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MMINA
+
+var t = async_test('File_listFiles_with_valid_successCallback'), resolveSuccess, resolveError,
+    listFilesSuccess;
+t.step(function () {
+
+    listFilesSuccess = t.step_func(function (files) {
+        assert_type(files, "array", "files");
+        t.done();
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        dir.listFiles(listFilesSuccess);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+});
+
+}
+
+function File_modified_attribute() {
+
+//==== TEST: File_modified_attribute
+//==== LABEL Check if File::modified attribute exists, has type Date and is readonly
+//==== SPEC: Tizen Web API:IO:Filesystem:File:modified A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA AE ARO AT
+
+var t = async_test('File_modified_attribute'),
+    resolveSuccess, resolveError, fsTestFileName, fsTestFile, date, tmp;
+
+t.step(function () {
+    fsTestFileName = getFileName("filesystem.txt");
+
+    resolveSuccess = t.step_func(function (dir) {
+        date = new Date();
+        fsTestFile = dir.createFile(fsTestFileName);
+        assert_own_property(fsTestFile, "modified", "File does not own modified property.");
+        assert_true("modified" in fsTestFile, "attribute modified doesn't exist in provided object.");
+        assert_type(fsTestFile.modified, "Date", "Type of modified is different.");
+        tmp = fsTestFile.modified;
+        fsTestFile.modified = new Date();
+        assert_equals(tmp.getTime(), fsTestFile.modified.getTime(), "created can be modified.");
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_moveTo() {
+
+//==== TEST: File_moveTo
+//==== LABEL Check if File::moveTo() can be called successfully
+//==== SPEC: Tizen Web API:IO:Filesystem:File:moveTo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MMINA MR
+
+var t = async_test('File_moveTo'), fsTestFileName, fsTestFile,
+    resolveSuccess, resolveError, retVal;
+
+t.step(function () {
+    fsTestFileName = getFileName("filesystem.txt");
+
+    resolveSuccess = t.step_func(function (dir) {
+        fsTestFile = dir.createFile(fsTestFileName);
+        retVal = dir.moveTo(fsTestFile.fullPath,
+            "images/"+fsTestFile.name, true);
+        assert_equals(retVal, undefined, "incorrect returned value");
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_moveTo_dir_samedir_samename_overwrite_false() {
+//==== TEST: File_moveTo_dir_samedir_samename_overwrite_false
+//==== LABEL Check if File::moveTo() invokes error callback when moving a directory to the same location with the same name (overwrite is false)
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:File:copyTo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MERRCB
+
+
+var resolveSuccess, resolveError, moveToSuccess, moveToError, fsTestDir1, fsTestDirName1, fsTestSubDir1,
+    fsTestSubDirName1, expected = "IOError",
+    t = async_test('File_moveTo_dir_samedir_samename_overwrite_false');
+
+t.step(function () {
+    fsTestDirName1 = getDirName("filesystem1");
+    fsTestSubDirName1 = getDirName("filesystem1sub");
+
+    moveToSuccess = t.step_func(function () {
+        assert_unreached("copySuccess callback shouldn't be invoked");
+    });
+
+    moveToError = t.step_func(function (error) {
+        assert_equals(error.name, expected, "wrong error type");
+        t.done();
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        fsTestDir1 = dir.createDirectory(fsTestDirName1);
+        fsTestSubDir1 = fsTestDir1.createDirectory(fsTestSubDirName1);
+        fsTestDir1.moveTo(fsTestSubDir1.fullPath, fsTestSubDir1.path, false, moveToSuccess, moveToError);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_moveTo_dir_samedir_samename_overwrite_true() {
+//==== TEST: File_moveTo_dir_samedir_samename_overwrite_true
+//==== LABEL Check if File::moveTo() invokes error callback when moving a directory to the same location with the same name (overwrite is true)
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:File:copyTo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MERRCB
+
+
+var resolveSuccess, resolveError, moveToSuccess, moveToError, fsTestDir1, fsTestDirName1, fsTestSubDir1,
+    fsTestSubDirName1, expected = "IOError",
+    t = async_test('File_moveTo_dir_samedir_samename_overwrite_true');
+
+t.step(function () {
+    fsTestDirName1 = getDirName("filesystem1");
+    fsTestSubDirName1 = getDirName("filesystem1sub");
+
+    moveToSuccess = t.step_func(function () {
+        assert_unreached("copySuccess callback shouldn't be invoked");
+    });
+
+    moveToError = t.step_func(function (error) {
+        assert_equals(error.name, expected, "wrong error type");
+        t.done();
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        fsTestDir1 = dir.createDirectory(fsTestDirName1);
+        fsTestSubDir1 = fsTestDir1.createDirectory(fsTestSubDirName1);
+        fsTestDir1.moveTo(fsTestSubDir1.fullPath, fsTestSubDir1.path, true, moveToSuccess, moveToError);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_moveTo_empty_destination_source_and_destination_paths() {
+
+//==== TEST: File_moveTo_empty_destination_source_and_destination_paths
+//==== LABEL Check if File::moveTo() invokes error callback when originFilePath and destinationFilePath are empty
+//==== SPEC Tizen Web API:IO:Filesystem:File:moveTo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MERRCB
+
+var t = async_test('File_moveTo_empty_destination_source_and_destination_paths'),
+    moveToSuccess, moveToError, resolveSuccess, resolveError;
+
+t.step(function () {
+    moveToSuccess = t.step_func(function () {
+        assert_unreached("moveToSuccess: moveToError should be invoked");
+    });
+
+    moveToError = t.step_func(function (error) {
+        t.done();
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        dir.moveTo("", "", false, moveToSuccess, moveToError);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+});
+
+}
+
+function File_moveTo_exist() {
+
+//==== TEST: File_moveTo_exist
+//==== LABEL Check if File::moveTo() method exists
+//==== PRIORITY P0
+//==== SPEC Tizen Web API:IO:Filesystem:File:moveTo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA ME
+
+var t = async_test('File_moveTo_exist'), resolveSuccess, resolveError;
+
+t.step(function () {
+    resolveSuccess = t.step_func(function (dir) {
+        assert_true("moveTo" in dir, "method moveTo exists");
+        check_method_exists(dir, "moveTo");
+        t.done();
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+});
+
+}
+
+function File_moveTo_file_samedir_samename_overwrite_false() {
+//==== TEST: File_moveTo_file_samedir_samename_overwrite_false
+//==== LABEL Check if File::moveTo() invokes error callback when moving a file to the same location with the same name (overwrite is false)
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:File:moveTo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MERRCB
+
+
+var t = async_test('File_moveTo_file_samedir_samename_overwrite_false'), resolveSuccess,
+    resolveError, moveToSuccess, moveToError, expectedError = "IOError",
+    fsTestDirName1, fsTestDirName2, fsTestFileName, fsTestDir1, fsTestDir2, fsTestFile;
+
+t.step(function () {
+    fsTestDirName1 = getDirName("filesystem");
+    fsTestDirName2 = getDirName("destination");
+    fsTestFileName = getFileName("filesystem.txt");
+
+    moveToSuccess = t.step_func(function () {
+        assert_unreached("moveToSuccess callback should not be invoked");
+    });
+
+    moveToError = t.step_func(function (error) {
+        assert_equals(error.name, expectedError, "wrong error type");
+        t.done();
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        fsTestDir1 = dir.createDirectory(fsTestDirName1);
+        fsTestDir2 = fsTestDir1.createDirectory(fsTestDirName2);
+        fsTestFile = fsTestDir2.createFile(fsTestFileName);
+        fsTestDir2.moveTo(fsTestFile.fullPath, "documents/"+fsTestDir1.name+"/"+fsTestDir2.name+"/",
+            false, moveToSuccess, moveToError);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_moveTo_file_samedir_samename_overwrite_true() {
+//==== TEST: File_moveTo_file_samedir_samename_overwrite_true
+//==== LABEL Check if File::moveTo() error callback when moving a file to the same location with the same name (overwrite is true)
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:File:moveTo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MERRCB
+
+
+var t = async_test('File_moveTo_file_samedir_samename_overwrite_true'), resolveSuccess,
+    resolveError, moveToSuccess, moveToError, expectedError = "IOError",
+    fsTestDirName1, fsTestDirName2, fsTestFileName, fsTestDir1,
+    fsTestDir2, fsTestFile;
+
+t.step(function () {
+    fsTestDirName1 = getDirName("filesystem");
+    fsTestDirName2 = getDirName("destination");
+    fsTestFileName = getFileName("filesystem.txt");
+
+    moveToSuccess = t.step_func(function () {
+        assert_unreached("moveToSuccess callback should not be invoked");
+    });
+
+    moveToError = t.step_func(function (error) {
+        assert_equals(error.name, expectedError, "wrong error type");
+        t.done();
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        fsTestDir1 = dir.createDirectory(fsTestDirName1);
+        fsTestDir2 = fsTestDir1.createDirectory(fsTestDirName2);
+        fsTestFile = fsTestDir2.createFile(fsTestFileName);
+        fsTestDir2.moveTo(fsTestFile.fullPath, "documents/" + fsTestDir1.name + "/" + fsTestDir2.name + "/",
+            true, moveToSuccess, moveToError);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_moveTo_onerror_TypeMismatch() {
+
+//==== TEST: File_moveTo_onerror_TypeMismatch
+//==== LABEL Check if File::moveTo() throws exception for wrong type of onerror
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:IO:Filesystem:File:moveTo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MC
+
+var t = async_test('File_moveTo_onerror_TypeMismatch'),
+    resolveSuccess, resolveError, conversionTable, moveToError, i, moveToSuccess,
+    exceptionName = "TypeMismatchError";
+
+t.step(function () {
+    moveToSuccess = t.step_func(function () {
+        assert_unreached("successCalback should not be called");
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        conversionTable = getTypeConversionExceptions("functionObject", true);
+        for (i = 0; i < conversionTable.length; i++) {
+            moveToError = conversionTable[i][0];
+            exceptionName = conversionTable[i][1];
+
+            assert_throws({
+                    name: exceptionName
+                }, function () {
+                    dir.moveTo("verybadfile.txt", "images", true, moveToSuccess, moveToError);
+                }, exceptionName + " should be thrown - given incorrect error callback.");
+        }
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+});
+
+}
+
+function File_moveTo_onerror_invalid_cb() {
+
+//==== TEST: File_moveTo_onerror_invalid_cb
+//==== LABEL Check if File::moveTo() throws exception for wrong onerror
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:IO:Filesystem:File:moveTo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MTCB
+
+var t = async_test('File_moveTo_onerror_invalid_cb'), fsTestFileName, fsTestFile,
+    resolveSuccess, resolveError, moveToSuccess, moveToError;
+
+t.step(function () {
+    fsTestFileName = getFileName("filesystem.txt");
+
+    moveToError = {
+        onerror: t.step_func(function () {
+            assert_unreached("moveTo() error callback invoked");
+        })
+    };
+    moveToSuccess = t.step_func(function () {
+        assert_unreached("moveTo() success callback invoked");
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        fsTestFile = dir.createFile(fsTestFileName);
+        assert_throws(TYPE_MISMATCH_EXCEPTION,
+            function () {
+                dir.moveTo(fsTestFile.fullPath, "images", true, moveToSuccess, moveToError);
+            }, "given incorrect errorCallback");
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_moveTo_onsuccess_TypeMismatch() {
+
+//==== TEST: File_moveTo_onsuccess_TypeMismatch
+//==== LABEL Check if File::moveTo() throws exception for wrong type of onsuccess
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:IO:Filesystem:File:moveTo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MC
+
+var t = async_test('File_moveTo_onsuccess_TypeMismatch'), moveToSuccess, fsTestFileName, fsTestFile,
+    resolveSuccess, resolveError, conversionTable, i, exceptionName = "TypeMismatchError";
+
+t.step(function () {
+    fsTestFileName = getFileName("filesystem.txt");
+
+    resolveSuccess = t.step_func(function (dir) {
+        fsTestFile = dir.createFile(fsTestFileName);
+        conversionTable = getTypeConversionExceptions("functionObject", true);
+        for (i = 0; i < conversionTable.length; i++) {
+            moveToSuccess = conversionTable[i][0];
+            exceptionName = conversionTable[i][1];
+
+            assert_throws({name: exceptionName},
+                function () {
+                    dir.moveTo(fsTestFile.fullPath, "images", true, moveToSuccess);
+                }, exceptionName + " should be thrown - given incorrect success callback.");
+        }
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_moveTo_onsuccess_invalid_cb() {
+
+//==== TEST: File_moveTo_onsuccess_invalid_cb
+//==== LABEL Check if File::moveTo() throws exception for wrong onsuccess
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:IO:Filesystem:File:moveTo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MTCB
+
+var t = async_test('File_moveTo_onsuccess_invalid_cb'), resolveSuccess, resolveError,
+    moveToSuccess, fsTestFileName, fsTestFile;
+
+t.step(function () {
+    fsTestFileName = getFileName("filesystem.txt");
+
+    moveToSuccess = {
+        onsuccess: t.step_func(function () {
+            assert_unreached("Invalid callback invoked: ");
+        })
+    };
+
+    resolveSuccess = t.step_func(function (dir) {
+        fsTestFile = dir.createFile(fsTestFileName);
+        assert_throws(TYPE_MISMATCH_EXCEPTION,
+            function () {
+                dir.moveTo(fsTestFile.fullPath, "images", true, moveToSuccess);
+            }, "given incorrect successCallback");
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_moveTo_with_additional_null_parameter() {
+
+//==== TEST: File_moveTo_with_additional_null_parameter
+//==== LABEL Check if File::moveTo() method can be invoked with extra null parameter
+//==== SPEC Tizen Web API:IO:Filesystem:File:moveTo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MOA
+
+var t = async_test('File_moveTo_with_additional_null_parameter'), fsTestFileName2,
+    resolveSuccess, resolveError, file, movedPath, fsTestFileName, moveToSuccess;
+t.step(function () {
+    fsTestFileName = getFileName("filesystem.txt");
+    fsTestFileName2 = getFileName("filesystem2.txt");
+
+    moveToSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        file = dir.createFile(fsTestFileName);
+        assert_true(isFileObject(file), "isFileObject(createdFile)");
+        movedPath = dir.fullPath + "/" + fsTestFileName2;
+        dir.moveTo(file.fullPath, movedPath, true, moveToSuccess, null, null);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve(TEST_ROOT_LOCATION, resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_moveTo_with_file_handle() {
+
+//==== TEST: File_moveTo_with_file_handle
+//==== LABEL Check if File::moveTo() calls errorCallback when called on File object representing file, not a directory
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:File:moveTo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MERRCB
+
+
+var resolveSuccess, resolveError, moveToSuccess, moveToError, fsTestDirName1,
+    fsTestDirName2, fsTestDir1, fsTestDir2, fsTestFileName, fsTestFile,
+    expectedError = "IOError", t = async_test('File_moveTo_with_file_handle');
+
+t.step(function () {
+    fsTestDirName1 = getFileName("filesystem");
+    fsTestDirName2 = getFileName("filesystem2");
+    fsTestFileName = getFileName("filesystem.txt");
+
+    moveToSuccess = t.step_func(function () {
+        assert_unreached("There is no exception thrown when when copyTo with file handle");
+    });
+
+    moveToError = t.step_func(function (error) {
+        assert_equals(error.name, expectedError, expectedError + " should be thrown");
+        t.done();
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        fsTestDir1 = dir.createDirectory(fsTestDirName1);
+        fsTestDir2 = fsTestDir1.createDirectory(fsTestDirName2);
+        fsTestFile = fsTestDir2.createFile(fsTestFileName);
+        fsTestFile.moveTo(fsTestFile.fullPath, fsTestDir1.path, true, moveToSuccess, moveToError);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_moveTo_with_onerror() {
+
+//==== TEST: File_moveTo_with_onerror
+//==== LABEL Check if File::moveTo() calls errorCallback (source file does not exist)
+//==== SPEC: Tizen Web API:IO:Filesystem:File:moveTo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MERRCB
+
+var t = async_test('File_moveTo_with_onerror'),
+    resolveSuccess, resolveError, moveToSuccess, moveToError, fsTestFileName;
+
+t.step(function () {
+    fsTestFileName = getFileName("noExistFile.txt");
+
+    moveToError = t.step_func(function () {
+        t.done();
+    });
+    moveToSuccess = t.step_func(function (files) {
+        assert_unreached("moveTo() error callback invoked: moveTo() error callback should be called");
+    });
+    resolveSuccess = t.step_func(function (dir) {
+        dir.moveTo("documents/" + fsTestFileName,
+            "images/" + fsTestFileName, true, moveToSuccess, moveToError);
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+
+});
+
+}
+
+function File_moveTo_with_onsuccess() {
+
+//==== TEST: File_moveTo_with_onsuccess
+//==== LABEL Check if File::moveTo() calls successCallback
+//==== SPEC: Tizen Web API:IO:Filesystem:File:moveTo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MAST MOA
+
+var t = async_test('File_moveTo_with_onsuccess'), listFilesError, resolveError,
+    resolveSuccess, documentsDir, listFilesSuccess, moveToSuccess, i, fsTestFileName;
+t.step(function () {
+    fsTestFileName = getFileName("filesystem.txt");
+
+    moveToSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    listFilesSuccess = t.step_func(function (files) {
+        for (i = 0; i < files.length; i++) {
+            if (files[i].name === fsTestFileName) {
+                try {
+                    documentsDir.moveTo(files[i].fullPath,
+                        "images/" + files[i].name, true, moveToSuccess);
+                } catch (error) {
+                    assert_unreached("listFiles() success callback invoked: name:" + error.name + "msg:" + error.message);
+                }
+            }
+        }
+    });
+
+    listFilesError = t.step_func(function (error) {
+        assert_unreached("listFiles() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        documentsDir = dir;
+        dir.createFile(fsTestFileName);
+        dir.listFiles(listFilesSuccess, listFilesError);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+
+});
+
+}
+
+function File_moveTo_with_path_invalid() {
+
+//==== TEST: File_moveTo_with_path_invalid
+//==== LABEL Check if File::moveTo() calls errorCallback (NotFound) when destinationFilePath is in non-existing directory
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:File:moveTo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MERRCB
+
+
+var t = async_test('File_moveTo_with_path_invalid'), fsTestDirName, fsTestDir,
+    expected = "NotFoundError", documentsDir, resolveSuccess, resolveError,
+    moveToSuccess, moveToError;
+
+t.step(function () {
+    fsTestDirName = getFileName("filesystem");
+
+    moveToSuccess = t.step_func(function () {
+        assert_unreached("moveTo() success callback invoked: No exception be thrown when move file to an invalid path");
+    });
+
+    moveToError = t.step_func(function (error) {
+        assert_equals(error.name, expected, "exception is not our expected value");
+        t.done();
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        documentsDir = dir;
+        fsTestDir = dir.createDirectory(fsTestDirName);
+        dir.moveTo(fsTestDir.fullPath, "hello/" + fsTestDirName, true, moveToSuccess, moveToError);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_moveTo_writeFile_newName() {
+
+//==== TEST: File_moveTo_writeFile_newName
+//==== LABEL Check if you can create a new file, write content to it, and then move the file to the same directory with different file name
+//==== SPEC Tizen Web API:IO:Filesystem:File:moveTo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MOA
+
+
+var resolveSuccess, resolveError, fsTestDirName, fsTestFileName, fsTestDir,
+    fsTestFile, fsTestFileName2, moveToSuccess, moveToError, t = async_test('File_moveTo_writeFile_newName'),
+    openStreamSuccess, openStreamError;
+
+t.step(function () {
+    fsTestDirName = getFileName("filesystem");
+    fsTestFileName = getFileName("filesystem.txt");
+    fsTestFileName2 = getFileName("filesystem2.txt");
+
+    moveToSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    moveToError = t.step_func(function (error) {
+        assert_unreached("moveTo() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    openStreamSuccess = t.step_func(function (fs) {
+        fs.write("test");
+        fs.close();
+        fsTestDir.moveTo(fsTestFile.fullPath, fsTestDir.fullPath + "/" + fsTestFileName2,
+            true, moveToSuccess, moveToError);
+    });
+
+    openStreamError = t.step_func(function (error) {
+        assert_unreached("openStream() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        fsTestDir = dir.createDirectory(fsTestDirName);
+        fsTestFile = fsTestDir.createFile(fsTestFileName);
+        fsTestFile.openStream("rw", openStreamSuccess, openStreamError, "UTF-8");
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_moveTo_writeFile_overwrite_false() {
+
+//==== TEST: File_moveTo_writeFile_overwrite_false
+//==== LABEL Check if File::moveTo() calls errorCallback when originFilePath and destinationFilePath is the same path (overwrite false)
+//==== SPEC Tizen Web API:IO:Filesystem:File:moveTo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MERRCB
+
+
+var t = async_test('File_moveTo_writeFile_overwrite_false'),
+    resolveSuccess, resolveError, openStreamSuccess, openStreamError, moveToSuccess, mainDir,
+    moveToError, fsTestFileName, fsTestFile, fsTestDirName, fsTestDir, expectedError = "IOError";
+
+t.step(function () {
+    fsTestDirName = getFileName("filesystem");
+    fsTestFileName = getFileName("filesystem.txt");
+
+    moveToSuccess = t.step_func(function () {
+        assert_unreached("moveToSuccess callback shouldn't be invoked");
+    });
+
+    moveToError = t.step_func(function (error) {
+        assert_equals(error.name, expectedError, "wrong error type");
+        t.done();
+    });
+
+    openStreamSuccess = t.step_func(function (fs) {
+        fs.write("test");
+        fs.close();
+        mainDir.moveTo(fsTestFile.fullPath, fsTestDir.fullPath + "/" + fsTestFile.name,
+            false, moveToSuccess, moveToError);
+    });
+    openStreamError = t.step_func(function (error) {
+        assert_unreached("openStream() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        mainDir = dir;
+        fsTestFile = dir.createFile(fsTestFileName);
+        fsTestDir = dir.createDirectory(fsTestDirName);
+        fsTestDir.createFile(fsTestFileName);
+        fsTestFile.openStream("rw", openStreamSuccess, openStreamError, "UTF-8");
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_moveTo_writeFile_subdir() {
+
+//==== TEST: File_moveTo_writeFile_subdir
+//==== LABEL Check if you can create a new file, write content to it, and then move the file to a subdirectory keeping the name of the file
+//==== SPEC Tizen Web API:IO:Filesystem:File:moveTo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MOA
+
+
+var resolveSuccess, resolveError, openStreamSuccess, openStreamError, moveToSuccess,
+    moveToError, fsTestDirName1, fsTestDirName2, fsTestFileName,
+    fsTestFile, fsTestDir1, fsTestDir2, t = async_test('File_moveTo_writeFile_subdir');
+
+t.step(function () {
+    fsTestDirName1 = getFileName("filesystem");
+    fsTestDirName2 = getFileName("destination");
+    fsTestFileName = getFileName("filesystem.txt");
+
+    moveToSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    moveToError = t.step_func(function (error) {
+        assert_unreached("moveTo() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    openStreamSuccess = t.step_func(function (fs) {
+        fs.write("test");
+        fs.close();
+        fsTestDir1.moveTo(fsTestFile.fullPath, fsTestDir2.fullPath + "/" + fsTestFile.name, true, moveToSuccess, moveToError);
+    });
+
+    openStreamError = t.step_func(function (error) {
+        assert_unreached("openStream() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        fsTestDir1 = dir.createDirectory(fsTestDirName1);
+        fsTestDir2 = fsTestDir1.createDirectory(fsTestDirName2);
+        fsTestFile = fsTestDir1.createFile(fsTestFileName);
+        fsTestFile.openStream("rw", openStreamSuccess, openStreamError, "UTF-8");
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_name_attribute() {
+
+//==== TEST: File_name_attribute
+//==== LABEL Check if File::name attribute exists, has type DOMString and is readonly
+//==== SPEC: Tizen Web API:IO:Filesystem:File:name A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA AE ARO AT
+
+var t = async_test('File_name_attribute'), fsTestFileName,
+    fsTestFile, resolveSuccess, resolveError;
+t.step(function () {
+    fsTestFileName = getFileName("filesystem.txt");
+
+    resolveSuccess = t.step_func(function (dir) {
+        fsTestFile = dir.createFile(fsTestFileName);
+        assert_own_property(fsTestFile, "name", "File does not own name property.");
+        check_readonly(fsTestFile, "name", fsTestFile.name, "string", fsTestFile.name + "dummyValue");
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_notexist() {
+
+//==== TEST: File_notexist
+//==== LABEL Interface File should not be accessible
+//==== PRIORITY: P3
+//==== SPEC Tizen Web API:IO:Filesystem:File:File U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA NIO
+test(function () {
+    check_no_interface_object("File");
+}, 'File_notexist');
+
+}
+
+function File_openStream() {
+
+//==== TEST: File_openStream
+//==== LABEL Check if File::openStream() method works properly
+//==== SPEC: Tizen Web API:IO:Filesystem:File:openStream M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MMINA MR
+
+var t = async_test('File_openStream'), fsTestFileName, fsTestFile,
+    resolveSuccess, resolveError, retVal = null;
+t.step(function () {
+    fsTestFileName = getFileName("filesystem.txt");
+
+    resolveSuccess = t.step_func(function (dir) {
+        fsTestFile = dir.createFile(fsTestFileName);
+        retVal = fsTestFile.openStream("w",
+            t.step_func(function (fs) {
+                assert_equals(retVal, undefined, "incorrect returned value");
+                fs.write("HelloWorld");
+                fs.close();
+                t.done();
+            }));
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_openStream_encoding_invalid() {
+
+//==== TEST: File_openStream_encoding_invalid
+//==== LABEL Check if File::openStream() throws an exception for invalid encoding value
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:File:openStream M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MC
+
+
+var t = async_test('File_openStream_encoding_invalid'),
+    resolveSuccess, resolveError, openStreamSuccess, openStreamError,
+    fsTestFileName, fsTestFile, documentsDir;
+
+t.step(function () {
+    fsTestFileName = getFileName("filesystem.txt");
+
+    openStreamSuccess = t.step_func(function (fs) {
+        fs.close();
+        assert_unreached("There in no exception thrown when open the file in invalid encoding");
+    });
+
+    openStreamError = t.step_func(function (error) {
+        assert_unreached("openStream() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        documentsDir = dir;
+        fsTestFile = dir.createFile(fsTestFileName);
+        assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+            fsTestFile.openStream("r", openStreamSuccess, openStreamError, "coding");
+        });
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_openStream_exist() {
+
+//==== TEST: File_openStream_exist
+//==== LABEL Check if File::openStream() method exists
+//==== PRIORITY P0
+//==== SPEC Tizen Web API:IO:Filesystem:File:openStream M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA ME
+var t = async_test('File_openStream_exist'), resolveSuccess, resolveError;
+
+t.step(function (){
+    resolveSuccess = t.step_func(function (dir) {
+        assert_true("openStream" in dir, "method openStream exists");
+        check_method_exists(dir, "listFiles");
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+});
+
+}
+
+function File_openStream_missarg() {
+
+//==== TEST: File_openStream_missarg
+//==== PRIORITY: P2
+//==== LABEL Check if File::openStream() method throws exception for missing mandatory argument
+//==== SPEC: Tizen Web API:IO:Filesystem:File:openStream M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MMA
+
+var t = async_test('File_openStream_missarg'), fsTestFileName, fsTestFile,
+    resolveSuccess, resolveError;
+t.step(function () {
+    fsTestFileName = getFileName("filesystem.txt");
+
+    resolveSuccess = t.step_func(function (dir) {
+        fsTestFile = dir.createFile(fsTestFileName);
+        assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+                fsTestFile.openStream();
+            });
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_openStream_mode_TypeMismatch() {
+
+//==== TEST: File_openStream_mode_TypeMismatch
+//==== LABEL Check if File::openStream() throws exception for wrong type of mode argument
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:IO:Filesystem:File:openStream M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MC
+
+var t = async_test('File_openStream_mode_TypeMismatch'),
+    resolveSuccess, resolveError, conversionTable, i, exceptionName = "TypeMismatchError",
+    openStreamSuccess, mode;
+
+t.step(function () {
+    openStreamSuccess = t.step_func(function (fs) {
+        fs.close();
+        assert_unreached("openStream() success callback invoked: should not be called");
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        conversionTable = getTypeConversionExceptions("enum", false);
+        for (i = 0; i < conversionTable.length; i++) {
+            mode = conversionTable[i][0];
+            exceptionName = conversionTable[i][1];
+
+            assert_throws({name: exceptionName},
+                function () {
+                    dir.openStream(mode, openStreamSuccess);
+                }, exceptionName + " should be thrown - given incorrect mode.");
+        }
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+});
+
+}
+
+function File_openStream_mode_a() {
+
+//==== TEST: File_openStream_mode_a
+//==== LABEL Check if File::openStream() works for mode a
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:File:openStream M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MOA
+
+
+var resolveSuccess, resolveError, openStreamSuccess, openStreamError, fsTestFileName,
+    fsTestFile, documentsDir, t = async_test('File_openStream_mode_a');
+
+t.step(function () {
+    fsTestFileName = getFileName("filesystem.txt");
+
+    openStreamSuccess = t.step_func(function (fs) {
+        fs.close();
+        t.done();
+    });
+
+    openStreamError = t.step_func(function (error) {
+        assert_unreached("openStream() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        documentsDir = dir;
+        fsTestFile = dir.createFile(fsTestFileName);
+        fsTestFile.openStream("a", openStreamSuccess, openStreamError, "UTF-8");
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_openStream_mode_r() {
+
+//==== TEST: File_openStream_mode_r
+//==== LABEL Check if File::openStream() works for mode r
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:File:openStream M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MAST MOA
+
+
+var resolveSuccess, resolveError, openStreamSuccess, openStreamError, fsTestFileName,
+    fsTestFile, documentsDir, t = async_test('File_openStream_mode_r');
+
+t.step(function (){
+    fsTestFileName = getFileName("filesystem.txt");
+
+    openStreamSuccess = t.step_func(function (fs) {
+        fs.close();
+        t.done();
+    });
+
+    openStreamError = t.step_func(function (error) {
+        assert_unreached("openStream() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        documentsDir = dir;
+        fsTestFile = dir.createFile(fsTestFileName);
+        fsTestFile.openStream("r", openStreamSuccess, openStreamError, "UTF-8");
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_openStream_mode_rw() {
+
+//==== TEST: File_openStream_mode_rw
+//==== LABEL Check if File::openStream() works for mode rw
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:File:openStream M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MAST MOA
+
+
+var resolveSuccess, resolveError, openStreamSuccess, openStreamError, fsTestFileName,
+    fsTestFile, documentsDir, t = async_test('File_openStream_mode_rw');
+
+t.step(function () {
+    fsTestFileName = getFileName("filesystem.txt");
+
+    openStreamSuccess = t.step_func(function (fs) {
+        fs.close();
+        t.done();
+    });
+
+    openStreamError = t.step_func(function (error) {
+        assert_unreached("openStream() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        documentsDir = dir;
+        fsTestFile = dir.createFile(fsTestFileName);
+        fsTestFile.openStream("rw", openStreamSuccess, openStreamError, "UTF-8");
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_openStream_mode_w() {
+
+//==== TEST: File_openStream_mode_w
+//==== LABEL Check if File::openStream() works for mode w
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:File:openStream M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MAST MOA
+
+
+var resolveSuccess, resolveError, openStreamSuccess, openStreamError, fsTestFileName,
+    fsTestFile, documentsDir, t = async_test('File_openStream_mode_w');
+
+t.step(function () {
+    fsTestFileName = getFileName("filesystem.txt");
+
+    openStreamSuccess = t.step_func(function (fs) {
+        fs.close();
+        t.done();
+    });
+
+    openStreamError = t.step_func(function (error) {
+        assert_unreached("openStream() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        documentsDir = dir;
+        fsTestFile = dir.createFile(fsTestFileName);
+        fsTestFile.openStream("w", openStreamSuccess, openStreamError, "UTF-8");
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_openStream_onerror_TypeMismatch() {
+//==== TEST: File_openStream_onerror_TypeMismatch
+//==== LABEL Check if File::openStream() method throws exception for wrong type of onerror
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:IO:Filesystem:File:openStream M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MC
+
+var t = async_test('File_openStream_onerror_TypeMismatch'),
+    resolveSuccess, resolveError, conversionTable, openStreamError, i, openStreamSuccess,
+    exceptionName = "TypeMismatchError";
+t.step(function () {
+    openStreamSuccess = t.step_func(function (fs) {
+        fs.close();
+        assert_unreached("openStream() success callback invoked: should not be called");
+    });
+    resolveSuccess = t.step_func(function (dir) {
+        conversionTable = getTypeConversionExceptions("functionObject", true);
+        for (i = 0; i < conversionTable.length; i++) {
+            openStreamError = conversionTable[i][0];
+            exceptionName = conversionTable[i][1];
+
+            assert_throws({name: exceptionName},
+                function () {
+                    dir.openStream("r", openStreamSuccess, openStreamError);
+                }, exceptionName + " should be thrown - given incorrect errorCallback.");
+        }
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+});
+
+}
+
+function File_openStream_onerror_invalid_cb() {
+//==== TEST: File_openStream_onerror_invalid_cb
+//==== LABEL Check if File::openStream() method throws exception for wrong onerror
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:IO:Filesystem:File:openStream M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MTCB
+
+var t = async_test('File_openStream_onerror_invalid_cb'),
+    resolveSuccess, resolveError, openStreamSuccess, openStreamError;
+t.step(function () {
+    openStreamError = {
+        onerror: t.step_func(function (error) {
+            assert_unreached("openStream() error callback invoked: name:" + error.name + "msg:" + error.message);
+        })
+    };
+
+    openStreamSuccess = t.step_func(function (fs) {
+        fs.close();
+        assert_unreached("successCallback should not be called");
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        assert_throws(TYPE_MISMATCH_EXCEPTION,
+            function () {
+                dir.openStream("r", openStreamSuccess, openStreamError);
+            }, "given incorrect errorCallback");
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+});
+
+}
+
+function File_openStream_onsuccess_TypeMismatch() {
+
+//==== TEST: File_openStream_onsuccess_TypeMismatch
+//==== LABEL Check if File::openStream() method throws exception for wrong type of onsuccess
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:IO:Filesystem:File:openStream M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MC
+
+var t = async_test('File_openStream_onsuccess_TypeMismatch'), openStreamSuccess,
+    resolveSuccess, resolveError, conversionTable, i, exceptionName = "TypeMismatchError",
+    fsTestFileName, fsTestFile;
+t.step(function () {
+    fsTestFileName = getFileName("filesystem.txt");
+
+    resolveSuccess = t.step_func(function (dir) {
+        fsTestFile = dir.createFile(fsTestFileName);
+        conversionTable = getTypeConversionExceptions("functionObject", false);
+        for (i = 0; i < conversionTable.length; i++) {
+            openStreamSuccess = conversionTable[i][0];
+            exceptionName = conversionTable[i][1];
+
+            assert_throws({name: exceptionName},
+                function () {
+                    fsTestFile.openStream("r", openStreamSuccess);
+                }, exceptionName + " should be thrown - given incorrect successCallback.");
+        }
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_openStream_onsuccess_invalid_cb() {
+
+//==== TEST: File_openStream_onsuccess_invalid_cb
+//==== LABEL Check if File::openStream() method throws exception for wrong onsuccess
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:IO:Filesystem:File:openStream M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MTCB
+
+var t = async_test('File_openStream_onsuccess_invalid_cb'),
+    resolveSuccess, resolveError, openStreamSuccess, fsTestFileName, fsTestFile;
+t.step(function (){
+    fsTestFileName = getFileName("filesystem.txt");
+
+    openStreamSuccess = {
+        onsuccess: t.step_func(function () {
+            assert_unreached("openStream() success callback invoked: Invalid callback invoked.");
+        })
+    };
+
+    resolveSuccess = t.step_func(function (dir) {
+        fsTestFile = dir.createFile(fsTestFileName);
+        assert_throws(TYPE_MISMATCH_EXCEPTION,
+            function () {
+                fsTestFile.openStream("r", openStreamSuccess);
+            }, "given incorrect successCallback");
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_openStream_with_encoding() {
+
+//==== TEST: File_openStream_with_encoding
+//==== LABEL Check if File::openStream() method can be called with valid encoding argument
+//==== SPEC: Tizen Web API:IO:Filesystem:File:openStream M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MAST MOA
+
+var t = async_test('File_openStream_with_encoding'), resolveSuccess, resolveError,
+    openStreamSuccess, openStreamError, fsTestFileName, fsTestFile;
+
+t.step(function (){
+    fsTestFileName = getFileName("filesystem.txt");
+
+    openStreamError = t.step_func(function (error) {
+        assert_unreached("openStream() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    openStreamSuccess = t.step_func(function (fs) {
+        fs.close();
+        t.done();
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        fsTestFile = dir.createFile(fsTestFileName);
+        fsTestFile.openStream("r", openStreamSuccess, openStreamError, "ISO-8859-1");
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_openStream_with_nonexist_file() {
+//==== TEST: File_openStream_with_nonexist_file
+//==== LABEL Check if File::openStream() method calls errorCallback when invoked for file which was already removed
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:File:openStream M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MERRCB
+
+
+var fsTestFileName, fsTestFile, resolveSuccess, resolveError, deleteFileSuccess,
+    deleteFileError, openStreamSuccess, openStreamError,
+    t = async_test('File_openStream_with_nonexist_file');
+
+t.step(function () {
+    fsTestFileName = getFileName("filesystem.txt");
+
+    openStreamSuccess = t.step_func(function (fs) {
+        fs.close();
+        assert_unreached("openStream() success callback invoked: expect throw an exception when open the file which not exist");
+    });
+
+    openStreamError = t.step_func(function (error) {
+        assert_equals(error.name, "IOError", "expect throw an exception");
+        t.done();
+    });
+
+    deleteFileSuccess = t.step_func(function () {
+        fsTestFile.openStream("r", openStreamSuccess, openStreamError, "UTF-8");
+    });
+
+    deleteFileError = t.step_func(function (error) {
+        assert_unreached("deleteFile() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        fsTestFile = dir.createFile(fsTestFileName);
+        dir.deleteFile(fsTestFile.fullPath, deleteFileSuccess, deleteFileError);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_openStream_with_onerror() {
+
+//==== TEST: File_openStream_with_onerror
+//==== LABEL Check if File::openStream() method calls errorCallback properly (openStream used on directory)
+//==== SPEC: Tizen Web API:IO:Filesystem:File:openStream M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MAST MOA
+
+var t = async_test('File_openStream_with_onerror'),
+    resolveSuccess, resolveError, openStreamSuccess, openStreamError;
+t.step(function (){
+    openStreamError = t.step_func(function () {
+        t.done();
+    });
+    openStreamSuccess = t.step_func(function (fs) {
+        fs.close();
+        assert_unreached("this function should not be executed");
+    });
+    resolveSuccess = t.step_func(function (dir) {
+        dir.openStream("r", openStreamSuccess, openStreamError);
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+});
+
+}
+
+function File_parent_attribute() {
+
+//==== TEST: File_parent_attribute
+//==== LABEL Check if File::parent attribute exists, has type File and is readonly
+//==== SPEC: Tizen Web API:IO:Filesystem:File:parent A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA AE ARO AT
+
+var t = async_test('File_parent_attribute'), resolveSuccess, resolveError, fsTestFileName,
+    fsTestFile, fsTestDir, fsTestDirName;
+
+t.step(function () {
+    fsTestFileName = getFileName("filesystem");
+    fsTestDirName = getDirName("filesystemDir");
+
+    resolveSuccess = t.step_func(function (dir) {
+        assert_true("parent" in dir, "parent attribute doesn't exist");
+        assert_equals(dir.parent, null, "incorrect parent value for root directory");
+        fsTestDir = dir.createDirectory(fsTestDirName);
+        fsTestFile = fsTestDir.createFile(fsTestFileName);
+        assert_type(fsTestFile.parent, "object", "parent isn't an object");
+        checkOwnProperties(fsTestFile.parent);
+        assert_equals(fsTestFile.parent.name, fsTestDir.name, "incorrect parent");
+        fsTestFile.parent = dir;
+        assert_equals(fsTestFile.parent.name, fsTestDir.name, "parent can be modified");
+        t.done();
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_parent_attribute_notnull_using_resolve() {
+
+//==== TEST: File_parent_attribute_notnull_using_resolve
+//==== LABEL Check if File::parent attribute is set by resolve() for subdirectory of Documents
+//==== SPEC: Tizen Web API:IO:Filesystem:File:parent A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA
+
+var t = async_test('File_parent_attribute_notnull_using_resolve'),
+    resolveSuccess, resolveError, resolveFileSuccess, fsTestFileName;
+
+t.step(function (){
+    fsTestFileName = getFileName("filesystem.txt");
+
+    resolveFileSuccess = t.step_func(function (file) {
+        assert_not_equals(file.parent, null, "File.parent should not be null.");
+        t.done();
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        try {
+            dir.createFile(fsTestFileName);
+        } catch (e) {
+            if (e.name !== "IOError") {
+                assert_unreached("createFile() error throw: name: " + e.name + ", msg: " + e.message);
+            }
+        }
+        tizen.filesystem.resolve("documents/" + fsTestFileName, resolveFileSuccess, resolveError, "rw");
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_path_attribute() {
+
+//==== TEST: File_path_attribute
+//==== LABEL Check if File::path attribute exists, has type DOMString and is readonly
+//==== SPEC: Tizen Web API:IO:Filesystem:File:path A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA AE ARO AT
+
+var t = async_test('File_path_attribute'), resolveSuccess, resolveError;
+
+t.step(function () {
+    resolveSuccess = t.step_func(function (dir) {
+        assert_own_property(dir, "path", "file does not have own path property");
+        check_readonly(dir, "path", dir.path, "string", "images");
+        assert_equals(dir.path, "documents", "incorrect path");
+        t.done();
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+});
+
+}
+
+function File_readAsText() {
+
+//==== TEST: File_readAsText
+//==== LABEL Check if File::readAsText() method works properly without errorCallback
+//==== SPEC: Tizen Web API:IO:Filesystem:File:readAsText M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MMINA MR
+
+var t = async_test('File_readAsText'), resolveSuccess, resolveError, stringInFile = "HelloWorld",
+    readAsTextSuccess, file, fsTestFileName = getFileName("testReadAsTextAgain.txt"), retVal = null;
+
+t.step(function () {
+    readAsTextSuccess = t.step_func(function (str) {
+        assert_equals(retVal, undefined, "incorrect returned value");
+        assert_equals(str, stringInFile, "incorrect read value");
+        t.done();
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        file = dir.createFile(fsTestFileName);
+        file.openStream("w",
+            t.step_func(function (fs) {
+                fs.write(stringInFile);
+                fs.close();
+                retVal = file.readAsText(readAsTextSuccess);
+            }));
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t,
+        function () {
+            tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+        }
+    );
+
+});
+
+}
+
+function File_readAsText_encoding_invalid() {
+
+//==== TEST: File_readAsText_encoding_invalid
+//==== LABEL Check if File::readAsText() method throws exception for invalid encoding value
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:File:readAsText M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA
+
+var t = async_test('File_readAsText_encoding_invalid'), resolveSuccess, resolveError,
+    readAsTextSuccess, documentsDir, expected = "TypeMismatchError", fsTestFileName,
+    fsTestFile, readAsTextError;
+
+t.step(function () {
+    fsTestFileName = getFileName("filesystem.txt");
+
+    readAsTextSuccess = t.step_func(function (str) {
+        assert_unreached("readAsText() success callback invoked: There is no exception thrown when readAsText() in invalid encoding");
+    });
+
+    readAsTextError = t.step_func(function (error) {
+        assert_unreached("readAsText() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        documentsDir = dir;
+        fsTestFile = dir.createFile(fsTestFileName);
+        assert_throws({"name": expected}, function () {
+                fsTestFile.readAsText(readAsTextSuccess, readAsTextError, true);
+            });
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_readAsText_exist() {
+
+//==== TEST: File_readAsText_exist
+//==== LABEL Check if File::readAsText() method exists
+//==== PRIORITY P0
+//==== SPEC Tizen Web API:IO:Filesystem:File:readAsText M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA ME
+var t = async_test('File_readAsText_exist'), resolveSuccess, resolveError;
+
+t.step(function (){
+    resolveSuccess = t.step_func(function (dir) {
+        assert_true("readAsText" in dir, "method readAsText exists");
+        check_method_exists(dir, "readAsText");
+        t.done();
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+});
+
+}
+
+function File_readAsText_listDocumentsFiles() {
+//==== TEST: File_readAsText_listDocumentsFiles
+//==== LABEL Check if File::readAsText() method works for a file created in Documents
+//==== SPEC Tizen Web API:IO:Filesystem:File:readAsText M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MOA
+
+var testFile, resolveSuccess, resolveError, readAsTextSuccess,
+    readAsTextError, openStreamSuccess, openStreamError,
+    listFilesSuccess, listFilesError, text = "test write method",
+    t = async_test('File_readAsText_listDocumentsFiles'),
+    fsTestFileName = getFileName("write01.txt");
+
+t.step(function (){
+    readAsTextSuccess = t.step_func(function (str) {
+        assert_equals(str, text, "text read from file is wrong");
+        t.done();
+    });
+
+    readAsTextError = t.step_func(function (error) {
+        assert_unreached("readAsText() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    openStreamSuccess = t.step_func(function (fs) {
+        fs.write(text);
+        fs.close();
+        testFile.readAsText(readAsTextSuccess, readAsTextError, "UTF-8");
+    });
+
+    openStreamError = t.step_func(function (error) {
+        assert_unreached("openStream() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    listFilesSuccess = t.step_func(function (files) {
+        testFile.openStream("rw", openStreamSuccess, openStreamError);
+    });
+
+    listFilesError = t.step_func(function (error) {
+        assert_unreached("listFiles() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        testFile = dir.createFile(fsTestFileName);
+        dir.listFiles(listFilesSuccess, listFilesError);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t,
+        function () {
+            tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+        }
+    );
+});
+
+}
+
+function File_readAsText_listDownloadsFiles() {
+//==== TEST: File_readAsText_listDownloadsFiles
+//==== LABEL Check if File::readAsText() method works for a file created in Downloads
+//==== SPEC Tizen Web API:IO:Filesystem:File:readAsText M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MOA
+
+var t = async_test('File_readAsText_listDownloadsFiles'),
+    text = "test write method", testFile, resolveSuccess, resolveError,
+    listFilesSuccess, listFilesError, openStreamSuccess,
+    openStreamError, readAsTextSuccess, readAsTextError,
+    fsTestFileName = getFileName("write01.txt");
+
+t.step(function (){
+    readAsTextSuccess = t.step_func(function (str) {
+        assert_equals(str, text, "text read from file is wrong");
+        t.done();
+    });
+
+    readAsTextError = t.step_func(function (error) {
+        assert_unreached("readAsText() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    openStreamSuccess = t.step_func(function (fs) {
+        fs.write(text);
+        fs.close();
+        testFile.readAsText(readAsTextSuccess, readAsTextError, "UTF-8");
+    });
+    openStreamError = t.step_func(function (error) {
+        assert_unreached("openStream() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    listFilesSuccess = t.step_func(function (files) {
+        testFile.openStream("rw", openStreamSuccess, openStreamError);
+    });
+    listFilesError = t.step_func(function (error) {
+        assert_unreached("listFiles() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        testFile = dir.createFile(fsTestFileName);
+        dir.listFiles(listFilesSuccess, listFilesError);
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t,
+        function () {
+            tizen.filesystem.resolve("downloads", resolveSuccess, resolveError, "rw");
+        }
+    );
+});
+
+}
+
+function File_readAsText_listImagesFiles() {
+//==== TEST: File_readAsText_listImagesFiles
+//==== LABEL Check if File::readAsText() method works for a file created in Images
+//==== SPEC Tizen Web API:IO:Filesystem:File:readAsText M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MOA
+
+var text = "test write method", t = async_test('File_readAsText_listImagesFiles'),
+    testFile, resolveSuccess, resolveError, listFilesSuccess,
+    listFilesError, openStreamSuccess, openStreamError,
+    readAsTextSuccess, readAsTextError,
+    fsTestFileName = getFileName("write01.txt");
+
+t.step(function (){
+    readAsTextSuccess = t.step_func(function (str) {
+        assert_equals(str, text, "text read from file is wrong");
+        t.done();
+    });
+
+    readAsTextError = t.step_func(function (error) {
+        assert_unreached("readAsText() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    openStreamSuccess = t.step_func(function (fs) {
+        fs.write(text);
+        fs.close();
+        testFile.readAsText(readAsTextSuccess, readAsTextError, "UTF-8");
+    });
+
+    openStreamError = t.step_func(function (error) {
+        assert_unreached("openStream() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    listFilesSuccess = t.step_func(function (files) {
+        testFile.openStream("rw", openStreamSuccess, openStreamError);
+    });
+
+    listFilesError = t.step_func(function (error) {
+        assert_unreached("listFiles() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        testFile = dir.createFile(fsTestFileName);
+        dir.listFiles(listFilesSuccess, listFilesError);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t,
+        function () {
+            tizen.filesystem.resolve("images", resolveSuccess, resolveError, "rw");
+        }
+    );
+});
+
+}
+
+function File_readAsText_listMusicFiles() {
+//==== TEST: File_readAsText_listMusicFiles
+//==== LABEL Check if File::readAsText() method works for a file created in Music
+//==== SPEC Tizen Web API:IO:Filesystem:File:readAsText M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MOA
+
+var testFile, resolveSuccess, resolveError, listFilesSuccess,
+    listFilesError, openStreamSuccess, openStreamError, readAsTextSuccess,
+    readAsTextError, text = "test write method",
+    t = async_test('File_readAsText_listMusicFiles'),
+    fsTestFileName = getFileName("write01.txt");
+
+t.step(function (){
+    readAsTextSuccess = t.step_func(function (str) {
+        assert_equals(str, text, "text read from file is wrong");
+        t.done();
+    });
+
+    readAsTextError = t.step_func(function (error) {
+        assert_unreached("readAsText() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    openStreamSuccess = t.step_func(function (fs) {
+        fs.write(text);
+        fs.close();
+        testFile.readAsText(readAsTextSuccess, readAsTextError, "UTF-8");
+    });
+
+    openStreamError = t.step_func(function (error) {
+        assert_unreached("openStream() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    listFilesSuccess = t.step_func(function (files) {
+        testFile.openStream("rw", openStreamSuccess, openStreamError);
+    });
+
+    listFilesError = t.step_func(function (error) {
+        assert_unreached("listFiles() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        testFile = dir.createFile(fsTestFileName);
+        dir.listFiles(listFilesSuccess, listFilesError);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t,
+        function () {
+            tizen.filesystem.resolve("music", resolveSuccess, resolveError, "rw");
+        }
+    );
+});
+
+}
+
+function File_readAsText_listVideosFiles() {
+//==== TEST: File_readAsText_listVideosFiles
+//==== LABEL Check if File::readAsText() method works for a file created in Videos
+//==== SPEC Tizen Web API:IO:Filesystem:File:readAsText M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MOA
+
+var text = "test write method", t = async_test('File_readAsText_listVideosFiles'),
+    testFile, resolveSuccess, resolveError, listFilesSuccess,
+    listFilesError, openStreamSuccess, openStreamError,
+    readAsTextSuccess, readAsTextError,
+    fsTestFileName = getFileName("write01.txt");
+
+t.step(function (){
+    readAsTextSuccess = t.step_func(function (str) {
+        assert_equals(str, text, "text read from file is wrong");
+        t.done();
+    });
+
+    readAsTextError = t.step_func(function (error) {
+        assert_unreached("readAsText() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    openStreamSuccess = t.step_func(function (fs) {
+        fs.write(text);
+        fs.close();
+        testFile.readAsText(readAsTextSuccess, readAsTextError, "UTF-8");
+    });
+
+    openStreamError = t.step_func(function (error) {
+        assert_unreached("openStream() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    listFilesSuccess = t.step_func(function (files) {
+        testFile.openStream("rw", openStreamSuccess, openStreamError);
+    });
+
+    listFilesError = t.step_func(function (error) {
+        assert_unreached("listFiles() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        testFile = dir.createFile(fsTestFileName);
+        dir.listFiles(listFilesSuccess, listFilesError);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t,
+        function () {
+            tizen.filesystem.resolve("videos", resolveSuccess, resolveError, "rw");
+        }
+    );
+});
+
+}
+
+function File_readAsText_missarg() {
+
+//==== TEST: File_readAsText_missarg
+//==== PRIORITY: P2
+//==== LABEL Check if File::readAsText() throws exception for missing mandatory parameter
+//==== SPEC: Tizen Web API:IO:Filesystem:File:readAsText M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MMA
+
+var t = async_test('File_readAsText_missarg'),
+    resolveSuccess, resolveError, file,
+    fsTestFileName = getFileName("testMissArg.txt");
+
+t.step(function () {
+    resolveSuccess = t.step_func(function (dir) {
+        file = dir.createFile(fsTestFileName);
+        file.openStream("w",
+            t.step_func(function (fs) {
+                fs.write("HelloWorld");
+                fs.close();
+                assert_throws(TYPE_MISMATCH_EXCEPTION,
+                    function () {
+                        file.readAsText();
+                    });
+                t.done();
+            }));
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t,
+        function () {
+            tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+        }
+    );
+
+});
+
+}
+
+function File_readAsText_onerror_TypeMismatch() {
+//==== TEST: File_readAsText_onerror_TypeMismatch
+//==== LABEL Check if File::readAsText() method throws exception for wrong type of onerror
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:IO:Filesystem:File:readAsText M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MC
+
+var t = async_test('File_readAsText_onerror_TypeMismatch'),
+    resolveSuccess, resolveError, conversionTable, readAsTextError, i,
+    readAsTextSuccess, exceptionName = "TypeMismatchError";
+
+t.step(function () {
+    readAsTextSuccess = t.step_func(function () {
+        assert_unreached("successCalback should not be called");
+    });
+    resolveSuccess = t.step_func(function (dir) {
+        conversionTable = getTypeConversionExceptions("functionObject", true);
+        for (i = 0; i < conversionTable.length; i++) {
+            readAsTextError = conversionTable[i][0];
+            exceptionName = conversionTable[i][1];
+
+            assert_throws({name: exceptionName},
+                function () {
+                    dir.readAsText(readAsTextSuccess, readAsTextError);
+                }, exceptionName + " should be thrown - given incorrect errorCallback.");
+        }
+        t.done();
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+});
+
+}
+
+function File_readAsText_onerror_invalid_cb() {
+//==== TEST: File_readAsText_onerror_invalid_cb
+//==== LABEL Check if File::readAsText() method throws exception for wrong onerror
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:IO:Filesystem:File:readAsText M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MTCB
+
+var t = async_test('File_readAsText_onerror_invalid_cb'),
+    resolveSuccess, resolveError, readAsTextSuccess, readAsTextError;
+
+t.step(function () {
+    readAsTextError = {
+        onerror: t.step_func(function () {
+            assert_unreached("Invalid callback invoked: ");
+        })
+    };
+    readAsTextSuccess = t.step_func(function () {
+        assert_unreached("successCallback should not be called");
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        assert_throws(TYPE_MISMATCH_EXCEPTION,
+            function () {
+                dir.readAsText(readAsTextSuccess, readAsTextError);
+            }, "given incorrect errorCallback");
+        t.done();
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+});
+
+}
+
+function File_readAsText_onsuccess_TypeMismatch() {
+//==== TEST: File_readAsText_onsuccess_TypeMismatch
+//==== LABEL Check if File::readAsText() method throws exception for wrong type of onsuccess
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:IO:Filesystem:File:readAsText M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MC
+
+var t = async_test('File_readAsText_onsuccess_TypeMismatch'), readAsTextSuccess,
+    resolveSuccess, resolveError, conversionTable, i, file,
+    exceptionName = "TypeMismatchError",
+    fsTestFileName = getFileName("goodFile2.txt");
+
+t.step(function (){
+    resolveSuccess = t.step_func(function (dir) {
+        file = dir.createFile(fsTestFileName);
+        conversionTable = getTypeConversionExceptions("functionObject", false);
+
+        for (i = 0; i < conversionTable.length; i++) {
+            readAsTextSuccess = conversionTable[i][0];
+            exceptionName = conversionTable[i][1];
+
+            assert_throws({name: exceptionName},
+                function () {
+                    file.readAsText(readAsTextSuccess);
+                }, exceptionName + " should be thrown - given incorrect successCallback.");
+        }
+        t.done();
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t,
+        function () {
+            tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+        }
+    );
+
+});
+
+}
+
+function File_readAsText_onsuccess_invalid_cb() {
+//==== TEST: File_readAsText_onsuccess_invalid_cb
+//==== LABEL Check if File::readAsText() method throws exception for wrong onsuccess
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:IO:Filesystem:File:readAsText M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MTCB
+
+var t = async_test('File_readAsText_onsuccess_invalid_cb'),
+    resolveSuccess, resolveError, readAsTextSuccess,
+    fsTestFileName = getFileName("goodFile.txt"), file;
+
+t.step(function (){
+    readAsTextSuccess = {
+        onsuccess: t.step_func(function () {
+            assert_unreached("Invalid callback invoked: ");
+        })
+    };
+    resolveSuccess = t.step_func(function (dir) {
+        file = dir.createFile(fsTestFileName);
+        assert_throws(TYPE_MISMATCH_EXCEPTION,
+            function () {
+                file.readAsText(readAsTextSuccess);
+            }, "given incorrect successCallback");
+        t.done();
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t,
+        function () {
+            tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+        }
+    );
+
+});
+
+}
+
+function File_readAsText_with_encoding() {
+//==== TEST: File_readAsText_with_encoding
+//==== LABEL Check if File::readAsText() method works with encoding argument
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:IO:Filesystem:File:readAsText M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MOA
+
+var t = async_test('File_readAsText_with_encoding'),
+    resolveSuccess, resolveError, listFilesSuccess, listFilesError,
+    readAsTextSuccess, readAsTextError, i;
+
+t.step(function (){
+    readAsTextSuccess = t.step_func(function (text) {
+        t.done();
+    });
+    readAsTextError = t.step_func(function (error) {
+        assert_unreached("readAsText() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    listFilesSuccess = t.step_func(function (files) {
+        for (i = 0; i < files.length; i++) {
+            if (files[i].isDirectory === false){
+                files[i].readAsText(readAsTextSuccess,
+                    readAsTextError, "ISO-8859-1");
+            }
+        }
+    });
+    listFilesError = t.step_func(function (error) {
+        assert_unreached("listFiles() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        dir.listFiles(listFilesSuccess, listFilesError);
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+});
+
+}
+
+function File_readAsText_with_onerror() {
+//==== TEST: File_readAsText_with_onerror
+//==== LABEL Check if File::readAsText() properly calls errorCallback (called on a directory instead of file)
+//==== SPEC: Tizen Web API:IO:Filesystem:File:readAsText M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MERRCB
+
+var t = async_test('File_readAsText_with_onerror'),
+    resolveSuccess, resolveError, readAsTextSuccess, readAsTextError;
+
+t.step(function () {
+    readAsTextError = t.step_func(function (error) {
+        assert_equals(error.name, "IOError", "incorrect error name");
+        assert_type(error.message, "string", "incorrect error message type");
+        assert_not_equals(error.message, "", "incorrect error message");
+        t.done();
+    });
+    readAsTextSuccess = t.step_func(function (text) {
+        assert_unreached("readAsTextSuccess: readAsTextError should be invoked");
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        dir.readAsText(readAsTextSuccess, readAsTextError);
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+});
+
+}
+
+function File_readOnly_attribute() {
+//==== TEST: File_readOnly_attribute
+//==== LABEL Check if File::readOnly attribute exists, has type Boolean and is readonly
+//==== SPEC: Tizen Web API:IO:Filesystem:File:readOnly A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA AE AT ARO
+
+var t = async_test('File_readOnly_attribute'),
+    onSuccess, onError;
+t.step(function () {
+    onSuccess = t.step_func(function (dir) {
+        assert_own_property(dir, "readOnly", "File does not own readOnly property.");
+        check_readonly(dir, "readOnly", false, "boolean", true);
+        t.done();
+    });
+    onError = t.step_func(function (error) {
+        assert_unreached("Error: " + error.message);
+    });
+
+    tizen.filesystem.resolve("documents", onSuccess, onError, "rw");
+});
+
+}
+
+function File_resolve() {
+//==== TEST: File_resolve
+//==== LABEL Check if File::resolve() method works properly
+//==== SPEC: Tizen Web API:IO:Filesystem:File:resolve M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MMINA MR
+
+var t = async_test('File_resolve'),
+    resolveSuccess, resolveError, listFilesSuccess, i, ds, file,
+    fsTestFileName = getFileName("goodFile2.txt");
+t.step(function () {
+    listFilesSuccess = t.step_func(function (files) {
+        for (i = 0; i < files.length; i++) {
+            if (files[i].name === fsTestFileName) {
+                file = ds.resolve(fsTestFileName);
+                assert_equals(file.name, fsTestFileName, "Attribute check");
+                t.done();
+            }
+        }
+    });
+    resolveSuccess = t.step_func(function (dir) {
+        ds = dir;
+        dir.createFile(fsTestFileName);
+        dir.listFiles(listFilesSuccess);
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t,
+        function () {
+            tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+        }
+    );
+
+});
+
+}
+
+function File_resolve_exist() {
+//==== TEST: File_resolve_exist
+//==== LABEL Check if File::resolve() method exists
+//==== PRIORITY P0
+//==== SPEC Tizen Web API:IO:Filesystem:File:resolve M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA ME
+
+var t = async_test('File_resolve_exist'),
+    onSuccess, onError;
+t.step(function (){
+    onSuccess = t.step_func(function (dir) {
+        assert_true("resolve" in dir, "method resolve exists");
+        check_method_exists(dir, "resolve");
+        t.done();
+    });
+    onError = t.step_func(function (error) {
+        assert_unreached("Error: " + error.message);
+    });
+
+    tizen.filesystem.resolve("documents", onSuccess, onError, "rw");
+});
+
+}
+
+function File_resolve_with_nonexist() {
+
+//==== TEST: File_resolve_with_nonexist
+//==== LABEL Check if File::resolve() throws exception when resolving a file which not exist
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:File:resolve M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA
+
+var t = async_test('File_resolve_with_nonexist'), resolveSuccess, resolveError, fsTestFileName, expected = "NotFoundError";
+
+t.step(function () {
+    fsTestFileName = getFileName("noExistFile.txt");
+
+    resolveSuccess = t.step_func(function (dir) {
+        try{
+            dir.resolve(fsTestFileName);
+        }catch(error) {
+            assert_equals(error.name, expected, "expect throw an exception");
+            t.done();
+        }
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t,
+        function () {
+            tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+        }
+    );
+
+});
+
+}
+
+function File_toURI() {
+
+//==== TEST: File_toURI
+//==== LABEL Check if File::toURI() method works properly
+//==== SPEC: Tizen Web API:IO:Filesystem:File:toURI M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MNA MR
+
+var t = async_test('File_toURI'), resolveSuccess, resolveError, returnedValue, fsTestFileName, fsTestFile;
+
+t.step(function () {
+    fsTestFileName =  getFileName("filesystem.txt");
+
+    resolveSuccess = t.step_func(function (dir) {
+        fsTestFile = dir.createFile(fsTestFileName);
+        returnedValue = fsTestFile.toURI();
+        assert_type(returnedValue, "string", "incorrect returned type");
+        assert_not_equals(returnedValue, "", "incorrect returned value");
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+});
+
+}
+
+function File_toURI_exist() {
+
+//==== TEST: File_toURI_exist
+//==== LABEL Check if File::toURI() method exists
+//==== PRIORITY P0
+//==== SPEC Tizen Web API:IO:Filesystem:File:toURI M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA ME
+
+var t = async_test('File_toURI_exist'), resolveSuccess, resolveError;
+
+t.step(function () {
+    resolveSuccess = t.step_func(function (dir) {
+        check_method_exists(dir, "toURI");
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    tizen.filesystem.resolve("documents", resolveSuccess, resolveError);
+});
+
+}
+
+function File_toURI_extra_argument() {
+
+//==== TEST: File_toURI_extra_argument
+//==== LABEL Check if File::toURI() method accepts extra argument
+//==== SPEC: Tizen Web API:IO:Filesystem:File:toURI M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MNAEX
+
+var t = async_test('File_toURI_extra_argument'), resolveSuccess, resolveError;
+
+t.step(function (){
+    resolveSuccess = t.step_func(function (dir) {
+        checkExtraArgument(dir, "toURI");
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    tizen.filesystem.resolve("documents", resolveSuccess, resolveError);
+});
+
+}
+
+function File_toURI_with_nonexist_file() {
+//==== TEST: File_toURI_with_nonexist_file
+//==== LABEL Check if File::toURI() method throws exception when get a URI of non-existing file
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:File:toURI M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MNA
+
+
+var t = async_test('File_toURI_with_nonexist_file'),
+    resolveSuccess, resolveError, deleteFileSuccess, deleteFileError , fsTestFileName, fsTestFile, returnedValue;
+
+t.step(function () {
+    fsTestFileName =  getFileName("filesystem.txt");
+
+    deleteFileSuccess = t.step_func(function () {
+        returnedValue = fsTestFile.toURI();
+        assert_type(returnedValue, "string", "wrong type");
+        t.done();
+    });
+
+    deleteFileError = t.step_func(function (error) {
+        assert_unreached("deleteFile() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        fsTestFile = dir.createFile(fsTestFileName);
+        dir.deleteFile(fsTestFile.fullPath, deleteFileSuccess, deleteFileError);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t, function () {
+        tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+    });
+
+});
+
+}
+
+function filesystem_FileStreamSuccessCallback_onsuccess() {
+//==== TEST: filesystem_FileStreamSuccessCallback_onsuccess
+//==== LABEL Test whether FileStreamSuccessCallback::onsuccess is called with valid argument
+//==== SPEC Tizen Web API:IO:Filesystem:FileStreamSuccessCallback:onsuccess M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA CBOA
+
+var t = async_test('filesystem_FileStreamSuccessCallback_onsuccess'),
+    resolveSuccess, resolveError, openStreamSuccess, openStreamError, file,
+    fsTestFileName = getFileName("successFile.txt");
+
+t.step(function () {
+    openStreamSuccess = t.step_func(function (fs) {
+        assert_not_equals(fs, null, "fs should not be null");
+        fs.close();
+        t.done();
+    });
+    openStreamError = t.step_func(function (error) {
+        assert_unreached("openStream() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        file = dir.createFile(fsTestFileName);
+        file.openStream("w", openStreamSuccess, openStreamError, "UTF-8");
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t,
+        function () {
+            tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+        }
+    );
+});
+
+}
+
+function filesystem_File_copyTo() {
+//==== TEST: filesystem_File_copyTo
+//==== LABEL Check if File::copyTo() can be called
+//==== PRIORITY P0
+//==== SPEC Tizen Web API:IO:Filesystem:File:copyTo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MOA
+
+var t = async_test('filesystem_File_copyTo'),
+    createFile, resolveSuccess, resolveError, copyToSuccess, copyToError,
+    fsTestFileName = getFileName("copyFile.txt");
+
+t.step(function (){
+    copyToSuccess = t.step_func(function () {
+        t.done();
+    });
+    copyToError = t.step_func(function (error) {
+        assert_unreached("copyTo() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        createFile = dir.createFile(fsTestFileName);
+        dir.copyTo(createFile.fullPath, "downloads/" + createFile.name, true, copyToSuccess, copyToError);
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t,
+        function () {
+            tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+        }
+    );
+});
+
+}
+
+function filesystem_File_readAsText() {
+//==== TEST: filesystem_File_readAsText
+//==== LABEL Check if File::readAsText() method reads the content of a file as a DOMString
+//==== SPEC Tizen Web API:IO:Filesystem:File:readAsText M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MOA
+
+var t = async_test('filesystem_File_readAsText'), text = "test write method",
+    testFile, resolveSuccess, resolveError, openStreamSuccess, openStreamError,
+    readAsTextSuccess, readAsTextError,
+    fsTestFileName = getFileName("write01.txt");
+
+t.step(function (){
+    readAsTextSuccess = t.step_func(function (str) {
+        assert_equals(str, text, "text read from file is wrong");
+        t.done();
+    });
+    readAsTextError = t.step_func(function (error) {
+        assert_unreached("readAsText() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    openStreamSuccess = t.step_func(function (fs) {
+        fs.write(text);
+        fs.close();
+        testFile.readAsText(readAsTextSuccess, readAsTextError, "UTF-8");
+    });
+    openStreamError = t.step_func(function (error) {
+        assert_unreached("openStream() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        testFile = dir.createFile(fsTestFileName);
+        testFile.openStream("rw", openStreamSuccess, openStreamError, "UTF-8");
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t,
+        function () {
+            tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+        }
+    );
+});
+
+}
+
+function filesystem_File_resolve() {
+//==== TEST: filesystem_File_resolve
+//==== LABEL Check if File::resolve() method called for a file returns a file handle
+//==== SPEC Tizen Web API:IO:Filesystem:File:resolve M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MMINA
+
+var t = async_test('filesystem_File_resolve'),
+    resolveSuccess, resolveError, expected = "object", handle,
+    fsTestFileName = getFileName("resolve.doc");
+
+t.step(function () {
+    resolveSuccess = t.step_func(function (dir) {
+        dir.createFile(fsTestFileName);
+        handle = dir.resolve(fsTestFileName);
+        assert_equals(typeof(handle), expected, "resolve a file and return a file handle");
+        t.done();
+    });
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t,
+        function () {
+            tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+        }
+    );
+});
+
+}
+
+function FileSystemManager_resolve_location_invalid() {
+//==== TEST: FileSystemManager_resolve_location_invalid
+//==== LABEL Check if FileSystemManager::resolve() method work for invalid location
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:resolve M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MERRCB
+
+var t = async_test('FileSystemManager_resolve_location_invalid'), resolveSuccess, resolveError;
+
+t.step(function () {
+    resolveSuccess = t.step_func(function (dir) {
+        assert_unreached("resolveSuccess was invoked");
+    });
+
+    resolveError = t.step_func(function (error) {
+        t.done();
+    });
+
+    tizen.filesystem.resolve("", resolveSuccess, resolveError, "rw");
+});
+
+}
+
+function FileSystemManager_resolve_errorCallback_invoked() {
+//==== TEST: FileSystemManager_resolve_errorCallback_invoked
+//==== LABEL Check if errorcallback of FileSystemManager::resolve() method can be invoked when location is wrong type
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:resolve M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MERRCB
+
+var t = async_test('FileSystemManager_resolve_errorCallback_invoked'), resolveSuccess, resolveError;
+
+t.step(function () {
+    resolveSuccess = t.step_func(function (dir) {
+        assert_unreached("resolveSuccess was invoked");
+    });
+
+    resolveError = t.step_func(function (error) {
+        t.done();
+    });
+
+    tizen.filesystem.resolve(undefined, resolveSuccess, resolveError, "rw");
+});
+
+}
+
+function FileSystemManager_getStorage_errorCallback_invoked() {
+//==== TEST: FileSystemManager_getStorage_errorCallback_invoked
+//==== LABEL Check if errorcallback of FileSystemManager::getStorage() method can be invoked
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:FileSystemManager:getStorage M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MERRCB
+
+var t = async_test('FileSystemManager_getStorage_errorCallback_invoked'), onSuccess, onError, label;
+
+t.step(function (){
+    onSuccess = t.step_func(function (storages) {
+        assert_unreached("success callback was invoked");
+    });
+
+    onError = t.step_func(function (error) {
+        assert_equals(error.name, NOT_FOUND_EXCEPTION, "expect throw an exception");
+        t.done();
+    });
+
+    tizen.filesystem.getStorage(label, onSuccess, onError);
+    t.done();
+});
+
+}
+
+function File_openStream_mode_invalid() {
+//==== TEST: File_openStream_mode_invalid
+//==== LABEL Check if File::openStream() method throws exception for wrong mode
+//==== PRIORITY P2
+//==== SPEC: Tizen Web API:IO:Filesystem:File:openStream M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MC
+
+var t = async_test('File_openStream_mode_invalid'), resolveSuccess, resolveError, openStreamSuccess;
+
+t.step(function () {
+    resolveSuccess = t.step_func(function (dir) {
+        assert_throws(TYPE_MISMATCH_EXCEPTION,
+            function () {
+                dir.openStream(5);
+            }, TYPE_MISMATCH_EXCEPTION + " should be thrown - given invalid mode");
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+});
+
+}
+
+function File_copyTo_destinationFilePath_invalid() {
+//==== TEST: File_copyTo_destinationFilePath_invalid
+//==== LABEL Check if copyTo method called with invalid destinationFilePath does what it should
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:File:copyTo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MERRCB
+
+var t = async_test('File_copyTo_destinationFilePath_invalid'), resolveSuccess, resolveError, fsTestFile, fsTestFileName, copyToFileSuccess, copyToFileError;
+
+t.step(function (){
+    fsTestFileName = getFileName("filesystemtyh.txt");
+    copytoFileSuccess = t.step_func(function () {
+        assert_unreached("copyTo: should invoke error callback");
+    });
+
+    copytoFileError = t.step_func(function (error) {
+        t.done();
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        fsTestFile = dir.createFile(fsTestFileName);
+        dir.copyTo(fsTestFile.fullPath, "", true, copytoFileSuccess, copytoFileError);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+});
+
+}
+
+function File_copyTo_originFilePath_invalid() {
+//==== TEST: File_copyTo_originFilePath_invalid
+//==== LABEL Check if copyTo method called with invalid originFilePath does what it should
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:File:copyTo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MERRCB
+
+var t = async_test('File_copyTo_originFilePath_invalid'), resolveSuccess, resolveError, fsTestFile, fsTestFileName, copyToFileSuccess, copyToFileError;
+
+t.step(function (){
+    fsTestFileName = getFileName("filesystem.txt");
+
+    copytoFileSuccess = t.step_func(function () {
+        assert_unreached("copyTo:should invoke error callback");
+    });
+
+    copytoFileError = t.step_func(function (error) {
+        t.done();
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        fsTestFile = dir.createFile(fsTestFileName);
+        dir.copyTo("", "images/" + fsTestFile.name, true, copytoFileSuccess, copytoFileError);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+});
+
+}
+
+function File_createDirectory_misarg() {
+//==== TEST: File_createDirectory_misarg
+//==== LABEL Check if createDirectory method throws exception with missing non-optional argument
+//==== SPEC Tizen Web API:IO:Filesystem:File:createDirectory M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MMA
+
+var t = async_test('File_createDirectory_misarg'), resolveSuccess, resolveError;
+
+t.step(function (){
+    resolveSuccess = t.step_func(function (dir) {
+        assert_throws(INVALID_VALUES_EXCEPTION,
+            function () {
+                dir.createDirectory();
+            }, INVALID_VALUES_EXCEPTION + " should be thrown");
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+});
+
+}
+
+function File_resolve_misarg() {
+//==== TEST: File_resolve_misarg
+//==== LABEL Check if File::resolve() throws exception when resolving a file which missing argument
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:File:resolve M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MMA
+
+var t = async_test('File_resolve_misarg'), resolveSuccess, resolveError, fsTestFileName;
+
+t.step(function () {
+    fsTestFileName = getFileName("noExistFile.txt");
+    resolveSuccess = t.step_func(function (dir) {
+        try {
+            dir.resolve();
+        } catch (error) {
+            t.done();
+        }
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+});
+
+}
+
+function File_deleteDirectory_misarg() {
+//==== TEST: File_deleteDirectory_misarg
+//==== LABEL Check if File::deleteDirectory() throws exception with missing mandatory argument
+//==== SPEC Tizen Web API:IO:Filesystem:File:deleteDirectory M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MMA
+
+var t = async_test('File_deleteDirectory_misarg'), resolveSuccess, resolveError, fsTestDirName;
+
+t.step(function () {
+    fsTestDirName = getDirName("filesystem");
+    resolveSuccess = t.step_func(function (dir) {
+        dir.createDirectory(fsTestDirName);
+        assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+            dir.deleteDirectory();
+        }, TYPE_MISMATCH_EXCEPTION + " should be thrown.");
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+});
+
+}
+
+function File_path_attribute_limitation() {
+//==== TEST: File_path_attribute_limitation
+//==== LABEL Check if File::path attribute has proper value limitation
+//==== SPEC: Tizen Web API:IO:Filesystem:File:path A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA AVL
+
+var t = async_test('File_path_attribute_limitation'), resolveSuccess, resolveError;
+
+t.step(function () {
+    resolveSuccess = t.step_func(function (dir) {
+        assert_less_than_equal(dir.path.length, tizen.filesystem.maxPathLength, "the length of path should not have value greater than maxPathLength");
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+});
+
+}
+
+function FileStream_read_misarg() {
+//==== TEST: FileStream_read_misarg
+//==== LABEL Check if FileStream::read() throws exception with missing mandatory argument
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:FileStream:read M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MMA
+
+var t = async_test('FileStream_read_misarg'), fsTestFileName = getFileName("filesystem01.txt"), resolveSuccess, resolveError, openStreamError, openStreamSuccess, openStreamReadSuccess, file;
+
+t.step(function (){
+    openStreamReadSuccess = t.step_func(function (fs) {
+        assert_throws(INVALID_VALUES_EXCEPTION, function () {
+            fs.read();
+        }, INVALID_VALUES_EXCEPTION + " should be thrown - missing type");
+        t.done();
+    });
+
+    openStreamSuccess = t.step_func(function (fs) {
+        fs.write("abcdefg");
+        fs.close();
+        file.openStream("r", openStreamReadSuccess, openStreamError);
+    });
+
+    openStreamError = t.step_func(function (error) {
+        assert_unreached("openStream() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        file = dir.createFile(fsTestFileName);
+        file.openStream("w", openStreamSuccess, openStreamError);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    prepareForTesting(t,
+        function () {
+            tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+        }
+    );
+});
+
+}
+
+function FileStream_read_TypeMismatch() {
+//==== TEST: FileStream_read_TypeMismatch
+//==== LABEL Check if FileStream::read() throws an exception when given wrong type of charCount
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:FileStream:read M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MC
+
+var t = async_test('FileStream_read_TypeMismatch'), fsTestFileName = getFileName("write03.txt"), testFile, resolveSuccess, resolveError, openStreamSuccess, openStreamError, charCount, conversionTable, i;
+
+t.step(function () {
+    conversionTable = getTypeConversionExceptions("long", false);
+    openStreamSuccess = t.step_func(function (fs) {
+        for (i = 0; i < conversionTable.length; i++) {
+            charCount = conversionTable[i][0];
+            assert_throws(INVALID_VALUES_EXCEPTION,
+                function () {
+                    fs.read(charCount);
+                }, INVALID_VALUES_EXCEPTION + " should be thrown - charCount type mismatch.");
+        }
+        fs.close();
+        t.done();
+    });
+
+    openStreamError = t.step_func(function (error) {
+        assert_unreached("openStream() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        testFile = dir.createFile(fsTestFileName);
+        testFile.openStream("r", openStreamSuccess, openStreamError, "UTF-8");
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+});
+
+}
+
+function File_createDirectory_dirPath_invalid() {
+//==== TEST: File_createDirectory_dirPath_invalid
+//==== LABEL Check if File::createDirectory() throws exception when dirPath is invalid.
+//==== SPEC Tizen Web API:IO:Filesystem:File:createDirectory M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== PRIORITY: P2
+//==== TEST_CRITERIA MC
+
+var t = async_test('File_createDirectory_dirPath_invalid'), resolveSuccess, resolveError, fsTestDir;
+
+t.step(function (){
+    resolveSuccess = t.step_func(function (dir) {
+        assert_throws(INVALID_VALUES_EXCEPTION,
+            function () {
+                fsTestDir = dir.createDirectory("");
+            }, INVALID_VALUES_EXCEPTION + " should be thrown - invalid dirPath ");
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+});
+
+}
+
+function File_openStream_with_encoding_not_default() {
+//==== TEST: File_openStream_with_encoding_not_default
+//==== LABEL Check if File::openStream() method works properly when the encoding is "ISO-8859-1"
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:File:openStream M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MC
+
+var t = async_test('File_openStream_with_encoding_not_default'), resolveSuccess, resolveError, openStreamError, openStreamSuccess, fsTestFileName, fsTestFile;
+
+t.step(function () {
+    fsTestFileName = getFileName("filesystem06.txt");
+
+    openStreamSuccess = t.step_func(function (fs) {
+        fs.close();
+        t.done();
+    });
+
+    openStreamError = t.step_func(function (error) {
+        assert_unreached("openStream() error callback invoked: should not be called");
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        fsTestFile = dir.createFile(fsTestFileName);
+        fsTestFile.openStream("r", openStreamSuccess, openStreamError, "ISO-8859-1");
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+});
+
+}
+
+function File_readAsText_with_encoding_not_default() {
+//==== TEST: File_readAsText_with_encoding_not_default
+//==== LABEL Check if File::readAsText() method works properly when the encoding is "ISO-8859-1"
+//==== PRIORITY P2
+//==== SPEC: Tizen Web API:IO:Filesystem:File:readAsText M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MC
+
+var t = async_test('File_readAsText_with_encoding_not_default'), resolveSuccess, resolveError, readAsTextError, readAsTextSuccess, fsTestFileName, fsTestFile;
+
+t.step(function () {
+    fsTestFileName = getFileName("filesystem07.txt");
+
+    readAsTextSuccess = t.step_func(function () {
+        t.done();
+    });
+
+    readAsTextError = t.step_func(function (error) {
+        assert_unreached("readAsText() errorcallback should not be called");
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        fsTestFile = dir.createFile(fsTestFileName);
+        fsTestFile.readAsText(readAsTextSuccess, readAsTextError, "ISO-8859-1");
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+});
+
+}
+
+function File_resolve_filePath_invalid() {
+//==== TEST: File_resolve_filePath_invalid
+//==== LABEL Check if File::resolve() throws exception when filePath is invalid
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:File:resolve M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MC
+
+var t = async_test('File_resolve_filePath_invalid'), resolveSuccess, resolveError;
+
+t.step(function () {
+    resolveSuccess = t.step_func(function (dir) {
+        assert_throws(NOT_FOUND_EXCEPTION, function () {
+            dir.resolve(true);
+        }, NOT_FOUND_EXCEPTION + " should be thrown - invalid filePath.");
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+});
+
+}
+
+function FileStream_readBytes_misarg() {
+//==== TEST: FileStream_readBytes_misarg
+//==== LABEL Check if FileStream::readBytes() with missing mandatory argument throws exception
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Filesystem:FileStream:readBytes M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== TEST_CRITERIA MMA
+
+var t = async_test('FileStream_readBytes_misarg'), fsTestFileName = getFileName("readBytesFile.txt"), stringToWrite = "1234567", resolveSuccess, resolveError,
+    openStreamSuccess, openStreamError, openStreamReadSuccess, file;
+
+t.step(function () {
+    openStreamReadSuccess = t.step_func(function (fs) {
+        assert_throws(INVALID_VALUES_EXCEPTION, function () {
+            fs.readBytes();
+        }, INVALID_VALUES_EXCEPTION + " should be thrown.");
+        fs.close();
+        t.done();
+    });
+
+    openStreamSuccess = t.step_func(function (fs) {
+        fs.write(stringToWrite);
+        fs.close();
+        file.openStream("r", openStreamReadSuccess, openStreamError);
+    });
+
+    openStreamError = t.step_func(function (error) {
+        assert_unreached("openStream() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    resolveSuccess = t.step_func(function (dir) {
+        file = dir.createFile(fsTestFileName);
+        file.openStream("w", openStreamSuccess, openStreamError);
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+});
+
+}
+
+function File_createFile_misarg() {
+//==== TEST: File_createFile_misarg
+//==== LABEL Check if File::createFile() with missing mandatory argument throws exception
+//==== SPEC Tizen Web API:IO:Filesystem:File:createFile M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/filesystem.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MMA
+
+var t = async_test('File_createFile_misarg'), resolveSuccess, resolveError, fsTestFileName;
+
+t.step(function () {
+    fsTestFileName =  getFileName("filesystem.txt");
+    resolveSuccess = t.step_func(function (dir) {
+        assert_throws(INVALID_VALUES_EXCEPTION, function () {
+            dir.createFile();
+        }, INVALID_VALUES_EXCEPTION + " should be thrown");
+        t.done();
+    });
+
+    resolveError = t.step_func(function (error) {
+        assert_unreached("resolve() error callback invoked: name: " + error.name + ", msg: " + error.message);
+    });
+
+    tizen.filesystem.resolve("documents", resolveSuccess, resolveError, "rw");
+});
+
+}
+
+
+var moduleName = "tct-filesystem-tizen-tests";
+add_test_case(moduleName, FileArraySuccessCallback_notexist);
+add_test_case(moduleName, FileArraySuccessCallback_onsuccess);
+add_test_case(moduleName, FileStreamSuccessCallback_notexist);
+add_test_case(moduleName, FileStreamSuccessCallback_onsuccess);
+add_test_case(moduleName, FileStream_bytesAvailable_attribute);
+add_test_case(moduleName, FileStream_close);
+add_test_case(moduleName, FileStream_close_exist);
+add_test_case(moduleName, FileStream_close_extra_argument);
+add_test_case(moduleName, FileStream_eof_attribute);
+add_test_case(moduleName, FileStream_extend);
+add_test_case(moduleName, FileStream_notexist);
+add_test_case(moduleName, FileStream_position_attribute);
+add_test_case(moduleName, FileStream_read);
+add_test_case(moduleName, FileStream_readBase64);
+add_test_case(moduleName, FileStream_readBase64_exist);
+add_test_case(moduleName, FileStream_readBase64_without_r_permission);
+add_test_case(moduleName, FileStream_readBase64_writeFile);
+add_test_case(moduleName, FileStream_readBytes);
+add_test_case(moduleName, FileStream_readBytes_exist);
+add_test_case(moduleName, FileStream_readBytes_without_r_permission);
+add_test_case(moduleName, FileStream_readBytes_writeFile);
+add_test_case(moduleName, FileStream_read_exist);
+add_test_case(moduleName, FileStream_read_without_r_permission);
+add_test_case(moduleName, FileStream_read_writeFile);
+add_test_case(moduleName, FileStream_write);
+add_test_case(moduleName, FileStream_writeBase64);
+add_test_case(moduleName, FileStream_writeBase64_exist);
+add_test_case(moduleName, FileStream_writeBase64_without_w_permission);
+add_test_case(moduleName, FileStream_writeBytes);
+add_test_case(moduleName, FileStream_writeBytes_byteData_TypeMismatch);
+add_test_case(moduleName, FileStream_writeBytes_exist);
+add_test_case(moduleName, FileStream_writeBytes_missarg);
+add_test_case(moduleName, FileStream_writeBytes_with_additional_null_parameter);
+add_test_case(moduleName, FileStream_writeBytes_without_w_permission);
+add_test_case(moduleName, FileStream_write_exist);
+add_test_case(moduleName, FileStream_write_without_w_permission);
+add_test_case(moduleName, FileStringSuccessCallback_notexist);
+add_test_case(moduleName, FileStringSuccessCallback_onsuccess);
+add_test_case(moduleName, FileSuccessCallback_notexist);
+add_test_case(moduleName, FileSuccessCallback_onsuccess);
+add_test_case(moduleName, FileSystemManagerObject_notexist);
+//add_test_case(moduleName, FileSystemManager_addStorageStateChangeListener);
+add_test_case(moduleName, FileSystemManager_addStorageStateChangeListener_exist);
+add_test_case(moduleName, FileSystemManager_addStorageStateChangeListener_missarg);
+add_test_case(moduleName, FileSystemManager_addStorageStateChangeListener_onerror_TypeMismatch);
+add_test_case(moduleName, FileSystemManager_addStorageStateChangeListener_onerror_invalid_cb);
+add_test_case(moduleName, FileSystemManager_addStorageStateChangeListener_onsuccess_TypeMismatch);
+add_test_case(moduleName, FileSystemManager_addStorageStateChangeListener_onsuccess_invalid_cb);
+//add_test_case(moduleName, FileSystemManager_addStorageStateChangeListener_with_onerror);
+add_test_case(moduleName, FileSystemManager_addStorageStateChangeListener_without_arguments);
+add_test_case(moduleName, FileSystemManager_extend);
+add_test_case(moduleName, FileSystemManager_getStorage);
+add_test_case(moduleName, FileSystemManager_getStorage_exist);
+add_test_case(moduleName, FileSystemManager_getStorage_missarg);
+add_test_case(moduleName, FileSystemManager_getStorage_onerror_TypeMismatch);
+add_test_case(moduleName, FileSystemManager_getStorage_onerror_invalid_cb);
+add_test_case(moduleName, FileSystemManager_getStorage_onsuccess_TypeMismatch);
+add_test_case(moduleName, FileSystemManager_getStorage_onsuccess_invalid_cb);
+add_test_case(moduleName, FileSystemManager_getStorage_with_nonexist_label);
+add_test_case(moduleName, FileSystemManager_getStorage_with_onerror);
+add_test_case(moduleName, FileSystemManager_in_tizen);
+add_test_case(moduleName, FileSystemManager_listStorages);
+add_test_case(moduleName, FileSystemManager_listStorages_exist);
+add_test_case(moduleName, FileSystemManager_listStorages_missarg);
+add_test_case(moduleName, FileSystemManager_listStorages_onerror_TypeMismatch);
+add_test_case(moduleName, FileSystemManager_listStorages_onerror_invalid_cb);
+add_test_case(moduleName, FileSystemManager_listStorages_onsuccess_TypeMismatch);
+add_test_case(moduleName, FileSystemManager_listStorages_onsuccess_invalid_cb);
+add_test_case(moduleName, FileSystemManager_listStorages_storages_retrieve);
+add_test_case(moduleName, FileSystemManager_listStorages_with_invalid_error_callbacks);
+add_test_case(moduleName, FileSystemManager_listStorages_with_onerror);
+add_test_case(moduleName, FileSystemManager_listStorages_without_arguments);
+add_test_case(moduleName, FileSystemManager_listStorages_works_correctly);
+add_test_case(moduleName, FileSystemManager_maxPathLength_attribute);
+add_test_case(moduleName, FileSystemManager_notexist);
+//add_test_case(moduleName, FileSystemManager_removeStorageStateChangeListener);
+add_test_case(moduleName, FileSystemManager_removeStorageStateChangeListener_exist);
+add_test_case(moduleName, FileSystemManager_removeStorageStateChangeListener_works_correctly);
+add_test_case(moduleName, FileSystemManager_resolve);
+add_test_case(moduleName, FileSystemManager_resolve_documents);
+add_test_case(moduleName, FileSystemManager_resolve_downloads);
+add_test_case(moduleName, FileSystemManager_resolve_error_invoked);
+add_test_case(moduleName, FileSystemManager_resolve_exist);
+add_test_case(moduleName, FileSystemManager_resolve_images);
+add_test_case(moduleName, FileSystemManager_resolve_missarg);
+add_test_case(moduleName, FileSystemManager_resolve_mode_TypeMismatch);
+add_test_case(moduleName, FileSystemManager_resolve_mode_a);
+add_test_case(moduleName, FileSystemManager_resolve_mode_r);
+add_test_case(moduleName, FileSystemManager_resolve_mode_w);
+add_test_case(moduleName, FileSystemManager_resolve_music);
+add_test_case(moduleName, FileSystemManager_resolve_onerror_TypeMismatch);
+add_test_case(moduleName, FileSystemManager_resolve_onerror_invalid_cb);
+add_test_case(moduleName, FileSystemManager_resolve_onsuccess_TypeMismatch);
+add_test_case(moduleName, FileSystemManager_resolve_onsuccess_invalid_cb);
+add_test_case(moduleName, FileSystemManager_resolve_ringtones);
+add_test_case(moduleName, FileSystemManager_resolve_ringtones_invalid_mode_a);
+add_test_case(moduleName, FileSystemManager_resolve_ringtones_invalid_mode_rw);
+add_test_case(moduleName, FileSystemManager_resolve_ringtones_invalid_mode_w);
+add_test_case(moduleName, FileSystemManager_resolve_videos);
+add_test_case(moduleName, FileSystemManager_resolve_wgt_package_invalid_mode_a);
+add_test_case(moduleName, FileSystemManager_resolve_wgt_package_invalid_mode_rw);
+add_test_case(moduleName, FileSystemManager_resolve_wgt_package_invalid_mode_w);
+add_test_case(moduleName, FileSystemManager_resolve_wgt_package);
+add_test_case(moduleName, FileSystemManager_resolve_wgt_private);
+add_test_case(moduleName, FileSystemManager_resolve_wgt_private_tmp);
+add_test_case(moduleName, FileSystemManager_resolve_with_mode);
+add_test_case(moduleName, FileSystemManager_resolve_with_onerror);
+add_test_case(moduleName, FileSystemManager_resolve_works_correctly);
+add_test_case(moduleName, FileSystemStorageArraySuccessCallback_notexist);
+add_test_case(moduleName, FileSystemStorageArraySuccessCallback_onsuccess);
+add_test_case(moduleName, FileSystemStorageSuccessCallback_notexist);
+add_test_case(moduleName, FileSystemStorageSuccessCallback_onsuccess);
+add_test_case(moduleName, FileSystemStorage_extend);
+add_test_case(moduleName, FileSystemStorage_label_attribute);
+add_test_case(moduleName, FileSystemStorage_notexist);
+add_test_case(moduleName, FileSystemStorage_state_attribute);
+add_test_case(moduleName, FileSystemStorage_type_attribute);
+add_test_case(moduleName, File_copyTo);
+add_test_case(moduleName, File_copyTo_dir_overwrite_false);
+add_test_case(moduleName, File_copyTo_dir_overwrite_true);
+add_test_case(moduleName, File_copyTo_dir_samedir_samename_overwrite_false);
+add_test_case(moduleName, File_copyTo_dir_samedir_samename_overwrite_true);
+add_test_case(moduleName, File_copyTo_exist);
+add_test_case(moduleName, File_copyTo_file_overwrite_false);
+add_test_case(moduleName, File_copyTo_file_overwrite_true);
+add_test_case(moduleName, File_copyTo_file_samedir_samename_overwrite_false);
+add_test_case(moduleName, File_copyTo_file_samedir_samename_overwrite_true);
+add_test_case(moduleName, File_copyTo_onerror_TypeMismatch);
+add_test_case(moduleName, File_copyTo_onerror_invalid_cb);
+add_test_case(moduleName, File_copyTo_onsuccess_TypeMismatch);
+add_test_case(moduleName, File_copyTo_onsuccess_invalid_cb);
+add_test_case(moduleName, File_copyTo_with_file_handle);
+add_test_case(moduleName, File_copyTo_with_null_success_and_error_callbacks);
+add_test_case(moduleName, File_copyTo_with_onerror);
+add_test_case(moduleName, File_copyTo_with_onsuccess);
+add_test_case(moduleName, File_copyTo_writeFile_newName);
+add_test_case(moduleName, File_copyTo_writeFile_overwrite_false);
+add_test_case(moduleName, File_copyTo_writeFile_subdir);
+add_test_case(moduleName, File_createDirectory);
+add_test_case(moduleName, File_createDirectory_exist);
+add_test_case(moduleName, File_createDirectory_level2);
+add_test_case(moduleName, File_createFile);
+add_test_case(moduleName, File_createFile_exist);
+add_test_case(moduleName, File_createFile_existing_file);
+add_test_case(moduleName, File_created_attribute);
+add_test_case(moduleName, File_deleteDirectory);
+add_test_case(moduleName, File_deleteDirectory_createDir_documents);
+add_test_case(moduleName, File_deleteDirectory_createDir_downloads);
+add_test_case(moduleName, File_deleteDirectory_createDir_images);
+add_test_case(moduleName, File_deleteDirectory_createDir_music);
+add_test_case(moduleName, File_deleteDirectory_createDir_videos);
+add_test_case(moduleName, File_deleteDirectory_exist);
+add_test_case(moduleName, File_deleteDirectory_onerror_TypeMismatch);
+add_test_case(moduleName, File_deleteDirectory_onerror_invalid_cb);
+add_test_case(moduleName, File_deleteDirectory_onsuccess_TypeMismatch);
+add_test_case(moduleName, File_deleteDirectory_onsuccess_invalid_cb);
+add_test_case(moduleName, File_deleteDirectory_with_empty_path);
+add_test_case(moduleName, File_deleteDirectory_with_file_handle);
+add_test_case(moduleName, File_deleteDirectory_with_null_callbacks);
+add_test_case(moduleName, File_deleteDirectory_with_onerror);
+add_test_case(moduleName, File_deleteDirectory_with_onsuccess);
+add_test_case(moduleName, File_deleteFile);
+add_test_case(moduleName, File_deleteFile_copyFile_downloads);
+add_test_case(moduleName, File_deleteFile_copyFile_images);
+add_test_case(moduleName, File_deleteFile_copyFile_music);
+add_test_case(moduleName, File_deleteFile_copyFile_videos);
+add_test_case(moduleName, File_deleteFile_createFile);
+add_test_case(moduleName, File_deleteFile_exist);
+add_test_case(moduleName, File_deleteFile_listDocumentsFiles);
+add_test_case(moduleName, File_deleteFile_listDownloadsFiles);
+add_test_case(moduleName, File_deleteFile_listImagsFiles);
+add_test_case(moduleName, File_deleteFile_listMusicFiles);
+add_test_case(moduleName, File_deleteFile_listVideosfiles);
+add_test_case(moduleName, File_deleteFile_onerror_TypeMismatch);
+add_test_case(moduleName, File_deleteFile_onerror_invalid_cb);
+add_test_case(moduleName, File_deleteFile_onsuccess_TypeMismatch);
+add_test_case(moduleName, File_deleteFile_onsuccess_invalid_cb);
+add_test_case(moduleName, File_deleteFile_with_dir_handle);
+add_test_case(moduleName, File_deleteFile_with_nonexist);
+add_test_case(moduleName, File_deleteFile_with_onerror);
+add_test_case(moduleName, File_deleteFile_with_onsuccess);
+add_test_case(moduleName, File_deleteFile_with_vaild_callbacks);
+add_test_case(moduleName, File_deleteFile_with_valid_filePath);
+add_test_case(moduleName, File_extend);
+add_test_case(moduleName, File_fileSize_attribute);
+add_test_case(moduleName, File_fullPath_attribute);
+add_test_case(moduleName, File_isDirectory_attribute);
+add_test_case(moduleName, File_isFile_attribute);
+add_test_case(moduleName, File_length_attribute);
+add_test_case(moduleName, File_listFiles);
+add_test_case(moduleName, File_listFiles_createFiles);
+add_test_case(moduleName, File_listFiles_exist);
+add_test_case(moduleName, File_listFiles_filter_TypeMismatch);
+add_test_case(moduleName, File_listFiles_filter_empty);
+add_test_case(moduleName, File_listFiles_missarg);
+add_test_case(moduleName, File_listFiles_onerror_TypeMismatch);
+add_test_case(moduleName, File_listFiles_onerror_invalid_cb);
+add_test_case(moduleName, File_listFiles_onsuccess_TypeMismatch);
+add_test_case(moduleName, File_listFiles_onsuccess_invalid_cb);
+add_test_case(moduleName, File_listFiles_with_file_handle);
+add_test_case(moduleName, File_listFiles_with_filter);
+add_test_case(moduleName, File_listFiles_with_onerror);
+add_test_case(moduleName, File_listFiles_with_valid_successCallback);
+add_test_case(moduleName, File_modified_attribute);
+add_test_case(moduleName, File_moveTo);
+add_test_case(moduleName, File_moveTo_dir_samedir_samename_overwrite_false);
+add_test_case(moduleName, File_moveTo_dir_samedir_samename_overwrite_true);
+add_test_case(moduleName, File_moveTo_empty_destination_source_and_destination_paths);
+add_test_case(moduleName, File_moveTo_exist);
+add_test_case(moduleName, File_moveTo_file_samedir_samename_overwrite_false);
+add_test_case(moduleName, File_moveTo_file_samedir_samename_overwrite_true);
+add_test_case(moduleName, File_moveTo_onerror_TypeMismatch);
+add_test_case(moduleName, File_moveTo_onerror_invalid_cb);
+add_test_case(moduleName, File_moveTo_onsuccess_TypeMismatch);
+add_test_case(moduleName, File_moveTo_onsuccess_invalid_cb);
+add_test_case(moduleName, File_moveTo_with_additional_null_parameter);
+add_test_case(moduleName, File_moveTo_with_file_handle);
+add_test_case(moduleName, File_moveTo_with_onerror);
+add_test_case(moduleName, File_moveTo_with_onsuccess);
+add_test_case(moduleName, File_moveTo_with_path_invalid);
+add_test_case(moduleName, File_moveTo_writeFile_newName);
+add_test_case(moduleName, File_moveTo_writeFile_overwrite_false);
+add_test_case(moduleName, File_moveTo_writeFile_subdir);
+add_test_case(moduleName, File_name_attribute);
+add_test_case(moduleName, File_notexist);
+add_test_case(moduleName, File_openStream);
+add_test_case(moduleName, File_openStream_encoding_invalid);
+add_test_case(moduleName, File_openStream_exist);
+add_test_case(moduleName, File_openStream_missarg);
+add_test_case(moduleName, File_openStream_mode_TypeMismatch);
+add_test_case(moduleName, File_openStream_mode_a);
+add_test_case(moduleName, File_openStream_mode_r);
+add_test_case(moduleName, File_openStream_mode_rw);
+add_test_case(moduleName, File_openStream_mode_w);
+add_test_case(moduleName, File_openStream_onerror_TypeMismatch);
+add_test_case(moduleName, File_openStream_onerror_invalid_cb);
+add_test_case(moduleName, File_openStream_onsuccess_TypeMismatch);
+add_test_case(moduleName, File_openStream_onsuccess_invalid_cb);
+add_test_case(moduleName, File_openStream_with_encoding);
+add_test_case(moduleName, File_openStream_with_nonexist_file);
+add_test_case(moduleName, File_openStream_with_onerror);
+add_test_case(moduleName, File_parent_attribute);
+add_test_case(moduleName, File_parent_attribute_notnull_using_resolve);
+add_test_case(moduleName, File_path_attribute);
+add_test_case(moduleName, File_readAsText);
+add_test_case(moduleName, File_readAsText_encoding_invalid);
+add_test_case(moduleName, File_readAsText_exist);
+add_test_case(moduleName, File_readAsText_listDocumentsFiles);
+add_test_case(moduleName, File_readAsText_listDownloadsFiles);
+add_test_case(moduleName, File_readAsText_listImagesFiles);
+add_test_case(moduleName, File_readAsText_listMusicFiles);
+add_test_case(moduleName, File_readAsText_listVideosFiles);
+add_test_case(moduleName, File_readAsText_missarg);
+add_test_case(moduleName, File_readAsText_onerror_TypeMismatch);
+add_test_case(moduleName, File_readAsText_onerror_invalid_cb);
+add_test_case(moduleName, File_readAsText_onsuccess_TypeMismatch);
+add_test_case(moduleName, File_readAsText_onsuccess_invalid_cb);
+add_test_case(moduleName, File_readAsText_with_encoding);
+add_test_case(moduleName, File_readAsText_with_onerror);
+add_test_case(moduleName, File_readOnly_attribute);
+add_test_case(moduleName, File_resolve);
+add_test_case(moduleName, File_resolve_exist);
+add_test_case(moduleName, File_resolve_with_nonexist);
+add_test_case(moduleName, File_toURI);
+add_test_case(moduleName, File_toURI_exist);
+add_test_case(moduleName, File_toURI_extra_argument);
+add_test_case(moduleName, File_toURI_with_nonexist_file);
+add_test_case(moduleName, filesystem_FileStreamSuccessCallback_onsuccess);
+add_test_case(moduleName, filesystem_File_copyTo);
+add_test_case(moduleName, filesystem_File_readAsText);
+add_test_case(moduleName, filesystem_File_resolve);
+add_test_case(moduleName, FileSystemManager_resolve_location_invalid);
+add_test_case(moduleName, FileSystemManager_resolve_errorCallback_invoked);
+add_test_case(moduleName, FileSystemManager_getStorage_errorCallback_invoked);
+add_test_case(moduleName, File_openStream_mode_invalid);
+add_test_case(moduleName, File_copyTo_destinationFilePath_invalid);
+add_test_case(moduleName, File_copyTo_originFilePath_invalid);
+add_test_case(moduleName, File_createDirectory_misarg);
+add_test_case(moduleName, File_resolve_misarg);
+add_test_case(moduleName, File_deleteDirectory_misarg);
+add_test_case(moduleName, File_path_attribute_limitation);
+add_test_case(moduleName, FileStream_read_misarg);
+add_test_case(moduleName, FileStream_read_TypeMismatch);
+add_test_case(moduleName, File_createDirectory_dirPath_invalid);
+add_test_case(moduleName, File_openStream_with_encoding_not_default);
+add_test_case(moduleName, File_readAsText_with_encoding_not_default);
+add_test_case(moduleName, File_resolve_filePath_invalid);
+add_test_case(moduleName, FileStream_readBytes_misarg);
+add_test_case(moduleName, File_createFile_misarg);
diff --git a/webWidgetTCT_device/test/tct/tests/TestHtml.js b/webWidgetTCT_device/test/tct/tests/TestHtml.js
new file mode 100755 (executable)
index 0000000..43402dc
--- /dev/null
@@ -0,0 +1,535 @@
+if (typeof String.prototype.endsWith != 'function') {
+    String.prototype.endsWith = function(suffix) {
+        return this.indexOf(suffix, this.length - suffix.length) !== -1;
+    };
+}
+
+function HTML_html_globalattribute() {
+//==== TEST: HTML_html_globalattribute
+//==== LABEL Check if element html of HTMLScriptElement exists, has type DOMString
+//==== SPEC Tizen W3C API:TBD::HTMLImageElement:html A
+//==== SPEC_URL http://www.w3.org/TR/html5/semantics.html#the-root-element
+//==== PRIORITY P0
+//==== TEST_CRITERIA AE AT ASG
+
+test(function () {
+    var x = document.createElement("html");
+    assert_true("id" in x);
+    assert_true("dir" in x);
+    assert_true("style" in x);
+    assert_type(x.id, "string", "id attribute should return string type");
+    assert_type(x.dir, "string", "dir attribute should return string type");
+    assert_type(x.style, "object", "style attribute should return string type");
+    x.id = "id";
+    assert_equals(x.id, "id");
+}, "HTML_html_globalattribute");
+
+}
+
+function HTML_head_globalattribute() {
+//==== TEST: HTML_head_globalattribute
+//==== LABEL Check if element head of HTMLScriptElement exists, has type DOMString
+//==== SPEC Tizen W3C API:TBD::HTMLImageElement:head A
+//==== SPEC_URL https://www.w3.org/TR/html5/document-metadata.html#the-head-element
+//==== PRIORITY P0
+//==== TEST_CRITERIA AE AT ASG
+
+test(function () {
+    var x = document.createElement("head");
+    assert_true("id" in x);
+    assert_true("dir" in x);
+    assert_true("style" in x);
+    assert_type(x.id, "string", "id attribute should return string type");
+    assert_type(x.dir, "string", "dir attribute should return string type");
+    assert_type(x.style, "object", "style attribute should return string type");
+    x.id = "id";
+    assert_equals(x.id, "id");
+}, "HTML_head_globalattribute");
+
+}
+
+function HTMLLinkElement_rel_attribute() {
+//==== TEST: HTMLLinkElement_rel_attribute
+//==== LABEL Check if attribute rel of HTMLLinkElement exists, has type DOMString
+//==== SPEC Tizen W3C API:TBD::HTMLImageElement:rel A
+//==== SPEC_URL http://www.w3.org/TR/html5/document-metadata.html#the-link-element
+//==== PRIORITY P0
+//==== TEST_CRITERIA AE AT ASG AN
+
+test(function () {
+    var x = document.createElement("link");
+    check_attribute(x, "rel", x.rel, "string", x.rel+"5");
+}, "HTMLLinkElement_rel_attribute");
+
+}
+
+function HTMLLinkElement_href_attribute() {
+//==== TEST: HTMLLinkElement_href_attribute
+//==== LABEL Check if attribute href of HTMLLinkElement exists, has type DOMString
+//==== SPEC Tizen W3C API:TBD::HTMLImageElement:href A
+//==== SPEC_URL http://www.w3.org/TR/html5/document-metadata.html#the-link-element
+//==== PRIORITY P0
+//==== TEST_CRITERIA AE AT ASG AN
+
+test(function () {
+    var x = document.createElement("link");
+    assert_true("href" in x);
+    assert_type(x.href, "string", "href attribute should return string type");
+    x.href = "href";
+    assert_true(x.href.endsWith("f02/href"), "check href path value");
+}, "HTMLLinkElement_href_attribute");
+
+}
+
+function HTMLLinkElement_type_attribute() {
+//==== TEST: HTMLLinkElement_type_attribute
+//==== LABEL Check if attribute type of HTMLLinkElement exists, has type DOMString
+//==== SPEC Tizen W3C API:TBD::HTMLImageElement:type A
+//==== SPEC_URL http://www.w3.org/TR/html5/document-metadata.html#the-link-element
+//==== PRIORITY P0
+//==== TEST_CRITERIA AE AT ASG AN
+
+test(function () {
+    var x = document.createElement("link");
+    check_attribute(x, "type", x.type, "string", x.type+"5");
+}, "HTMLLinkElement_type_attribute");
+
+}
+
+function link_dir_attribute() {
+
+test(function () {
+    var linktest = document.createElement("link");
+    assert_true("dir" in linktest);
+    assert_type(linktest.dir, "string", "dir attribute should return string type");
+    assert_equals(linktest.dir, "");
+}, "link_dir_attribute");
+
+}
+
+function link_id_attribute() {
+
+test(function () {
+    var linktest = document.createElement("link");
+    assert_true("id" in linktest);
+    assert_type(linktest.id, "string", "id attribute should return string type");
+    linktest.id = "id";
+    assert_equals(linktest.id, "id");
+}, "link_id_attribute");
+
+}
+
+function link_style_attribute() {
+
+test(function () {
+    var linktest = document.createElement("link");
+    assert_true("style" in linktest);
+    assert_type(linktest.style, "object", "style attribute should return object type");
+}, "link_style_attribute");
+
+}
+
+function meta_dir_attribute() {
+
+test(function () {
+    var metatest = document.createElement("meta");
+    assert_true("dir" in metatest);
+    assert_type(metatest.dir, "string", "dir attribute should return string type");
+    assert_equals(metatest.dir, "");
+}, "meta_dir_attribute");
+
+}
+
+function meta_id_attribute() {
+
+test(function () {
+    var metatest = document.createElement("meta");
+    check_attribute(metatest, "id", "", "string", "idname");
+}, "meta_id_attribute");
+
+}
+
+function meta_style_attribute() {
+
+test(function () {
+    var metatest = document.createElement("meta");
+    assert_true("style" in metatest);
+    assert_type(metatest.style, "object", "style attribute should return object type");
+}, "meta_style_attribute");
+
+}
+
+function HTMLStyle_type_attribute() {
+//==== TEST: HTMLStyle_type_attribute
+//==== LABEL Check if attribute type of HTMLMeta exists, has type DOMString
+//==== SPEC Tizen W3C API:TBD::HTMLImageElement:type A
+//==== SPEC_URL https://www.w3.org/TR/html5/document-metadata.html#the-style-element
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ASG AN
+
+test(function () {
+    var x = document.createElement("style");
+    check_attribute(x, "type", x.type, "string", x.type+"5");
+}, "HTMLStyle_type_attribute");
+
+}
+
+function style_dir_attribute() {
+
+test(function () {
+    var styletest = document.createElement("style");
+    assert_true("dir" in styletest);
+    assert_type(styletest.dir, "string", "dir attribute should return string type");
+    assert_equals(styletest.dir, "");
+}, "style_dir_attribute");
+
+}
+
+function style_id_attribute() {
+
+test(function () {
+    var styletest = document.createElement("style");
+    check_attribute(styletest, "id", "", "string", "idname");
+}, "style_id_attribute");
+
+}
+
+function style_style_attribute() {
+
+test(function () {
+    var styletest = document.createElement("style");
+    assert_type(styletest.style, "object", "style attribute should return object type");
+}, "style_style_attribute");
+
+}
+
+function body_onload_attribute() {
+
+test(function () {
+    var testbody = document.createElement("body");
+    assert_true("onload" in testbody, "onload attribute in HTMLBodyElement element");
+    assert_equals(typeof testbody.onload , "object", "onload attribute has type object");
+}, 'body_onload_attribute');
+
+}
+
+function body_onclick_attribute() {
+
+test(function () {
+    var testbody = document.createElement("body");
+    assert_true("onclick" in testbody, "onclick attribute in HTMLBodyElement element");
+    assert_equals(typeof testbody.onclick , "object", "onclick attribute has type object");
+}, 'body_onclick_attribute');
+
+}
+
+function body_dir_attribute() {
+
+test(function () {
+    var testbody = document.createElement("body");
+    assert_true("dir" in testbody);
+    assert_type(testbody.dir, "string", "dir attribute should return string type");
+    assert_equals(testbody.dir, "");
+}, "body_dir_attribute");
+
+}
+
+function body_id_attribute() {
+
+test(function () {
+    var testbody = document.createElement("body");
+    check_attribute(testbody, "id", "", "string", "id");
+}, "body_id_attribute");
+
+}
+
+function body_style_attribute() {
+
+test(function () {
+    var testbody = document.createElement("body");
+    assert_true("style" in testbody, "style attribute in HTMLBodyElement element");
+    assert_equals(typeof testbody.style , "object", "onstorage attribute has type object");
+}, "body_style_attribute");
+
+}
+
+function HTML_p_globalattribute() {
+//==== TEST: HTML_p_globalattribute
+//==== LABEL Check if element p of HTMLScriptElement exists, has type DOMString
+//==== SPEC Tizen W3C API:TBD::HTMLImageElement:p A
+//==== SPEC_URL https://www.w3.org/TR/html5/grouping-content.html#the-p-element
+//==== PRIORITY P1
+
+test(function () {
+    var x=document.createElement("p");
+    assert_true("id" in x);
+    assert_true("dir" in x);
+    assert_true("style" in x);
+    assert_type(x.id, "string", "id attribute should return string type");
+    assert_type(x.dir, "string", "dir attribute should return string type");
+    assert_type(x.style, "object", "style attribute should return string type");
+    x.id = "id";
+    assert_equals(x.id, "id");
+}, "HTML_p_globalattribute");
+
+}
+
+function HTML_div_globalattribute() {
+//==== TEST: HTML_div_globalattribute
+//==== LABEL Check if element div of HTMLScriptElement exists, has type DOMString
+//==== SPEC Tizen W3C API:TBD::HTMLImageElement:div A
+//==== SPEC_URL https://www.w3.org/TR/html5/grouping-content.html#the-div-element
+//==== PRIORITY P1
+
+test(function () {
+    var x=document.createElement("div");
+    assert_true("id" in x);
+    assert_true("dir" in x);
+    assert_true("style" in x);
+    assert_type(x.id, "string", "id attribute should return string type");
+    assert_type(x.dir, "string", "dir attribute should return string type");
+    assert_type(x.style, "object", "style attribute should return string type");
+    x.id = "id";
+    assert_equals(x.id, "id");
+}, "HTML_div_globalattribute");
+
+}
+
+function HTML_span_globalattribute() {
+//==== TEST: HTML_span_globalattribute
+//==== LABEL Check if element div of HTMLScriptElement exists, has type DOMString
+//==== SPEC Tizen W3C API:TBD::HTMLImageElement:div A
+//==== SPEC_URL https://www.w3.org/TR/html5/text-level-semantics.html#the-span-element
+//==== PRIORITY P1
+
+test(function () {
+    var x=document.createElement("span");
+    assert_true("id" in x);
+    assert_true("dir" in x);
+    assert_true("style" in x);
+    assert_type(x.id, "string", "id attribute should return string type");
+    assert_type(x.dir, "string", "dir attribute should return string type");
+    assert_type(x.style, "object", "style attribute should return string type");
+    x.id = "id";
+    assert_equals(x.id, "id");
+}, "HTML_span_globalattribute");
+
+}
+
+function HTML_br_globalattribute() {
+//==== TEST: HTML_br_globalattribute
+//==== LABEL Check if element br of HTMLScriptElement exists, has type DOMString
+//==== SPEC Tizen W3C API:TBD::HTMLImageElement:br A
+//==== SPEC_URL http://www.w3.org/TR/html5/scripting-1.html#the-script-element
+//==== PRIORITY P1
+
+test(function () {
+    var x=document.createElement("br");
+    assert_true("id" in x);
+    assert_true("dir" in x);
+    assert_true("style" in x);
+    assert_type(x.id, "string", "id attribute should return string type");
+    assert_type(x.dir, "string", "dir attribute should return string type");
+    assert_type(x.style, "object", "style attribute should return string type");
+    x.id = "id";
+    assert_equals(x.id, "id");
+}, "HTML_br_globalattribute");
+
+}
+
+function HTMLImageElement_height_attribute() {
+//==== TEST: HTMLImageElement_height_attribute
+//==== LABEL Check if attribute height of HTMLImageElement exists, has type long
+//==== SPEC Tizen W3C API:TBD::HTMLImageElement:height A
+//==== SPEC_URL https://html.spec.whatwg.org/multipage/embedded-content.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT
+
+test(function () {
+    var img = document.createElement("img");
+    assert_true("height" in img);
+    assert_type(img.height, "number", "height attribute should return number type");
+}, "HTMLImageElement_height_attribute");
+
+}
+
+function HTMLImageElement_width_attribute() {
+//==== TEST: HTMLImageElement_width_attribute
+//==== LABEL Check if attribute width of HTMLImageElement exists, has type long
+//==== SPEC Tizen W3C API:TBD::HTMLImageElement:width A
+//==== SPEC_URL https://html.spec.whatwg.org/multipage/embedded-content.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ASG AN
+
+test(function () {
+    var img = document.createElement("img");
+    assert_true("width" in img);
+    assert_type(img.width, "number", "width attribute should return number type");
+}, "HTMLImageElement_width_attribute");
+
+}
+
+function HTMLImageElement_src_attribute() {
+//==== TEST: HTMLImageElement_src_attribute
+//==== LABEL Check if attribute src of HTMLImageElement exists, has type DOMString
+//==== SPEC Tizen W3C API:TBD::HTMLImageElement:src A
+//==== SPEC_URL https://html.spec.whatwg.org/multipage/embedded-content.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ASG AN
+
+test(function () {
+    var img = document.createElement("img");
+    assert_true("src" in img);
+    assert_type(img.src, "string", "src attribute should return string type");
+}, "HTMLImageElement_src_attribute");
+
+}
+
+function img_dir_attribute() {
+
+test(function () {
+    var imgtest = document.createElement("img");
+    assert_true("dir" in imgtest);
+    assert_type(imgtest.dir, "string", "dir attribute should return string type");
+}, "img_dir_attribute");
+
+}
+
+function img_id_attribute() {
+
+test(function () {
+    var imgtest = document.createElement('img');
+    check_attribute(imgtest, "id", "", "string", "idname");
+}, "img_id_attribute");
+
+}
+
+function img_style_attribute() {
+
+test(function () {
+    var imgtest = document.createElement("img");
+    assert_true("style" in imgtest);
+    assert_type(imgtest.style, "object", "style attribute should return object type");
+}, "img_style_attribute");
+
+}
+
+
+function HTMLScriptElement_src_attribute() {
+//==== TEST: HTMLScriptElement_src_attribute
+//==== LABEL Check if attribute src of HTMLScriptElement exists, has type DOMString
+//==== SPEC Tizen W3C API:TBD::HTMLImageElement:src A
+//==== SPEC_URL http://www.w3.org/TR/html5/scripting-1.html#the-script-element
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ASG AN
+
+test(function () {
+    var x=document.createElement("script");
+    var PATH = "file:///opt/usr/home/owner";
+    assert_true("src" in x);
+    assert_type(x.src, "string", "src attribute should return string type");
+    x.src = "src";
+    assert_true(x.src.endsWith("f02/src"), "check src path value");
+}, 'HTMLScriptElement_src_attribute');
+
+}
+
+function HTMLScriptElement_type_attribute() {
+//==== TEST: HTMLScriptElement_type_attribute
+//==== LABEL Check if attribute type of HTMLScriptElement exists, has type DOMString
+//==== SPEC Tizen W3C API:TBD::HTMLImageElement:type A
+//==== SPEC_URL http://www.w3.org/TR/html5/scripting-1.html#the-script-element
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ASG AN
+
+test(function () {
+    var x=document.createElement("script");
+    check_attribute(x, "type", x.type, "string", x.type+"5");
+}, 'HTMLScriptElement_type_attribute');
+
+}
+
+function HTMLScriptElement_charset_attribute() {
+//==== TEST: HTMLScriptElement_charset_attribute
+//==== LABEL Check if attribute charset of HTMLScriptElement exists, has type DOMString
+//==== SPEC Tizen W3C API:TBD::HTMLImageElement:charset A
+//==== SPEC_URL http://www.w3.org/TR/html5/scripting-1.html#the-script-element
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT
+
+test(function () {
+    var x=document.createElement("script");
+    assert_true("charset" in x);
+    assert_type(x.charset, "string", "charset attribute should return string type");
+}, "HTMLScriptElement_charset_attribute");
+
+}
+
+function script_dir_attribute() {
+
+test(function () {
+    var scripttest = document.createElement("script");
+    assert_true("dir" in scripttest);
+    assert_type(scripttest.dir, "string", "dir attribute should return string type");
+}, "script_dir_attribute");
+
+}
+
+function script_id_attribute() {
+
+test(function () {
+    var scripttest = document.createElement("script");
+    check_attribute(scripttest, "id", "", "string", "idname");
+}, "script_id_attribute");
+
+}
+
+function script_style_attribute() {
+
+test(function () {
+    var scripttest = document.createElement("script");
+    assert_true("style" in scripttest);
+    assert_type(scripttest.style, "object", "style attribute should return object type");
+}, "script_style_attribute");
+
+}
+
+
+
+var moduleName = "tct-html-w3c-tests";
+add_test_case(moduleName, HTML_html_globalattribute);
+add_test_case(moduleName, HTML_head_globalattribute);
+add_test_case(moduleName, HTMLLinkElement_rel_attribute);
+add_test_case(moduleName, HTMLLinkElement_href_attribute);
+add_test_case(moduleName, HTMLLinkElement_type_attribute);
+add_test_case(moduleName, link_dir_attribute);
+add_test_case(moduleName, link_id_attribute);
+add_test_case(moduleName, link_style_attribute);
+add_test_case(moduleName, meta_dir_attribute);
+add_test_case(moduleName, meta_id_attribute);
+add_test_case(moduleName, meta_style_attribute);
+add_test_case(moduleName, HTMLStyle_type_attribute);
+add_test_case(moduleName, style_dir_attribute);
+add_test_case(moduleName, style_id_attribute);
+add_test_case(moduleName, style_style_attribute);
+add_test_case(moduleName, body_onload_attribute);
+add_test_case(moduleName, body_onclick_attribute);
+add_test_case(moduleName, body_dir_attribute);
+add_test_case(moduleName, body_id_attribute);
+add_test_case(moduleName, body_style_attribute);
+add_test_case(moduleName, HTML_p_globalattribute);
+add_test_case(moduleName, HTML_div_globalattribute);
+add_test_case(moduleName, HTML_span_globalattribute);
+add_test_case(moduleName, HTML_br_globalattribute);
+add_test_case(moduleName, HTMLImageElement_height_attribute);
+add_test_case(moduleName, HTMLImageElement_width_attribute);
+add_test_case(moduleName, HTMLImageElement_src_attribute);
+add_test_case(moduleName, img_dir_attribute);
+add_test_case(moduleName, img_id_attribute);
+add_test_case(moduleName, img_style_attribute);
+add_test_case(moduleName, HTMLScriptElement_src_attribute);
+add_test_case(moduleName, HTMLScriptElement_type_attribute);
+add_test_case(moduleName, HTMLScriptElement_charset_attribute);
+add_test_case(moduleName, script_dir_attribute);
+add_test_case(moduleName, script_id_attribute);
+add_test_case(moduleName, script_style_attribute);
diff --git a/webWidgetTCT_device/test/tct/tests/TestMessagePort.js b/webWidgetTCT_device/test/tct/tests/TestMessagePort.js
new file mode 100755 (executable)
index 0000000..4f3dd4f
--- /dev/null
@@ -0,0 +1,1092 @@
+/*
+
+Copyright (c) 2013 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+
+
+Authors:
+
+*/
+
+var localConversionArr = [[undefined, "undefined"], [null, "null"], [0, "0"], [true, "true"], [false, "false"], [{a: "test"}, "[object Object]"]];
+
+function getDOMStringConversionArray(isOptional) {
+    var typeArr = [false, true, NaN, 0, undefined, [1,2], {"a":1,"b":2}, function(){} ];
+    if (!isOptional) {
+        typeArr.push(null);
+    }
+    return typeArr;
+}
+
+function LocalMessagePort_notexist() {
+//==== TEST: LocalMessagePort_notexist
+//==== PRIORITY P3
+//==== LABEL Check if interface LocalMessagePort exists, it should not
+//==== SPEC Tizen Web API:IO:Messageport:LocalMessagePort:LocalMessagePort U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/messageport.html
+//==== TEST_CRITERIA NIO
+test(function () {
+    check_no_interface_object("LocalMessagePort");
+}, 'LocalMessagePort_notexist');
+
+}
+
+function MessagePortCallback_notexist() {
+//==== TEST: MessagePortCallback_notexist
+//==== PRIORITY P3
+//==== LABEL Check if interface MessagePortCallback exists, it should not
+//==== SPEC Tizen Web API:IO:Messageport:MessagePortCallback:MessagePortCallback U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/messageport.html
+//==== TEST_CRITERIA CBNIO
+test(function () {
+    check_no_interface_object("MessagePortCallback");
+}, 'MessagePortCallback_notexist');
+
+}
+
+function MessagePortManagerObject_notexist() {
+//==== TEST: MessagePortManagerObject_notexist
+//==== PRIORITY P3
+//==== LABEL Check if interface MessagePortManagerObject exists, it should not
+//==== SPEC Tizen Web API:IO:Messageport:MessagePortManagerObject:MessagePortManagerObject U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/messageport.html
+//==== TEST_CRITERIA NIO
+test(function () {
+    check_no_interface_object("MessagePortManagerObject");
+}, 'MessagePortManagerObject_notexist');
+
+}
+
+function MessagePortManager_notexist() {
+//==== TEST: MessagePortManager_notexist
+//==== PRIORITY P3
+//==== LABEL Check if interface MessagePortManager exists, it should not
+//==== SPEC Tizen Web API:IO:Messageport:MessagePortManager:MessagePortManager U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/messageport.html
+//==== TEST_CRITERIA NIO
+test(function () {
+    check_no_interface_object("MessagePortManager");
+}, 'MessagePortManager_notexist');
+
+}
+
+function RemoteMessagePort_notexist() {
+//==== TEST: RemoteMessagePort_notexist
+//==== PRIORITY P3
+//==== LABEL Check if interface RemoteMessagePort exists, it should not
+//==== SPEC Tizen Web API:IO:Messageport:RemoteMessagePort:RemoteMessagePort U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/messageport.html
+//==== TEST_CRITERIA NIO
+test(function () {
+    check_no_interface_object("RemoteMessagePort");
+}, 'RemoteMessagePort_notexist');
+
+}
+
+function MessagePortManager_in_tizen() {
+//==== TEST: MessagePortManager_in_tizen
+//==== LABEL Check if messageport exists in tizen
+//==== SPEC Tizen Web API:IO:Messageport:MessagePortManager:MessagePortManager U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/messageport.html
+//==== TEST_CRITERIA OBME
+//==== PRIORITY P3
+test(function () {
+    assert_true("messageport" in tizen, "No messageport in tizen");
+    check_readonly(tizen, "messageport", tizen.messageport, "object", "dummyValue");
+}, 'MessagePortManager_in_tizen');
+
+}
+
+function MessagePortManager_requestLocalMessagePort_exist() {
+//==== TEST: MessagePortManager_requestLocalMessagePort_exist
+//==== LABEL Check if method requestLocalMessagePort of MessagePortManager exists
+//==== SPEC Tizen Web API:IO:Messageport:MessagePortManager:requestLocalMessagePort M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/messageport.html
+//==== TEST_CRITERIA ME
+test(function () {
+    assert_true("requestLocalMessagePort" in tizen.messageport, "No requestLocalMessagePort method in tizen.messageport");
+    check_method_exists(tizen.messageport, "requestLocalMessagePort");
+}, 'MessagePortManager_requestLocalMessagePort_exist');
+
+}
+
+function MessagePortManager_requestRemoteMessagePort_exist() {
+//==== TEST: MessagePortManager_requestRemoteMessagePort_exist
+//==== LABEL Check if method requestRemoteMessagePort of MessagePortManager exists
+//==== SPEC Tizen Web API:IO:Messageport:MessagePortManager:requestRemoteMessagePort M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/messageport.html
+//==== TEST_CRITERIA ME
+test(function () {
+    assert_true("requestRemoteMessagePort" in tizen.messageport, "No requestRemoteMessagePort method in tizen.messageport");
+    check_method_exists(tizen.messageport, "requestRemoteMessagePort");
+}, 'MessagePortManager_requestRemoteMessagePort_exist');
+
+}
+
+function MessagePortManager_requestTrustedRemoteMessagePort_exist() {
+//==== TEST: MessagePortManager_requestTrustedRemoteMessagePort_exist
+//==== LABEL Check if method requestTrustedRemoteMessagePort of MessagePortManager exists
+//==== SPEC Tizen Web API:IO:Messageport:MessagePortManager:requestTrustedRemoteMessagePort M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/messageport.html
+//==== TEST_CRITERIA ME
+test(function () {
+    assert_true("requestTrustedRemoteMessagePort" in tizen.messageport, "No requestTrustedRemoteMessagePort method in tizen.messageport");
+    check_method_exists(tizen.messageport, "requestTrustedRemoteMessagePort");
+}, 'MessagePortManager_requestTrustedRemoteMessagePort_exist');
+
+}
+
+function MessagePortManager_requestTrustedLocalMessagePort_exist() {
+//==== TEST: MessagePortManager_requestTrustedLocalMessagePort_exist
+//==== LABEL Check if method requestTrustedLocalMessagePort of MessagePortManager exists
+//==== SPEC Tizen Web API:IO:Messageport:MessagePortManager:requestTrustedLocalMessagePort M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/messageport.html
+//==== TEST_CRITERIA ME
+test(function () {
+    assert_true("requestTrustedLocalMessagePort" in tizen.messageport, "No requestTrustedLocalMessagePort method in tizen.messageport");
+    check_method_exists(tizen.messageport, "requestTrustedLocalMessagePort");
+}, 'MessagePortManager_requestTrustedLocalMessagePort_exist');
+
+}
+
+function MessagePortManager_extend() {
+//==== TEST: MessagePortManager_extend
+//==== PRIORITY P3
+//==== LABEL Check if instance of interface MessagePortManager can be extended with new property
+//==== SPEC Tizen Web API:IO:Messageport:MessagePortManager:MessagePortManager U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/messageport.html
+//==== TEST_CRITERIA OBX
+test(function () {
+    check_extensibility(tizen.messageport);
+}, 'MessagePortManager_extend');
+
+}
+
+function MessagePortManager_requestLocalMessagePort() {
+//==== TEST: MessagePortManager_requestLocalMessagePort
+//==== LABEL Check if method requestLocalMessagePort works properly
+//==== SPEC Tizen Web API:IO:Messageport:MessagePortManager:requestLocalMessagePort M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/messageport.html
+//==== TEST_CRITERIA MMINA MR
+test(function () {
+    var localMsgPort;
+
+    localMsgPort = tizen.messageport.requestLocalMessagePort("localMsgPort");
+
+    assert_equals(localMsgPort.messagePortName, "localMsgPort", "localMsgPort should have proper name");
+    assert_equals(localMsgPort.isTrusted, false, "isTrusted property should be false");
+}, 'MessagePortManager_requestLocalMessagePort');
+
+}
+
+function MessagePortManager_requestTrustedLocalMessagePort() {
+//==== TEST: MessagePortManager_requestTrustedLocalMessagePort
+//==== LABEL Check if method requestTrustedLocalMessagePort works properly
+//==== SPEC Tizen Web API:IO:Messageport:MessagePortManager:requestTrustedLocalMessagePort M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/messageport.html
+//==== TEST_CRITERIA MMINA MR
+test(function () {
+    var trustedLocalMsgPort;
+
+    trustedLocalMsgPort = tizen.messageport.requestTrustedLocalMessagePort("trustedLocalMsgPort");
+
+    assert_equals(trustedLocalMsgPort.messagePortName, "trustedLocalMsgPort", "trustedLocalMsgPort should have proper name");
+    assert_equals(trustedLocalMsgPort.isTrusted, true, "trustedLocalMsgPort should be trusted");
+}, 'MessagePortManager_requestTrustedLocalMessagePort');
+
+}
+
+function MessagePortManager_requestRemoteMessagePort() {
+//==== TEST: MessagePortManager_requestRemoteMessagePort
+//==== LABEL Check if method requestRemoteMessagePort works properly
+//==== SPEC Tizen Web API:IO:Messageport:MessagePortManager:requestRemoteMessagePort M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/messageport.html
+//==== TEST_CRITERIA MMINA MR
+test(function () {
+    var remoteMsgPort, localMsgPort,
+        app = tizen.application.getCurrentApplication();
+
+    localMsgPort = tizen.messageport.requestLocalMessagePort("remoteMsgPort");
+    remoteMsgPort = tizen.messageport.requestRemoteMessagePort(app.appInfo.id, "remoteMsgPort");
+
+    assert_equals(remoteMsgPort.messagePortName, "remoteMsgPort", "remoteMsgPort should have proper name");
+    assert_equals(remoteMsgPort.appId, app.appInfo.id, "ids should be equal");
+    assert_equals(remoteMsgPort.isTrusted, false, "isTrusted property should be false");
+}, 'MessagePortManager_requestRemoteMessagePort');
+
+}
+
+function MessagePortManager_requestTrustedRemoteMessagePort() {
+//==== TEST: MessagePortManager_requestTrustedRemoteMessagePort
+//==== LABEL Check if method requestTrustedRemoteMessagePort works properly
+//==== SPEC Tizen Web API:IO:Messageport:MessagePortManager:requestTrustedRemoteMessagePort M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/messageport.html
+//==== TEST_CRITERIA MMINA MR
+test(function () {
+    var trustedRemoteMsgPort, localMsgPort,
+        app = tizen.application.getCurrentApplication();
+
+    localMsgPort = tizen.messageport.requestTrustedLocalMessagePort("remoteMsgPort");
+    trustedRemoteMsgPort = tizen.messageport.requestTrustedRemoteMessagePort(app.appInfo.id, "remoteMsgPort");
+
+    assert_equals(trustedRemoteMsgPort.messagePortName, "remoteMsgPort", "trustedRemoteMsgPort should have proper name");
+    assert_equals(trustedRemoteMsgPort.appId, app.appInfo.id, "ids should be equal");
+    assert_equals(trustedRemoteMsgPort.isTrusted, true, "trustedRemoteMsgPort should be trusted");
+}, 'MessagePortManager_requestTrustedRemoteMessagePort');
+
+}
+
+function RemoteMessagePort_extend() {
+//==== TEST: RemoteMessagePort_extend
+//==== LABEL Check if instance of interface RemoteMessagePort can be extended with new property
+//==== PRIORITY P3
+//==== SPEC Tizen Web API:IO:Messageport:RemoteMessagePort:RemoteMessagePort U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/messageport.html
+//==== TEST_CRITERIA OBX
+test(function () {
+    var remoteMsgPort, localMsgPort,
+        app = tizen.application.getCurrentApplication();
+
+    localMsgPort = tizen.messageport.requestLocalMessagePort("remoteMsgPort");
+    remoteMsgPort = tizen.messageport.requestRemoteMessagePort(app.appInfo.id, "remoteMsgPort");
+
+    check_extensibility(remoteMsgPort);
+}, 'RemoteMessagePort_extend');
+
+}
+
+function RemoteMessagePort_sendMessage_exist() {
+//==== TEST: RemoteMessagePort_sendMessage_exist
+//==== LABEL Check if method sendMessage of RemoteMessagePort exists
+//==== SPEC Tizen Web API:IO:Messageport:RemoteMessagePort:sendMessage M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/messageport.html
+//==== TEST_CRITERIA ME
+test(function () {
+    var remoteMsgPort, localMsgPort,
+        app = tizen.application.getCurrentApplication();
+
+    localMsgPort = tizen.messageport.requestLocalMessagePort("remoteMsgPort");
+    remoteMsgPort = tizen.messageport.requestRemoteMessagePort(app.appInfo.id, "remoteMsgPort");
+
+    assert_true("sendMessage" in remoteMsgPort, "No sendMessage method in RemoteMessagePort");
+    check_method_exists(remoteMsgPort, "sendMessage");
+}, 'RemoteMessagePort_sendMessage_exist');
+
+}
+
+function LocalMessagePort_extend() {
+//==== TEST: LocalMessagePort_extend
+//==== PRIORITY P3
+//==== LABEL Check if instance of interface LocalMessagePort can be extended with new property
+//==== SPEC Tizen Web API:IO:Messageport:LocalMessagePort:LocalMessagePort U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/messageport.html
+//==== TEST_CRITERIA OBX
+test(function () {
+    var localMsgPort = tizen.messageport.requestLocalMessagePort("localMsgPort");
+
+    check_extensibility(localMsgPort);
+}, 'LocalMessagePort_extend');
+
+}
+
+function LocalMessagePort_addMessagePortListener_exist() {
+//==== TEST: LocalMessagePort_addMessagePortListener_exist
+//==== LABEL Check if method addMessagePortListener of LocalMessagePort exists
+//==== SPEC Tizen Web API:IO:Messageport:LocalMessagePort:addMessagePortListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/messageport.html
+//==== TEST_CRITERIA ME
+test(function () {
+    var localMsgPort = tizen.messageport.requestLocalMessagePort("localMsgPort");
+
+    assert_true("addMessagePortListener" in localMsgPort, "No addMessagePortListener method in localMsgPort");
+    check_method_exists(localMsgPort, "addMessagePortListener");
+}, 'LocalMessagePort_addMessagePortListener_exist');
+
+}
+
+function LocalMessagePort_removeMessagePortListener_exist() {
+//==== TEST: LocalMessagePort_removeMessagePortListener_exist
+//==== LABEL Check if method removeMessagePortListener of LocalMessagePort exists
+//==== SPEC Tizen Web API:IO:Messageport:LocalMessagePort:removeMessagePortListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/messageport.html
+//==== TEST_CRITERIA ME
+test(function () {
+    var localMsgPort;
+
+    localMsgPort = tizen.messageport.requestLocalMessagePort("localMsgPort");
+
+    assert_true("removeMessagePortListener" in localMsgPort, "No removeMessagePortListener method in localMsgPort");
+    check_method_exists(localMsgPort, "removeMessagePortListener");
+}, 'LocalMessagePort_removeMessagePortListener_exist');
+
+}
+
+function RemoteMessagePort_appId_attribute() {
+//==== TEST: RemoteMessagePort_appId_attribute
+//==== LABEL Check if attribute appId of RemoteMessagePort exists, has type ApplicationId and is readonly
+//==== SPEC Tizen Web API:IO:Messageport:RemoteMessagePort:appId A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/messageport.html
+//==== TEST_CRITERIA AE AT ARO
+test(function () {
+    var remoteMsgPort, localMsgPort,
+        app = tizen.application.getCurrentApplication();
+
+    localMsgPort = tizen.messageport.requestLocalMessagePort("remoteMsgPort");
+    remoteMsgPort = tizen.messageport.requestRemoteMessagePort(app.appInfo.id, "remoteMsgPort");
+    assert_own_property(remoteMsgPort, "appId", "RemoteMessagePort does not own appId property");
+    check_readonly(remoteMsgPort, "appId", app.appInfo.id, "string", "invalid");
+}, 'RemoteMessagePort_appId_attribute');
+
+}
+
+function RemoteMessagePort_isTrusted_attribute() {
+//==== TEST: RemoteMessagePort_isTrusted_attribute
+//==== LABEL Check if attribute isTrusted of RemoteMessagePort exists, has type Boolean and is readonly
+//==== SPEC Tizen Web API:IO:Messageport:RemoteMessagePort:isTrusted A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/messageport.html
+//==== TEST_CRITERIA AE AT ARO
+test(function () {
+    var remoteMsgPort, localMsgPort,
+        app = tizen.application.getCurrentApplication();
+
+    localMsgPort = tizen.messageport.requestLocalMessagePort("remoteMsgPort");
+    remoteMsgPort = tizen.messageport.requestRemoteMessagePort(app.appInfo.id, "remoteMsgPort");
+    assert_own_property(remoteMsgPort, "isTrusted", "RemoteMessagePort does not own isTrusted property");
+    check_readonly(remoteMsgPort, "isTrusted", false, "boolean", true);
+}, 'RemoteMessagePort_isTrusted_attribute');
+
+}
+
+function RemoteMessagePort_messagePortName_attribute() {
+//==== TEST: RemoteMessagePort_messagePortName_attribute
+//==== LABEL Check if attribute messagePortName of RemoteMessagePort exists, has type DOMString and is readonly
+//==== SPEC Tizen Web API:IO:Messageport:RemoteMessagePort:messagePortName A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/messageport.html
+//==== TEST_CRITERIA AE AT ARO
+test(function () {
+    var remoteMsgPort, localMsgPort,
+        app = tizen.application.getCurrentApplication();
+
+    localMsgPort = tizen.messageport.requestLocalMessagePort("remoteMsgPort");
+    remoteMsgPort = tizen.messageport.requestRemoteMessagePort(app.appInfo.id, "remoteMsgPort");
+    assert_own_property(remoteMsgPort, "messagePortName", "RemoteMessagePort does not own messagePortName property");
+    check_readonly(remoteMsgPort, "messagePortName", "remoteMsgPort", "string", "invalid");
+}, 'RemoteMessagePort_messagePortName_attribute');
+
+}
+
+function LocalMessagePort_isTrusted_attribute() {
+//==== TEST: LocalMessagePort_isTrusted_attribute
+//==== LABEL Check if attribute isTrusted of LocalMessagePort exists, has type boolean and is readonly
+//==== SPEC Tizen Web API:IO:Messageport:LocalMessagePort:isTrusted A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/messageport.html
+//==== TEST_CRITERIA AE AT ARO
+test(function () {
+    var localMsgPort = tizen.messageport.requestLocalMessagePort("localMsgPort");
+    assert_own_property(localMsgPort, "isTrusted", "LocalMessagePort does not own isTrusted property");
+    check_readonly(localMsgPort, "isTrusted", false, "boolean", true);
+}, 'LocalMessagePort_isTrusted_attribute');
+
+}
+
+function LocalMessagePort_messagePortName_attribute() {
+//==== TEST: LocalMessagePort_messagePortName_attribute
+//==== LABEL Check if attribute messagePortName of LocalMessagePort exists, has type DOMString and is readonly
+//==== SPEC Tizen Web API:IO:Messageport:LocalMessagePort:messagePortName A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/messageport.html
+//==== TEST_CRITERIA AE AT ARO
+test(function () {
+    var localMsgPort;
+
+    localMsgPort = tizen.messageport.requestLocalMessagePort("localMsgPort");
+    assert_own_property(localMsgPort, "messagePortName", "LocalMessagePort does not own messagePortName property");
+    check_readonly(localMsgPort, "messagePortName", "localMsgPort", "string", "invalid");
+}, 'LocalMessagePort_messagePortName_attribute');
+
+}
+
+function RemoteMessagePort_sendMessage() {
+//==== TEST: RemoteMessagePort_sendMessage
+//==== LABEL Check if method sendMessage works properly
+//==== SPEC Tizen Web API:IO:Messageport:RemoteMessagePort:sendMessage M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/messageport.html
+//==== TEST_CRITERIA MMINA MR
+var t = async_test('RemoteMessagePort_sendMessage'), retValue = null, remoteMsgPort, localMsgPort, onReceived, listenerId, messagePortData = [{key: "RESULT",
+    value: "OK"}], app = tizen.application.getCurrentApplication();
+
+t.step(function () {
+
+    onReceived = t.step_func(function (data) {
+        assert_equals(retValue, undefined, "sendMessage returns wrong value");
+        assert_equals(data.key, messagePortData.key, "received data should be the same");
+        assert_equals(data.value, messagePortData.value, "received data should be the same");
+        localMsgPort.removeMessagePortListener(listenerId);
+        t.done();
+    });
+
+    localMsgPort = tizen.messageport.requestLocalMessagePort("remoteMsgPort");
+    remoteMsgPort = tizen.messageport.requestRemoteMessagePort(app.appInfo.id, "remoteMsgPort");
+    listenerId = localMsgPort.addMessagePortListener(onReceived);
+
+    retValue = remoteMsgPort.sendMessage(messagePortData);
+});
+
+}
+
+function LocalMessagePort_addMessagePortListener() {
+//==== TEST: LocalMessagePort_addMessagePortListener
+//==== LABEL Check if method addMessagePortListener works properly
+//==== SPEC Tizen Web API:IO:Messageport:LocalMessagePort:addMessagePortListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/messageport.html
+//==== TEST_CRITERIA MMINA MAST MR
+var t = async_test('LocalMessagePort_addMessagePortListener'), remoteMsgPort, localMsgPort, onReceived, listenerId, messagePortData = [{key: "RESULT",
+    value: "OK"}], app = tizen.application.getCurrentApplication();
+
+t.step(function () {
+
+    onReceived = t.step_func(function (data) {
+        assert_type(data, "array", "MessagePortDataItem should be an array");
+        assert_equals(data.length, 1, "There should be MessagePortDataItem");
+        assert_array_equals(data[0], messagePortData[0],
+            "Received data should be equal to init data");
+        assert_not_equals(listenerId, null, "id should be not null");
+        assert_type(listenerId, "long", "id of MessagePortListener should be type of number");
+        localMsgPort.removeMessagePortListener(listenerId);
+        t.done();
+    });
+
+    localMsgPort = tizen.messageport.requestLocalMessagePort("remoteMsgPort");
+    remoteMsgPort = tizen.messageport.requestRemoteMessagePort(app.appInfo.id, "remoteMsgPort");
+    listenerId = localMsgPort.addMessagePortListener(onReceived);
+
+    remoteMsgPort.sendMessage(messagePortData);
+});
+
+}
+
+function LocalMessagePort_removeMessagePortListener() {
+//==== TEST: LocalMessagePort_removeMessagePortListener
+//==== LABEL Check if method removeMessagePortListener works properly
+//==== SPEC Tizen Web API:IO:Messageport:LocalMessagePort:removeMessagePortListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/messageport.html
+//==== TEST_CRITERIA MMINA MAST MR
+var t = async_test('LocalMessagePort_removeMessagePortListener'), localMsgPort, remoteMsgPort, listenerId, onReceived,
+    app = tizen.application.getCurrentApplication(), messagePortData = [{key: "RESULT", value: "OK"}],
+    retValue = null;
+
+t.step(function () {
+    localMsgPort = tizen.messageport.requestLocalMessagePort("remoteMsgPort");
+
+    onReceived = t.step_func(function (data) {
+        assert_unreached("Callback should be unregistered");
+    });
+    listenerId = localMsgPort.addMessagePortListener(onReceived);
+    retValue = localMsgPort.removeMessagePortListener(listenerId);
+
+    remoteMsgPort = tizen.messageport.requestRemoteMessagePort(app.appInfo.id, "remoteMsgPort");
+    remoteMsgPort.sendMessage(messagePortData);
+
+    setTimeout(t.step_func(function () {
+        assert_equals(retValue, undefined, "removeMessagePortListener returns wrong value");
+
+        t.done();
+    }), 500);
+});
+
+}
+
+function MessagePortCallback_onreceived() {
+//==== TEST: MessagePortCallback_onreceived
+//==== LABEL Check if MessagePortCallback works correctly with mandatory arguments
+//==== SPEC Tizen Web API:IO:Messageport:MessagePortCallback:onreceived M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/messageport.html
+//==== TEST_CRITERIA CBT CBOA
+var t = async_test('MessagePortCallback_onreceived'), remoteMsgPort, localMsgPort, onReceived, listenerId, messagePortData = [{key: "RESULT",
+    value: "OK"}], app = tizen.application.getCurrentApplication();
+
+t.step(function () {
+
+    onReceived = t.step_func(function (data) {
+        assert_type(data, "array", "Argument data has an invalid type");
+        assert_greater_than(data.length, 0, "Callback onReceived called with an empty array");
+        assert_type(data[0], "object", "MessagePortDataItem has an invalid type");
+
+        assert_equals(data[0].key, messagePortData[0].key, "Received data should be the same");
+        assert_equals(data[0].value, messagePortData[0].value, "Received data should be the same");
+
+        localMsgPort.removeMessagePortListener(listenerId);
+        t.done();
+    });
+
+    localMsgPort = tizen.messageport.requestLocalMessagePort("remoteMsgPort");
+    remoteMsgPort = tizen.messageport.requestRemoteMessagePort(app.appInfo.id, "remoteMsgPort");
+    listenerId = localMsgPort.addMessagePortListener(onReceived);
+
+    remoteMsgPort.sendMessage(messagePortData);
+});
+
+}
+
+function MessagePortCallback_onreceived_all() {
+//==== TEST: MessagePortCallback_onreceived_all
+//==== LABEL Check if MessagePortCallback works correctly with all arguments
+//==== SPEC Tizen Web API:IO:Messageport:MessagePortCallback:onreceived M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/messageport.html
+//==== TEST_CRITERIA CBOA
+var t = async_test('MessagePortCallback_onreceived_all'), remoteMsgPort, localMsgPort, onReceived, listenerId, messagePortData = [{key: "RESULT",
+    value: "OK"}], app = tizen.application.getCurrentApplication();
+
+t.step(function () {
+
+    onReceived = t.step_func(function (data, remoteMessagePort) {
+        assert_equals(data.key, messagePortData.key, "Received data should be the same");
+        assert_equals(data.value, messagePortData.value, "Received data should be the same");
+        assert_not_equals(remoteMessagePort, null, "remoteMessagePort should be not null}");
+        localMsgPort.removeMessagePortListener(listenerId);
+        t.done();
+    });
+
+    localMsgPort = tizen.messageport.requestLocalMessagePort("remoteMsgPort");
+    remoteMsgPort = tizen.messageport.requestRemoteMessagePort(app.appInfo.id, "remoteMsgPort");
+    listenerId = localMsgPort.addMessagePortListener(onReceived);
+
+    remoteMsgPort.sendMessage(messagePortData, localMsgPort);
+});
+
+}
+
+function RemoteMessagePort_sendMessage_with_localMessagePort() {
+//==== TEST: RemoteMessagePort_sendMessage_with_localMessagePort
+//==== LABEL Check if method sendMessage works properly with all arguments
+//==== SPEC Tizen Web API:IO:Messageport:RemoteMessagePort:sendMessage M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/messageport.html
+//==== TEST_CRITERIA MOA MAST
+var t = async_test('RemoteMessagePort_sendMessage_with_localMessagePort'), remoteMsgPort, localMsgPort, onReceived, listenerId, messagePortData = [{key: "RESULT",
+    value: "OK"}], app = tizen.application.getCurrentApplication();
+
+t.step(function () {
+
+    onReceived = t.step_func(function (data, remoteMessagePort) {
+        assert_type(data, "array", "MessagePortDataItem should be an array");
+        assert_equals(data.length, 1, "There should be MessagePortDataItem");
+        assert_array_equals(data[0], messagePortData[0],
+            "Received data should be equal to init data");
+
+        if (remoteMessagePort === null) {
+            localMsgPort.removeMessagePortListener(listenerId);
+            t.done();
+        } else {
+            remoteMessagePort.sendMessage(messagePortData);
+        }
+    });
+
+    localMsgPort = tizen.messageport.requestLocalMessagePort("remoteMsgPort");
+    remoteMsgPort = tizen.messageport.requestRemoteMessagePort(app.appInfo.id, "remoteMsgPort");
+    listenerId = localMsgPort.addMessagePortListener(onReceived);
+
+    remoteMsgPort.sendMessage(messagePortData, localMsgPort);
+});
+
+}
+
+function RemoteMessagePort_sendMessage_missarg() {
+//==== TEST: RemoteMessagePort_sendMessage_missarg
+//==== LABEL Check if sendMessage method called with no arguments throws exception
+//==== SPEC Tizen Web API:IO:Messageport:RemoteMessagePort:sendMessage M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/messageport.html
+//==== TEST_CRITERIA MMA
+test(function () {
+    var remoteMsgPort, localMsgPort,
+        app = tizen.application.getCurrentApplication();
+
+    localMsgPort = tizen.messageport.requestLocalMessagePort("remoteMsgPort");
+    remoteMsgPort = tizen.messageport.requestRemoteMessagePort(app.appInfo.id, "remoteMsgPort");
+
+    assert_throws(TYPE_MISMATCH_EXCEPTION,
+        function () {
+            remoteMsgPort.sendMessage();
+        }, "TypeMismatchError should be thrown");
+
+}, 'RemoteMessagePort_sendMessage_missarg');
+
+}
+
+function RemoteMessagePort_sendMessage_data_TypeMismatch() {
+//==== TEST: RemoteMessagePort_sendMessage_data_TypeMismatch
+//==== LABEL Check type conversions for data argument of RemoteMessagePort.sendMessage method
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Messageport:RemoteMessagePort:sendMessage M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/messageport.html
+//==== TEST_CRITERIA MC
+test(function () {
+    var remoteMsgPort, localMsgPort, conversionTable, param, exceptionName, i,
+        app = tizen.application.getCurrentApplication();
+
+    localMsgPort = tizen.messageport.requestLocalMessagePort("remoteMsgPort");
+    remoteMsgPort = tizen.messageport.requestRemoteMessagePort(app.appInfo.id, "remoteMsgPort");
+
+    conversionTable = getTypeConversionExceptions("object", false);
+    for (i = 0; i < conversionTable.length; i++) {
+        param = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+
+        assert_throws({name: exceptionName},
+            function () {
+                remoteMsgPort.sendMessage(param);
+            }, exceptionName + " should be thrown - given incorrect");
+    }
+}, 'RemoteMessagePort_sendMessage_data_TypeMismatch');
+
+}
+
+function RemoteMessagePort_sendMessage_localMessagePort_TypeMismatch() {
+//==== TEST: RemoteMessagePort_sendMessage_localMessagePort_TypeMismatch
+//==== LABEL Check type conversions for localMessagePort argument of RemoteMessagePort.sendMessage method
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Messageport:RemoteMessagePort:sendMessage M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/messageport.html
+//==== TEST_CRITERIA MC
+test(function () {
+    var remoteMsgPort, localMsgPort, conversionTable, param, exceptionName, i,
+        messagePortData = [{key:"RESULT", value:"OK"}],
+        app = tizen.application.getCurrentApplication();
+
+    localMsgPort = tizen.messageport.requestLocalMessagePort("remoteMsgPort");
+    remoteMsgPort = tizen.messageport.requestRemoteMessagePort(app.appInfo.id, "remoteMsgPort");
+
+    conversionTable = getTypeConversionExceptions("object", true);
+    for (i = 0; i < conversionTable.length; i++) {
+        param = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+
+        assert_throws({name: exceptionName},
+            function () {
+                remoteMsgPort.sendMessage(messagePortData, param);
+            }, exceptionName + " should be thrown - given incorrect");
+    }
+}, 'RemoteMessagePort_sendMessage_localMessagePort_TypeMismatch');
+
+}
+
+function LocalMessagePort_addMessagePortListener_missarg() {
+//==== TEST: LocalMessagePort_addMessagePortListener_missarg
+//==== LABEL Check if addMessagePortListener method called with no arguments throws exception
+//==== SPEC Tizen Web API:IO:Messageport:LocalMessagePort:addMessagePortListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/messageport.html
+//==== TEST_CRITERIA MMA
+test(function () {
+    var localMsgPort;
+
+    localMsgPort = tizen.messageport.requestLocalMessagePort("localMsgPort");
+
+    assert_throws(TYPE_MISMATCH_EXCEPTION,
+        function () {
+            localMsgPort.addMessagePortListener();
+        }, "TypeMismatchError should be thrown");
+
+}, 'LocalMessagePort_addMessagePortListener_missarg');
+
+}
+
+function LocalMessagePort_addMessagePortListener_listener_invalid_cb() {
+//==== TEST: LocalMessagePort_addMessagePortListener_listener_invalid_cb
+//==== LABEL Check if LocalMessagePort.addMessagePortListener method throws exception when listener is invalid
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Messageport:LocalMessagePort:addMessagePortListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/messageport.html
+//==== TEST_CRITERIA MTCB
+var t = async_test('LocalMessagePort_addMessagePortListener_listener_invalid_cb'), localMsgPort, incorrectCallback;
+
+t.step(function () {
+
+    localMsgPort = tizen.messageport.requestLocalMessagePort("localMsgPort");
+
+    incorrectCallback = {
+        onreceived: t.step_func(function () {
+            assert_unreached("Invalid callback invoked");
+        })
+    };
+
+    assert_throws(TYPE_MISMATCH_EXCEPTION,
+        function () {
+            localMsgPort.addMessagePortListener(incorrectCallback);
+        });
+
+    t.done();
+});
+
+}
+
+function LocalMessagePort_addMessagePortListener_listener_TypeMismatch() {
+//==== TEST: LocalMessagePort_addMessagePortListener_listener_TypeMismatch
+//==== LABEL Check type conversions for listener argument of LocalMessagePort.addMessagePortListener method
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:IO:Messageport:LocalMessagePort:addMessagePortListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/messageport.html
+//==== TEST_CRITERIA MC
+test(function () {
+    var localMsgPort, conversionTable, param, exceptionName, i;
+
+    localMsgPort = tizen.messageport.requestLocalMessagePort("localMsgPort");
+
+    conversionTable = getTypeConversionExceptions("functionObject", false);
+    for (i = 0; i < conversionTable.length; i++) {
+        param = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+
+        assert_throws({name: exceptionName},
+            function () {
+                localMsgPort.addMessagePortListener(param);
+            }, exceptionName + " should be thrown - given incorrect");
+    }
+}, 'LocalMessagePort_addMessagePortListener_listener_TypeMismatch');
+
+}
+
+
+function MessagePortManager_requestLocalMessagePort_typeconversion() {
+//==== TEST: MessagePortManager_requestLocalMessagePort_typeconversion
+//==== LABEL Check if method requestLocalMessagePort converts other type of parameters into string
+//==== SPEC Tizen Web API:IO:Messageport:MessagePortManager:requestLocalMessagePort M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/messageport.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+var localMsgPort, msgPortName, conversionArr, i;
+
+test(function () {
+    conversionArr = localConversionArr;
+    for(i = 0; i < conversionArr.length; i++){
+        msgPort = conversionArr[i][0];
+        msgPortName = conversionArr[i][1];
+        localMsgPort = tizen.messageport.requestLocalMessagePort(msgPort);
+        assert_equals(localMsgPort.messagePortName, msgPortName, "messageport name found as " + localMsgPort.messagePortName);
+    }
+
+}, 'MessagePortManager_requestLocalMessagePort_typeconversion');
+
+}
+
+function MessagePortManager_requestTrustedLocalMessagePort_typeconversion() {
+//==== TEST: MessagePortManager_requestTrustedLocalMessagePort_typeconversion
+//==== LABEL Check if method requestTrustedLocalMessagePort converts other type of parameters into string
+//==== SPEC Tizen Web API:IO:Messageport:MessagePortManager:requestTrustedLocalMessagePort M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/messageport.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+var trustedLocalMsgPort, msgPortName, conversionArr, i;
+
+test(function () {
+    conversionArr = localConversionArr;
+    for(i = 0; i < conversionArr.length; i++){
+        msgPort = conversionArr[i][0];
+        msgPortName = conversionArr[i][1];
+        trustedLocalMsgPort = tizen.messageport.requestTrustedLocalMessagePort(msgPort);
+        assert_equals(trustedLocalMsgPort.messagePortName, msgPortName, "messageport name found as " + trustedLocalMsgPort.messagePortName);
+    }
+
+}, 'MessagePortManager_requestTrustedLocalMessagePort_typeconversion');
+
+}
+
+function MessagePortManager_requestRemoteMessagePort_NotFoundError() {
+//==== TEST: MessagePortManager_requestRemoteMessagePort_NotFoundError
+//==== LABEL Check if method requestRemoteMessagePort throws exception when called with invalid parameter
+//==== SPEC Tizen Web API:IO:Messageport:MessagePortManager:requestRemoteMessagePort M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/messageport.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+test(function () {
+    var localMsgPort, conversionArr, app = tizen.application.getCurrentApplication(), i;
+
+    localMsgPort = tizen.messageport.requestLocalMessagePort("msgPortA");
+    conversionArr = getDOMStringConversionArray(false);
+    for(i = 0; i < conversionArr.length; i++){
+        msgPort = conversionArr[i];
+        assert_throws(NOT_FOUND_EXCEPTION, function () {
+            tizen.messageport.requestRemoteMessagePort(app, conversionArr[i]);
+        }, "NotFoundError exception should be thrown");
+    }
+}, 'MessagePortManager_requestRemoteMessagePort_NotFoundError');
+
+}
+
+function MessagePortManager_requestTrustedRemoteMessagePort_NotFoundError() {
+//==== TEST: MessagePortManager_requestTrustedRemoteMessagePort_NotFoundError
+//==== LABEL Check if method requestTrustedRemoteMessagePort throws exception when called with invalid parameter
+//==== SPEC Tizen Web API:IO:Messageport:MessagePortManager:requestTrustedRemoteMessagePort M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/messageport.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+test(function () {
+    var localMsgPort, conversionArr, msgPort, app = tizen.application.getCurrentApplication(), i;
+
+    localMsgPort = tizen.messageport.requestTrustedLocalMessagePort("msgPortA");
+    conversionArr = getDOMStringConversionArray(false);
+    for(i = 0; i < conversionArr.length; i++){
+        msgPort = conversionArr[i];
+        assert_throws(NOT_FOUND_EXCEPTION, function () {
+            tizen.messageport.requestTrustedRemoteMessagePort(app, msgPort);
+        }, "NotFoundError exception should be thrown");
+    }
+}, 'MessagePortManager_requestTrustedRemoteMessagePort_NotFoundError');
+
+}
+
+function LocalMessagePort_removeMessagePortListener_TypeMismatch() {
+//==== TEST: LocalMessagePort_removeMessagePortListener_TypeMismatch
+//==== LABEL Check if method removeMessagePortListener throws exception when called with invalid argument
+//==== SPEC Tizen Web API:IO:Messageport:LocalMessagePort:removeMessagePortListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/messageport.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 90000});
+
+var t = async_test('LocalMessagePort_removeMessagePortListener_TypeMismatch', {timeout: 90000}), localMsgPort, onReceived, listenerId, conversionTable,
+    messagePortData = [{key: "RESULT", value: "OK"}], app = tizen.application.getCurrentApplication(), i;
+
+t.step(function () {
+    onReceived = t.step_func(function (data) {
+        assert_equals(data.key, messagePortData.key, "received key should be the same");
+        assert_equals(data.value, messagePortData.value, "received value should be the same");
+        localMsgPort.removeMessagePortListener(listenerId);
+    });
+
+    localMsgPort = tizen.messageport.requestLocalMessagePort("remoteMsgPort");
+    tizen.messageport.requestRemoteMessagePort(app.appInfo.id, "remoteMsgPort");
+    listenerId = localMsgPort.addMessagePortListener(onReceived);
+    conversionTable = getTypeConversionExceptions("double", false);
+    for (i = 0; i < conversionTable.length; i++) {
+        assert_throws(NOT_FOUND_EXCEPTION, function () {
+            localMsgPort.removeMessagePortListener(conversionTable[i][0]);
+        }, NOT_FOUND_EXCEPTION + " should be thrown - given incorrect argument");
+    }
+    t.done();
+});
+
+}
+
+function RemoteMessagePort_sendMessage_empty() {
+//==== TEST: RemoteMessagePort_sendMessage_empty
+//==== LABEL Check if sendMessage method can be called with empty object as messagePortData argument
+//==== SPEC Tizen Web API:IO:Messageport:RemoteMessagePort:sendMessage M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/messageport.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTD
+
+setup({timeout: 90000});
+
+var t = async_test('RemoteMessagePort_sendMessage_empty', {timeout: 90000}), onReceived, app = tizen.application.getCurrentApplication(),
+    localMsgPort, remoteMsgPort;
+
+t.step(function () {
+
+    localMsgPort = tizen.messageport.requestLocalMessagePort("remoteMsgPort");
+    remoteMsgPort = tizen.messageport.requestRemoteMessagePort(app.appInfo.id, "remoteMsgPort");
+
+    assert_throws(INVALID_VALUES_EXCEPTION, function () {
+        remoteMsgPort.sendMessage([{}], localMsgPort);
+    }, "InvalidValuesError should be thrown");
+    t.done();
+});
+
+}
+
+function LocalMessagePort_removeMessagePortListener_misarg() {
+//==== TEST: LocalMessagePort_removeMessagePortListener_misarg
+//==== LABEL Check if method removeMessagePortListener throws exception when called without a non optional argument
+//==== SPEC Tizen Web API:IO:Messageport:LocalMessagePort:removeMessagePortListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/messageport.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MMA
+
+setup({timeout: 90000});
+
+var t = async_test('LocalMessagePort_removeMessagePortListener_misarg', {timeout: 90000}), remoteMsgPort, localMsgPort, onReceived, listenerId,
+    messagePortData = [{key: "RESULT", value: "OK"}], app = tizen.application.getCurrentApplication();
+
+t.step(function () {
+    onReceived = t.step_func(function (data) {
+        assert_equals(data.key, messagePortData.key, "received key should be the same");
+        assert_equals(data.value, messagePortData.value, "received value should be the same");
+        localMsgPort.removeMessagePortListener(listenerId);
+    });
+
+    localMsgPort = tizen.messageport.requestLocalMessagePort("remoteMsgPort");
+    remoteMsgPort = tizen.messageport.requestRemoteMessagePort(app.appInfo.id, "remoteMsgPort");
+    listenerId = localMsgPort.addMessagePortListener(onReceived);
+    remoteMsgPort.sendMessage(messagePortData, localMsgPort);
+    assert_throws(NOT_FOUND_EXCEPTION, function () {
+        localMsgPort.removeMessagePortListener();
+    }, NOT_FOUND_EXCEPTION + " should be thrown - given invalid parameter.");
+    t.done();
+});
+
+}
+
+function MessagePortManager_requestRemoteMessagePort_misarg() {
+//==== TEST: MessagePortManager_requestRemoteMessagePort_misarg
+//==== LABEL Check if method requestRemoteMessagePort throws exception when called without a non optional argument
+//==== SPEC Tizen Web API:IO:Messageport:MessagePortManager:requestRemoteMessagePort M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/messageport.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MMA
+
+test(function () {
+    assert_throws(NOT_FOUND_EXCEPTION, function () {
+        tizen.messageport.requestRemoteMessagePort();
+    }, "NotFoundError exception should be thrown - given invalid parameter.");
+}, 'MessagePortManager_requestRemoteMessagePort_misarg');
+
+}
+
+function MessagePortManager_requestTrustedRemoteMessagePort_misarg() {
+//==== TEST: MessagePortManager_requestTrustedRemoteMessagePort_misarg
+//==== LABEL Check if method requestTrustedRemoteMessagePort throws exception when called without a non optional argument
+//==== SPEC Tizen Web API:IO:Messageport:MessagePortManager:requestTrustedRemoteMessagePort M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/messageport.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MMA
+
+test(function () {
+    assert_throws(NOT_FOUND_EXCEPTION, function () {
+        tizen.messageport.requestTrustedRemoteMessagePort();
+    }, "NotFoundError exception should be thrown - given invalid parameter.");
+}, 'MessagePortManager_requestTrustedRemoteMessagePort_misarg');
+
+}
+
+function LocalMessagePort_addMessagePortListener_onreceived_invalid_cb() {
+//==== TEST: LocalMessagePort_addMessagePortListener_onreceived_invalid_cb
+//==== LABEL Check if method addMessagePortListener throws exception when onreceived has non callable attributes
+//==== SPEC Tizen Web API:IO:Messageport:LocalMessagePort:addMessagePortListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/messageport.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTL
+
+setup({timeout: 90000});
+
+var t = async_test('LocalMessagePort_addMessagePortListener_onreceived_invalid_cb', {timeout: 90000}), remoteMsgPort, localMsgPort, incorrectListener, messagePortData, onreceived, app, i, exceptionName;
+
+t.step(function () {
+    app = tizen.application.getCurrentApplication();
+    messagePortData = [{key: "RESULT", value: "OK"}];
+    incorrectListener = getListenerConversionExceptions("onreceived");
+    localMsgPort = tizen.messageport.requestLocalMessagePort("MsgPortA");
+    remoteMsgPort = tizen.messageport.requestRemoteMessagePort(app.appInfo.id, "MsgPortA");
+    for(i = 0; i < incorrectListener.length; i++) {
+        onreceived = incorrectListener[i][0];
+        exceptionName = incorrectListener[i][1];
+        assert_throws(exceptionName, function () {
+            localMsgPort.addMessagePortListener(onreceived);
+            remoteMsgPort.sendMessage(messagePortData, localMsgPort);
+        }, exceptionName + " should be thrown - given invalid parameter.");
+    }
+    t.done();
+});
+
+}
+
+function RemoteMessagePort_sendMessage_localMsgPort_invalid_obj() {
+//==== TEST: RemoteMessagePort_sendMessage_localMsgPort_invalid_obj
+//==== LABEL Check if method sendMessage throws exception when a fake system object was passed
+//==== SPEC Tizen Web API:IO:Messageport:RemoteMessagePort:sendMessage M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/messageport.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTO
+
+setup({timeout: 90000});
+
+var t = async_test('RemoteMessagePort_sendMessage_localMsgPort_invalid_obj', {timeout: 90000}), remoteMsgPort, localMsgPort, onReceived, messagePortData = [{key: "RESULT", value: "OK"}],
+    app = tizen.application.getCurrentApplication(), invalidLocalMsgPort;
+
+t.step(function () {
+    onReceived = t.step_func(function (data) {
+        assert_unreached("Message should not be sent.");
+    });
+
+    localMsgPort = tizen.messageport.requestLocalMessagePort("msgPortA");
+    remoteMsgPort = tizen.messageport.requestRemoteMessagePort(app.appInfo.id, "msgPortA");
+    localMsgPort.addMessagePortListener(onReceived);
+
+    invalidLocalMsgPort = {
+        messagePortName: "invalidPort",
+        isTrusted: false,
+        addMessagePortListener: function (listener) {},
+        removeMessagePortListener: function (watchId) {} 
+    };
+
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        remoteMsgPort.sendMessage(messagePortData, invalidLocalMsgPort);
+    }, "TypeMismatchError should be thrown");
+    t.done();
+
+});
+
+}
+
+var moduleName = "tct-messageport-tizen-tests";
+add_test_case(moduleName, LocalMessagePort_notexist);
+add_test_case(moduleName, MessagePortCallback_notexist);
+add_test_case(moduleName, MessagePortManagerObject_notexist);
+add_test_case(moduleName, MessagePortManager_notexist);
+add_test_case(moduleName, RemoteMessagePort_notexist);
+add_test_case(moduleName, MessagePortManager_in_tizen);
+add_test_case(moduleName, MessagePortManager_requestLocalMessagePort_exist);
+add_test_case(moduleName, MessagePortManager_requestRemoteMessagePort_exist);
+add_test_case(moduleName, MessagePortManager_requestTrustedRemoteMessagePort_exist);
+add_test_case(moduleName, MessagePortManager_requestTrustedLocalMessagePort_exist);
+add_test_case(moduleName, MessagePortManager_extend);
+add_test_case(moduleName, MessagePortManager_requestLocalMessagePort);
+add_test_case(moduleName, MessagePortManager_requestTrustedLocalMessagePort);
+add_test_case(moduleName, MessagePortManager_requestRemoteMessagePort);
+add_test_case(moduleName, MessagePortManager_requestTrustedRemoteMessagePort);
+add_test_case(moduleName, RemoteMessagePort_extend);
+add_test_case(moduleName, RemoteMessagePort_sendMessage_exist);
+add_test_case(moduleName, LocalMessagePort_extend);
+add_test_case(moduleName, LocalMessagePort_addMessagePortListener_exist);
+add_test_case(moduleName, LocalMessagePort_removeMessagePortListener_exist);
+add_test_case(moduleName, RemoteMessagePort_appId_attribute);
+add_test_case(moduleName, RemoteMessagePort_isTrusted_attribute);
+add_test_case(moduleName, RemoteMessagePort_messagePortName_attribute);
+add_test_case(moduleName, LocalMessagePort_isTrusted_attribute);
+add_test_case(moduleName, LocalMessagePort_messagePortName_attribute);
+add_test_case(moduleName, RemoteMessagePort_sendMessage);
+add_test_case(moduleName, LocalMessagePort_addMessagePortListener);
+add_test_case(moduleName, LocalMessagePort_removeMessagePortListener);
+add_test_case(moduleName, MessagePortCallback_onreceived);
+add_test_case(moduleName, MessagePortCallback_onreceived_all);
+add_test_case(moduleName, RemoteMessagePort_sendMessage_with_localMessagePort);
+add_test_case(moduleName, RemoteMessagePort_sendMessage_missarg);
+add_test_case(moduleName, RemoteMessagePort_sendMessage_data_TypeMismatch);
+add_test_case(moduleName, RemoteMessagePort_sendMessage_localMessagePort_TypeMismatch);
+add_test_case(moduleName, LocalMessagePort_addMessagePortListener_missarg);
+add_test_case(moduleName, LocalMessagePort_addMessagePortListener_listener_invalid_cb);
+add_test_case(moduleName, LocalMessagePort_addMessagePortListener_listener_TypeMismatch);
+add_test_case(moduleName, MessagePortManager_requestLocalMessagePort_typeconversion);
+add_test_case(moduleName, MessagePortManager_requestTrustedLocalMessagePort_typeconversion);
+add_test_case(moduleName, MessagePortManager_requestRemoteMessagePort_NotFoundError);
+add_test_case(moduleName, MessagePortManager_requestTrustedRemoteMessagePort_NotFoundError);
+add_test_case(moduleName, LocalMessagePort_removeMessagePortListener_TypeMismatch);
+add_test_case(moduleName, RemoteMessagePort_sendMessage_empty);
+add_test_case(moduleName, LocalMessagePort_removeMessagePortListener_misarg);
+add_test_case(moduleName, MessagePortManager_requestRemoteMessagePort_misarg);
+add_test_case(moduleName, MessagePortManager_requestTrustedRemoteMessagePort_misarg);
+add_test_case(moduleName, LocalMessagePort_addMessagePortListener_onreceived_invalid_cb);
+add_test_case(moduleName, RemoteMessagePort_sendMessage_localMsgPort_invalid_obj);
diff --git a/webWidgetTCT_device/test/tct/tests/TestPackage.js b/webWidgetTCT_device/test/tct/tests/TestPackage.js
new file mode 100755 (executable)
index 0000000..9a47a2d
--- /dev/null
@@ -0,0 +1,1957 @@
+/*
+Copyright (c) 2013 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Authors:
+        Junghyuk Park <junghyuk.park@samsung.com>
+
+*/
+
+var TCT_PACKAGE_TIZEN_TESTS_PACKAGE_ID = "tizenutc00";
+var TCT_PACKAGE_TIZEN_TESTS_PACKAGE_NAME = "WebServiceTest";
+var TCT_PACKAGE_TIZEN_TESTS_PACKAGE_APP_ID = "tizenutc00.UnitTest";
+var TCT_PACKAGE_TIZEN_TESTS_PACKAGE_APP_ID_2 = "tizenutcmp.MsgPortSvr";
+var TCT_PACKAGE_TIZEN_TESTS_PACKAGE_APP_ID_3 = "tizenutc00.WebServiceTest";
+var TCT_PACKAGE_TIZEN_TESTS_PACKAGE_AUTHOR = "";
+var TCT_PACKAGE_TIZEN_TESTS_PACKAGE_DESCRIPTION = "";
+
+
+var TCT_PACKAGE_MANAGER_TEST_PACKAGE_PATH = "/home/owner/share/TCTPackageManagerTest1.1.1.wgt";
+var TCT_PACKAGE_MANAGER_TEST_PACKAGE_PATH_2 = "/home/owner/share/TCTPackageManagerTest2.2.2.wgt";
+var TCT_PACKAGE_MANAGER_TEST_PACKAGE_ID = "api1pack10";
+var TCT_PACKAGE_MANAGER_TEST_PACKAGE_NAME = "TCTPackageManagerTest";
+var TCT_PACKAGE_MANAGER_TEST_PACKAGE_APP_ID = "api1pack10.TCTPackageManagerTest";
+var TCT_PACKAGE_MANAGER_TEST_PACKAGE_VERSION_1 = "1.1.1";
+var TCT_PACKAGE_MANAGER_TEST_PACKAGE_VERSION_2 = "2.2.2";
+var TCT_PACKAGE_MANAGER_TEST_PACKAGE_AUTHOR = "The author of TCTPackageManagerTest";
+var TCT_PACKAGE_MANAGER_TEST_PACKAGE_DESCRIPTION = "The description of TCTPackageManagerTest";
+
+
+var TCT_PACKAGE_INFO_TEST_PACKAGE_ID = "api1pack20";
+var TCT_PACKAGE_INFO_TEST_PACKAGE_NAME = "TCTPackageInfoTest";
+var TCT_PACKAGE_INFO_TEST_PACKAGE_ICON_PATH = "icon.png";
+var TCT_PACKAGE_INFO_TEST_PACKAGE_VERSION = "1.2.3";
+var TCT_PACKAGE_INFO_TEST_PACKAGE_AUTHOR = "The author of TCTPackageInfoTest";
+var TCT_PACKAGE_INFO_TEST_PACKAGE_DESCRIPTION = "The description of TCTPackageInfoTest";
+var TCT_PACKAGE_INFO_TEST_PACKAGE_APP_ID = "api1pack20.TCTPackageInfoTest";
+
+var NOT_EXISTING_PACKAGE_ID = "api1dummy0";
+
+function getDOMStringConversionArray(isOptional) {
+    var typeArr = [false, true, NaN, 0, undefined, [1,2], {"a":1,"b":2}, function(){} ];
+    if (!isOptional) {
+        typeArr.push(null);
+    }
+    return typeArr;
+}
+
+function PackageInformationArraySuccessCallback_notexist() {
+//==== TEST: PackageInformationArraySuccessCallback_notexist
+//==== PRIORITY P3
+//==== LABEL Check if interface PackageInformationArraySuccessCallback exists, it should not
+//==== SPEC Tizen Web API:Application:Package:PackageInformationArraySuccessCallback:PackageInformationArraySuccessCallback U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== TEST_CRITERIA CBNIO
+test(function () {
+    check_no_interface_object("PackageInformationArraySuccessCallback");
+}, 'PackageInformationArraySuccessCallback_notexist');
+
+}
+
+function PackageInformationArraySuccessCallback_onsuccess() {
+//==== TEST: PackageInformationArraySuccessCallback_onsuccess
+//==== LABEL Check if PackageInformationArraySuccessCallback works
+//==== SPEC Tizen Web API:Application:Package:PackageInformationArraySuccessCallback:onsuccess M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA CBT CBOA
+setup({timeout: 90000});
+
+var t = async_test('PackageInformationArraySuccessCallback_onsuccess', {timeout: 90000}), packageInformation,
+    packageInformationArraySuccessCallback, errorCallback;
+
+t.step(function () {
+    packageInformationArraySuccessCallback = t.step_func(function (informationArray) {
+
+        assert_true(Array.isArray(informationArray), "informationArray is not an array.");
+        assert_greater_than(informationArray.length, 0, "Incorrect length of informationArray.");
+
+        packageInformation = informationArray[0];
+
+        assert_type(packageInformation.id, "string", "PackageInformation.id attribute is not a string.");
+        assert_not_equals(packageInformation.id, "", "PackageInformation.id is empty string.");
+
+        assert_type(packageInformation.name, "string", "PackageInformation.name attribute is not a string.");
+        assert_not_equals(packageInformation.name, "", "PackageInformation.name is empty string.");
+
+        assert_type(packageInformation.iconPath, "string", "PackageInformation.iconPath attribute is not a string.");
+
+        assert_type(packageInformation.version, "string", "PackageInformation.version attribute is not a string.");
+
+        assert_type(packageInformation.totalSize, "long", "PackageInformation.totalSize is not a number");
+
+        assert_type(packageInformation.dataSize, "long", "PackageInformation.dataSize is not a number");
+
+        assert_greater_than_equal(packageInformation.totalSize, packageInformation.dataSize,
+            "PackageInformation.dataSize is bigger than packageInformation.totalSize.");
+
+        assert_true(packageInformation.lastModified instanceof Date, "PackageInformation.lastModified is not a Date");
+        assert_true(packageInformation.lastModified < new Date(),
+            "PackageInformation.lastModified is from present ot future.");
+
+        assert_type(packageInformation.author, "string", "PackageInformation.author attribute is not a string");
+
+        assert_type(packageInformation.appIds, "array", "PackageInformation.appIds is not an array.");
+
+        assert_type(packageInformation.description, "string", "PackageInformation.description attribute is not a string.");
+        t.done();
+    });
+
+    errorCallback = t.step_func(function (error) {
+        assert_unreached("ErrorCallback invoked. Exception name:" + error.name + ", message: " + error.message);
+    });
+
+    tizen.package.getPackagesInfo(packageInformationArraySuccessCallback, errorCallback);
+});
+
+}
+
+function PackageInformationEventCallback_notexist() {
+//==== TEST: PackageInformationEventCallback_notexist
+//==== PRIORITY P3
+//==== LABEL Check if interface PackageInformationEventCallback exists, it should not
+//==== SPEC Tizen Web API:Application:Package:PackageInformationEventCallback:PackageInformationEventCallback U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== TEST_CRITERIA CBNIO
+test(function () {
+    check_no_interface_object("PackageInformationEventCallback");
+}, 'PackageInformationEventCallback_notexist');
+
+}
+
+function PackageInformation_appIds_attribute() {
+//==== TEST: PackageInformation_appIds_attribute
+//==== LABEL Check if attribute appIds of PackageInformation exists, has type Array and is readonly
+//==== SPEC Tizen Web API:Application:Package:PackageInformation:appIds A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== TEST_CRITERIA AE ARO AT
+test(function () {
+    var packageInformation = tizen.package.getPackageInfo(TCT_PACKAGE_INFO_TEST_PACKAGE_ID), newValue = ["newValue"],
+        expectedValue = [TCT_PACKAGE_INFO_TEST_PACKAGE_APP_ID];
+    assert_own_property(packageInformation, "appIds" , "PackageInformation does not own appIds property.");
+
+    assert_type(packageInformation.appIds, "array", "Not an array");
+    assert_array_equals(packageInformation.appIds, expectedValue, "PackageInformation.appIds is incorrect.");
+
+    packageInformation.appIds = newValue;
+    assert_array_equals(packageInformation.appIds, expectedValue, "PackageInformation.appIds is incorrect.");
+
+    packageInformation.appIds = null;
+    assert_array_equals(packageInformation.appIds, expectedValue, "PackageInformation.appIds is incorrect.");
+}, 'PackageInformation_appIds_attribute');
+
+}
+
+function PackageInformation_author_attribute() {
+//==== TEST: PackageInformation_author_attribute
+//==== LABEL Check if attribute author of PackageInformation exists, has type DOMString and is readonly
+//==== SPEC Tizen Web API:Application:Package:PackageInformation:author A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== TEST_CRITERIA AE AT ARO
+test(function () {
+    var packageInformation = tizen.package.getPackageInfo(TCT_PACKAGE_INFO_TEST_PACKAGE_ID);
+    assert_own_property(packageInformation, "author" , "PackageInformation does not own author property.");
+    check_readonly(packageInformation, "author", TCT_PACKAGE_INFO_TEST_PACKAGE_AUTHOR, "string", "newValue");
+}, 'PackageInformation_author_attribute');
+
+}
+
+function PackageInformation_dataSize_attribute() {
+//==== TEST: PackageInformation_dataSize_attribute
+//==== LABEL Check if attribute dataSize of PackageInformation exists, has type Number and is readonly
+//==== SPEC Tizen Web API:Application:Package:PackageInformation:dataSize A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== TEST_CRITERIA AE AT ARO
+test(function () {
+    var originalValue, packageInformation = tizen.package.getPackageInfo(TCT_PACKAGE_INFO_TEST_PACKAGE_ID), newValue = 1234567;
+    assert_own_property(packageInformation, "dataSize" , "PackageInformation does not own dataSize property.");
+
+    assert_type(packageInformation.dataSize, "long", "Incorrect type for PackageInformation.dataSize attribute.");
+
+    originalValue = packageInformation.dataSize;
+    packageInformation.dataSize = newValue;
+    assert_type(packageInformation.dataSize, "long", "Incorrect type for PackageInformation.dataSize after assignment.");
+    assert_not_equals(packageInformation.dataSize, newValue, "PackageInformation.dataSize can be modified.");
+    assert_equals(packageInformation.dataSize, originalValue, "PackageInformation.dataSize can be modified.");
+
+    packageInformation.dataSize = null;
+    assert_type(packageInformation.dataSize, "long", "Incorrect type for PackageInformation.dataSize after assignment.");
+    assert_not_equals(packageInformation.dataSize, null, "PackageInformation.dataSize can be modified.");
+    assert_equals(packageInformation.dataSize, originalValue, "PackageInformation.dataSize can be modified.");
+}, 'PackageInformation_dataSize_attribute');
+
+}
+
+function PackageInformation_description_attribute() {
+//==== TEST: PackageInformation_description_attribute
+//==== LABEL Check if attribute description of PackageInformation exists, has type DOMString and is readonly
+//==== SPEC Tizen Web API:Application:Package:PackageInformation:description A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== TEST_CRITERIA AE AT ARO
+test(function () {
+    var packageInformation = tizen.package.getPackageInfo(TCT_PACKAGE_INFO_TEST_PACKAGE_ID);
+    assert_own_property(packageInformation, "description" , "PackageInformation does not own description property.");
+    check_readonly(packageInformation, "description", TCT_PACKAGE_INFO_TEST_PACKAGE_DESCRIPTION, "string", "newValue");
+}, 'PackageInformation_description_attribute');
+
+}
+
+function PackageInformation_extend() {
+//==== TEST: PackageInformation_extend
+//==== LABEL Check if PackageInformation is extendable
+//==== SPEC Tizen Web API:Application:Package:PackageInformation:PackageInformation U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA OBX
+test(function () {
+    var packageInformation = tizen.package.getPackageInfo();
+    check_extensibility(packageInformation);
+}, 'PackageInformation_extend');
+
+}
+
+function PackageInformation_iconPath_attribute() {
+//==== TEST: PackageInformation_iconPath_attribute
+//==== LABEL Check if attribute iconPath of PackageInformation exists, has type DOMString and is readonly
+//==== SPEC Tizen Web API:Application:Package:PackageInformation:iconPath A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== TEST_CRITERIA AE AT ARO
+test(function () {
+    var originalValue, packageInformation = tizen.package.getPackageInfo(TCT_PACKAGE_INFO_TEST_PACKAGE_ID), newValue = "newValue";
+    assert_own_property(packageInformation, "iconPath" , "PackageInformation does not own iconPath property.");
+
+    assert_type(packageInformation.iconPath, "string", "Incorrect type for PackageInformation.iconPath attribute.");
+    assert_not_equals(packageInformation.iconPath, "", "PackageInformation.iconPath is an empty string.");
+
+    originalValue = packageInformation.iconPath;
+    packageInformation.iconPath = newValue;
+    assert_type(packageInformation.iconPath, "string", "Incorrect type for PackageInformation.iconPath after assignment.");
+    assert_not_equals(packageInformation.iconPath, newValue, "PackageInformation.iconPath can be modified.");
+    assert_equals(packageInformation.iconPath, originalValue, "PackageInformation.iconPath can be modified.");
+
+    packageInformation.iconPath = null;
+    assert_type(packageInformation.iconPath, "string", "Incorrect type for PackageInformation.iconPath after assignment.");
+    assert_not_equals(packageInformation.iconPath, null, "PackageInformation.iconPath can be modified.");
+    assert_equals(packageInformation.iconPath, originalValue, "PackageInformation.iconPath can be modified.");
+
+}, 'PackageInformation_iconPath_attribute');
+
+}
+
+function PackageInformation_id_attribute() {
+//==== TEST: PackageInformation_id_attribute
+//==== LABEL Check if attribute id of PackageInformation exists, has type PackageId and is readonly
+//==== SPEC Tizen Web API:Application:Package:PackageInformation:id A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== TEST_CRITERIA AE AT ARO
+test(function () {
+    var packageInformation = tizen.package.getPackageInfo(TCT_PACKAGE_INFO_TEST_PACKAGE_ID);
+    assert_own_property(packageInformation, "id" , "PackageInformation does not own id property.");
+    check_readonly(packageInformation, "id", TCT_PACKAGE_INFO_TEST_PACKAGE_ID, "string", "newValue");
+}, 'PackageInformation_id_attribute');
+
+}
+
+function PackageInformation_lastModified_attribute() {
+//==== TEST: PackageInformation_lastModified_attribute
+//==== LABEL Check if attribute lastModified of PackageInformation exists, has type Date and is readonly
+//==== SPEC Tizen Web API:Application:Package:PackageInformation:lastModified A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== TEST_CRITERIA AE AT ARO
+test(function () {
+    var originalValue, packageInformation = tizen.package.getPackageInfo(TCT_PACKAGE_INFO_TEST_PACKAGE_ID), newValue = new Date();
+    assert_own_property(packageInformation, "lastModified" , "PackageInformation does not own lastModified property.");
+
+    assert_true(packageInformation.lastModified instanceof Date, "PackageInformation.lastModified is not a Date");
+
+    originalValue = packageInformation.lastModified;
+    packageInformation.lastModified = newValue;
+    assert_true(packageInformation.lastModified instanceof Date, "PackageInformation.lastModified is not a Date");
+    assert_not_equals(packageInformation.lastModified.getTime(), newValue.getTime(), "PackageInformation.lastModified can be modified.");
+    assert_equals(packageInformation.lastModified.getTime(), originalValue.getTime(), "PackageInformation.lastModified can be modified.");
+
+    packageInformation.lastModified = null;
+    assert_true(packageInformation.lastModified instanceof Date, "PackageInformation.lastModified is not a Date");
+    assert_not_equals(packageInformation.lastModified, null, "PackageInformation.lastModified can be modified.");
+    assert_equals(packageInformation.lastModified.getTime(), originalValue.getTime(), "PackageInformation.lastModified can be modified.");
+
+}, 'PackageInformation_lastModified_attribute');
+
+}
+
+function PackageInformation_name_attribute() {
+//==== TEST: PackageInformation_name_attribute
+//==== LABEL Check if attribute name of PackageInformation exists, has type DOMString and is readonly
+//==== SPEC Tizen Web API:Application:Package:PackageInformation:name A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== TEST_CRITERIA AE AT ARO
+test(function () {
+    var packageInformation = tizen.package.getPackageInfo(TCT_PACKAGE_INFO_TEST_PACKAGE_ID);
+    assert_own_property(packageInformation, "name" , "PackageInformation does not own name property.");
+    check_readonly(packageInformation, "name", TCT_PACKAGE_INFO_TEST_PACKAGE_NAME, "string", "newValue");
+}, 'PackageInformation_name_attribute');
+
+}
+
+function PackageInformation_notexist() {
+//==== TEST: PackageInformation_notexist
+//==== PRIORITY P3
+//==== LABEL Check if interface PackageInformation exists, it should not
+//==== SPEC Tizen Web API:Application:Package:PackageInformation:PackageInformation U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== TEST_CRITERIA NIO
+test(function () {
+    check_no_interface_object("PackageInformation");
+}, 'PackageInformation_notexist');
+
+}
+
+function PackageInformation_totalSize_attribute() {
+//==== TEST: PackageInformation_totalSize_attribute
+//==== LABEL Check if attribute totalSize of PackageInformation exists, has type Number and is readonly
+//==== SPEC Tizen Web API:Application:Package:PackageInformation:totalSize A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== TEST_CRITERIA AE AT ARO
+test(function () {
+    var originalValue, packageInformation = tizen.package.getPackageInfo(TCT_PACKAGE_INFO_TEST_PACKAGE_ID), newValue = 1234567;
+    assert_own_property(packageInformation, "totalSize" , "PackageInformation does not own totalSize property.");
+
+    assert_type(packageInformation.totalSize, "long", "Incorrect type for PackageInformation.totalSize attribute.");
+
+    originalValue = packageInformation.totalSize;
+    packageInformation.totalSize = newValue;
+    assert_type(packageInformation.totalSize, "long", "Incorrect type for PackageInformation.totalSize after assignment.");
+    assert_not_equals(packageInformation.totalSize, newValue, "PackageInformation.totalSize can be modified.");
+    assert_equals(packageInformation.totalSize, originalValue, "PackageInformation.totalSize can be modified.");
+
+    packageInformation.totalSize = null;
+    assert_type(packageInformation.totalSize, "long", "Incorrect type for PackageInformation.totalSize after assignment.");
+    assert_not_equals(packageInformation.totalSize, null, "PackageInformation.totalSize can be modified.");
+    assert_equals(packageInformation.totalSize, originalValue, "PackageInformation.totalSize can be modified.");
+}, 'PackageInformation_totalSize_attribute');
+
+}
+
+function PackageInformation_version_attribute() {
+//==== TEST: PackageInformation_version_attribute
+//==== LABEL Check if attribute version of PackageInformation exists, has type DOMString and is readonly
+//==== SPEC Tizen Web API:Application:Package:PackageInformation:version A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== TEST_CRITERIA AE AT ARO
+test(function () {
+    var packageInformation = tizen.package.getPackageInfo(TCT_PACKAGE_INFO_TEST_PACKAGE_ID);
+    assert_own_property(packageInformation, "version" , "PackageInformation does not own version property.");
+    check_readonly(packageInformation, "version", TCT_PACKAGE_INFO_TEST_PACKAGE_VERSION, "string", "newValue");
+}, 'PackageInformation_version_attribute');
+
+}
+
+function PackageManagerObject_notexist() {
+//==== TEST: PackageManagerObject_notexist
+//==== PRIORITY P3
+//==== LABEL Check if interface PackageManagerObject exists, it should not
+//==== SPEC Tizen Web API:Application:Package:PackageManagerObject:PackageManagerObject U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== TEST_CRITERIA NIO
+test(function () {
+    check_no_interface_object("PackageManagerObject");
+}, 'PackageManagerObject_notexist');
+
+}
+
+function PackageManager_extend() {
+//==== TEST: PackageManager_extend
+//==== LABEL Check if PackageManager is extendable
+//==== SPEC Tizen Web API:Application:Package:PackageManager:PackageManager U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA OBX
+test(function () {
+    check_extensibility(tizen.package);
+}, 'PackageManager_extend');
+
+}
+
+function PackageManager_getPackageInfo() {
+//==== TEST: PackageManager_getPackageInfo
+//==== LABEL Check if method getPackageInfo of PackageManager works properly
+//==== SPEC Tizen Web API:Application:Package:PackageManager:getPackageInfo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== TEST_CRITERIA MMINA MR
+test(function () {
+    var packageInformation;
+    packageInformation = tizen.package.getPackageInfo();
+
+    assert_equals(packageInformation.id, TCT_PACKAGE_TIZEN_TESTS_PACKAGE_ID, "PackageInformation.id is incorrect.");
+    assert_equals(packageInformation.name, TCT_PACKAGE_TIZEN_TESTS_PACKAGE_NAME, "PackageInformation.name is incorrect.");
+
+    assert_type(packageInformation.iconPath, "string", "Incorrect type for PackageInformation.iconPath attribute.");
+    assert_not_equals(packageInformation.iconPath, "", "PackageInformation.iconPath is an empty string.");
+
+    assert_type(packageInformation.version, "string", "Incorrect type of PackageInformation.version");
+    assert_not_equals(packageInformation.version, "", "PackageInformation.version is an empty string");
+
+    assert_type(packageInformation.totalSize, "long", "Incorrect type of PackageInformation.totalSize");
+    assert_type(packageInformation.dataSize, "long", "Incorrect type of PackageInformation.dataSize");
+    assert_greater_than_equal(packageInformation.totalSize, packageInformation.dataSize,
+        "PackageInformation.dataSize is bigger than packageInformation.totalSize.");
+
+    assert_true(packageInformation.lastModified instanceof Date, "PackageInformation.lastModified is not a Date");
+
+    assert_equals(packageInformation.author, TCT_PACKAGE_TIZEN_TESTS_PACKAGE_AUTHOR, "PackageInformation.author is incorrect.");
+
+    assert_array_equals(packageInformation.appIds, [TCT_PACKAGE_TIZEN_TESTS_PACKAGE_APP_ID, TCT_PACKAGE_TIZEN_TESTS_PACKAGE_APP_ID_2, TCT_PACKAGE_TIZEN_TESTS_PACKAGE_APP_ID_3],
+        "packageInformation.appIds is incorrect");
+
+    assert_equals(packageInformation.description, TCT_PACKAGE_TIZEN_TESTS_PACKAGE_DESCRIPTION,
+        "PackageInformation.description is incorect.");
+
+}, 'PackageManager_getPackageInfo');
+
+}
+
+function PackageManager_getPackageInfo_exist() {
+//==== TEST: PackageManager_getPackageInfo_exist
+//==== LABEL Check if method getPackageInfo of PackageManager exists
+//==== SPEC Tizen Web API:Application:Package:PackageManager:getPackageInfo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== TEST_CRITERIA ME
+test(function () {
+    assert_true("getPackageInfo" in tizen.package, "No getPackageInfo method in tizen.package");
+    check_method_exists(tizen.package, "getPackageInfo");
+}, 'PackageManager_getPackageInfo_exist');
+
+}
+
+function PackageManager_getPackageInfo_TypeMismatch() {
+//==== TEST: PackageManager_getPackageInfo_TypeMismatch
+//==== LABEL Check if package information is get properly with invalid argument.
+//==== SPEC Tizen Web API:Application:Package:PackageManager:getPackageInfo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+test(function () {
+    var packageInfo, conversionArr, i;
+    conversionArr = getDOMStringConversionArray(true);
+    for(i = 0; i < conversionArr.length; i++) {
+        assert_throws(NOT_FOUND_EXCEPTION, function(){
+            packageInfo = tizen.package.getPackageInfo(conversionArr[i]);
+        }, "Exception should be thrown");
+    }
+}, 'PackageManager_getPackageInfo_TypeMismatch');
+
+}
+
+function PackageManager_getPackageInfo_with_id() {
+//==== TEST: PackageManager_getPackageInfo_with_id
+//==== LABEL Check if method getPackageInfo of PackageManager works properly with id
+//==== SPEC Tizen Web API:Application:Package:PackageManager:getPackageInfo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== TEST_CRITERIA MOA MR
+test(function () {
+    var packageInformation;
+    packageInformation = tizen.package.getPackageInfo(TCT_PACKAGE_INFO_TEST_PACKAGE_ID);
+
+    assert_equals(packageInformation.id, TCT_PACKAGE_INFO_TEST_PACKAGE_ID, "PackageInformation.id is incorrect.");
+    assert_equals(packageInformation.name, TCT_PACKAGE_INFO_TEST_PACKAGE_NAME, "PackageInformation.name is incorrect.");
+
+    assert_type(packageInformation.iconPath, "string", "Incorrect type for PackageInformation.iconPath attribute.");
+    assert_not_equals(packageInformation.iconPath, "", "PackageInformation.iconPath is an empty string.");
+
+    assert_equals(packageInformation.version, TCT_PACKAGE_INFO_TEST_PACKAGE_VERSION, "PackageInformation.version is incorrect.");
+
+    assert_type(packageInformation.totalSize, "long", "Incorrect type of PackageInformation.totalSize");
+    assert_type(packageInformation.dataSize, "long", "Incorrect type of PackageInformation.dataSize");
+    assert_greater_than_equal(packageInformation.totalSize, packageInformation.dataSize,
+        "PackageInformation.dataSize is bigger than packageInformation.totalSize.");
+
+    assert_true(packageInformation.lastModified instanceof Date,
+        "PackageInformation.lastModified is not a Date");
+
+    assert_equals(packageInformation.author, TCT_PACKAGE_INFO_TEST_PACKAGE_AUTHOR, "PackageInformation.author is incorrect.");
+
+    assert_array_equals(packageInformation.appIds, [TCT_PACKAGE_INFO_TEST_PACKAGE_APP_ID],
+        "packageInformation.appIds is incorrect");
+
+    assert_equals(packageInformation.description, TCT_PACKAGE_INFO_TEST_PACKAGE_DESCRIPTION,
+        "PackageInformation.description is incorect.");
+
+}, 'PackageManager_getPackageInfo_with_id');
+
+}
+
+function PackageManager_getPackageInfo_with_id_null() {
+//==== TEST: PackageManager_getPackageInfo_with_id_null
+//==== LABEL Check if method getPackageInfo of PackageManager works properly with id parameter null
+//==== SPEC Tizen Web API:Application:Package:PackageManager:getPackageInfo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+test(function () {
+    var packageInfo = tizen.package.getPackageInfo(null);
+    assert_equals(packageInfo.id, "tizenutc00", "Id of the package should be tizenutc00 by default");
+}, 'PackageManager_getPackageInfo_with_id_null');
+
+}
+
+function PackageManager_getPackagesInfo() {
+//==== TEST: PackageManager_getPackagesInfo
+//==== LABEL Check if method getPackagesInfo of PackageManager works properly
+//==== SPEC Tizen Web API:Application:Package:PackageManager:getPackagesInfo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== ONLOAD_DELAY 90
+//==== TEST_CRITERIA MMINA MR
+setup({timeout: 90000});
+
+var t = async_test('PackageManager_getPackagesInfo', {timeout: 90000}),
+    packageInformationArraySuccessCallback, returnedValue = null;
+
+t.step(function () {
+    packageInformationArraySuccessCallback = t.step_func(function (informationArray) {
+        assert_equals(returnedValue, undefined, "Incorect returned value from getPackagesInfo method");
+
+        assert_true(Array.isArray(informationArray), "informationArray is not an array.");
+        assert_greater_than(informationArray.length, 0, "Incorrect length of informationArray.");
+
+        t.done();
+    });
+
+    returnedValue = tizen.package.getPackagesInfo(packageInformationArraySuccessCallback);
+});
+
+}
+
+function PackageManager_getPackagesInfo_errorCallback_TypeMismatch() {
+//==== TEST: PackageManager_getPackagesInfo_errorCallback_TypeMismatch
+//==== LABEL Check if getPackagesInfo throws exception when errorCallback is incorrect
+//==== PRIORITY: P2
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Application:Package:PackageManager:getPackagesInfo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== TEST_CRITERIA MC
+setup({timeout: 30000});
+
+var t = async_test('PackageManager_getPackagesInfo_errorCallback_TypeMismatch', {timeout: 30000}), conversionTable,
+    packageInformationArraySuccessCallback, exceptionName, errorCallback, i;
+
+t.step(function () {
+    packageInformationArraySuccessCallback = t.step_func(function (informationArray) {
+        assert_unreached("Success callback invoked");
+    });
+
+    conversionTable = getTypeConversionExceptions("functionObject", true);
+
+    for(i = 0; i < conversionTable.length; i++) {
+        errorCallback  = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+
+        assert_throws({name: exceptionName},
+            function () {
+                tizen.package.getPackagesInfo(packageInformationArraySuccessCallback, errorCallback);
+            }, exceptionName + " should be thrown - given incorrect errorCallback: " + errorCallback + ".");
+    }
+    t.done();
+});
+
+}
+
+function PackageManager_getPackagesInfo_errorCallback_invalid_cb() {
+//==== TEST: PackageManager_getPackagesInfo_errorCallback_invalid_cb
+//==== LABEL Check if getPackagesInfo throws exception when errorCallback is invalid
+//==== PRIORITY: P2
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Application:Package:PackageManager:getPackagesInfo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== TEST_CRITERIA MTCB
+setup({timeout: 30000});
+
+var t = async_test('PackageManager_getPackagesInfo_errorCallback_invalid_cb', {timeout: 30000}), exceptionName = "TypeMismatchError",
+    invalidCallback, packageInformationArraySuccessCallback;
+
+t.step(function () {
+    packageInformationArraySuccessCallback = t.step_func(function (informationArray) {
+        assert_unreached("Success callback invoked");
+    });
+
+    invalidCallback = {
+        onerror: t.step_func(function (error) {
+            assert_unreached("Invalid error callback invoked");
+        })
+    };
+
+    assert_throws({name: exceptionName},
+        function () {
+            tizen.package.getPackagesInfo(packageInformationArraySuccessCallback, invalidCallback);
+        }, exceptionName + " should be thrown - given incorrect error callback - object.");
+    t.done();
+});
+
+}
+
+function PackageManager_getPackagesInfo_exist() {
+//==== TEST: PackageManager_getPackagesInfo_exist
+//==== LABEL Check if method getPackagesInfo of PackageManager exists
+//==== SPEC Tizen Web API:Application:Package:PackageManager:getPackagesInfo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== TEST_CRITERIA ME
+test(function () {
+    assert_true("getPackagesInfo" in tizen.package, "No getPackagesInfo method in tizen.package");
+    check_method_exists(tizen.package, "getPackagesInfo");
+}, 'PackageManager_getPackagesInfo_exist');
+
+}
+
+function PackageManager_getPackagesInfo_missarg() {
+//==== TEST: PackageManager_getPackagesInfo_missarg
+//==== LABEL Check if getPackagesInfo throws exception when non-optional argument is missing
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Application:Package:PackageManager:getPackagesInfo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== TEST_CRITERIA MMA
+setup({timeout: 30000});
+
+var t = async_test('PackageManager_getPackagesInfo_missarg', {timeout: 30000}),
+    exceptionName = "TypeMismatchError";
+
+t.step(function () {
+    assert_throws({name: exceptionName},
+        function () {
+            tizen.package.getPackagesInfo();
+        }, exceptionName + " should be thrown - missing successCallback.");
+
+    t.done();
+});
+
+}
+
+function PackageManager_getPackagesInfo_successCallback_TypeMismatch() {
+//==== TEST: PackageManager_getPackagesInfo_successCallback_TypeMismatch
+//==== LABEL Check if getPackagesInfo throws exception when successCallback is incorrect
+//==== PRIORITY: P2
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Application:Package:PackageManager:getPackagesInfo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== TEST_CRITERIA MC
+setup({timeout: 30000});
+
+var t = async_test('PackageManager_getPackagesInfo_successCallback_TypeMismatch', {timeout: 30000}), conversionTable,
+    packageInformationArraySuccessCallback, exceptionName, errorCallback, i;
+
+t.step(function () {
+    errorCallback = t.step_func(function (error) {
+        assert_unreached("getPackagesInfo() error callback: name:" + error.name + ", msg:" + error.message);
+    });
+
+    conversionTable = getTypeConversionExceptions("functionObject", false);
+
+    for(i = 0; i < conversionTable.length; i++) {
+        packageInformationArraySuccessCallback  = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+
+        assert_throws({name: exceptionName},
+            function () {
+                tizen.package.getPackagesInfo(packageInformationArraySuccessCallback, errorCallback);
+            }, exceptionName + " should be thrown - given incorrect successCallback: " + packageInformationArraySuccessCallback + ".");
+    }
+    t.done();
+});
+
+}
+
+function PackageManager_getPackagesInfo_successCallback_invalid_cb() {
+//==== TEST: PackageManager_getPackagesInfo_successCallback_invalid_cb
+//==== LABEL Check if getPackagesInfo throws exception when successCallback is invalid
+//==== PRIORITY: P2
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Application:Package:PackageManager:getPackagesInfo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== TEST_CRITERIA MTCB
+setup({timeout: 30000});
+
+var t = async_test('PackageManager_getPackagesInfo_successCallback_invalid_cb', {timeout: 30000}), exceptionName = "TypeMismatchError",
+    errorCallback, invalidCallback;
+
+t.step(function () {
+    invalidCallback = {
+        onsuccess: t.step_func(function (informationArray) {
+            assert_unreached("Invalid success callback invoked");
+        })
+    };
+
+    errorCallback = t.step_func(function (error) {
+        assert_unreached("ErrorCallback invoked: " + error.name + ": " + error.message);
+    });
+
+    assert_throws({name: exceptionName},
+        function () {
+            tizen.package.getPackagesInfo(invalidCallback, errorCallback);
+        }, exceptionName + " should be thrown - given incorrect successCallback - object.");
+    t.done();
+});
+
+}
+
+function PackageManager_getPackagesInfo_with_errorCallback() {
+//==== TEST: PackageManager_getPackagesInfo_with_errorCallback
+//==== LABEL Check if method getPackagesInfo of PackageManager works properly with errorCallback
+//==== SPEC Tizen Web API:Application:Package:PackageManager:getPackagesInfo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== ONLOAD_DELAY 90
+//==== TEST_CRITERIA MOA
+setup({timeout: 90000});
+
+var t = async_test('PackageManager_getPackagesInfo_with_errorCallback', {timeout: 90000}),
+    packageInformationArraySuccessCallback, errorCallback;
+
+t.step(function () {
+    packageInformationArraySuccessCallback = t.step_func(function (informationArray) {
+
+        assert_true(Array.isArray(informationArray), "informationArray is not an array.");
+        assert_greater_than(informationArray.length, 0, "Incorrect length of informationArray.");
+
+        t.done();
+    });
+
+    errorCallback = t.step_func(function (error) {
+        assert_unreached("ErrorCallback invoked. Exception name:" + error.name + ", message: " + error.message);
+    });
+
+    tizen.package.getPackagesInfo(packageInformationArraySuccessCallback, errorCallback);
+});
+
+}
+
+function PackageManager_in_tizen() {
+//==== TEST: PackageManager_in_tizen
+//==== PRIORITY P3
+//==== LABEL Check if package exists in tizen
+//==== SPEC Tizen Web API:Application:Package:PackageManager:PackageManager U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== TEST_CRITERIA OBME
+test(function () {
+    assert_true("package" in tizen, "No package in tizen.");
+    check_readonly(tizen, "package", tizen.package, "object", "dummyValue");
+}, 'PackageManager_in_tizen');
+
+}
+
+function PackageManager_install_exist() {
+//==== TEST: PackageManager_install_exist
+//==== LABEL Check if method install of PackageManager exists
+//==== SPEC Tizen Web API:Application:Package:PackageManager:install M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== TEST_CRITERIA ME
+test(function () {
+    assert_true("install" in tizen.package, "No install method in tizen.package");
+    check_method_exists(tizen.package, "install");
+}, 'PackageManager_install_exist');
+
+}
+
+function PackageManager_notexist() {
+//==== TEST: PackageManager_notexist
+//==== PRIORITY P3
+//==== LABEL Check if interface PackageManager exists, it should not
+//==== SPEC Tizen Web API:Application:Package:PackageManager:PackageManager U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== TEST_CRITERIA NIO
+test(function () {
+    check_no_interface_object("PackageManager");
+}, 'PackageManager_notexist');
+
+}
+
+function PackageManager_setPackageInfoEventListener_exist() {
+//==== TEST: PackageManager_setPackageInfoEventListener_exist
+//==== LABEL Check if method setPackageInfoEventListener of PackageManager exists
+//==== SPEC Tizen Web API:Application:Package:PackageManager:setPackageInfoEventListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== TEST_CRITERIA ME
+test(function () {
+    assert_true("setPackageInfoEventListener" in tizen.package, "No setPackageInfoEventListener method in tizen.package");
+    check_method_exists(tizen.package, "setPackageInfoEventListener");
+}, 'PackageManager_setPackageInfoEventListener_exist');
+
+}
+
+function PackageManager_uninstall_exist() {
+//==== TEST: PackageManager_uninstall_exist
+//==== LABEL Check if method uninstall of PackageManager exists
+//==== SPEC Tizen Web API:Application:Package:PackageManager:uninstall M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== TEST_CRITERIA ME
+test(function () {
+    assert_true("uninstall" in tizen.package, "No uninstall method in tizen.package");
+    check_method_exists(tizen.package, "uninstall");
+}, 'PackageManager_uninstall_exist');
+
+}
+
+function PackageManager_unsetPackageInfoEventListener_exist() {
+//==== TEST: PackageManager_unsetPackageInfoEventListener_exist
+//==== LABEL Check if method unsetPackageInfoEventListener of PackageManager exists
+//==== SPEC Tizen Web API:Application:Package:PackageManager:unsetPackageInfoEventListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== TEST_CRITERIA ME
+test(function () {
+    assert_true("unsetPackageInfoEventListener" in tizen.package, "No unsetPackageInfoEventListener method in tizen.package");
+    check_method_exists(tizen.package, "unsetPackageInfoEventListener");
+}, 'PackageManager_unsetPackageInfoEventListener_exist');
+
+}
+
+function PackageManager_unsetPackageInfoEventListener_extra_argument() {
+//==== TEST: PackageManager_unsetPackageInfoEventListener_extra_argument
+//==== LABEL Check if method unsetPackageInfoEventListener of PackageManager accepts extra argument
+//==== SPEC Tizen Web API:Application:Package:PackageManager:unsetPackageInfoEventListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== TEST_CRITERIA MNAEX
+test(function () {
+    checkExtraArgument(tizen.package, "unsetPackageInfoEventListener");
+}, 'PackageManager_unsetPackageInfoEventListener_extra_argument');
+
+}
+
+function PackageManager_setPackageInfoEventListener_eventCallback_TypeMismatch() {
+//==== TEST: PackageManager_setPackageInfoEventListener_eventCallback_TypeMismatch
+//==== LABEL Check if setPackageInfoEventListener throws exception when successCallback is incorrect
+//==== PRIORITY: P2
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Application:Package:PackageManager:setPackageInfoEventListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== TEST_CRITERIA MC
+setup({timeout: 30000});
+
+var t = async_test('PackageManager_setPackageInfoEventListener_eventCallback_TypeMismatch', {timeout: 30000}), conversionTable,
+    packageInformationEventCallback, exceptionName, i;
+
+t.step(function () {
+    conversionTable = getTypeConversionExceptions("object", false);
+
+    for(i = 0; i < conversionTable.length; i++) {
+        packageInformationEventCallback  = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+
+        assert_throws({name: exceptionName},
+            function () {
+                tizen.package.setPackageInfoEventListener(packageInformationEventCallback);
+            }, exceptionName + " should be thrown - given incorrect listener: " + packageInformationEventCallback + ".");
+    }
+    t.done();
+});
+
+}
+
+function PackageManager_setPackageInfoEventListener_eventCallback_invalid_cb() {
+//==== TEST: PackageManager_setPackageInfoEventListener_eventCallback_invalid_cb
+//==== LABEL Check if setPackageInfoEventListener throws exception when successCallback is invalid
+//==== PRIORITY: P2
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Application:Package:PackageManager:setPackageInfoEventListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== TEST_CRITERIA MTL
+setup({timeout: 30000});
+
+var t = async_test('PackageManager_setPackageInfoEventListener_eventCallback_invalid_cb', {timeout: 30000}), exceptionName,
+    incorrectListeners, i, packageInformationEventCallback;
+
+t.step(function () {
+    incorrectListeners = getListenerConversionExceptions(["oninstalled", "onupdated", "onuninstalled"]);
+    for(i = 0; i < incorrectListeners.length; i++) {
+        packageInformationEventCallback  = incorrectListeners[i][0];
+        exceptionName = incorrectListeners[i][1];
+        assert_throws({name: exceptionName},
+            function () {
+                tizen.package.setPackageInfoEventListener(packageInformationEventCallback);
+            }, exceptionName + " should be thrown - given incorrect successCallback.");
+    }
+
+    t.done();
+});
+
+}
+
+function PackageManager_setPackageInfoEventListener_misarg() {
+//==== TEST: PackageManager_setPackageInfoEventListener_misarg
+//==== LABEL Check if setPackageInfoEventListener throws exception when successCallback is missing
+//==== SPEC Tizen Web API:Application:Package:PackageManager:setPackageInfoEventListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== TEST_CRITERIA MMA
+test(function () {
+    var exceptionName = "TypeMismatchError";
+
+    assert_throws({name: exceptionName},
+        function () {
+            tizen.package.setPackageInfoEventListener();
+        }, exceptionName + " should be thrown - not given any argument.");
+}, 'PackageManager_setPackageInfoEventListener_misarg');
+
+}
+
+function PackageProgressCallback_notexist() {
+//==== TEST: PackageProgressCallback_notexist
+//==== PRIORITY P3
+//==== LABEL Check if interface PackageProgressCallback exists, it should not
+//==== SPEC Tizen Web API:Application:Package:PackageProgressCallback:PackageProgressCallback U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== TEST_CRITERIA CBNIO
+test(function () {
+    check_no_interface_object("PackageProgressCallback");
+}, 'PackageProgressCallback_notexist');
+
+}
+
+function PackageManager_setPackageInfoEventListener() {
+//==== TEST: PackageManager_setPackageInfoEventListener
+//==== LABEL Check if method setPackageInfoEventListener of PackageManager returns properly value
+//==== SPEC Tizen Web API:Application:Package:PackageManager:setPackageInfoEventListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== TEST_CRITERIA MMINA MR
+test(function () {
+    var returnedValue = null;
+    try {
+        returnedValue = tizen.package.setPackageInfoEventListener({});
+        assert_equals(returnedValue, undefined, "Incorrect returned value from setPackageInfoEventListener method");
+    } finally {
+        tizen.package.unsetPackageInfoEventListener();
+    }
+}, 'PackageManager_setPackageInfoEventListener');
+
+}
+
+function PackageManager_install_missarg() {
+//==== TEST: PackageManager_install_missarg
+//==== LABEL Check with missing non-optional argument - PackageManager.install
+//==== SPEC Tizen Web API:Application:Package:PackageManager:install M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== TEST_CRITERIA MMA
+test(function () {
+    var exceptionName = "TypeMismatchError";
+    assert_throws({name: exceptionName}, function () {
+        tizen.package.install(TCT_PACKAGE_MANAGER_TEST_PACKAGE_PATH);
+    }, exceptionName + " should be thrown - missing argument.");
+}, 'PackageManager_install_missarg');
+
+}
+
+function PackageManager_uninstall_missarg() {
+//==== TEST: PackageManager_uninstall_missarg
+//==== LABEL Check with missing non-optional argument - PackageManager.uninstall
+//==== SPEC Tizen Web API:Application:Package:PackageManager:uninstall M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== TEST_CRITERIA MMA
+test(function () {
+    var exceptionName = "TypeMismatchError";
+    assert_throws({name: exceptionName}, function () {
+        tizen.package.uninstall(TCT_PACKAGE_MANAGER_TEST_PACKAGE_PATH);
+    }, exceptionName + " should be thrown - missing argument.");
+}, 'PackageManager_uninstall_missarg');
+
+}
+
+function PackageManager_install_errorCallback_TypeMismatch() {
+//==== TEST: PackageManager_install_errorCallback_TypeMismatch
+//==== LABEL Check argument errorCallback conversions exception - install
+//==== PRIORITY: P2
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Application:Package:PackageManager:install M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== TEST_CRITERIA MC
+setup({timeout: 30000});
+
+var t = async_test('PackageManager_install_errorCallback_TypeMismatch', {timeout: 30000}), exceptionName,
+    incorrectCallback, installProgressCallback, conversionTable, i;
+
+t.step(function () {
+    installProgressCallback = {
+        onprogress: t.step_func(function (packageId, progress) {
+            assert_unreached("onprogress invoked.");
+        }),
+        oncomplete: t.step_func(function (packageId) {
+            assert_unreached("oncomplete invoked, ");
+        })
+    };
+
+    conversionTable = getTypeConversionExceptions("functionObject", true);
+    for(i = 0; i < conversionTable.length; i++) {
+        incorrectCallback  = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+
+        assert_throws({name: exceptionName},
+        function () {
+            tizen.package.install(TCT_PACKAGE_MANAGER_TEST_PACKAGE_PATH, installProgressCallback, incorrectCallback);
+        }, exceptionName + " should be thrown - given incorrect errorCallback: " + incorrectCallback + ".");
+    }
+    t.done();
+});
+
+}
+
+function PackageManager_install_errorCallback_invalid_cb() {
+//==== TEST: PackageManager_install_errorCallback_invalid_cb
+//==== LABEL Check argument errorCallback validation - install
+//==== PRIORITY: P2
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Application:Package:PackageManager:install M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== TEST_CRITERIA MTCB
+setup({timeout: 30000});
+
+var t = async_test('PackageManager_install_errorCallback_invalid_cb', {timeout: 30000}), exceptionName = "TypeMismatchError",
+    invalidCallback, installProgressCallback;
+
+t.step(function () {
+    installProgressCallback = {
+        onprogress: t.step_func(function (packageId, progress) {
+            assert_unreached("onprogress invoked.");
+        }),
+        oncomplete: t.step_func(function (packageId) {
+            assert_unreached("oncomplete invoked, ");
+        })
+    };
+
+    invalidCallback = {
+        onerror: t.step_func(function (error) {
+            assert_unreached("Invalid error callback invoked");
+        })
+    };
+
+    assert_throws({name: exceptionName},
+        function () {
+            tizen.package.install(TCT_PACKAGE_MANAGER_TEST_PACKAGE_PATH, installProgressCallback, invalidCallback);
+        }, exceptionName + " should be thrown - given incorrect errorCallback - object.");
+    t.done();
+});
+
+}
+
+function PackageManager_install_progressCallback_TypeMismatch() {
+//==== TEST: PackageManager_install_progressCallback_TypeMismatch
+//==== LABEL Check argument progressCallback conversions exception - install
+//==== PRIORITY: P2
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Application:Package:PackageManager:install M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== TEST_CRITERIA MC
+setup({timeout: 30000});
+
+var t = async_test('PackageManager_install_progressCallback_TypeMismatch', {timeout: 30000}), installProgressCallback, installError,
+    exceptionName, i, conversionTable;
+
+t.step(function () {
+    installError = t.step_func(function (error) {
+        assert_unreached("install() error callback: name:" + error.name + ", msg:" + error.message);
+    });
+
+    conversionTable = getTypeConversionExceptions("object", false);
+
+    for(i = 0; i < conversionTable.length; i++) {
+        installProgressCallback  = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+
+        assert_throws({name: exceptionName},
+            function () {
+                tizen.package.install(TCT_PACKAGE_MANAGER_TEST_PACKAGE_PATH, installProgressCallback, installError);
+            }, exceptionName + " should be thrown - given incorrect listener: " + installProgressCallback + ".");
+    }
+    t.done();
+});
+
+}
+
+function PackageManager_install_progressCallback_invalid_cb() {
+//==== TEST: PackageManager_install_progressCallback_invalid_cb
+//==== LABEL Check argument progressCallback validation - install
+//==== PRIORITY: P2
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Application:Package:PackageManager:install M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== TEST_CRITERIA MTL
+setup({timeout: 30000});
+
+var t = async_test('PackageManager_install_progressCallback_invalid_cb', {timeout: 30000}), exceptionName,
+    incorrectListeners, i, installError, installProgressCallback;
+
+t.step(function () {
+    installError = t.step_func(function (error) {
+        assert_unreached("install() error callback: name:" + error.name + ", msg:" + error.message);
+    });
+
+    incorrectListeners = getListenerConversionExceptions(["onprogress", "oncomplete"]);
+    for(i = 0; i < incorrectListeners.length; i++) {
+        installProgressCallback  = incorrectListeners[i][0];
+        exceptionName = incorrectListeners[i][1];
+        assert_throws({name: exceptionName},
+            function () {
+                tizen.package.install(TCT_PACKAGE_MANAGER_TEST_PACKAGE_PATH, installProgressCallback, installError);
+            }, exceptionName + " should be thrown - given incorrect listener.");
+    }
+
+    t.done();
+});
+
+}
+
+function PackageManager_uninstall_errorCallback_TypeMismatch() {
+//==== TEST: PackageManager_uninstall_errorCallback_TypeMismatch
+//==== LABEL Check argument errorCallback conversions exception - uninstall
+//==== PRIORITY: P2
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Application:Package:PackageManager:uninstall M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== TEST_CRITERIA MC
+setup({timeout: 30000});
+
+var t = async_test('PackageManager_uninstall_errorCallback_TypeMismatch', {timeout: 30000}),
+    exceptionName, incorrectCallback, uninstallProgressCallback, conversionTable, i;
+
+t.step(function () {
+    uninstallProgressCallback = {
+        onprogress: t.step_func(function (packageId, progress) {
+            assert_unreached("onprogress invoked.");
+        }),
+        oncomplete: t.step_func(function (packageId) {
+            assert_unreached("oncomplete invoked, ");
+        })
+    };
+
+    conversionTable = getTypeConversionExceptions("functionObject", true);
+    for(i = 0; i < conversionTable.length; i++) {
+        incorrectCallback  = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+
+        assert_throws({name: exceptionName},
+        function () {
+            tizen.package.uninstall(TCT_PACKAGE_MANAGER_TEST_PACKAGE_PATH, uninstallProgressCallback, incorrectCallback);
+        }, exceptionName + " should be thrown - given incorrect errorCallback: " + incorrectCallback + ".");
+    }
+    t.done();
+});
+
+}
+
+function PackageManager_uninstall_errorCallback_invalid_cb() {
+//==== TEST: PackageManager_uninstall_errorCallback_invalid_cb
+//==== LABEL Check argument errorCallback validation - uninstall
+//==== PRIORITY: P2
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Application:Package:PackageManager:uninstall M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== TEST_CRITERIA MTCB
+setup({timeout: 30000});
+
+var t = async_test('PackageManager_uninstall_errorCallback_invalid_cb', {timeout: 30000}),
+    exceptionName = "TypeMismatchError", invalidCallback, uninstallProgressCallback;
+
+t.step(function () {
+    uninstallProgressCallback = {
+        onprogress: t.step_func(function (packageId, progress) {
+            assert_unreached("onprogress invoked.");
+        }),
+        oncomplete: t.step_func(function (packageId) {
+            assert_unreached("oncomplete invoked.");
+        })
+    };
+
+    invalidCallback = {
+        onerror: t.step_func(function (error) {
+            assert_unreached("Invalid error callback invoked");
+        })
+    };
+
+    assert_throws({name: exceptionName},
+        function () {
+            tizen.package.uninstall(TCT_PACKAGE_MANAGER_TEST_PACKAGE_PATH, uninstallProgressCallback, invalidCallback);
+        }, exceptionName + " should be thrown - given incorrect errorCallback - object.");
+    t.done();
+});
+
+}
+
+function PackageManager_uninstall_progressCallback_TypeMismatch() {
+//==== TEST: PackageManager_uninstall_progressCallback_TypeMismatch
+//==== LABEL Check argument progressCallback conversions exception - uninstall
+//==== PRIORITY: P2
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Application:Package:PackageManager:uninstall M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== TEST_CRITERIA MC
+setup({timeout: 30000});
+
+var t = async_test('PackageManager_uninstall_progressCallback_TypeMismatch', {timeout: 30000}), uninstallProgressCallback, uninstallError,
+    exceptionName, i, conversionTable;
+
+t.step(function () {
+    uninstallError = t.step_func(function (error) {
+        assert_unreached("uninstall() error callback: name:" + error.name + ", msg:" + error.message);
+    });
+
+    conversionTable = getTypeConversionExceptions("object", false);
+
+    for(i = 0; i < conversionTable.length; i++) {
+        uninstallProgressCallback  = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+
+        assert_throws({name: exceptionName},
+            function () {
+                tizen.package.uninstall(TCT_PACKAGE_MANAGER_TEST_PACKAGE_PATH, uninstallProgressCallback, uninstallError);
+            }, exceptionName + " should be thrown - given incorrect listener: " + uninstallProgressCallback + ".");
+    }
+    t.done();
+});
+
+}
+
+function PackageManager_uninstall_progressCallback_invalid_cb() {
+//==== TEST: PackageManager_uninstall_progressCallback_invalid_cb
+//==== LABEL Check argument progressCallback validation - uninstall
+//==== PRIORITY: P2
+//==== ONLOAD_DELAY 30
+//==== SPEC Tizen Web API:Application:Package:PackageManager:uninstall M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== TEST_CRITERIA MTL
+setup({timeout: 30000});
+
+var t = async_test('PackageManager_uninstall_progressCallback_invalid_cb', {timeout: 30000}), exceptionName,
+    incorrectListeners, i, uninstallError, uninstallProgressCallback;
+
+t.step(function () {
+    uninstallError = t.step_func(function (error) {
+        assert_unreached("uninstall() error callback: name:" + error.name + ", msg:" + error.message);
+    });
+
+    incorrectListeners = getListenerConversionExceptions(["onprogress", "oncomplete"]);
+    for(i = 0; i < incorrectListeners.length; i++) {
+        uninstallProgressCallback  = incorrectListeners[i][0];
+        exceptionName = incorrectListeners[i][1];
+        assert_throws({name: exceptionName},
+            function () {
+                tizen.package.uninstall(TCT_PACKAGE_MANAGER_TEST_PACKAGE_PATH, uninstallProgressCallback, uninstallError);
+            }, exceptionName + " should be thrown - given incorrect listener.");
+    }
+
+    t.done();
+});
+
+}
+
+function PackageManager_install_errorCallback_invoked() {
+//==== TEST: PackageManager_install_errorCallback_invoked
+//==== LABEL Check exception in error callback of install method
+//==== SPEC Tizen Web API:Application:Package:PackageManager:install M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MERRCB
+setup({timeout: 30000});
+
+var t = async_test('PackageManager_install_errorCallback_invoked', {timeout: 30000}), installProgressCallback, installError;
+
+t.step(function () {
+    installProgressCallback = {
+        onprogress: t.step_func(function (packageId, progress) {
+            assert_unreached("onprogress invoked, packageId = " + packageId + ", progress = " + progress);
+        }),
+        oncomplete: t.step_func(function (packageId) {
+            assert_unreached("oncomplete invoked, packageId = " + packageId);
+        })
+    };
+
+    installError = t.step_func(function (error) {
+        assert_equals(error.code, 8, "Incorrect error code.");
+        assert_equals(error.name, "NotFoundError", "Incorrect error name.");
+        assert_type(error.message, "string", "Error message is not a string");
+        assert_not_equals(error.message, "", "Error message is empty");
+
+        t.done();
+    });
+
+    tizen.package.install(NOT_EXISTING_PACKAGE_ID, installProgressCallback, installError);
+});
+
+}
+
+function PackageManager_uninstall_errorCallback_invoked() {
+//==== TEST: PackageManager_uninstall_errorCallback_invoked
+//==== LABEL Check exception in error callback of uninstall method
+//==== SPEC Tizen Web API:Application:Package:PackageManager:uninstall M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MERRCB
+setup({timeout: 30000});
+
+var t = async_test('PackageManager_uninstall_errorCallback_invoked', {timeout: 30000}),
+    uninstallProgressCallback, uninstallError;
+
+t.step(function () {
+    uninstallProgressCallback = {
+        onprogress: t.step_func(function (packageId, progress) {
+            assert_unreached("onprogress invoked, packageId = " + packageId + ", progress = " + progress);
+        }),
+        oncomplete: t.step_func(function (packageId) {
+            assert_unreached("oncomplete invoked, packageId = " + packageId);
+        })
+    };
+
+    uninstallError = t.step_func(function (error) {
+        assert_equals(error.code, 8, "Incorrect error code.");
+        assert_equals(error.name, "NotFoundError", "Incorrect error name.");
+        assert_type(error.message, "string", "Error message is not a string");
+        assert_not_equals(error.message, "", "Error message is empty");
+
+        t.done();
+    });
+
+    tizen.package.uninstall(NOT_EXISTING_PACKAGE_ID, uninstallProgressCallback, uninstallError);
+});
+
+}
+
+function PackageInformationEventCallback_oninstalled() {
+//==== TEST: PackageInformationEventCallback_oninstalled
+//==== LABEL Check if PackageInformationEventCallback.oninstalled works properly
+//==== SPEC Tizen Web API:Application:Package:PackageInformationEventCallback:oninstalled M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== EXECUTION_TYPE manual
+//==== PRE Make sure that TCTPackageManagerTest1.1.1.wgt application is not installed.
+//==== STEP Run the test
+//==== EXPECT Pass.
+//==== TEST_CRITERIA CBT CBOA
+setup({timeout: 90000});
+
+var packageInformationEventCallback, installation, installError,
+    t = async_test('PackageInformationEventCallback_oninstalled',  {timeout: 90000});
+
+t.step(function () {
+    packageInformationEventCallback = {
+        oninstalled: t.step_func(function (packageInformation) {
+            try {
+                assert_equals(packageInformation.id, TCT_PACKAGE_MANAGER_TEST_PACKAGE_ID, "PackageInformation.id is incorrect.");
+                assert_equals(packageInformation.name, TCT_PACKAGE_MANAGER_TEST_PACKAGE_NAME, "PackageInformation.name is incorrect.");
+
+                assert_type(packageInformation.iconPath, "string", "Incorrect type for PackageInformation.iconPath attribute.");
+                assert_not_equals(packageInformation.iconPath, "", "PackageInformation.iconPath is an empty string.");
+
+                assert_equals(packageInformation.version, TCT_PACKAGE_MANAGER_TEST_PACKAGE_VERSION_1, "PackageInformation.version is incorrect.");
+
+                assert_type(packageInformation.totalSize, "long", "Incorrect type of PackageInformation.totalSize");
+                assert_type(packageInformation.dataSize, "long", "Incorrect type of PackageInformation.dataSize");
+                assert_greater_than_equal(packageInformation.totalSize, packageInformation.dataSize,
+                    "PackageInformation.dataSize is bigger than packageInformation.totalSize.");
+
+                assert_true(packageInformation.lastModified instanceof Date,
+                    "PackageInformation.lastModified is not a Date");
+                assert_true(packageInformation.lastModified < new Date(),
+                    "PackageInformation.lastModified is from present ot future.");
+
+                assert_equals(packageInformation.author, TCT_PACKAGE_MANAGER_TEST_PACKAGE_AUTHOR, "PackageInformation.author is incorrect.");
+
+                assert_array_equals(packageInformation.appIds, [TCT_PACKAGE_MANAGER_TEST_PACKAGE_APP_ID],
+                    "packageInformation.appIds is incorrect");
+
+                assert_equals(packageInformation.description, TCT_PACKAGE_MANAGER_TEST_PACKAGE_DESCRIPTION,
+                    "PackageInformation.description is incorect.");
+            } finally {
+                tizen.package.unsetPackageInfoEventListener();
+            }
+            t.done();
+        }),
+        onupdated: t.step_func(function (packageInformation) {
+            tizen.package.unsetPackageInfoEventListener();
+            assert_unreached("onupdated invoked.");
+        }),
+        onuninstalled: t.step_func(function (packageId) {
+            tizen.package.unsetPackageInfoEventListener();
+            assert_unreached("onuninstalled invoked.");
+        })
+    };
+    installation = {
+        oncomplete : function(packageId){
+            //do nothing here
+        }
+    };
+    installError = t.step_func(function (error) {
+        assert_unreached("install() error callback: name:" + error.name + ", msg:" + error.message);
+    });
+    tizen.package.unsetPackageInfoEventListener();
+    tizen.package.setPackageInfoEventListener(packageInformationEventCallback);
+
+    tizen.package.install(TCT_PACKAGE_MANAGER_TEST_PACKAGE_PATH, installation, installError);
+});
+
+}
+
+function PackageInformationEventCallback_onupdated() {
+//==== TEST: PackageInformationEventCallback_onupdated
+//==== LABEL Check if PackageInformationEventCallback.onupdated works properly
+//==== SPEC Tizen Web API:Application:Package:PackageInformationEventCallback:onupdated M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== EXECUTION_TYPE manual
+//==== PRE Make sure that TCTPackageManagerTest1.1.1.wgt application is installed.
+//==== STEP Run the test
+//==== EXPECT Pass.
+//==== TEST_CRITERIA CBT CBOA
+setup({timeout: 90000});
+
+var packageInformationEventCallback, installation, installError,
+    t = async_test('PackageInformationEventCallback_onupdated',  {timeout: 90000});
+
+t.step(function () {
+    packageInformationEventCallback = {
+        oninstalled: t.step_func(function (packageInformation) {
+            tizen.package.unsetPackageInfoEventListener();
+            assert_unreached("oninstalled invoked.");
+        }),
+        onupdated: t.step_func(function (packageInformation) {
+            try {
+                assert_equals(packageInformation.id, TCT_PACKAGE_MANAGER_TEST_PACKAGE_ID, "PackageInformation.id is incorrect.");
+                assert_equals(packageInformation.name, TCT_PACKAGE_MANAGER_TEST_PACKAGE_NAME, "PackageInformation.name is incorrect.");
+
+                assert_type(packageInformation.iconPath, "string", "Incorrect type for PackageInformation.iconPath attribute.");
+                assert_not_equals(packageInformation.iconPath, "", "PackageInformation.iconPath is an empty string.");
+
+                assert_equals(packageInformation.version, TCT_PACKAGE_MANAGER_TEST_PACKAGE_VERSION_2, "PackageInformation.version is incorrect.");
+
+                assert_type(packageInformation.totalSize, "long", "Incorrect type of PackageInformation.totalSize");
+                assert_type(packageInformation.dataSize, "long", "Incorrect type of PackageInformation.dataSize");
+                assert_greater_than_equal(packageInformation.totalSize, packageInformation.dataSize,
+                    "PackageInformation.dataSize is bigger than packageInformation.totalSize.");
+
+                assert_true(packageInformation.lastModified instanceof Date,
+                    "PackageInformation.lastModified is not a Date");
+                assert_true(packageInformation.lastModified < new Date(),
+                    "PackageInformation.lastModified is from present ot future.");
+
+                assert_equals(packageInformation.author, TCT_PACKAGE_MANAGER_TEST_PACKAGE_AUTHOR, "PackageInformation.author is incorrect.");
+
+                assert_array_equals(packageInformation.appIds, [TCT_PACKAGE_MANAGER_TEST_PACKAGE_APP_ID],
+                    "packageInformation.appIds is incorrect");
+
+                assert_equals(packageInformation.description, TCT_PACKAGE_MANAGER_TEST_PACKAGE_DESCRIPTION,
+                    "PackageInformation.description is incorect.");
+            } finally {
+                tizen.package.unsetPackageInfoEventListener();
+            }
+            t.done();
+        }),
+        onuninstalled: t.step_func(function (packageId) {
+            tizen.package.unsetPackageInfoEventListener();
+            assert_unreached("onuninstalled invoked.");
+        })
+    };
+    installation = {
+        oncomplete : function(packageId){
+            //do nothing here
+        }
+    };
+    installError = t.step_func(function (error) {
+        assert_unreached("install() error callback: name:" + error.name + ", msg:" + error.message);
+    });
+    tizen.package.unsetPackageInfoEventListener();
+    tizen.package.setPackageInfoEventListener(packageInformationEventCallback);
+
+    tizen.package.install(TCT_PACKAGE_MANAGER_TEST_PACKAGE_PATH_2, installation, installError);
+});
+
+}
+
+function PackageInformationEventCallback_onuninstalled() {
+//==== TEST: PackageInformationEventCallback_onuninstalled
+//==== LABEL Check if PackageInformationEventCallback.onuninstalled works properly
+//==== SPEC Tizen Web API:Application:Package:PackageInformationEventCallback:onuninstalled M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== EXECUTION_TYPE manual
+//==== PRE Make sure that TCTPackageManagerTest1.1.1.wgt application is installed (You can install it from My files app (Phone/Others directory)).
+//==== STEP Run the test and uninstall TCTPackageManagerTest1.1.1.wgt application.
+//==== EXPECT Pass.
+//==== TEST_CRITERIA CBT CBOA
+setup({timeout: 90000});
+
+var packageInformationEventCallback, uninstallation, uninstallError,
+    t = async_test('PackageInformationEventCallback_onuninstalled',  {timeout: 90000});
+
+t.step(function () {
+    packageInformationEventCallback = {
+        oninstalled: t.step_func(function (packageInformation) {
+            tizen.package.unsetPackageInfoEventListener();
+            assert_unreached("oninstalled invoked.");
+        }),
+        onupdated: t.step_func(function (packageInformation) {
+            tizen.package.unsetPackageInfoEventListener();
+            assert_unreached("onupdated invoked.");
+        }),
+        onuninstalled: t.step_func(function (packageId) {
+            try {
+                assert_equals(packageId, TCT_PACKAGE_MANAGER_TEST_PACKAGE_ID, "PackageInformation.id is incorrect.");
+            } finally {
+                tizen.package.unsetPackageInfoEventListener();
+            }
+            t.done();
+        })
+    };
+    uninstallation = {
+        oncomplete : function(packageId){
+            //do nothing here
+        }
+    };
+    uninstallError = t.step_func(function (error) {
+        assert_unreached("uninstall() error callback: name:" + error.name + ", msg:" + error.message);
+    });
+    tizen.package.unsetPackageInfoEventListener();
+    tizen.package.setPackageInfoEventListener(packageInformationEventCallback);
+
+    tizen.package.uninstall(TCT_PACKAGE_MANAGER_TEST_PACKAGE_ID, uninstallation, uninstallError);
+});
+
+}
+
+function PackageManager_install() {
+//==== TEST: PackageManager_install
+//==== LABEL Check install method of package
+//==== SPEC Tizen Web API:Application:Package:PackageManager:install M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== EXECUTION_TYPE manual
+//==== PRE Make sure that TCTPackageManagerTest1.1.1.wgt application is NOT installed.
+//==== STEP Run the test.
+//==== EXPECT Pass.
+//==== TEST_CRITERIA MOA MR MAST
+setup({timeout: 90000});
+
+var t = async_test('PackageManager_install', {timeout: 90000}), wasInProgress = false, installProgressCallback, installError,
+    returnedValue = null, packageInformation;
+
+t.step(function () {
+    installProgressCallback = {
+        onprogress: t.step_func(function (packageId, progress) {
+            wasInProgress = true;
+        }),
+        oncomplete: t.step_func(function (packageId) {
+            assert_equals(returnedValue, undefined, "Incorrect returned value");
+
+            assert_true(wasInProgress, "onprogress callback was not invoked.");
+            assert_equals(packageId, TCT_PACKAGE_MANAGER_TEST_PACKAGE_ID, "Incorrect packageId.");
+
+            packageInformation = tizen.package.getPackageInfo(TCT_PACKAGE_MANAGER_TEST_PACKAGE_ID);
+            assert_equals(packageInformation.id, TCT_PACKAGE_MANAGER_TEST_PACKAGE_ID, "Not installed.");
+            t.done();
+        })
+    };
+
+    installError = t.step_func(function (error) {
+        assert_unreached("install() error callback: name:" + error.name + ", msg:" + error.message);
+    });
+
+    returnedValue = tizen.package.install(TCT_PACKAGE_MANAGER_TEST_PACKAGE_PATH, installProgressCallback, installError);
+});
+
+}
+
+function PackageManager_uninstall() {
+//==== TEST: PackageManager_uninstall
+//==== LABEL Check uninstall method of package
+//==== SPEC Tizen Web API:Application:Package:PackageManager:uninstall M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== EXECUTION_TYPE manual
+//==== PRE Make sure that TCTPackageManagerTest1.1.1.wgt application is installed (You can install it from My files app (Phone/Others directory)).
+//==== STEP Run the test.
+//==== EXPECT Pass.
+//==== TEST_CRITERIA MOA MR MAST
+setup({timeout: 90000});
+
+var t = async_test('PackageManager_uninstall', {timeout: 90000}), wasInProgress = false,
+    uninstallProgressCallback, uninstallError, returnedValue = null;
+
+t.step(function () {
+    uninstallProgressCallback = {
+        onprogress: t.step_func(function (packageId, progress) {
+            wasInProgress = true;
+        }),
+        oncomplete: t.step_func(function (packageId) {
+            assert_equals(returnedValue, undefined, "Incorrect returned value");
+
+            assert_true(wasInProgress, "onprogress callback was not invoked.");
+            assert_equals(packageId, TCT_PACKAGE_MANAGER_TEST_PACKAGE_ID, "Incorrect packageId.");
+
+            assert_throws(NOT_FOUND_EXCEPTION,
+                function () {
+                    tizen.package.getPackageInfo(TCT_PACKAGE_MANAGER_TEST_PACKAGE_ID);
+                }, "Package is still installed.");
+            t.done();
+        })
+    };
+
+    uninstallError = t.step_func(function (error) {
+        assert_unreached("uninstall() error callback: name:" + error.name + ", msg:" + error.message);
+    });
+
+    returnedValue = tizen.package.uninstall(TCT_PACKAGE_MANAGER_TEST_PACKAGE_ID, uninstallProgressCallback, uninstallError);
+});
+
+}
+
+function PackageManager_install_without_errorCallback() {
+//==== TEST: PackageManager_install_without_errorCallback
+//==== LABEL Check install method without errorCallback
+//==== SPEC Tizen Web API:Application:Package:PackageManager:install M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== EXECUTION_TYPE manual
+//==== PRE Make sure that TCTPackageManagerTest1.1.1.wgt application is NOT installed.
+//==== STEP Run the test.
+//==== EXPECT Pass.
+//==== TEST_CRITERIA MMINA MR MAST
+setup({timeout: 90000});
+
+var t = async_test('PackageManager_install_without_errorCallback', {timeout: 90000}), wasInProgress = false, installProgressCallback,
+    returnedValue = null, packageInformation;
+
+t.step(function () {
+    installProgressCallback = {
+        onprogress: t.step_func(function (packageId, progress) {
+            wasInProgress = true;
+        }),
+        oncomplete: t.step_func(function (packageId) {
+            assert_equals(returnedValue, undefined, "Incorrect returned value");
+
+            assert_true(wasInProgress, "onprogress callback was not invoked.");
+            assert_equals(packageId, TCT_PACKAGE_MANAGER_TEST_PACKAGE_ID, "Incorrect packageId.");
+
+            packageInformation = tizen.package.getPackageInfo(TCT_PACKAGE_MANAGER_TEST_PACKAGE_ID);
+            assert_equals(packageInformation.id, TCT_PACKAGE_MANAGER_TEST_PACKAGE_ID, "Not installed.");
+            t.done();
+        })
+    };
+
+    returnedValue = tizen.package.install(TCT_PACKAGE_MANAGER_TEST_PACKAGE_PATH, installProgressCallback);
+});
+
+}
+
+function PackageManager_uninstall_without_errorCallback() {
+//==== TEST: PackageManager_uninstall_without_errorCallback
+//==== LABEL Check uninstall method without errorCallback
+//==== SPEC Tizen Web API:Application:Package:PackageManager:uninstall M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== EXECUTION_TYPE manual
+//==== PRE Make sure that TCTPackageManagerTest1.1.1.wgt application is installed (You can install it from My files app (Phone/Others directory)).
+//==== STEP Run the test.
+//==== EXPECT Pass.
+//==== TEST_CRITERIA MMINA MR MAST
+setup({timeout: 90000});
+
+var t = async_test('PackageManager_uninstall_without_errorCallback', {timeout: 90000}), wasInProgress = false,
+    uninstallProgressCallback, returnedValue = null;
+
+t.step(function () {
+    uninstallProgressCallback = {
+        onprogress: t.step_func(function (packageId, progress) {
+            wasInProgress = true;
+        }),
+        oncomplete: t.step_func(function (packageId) {
+            assert_equals(returnedValue, undefined, "Incorrect returned value");
+
+            assert_true(wasInProgress, "onprogress callback was not invoked.");
+            assert_equals(packageId, TCT_PACKAGE_MANAGER_TEST_PACKAGE_ID, "Incorrect packageId.");
+
+            assert_throws(NOT_FOUND_EXCEPTION,
+                function () {
+                    tizen.package.getPackageInfo(TCT_PACKAGE_MANAGER_TEST_PACKAGE_ID);
+                }, "Package is still installed.");
+            t.done();
+        })
+    };
+
+    returnedValue = tizen.package.uninstall(TCT_PACKAGE_MANAGER_TEST_PACKAGE_ID, uninstallProgressCallback);
+});
+
+}
+
+function PackageProgressCallback_onprogress_install() {
+//==== TEST: PackageProgressCallback_onprogress_install
+//==== LABEL Check if PackageProgressCallback.onprogress - install
+//==== SPEC Tizen Web API:Application:Package:PackageProgressCallback:onprogress M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== EXECUTION_TYPE manual
+//==== PRE Make sure that TCTPackageManagerTest1.1.1.wgt application is NOT installed.
+//==== STEP Run the test.
+//==== EXPECT Pass.
+//==== TEST_CRITERIA CBT CBOA
+setup({timeout: 90000});
+
+var t = async_test('PackageProgressCallback_onprogress_install', {timeout: 90000}), wasInProgress = false,
+    installProgressCallback, installError;
+
+t.step(function () {
+    installProgressCallback = {
+        onprogress: t.step_func(function (packageId, progress) {
+            wasInProgress = true;
+            assert_equals(packageId, TCT_PACKAGE_MANAGER_TEST_PACKAGE_ID, "Incorrect packageId.");
+            assert_type(progress, "short" , "Incorrect type for progress.");
+            assert_greater_than_equal(progress, 0, "Progress is less than zero.");
+            assert_less_than_equal(progress, 100, "Progress is greater than 100.");
+        }),
+        oncomplete: t.step_func(function (packageId) {
+            assert_true(wasInProgress, "onprogress callback was not invoked.");
+            t.done();
+        })
+    };
+
+    installError = t.step_func(function (error) {
+        assert_unreached("install() error callback: name:" + error.name + ", msg:" + error.message);
+    });
+
+    tizen.package.install(TCT_PACKAGE_MANAGER_TEST_PACKAGE_PATH, installProgressCallback, installError);
+});
+
+}
+
+function PackageProgressCallback_onprogress_uninstall() {
+//==== TEST: PackageProgressCallback_onprogress_uninstall
+//==== LABEL Check if PackageProgressCallback.onprogress - uninstall
+//==== SPEC Tizen Web API:Application:Package:PackageProgressCallback:onprogress M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== EXECUTION_TYPE manual
+//==== PRE Make sure that TCTPackageManagerTest1.1.1.wgt application is installed (You can install it from My files app (Phone/Others directory)).
+//==== STEP Run the test.
+//==== EXPECT Pass.
+//==== TEST_CRITERIA CBT CBOA
+setup({timeout: 90000});
+
+var t = async_test('PackageProgressCallback_onprogress_uninstall', {timeout: 90000}), wasInProgress = false,
+    uninstallProgressCallback, uninstallError;
+
+t.step(function () {
+    uninstallProgressCallback = {
+        onprogress: t.step_func(function (packageId, progress) {
+            wasInProgress = true;
+            assert_equals(packageId, TCT_PACKAGE_MANAGER_TEST_PACKAGE_ID, "Incorrect packageId.");
+            assert_type(progress, "short" , "Incorrect type for progress.");
+            assert_greater_than_equal(progress, 0, "Progress is less than zero.");
+            assert_less_than_equal(progress, 100, "Progress is greater than 100.");
+        }),
+        oncomplete: t.step_func(function (packageId) {
+            assert_true(wasInProgress, "onprogress callback was not invoked.");
+            t.done();
+        })
+    };
+
+    uninstallError = t.step_func(function (error) {
+        assert_unreached("uninstall() error callback: name:" + error.name + ", msg:" + error.message);
+    });
+
+    tizen.package.uninstall(TCT_PACKAGE_MANAGER_TEST_PACKAGE_ID, uninstallProgressCallback, uninstallError);
+});
+
+}
+
+function PackageProgressCallback_oncomplete_install() {
+//==== TEST: PackageProgressCallback_oncomplete_install
+//==== LABEL Check if PackageProgressCallback.oncomplete - install
+//==== SPEC Tizen Web API:Application:Package:PackageProgressCallback:oncomplete M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== EXECUTION_TYPE manual
+//==== PRE Make sure that TCTPackageManagerTest1.1.1.wgt application is NOT installed.
+//==== STEP Run the test.
+//==== EXPECT Pass.
+//==== TEST_CRITERIA CBT CBOA
+setup({timeout: 90000});
+
+var t = async_test('PackageProgressCallback_oncomplete_install', {timeout: 90000}), installProgressCallback, installError;
+
+t.step(function () {
+    installProgressCallback = {
+        oncomplete: t.step_func(function (packageId) {
+            assert_equals(packageId, TCT_PACKAGE_MANAGER_TEST_PACKAGE_ID, "Incorrect packageId.");
+            t.done();
+        })
+    };
+
+    installError = t.step_func(function (error) {
+        assert_unreached("install() error callback: name:" + error.name + ", msg:" + error.message);
+    });
+
+    tizen.package.install(TCT_PACKAGE_MANAGER_TEST_PACKAGE_PATH, installProgressCallback, installError);
+});
+
+}
+
+function PackageProgressCallback_oncomplete_uninstall() {
+//==== TEST: PackageProgressCallback_oncomplete_uninstall
+//==== LABEL Check if PackageProgressCallback.oncomplete - uninstall
+//==== SPEC Tizen Web API:Application:Package:PackageProgressCallback:oncomplete M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== EXECUTION_TYPE manual
+//==== PRE Make sure that TCTPackageManagerTest1.1.1.wgt application is installed (You can install it from My files app (Phone/Others directory)).
+//==== STEP Run the test.
+//==== EXPECT Pass.
+//==== TEST_CRITERIA CBT CBOA
+setup({timeout: 90000});
+
+var t = async_test('PackageProgressCallback_oncomplete_uninstall', {timeout: 90000}),
+    uninstallProgressCallback, uninstallError;
+
+t.step(function () {
+    uninstallProgressCallback = {
+        oncomplete: t.step_func(function (packageId) {
+            assert_equals(packageId, TCT_PACKAGE_MANAGER_TEST_PACKAGE_ID, "Incorrect packageId.");
+            t.done();
+        })
+    };
+
+    uninstallError = t.step_func(function (error) {
+        assert_unreached("uninstall() error callback: name:" + error.name + ", msg:" + error.message);
+    });
+
+    tizen.package.uninstall(TCT_PACKAGE_MANAGER_TEST_PACKAGE_ID, uninstallProgressCallback, uninstallError);
+});
+
+}
+
+function PackageManager_unsetPackageInfoEventListener() {
+//==== TEST: PackageManager_unsetPackageInfoEventListener
+//==== LABEL Check if method unsetPackageInfoEventListener works correctly
+//==== SPEC Tizen Web API:Application:Package:PackageManager:unsetPackageInfoEventListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/package.html
+//==== EXECUTION_TYPE manual
+//==== PRE Make sure that TCTPackageManagerTest1.1.1.wgt application is not installed.
+//==== STEP Run the test.
+//==== EXPECT Pass.
+//==== TEST_CRITERIA MNA MNAST MR
+setup({timeout: 90000});
+
+var packageInformationEventCallback, uninstallation, installation, installError, uninstallError, returnedValue = null,
+     t = async_test('PackageManager_unsetPackageInfoEventListener',  {timeout: 90000});
+
+t.step(function () {
+    add_result_callback(function () {
+        try {
+            tizen.package.uninstall(TCT_PACKAGE_MANAGER_TEST_PACKAGE_ID, uninstallation, uninstallError);
+        } catch (err) {
+            // do nothing in case stop throw an exception
+        }
+    });
+
+    packageInformationEventCallback = {
+        oninstalled: t.step_func(function (packageInformation) {
+            assert_unreached("oninstalled invoked.");
+        }),
+        onupdated: t.step_func(function (packageInformation) {
+            assert_unreached("onupdated invoked.");
+        }),
+        onuninstalled: t.step_func(function (packageId) {
+            assert_unreached("onuninstalled invoked.");
+        })
+    };
+    uninstallation = {
+        oncomplete : t.step_func(function (packageId){
+            //do nothing here
+        })
+    };
+    installation = {
+        oncomplete : t.step_func(function (packageId){
+            t.done();
+        })
+    };
+    installError = t.step_func(function (error) {
+        assert_unreached("install() error callback: name:" + error.name + ", msg:" + error.message);
+    });
+    uninstallError = t.step_func(function (error) {
+        assert_unreached("uninstall() error callback: name:" + error.name + ", msg:" + error.message);
+    });
+    tizen.package.setPackageInfoEventListener(packageInformationEventCallback);
+    returnedValue = tizen.package.unsetPackageInfoEventListener();
+    assert_equals(returnedValue, undefined, "Incorrect returned value from unsetPackageInfoEventListener method");
+
+    tizen.package.install(TCT_PACKAGE_MANAGER_TEST_PACKAGE_PATH, installation, installError);
+});
+
+}
+
+
+var moduleName = "tct-package-tizen-tests";
+add_test_case(moduleName, PackageInformation_appIds_attribute);
+add_test_case(moduleName, PackageInformationArraySuccessCallback_notexist);
+add_test_case(moduleName, PackageInformationArraySuccessCallback_onsuccess);
+add_test_case(moduleName, PackageInformation_author_attribute);
+add_test_case(moduleName, PackageInformation_dataSize_attribute);
+add_test_case(moduleName, PackageInformation_description_attribute);
+add_test_case(moduleName, PackageInformationEventCallback_notexist);
+add_test_case(moduleName, PackageInformation_extend);
+add_test_case(moduleName, PackageInformation_iconPath_attribute);
+add_test_case(moduleName, PackageInformation_id_attribute);
+add_test_case(moduleName, PackageInformation_lastModified_attribute);
+add_test_case(moduleName, PackageInformation_name_attribute);
+add_test_case(moduleName, PackageInformation_notexist);
+add_test_case(moduleName, PackageInformation_totalSize_attribute);
+add_test_case(moduleName, PackageInformation_version_attribute);
+add_test_case(moduleName, PackageManager_extend);
+add_test_case(moduleName, PackageManager_getPackageInfo);
+add_test_case(moduleName, PackageManager_getPackageInfo_exist);
+add_test_case(moduleName, PackageManager_getPackageInfo_TypeMismatch);
+add_test_case(moduleName, PackageManager_getPackageInfo_with_id);
+add_test_case(moduleName, PackageManager_getPackageInfo_with_id_null);
+add_test_case(moduleName, PackageManager_getPackagesInfo);
+add_test_case(moduleName, PackageManager_getPackagesInfo_errorCallback_invalid_cb);
+add_test_case(moduleName, PackageManager_getPackagesInfo_errorCallback_TypeMismatch);
+add_test_case(moduleName, PackageManager_getPackagesInfo_exist);
+add_test_case(moduleName, PackageManager_getPackagesInfo_missarg);
+add_test_case(moduleName, PackageManager_getPackagesInfo_successCallback_invalid_cb);
+add_test_case(moduleName, PackageManager_getPackagesInfo_successCallback_TypeMismatch);
+add_test_case(moduleName, PackageManager_getPackagesInfo_with_errorCallback);
+add_test_case(moduleName, PackageManager_install_errorCallback_invalid_cb);
+add_test_case(moduleName, PackageManager_install_errorCallback_invoked);
+add_test_case(moduleName, PackageManager_install_errorCallback_TypeMismatch);
+add_test_case(moduleName, PackageManager_install_exist);
+add_test_case(moduleName, PackageManager_install_missarg);
+add_test_case(moduleName, PackageManager_install_progressCallback_invalid_cb);
+add_test_case(moduleName, PackageManager_install_progressCallback_TypeMismatch);
+add_test_case(moduleName, PackageManager_in_tizen);
+add_test_case(moduleName, PackageManager_notexist);
+add_test_case(moduleName, PackageManagerObject_notexist);
+add_test_case(moduleName, PackageManager_setPackageInfoEventListener);
+add_test_case(moduleName, PackageManager_setPackageInfoEventListener_eventCallback_invalid_cb);
+add_test_case(moduleName, PackageManager_setPackageInfoEventListener_eventCallback_TypeMismatch);
+add_test_case(moduleName, PackageManager_setPackageInfoEventListener_exist);
+add_test_case(moduleName, PackageManager_setPackageInfoEventListener_misarg);
+add_test_case(moduleName, PackageManager_uninstall_errorCallback_invalid_cb);
+add_test_case(moduleName, PackageManager_uninstall_errorCallback_invoked);
+add_test_case(moduleName, PackageManager_uninstall_errorCallback_TypeMismatch);
+add_test_case(moduleName, PackageManager_uninstall_exist);
+add_test_case(moduleName, PackageManager_uninstall_missarg);
+add_test_case(moduleName, PackageManager_uninstall_progressCallback_invalid_cb);
+add_test_case(moduleName, PackageManager_uninstall_progressCallback_TypeMismatch);
+add_test_case(moduleName, PackageManager_unsetPackageInfoEventListener_exist);
+add_test_case(moduleName, PackageManager_unsetPackageInfoEventListener_extra_argument);
+add_test_case(moduleName, PackageProgressCallback_notexist);
+
+//add_test_case(moduleName, PackageInformationEventCallback_oninstalled);
+//add_test_case(moduleName, PackageInformationEventCallback_onupdated);
+//add_test_case(moduleName, PackageInformationEventCallback_onuninstalled);
+//add_test_case(moduleName, PackageManager_install);
+//add_test_case(moduleName, PackageManager_uninstall);
+//add_test_case(moduleName, PackageManager_install_without_errorCallback);
+//add_test_case(moduleName, PackageManager_uninstall_without_errorCallback);
+//add_test_case(moduleName, PackageProgressCallback_onprogress_install);
+//add_test_case(moduleName, PackageProgressCallback_onprogress_uninstall);
+//add_test_case(moduleName, PackageProgressCallback_oncomplete_install);
+//add_test_case(moduleName, PackageProgressCallback_oncomplete_uninstall);
+//add_test_case(moduleName, PackageManager_unsetPackageInfoEventListener);
diff --git a/webWidgetTCT_device/test/tct/tests/TestPageVisibility.js b/webWidgetTCT_device/test/tct/tests/TestPageVisibility.js
new file mode 100755 (executable)
index 0000000..3877476
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2012 Intel Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * *Redistributions of works must retain the original copyright notice, this list
+ * of conditions and the following disclaimer.
+ * *Redistributions in binary form must reproduce the original copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * *Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this work without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors:
+ *      HaoYunfen <yunfenx.hao@intel.com>
+ *      Xu,Yuhan <yuhanx.xu@intel.com>
+ */
+
+
+
+// The TCs are moved to TestAnimationTiming.js
+/*
+var alert = console.log;
+function pagevisibility_DocumentVisibility_hidden_lockScreen() {
+
+            setTimeout(hiddenTest,2000);
+            var t=async_test("pagevisibility_DocumentVisibility_hidden_lockScreen");
+            function hiddenTest(){
+                var hidden = document.hidden || document.webkitHidden || document.mozHidden|| document.msHidden;
+                t.step(function(){
+                    assert_true(hidden,"expects hidden attribute is true");
+                    t.done();
+                });
+            }
+}
+
+function pagevisibility_DocumentVisibility_hidden_minimize() {
+
+            setTimeout(hiddenTest,2000);
+            var t=async_test("pagevisibility_DocumentVisibility_hidden_minimize");
+            function hiddenTest(){
+                var hidden = document.hidden || document.webkitHidden || document.mozHidden|| document.msHidden;
+                t.step(function() {
+                    assert_true(hidden,"expects hidden attribute is true");
+                    t.done();
+                });
+            }
+}
+function pagevisibility_DocumentVisibility_visibilitychange() {
+
+setup({timeout:300000});
+
+        var t = async_test('pagevisibility_DocumentVisibility_visibilitychange', {timeout: 300000});
+        var visibilityChange = document.visibilitychange || document.webkitvisibilitychange || document.mozvisibilitychange|| document.msvisibilitychange;
+                t.step(function() {
+                    document.addEventListener("visibilitychange", function() {
+                        t.done();
+                    }, false);
+                });
+    alert("change to minimize and then open the webpage");
+}
+
+
+
+
+var moduleName = "tct-pagevisibility-w3c-tests";
+add_test_case(moduleName, pagevisibility_DocumentVisibility_hidden_lockScreen);
+add_test_case(moduleName, pagevisibility_DocumentVisibility_hidden_minimize);
+add_test_case(moduleName, pagevisibility_DocumentVisibility_visibilitychange);
+*/
diff --git a/webWidgetTCT_device/test/tct/tests/TestPreference.js b/webWidgetTCT_device/test/tct/tests/TestPreference.js
new file mode 100755 (executable)
index 0000000..b50adb5
--- /dev/null
@@ -0,0 +1,923 @@
+function PreferenceChangeCallback_notexist() {
+//==== TEST: PreferenceChangeCallback_notexist
+//==== LABEL Check if interface PreferenceChangeCallback exists,it should not
+//==== SPEC Tizen Web API:TBD:Preference:PreferenceChangeCallback:PreferenceChangeCallback U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/preference.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA CBNIO
+
+test(function () {
+    check_no_interface_object("PreferenceChangeCallback");
+}, "PreferenceChangeCallback_notexist");
+
+}
+function PreferenceChangeCallback_onsuccess() {
+//==== TEST: PreferenceChangeCallback_onsuccess
+//==== LABEL Check if PreferenceChangeCallback onsuccess is called and if its arguments have proper type
+//==== SPEC Tizen Web API:TBD:Preference:PreferenceChangeCallback:onsuccess M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/preference.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA CBOA CBT
+
+setup({timeout: 90000});
+
+var t = async_test("PreferenceChangeCallback_onsuccess", {timeout: 90000}), onsuccess;
+
+t.step(function () {
+    onsuccess = t.step_func(function (data) {
+        assert_not_equals(data , null, "Argument should not be null.");
+        assert_type(data, "object", "Incorrect type.");
+        assert_type(data.key, "string", "key type check");
+        assert_type(data.value, "string", "value type check");
+        tizen.preference.unsetChangeListener(data.key);
+        tizen.preference.removeAll();
+        t.done();
+    });
+
+    tizen.preference.setValue('key1', 'Sample value');
+    tizen.preference.setChangeListener('key1', onsuccess);
+    tizen.preference.setValue('key1', 'New value');
+});
+
+}
+function PreferenceData_key_attribute() {
+//==== TEST: PreferenceData_key_attribute
+//==== LABEL Check if attribute key of PreferenceData exists, has appropriate type
+//==== SPEC Tizen Web API:TBD:Preference:PreferenceData:key A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/preference.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ASG AN
+
+setup({timeout: 9000});
+
+var t = async_test("PreferenceData_key_attribute", {timeout: 9000}), successCB, initKey = 'key1';
+
+t.step(function () {
+
+    successCB = t.step_func(function (preferences) {
+        check_readonly(preferences[0], "key", preferences[0].key, "string", "keyNew");
+        check_not_nullable(preferences[0].key, "key");
+        tizen.preference.removeAll();
+        t.done();
+    });
+
+    tizen.preference.setValue(initKey, 'Sample value');
+    tizen.preference.getAll(successCB);
+});
+
+}
+function PreferenceData_notexist() {
+//==== TEST: PreferenceData_notexist
+//==== LABEL Check if interface PreferenceData exists, it should not exists
+//==== SPEC Tizen Web API:TBD:Preference:PreferenceData:PreferenceData U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/preference.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("PreferenceData");
+}, "PreferenceData_notexist");
+
+}
+function PreferenceData_value_attribute() {
+//==== TEST: PreferenceData_value_attribute
+//==== LABEL Check if attribute value of PreferenceData exists, has appropriate type
+//==== SPEC Tizen Web API:TBD:Preference:PreferenceData:value A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/preference.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ASG AN
+
+setup({timeout: 9000});
+
+var t = async_test("PreferenceData_value_attribute", {timeout: 9000}), successCB, initValue ='Sample';
+
+t.step(function () {
+
+    successCB = t.step_func(function (preferences) {
+        check_readonly(preferences[0], "value", preferences[0].value, "string", "New");
+        check_not_nullable(preferences[0].value, "value");
+        tizen.preference.removeAll();
+        t.done();
+    });
+
+    tizen.preference.setValue('key1', initValue);
+    tizen.preference.getAll(successCB);
+});
+
+}
+function PreferenceGetAllCallback_notexist() {
+//==== TEST: PreferenceGetAllCallback_notexist
+//==== LABEL Check if interface PreferenceGetAllCallback exists,it should not
+//==== SPEC Tizen Web API:TBD:Preference:PreferenceGetAllCallback:PreferenceGetAllCallback U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/preference.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA CBNIO
+
+test(function () {
+    check_no_interface_object("PreferenceGetAllCallback");
+}, "PreferenceGetAllCallback_notexist");
+
+}
+function PreferenceGetAllCallback_onsuccess() {
+//==== TEST: PreferenceGetAllCallback_onsuccess
+//==== LABEL Check if PreferenceGetAllCallback onsuccess is called and if its arguments have proper type
+//==== SPEC Tizen Web API:TBD:Preference:PreferenceGetAllCallback:onsuccess M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/preference.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA CBOA CBT
+
+setup({timeout: 90000});
+
+var t = async_test("PreferenceGetAllCallback_onsuccess", {timeout: 90000}), onsuccess;
+
+t.step(function () {
+    onsuccess = t.step_func(function (preferences) {
+        assert_not_equals(preferences.length , null, "preferences.length should not be null.");
+        assert_type(preferences[0].key, "string", "key type check");
+        assert_type(preferences[0].value, "string", "value type check");
+        tizen.preference.removeAll();
+        t.done();
+    });
+
+    tizen.preference.setValue('key1', 'Sample value');
+    tizen.preference.getAll(onsuccess);
+});
+
+}
+function PreferenceManager_exists_exist() {
+//==== TEST: PreferenceManager_exists_exist
+//==== LABEL Check if PreferenceManager::exists method exists
+//==== SPEC Tizen Web API:TBD:Preference:PreferenceManager:exists M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/preference.html
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    check_method_exists(tizen.preference, "exists");
+}, "PreferenceManager_exists_exist");
+
+}
+function PreferenceManager_exists() {
+//==== TEST: PreferenceManager_exists
+//==== LABEL Check if PreferenceManager::exists works properly
+//==== SPEC Tizen Web API:TBD:Preference:PreferenceManager:exists M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/preference.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var returnedValue = null;
+    tizen.preference.setValue('key1', 'Sample value');
+    returnedValue = tizen.preference.exists('key1');
+    assert_equals(returnedValue, true, "exists should return true.");
+    tizen.preference.removeAll();
+}, "PreferenceManager_exists");
+
+}
+function PreferenceManager_exists_key_invalid() {
+//==== TEST: PreferenceManager_exists_key_invalid
+//==== LABEL Check if PreferenceManager::exists key contains invalid value should throw exception
+//==== SPEC Tizen Web API:TBD:Preference:PreferenceManager:exists M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/preference.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+test(function () {
+    tizen.preference.setValue('key1', 'Sample value');
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        tizen.preference.exists(undefine);
+    }, "exception should be thrown");
+    tizen.preference.removeAll();
+}, "PreferenceManager_exists_key_invalid");
+
+}
+function PreferenceManager_extend() {
+//==== TEST: PreferenceManager_extend
+//==== LABEL Check if PreferenceManager object is extendable
+//==== SPEC Tizen Web API:TBD:Preference:PreferenceManager:PreferenceManager U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/preference.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA OBX
+
+test(function () {
+    check_extensibility(tizen.preference);
+}, "PreferenceManager_extend");
+
+}
+function PreferenceManager_getAll_errorCallback_invalid_cb() {
+//==== TEST: PreferenceManager_getAll_errorCallback_invalid_cb
+//==== LABEL Check if PreferenceManager::getAll throws exception when errorCallback is invalid
+//==== SPEC Tizen Web API:TBD:Preference:PreferenceManager:getAll M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/preference.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 90000});
+
+var t = async_test("PreferenceManager_getAll_errorCallback_invalid_cb", {timeout: 90000}), exceptionName = "TypeMismatchError",
+    invaliderrorCallback, successCB;
+
+t.step(function () {
+    invaliderrorCallback = {
+        onerror: t.step_func(function (error) {
+            assert_unreached("Invalid error callback invoked");
+    })
+    };
+
+    successCB = t.step_func(function (preferences) {
+            assert_unreached("success callback invoked");
+        });
+
+    tizen.preference.setValue('key1', 'Sample value');
+    assert_throws({name: exceptionName},
+        function () {
+            tizen.preference.getAll(successCB, invaliderrorCallback);
+        }, exceptionName + " should be thrown - given incorrect successCallback - object.");
+    tizen.preference.removeAll();
+    t.done();
+});
+
+}
+function PreferenceManager_getAll_exist() {
+//==== TEST: PreferenceManager_getAll_exist
+//==== LABEL Check if PreferenceManager::getAll method exists
+//==== SPEC Tizen Web API:TBD:Preference:PreferenceManager:getAll M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/preference.html
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    check_method_exists(tizen.preference, "getAll");
+}, "PreferenceManager_getAll_exist");
+
+}
+function PreferenceManager_getAll() {
+//==== TEST: PreferenceManager_getAll
+//==== LABEL Check if PreferenceManager::getAll works properly
+//==== SPEC Tizen Web API:TBD:Preference:PreferenceManager:getAll M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/preference.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR MMINA
+
+setup({timeout: 9000});
+
+var t = async_test("PreferenceManager_getAll", {timeout: 9000}), successCB, returnedValue = null;
+
+t.step(function () {
+
+    successCB = t.step_func(function (preferences) {
+        assert_equals(returnedValue, undefined, "getAll() should return undefined.");
+        tizen.preference.removeAll();
+        t.done();
+    });
+
+    tizen.preference.setValue('key1', 'Sample value');
+    returnedValue = tizen.preference.getAll(successCB);
+});
+
+}
+function PreferenceManager_getAll_misarg() {
+//==== TEST: PreferenceManager_getAll_misarg
+//==== LABEL Check PreferenceManager::getAll method without mandatory param should throw exception
+//==== SPEC Tizen Web API:TBD:Preference:PreferenceManager:getAll M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/preference.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MMA
+
+test(function () {
+    tizen.preference.setValue('key1', 'Sample value');
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        tizen.preference.getAll();
+    }, "exception should be thrown");
+    tizen.preference.removeAll();
+}, "PreferenceManager_getAll_misarg");
+
+}
+function PreferenceManager_getAll_successCallback_invalid_cb() {
+//==== TEST: PreferenceManager_getAll_successCallback_invalid_cb
+//==== LABEL Check if PreferenceManager::getAll throws exception when successCallback is invalid
+//==== SPEC Tizen Web API:TBD:Preference:PreferenceManager:getAll M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/preference.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 90000});
+
+var t = async_test("PreferenceManager_getAll_successCallback_invalid_cb", {timeout: 90000}), exceptionName = "TypeMismatchError",
+    errorCallback, invalidCallback;
+
+t.step(function () {
+    invalidCallback = {
+        onsuccess: t.step_func(function (preferences) {
+            assert_unreached("Invalid success callback invoked");
+        })
+    };
+
+    errorCallback = t.step_func(function (error) {
+        assert_unreached("ErrorCallback invoked: " + error.name + ": " + error.message);
+    });
+
+    tizen.preference.setValue('key1', 'Sample value');
+    assert_throws({name: exceptionName},
+        function () {
+            tizen.preference.getAll(invalidCallback, errorCallback);
+        }, exceptionName + " should be thrown - given incorrect successCallback - object.");
+    tizen.preference.removeAll();
+    t.done();
+});
+
+}
+function PreferenceManager_getAll_with_errorCallback() {
+//==== TEST: PreferenceManager_getAll_with_errorCallback
+//==== LABEL Check if PreferenceManager::getAll with optional param works properly
+//==== SPEC Tizen Web API:TBD:Preference:PreferenceManager:getAll M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/preference.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MOA MR
+
+setup({timeout: 90000});
+
+var t = async_test("PreferenceManager_getAll_with_errorCallback", {timeout: 90000}), successCB, errorCB, returnedValue = null;
+
+t.step(function () {
+
+    errorCB = t.step_func(function (error) {
+        assert_unreached("errorCallback is invoked");
+    });
+
+
+    successCB = t.step_func(function (preferences) {
+        assert_equals(returnedValue, undefined, "getAll() should return undefined.");
+        tizen.preference.removeAll();
+        t.done();
+    });
+
+    tizen.preference.setValue('key1', 'Sample value');
+    returnedValue = tizen.preference.getAll(successCB, errorCB);
+});
+
+}
+function PreferenceManager_getValue_exist() {
+//==== TEST: PreferenceManager_getValue_exist
+//==== LABEL Check if PreferenceManager::getValue method exists
+//==== SPEC Tizen Web API:TBD:Preference:PreferenceManager:getValue M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/preference.html
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    check_method_exists(tizen.preference, "getValue");
+}, "PreferenceManager_getValue_exist");
+
+}
+function PreferenceManager_getValue() {
+//==== TEST: PreferenceManager_getValue
+//==== LABEL Check if PreferenceManager.getValue works properly
+//==== SPEC Tizen Web API:TBD:Preference:PreferenceManager:getValue M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/preference.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var currentValue;
+    tizen.preference.setValue('key1', 'New value');
+    currentValue = tizen.preference.getValue('key1');
+    assert_equals(currentValue, 'New value', "getValue() should return correct value.");
+    tizen.preference.removeAll();
+}, "PreferenceManager_getValue");
+
+}
+function PreferenceManager_getValue_key_NotFound() {
+//==== TEST: PreferenceManager_getValue_key_NotFound
+//==== LABEL Check if PreferenceManager.getValue required key not available throw exception
+//==== SPEC Tizen Web API:TBD:Preference:PreferenceManager:getValue M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/preference.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MR
+
+test(function () {
+    tizen.preference.setValue('key1', 'New value');
+    assert_throws(NOT_FOUND_EXCEPTION, function () {
+        tizen.preference.getValue("@$%^");
+    }, "exception should be thrown");
+    tizen.preference.removeAll();
+}, "PreferenceManager_getValue_key_NotFound");
+
+}
+function PreferenceManager_getValue_misarg() {
+//==== TEST: PreferenceManager_getValue_misarg
+//==== LABEL Check PreferenceManager::getValue method without mandatory param should throw exception
+//==== SPEC Tizen Web API:TBD:Preference:PreferenceManager:getValue M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/preference.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MMA
+
+test(function () {
+    tizen.preference.setValue('key1', 'New value');
+    assert_throws(NOT_FOUND_EXCEPTION, function () {
+        tizen.preference.getValue();
+    }, "exception should be thrown");
+    tizen.preference.removeAll();
+}, "PreferenceManager_getValue_misarg");
+
+}
+function PreferenceManager_in_tizen() {
+//==== TEST: PreferenceManager_in_tizen
+//==== LABEL Check if PreferenceManager exists in tizen
+//==== SPEC Tizen Web API:TBD:Preference:PreferenceManager:PreferenceManager U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/preference.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA OBME
+
+test(function () {
+    assert_true("preference" in tizen, "No preference method in tizen.");
+    check_readonly(tizen, "preference", tizen.preference, "object", null);
+}, "PreferenceManager_in_tizen");
+
+}
+function PreferenceManager_notexist() {
+//==== TEST: PreferenceManager_notexist
+//==== LABEL Check if interface PreferenceManager exists, it should not exists
+//==== SPEC Tizen Web API:TBD:Preference:PreferenceManager:PreferenceManager U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/preference.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("PreferenceManager");
+}, "PreferenceManager_notexist");
+
+}
+function PreferenceManagerObject_notexist() {
+//==== TEST: PreferenceManagerObject_notexist
+//==== LABEL Check if interface PreferenceManagerObject exists, it should not exists.
+//==== SPEC Tizen Web API:TBD:Preference:PreferenceManagerObject:PreferenceManagerObject U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/preference.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("PreferenceManagerObject");
+}, "PreferenceManagerObject_notexist");
+
+}
+function PreferenceManager_removeAll_exist() {
+//==== TEST: PreferenceManager_removeAll_exist
+//==== LABEL Check if PreferenceManager::removeAll method exists
+//==== SPEC Tizen Web API:TBD:Preference:PreferenceManager:removeAll M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/preference.html
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    check_method_exists(tizen.preference, "removeAll");
+}, "PreferenceManager_removeAll_exist");
+
+}
+function PreferenceManager_removeAll_extra_argument() {
+//==== TEST: PreferenceManager_removeAll_extra_argument
+//==== LABEL Check if method removeAll of PreferenceManager accepts extra argument
+//==== SPEC Tizen Web API:TBD:Preference:PreferenceManager:removeAll M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/preference.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MNAEX
+
+test(function () {
+    checkExtraArgument(tizen.preference, "removeAll");
+}, "PreferenceManager_removeAll_extra_argument");
+
+}
+function PreferenceManager_removeAll() {
+//==== TEST: PreferenceManager_removeAll
+//==== LABEL Check if PreferenceManager::removeAll method works correctly
+//==== SPEC Tizen Web API:TBD:Preference:PreferenceManager:removeAll M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/preference.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR MNA MNAST
+
+test(function () {
+    var returnedValue = null;
+    tizen.preference.setValue('key1', 'Sample value');
+    returnedValue = tizen.preference.removeAll();
+    assert_equals(returnedValue, undefined, "removeAll() should return undefined.");
+    assert_equals(tizen.preference.exists('key1'), false, "remove successfully");
+}, "PreferenceManager_removeAll");
+
+}
+function PreferenceManager_remove_exist() {
+//==== TEST: PreferenceManager_remove_exist
+//==== LABEL Check if PreferenceManager::remove method exists
+//==== SPEC Tizen Web API:TBD:Preference:PreferenceManager:remove M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/preference.html
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    check_method_exists(tizen.preference, "remove");
+}, "PreferenceManager_remove_exist");
+
+}
+function PreferenceManager_remove() {
+//==== TEST: PreferenceManager_remove
+//==== LABEL Check if PreferenceManager::remove method works correctly
+//==== SPEC Tizen Web API:TBD:Preference:PreferenceManager:remove M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/preference.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR MAST
+
+test(function () {
+    var returnedValue = null;
+    tizen.preference.setValue('key1', 'Sample value');
+    returnedValue = tizen.preference.remove('key1');
+    assert_equals(returnedValue, undefined, "remove() should return undefined.");
+    assert_equals(tizen.preference.exists('key1'), false, "remove successfully");
+}, "PreferenceManager_remove");
+
+}
+function PreferenceManager_remove_misarg() {
+//==== TEST: PreferenceManager_remove_misarg
+//==== LABEL Check PreferenceManager::remove method without mandatory param should throw exception
+//==== SPEC Tizen Web API:TBD:Preference:PreferenceManager:remove M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/preference.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MMA
+
+test(function () {
+    tizen.preference.setValue('key1', 'Sample value');
+    assert_throws(NOT_FOUND_EXCEPTION, function () {
+        tizen.preference.remove();
+    }, "exception should be thrown");
+}, "PreferenceManager_remove_misarg");
+
+}
+function PreferenceManager_setChangeListener_exist() {
+//==== TEST: PreferenceManager_setChangeListener_exist
+//==== LABEL Check PreferenceManager:setChangeListener() method is exist
+//==== SPEC Tizen Web API:TBD:Preference:PreferenceManager:setChangeListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/preference.html
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    check_method_exists(tizen.preference, "setChangeListener");
+}, "PreferenceManager_setChangeListener_exist");
+
+}
+function PreferenceManager_setChangeListener() {
+//==== TEST: PreferenceManager_setChangeListener
+//==== LABEL Check if PreferenceManager::setChangeListener method works properly
+//==== SPEC Tizen Web API:TBD:Preference:PreferenceManager:setChangeListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/preference.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+setup({timeout: 90000});
+
+var t = async_test("PreferenceManager_setChangeListener", {timeout: 90000}), listener, newValue = 'New value', returnedValue = null;
+
+t.step(function () {
+
+    listener = function (data) {
+            assert_equals(data.value, newValue, "data key has wrong value.");
+            assert_equals(returnedValue, undefined, "setChangeListener should return undefined.");
+            tizen.preference.unsetChangeListener(data.key);
+            tizen.preference.removeAll();
+            t.done();
+        };
+
+    tizen.preference.setValue('key1', 'Sample value');
+    returnedValue = tizen.preference.setChangeListener('key1', listener);
+    tizen.preference.setValue('key1', newValue);
+});
+
+}
+function PreferenceManager_setChangeListener_listener_TypeMismatch() {
+//==== TEST: PreferenceManager_setChangeListener_listener_TypeMismatch
+//==== LABEL Check if PreferenceManager::setChangeListener throws exception when changeCallback is incorrect
+//==== SPEC Tizen Web API:TBD:Preference:PreferenceManager:setChangeListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/preference.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+var conversionTable, listener, exceptionName, i;
+
+test(function () {
+    conversionTable = getTypeConversionExceptions("object", false);
+
+    for(i = 0; i < conversionTable.length; i++) {
+        listener = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+
+        assert_throws({name: exceptionName},
+            function () {
+                tizen.preference.setChangeListener('key1', listener);
+            }, "Given incorrect listener.");
+    }
+
+}, "PreferenceManager_setChangeListener_listener_TypeMismatch");
+
+}
+function PreferenceManager_setChangeListener_misarg() {
+//==== TEST: PreferenceManager_setChangeListener_misarg
+//==== LABEL Check if PreferenceManager::setChangeListener method called with missing non-optional argument throws an exception
+//==== SPEC Tizen Web API:TBD:Preference:PreferenceManager:setChangeListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/preference.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MMA
+
+test(function () {
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        tizen.preference.setChangeListener();
+    }, "Invoked without non-optional arguments.");
+}, "PreferenceManager_setChangeListener_misarg");
+
+}
+function PreferenceManager_setValue_exist() {
+//==== TEST: PreferenceManager_setValue_exist
+//==== LABEL Check if PreferenceManager::setValue method exists
+//==== SPEC Tizen Web API:TBD:Preference:PreferenceManager:setValue M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/preference.html
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    check_method_exists(tizen.preference, "setValue");
+}, "PreferenceManager_setValue_exist");
+
+}
+function PreferenceManager_setValue() {
+//==== TEST: PreferenceManager_setValue
+//==== LABEL Check if PreferenceManager::setValue works properly
+//==== SPEC Tizen Web API:TBD:Preference:PreferenceManager:setValue M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/preference.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR MAST
+
+setup({timeout: 9000});
+
+var t = async_test("PreferenceManager_setValue", {timeout: 9000}), returnedValue, successCB, initKey = 'key1';
+
+t.step(function () {
+
+    successCB = t.step_func(function (preferences) {
+        assert_equals(returnedValue, undefined, "setValue() should return undefined.");
+        assert_equals(preferences[0].key, initKey, "key attribute not set.");
+        tizen.preference.removeAll();
+        t.done();
+    });
+
+    returnedValue = tizen.preference.setValue(initKey, 'Sample value');
+    tizen.preference.getAll(successCB);
+});
+
+}
+function PreferenceManager_setValue_key_invalid() {
+//==== TEST: PreferenceManager_setValue_key_invalid
+//==== LABEL PreferenceManager::setValue() method key contains an invalid value
+//==== SPEC Tizen Web API:TBD:Preference:PreferenceManager:setValue M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/preference.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+test(function () {
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        tizen.preference.setValue(undefined, 'New value');
+    }, "exception should be thrown");
+    tizen.preference.removeAll();
+}, "PreferenceManager_setValue_key_invalid");
+
+}
+function PreferenceManager_unsetChangeListener_exist() {
+//==== TEST: PreferenceManager_unsetChangeListener_exist
+//==== LABEL Check PreferenceManager:unsetChangeListener() method is exist
+//==== SPEC Tizen Web API:TBD:Preference:PreferenceManager:unsetChangeListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/preference.html
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    check_method_exists(tizen.preference, "unsetChangeListener");
+}, "PreferenceManager_unsetChangeListener_exist");
+
+}
+function PreferenceManager_unsetChangeListener() {
+//==== TEST: PreferenceManager_unsetChangeListener
+//==== LABEL Check if PreferenceManager::unsetChangeListener method works properly
+//==== SPEC Tizen Web API:TBD:Preference:PreferenceManager:unsetChangeListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/preference.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+setup({timeout: 90000});
+
+var t = async_test("PreferenceManager_unsetChangeListener", {timeout: 90000}), listener, newValue = 'New value', returnedValue = null;
+
+t.step(function () {
+    listener = function (data) {
+        returnedValue = tizen.preference.unsetChangeListener(data.key);
+        assert_equals(returnedValue, undefined, "setChangeListener should return undefined.");
+        tizen.preference.removeAll();
+        t.done();
+    };
+
+    tizen.preference.setValue('key1', 'Sample value');
+    tizen.preference.setChangeListener('key1', listener);
+    tizen.preference.setValue('key1', newValue);
+});
+
+}
+function PreferenceManager_setChangeListener_NotFoundError(){
+
+//==== TEST: PreferenceManager_setChangeListener_NotFoundError
+//==== LABEL Check if PreferenceManager::setChangeListener method throws exception when called with not given key
+//==== SPEC Tizen Web API:TBD:Preference:PreferenceManager:setChangeListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/preference.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 90000});
+
+var t = async_test("PreferenceManager_setChangeListener_NotFoundError", {timeout: 90000}), listener;
+
+t.step(function () {
+
+    listener = function (data) {
+        tizen.preference.remove('key1');
+        assert_throws(NOT_FOUND_EXCEPTION, function () {
+            tizen.preference.setChangeListener(data.key, listener);
+        }, "exception should be thrown");
+        t.done();
+        };
+
+    tizen.preference.setValue('key1', 'Sample value');
+    tizen.preference.setChangeListener('key1', listener);
+    tizen.preference.setValue('key1', 'New value');
+});
+
+}
+function PreferenceManager_setChangeListener_onsuccess_invalid_cb(){
+
+//==== TEST: PreferenceManager_setChangeListener_onsuccess_invalid_cb
+//==== LABEL Check if PreferenceManager::setChangeListener throws exception when onsuccess has non callable attributes
+//==== SPEC Tizen Web API:TBD:Preference:PreferenceManager:setChangeListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/preference.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTL
+
+setup({timeout: 90000});
+
+var t = async_test("PreferenceManager_setChangeListener_onsuccess_invalid_cb", {timeout: 90000}), incorrectListeners, changeCallback, i, exceptionName;
+
+t.step(function () {
+    incorrectListeners = getListenerConversionExceptions("onsuccess");
+    for(i = 0; i < incorrectListeners.length; i++) {
+        changeCallback  = incorrectListeners[i][0];
+        exceptionName = incorrectListeners[i][1];
+        assert_throws({name: exceptionName},
+            function () {
+                tizen.preference.setValue('key1', 'Sample value');
+                tizen.preference.setChangeListener('key1', changeCallback);
+            }, "Given invalid changeCallback.");
+    }
+    t.done();
+});
+
+}
+function PreferenceManager_getAll_errorCallback_TypeMismatch(){
+
+//==== TEST: PreferenceManager_getAll_errorCallback_TypeMismatch
+//==== LABEL PreferenceManager::getAll() method errorCallback contains an invalid value throws typemismatch error
+//==== SPEC Tizen Web API:TBD:Preference:PreferenceManager:getAll M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/preference.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 9000});
+
+var t = async_test("PreferenceManager_getAll_errorCallback_TypeMismatch", {timeout: 9000}), successCB;
+
+t.step(function () {
+
+    successCB = t.step_func(function (preferences) {
+    });
+
+    tizen.preference.setValue('key1', 'Sample value');
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        tizen.preference.getAll(successCB, -1);
+    }, "exception should be thrown");
+    t.done();
+    tizen.preference.removeAll();
+});
+
+}
+function PreferenceManager_getAll_successCallback_TypeMismatch(){
+
+//==== TEST: PreferenceManager_getAll_successCallback_TypeMismatch
+//==== LABEL PreferenceManager::getAll() method successcallback contains an invalid value throws typemismatch error
+//==== SPEC Tizen Web API:TBD:Preference:PreferenceManager:getAll M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/preference.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+test(function () {
+    tizen.preference.setValue('key1', 'Sample value');
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        tizen.preference.getAll(-1);
+    }, "exception should be thrown");
+    tizen.preference.removeAll();
+}, "PreferenceManager_getAll_successCallback_TypeMismatch");
+
+}
+function PreferenceManager_remove_key_NotFound(){
+
+//==== TEST: PreferenceManager_remove_key_NotFound
+//==== LABEL Check if PreferenceManager::remove method with notfound key should throw exception
+//==== SPEC Tizen Web API:TBD:Preference:PreferenceManager:remove M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/preference.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+test(function () {
+    tizen.preference.setValue('key1', 'Sample value');
+    assert_throws(NOT_FOUND_EXCEPTION, function () {
+        tizen.preference.remove(-1);
+    }, "exception should be thrown");
+}, "PreferenceManager_remove_key_NotFound");
+
+}
+function PreferenceManager_unsetChangeListener_NotFoundError(){
+
+//==== TEST: PreferenceManager_unsetChangeListener_NotFoundError
+//==== LABEL Check if PreferenceManager::unsetChangeListener method throws exception when called with not given key
+//==== SPEC Tizen Web API:TBD:Preference:PreferenceManager:unsetChangeListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/preference.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 90000});
+
+var t = async_test("PreferenceManager_unsetChangeListener_NotFoundError", {timeout: 90000}), listener;
+
+t.step(function () {
+
+    listener = function (data) {
+        tizen.preference.remove('key1');
+        assert_throws(NOT_FOUND_EXCEPTION, function () {
+            tizen.preference.unsetChangeListener(data.key, listener);
+        }, "exception should be thrown");
+        t.done();
+        };
+
+    tizen.preference.setValue('key1', 'Sample value');
+    tizen.preference.setChangeListener('key1', listener);
+    tizen.preference.setValue('key1', 'New value');
+});
+
+
+}
+
+var moduleName = "tct-preference-tizen-tests";
+
+add_test_case(moduleName, PreferenceChangeCallback_notexist);
+add_test_case(moduleName, PreferenceChangeCallback_onsuccess);
+add_test_case(moduleName, PreferenceData_key_attribute);
+add_test_case(moduleName, PreferenceData_notexist);
+add_test_case(moduleName, PreferenceData_value_attribute);
+add_test_case(moduleName, PreferenceGetAllCallback_notexist);
+add_test_case(moduleName, PreferenceGetAllCallback_onsuccess);
+add_test_case(moduleName, PreferenceManagerObject_notexist);
+add_test_case(moduleName, PreferenceManager_exists);
+add_test_case(moduleName, PreferenceManager_exists_exist);
+add_test_case(moduleName, PreferenceManager_extend);
+add_test_case(moduleName, PreferenceManager_getAll);
+add_test_case(moduleName, PreferenceManager_getAll_errorCallback_invalid_cb);
+add_test_case(moduleName, PreferenceManager_getAll_exist);
+add_test_case(moduleName, PreferenceManager_getAll_misarg);
+add_test_case(moduleName, PreferenceManager_getAll_successCallback_invalid_cb);
+add_test_case(moduleName, PreferenceManager_getAll_with_errorCallback);
+add_test_case(moduleName, PreferenceManager_getValue);
+add_test_case(moduleName, PreferenceManager_getValue_exist);
+add_test_case(moduleName, PreferenceManager_getValue_key_NotFound);
+add_test_case(moduleName, PreferenceManager_getValue_misarg);
+add_test_case(moduleName, PreferenceManager_in_tizen);
+add_test_case(moduleName, PreferenceManager_notexist);
+add_test_case(moduleName, PreferenceManager_remove);
+add_test_case(moduleName, PreferenceManager_removeAll);
+add_test_case(moduleName, PreferenceManager_removeAll_exist);
+add_test_case(moduleName, PreferenceManager_removeAll_extra_argument);
+add_test_case(moduleName, PreferenceManager_remove_exist);
+add_test_case(moduleName, PreferenceManager_remove_misarg);
+add_test_case(moduleName, PreferenceManager_setChangeListener);
+add_test_case(moduleName, PreferenceManager_setChangeListener_exist);
+add_test_case(moduleName, PreferenceManager_setChangeListener_listener_TypeMismatch);
+add_test_case(moduleName, PreferenceManager_setChangeListener_misarg);
+add_test_case(moduleName, PreferenceManager_setValue);
+add_test_case(moduleName, PreferenceManager_setValue_exist);
+add_test_case(moduleName, PreferenceManager_unsetChangeListener);
+add_test_case(moduleName, PreferenceManager_unsetChangeListener_exist);
+add_test_case(moduleName, PreferenceManager_setChangeListener_NotFoundError);
+add_test_case(moduleName, PreferenceManager_setChangeListener_onsuccess_invalid_cb);
+add_test_case(moduleName, PreferenceManager_getAll_errorCallback_TypeMismatch);
+add_test_case(moduleName, PreferenceManager_getAll_successCallback_TypeMismatch);
+add_test_case(moduleName, PreferenceManager_remove_key_NotFound);
+add_test_case(moduleName, PreferenceManager_unsetChangeListener_NotFoundError);
diff --git a/webWidgetTCT_device/test/tct/tests/TestSensor.js b/webWidgetTCT_device/test/tct/tests/TestSensor.js
new file mode 100755 (executable)
index 0000000..befe4b0
--- /dev/null
@@ -0,0 +1,7152 @@
+var alert = console.log;
+
+/*
+Copyright (c) 2015 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Authors:
+        Xiaoyan Qian <xy.qian@samsung.com>
+
+*/
+
+function HRMRawSensor_extend() {
+
+
+
+
+
+
+
+
+//==== TEST: HRMRawSensor_extend
+//==== LABEL Check if HRMRawSensor is extendable
+//==== SPEC Tizen Web API:System:Sensor:HRMRawSensor:HRMRawSensor U
+//==== SPEC_URL TBD
+//==== PRIORITY P3
+//==== TEST_CRITERIA OBX
+
+test(function () {
+    if(!tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.heart_rate_monitor.led_green") &&
+        !tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.heart_rate_monitor.led_red") &&
+        !tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.heart_rate_monitor.led_ir")) {
+        return;
+    }
+    var HRMrawsensor = tizen.sensorservice.getDefaultSensor("HRM_RAW");
+    check_extensibility(HRMrawsensor);
+}, "HRMRawSensor_extend");
+
+
+
+}
+/*
+Copyright (c) 2015 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Authors:
+        Xiaoyan Qian <xy.qian@samsung.com>
+
+*/
+
+function HRMRawSensor_getHRMRawSensorData_errorCallback_invalid_cb() {
+
+
+
+
+
+
+
+
+//==== TEST: HRMRawSensor_getHRMRawSensorData_errorCallback_invalid_cb
+//==== LABEL Check if HRMRawSensor::getHRMRawSensorData() method throws exception when errorCallback is invalid
+//==== SPEC Tizen Web API:System:Sensor:HRMRawSensor:getHRMRawSensorData M
+//==== SPEC_URL TBD
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 30000});
+
+var t = async_test("HRMRawSensor_getHRMRawSensorData_errorCallback_invalid_cb", {timeout: 30000}), invalidcallback, onsuccessCB, HRMrawsensor, onGetSuccessCB;
+
+t.step(function () {
+    if(!tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.heart_rate_monitor.led_green") &&
+        !tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.heart_rate_monitor.led_red") &&
+        !tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.heart_rate_monitor.led_ir")) {
+        t.done();
+        return;
+    }
+    HRMrawsensor = tizen.sensorservice.getDefaultSensor("HRM_RAW");
+
+    add_result_callback(function () {
+        HRMrawsensor.stop();
+    });
+
+    invalidcallback = {
+        onerror: t.step_func(function (sensorData) {
+            assert_unreached("getHRMRawSensorData() successcallback invoked");
+        })
+    };
+
+    onGetSuccessCB = t.step_func(function (sensorData) {
+        assert_unreached("SuccessCallback should not be called");
+    });
+
+    onsuccessCB = t.step_func(function () {
+        assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+            HRMrawsensor.getHRMRawSensorData(onGetSuccessCB, invalidcallback);
+        }, TYPE_MISMATCH_EXCEPTION + " Should throw exception");
+        t.done();
+    });
+
+    HRMrawsensor.start(onsuccessCB);
+});
+
+
+
+}
+/*
+Copyright (c) 2015 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Authors:
+        Xiaoyan Qian <xy.qian@samsung.com>
+
+*/
+
+function HRMRawSensor_getHRMRawSensorData_errorCallback_invoked() {
+
+
+
+
+
+
+
+
+//==== TEST: HRMRawSensor_getHRMRawSensorData_errorCallback_invoked
+//==== LABEL Check exception in error callback of HRMRawSensor::getHRMRawSensorData() method
+//==== SPEC Tizen Web API:System:Sensor:HRMRawSensor:getHRMRawSensorData M
+//==== SPEC_URL TBD
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P2
+//==== TEST_CRITERIA MERRCB
+
+setup({timeout: 30000});
+
+var t = async_test("HRMRawSensor_getHRMRawSensorData_errorCallback_invoked", {timeout: 30000}), onerrorCB, onGetSuccessCB, HRMrawsensor;
+
+t.step(function () {
+    if(!tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.heart_rate_monitor.led_green") &&
+        !tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.heart_rate_monitor.led_red") &&
+        !tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.heart_rate_monitor.led_ir")) {
+        t.done();
+        return;
+    }
+    HRMrawsensor = tizen.sensorservice.getDefaultSensor("HRM_RAW");
+
+    onGetSuccessCB = t.step_func(function (sensorData) {
+        assert_unreached("SuccessCallback should not be called");
+    });
+
+    onerrorCB = t.step_func(function (error) {
+        assert_equals("ServiceNotAvailableError", error.name, "Error callback should be thrown with error: " + error.name);
+        t.done();
+    });
+
+    HRMrawsensor.getHRMRawSensorData(onGetSuccessCB, onerrorCB);
+});
+
+
+}
+/*
+Copyright (c) 2015 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Authors:
+        Xiaoyan Qian <xy.qian@samsung.com>
+
+*/
+
+function HRMRawSensor_getHRMRawSensorData_errorCallback_TypeMismatch() {
+
+
+
+
+
+
+
+
+//==== TEST: HRMRawSensor_getHRMRawSensorData_errorCallback_TypeMismatch
+//==== LABEL Check if HRMRawSensor::getHRMRawSensorData() with incorrect errorCallback argument throws exception
+//==== SPEC Tizen Web API:System:Sensor:HRMRawSensor:getHRMRawSensorData M
+//==== SPEC_URL TBD
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test("HRMRawSensor_getHRMRawSensorData_errorCallback_TypeMismatch", {timeout: 30000}), exceptionName, i, conversionTable, onGetSuccessCB, onerrorCB, HRMrawsensor, onsuccessCB;
+
+t.step(function () {
+    if(!tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.heart_rate_monitor.led_green") &&
+        !tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.heart_rate_monitor.led_red") &&
+        !tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.heart_rate_monitor.led_ir")) {
+        t.done();
+        return;
+    }
+    HRMrawsensor = tizen.sensorservice.getDefaultSensor("HRM_RAW");
+
+    add_result_callback(function () {
+        HRMrawsensor.stop();
+    });
+
+    onGetSuccessCB = t.step_func(function () {
+        assert_unreached("Unexpected successCallback");
+    });
+
+    onsuccessCB = t.step_func(function () {
+        conversionTable = getTypeConversionExceptions("functionObject", true);
+        for (i = 0; i < conversionTable.length; i++) {
+            onerrorCB = conversionTable[i][0];
+            exceptionName = conversionTable[i][1];
+            assert_throws({name: exceptionName}, function () {
+                HRMrawsensor.getHRMRawSensorData(onGetSuccessCB, onerrorCB);
+            }, exceptionName + " should be thrown");
+        }
+        t.done();
+    });
+
+    HRMrawsensor.start(onsuccessCB);
+});
+
+
+
+}
+/*
+Copyright (c) 2015 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Authors:
+        Xiaoyan Qian <xy.qian@samsung.com>
+
+*/
+
+function HRMRawSensor_getHRMRawSensorData_exist() {
+
+
+
+
+
+
+
+
+//==== TEST: HRMRawSensor_getHRMRawSensorData_exist
+//==== LABEL Check if HRMRawSensor::getHRMRawSensorData() method exists
+//==== SPEC Tizen Web API:System:Sensor:HRMRawSensor:getHRMRawSensorData M
+//==== SPEC_URL TBD
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    var HRMrawsensor;
+    if(!tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.heart_rate_monitor.led_green") &&
+        !tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.heart_rate_monitor.led_red") &&
+        !tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.heart_rate_monitor.led_ir")) {
+        return;
+    }
+    HRMrawsensor = tizen.sensorservice.getDefaultSensor("HRM_RAW");
+    assert_true("getHRMRawSensorData" in HRMrawsensor, "No getHRMRawSensorData method in HRMrawsensor");
+    check_method_exists(HRMrawsensor, "getHRMRawSensorData");
+}, "HRMRawSensor_getHRMRawSensorData_exist");
+
+
+
+}
+/*
+Copyright (c) 2015 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Authors:
+        Xiaoyan Qian <xy.qian@samsung.com>
+
+*/
+
+function HRMRawSensor_getHRMRawSensorData() {
+
+
+
+
+
+
+
+
+//==== TEST: HRMRawSensor_getHRMRawSensorData
+//==== LABEL Check if HRMRawSensor::getHRMRawSensorData() method works properly
+//==== SPEC Tizen Web API:System:Sensor:HRMRawSensor:getHRMRawSensorData M
+//==== SPEC_URL TBD
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P1
+//==== TEST_CRITERIA MMINA MR
+
+setup({timeout: 30000});
+
+var t = async_test("HRMRawSensor_getHRMRawSensorData", {timeout: 30000}), onGetSuccessCB, onsuccessCB, HRMrawsensor, retValue = null;
+
+t.step(function () {
+    if(!tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.heart_rate_monitor.led_green") &&
+        !tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.heart_rate_monitor.led_red") &&
+        !tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.heart_rate_monitor.led_ir")) {
+        t.done();
+        return;
+    }
+    HRMrawsensor = tizen.sensorservice.getDefaultSensor("HRM_RAW");
+
+    add_result_callback(function () {
+        HRMrawsensor.stop();
+    });
+
+    onGetSuccessCB = t.step_func(function (sensorData) {
+        assert_equals(retValue, undefined, "getHRMRawSensorData returns wrong value");
+        t.done();
+    });
+
+    onsuccessCB = t.step_func(function () {
+        retValue = HRMrawsensor.getHRMRawSensorData(onGetSuccessCB);
+    });
+
+    HRMrawsensor.start(onsuccessCB);
+});
+
+
+
+}
+/*
+Copyright (c) 2015 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Authors:
+        Xiaoyan Qian <xy.qian@samsung.com>
+
+*/
+
+function HRMRawSensor_getHRMRawSensorData_misarg() {
+
+
+
+
+
+
+
+
+//==== TEST: HRMRawSensor_getHRMRawSensorData_misarg
+//==== LABEL Check if HRMRawSensor::getHRMRawSensorData() throws exception when successCallback is missing
+//==== SPEC Tizen Web API:System:Sensor:HRMRawSensor:getHRMRawSensorData M
+//==== SPEC_URL TBD
+//==== PRIORITY P2
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MMA
+
+setup({timeout: 30000});
+
+var t = async_test("HRMRawSensor_getHRMRawSensorData_misarg", {timeout: 30000}), onsuccessCB, HRMrawsensor;
+
+t.step(function () {
+    if(!tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.heart_rate_monitor.led_green") &&
+        !tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.heart_rate_monitor.led_red") &&
+        !tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.heart_rate_monitor.led_ir")) {
+        t.done();
+        return;
+    }
+    HRMrawsensor = tizen.sensorservice.getDefaultSensor("HRM_RAW");
+
+
+    add_result_callback(function () {
+        HRMrawsensor.stop();
+    });
+
+    onsuccessCB = t.step_func(function () {
+        assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        HRMrawsensor.getHRMRawSensorData();
+        }, TYPE_MISMATCH_EXCEPTION + " should be thrown");
+        t.done();
+    });
+
+    HRMrawsensor.start(onsuccessCB);
+});
+
+
+
+}
+/*
+Copyright (c) 2015 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Authors:
+        Xiaoyan Qian <xy.qian@samsung.com>
+
+*/
+
+function HRMRawSensor_getHRMRawSensorData_successCallback_invalid_cb() {
+
+
+
+
+
+
+
+
+//==== TEST: HRMRawSensor_getHRMRawSensorData_successCallback_invalid_cb
+//==== LABEL Check if HRMRawSensor::getHRMRawSensorData() method throws exception when successCallback is invalid
+//==== SPEC Tizen Web API:System:Sensor:HRMRawSensor:getHRMRawSensorData M
+//==== SPEC_URL TBD
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 30000});
+
+var t = async_test("HRMRawSensor_getHRMRawSensorData_successCallback_invalid_cb", {timeout: 30000}), invalidcallback, onsuccessCB, HRMrawsensor;
+
+t.step(function () {
+    if(!tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.heart_rate_monitor.led_green") &&
+        !tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.heart_rate_monitor.led_red") &&
+        !tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.heart_rate_monitor.led_ir")) {
+        t.done();
+        return;
+    }
+    HRMrawsensor = tizen.sensorservice.getDefaultSensor("HRM_RAW");
+
+    add_result_callback(function () {
+        HRMrawsensor.stop();
+    });
+
+    invalidcallback = {
+        onsuccess: t.step_func(function (sensorData) {
+            assert_unreached("getHRMRawSensorData() successcallback invoked")
+        })
+    };
+
+    onsuccessCB = t.step_func(function () {
+        assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+            HRMrawsensor.getHRMRawSensorData(invalidcallback);
+        }, TYPE_MISMATCH_EXCEPTION + " Should throw exception");
+        t.done();
+    });
+
+    HRMrawsensor.start(onsuccessCB);
+});
+
+
+
+}
+/*
+Copyright (c) 2015 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Authors:
+        Xiaoyan Qian <xy.qian@samsung.com>
+
+*/
+
+function HRMRawSensor_getHRMRawSensorData_successCallback_TypeMismatch() {
+
+
+
+
+
+
+
+
+//==== TEST: HRMRawSensor_getHRMRawSensorData_successCallback_TypeMismatch
+//==== LABEL Check if HRMRawSensor::getHRMRawSensorData() with incorrect successCallback argument throws exception
+//==== SPEC Tizen Web API:System:Sensor:HRMRawSensor:getHRMRawSensorData M
+//==== SPEC_URL TBD
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test("HRMRawSensor_getHRMRawSensorData_successCallback_TypeMismatch", {timeout: 30000}), exceptionName, i, conversionTable, onGetSuccessCB, onerrorCB, HRMrawsensor, onsuccessCB;
+
+t.step(function () {
+    if(!tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.heart_rate_monitor.led_green") &&
+        !tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.heart_rate_monitor.led_red") &&
+        !tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.heart_rate_monitor.led_ir")) {
+        t.done();
+        return;
+    }
+    HRMrawsensor = tizen.sensorservice.getDefaultSensor("HRM_RAW");
+
+
+    add_result_callback(function () {
+        HRMrawsensor.stop();
+    });
+
+    onerrorCB = t.step_func(function (error) {
+        assert_unreached("getHRMRawSensorData() error callback invoked: name:" + error.name + ", msg: " + error.message);
+    });
+
+    onsuccessCB = t.step_func(function () {
+        conversionTable = getTypeConversionExceptions("functionObject", false);
+        for (i = 0; i < conversionTable.length; i++) {
+            onGetSuccessCB = conversionTable[i][0];
+            exceptionName = conversionTable[i][1];
+            assert_throws({name: exceptionName}, function () {
+                HRMrawsensor.getHRMRawSensorData(onGetSuccessCB, onerrorCB);
+            }, exceptionName + " should be thrown - given incorrect successCallback.");
+        }
+        t.done();
+    });
+
+    HRMrawsensor.start(onsuccessCB);
+});
+
+
+
+}
+/*
+Copyright (c) 2015 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Authors:
+        Xiaoyan Qian <xy.qian@samsung.com>
+
+*/
+
+function HRMRawSensor_getHRMRawSensorData_with_errorCallback() {
+
+
+
+
+
+
+
+
+//==== TEST: HRMRawSensor_getHRMRawSensorData_with_errorCallback
+//==== LABEL Check if HRMRawSensor::getHRMRawSensorData() method works properly with optional argument
+//==== SPEC Tizen Web API:System:Sensor:HRMRawSensor:getHRMRawSensorData M
+//==== SPEC_URL TBD
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P1
+//==== TEST_CRITERIA MOA MR
+
+setup({timeout: 30000});
+
+var t = async_test("HRMRawSensor_getHRMRawSensorData_with_errorCallback", {timeout: 30000}), onGetSuccessCB, onsuccessCB, HRMrawsensor, retValue = null, onerrorCB;
+
+t.step(function () {
+    if(!tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.heart_rate_monitor.led_green") &&
+        !tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.heart_rate_monitor.led_red") &&
+        !tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.heart_rate_monitor.led_ir")) {
+        t.done();
+        return;
+    }
+    HRMrawsensor = tizen.sensorservice.getDefaultSensor("HRM_RAW");
+
+    add_result_callback(function () {
+        HRMrawsensor.stop();
+    });
+
+    onGetSuccessCB = t.step_func(function (HRMrawsensordata) {
+        assert_not_equals(HRMrawsensordata.lightIntensity, null, "Fail to getHRMRawSensorData");
+        assert_equals(retValue, undefined, "getHRMRawSensorData returns wrong value");
+        t.done();
+    });
+
+    onerrorCB = t.step_func(function (error) {
+        assert_unreached("getHRMRawSensorData() error callback invoked: name:" + error.name + ", msg: " + error.message);
+    });
+
+    onsuccessCB = t.step_func(function () {
+        retValue = HRMrawsensor.getHRMRawSensorData(onGetSuccessCB, onerrorCB);
+    });
+
+    HRMrawsensor.start(onsuccessCB);
+});
+
+
+
+}
+/*
+Copyright (c) 2015 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Authors:
+        Xiaoyan Qian <xy.qian@samsung.com>
+
+*/
+
+function HRMRawSensor_notexist() {
+
+
+
+
+
+
+
+
+//==== TEST: HRMRawSensor_notexist
+//==== LABEL Check if interface HRMRawSensor exists, it should not
+//==== SPEC Tizen Web API:System:Sensor:HRMRawSensor:HRMRawSensor U
+//==== SPEC_URL TBD
+//==== PRIORITY P3
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("HRMRawSensor");
+}, "HRMRawSensor_notexist");
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saleh Enam Shohag <saleh.enam@samsung.com>
+
+*/
+function LightSensor_extend() {
+
+
+
+
+
+
+
+
+//==== TEST: LightSensor_extend
+//==== LABEL Check if LightSensor is extendable
+//==== SPEC Tizen Web API:System:Sensor:LightSensor:LightSensor U
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA OBX
+
+test(function () {
+    var lightSensor = tizen.sensorservice.getDefaultSensor("LIGHT");
+    check_extensibility(lightSensor);
+}, "LightSensor_extend");
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+        Saleh Enam Shohag <saleh.enam@samsung.com>
+
+*/
+function LightSensor_getLightSensorData_errorCallback_invalid_cb() {
+
+
+
+
+
+
+
+
+//==== TEST: LightSensor_getLightSensorData_errorCallback_invalid_cb
+//==== LABEL Check if LightSensor::getLightSensorData() method throws exception when errorCallback is invalid
+//==== SPEC Tizen Web API:System:Sensor:LightSensor:getLightSensorData M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 30000});
+
+var t = async_test("LightSensor_getLightSensorData_errorCallback_invalid_cb", {timeout: 30000}), invalidcallback, onsuccessCB, lightSensor, onGetSuccessCB;
+
+t.step(function () {
+    lightSensor = tizen.sensorservice.getDefaultSensor("LIGHT");
+
+    add_result_callback(function () {
+        lightSensor.stop();
+    });
+
+    invalidcallback = {
+        onerror: t.step_func(function (sensorData) {
+            assert_unreached("getLightSensorData() errorCallback invoked");
+        })
+    };
+
+    onGetSuccessCB = t.step_func(function (sensorData) {
+        assert_unreached("SuccessCallback should not be called");
+    });
+
+    onsuccessCB = t.step_func(function () {
+        assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+            lightSensor.getLightSensorData(onGetSuccessCB, invalidcallback);
+        }, TYPE_MISMATCH_EXCEPTION + " Should throw exception");
+        t.done();
+    });
+
+    lightSensor.start(onsuccessCB);
+});
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+        Saleh Enam Shohag <saleh.enam@samsung.com>
+
+*/
+function LightSensor_getLightSensorData_errorCallback_invoked() {
+
+
+
+
+
+
+
+
+//==== TEST: LightSensor_getLightSensorData_errorCallback_invoked
+//==== LABEL Check exception in errorCallback of LightSensor::getLightSensorData() method
+//==== SPEC Tizen Web API:System:Sensor:LightSensor:getLightSensorData M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P2
+//==== TEST_CRITERIA MERRCB
+
+setup({timeout: 30000});
+
+var t = async_test("LightSensor_getLightSensorData_errorCallback_invoked", {timeout: 30000}), onerrorCB, onGetSuccessCB, lightSensor;
+
+t.step(function () {
+    lightSensor = tizen.sensorservice.getDefaultSensor("LIGHT");
+
+    add_result_callback(function () {
+        lightSensor.stop();
+    });
+
+    onGetSuccessCB = t.step_func(function (sensorData) {
+        assert_unreached("SuccessCallback should not be called");
+    });
+
+    onerrorCB = t.step_func(function (error) {
+        assert_equals("ServiceNotAvailableError", error.name, "Incorrect error name.");
+        t.done();
+    });
+
+    lightSensor.getLightSensorData(onGetSuccessCB, onerrorCB);
+});
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+        Saleh Enam Shohag <saleh.enam@samsung.com>
+
+*/
+function LightSensor_getLightSensorData_errorCallback_TypeMismatch() {
+
+
+
+
+
+
+
+
+//==== TEST: LightSensor_getLightSensorData_errorCallback_TypeMismatch
+//==== LABEL Check if LightSensor::getLightSensorData() with incorrect errorCallback argument throws exception
+//==== SPEC Tizen Web API:System:Sensor:LightSensor:getLightSensorData M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test("LightSensor_getLightSensorData_errorCallback_TypeMismatch", {timeout: 30000}), exceptionName, i, conversionTable, onGetSuccessCB, onerrorCB, lightSensor, onsuccessCB;
+
+t.step(function () {
+    lightSensor = tizen.sensorservice.getDefaultSensor("LIGHT");
+
+    add_result_callback(function () {
+        lightSensor.stop();
+    });
+
+    onGetSuccessCB = t.step_func(function () {
+        assert_unreached("Unexpected successCallback");
+    });
+
+    onsuccessCB = t.step_func(function () {
+        conversionTable = getTypeConversionExceptions("functionObject", true);
+        for (i = 0; i < conversionTable.length; i++) {
+            onerrorCB = conversionTable[i][0];
+            exceptionName = conversionTable[i][1];
+            assert_throws({name: exceptionName}, function () {
+                lightSensor.getLightSensorData(onGetSuccessCB, onerrorCB);
+            }, exceptionName + " should be thrown - given incorrect errorCallback.");
+        }
+        t.done();
+    });
+
+    lightSensor.start(onsuccessCB);
+});
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+        Saleh Enam Shohag <saleh.enam@samsung.com>
+
+*/
+function LightSensor_getLightSensorData_exist() {
+
+
+
+
+
+
+
+
+//==== TEST: LightSensor_getLightSensorData_exist
+//==== LABEL Check if LightSensor::getLightSensorData() method exists
+//==== SPEC Tizen Web API:System:Sensor:LightSensor:getLightSensorData M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    var lightSensor;
+    lightSensor = tizen.sensorservice.getDefaultSensor("LIGHT");
+    assert_true("getLightSensorData" in lightSensor, "No getLightSensorData method in lightSensor");
+    check_method_exists(lightSensor, "getLightSensorData");
+}, "LightSensor_getLightSensorData_exist");
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+        Saleh Enam Shohag <saleh.enam@samsung.com>
+
+*/
+function LightSensor_getLightSensorData() {
+
+
+
+
+
+
+
+
+//==== TEST: LightSensor_getLightSensorData
+//==== LABEL Check if LightSensor::getLightSensorData() method works properly
+//==== SPEC Tizen Web API:System:Sensor:LightSensor:getLightSensorData M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P1
+//==== TEST_CRITERIA MMINA MR
+
+setup({timeout: 30000});
+
+var t = async_test("LightSensor_getLightSensorData", {timeout: 30000}), onGetSuccessCB, onsuccessCB, lightSensor, retValue = null;
+
+t.step(function () {
+    lightSensor = tizen.sensorservice.getDefaultSensor("LIGHT");
+
+    add_result_callback(function () {
+        lightSensor.stop();
+    });
+
+    onGetSuccessCB = t.step_func(function (light) {
+        assert_not_equals(light.lightLevel, null, "Fail to getLightSensorData");
+        assert_equals(retValue, undefined, "getLightSensorData returns wrong value");
+        t.done();
+    });
+
+    onsuccessCB = t.step_func(function () {
+        retValue = lightSensor.getLightSensorData(onGetSuccessCB);
+    });
+
+    lightSensor.start(onsuccessCB);
+});
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+        Saleh Enam Shohag <saleh.enam@samsung.com>
+
+*/
+function LightSensor_getLightSensorData_misarg() {
+
+
+
+
+
+
+
+
+//==== TEST: LightSensor_getLightSensorData_misarg
+//==== LABEL Check if LightSensor::getLightSensorData() throws exception when successCallback is missing
+//==== SPEC Tizen Web API:System:Sensor:LightSensor:getLightSensorData M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P2
+//==== TEST_CRITERIA MMA
+
+setup({timeout: 30000});
+
+var t = async_test("LightSensor_getLightSensorData_misarg", {timeout: 30000}), onsuccessCB, lightSensor;
+
+t.step(function () {
+    lightSensor = tizen.sensorservice.getDefaultSensor("LIGHT");
+
+    add_result_callback(function () {
+        lightSensor.stop();
+    });
+
+    onsuccessCB = t.step_func(function () {
+        assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+            lightSensor.getLightSensorData();
+        }, TYPE_MISMATCH_EXCEPTION + " should be thrown");
+        t.done();
+    });
+
+    lightSensor.start(onsuccessCB);
+});
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saleh Enam Shohag <saleh.enam@samsung.com>
+
+*/
+function LightSensor_getLightSensorData_successCallback_invalid_cb() {
+
+
+
+
+
+
+
+
+//==== TEST: LightSensor_getLightSensorData_successCallback_invalid_cb
+//==== LABEL Check if LightSensor::getLightSensorData() method throws exception when successCallback is invalid
+//==== SPEC Tizen Web API:System:Sensor:LightSensor:getLightSensorData M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 30000});
+
+var t = async_test("LightSensor_getLightSensorData_successCallback_invalid_cb", {timeout: 30000}), invalidcallback, onsuccessCB, lightSensor;
+
+t.step(function () {
+    lightSensor = tizen.sensorservice.getDefaultSensor("LIGHT");
+
+    add_result_callback(function () {
+        lightSensor.stop();
+    });
+
+    invalidcallback = {
+        onsuccess: t.step_func(function (sensorData) {
+            assert_unreached("getLightSensorData() successcallback invoked");
+        })
+    };
+
+    onsuccessCB = t.step_func(function () {
+        assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+            lightSensor.getLightSensorData(invalidcallback);
+        }, "Should throw exception");
+        t.done();
+    });
+
+    lightSensor.start(onsuccessCB);
+});
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+        Saleh Enam Shohag <saleh.enam@samsung.com>
+
+*/
+function LightSensor_getLightSensorData_successCallback_TypeMismatch() {
+
+
+
+
+
+
+
+
+//==== TEST: LightSensor_getLightSensorData_successCallback_TypeMismatch
+//==== LABEL Check if LightSensor::getLightSensorData() with incorrect successCallback argument throws exception
+//==== SPEC Tizen Web API:System:Sensor:LightSensor:getLightSensorData M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test("LightSensor_getLightSensorData_successCallback_TypeMismatch", {timeout: 30000}), exceptionName, i, conversionTable, onGetSuccessCB, onerrorCB, lightSensor, onsuccessCB;
+
+t.step(function () {
+    lightSensor = tizen.sensorservice.getDefaultSensor("LIGHT");
+
+    add_result_callback(function () {
+        lightSensor.stop();
+    });
+
+    onerrorCB = t.step_func(function (error) {
+        assert_unreached("getLightSensorData() error callback invoked: name:" +
+            error.name + ", msg: " + error.message);
+    });
+
+    onsuccessCB = t.step_func(function () {
+        conversionTable = getTypeConversionExceptions("functionObject", false);
+        for (i = 0; i < conversionTable.length; i++) {
+            onGetSuccessCB = conversionTable[i][0];
+            exceptionName = conversionTable[i][1];
+            assert_throws({name: exceptionName}, function () {
+                lightSensor.getLightSensorData(onGetSuccessCB, onerrorCB);
+            }, exceptionName + " should be thrown - given incorrect successCallback.");
+        }
+        t.done();
+    });
+
+    lightSensor.start(onsuccessCB);
+});
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+        Saleh Enam Shohag <saleh.enam@samsung.com>
+
+*/
+function LightSensor_getLightSensorData_with_errorCallback() {
+
+
+
+
+
+
+
+
+//==== TEST: LightSensor_getLightSensorData_with_errorCallback
+//==== LABEL Check if LightSensor::getLightSensorData() method works properly with optional argument
+//==== SPEC Tizen Web API:System:Sensor:LightSensor:getLightSensorData M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P1
+//==== TEST_CRITERIA MOA
+
+setup({timeout: 30000});
+
+var t = async_test("LightSensor_getLightSensorData_with_errorCallback", {timeout: 30000}), onGetSuccessCB, onsuccessCB, lightSensor, onerrorCB;
+
+t.step(function () {
+    lightSensor = tizen.sensorservice.getDefaultSensor("LIGHT");
+
+    add_result_callback(function () {
+        lightSensor.stop();
+    });
+
+    onGetSuccessCB = t.step_func(function (light) {
+        assert_not_equals(light.lightLevel, null, "Fail to getLightSensorData");
+        t.done();
+    });
+
+    onerrorCB = t.step_func(function (error) {
+        assert_unreached("getLightSensorData() error callback invoked: name: " + error.message + ", msg: " + error.name);
+    });
+
+    onsuccessCB = t.step_func(function () {
+        lightSensor.getLightSensorData(onGetSuccessCB, onerrorCB);
+    });
+
+    lightSensor.start(onsuccessCB);
+});
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saleh Enam Shohag <saleh.enam@samsung.com>
+
+*/
+function LightSensor_notexist() {
+
+
+
+
+
+
+
+
+//==== TEST: LightSensor_notexist
+//==== LABEL Check if interface LightSensor exists, it should not
+//==== SPEC Tizen Web API:System:Sensor:LightSensor:LightSensor U
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("LightSensor");
+}, "LightSensor_notexist");
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saleh Enam Shohag <saleh.enam@samsung.com>
+        Md. Samsuddin Alam <ss.alam@samsung.com>
+
+*/
+function MagneticSensor_extend() {
+
+
+
+
+
+
+
+
+//==== TEST: MagneticSensor_extend
+//==== LABEL Check if MagneticSensor is extendable
+//==== SPEC Tizen Web API:System:Sensor:MagneticSensor:MagneticSensor U
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA OBX
+
+test(function () {
+    var magneticSensor = tizen.sensorservice.getDefaultSensor("MAGNETIC");
+    check_extensibility(magneticSensor);
+}, "MagneticSensor_extend");
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saleh Enam Shohag <saleh.enam@samsung.com>
+
+*/
+function MagneticSensor_getMagneticSensorData_errorCallback_invalid_cb() {
+
+
+
+
+
+
+
+
+//==== TEST: MagneticSensor_getMagneticSensorData_errorCallback_invalid_cb
+//==== LABEL Check if MagneticSensor::getMagneticSensorData() method throws exception when errorCallback is invalid
+//==== SPEC Tizen Web API:System:Sensor:MagneticSensor:getMagneticSensorData M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 30000});
+
+var t = async_test("MagneticSensor_getMagneticSensorData_errorCallback_invalid_cb", {timeout: 30000}), invalidcallback, onsuccessCB, magneticSensor, onGetSuccessCB;
+
+t.step(function () {
+    magneticSensor = tizen.sensorservice.getDefaultSensor("MAGNETIC");
+
+    add_result_callback(function () {
+        magneticSensor.stop();
+    });
+
+    invalidcallback = {
+        onerror: t.step_func(function (sensorData) {
+            assert_unreached("getMagneticSensorData() successcallback invoked");
+        })
+    };
+
+    onGetSuccessCB = t.step_func(function (sensorData) {
+        assert_unreached("SuccessCallback should not be called");
+    });
+
+    onsuccessCB = t.step_func(function () {
+        assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+            magneticSensor.getMagneticSensorData(onGetSuccessCB, invalidcallback);
+        }, TYPE_MISMATCH_EXCEPTION + " Should throw exception");
+        t.done();
+    });
+
+    magneticSensor.start(onsuccessCB);
+});
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+        Md. Samsuddin Alam <ss.alam@samsung.com>
+
+*/
+function MagneticSensor_getMagneticSensorData_errorCallback_invoked() {
+
+
+
+
+
+
+
+
+//==== TEST: MagneticSensor_getMagneticSensorData_errorCallback_invoked
+//==== LABEL Check exception in errorCallback of MagneticSensor::getMagneticSensorData() method
+//==== SPEC Tizen Web API:System:Sensor:MagneticSensor:getMagneticSensorData M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P2
+//==== TEST_CRITERIA MERRCB
+
+setup({timeout: 30000});
+
+var t = async_test("MagneticSensor_getMagneticSensorData_errorCallback_invoked", {timeout: 30000}), onerrorCB, onGetSuccessCB, magneticSensor;
+
+t.step(function () {
+    magneticSensor = tizen.sensorservice.getDefaultSensor("MAGNETIC");
+
+    onGetSuccessCB = t.step_func(function (sensorData) {
+        assert_unreached("SuccessCallback should not be called");
+    });
+
+    onerrorCB = t.step_func(function (error) {
+        assert_equals("ServiceNotAvailableError", error.name, "Error callback should be thrown with error: " + error.name + ".");
+        t.done();
+    });
+
+    magneticSensor.getMagneticSensorData(onGetSuccessCB, onerrorCB);
+});
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+        Md. Samsuddin Alam <ss.alam@samsung.com>
+
+*/
+function MagneticSensor_getMagneticSensorData_errorCallback_TypeMismatch() {
+
+
+
+
+
+
+
+
+//==== TEST: MagneticSensor_getMagneticSensorData_errorCallback_TypeMismatch
+//==== LABEL Check if MagneticSensor::getMagneticSensorData() with incorrect errorCallback argument throws exception
+//==== SPEC Tizen Web API:System:Sensor:MagneticSensor:getMagneticSensorData M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test("MagneticSensor_getMagneticSensorData_errorCallback_TypeMismatch", {timeout: 30000}), exceptionName, i, conversionTable, onGetSuccessCB, onerrorCB, magneticSensor, onsuccessCB;
+
+t.step(function () {
+    magneticSensor = tizen.sensorservice.getDefaultSensor("MAGNETIC");
+
+    add_result_callback(function () {
+        magneticSensor.stop();
+    });
+
+    onGetSuccessCB = t.step_func(function () {
+        assert_unreached("Unexpected successCallback");
+    });
+
+    onsuccessCB = t.step_func(function () {
+        conversionTable = getTypeConversionExceptions("functionObject", true);
+        for (i = 0; i < conversionTable.length; i++) {
+            onerrorCB = conversionTable[i][0];
+            exceptionName = conversionTable[i][1];
+            assert_throws({name: exceptionName}, function () {
+                magneticSensor.getMagneticSensorData(onGetSuccessCB, onerrorCB);
+            }, exceptionName + " should be thrown - given incorrect errorCallback.");
+        }
+        t.done();
+    });
+
+    magneticSensor.start(onsuccessCB);
+});
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+        Md. Samsuddin Alam <ss.alam@samsung.com>
+
+*/
+function MagneticSensor_getMagneticSensorData_exist() {
+
+
+
+
+
+
+
+
+//==== TEST: MagneticSensor_getMagneticSensorData_exist
+//==== LABEL Check if MagneticSensor::getMagneticSensorData() method exists
+//==== SPEC Tizen Web API:System:Sensor:MagneticSensor:getMagneticSensorData M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    var magneticSensor;
+    magneticSensor = tizen.sensorservice.getDefaultSensor("MAGNETIC");
+    assert_true("getMagneticSensorData" in magneticSensor, "No getMagneticSensorData method in magneticSensor");
+    check_method_exists(magneticSensor, "getMagneticSensorData");
+}, "MagneticSensor_getMagneticSensorData_exist");
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+        Md. Samsuddin Alam <ss.alam@samsung.com>
+
+*/
+function MagneticSensor_getMagneticSensorData() {
+
+
+
+
+
+
+
+
+//==== TEST: MagneticSensor_getMagneticSensorData
+//==== LABEL Check if MagneticSensor::getMagneticSensorData() method works properly
+//==== SPEC Tizen Web API:System:Sensor:MagneticSensor:getMagneticSensorData M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR MMINA
+
+setup({timeout: 30000});
+
+var t = async_test("MagneticSensor_getMagneticSensorData", {timeout: 30000}), onGetSuccessCB, onsuccessCB, magneticSensor, retValue = null;
+
+t.step(function () {
+    magneticSensor = tizen.sensorservice.getDefaultSensor("MAGNETIC");
+
+    add_result_callback(function () {
+        magneticSensor.stop();
+    });
+
+    onGetSuccessCB = t.step_func(function (magnetic) {
+        assert_not_equals(magnetic.x, null, "Fail to getMagneticSensorData");
+        assert_not_equals(magnetic.y, null, "Fail to getMagneticSensorData");
+        assert_not_equals(magnetic.z, null, "Fail to getMagneticSensorData");
+        assert_not_equals(magnetic.accuracy, null, "Fail to getMagneticSensorData");
+        assert_equals(retValue, undefined, "getMagneticSensorData returns wrong value");
+        t.done();
+    });
+
+    onsuccessCB = t.step_func(function () {
+        retValue = magneticSensor.getMagneticSensorData(onGetSuccessCB);
+    });
+
+    magneticSensor.start(onsuccessCB);
+});
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+        Md. Samsuddin Alam <ss.alam@samsung.com>
+
+*/
+function MagneticSensor_getMagneticSensorData_misarg() {
+
+
+
+
+
+
+
+
+//==== TEST: MagneticSensor_getMagneticSensorData_misarg
+//==== LABEL Check if MagneticSensor::getMagneticSensorData() throws exception when successCallback is missing
+//==== SPEC Tizen Web API:System:Sensor:MagneticSensor:getMagneticSensorData M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P2
+//==== TEST_CRITERIA MMA
+
+setup({timeout: 30000});
+
+var t = async_test("MagneticSensor_getMagneticSensorData_misarg", {timeout: 30000}), onsuccessCB, magneticSensor;
+
+t.step(function () {
+    magneticSensor = tizen.sensorservice.getDefaultSensor("MAGNETIC");
+
+    add_result_callback(function () {
+        magneticSensor.stop();
+    });
+
+    onsuccessCB = t.step_func(function () {
+        assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+            magneticSensor.getMagneticSensorData();
+        }, TYPE_MISMATCH_EXCEPTION + " should be thrown");
+        t.done();
+    });
+
+    magneticSensor.start(onsuccessCB);
+});
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saleh Enam Shohag <saleh.enam@samsung.com>
+        Md. Samsuddin Alam <ss.alam@samsung.com>
+
+*/
+function MagneticSensor_getMagneticSensorData_successCallback_invalid_cb() {
+
+
+
+
+
+
+
+
+//==== TEST: MagneticSensor_getMagneticSensorData_successCallback_invalid_cb
+//==== LABEL Check if MagneticSensor::getMagneticSensorData() method throws exception when successCallback is invalid
+//==== SPEC Tizen Web API:System:Sensor:MagneticSensor:getMagneticSensorData M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 30000});
+
+var t = async_test("MagneticSensor_getMagneticSensorData_successCallback_invalid_cb", {timeout: 30000}), invalidcallback, onsuccessCB, magneticSensor;
+
+t.step(function () {
+    magneticSensor = tizen.sensorservice.getDefaultSensor("MAGNETIC");
+
+    add_result_callback(function () {
+        magneticSensor.stop();
+    });
+
+    invalidcallback = {
+        onsuccess: t.step_func(function (sensorData) {
+            assert_unreached("getMagneticSensorData() successcallback invoked");
+        })
+    };
+
+    onsuccessCB = t.step_func(function () {
+        assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+            magneticSensor.getMagneticSensorData(invalidcallback);
+        }, "Should throw exception");
+        t.done();
+    });
+
+    magneticSensor.start(onsuccessCB);
+});
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+        Md. Samsuddin Alam <ss.alam@samsung.com>
+
+*/
+function MagneticSensor_getMagneticSensorData_successCallback_TypeMismatch() {
+
+
+
+
+
+
+
+
+//==== TEST: MagneticSensor_getMagneticSensorData_successCallback_TypeMismatch
+//==== LABEL Check if MagneticSensor::getMagneticSensorData() with incorrect successCallback argument throws exception
+//==== SPEC Tizen Web API:System:Sensor:MagneticSensor:getMagneticSensorData M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test("MagneticSensor_getMagneticSensorData_successCallback_TypeMismatch", {timeout: 30000}), exceptionName, i, conversionTable, onGetSuccessCB, onerrorCB, magneticSensor, onsuccessCB;
+
+t.step(function () {
+    magneticSensor = tizen.sensorservice.getDefaultSensor("MAGNETIC");
+
+    add_result_callback(function () {
+        magneticSensor.stop();
+    });
+
+    onerrorCB = t.step_func(function (error) {
+        assert_unreached("getMagneticSensorData() error callback invoked: name:" + error.name + ", msg: " + error.message);
+    });
+
+    onsuccessCB = t.step_func(function () {
+        conversionTable = getTypeConversionExceptions("functionObject", false);
+        for (i = 0; i < conversionTable.length; i++) {
+            onGetSuccessCB = conversionTable[i][0];
+            exceptionName = conversionTable[i][1];
+            assert_throws({name: exceptionName}, function () {
+                magneticSensor.getMagneticSensorData(onGetSuccessCB, onerrorCB);
+            }, exceptionName + " should be thrown - given incorrect successCallback.");
+        }
+        t.done();
+    });
+
+    magneticSensor.start(onsuccessCB);
+});
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+        Md. Samsuddin Alam <ss.alam@samsung.com>
+
+*/
+function MagneticSensor_getMagneticSensorData_with_errorCallback() {
+
+
+
+
+
+
+
+
+//==== TEST: MagneticSensor_getMagneticSensorData_with_errorCallback
+//==== LABEL Check if MagneticSensor::getMagneticSensorData() method works properly with optional argument
+//==== SPEC Tizen Web API:System:Sensor:MagneticSensor:getMagneticSensorData M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR MOA
+
+setup({timeout: 30000});
+
+var t = async_test("MagneticSensor_getMagneticSensorData_with_errorCallback", {timeout: 30000}), onGetSuccessCB, onsuccessCB, magneticSensor, retValue = null, onerrorCB;
+
+t.step(function () {
+    magneticSensor = tizen.sensorservice.getDefaultSensor("MAGNETIC");
+
+    add_result_callback(function () {
+        magneticSensor.stop();
+    });
+
+    onGetSuccessCB = t.step_func(function (magnetic) {
+        assert_not_equals(magnetic.x, null, "Fail to getMagneticSensorData");
+        assert_not_equals(magnetic.y, null, "Fail to getMagneticSensorData");
+        assert_not_equals(magnetic.z, null, "Fail to getMagneticSensorData");
+        assert_not_equals(magnetic.accuracy, null, "Fail to getMagneticSensorData");
+        assert_equals(retValue, undefined, "getMagneticSensorData returns wrong value");
+        t.done();
+    });
+
+    onerrorCB = t.step_func(function (error) {
+        assert_unreached("getMagneticSensorData() error callback invoked: name: " + error.message + ", msg: " + error.name);
+    });
+
+    onsuccessCB = t.step_func(function () {
+        retValue = magneticSensor.getMagneticSensorData(onGetSuccessCB, onerrorCB);
+    });
+
+    magneticSensor.start(onsuccessCB);
+});
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saleh Enam Shohag <saleh.enam@samsung.com>
+
+*/
+function MagneticSensor_notexist() {
+
+
+
+
+
+
+
+
+//==== TEST: MagneticSensor_notexist
+//==== LABEL Check if interface MagneticSensor exists, it should not
+//==== SPEC Tizen Web API:System:Sensor:MagneticSensor:MagneticSensor U
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("MagneticSensor");
+}, "MagneticSensor_notexist");
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saleh Enam Shohag <saleh.enam@samsung.com>
+
+*/
+function PressureSensor_extend() {
+
+
+
+
+
+
+
+
+//==== TEST: PressureSensor_extend
+//==== LABEL Check if PressureSensor is extendable
+//==== SPEC Tizen Web API:System:Sensor:PressureSensor:PressureSensor U
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA OBX
+
+test(function () {
+    var pressureSensor = tizen.sensorservice.getDefaultSensor("PRESSURE");
+    check_extensibility(pressureSensor);
+}, "PressureSensor_extend");
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saleh Enam Shohag <saleh.enam@samsung.com>
+
+*/
+function PressureSensor_getPressureSensorData_errorCallback_invalid_cb() {
+
+
+
+
+
+
+
+
+//==== TEST: PressureSensor_getPressureSensorData_errorCallback_invalid_cb
+//==== LABEL Check if PressureSensor::getPressureSensorData() method throws exception when errorCallback is invalid
+//==== SPEC Tizen Web API:System:Sensor:PressureSensor:getPressureSensorData M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 30000});
+
+var t = async_test("PressureSensor_getPressureSensorData_errorCallback_invalid_cb", {timeout: 30000}), invalidcallback, onsuccessCB, pressureSensor, onGetSuccessCB;
+
+t.step(function () {
+    pressureSensor = tizen.sensorservice.getDefaultSensor("PRESSURE");
+
+    add_result_callback(function () {
+        pressureSensor.stop();
+    });
+
+    invalidcallback = {
+        onerror: t.step_func(function (sensorData) {
+            assert_unreached("getPressureSensorData() successcallback invoked");
+        })
+    };
+
+    onGetSuccessCB = t.step_func(function (sensorData) {
+        assert_unreached("SuccessCallback should not be called");
+    });
+
+    onsuccessCB = t.step_func(function () {
+        assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+            pressureSensor.getPressureSensorData(onGetSuccessCB, invalidcallback);
+        }, TYPE_MISMATCH_EXCEPTION + "Should throw exception");
+        t.done();
+    });
+
+    pressureSensor.start(onsuccessCB);
+});
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+        Saleh Enam Shohag <saleh.enam@samsung.com>
+
+*/
+function PressureSensor_getPressureSensorData_errorCallback_invoked() {
+
+
+
+
+
+
+
+
+//==== TEST: PressureSensor_getPressureSensorData_errorCallback_invoked
+//==== LABEL Check exception in errorCallback of getPressureSensorData method
+//==== SPEC Tizen Web API:System:Sensor:PressureSensor:getPressureSensorData M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P2
+//==== TEST_CRITERIA MERRCB
+
+setup({timeout: 30000});
+
+var t = async_test("PressureSensor_getPressureSensorData_errorCallback_invoked", {timeout: 30000}), onerrorCB, onGetSuccessCB, pressureSensor;
+
+t.step(function () {
+    pressureSensor = tizen.sensorservice.getDefaultSensor("PRESSURE");
+
+    onGetSuccessCB = t.step_func(function (sensorData) {
+        assert_unreached("SuccessCallback should not be called");
+    });
+
+    onerrorCB = t.step_func(function (error) {
+        assert_equals("ServiceNotAvailableError", error.name, "Error callback should be thrown with error: " + error.name);
+        t.done();
+    });
+
+    pressureSensor.getPressureSensorData(onGetSuccessCB, onerrorCB);
+});
+
+
+}
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+        Saleh Enam Shohag <saleh.enam@samsung.com>
+
+*/
+function PressureSensor_getPressureSensorData_errorCallback_TypeMismatch() {
+
+
+
+
+
+
+
+
+//==== TEST: PressureSensor_getPressureSensorData_errorCallback_TypeMismatch
+//==== LABEL Check if PressureSensor::getPressureSensorData() with incorrect errorCallback argument throws exception
+//==== SPEC Tizen Web API:System:Sensor:PressureSensor:getPressureSensorData M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 90000});
+
+var t = async_test("PressureSensor_getPressureSensorData_errorCallback_TypeMismatch", {timeout: 90000}), exceptionName, i, conversionTable, onGetSuccessCB, onerrorCB, pressureSensor, onsuccessCB;
+
+t.step(function () {
+    pressureSensor = tizen.sensorservice.getDefaultSensor("PRESSURE");
+
+    add_result_callback(function () {
+        pressureSensor.stop();
+    });
+
+    onGetSuccessCB = t.step_func(function () {
+        assert_unreached("Unexpected successCallback");
+    });
+
+    onsuccessCB = t.step_func(function () {
+        conversionTable = getTypeConversionExceptions("functionObject", true);
+        for (i = 0; i < conversionTable.length; i++) {
+            onerrorCB = conversionTable[i][0];
+            exceptionName = conversionTable[i][1];
+            assert_throws({name: exceptionName}, function () {
+                pressureSensor.getPressureSensorData(onGetSuccessCB, onerrorCB);
+            }, exceptionName + " should be thrown - given incorrect errorCallback.");
+        }
+        t.done();
+    });
+
+    pressureSensor.start(onsuccessCB);
+});
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+        Saleh Enam Shohag <saleh.enam@samsung.com>
+
+*/
+function PressureSensor_getPressureSensorData_exist() {
+
+
+
+
+
+
+
+
+//==== TEST: PressureSensor_getPressureSensorData_exist
+//==== LABEL Check if PressureSensor::getPressureSensorData() method exists
+//==== SPEC Tizen Web API:System:Sensor:PressureSensor:getPressureSensorData M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    var pressureSensor;
+    pressureSensor = tizen.sensorservice.getDefaultSensor("PRESSURE");
+    assert_true("getPressureSensorData" in pressureSensor, "No getPressureSensorData method in pressureSensor");
+    check_method_exists(pressureSensor, "getPressureSensorData");
+}, "PressureSensor_getPressureSensorData_exist");
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+        Saleh Enam Shohag <saleh.enam@samsung.com>
+
+*/
+function PressureSensor_getPressureSensorData() {
+
+
+
+
+
+
+
+
+//==== TEST: PressureSensor_getPressureSensorData
+//==== LABEL Check if PressureSensor::getPressureSensorData() method works properly
+//==== SPEC Tizen Web API:System:Sensor:PressureSensor:getPressureSensorData M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P1
+//==== TEST_CRITERIA MMINA MR
+
+setup({timeout: 30000});
+
+var t = async_test("PressureSensor_getPressureSensorData", {timeout: 30000}), onGetSuccessCB, onsuccessCB, pressureSensor, retValue = null;
+
+t.step(function () {
+    pressureSensor = tizen.sensorservice.getDefaultSensor("PRESSURE");
+
+    add_result_callback(function () {
+        pressureSensor.stop();
+    });
+
+    onGetSuccessCB = t.step_func(function (sensorData) {
+        assert_equals(retValue, undefined, "getPressureSensorData returns wrong value");
+        t.done();
+    });
+
+    onsuccessCB = t.step_func(function () {
+        retValue = pressureSensor.getPressureSensorData(onGetSuccessCB);
+    });
+
+    pressureSensor.start(onsuccessCB);
+});
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+        Saleh Enam Shohag <saleh.enam@samsung.com>
+
+*/
+function PressureSensor_getPressureSensorData_misarg() {
+
+
+
+
+
+
+
+
+//==== TEST: PressureSensor_getPressureSensorData_misarg
+//==== LABEL Check if PressureSensor::getPressureSensorData() throws exception when successCallback is missing
+//==== SPEC Tizen Web API:System:Sensor:PressureSensor:getPressureSensorData M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P2
+//==== TEST_CRITERIA MMA
+
+setup({timeout: 30000});
+
+var t = async_test("PressureSensor_getPressureSensorData_misarg", {timeout: 30000}), onsuccessCB, pressureSensor;
+
+t.step(function () {
+    pressureSensor = tizen.sensorservice.getDefaultSensor("PRESSURE");
+
+    add_result_callback(function () {
+        pressureSensor.stop();
+    });
+
+    onsuccessCB = t.step_func(function () {
+        assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+            pressureSensor.getPressureSensorData();
+        }, TYPE_MISMATCH_EXCEPTION + " should be thrown.");
+        t.done();
+    });
+
+    pressureSensor.start(onsuccessCB);
+});
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saleh Enam Shohag <saleh.enam@samsung.com>
+
+*/
+function PressureSensor_getPressureSensorData_successCallback_invalid_cb() {
+
+
+
+
+
+
+
+
+//==== TEST: PressureSensor_getPressureSensorData_successCallback_invalid_cb
+//==== LABEL Check if PressureSensor::getPressureSensorData() method throws exception when successCallback is invalid
+//==== SPEC Tizen Web API:System:Sensor:PressureSensor:getPressureSensorData M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 30000});
+
+var t = async_test("PressureSensor_getPressureSensorData_successCallback_invalid_cb", {timeout: 30000}), invalidCallback, onsuccessCB, pressureSensor;
+
+t.step(function () {
+    pressureSensor = tizen.sensorservice.getDefaultSensor("PRESSURE");
+
+    add_result_callback(function () {
+        pressureSensor.stop();
+    });
+
+    invalidCallback = {
+        onsuccess: t.step_func(function (sensorData) {
+            assert_unreached("getPressureSensorData() successcallback invoked");
+        })
+    };
+
+    onsuccessCB = t.step_func(function () {
+        assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+            pressureSensor.getPressureSensorData(invalidCallback);
+        }, "Should throw exception");
+        t.done();
+    });
+
+    pressureSensor.start(onsuccessCB);
+});
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+        Saleh Enam Shohag <saleh.enam@samsung.com>
+
+*/
+function PressureSensor_getPressureSensorData_successCallback_TypeMismatch() {
+
+
+
+
+
+
+
+
+//==== TEST: PressureSensor_getPressureSensorData_successCallback_TypeMismatch
+//==== LABEL Check if PressureSensor::getPressureSensorData() with incorrect successCallback argument throws exception
+//==== SPEC Tizen Web API:System:Sensor:PressureSensor:getPressureSensorData M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test("PressureSensor_getPressureSensorData_successCallback_TypeMismatch", {timeout: 30000}), exceptionName, i, conversionTable, onGetSuccessCB, onerrorCB, pressureSensor, onsuccessCB;
+
+t.step(function () {
+    pressureSensor = tizen.sensorservice.getDefaultSensor("PRESSURE");
+
+    add_result_callback(function () {
+        pressureSensor.stop();
+    });
+
+    onerrorCB = t.step_func(function (error) {
+        assert_unreached("getPressureSensorData() error callback invoked: name:" + error.name + ", msg: " + error.message);
+    });
+
+    onsuccessCB = t.step_func(function () {
+        conversionTable = getTypeConversionExceptions("functionObject", false);
+        for (i = 0; i < conversionTable.length; i++) {
+            onGetSuccessCB = conversionTable[i][0];
+            exceptionName = conversionTable[i][1];
+            assert_throws({name: exceptionName}, function () {
+                pressureSensor.getPressureSensorData(onGetSuccessCB, onerrorCB);
+            }, exceptionName + " should be thrown - given incorrect successCallback.");
+        }
+        t.done();
+    });
+
+    pressureSensor.start(onsuccessCB);
+});
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+        Saleh Enam Shohag <saleh.enam@samsung.com>
+
+*/
+function PressureSensor_getPressureSensorData_with_errorCallback() {
+
+
+
+
+
+
+
+
+//==== TEST: PressureSensor_getPressureSensorData_with_errorCallback
+//==== LABEL Check if PressureSensor::getPressureSensorData() method works properly with optional argument
+//==== SPEC Tizen Web API:System:Sensor:PressureSensor:getPressureSensorData M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P1
+//==== TEST_CRITERIA MOA MR
+
+setup({timeout: 30000});
+
+var t = async_test("PressureSensor_getPressureSensorData_with_errorCallback", {timeout: 30000}), onGetSuccessCB, onsuccessCB, pressureSensor, retValue = null, onerrorCB;
+
+t.step(function () {
+    pressureSensor = tizen.sensorservice.getDefaultSensor("PRESSURE");
+
+    add_result_callback(function () {
+        pressureSensor.stop();
+    });
+
+    onGetSuccessCB = t.step_func(function (pressure) {
+        assert_not_equals(pressure.pressure, null, "Fail to getPressureSensorData");
+        assert_equals(retValue, undefined, "getPressureSensorData returns wrong value");
+        t.done();
+    });
+
+    onerrorCB = t.step_func(function (error) {
+        assert_unreached("getPressureSensorData() error callback invoked: name:" + error.name + ", msg: " + error.message);
+    });
+
+    onsuccessCB = t.step_func(function () {
+        retValue = pressureSensor.getPressureSensorData(onGetSuccessCB, onerrorCB);
+    });
+
+    pressureSensor.start(onsuccessCB);
+});
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saleh Enam Shohag <saleh.enam@samsung.com>
+
+*/
+function PressureSensor_notexist() {
+
+
+
+
+
+
+
+
+//==== TEST: PressureSensor_notexist
+//==== LABEL Check if interface PressureSensor exists, it should not
+//==== SPEC Tizen Web API:System:Sensor:PressureSensor:PressureSensor U
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("PressureSensor");
+}, "PressureSensor_notexist");
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saleh Enam Shohag <saleh.enam@samsung.com>
+
+*/
+function ProximitySensor_extend() {
+
+
+
+
+
+
+
+
+//==== TEST: ProximitySensor_extend
+//==== LABEL Check if ProximitySensor is extendable
+//==== SPEC Tizen Web API:System:Sensor:ProximitySensor:ProximitySensor U
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA OBX
+
+test(function () {
+    var proximitySensor = tizen.sensorservice.getDefaultSensor("PROXIMITY");
+    check_extensibility(proximitySensor);
+}, "ProximitySensor_extend");
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saleh Enam Shohag <saleh.enam@samsung.com>
+
+*/
+function ProximitySensor_getProximitySensorData_errorCallback_invalid_cb() {
+
+
+
+
+
+
+
+
+//==== TEST: ProximitySensor_getProximitySensorData_errorCallback_invalid_cb
+//==== LABEL Check if ProximitySensor::getProximitySensorData() method throws exception when errorCallback is invalid
+//==== SPEC Tizen Web API:System:Sensor:ProximitySensor:getProximitySensorData M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== PRE Prepare to change sensor values.
+//==== STEP Click run and move in front of the phone.
+//==== EXPECT Pass
+//==== EXECUTION_TYPE manual
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 30000});
+
+var t = async_test("ProximitySensor_getProximitySensorData_errorCallback_invalid_cb", {timeout: 30000}), invalidcallback, onsuccessCB, proximitySensor, onGetSuccessCB;
+
+t.step(function () {
+    proximitySensor = tizen.sensorservice.getDefaultSensor("PROXIMITY");
+
+    add_result_callback(function () {
+        proximitySensor.stop();
+    });
+
+    invalidcallback = {
+        onerror: t.step_func(function (sensorData) {
+            assert_unreached("getProximitySensorData() successcallback invoked");
+        })
+    };
+
+    onGetSuccessCB = t.step_func(function (sensorData) {
+        assert_unreached("SuccessCallback should not be called");
+    });
+
+    onsuccessCB = t.step_func(function () {
+        assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+            proximitySensor.getProximitySensorData(onGetSuccessCB, invalidcallback);
+        }, TYPE_MISMATCH_EXCEPTION + " Should throw exception");
+        t.done();
+    });
+
+    proximitySensor.start(onsuccessCB);
+    alert("Change the value of the proximity sensor");
+});
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saleh Enam Shohag<saleh.enam@samsung.com>
+
+*/
+function ProximitySensor_getProximitySensorData_errorCallback_invoked() {
+
+
+
+
+
+
+
+//==== TEST: ProximitySensor_getProximitySensorData_errorCallback_invoked
+//==== LABEL Check exception in error callback of ProximitySensor::getProximitySensorData() method
+//==== SPEC Tizen Web API:System:Sensor:ProximitySensor:getProximitySensorData M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P2
+//==== TEST_CRITERIA MERRCB
+
+setup({timeout: 30000});
+
+var t = async_test("ProximitySensor_getProximitySensorData_errorCallback_invoked", {timeout: 30000}), onerrorCB, onGetSuccessCB, proximitySensor;
+
+t.step(function () {
+    proximitySensor = tizen.sensorservice.getDefaultSensor("PROXIMITY");
+
+    onGetSuccessCB = t.step_func(function (sensorData) {
+        assert_unreached("SuccessCallback should not be called");
+    });
+
+    onerrorCB = t.step_func(function (error) {
+        assert_equals("ServiceNotAvailableError", error.name, "Error callback should be thrown with error: " + error.name);
+        t.done();
+    });
+
+    proximitySensor.getProximitySensorData(onGetSuccessCB, onerrorCB);
+});
+
+
+}
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+
+*/
+function ProximitySensor_getProximitySensorData_errorCallback_TypeMismatch() {
+
+
+
+
+
+
+
+
+//==== TEST: ProximitySensor_getProximitySensorData_errorCallback_TypeMismatch
+//==== LABEL Check if ProximitySensor::getProximitySensorData() with incorrect errorCallback argument throws exception
+//==== SPEC Tizen Web API:System:Sensor:ProximitySensor:getProximitySensorData M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== PRE Prepare to change sensor values.
+//==== STEP Click run and move in front of the phone.
+//==== EXPECT Pass
+//==== EXECUTION_TYPE manual
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test("ProximitySensor_getProximitySensorData_errorCallback_TypeMismatch", {timeout: 30000}), exceptionName, i, conversionTable, onGetSuccessCB, onerrorCB, proximitySensor, onsuccessCB;
+
+t.step(function () {
+    proximitySensor = tizen.sensorservice.getDefaultSensor("PROXIMITY");
+
+    add_result_callback(function () {
+        proximitySensor.stop();
+    });
+
+    onGetSuccessCB = t.step_func(function () {
+        assert_unreached("Unexpected successCallback");
+    });
+
+    onsuccessCB = t.step_func(function () {
+        conversionTable = getTypeConversionExceptions("functionObject", true);
+        for (i = 0; i < conversionTable.length; i++) {
+            onerrorCB = conversionTable[i][0];
+            exceptionName = conversionTable[i][1];
+            assert_throws({name: exceptionName}, function () {
+                proximitySensor.getProximitySensorData(onGetSuccessCB, onerrorCB);
+            }, exceptionName + " should be thrown");
+        }
+        t.done();
+    });
+
+    proximitySensor.start(onsuccessCB);
+    alert("Change the value of the proximity sensor");
+});
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+
+*/
+function ProximitySensor_getProximitySensorData_exist() {
+
+
+
+
+
+
+
+
+//==== TEST: ProximitySensor_getProximitySensorData_exist
+//==== LABEL Check if ProximitySensor::getProximitySensorData() method exists
+//==== SPEC Tizen Web API:System:Sensor:ProximitySensor:getProximitySensorData M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    var proximitySensor;
+    proximitySensor = tizen.sensorservice.getDefaultSensor("PROXIMITY");
+    assert_true("getProximitySensorData" in proximitySensor, "No getProximitySensorData method in proximitySensor");
+    check_method_exists(proximitySensor, "getProximitySensorData");
+}, "ProximitySensor_getProximitySensorData_exist");
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saleh Enam Shohag<saleh.enam@samsung.com>
+
+*/
+function ProximitySensor_getProximitySensorData() {
+
+
+
+
+
+
+
+
+//==== TEST: ProximitySensor_getProximitySensorData
+//==== LABEL Check if ProximitySensor::getProximitySensorData() method works properly
+//==== SPEC Tizen Web API:System:Sensor:ProximitySensor:getProximitySensorData M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== PRE Prepare to change sensor values.
+//==== STEP Please touch or get closer your hand to proximity sensor which is next to front camera.
+//==== EXPECT Pass
+//==== EXECUTION_TYPE manual
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P1
+//==== TEST_CRITERIA MMINA MR
+
+setup({timeout: 30000});
+
+var t = async_test("ProximitySensor_getProximitySensorData", {timeout: 30000}), onGetSuccessCB, onsuccessCB, proximitySensor, retValue = null;
+
+t.step(function () {
+    proximitySensor = tizen.sensorservice.getDefaultSensor("PROXIMITY");
+
+    add_result_callback(function () {
+        proximitySensor.stop();
+    });
+
+    onGetSuccessCB = t.step_func(function (sensorData) {
+        assert_equals(retValue, undefined, "getProximitySensorData returns wrong value");
+        t.done();
+    });
+
+    onsuccessCB = t.step_func(function () {
+        alert("Change the value of the proximity sensor");
+    });
+
+    onchangedCB = t.step_func(function (sensorData) {
+        retValue = proximitySensor.getProximitySensorData(onGetSuccessCB);
+    });
+
+    proximitySensor.setChangeListener(onchangedCB);
+    proximitySensor.start(onsuccessCB);
+});
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+
+*/
+function ProximitySensor_getProximitySensorData_misarg() {
+
+
+
+
+
+
+
+
+//==== TEST: ProximitySensor_getProximitySensorData_misarg
+//==== LABEL Check if ProximitySensor::getProximitySensorData() throws exception when successCallback is missing
+//==== SPEC Tizen Web API:System:Sensor:ProximitySensor:getProximitySensorData M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== PRE Prepare to change sensor values.
+//==== STEP Click run and move in front of the phone.
+//==== EXPECT Pass
+//==== EXECUTION_TYPE manual
+//==== PRIORITY P2
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MMA
+
+setup({timeout: 30000});
+
+var t = async_test("ProximitySensor_getProximitySensorData_misarg", {timeout: 30000}), onsuccessCB, proximitySensor;
+
+t.step(function () {
+    proximitySensor = tizen.sensorservice.getDefaultSensor("PROXIMITY");
+
+    add_result_callback(function () {
+        proximitySensor.stop();
+    });
+
+    onsuccessCB = t.step_func(function () {
+        assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        proximitySensor.getProximitySensorData();
+        }, TYPE_MISMATCH_EXCEPTION + " should be thrown");
+        t.done();
+    });
+
+    proximitySensor.start(onsuccessCB);
+    alert("Change the value of the proximity sensor");
+});
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saleh Enam Shohag <saleh.enam@samsung.com>
+
+*/
+function ProximitySensor_getProximitySensorData_successCallback_invalid_cb() {
+
+
+
+
+
+
+
+
+//==== TEST: ProximitySensor_getProximitySensorData_successCallback_invalid_cb
+//==== LABEL Check if ProximitySensor::getProximitySensorData() method throws exception when successCallback is invalid
+//==== SPEC Tizen Web API:System:Sensor:ProximitySensor:getProximitySensorData M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== PRE Prepare to change sensor values.
+//==== STEP Click run and move in front of the phone.
+//==== EXPECT Pass
+//==== EXECUTION_TYPE manual
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 30000});
+
+var t = async_test("ProximitySensor_getProximitySensorData_successCallback_invalid_cb", {timeout: 30000}), invalidcallback, onsuccessCB, proximitySensor;
+
+t.step(function () {
+    proximitySensor = tizen.sensorservice.getDefaultSensor("PROXIMITY");
+
+    add_result_callback(function () {
+        proximitySensor.stop();
+    });
+
+    invalidcallback = {
+        onsuccess: t.step_func(function (sensorData) {
+            assert_unreached("getProximitySensorData() successcallback invoked")
+        })
+    };
+
+    onsuccessCB = t.step_func(function () {
+        assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+            proximitySensor.getProximitySensorData(invalidcallback);
+        }, "Should throw exception");
+        t.done();
+    });
+
+    proximitySensor.start(onsuccessCB);
+    alert("Change the value of the proximity sensor");
+});
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+
+*/
+function ProximitySensor_getProximitySensorData_successCallback_TypeMismatch() {
+
+
+
+
+
+
+
+
+//==== TEST: ProximitySensor_getProximitySensorData_successCallback_TypeMismatch
+//==== LABEL Check if ProximitySensor::getProximitySensorData() with incorrect successCallback argument throws exception
+//==== SPEC Tizen Web API:System:Sensor:ProximitySensor:getProximitySensorData M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== PRE Prepare to change sensor values.
+//==== STEP Click run and move in front of the phone.
+//==== EXPECT Pass
+//==== EXECUTION_TYPE manual
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test("ProximitySensor_getProximitySensorData_successCallback_TypeMismatch", {timeout: 30000}), exceptionName, i, conversionTable, onGetSuccessCB, onerrorCB, proximitySensor, onsuccessCB;
+
+t.step(function () {
+    proximitySensor = tizen.sensorservice.getDefaultSensor("PROXIMITY");
+
+    add_result_callback(function () {
+        proximitySensor.stop();
+    });
+
+    onerrorCB = t.step_func(function (error) {
+        assert_unreached("getProximitySensorData() error callback invoked: name:" + error.name + ", msg: " + error.message);
+    });
+
+    onsuccessCB = t.step_func(function () {
+        conversionTable = getTypeConversionExceptions("functionObject", false);
+        for (i = 0; i < conversionTable.length; i++) {
+            onGetSuccessCB = conversionTable[i][0];
+            exceptionName = conversionTable[i][1];
+            assert_throws({name: exceptionName}, function () {
+                proximitySensor.getProximitySensorData(onGetSuccessCB, onerrorCB);
+            }, exceptionName + " should be thrown - given incorrect successCallback.");
+        }
+        t.done();
+    });
+
+    proximitySensor.start(onsuccessCB);
+    alert("Change the value of the proximity sensor");
+});
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+
+*/
+function ProximitySensor_getProximitySensorData_with_errorCallback() {
+
+
+
+
+
+
+
+
+//==== TEST: ProximitySensor_getProximitySensorData_with_errorCallback
+//==== LABEL Check if ProximitySensor::getProximitySensorData() method works properly with optional argument
+//==== SPEC Tizen Web API:System:Sensor:ProximitySensor:getProximitySensorData M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== PRE Prepare to change sensor values.
+//==== STEP Please touch or get closer your hand to proximity sensor which is next to front camera.
+//==== EXPECT Pass
+//==== EXECUTION_TYPE manual
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P1
+//==== TEST_CRITERIA MOA MR
+
+setup({timeout: 30000});
+
+var t = async_test("ProximitySensor_getProximitySensorData_with_errorCallback", {timeout: 30000}), onGetSuccessCB, onsuccessCB, proximitySensor, retValue = null, onerrorCB;
+
+t.step(function () {
+    proximitySensor = tizen.sensorservice.getDefaultSensor("PROXIMITY");
+
+    add_result_callback(function () {
+        proximitySensor.stop();
+    });
+
+    onGetSuccessCB = t.step_func(function (proximity) {
+        assert_not_equals(proximity.proximityState, null, "Fail to getProximitySensorData");
+        assert_equals(retValue, undefined, "getProximitySensorData returns wrong value");
+        t.done();
+    });
+
+    onerrorCB = t.step_func(function (error) {
+        assert_unreached("getProximitySensorData() error callback invoked: name:" + error.name + ", msg: " + error.message);
+    });
+
+    onsuccessCB = t.step_func(function () {
+        alert("Change the value of the proximity sensor");
+    });
+
+    onchangedCB = t.step_func(function (sensorData) {
+        retValue = proximitySensor.getProximitySensorData(onGetSuccessCB, onerrorCB);
+    });
+
+    proximitySensor.setChangeListener(onchangedCB);
+    proximitySensor.start(onsuccessCB);
+});
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saleh Enam Shohag <saleh.enam@samsung.com>
+
+*/
+function ProximitySensor_notexist() {
+
+
+
+
+
+
+
+
+//==== TEST: ProximitySensor_notexist
+//==== LABEL Check if interface ProximitySensor exists, it should not
+//==== SPEC Tizen Web API:System:Sensor:ProximitySensor:ProximitySensor U
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("ProximitySensor");
+}, "ProximitySensor_notexist");
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+        Wahid Dilawar Al-Hakim <wahid.h@samsung.com>
+
+*/
+function SensorData_notexist() {
+
+
+
+
+
+
+
+
+//==== TEST: SensorData_notexist
+//==== LABEL Check if interface SensorData does not exist
+//==== SPEC Tizen Web API:System:Sensor:SensorData:SensorData U
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("SensorData");
+}, "SensorData_notexist");
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+        Wahid Dilawar Al-Hakim <wahid.h@samsung.com>
+
+*/
+function SensorDataSuccessCallback_notexist() {
+
+
+
+
+
+
+
+
+//==== TEST: SensorDataSuccessCallback_notexist
+//==== LABEL Check if interface SensorDataSuccessCallback exists, it should not
+//==== SPEC Tizen Web API:System:Sensor:SensorDataSuccessCallback:SensorDataSuccessCallback U
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA CBNIO
+
+test(function () {
+    check_no_interface_object("SensorDataSuccessCallback");
+}, "SensorDataSuccessCallback_notexist");
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+        Wahid Dilawar Al-Hakim <wahid.h@samsung.com>
+
+*/
+function SensorDataSuccessCallback_onsuccess() {
+
+
+
+
+
+
+
+
+//==== TEST: SensorDataSuccessCallback_onsuccess
+//==== LABEL Check if SensorDataSuccessCallback::onsuccess() works properly
+//==== SPEC Tizen Web API:System:Sensor:SensorDataSuccessCallback:onsuccess M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P1
+//==== TEST_CRITERIA CBOA CBT
+
+setup({timeout: 30000});
+
+var t = async_test("SensorDataSuccessCallback_onsuccess", {timeout: 30000}), onGetSuccessCB, onerrorCB, onsuccessCB, magneticSensor;
+
+t.step(function () {
+    magneticSensor = tizen.sensorservice.getDefaultSensor("MAGNETIC");
+
+    add_result_callback(function () {
+        magneticSensor.stop();
+    });
+
+    onGetSuccessCB = t.step_func(function (sensorData) {
+        assert_not_equals(sensorData, null, "Argument should not be null");
+        assert_type(sensorData, "object", "sensorData is Incorrect type");
+        t.done();
+    });
+
+    onerrorCB = t.step_func(function (error) {
+        assert_unreached("getMagneticSensorData() error callback invoked: name: " + error.message + ", msg: " + error.name);
+    });
+
+    onsuccessCB = t.step_func(function () {
+        magneticSensor.getMagneticSensorData(onGetSuccessCB, onerrorCB);
+    });
+
+    magneticSensor.start(onsuccessCB);
+});
+
+
+
+}
+/*
+Copyright (c) 2015 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Authors:
+        Xiaoyan Qian <xy.qian@samsung.com>
+
+*/
+
+function SensorHRMRawData_lightIntensity_attribute() {
+
+
+
+
+
+
+
+
+//==== TEST: SensorHRMRawData_lightIntensity_attribute
+//==== LABEL Check if SensorHRMRawData::lightIntensity attribute exists, has type number and is readonly
+//==== SPEC Tizen Web API:System:Sensor:SensorHRMRawData:lightIntensity A
+//==== SPEC_URL TBD
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ARO
+
+setup({timeout: 30000});
+
+var t = async_test("SensorHRMRawData_lightIntensity_attribute", {timeout: 30000}), onGetSuccessCB, onerrorCB, onsuccessCB, HRMrawsensor;
+
+t.step(function () {
+    if(!tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.heart_rate_monitor.led_green") &&
+        !tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.heart_rate_monitor.led_red") &&
+        !tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.heart_rate_monitor.led_ir")) {
+        t.done();
+        return;
+    }
+    HRMrawsensor = tizen.sensorservice.getDefaultSensor("HRM_RAW");
+
+
+    add_result_callback(function () {
+        HRMrawsensor.stop();
+    });
+
+    onGetSuccessCB = t.step_func(function (sensorData) {
+        check_readonly(sensorData, "lightIntensity", sensorData.lightIntensity, "number", sensorData.lightIntensity + 1);
+        t.done();
+    });
+
+    onerrorCB = t.step_func(function (error) {
+        assert_unreached("getHRMRawSensorData() error callback invoked: name: " + error.message + ", msg: " + error.name);
+    });
+
+    onsuccessCB = t.step_func(function () {
+        HRMrawsensor.getHRMRawSensorData(onGetSuccessCB, onerrorCB);
+    });
+
+    HRMrawsensor.start(onsuccessCB);
+});
+
+
+
+}
+/*
+Copyright (c) 2015 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Authors:
+        Xiaoyan Qian <xy.qian@samsung.com>
+
+*/
+
+function SensorHRMRawData_lightType_attribute() {
+
+
+
+
+
+
+
+
+//==== TEST: SensorHRMRawData_lightType_attribute
+//==== LABEL Check if SensorHRMRawData::lightType attribute exists, has type string and is readonly
+//==== SPEC Tizen Web API:System:Sensor:SensorHRMRawData:lightType A
+//==== SPEC_URL TBD
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ARO AVL
+
+setup({timeout: 30000});
+
+var t = async_test("SensorHRMRawData_lightType_attribute", {timeout: 30000}), onGetSuccessCB, onerrorCB, onsuccessCB, HRMrawsensor;
+
+t.step(function () {
+    if(!tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.heart_rate_monitor.led_green") &&
+        !tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.heart_rate_monitor.led_red") &&
+        !tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.heart_rate_monitor.led_ir")) {
+        t.done();
+        return;
+    }
+    HRMrawsensor = tizen.sensorservice.getDefaultSensor("HRM_RAW");
+
+
+    add_result_callback(function () {
+        HRMrawsensor.stop();
+    });
+
+    onGetSuccessCB = t.step_func(function (sensorData) {
+        check_readonly(sensorData, "lightType", sensorData.lightType, "string", "invalid_string");
+        assert_in_array(sensorData.lightType, ["LED_IR", "LED_RED", "LED_GREEN"], "lightType value is incorrect.");
+        t.done();
+    });
+
+    onerrorCB = t.step_func(function (error) {
+        assert_unreached("getHRMRawSensorData() error callback invoked: name: " + error.message + ", msg: " + error.name);
+    });
+
+    onsuccessCB = t.step_func(function () {
+        HRMrawsensor.getHRMRawSensorData(onGetSuccessCB, onerrorCB);
+    });
+
+    HRMrawsensor.start(onsuccessCB);
+});
+
+
+
+}
+/*
+Copyright (c) 2015 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Authors:
+        Xiaoyan Qian <xy.qian@samsung.com>
+
+*/
+
+function SensorHRMRawData_notexist() {
+
+
+
+
+
+
+
+
+//==== TEST: SensorHRMRawData_notexist
+//==== LABEL Check if interface SensorHRMRawData does not exists
+//==== SPEC Tizen Web API:System:Sensor:SensorHRMRawData:SensorHRMRawData U
+//==== SPEC_URL TBD
+//==== PRIORITY P3
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("SensorHRMRawData");
+}, "SensorHRMRawData_notexist");
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+        Wahid Dilawar Al-Hakim <wahid.h@samsung.com>
+
+*/
+function SensorLightData_lightLevel_attribute() {
+
+
+
+
+
+
+
+
+//==== TEST: SensorLightData_lightLevel_attribute
+//==== LABEL Check if SensorLightData::lightLevel attribute exists, has type number and is readonly
+//==== SPEC Tizen Web API:System:Sensor:SensorLightData:lightLevel A
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ARO
+
+setup({timeout: 30000});
+
+var t = async_test("SensorLightData_lightLevel_attribute", {timeout: 30000}), onGetSuccessCB, onerrorCB, onsuccessCB, lightSensor;
+
+t.step(function () {
+    lightSensor = tizen.sensorservice.getDefaultSensor("LIGHT");
+
+    add_result_callback(function () {
+        lightSensor.stop();
+    });
+
+    onGetSuccessCB = t.step_func(function (sensorData) {
+        check_readonly(sensorData, "lightLevel", sensorData.lightLevel, "number", 12);
+        t.done();
+    });
+
+    onerrorCB = t.step_func(function (error) {
+        assert_unreached("getLightSensorData() error callback invoked: name: " + error.message + ", msg: " + error.name);
+    });
+
+    onsuccessCB = t.step_func(function () {
+        lightSensor.getLightSensorData(onGetSuccessCB, onerrorCB);
+    });
+
+    lightSensor.start(onsuccessCB);
+});
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+        Wahid Dilawar Al-Hakim <wahid.h@samsung.com>
+
+*/
+function SensorLightData_notexist() {
+
+
+
+
+
+
+
+
+//==== TEST: SensorLightData_notexist
+//==== LABEL Check if interface SensorLightData does not exists
+//==== SPEC Tizen Web API:System:Sensor:SensorLightData:SensorLightData U
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("SensorLightData");
+}, "SensorLightData_notexist");
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+        Md. Samsuddin Alam <ss.alam@samsung.com>
+
+*/
+function SensorMagneticData_accuracy_attribute() {
+
+
+
+
+
+
+
+
+//==== TEST: SensorMagneticData_accuracy_attribute
+//==== LABEL Check if accuracy attribute of SensorMagneticData exists, type is string and readonly
+//==== SPEC Tizen Web API:System:Sensor:SensorMagneticData:accuracy A
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ARO
+
+setup({timeout: 30000});
+
+var t = async_test("SensorMagneticData_accuracy_attribute", {timeout: 30000}), magneticSensor, onGetSuccessCB, onerrorCB, onsuccessCB;
+
+t.step(function () {
+    magneticSensor = tizen.sensorservice.getDefaultSensor("MAGNETIC");
+
+    add_result_callback(function () {
+        magneticSensor.stop();
+    });
+
+    onGetSuccessCB = t.step_func(function (sensorData) {
+        check_readonly(sensorData, "accuracy", sensorData.accuracy, "string", "abc");
+        t.done();
+    });
+
+    onerrorCB = t.step_func(function (error) {
+        assert_unreached("getMagneticSensorData() error callback invoked: name: " + error.message + ", msg: " + error.name);
+    });
+
+    onsuccessCB = t.step_func(function () {
+        magneticSensor.getMagneticSensorData(onGetSuccessCB, onerrorCB);
+    });
+
+    magneticSensor.start(onsuccessCB);
+});
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+        Saleh Enam Shohag <saleh.enam@samsung.com>
+
+*/
+function SensorMagneticData_notexist() {
+
+
+
+
+
+
+
+
+//==== TEST: SensorMagneticData_notexist
+//==== LABEL Check if interface SensorMagneticData exists, it should not.
+//==== SPEC Tizen Web API:System:Sensor:SensorMagneticData:SensorMagneticData U
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== TEST_CRITERIA NIO
+//==== PRIORITY P3
+
+test(function () {
+    check_no_interface_object("SensorMagneticData");
+}, "SensorMagneticData_notexist");
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+        Md. Samsuddin Alam <ss.alam@samsung.com>
+
+*/
+function SensorMagneticData_x_attribute() {
+
+
+
+
+
+
+
+
+//==== TEST: SensorMagneticData_x_attribute
+//==== LABEL Check if x attribute of SensorMagneticData exists, type is string and readonly
+//==== SPEC Tizen Web API:System:Sensor:SensorMagneticData:x A
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ARO
+
+setup({timeout: 30000});
+
+var t = async_test("SensorMagneticData_x_attribute", {timeout: 30000}), onGetSuccessCB, onerrorCB, onsuccessCB, magneticSensor;
+
+t.step(function () {
+    magneticSensor = tizen.sensorservice.getDefaultSensor("MAGNETIC");
+
+    add_result_callback(function () {
+        magneticSensor.stop();
+    });
+
+    onGetSuccessCB = t.step_func(function (sensorData) {
+        check_readonly(sensorData, "x", sensorData.x, "number", 123);
+        t.done();
+    });
+
+    onerrorCB = t.step_func(function (error) {
+        assert_unreached("getMagneticSensorData() error callback invoked: name: " + error.message + ", msg: " + error.name);
+    });
+
+    onsuccessCB = t.step_func(function () {
+        magneticSensor.getMagneticSensorData(onGetSuccessCB, onerrorCB);
+    });
+
+    magneticSensor.start(onsuccessCB);
+});
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+        Md. Samsuddin Alam <ss.alam@samsung.com>
+
+*/
+function SensorMagneticData_y_attribute() {
+
+
+
+
+
+
+
+
+//==== TEST: SensorMagneticData_y_attribute
+//==== LABEL Check if y attribute of SensorMagneticData exists, type is string and readonly
+//==== SPEC Tizen Web API:System:Sensor:SensorMagneticData:y A
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ARO
+
+setup({timeout: 30000});
+
+var t = async_test("SensorMagneticData_y_attribute", {timeout: 30000}), onGetSuccessCB, onerrorCB, onsuccessCB;
+
+t.step(function () {
+    var magneticSensor = tizen.sensorservice.getDefaultSensor("MAGNETIC");
+
+    add_result_callback(function () {
+        magneticSensor.stop();
+    });
+
+    onGetSuccessCB = t.step_func(function (sensorData) {
+        check_readonly(sensorData, "y", sensorData.y, "number", 123);
+        t.done();
+    });
+
+    onerrorCB = t.step_func(function (error) {
+        assert_unreached("getMagneticSensorData() error callback invoked: name: " + error.message + ", msg: " + error.name);
+    });
+
+    onsuccessCB = t.step_func(function () {
+        magneticSensor.getMagneticSensorData(onGetSuccessCB, onerrorCB);
+    });
+
+    magneticSensor.start(onsuccessCB);
+});
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+        Md. Samsuddin Alam <ss.alam@samsung.com>
+
+*/
+function SensorMagneticData_z_attribute() {
+
+
+
+
+
+
+
+
+//==== TEST: SensorMagneticData_z_attribute
+//==== LABEL Check if z attribute of SensorMagneticData exists, type is string and readonly
+//==== SPEC Tizen Web API:System:Sensor:SensorMagneticData:z A
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ARO
+
+setup({timeout: 30000});
+
+var t = async_test("SensorMagneticData_z_attribute", {timeout: 30000}), onGetSuccessCB, onerrorCB, onsuccessCB;
+
+t.step(function () {
+    var magneticSensor = tizen.sensorservice.getDefaultSensor("MAGNETIC");
+
+    add_result_callback(function () {
+        magneticSensor.stop();
+    });
+
+    onGetSuccessCB = t.step_func(function (sensorData) {
+        check_readonly(sensorData, "z", sensorData.z, "number", 123);
+        t.done();
+    });
+
+    onerrorCB = t.step_func(function (error) {
+        assert_unreached("getMagneticSensorData() error callback invoked: name: " +
+        error.message + ", msg: " + error.name);
+    });
+
+    onsuccessCB = t.step_func(function () {
+        magneticSensor.getMagneticSensorData(onGetSuccessCB, onerrorCB);
+    });
+
+    magneticSensor.start(onsuccessCB);
+});
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+        Md. Samsuddin Alam <ss.alam@samsung.com>
+
+*/
+function Sensor_notexist() {
+
+
+
+
+
+
+
+
+//==== TEST: Sensor_notexist
+//==== LABEL Check if interface Sensor exists, it should not
+//==== SPEC Tizen Web API:System:Sensor:Sensor:Sensor U
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== PRIORITY: P3
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("Sensor");
+}, "Sensor_notexist");
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saleh Enam Shohag <saleh.enam@samsung.com>
+
+*/
+function SensorPressureData_notexist() {
+
+
+
+
+
+
+
+
+//==== TEST: SensorPressureData_notexist
+//==== LABEL Check if interface SensorPressureData exists, it should not.
+//==== SPEC Tizen Web API:System:Sensor:SensorPressureData:SensorPressureData U
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("SensorPressureData");
+}, "SensorPressureData_notexist");
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+
+*/
+function SensorPressureData_pressure_attribute() {
+
+
+
+
+
+
+
+
+//==== TEST: SensorPressureData_pressure_attribute
+//==== LABEL Check attribute pressure in SensorPressureData
+//==== SPEC Tizen Web API:System:Sensor:SensorPressureData:z A
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ARO
+
+setup({timeout: 30000});
+
+var t = async_test("SensorPressureData_pressure_attribute", {timeout: 30000}), onGetSuccessCB, onerrorCB, onsuccessCB, pressureSensor;
+
+t.step(function () {
+    pressureSensor = tizen.sensorservice.getDefaultSensor("PRESSURE");
+
+    add_result_callback(function () {
+        pressureSensor.stop();
+    });
+
+    onGetSuccessCB = t.step_func(function (sensorData) {
+        check_readonly(sensorData, "pressure", sensorData.pressure, "number", null);
+        t.done();
+    });
+
+    onerrorCB = t.step_func(function (error) {
+        assert_unreached("getPressureSensorData() error callback invoked: name: " + error.message + ", msg: " + error.name);
+    });
+
+    onsuccessCB = t.step_func(function () {
+        pressureSensor.getPressureSensorData(onGetSuccessCB, onerrorCB);
+    });
+
+    pressureSensor.start(onsuccessCB);
+});
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+
+*/
+function SensorProximityData_notexist() {
+
+
+
+
+
+
+
+
+//==== TEST: SensorProximityData_notexist
+//==== LABEL Check if interface SensorProximityData exists, it should not.
+//==== SPEC Tizen Web API:System:Sensor:SensorProximityData:SensorProximityData U
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("SensorProximityData");
+}, "SensorProximityData_notexist");
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+
+*/
+function SensorProximityData_proximityState_attribute() {
+
+
+
+
+
+
+
+
+//==== TEST: SensorProximityData_proximityState_attribute
+//==== LABEL Check proximityState in SensorProximityData
+//==== SPEC Tizen Web API:System:Sensor:SensorProximityData:proximityState A
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE ARO AT
+
+setup({timeout: 30000});
+
+var t = async_test("SensorProximityData_proximityState_attribute", {timeout: 30000}), onGetSuccessCB, onerrorCB, onsuccessCB, proximitySensor;
+
+t.step(function () {
+    proximitySensor = tizen.sensorservice.getDefaultSensor("PROXIMITY");
+
+    add_result_callback(function () {
+        proximitySensor.stop();
+    });
+
+    onGetSuccessCB = t.step_func(function (sensorData) {
+        check_readonly(sensorData, "proximityState", sensorData.proximityState, "string", null);
+        t.done();
+    });
+
+    onerrorCB = t.step_func(function (error) {
+        assert_unreached("getProximitySensorData() error callback invoked: name: " + error.message + ", msg: " + error.name);
+    });
+
+    onsuccessCB = t.step_func(function () {
+        alert("Change the value of the proximity sensor");
+    });
+
+    onchangedCB = t.step_func(function (sensorData) {
+        proximitySensor.getProximitySensorData(onGetSuccessCB, onerrorCB);
+    });
+
+    proximitySensor.setChangeListener(onchangedCB);
+    proximitySensor.start(onsuccessCB);
+});
+
+
+
+}
+
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+        Wahid Dilawar Al-Hakim <wahid.h@samsung.com>
+
+*/
+function SensorService_extend() {
+
+
+
+
+
+
+
+
+//==== TEST: SensorService_extend
+//==== LABEL Check if SensorService object is extendable
+//==== SPEC Tizen Web API:System:Sensor:SensorService:SensorService U
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA OBX
+
+test(function () {
+    check_extensibility(tizen.sensorservice);
+}, "SensorService_extend");
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+        Wahid Dilawar Al-Hakim <wahid.h@samsung.com>
+
+*/
+function SensorService_getAvailableSensors_exist() {
+
+
+
+
+
+
+
+
+//==== TEST: SensorService_getAvailableSensors_exist
+//==== LABEL Check if sensorservice::getAvailableSensors() methods exists
+//==== SPEC Tizen Web API:System:Sensor:SensorService:getAvailableSensors M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    check_method_exists(tizen.sensorservice, "getAvailableSensors");
+}, "SensorService_getAvailableSensors_exist");
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+        Wahid Dilawar Al-Hakim <wahid.h@samsung.com>
+
+*/
+function SensorService_getAvailableSensors_extra_argument() {
+
+
+
+
+
+
+
+
+//==== TEST: SensorService_getAvailableSensors_extra_argument
+//==== LABEL Check using sensorservice::getAvailableSensors() method with extra argument
+//==== SPEC Tizen Web API:System:Sensor:SensorService:getAvailableSensors M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MNAEX
+
+test(function () {
+    checkExtraArgument(tizen.sensorservice, "getAvailableSensors");
+}, "SensorService_getAvailableSensors_extra_argument");
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+        Wahid Dilawar Al-Hakim <wahid.h@samsung.com>
+
+*/
+function SensorService_getAvailableSensors() {
+
+
+
+
+
+
+
+
+//==== TEST: SensorService_getAvailableSensors
+//==== LABEL Check if SensorService::getAvailableSensors() method returns properly
+//==== SPEC Tizen Web API:System:Sensor:SensorService:getAvailableSensors M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MNA MR
+
+test(function () {
+    var sensorCapabilities;
+
+    sensorCapabilities = tizen.sensorservice.getAvailableSensors();
+    assert_type(sensorCapabilities, "array", "Method getAvailableSensors returns wrong type");
+    assert_greater_than(sensorCapabilities.length, 0, "Method gerAvailableSensors returns empty array")
+}, "SensorService_getAvailableSensors");
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+        Wahid Dilawar Al-Hakim <wahid.h@samsung.com>
+
+*/
+function SensorService_getDefaultSensor_exist() {
+
+
+
+
+
+
+
+
+//==== TEST: SensorService_getDefaultSensor_exist
+//==== LABEL Check if SensorService::getDefaultSensor() method exists
+//==== SPEC Tizen Web API:System:Sensor:SensorService:getDefaultSensor M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    check_method_exists(tizen.sensorservice, "getDefaultSensor");
+}, "SensorService_getDefaultSensor_exist");
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+        Wahid Dilawar Al-Hakim <wahid.h@samsung.com>
+
+*/
+function SensorService_getDefaultSensor_misarg() {
+
+
+
+
+
+
+
+
+//==== TEST: SensorService_getDefaultSensor_misarg
+//==== LABEL Check if SensorService::getDefaultSensor() method throws an exception when SensorType is missing
+//==== SPEC Tizen Web API:System:Sensor:SensorService:getDefaultSensor M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MMA
+
+test(function () {
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        tizen.sensorservice.getDefaultSensor();
+    }, TYPE_MISMATCH_EXCEPTION + "should be thrown");
+}, "SensorService_getDefaultSensor_misarg");
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saleh Enam Shohag <saleh.enam@samsung.com>
+        Wahid Dilawar Al-Hakim <wahid.h@samsung.com>
+
+*/
+function SensorService_getDefaultSensor_type_light() {
+
+
+
+
+
+
+
+
+//==== TEST: SensorService_getDefaultSensor_type_light
+//==== LABEL Check if sensorservice::getDefaultSensor() method returns LightSensor object when called with LIGHT
+//==== SPEC Tizen Web API:System:Sensor:SensorService:getDefaultSensor M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var lightSensor;
+
+    lightSensor = tizen.sensorservice.getDefaultSensor("LIGHT");
+    assert_not_equals(lightSensor, undefined, "Method returned wrong value");
+}, "SensorService_getDefaultSensor_type_light");
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saleh Enam Shohag <saleh.enam@samsung.com>
+        Wahid Dilawar Al-Hakim <wahid.h@samsung.com>
+
+*/
+function SensorService_getDefaultSensor_type_magnetic() {
+
+
+
+
+
+
+
+
+//==== TEST: SensorService_getDefaultSensor_type_magnetic
+//==== LABEL Check if sensorservice::getDefaultSensor() method returns MagneticSensor object when called with MAGNETIC
+//==== SPEC Tizen Web API:System:Sensor:SensorService:getDefaultSensor M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var magneticSensor;
+
+    magneticSensor = tizen.sensorservice.getDefaultSensor("MAGNETIC");
+    assert_not_equals(magneticSensor, undefined, "Method returned wrong value");
+}, "SensorService_getDefaultSensor_type_magnetic");
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saleh Enam Shohag <saleh.enam@samsung.com>
+        Wahid Dilawar Al-Hakim <wahid.h@samsung.com>
+
+*/
+function SensorService_getDefaultSensor_type_pressure() {
+
+
+
+
+
+
+
+
+//==== TEST: SensorService_getDefaultSensor_type_pressure
+//==== LABEL Check if sensorservice::getDefaultSensor() method returns PressureSensor object when called with PRESSURE
+//==== SPEC Tizen Web API:System:Sensor:SensorService:getDefaultSensor M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var pressureSensor;
+
+    pressureSensor = tizen.sensorservice.getDefaultSensor("PRESSURE");
+    assert_not_equals(pressureSensor, undefined, "Method returned wrong value");
+}, "SensorService_getDefaultSensor_type_pressure");
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saleh Enam Shohag <saleh.enam@samsung.com>
+        Wahid Dilawar Al-Hakim <wahid.h@samsung.com>
+
+*/
+function SensorService_getDefaultSensor_type_proximity() {
+
+
+
+
+
+
+
+
+//==== TEST: SensorService_getDefaultSensor_type_proximity
+//==== LABEL Check if sensorservice::getDefaultSensor() method returns ProximitySensor object when called with PROXIMITY
+//==== SPEC Tizen Web API:System:Sensor:SensorService:getDefaultSensor M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var proximitySensor;
+
+    proximitySensor = tizen.sensorservice.getDefaultSensor("PROXIMITY");
+    assert_not_equals(proximitySensor, undefined, "Method returned wrong value");
+}, "SensorService_getDefaultSensor_type_proximity");
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+        Wahid Dilawar Al-Hakim <wahid.h@samsung.com>
+
+*/
+function SensorService_getDefaultSensor_type_TypeMismatch() {
+
+
+
+
+
+
+
+
+//==== TEST: SensorService_getDefaultSensor_type_TypeMismatch
+//==== LABEL check if sensorservice::getDefaultSensor() method with incorrect type argument throws an exception
+//==== SPEC Tizen Web API:System:Sensor:SensorService:getDefaultSensor M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+test(function () {
+    var conversionTable, type, exceptionName, i;
+    conversionTable = getTypeConversionExceptions("enum", false);
+    for (i = 0; i < conversionTable.length; i++) {
+        type = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+        assert_throws({name: exceptionName}, function () {
+            tizen.sensorservice.getDefaultSensor(type);
+        }, exceptionName + " should be thrown - given incorrect type");
+    }
+}, "SensorService_getDefaultSensor_type_TypeMismatch");
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saleh Enam Shohag <saleh.enam@samsung.com>
+
+*/
+function SensorService_getDefaultSensor_type_ultraviolet() {
+
+
+
+
+
+
+
+
+//==== TEST: SensorService_getDefaultSensor_type_ultraviolet
+//==== LABEL Check if sensorservice::getDefaultSensor() method returns UltravioletSensor object when called with ULTRAVIOLET
+//==== SPEC Tizen Web API:System:Sensor:SensorService:getDefaultSensor M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var ultravioletSensor;
+    ultravioletSensor = tizen.sensorservice.getDefaultSensor("ULTRAVIOLET");
+    assert_type(ultravioletSensor, 'object', "Method return wrong value");
+}, "SensorService_getDefaultSensor_type_ultraviolet");
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+        Wahid Dilawar Al-Hakim <wahid.h@samsung.com>
+
+*/
+function SensorService_in_tizen() {
+
+
+
+
+
+
+
+
+//==== TEST: SensorService_in_tizen
+//==== LABEL Check if SensorService exists in tizen
+//==== SPEC Tizen Web API:System:Sensor:SensorService:SensorService U
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA OBME
+
+test(function () {
+    assert_true("sensorservice" in tizen, "No sensorservice object in tizen.");
+}, "SensorService_in_tizen");
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+        Wahid Dilawar Al-Hakim <wahid.h@samsung.com>
+
+*/
+function SensorServiceManagerObject_notexist() {
+
+
+
+
+
+
+
+
+//==== TEST: SensorServiceManagerObject_notexist
+//==== LABEL Check if interface SensorServiceManagerObject exists, it should not
+//==== SPEC Tizen Web API:System:Sensor:SensorServiceManagerObject:SensorServiceManagerObject U
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("SensorServiceManagerObject");
+}, "SensorServiceManagerObject_notexist");
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+        Wahid Dilawar Al-Hakim <wahid.h@samsung.com>
+
+*/
+function SensorService_notexist() {
+
+
+
+
+
+
+
+
+//==== TEST: SensorService_notexist
+//==== LABEL Check if interface SensorService exists, it should not
+//==== SPEC Tizen Web API:System:Sensor:SensorService:SensorService U
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("SensorService");
+}, "SensorService_notexist");
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+        Md. Samsuddin Alam <ss.alam@samsung.com>
+        Hyukin Kwon <hyukin.kwon@samsung.com>
+
+*/
+function Sensor_setChangeListener_exist() {
+
+
+
+
+
+
+
+
+//==== TEST: Sensor_setChangeListener_exist
+//==== LABEL Check if Sensor::setChangeListener() method exists
+//==== SPEC Tizen Web API:System:Sensor:Sensor:setChangeListener M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    var availableSensorTypes = null, availableSensor;
+
+    availableSensorTypes = tizen.sensorservice.getAvailableSensors();
+    
+    if (availableSensorTypes.length == 0 || availableSensorTypes == null)
+        assert_unreached("No sensors are available in this device.");
+
+    availableSensor = tizen.sensorservice.getDefaultSensor(availableSensorTypes[0]);
+    check_method_exists(availableSensor, "setChangeListener");
+}, "Sensor_setChangeListener_exist");
+
+
+
+}
+
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+        Md. Samsuddin Alam <ss.alam@samsung.com>
+        Hyukin Kwon <hyukin.kwon@samsung.com>
+
+*/
+function Sensor_setChangeListener() {
+
+
+
+
+
+
+
+
+//==== TEST: Sensor_setChangeListener
+//==== LABEL Check if setChangeListener() works properly
+//==== SPEC Tizen Web API:System:Sensor:Sensor:setChangeListener M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== PRE Prepare to change sensor values.
+//==== STEP Click run and change the value of the sensor according to the pop up.
+//==== EXPECT Pass
+//==== EXECUTION_TYPE manual
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+setup({timeout: 30000});
+
+var t = async_test("Sensor_setChangeListener", {timeout: 30000}), onsuccessCB, onchangedCB, availableSensorTypes = null, availableSensor, retValue = null;
+
+t.step(function () {
+    add_result_callback(function () {
+        availableSensor.stop();
+    });
+
+    availableSensorTypes = tizen.sensorservice.getAvailableSensors();
+
+    if (availableSensorTypes.length == 0 || availableSensorTypes == null)
+        assert_unreached("No sensors are available in this device.");
+
+    availableSensor = tizen.sensorservice.getDefaultSensor(availableSensorTypes[0]);
+
+    onchangedCB = t.step_func(function (sensorData) {        
+        assert_equals(retValue, undefined, "setChangeListener returns wrong value");
+        t.done();
+    });
+
+    onsuccessCB = t.step_func(function () {
+    });
+
+    retValue = availableSensor.setChangeListener(onchangedCB);
+    availableSensor.start(onsuccessCB);
+
+    alert("Change the value of the following sensor type : " + availableSensorTypes[0]);
+});
+
+
+
+}
+
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+        Md. Samsuddin Alam <ss.alam@samsung.com>
+        Hyukin Kwon <hyukin.kwon@samsung.com>
+
+*/
+function Sensor_setChangeListener_misarg() {
+
+
+
+
+
+
+
+
+//==== TEST: Sensor_setChangeListener_misarg
+//==== LABEL Check if Sensor::setChangeListener() throws exception when successCallback is missing
+//==== SPEC Tizen Web API:System:Sensor:Sensor:setChangeListener M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MMA
+
+test(function () {
+    var availableSensorTypes = null, availableSensor;
+
+    availableSensorTypes = tizen.sensorservice.getAvailableSensors();
+    
+    if (availableSensorTypes.length == 0 || availableSensorTypes == null)
+        assert_unreached("No sensors are available in this device.");
+
+    availableSensor = tizen.sensorservice.getDefaultSensor(availableSensorTypes[0]);
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        availableSensor.setChangeListener();
+    }, TYPE_MISMATCH_EXCEPTION + " should be thrown");
+}, "Sensor_setChangeListener_misarg");
+
+
+
+}
+
+/*
+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.
+
+Authors:
+        Saleh Enam Shohag<saleh.enam@samsung.com>
+        Hyukin Kwon <hyukin.kwon@samsung.com>
+
+*/
+function Sensor_setChangeListener_successCallback_invalid_cb() {
+
+
+
+
+
+
+
+
+//==== TEST: Sensor_setChangeListener_successCallback_invalid_cb
+//==== LABEL Check if Sensor::setChangeListener() throw exception when successCallback has non callable attributes
+//==== SPEC Tizen Web API:System:Sensor:Sensor:setChangeListener M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTL
+
+setup({timeout: 30000});
+
+var t = async_test("Sensor_setChangeListener_successCallback_invalid_cb", {timeout: 30000}), availableSensorTypes = null, availableSensor, successCallback, exceptionName, incorrectListeners, i;
+
+t.step(function () {
+    add_result_callback(function () {
+        availableSensor.stop();
+    });
+
+    availableSensorTypes = tizen.sensorservice.getAvailableSensors();
+    
+    if (availableSensorTypes.length == 0 || availableSensorTypes == null)
+        assert_unreached("No sensors are available in this device.");
+
+    availableSensor = tizen.sensorservice.getDefaultSensor(availableSensorTypes[0]);
+
+    incorrectListeners = getListenerConversionExceptions(["onsuccess"]);
+    for(i = 0; i < incorrectListeners.length; i++) {
+        successCallback = incorrectListeners[i][0];
+        exceptionName = incorrectListeners[i][1];
+        assert_throws({name : exceptionName},
+            function () {
+                availableSensor.setChangeListener(successCallback);
+            }, exceptionName + " should be thrown - given incorrect successCallback.");
+    }
+    t.done();
+});
+
+
+
+}
+
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+        Md. Samsuddin Alam <ss.alam@samsung.com>
+        Hyukin Kwon <hyukin.kwon@samsung.com>
+
+*/
+function Sensor_setChangeListener_successCallback_TypeMismatch() {
+
+
+
+
+
+
+
+
+//==== TEST: Sensor_setChangeListener_successCallback_TypeMismatch
+//==== LABEL Check if Sensor::setChangeListener() with incorrect successCallback argument throws exception
+//==== SPEC Tizen Web API:System:Sensor:Sensor:setChangeListener M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test("Sensor_setChangeListener_successCallback_TypeMismatch", {timeout: 30000}), onsuccessCB, onchangedCB, exceptionName, i, conversionTable, availableSensorTypes = null, availableSensor;
+
+t.step(function () {
+    add_result_callback(function () {
+        availableSensor.stop();
+    });
+
+    availableSensorTypes = tizen.sensorservice.getAvailableSensors();
+    
+    if (availableSensorTypes.length == 0 || availableSensorTypes == null)
+        assert_unreached("No sensors are available in this device.");
+
+    availableSensor = tizen.sensorservice.getDefaultSensor(availableSensorTypes[0]);
+
+    onsuccessCB = t.step_func(function () {
+        conversionTable = getTypeConversionExceptions("functionObject", false);
+        for (i = 0; i < conversionTable.length; i++) {
+            onchangedCB = conversionTable[i][0];
+            exceptionName = conversionTable[i][1];
+            assert_throws({name: exceptionName}, function () {
+                availableSensor.setChangeListener(onchangedCB);
+            }, exceptionName + " should be thrown - given incorrect successCallback.");
+        }
+        t.done();
+    });
+
+    availableSensor.start(onsuccessCB);
+});
+
+
+
+}
+
+/*
+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.
+
+Authors:
+        Mohammad Ashekur Rahman <ashek.rahman@samsung.com>
+        Hyukin Kwon <hyukin.kwon@samsung.com>
+
+*/
+function Sensor_start_errorCallback_invalid_cb() {
+
+
+
+
+
+
+
+
+//==== TEST: Sensor_start_errorCallback_invalid_cb
+//==== LABEL Check if Sensor::start() method throws exception when errorCallback is invalid
+//==== SPEC Tizen Web API:System:Sensor:Sensor:start M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== PRIORITY P2
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 30000});
+
+var t = async_test("Sensor_start_errorCallback_invalid_cb", {timeout: 30000}), onsuccessCB, invalidCallback, availableSensorTypes = null, availableSensor;
+
+t.step(function () {
+    availableSensorTypes = tizen.sensorservice.getAvailableSensors();
+
+    if (availableSensorTypes.length == 0 || availableSensorTypes == null)
+        assert_unreached("No sensors are available in this device.");
+
+    availableSensor = tizen.sensorservice.getDefaultSensor(availableSensorTypes[0]);
+
+    onsuccessCB = t.step_func(function () {
+        assert_unreached("start() success callback invoked");
+    });
+
+    invalidCallback = {
+        onerror: t.step_func(function () {
+            assert_unreached("start() invalid error callback invoked");
+        })
+    };
+
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        availableSensor.start(onsuccessCB, invalidCallback);
+    }, TYPE_MISMATCH_EXCEPTION + " should be thrown");
+
+    t.done();
+});
+
+
+
+}
+
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+        Shahriar Hasan <shahriar.j@samsung.com>
+        Hyukin Kwon <hyukin.kwon@samsung.com>
+
+*/
+function Sensor_start_errorCallback_TypeMismatch() {
+
+
+
+
+
+
+
+
+//==== TEST: Sensor_start_errorCallback_TypeMismatch
+//==== LABEL Check if Sensor::start() with incorrect errorCallback argument throws exception
+//==== SPEC Tizen Web API:System:Sensor:Sensor:start M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test("Sensor_start_errorCallback_TypeMismatch", {timeout: 30000}), startSuccessCallback, conversionTable, incorrectCallback, exceptionName, i, availableSensorTypes = null, availableSensor;
+
+t.step(function () {
+    availableSensorTypes = tizen.sensorservice.getAvailableSensors();
+
+    if (availableSensorTypes.length == 0 || availableSensorTypes == null)
+        assert_unreached("No sensors are available in this device.");
+
+    availableSensor = tizen.sensorservice.getDefaultSensor(availableSensorTypes[0]);
+
+    startSuccessCallback = t.step_func(function () {
+        assert_unreached("Callback invoked");
+    });
+
+    conversionTable = getTypeConversionExceptions("functionObject", true);
+    for (i = 0; i < conversionTable.length; i++) {
+        incorrectCallback = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+        assert_throws({name: exceptionName}, function () {
+            availableSensor.start(startSuccessCallback, incorrectCallback);
+        }, exceptionName + " should be thrown - given incorrect error callback - " + incorrectCallback);
+    }
+
+    t.done();
+});
+
+
+
+}
+
+/*
+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.
+
+Authors:
+        Saleh Enam Shohag <saleh.enam@samsung.com>
+        Hyukin Kwon <hyukin.kwon@samsung.com>
+
+*/
+function Sensor_start_exist() {
+
+
+
+
+
+
+
+
+//==== TEST: Sensor_start_exist
+//==== LABEL Check if Sensor::start() method exists
+//==== SPEC Tizen Web API:System:Sensor:Sensor:start M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    var availableSensorTypes = null, availableSensor;
+
+    availableSensorTypes = tizen.sensorservice.getAvailableSensors();
+
+    if (availableSensorTypes.length == 0 || availableSensorTypes == null)
+        assert_unreached("No sensors are available in this device.");
+
+    availableSensor = tizen.sensorservice.getDefaultSensor(availableSensorTypes[0]);
+
+    check_method_exists(availableSensor, "start");
+}, "Sensor_start_exist");
+
+
+
+}
+
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+        Md. Samsuddin Alam <ss.alam@samsung.com>
+        Hyukin Kwon <hyukin.kwon@samsung.com>
+
+*/
+function Sensor_start() {
+
+
+
+
+
+
+
+
+//==== TEST: Sensor_start
+//==== LABEL Check if Sensor::start() method works properly
+//==== SPEC Tizen Web API:System:Sensor:Sensor:start M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P1
+//==== TEST_CRITERIA MMINA MAST
+
+setup({timeout: 30000});
+
+var t = async_test("Sensor_start", {timeout: 30000}), onsuccessCB, availableSensorTypes = null, availableSensor;
+
+t.step(function () {
+    availableSensorTypes = tizen.sensorservice.getAvailableSensors();
+
+    if (availableSensorTypes.length == 0 || availableSensorTypes == null)
+        assert_unreached("No sensors are available in this device.");
+
+    availableSensor = tizen.sensorservice.getDefaultSensor(availableSensorTypes[0]);
+
+    onsuccessCB = t.step_func(function () {
+        availableSensor.stop();
+        t.done();
+    });
+
+    availableSensor.start(onsuccessCB);
+});
+
+
+
+}
+
+/*
+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.
+
+Authors:
+        Saleh Enam Shohag <saleh.enam@samsung.com>
+        Hyukin Kwon <hyukin.kwon@samsung.com>
+
+*/
+function Sensor_start_misarg() {
+
+
+
+
+
+
+
+
+//==== TEST: Sensor_start_misarg
+//==== LABEL Check if Sensor::start() throws exception when successCallback is missing
+//==== SPEC Tizen Web API:System:Sensor:Sensor:start M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MMA
+
+test(function () {
+    var availableSensorTypes = null, availableSensor;
+
+    availableSensorTypes = tizen.sensorservice.getAvailableSensors();
+
+    if (availableSensorTypes.length == 0 || availableSensorTypes == null)
+        assert_unreached("No sensors are available in this device.");
+
+    availableSensor = tizen.sensorservice.getDefaultSensor(availableSensorTypes[0]);
+
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        availableSensor.start();
+    }, "Exception should thrown - Not given any argument");
+}, "Sensor_start_misarg");
+
+
+
+}
+
+/*
+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.
+
+Authors:
+        Saleh Enam Shohag<saleh.enam@samsung.com>
+        Hyukin Kwon <hyukin.kwon@samsung.com>
+
+*/
+function Sensor_start_successCallback_invalid_cb() {
+
+
+
+
+
+
+
+
+//==== TEST: Sensor_start_successCallback_invalid_cb
+//==== LABEL Check if Sensor::start() method throws exception when successCallback is invalid
+//==== SPEC Tizen Web API:System:Sensor:Sensor:start M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 30000});
+
+var t = async_test("Sensor_start_successCallback_invalid_cb", {timeout: 30000}), invalidCallback, availableSensorTypes = null, availableSensor;
+
+t.step(function () {
+    availableSensorTypes = tizen.sensorservice.getAvailableSensors();
+
+    if (availableSensorTypes.length == 0 || availableSensorTypes == null)
+        assert_unreached("No sensors are available in this device.");
+
+    availableSensor = tizen.sensorservice.getDefaultSensor(availableSensorTypes[0]);
+
+    invalidCallback = {
+        onsuccess: t.step_func(function () {
+            assert_unreached("start() success callback invoked");
+        })
+    }
+
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        availableSensor.start(invalidCallback);
+    }, TYPE_MISMATCH_EXCEPTION + " should be thrown");
+
+    t.done();
+});
+
+
+
+}
+
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+        Shahriar Hasan <shahriar.j@samsung.com>
+        Hyukin Kwon <hyukin.kwon@samsung.com>
+
+*/
+function Sensor_start_successCallback_TypeMismatch() {
+
+
+
+
+
+
+
+
+//==== TEST: Sensor_start_successCallback_TypeMismatch
+//==== LABEL Check if Sensor::start() with incorrect successCallback argument throws exception
+//==== SPEC Tizen Web API:System:Sensor:Sensor:start M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test("Sensor_start_successCallback_TypeMismatch", {timeout: 30000}), errorCallback, conversionTable, incorrectCallback, exceptionName, i, availableSensor, availableSensorTypes = null;
+
+t.step(function () {
+    availableSensorTypes = tizen.sensorservice.getAvailableSensors();
+
+    if (availableSensorTypes.length == 0 || availableSensorTypes == null)
+        assert_unreached("No sensors are available in this device.");
+
+    availableSensor = tizen.sensorservice.getDefaultSensor(availableSensorTypes[0]);
+
+    errorCallback = t.step_func(function (error) {
+        assert_unreached("ErrorCallback invoked: " + error.name + ": " + error.message);
+    });
+
+    conversionTable = getTypeConversionExceptions("functionObject", true);
+
+    for (i = 0; i < conversionTable.length; i++) {
+        incorrectCallback = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+        assert_throws({name: exceptionName}, function () {
+            availableSensor.start(incorrectCallback, errorCallback);
+        }, exceptionName + " should be thrown - given incorrect success callback - " + incorrectCallback);
+    }
+
+    t.done();
+});
+
+
+
+}
+
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+        Hyukin Kwon <hyukin.kwon@samsung.com>
+
+*/
+function Sensor_start_with_errorCallback() {
+
+
+
+
+
+
+
+
+//==== TEST: Sensor_start_with_errorCallback
+//==== LABEL Check method start of Sensor with errorCallback
+//==== SPEC Tizen Web API:System:Sensor:Sensor:start M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P1
+//==== TEST_CRITERIA MOA MR
+
+setup({timeout: 30000});
+
+var t = async_test("Sensor_start_with_errorCallback", {timeout: 30000}), onsuccessCB, onerrorCB, returnValue = null, availableSensorTypes = null, availableSensor;
+
+t.step(function () {
+    add_result_callback(function () {
+        availableSensor.stop();
+    });
+
+    availableSensorTypes = tizen.sensorservice.getAvailableSensors();
+
+    if (availableSensorTypes.length == 0 || availableSensorTypes == null)
+        assert_unreached("No sensors are available in this device.");
+
+    availableSensor = tizen.sensorservice.getDefaultSensor(availableSensorTypes[0]);
+
+    onsuccessCB = t.step_func(function () {
+        assert_equals(returnValue, undefined, "Return value is wrong");
+        t.done();
+    });
+
+    onerrorCB = t.step_func(function () {
+        assert_unreached("errorCallback is invoked");
+    });
+
+    returnValue = availableSensor.start(onsuccessCB, onerrorCB);
+});
+
+
+
+}
+
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+        Saleh Enam Shohag<saleh.enam@samsung.com>
+
+*/
+function Sensor_stop_exist() {
+
+
+
+
+
+
+
+
+//==== TEST: Sensor_stop_exist
+//==== LABEL Check if Sensor::stop() method exists
+//==== SPEC Tizen Web API:System:Sensor:Sensor:stop M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    var availableSensorTypes = null, availableSensor;
+    availableSensorTypes = tizen.sensorservice.getAvailableSensors();
+
+    if (availableSensorTypes.length == 0 || availableSensorTypes == null)
+        assert_unreached("No sensors are available in this device.");
+
+    availableSensor = tizen.sensorservice.getDefaultSensor(availableSensorTypes[0]);
+
+    check_method_exists(availableSensor, "stop");
+}, "Sensor_stop_exist");
+
+
+
+}
+
+/*
+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.
+
+Authors:
+        Saleh Enam Shohag <saleh.enam@samsung.com>
+
+*/
+function Sensor_stop_extra_argument() {
+
+
+
+
+
+
+
+
+//==== TEST: Sensor_stop_extra_argument
+//==== LABEL Check Sensor::stop() method with extra argument
+//==== SPEC Tizen Web API:System:Sensor:Sensor:stop M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P2
+//==== TEST_CRITERIA MNAEX
+
+setup({timeout: 30000});
+
+var t = async_test("Sensor_stop_extra_argument", {timeout: 30000}), onsuccessCB, availableSensor, availableSensorTypes = null;
+
+t.step(function () {
+    var availableSensorTypes = null, availableSensor;
+    availableSensorTypes = tizen.sensorservice.getAvailableSensors();
+
+    if (availableSensorTypes.length == 0 || availableSensorTypes == null)
+        assert_unreached("No sensors are available in this device.");
+
+    availableSensor = tizen.sensorservice.getDefaultSensor(availableSensorTypes[0]);
+
+    onsuccessCB = t.step_func(function () {
+        checkExtraArgument(availableSensor, "stop");
+        t.done();
+    });
+
+    availableSensor.start(onsuccessCB);
+});
+
+
+
+}
+
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+        Saleh Enam Shohag <saleh.enam@samsung.com>
+        Hyukin Kwon <hyukin.kwon@samsung.com>
+
+*/
+function Sensor_stop() {
+
+
+
+
+
+
+
+
+//==== TEST: Sensor_stop
+//==== LABEL Check if Sensor::stop() method works properly
+//==== SPEC Tizen Web API:System:Sensor:Sensor:stop M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR MOA
+
+setup({timeout: 30000});
+
+var t = async_test("Sensor_stop", {timeout: 30000}), onsuccessCB, availableSensor, availableSensorTypes = null, retVal = null;
+
+t.step(function () {
+    availableSensorTypes = tizen.sensorservice.getAvailableSensors();
+
+    if (availableSensorTypes.length == 0 || availableSensorTypes == null)
+        assert_unreached("No sensors are available in this device.");
+
+    availableSensor = tizen.sensorservice.getDefaultSensor(availableSensorTypes[0]);
+
+    onsuccessCB = t.step_func(function () {
+        retVal = availableSensor.stop();
+        assert_equals(retVal, undefined, "Return type should be undefined");
+        t.done();
+    });
+
+    availableSensor.start(onsuccessCB);
+});
+
+
+
+}
+
+/*
+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.
+
+Authors:
+        Saleh Enam Shohag <saleh.enam@samsung.com>
+
+*/
+function Sensor_stop_without_sensor_type() {
+
+
+
+
+
+
+
+
+//==== TEST: Sensor_stop_without_sensor_type
+//==== LABEL Check if Sensor::stop() method works properly
+//==== SPEC Tizen Web API:System:Sensor:Sensor:stop M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== PRIORITY P1
+//==== ONLOAD_DELAY 30
+//==== TEST_CRITERIA MMINA
+
+setup({timeout: 30000});
+
+var t = async_test("Sensor_stop_without_sensor_type", {timeout: 30000}), onsuccessCB, availableSensor, availableSensorTypes = null, retVal = null;
+
+t.step(function () {
+    availableSensorTypes = tizen.sensorservice.getAvailableSensors();
+
+    if (availableSensorTypes.length == 0 || availableSensorTypes == null)
+        assert_unreached("No sensors are available in this device.");
+
+    availableSensor = tizen.sensorservice.getDefaultSensor(availableSensorTypes[0]);
+
+    onsuccessCB = t.step_func(function () {
+        retVal = availableSensor.stop();
+        assert_equals(retVal, undefined, "Return type should be undefined");
+        t.done();
+    });
+
+    availableSensor.start(onsuccessCB);
+});
+
+
+
+}
+
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+        Saleh Enam Shohag <saleh.enam@samsung.com>
+        Hyukin.Kwon <hyukin.kwon@samsung.com>
+
+*/
+function Sensor_unsetChangeListener_exist() {
+
+
+
+
+
+
+
+
+//==== TEST: Sensor_unsetChangeListener_exist
+//==== LABEL Check if Sensor::unsetChangeListener() method exists
+//==== SPEC Tizen Web API:System:Sensor:Sensor:unsetChangeListener M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== TEST_CRITERIA ME
+//==== PRIORITY P0
+
+test(function () {
+    var availableSensorTypes = null, availableSensor;
+
+    availableSensorTypes = tizen.sensorservice.getAvailableSensors();
+
+    if (availableSensorTypes.length == 0 || availableSensorTypes == null)
+        assert_unreached("No sensors are available in this device.");
+
+    availableSensor = tizen.sensorservice.getDefaultSensor(availableSensorTypes[0]);
+
+    check_method_exists(availableSensor, "unsetChangeListener");
+}, "Sensor_unsetChangeListener_exist");
+
+
+
+}
+
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+        Hyukin.Kwon <hyukin.kwon@samsung.com>
+
+*/
+function Sensor_unsetChangeListener_extra_argument() {
+
+
+
+
+
+
+
+
+//==== TEST: Sensor_unsetChangeListener_extra_argument
+//==== LABEL Check Sensor::unsetChangeListener() method with extra argument
+//==== SPEC Tizen Web API:System:Sensor:Sensor:unsetChangeListener M
+//==== SPEC_URL TBD
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P2
+//==== TEST_CRITERIA MNAEX
+
+test(function () {
+    var availableSensorTypes = null, availableSensor;
+
+    availableSensorTypes = tizen.sensorservice.getAvailableSensors();
+
+    if (availableSensorTypes.length == 0 || availableSensorTypes == null)
+        assert_unreached("No sensors are available in this device.");
+
+    availableSensor = tizen.sensorservice.getDefaultSensor(availableSensorTypes[0]);
+
+    check_method_exists(availableSensor, "unsetChangeListener");
+
+    checkExtraArgument(availableSensor, "unsetChangeListener");
+}, "Sensor_unsetChangeListener_extra_argument");
+
+
+
+}
+
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+        Saleh Enam Shohag<saleh.enam@samsung.com>
+        Hyukin.Kwon <hyukin.kwon@samsung.com>
+
+*/
+function Sensor_unsetChangeListener() {
+
+
+
+
+
+
+
+
+//==== TEST: Sensor_unsetChangeListener
+//==== LABEL Check if unsetChangeListener() works properly
+//==== SPEC Tizen Web API:System:Sensor:Sensor:unsetChangeListener M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+setup({timeout: 30000});
+
+var t = async_test("Sensor_unsetChangeListener", {timeout: 30000}), onchangedCB, availableSensor, availableSensorTypes = null, retVal;
+
+t.step(function () {
+    availableSensorTypes = tizen.sensorservice.getAvailableSensors();
+
+    if (availableSensorTypes.length == 0 || availableSensorTypes == null)
+        assert_unreached("No sensors are available in this device.");
+
+    availableSensor = tizen.sensorservice.getDefaultSensor(availableSensorTypes[0]);
+
+    onchangedCB = t.step_func(function (sensorData) {        
+    });
+
+    availableSensor.setChangeListener(onchangedCB);
+    retVal = availableSensor.unsetChangeListener();
+    assert_equals(retVal, undefined, "Return type should be undefined");
+    t.done();
+});
+
+
+
+}
+
+/*
+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.
+
+Authors:
+        Saleh Enam Shohag <saleh.enam@samsung.com>
+
+*/
+function UltravioletSensor_extend() {
+
+
+
+
+
+
+
+
+//==== TEST: UltravioletSensor_extend
+//==== LABEL Check if UltravioletSensor is extendable
+//==== SPEC Tizen Web API:System:Sensor:UltravioletSensor:UltravioletSensor U
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA OBX
+
+test(function () {
+    var ultravioletSensor;
+    ultravioletSensor = tizen.sensorservice.getDefaultSensor("ULTRAVIOLET");
+    check_extensibility(ultravioletSensor);
+}, "UltravioletSensor_extend");
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saleh Enam Shohag <saleh.enam@samsung.com>
+
+*/
+function UltravioletSensor_getUltravioletSensorData_errorCallback_invalid_cb() {
+
+
+
+
+
+
+
+
+//==== TEST: UltravioletSensor_getUltravioletSensorData_errorCallback_invalid_cb
+//==== LABEL Check if UltravioletSensor::getUltravioletSensorData() method throws exception when errorCallback is invalid
+//==== SPEC Tizen Web API:System:Sensor:UltravioletSensor:getUltravioletSensorData M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 30000});
+
+var t = async_test("UltravioletSensor_getUltravioletSensorData_errorCallback_invalid_cb", {timeout: 30000}), invalidcallback, onsuccessCB, ultravioletSensor;
+
+t.step(function () {
+    ultravioletSensor = tizen.sensorservice.getDefaultSensor("ULTRAVIOLET");
+
+    add_result_callback(function () {
+        ultravioletSensor.stop();
+    });
+
+    invalidcallback = {
+        onerror: t.step_func(function (sensorData) {
+            assert_unreached("getUltravioletSensorData() successcallback invoked");
+        })
+    };
+
+    onGetSuccessCB = t.step_func(function (sensorData) {
+        assert_unreached("SuccessCallback should not be called");
+    });
+
+    onsuccessCB = t.step_func(function () {
+        assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+            ultravioletSensor.getUltravioletSensorData(onGetSuccessCB, invalidcallback);
+        }, TYPE_MISMATCH_EXCEPTION + " Should throw exception");
+        t.done();
+    });
+
+    ultravioletSensor.start(onsuccessCB);
+});
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saud Mohammad Mostafa <saud.mm@samsung.com>
+        Md. Samsuddin Alam <ss.alam@samsung.com>
+
+*/
+function UltravioletSensor_getUltravioletSensorData_errorCallback_invoked() {
+
+
+
+
+
+
+
+
+//==== TEST: UltravioletSensor_getUltravioletSensorData_errorCallback_invoked
+//==== LABEL Check exception in error callback of getUltravioletSensorData method
+//==== SPEC Tizen Web API:System:Sensor:UltravioletSensor:getUltravioletSensorData M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P2
+//==== TEST_CRITERIA MERRCB
+
+setup({timeout: 30000});
+
+var t = async_test("UltravioletSensor_getUltravioletSensorData_errorCallback_invoked", {timeout: 30000}), onerrorCB, onGetSuccessCB, ultravioletSensor;
+
+t.step(function () {
+    ultravioletSensor = tizen.sensorservice.getDefaultSensor("ULTRAVIOLET");
+
+    onGetSuccessCB = t.step_func(function (sensorData) {
+        assert_unreached("SuccessCallback should not be called");
+    });
+
+    onerrorCB = t.step_func(function (error) {
+        assert_equals("ServiceNotAvailableError", error.name, "Error callback should be thrown with error: " + error.name + ".");
+        t.done();
+    });
+
+    ultravioletSensor.getUltravioletSensorData(onGetSuccessCB, onerrorCB);
+});
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saleh Enam Shohag <saleh.enam@samsung.com>
+
+*/
+function UltravioletSensor_getUltravioletSensorData_errorCallback_TypeMismatch() {
+
+
+
+
+
+
+
+
+//==== TEST: UltravioletSensor_getUltravioletSensorData_errorCallback_TypeMismatch
+//==== LABEL Check if UltravioletSensor::getUltravioletSensorData() with incorrect errorCallback argument throws exception
+//==== SPEC Tizen Web API:System:Sensor:UltravioletSensor:getUltravioletSensorData M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test("UltravioletSensor_getUltravioletSensorData_errorCallback_TypeMismatch", {timeout: 30000}), exceptionName, i, conversionTable, onGetSuccessCB, onerrorCB, ultravioletSensor, onsuccessCB;
+
+t.step(function () {
+    ultravioletSensor = tizen.sensorservice.getDefaultSensor("ULTRAVIOLET");
+
+    add_result_callback(function () {
+        ultravioletSensor.stop();
+    });
+
+    onGetSuccessCB = t.step_func(function () {
+        assert_unreached("Unexpected successCallback");
+    });
+
+    onsuccessCB = t.step_func(function () {
+        conversionTable = getTypeConversionExceptions("functionObject", true);
+        for (i = 0; i < conversionTable.length; i++) {
+            onerrorCB = conversionTable[i][0];
+            exceptionName = conversionTable[i][1];
+            assert_throws({name: exceptionName}, function () {
+                ultravioletSensor.getUltravioletSensorData(onGetSuccessCB, onerrorCB);
+            }, exceptionName + " should be thrown - given incorrect errorCallback.");
+        }
+        t.done();
+    });
+
+    ultravioletSensor.start(onsuccessCB);
+});
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saleh Enam Shohag <saleh.enam@samsung.com>
+
+*/
+function UltravioletSensor_getUltravioletSensorData_exist() {
+
+
+
+
+
+
+
+
+//==== TEST: UltravioletSensor_getUltravioletSensorData_exist
+//==== LABEL Check if UltravioletSensor::getUltravioletSensorData() method exists
+//==== SPEC Tizen Web API:System:Sensor:UltravioletSensor:getUltravioletSensorData M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    var ultravioletSensor;
+    ultravioletSensor = tizen.sensorservice.getDefaultSensor("ULTRAVIOLET");
+    assert_true("getUltravioletSensorData" in ultravioletSensor, "No getUltravioletSensorData method in ultravioletSensor");
+    check_method_exists(ultravioletSensor, "getUltravioletSensorData");
+}, "UltravioletSensor_getUltravioletSensorData_exist");
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saleh Enam Shohag <saleh.enam@samsung.com>
+
+*/
+function UltravioletSensor_getUltravioletSensorData() {
+
+
+
+
+
+
+
+
+//==== TEST: UltravioletSensor_getUltravioletSensorData
+//==== LABEL Check if UltravioletSensor::getUltravioletSensorData() method works properly
+//==== SPEC Tizen Web API:System:Sensor:UltravioletSensor U
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR MMINA
+
+setup({timeout: 30000});
+
+var t = async_test("UltravioletSensor_getUltravioletSensorData", {timeout: 30000}), onGetSuccessCb, onsuccessCB, ultravioletSensor, returnValue;
+
+t.step(function () {
+    ultravioletSensor = tizen.sensorservice.getDefaultSensor("ULTRAVIOLET");
+
+    add_result_callback(function () {
+        ultravioletSensor.stop();
+    });
+
+    onGetSuccessCB = t.step_func(function (ultraviolet) {
+        assert_not_equals(ultraviolet.ultravioletLevel, null, "Fail to getUltravioletSensorData");
+        assert_equals(returnValue, undefined, "getUltravioletSensorData returns wrong value");
+        t.done();
+    });
+
+    onsuccessCB = t.step_func(function () {
+        returnValue = ultravioletSensor.getUltravioletSensorData(onGetSuccessCB);
+    });
+
+    ultravioletSensor.start(onsuccessCB);
+});
+
+
+}
+/*
+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.
+
+Authors:
+        Saleh Enam Shohag <saleh.enam@samsung.com>
+
+*/
+function UltravioletSensor_getUltravioletSensorData_misarg() {
+
+
+
+
+
+
+
+
+//==== TEST: UltravioletSensor_getUltravioletSensorData_misarg
+//==== LABEL Check if UltravioletSensor::getUltravioletSensorData() throws exception when successCallback is missing
+//==== SPEC Tizen Web API:System:Sensor:UltravioletSensor:getUltravioletSensorData M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P2
+//==== TEST_CRITERIA MMA
+
+setup({timeout: 30000});
+
+var t = async_test("UltravioletSensor_getUltravioletSensorData_misarg", {timeout: 30000}), onsuccessCB, ultravioletSensor;
+
+t.step(function () {
+    ultravioletSensor = tizen.sensorservice.getDefaultSensor("ULTRAVIOLET");
+
+    add_result_callback(function () {
+        ultravioletSensor.stop();
+    });
+
+    onsuccessCB = t.step_func(function() {
+        assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+            ultravioletSensor.getUltravioletSensorData();
+        }, TYPE_MISMATCH_EXCEPTION + " should be thrown");
+        t.done();
+    });
+
+    ultravioletSensor.start(onsuccessCB);
+});
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saleh Enam Shohag <saleh.enam@samsung.com>
+
+*/
+function UltravioletSensor_getUltravioletSensorData_successCallback_invalid_cb() {
+
+
+
+
+
+
+
+
+//==== TEST: UltravioletSensor_getUltravioletSensorData_successCallback_invalid_cb
+//==== LABEL Check if UltravioletSensor::getUltravioletSensorData() method throws exception when successCallback is invalid
+//==== SPEC Tizen Web API:System:Sensor:UltravioletSensor:getUltravioletSensorData M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 30000});
+
+var t = async_test("UltravioletSensor_getUltravioletSensorData_successCallback_invalid_cb", {timeout: 30000}), invalidcallback, onsuccessCB, ultravioletSensor;
+
+t.step(function () {
+    ultravioletSensor = tizen.sensorservice.getDefaultSensor("ULTRAVIOLET");
+
+    add_result_callback(function () {
+        ultravioletSensor.stop();
+    });
+
+    invalidcallback = {
+        onsuccess: t.step_func(function (sensorData) {
+            assert_unreached("getUltravioletSensorData() successcallback invoked")
+        })
+    };
+
+    onsuccessCB = t.step_func(function () {
+        assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+            ultravioletSensor.getUltravioletSensorData(invalidcallback);
+        }, TYPE_MISMATCH_EXCEPTION + " Should be thrown");
+        t.done();
+    });
+
+    ultravioletSensor.start(onsuccessCB);
+});
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saleh Enam Shohag <saleh.enam@samsung.com>
+
+*/
+function UltravioletSensor_getUltravioletSensorData_successCallback_TypeMismatch() {
+
+
+
+
+
+
+
+
+//==== TEST: UltravioletSensor_getUltravioletSensorData_successCallback_TypeMismatch
+//==== LABEL Check if UltravioletSensor::getUltravioletSensorData() with incorrect successCallback argument throws exception
+//==== SPEC Tizen Web API:System:Sensor:UltravioletSensor:getUltravioletSensorData M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 30000});
+
+var t = async_test("UltravioletSensor_getUltravioletSensorData_successCallback_TypeMismatch", {timeout: 30000}), exceptionName, i, conversionTable, onGetSuccessCB, onerrorCB, ultravioletSensor, onsuccessCB;
+
+t.step(function () {
+    ultravioletSensor = tizen.sensorservice.getDefaultSensor("ULTRAVIOLET");
+
+    add_result_callback(function () {
+        ultravioletSensor.stop();
+    });
+
+    onerrorCB = t.step_func(function (error) {
+        assert_unreached("getUltravioletSensorData() error callback invoked: name:" + error.name + ", msg: " + error.message);
+    });
+
+    onsuccessCB = t.step_func(function () {
+        conversionTable = getTypeConversionExceptions("functionObject", false);
+        for (i = 0; i < conversionTable.length; i++) {
+            onGetSuccessCB = conversionTable[i][0];
+            exceptionName = conversionTable[i][1];
+            assert_throws({name: exceptionName}, function () {
+                ultravioletSensor.getUltravioletSensorData(onGetSuccessCB, onerrorCB);
+            }, exceptionName + " should be thrown - given incorrect successCallback.");
+        }
+        t.done();
+    });
+
+    ultravioletSensor.start(onsuccessCB);
+});
+
+
+
+}
+/*
+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.
+
+Authors:
+        Saleh Enam Shohag <saleh.enam@samsung.com>
+
+*/
+function UltravioletSensor_getUltravioletSensorData_with_errorCallback() {
+
+
+
+
+
+
+
+
+//==== TEST: UltravioletSensor_getUltravioletSensorData_with_errorCallback
+//==== LABEL Check if UltravioletSensor::getUltravioletSensorData() method works properly with optional argument
+//==== SPEC Tizen Web API:System:Sensor:UltravioletSensor:getUltravioletSensorData M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== ONLOAD_DELAY 30
+//==== PRIORITY P1
+//==== TEST_CRITERIA MOA MR
+
+setup({timeout: 30000});
+
+var t = async_test("UltravioletSensor_getUltravioletSensorData_with_errorCallback", {timeout: 30000}), onGetSuccessCb, onsuccessCB, ultravioletSensor, returnValue, onerrorCB;
+
+t.step(function () {
+    ultravioletSensor = tizen.sensorservice.getDefaultSensor("ULTRAVIOLET");
+
+    add_result_callback(function () {
+        ultravioletSensor.stop();
+    });
+
+    onGetSuccessCB = t.step_func(function (ultraviolet) {
+        assert_not_equals(ultraviolet.ultravioletLevel, null, "Fail to getUltravioletSensorData");
+        assert_equals(returnValue, undefined, "getUltravioletSensorData returns wrong value");
+        t.done();
+    });
+
+    onerrorCB = t.step_func(function () {
+        assert_unreached("getUltravioletSensorData() error callback invoked: name:" + error.name + ", msg: " + error.message);
+    });
+
+    onsuccessCB = t.step_func(function () {
+        returnValue = ultravioletSensor.getUltravioletSensorData(onGetSuccessCB, onerrorCB);
+    });
+
+    returnValue = null;
+    ultravioletSensor.start(onsuccessCB);
+});
+
+
+}
+/*
+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.
+
+Authors:
+        Saleh Enam Shohag <saleh.enam@samsung.com>
+
+*/
+function UltravioletSensor_notexist() {
+
+
+
+
+
+
+
+
+//==== TEST: UltravioletSensor_notexist
+//==== LABEL Check if interface UltravioletSensor exists, it should not
+//==== SPEC Tizen Web API:System:Sensor:UltravioletSensor:UltravioletSensor U
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.3.0/org.tizen.mobile.web.device.apireference/tizen/sensor.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("UltravioletSensor");
+}, "UltravioletSensor_notexist");
+
+
+
+}
+var moduleName = "tct-sensorservice-tizen-tests";
+
+if(tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.photometer")){
+add_test_case(moduleName, SensorLightData_lightLevel_attribute);
+add_test_case(moduleName, SensorLightData_notexist);
+add_test_case(moduleName, LightSensor_extend);
+add_test_case(moduleName, LightSensor_getLightSensorData_errorCallback_invalid_cb);
+add_test_case(moduleName, LightSensor_getLightSensorData_errorCallback_invoked);
+add_test_case(moduleName, LightSensor_getLightSensorData_errorCallback_TypeMismatch);
+add_test_case(moduleName, LightSensor_getLightSensorData_exist);
+add_test_case(moduleName, LightSensor_getLightSensorData);
+add_test_case(moduleName, LightSensor_getLightSensorData_misarg);
+add_test_case(moduleName, LightSensor_getLightSensorData_successCallback_invalid_cb);
+add_test_case(moduleName, LightSensor_getLightSensorData_successCallback_TypeMismatch);
+add_test_case(moduleName, LightSensor_getLightSensorData_with_errorCallback);
+add_test_case(moduleName, LightSensor_notexist);
+add_test_case(moduleName, SensorService_getDefaultSensor_type_light);
+}
+
+if(tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.magnetometer")){
+add_test_case(moduleName, SensorMagneticData_accuracy_attribute);
+add_test_case(moduleName, SensorMagneticData_notexist);
+add_test_case(moduleName, SensorMagneticData_x_attribute);
+add_test_case(moduleName, SensorMagneticData_y_attribute);
+add_test_case(moduleName, SensorMagneticData_z_attribute);
+add_test_case(moduleName, MagneticSensor_extend);
+add_test_case(moduleName, MagneticSensor_getMagneticSensorData_errorCallback_invalid_cb);
+add_test_case(moduleName, MagneticSensor_getMagneticSensorData_errorCallback_invoked);
+add_test_case(moduleName, MagneticSensor_getMagneticSensorData_errorCallback_TypeMismatch);
+add_test_case(moduleName, MagneticSensor_getMagneticSensorData_exist);
+add_test_case(moduleName, MagneticSensor_getMagneticSensorData);
+add_test_case(moduleName, MagneticSensor_getMagneticSensorData_misarg);
+add_test_case(moduleName, MagneticSensor_getMagneticSensorData_successCallback_invalid_cb);
+add_test_case(moduleName, MagneticSensor_getMagneticSensorData_successCallback_TypeMismatch);
+add_test_case(moduleName, MagneticSensor_getMagneticSensorData_with_errorCallback);
+add_test_case(moduleName, MagneticSensor_notexist);
+add_test_case(moduleName, SensorDataSuccessCallback_onsuccess);
+add_test_case(moduleName, SensorService_getDefaultSensor_type_magnetic);
+}
+
+if(tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.barometer")){
+add_test_case(moduleName, SensorPressureData_notexist);
+add_test_case(moduleName, SensorPressureData_pressure_attribute);
+add_test_case(moduleName, PressureSensor_extend);
+add_test_case(moduleName, PressureSensor_getPressureSensorData_errorCallback_invalid_cb);
+add_test_case(moduleName, PressureSensor_getPressureSensorData_errorCallback_invoked);
+add_test_case(moduleName, PressureSensor_getPressureSensorData_errorCallback_TypeMismatch);
+add_test_case(moduleName, PressureSensor_getPressureSensorData_exist);
+add_test_case(moduleName, PressureSensor_getPressureSensorData);
+add_test_case(moduleName, PressureSensor_getPressureSensorData_misarg);
+add_test_case(moduleName, PressureSensor_getPressureSensorData_successCallback_invalid_cb);
+add_test_case(moduleName, PressureSensor_getPressureSensorData_successCallback_TypeMismatch);
+add_test_case(moduleName, PressureSensor_getPressureSensorData_with_errorCallback);
+add_test_case(moduleName, PressureSensor_notexist);
+add_test_case(moduleName, SensorService_getDefaultSensor_type_pressure);
+}
+
+if(tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.proximity")){
+add_test_case(moduleName, SensorProximityData_notexist);
+add_test_case(moduleName, SensorProximityData_proximityState_attribute);
+add_test_case(moduleName, ProximitySensor_extend);
+add_test_case(moduleName, ProximitySensor_getProximitySensorData_errorCallback_invalid_cb);
+add_test_case(moduleName, ProximitySensor_getProximitySensorData_errorCallback_invoked);
+add_test_case(moduleName, ProximitySensor_getProximitySensorData_errorCallback_TypeMismatch);
+add_test_case(moduleName, ProximitySensor_getProximitySensorData_exist);
+add_test_case(moduleName, ProximitySensor_getProximitySensorData);
+add_test_case(moduleName, ProximitySensor_getProximitySensorData_misarg);
+add_test_case(moduleName, ProximitySensor_getProximitySensorData_successCallback_invalid_cb);
+add_test_case(moduleName, ProximitySensor_getProximitySensorData_successCallback_TypeMismatch);
+add_test_case(moduleName, ProximitySensor_getProximitySensorData_with_errorCallback);
+add_test_case(moduleName, ProximitySensor_notexist);
+add_test_case(moduleName, SensorService_getDefaultSensor_type_proximity);
+add_test_case(moduleName, SensorData_notexist);
+add_test_case(moduleName, SensorDataSuccessCallback_notexist);
+add_test_case(moduleName, SensorServiceManagerObject_notexist);
+add_test_case(moduleName, SensorService_extend);
+add_test_case(moduleName, SensorService_getAvailableSensors_exist);
+add_test_case(moduleName, SensorService_getAvailableSensors_extra_argument);
+add_test_case(moduleName, SensorService_getAvailableSensors);
+add_test_case(moduleName, SensorService_getDefaultSensor_exist);
+add_test_case(moduleName, SensorService_getDefaultSensor_misarg);
+add_test_case(moduleName, SensorService_getDefaultSensor_type_TypeMismatch);
+add_test_case(moduleName, SensorService_in_tizen);
+add_test_case(moduleName, SensorService_notexist);
+add_test_case(moduleName, Sensor_notexist);
+add_test_case(moduleName, Sensor_start_errorCallback_invalid_cb);
+add_test_case(moduleName, Sensor_start_errorCallback_TypeMismatch);
+add_test_case(moduleName, Sensor_start_exist);
+add_test_case(moduleName, Sensor_start);
+add_test_case(moduleName, Sensor_start_misarg);
+add_test_case(moduleName, Sensor_start_successCallback_invalid_cb);
+add_test_case(moduleName, Sensor_start_successCallback_TypeMismatch);
+add_test_case(moduleName, Sensor_start_with_errorCallback);
+add_test_case(moduleName, Sensor_stop_exist);
+add_test_case(moduleName, Sensor_stop_extra_argument);
+add_test_case(moduleName, Sensor_stop);
+add_test_case(moduleName, Sensor_stop_without_sensor_type);
+add_test_case(moduleName, Sensor_unsetChangeListener_exist);
+add_test_case(moduleName, Sensor_unsetChangeListener_extra_argument);
+add_test_case(moduleName, Sensor_unsetChangeListener);
+add_test_case(moduleName, Sensor_setChangeListener);
+add_test_case(moduleName, Sensor_setChangeListener_exist);
+add_test_case(moduleName, Sensor_setChangeListener_misarg);
+add_test_case(moduleName, Sensor_setChangeListener_successCallback_invalid_cb);
+add_test_case(moduleName, Sensor_setChangeListener_successCallback_TypeMismatch);
+}
+
+if(tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.ultraviolet")){
+add_test_case(moduleName, UltravioletSensor_extend);
+add_test_case(moduleName, UltravioletSensor_getUltravioletSensorData_errorCallback_invalid_cb);
+add_test_case(moduleName, UltravioletSensor_getUltravioletSensorData_errorCallback_invoked);
+add_test_case(moduleName, UltravioletSensor_getUltravioletSensorData_errorCallback_TypeMismatch);
+add_test_case(moduleName, UltravioletSensor_getUltravioletSensorData_exist);
+add_test_case(moduleName, UltravioletSensor_getUltravioletSensorData);
+add_test_case(moduleName, UltravioletSensor_getUltravioletSensorData_misarg);
+add_test_case(moduleName, UltravioletSensor_getUltravioletSensorData_successCallback_invalid_cb);
+add_test_case(moduleName, UltravioletSensor_getUltravioletSensorData_successCallback_TypeMismatch);
+add_test_case(moduleName, UltravioletSensor_getUltravioletSensorData_with_errorCallback);
+add_test_case(moduleName, UltravioletSensor_notexist);
+add_test_case(moduleName, SensorService_getDefaultSensor_type_ultraviolet);
+}
+
+if(tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.heart_rate_monitor")){
+add_test_case(moduleName, HRMRawSensor_extend);
+add_test_case(moduleName, HRMRawSensor_getHRMRawSensorData_errorCallback_invalid_cb);
+add_test_case(moduleName, HRMRawSensor_getHRMRawSensorData_errorCallback_invoked);
+add_test_case(moduleName, HRMRawSensor_getHRMRawSensorData_errorCallback_TypeMismatch);
+add_test_case(moduleName, HRMRawSensor_getHRMRawSensorData_exist);
+add_test_case(moduleName, HRMRawSensor_getHRMRawSensorData);
+add_test_case(moduleName, HRMRawSensor_getHRMRawSensorData_misarg);
+add_test_case(moduleName, HRMRawSensor_getHRMRawSensorData_successCallback_invalid_cb);
+add_test_case(moduleName, HRMRawSensor_getHRMRawSensorData_successCallback_TypeMismatch);
+add_test_case(moduleName, HRMRawSensor_getHRMRawSensorData_with_errorCallback);
+add_test_case(moduleName, HRMRawSensor_notexist);
+add_test_case(moduleName, SensorHRMRawData_lightIntensity_attribute);
+add_test_case(moduleName, SensorHRMRawData_lightType_attribute);
+add_test_case(moduleName, SensorHRMRawData_notexist);
+}
+
diff --git a/webWidgetTCT_device/test/tct/tests/TestSysteminfo.js b/webWidgetTCT_device/test/tct/tests/TestSysteminfo.js
new file mode 100755 (executable)
index 0000000..244cf2e
--- /dev/null
@@ -0,0 +1,6015 @@
+/*
+Copyright (c) 2013 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+
+ */
+
+var attribute = "";
+var status_value = "";
+var isRoaming = false;
+
+var SystemInfoDeviceCapability = ["bluetooth", "nfc", "nfcReservedPush", "multiTouchCount", "inputKeyboard", "inputKeyboardLayout", "wifi", "wifiDirect", "opengles", "openglestextureFormat", "openglesVersion1_1", "openglesVersion2_0", "fmRadio", "platformVersion", "webApiVersion", "platformName", "camera", "cameraFront", "cameraFrontFlash", "cameraBack", "cameraBackFlash", "location", "locationGps", "locationWps", "microphone", "usbHost", "usbAccessory", "screenOutputRca", "screenOutputHdmi", "platformCoreCpuArch", "platformCoreFpuArch", "sipVoip", "speechRecognition", "speechSynthesis", "accelerometer", "accelerometerWakeup", "barometer", "barometerWakeup", "gyroscope", "gyroscopeWakeup", "magnetometer", "magnetometerWakeup", "photometer", "photometerWakeup", "proximity", "proximityWakeup", "tiltmeter", "tiltmeterWakeup", "dataEncryption", "graphicsAcceleration", "push", "telephony", "telephonyMms", "telephonySms", "autoRotation", "visionImageRecognition", "visionQrcodeGeneration", "visionQrcodeRecognition", "visionFaceRecognition", "secureElement", "profile"];
+var SystemInfoStorageUnit = ["type", "capacity", "availableCapacity", "isRemovable"];
+var systemInfoPropertyId = ["BATTERY", "CPU", "STORAGE", "DISPLAY", "DEVICE_ORIENTATION", "BUILD", "LOCALE", "NETWORK", "WIFI_NETWORK", "ETHERNET_NETWORK", "CELLULAR_NETWORK", "SIM", "PERIPHERAL", "MEMORY", "VIDEOSOURCE", "CAMERA_FLASH"];
+var SYSTEM_INFO_DEVICE_ORIENTATION_STATUS = ["PORTRAIT_PRIMARY", "PORTRAIT_SECONDARY", "LANDSCAPE_PRIMARY", "LANDSCAPE_SECONDARY"];
+var PLATFROM_CORE_CPU_ARCH = ["armv6", "armv7", "x86", "llvm"];
+var PLATFROM_CORE_FPU_ARCH = ["vfpv3", "sse2", "sse3", "ssse3"];
+var SYSTEM_INFO_PROFILE = ["MOBILE_FULL", "MOBILE_WEB", "MOBILE", "WEARABLE", "TV"];
+var SYSTEMINFO_WIFISECURITY_MODE = ["NONE", "WEP", "WPA_PSK", "WPA2_PSK", "EAP"];
+var SYSTEMINFO_NETWORK_IPMODE =  ["NONE", "STATIC", "DYNAMIC", "AUTO", "FIXED"];
+var SYSTEMINFO_WIFIENCRYPTION_TYPE = ["NONE", "WEP", "TKIP", "AES", "TKIP_AES_MIXED"];
+var SYSTEMINFO_VIDEOSOURCE_TYPE = ["TV", "AV", "SVIDEO", "COMP", "PC", "HDMI", "SCART", "DVI", "MEDIA"];
+var SYSTEM_INFO_NETWORK_TYPE = ["NONE", "2G", "2.5G", "3G", "4G", "WIFI", "ETHERNET", "UNKNOWN"];
+
+var INVALID_VALUES_ERR = {
+    name: "InvalidValuesError"
+};
+var TYPE_MISMATCH_ERR = {
+    name: "TypeMismatchError"
+};
+
+function assert_value_in_range(minValue, maxValue, attributeValue, description) {
+    var expected, epsilon;
+
+    assert_type(attributeValue, "number", "attributeValue is not a number.");
+
+    epsilon = Math.abs((Number(maxValue) - Number(minValue)) / 2);
+    expected = Number(maxValue) - epsilon;
+    assert_approx_equals(attributeValue, expected, epsilon, description)
+}
+
+function SystemInfo_getPropertyValue_exist() {
+//==== TEST: SystemInfo_getPropertyValue_exist
+//==== LABEL Check if method getPropertyValue of SystemInfo exists
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfo:getPropertyValue M
+//==== TEST_CRITERIA ME
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+test(function () {
+    assert_true("getPropertyValue" in tizen.systeminfo, "No getPropertyValue method in tizen.systeminfo.");
+    check_method_exists(tizen.systeminfo, "getPropertyValue");
+}, 'SystemInfo_getPropertyValue_exist');
+
+}
+
+function SystemInfo_getPropertyValue() {
+//==== TEST: SystemInfo_getPropertyValue
+//==== LABEL Check method getPropertyValue of SystemInfo
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfo:getPropertyValue M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA MMINA MR
+setup({timeout: 90000});
+
+var t = async_test('SystemInfo_getPropertyValue', {timeout: 90000}), getPropertyValueSuccess, retValue = null;
+
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (cpu) {
+        assert_not_equals(cpu.load, null, "Fail to getPropertyValue");
+        assert_equals(retValue, undefined, "getPropertyValue returns wrong value");
+
+        t.done();
+    });
+    retValue = tizen.systeminfo.getPropertyValue("CPU", getPropertyValueSuccess);
+});
+
+}
+
+function SystemInfo_addPropertyValueChangeListener_exist() {
+//==== TEST: SystemInfo_addPropertyValueChangeListener_exist
+//==== LABEL Check if method addPropertyValueChangeListener of SystemInfo exists
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfo:addPropertyValueChangeListener M
+//==== TEST_CRITERIA ME
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+test(function () {
+    assert_true("addPropertyValueChangeListener" in tizen.systeminfo,
+        "tizen.systeminfo.addPropertyValueChangeListener method exists");
+    check_method_exists(tizen.systeminfo, "addPropertyValueChangeListener");
+}, 'SystemInfo_addPropertyValueChangeListener_exist');
+
+}
+
+function SystemInfo_SystemInfoObject_systeminfo_attribute() {
+//==== TEST: SystemInfo_SystemInfoObject_systeminfo_attribute
+//==== LABEL Check if SystemInfo exists and implements methods
+//==== PRIORITY P3
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfo:SystemInfo U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA
+
+test(function () {
+    assert_equals(typeof (tizen), "object", "Checking tizen object");
+    assert_true(typeof (tizen.systeminfo) === "object", "Checking Systeminfo object");
+    assert_equals(typeof (tizen.systeminfo.getCapabilities), "function", "Checking type of getCapabilities");
+    assert_equals(typeof (tizen.systeminfo.getPropertyValue), "function", "Checking type of getPropertyValue");
+    assert_equals(typeof (tizen.systeminfo.addPropertyValueChangeListener), "function", "Checking type of addPropertyValueChangeListener");
+    assert_equals(typeof (tizen.systeminfo.removePropertyValueChangeListener), "function", "Checking type of removePropertyValueChangeListener");
+}, 'SystemInfo_SystemInfoObject_systeminfo_attribute');
+
+}
+
+function SystemInfoBattery_notexist() {
+//==== TEST: SystemInfoBattery_notexist
+//==== PRIORITY P3
+//==== LABEL Check if interface SystemInfoBattery exists, it should not.
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoBattery:SystemInfoBattery U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("SystemInfoBattery");
+}, 'SystemInfoBattery_notexist');
+
+}
+
+function SystemInfoBuild_notexist() {
+//==== TEST: SystemInfoBuild_notexist
+//==== PRIORITY P3
+//==== LABEL Check if interface SystemInfoBuild exists, it should not.
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoBuild:SystemInfoBuild U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("SystemInfoBuild");
+}, 'SystemInfoBuild_notexist');
+
+}
+
+function SystemInfoCpu_notexist() {
+//==== TEST: SystemInfoCpu_notexist
+//==== PRIORITY P3
+//==== LABEL Check if interface SystemInfoCpu exists, it should not.
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoCpu:SystemInfoCpu U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("SystemInfoCpu");
+}, 'SystemInfoCpu_notexist');
+
+}
+
+function SystemInfoDeviceCapability_notexist() {
+//==== TEST: SystemInfoDeviceCapability_notexist
+//==== PRIORITY P3
+//==== LABEL Check if interface SystemInfoDeviceCapability exists, it should not.
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:SystemInfoDeviceCapability U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("SystemInfoDeviceCapability");
+}, 'SystemInfoDeviceCapability_notexist');
+
+}
+
+function SystemInfoDeviceOrientation_notexist() {
+//==== TEST: SystemInfoDeviceOrientation_notexist
+//==== PRIORITY P3
+//==== LABEL Check if interface SystemInfoDeviceOrientation exists, it should not.
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceOrientation:SystemInfoDeviceOrientation U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("SystemInfoDeviceOrientation");
+}, 'SystemInfoDeviceOrientation_notexist');
+
+}
+
+function SystemInfoDisplay_notexist() {
+//==== TEST: SystemInfoDisplay_notexist
+//==== PRIORITY P3
+//==== LABEL Check if interface SystemInfoDisplay exists, it should not.
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDisplay:SystemInfoDisplay U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("SystemInfoDisplay");
+}, 'SystemInfoDisplay_notexist');
+
+}
+
+function SystemInfoObject_notexist() {
+//==== TEST: SystemInfoObject_notexist
+//==== PRIORITY P3
+//==== LABEL Check if interface SystemInfoObject exists, it should not.
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoObject:SystemInfoObject U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("SystemInfoObject");
+}, 'SystemInfoObject_notexist');
+
+}
+
+function SystemInfoPeripheral_notexist() {
+//==== TEST: SystemInfoPeripheral_notexist
+//==== PRIORITY P3
+//==== LABEL Check if interface SystemInfoPeripheral exists, it should not.
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoPeripheral:SystemInfoPeripheral U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("SystemInfoPeripheral");
+}, 'SystemInfoPeripheral_notexist');
+
+}
+
+function SystemInfoPropertySuccessCallback_notexist() {
+//==== TEST: SystemInfoPropertySuccessCallback_notexist
+//==== PRIORITY P3
+//==== LABEL Check if interface SystemInfoPropertySuccessCallback exists, it should not.
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoPropertySuccessCallback:SystemInfoPropertySuccessCallback U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA CBNIO
+
+test(function () {
+    check_no_interface_object("SystemInfoPropertySuccessCallback");
+}, 'SystemInfoPropertySuccessCallback_notexist');
+
+}
+
+function SystemInfoProperty_notexist() {
+//==== TEST: SystemInfoProperty_notexist
+//==== PRIORITY P3
+//==== LABEL Check if interface SystemInfoProperty exists, it should not.
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoProperty:SystemInfoProperty U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("SystemInfoProperty");
+}, 'SystemInfoProperty_notexist');
+
+}
+
+function SystemInfoStorageUnit_notexist() {
+//==== TEST: SystemInfoStorageUnit_notexist
+//==== PRIORITY P3
+//==== LABEL Check if interface SystemInfoStorageUnit exists, it should not.
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoStorageUnit:SystemInfoStorageUnit U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA NIO
+
+
+test(function () {
+    check_no_interface_object("SystemInfoStorageUnit");
+}, 'SystemInfoStorageUnit_notexist');
+
+}
+
+function SystemInfoStorage_notexist() {
+//==== TEST: SystemInfoStorage_notexist
+//==== PRIORITY P3
+//==== LABEL Check if interface SystemInfoStorage exists, it should not.
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoStorage:SystemInfoStorage U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("SystemInfoStorage");
+}, 'SystemInfoStorage_notexist');
+
+}
+
+function SystemInfo_notexist() {
+//==== TEST: SystemInfo_notexist
+//==== PRIORITY P3
+//==== LABEL Check if interface SystemInfo exists, it should not.
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfo:SystemInfo U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("SystemInfo");
+}, 'SystemInfo_notexist');
+
+}
+
+function SystemInfo_getCapability_network_bluetooth() {
+//==== TEST: SystemInfo_getCapability_network_bluetooth
+//==== LABEL Check if attribute bluetooth of SystemInfoDeviceCapability exists, has type Boolean and is readonly
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:bluetooth A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/network.bluetooth");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_network_bluetooth');
+
+}
+
+function SystemInfoDeviceCapability_extend() {
+//==== TEST: SystemInfoDeviceCapability_extend
+//==== PRIORITY P3
+//==== LABEL Check if instance of interface SystemInfoDeviceCapability can be extended with new property
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:SystemInfoDeviceCapability U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA OBX
+var deviceCapabilities = tizen.systeminfo.getCapabilities();
+
+test(function () {
+    check_extensibility(deviceCapabilities);
+}, 'SystemInfoDeviceCapability_extend');
+
+}
+
+function SystemInfo_getCapability_network_nfc() {
+//==== TEST: SystemInfo_getCapability_network_nfc
+//==== LABEL Check if attribute nfc of SystemInfoDeviceCapability exists, has type Boolean and is readonly
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:nfc A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/network.nfc");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_network_nfc');
+
+}
+
+function SystemInfo_getCapability_multi_point_touch_point_count() {
+//==== TEST: SystemInfo_getCapability_multi_point_touch_point_count
+//==== LABEL Check if attribute multiTouchCount of SystemInfoDeviceCapability exists, has type unsigned short and is readonly
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:multiTouchCount A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/multi_point_touch.point_count");
+    assert_type(deviceCapability, "number", "deviceCapability should be a number");
+}, 'SystemInfo_getCapability_multi_point_touch_point_count');
+
+}
+
+function SystemInfo_getCapability_input_keyboard() {
+//==== TEST: SystemInfo_getCapability_input_keyboard
+//==== LABEL Check if attribute inputKeyboard of SystemInfoDeviceCapability exists, has type Boolean and is readonly
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:inputKeyboard A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/input.keyboard");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_input_keyboard');
+
+}
+
+function SystemInfo_getCapability_network_wifi() {
+//==== TEST: SystemInfo_getCapability_network_wifi
+//==== LABEL Check if attribute wifi of SystemInfoDeviceCapability exists, has type Boolean and is readonly
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:wifi A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/network.wifi");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_network_wifi');
+
+}
+
+function SystemInfo_getCapability_network_wifi_direct() {
+//==== TEST: SystemInfo_getCapability_network_wifi_direct
+//==== LABEL Check if attribute wifiDirect of SystemInfoDeviceCapability exists, has type Boolean and is readonly
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:wifiDirect A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/network.wifi.direct");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_network_wifi_direct');
+
+}
+
+function SystemInfo_getCapability_fmradio() {
+//==== TEST: SystemInfo_getCapability_fmradio
+//==== LABEL Check if attribute fmRadio of SystemInfoDeviceCapability exists, has type Boolean and is readonly
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:fmRadio A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/fmradio");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_fmradio');
+
+}
+
+function SystemInfo_getCapability_opengles_version_1_1() {
+//==== TEST: SystemInfo_getCapability_opengles_version_1_1
+//==== LABEL Check if attribute openglesVersion1_1 of SystemInfoDeviceCapability exists, has type Boolean and is readonly
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:openglesVersion1_1 A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/opengles.version.1_1");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_opengles_version_1_1');
+
+}
+
+function SystemInfo_getCapability_opengles_version_2_0() {
+//==== TEST: SystemInfo_getCapability_opengles_version_2_0
+//==== LABEL Check if attribute openglesVersion2_0 of SystemInfoDeviceCapability exists, has type Boolean and is readonly
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:openglesVersion2_0 A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/opengles.version.2_0");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_opengles_version_2_0');
+
+}
+
+function SystemInfo_getCapability_platform_name() {
+//==== TEST: SystemInfo_getCapability_platform_name
+//==== LABEL Check if attribute platformName of SystemInfoDeviceCapability exists, has type DOMString and is readonly
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:platformName A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/system/platform.name");
+    assert_type(deviceCapability, "string", "deviceCapability should be a string");
+}, 'SystemInfo_getCapability_platform_name');
+
+}
+
+function SystemInfo_getCapability_platform_version() {
+//==== TEST: SystemInfo_getCapability_platform_version
+//==== LABEL Check if attribute platformVersion of SystemInfoDeviceCapability exists, has type DOMString and is readonly
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:platformVersion A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/platform.version");
+    assert_type(deviceCapability, "string", "deviceCapability should be a string");
+}, 'SystemInfo_getCapability_platform_version');
+
+}
+
+function SystemInfo_getCapability_platform_web_api_version() {
+//==== TEST: SystemInfo_getCapability_platform_web_api_version
+//==== LABEL Check if attribute webApiVersion of SystemInfoDeviceCapability exists, has type DOMString and is readonly
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:webApiVersion A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/platform.web.api.version");
+    assert_type(deviceCapability, "string", "deviceCapability should be a string");
+}, 'SystemInfo_getCapability_platform_web_api_version');
+
+}
+
+function SystemInfo_getCapability_sensor_accelerometer() {
+//==== TEST: SystemInfo_getCapability_sensor_accelerometer
+//==== LABEL Check if attribute accelerometer of SystemInfoDeviceCapability exists, has type Boolean and is readonly
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:accelerometer A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.accelerometer");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_sensor_accelerometer');
+
+}
+
+function SystemInfo_getCapability_sensor_barometer() {
+//==== TEST: SystemInfo_getCapability_sensor_barometer
+//==== LABEL Check if attribute barometer of SystemInfoDeviceCapability exists, has type Boolean and is readonly
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:barometer A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.barometer");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_sensor_barometer');
+
+}
+
+function SystemInfo_getCapability_camera_back_flash() {
+//==== TEST: SystemInfo_getCapability_camera_back_flash
+//==== LABEL Check if attribute cameraBackFlash of SystemInfoDeviceCapability exists, has type Boolean and is readonly
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:cameraBackFlash A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/camera.back.flash");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_camera_back_flash');
+
+}
+
+function SystemInfo_getCapability_camera_back() {
+//==== TEST: SystemInfo_getCapability_camera_back
+//==== LABEL Check if attribute cameraBack of SystemInfoDeviceCapability exists, has type Boolean and is readonly
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:cameraBack A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/camera.back");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_camera_back');
+
+}
+
+function SystemInfo_getCapability_camera_front_flash() {
+//==== TEST: SystemInfo_getCapability_camera_front_flash
+//==== LABEL Check if attribute cameraFrontFlash of SystemInfoDeviceCapability exists, has type Boolean and is readonly
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:cameraFrontFlash A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/camera.front.flash");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_camera_front_flash');
+
+}
+
+function SystemInfo_getCapability_camera_front() {
+//==== TEST: SystemInfo_getCapability_camera_front
+//==== LABEL Check if attribute cameraFront of SystemInfoDeviceCapability exists, has type Boolean and is readonly
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:cameraFront A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/camera.front");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_camera_front');
+
+}
+
+function SystemInfo_getCapability_sensor_gyroscope() {
+//==== TEST: SystemInfo_getCapability_sensor_gyroscope
+//==== LABEL Check if attribute gyroscope of SystemInfoDeviceCapability exists, has type Boolean and is readonly
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:gyroscope A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.gyroscope");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_sensor_gyroscope');
+
+}
+
+function SystemInfo_getCapability_location_gps() {
+//==== TEST: SystemInfo_getCapability_location_gps
+//==== LABEL Check if attribute locationGps of SystemInfoDeviceCapability exists, has type Boolean and is readonly
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:locationGps A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/location.gps");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_location_gps');
+
+}
+
+function SystemInfo_getCapability_location_wps() {
+//==== TEST: SystemInfo_getCapability_location_wps
+//==== LABEL Check if attribute locationWps of SystemInfoDeviceCapability exists, has type Boolean and is readonly
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:locationWps A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/location.wps");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_location_wps');
+
+}
+
+function SystemInfo_getCapability_location() {
+//==== TEST: SystemInfo_getCapability_location
+//==== LABEL Check if attribute location of SystemInfoDeviceCapability exists, has type Boolean and is readonly
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:location A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/location");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_location');
+
+}
+
+function SystemInfo_getCapability_sensor_magnetometer() {
+//==== TEST: SystemInfo_getCapability_sensor_magnetometer
+//==== LABEL Check if attribute magnetometer of SystemInfoDeviceCapability exists, has type Boolean and is readonly
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:magnetometer A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.magnetometer");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_sensor_magnetometer');
+
+}
+
+function SystemInfo_getCapability_microphone() {
+//==== TEST: SystemInfo_getCapability_microphone
+//==== LABEL Check if attribute microphone of SystemInfoDeviceCapability exists, has type Boolean and is readonly
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:microphone A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/microphone");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_microphone');
+
+}
+
+function SystemInfo_getCapability_platform_core_cpu_arch() {
+//==== TEST: SystemInfo_getCapability_platform_core_cpu_arch
+//==== LABEL Check if attribute platformCoreCpuArch of SystemInfoDeviceCapability exists, has type DOMString and is readonly
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:platformCoreCpuArch A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO AVL
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/platform.core.cpu.arch");
+    assert_type(deviceCapability, "string", "deviceCapability should be a String");
+}, 'SystemInfo_getCapability_platform_core_cpu_arch');
+
+}
+
+function SystemInfo_getCapability_platform_core_fpu_arch() {
+//==== TEST: SystemInfo_getCapability_platform_core_fpu_arch
+//==== LABEL Check if attribute platformCoreFpuArch of SystemInfoDeviceCapability exists, has type DOMString and is readonly
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:platformCoreFpuArch A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO AVL
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/platform.core.fpu.arch");
+    assert_type(deviceCapability, "string", "deviceCapability should be a DOMString.");
+}, 'SystemInfo_getCapability_platform_core_fpu_arch');
+
+}
+
+function SystemInfo_getCapability_sensor_proximity() {
+//==== TEST: SystemInfo_getCapability_sensor_proximity
+//==== LABEL Check if attribute proximity of SystemInfoDeviceCapability exists, has type Boolean and is readonly
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:proximity A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.proximity");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_sensor_proximity');
+
+}
+
+function SystemInfo_getCapability_screen_output_hdmi() {
+//==== TEST: SystemInfo_getCapability_screen_output_hdmi
+//==== LABEL Check if attribute screenOutputHdmi of SystemInfoDeviceCapability exists, has type Boolean and is readonly
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:screenOutputHdmi A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/screen.output.hdmi");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_screen_output_hdmi');
+
+}
+
+function SystemInfo_getCapability_screen_output_rca() {
+//==== TEST: SystemInfo_getCapability_screen_output_rca
+//==== LABEL Check if attribute screenOutputRca of SystemInfoDeviceCapability exists, has type Boolean and is readonly
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:screenOutputRca A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/screen.output.rca");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_screen_output_rca');
+
+}
+
+function SystemInfo_getCapability_sip_voip() {
+//==== TEST: SystemInfo_getCapability_sip_voip
+//==== LABEL Check if attribute sipVoip of SystemInfoDeviceCapability exists, has type Boolean and is readonly
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:sipVoip A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/sip.voip");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean.");
+}, 'SystemInfo_getCapability_sip_voip');
+
+}
+
+function SystemInfo_getCapability_speech_recognition() {
+//==== TEST: SystemInfo_getCapability_speech_recognition
+//==== LABEL Check if attribute speechRecognition of SystemInfoDeviceCapability exists, has type Boolean and is readonly
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:speechRecognition A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/speech.recognition");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean.");
+}, 'SystemInfo_getCapability_speech_recognition');
+
+}
+
+function SystemInfo_getCapability_usb_accessory() {
+//==== TEST: SystemInfo_getCapability_usb_accessory
+//==== LABEL Check if attribute usbAccessory of SystemInfoDeviceCapability exists, has type Boolean and is readonly
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:usbAccessory A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/usb.accessory");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean.");
+}, 'SystemInfo_getCapability_usb_accessory');
+
+}
+
+function SystemInfo_getCapability_usb_host() {
+//==== TEST: SystemInfo_getCapability_usb_host
+//==== LABEL Check if attribute usbHost of SystemInfoDeviceCapability exists, has type Boolean and is readonly
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:usbHost A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/usb.host");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean.");
+}, 'SystemInfo_getCapability_usb_host');
+
+}
+
+function SystemInfoBattery_extend() {
+//==== TEST: SystemInfoBattery_extend
+//==== LABEL Check if SystemInfoBattery can have new property added
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoBattery:SystemInfoBattery U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA OBX
+//==== PRIORITY P3
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoBattery_extend', {timeout: 90000}), getPropertyValueSuccess,
+    getPropertyValueError;
+
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        check_extensibility(property);
+        t.done();
+    });
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name:" +
+            error.message + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("BATTERY", getPropertyValueSuccess, getPropertyValueError);
+});
+
+}
+
+function SystemInfoBattery_level_attribute() {
+//==== TEST: SystemInfoBattery_level_attribute
+//==== LABEL Check attribute level in SystemInfoBattery
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoBattery:level A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO AVL
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoBattery_level_attribute', {timeout: 90000}), getPropertyValueSuccess,
+    getPropertyValueError;
+
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        assert_own_property(property, "level", "BATTERY does not own level property.");
+        check_readonly(property, "level", property.level, "number", null);
+        assert_value_in_range(0, 1, property.level,
+            "Remaining level of an internal battery MUST be between 0 and 1.");
+        t.done();
+    });
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.message + ", msg: " + error.name);
+    });
+
+    tizen.systeminfo.getPropertyValue("BATTERY", getPropertyValueSuccess, getPropertyValueError);
+});
+
+}
+
+function SystemInfoBattery_isCharging_attribute() {
+//==== TEST: SystemInfoBattery_isCharging_attribute
+//==== LABEL Check attribute isCharging in SystemInfoBattery
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoBattery:isCharging A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoBattery_isCharging_attribute', {timeout: 90000}),
+    getPropertyValueSuccess, getPropertyValueError;
+
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        assert_own_property(property, "isCharging", "BATTERY doesn't own isCharging property.");
+        check_readonly(property, "isCharging", property.isCharging, "boolean", null);
+        t.done();
+    });
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.message + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("BATTERY", getPropertyValueSuccess, getPropertyValueError);
+});
+
+}
+
+function SystemInfo_extend() {
+//==== TEST: SystemInfo_extend
+//==== PRIORITY P3
+//==== LABEL Check if instance of interface SystemInfo can be extended with new property
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfo:SystemInfo U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA OBX
+
+test(function () {
+    check_extensibility(tizen.systeminfo);
+}, 'SystemInfo_extend');
+
+}
+
+function SystemInfo_getCapabilities_exist() {
+//==== TEST: SystemInfo_getCapabilities_exist
+//==== LABEL Check if method getCapabilities of SystemInfo exists
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfo:getCapabilities M
+//==== TEST_CRITERIA ME
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+test(function () {
+    assert_true("getCapabilities" in tizen.systeminfo, "No getCapabilities method in tizen.systeminfo.");
+    check_method_exists(tizen.systeminfo, "getCapabilities");
+}, 'SystemInfo_getCapabilities_exist');
+
+}
+
+function SystemInfo_getCapabilities() {
+//==== TEST: SystemInfo_getCapabilities
+//==== LABEL Check method getCapabilities of SystemInfo
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfo:getCapabilities M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA MNA MR
+
+test(function () {
+    var deviceCapabilities = tizen.systeminfo.getCapabilities(), i;
+    for(i = 0; i < SystemInfoDeviceCapability.length; i++) {
+        assert_true(SystemInfoDeviceCapability[i] in deviceCapabilities,
+            "There is no "+SystemInfoDeviceCapability[i]+
+            " attribute in tizen.systeminfo.getCapabilities().");
+    }
+}, 'SystemInfo_getCapabilities');
+
+}
+
+function SystemInfo_getCapabilities_extra_argument() {
+//==== TEST: SystemInfo_getCapabilities_extra_argument
+//==== LABEL Check if method getCapabilities of SystemInfo accepts extra argument
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfo:getCapabilities M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA MNAEX
+
+test(function () {
+    checkExtraArgument(tizen.systeminfo, "getCapabilities");
+}, 'SystemInfo_getCapabilities_extra_argument');
+
+}
+
+function SystemInfoDisplay_brightness_attribute() {
+//==== TEST: SystemInfoDisplay_brightness_attribute
+//==== LABEL Check if attribute brightness of SystemInfoDisplay exists, has type Number and is readonly
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDisplay:brightness A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO AVL
+
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoDisplay_brightness_attribute', {timeout: 90000}),
+    getPropertyValueSuccess, getPropertyValueError;
+
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        assert_own_property(property, "brightness",
+            "SystemInfoDisplay does not own brightness property.");
+        check_readonly(property, "brightness", property.brightness,
+            "number", null);
+        assert_value_in_range(0, 1, property.brightness, "brightness MUST be between 0 and 1.");
+        t.done();
+    });
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("DISPLAY", getPropertyValueSuccess,
+        getPropertyValueError);
+});
+
+}
+
+function SystemInfoDisplay_dotsPerInchHeight_attribute() {
+//==== TEST: SystemInfoDisplay_dotsPerInchHeight_attribute
+//==== LABEL Check if attribute dotsPerInchHeight of SystemInfoDisplay exists, has type Number and is readonly
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDisplay:dotsPerInchHeight A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoDisplay_dotsPerInchHeight_attribute', {timeout: 90000}),
+    getPropertyValueSuccess, getPropertyValueError;
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        assert_own_property(property, "dotsPerInchHeight",
+            "SystemInfoDisplay does not own dotsPerInchHeight property.");
+        check_readonly(property, "dotsPerInchHeight",
+            property.dotsPerInchHeight, "number", null);
+        t.done();
+    });
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("DISPLAY", getPropertyValueSuccess,
+        getPropertyValueError);
+}, "SystemInfoDisplay_dotsPerInchHeight_attribute");
+
+}
+
+function SystemInfoDisplay_dotsPerInchWidth_attribute() {
+//==== TEST: SystemInfoDisplay_dotsPerInchWidth_attribute
+//==== LABEL Check if attribute dotsPerInchWidth of SystemInfoDisplay exists, has type Number and is readonly
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDisplay:dotsPerInchWidth A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoDisplay_dotsPerInchWidth_attribute', {timeout: 90000}),
+    getPropertyValueSuccess, getPropertyValueError;
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        assert_own_property(property, "dotsPerInchWidth", "SystemInfoDisplay does not own dotsPerInchWidth property.");
+        check_readonly(property, "dotsPerInchWidth", property.dotsPerInchWidth, "number", null);
+        t.done();
+    });
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("DISPLAY", getPropertyValueSuccess,
+        getPropertyValueError);
+}, "SystemInfoDisplay_dotsPerInchWidth_attribute");
+
+}
+
+function SystemInfoDisplay_physicalHeight_attribute() {
+//==== TEST: SystemInfoDisplay_physicalHeight_attribute
+//==== LABEL Check if attribute physicalHeight of SystemInfoDisplay exists, has type Number and is readonly
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDisplay:physicalHeight A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoDisplay_physicalHeight_attribute', {timeout: 90000}),
+    getPropertyValueSuccess, getPropertyValueError;
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        assert_own_property(property, "physicalHeight",
+            "SystemInfoDisplay does not own physicalHeight property.");
+        check_readonly(property, "physicalHeight",
+            property.physicalHeight, "number", null);
+        t.done();
+    });
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("DISPLAY", getPropertyValueSuccess,
+        getPropertyValueError);
+}, "SystemInfoDisplay_physicalHeight_attribute");
+
+}
+
+function SystemInfoDisplay_physicalWidth_attribute() {
+//==== TEST: SystemInfoDisplay_physicalWidth_attribute
+//==== LABEL Check if attribute physicalWidth of SystemInfoDisplay exists, has type Number and is readonly
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDisplay:physicalWidth A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoDisplay_physicalWidth_attribute', {timeout: 90000}),
+    getPropertyValueSuccess, getPropertyValueError;
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        assert_own_property(property, "physicalWidth", "SystemInfoDisplay does not own physicalWidth property.");
+        check_readonly(property, "physicalWidth", property.physicalWidth, "number", null);
+        t.done();
+    });
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("DISPLAY", getPropertyValueSuccess,
+        getPropertyValueError);
+});
+
+}
+
+function SystemInfoDisplay_resolutionHeight_attribute() {
+//==== TEST: SystemInfoDisplay_resolutionHeight_attribute
+//==== LABEL Check if attribute resolutionHeight of SystemInfoDisplay exists, has type Number and is readonly
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDisplay:resolutionHeight A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoDisplay_resolutionHeight_attribute', {timeout: 90000}),
+    getPropertyValueSuccess, getPropertyValueError;
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        assert_own_property(property, "resolutionHeight",
+            "SystemInfoDisplay does not own resolutionHeight property.");
+        check_readonly(property, "resolutionHeight", property.resolutionHeight,
+            "number", null);
+        t.done();
+    });
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("DISPLAY", getPropertyValueSuccess,
+        getPropertyValueError);
+});
+
+}
+
+function SystemInfoDisplay_resolutionWidth_attribute() {
+//==== TEST: SystemInfoDisplay_resolutionWidth_attribute
+//==== LABEL Check if attribute resolutionWidth of SystemInfoDisplay exists, has type Number and is readonly
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDisplay:resolutionWidth A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoDisplay_resolutionWidth_attribute', {timeout: 90000}), getPropertyValueSuccess,
+    getPropertyValueError;
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        assert_own_property(property, "resolutionWidth", "SystemInfoDisplay does not own resolutionWidth property.");
+        check_readonly(property, "resolutionWidth", property.resolutionWidth, "number", null);
+        t.done();
+    });
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("DISPLAY", getPropertyValueSuccess,
+        getPropertyValueError);
+});
+
+}
+
+function SystemInfoPeripheral_isVideoOutputOn_attribute() {
+//==== TEST: SystemInfoPeripheral_isVideoOutputOn_attribute
+//==== LABEL Check if attribute isVideoOutputOn of SystemInfoPeripheral exists, has type Boolean and is readonly
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoPeripheral:isVideoOutputOn A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoPeripheral_isVideoOutputOn_attribute', {timeout: 90000}),
+    getPropertyValueSuccess, getPropertyValueError;
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        assert_own_property(property, "isVideoOutputOn",
+            "SystemInfoPeripheral does not own isVideoOutputOn property.");
+        check_readonly(property, "isVideoOutputOn",
+            property.isVideoOutputOn, "boolean", null);
+        t.done();
+    });
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("PERIPHERAL", getPropertyValueSuccess,
+        getPropertyValueError);
+});
+
+}
+
+function SystemInfoCpu_load_attribute() {
+//==== TEST: SystemInfoCpu_load_attribute
+//==== LABEL Check if attribute load of SystemInfoCpu exists, has type Number and is readonly
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoCpu:load A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO AVL
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoCpu_load_attribute', {timeout: 90000}),
+    getPropertyValueSuccess, getPropertyValueError;
+
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        assert_own_property(property, "load", "SystemInfoCpu does not own load property.");
+        check_readonly(property, "load", property.load, "number", null);
+        assert_value_in_range(0, 1, property.load,
+            "An attribute to indicate the current CPU load MUST be between 0 and 1.");
+        t.done();
+    });
+
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("CPU", getPropertyValueSuccess,
+        getPropertyValueError);
+});
+
+}
+
+function SystemInfoStorage_units_attribute() {
+//==== TEST: SystemInfoStorage_units_attribute
+//==== LABEL Check if attribute units of SystemInfoStorage exists, has type Array and is readonly
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoStorage:units A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+//==== ONLOAD_DELAY 90
+var t = async_test('SystemInfoStorage_units_attribute', {timeout: 90000}),
+    getPropertyValueSuccess, getPropertyValueError, i, j, units;
+setup({timeout: 90000});
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        assert_own_property(property, "units",
+            "SystemInfoStorage does not own units property.");
+        assert_true(Array.isArray(property.units),
+            "SystemInfoStorage_units is not an array");
+
+        assert_true(property.units.length > 0, "No available units.");
+
+        for(i = 0; i < property.units.length; i++) {
+            for(j = 0; j < SystemInfoStorageUnit.length; j++) {
+                assert_own_property(property.units[i], SystemInfoStorageUnit[j],
+                    "storage unit does not own " + SystemInfoStorageUnit[j] +
+                    " property.");
+            }
+        }
+
+        units = property.units;
+        property.units = [];
+        for(i = 0; i < units.length; i++) {
+            for(j = 0; j < SystemInfoStorageUnit.length; j++) {
+                assert_equals(property.units[i][SystemInfoStorageUnit[j]],
+                    units[i][SystemInfoStorageUnit[j]],
+                    "units is not a read-only on property " + SystemInfoStorageUnit[j] + " at unit[" + i + "]");
+            }
+        }
+        t.done();
+    });
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("STORAGE", getPropertyValueSuccess,
+        getPropertyValueError);
+});
+
+}
+
+function SystemInfoDeviceOrientation_status_attribute() {
+//==== TEST: SystemInfoDeviceOrientation_status_attribute
+//==== LABEL Check status attribute of SystemInfoDeviceOrientation
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceOrientation:status A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoDeviceOrientation_status_attribute', {timeout: 90000}),
+    getPropertyValueSuccess, getPropertyValueError;
+
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        assert_own_property(property, "status", "DEVICE_ORIENTATION doesn't own status property.");
+        check_readonly(property, "status", property.status, "string", null);
+        assert_in_array(property.status, SYSTEM_INFO_DEVICE_ORIENTATION_STATUS,
+            "status isn't type of SystemInfoDeviceOrientationStatus");
+        t.done();
+    });
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("DEVICE_ORIENTATION",
+        getPropertyValueSuccess, getPropertyValueError);
+}, "SystemInfoDeviceOrientation_status_attribute");
+
+}
+
+function SystemInfoCpu_extend() {
+//==== TEST: SystemInfoCpu_extend
+//==== PRIORITY P3
+//==== LABEL Check if instance of interface SystemInfoCpu can be extended with new property
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoCpu:SystemInfoCpu U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA OBX
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoCpu_extend', {timeout: 90000}),
+    getPropertyValueSuccess, getPropertyValueError;
+
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        check_extensibility(property);
+        t.done();
+    });
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+           error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("CPU", getPropertyValueSuccess,
+        getPropertyValueError);
+});
+
+}
+
+function SystemInfoDisplay_extend() {
+//==== TEST: SystemInfoDisplay_extend
+//==== PRIORITY P3
+//==== LABEL Check if instance of interface SystemInfoDisplay can be extended with new property
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDisplay:SystemInfoDisplay U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA OBX
+
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoDisplay_extend', {timeout: 90000}), getPropertyValueSuccess,
+    getPropertyValueError;
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        check_extensibility(property);
+        t.done();
+    });
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("DISPLAY", getPropertyValueSuccess,
+        getPropertyValueError);
+}, "SystemInfoDisplay_extend");
+
+}
+
+function SystemInfoPeripheral_extend() {
+//==== TEST: SystemInfoPeripheral_extend
+//==== PRIORITY P3
+//==== LABEL Check if instance of interface SystemInfoPeripheral can be extended with new property
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoPeripheral:SystemInfoPeripheral U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA OBX
+
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoPeripheral_extend', {timeout: 90000}), getPropertyValueSuccess,
+    getPropertyValueError;
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        check_extensibility(property);
+        t.done();
+    });
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("PERIPHERAL", getPropertyValueSuccess,
+        getPropertyValueError);
+});
+
+}
+
+function SystemInfoStorageUnit_availableCapacity_attribute() {
+//==== TEST: SystemInfoStorageUnit_availableCapacity_attribute
+//==== LABEL Check if attribute availableCapacity of SystemInfoStorageUnit exists, has type Number and is readonly
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoStorageUnit:availableCapacity A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoStorageUnit_availableCapacity_attribute', {timeout: 90000}),
+    getPropertyValueSuccess, getPropertyValueError;
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        assert_own_property(property, "units", "No units property.");
+        assert_true(Array.isArray(property.units),
+            "SystemInfoStorage_units is not an array");
+        assert_true(property.units.length > 0, "No available units.");
+        assert_own_property(property.units[0], "availableCapacity", "SystemInfoStorageUnit does not own availableCapacity property.");
+        check_readonly(property.units[0], "availableCapacity", property.units[0].availableCapacity, "number", null);
+        t.done();
+    });
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("STORAGE", getPropertyValueSuccess,
+        getPropertyValueError);
+});
+
+}
+
+function SystemInfoStorageUnit_capacity_attribute() {
+//==== TEST: SystemInfoStorageUnit_capacity_attribute
+//==== LABEL Check if attribute capacity of SystemInfoStorageUnit exists, has type Number and is readonly
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoStorageUnit:capacity A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoStorageUnit_capacity_attribute', {timeout: 90000}),
+    getPropertyValueSuccess, getPropertyValueError;
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        assert_own_property(property, "units", "No units property.");
+        assert_true(Array.isArray(property.units),
+            "SystemInfoStorage_units is not an array");
+        assert_true(property.units.length > 0, "No available units.");
+
+        assert_own_property(property.units[0], "capacity",
+            "SystemInfoStorageUnit does not own capacity property.units[0].");
+        check_readonly(property.units[0], "capacity", property.units[0].capacity, "number", null);
+        t.done();
+    });
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("STORAGE", getPropertyValueSuccess,
+        getPropertyValueError);
+});
+
+}
+
+function SystemInfoStorageUnit_isRemovable_attribute() {
+//==== TEST: SystemInfoStorageUnit_isRemovable_attribute
+//==== LABEL Check if attribute isRemovable of SystemInfoStorageUnit exists, has type Boolean and is readonly
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoStorageUnit:isRemovable A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoStorageUnit_isRemovable_attribute', {timeout: 90000}),
+    getPropertyValueSuccess, getPropertyValueError;
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        assert_own_property(property, "units", "No units property.");
+        assert_true(Array.isArray(property.units),
+            "SystemInfoStorage_units is not an array");
+        assert_true(property.units.length > 0, "No available units.");
+        assert_own_property(property.units[0], "isRemovable", "SystemInfoStorageUnit does not own isRemovable property.");
+        check_readonly(property.units[0], "isRemovable", property.units[0].isRemovable, "boolean", null);
+        t.done();
+    });
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("STORAGE", getPropertyValueSuccess,
+        getPropertyValueError);
+});
+
+}
+
+function SystemInfoStorageUnit_isRemoveable_attribute() {
+//==== TEST: SystemInfoStorageUnit_isRemoveable_attribute
+//==== LABEL Check if attribute isRemoveable of SystemInfoStorageUnit exists, has type Boolean and is readonly
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoStorageUnit:isRemoveable A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoStorageUnit_isRemoveable_attribute', {timeout: 90000}),
+    getPropertyValueSuccess, getPropertyValueError;
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        assert_own_property(property, "units", "No units property.");
+        assert_true(Array.isArray(property.units),
+            "SystemInfoStorage_units is not an array");
+        assert_true(property.units.length > 0, "No available units.");
+        assert_own_property(property.units[0], "isRemoveable", "SystemInfoStorageUnit does not own isRemoveable property.");
+        check_readonly(property.units[0], "isRemoveable", property.units[0].isRemoveable, "boolean", null);
+        t.done();
+    });
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("STORAGE", getPropertyValueSuccess,
+        getPropertyValueError);
+});
+
+}
+
+function SystemInfoStorageUnit_type_attribute() {
+//==== TEST: SystemInfoStorageUnit_type_attribute
+//==== LABEL Check if attribute type of SystemInfoStorageUnit exists, has type DOMString and is readonly
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoStorageUnit:type A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoStorageUnit_type_attribute', {timeout: 90000}),
+    getPropertyValueSuccess, getPropertyValueError;
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        assert_own_property(property, "units", "No units property.");
+        assert_true(Array.isArray(property.units),
+            "SystemInfoStorage_units is not an array");
+        assert_true(property.units.length > 0, "No available units.");
+        assert_own_property(property.units[0], "type", "SystemInfoStorageUnit does not own type property.");
+        check_readonly(property.units[0], "type", property.units[0].type, "string", null);
+        assert_true(property.units[0].type !== "", "null check");
+        t.done();
+    });
+    getPropertyValueError = t.step_func(function (e) {
+        assert_unreached("Exception: " + e.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("STORAGE", getPropertyValueSuccess,
+        getPropertyValueError);
+});
+
+}
+
+function SystemInfoStorageUnit_extend() {
+//==== TEST: SystemInfoStorageUnit_extend
+//==== LABEL Check if SystemInfoStorageUnit is extendable
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoStorageUnit:SystemInfoStorageUnit U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA OBX
+//==== PRIORITY P3
+
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoStorageUnit_extend', {timeout: 90000}),
+    getPropertyValueSuccess, getPropertyValueError;
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        assert_own_property(property, "units", "No units property.");
+        assert_true(Array.isArray(property.units),
+            "SystemInfoStorage_units is not an array");
+        assert_true(property.units.length > 0, "No available units.");
+        check_extensibility(property.units[0]);
+        t.done();
+    });
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("STORAGE", getPropertyValueSuccess,
+        getPropertyValueError);
+});
+
+}
+
+function SystemInfoBuild_extend() {
+//==== TEST: SystemInfoBuild_extend
+//==== LABEL Check if SystemInfoBuild can have new property added
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoBuild:SystemInfoBuild U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA OBX
+//==== PRIORITY P3
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoBuild_extend', {timeout: 90000}), getPropertyValueSuccess,
+    getPropertyValueError;
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        check_extensibility(property);
+        t.done();
+    });
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("BUILD", getPropertyValueSuccess, getPropertyValueError);
+});
+
+}
+
+function SystemInfoBuild_manufacturer_attribute() {
+//==== TEST: SystemInfoBuild_manufacturer_attribute
+//==== LABEL Check attribute manufacturer of SystemInfoBuild_manufacturer
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoBuild:manufacturer A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoBuild_manufacturer_attribute', {timeout: 90000}), getPropertyValueSuccess,
+    getPropertyValueError;
+
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (cellular) {
+        assert_own_property(cellular, "manufacturer", "CELLULAR_NETWORK doesn't own manufacturer property.");
+        check_readonly(cellular, "manufacturer", cellular.manufacturer, "string", null);
+        t.done();
+    });
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.message + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("BUILD", getPropertyValueSuccess, getPropertyValueError);
+});
+
+}
+
+function SystemInfoBuild_model_attribute() {
+//==== TEST: SystemInfoBuild_model_attribute
+//==== LABEL Check attribute model of SystemInfoBuild
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoBuild:model A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoBuild_model_attribute', {timeout: 90000}), getPropertyValueSuccess,
+    getPropertyValueError;
+
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (cellular) {
+        assert_own_property(cellular, "model", "CELLULAR_NETWORK doesn't own model property.");
+        check_readonly(cellular, "model", cellular.model, "string", null);
+        t.done();
+    });
+    getPropertyValueError = t.step_func(function (e) {
+        assert_unreached("Exception: " + e.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("BUILD", getPropertyValueSuccess, getPropertyValueError);
+});
+
+}
+
+function SystemInfoDeviceOrientation_extend() {
+//==== TEST: SystemInfoDeviceOrientation_extend
+//==== LABEL Check if SystemInfoDeviceOrientation can have new property added
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceOrientation:SystemInfoDeviceOrientation U
+//==== TEST_CRITERIA OBX
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P3
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoDeviceOrientation_extend', {timeout: 90000}),
+    getPropertyValueSuccess, getPropertyValueError;
+
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        check_extensibility(property);
+        t.done();
+    });
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("Exception: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("DEVICE_ORIENTATION",
+        getPropertyValueSuccess, getPropertyValueError);
+}, "SystemInfoDeviceOrientation_extend");
+
+}
+
+function SystemInfoStorage_extend() {
+//==== TEST: SystemInfoStorage_extend
+//==== LABEL Check if SystemInfoStorage can have new property added
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoStorage:SystemInfoStorage U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA OBX
+//==== PRIORITY P3
+
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoStorage_extend', {timeout: 90000}),
+    getPropertyValueSuccess, getPropertyValueError;
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        check_extensibility(property);
+        t.done();
+    });
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("STORAGE", getPropertyValueSuccess,
+        getPropertyValueError);
+});
+
+}
+
+function SystemInfo_in_tizen() {
+//==== TEST: SystemInfo_in_tizen
+//==== PRIORITY P3
+//==== LABEL Check if package exists in tizen.
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfo:SystemInfo U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA OBME
+test(function () {
+    assert_true("systeminfo" in tizen, "No systeminfo in tizen.");
+    check_readonly(tizen, "systeminfo", tizen.systeminfo, "object", "dummyValue");
+}, 'SystemInfo_in_tizen');
+
+}
+
+function SystemInfo_getPropertyValue_missarg() {
+//==== TEST: SystemInfo_getPropertyValue_missarg
+//==== LABEL Check if getPropertyValue method called with missing non-optional argument throws an exception
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfo:getPropertyValue M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA MMA
+test(function () {
+    assert_throws( TYPE_MISMATCH_EXCEPTION,
+        function () {
+            tizen.systeminfo.getPropertyValue();
+        }, TYPE_MISMATCH_ERR + " should be thrown");
+}, 'SystemInfo_getPropertyValue_missarg');
+
+}
+
+function SystemInfo_getPropertyValue_with_errorCallback() {
+//==== TEST: SystemInfo_getPropertyValue_with_errorCallback
+//==== LABEL Check method SystemInfo_getPropertyValue with errorCallback
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfo:getPropertyValue M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA MOA
+setup({timeout: 90000});
+
+var t = async_test('SystemInfo_getPropertyValue_with_errorCallback', {timeout: 90000}),
+    getPropertyValueSuccess, getPropertyValueError;
+
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (cpu) {
+        assert_not_equals(cpu.load, null, "Failed to getPropertyValue");
+        t.done();
+    });
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name:" +
+            error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("CPU", getPropertyValueSuccess, getPropertyValueError);
+});
+
+}
+
+function SystemInfo_getPropertyValue_property_TypeMismatch() {
+//==== TEST: SystemInfo_getPropertyValue_property_TypeMismatch
+//==== LABEL Check if getPropertyValue throws exception when property is incorrect
+//==== PRIORITY: P2
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfo:getPropertyValue M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA MC
+setup({timeout: 90000});
+
+var t = async_test('SystemInfo_getPropertyValue_property_TypeMismatch', {timeout: 90000}), i, conversionTable, systemInfoProperty, exceptionName,
+    getPropertyValueSuccess, getPropertyValueError;
+
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        assert_unreached("Should not be here.");
+    });
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("Should not be here: " + error.name + ": " + error.message);
+    });
+
+    conversionTable = getTypeConversionExceptions("enum", false);
+
+    for(i = 0; i < conversionTable.length; i++) {
+        systemInfoProperty = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+
+        assert_throws({name: exceptionName},
+            function () {
+                tizen.systeminfo.getPropertyValue(systemInfoProperty,
+                    getPropertyValueSuccess, getPropertyValueError);
+            }, exceptionName + " should be thrown - given incorrect SystemSettingType - ");
+    }
+    t.done();
+}, "SystemInfo_getPropertyValue_property_TypeMismatch");
+
+}
+
+function SystemInfo_getPropertyValue_successCallback_invalid_cb() {
+//==== TEST: SystemInfo_getPropertyValue_successCallback_invalid_cb
+//==== LABEL Check getPropertyValue() argument successCallback validation - use {onsuccess: function (){}}
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:System:SystemInfo:SystemInfo:getPropertyValue M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA MTCB
+//==== ONLOAD_DELAY 90
+setup({timeout: 90000});
+
+var t = async_test('SystemInfo_getPropertyValue_successCallback_invalid_cb', {timeout: 90000}),
+    getPropertyValueSuccess, exceptionName = "TypeMismatchError", i;
+t.step(function () {
+    getPropertyValueSuccess = {
+        onsuccess: t.step_func(function () {
+            assert_unreached("Invalid successCallback invoked: ");
+        })
+    };
+    for (i = 0;  i < systemInfoPropertyId.length; i++) {
+        assert_throws({name: exceptionName},
+            function () {
+                tizen.systeminfo.getPropertyValue(systemInfoPropertyId[i], getPropertyValueSuccess);
+            }, exceptionName + " should be thrown - given incorrect success callback.");
+    }
+    t.done();
+});
+
+}
+
+function SystemInfo_getPropertyValue_errorCallback_TypeMismatch() {
+//==== TEST: SystemInfo_getPropertyValue_errorCallback_TypeMismatch
+//==== LABEL Check if getPropertyValue throws exception when errorCallback is incorrect
+//==== PRIORITY: P2
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfo:getPropertyValue M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA MC
+setup({timeout: 90000});
+
+var t = async_test('SystemInfo_getPropertyValue_errorCallback_TypeMismatch', {timeout: 90000}),
+    conversionTable, getPropertyValueSuccess, getPropertyValueError, exceptionName, i;
+
+t.step(function () {
+    conversionTable = getTypeConversionExceptions("functionObject", true);
+
+    getPropertyValueSuccess = t.step_func(function () {
+        assert_unreached("Unexpected successCallback");
+    });
+
+    for (i = 0; i < conversionTable.length; i++) {
+        getPropertyValueError = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+
+        assert_throws({name: exceptionName},
+            function () {
+                tizen.systeminfo.getPropertyValue("STORAGE", getPropertyValueSuccess, getPropertyValueError);
+            }, exceptionName + " should be thrown - give incorrect errorCallback.");
+    }
+    t.done();
+});
+
+}
+
+function SystemInfo_getPropertyValue_errorCallback_invalid_cb() {
+//==== TEST: SystemInfo_getPropertyValue_errorCallback_invalid_cb
+//==== LABEL Check if getPropertyValue throws exception when errorCallback is invalid
+//==== PRIORITY: P2
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfo:getPropertyValue M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA MTCB
+setup({timeout: 90000});
+
+var t = async_test('SystemInfo_getPropertyValue_errorCallback_invalid_cb', {timeout: 90000}), getPropertyValueSuccess, getPropertyValueError, i;
+
+t.step(function () {
+    getPropertyValueError = {
+        onerror: t.step_func(function (error) {
+            assert_unreached("getPropertyValue() error callback invoked: name:" +
+                error.name + ", msg: " + error.message);
+        })
+    };
+    getPropertyValueSuccess = t.step_func(function () {
+        assert_unreached("Unexpected successCallback");
+    });
+    for (i = 0;  i < systemInfoPropertyId.length; i++) {
+        assert_throws(TYPE_MISMATCH_EXCEPTION,
+            function () {
+                tizen.systeminfo.getPropertyValue(systemInfoPropertyId[i], getPropertyValueSuccess, getPropertyValueError);
+            }, TYPE_MISMATCH_ERR + " should be thrown");
+    }
+    t.done();
+});
+
+}
+
+function SystemInfo_addPropertyValueChangeListener_options_TypeMismatch() {
+//==== TEST: SystemInfo_addPropertyValueChangeListener_options_TypeMismatch
+//==== LABEL Check if addPropertyValueChangeListener of SystemInfo throws exception when option is incorrect
+//==== PRIORITY: P2
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfo:addPropertyValueChangeListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA MC
+//==== ONLOAD_DELAY 90
+var t = async_test('SystemInfo_addPropertyValueChangeListener_options_TypeMismatch', {timeout: 90000}), i, conversionTable,
+    systemInfoOption, exceptionName, addPropertyValueChangeListenerSuccess;
+
+setup({timeout: 90000});
+
+t.step(function () {
+    addPropertyValueChangeListenerSuccess = t.step_func(function (property) {
+        assert_unreached("Should not be here.");
+    });
+
+    conversionTable = getTypeConversionExceptions("dictionary", true);
+
+    for(i = 0; i < conversionTable.length; i++) {
+        systemInfoOption = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+
+        assert_throws({name: exceptionName},
+            function () {
+                tizen.systeminfo.addPropertyValueChangeListener("BATTERY",
+                    addPropertyValueChangeListenerSuccess, systemInfoOption);
+            }, exceptionName + " should be thrown - given incorrect systemInfoOption - " + systemInfoOption);
+    }
+    t.done();
+});
+
+}
+
+function SystemInfo_addPropertyValueChangeListener_property_TypeMismatch() {
+//==== TEST: SystemInfo_addPropertyValueChangeListener_property_TypeMismatch
+//==== LABEL Check if addPropertyValueChangeListener throws exception when property is incorrect
+//==== PRIORITY: P2
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfo:addPropertyValueChangeListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA MC
+//==== ONLOAD_DELAY 90
+var t = async_test('SystemInfo_addPropertyValueChangeListener_property_TypeMismatch', {timeout: 90000}),
+    i, conversionTable, systemInfoProperty, exceptionName, addPropertyValueChangeListenerSuccess;
+setup({timeout: 90000});
+
+t.step(function () {
+    addPropertyValueChangeListenerSuccess = t.step_func(function (property) {
+        assert_unreached("Should not be here.");
+    });
+
+    conversionTable = getTypeConversionExceptions("enum", false);
+
+    for (i = 0; i < conversionTable.length; i++) {
+        systemInfoProperty = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+
+        assert_throws({name: exceptionName},
+            function () {
+                tizen.systeminfo.addPropertyValueChangeListener(systemInfoProperty, addPropertyValueChangeListenerSuccess);
+            }, exceptionName + " should be thrown - given incorrect systemInfoPropertyId - " + systemInfoProperty);
+    }
+    t.done();
+});
+
+}
+
+function SystemInfo_addPropertyValueChangeListener_missarg() {
+//==== TEST: SystemInfo_addPropertyValueChangeListener_missarg
+//==== LABEL Check if addPropertyValueChangeListener method of SystemInfo called with missing non-optional argument throws an exception
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfo:addPropertyValueChangeListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA MMA
+test(function () {
+    assert_throws(TYPE_MISMATCH_EXCEPTION,
+        function () {
+            tizen.systeminfo.addPropertyValueChangeListener();
+        }, "Calling addPropertyValueChangeListener without arguments should throw an exception.");
+}, 'SystemInfo_addPropertyValueChangeListener_missarg');
+
+}
+
+function SystemInfo_addPropertyValueChangeListener_successCallback_TypeMismatch() {
+
+//==== TEST: SystemInfo_addPropertyValueChangeListener_successCallback_TypeMismatch
+//==== LABEL Check argument successCallback conversions exception
+//==== PRIORITY: P2
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfo:addPropertyValueChangeListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA MC
+setup({timeout: 90000});
+
+var t = async_test('SystemInfo_addPropertyValueChangeListener_successCallback_TypeMismatch', {timeout: 90000}), addPropertyValueChangeListenerSuccess, exceptionName, i, conversionTable;
+
+t.step(function () {
+    conversionTable = getTypeConversionExceptions("functionObject", false);
+
+    for(i = 0; i < conversionTable.length; i++) {
+        addPropertyValueChangeListenerSuccess = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+
+        assert_throws({name: exceptionName},
+            function () {
+                tizen.systeminfo.addPropertyValueChangeListener("STORAGE", addPropertyValueChangeListenerSuccess);
+            }, exceptionName + " should be thrown - given incorrect success callback.");
+    }
+    t.done();
+});
+
+}
+
+function SystemInfo_addPropertyValueChangeListener_successCallback_invalid_cb() {
+//==== TEST: SystemInfo_addPropertyValueChangeListener_successCallback_invalid_cb
+//==== LABEL Check addPropertyValueChangeListener() argument successCallback validation - use {onsuccess: function (){}}
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:System:SystemInfo:SystemInfo:addPropertyValueChangeListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA MTCB
+//==== ONLOAD_DELAY 90
+setup({timeout: 90000});
+
+var t = async_test('SystemInfo_addPropertyValueChangeListener_successCallback_invalid_cb',
+    {timeout: 90000}), addPropertyValueChangeListenerSuccess, exceptionName = "TypeMismatchError";
+t.step(function () {
+    addPropertyValueChangeListenerSuccess = {
+        onsuccess: t.step_func(function () {
+            assert_unreached("Invalid successCallback invoked: ");
+        })
+    };
+    assert_throws({name: exceptionName},
+        function () {
+            tizen.systeminfo.addPropertyValueChangeListener("STORAGE", addPropertyValueChangeListenerSuccess);
+        }, exceptionName + " should be thrown - given incorrect success callback.");
+    t.done();
+});
+
+}
+
+function SystemInfo_removePropertyValueChangeListener_exist() {
+//==== TEST: SystemInfo_removePropertyValueChangeListener_exist
+//==== LABEL Check if method removePropertyValueChangeListener of SystemInfo exists
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfo:removePropertyValueChangeListener M
+//==== TEST_CRITERIA ME
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+test(function () {
+    assert_true("removePropertyValueChangeListener" in tizen.systeminfo, "No removePropertyValueChangeListener method in tizen.systeminfo.");
+    check_method_exists(tizen.systeminfo, "removePropertyValueChangeListener");
+}, 'SystemInfo_removePropertyValueChangeListener_exist');
+
+}
+
+function SystemInfoPropertySuccessCallback_onsuccess() {
+//==== TEST: SystemInfoPropertySuccessCallback_onsuccess
+//==== LABEL Check if SystemInfoPropertySuccessCallback works
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoPropertySuccessCallback:onsuccess M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA CBOA
+//==== PRIORITY P1
+
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoPropertySuccessCallback_onsuccess', {timeout: 90000}),
+    getPropertyValueSuccess, getPropertyValueError;
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (value) {
+        assert_not_equals(value , null, "Argument should not be null.");
+        assert_type(value, "object", "Incorrect type.");
+        t.done();
+    });
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("STORAGE", getPropertyValueSuccess,
+        getPropertyValueError);
+});
+
+}
+
+function SystemInfo_getCapability_sensor_accelerometer_wakeup() {
+//==== TEST: SystemInfo_getCapability_sensor_accelerometer_wakeup
+//==== LABEL Check attribute accelerometerWakeup of SystemInfoDeviceCapability
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:accelerometerWakeup A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.accelerometer.wakeup");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_sensor_accelerometer_wakeup');
+
+}
+
+function SystemInfoDeviceCapability_autoRotation_attribute() {
+//==== TEST: SystemInfoDeviceCapability_autoRotation_attribute
+//==== LABEL Check attribute autoRotation of SystemInfoDeviceCapability
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:autoRotation A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+var deviceCapabilities = tizen.systeminfo.getCapabilities();
+
+test(function () {
+    assert_own_property(deviceCapabilities, "autoRotation",
+        "SystemInfoDeviceCapability does not own autoRotation property.");
+    check_readonly(deviceCapabilities, "autoRotation",
+        deviceCapabilities.autoRotation, "boolean", null);
+}, 'SystemInfoDeviceCapability_autoRotation_attribute');
+
+}
+
+function SystemInfo_getCapability_sensor_barometer_wakeup() {
+//==== TEST: SystemInfo_getCapability_sensor_barometer_wakeup
+//==== LABEL Check attribute barometerWakeup of SystemInfoDeviceCapability
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:barometerWakeup A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.barometer.wakeup");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_sensor_barometer_wakeup');
+
+}
+
+function SystemInfo_getCapability_camera() {
+//==== TEST: SystemInfo_getCapability_camera
+//==== LABEL Check attribute camera of SystemInfoDeviceCapability
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:camera A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/camera");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_camera');
+
+}
+
+function SystemInfo_getCapability_database_encryption() {
+//==== TEST: SystemInfo_getCapability_database_encryption
+//==== LABEL Check attribute dataEncryption of SystemInfoDeviceCapability
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:dataEncryption A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/database.encryption");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_database_encryption');
+
+}
+
+function SystemInfo_getCapability_graphics_acceleration() {
+//==== TEST: SystemInfo_getCapability_graphics_acceleration
+//==== LABEL Check attribute graphicsAcceleration of SystemInfoDeviceCapability
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:graphicsAcceleration A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/graphics.acceleration");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_graphics_acceleration');
+
+}
+
+function SystemInfo_getCapability_sensor_gyroscope_wakeup() {
+//==== TEST: SystemInfo_getCapability_sensor_gyroscope_wakeup
+//==== LABEL Check attribute gyroscopeWakeup of SystemInfoDeviceCapability
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:gyroscopeWakeup A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.gyroscope.wakeup");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_sensor_gyroscope_wakeup');
+
+}
+
+function SystemInfo_getCapability_input_keyboard_layout() {
+//==== TEST: SystemInfo_getCapability_input_keyboard_layout
+//==== LABEL Check attribute inputKeyboardLayout of SystemInfoDeviceCapability
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:inputKeyboardLayout A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/input.keyboard.layout");
+    assert_type(deviceCapability, "string", "deviceCapability should be a String");
+}, 'SystemInfo_getCapability_input_keyboard_layout');
+
+}
+
+function SystemInfo_getCapability_sensor_magnetometer_wakeup() {
+//==== TEST: SystemInfo_getCapability_sensor_magnetometer_wakeup
+//==== LABEL Check attribute magnetometerWakeup of SystemInfoDeviceCapability
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:magnetometerWakeup A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.magnetometer.wakeup");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_sensor_magnetometer_wakeup');
+
+}
+
+function SystemInfo_getCapability_network_nfc_reserved_push() {
+//==== TEST: SystemInfo_getCapability_network_nfc_reserved_push
+//==== LABEL Check attribute nfcReservedPush of SystemInfoDeviceCapability
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:nfcReservedPush A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/network.nfc.reserved_push");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_network_nfc_reserved_push');
+
+}
+
+function SystemInfo_getCapability_opengles() {
+//==== TEST: SystemInfo_getCapability_opengles
+//==== LABEL Check attribute opengles of SystemInfoDeviceCapability
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:opengles A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/opengles");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_opengles');
+
+}
+
+function SystemInfo_getCapability_opengles_texture_format() {
+//==== TEST: SystemInfo_getCapability_opengles_texture_format
+//==== LABEL Check attribute openglestextureFormat of SystemInfoDeviceCapability
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:openglestextureFormat A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/opengles.texture_format");
+    assert_type(deviceCapability, "string", "deviceCapability should be a String");
+}, 'SystemInfo_getCapability_opengles_texture_format');
+
+}
+
+function SystemInfo_getCapability_sensor_photometer_wakeup() {
+//==== TEST: SystemInfo_getCapability_sensor_photometer_wakeup
+//==== LABEL Check attribute photometerWakeup of SystemInfoDeviceCapability
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:photometerWakeup A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.photometer.wakeup");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_sensor_photometer_wakeup');
+
+}
+
+function SystemInfo_getCapability_sensor_photometer() {
+//==== TEST: SystemInfo_getCapability_sensor_photometer
+//==== LABEL Check attribute photometer of SystemInfoDeviceCapability
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:photometer A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.photometer");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_sensor_photometer');
+
+}
+
+function SystemInfo_getCapability_sensor_proximity_wakeup() {
+//==== TEST: SystemInfo_getCapability_sensor_proximity_wakeup
+//==== LABEL Check attribute proximityWakeup of SystemInfoDeviceCapability
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:proximityWakeup A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.proximity.wakeup");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_sensor_proximity_wakeup');
+
+}
+
+function SystemInfo_getCapability_network_push() {
+//==== TEST: SystemInfo_getCapability_network_push
+//==== LABEL Check attribute push of SystemInfoDeviceCapability
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:push A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/network.push");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_network_push');
+
+}
+
+function SystemInfo_getCapability_network_secure_element() {
+//==== TEST: SystemInfo_getCapability_network_secure_element
+//==== LABEL Check attribute secureElement of SystemInfoDeviceCapability
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:secureElement A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/network.secure_element");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_network_secure_element');
+
+}
+
+function SystemInfo_getCapability_speech_synthesis() {
+//==== TEST: SystemInfo_getCapability_speech_synthesis
+//==== LABEL Check attribute speechSynthesis of SystemInfoDeviceCapability
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:speechSynthesis A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/speech.synthesis");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean.");
+}, 'SystemInfo_getCapability_speech_synthesis');
+
+}
+
+function SystemInfo_getCapability_network_telephony_mms() {
+//==== TEST: SystemInfo_getCapability_network_telephony_mms
+//==== LABEL Check attribute telephonyMms of SystemInfoDeviceCapability
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:telephonyMms A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/network.telephony.mms");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_network_telephony_mms');
+
+}
+
+function SystemInfoDeviceCapability_telephonySms_attribute() {
+//==== TEST: SystemInfoDeviceCapability_telephonySms_attribute
+//==== LABEL Check attribute telephonySms of SystemInfoDeviceCapability
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:telephonySms A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+var deviceCapabilities = tizen.systeminfo.getCapabilities();
+test(function () {
+
+
+    assert_own_property(deviceCapabilities, "telephonySms", "SystemInfoDeviceCapability does not own telephonySms property.");
+
+
+    check_readonly(deviceCapabilities, "telephonySms", deviceCapabilities.telephonySms, "boolean", null);
+
+
+}, 'SystemInfoDeviceCapability_telephonySms_attribute');
+
+}
+
+function SystemInfo_getCapability_network_telephony() {
+//==== TEST: SystemInfo_getCapability_network_telephony
+//==== LABEL Check attribute telephony of SystemInfoDeviceCapability
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:telephony A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/network.telephony");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_network_telephony');
+
+}
+
+function SystemInfo_getCapability_sensor_tiltmeter_wakeup() {
+//==== TEST: SystemInfo_getCapability_sensor_tiltmeter_wakeup
+//==== LABEL Check attribute tiltmeterWakeup of SystemInfoDeviceCapability
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:tiltmeterWakeup A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.tiltmeter.wakeup");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_sensor_tiltmeter_wakeup');
+
+}
+
+function SystemInfo_getCapability_sensor_tiltmeter() {
+//==== TEST: SystemInfo_getCapability_sensor_tiltmeter
+//==== LABEL Check attribute tiltmeter of SystemInfoDeviceCapability
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:tiltmeter A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.tiltmeter");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_sensor_tiltmeter');
+
+}
+
+function SystemInfo_getCapability_vision_face_recognition() {
+//==== TEST: SystemInfo_getCapability_vision_face_recognition
+//==== LABEL Check attribute visionFaceRecognition of SystemInfoDeviceCapability
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:visionFaceRecognition A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/vision.face_recognition");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean.");
+}, 'SystemInfo_getCapability_vision_face_recognition');
+
+}
+
+function SystemInfo_getCapability_vision_image_recognition() {
+//==== TEST: SystemInfo_getCapability_vision_image_recognition
+//==== LABEL Check attribute visionImageRecognition of SystemInfoDeviceCapability
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:visionImageRecognition A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/vision.image_recognition");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean.");
+}, 'SystemInfo_getCapability_vision_image_recognition');
+
+}
+
+function SystemInfo_getCapability_vision_qrcode_generation() {
+//==== TEST: SystemInfo_getCapability_vision_qrcode_generation
+//==== LABEL Check attribute visionQrcodeGeneration of SystemInfoDeviceCapability
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:visionQrcodeGeneration A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/vision.qrcode_generation");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean.");
+}, 'SystemInfo_getCapability_vision_qrcode_generation');
+
+}
+
+function SystemInfo_getCapability_vision_qrcode_recognition() {
+//==== TEST: SystemInfo_getCapability_vision_qrcode_recognition
+//==== LABEL Check attribute visionQrcodeRecognition of SystemInfoDeviceCapability
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:visionQrcodeRecognition A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/vision.qrcode_recognition");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean.");
+}, 'SystemInfo_getCapability_vision_qrcode_recognition');
+
+}
+
+function SystemInfo_removePropertyValueChangeListener_all_properties() {
+//==== TEST: SystemInfo_removePropertyValueChangeListener_all_properties
+//==== LABEL Check whether removePropertyValueChangeListener() method properly unsubscribes notifications for property changes
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfo:removePropertyValueChangeListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA MMINA
+
+var lId, addPropertyValueChangeListenerSuccess, i;
+
+test(function () {
+    addPropertyValueChangeListenerSuccess = function () {};
+
+    for (i = 0; i < systemInfoPropertyId.length; i++) {
+        lId = tizen.systeminfo.addPropertyValueChangeListener(systemInfoPropertyId[i],
+            addPropertyValueChangeListenerSuccess);
+
+        tizen.systeminfo.removePropertyValueChangeListener(lId);
+    }
+}, 'SystemInfo_removePropertyValueChangeListener_all_properties');
+
+}
+
+function SystemInfoPropertySuccessCallback_onsuccess_CPU() {
+//==== TEST: SystemInfoPropertySuccessCallback_onsuccess_CPU
+//==== LABEL Check if getPropertyValue('CPU', successCB, errorCB) calls successCallback + results' attributes
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoPropertySuccessCallback:onsuccess M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA CBT CBOA
+//==== ONLOAD_DELAY 90
+
+var t = async_test('SystemInfoPropertySuccessCallback_onsuccess_CPU', {timeout: 90000}),
+    getPropertyValueSuccess, getPropertyValueError;
+setup({timeout: 90000});
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (cpu) {
+        assert_equals(typeof(cpu.load), "number", "load attribute ");
+        t.done();
+    });
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("CPU", getPropertyValueSuccess,
+        getPropertyValueError);
+});
+
+}
+
+function SystemInfoPropertySuccessCallback_onsuccess_DeviceOrientation() {
+//==== TEST: SystemInfoPropertySuccessCallback_onsuccess_DeviceOrientation
+//==== LABEL Check if getPropertyValue('DEVICE_ORIENTATION', successCB, errorCB) calls successCallback + results' attributes
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoPropertySuccessCallback:onsuccess M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA CBOA
+//==== ONLOAD_DELAY 90
+
+var t = async_test('SystemInfoPropertySuccessCallback_onsuccess_DeviceOrientation', {timeout: 90000}),
+    getPropertyValueSuccess, getPropertyValueError;
+setup({timeout: 90000});
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (deviceorientation) {
+        assert_type(deviceorientation.status, "string", "status type check");
+
+        t.done();
+    });
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("DEVICE_ORIENTATION", getPropertyValueSuccess,
+        getPropertyValueError);
+});
+
+}
+
+function SystemInfoDisplay_constructor_display() {
+//==== TEST: SystemInfoDisplay_constructor_display
+//==== LABEL Check if getPropertyValue('Display', successCB, errorCB) calls successCallback + results' attributes
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDisplay:resolutionWidth A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AT
+//==== ONLOAD_DELAY 90
+var t = async_test('SystemInfoDisplay_constructor_display', {timeout: 90000}),
+    getPropertyValueSuccess, getPropertyValueError;
+setup({timeout: 90000});
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (display) {
+        assert_type(display.resolutionWidth, "unsigned long", "resolutionWidth");
+        assert_type(display.resolutionHeight, "unsigned long", "resolutionHeight");
+        assert_type(display.dotsPerInchWidth, "unsigned long", "dotsPerInchWidth");
+        assert_type(display.dotsPerInchHeight, "unsigned long", "dotsPerInchHeight");
+        assert_type(display.physicalWidth, "double", "physicalWidth");
+        assert_type(display.physicalHeight, "double", "physicalHeight");
+        assert_type(display.brightness, "double", "brightness");
+        t.done();
+    });
+
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("DISPLAY", getPropertyValueSuccess,
+        getPropertyValueError);
+});
+
+}
+
+function SystemInfoPropertySuccessCallback_onsuccess_Storage() {
+
+//==== TEST: SystemInfoPropertySuccessCallback_onsuccess_Storage
+//==== LABEL Check if getPropertyValue('Storage', successCB, errorCB) calls successCallback + results' attributes
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoPropertySuccessCallback:onsuccess M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA CBT CBOA
+//==== ONLOAD_DELAY 90
+
+var t = async_test('SystemInfoPropertySuccessCallback_onsuccess_Storage', {timeout: 90000}),
+    getPropertyValueSuccess, getPropertyValueError;
+setup({timeout: 90000});
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        assert_own_property(property, "units", "No units property.");
+        assert_true(Array.isArray(property.units),
+            "SystemInfoStorage_units is not an array");
+        assert_true(property.units.length > 0, "No available units.");
+        assert_type(property.units[0].type, "string", "type attribute");
+        assert_type(property.units[0].capacity, "unsigned long long", "capacity attribute");
+        assert_type(property.units[0].availableCapacity, "unsigned long long", "availableCapacity attribute");
+        assert_type(property.units[0].isRemovable, "boolean", "isRemovable attribute");
+        t.done();
+    });
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("STORAGE", getPropertyValueSuccess,
+        getPropertyValueError);
+});
+
+}
+
+function SystemInfo_addPropertyValueChangeListener() {
+//==== TEST: SystemInfo_addPropertyValueChangeListener
+//==== LABEL Check method addPropertyValueChangeListener of SystemInfo
+//==== SPEC Tizen Web API:Tizen Specification:SystemInfo:SystemInfo:addPropertyValueChangeListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA MMINA MAST MR
+//==== ONLOAD_DELAY 90
+var t = async_test('SystemInfo_addPropertyValueChangeListener', {timeout: 90000}),
+    addPropertyValueChangeListenerSuccess, addPropertyValueChangeListenerError, retValue = null;
+
+setup({timeout: 90000});
+
+t.step(function () {
+    addPropertyValueChangeListenerError = t.step_func(function (error) {
+        assert_unreached("addPropertyValueChangeListener() error callback invoked: name:" + error.name + ", msg:"  + error.message);
+    });
+
+    addPropertyValueChangeListenerSuccess = t.step_func(function (property) {
+        assert_own_property(property, "load", "CPU does not own load property.");
+        assert_type(retValue, "unsigned long", "addPropertyValueChangeListener returns wrong value");
+
+        t.done();
+    });
+
+    retValue = tizen.systeminfo.addPropertyValueChangeListener("CPU", addPropertyValueChangeListenerSuccess);
+});
+
+}
+
+function SystemInfo_addPropertyValueChangeListener_with_options() {
+//==== TEST: SystemInfo_addPropertyValueChangeListener_with_options
+//==== LABEL Check with optional arguments addPropertyValueChangeListener(valid_property, valid_successCallback, valid_options)
+//==== SPEC Tizen Web API:Tizen Specification:SystemInfo:SystemInfo:addPropertyValueChangeListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA MOA MAST
+//==== ONLOAD_DELAY 90
+var t = async_test('SystemInfo_addPropertyValueChangeListener_with_options', {timeout: 90000}),
+    addPropertyValueChangeListenerSuccess, lId;
+
+setup({timeout: 90000});
+
+t.step(function () {
+    addPropertyValueChangeListenerSuccess = t.step_func(function (property) {
+        t.done();
+    });
+
+    lId = tizen.systeminfo.addPropertyValueChangeListener("CPU", addPropertyValueChangeListenerSuccess,
+        {highThreshold: 0, lowThreshold: 1});
+});
+
+}
+
+function SystemInfo_removePropertyValueChangeListener() {
+//==== TEST: SystemInfo_removePropertyValueChangeListener
+//==== LABEL Check method removePropertyValueChangeListener of SystemInfo
+//==== ONLOAD_DELAY 90
+//==== SPEC: Tizen Web API:System:SystemInfo:SystemInfo:removePropertyValueChangeListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA MMINA MAST MR
+setup({timeout: 90000});
+var t = async_test('SystemInfo_removePropertyValueChangeListener', {timeout: 90000}),
+    addPropertyValueChangeListenerSuccess, lId, retValue = null;
+
+t.step(function () {
+    addPropertyValueChangeListenerSuccess = t.step_func(function (property) {
+        assert_unreached("Method removePropertyValueChangeListener does not remove listener.");
+    });
+
+    lId = tizen.systeminfo.addPropertyValueChangeListener("CPU", addPropertyValueChangeListenerSuccess);
+    retValue = tizen.systeminfo.removePropertyValueChangeListener(lId);
+    setTimeout(t.step_func(function () {
+        assert_equals(retValue, undefined, "removePropertyValueChangeListener returns wrong value");
+
+        t.done();
+    }), 3000);
+});
+
+}
+
+function SystemInfo_getPropertyValue_successCallback_missarg() {
+//==== TEST: SystemInfo_getPropertyValue_successCallback_missarg
+//==== LABEL Check if getPropertyValue(SystemInfoPropertyId) (no success callback) throws an exception
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfo:getPropertyValue M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA MMA
+var i;
+
+test(function () {
+    for (i = 0;  i < systemInfoPropertyId.length; i++) {
+        assert_throws(TYPE_MISMATCH_EXCEPTION,
+            function () {
+                tizen.systeminfo.getPropertyValue(systemInfoPropertyId[i]);
+            }, TYPE_MISMATCH_ERR + " should be thrown");
+    }
+}, 'SystemInfo_getPropertyValue_successCallback_missarg');
+
+}
+
+function SystemInfo_addPropertyValueChangeListener_successCallback_missarg() {
+//==== TEST: SystemInfo_addPropertyValueChangeListener_successCallback_missarg
+//==== LABEL Check if addPropertyValueChangeListener(SystemInfoPropertyId) (no success callback) throws an exception when successCallback is missing
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfo:addPropertyValueChangeListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA MMA
+
+var lId, i;
+
+test(function () {
+    for (i = 0; i < systemInfoPropertyId.length; i++) {
+        assert_throws(TYPE_MISMATCH_EXCEPTION,
+            function () {
+                lId = tizen.systeminfo.addPropertyValueChangeListener(systemInfoPropertyId[i]);
+                tizen.systeminfo.removePropertyValueChangeListener(lId);
+            });
+    }
+}, 'SystemInfo_addPropertyValueChangeListener_successCallback_missarg');
+
+}
+
+function SystemInfo_getPropertyValue_successCallback_TypeMismatch() {
+//==== TEST: SystemInfo_getPropertyValue_successCallback_TypeMismatch
+//==== LABEL Check if getPropertyValue throws exception when successCallback is incorrect
+//==== PRIORITY: P2
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfo:getPropertyValue M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA MC
+setup({timeout: 90000});
+
+var t = async_test('SystemInfo_getPropertyValue_successCallback_TypeMismatch', {timeout: 90000}),
+    getPropertyValueSuccess, exceptionName, getPropertyValueError, i, conversionTable;
+
+t.step(function () {
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name:" +
+            error.name + ", msg: " + error.message);
+    });
+
+    conversionTable = getTypeConversionExceptions("functionObject", false);
+
+    for(i = 0; i < conversionTable.length; i++) {
+        getPropertyValueSuccess = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+
+        assert_throws({name: exceptionName},
+            function () {
+                tizen.systeminfo.getPropertyValue("STORAGE", getPropertyValueSuccess,
+                    getPropertyValueError);
+            }, exceptionName + " should be thrown - given incorrect successCallback.");
+    }
+    t.done();
+});
+
+}
+
+function SystemInfoPropertySuccessCallback_onsuccess_Battery() {
+//==== TEST: SystemInfoPropertySuccessCallback_onsuccess_Battery
+//==== LABEL Check if getPropertyValue('BATTERY', successCB, errorCB) calls successCallback + results' attributes
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoPropertySuccessCallback:onsuccess M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA CBT CBOA
+//==== ONLOAD_DELAY 90
+
+var t = async_test('SystemInfoPropertySuccessCallback_onsuccess_Battery', {timeout: 90000}),
+    getPropertyValueSuccess, getPropertyValueError;
+setup({timeout: 90000});
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (battery) {
+        assert_type(battery.level, "double", "level type check");
+        assert_type(battery.isCharging, "boolean", "isCharging type check");
+        t.done();
+    });
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("BATTERY", getPropertyValueSuccess,
+        getPropertyValueError);
+});
+
+}
+
+function SystemInfoPropertySuccessCallback_onsuccess_Build() {
+//==== TEST: SystemInfoPropertySuccessCallback_onsuccess_Build
+//==== LABEL Check if getPropertyValue('BUILD', successCB, errorCB) calls successCallback + results' attributes
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoPropertySuccessCallback:onsuccess M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA CBOA
+//==== ONLOAD_DELAY 90
+
+var t = async_test('SystemInfoPropertySuccessCallback_onsuccess_Build', {timeout: 90000}),
+    getPropertyValueSuccess, getPropertyValueError;
+setup({timeout: 90000});
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (build) {
+        assert_type(build.model, "string", "model type check");
+        assert_type(build.manufacturer, "string", "manufacturer type check");
+        t.done();
+    });
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("BUILD", getPropertyValueSuccess,
+        getPropertyValueError);
+});
+
+}
+
+function SystemInfoPropertySuccessCallback_onsuccess_Display() {
+//==== TEST: SystemInfoPropertySuccessCallback_onsuccess_Display
+//==== LABEL Check if getPropertyValue('DISPLAY', successCB, errorCB) calls successCallback + results' attributes
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoPropertySuccessCallback:onsuccess M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA CBT CBOA
+//==== ONLOAD_DELAY 90
+
+var t = async_test('SystemInfoPropertySuccessCallback_onsuccess_Display', {timeout: 90000}),
+    getPropertyValueSuccess, getPropertyValueError;
+setup({timeout: 90000});
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (display) {
+        assert_type(display.resolutionWidth, "unsigned long", "resolutionWidth type check");
+        assert_type(display.resolutionHeight, "unsigned long", "resolutionHeight type check");
+        assert_type(display.dotsPerInchWidth, "unsigned long", "dotsPerInchWidth type check");
+        assert_type(display.dotsPerInchHeight, "unsigned long", "dotsPerInchHeight type check");
+        assert_type(display.physicalWidth, "double", "physicalWidth type check");
+        assert_type(display.physicalHeight, "double", "physicalHeight type check");
+        assert_type(display.brightness, "double", "brightness type check");
+        t.done();
+    });
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("DISPLAY", getPropertyValueSuccess,
+        getPropertyValueError);
+});
+
+}
+
+function SystemInfoPropertySuccessCallback_onsuccess_Peripheral() {
+//==== TEST: SystemInfoPropertySuccessCallback_onsuccess_Peripheral
+//==== LABEL Check if getPropertyValue('PERIPHERAL', successCB, errorCB) calls successCallback + results' attributes
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoPropertySuccessCallback:onsuccess M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA CBT CBOA
+//==== ONLOAD_DELAY 90
+
+var t = async_test('SystemInfoPropertySuccessCallback_onsuccess_Peripheral', {timeout: 90000}),
+    getPropertyValueSuccess, getPropertyValueError;
+setup({timeout: 90000});
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (peripheral) {
+        assert_type(peripheral.isVideoOutputOn, "boolean", "isVideoOutputOn type check");
+        t.done();
+    });
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("PERIPHERAL", getPropertyValueSuccess,
+        getPropertyValueError);
+});
+
+}
+
+function SystemInfoBuild_buildVersion_attribute() {
+//==== TEST: SystemInfoBuild_buildVersion_attribute
+//==== LABEL Check attribute buildVersion of SystemInfoBuild
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoBuild:buildVersion A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoBuild_buildVersion_attribute', {timeout: 90000}), getPropertyValueSuccess,
+    getPropertyValueError;
+
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (cellular) {
+        assert_own_property(cellular, "buildVersion",
+            "SystemInfoBuild doesn't own buildVersion property.");
+        check_readonly(cellular, "buildVersion", cellular.buildVersion,
+            "string", null);
+        t.done();
+    });
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name:" + error.name + "msg:" + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("BUILD", getPropertyValueSuccess, getPropertyValueError);
+});
+
+}
+
+function SystemInfo_getCapability_profile() {
+//==== TEST: SystemInfo_getCapability_profile
+//==== LABEL Check if attribute profile of SystemInfoDeviceCapability exists, has type SystemInfoProfile and is readonly
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceCapability:profile A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/profile");
+    assert_type(deviceCapability, "string", "deviceCapability should be a string");
+}, 'SystemInfo_getCapability_profile');
+
+}
+
+function SystemInfoDeviceOrientation_isAutoRotation_attribute() {
+//==== TEST: SystemInfoDeviceOrientation_isAutoRotation_attribute
+//==== LABEL Check isAutoRotation attribute of SystemInfoDeviceOrientation
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoDeviceOrientation:isAutoRotation A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoDeviceOrientation_isAutoRotation_attribute', {timeout: 90000}),
+    getPropertyValueSuccess, getPropertyValueError;
+
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        assert_own_property(property, "isAutoRotation",
+            "SystemInfoDeviceOrientation doesn't own isAutoRotation property.");
+        check_readonly(property, "isAutoRotation", property.isAutoRotation,
+            "boolean", null);
+        t.done();
+    });
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("DEVICE_ORIENTATION",
+        getPropertyValueSuccess, getPropertyValueError);
+}, "SystemInfoDeviceOrientation_status_attribute");
+
+}
+
+function SystemInfo_addPropertyValueChangeListener_property_empty() {
+//==== TEST: SystemInfo_addPropertyValueChangeListener_property_empty
+//==== LABEL Check with empty SystemInfoPropertyId argument of addPropertyValueChangeListener
+//==== PRIORITY: P2
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfo:addPropertyValueChangeListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA MTD
+setup({timeout: 90000});
+
+var t = async_test('SystemInfo_addPropertyValueChangeListener_property_empty', {timeout: 90000}), addPropertyValueChangeListenerSuccess;
+
+t.step(function () {
+    addPropertyValueChangeListenerSuccess = t.step_func(function (property) {
+        t.done();
+    });
+
+    tizen.systeminfo.addPropertyValueChangeListener("CPU", addPropertyValueChangeListenerSuccess, {});
+});
+
+}
+
+function SystemInfoLocale_notexist() {
+//==== TEST: SystemInfoLocale_notexist
+//==== PRIORITY P3
+//==== LABEL Check if interface SystemInfoLocale exists, it should not.
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoLocale:SystemInfoLocale U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("SystemInfoLocale");
+}, 'SystemInfoLocale_notexist');
+
+}
+
+function SystemInfoNetwork_notexist() {
+//==== TEST: SystemInfoNetwork_notexist
+//==== PRIORITY P3
+//==== LABEL Check if interface SystemInfoNetwork exists, it should not.
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoNetwork:SystemInfoNetwork U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("SystemInfoNetwork");
+}, 'SystemInfoNetwork_notexist');
+
+}
+
+function SystemInfoSIM_notexist() {
+//==== TEST: SystemInfoSIM_notexist
+//==== PRIORITY P3
+//==== LABEL Check if interface SystemInfoSIM exists, it should not.
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoSIM:SystemInfoSIM U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("SystemInfoSIM");
+}, 'SystemInfoSIM_notexist');
+
+}
+
+function SystemInfoWifiNetwork_notexist() {
+//==== TEST: SystemInfoWifiNetwork_notexist
+//==== PRIORITY P3
+//==== LABEL Check if interface SystemInfoWifiNetwork exists, it should not.
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoWifiNetwork:SystemInfoWifiNetwork U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("SystemInfoWifiNetwork");
+}, 'SystemInfoWifiNetwork_notexist');
+
+}
+
+function SystemInfoPropertyArraySuccessCallback_notexist() {
+//==== TEST: SystemInfoPropertyArraySuccessCallback_notexist
+//==== LABEL Check if interface SystemInfoPropertyArraySuccessCallback exists, it should not.
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoPropertyArraySuccessCallback:SystemInfoPropertyArraySuccessCallback U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA CBNIO
+
+test(function () {
+    check_no_interface_object("SystemInfoPropertyArraySuccessCallback");
+}, 'SystemInfoPropertyArraySuccessCallback_notexist');
+
+}
+
+function SystemInfo_getCapability_datacontrol() {
+//==== TEST: SystemInfo_getCapability_datacontrol
+//==== LABEL Check if getCapability() method of SystemInfo with datacontrol attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.2.0/org.tizen.web.appprogramming/html/guide/sys_guide/systeminfo.htm
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/datacontrol");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_datacontrol');
+
+}
+
+function SystemInfoNetwork_extend() {
+//==== TEST: SystemInfoNetwork_extend
+//==== LABEL Check if SystemInfoNetwork can have new property added
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoNetwork:SystemInfoNetwork U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA OBX
+//==== PRIORITY P3
+
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoNetwork_extend', {timeout: 90000}), getPropertyValueSuccess,
+    getPropertyValueError;
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        check_extensibility(property);
+        t.done();
+    });
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("NETWORK", getPropertyValueSuccess,
+        getPropertyValueError);
+});
+
+}
+
+function SystemInfoNetwork_networkType_attribute() {
+//==== TEST: SystemInfoNetwork_networkType_attribute
+//==== LABEL Check networkType attribute of SystemInfoNetwork
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoNetwork:networkType A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoNetwork_networkType_attribute', {timeout: 90000}), getPropertyValueSuccess,
+    getPropertyValueError;
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        assert_own_property(property, "networkType",
+            "NETWORK doesn't own networkType property.");
+        assert_in_array(property.networkType, SYSTEM_INFO_NETWORK_TYPE,
+            "networkType isn't type of SystemInfoNetworkType");
+        assert_type(property.networkType, "string", "networkType");
+        check_readonly(property, "networkType", property.networkType,
+            "string", null);
+        t.done();
+    });
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("NETWORK", getPropertyValueSuccess,
+        getPropertyValueError);
+});
+
+}
+
+function SystemInfoLocale_country_attribute() {
+//==== TEST: SystemInfoLocale_country_attribute
+//==== LABEL Check if attribute country of SystemInfoLocale exists, has type DOMString and is readonly
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoLocale:country A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoLocale_country_attribute', {timeout: 90000}), getPropertyValueSuccess,
+    getPropertyValueError;
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        assert_own_property(property, "country", "SystemInfoLocale does not own country property.");
+        check_readonly(property, "country", property.country, "string", null);
+        assert_true(property.country !== "", "null check");
+        t.done();
+    });
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("LOCALE", getPropertyValueSuccess,
+        getPropertyValueError);
+});
+
+}
+
+function SystemInfoLocale_language_attribute() {
+//==== TEST: SystemInfoLocale_language_attribute
+//==== LABEL Check if attribute language of SystemInfoLocale exists, has type DOMString and is readonly
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoLocale:language A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoLocale_language_attribute', {timeout: 90000}), getPropertyValueSuccess,
+    getPropertyValueError;
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        assert_own_property(property, "language", "SystemInfoLocale does not own language property.");
+        check_readonly(property, "language", property.language, "string", null);
+        assert_true(property.language !== "", "null check");
+        t.done();
+    });
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("LOCALE", getPropertyValueSuccess,
+        getPropertyValueError);
+});
+
+}
+
+function SystemInfoLocale_extend() {
+//==== TEST: SystemInfoLocale_extend
+//==== PRIORITY P3
+//==== LABEL Check if instance of interface SystemInfoLocale can be extended with new property
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoLocale:SystemInfoLocale U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA OBX
+
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoLocale_extend', {timeout: 90000}), getPropertyValueSuccess,
+    getPropertyValueError;
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        check_extensibility(property);
+        t.done();
+    });
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("LOCALE", getPropertyValueSuccess,
+        getPropertyValueError);
+});
+
+}
+
+function SystemInfoPropertySuccessCallback_onsuccess_Locale() {
+//==== TEST: SystemInfoPropertySuccessCallback_onsuccess_Locale
+//==== LABEL Check if getPropertyValue('LOCALE', successCB, errorCB) calls successCallback + results' attributes
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoPropertySuccessCallback:onsuccess M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA CBT CBOA
+//==== ONLOAD_DELAY 90
+
+var t = async_test('SystemInfoPropertySuccessCallback_onsuccess_Locale', {timeout: 90000}),
+    getPropertyValueSuccess, getPropertyValueError;
+setup({timeout: 90000});
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (locale) {
+        assert_type(locale.language, "string", "language type check");
+        assert_type(locale.country, "string", "country type check");
+        t.done();
+    });
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("LOCALE", getPropertyValueSuccess,
+        getPropertyValueError);
+});
+
+}
+
+function SystemInfoPropertySuccessCallback_onsuccess_Network() {
+//==== TEST: SystemInfoPropertySuccessCallback_onsuccess_Network
+//==== LABEL Check if getPropertyValue('NETWORK', successCB, errorCB) calls successCallback + results' attributes
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoPropertySuccessCallback:onsuccess M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA CBT CBOA
+//==== ONLOAD_DELAY 90
+
+var t = async_test('SystemInfoPropertySuccessCallback_onsuccess_Network', {timeout: 90000}),
+    getPropertyValueSuccess, getPropertyValueError;
+setup({timeout: 90000});
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (network) {
+        assert_type(network.networkType, "string", "networkType type check");
+        t.done();
+    });
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("NETWORK", getPropertyValueSuccess,
+        getPropertyValueError);
+});
+
+}
+
+function SystemInfo_removePropertyValueChangeListener_listenerId_invalid() {
+//==== TEST: SystemInfo_removePropertyValueChangeListener_listenerId_invalid
+//==== LABEL Check whether removePropertyValueChangeListener() method throws exception with invalid argument
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfo:removePropertyValueChangeListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+var listenerId = -1;
+
+test(function () {
+    assert_throws(INVALID_VALUES_EXCEPTION,
+        function () {
+            tizen.systeminfo.removePropertyValueChangeListener(listenerId);
+        }, "InvalidValuesError should be thrown");
+}, 'SystemInfo_removePropertyValueChangeListener_listenerId_invalid');
+
+}
+
+function SystemInfoStorageUnit_isRemovable_attribute_value() {
+//==== TEST: SystemInfoStorageUnit_isRemovable_attribute_value
+//==== LABEL Check SystemInfoStorageUnit have attribute isRemovable and has proper value limitations
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoStorageUnit:isRemovable A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY: P1
+//==== TEST_CRITERIA AE AT AVL
+
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoStorageUnit_isRemovable_attribute_value', {timeout: 90000}), getPropertyValueSuccess, getPropertyValueError;
+
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        assert_own_property(property, "units", "No units property.");
+        assert_true(Array.isArray(property.units), "SystemInfoStorage_units is not an array");
+        assert_greater_than(property.units.length, 0, "No available units.");
+        assert_own_property(property.units[0], "isRemovable", "SystemInfoStorageUnit does not own isRemovable property.");
+        assert_true(property.units[0].isRemovable === true || property.units[0].isRemovable === false, "check isRemovable");
+        t.done();
+    });
+
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("STORAGE", getPropertyValueSuccess, getPropertyValueError);
+});
+
+}
+
+function SystemInfoStorageUnit_type_attribute_value() {
+//==== TEST: SystemInfoStorageUnit_type_attribute_value
+//==== LABEL Check SystemInfoStorageUnit have attribute type and has proper value limitations
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoStorageUnit:type A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY: P1
+//==== TEST_CRITERIA AE AT AVL
+
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoStorageUnit_type_attribute_value', {timeout: 90000}), getPropertyValueSuccess, getPropertyValueError;
+
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        assert_own_property(property, "units", "No units property.");
+        assert_true(Array.isArray(property.units), "SystemInfoStorage_units is not an array");
+        assert_greater_than(property.units.length, 0, "No available units.");
+        assert_own_property(property.units[0], "type", "SystemInfoStorageUnit does not own type property.");
+        assert_true(property.units[0].type === "UNKNOWN" || property.units[0].type === "INTERNAL" || property.units[0].type === "USB_HOST" || property.units[0].type === "MMC" || property.units[0].type === "USB_DEVICE", "type check");
+        t.done();
+    });
+
+    getPropertyValueError = t.step_func(function (e) {
+        assert_unreached("Exception: " + e.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("STORAGE", getPropertyValueSuccess, getPropertyValueError);
+});
+
+}
+
+function SystemInfo_getCapability_account() {
+//==== TEST: SystemInfo_getCapability_account
+//==== LABEL Check if getCapability() method of SystemInfo with account attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.2.0/org.tizen.web.appprogramming/html/guide/sys_guide/systeminfo.htm
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/account");
+    assert_type(deviceCapability, "boolean", "deviceCapabilityshould be a boolean");
+}, 'SystemInfo_getCapability_account');
+
+}
+
+function SystemInfo_getCapability_bookmark() {
+//==== TEST: SystemInfo_getCapability_bookmark
+//==== LABEL Check if getCapability() method of SystemInfo with bookmark attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.2.0/org.tizen.web.appprogramming/html/guide/sys_guide/systeminfo.htm
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/bookmark");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_bookmark');
+
+}
+
+function SystemInfo_getCapability_calendar() {
+//==== TEST: SystemInfo_getCapability_calendar
+//==== LABEL Check if getCapability() method of SystemInfo with calendar attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.2.0/org.tizen.web.appprogramming/html/guide/sys_guide/systeminfo.htm
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/calendar");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_calendar');
+
+}
+
+function SystemInfo_getCapability_contact() {
+//==== TEST: SystemInfo_getCapability_contact
+//==== LABEL Check if getCapability() method of SystemInfo with contact attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.2.0/org.tizen.web.appprogramming/html/guide/sys_guide/systeminfo.htm
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/contact");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_contact');
+
+}
+
+function SystemInfo_getCapability_datasync() {
+//==== TEST: SystemInfo_getCapability_datasync
+//==== LABEL Check if getCapability() method of SystemInfo with datasync attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.2.0/org.tizen.web.appprogramming/html/guide/sys_guide/systeminfo.htm
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/datasync");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_datasync');
+
+}
+
+function SystemInfo_getCapability_download() {
+//==== TEST: SystemInfo_getCapability_download
+//==== LABEL Check if getCapability() method of SystemInfo with download attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.2.0/org.tizen.web.appprogramming/html/guide/sys_guide/systeminfo.htm
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/download");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_download');
+
+}
+
+function SystemInfo_getCapability_email() {
+//==== TEST: SystemInfo_getCapability_email
+//==== LABEL Check if getCapability() method of SystemInfo with email attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.2.0/org.tizen.web.appprogramming/html/guide/sys_guide/systeminfo.htm
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/email");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_email');
+
+}
+
+function SystemInfo_getCapability_notification() {
+//==== TEST: SystemInfo_getCapability_notification
+//==== LABEL Check if getCapability() method of SystemInfo with notification attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.2.0/org.tizen.web.appprogramming/html/guide/sys_guide/systeminfo.htm
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/notification");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_notification');
+
+}
+
+function SystemInfo_getCapability_screen_height() {
+//==== TEST: SystemInfo_getCapability_screen_height
+//==== LABEL Check if getCapability() method of SystemInfo with screen.height attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/screen.height");
+    assert_type(deviceCapability, "number", "deviceCapability should be a number");
+}, 'SystemInfo_getCapability_screen_height');
+
+}
+
+function SystemInfo_getCapability_screen_size_normal_480_800() {
+//==== TEST: SystemInfo_getCapability_screen_size_normal_480_800
+//==== LABEL Check if getCapability() method of SystemInfo with screen.size.normal.480.800 attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.2.0/org.tizen.web.appprogramming/html/guide/sys_guide/systeminfo.htm
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/screen.size.normal.480.800");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_screen_size_normal_480_800');
+
+}
+
+function SystemInfo_getCapability_screen_size_normal_720_1280() {
+//==== TEST: SystemInfo_getCapability_screen_size_normal_720_1280
+//==== LABEL Check if getCapability() method of SystemInfo with screen.size.normal.720.1280 attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.2.0/org.tizen.web.appprogramming/html/guide/sys_guide/systeminfo.htm
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/screen.size.normal.720.1280");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_screen_size_normal_720_1280');
+
+}
+
+function SystemInfo_getCapability_screen_width() {
+//==== TEST: SystemInfo_getCapability_screen_width
+//==== LABEL Check if getCapability() method of SystemInfo with screen.width attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.2.0/org.tizen.web.appprogramming/html/guide/sys_guide/systeminfo.htm
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/screen.width");
+    assert_type(deviceCapability, "number", "deviceCapability should be a number");
+}, 'SystemInfo_getCapability_screen_width');
+
+}
+
+function SystemInfo_getCapability_sensor_ultraviolet() {
+//==== TEST: SystemInfo_getCapability_sensor_ultraviolet
+//==== LABEL Check if getCapability() method of SystemInfo with sensor.ultraviolet attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.ultraviolet");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_sensor_ultraviolet');
+
+}
+
+function SystemInfo_getCapability_systemsetting() {
+//==== TEST: SystemInfo_getCapability_systemsetting
+//==== LABEL Check if getCapability() method of SystemInfo with systemsetting attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.2.0/org.tizen.web.appprogramming/html/guide/sys_guide/systeminfo.htm
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/systemsetting");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_systemsetting');
+
+}
+
+function SystemInfo_getCapability_websetting() {
+//==== TEST: SystemInfo_getCapability_websetting
+//==== LABEL Check if getCapability() method of SystemInfo with websetting attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.2.0/org.tizen.web.appprogramming/html/guide/sys_guide/systeminfo.htm
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/websetting");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_websetting');
+
+}
+
+function SystemInfo_getCapability_multi_point_touch_pinch_zoom() {
+//==== TEST: SystemInfo_getCapability_multi_point_touch_pinch_zoom
+//==== LABEL Check if getCapability() method of SystemInfo with multi_point_touch.pinch_zoom attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/multi_point_touch.pinch_zoom");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_multi_point_touch_pinch_zoom');
+
+}
+
+function SystemInfo_getCapability_opengles_texture_format_3dc() {
+//==== TEST: SystemInfo_getCapability_opengles_texture_format_3dc
+//==== LABEL Check if getCapability() method of SystemInfo with opengles.texture_format.3dc attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/opengles.texture_format.3dc");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_opengles_texture_format_3dc');
+
+}
+
+function SystemInfo_getCapability_opengles_texture_format_atc() {
+//==== TEST: SystemInfo_getCapability_opengles_texture_format_atc
+//==== LABEL Check if getCapability() method of SystemInfo with opengles.texture_format.atc attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/opengles.texture_format.atc");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_opengles_texture_format_atc');
+
+}
+
+function SystemInfo_getCapability_opengles_texture_format_etc() {
+//==== TEST: SystemInfo_getCapability_opengles_texture_format_etc
+//==== LABEL Check if getCapability() method of SystemInfo with opengles.texture_format.etc attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/opengles.texture_format.etc");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_opengles_texture_format_etc');
+
+}
+
+function SystemInfo_getCapability_opengles_texture_format_ptc() {
+//==== TEST: SystemInfo_getCapability_opengles_texture_format_ptc
+//==== LABEL Check if getCapability() method of SystemInfo with opengles.texture_format.ptc attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/opengles.texture_format.ptc");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_opengles_texture_format_ptc');
+
+}
+
+function SystemInfo_getCapability_opengles_texture_format_pvrtc() {
+//==== TEST: SystemInfo_getCapability_opengles_texture_format_pvrtc
+//==== LABEL Check if getCapability() method of SystemInfo with opengles.texture_format.pvrtc attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/opengles.texture_format.pvrtc");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_opengles_texture_format_pvrtc');
+
+}
+
+function SystemInfo_getCapability_opengles_texture_format_utc() {
+//==== TEST: SystemInfo_getCapability_opengles_texture_format_utc
+//==== LABEL Check if getCapability() method of SystemInfo with opengles.texture_format.utc attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/opengles.texture_format.utc");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_opengles_texture_format_utc');
+
+}
+
+function SystemInfo_getCapability_platform_core_cpu_arch_armv6() {
+//==== TEST: SystemInfo_getCapability_platform_core_cpu_arch_armv6
+//==== LABEL Check if getCapability() method of SystemInfo with platform.core.cpu.arch.armv6 attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/platform.core.cpu.arch.armv6");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_platform_core_cpu_arch_armv6');
+
+}
+
+function SystemInfo_getCapability_platform_core_cpu_arch_armv7() {
+//==== TEST: SystemInfo_getCapability_platform_core_cpu_arch_armv7
+//==== LABEL Check if getCapability() method of SystemInfo with platform.core.cpu.arch.armv7 attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/platform.core.cpu.arch.armv7");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_platform_core_cpu_arch_armv7');
+
+}
+
+function SystemInfo_getCapability_platform_core_cpu_arch_x86() {
+//==== TEST: SystemInfo_getCapability_platform_core_cpu_arch_x86
+//==== LABEL Check if getCapability() method of SystemInfo with platform.core.cpu.arch.x86 attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/platform.core.cpu.arch.x86");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_platform_core_cpu_arch_x86');
+
+}
+
+function SystemInfo_getCapability_platform_core_fpu_arch_sse2() {
+//==== TEST: SystemInfo_getCapability_platform_core_fpu_arch_sse2
+//==== LABEL Check if getCapability() method of SystemInfo with platform.core.fpu.arch.sse2 attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/platform.core.fpu.arch.sse2");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_platform_core_fpu_arch_sse2');
+
+}
+
+function SystemInfo_getCapability_platform_core_fpu_arch_sse3() {
+//==== TEST: SystemInfo_getCapability_platform_core_fpu_arch_sse3
+//==== LABEL Check if getCapability() method of SystemInfo with platform.core.fpu.arch.sse3 attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/platform.core.fpu.arch.sse3");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_platform_core_fpu_arch_sse3');
+
+}
+
+function SystemInfo_getCapability_platform_core_fpu_arch_ssse3() {
+//==== TEST: SystemInfo_getCapability_platform_core_fpu_arch_ssse3
+//==== LABEL Check if getCapability() method of SystemInfo with platform.core.fpu.arch.ssse3 attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/platform.core.fpu.arch.ssse3");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_platform_core_fpu_arch_ssse3');
+
+}
+
+function SystemInfo_getCapability_platform_core_fpu_arch_vfpv2() {
+//==== TEST: SystemInfo_getCapability_platform_core_fpu_arch_vfpv2
+//==== LABEL Check if getCapability() method of SystemInfo with platform.core.fpu.arch.vfpv2 attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/platform.core.fpu.arch.vfpv2");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_platform_core_fpu_arch_vfpv2');
+
+
+}
+
+function SystemInfo_getCapability_platform_core_fpu_arch_vfpv3() {
+//==== TEST: SystemInfo_getCapability_platform_core_fpu_arch_vfpv3
+//==== LABEL Check if getCapability() method of SystemInfo with platform.core.fpu.arch.vfpv3 attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/platform.core.fpu.arch.vfpv3");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_platform_core_fpu_arch_vfpv3');
+
+
+}
+
+function SystemInfo_getCapability_platform_native_osp_compatible() {
+//==== TEST: SystemInfo_getCapability_platform_native_osp_compatible
+//==== LABEL Check if getCapability() method of SystemInfo with platform.native.osp_compatible attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/platform.native.osp_compatible");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_platform_native_osp_compatible');
+
+}
+
+function SystemInfo_getCapability_screen_auto_rotation() {
+//==== TEST: SystemInfo_getCapability_screen_auto_rotation
+//==== LABEL Check if getCapability() method of SystemInfo with screen.auto_rotation attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/screen.auto_rotation");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_screen_auto_rotation');
+
+}
+
+function SystemInfo_getCapability_shell_appwidget() {
+//==== TEST: SystemInfo_getCapability_shell_appwidget
+//==== LABEL Check if getCapability() method of SystemInfo with shell.appwidget attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/shell.appwidget");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean.");
+}, 'SystemInfo_getCapability_shell_appwidget');
+
+}
+
+function SystemInfo_getCapability_network_nfc_card_emulation() {
+//==== TEST: SystemInfo_getCapability_network_nfc_card_emulation
+//==== LABEL Check if getCapability() method of SystemInfo with network.nfc.card_emulation attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/network.nfc.card_emulation");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_network_nfc_card_emulation');
+
+}
+
+function SystemInfo_getCapability_platform_native_api_version() {
+//==== TEST: SystemInfo_getCapability_platform_native_api_version
+//==== LABEL Check if getCapability() method of SystemInfo with platform.native.api.version attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/platform.native.api.version");
+    assert_type(deviceCapability, "string", "deviceCapability should be a string");
+}, 'SystemInfo_getCapability_platform_native_api_version');
+
+}
+
+function SystemInfo_getCapability_platform_core_api_version() {
+//==== TEST: SystemInfo_getCapability_platform_core_api_version
+//==== LABEL Check if getCapability() method of SystemInfo with platform.core.api.version attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/platform.core.api.version");
+    assert_type(deviceCapability, "string", "deviceCapability should be a string");
+}, 'SystemInfo_getCapability_platform_core_api_version');
+
+}
+
+function SystemInfo_getCapability_screen_size_normal_1080_1920() {
+//==== TEST: SystemInfo_getCapability_screen_size_normal_1080_1920
+//==== LABEL Check if getCapability() method of SystemInfo with screen.size.normal.1080.1920 attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/screen.size.normal.1080.1920");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_screen_size_normal_1080_1920');
+
+}
+
+function SystemInfo_getCapability_screen_size_normal_600_1024() {
+//==== TEST: SystemInfo_getCapability_screen_size_normal_600_1024
+//==== LABEL Check if getCapability() method of SystemInfo with screen.size.normal.600.1024 attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/screen.size.normal.600.1024");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_screen_size_normal_600_1024');
+
+}
+
+function SystemInfo_getCapability_screen_size_normal_540_960() {
+//==== TEST: SystemInfo_getCapability_screen_size_normal_540_960
+//==== LABEL Check if getCapability() method of SystemInfo with screen.size.normal.540.960 attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/screen.size.normal.540.960");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_screen_size_normal_540_960');
+
+}
+
+function SystemInfo_getCapability_screen_size_normal_320_480() {
+//==== TEST: SystemInfo_getCapability_screen_size_normal_320_480
+//==== LABEL Check if getCapability() method of SystemInfo with screen.size.normal.320.480 attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/screen.size.normal.320.480");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_screen_size_normal_320_480');
+
+}
+
+function SystemInfo_getCapability_screen_size_normal_320_320() {
+//==== TEST: SystemInfo_getCapability_screen_size_normal_320_320
+//==== LABEL Check if getCapability() method of SystemInfo with screen.size.normal.320.320 attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/screen.size.normal.320.320");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_screen_size_normal_320_320');
+
+}
+
+function SystemInfo_getCapability_screen_size_normal_240_400() {
+//==== TEST: SystemInfo_getCapability_screen_size_normal_240_400
+//==== LABEL Check if getCapability() method of SystemInfo with screen.size.normal.240.400 attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/screen.size.normal.240.400");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_screen_size_normal_240_400');
+
+}
+
+function SystemInfo_getCapability_screen_size_normal() {
+//==== TEST: SystemInfo_getCapability_screen_size_normal
+//==== LABEL Check if getCapability() method of SystemInfo with screen.size.normal attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/screen.size.normal");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_screen_size_normal');
+
+}
+
+function SystemInfo_getCapability_screen_dpi() {
+//==== TEST: SystemInfo_getCapability_screen_dpi
+//==== LABEL Check if getCapability() method of SystemInfo with screen.dpi attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/screen.dpi");
+    assert_type(deviceCapability, "number", "deviceCapability should be a unsigned short.");
+}, 'SystemInfo_getCapability_screen_dpi');
+
+}
+
+function SystemInfo_getCapability_screen_coordinate_system_size_normal() {
+//==== TEST: SystemInfo_getCapability_screen_coordinate_system_size_normal
+//==== LABEL Check if getCapability() method of SystemInfo with screen.coordinate_system.size.normal attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/screen.coordinate_system.size.normal");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_screen_coordinate_system_size_normal');
+
+}
+
+function SystemInfo_getCapability_screen_coordinate_system_size_large() {
+//==== TEST: SystemInfo_getCapability_screen_coordinate_system_size_large
+//==== LABEL Check if getCapability() method of SystemInfo with screen.coordinate_system.size.large attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/screen.coordinate_system.size.large");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_screen_coordinate_system_size_large');
+
+}
+
+function SystemInfo_getCapability_screen_bpp() {
+//==== TEST: SystemInfo_getCapability_screen_bpp
+//==== LABEL Check if getCapability() method of SystemInfo with screen.bpp attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/screen.bpp");
+    assert_type(deviceCapability, "number", "deviceCapability should be a unsigned short.");
+}, 'SystemInfo_getCapability_screen_bpp');
+
+}
+
+function SystemInfo_getCapability_sensor_heart_rate_monitor() {
+//==== TEST: SystemInfo_getCapability_sensor_heart_rate_monitor
+//==== LABEL Check if getCapability() method of SystemInfo with sensor.heart_rate_monitor attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.2.0/org.tizen.web.appprogramming/html/guide/sys_guide/systeminfo.htm
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.heart_rate_monitor");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_sensor_heart_rate_monitor');
+
+}
+
+function SystemInfo_getCapability_sensor_pedometer() {
+//==== TEST: SystemInfo_getCapability_sensor_pedometer
+//==== LABEL Check if getCapability() method of SystemInfo with sensor.pedometer attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.2.0/org.tizen.web.appprogramming/html/guide/sys_guide/systeminfo.htm
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.pedometer");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_sensor_pedometer');
+
+}
+
+function SystemInfo_getCapability_sensor_wrist_up() {
+//==== TEST: SystemInfo_getCapability_sensor_wrist_up
+//==== LABEL Check if getCapability() method of SystemInfo with sensor.wrist_up attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.2.0/org.tizen.web.appprogramming/html/guide/sys_guide/systeminfo.htm
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.wrist_up");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_sensor_wrist_up');
+
+}
+
+function SystemInfo_getCapability_exist() {
+//==== TEST: SystemInfo_getCapability_exist
+//==== LABEL Check if method getCapability of SystemInfo exists
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    assert_true("getCapability" in tizen.systeminfo, "getCapability method not in tizen.systeminfo.");
+    check_method_exists(tizen.systeminfo, "getCapability");
+}, 'SystemInfo_getCapability_exist');
+
+}
+
+function SystemInfo_getCapability_screen() {
+//==== TEST: SystemInfo_getCapability_screen
+//==== LABEL Check if getCapability() method of SystemInfo with screen attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/screen");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_screen');
+
+}
+
+function SystemInfo_getCapability_systemsetting_home_screen() {
+//==== TEST: SystemInfo_getCapability_systemsetting_home_screen
+//==== LABEL Check if getCapability() method of SystemInfo with systemsetting.home_screen attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.2.0/org.tizen.web.appprogramming/html/guide/sys_guide/systeminfo.htm
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/systemsetting.home_screen");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_systemsetting_home_screen');
+
+}
+
+function SystemInfo_getCapability_systemsetting_lock_screen() {
+//==== TEST: SystemInfo_getCapability_systemsetting_lock_screen
+//==== LABEL Check if getCapability() method of SystemInfo with systemsetting.lock_screen attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.2.0/org.tizen.web.appprogramming/html/guide/sys_guide/systeminfo.htm
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/systemsetting.lock_screen");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_systemsetting_lock_screen');
+
+}
+
+function SystemInfo_getCapability_systemsetting_incoming_call() {
+//==== TEST: SystemInfo_getCapability_systemsetting_incoming_call
+//==== LABEL Check if getCapability() method of SystemInfo with systemsetting.incoming_call attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.2.0/org.tizen.web.appprogramming/html/guide/sys_guide/systeminfo.htm
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/systemsetting.incoming_call");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_systemsetting_incoming_call');
+
+}
+
+function SystemInfo_getCapability_systemsetting_notification_email() {
+//==== TEST: SystemInfo_getCapability_systemsetting_notification_email
+//==== LABEL Check if getCapability() method of SystemInfo with systemsetting.notification_email attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.2.0/org.tizen.web.appprogramming/html/guide/sys_guide/systeminfo.htm
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/systemsetting.notification_email");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_systemsetting_notification_email');
+
+}
+
+function SystemInfo_getCapability_network_bluetooth_always_on() {
+//==== TEST: SystemInfo_getCapability_network_bluetooth_always_on
+//==== LABEL Check if getCapability() method of SystemInfo with network.bluetooth.always_on attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.2.0/org.tizen.web.appprogramming/html/guide/sys_guide/systeminfo.htm
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/capability/network.bluetooth.always_on");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_network_bluetooth_always_on');
+
+}
+
+function SystemInfo_getCapability_network_bluetooth_health() {
+//==== TEST: SystemInfo_getCapability_network_bluetooth_health
+//==== LABEL Check if getCapability() method of SystemInfo with network.bluetooth.health attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.2.0/org.tizen.web.appprogramming/html/guide/sys_guide/systeminfo.htm
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/network.bluetooth.health");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_network_bluetooth_health');
+
+}
+
+function SystemInfo_addPropertyValueChangeListener_errorCallback_TypeMismatch() {
+//==== TEST: SystemInfo_addPropertyValueArrayChangeListener_errorCallback_TypeMismatch
+//==== LABEL Check argument errorCallback conversions exception
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfo:addPropertyValueArrayChangeListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 90000});
+
+var t = async_test('SystemInfo_addPropertyValueChangeListener_errorCallback_TypeMismatch', {timeout: 90000}), addPropertyValueArrayChangeListenerSuccess, addPropertyValueArrayChangeListenerError,
+    exceptionName, i, conversionTable;
+
+t.step(function () {
+    addPropertyValueArrayChangeListenerSuccess = t.step_func(function (properties) {
+        assert_unreached("successCallback should not invoked");
+    });
+
+    conversionTable = getTypeConversionExceptions("functionObject", true);
+    for (i = 0; i < conversionTable.length; i++) {
+        addPropertyValueArrayChangeListenerError = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+        assert_throws({name: exceptionName}, function () {
+            tizen.systeminfo.addPropertyValueArrayChangeListener("STORAGE", addPropertyValueArrayChangeListenerSuccess,
+                {highThreshold: 0, lowThreshold: 1}, addPropertyValueArrayChangeListenerError);
+        }, exceptionName + " should be thrown - given incorrect error callback.");
+    }
+    t.done();
+});
+
+}
+
+function SystemInfo_getCapability_archive() {
+//==== TEST: SystemInfo_getCapability_archive
+//==== LABEL Check if getCapability() method of SystemInfo with archive attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/archive");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_archive');
+
+}
+
+function SystemInfo_getCapability_badge() {
+//==== TEST: SystemInfo_getCapability_badge
+//==== LABEL Check if getCapability() method of SystemInfo with badge attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/badge");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_badge');
+
+}
+
+function SystemInfo_getCapability_exif() {
+//==== TEST: SystemInfo_getCapability_exif
+//==== LABEL Check if getCapability() method of SystemInfo with exif attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/exif");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_exif');
+
+}
+
+function SystemInfo_getCapability_led() {
+//==== TEST: SystemInfo_getCapability_led
+//==== LABEL Check if getCapability() method of SystemInfo with led attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/led");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_led');
+
+}
+
+function SystemInfo_getCapability_network_bluetooth_audio_call() {
+//==== TEST: SystemInfo_getCapability_network_bluetooth_audio_call
+//==== LABEL Check if getCapability() method of SystemInfo with network.bluetooth.audio.call attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/network.bluetooth.audio.call");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_network_bluetooth_audio_call');
+
+}
+
+function SystemInfo_getCapability_network_bluetooth_audio_media() {
+//==== TEST: SystemInfo_getCapability_network_bluetooth_audio_media
+//==== LABEL Check if getCapability() method of SystemInfo with network.bluetooth.audio.media attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/network.bluetooth.audio.media");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_network_bluetooth_audio_media');
+
+}
+
+function SystemInfo_getCapability_network_bluetooth_hid() {
+//==== TEST: SystemInfo_getCapability_network_bluetooth_hid
+//==== LABEL Check if getCapability() method of SystemInfo with network.bluetooth.hid attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/network.bluetooth.hid");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_network_bluetooth_hid');
+
+}
+
+function SystemInfo_getCapability_network_bluetooth_le() {
+//==== TEST: SystemInfo_getCapability_network_bluetooth_le
+//==== LABEL Check if getCapability() method of SystemInfo with network.bluetooth.le attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/network.bluetooth.le");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_network_bluetooth_le');
+
+}
+
+function SystemInfo_getCapability_network_bluetooth_opp() {
+//==== TEST: SystemInfo_getCapability_network_bluetooth_opp
+//==== LABEL Check if getCapability() method of SystemInfo with network.bluetooth.opp attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/network.bluetooth.opp");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_network_bluetooth_opp');
+
+}
+
+function SystemInfo_getCapability_screen_size_all() {
+//==== TEST: SystemInfo_getCapability_screen_size_all
+//==== LABEL Check if getCapability() method of SystemInfo with screen.size.all attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/screen.size.all");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_screen_size_all');
+
+}
+
+function SystemInfo_getCapability_screen_size_large() {
+//==== TEST: SystemInfo_getCapability_screen_size_large
+//==== LABEL Check if getCapability() method of SystemInfo with screen.size.large attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/screen.size.large");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_screen_size_large');
+
+}
+
+function SystemInfo_getCapability_screen_size_normal_360_480() {
+//==== TEST: SystemInfo_getCapability_screen_size_normal_360_480
+//==== LABEL Check if getCapability() method of SystemInfo with screen.size.normal.360.480 attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/screen.size.normal.360.480");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_screen_size_normal_360_480');
+
+}
+
+function SystemInfo_getCapability_sensor_activity_recognition() {
+//==== TEST: SystemInfo_getCapability_sensor_activity_recognition
+//==== LABEL Check if getCapability() method of SystemInfo with sensor.activity_recognition attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.activity_recognition");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_sensor_activity_recognition');
+
+
+}
+
+function SystemInfo_getCapability_sensor_gesture_recognition() {
+//==== TEST: SystemInfo_getCapability_sensor_gesture_recognition
+//==== LABEL Check if getCapability() method of SystemInfo with sensor.gesture_recognition attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.gesture_recognition");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_sensor_gesture_recognition');
+
+}
+
+function SystemInfo_getCapability_sensor_gravity() {
+//==== TEST: SystemInfo_getCapability_sensor_gravity
+//==== LABEL Check if getCapability() method of SystemInfo with sensor.gravity attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.gravity");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_sensor_gravity');
+
+}
+
+function SystemInfo_getCapability_sensor_humidity() {
+//==== TEST: SystemInfo_getCapability_sensor_humidity
+//==== LABEL Check if getCapability() method of SystemInfo with sensor.humidity attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.humidity");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_sensor_humidity');
+
+}
+
+function SystemInfo_getCapability_sensor_linear_acceleration() {
+//==== TEST: SystemInfo_getCapability_sensor_linear_acceleration
+//==== LABEL Check if getCapability() method of SystemInfo with sensor.linear_acceleration attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.linear_acceleration");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_sensor_linear_acceleration');
+
+}
+
+function SystemInfo_getCapability_sensor_rotation_vector() {
+//==== TEST: SystemInfo_getCapability_sensor_rotation_vector
+//==== LABEL Check if getCapability() method of SystemInfo with sensor.rotation_vector attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.rotation_vector");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_sensor_rotation_vector');
+
+}
+
+function SystemInfo_getCapability_sensor_temperature() {
+//==== TEST: SystemInfo_getCapability_sensor_temperature
+//==== LABEL Check if getCapability() method of SystemInfo with sensor.temperature attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/sensor.temperature");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_sensor_temperature');
+
+}
+
+function SystemInfo_getCapability_build_date() {
+//==== TEST: SystemInfo_getCapability_build_date
+//==== LABEL Check if getCapability() method of SystemInfo with build.date attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/system/build.date");
+    assert_type(deviceCapability, "string", "deviceCapability should be a string");
+}, 'SystemInfo_getCapability_build_date');
+
+}
+
+function SystemInfo_getCapability_build_string() {
+//==== TEST: SystemInfo_getCapability_build_string
+//==== LABEL Check if getCapability() method of SystemInfo with build.string attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/system/build.string");
+    assert_type(deviceCapability, "string", "deviceCapability should be a string");
+}, 'SystemInfo_getCapability_build_string');
+
+}
+
+function SystemInfo_getCapability_build_time() {
+//==== TEST: SystemInfo_getCapability_build_time
+//==== LABEL Check if getCapability() method of SystemInfo with build.time attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/system/build.time");
+    assert_type(deviceCapability, "string", "deviceCapability should be a string");
+}, 'SystemInfo_getCapability_build_time');
+
+}
+
+function SystemInfo_getCapability_manufacturer() {
+//==== TEST: SystemInfo_getCapability_manufacturer
+//==== LABEL Check if getCapability() method of SystemInfo with manufacturer attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/system/manufacturer");
+    assert_type(deviceCapability, "string", "deviceCapability should be a string");
+}, 'SystemInfo_getCapability_manufacturer');
+
+}
+
+function SystemInfo_getCapability_tizenid() {
+//==== TEST: SystemInfo_getCapability_tizenid
+//==== LABEL Check if getCapability() method of SystemInfo with tizenid attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/system/tizenid");
+    assert_type(deviceCapability, "string", "deviceCapability should be a string");
+}, 'SystemInfo_getCapability_tizenid');
+
+}
+
+function SystemInfo_getCapability_model_name() {
+//==== TEST: SystemInfo_getCapability_model_name
+//==== LABEL Check if getCapability() method of SystemInfo with model_name attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/system/model_name");
+    assert_type(deviceCapability, "string", "deviceCapability should be a string");
+}, 'SystemInfo_getCapability_model_name');
+
+}
+
+function SystemInfo_getCapability_platform_communication_processor() {
+//==== TEST: SystemInfo_getCapability_platform_communication_processor
+//==== LABEL Check if getCapability() method of SystemInfo with platform.communication_processor attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/system/platform.communication_processor");
+    assert_type(deviceCapability, "string", "deviceCapability should be a string");
+}, 'SystemInfo_getCapability_platform_communication_processor');
+
+}
+
+function SystemInfo_getCapability_platform_processor() {
+//==== TEST: SystemInfo_getCapability_platform_processor
+//==== LABEL Check if getCapability() method of SystemInfo with platform.processor attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/system/platform.processor");
+    assert_type(deviceCapability, "string", "deviceCapability should be a string");
+}, 'SystemInfo_getCapability_platform_processor');
+
+}
+
+function SystemInfo_getCapability_multimedia_transcoder() {
+//==== TEST: SystemInfo_getCapability_multimedia_transcoder
+//==== LABEL Check if getCapability() method of SystemInfo with multimedia.transcoder attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/multimedia.transcoder");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_multimedia_transcoder');
+
+}
+
+function SystemInfo_getCapability_platform_core_cpu_frequency() {
+//==== TEST: SystemInfo_getCapability_platform_core_cpu_frequency
+//==== LABEL Check if getCapability() method of SystemInfo with platform.core.cpu.frequency attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/platform.core.cpu.frequency");
+    assert_type(deviceCapability, "long", "deviceCapability should be a long");
+}, 'SystemInfo_getCapability_platform_core_cpu_frequency');
+
+}
+
+function SystemInfo_getCapability_platform_version_name() {
+//==== TEST: SystemInfo_getCapability_platform_version_name
+//==== LABEL Check if getCapability() method of SystemInfo with platform.version.name attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/platform.version.name");
+    assert_type(deviceCapability, "string", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_platform_version_name');
+
+}
+
+function SystemInfoMemory_extend() {
+//==== TEST: SystemInfoMemory_extend
+//==== LABEL Check if SystemInfo::SystemInfoMemory interface can be extended with new property
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoMemory:SystemInfoMemory U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P3
+//==== TEST_CRITERIA OBX
+
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoMemory_extend', {timeout: 90000}), getPropertyValueSuccess, getPropertyValueError;
+
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        check_extensibility(property);
+        t.done();
+    });
+
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked");
+    });
+
+    tizen.systeminfo.getPropertyValue("MEMORY", getPropertyValueSuccess, getPropertyValueError);
+});
+
+}
+
+function SystemInfoMemory_getAvailableMemory() {
+//==== TEST: SystemInfoMemory_getAvailableMemory
+//==== LABEL Check if SystemInfoMemory::getAvailableMemory() method works properly
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoMemory:getAvailableMemory M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR MNA
+
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoMemory_getAvailableMemory', {timeout: 90000}), getPropertyValueSuccess, getPropertyValueError, retVal;
+
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        retVal = tizen.systeminfo.getAvailableMemory();
+        assert_type(retVal, "long", "getAvailableMemory returns wrong value");
+        t.done();
+    });
+
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked");
+    });
+
+    tizen.systeminfo.getPropertyValue("MEMORY", getPropertyValueSuccess, getPropertyValueError);
+});
+
+}
+
+function SystemInfoMemory_getAvailableMemory_exist() {
+//==== TEST: SystemInfoMemory_getAvailableMemory_exist
+//==== LABEL Check if SystemInfoMemory::getAvailableMemory() method exists
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoMemory:getAvailableMemory M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoMemory_getAvailableMemory_exist', {timeout: 90000}), getPropertyValueSuccess, getPropertyValueError;
+
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        //assert_true("getAvailableMemory" in property, "No getAvailableMemory method in SystemInfoMemory");
+        check_method_exists(tizen.systeminfo , "getAvailableMemory");
+        t.done();
+    });
+
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked");
+    });
+
+    tizen.systeminfo.getPropertyValue("MEMORY", getPropertyValueSuccess, getPropertyValueError);
+});
+
+}
+
+function SystemInfoMemory_getAvailableMemory_extra_argument() {
+//==== TEST: SystemInfoMemory_getAvailableMemory_extra_argument
+//==== LABEL Check if SystemInfoMemory::getAvailableMemory() method accepts extra argument
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoMemory:getAvailableMemory M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MNAEX
+
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoMemory_getAvailableMemory_extra_argument', {timeout: 90000}), getPropertyValueSuccess, getPropertyValueError;
+
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        checkExtraArgument(tizen.systeminfo , "getAvailableMemory");
+        t.done();
+    });
+
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked");
+    });
+
+    tizen.systeminfo.getPropertyValue("MEMORY", getPropertyValueSuccess, getPropertyValueError);
+});
+
+}
+
+function SystemInfoMemory_getTotalMemory() {
+//==== TEST: SystemInfoMemory_getTotalMemory
+//==== LABEL Check if SystemInfoMemory::getTotalMemory() method works properly
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoMemory:getTotalMemory M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR MNA
+
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoMemory_getTotalMemory', {timeout: 90000}), getPropertyValueSuccess, getPropertyValueError, retVal;
+
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        retVal = tizen.systeminfo.getTotalMemory();
+        assert_type(retVal, "long", "getTotalMemory returns wrong value");
+        t.done();
+    });
+
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked");
+    });
+
+    tizen.systeminfo.getPropertyValue("MEMORY", getPropertyValueSuccess, getPropertyValueError);
+});
+
+}
+
+function SystemInfoMemory_getTotalMemory_exist() {
+//==== TEST: SystemInfoMemory_getTotalMemory_exist
+//==== LABEL Check if SystemInfoMemory::getTotalMemory() method exists
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoMemory:getTotalMemory M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoMemory_getTotalMemory_exist', {timeout: 90000}), getPropertyValueSuccess, getPropertyValueError;
+
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        assert_true("getTotalMemory" in tizen.systeminfo , "No getTotalMemory method in SystemInfoMemory");
+        check_method_exists(tizen.systeminfo , "getTotalMemory");
+        t.done();
+    });
+
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked");
+    });
+
+    tizen.systeminfo.getPropertyValue("MEMORY", getPropertyValueSuccess, getPropertyValueError);
+});
+
+}
+
+function SystemInfoMemory_getTotalMemory_extra_argument() {
+//==== TEST: SystemInfoMemory_getTotalMemory_extra_argument
+//==== LABEL Check if SystemInfoMemory::getTotalMemory() method accepts extra argument
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoMemory:getTotalMemory M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MNAEX
+
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoMemory_getTotalMemory_extra_argument', {timeout: 90000}), getPropertyValueSuccess, getPropertyValueError;
+
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        checkExtraArgument(tizen.systeminfo , "getTotalMemory");
+        t.done();
+    });
+
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked");
+    });
+
+    tizen.systeminfo.getPropertyValue("MEMORY", getPropertyValueSuccess, getPropertyValueError);
+});
+
+}
+
+function SystemInfoMemory_status_attribute() {
+//==== TEST: SystemInfoMemory_status_attribute
+//==== LABEL Check if SystemInfoMemory::status attribute exists, has type Number and is readonly
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoMemory:status A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ARO
+
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoMemory_status_attribute', {timeout: 90000}), getPropertyValueSuccess, getPropertyValueError;
+
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        assert_own_property(property, "status", "SystemInfoMemory does not own status property.");
+        check_readonly(property, "status", property.status, "string", null);
+        t.done();
+    });
+
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked");
+    });
+
+    tizen.systeminfo.getPropertyValue("MEMORY", getPropertyValueSuccess, getPropertyValueError);
+});
+
+}
+
+function SystemInfo_addPropertyValueChangeListener_property_invalid() {
+//==== TEST: SystemInfo_addPropertyValueChangeListener_property_invalid
+//==== LABEL Check method addPropertyValueChangeListener of SystemInfo throws exception with invalid property
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:Tizen Specification:SystemInfo:SystemInfo:addPropertyValueChangeListener M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 90000});
+
+var t = async_test('SystemInfo_addPropertyValueChangeListener_property_invalid', {timeout: 90000}), i, addPropertyValueChangeListenerSuccess;
+
+t.step(function () {
+    addPropertyValueChangeListenerSuccess = t.step_func(function (property) {
+        assert_unreached("Should not be here.");
+    });
+    for (i = 0;  i < systemInfoPropertyId.length; i++) {
+        assert_throws(TYPE_MISMATCH_EXCEPTION,
+            function () {
+                tizen.systeminfo.addPropertyValueChangeListener(systemInfoPropertyId[i] + "@.**.", addPropertyValueChangeListenerSuccess);
+            }, "TypeMismatchError should be thrown");
+    }
+    t.done();
+});
+
+}
+
+function SystemInfo_getCapability_network_ethernet() {
+//==== TEST: SystemInfo_getCapability_network_ethernet
+//==== LABEL Check if getCapability() method of SystemInfo with network.ethernet attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.2.0/org.tizen.web.appprogramming/html/guide/sys_guide/systeminfo.htm
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/network.ethernet");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_network_ethernet');
+
+}
+
+function SystemInfo_getCapability_input_rotating_bezel() {
+//==== TEST: SystemInfo_getCapability_input_rotating_bezel
+//==== LABEL Check if getCapability() method of SystemInfo with input.rotating_bezel attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/input.rotating_bezel");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_input_rotating_bezel');
+
+}
+
+function SystemInfo_getCapability_screen_shape_circle() {
+//==== TEST: SystemInfo_getCapability_screen_shape_circle
+//==== LABEL Check if getCapability() method of SystemInfo with screen.shape.circle attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/screen.shape.circle");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_screen_shape_circle');
+
+}
+
+function SystemInfo_getCapability_screen_shape_rectangle() {
+//==== TEST: SystemInfo_getCapability_screen_shape_rectangle
+//==== LABEL Check if getCapability() method of SystemInfo with screen.shape.rectangle attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/screen.shape.rectangle");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_screen_shape_rectangle');
+
+}
+
+function SystemInfo_getCapability_network_internet() {
+//==== TEST: SystemInfo_getCapability_network_internet
+//==== LABEL Check if getCapability() method of SystemInfo with network.internet attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.2.0/org.tizen.web.appprogramming/html/guide/sys_guide/systeminfo.htm
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/network.internet");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_network_internet');
+
+}
+
+function SystemInfo_getCapability_network_nfc_card_emulation_hce() {
+//==== TEST: SystemInfo_getCapability_network_nfc_card_emulation_hce
+//==== LABEL Check if getCapability() method of SystemInfo with network.nfc.card_emulation.hce attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.2.0/org.tizen.web.appprogramming/html/guide/sys_guide/systeminfo.htm
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/network.nfc.card_emulation.hce");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_network_nfc_card_emulation_hce');
+
+}
+
+function SystemInfo_getCapability_network_nfc_tag() {
+//==== TEST: SystemInfo_getCapability_network_nfc_tag
+//==== LABEL Check if getCapability() method of SystemInfo with network.nfc.tag attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.2.0/org.tizen.web.appprogramming/html/guide/sys_guide/systeminfo.htm
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/network.nfc.tag");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_network_nfc_tag');
+
+}
+
+function SystemInfo_getCapability_network_nfc_p2p() {
+//==== TEST: SystemInfo_getCapability_network_nfc_p2p
+//==== LABEL Check if getCapability() method of SystemInfo with network.nfc.p2p attribute works properly
+//==== SPEC Tizen Web API:System:SystemInfo:getCapability M
+//==== SPEC_URL https://developer.tizen.org/dev-guide/2.2.0/org.tizen.web.appprogramming/html/guide/sys_guide/systeminfo.htm
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var deviceCapability = tizen.systeminfo.getCapability("http://tizen.org/feature/network.nfc.p2p");
+    assert_type(deviceCapability, "boolean", "deviceCapability should be a boolean");
+}, 'SystemInfo_getCapability_network_nfc_p2p');
+
+}
+
+function SystemInfoVideoSourceInfo_extend() {
+//==== TEST: SystemInfoVideoSource_extend
+//==== PRIORITY P3
+//==== LABEL Check if instance of SystemInfoVideoSource interface can be extended with new property
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoVideoSource:SystemInfoVideoSource U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA OBX
+
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoVideoSourceInfo_extend', {timeout: 90000}), getPropertyValueSuccess,
+    getPropertyValueError;
+
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        check_extensibility(property);
+        t.done();
+    });
+
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("VIDEOSOURCE", getPropertyValueSuccess,
+        getPropertyValueError);
+});
+
+}
+
+function SystemInfoVideoSourceInfo_notexist() {
+//==== TEST: SystemInfoVideoSourceInfo_notexist
+//==== PRIORITY P3
+//==== LABEL Check if interface SystemInfoVideoSourceInfo exists, it should not.
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoVideoSourceInfo:SystemInfoVideoSourceInfo U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("SystemInfoVideoSourceInfo");
+}, 'SystemInfoVideoSourceInfo_notexist');
+
+}
+
+function SystemInfoVideoSourceInfo_number_attribute() {
+//==== TEST: SystemInfoVideoSourceInfo_number_attribute
+//==== LABEL Check if attribute number of SystemInfoVideoSourceInfo exists, has type long and is readonly
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoVideoSourceInfo:number A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ARO
+
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoVideoSourceInfo_number_attribute', {timeout: 90000}), getPropertyValueSuccess,
+    getPropertyValueError;
+
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        check_readonly(property.disconnected[0], "number", property.disconnected[0].number,
+            "long", property.disconnected[0].number + 5);
+        t.done();
+    });
+
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("VIDEOSOURCE", getPropertyValueSuccess,
+        getPropertyValueError);
+});
+
+}
+
+function SystemInfoVideoSourceInfo_type_attribute() {
+//==== TEST: SystemInfoVideoSourceInfo_type_attribute
+//==== LABEL Check if attribute type of SystemInfoVideoSourceInfo exists, has type String and is readonly
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoVideoSourceInfo:type A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ARO AVL
+
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoVideoSourceInfo_type_attribute', {timeout: 90000}), getPropertyValueSuccess,
+    getPropertyValueError;
+
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        check_readonly(property.disconnected[0], "type", property.disconnected[0].type,
+            "string", property.disconnected[0].type + "5");
+        assert_in_array(property.disconnected[0].type, SYSTEMINFO_VIDEOSOURCE_TYPE, "Incorrect value of property.disconnected[0].type");
+        t.done();
+    });
+
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("VIDEOSOURCE", getPropertyValueSuccess,
+        getPropertyValueError);
+});
+
+}
+
+function SystemInfoVideoSource_connected_attribute() {
+//==== TEST: SystemInfoVideoSource_connected_attribute
+//==== LABEL Check if attribute connected of SystemInfoVideoSource exists, has connected array and is readonly
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoVideoSource:connected A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoVideoSource_connected_attribute', {timeout: 90000}), getPropertyValueSuccess,
+    getPropertyValueError, tmpConnected = null;
+
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        assert_own_property(property, "connected", "SystemInfoVideoSource does not own connected property.");
+        assert_type(property.connected, "array", "connected should be an array");
+        property.connected = tmpConnected;
+        assert_not_equals(property.connected, tmpConnected, "connected should not be modified");
+        t.done();
+    });
+
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("VIDEOSOURCE", getPropertyValueSuccess,
+        getPropertyValueError);
+});
+
+}
+
+function SystemInfoVideoSource_disconnected_attribute() {
+//==== TEST: SystemInfoVideoSource_disconnected_attribute
+//==== LABEL Check if attribute disconnected of SystemInfoVideoSource exists, has disconnected array and is readonly
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoVideoSource:disconnected A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoVideoSource_disconnected_attribute', {timeout: 90000}), getPropertyValueSuccess,
+    getPropertyValueError, tmpDisconnected = null;
+
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        assert_own_property(property, "disconnected", "SystemInfoVideoSource does not own disconnected property.");
+        assert_type(property.disconnected, "array", "disconnected should be an array");
+        property.disconnected = tmpDisconnected;
+        assert_not_equals(property.disconnected, tmpDisconnected, "disconnected should not be modified");
+        t.done();
+    });
+
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("VIDEOSOURCE", getPropertyValueSuccess,
+        getPropertyValueError);
+});
+
+}
+
+function SystemInfoVideoSource_extend() {
+//==== TEST: SystemInfoVideoSource_extend
+//==== PRIORITY P3
+//==== LABEL Check if instance of SystemInfoVideoSource interface can be extended with new property
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoVideoSource:SystemInfoVideoSource U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA OBX
+
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoVideoSource_extend', {timeout: 90000}), getPropertyValueSuccess,
+    getPropertyValueError;
+
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        check_extensibility(property);
+        t.done();
+    });
+
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("VIDEOSOURCE", getPropertyValueSuccess,
+        getPropertyValueError);
+});
+
+}
+
+function SystemInfoVideoSource_notexist() {
+//==== TEST: SystemInfoVideoSource_notexist
+//==== PRIORITY P3
+//==== LABEL Check if interface SystemInfoVideoSource exists, it should not.
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoVideoSource:SystemInfoVideoSource U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("SystemInfoVideoSource");
+}, 'SystemInfoVideoSource_notexist');
+
+}
+
+function SystemInfoWifiNetwork_ipAddress_attribute() {
+//==== TEST: SystemInfoWifiNetwork_ipAddress_attribute
+//==== LABEL Check if attribute ipAddress of SystemInfoWifiNetwork exists, has type DOMString and is readonly
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoWifiNetwork:ipAddress A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoWifiNetwork_ipAddress_attribute', {timeout: 90000}),
+    getPropertyValueSuccess, getPropertyValueError;
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        assert_own_property(property, "ipAddress", "SystemInfoWifiNetwork does not own ipAddress property.");
+        check_readonly(property, "ipAddress", property.ipAddress, "string", null);
+        t.done();
+    });
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("WIFI_NETWORK", getPropertyValueSuccess,
+        getPropertyValueError);
+});
+
+}
+
+function SystemInfoWifiNetwork_ipv6Address_attribute() {
+//==== TEST: SystemInfoWifiNetwork_ipv6Address_attribute
+//==== LABEL Check if attribute ipv6Address of SystemInfoWifiNetwork exists, has type DOMString and is readonly
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoWifiNetwork:ipv6Address A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoWifiNetwork_ipv6Address_attribute', {timeout: 90000}),
+    getPropertyValueSuccess, getPropertyValueError;
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        assert_own_property(property, "ipv6Address", "SystemInfoWifiNetwork does not own ipv6Address property.");
+        check_readonly(property, "ipv6Address", property.ipv6Address, "string", null);
+        t.done();
+    });
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("WIFI_NETWORK", getPropertyValueSuccess,
+        getPropertyValueError);
+});
+
+}
+
+function SystemInfoWifiNetwork_signalStrength_attribute() {
+//==== TEST: SystemInfoWifiNetwork_signalStrength_attribute
+//==== LABEL Check if attribute signalStrength of SystemInfoWifiNetwork exists, has type Number and is readonly
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoWifiNetwork:signalStrength A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO AVL
+
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoWifiNetwork_signalStrength_attribute', {timeout: 90000}),
+    getPropertyValueSuccess, getPropertyValueError;
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        assert_own_property(property, "signalStrength", "SystemInfoWifiNetwork does not own signalStrength property.");
+        check_readonly(property, "signalStrength", property.signalStrength, "number", null);
+        assert_value_in_range(0, 1, property.signalStrength, "signalStrength MUST be between 0 and 1.");
+        t.done();
+    });
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("WIFI_NETWORK", getPropertyValueSuccess,
+        getPropertyValueError);
+});
+
+}
+
+function SystemInfoWifiNetwork_ssid_attribute() {
+//==== TEST: SystemInfoWifiNetwork_ssid_attribute
+//==== LABEL Check if attribute ssid of SystemInfoWifiNetwork exists, has type DOMString and is readonly
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoWifiNetwork:ssid A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoWifiNetwork_ssid_attribute', {timeout: 90000}),
+    getPropertyValueSuccess, getPropertyValueError;
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        assert_own_property(property, "ssid", "SystemInfoWifiNetwork does not own ssid property.");
+        check_readonly(property, "ssid", property.ssid, "string", null);
+        t.done();
+    });
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("WIFI_NETWORK", getPropertyValueSuccess,
+        getPropertyValueError);
+});
+
+}
+
+function SystemInfoWifiNetwork_status_attribute() {
+//==== TEST: SystemInfoWifiNetwork_status_attribute
+//==== LABEL Check if attribute status of SystemInfoWifiNetwork exists, has type DOMString and is readonly
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoWifiNetwork:status A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO AVL
+
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoWifiNetwork_status_attribute', {timeout: 90000}),
+    getPropertyValueSuccess, getPropertyValueError;
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        assert_own_property(property, "status",
+            "SystemInfoWifiNetwork does not own status property.");
+        check_readonly(property, "status", property.status, "string", null);
+        assert_true(property.status === "ON" || property.status === "OFF",
+            "Status in not ON nor OFF");
+        t.done();
+    });
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("WIFI_NETWORK", getPropertyValueSuccess,
+        getPropertyValueError);
+});
+
+}
+
+function SystemInfoWifiNetwork_extend() {
+//==== TEST: SystemInfoWifiNetwork_extend
+//==== PRIORITY P3
+//==== LABEL Check if instance of interface SystemInfoWifiNetwork can be extended with new property
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoWifiNetwork:SystemInfoWifiNetwork U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA OBX
+
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoWifiNetwork_extend', {timeout: 90000}),
+    getPropertyValueSuccess, getPropertyValueError;
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        check_extensibility(property);
+        t.done();
+    });
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("WIFI_NETWORK", getPropertyValueSuccess,
+        getPropertyValueError);
+});
+
+}
+
+function SystemInfoPropertySuccessCallback_onsuccess_WifiNetwork() {
+//==== TEST: SystemInfoPropertySuccessCallback_onsuccess_WifiNetwork
+//==== LABEL Check if getPropertyValue('WifiNetwork', successCB, errorCB) calls successCallback + results' attributes
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoPropertySuccessCallback:onsuccess M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA CBT CBOA
+//==== ONLOAD_DELAY 90
+
+var t = async_test('SystemInfoPropertySuccessCallback_onsuccess_WifiNetwork', {timeout: 90000}),
+    getPropertyValueSuccess, getPropertyValueError;
+setup({timeout: 90000});
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (wifinetwork) {
+        assert_type(wifinetwork.status, "string", "status type check");
+        assert_type(wifinetwork.ipAddress, "string", "ipAddress type check");
+        assert_type(wifinetwork.ipv6Address, "string", "ipv6Address type check");
+        assert_type(wifinetwork.ssid, "string", "ssid type check");
+        assert_type(wifinetwork.signalStrength, "double", "signalStrength type check");
+        t.done();
+    });
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("WIFI_NETWORK", getPropertyValueSuccess,
+        getPropertyValueError);
+});
+
+}
+
+function SystemInfoWifiNetwork_macAddress_attribute() {
+//==== TEST: SystemInfoWifiNetwork_macAddress_attribute
+//==== LABEL Check if attribute macAddress of SystemInfoWifiNetwork exists, has type DOMString and is readonly
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoWifiNetwork:macAddress A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== TEST_CRITERIA AE AT ARO
+
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoWifiNetwork_macAddress_attribute', {timeout: 90000}), getPropertyValueSuccess, getPropertyValueError;
+
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        assert_own_property(property, "macAddress", "SystemInfoWifiNetwork does not own macAddress property.");
+        check_readonly(property, "macAddress", property.macAddress, "string", null);
+        t.done();
+    });
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("WIFI_NETWORK", getPropertyValueSuccess,
+        getPropertyValueError);
+});
+
+}
+
+function SystemInfoWifiNetwork_dns_attribute() {
+//==== TEST: SystemInfoWifiNetwork_dns_attribute
+//==== LABEL Check if attribute dns of SystemInfoWifiNetwork exists, has type DOMString and is readonly
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoWifiNetwork:dns A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ARO
+
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoWifiNetwork_dns_attribute', {timeout: 90000}),
+    getPropertyValueSuccess, getPropertyValueError;
+
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        check_readonly(property, "dns", property.dns, "string", property.dns + "5");
+        t.done();
+    });
+
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("WIFI_NETWORK", getPropertyValueSuccess,
+        getPropertyValueError);
+});
+
+}
+
+function SystemInfoWifiNetwork_encryptionType_attribute() {
+//==== TEST: SystemInfoWifiNetwork_encryptionType_attribute
+//==== LABEL Check if attribute encryptionType of SystemInfoWifiNetwork exists, has type DOMString and is readonly
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoWifiNetwork:encryptionType A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ARO AVL
+
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoWifiNetwork_encryptionType_attribute', {timeout: 90000}), getPropertyValueSuccess,
+    getPropertyValueError;
+
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        check_readonly(property, "encryptionType", property.encryptionType, "string", property.encryptionType + "5");
+        assert_in_array(property.encryptionType, SYSTEMINFO_WIFIENCRYPTION_TYPE, "Incorrect value of property.encryptionType");
+        t.done();
+    });
+
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("WIFI_NETWORK", getPropertyValueSuccess,
+        getPropertyValueError);
+});
+
+}
+
+function SystemInfoWifiNetwork_gateway_attribute() {
+//==== TEST: SystemInfoWifiNetwork_gateway_attribute
+//==== LABEL Check if attribute gateway of SystemInfoWifiNetwork exists, has type DOMString and is readonly
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoWifiNetwork:gateway A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ARO
+
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoWifiNetwork_gateway_attribute', {timeout: 90000}),
+    getPropertyValueSuccess, getPropertyValueError;
+
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        check_readonly(property, "gateway", property.gateway, "string", property.gateway + "5");
+        t.done();
+    });
+
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("WIFI_NETWORK", getPropertyValueSuccess,
+        getPropertyValueError);
+});
+
+}
+
+function SystemInfoWifiNetwork_ipMode_attribute() {
+//==== TEST: SystemInfoWifiNetwork_ipMode_attribute
+//==== LABEL Check if attribute ipMode of SystemInfoWifiNetwork exists, has type DOMString and is readonly
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoWifiNetwork:ipMode A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ARO AVL
+
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoWifiNetwork_ipMode_attribute', {timeout: 90000}),
+    getPropertyValueSuccess, getPropertyValueError;
+
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        check_readonly(property, "ipMode", property.ipMode, "string", property.ipMode + "5");
+        assert_in_array(property.ipMode, SYSTEMINFO_NETWORK_IPMODE, "Incorrect value of property.ipMode");
+        t.done();
+    });
+
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("WIFI_NETWORK", getPropertyValueSuccess,
+        getPropertyValueError);
+});
+
+}
+
+function SystemInfoWifiNetwork_securityMode_attribute() {
+//==== TEST: SystemInfoWifiNetwork_securityMode_attribute
+//==== LABEL Check if attribute securityMode of SystemInfoWifiNetwork exists, has type DOMString and is readonly
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoWifiNetwork:securityMode A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ARO AVL
+
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoWifiNetwork_securityMode_attribute', {timeout: 90000}),
+    getPropertyValueSuccess, getPropertyValueError;
+
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        check_readonly(property, "securityMode", property.securityMode, "string", property.securityMode + "5");
+        assert_in_array(property.securityMode, SYSTEMINFO_WIFISECURITY_MODE, "Incorrect value of property.securityMode");
+        t.done();
+    });
+
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("WIFI_NETWORK", getPropertyValueSuccess,
+        getPropertyValueError);
+});
+
+}
+
+function SystemInfoWifiNetwork_subnetMask_attribute() {
+//==== TEST: SystemInfoWifiNetwork_subnetMask_attribute
+//==== LABEL Check if attribute subnetMask of SystemInfoWifiNetwork exists, has type DOMString and is readonly
+//==== ONLOAD_DELAY 90
+//==== SPEC Tizen Web API:System:SystemInfo:SystemInfoWifiNetwork:subnetMask A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/systeminfo.html
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ARO
+
+setup({timeout: 90000});
+
+var t = async_test('SystemInfoWifiNetwork_subnetMask_attribute', {timeout: 90000}),
+    getPropertyValueSuccess, getPropertyValueError;
+
+t.step(function () {
+    getPropertyValueSuccess = t.step_func(function (property) {
+        check_readonly(property, "subnetMask", property.subnetMask, "string", property.subnetMask + "5");
+        t.done();
+    });
+
+    getPropertyValueError = t.step_func(function (error) {
+        assert_unreached("getPropertyValue() error callback invoked: name: " +
+            error.name + ", msg: " + error.message);
+    });
+
+    tizen.systeminfo.getPropertyValue("WIFI_NETWORK", getPropertyValueSuccess,
+        getPropertyValueError);
+});
+
+}
+
+
+var moduleName = "tct-systeminfo-tizen-tests";
+add_test_case(moduleName, SystemInfo_getPropertyValue_exist);
+add_test_case(moduleName, SystemInfo_getPropertyValue);
+add_test_case(moduleName, SystemInfo_addPropertyValueChangeListener_exist);
+add_test_case(moduleName, SystemInfo_SystemInfoObject_systeminfo_attribute);
+add_test_case(moduleName, SystemInfoBuild_notexist);
+add_test_case(moduleName, SystemInfoCpu_notexist);
+add_test_case(moduleName, SystemInfoDisplay_notexist);
+add_test_case(moduleName, SystemInfoLocale_notexist);
+add_test_case(moduleName, SystemInfoNetwork_notexist);
+add_test_case(moduleName, SystemInfoObject_notexist);
+add_test_case(moduleName, SystemInfoPeripheral_notexist);
+add_test_case(moduleName, SystemInfoPropertySuccessCallback_notexist);
+add_test_case(moduleName, SystemInfoProperty_notexist);
+add_test_case(moduleName, SystemInfoSIM_notexist);
+add_test_case(moduleName, SystemInfoStorageUnit_notexist);
+add_test_case(moduleName, SystemInfoStorage_notexist);
+add_test_case(moduleName, SystemInfo_notexist);
+add_test_case(moduleName, SystemInfoPropertyArraySuccessCallback_notexist);
+add_test_case(moduleName, SystemInfo_getCapability_datacontrol);
+add_test_case(moduleName, SystemInfoNetwork_extend);
+add_test_case(moduleName, SystemInfoNetwork_networkType_attribute);
+add_test_case(moduleName, SystemInfo_extend);
+add_test_case(moduleName, SystemInfoDisplay_brightness_attribute);
+add_test_case(moduleName, SystemInfoDisplay_dotsPerInchHeight_attribute);
+add_test_case(moduleName, SystemInfoDisplay_dotsPerInchWidth_attribute);
+add_test_case(moduleName, SystemInfoDisplay_physicalHeight_attribute);
+add_test_case(moduleName, SystemInfoDisplay_physicalWidth_attribute);
+add_test_case(moduleName, SystemInfoDisplay_resolutionHeight_attribute);
+add_test_case(moduleName, SystemInfoDisplay_resolutionWidth_attribute);
+add_test_case(moduleName, SystemInfoPeripheral_isVideoOutputOn_attribute);
+add_test_case(moduleName, SystemInfoCpu_load_attribute);
+add_test_case(moduleName, SystemInfoStorage_units_attribute);
+add_test_case(moduleName, SystemInfoLocale_country_attribute);
+add_test_case(moduleName, SystemInfoLocale_language_attribute);
+add_test_case(moduleName, SystemInfoCpu_extend);
+add_test_case(moduleName, SystemInfoDisplay_extend);
+add_test_case(moduleName, SystemInfoLocale_extend);
+add_test_case(moduleName, SystemInfoPeripheral_extend);
+add_test_case(moduleName, SystemInfoStorageUnit_availableCapacity_attribute);
+add_test_case(moduleName, SystemInfoStorageUnit_capacity_attribute);
+add_test_case(moduleName, SystemInfoStorageUnit_isRemovable_attribute);
+add_test_case(moduleName, SystemInfoStorageUnit_isRemoveable_attribute);
+add_test_case(moduleName, SystemInfoStorageUnit_type_attribute);
+add_test_case(moduleName, SystemInfoStorageUnit_extend);
+add_test_case(moduleName, SystemInfoBuild_extend);
+add_test_case(moduleName, SystemInfoBuild_manufacturer_attribute);
+add_test_case(moduleName, SystemInfoBuild_model_attribute);
+add_test_case(moduleName, SystemInfoStorage_extend);
+add_test_case(moduleName, SystemInfo_in_tizen);
+add_test_case(moduleName, SystemInfo_getPropertyValue_missarg);
+add_test_case(moduleName, SystemInfo_getPropertyValue_with_errorCallback);
+add_test_case(moduleName, SystemInfo_getPropertyValue_property_TypeMismatch);
+add_test_case(moduleName, SystemInfo_getPropertyValue_successCallback_invalid_cb);
+add_test_case(moduleName, SystemInfo_getPropertyValue_errorCallback_TypeMismatch);
+add_test_case(moduleName, SystemInfo_getPropertyValue_errorCallback_invalid_cb);
+add_test_case(moduleName, SystemInfo_addPropertyValueChangeListener_property_TypeMismatch);
+add_test_case(moduleName, SystemInfo_addPropertyValueChangeListener_missarg);
+add_test_case(moduleName, SystemInfo_addPropertyValueChangeListener_successCallback_TypeMismatch);
+add_test_case(moduleName, SystemInfo_addPropertyValueChangeListener_successCallback_invalid_cb);
+add_test_case(moduleName, SystemInfo_removePropertyValueChangeListener_exist);
+add_test_case(moduleName, SystemInfoPropertySuccessCallback_onsuccess);
+add_test_case(moduleName, SystemInfoPropertySuccessCallback_onsuccess_CPU);
+add_test_case(moduleName, SystemInfoDisplay_constructor_display);
+add_test_case(moduleName, SystemInfoPropertySuccessCallback_onsuccess_Storage);
+add_test_case(moduleName, SystemInfo_addPropertyValueChangeListener);
+add_test_case(moduleName, SystemInfo_addPropertyValueChangeListener_with_options);
+add_test_case(moduleName, SystemInfo_removePropertyValueChangeListener);
+add_test_case(moduleName, SystemInfo_getPropertyValue_successCallback_missarg);
+add_test_case(moduleName, SystemInfo_addPropertyValueChangeListener_successCallback_missarg);
+add_test_case(moduleName, SystemInfo_getPropertyValue_successCallback_TypeMismatch);
+add_test_case(moduleName, SystemInfoPropertySuccessCallback_onsuccess_Build);
+add_test_case(moduleName, SystemInfoPropertySuccessCallback_onsuccess_Display);
+add_test_case(moduleName, SystemInfoPropertySuccessCallback_onsuccess_Locale);
+add_test_case(moduleName, SystemInfoPropertySuccessCallback_onsuccess_Network);
+add_test_case(moduleName, SystemInfoPropertySuccessCallback_onsuccess_Peripheral);
+add_test_case(moduleName, SystemInfoBuild_buildVersion_attribute);
+add_test_case(moduleName, SystemInfo_addPropertyValueChangeListener_property_empty);
+add_test_case(moduleName, SystemInfo_removePropertyValueChangeListener_listenerId_invalid);
+add_test_case(moduleName, SystemInfoStorageUnit_isRemovable_attribute_value);
+add_test_case(moduleName, SystemInfoStorageUnit_type_attribute_value);
+add_test_case(moduleName, SystemInfo_getCapability_account);
+add_test_case(moduleName, SystemInfo_getCapability_bookmark);
+add_test_case(moduleName, SystemInfo_getCapability_calendar);
+add_test_case(moduleName, SystemInfo_getCapability_contact);
+add_test_case(moduleName, SystemInfo_getCapability_datasync);
+add_test_case(moduleName, SystemInfo_getCapability_download);
+add_test_case(moduleName, SystemInfo_getCapability_email);
+add_test_case(moduleName, SystemInfo_getCapability_network_bluetooth);
+add_test_case(moduleName, SystemInfo_getCapability_network_nfc);
+add_test_case(moduleName, SystemInfo_getCapability_network_push);
+add_test_case(moduleName, SystemInfo_getCapability_network_secure_element);
+add_test_case(moduleName, SystemInfo_getCapability_notification);
+add_test_case(moduleName, SystemInfo_getCapability_screen_height);
+add_test_case(moduleName, SystemInfo_getCapability_screen_size_normal_480_800);
+add_test_case(moduleName, SystemInfo_getCapability_screen_size_normal_720_1280);
+add_test_case(moduleName, SystemInfo_getCapability_screen_width);
+add_test_case(moduleName, SystemInfo_getCapability_sensor_accelerometer);
+add_test_case(moduleName, SystemInfo_getCapability_sensor_accelerometer_wakeup);
+add_test_case(moduleName, SystemInfo_getCapability_sensor_barometer);
+add_test_case(moduleName, SystemInfo_getCapability_sensor_barometer_wakeup);
+add_test_case(moduleName, SystemInfo_getCapability_sensor_gyroscope);
+add_test_case(moduleName, SystemInfo_getCapability_sensor_gyroscope_wakeup);
+add_test_case(moduleName, SystemInfo_getCapability_sensor_magnetometer);
+add_test_case(moduleName, SystemInfo_getCapability_sensor_magnetometer_wakeup);
+add_test_case(moduleName, SystemInfo_getCapability_sensor_photometer);
+add_test_case(moduleName, SystemInfo_getCapability_sensor_photometer_wakeup);
+add_test_case(moduleName, SystemInfo_getCapability_sensor_proximity);
+add_test_case(moduleName, SystemInfo_getCapability_sensor_proximity_wakeup);
+add_test_case(moduleName, SystemInfo_getCapability_sensor_tiltmeter);
+add_test_case(moduleName, SystemInfo_getCapability_sensor_tiltmeter_wakeup);
+add_test_case(moduleName, SystemInfo_getCapability_sensor_ultraviolet);
+add_test_case(moduleName, SystemInfo_getCapability_systemsetting);
+add_test_case(moduleName, SystemInfo_getCapability_websetting);
+add_test_case(moduleName, SystemInfo_getCapability_camera);
+add_test_case(moduleName, SystemInfo_getCapability_camera_back);
+add_test_case(moduleName, SystemInfo_getCapability_camera_back_flash);
+add_test_case(moduleName, SystemInfo_getCapability_camera_front);
+add_test_case(moduleName, SystemInfo_getCapability_camera_front_flash);
+add_test_case(moduleName, SystemInfo_getCapability_database_encryption);
+add_test_case(moduleName, SystemInfo_getCapability_fmradio);
+add_test_case(moduleName, SystemInfo_getCapability_graphics_acceleration);
+add_test_case(moduleName, SystemInfo_getCapability_input_keyboard);
+add_test_case(moduleName, SystemInfo_getCapability_input_keyboard_layout);
+add_test_case(moduleName, SystemInfo_getCapability_location);
+add_test_case(moduleName, SystemInfo_getCapability_location_gps);
+add_test_case(moduleName, SystemInfo_getCapability_location_wps);
+add_test_case(moduleName, SystemInfo_getCapability_microphone);
+add_test_case(moduleName, SystemInfo_getCapability_multi_point_touch_point_count);
+add_test_case(moduleName, SystemInfo_getCapability_multi_point_touch_pinch_zoom);
+add_test_case(moduleName, SystemInfo_getCapability_network_nfc_reserved_push);
+add_test_case(moduleName, SystemInfo_getCapability_network_wifi);
+add_test_case(moduleName, SystemInfo_getCapability_network_wifi_direct);
+add_test_case(moduleName, SystemInfo_getCapability_opengles);
+add_test_case(moduleName, SystemInfo_getCapability_opengles_texture_format);
+add_test_case(moduleName, SystemInfo_getCapability_opengles_texture_format_3dc);
+add_test_case(moduleName, SystemInfo_getCapability_opengles_texture_format_atc);
+add_test_case(moduleName, SystemInfo_getCapability_opengles_texture_format_etc);
+add_test_case(moduleName, SystemInfo_getCapability_opengles_texture_format_ptc);
+add_test_case(moduleName, SystemInfo_getCapability_opengles_texture_format_pvrtc);
+add_test_case(moduleName, SystemInfo_getCapability_opengles_texture_format_utc);
+add_test_case(moduleName, SystemInfo_getCapability_opengles_version_1_1);
+add_test_case(moduleName, SystemInfo_getCapability_opengles_version_2_0);
+add_test_case(moduleName, SystemInfo_getCapability_platform_core_cpu_arch);
+add_test_case(moduleName, SystemInfo_getCapability_platform_core_cpu_arch_armv6);
+add_test_case(moduleName, SystemInfo_getCapability_platform_core_cpu_arch_armv7);
+add_test_case(moduleName, SystemInfo_getCapability_platform_core_cpu_arch_x86);
+add_test_case(moduleName, SystemInfo_getCapability_platform_core_fpu_arch);
+add_test_case(moduleName, SystemInfo_getCapability_platform_core_fpu_arch_sse2);
+add_test_case(moduleName, SystemInfo_getCapability_platform_core_fpu_arch_sse3);
+add_test_case(moduleName, SystemInfo_getCapability_platform_core_fpu_arch_ssse3);
+add_test_case(moduleName, SystemInfo_getCapability_platform_core_fpu_arch_vfpv2);
+add_test_case(moduleName, SystemInfo_getCapability_platform_core_fpu_arch_vfpv3);
+add_test_case(moduleName, SystemInfo_getCapability_platform_native_osp_compatible);
+add_test_case(moduleName, SystemInfo_getCapability_profile);
+add_test_case(moduleName, SystemInfo_getCapability_screen_auto_rotation);
+add_test_case(moduleName, SystemInfo_getCapability_screen_output_hdmi);
+add_test_case(moduleName, SystemInfo_getCapability_screen_output_rca);
+add_test_case(moduleName, SystemInfo_getCapability_shell_appwidget);
+add_test_case(moduleName, SystemInfo_getCapability_sip_voip);
+add_test_case(moduleName, SystemInfo_getCapability_speech_recognition);
+add_test_case(moduleName, SystemInfo_getCapability_speech_synthesis);
+add_test_case(moduleName, SystemInfo_getCapability_usb_accessory);
+add_test_case(moduleName, SystemInfo_getCapability_usb_host);
+add_test_case(moduleName, SystemInfo_getCapability_vision_face_recognition);
+add_test_case(moduleName, SystemInfo_getCapability_vision_image_recognition);
+add_test_case(moduleName, SystemInfo_getCapability_vision_qrcode_generation);
+add_test_case(moduleName, SystemInfo_getCapability_vision_qrcode_recognition);
+add_test_case(moduleName, SystemInfo_getCapability_network_nfc_card_emulation);
+add_test_case(moduleName, SystemInfo_getCapability_network_telephony);
+add_test_case(moduleName, SystemInfo_getCapability_network_telephony_mms);
+add_test_case(moduleName, SystemInfo_getCapability_platform_native_api_version);
+add_test_case(moduleName, SystemInfo_getCapability_platform_core_api_version);
+add_test_case(moduleName, SystemInfo_getCapability_platform_version);
+add_test_case(moduleName, SystemInfo_getCapability_platform_web_api_version);
+add_test_case(moduleName, SystemInfo_getCapability_screen_size_normal_1080_1920);
+add_test_case(moduleName, SystemInfo_getCapability_screen_size_normal_600_1024);
+add_test_case(moduleName, SystemInfo_getCapability_screen_size_normal_540_960);
+add_test_case(moduleName, SystemInfo_getCapability_screen_size_normal_320_480);
+add_test_case(moduleName, SystemInfo_getCapability_screen_size_normal_320_320);
+add_test_case(moduleName, SystemInfo_getCapability_screen_size_normal_240_400);
+add_test_case(moduleName, SystemInfo_getCapability_screen_size_normal);
+add_test_case(moduleName, SystemInfo_getCapability_screen_dpi);
+add_test_case(moduleName, SystemInfo_getCapability_screen_coordinate_system_size_normal);
+add_test_case(moduleName, SystemInfo_getCapability_screen_coordinate_system_size_large);
+add_test_case(moduleName, SystemInfo_getCapability_screen_bpp);
+add_test_case(moduleName, SystemInfo_getCapability_sensor_heart_rate_monitor);
+add_test_case(moduleName, SystemInfo_getCapability_sensor_pedometer);
+add_test_case(moduleName, SystemInfo_getCapability_sensor_wrist_up);
+add_test_case(moduleName, SystemInfo_getCapability_exist);
+add_test_case(moduleName, SystemInfo_getCapability_screen);
+add_test_case(moduleName, SystemInfo_getCapability_systemsetting_home_screen);
+add_test_case(moduleName, SystemInfo_getCapability_systemsetting_lock_screen);
+add_test_case(moduleName, SystemInfo_getCapability_systemsetting_incoming_call);
+add_test_case(moduleName, SystemInfo_getCapability_systemsetting_notification_email);
+add_test_case(moduleName, SystemInfo_getCapability_network_bluetooth_always_on);
+add_test_case(moduleName, SystemInfo_getCapability_network_bluetooth_health);
+add_test_case(moduleName, SystemInfo_getCapability_platform_name);
+add_test_case(moduleName, SystemInfo_addPropertyValueChangeListener_errorCallback_TypeMismatch);
+add_test_case(moduleName, SystemInfo_getCapability_archive);
+add_test_case(moduleName, SystemInfo_getCapability_badge);
+add_test_case(moduleName, SystemInfo_getCapability_exif);
+add_test_case(moduleName, SystemInfo_getCapability_led);
+add_test_case(moduleName, SystemInfo_getCapability_network_bluetooth_audio_call);
+add_test_case(moduleName, SystemInfo_getCapability_network_bluetooth_audio_media);
+add_test_case(moduleName, SystemInfo_getCapability_network_bluetooth_hid);
+add_test_case(moduleName, SystemInfo_getCapability_network_bluetooth_le);
+add_test_case(moduleName, SystemInfo_getCapability_network_bluetooth_opp);
+add_test_case(moduleName, SystemInfo_getCapability_screen_size_all);
+add_test_case(moduleName, SystemInfo_getCapability_screen_size_large);
+add_test_case(moduleName, SystemInfo_getCapability_screen_size_normal_360_480);
+add_test_case(moduleName, SystemInfo_getCapability_sensor_activity_recognition);
+add_test_case(moduleName, SystemInfo_getCapability_sensor_gesture_recognition);
+add_test_case(moduleName, SystemInfo_getCapability_sensor_gravity);
+add_test_case(moduleName, SystemInfo_getCapability_sensor_humidity);
+add_test_case(moduleName, SystemInfo_getCapability_sensor_linear_acceleration);
+add_test_case(moduleName, SystemInfo_getCapability_sensor_rotation_vector);
+add_test_case(moduleName, SystemInfo_getCapability_sensor_temperature);
+add_test_case(moduleName, SystemInfo_getCapability_build_date);
+add_test_case(moduleName, SystemInfo_getCapability_build_string);
+add_test_case(moduleName, SystemInfo_getCapability_build_time);
+add_test_case(moduleName, SystemInfo_getCapability_manufacturer);
+add_test_case(moduleName, SystemInfo_getCapability_tizenid);
+add_test_case(moduleName, SystemInfo_getCapability_model_name);
+add_test_case(moduleName, SystemInfo_getCapability_platform_communication_processor);
+add_test_case(moduleName, SystemInfo_getCapability_platform_processor);
+add_test_case(moduleName, SystemInfo_getCapability_multimedia_transcoder);
+add_test_case(moduleName, SystemInfo_getCapability_platform_core_cpu_frequency);
+add_test_case(moduleName, SystemInfo_getCapability_platform_version_name);
+add_test_case(moduleName, SystemInfoMemory_extend);
+add_test_case(moduleName, SystemInfoMemory_getAvailableMemory);
+add_test_case(moduleName, SystemInfoMemory_getAvailableMemory_exist);
+add_test_case(moduleName, SystemInfoMemory_getAvailableMemory_extra_argument);
+add_test_case(moduleName, SystemInfoMemory_getTotalMemory);
+add_test_case(moduleName, SystemInfoMemory_getTotalMemory_exist);
+add_test_case(moduleName, SystemInfoMemory_getTotalMemory_extra_argument);
+add_test_case(moduleName, SystemInfoMemory_status_attribute);
+add_test_case(moduleName, SystemInfo_addPropertyValueChangeListener_property_invalid);
+add_test_case(moduleName, SystemInfo_getCapability_network_ethernet);
+add_test_case(moduleName, SystemInfo_getCapability_input_rotating_bezel);
+add_test_case(moduleName, SystemInfo_getCapability_screen_shape_circle);
+add_test_case(moduleName, SystemInfo_getCapability_screen_shape_rectangle);
+add_test_case(moduleName, SystemInfo_getCapability_network_internet);
+add_test_case(moduleName, SystemInfo_getCapability_network_nfc_card_emulation_hce);
+add_test_case(moduleName, SystemInfo_getCapability_network_nfc_tag);
+add_test_case(moduleName, SystemInfo_getCapability_network_nfc_p2p);
+/* not supported in tizen 2.3.1
+add_test_case(moduleName, SystemInfoVideoSourceInfo_extend);
+add_test_case(moduleName, SystemInfoVideoSourceInfo_notexist);
+add_test_case(moduleName, SystemInfoVideoSourceInfo_number_attribute);
+add_test_case(moduleName, SystemInfoVideoSourceInfo_type_attribute);
+add_test_case(moduleName, SystemInfoVideoSource_connected_attribute);
+add_test_case(moduleName, SystemInfoVideoSource_disconnected_attribute);
+add_test_case(moduleName, SystemInfoVideoSource_extend);
+add_test_case(moduleName, SystemInfoVideoSource_notexist);
+*/
+if(tizen.systeminfo.getCapability("http://tizen.org/feature/network.wifi")){
+add_test_case(moduleName, SystemInfoWifiNetwork_ipAddress_attribute);
+add_test_case(moduleName, SystemInfoWifiNetwork_ipv6Address_attribute);
+add_test_case(moduleName, SystemInfoWifiNetwork_signalStrength_attribute);
+add_test_case(moduleName, SystemInfoWifiNetwork_ssid_attribute);
+add_test_case(moduleName, SystemInfoWifiNetwork_status_attribute);
+add_test_case(moduleName, SystemInfoWifiNetwork_extend);
+add_test_case(moduleName, SystemInfoPropertySuccessCallback_onsuccess_WifiNetwork);
+add_test_case(moduleName, SystemInfoWifiNetwork_macAddress_attribute);
+add_test_case(moduleName, SystemInfoWifiNetwork_notexist);
+}
+/* not supported in tizen 2.3.1
+add_test_case(moduleName, SystemInfoWifiNetwork_dns_attribute);
+add_test_case(moduleName, SystemInfoWifiNetwork_encryptionType_attribute);
+add_test_case(moduleName, SystemInfoWifiNetwork_gateway_attribute);
+add_test_case(moduleName, SystemInfoWifiNetwork_ipMode_attribute);
+add_test_case(moduleName, SystemInfoWifiNetwork_securityMode_attribute);
+add_test_case(moduleName, SystemInfoWifiNetwork_subnetMask_attribute);
+*/
diff --git a/webWidgetTCT_device/test/tct/tests/TestTime.js b/webWidgetTCT_device/test/tct/tests/TestTime.js
new file mode 100755 (executable)
index 0000000..598d0f6
--- /dev/null
@@ -0,0 +1,7806 @@
+/*
+Copyright (c) 2012 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+* Redistributions of works must retain the original copyright notice, this list
+  of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the original copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+* Neither the name of Intel Corporation nor the names of its contributors
+  may be used to endorse or promote products derived from this work without
+  specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Authors:
+
+
+*/
+
+var NOT_SUPPORTED_ERR     = "NotSupportedError";
+var UNKNOWN_ERR           = "UnknownError";
+var TYPE_MISMATCH_ERR     = "TypeMismatchError";
+var INVALID_VALUES_ERR    = "InvalidValuesError";
+var NOT_FOUND_ERR         = "NotFoundError";
+var PERMISSION_DENIED_ERR = "SecurityError";
+var IO_ERR                = "IOError";
+var ERROR_STR             = "Error";
+var ERROR_NUM             = 3;
+
+var expected_year         = 2011;
+var expected_month        = 10;
+var expected_date         = 11;
+var expected_hours        = 4;
+var expected_minutes      = 55;
+var expected_seconds      = 54;
+var expected_milliseconds = 12;
+var expected_time_zone    = "Asia/Seoul";//GMT+9
+var expected_time_zone_offset = 9;
+
+var date = new tizen.TZDate(
+    expected_year,          //year
+    expected_month,         //month
+    expected_date,          //day
+    expected_hours,         //hours
+    expected_minutes,       //minutes
+    expected_seconds,       //seconds
+    expected_milliseconds,  //milliseconds
+    expected_time_zone      //timeZone
+);
+
+var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+
+function Time_TZDate_toLocaleDateString() {
+//==== TEST: Time_TZDate_toLocaleDateString
+//==== LABEL Check if TZDate::ToLocaleDateString() method returns string
+//==== SPEC Tizen Web API:System:Time:TZDate:toLocaleDateString M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var tz = tizen.time.getCurrentDateTime(), ldateS;
+    ldateS = tz.toLocaleDateString();
+    assert_not_equals(ldateS, null, "null check");
+    assert_type(ldateS, "string", "type check");
+}, 'Time_TZDate_toLocaleDateString');
+
+}
+
+function Time_TZDate_getUTCSeconds() {
+//==== TEST: Time_TZDate_getUTCSeconds
+//==== LABEL Check if TZDate.getUTCSeconds() works properly
+//==== SPEC Tizen Web API:System:Time:TZDate:getUTCSeconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var date1 = new Date(),
+        secs = tizen.time.getCurrentDateTime().getUTCSeconds(),
+        date2 = new Date();
+    assert_true(secs === date1.getUTCSeconds() || secs === date2.getUTCSeconds(), "seconds check");
+}, 'Time_TZDate_getUTCSeconds');
+
+}
+
+function Time_TZDate_getHours() {
+//==== TEST: Time_TZDate_getHours
+//==== LABEL Check if TZDate.getHours() works properly
+//==== SPEC Tizen Web API:System:Time:TZDate:getHours M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var myDate = new Date(), expHours, hours;
+
+    expHours = myDate.getHours();
+    hours = tizen.time.getCurrentDateTime().getHours();
+    assert_equals(hours, expHours, "hours check");
+}, 'Time_TZDate_getHours');
+
+}
+
+function Time_TZDate_getUTCMilliseconds() {
+//==== TEST: Time_TZDate_getUTCMilliseconds
+//==== LABEL Check if TZDate.getUTCMilliseconds() works properly
+//==== SPEC Tizen Web API:System:Time:TZDate:getUTCMilliseconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var myDate = new Date(), exputcMs, utcMs;
+
+    exputcMs = myDate.getUTCMilliseconds();
+    utcMs = tizen.time.getCurrentDateTime().getUTCMilliseconds();
+
+    assert_approx_equals(utcMs, exputcMs, 10, "milliseconds check");
+}, 'Time_TZDate_getUTCMilliseconds');
+
+}
+
+function Time_TZDate_toUTC() {
+//==== TEST: Time_TZDate_toUTC
+//==== LABEL Check if TZDate::toUTC() method returns string
+//==== SPEC Tizen Web API:System:Time:TZDate:toUTC M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var utz, utzd, utzy, utzm, myDate, expUd, expUy, expUm;
+    utz = tizen.time.getCurrentDateTime().toUTC();
+    utzd = utz.getUTCDate();
+    utzy = utz.getUTCFullYear();
+    utzm = utz.getUTCMonth();
+    myDate = new Date();
+    expUd = myDate.getUTCDate();
+    expUy = myDate.getUTCFullYear();
+    expUm = myDate.getUTCMonth();
+    assert_equals(utzd, expUd, "day check");
+    assert_equals(utzy, expUy, "year check");
+    assert_equals(utzm, expUm, "month check");
+    assert_type(utzd, "long", "type getUTCDate check");
+    assert_type(utzy, "long", "type getUTCFullYear check");
+    assert_type(utzm, "long", "type getUTCMonth check");
+}, 'Time_TZDate_toUTC');
+
+}
+
+function Time_TZDate_setSeconds_normal() {
+//==== TEST: Time_TZDate_setSeconds_normal
+//==== LABEL Check if TZDate.setSeconds() works properly
+//==== SPEC Tizen Web API:System:Time:TZDate:setSeconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+test(function () {
+    var setSecs = 35,
+        dt = tizen.time.getCurrentDateTime(),
+        secsAfterSet;
+
+    dt.setSeconds(setSecs);
+    secsAfterSet = dt.getSeconds();
+
+    assert_equals(secsAfterSet, setSecs, "normal secs could be set correctly");
+}, 'Time_TZDate_setSeconds_normal');
+
+}
+
+function Time_TZDate_earlierThan_true() {
+//==== TEST: Time_TZDate_earlierThan_true
+//==== LABEL Check if TZDate.earlierThan() with future date returns true
+//==== SPEC Tizen Web API:System:Time:TZDate:earlierThan M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA MR
+test(function () {
+    var tzOther = tizen.time.getCurrentDateTime(), res;
+
+    tzOther.setFullYear(tzOther.getFullYear() + 1);
+    res = tizen.time.getCurrentDateTime().earlierThan(tzOther);
+
+    assert_equals(res, true, "TZDate is earlier than another, result should be true");
+}, 'Time_TZDate_earlierThan_true');
+
+}
+
+function Time_TZDate_difference_compareWithEqual() {
+//==== TEST: Time_TZDate_difference_compareWithEqual
+//==== LABEL Check if TZDate.difference() with equal dates works
+//==== SPEC Tizen Web API:System:Time:TZDate:difference M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+test(function () {
+    var tzEqual = tizen.time.getCurrentDateTime(),
+        tzEqual1, diff;
+
+    tzEqual1 = tzEqual;
+    diff = tzEqual1.difference(tzEqual);
+    assert_equals(diff.length, 0, "time should be equal");
+}, 'Time_TZDate_difference_compareWithEqual');
+
+}
+
+function Time_TZDate_setMilliseconds_normal() {
+//==== TEST: Time_TZDate_setMilliseconds_normal
+//==== LABEL Check if TZDate.setMilliseconds() works properly
+//==== SPEC Tizen Web API:System:Time:TZDate:setMilliseconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+test(function () {
+    var setMs = 555,
+        dt = tizen.time.getCurrentDateTime(),
+        msAfterSet;
+
+    dt.setMilliseconds(setMs);
+    msAfterSet = dt.getMilliseconds();
+    assert_approx_equals(msAfterSet, setMs, 10, "getMilliseconds()");
+}, 'Time_TZDate_setMilliseconds_normal');
+
+}
+
+function Time_TZDate_getUTCFullYear() {
+//==== TEST: Time_TZDate_getUTCFullYear
+//==== LABEL Check if TZDate.getUTCFullYear() works properly
+//==== SPEC Tizen Web API:System:Time:TZDate:getUTCFullYear M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var myDate = new Date(), expUTCFullYear, utcFullYear;
+
+    expUTCFullYear = myDate.getUTCFullYear();
+    utcFullYear = tizen.time.getCurrentDateTime().getUTCFullYear();
+
+    assert_equals(utcFullYear, expUTCFullYear, "fullYear check");
+}, 'Time_TZDate_getUTCFullYear');
+
+}
+
+function Time_TZDate_secondsFromUTC() {
+//==== TEST: Time_TZDate_secondsFromUTC
+//==== LABEL Check if TZDate.secondsFromUTC works properly
+//==== SPEC Tizen Web API:System:Time:TZDate:secondsFromUTC M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var offset = tizen.time.getCurrentDateTime().secondsFromUTC(),
+        myDate = new Date(), expOffset;
+
+    expOffset = myDate.getTimezoneOffset() * 60;
+    assert_equals(offset, expOffset, "secondsFromUTC check");
+}, 'Time_TZDate_secondsFromUTC');
+
+}
+
+function Time_TZDate_toLocaleString() {
+//==== TEST: Time_TZDate_toLocaleString
+//==== LABEL Check if TZDate::ToLocaleString() method returns string
+//==== SPEC Tizen Web API:System:Time:TZDate:toLocaleString M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var tz = tizen.time.getCurrentDateTime(), localS;
+    localS = tz.toLocaleString();
+    assert_not_equals(localS, null, "null check");
+    assert_type(localS, "string", "type check");
+}, 'Time_TZDate_toLocaleString');
+
+}
+
+function Time_TZDate_setUTCFullYear_normal() {
+//==== TEST: Time_TZDate_setUTCFullYear_normal
+//==== LABEL Check if TZDate.setUTCFullYear() works properly
+//==== SPEC Tizen Web API:System:Time:TZDate:setUTCFullYear M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+test(function () {
+    var setUTCFullYear = 2008,
+        dt = tizen.time.getCurrentDateTime(),
+        yearAfterSet;
+
+    dt.setUTCFullYear(setUTCFullYear);
+    yearAfterSet = dt.getUTCFullYear();
+
+    assert_equals(yearAfterSet, setUTCFullYear, "years should be equal");
+}, 'Time_TZDate_setUTCFullYear_normal');
+
+}
+
+function Time_TZDate_setFullYear_normal() {
+//==== TEST: Time_TZDate_setFullYear_normal
+//==== LABEL Check if TZDate.setFullYear_normal() works properly
+//==== SPEC Tizen Web API:System:Time:TZDate:setFullYear M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+test(function () {
+    var setFullYear = 2008,
+        tizenDate = tizen.time.getCurrentDateTime(),
+        yearAfterSet;
+
+    tizenDate.setFullYear(setFullYear);
+    yearAfterSet = tizenDate.getFullYear();
+
+    assert_equals(yearAfterSet, setFullYear, "year after set should be equal to set one");
+}, 'Time_TZDate_setFullYear_normal');
+
+}
+
+function Time_TZDate_getMinutes() {
+//==== TEST: Time_TZDate_getMinutes
+//==== LABEL Check if TZDate.getMinutes() works properly
+//==== SPEC Tizen Web API:System:Time:TZDate:getMinutes M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var myDate = new Date(), expMins, mins;
+
+    expMins = myDate.getMinutes();
+    mins = tizen.time.getCurrentDateTime().getMinutes();
+    assert_equals(mins, expMins, "minutes check");
+}, 'Time_TZDate_getMinutes');
+
+}
+
+function Time_TZDate_getPreviousDSTTransition() {
+//==== TEST: Time_TZDate_getPreviousDSTTransition
+//==== LABEL Check if TZDate.getPreviousDSTTransition() works properly
+//==== PRIORITY P1
+//==== SPEC Tizen Web API:System:Time:TZDate:getPreviousDSTTransition M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var td = new tizen.TZDate(2012, 12, 1, 1, 1, 1, 1, "Europe/Berlin"),
+        prevTr, day, month;
+    prevTr = td.getPreviousDSTTransition();
+    day = prevTr.getDate();
+    month = prevTr.getMonth();
+    assert_equals(month, 9, "month check");
+    assert_equals(day, 28, "day check");
+}, 'Time_TZDate_getPreviousDSTTransition');
+
+}
+
+function Time_TZDate_setDate_normal() {
+//==== TEST: Time_TZDate_setDate_normal
+//==== LABEL Check if TZDate.setDate() works properly
+//==== SPEC Tizen Web API:System:Time:TZDate:setDate M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+test(function () {
+    var tz, setDate, expd;
+
+    tz = tizen.time.getCurrentDateTime();
+    setDate = 20;
+    tz.setDate(setDate);
+    expd = tz.getDate();
+
+    assert_equals(expd, setDate, "expd check");
+}, 'Time_TZDate_setDate_normal');
+
+}
+
+function Time_TZDate_setMinutes_normal() {
+//==== TEST: Time_TZDate_setMinutes_normal
+//==== LABEL Check if TZDate.setMinutes() works properly
+//==== SPEC Tizen Web API:System:Time:TZDate:setMinutes M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+test(function () {
+    var setMins = 29,
+        dt = tizen.time.getCurrentDateTime(),
+        minsAfterSet;
+
+    dt.setMinutes(setMins);
+    minsAfterSet = dt.getMinutes();
+
+    assert_equals(minsAfterSet, setMins, "minutes should be equals");
+}, 'Time_TZDate_setMinutes_normal');
+
+}
+
+function Time_TZDate_getTimezoneAbbreviation_summerMonth() {
+//==== TEST: Time_TZDate_getTimezoneAbbreviation_summerMonth
+//==== LABEL Check if TZDate.getTimezoneAbbreviation() works properly
+//==== SPEC Tizen Web API:System:Time:TZDate:getTimezoneAbbreviation M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var td = new tizen.TZDate(2013, 8, 1, 1, 1, 1, 1, "America/New_York");
+    assert_equals(td.getTimezoneAbbreviation(), "EDT", "timezoneAbbreviation check");
+}, 'Time_TZDate_getTimezoneAbbreviation_summerMonth');
+
+}
+
+function Time_TZDate_setUTCMilliseconds_normal() {
+//==== TEST: Time_TZDate_setUTCMilliseconds_normal
+//==== LABEL Check if TZDate.setUTCMilliseconds() works properly
+//==== SPEC Tizen Web API:System:Time:TZDate:setUTCMilliseconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+test(function () {
+    var setUTCMs = 1,
+        dt = tizen.time.getCurrentDateTime(),
+        utcMsAfterSet;
+
+    dt.setUTCMilliseconds(setUTCMs);
+    utcMsAfterSet = dt.getUTCMilliseconds();
+
+    assert_equals(utcMsAfterSet, setUTCMs, "getUTCMilliseconds check");
+}, 'Time_TZDate_setUTCMilliseconds_normal');
+
+}
+
+function Time_TZDate_toDateString() {
+//==== TEST: Time_TZDate_toDateString
+//==== LABEL Check if TZDate::ToDateString() method returns string
+//==== PRIORITY P0
+//==== SPEC Tizen Web API:System:Time:TZDate:toDateString M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var tz = tizen.time.getCurrentDateTime(), dateS;
+    dateS = tz.toDateString();
+    assert_not_equals(dateS, null, "null check");
+    assert_type(dateS, "string", "type check");
+}, 'Time_TZDate_toDateString');
+
+}
+
+function Time_TZDate_getTimezone() {
+//==== TEST: Time_TZDate_getTimezone
+//==== LABEL Check if TZDate.getTimezone() works properly
+//==== SPEC Tizen Web API:System:Time:TZDate:getTimezone M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var tzs = tizen.time.getCurrentDateTime().getTimezone();
+    assert_regexp_match(tzs, /(.+?)\/(.+?)/, "timezone check");
+}, 'Time_TZDate_getTimezone');
+
+}
+
+function Time_TZDate_toTimeString() {
+//==== TEST: Time_TZDate_toTimeString
+//==== LABEL Check if TZDate::ToTimeString() method returns string
+//==== SPEC Tizen Web API:System:Time:TZDate:toTimeString M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var tz = tizen.time.getCurrentDateTime(), timeS;
+    timeS = tz.toTimeString();
+    assert_not_equals(timeS, null, "null check");
+    assert_type(timeS, "string", "type check");
+}, 'Time_TZDate_toTimeString');
+
+}
+
+function Time_TZDate_toString() {
+//==== TEST: Time_TZDate_toString
+//==== LABEL Check if TZDate::ToString() method returns string
+//==== SPEC Tizen Web API:System:Time:TZDate:toString M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var tz = tizen.time.getCurrentDateTime(), toS;
+    toS = tz.toString();
+    assert_not_equals(toS, null, "null check");
+    assert_type(toS, "string", "type check");
+}, 'Time_TZDate_toString');
+
+}
+
+function Time_TZDate_getUTCHours() {
+//==== TEST: Time_TZDate_getUTCHours
+//==== LABEL Check if TZDate.getUTCHours() works properly
+//==== SPEC Tizen Web API:System:Time:TZDate:getUTCHours M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var myDate = new Date(), expUTCHours, utcHours;
+
+    expUTCHours = myDate.getUTCHours();
+    utcHours = tizen.time.getCurrentDateTime().getUTCHours();
+
+    assert_equals(utcHours, expUTCHours, "hours check");
+}, 'Time_TZDate_getUTCHours');
+
+}
+
+function Time_TZDate_setUTCMinutes_normal() {
+//==== TEST: Time_TZDate_setUTCMinutes_normal
+//==== LABEL Check if TZDate.setUTCMinutes() works properly
+//==== SPEC Tizen Web API:System:Time:TZDate:setUTCMinutes M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+test(function () {
+    var setUTCMins = 31,
+        dt = tizen.time.getCurrentDateTime(),
+        utcMinsAfterSet;
+
+    dt.setUTCMinutes(setUTCMins);
+    utcMinsAfterSet  = dt.getUTCMinutes();
+
+    assert_equals(utcMinsAfterSet, setUTCMins, "minutes should be equal");
+}, 'Time_TZDate_setUTCMinutes_normal');
+
+}
+
+function Time_TZDate_getDay() {
+//==== TEST: Time_TZDate_getDay
+//==== LABEL Check if TZDate.getDay() works properly
+//==== SPEC Tizen Web API:System:Time:TZDate:getDay M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var myDate = new Date(),
+        expDay, day;
+
+    expDay = myDate.getDay();
+    day = tizen.time.getCurrentDateTime().getDay();
+    assert_equals(day, expDay, "day check");
+}, 'Time_TZDate_getDay');
+
+}
+
+function Time_TZDate_setUTCMonth_normal() {
+//==== TEST: Time_TZDate_setUTCMonth_normal
+//==== LABEL Check if TZDate.setUTCMonth() works properly
+//==== SPEC Tizen Web API:System:Time:TZDate:setUTCMonth M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+test(function () {
+    var setUTCMonth = 6, dt, utcMonthAfterSet;
+    dt = tizen.time.getCurrentDateTime();
+    dt.setUTCMonth(setUTCMonth);
+    utcMonthAfterSet = dt.getUTCMonth();
+    assert_equals(utcMonthAfterSet, setUTCMonth, "normal UTCMonth could be set correctly");
+}, 'Time_TZDate_setUTCMonth_normal');
+
+}
+
+function Time_TZDate_getUTCDay() {
+//==== TEST: Time_TZDate_getUTCDay
+//==== LABEL Check if TZDate.getUTCDay() works properly
+//==== SPEC Tizen Web API:System:Time:TZDate:getUTCDay M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var myDate = new Date(), exputcday, utcday;
+
+    exputcday = myDate.getUTCDay();
+    utcday = tizen.time.getCurrentDateTime().getUTCDay();
+
+    assert_equals(utcday, exputcday, "day check");
+}, 'Time_TZDate_getUTCDay');
+
+}
+
+function Time_TZDate_getMilliseconds() {
+//==== TEST: Time_TZDate_getMilliseconds
+//==== LABEL Check if TZDate.getMilliseconds() works properly
+//==== SPEC Tizen Web API:System:Time:TZDate:getMilliseconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var myDate = new Date(), expMs, ms;
+
+    expMs = myDate.getMilliseconds();
+    ms = tizen.time.getCurrentDateTime().getMilliseconds();
+    assert_approx_equals(ms, expMs, 10, "getMilliseconds()");
+}, 'Time_TZDate_getMilliseconds');
+
+}
+
+function Time_TZDate_getUTCMinutes() {
+//==== TEST: Time_TZDate_getUTCMinutes
+//==== LABEL Check if TZDate.getUTCMinutes() works properly
+//==== SPEC Tizen Web API:System:Time:TZDate:getUTCMinutes M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var myDate = new Date(), exputcMins, utcMins;
+
+    exputcMins = myDate.getUTCMinutes();
+    utcMins = tizen.time.getCurrentDateTime().getUTCMinutes();
+
+    assert_equals(utcMins, exputcMins, "minutes check");
+}, 'Time_TZDate_getUTCMinutes');
+
+}
+
+function Time_TZDate_laterThan_true() {
+//==== TEST: Time_TZDate_laterThan_true
+//==== LABEL Check if TZDate.laterThan() works properly
+//==== SPEC Tizen Web API:System:Time:TZDate:laterThan M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA MR
+test(function () {
+    var tzOther = tizen.time.getCurrentDateTime(),
+        tzyCur, tzyOther, res;
+
+    tzyCur = tzOther.getFullYear();
+    tzOther.setFullYear(tzOther.getFullYear() - 1);
+    tzyOther = tzOther.getFullYear();
+    res = tizen.time.getCurrentDateTime().laterThan(tzOther);
+
+    assert_equals(tzyCur-1, tzyOther, "laterThan check");
+    assert_true(res, "laterThan check");
+}, 'Time_TZDate_laterThan_true');
+
+}
+
+function Time_TZDate_equalsTo_equal() {
+//==== TEST: Time_TZDate_equalsTo_equal
+//==== LABEL Check if TZDate.equalsTo() called with equal object returns true
+//==== PRIORITY P1
+//==== SPEC Tizen Web API:System:Time:TZDate:equalsTo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA MR
+test(function () {
+    var tzEqual, tzEqual1, res;
+
+    tzEqual = tizen.time.getCurrentDateTime();
+    tzEqual1 = tzEqual;
+    res = tzEqual1.equalsTo(tzEqual);
+    assert_equals(res, true, "Two same tzDate obj compare result should be true");
+}, 'Time_TZDate_equalsTo_equal');
+
+}
+
+function Time_TZDate_getMonth() {
+//==== TEST: Time_TZDate_getMonth
+//==== LABEL Check if TZDate.getMonth() works properly
+//==== SPEC Tizen Web API:System:Time:TZDate:getMonth M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var myDate = new Date(), expMonth, month;
+    expMonth = myDate.getMonth();
+    month = tizen.time.getCurrentDateTime().getMonth();
+    assert_equals(month, expMonth, "month check");
+}, 'Time_TZDate_getMonth');
+
+}
+
+function Time_TZDate_getNextDSTTransition() {
+//==== TEST: Time_TZDate_getNextDSTTransition
+//==== LABEL Check if TZDate.getNextDSSTTransition() works properly
+//==== PRIORITY P1
+//==== SPEC Tizen Web API:System:Time:TZDate:getNextDSTTransition M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var td = new tizen.TZDate(2012, 1, 1, 1, 1, 1, 1, "Europe/Berlin"),
+        nextTr, day, month;
+
+    nextTr = td.getNextDSTTransition();
+    day = nextTr.getDate();
+    month = nextTr.getMonth();
+    assert_equals(month, 2, "month check");
+    assert_equals(day, 25, "day check");
+}, 'Time_TZDate_getNextDSTTransition');
+
+}
+
+function Time_TZDate_getUTCMonth() {
+//==== TEST: Time_TZDate_getUTCMonth
+//==== LABEL Check if TZDate.getUTCMonth() works properly
+//==== SPEC Tizen Web API:System:Time:TZDate:getUTCMonth M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var myDate = new Date(), expUTCMonth, utcMonth;
+
+    expUTCMonth = myDate.getUTCMonth();
+    utcMonth = tizen.time.getCurrentDateTime().getUTCMonth();
+
+    assert_equals(utcMonth, expUTCMonth, "month check");
+}, 'Time_TZDate_getUTCMonth');
+
+}
+
+function Time_TZDate_toTimezone() {
+//==== TEST: Time_TZDate_toTimezone
+//==== LABEL Check if TZDate::toTimezone() method returns string
+//==== SPEC Tizen Web API:System:Time:TZDate:toTimezone M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA MR
+test(function () {
+    var tzID = "Asia/Shanghai", tz;
+    tz = tizen.time.getCurrentDateTime().toTimezone(tzID);
+    assert_equals(tz.getTimezone(), tzID, "check getTimezone");
+    assert_type(tz.getTimezone(), "string", "type check");
+}, 'Time_TZDate_toTimezone');
+
+}
+
+function Time_TZDate_isDST_true() {
+//==== TEST: Time_TZDate_isDST_true
+//==== LABEL Check if TZDate.isDST() returns true on DST date
+//==== SPEC Tizen Web API:System:Time:TZDate:isDST M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var td = new tizen.TZDate(2012, 5, 1, 1, 1, 1, 1, "Europe/Berlin");
+    assert_true(td.isDST(), "isDST check");
+}, 'Time_TZDate_isDST_true');
+
+}
+
+function Time_TZDate_setUTCSeconds_normal() {
+//==== TEST: Time_TZDate_setUTCSeconds_normal
+//==== LABEL Check if TZDate.setUTCSeconds() works properly
+//==== SPEC Tizen Web API:System:Time:TZDate:setUTCSeconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+test(function () {
+    var setUTCSecs = 35, dt, utcSecsAfterSet;
+    dt = tizen.time.getCurrentDateTime();
+    dt.setUTCSeconds(setUTCSecs);
+    utcSecsAfterSet = dt.getUTCSeconds();
+    assert_equals(utcSecsAfterSet, setUTCSecs, "normal UTCSecs could be set correctly");
+    assert_type(utcSecsAfterSet, "long", "type check");
+}, 'Time_TZDate_setUTCSeconds_normal');
+
+}
+
+function Time_TZDate_getUTCDate() {
+//==== TEST: Time_TZDate_getUTCDate
+//==== LABEL Check if TZDate.getUTCDate() works properly
+//==== SPEC Tizen Web API:System:Time:TZDate:getUTCDate M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var myDate = new Date(), expUTCdate, actUTCdate;
+
+    expUTCdate = myDate.getUTCDate();
+    actUTCdate = tizen.time.getCurrentDateTime().getUTCDate();
+
+    assert_equals(actUTCdate, expUTCdate, "date check");
+}, 'Time_TZDate_getUTCDate');
+
+}
+
+function Time_TZDate_toLocaleTimeString() {
+//==== TEST: Time_TZDate_toLocaleTimeString
+//==== LABEL Check if TZDate::ToLocaleTimeString() method returns string
+//==== SPEC Tizen Web API:System:Time:TZDate:toLocaleTimeString M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var tz = tizen.time.getCurrentDateTime(), ltimeS;
+    ltimeS = tz.toLocaleTimeString();
+    assert_not_equals(ltimeS, null, "null check");
+    assert_type(ltimeS, "string", "type check");
+}, 'Time_TZDate_toLocaleTimeString');
+
+}
+
+function Time_TZDate_setMonth_normal() {
+//==== TEST: Time_TZDate_setMonth_normal
+//==== LABEL Check if TZDate.setMonth() works properly
+//==== SPEC Tizen Web API:System:Time:TZDate:setMonth M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+test(function () {
+    var setMonth = 6,
+        dt = tizen.time.getCurrentDateTime(),
+        monthAfterSet;
+
+    dt.setMonth(setMonth);
+    monthAfterSet = dt.getMonth();
+
+    assert_equals(monthAfterSet, setMonth, "normal month could be set correctly");
+}, 'Time_TZDate_setMonth_normal');
+
+}
+
+function Time_TZDate_setUTCHours_normal() {
+//==== TEST: Time_TZDate_setUTCHours_normal
+//==== LABEL Check if TZDate.setUTCHours() works properly
+//==== SPEC Tizen Web API:System:Time:TZDate:setUTCHours M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+test(function () {
+    var setUTCHours = 15,
+        dt = tizen.time.getCurrentDateTime(),
+        utcHoursAfterSet;
+
+    dt.setUTCHours(setUTCHours);
+    utcHoursAfterSet = dt.getUTCHours();
+
+    assert_equals(utcHoursAfterSet, setUTCHours, "hours should be equal");
+}, 'Time_TZDate_setUTCHours_normal');
+
+}
+
+function Time_TZDate_getSeconds() {
+//==== TEST: Time_TZDate_getSeconds
+//==== LABEL Check if TZDate.getSeconds() works properly
+//==== SPEC Tizen Web API:System:Time:TZDate:getSeconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var date1 = new Date(),
+        secs = tizen.time.getCurrentDateTime().getSeconds(),
+        date2 = new Date();
+    assert_true(secs === date1.getSeconds() || secs === date2.getSeconds(), "seconds check");
+}, 'Time_TZDate_getSeconds');
+
+}
+
+function Time_TZDate_getDate() {
+//==== TEST: Time_TZDate_getDate
+//==== LABEL Check if TZDate.getDate() works properly
+//==== SPEC Tizen Web API:System:Time:TZDate:getDate M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var actDate = tizen.time.getCurrentDateTime().getDate(),
+        myDate = new Date(), expDate;
+
+    expDate = myDate.getDate();
+    assert_equals(actDate, expDate, "data check");
+}, 'Time_TZDate_getDate');
+
+}
+
+function Time_TZDate_getFullYear() {
+//==== TEST: Time_TZDate_getFullYear
+//==== LABEL Check if TZDate.getFullYear() works properly
+//==== SPEC Tizen Web API:System:Time:TZDate:getFullYear M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var myDate = new Date(), expFullYear, fullYear;
+
+    expFullYear = myDate.getFullYear();
+    fullYear = tizen.time.getCurrentDateTime().getFullYear();
+    assert_equals(fullYear, expFullYear, "fullYear check");
+}, 'Time_TZDate_getFullYear');
+
+}
+
+function Time_TZDate_setHours_normal() {
+//==== TEST: Time_TZDate_setHours_normal
+//==== LABEL Check if TZDate.setHours() works properly
+//==== SPEC Tizen Web API:System:Time:TZDate:setHours M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+test(function () {
+    var setHours = 15,
+        tizenDate = tizen.time.getCurrentDateTime(),
+        hoursAfterSet;
+
+    tizenDate.setHours(setHours);
+    hoursAfterSet = tizenDate.getHours();
+    assert_equals(hoursAfterSet, setHours, "hours should be set");
+}, 'Time_TZDate_setHours_normal');
+
+}
+
+function Time_TZDate_setUTCDate_normal() {
+//==== TEST: Time_TZDate_setUTCDate_normal
+//==== LABEL Check if TZDate.setUTCDate() works properly
+//==== SPEC Tizen Web API:System:Time:TZDate:setUTCDate M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+test(function () {
+    var setUTCdate = 11,
+        tizenDate = tizen.time.getCurrentDateTime(),
+        utcdateAfterSet;
+
+    tizenDate.setUTCDate(setUTCdate);
+    utcdateAfterSet = tizenDate.getUTCDate();
+
+    assert_equals(utcdateAfterSet, setUTCdate, "dates should be equal");
+}, 'Time_TZDate_setUTCDate_normal');
+
+}
+
+function Time_TZDate_difference_compareWithFutureDate() {
+//==== TEST: Time_TZDate_difference_compareWithFutureDate
+//==== LABEL Check if TZDate.difference() with future date works
+//==== PRIORITY P1
+//==== SPEC Tizen Web API:System:Time:TZDate:difference M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+test(function () {
+    var tzNow = new tizen.TZDate(2013, 1, 8),
+        tzFuture = new tizen.TZDate(2013, 1, 10),
+        diff;
+
+    diff = tzNow.difference(tzFuture);
+    assert_equals(diff.length, -2, "diff.length check");
+    assert_equals(diff.unit, "DAYS", "diff.unit check");
+}, 'Time_TZDate_difference_compareWithFutureDate');
+
+}
+
+function Time_TZDate_difference_compareWithFutureHour() {
+//==== TEST: Time_TZDate_difference_compareWithFutureHour
+//==== LABEL Check if TZDate.difference() with date hour later works
+//==== PRIORITY P1
+//==== SPEC Tizen Web API:System:Time:TZDate:difference M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+test(function () {
+    var tzNow = new tizen.TZDate(2013, 1, 8, 5),
+        tzFuture = new tizen.TZDate(2013, 1, 8, 6),
+        diff;
+
+    diff = tzNow.difference(tzFuture);
+    assert_equals(diff.length, -3600000, "diff.unit check");
+    assert_equals(diff.unit, "MSECS", "diff.unit check");
+}, 'Time_TZDate_difference_compareWithFutureHour');
+
+}
+
+function Time_TZDate_difference_compareWithFutureSeconds() {
+//==== TEST: Time_TZDate_difference_compareWithFutureSeconds
+//==== LABEL Check if TZDate.difference() with date seconds later works
+//==== PRIORITY P1
+//==== SPEC Tizen Web API:System:Time:TZDate:difference M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+test(function () {
+    var tzNow = new tizen.TZDate(2013, 1, 8, 12, 20, 30),
+        tzFuture = new tizen.TZDate(2013, 1, 8, 12, 20, 50),
+        diff;
+
+    diff = tzNow.difference(tzFuture);
+    assert_equals(diff.length, -20000, "diff.length check");
+    assert_equals(diff.unit, "MSECS", "diff.unit check");
+}, 'Time_TZDate_difference_compareWithFutureSeconds');
+
+}
+
+function Time_TZDate_difference_compareWithFutureYear() {
+//==== TEST: Time_TZDate_difference_compareWithFutureYear
+//==== LABEL Check if TZDate.difference() with date one year later works
+//==== PRIORITY P1
+//==== SPEC Tizen Web API:System:Time:TZDate:difference M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+test(function () {
+    var tzNow = new tizen.TZDate(2001, 1, 8),
+        tzFuture = new tizen.TZDate(2002, 1, 8),
+        diff;
+
+    diff = tzNow.difference(tzFuture);
+    assert_equals(diff.length, -365, "diff.length check");
+    assert_equals(diff.unit, "DAYS", "diff.unit check");
+}, 'Time_TZDate_difference_compareWithFutureYear');
+
+}
+
+function Time_TZDate_difference_compareWithCharacter() {
+//==== TEST: Time_TZDate_difference_compareWithCharacter
+//==== LABEL Check if TZDate.difference() with wrong string argument throws exception
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:difference M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MC
+test(function () {
+    assert_throws(TYPE_MISMATCH_EXCEPTION,
+        function () {
+            tizen.time.getCurrentDateTime().difference("abcd");
+        }, "Specific TypeMismatchError exception.");
+}, 'Time_TZDate_difference_compareWithCharacter');
+
+}
+
+function Time_TZDate_earlierThan_falseEqual() {
+//==== TEST: Time_TZDate_earlierThan_falseEqual
+//==== LABEL Check if TZDate.earlierThan() with same date returns false
+//==== PRIORITY P1
+//==== SPEC Tizen Web API:System:Time:TZDate:earlierThan M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA MR
+test(function () {
+    var tzOther = tizen.time.getCurrentDateTime(), res;
+
+    res = tzOther.earlierThan(tzOther);
+    assert_equals(res, false, "TZDate is equal to another, result should be false");
+}, 'Time_TZDate_earlierThan_falseEqual');
+
+}
+
+function Time_TZDate_earlierThan_falseLater() {
+//==== TEST: Time_TZDate_earlierThan_falseLater
+//==== LABEL Check if TZDate.earlierThan() with past date returns false
+//==== SPEC Tizen Web API:System:Time:TZDate:earlierThan M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA MR
+test(function () {
+    var tzOther, tzyCur, tzyOther, res;
+
+    tzOther = tizen.time.getCurrentDateTime();
+    tzyCur = tzOther.getFullYear();
+    tzOther.setFullYear(tzyCur - 1);
+    tzyOther = tzOther.getFullYear();
+    res = tizen.time.getCurrentDateTime().earlierThan(tzOther);
+
+    assert_equals(tzyCur - 1, tzyOther, "getFullYear check");
+    assert_equals(res, false, "TZDate is later than another, result should be false");
+}, 'Time_TZDate_earlierThan_falseLater');
+
+}
+
+function Time_TZDate_earlierThan_stringTZDate() {
+//==== TEST: Time_TZDate_earlierThan_stringTZDate
+//==== LABEL Check if TZDate.earlierThan() with string representation of date throws an error
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:earlierThan M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MC
+test(function () {
+    var tzStr = tizen.time.getCurrentDateTime().toString();
+    assert_throws(TYPE_MISMATCH_EXCEPTION,
+        function () {
+            tizen.time.getCurrentDateTime().earlierThan(tzStr);
+        }, "Specific TypeMismatchError exception.");
+}, 'Time_TZDate_earlierThan_stringTZDate');
+
+}
+
+function Time_TZDate_earlierThan_number() {
+//==== TEST: Time_TZDate_earlierThan_number
+//==== LABEL Check if TZDate.earlierThan() with number argument throws an error
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:earlierThan M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MC
+test(function () {
+    assert_throws(TYPE_MISMATCH_EXCEPTION,
+        function () {
+            tizen.time.getCurrentDateTime().earlierThan(123);
+        }, "Specific TypeMismatchError exception.");
+}, 'Time_TZDate_earlierThan_number');
+
+}
+
+function Time_TZDate_earlierThan_character() {
+//==== TEST: Time_TZDate_earlierThan_character
+//==== LABEL Check if TZDate.earlierThan() with wrong string argument throws an exception
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:earlierThan M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MC
+test(function () {
+    assert_throws(TYPE_MISMATCH_EXCEPTION,
+        function () {
+            tizen.time.getCurrentDateTime().earlierThan("abcd");
+        }, "Specific TypeMismatchError exception.");
+}, 'Time_TZDate_earlierThan_character');
+
+}
+
+function Time_TZDate_earlierThan_timezone() {
+//==== TEST: Time_TZDate_earlierThan_timezone
+//==== LABEL Check if TZDate.earlierThan() with past date converted to local timezone returns true
+//==== PRIORITY P1
+//==== SPEC Tizen Web API:System:Time:TZDate:earlierThan M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+test(function () {
+    var tzOther = tizen.time.getCurrentDateTime().toLocalTimezone(),
+        res = tizen.time.getCurrentDateTime().earlierThan(tzOther);
+
+    assert_false(res, "earlierThan check");
+}, 'Time_TZDate_earlierThan_timezone');
+
+}
+
+function Time_TZDate_equalsTo_diff() {
+//==== TEST: Time_TZDate_equalsTo_diff
+//==== LABEL Check if TZDate.equalsTo() called with different object returns false
+//==== PRIORITY P1
+//==== SPEC Tizen Web API:System:Time:TZDate:equalsTo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA MR
+test(function () {
+    var tzDiff, tzyCur, res;
+
+    tzDiff = tizen.time.getCurrentDateTime();
+    tzyCur = tzDiff.getFullYear();
+    tzDiff.setFullYear(tzyCur - 1);
+    res = tizen.time.getCurrentDateTime().equalsTo(tzDiff);
+
+    assert_equals(res, false, "Two different tzDate obj compare should be different.");
+}, 'Time_TZDate_equalsTo_diff');
+
+}
+
+function Time_TZDate_equalsTo_number() {
+//==== TEST: Time_TZDate_equalsTo_number
+//==== LABEL Check if TZDate.equalsTo() with number argument throws an exception
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:equalsTo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MC
+test(function () {
+    assert_throws(TYPE_MISMATCH_EXCEPTION,
+        function () {
+            tizen.time.getCurrentDateTime().equalsTo(123);
+        }, "Specific TypeMismatchError exception.");
+}, 'Time_TZDate_equalsTo_number');
+
+}
+
+function Time_TZDate_equalsTo_character() {
+//==== TEST: Time_TZDate_equalsTo_character
+//==== LABEL Check if TZDate.equalsTo() with string argument throws an exception
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:equalsTo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MC
+test(function () {
+    assert_throws(TYPE_MISMATCH_EXCEPTION,
+        function () {
+            tizen.time.getCurrentDateTime().equalsTo("abcd");
+        }, "Specific TypeMismatchError exception.");
+}, 'Time_TZDate_equalsTo_character');
+
+}
+
+function Time_TZDate_laterThan_falseEarlier() {
+//==== TEST: Time_TZDate_laterThan_falseEarlier
+//==== LABEL Check if TZDate.laterThan() with future date returns false
+//==== SPEC Tizen Web API:System:Time:TZDate:laterThan M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA MR
+test(function () {
+    var tzOther = tizen.time.getCurrentDateTime(),
+        tzyCur, tzyOther, res;
+
+    tzyCur = tzOther.getFullYear();
+    tzOther.setFullYear(tzOther.getFullYear() + 1);
+    tzyOther = tzOther.getFullYear();
+    res = tizen.time.getCurrentDateTime().laterThan(tzOther);
+
+    assert_equals(tzyCur+1, tzyOther, "laterThan check");
+    assert_false(res, "TZDate is earlier than another, result should be false");
+}, 'Time_TZDate_laterThan_falseEarlier');
+
+}
+
+function Time_TZDate_laterThan_falseEqual() {
+//==== TEST: Time_TZDate_laterThan_falseEqual
+//==== LABEL Check if TZDate.laterThan() with same date returns false
+//==== SPEC Tizen Web API:System:Time:TZDate:laterThan M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA MR
+test(function () {
+    var td1 = new tizen.TZDate(2012, 5, 1, 1, 1, 1, 1),
+        td2 = new tizen.TZDate(2012, 5, 1, 1, 1, 1, 1);
+    assert_false(td2.laterThan(td1), "date should not be later than the same date");
+}, 'Time_TZDate_laterThan_falseEqual');
+
+}
+
+function Time_TZDate_laterThan_number() {
+//==== TEST: Time_TZDate_laterThan_number
+//==== LABEL Check if TZDate.laterThan() with wrong number argument throws an exception
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:laterThan M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA MR
+test(function () {
+    assert_throws(TYPE_MISMATCH_EXCEPTION,
+        function () {
+            tizen.time.getCurrentDateTime().laterThan(123);
+        }, "Specific TypeMismatchError exception.");
+}, 'Time_TZDate_laterThan_number');
+
+}
+
+function Time_TZDate_laterThan_character() {
+//==== TEST: Time_TZDate_laterThan_character
+//==== LABEL Check if TZDate.laterThan() with wrong string argument throws an exception
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:laterThan M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MC
+test(function () {
+    assert_throws(TYPE_MISMATCH_EXCEPTION,
+        function () {
+            tizen.time.getCurrentDateTime().laterThan("abcd");
+        }, "Specific TypeMismatchError exception.");
+}, 'Time_TZDate_laterThan_character');
+
+}
+
+function Time_TZDate_laterThan_timezone() {
+//==== TEST: Time_TZDate_laterThan_timezone
+//==== LABEL Check if TZDate.laterThan() works properly with local timezone
+//==== SPEC Tizen Web API:System:Time:TZDate:laterThan M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA MR
+test(function () {
+    var tzOther = tizen.time.getCurrentDateTime().toLocalTimezone(),
+        tz = tizen.time.getCurrentDateTime(), res;
+
+    tz.setSeconds(tz.getSeconds() + 1);
+    res = tz.laterThan(tzOther);
+
+    assert_true(res, "laterThan check");
+}, 'Time_TZDate_laterThan_timezone');
+
+}
+
+function Time_TZDate_setDate_abnormalDecimal() {
+//==== TEST: Time_TZDate_setDate_abnormalDecimal
+//==== LABEL Check if TZDate.setDate() works properly with abnormal decimal as argument
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setDate M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var setDate = 15.5,
+        tz = tizen.time.getCurrentDateTime(),
+        expD;
+
+    tz.setDate(setDate);
+    expD = tz.getDate();
+
+    assert_not_equals(expD, setDate, "decimal 15.5 shouldn't be set to system date");
+}, 'Time_TZDate_setDate_abnormalDecimal');
+
+}
+
+function Time_TZDate_setDate_boundaryBiggerThanUpper() {
+//==== TEST: Time_TZDate_setDate_boundaryBiggerThanUpper
+//==== LABEL Check if TZDate.setDate() called with number bigger than upper boundary doesn't set the date
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setDate M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var setDate = 32, tz, afterDate;
+
+    tz = tizen.time.getCurrentDateTime();
+    tz.setDate(setDate);
+    afterDate = tz.getDate();
+
+    assert_not_equals(afterDate, setDate, "32 shouldn't be set to system date");
+}, 'Time_TZDate_setDate_boundaryBiggerThanUpper');
+
+}
+
+function Time_TZDate_setDate_boundaryLessThanLower() {
+//==== TEST: Time_TZDate_setDate_boundaryLessThanLower
+//==== LABEL Check if TZDate.setDate() called with number less than lower boundary doesn't set the date
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setDate M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var setDate = -1, tz, afterDate;
+
+    tz = tizen.time.getCurrentDateTime();
+    tz.setDate(setDate);
+    afterDate = tz.getDate();
+
+    assert_not_equals(afterDate, setDate, "-1 shouldn't be set to system date");
+}, 'Time_TZDate_setDate_boundaryLessThanLower');
+
+}
+
+function Time_TZDate_setDate_boundaryLowerLimit() {
+//==== TEST: Time_TZDate_setDate_boundaryLowerLimit
+//==== LABEL Check if TZDate.setDate() with argument equal to lower boundary works properly
+//==== SPEC Tizen Web API:System:Time:TZDate:setDate M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+test(function () {
+    var setDate = 1,
+        tz = tizen.time.getCurrentDateTime(),
+        dateAfterSet;
+
+    tz.setDate(setDate);
+    dateAfterSet = tz.getDate();
+
+    assert_equals(dateAfterSet, setDate, "getDate check");
+}, 'Time_TZDate_setDate_boundaryLowerLimit');
+
+}
+
+function Time_TZDate_setDate_boundaryUpperLimit() {
+//==== TEST: Time_TZDate_setDate_boundaryUpperLimit
+//==== LABEL Check if TZDate.setDate() with argument equal to upper boundary works properly
+//==== SPEC Tizen Web API:System:Time:TZDate:setDate M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+test(function () {
+    var setMonth = 7, setDate = 31,
+        tz = tizen.time.getCurrentDateTime(),
+        monthAfterSet, dateAfterSet;
+
+    tz.setMonth(setMonth);
+    tz.setDate(setDate);
+    monthAfterSet = tz.getMonth();
+    dateAfterSet = tz.getDate();
+
+    assert_equals(monthAfterSet, setMonth, "monthAfterSet check");
+    assert_equals(dateAfterSet, setDate, "dateAfterSet check");
+}, 'Time_TZDate_setDate_boundaryUpperLimit');
+
+}
+
+function Time_TZDate_setDate_invalidDate() {
+//==== TEST: Time_TZDate_setDate_invalidDate
+//==== LABEL Check if TZDate.setDate() called with wrong string argument doesn't set the date
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setDate M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var setDate = "a", dateAfterSet,
+        tz = tizen.time.getCurrentDateTime();
+
+    tz.setDate(setDate);
+    dateAfterSet = tz.getDate();
+
+    assert_not_equals(dateAfterSet, setDate, "a shouldn't be set to system date");
+}, 'Time_TZDate_setDate_invalidDate');
+
+}
+
+function Time_TZDate_setDate_notExistDayForCertainMonth() {
+//==== TEST: Time_TZDate_setDate_notExistDayForCertainMonth
+//==== LABEL Check if TZDate.setDate() called with date grater than days in the month sets the next month date
+//==== SPEC Tizen Web API:System:Time:TZDate:setDate M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA MAST
+test(function () {
+    var setYear = 2013, setMonth = 5, setDate = 30,
+        tz, yearAfterSet, monthAfterSet, dateAfterSet;
+
+    tz = new tizen.TZDate(setYear, setMonth, setDate);
+    tz.setDate(31);
+
+    yearAfterSet = tz.getFullYear();
+    monthAfterSet = tz.getMonth();
+    dateAfterSet = tz.getDate();
+
+    assert_equals(yearAfterSet, setYear, "year should not change");
+    assert_equals(monthAfterSet, setMonth + 1, "month should be a next month");
+    assert_equals(dateAfterSet, 1, "date should be 1");
+}, 'Time_TZDate_setDate_notExistDayForCertainMonth');
+
+}
+
+function Time_TZDate_setDate_notExistDayForFebruaryLeapYear() {
+//==== TEST: Time_TZDate_setDate_notExistDayForFebruaryLeapYear
+//==== LABEL Check if TZDate.setDate() called with argument with non existing date leap year, sets the next month date
+//==== SPEC Tizen Web API:System:Time:TZDate:setDate M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var setYear = 2000, setMonth = 1, setDate = 29,
+        myDate, yearAfterSet, monthAfterSet, dateAfterSet;
+
+    myDate = new tizen.TZDate(setYear, setMonth, setDate);
+    myDate.setUTCDate(30);
+
+    yearAfterSet = myDate.getUTCFullYear();
+    monthAfterSet = myDate.getUTCMonth();
+    dateAfterSet = myDate.getUTCDate();
+
+    assert_equals(yearAfterSet, setYear, "years should be equal");
+    assert_equals(monthAfterSet, setMonth + 1, "month should be next-one");
+    assert_equals(dateAfterSet, 1, "date should be 1st");
+}, 'Time_TZDate_setDate_notExistDayForFebruaryLeapYear');
+
+}
+
+function Time_TZDate_setDate_notExistDayForFebruaryNotLeapYear() {
+//==== TEST: Time_TZDate_setDate_notExistDayForFebruaryNotLeapYear
+//==== LABEL Check if TZDate.setDate() called with argument with non existing date non-leap year, sets the next month date
+//==== SPEC Tizen Web API:System:Time:TZDate:setDate M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var setYear = 2001, // non-leap year
+        setMonth = 1, setDate = 28,
+        myDate, yearAfterSet, monthAfterSet, dateAfterSet;
+
+    myDate = new tizen.TZDate(setYear, setMonth, setDate);
+    myDate.setUTCDate(29);
+
+    yearAfterSet = myDate.getUTCFullYear();
+    monthAfterSet = myDate.getUTCMonth();
+    dateAfterSet = myDate.getUTCDate();
+
+    assert_equals(yearAfterSet, setYear, "years should be equal");
+    assert_equals(monthAfterSet, setMonth + 1, "month should be next-one");
+    assert_equals(dateAfterSet, 1, "date should be 1st");
+}, 'Time_TZDate_setDate_notExistDayForFebruaryNotLeapYear');
+
+}
+
+function Time_TZDate_setFullYear_abnormalDecimal() {
+//==== TEST: Time_TZDate_setFullYear_abnormalDecimal
+//==== LABEL Check if TZDate.setFullYear() sets proper year when argument is a floating point number
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setFullYear M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var setFullYear = 1998.55,
+        tz = tizen.time.getCurrentDateTime(),
+        yearAfterSet, myDate, expFullYear;
+
+    tz.setFullYear(setFullYear);
+    yearAfterSet = tz.getFullYear();
+    myDate = new Date();
+    expFullYear = myDate.getFullYear();
+
+    assert_not_equals(yearAfterSet, expFullYear, "years should not be equal");
+    assert_not_equals(yearAfterSet, setFullYear, "years should be integer number");
+}, 'Time_TZDate_setFullYear_abnormalDecimal');
+
+}
+
+function Time_TZDate_setFullYear_boundaryBiggerThanUpper() {
+//==== TEST: Time_TZDate_setFullYear_boundaryBiggerThanUpper
+//==== LABEL Check if TZDate.setFullYear() called with year greater than upper boundary works properly
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setFullYear M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var setFullYear = 10000,
+        tz = tizen.time.getCurrentDateTime(),
+        yearAfterSet, myDate, expFullYear;
+
+    tz.setFullYear(setFullYear);
+    yearAfterSet = tz.getFullYear();
+    myDate = new Date();
+    expFullYear = myDate.getFullYear();
+
+    assert_not_equals(yearAfterSet, expFullYear, "years should change");
+    assert_equals(yearAfterSet, setFullYear, "years should be equal");
+}, 'Time_TZDate_setFullYear_boundaryBiggerThanUpper');
+
+}
+
+function Time_TZDate_setFullYear_boundaryLowerLimit() {
+//==== TEST: Time_TZDate_setFullYear_boundaryLowerLimit
+//==== LABEL Check if TZDate.setFullYear() called with the lowest possible value don't set the year
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setFullYear M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var setFullYear = 1,
+        tz = tizen.time.getCurrentDateTime(),
+        yearAfterSet, myDate, expFullYear;
+
+    tz.setFullYear(setFullYear);
+    yearAfterSet = tz.getFullYear();
+    myDate = new Date();
+    expFullYear = myDate.getFullYear();
+
+    assert_not_equals(expFullYear, yearAfterSet, "1 is a invalid year");
+}, 'Time_TZDate_setFullYear_boundaryLowerLimit');
+
+}
+
+function Time_TZDate_setFullYear_boundaryUpperLimit() {
+//==== TEST: Time_TZDate_setFullYear_boundaryUpperLimit
+//==== LABEL Check if TZDate.setHours() called with the highest possible value works properly
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setFullYear M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+test(function () {
+    var setFullYear = 9999,
+        tz = tizen.time.getCurrentDateTime(),
+        yearAfterSet, myDate, expFullYear;
+
+    tz.setFullYear(setFullYear);
+    yearAfterSet = tz.getFullYear();
+    myDate = new Date();
+    expFullYear = myDate.getFullYear();
+
+    assert_not_equals(yearAfterSet, expFullYear, "years should be not equal");
+    assert_equals(yearAfterSet, setFullYear, "year should be current one");
+}, 'Time_TZDate_setFullYear_boundaryUpperLimit');
+
+}
+
+function Time_TZDate_setFullYear_invalidYear() {
+//==== TEST: Time_TZDate_setFullYear_invalidYear
+//==== LABEL Check if TZDate.setFullYear() do not set the invalid date
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setFullYear M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var setFullYear = -1, myDate = new Date(), expFullYear;
+
+    expFullYear = myDate.getFullYear();
+
+    assert_not_equals(expFullYear, setFullYear, "-1 is a invalid year");
+}, 'Time_TZDate_setFullYear_invalidYear');
+
+}
+
+function Time_TZDate_setFullYear_invalidCharYear() {
+//==== TEST: Time_TZDate_setFullYear_invalidCharYear
+//==== LABEL Check if TZDate.setFullYear() called with invalid string argument works properly
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setFullYear M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var setFullYear = "a",
+        tz = tizen.time.getCurrentDateTime(),
+        yearAfterSet, myDate, expFullYear;
+
+    tz.setFullYear(setFullYear);
+    yearAfterSet = tz.getFullYear();
+    myDate = new Date();
+    expFullYear = myDate.getFullYear();
+
+    assert_not_equals(yearAfterSet, expFullYear, "expFullYear check");
+    assert_not_equals(yearAfterSet, setFullYear, "setFullYear check");
+}, 'Time_TZDate_setFullYear_invalidCharYear');
+
+}
+
+function Time_TZDate_setHours_abnormalDecimal() {
+//==== TEST: Time_TZDate_setHours_abnormalDecimal
+//==== LABEL Check if TZDate.setHours() doesn't set decimal number
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setHours M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var setHours = 8.45,
+        tz = tizen.time.getCurrentDateTime(),
+        myDate, hoursAfterSet;
+
+    tz.setHours(setHours);
+    myDate = new Date();
+    hoursAfterSet = myDate.getHours();
+    assert_not_equals(hoursAfterSet, setHours, "decimal shouldn't be set to system's hour");
+}, 'Time_TZDate_setHours_abnormalDecimal');
+
+}
+
+function Time_TZDate_setHours_boundaryBiggerThanUpper() {
+//==== TEST: Time_TZDate_setHours_boundaryBiggerThanUpper
+//==== LABEL Check if TZDate.setHours() doesn't set hour greater than 23
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setHours M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var setHours = 24,
+        tz = tizen.time.getCurrentDateTime(),
+        myDate, hoursAfterSet;
+
+    tz.setHours(setHours);
+    myDate = new Date();
+    hoursAfterSet = myDate.getHours();
+
+    assert_not_equals(hoursAfterSet, setHours, "24 shouldn't be set to system's hour");
+}, 'Time_TZDate_setHours_boundaryBiggerThanUpper');
+
+}
+
+function Time_TZDate_setHours_boundaryLessThanLower() {
+//==== TEST: Time_TZDate_setHours_boundaryLessThanLower
+//==== LABEL Check if TZDate.setHours() doesn't set hour less than 0
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setHours M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var setHours = -1,
+        tz = tizen.time.getCurrentDateTime(),
+        myDate, hoursAfterSet;
+
+    tz.setHours(setHours);
+    myDate = new Date();
+    hoursAfterSet = myDate.getHours();
+
+    assert_not_equals(hoursAfterSet, setHours, "-1 shouldn't be set to system's hour");
+}, 'Time_TZDate_setHours_boundaryLessThanLower');
+
+}
+
+function Time_TZDate_setHours_boundaryLowerLimit() {
+//==== TEST: Time_TZDate_setHours_boundaryLowerLimit
+//==== LABEL Check if TZDate.setHours() called with the lowest possible value works properly
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setHours M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+test(function () {
+    var setHours = 0,
+        tz = tizen.time.getCurrentDateTime(),
+        hoursAfterSet;
+
+    tz.setHours(setHours);
+    hoursAfterSet = tz.getHours();
+    assert_equals(hoursAfterSet, setHours, "hours should be set");
+}, 'Time_TZDate_setHours_boundaryLowerLimit');
+
+}
+
+function Time_TZDate_setHours_boundaryUpperLimit() {
+//==== TEST: Time_TZDate_setHours_boundaryUpperLimit
+//==== LABEL Check if TZDate.setHours() called with the greatest possible value works properly
+//==== SPEC Tizen Web API:System:Time:TZDate:setHours M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+test(function () {
+    var setHours = 23,
+        tz = tizen.time.getCurrentDateTime(),
+        hoursAfterSet;
+
+    tz.setHours(setHours);
+    hoursAfterSet = tz.getHours();
+    assert_equals(hoursAfterSet, setHours, "hours should be set");
+}, 'Time_TZDate_setHours_boundaryUpperLimit');
+
+}
+
+function Time_TZDate_setHours_invalidHours() {
+//==== TEST: Time_TZDate_setHours_invalidHours
+//==== LABEL Check if TZDate.setHours() called with wrong string argument doesn't set the hours
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setHours M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var setHours = "abcd",
+        tz = tizen.time.getCurrentDateTime(),
+        hoursAfterSet;
+
+    tz.setHours(setHours);
+    hoursAfterSet = tz.getHours();
+    assert_not_equals(hoursAfterSet, setHours, "string abcd shouldn't be set to system's hour");
+}, 'Time_TZDate_setHours_invalidHours');
+
+}
+
+function Time_TZDate_setMilliseconds_abnormalDecimal() {
+//==== TEST: Time_TZDate_setMilliseconds_abnormalDecimal
+//==== LABEL Check if TZDate.setMilliseconds() called with decimal don't set the milliseconds
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setMilliseconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var setMs = 100.5, tz, msAfterSet;
+
+    tz = tizen.time.getCurrentDateTime();
+    tz.setMilliseconds(setMs);
+    msAfterSet = tz.getMilliseconds();
+    assert_not_equals(msAfterSet, setMs, "decimal shouldn't be set to system's ms");
+}, 'Time_TZDate_setMilliseconds_abnormalDecimal');
+
+}
+
+function Time_TZDate_setMilliseconds_boundaryBiggerThanUpper() {
+//==== TEST: Time_TZDate_setMilliseconds_boundaryBiggerThanUpper
+//==== LABEL Check if TZDate.setMilliseconds() called with value greater than upper boundary works properly
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setMilliseconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var setMs = 1000, tz, msAfterSet;
+
+    tz = tizen.time.getCurrentDateTime();
+    tz.setMilliseconds(setMs);
+    msAfterSet = tz.getMilliseconds();
+    assert_not_equals(msAfterSet, setMs, "1000 shouldn't be set to system's ms");
+}, 'Time_TZDate_setMilliseconds_boundaryBiggerThanUpper');
+
+}
+
+function Time_TZDate_setMilliseconds_boundaryLessThanLower() {
+//==== TEST: Time_TZDate_setMilliseconds_boundaryLessThanLower
+//==== LABEL Check if TZDate.setMilliseconds() called with value less than lower boundary works properly
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setMilliseconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var setMs = -1, tz, msAfterSet;
+
+    tz = tizen.time.getCurrentDateTime();
+    tz.setMilliseconds(setMs);
+    msAfterSet = tz.getMilliseconds();
+    assert_not_equals(msAfterSet, setMs, "-1 shouldn't be set to system's ms");
+}, 'Time_TZDate_setMilliseconds_boundaryLessThanLower');
+
+}
+
+function Time_TZDate_setMilliseconds_boundaryLowerLimit() {
+//==== TEST: Time_TZDate_setMilliseconds_boundaryLowerLimit
+//==== LABEL Check if TZDate.setMilliseconds() called with the lowest value possible works properly
+//==== SPEC Tizen Web API:System:Time:TZDate:setMilliseconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+test(function () {
+    var setMs = 0, tz, msAfterSet;
+
+    tz = tizen.time.getCurrentDateTime();
+    tz.setMilliseconds(setMs);
+    msAfterSet = tz.getMilliseconds();
+    assert_equals(msAfterSet, setMs, "value after set sould be equal to set one");
+}, 'Time_TZDate_setMilliseconds_boundaryLowerLimit');
+
+}
+
+function Time_TZDate_setMilliseconds_boundaryUpperLimit() {
+//==== TEST: Time_TZDate_setMilliseconds_boundaryUpperLimit
+//==== LABEL Check if TZDate.setMilliseconds() called with the highest value possible works properly
+//==== SPEC Tizen Web API:System:Time:TZDate:setMilliseconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+test(function () {
+    var setMs = 999, tz, msAfterSet;
+
+    tz = tizen.time.getCurrentDateTime();
+    tz.setMilliseconds(setMs);
+    msAfterSet = tz.getMilliseconds();
+    assert_equals(msAfterSet, setMs, "value after set sould be equal to set one");
+}, 'Time_TZDate_setMilliseconds_boundaryUpperLimit');
+
+}
+
+function Time_TZDate_setMilliseconds_invalidMilliseconds() {
+//==== TEST: Time_TZDate_setMilliseconds_invalidMilliseconds
+//==== LABEL Check if TZDate.setMilliseconds() called with invalid string argument don't set the milliseconds
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setMilliseconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var setMs = "abcd", tz, msAfterSet;
+
+    tz = tizen.time.getCurrentDateTime();
+    tz.setMilliseconds(setMs);
+    msAfterSet = tz.getMilliseconds();
+    assert_not_equals(msAfterSet, setMs, "abcd shouldn't be set to system's ms");
+}, 'Time_TZDate_setMilliseconds_invalidMilliseconds');
+
+}
+
+function Time_TZDate_setMinutes_abnormalDecimal() {
+//==== TEST: Time_TZDate_setMinutes_abnormalDecimal
+//==== LABEL Check if TZDate.setMinutes() called with decimal number don't set the minutes
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setMinutes M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var setMins = 25.6,
+        tz = tizen.time.getCurrentDateTime(),
+        myDate, minsAfterSet;
+
+    tz.setMinutes(setMins);
+    myDate = new Date();
+    minsAfterSet  = myDate.getMinutes();
+
+    assert_not_equals(minsAfterSet, setMins, "decimal shouldn't be set to system's minute");
+}, 'Time_TZDate_setMinutes_abnormalDecimal');
+
+}
+
+function Time_TZDate_setMinutes_boundaryLessThanLower() {
+//==== TEST: Time_TZDate_setMinutes_boundaryLessThanLower
+//==== LABEL Check if TZDate.setMinutes() called with value less than lower limit don't set the minutes
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setMinutes M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var setMins = -1,
+        tz = tizen.time.getCurrentDateTime(),
+        myDate, minsAfterSet;
+
+    tz.setMinutes(setMins);
+    myDate = new Date();
+    minsAfterSet  = myDate.getMinutes();
+
+    assert_not_equals(minsAfterSet, setMins, "-1 shouldn't be set to system's minute");
+}, 'Time_TZDate_setMinutes_boundaryLessThanLower');
+
+}
+
+function Time_TZDate_setMinutes_boundaryLowerLimit() {
+//==== TEST: Time_TZDate_setMinutes_boundaryLowerLimit
+//==== LABEL Check if TZDate.setMinutes() called with lowest value possible works properly
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setMinutes M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+test(function () {
+    var setMins = 0, tz, minsAfterSet;
+
+    tz = tizen.time.getCurrentDateTime();
+    tz.setMinutes(setMins);
+    minsAfterSet = tz.getMinutes();
+
+    assert_equals(minsAfterSet, setMins, "Lower limit minutes 0 could be set correctly");
+}, 'Time_TZDate_setMinutes_boundaryLowerLimit');
+
+}
+
+function Time_TZDate_setMinutes_boundaryUpperLimit() {
+//==== TEST: Time_TZDate_setMinutes_boundaryUpperLimit
+//==== LABEL Check if TZDate.setMinutes() called with highest value possible works properly
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setMinutes M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+test(function () {
+    var setMins = 59, tz, minsAfterSet;
+
+    tz = tizen.time.getCurrentDateTime();
+    tz.setMinutes(setMins);
+    minsAfterSet = tz.getMinutes();
+
+    assert_equals(minsAfterSet, setMins, "Lower limit minutes 0 could be set correctly");
+}, 'Time_TZDate_setMinutes_boundaryUpperLimit');
+
+}
+
+function Time_TZDate_setMinutes_invalidMinutes() {
+//==== TEST: Time_TZDate_setMinutes_invalidMinutes
+//==== LABEL Check if TZDate.setMinutes() called with invalid string argument don't set the minutes
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setMinutes M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var setMins = "ab",
+        tz = tizen.time.getCurrentDateTime(),
+        myDate, minsAfterSet;
+
+    tz.setMinutes(setMins);
+    myDate = new Date();
+    minsAfterSet  = myDate.getMinutes();
+
+    assert_not_equals(minsAfterSet, setMins, "ab shouldn't be set to system's minute");
+}, 'Time_TZDate_setMinutes_invalidMinutes');
+
+}
+
+function Time_TZDate_setMonth_abnormalDecimal() {
+//==== TEST: Time_TZDate_setMonth_abnormalDecimal
+//==== LABEL Check if TZDate.setMonth() called with decimal number don't set the month
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setMonth M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var setMonth = 5.5,
+        tz = tizen.time.getCurrentDateTime(),
+        myDate, monthAfterSet;
+
+    tz.setMonth(setMonth);
+    myDate = new Date();
+    monthAfterSet = myDate.getMonth();
+
+    assert_not_equals(monthAfterSet, setMonth, "decimal shouldn't be set to system's month");
+}, 'Time_TZDate_setMonth_abnormalDecimal');
+
+}
+
+function Time_TZDate_setMonth_boundaryBiggerThanUpper() {
+//==== TEST: Time_TZDate_setMonth_boundaryBiggerThanUpper
+//==== LABEL Check if TZDate.setMonth() called with value greater than upper limit don't set the month
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setMonth M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var setMonth = 12,
+        tz = tizen.time.getCurrentDateTime(),
+        myDate, monthAfterSet;
+
+    tz.setMonth(setMonth);
+    myDate = new Date();
+    monthAfterSet = myDate.getMonth();
+
+    assert_not_equals(monthAfterSet, setMonth, "12 shouldn't be set to system's month");
+}, 'Time_TZDate_setMonth_boundaryBiggerThanUpper');
+
+}
+
+function Time_TZDate_setMonth_boundaryLessThanLower() {
+//==== TEST: Time_TZDate_setMonth_boundaryLessThanLower
+//==== LABEL Check if TZDate.setMonth() called with value less than lower limit don't set the month
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setMonth M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var setMonth = -1,
+        tz = tizen.time.getCurrentDateTime(),
+        myDate, monthAfterSet;
+
+    tz.setMonth(setMonth);
+    myDate = new Date();
+    monthAfterSet = myDate.getMonth();
+
+    assert_not_equals(monthAfterSet, setMonth, "-1 shouldn't be set to system's month");
+}, 'Time_TZDate_setMonth_boundaryLessThanLower');
+
+}
+
+function Time_TZDate_setMonth_boundaryLowerLimit() {
+//==== TEST: Time_TZDate_setMonth_boundaryLowerLimit
+//==== LABEL Check if TZDate.setMonth() called with lowest value possible works properly
+//==== SPEC Tizen Web API:System:Time:TZDate:setMonth M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+test(function () {
+    var setMonth = 0, tz, monthAfterSet;
+
+    tz = tizen.time.getCurrentDateTime();
+    tz.setMonth(setMonth);
+    monthAfterSet = tz.getMonth();
+
+    assert_equals(monthAfterSet, setMonth, "Lower limit 0 month could be set correctly");
+}, 'Time_TZDate_setMonth_boundaryLowerLimit');
+
+}
+
+function Time_TZDate_setMonth_boundaryUpperLimit() {
+//==== TEST: Time_TZDate_setMonth_boundaryUpperLimit
+//==== LABEL Check if TZDate.setMonth() called with highest value possible works properly
+//==== SPEC Tizen Web API:System:Time:TZDate:setMonth M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+test(function () {
+    var setMonth = 11, tz, monthAfterSet;
+
+    tz = tizen.time.getCurrentDateTime();
+    tz.setMonth(setMonth);
+    monthAfterSet = tz.getMonth();
+
+    assert_equals(monthAfterSet, setMonth, "getMonth check");
+}, 'Time_TZDate_setMonth_boundaryUpperLimit');
+
+}
+
+function Time_TZDate_setMonth_invalidMonth() {
+//==== TEST: Time_TZDate_setMonth_invalidMonth
+//==== LABEL Check if TZDate.setMonth() called with invalid string argument don't set the month
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setMonth M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var setMonth = "0100",
+        tz = tizen.time.getCurrentDateTime(),
+        myDate, monthAfterSet;
+
+    tz.setMonth(setMonth);
+    myDate = new Date();
+    monthAfterSet = myDate.getMonth();
+
+    assert_not_equals(monthAfterSet, setMonth, "0100 shouldn't be set to system's month");
+}, 'Time_TZDate_setMonth_invalidMonth');
+
+}
+
+function Time_TZDate_setSeconds_abnormalDecimal() {
+//==== TEST: Time_TZDate_setSeconds_abnormalDecimal
+//==== LABEL Check if TZDate.setSeconds() called with decimal number don't set the seconds
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setSeconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var setSecs = 5.5,
+        tz = tizen.time.getCurrentDateTime(),
+        myDate, secsAfterSet;
+
+    tz.setSeconds(setSecs);
+    myDate = new Date();
+    secsAfterSet = myDate.getSeconds();
+
+    assert_not_equals(secsAfterSet, setSecs, "decimal shouldn't be set to system's seconds");
+}, 'Time_TZDate_setSeconds_abnormalDecimal');
+
+}
+
+function Time_TZDate_setSeconds_boundaryBiggerThanUpper() {
+//==== TEST: Time_TZDate_setSeconds_boundaryBiggerThanUpper
+//==== LABEL Check if TZDate.setSeconds() called with value greater than upper limit don't set the seconds
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setSeconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var setSecs = 60, myDate, secsAfterSet;
+
+    tizen.time.getCurrentDateTime().setSeconds(setSecs);
+    myDate = new Date();
+    secsAfterSet = myDate.getSeconds();
+
+    assert_not_equals(secsAfterSet, setSecs, "BiggerThanUpper boundary value 60 shouldn't be set to system's seconds");
+}, 'Time_TZDate_setSeconds_boundaryBiggerThanUpper');
+
+}
+
+function Time_TZDate_setSeconds_boundaryLessThanLower() {
+//==== TEST: Time_TZDate_setSeconds_boundaryLessThanLower
+//==== LABEL Check if TZDate.setSeconds() called with value less than lower limit don't set the seconds
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setSeconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var setSecs = -1, myDate, secsAfterSet;
+
+    tizen.time.getCurrentDateTime().setSeconds(setSecs);
+    myDate = new Date();
+    secsAfterSet = myDate.getSeconds();
+
+    assert_not_equals(secsAfterSet, setSecs, "LessThanLower boundary value -1 shouldn't be set to system's seconds");
+}, 'Time_TZDate_setSeconds_boundaryLessThanLower');
+
+}
+
+function Time_TZDate_setSeconds_boundaryLowerLimit() {
+//==== TEST: Time_TZDate_setSeconds_boundaryLowerLimit
+//==== LABEL Check if TZDate.setSeconds() called with lowest value possible works properly
+//==== SPEC Tizen Web API:System:Time:TZDate:setSeconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+test(function () {
+    var setSecs = 0,
+        dt = tizen.time.getCurrentDateTime(),
+        secsAfterSet;
+
+    dt.setSeconds(setSecs);
+    secsAfterSet = dt.getSeconds();
+
+    assert_equals(secsAfterSet, setSecs, "lower secs could be set correctly");
+}, 'Time_TZDate_setSeconds_boundaryLowerLimit');
+
+}
+
+function Time_TZDate_setSeconds_boundaryUpperLimit() {
+//==== TEST: Time_TZDate_setSeconds_boundaryUpperLimit
+//==== LABEL Check if TZDate.setSeconds() called with highest value possible works properly
+//==== SPEC Tizen Web API:System:Time:TZDate:setSeconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+test(function () {
+    var setSecs = 59,
+        dt = tizen.time.getCurrentDateTime(),
+        secsAfterSet;
+
+    dt.setSeconds(setSecs);
+    secsAfterSet = dt.getSeconds();
+    assert_equals(secsAfterSet, setSecs, "upper secs could be set correctly");
+}, 'Time_TZDate_setSeconds_boundaryUpperLimit');
+
+}
+
+function Time_TZDate_setSeconds_invalidSeconds() {
+//==== TEST: Time_TZDate_setSeconds_invalidSeconds
+//==== LABEL Check if TZDate.setSeconds() called with invalid string argument don't set the seconds
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setSeconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var setSecs = "abc01", myDate, secsAfterSet;
+
+    tizen.time.getCurrentDateTime().setSeconds(setSecs);
+    myDate = new Date(2013, 2, 27, 18, 42, 48, 100);
+    secsAfterSet = myDate.getSeconds();
+
+    assert_not_equals(secsAfterSet, setSecs, "getSeconds check");
+}, 'Time_TZDate_setSeconds_invalidSeconds');
+
+}
+
+function Time_TZDate_setUTCDate_abnormalDecimal() {
+//==== TEST: Time_TZDate_setUTCDate_abnormalDecimal
+//==== LABEL Check if TZDate.setUTCDate() works properly with abnormal decimal as argument
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setUTCDate M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var setUTCdate = 15.5, tz, utcdateAfterSet;
+
+    tz = tizen.time.getCurrentDateTime();
+    tz.setUTCDate(setUTCdate);
+    utcdateAfterSet = tz.getUTCDate();
+
+    assert_not_equals(utcdateAfterSet, setUTCdate, "decimal 15.5 shouldn't be set to system UTCdate");
+}, 'Time_TZDate_setUTCDate_abnormalDecimal');
+
+}
+
+function Time_TZDate_setUTCDate_boundaryBiggerThanUpper() {
+//==== TEST: Time_TZDate_setUTCDate_boundaryBiggerThanUpper
+//==== LABEL Check if TZDate.setUTCDate() called with number bigger than upper boundary doesn't set the date
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setUTCDate M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var setUTCdate = 32, tz, utcdateAfterSet;
+
+    tz = tizen.time.getCurrentDateTime();
+    tz.setUTCDate(setUTCdate);
+    utcdateAfterSet = tz.getUTCDate();
+
+    assert_not_equals(utcdateAfterSet, setUTCdate, "decimal 32 shouldn't be set to system UTCdate");
+}, 'Time_TZDate_setUTCDate_boundaryBiggerThanUpper');
+
+}
+
+function Time_TZDate_setUTCDate_boundaryLessThanLower() {
+//==== TEST: Time_TZDate_setUTCDate_boundaryLessThanLower
+//==== LABEL Check if TZDate.setUTCDate() called with number less than lower boundary doesn't set the date
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setUTCDate M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var setUTCdate = -1, tz, utcdateAfterSet;
+
+    tz = tizen.time.getCurrentDateTime();
+    tz.setUTCDate(setUTCdate);
+    utcdateAfterSet = tz.getUTCDate();
+
+    assert_not_equals(utcdateAfterSet, setUTCdate, "decimal -1 shouldn't be set to system UTCdate");
+}, 'Time_TZDate_setUTCDate_boundaryLessThanLower');
+
+}
+
+function Time_TZDate_setUTCDate_boundaryLowerLimit() {
+//==== TEST: Time_TZDate_setUTCDate_boundaryLowerLimit
+//==== LABEL Check if TZDate.setUTCDate() with argument equal to lower boundary works properly
+//==== SPEC Tizen Web API:System:Time:TZDate:setUTCDate M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+test(function () {
+    var setUTCdate = 1,
+        tz = tizen.time.getCurrentDateTime(),
+        myDate, utcdateAfterSet;
+
+    tz.setUTCDate(setUTCdate);
+    myDate = new Date();
+    utcdateAfterSet = tz.getUTCDate();
+
+    assert_equals(utcdateAfterSet, setUTCdate, "dates should be equal");
+}, 'Time_TZDate_setUTCDate_boundaryLowerLimit');
+
+}
+
+function Time_TZDate_setUTCDate_boundaryUpperLimit() {
+//==== TEST: Time_TZDate_setUTCDate_boundaryUpperLimit
+//==== LABEL Check if TZDate.setUTCDate() with argument equal to upper boundary works properly
+//==== SPEC Tizen Web API:System:Time:TZDate:setUTCDate M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+test(function () {
+    var setUTCmonth = 7, setUTCdate = 31,
+        tz = tizen.time.getCurrentDateTime(),
+        myDate, utcdateAfterSet;
+
+    tz.setUTCMonth(setUTCmonth);
+    tz.setUTCDate(setUTCdate);
+    myDate = new Date();
+    utcdateAfterSet = tz.getUTCDate();
+
+    assert_equals(utcdateAfterSet, setUTCdate, "dates should be equal");
+}, 'Time_TZDate_setUTCDate_boundaryUpperLimit');
+
+}
+
+function Time_TZDate_setUTCDate_invalidDate() {
+//==== TEST: Time_TZDate_setUTCDate_invalidDate
+//==== LABEL Check if TZDate.setUTCDate() called with wrong string argument doesn't set the date
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setUTCDate M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var setUTCdate = "a",
+        tz = tizen.time.getCurrentDateTime(),
+        myDate, utcdateAfterSet;
+
+    tz.setUTCDate(setUTCdate);
+    myDate = new Date();
+    utcdateAfterSet = tz.getUTCDate();
+
+    assert_not_equals(utcdateAfterSet, setUTCdate, "decimal a shouldn't be set to system UTCdate");
+}, 'Time_TZDate_setUTCDate_invalidDate');
+
+}
+
+function Time_TZDate_setUTCDate_notExistDayForCertainMonth() {
+//==== TEST: Time_TZDate_setUTCDate_notExistDayForCertainMonth
+//==== LABEL Check if TZDate.setUTCDate() called with date greater than days in the month sets the next month date
+//==== SPEC Tizen Web API:System:Time:TZDate:setUTCDate M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA MAST
+test(function () {
+    var setYear = 2013, setMonth = 5, setDate = 30,
+        tz, yearAfterSet, monthAfterSet, dateAfterSet;
+
+    tz = new tizen.TZDate(setYear, setMonth, setDate);
+    tz.setUTCDate(31);
+
+    yearAfterSet = tz.getUTCFullYear();
+    monthAfterSet = tz.getUTCMonth();
+    dateAfterSet = tz.getUTCDate();
+
+    assert_equals(yearAfterSet, setYear, "year should be set");
+    assert_equals(monthAfterSet, setMonth + 1, "month should be set to next one");
+    assert_equals(dateAfterSet, 1, "date should be set to 1st of next month");
+}, 'Time_TZDate_setUTCDate_notExistDayForCertainMonth');
+
+}
+
+function Time_TZDate_setUTCDate_notExistDayForFebruaryLeapYear() {
+//==== TEST: Time_TZDate_setUTCDate_notExistDayForFebruaryLeapYear
+//==== LABEL Check if TZDate.setUTCDate() called with argument with non existing date leap year, sets the next month date
+//==== SPEC Tizen Web API:System:Time:TZDate:setUTCDate M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA MAST
+test(function () {
+    var setYear = 2000, // leap year
+        setMonth = 1, setDate = 29,
+        myDate, yearAfterSet, monthAfterSet, dateAfterSet;
+
+    myDate = new tizen.TZDate(setYear, setMonth, setDate);
+    myDate.setUTCDate(30);
+
+    yearAfterSet = myDate.getUTCFullYear();
+    monthAfterSet = myDate.getUTCMonth();
+    dateAfterSet = myDate.getUTCDate();
+
+    assert_equals(yearAfterSet, setYear, "year should be set");
+    assert_equals(monthAfterSet, setMonth + 1, "month should be the next one");
+    assert_equals(dateAfterSet, 1, "date should be 1st of next month");
+}, 'Time_TZDate_setUTCDate_notExistDayForFebruaryLeapYear');
+
+}
+
+function Time_TZDate_setUTCDate_notExistDayForFebruaryNotLeapYear() {
+//==== TEST: Time_TZDate_setUTCDate_notExistDayForFebruaryNotLeapYear
+//==== LABEL Check if TZDate.setUTCDate() called with argument with non existing date non-leap year, sets the next month date
+//==== SPEC Tizen Web API:System:Time:TZDate:setUTCDate M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA MAST
+test(function () {
+    var setYear = 2001, // non-leap year
+        setMonth = 1, setDate = 28,
+        myDate, yearAfterSet, monthAfterSet, dateAfterSet;
+
+    myDate = new tizen.TZDate(setYear, setMonth, setDate);
+    myDate.setUTCDate(29);
+
+    yearAfterSet = myDate.getUTCFullYear();
+    monthAfterSet = myDate.getUTCMonth();
+    dateAfterSet = myDate.getUTCDate();
+
+    assert_equals(yearAfterSet, setYear, "year should be set");
+    assert_equals(monthAfterSet, setMonth + 1, "month should be the next one");
+    assert_equals(dateAfterSet, 1, "day should be 1st of next month");
+}, 'Time_TZDate_setUTCDate_notExistDayForFebruaryNotLeapYear');
+
+}
+
+function Time_TZDate_setUTCFullYear_abnormalDecimal() {
+//==== TEST: Time_TZDate_setUTCFullYear_abnormalDecimal
+//==== LABEL Check if TZDate.setUTCFullYear() works properly with abnormal decimal as argument
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setUTCFullYear M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var setUTCFullYear = 1998.55,
+        tz = tizen.time.getCurrentDateTime(),
+        yearAfterSet;
+
+    tz.setUTCFullYear(setUTCFullYear);
+    yearAfterSet = tz.getUTCFullYear();
+
+    assert_not_equals(yearAfterSet, setUTCFullYear, "decimal shouldn't be set to system date's year");
+}, 'Time_TZDate_setUTCFullYear_abnormalDecimal');
+
+}
+
+function Time_TZDate_setUTCFullYear_boundaryBiggerThanUpper() {
+//==== TEST: Time_TZDate_setUTCFullYear_boundaryBiggerThanUpper
+//==== LABEL Check if TZDate.setUTCFullYear() called with year greater than upper boundary works properly
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setUTCFullYear M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+test(function () {
+    var setUTCFullYear = 10000,
+        tz = tizen.time.getCurrentDateTime(),
+        yearAfterSet;
+
+    tz.setUTCFullYear(setUTCFullYear);
+    yearAfterSet = tz.getUTCFullYear();
+
+    assert_equals(yearAfterSet, setUTCFullYear, "10000 should be set to system date's year");
+}, 'Time_TZDate_setUTCFullYear_boundaryBiggerThanUpper');
+
+}
+
+function Time_TZDate_setUTCFullYear_boundaryLowerLimit() {
+//==== TEST: Time_TZDate_setUTCFullYear_boundaryLowerLimit
+//==== LABEL Check if TZDate.setUTCFullYear() called with the lowest possible value works properly
+//==== SPEC Tizen Web API:System:Time:TZDate:setUTCFullYear M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+test(function () {
+    var setUTCFullYear = 1,
+        tz = tizen.time.getCurrentDateTime(),
+        yearAfterSet;
+
+    tz.setUTCFullYear(setUTCFullYear);
+    yearAfterSet = tz.getUTCFullYear();
+
+    assert_equals(yearAfterSet, setUTCFullYear, "years should be equal");
+}, 'Time_TZDate_setUTCFullYear_boundaryLowerLimit');
+
+}
+
+function Time_TZDate_setUTCFullYear_boundaryUpperLimit() {
+//==== TEST: Time_TZDate_setUTCFullYear_boundaryUpperLimit
+//==== LABEL Check if TZDate.setUTCFullYear() called with the highest possible value works properly
+//==== SPEC Tizen Web API:System:Time:TZDate:setUTCFullYear M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+test(function () {
+    var setUTCFullYear = 9999,
+        tz = tizen.time.getCurrentDateTime(),
+        yearAfterSet;
+
+    tz.setUTCFullYear(setUTCFullYear);
+    yearAfterSet = tz.getUTCFullYear();
+
+    assert_equals(yearAfterSet, setUTCFullYear, "year should be equal");
+}, 'Time_TZDate_setUTCFullYear_boundaryUpperLimit');
+
+}
+
+function Time_TZDate_setUTCFullYear_invalidYear() {
+//==== TEST: Time_TZDate_setUTCFullYear_invalidYear
+//==== LABEL Check if TZDate.setUTCFullYear() do not set the invalid date
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setUTCFullYear M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var setUTCFullYear = "-1abs10",
+        tz = tizen.time.getCurrentDateTime(),
+        yearAfterSet;
+
+    tz.setUTCFullYear(setUTCFullYear);
+    yearAfterSet = tz.getUTCFullYear();
+
+    assert_not_equals(yearAfterSet, setUTCFullYear, "getUTCFullYear check");
+}, 'Time_TZDate_setUTCFullYear_invalidYear');
+
+}
+
+function Time_TZDate_setUTCFullYear_invalidCharYear() {
+//==== TEST: Time_TZDate_setUTCFullYear_invalidCharYear
+//==== LABEL Check if TZDate.setUTCFullYear() called with invalid string argument works properly
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setUTCFullYear M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var setUTCFullYear = "a",
+        tz = tizen.time.getCurrentDateTime(),
+        yearAfterSet;
+
+    tz.setUTCFullYear(setUTCFullYear);
+    yearAfterSet = tz.getUTCFullYear();
+
+    assert_not_equals(yearAfterSet, setUTCFullYear, "a shouldn't be set to system date's year");
+}, 'Time_TZDate_setUTCFullYear_invalidCharYear');
+
+}
+
+function Time_TZDate_setUTCHours_abnormalDecimal() {
+//==== TEST: Time_TZDate_setUTCHours_abnormalDecimal
+//==== LABEL Check if TZDate.setUTCHours() doesn't set decimal number
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setUTCHours M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var setUTCHours = 8.45,
+        tz = tizen.time.getCurrentDateTime(),
+        utcHoursAfterSet;
+
+    tz.setUTCHours(setUTCHours);
+    utcHoursAfterSet = tz.getUTCHours();
+
+    assert_not_equals(utcHoursAfterSet, setUTCHours, "decimal shouldn't be set to system's UTCHour");
+}, 'Time_TZDate_setUTCHours_abnormalDecimal');
+
+}
+
+function Time_TZDate_setUTCHours_boundaryBiggerThanUpper() {
+//==== TEST: Time_TZDate_setUTCHours_boundaryBiggerThanUpper
+//==== LABEL Check if TZDate.setUTCHours() doesn't set hour greater than 23
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setUTCHours M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var setUTCHours = 24,
+        tz = tizen.time.getCurrentDateTime(),
+        utcHoursAfterSet;
+
+    tz.setUTCHours(setUTCHours);
+    utcHoursAfterSet = tz.getUTCHours();
+
+    assert_not_equals(utcHoursAfterSet, setUTCHours, "24 shouldn't be set to system's UTCHour");
+}, 'Time_TZDate_setUTCHours_boundaryBiggerThanUpper');
+
+}
+
+function Time_TZDate_setUTCHours_boundaryLessThanLower() {
+//==== TEST: Time_TZDate_setUTCHours_boundaryLessThanLower
+//==== LABEL Check if TZDate.setUTCHours() doesn't set hour less than 0
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setUTCHours M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var setUTCHours = -1,
+        tz = tizen.time.getCurrentDateTime(),
+        utcHoursAfterSet;
+
+    tz.setUTCHours(setUTCHours);
+    utcHoursAfterSet = tz.getUTCHours();
+
+    assert_not_equals(utcHoursAfterSet, setUTCHours, "-1 shouldn't be set to system's UTCHour");
+}, 'Time_TZDate_setUTCHours_boundaryLessThanLower');
+
+}
+
+function Time_TZDate_setUTCHours_boundaryLowerLimit() {
+//==== TEST: Time_TZDate_setUTCHours_boundaryLowerLimit
+//==== LABEL Check if TZDate.setUTCHours() called with the lowest possible value works properly
+//==== SPEC Tizen Web API:System:Time:TZDate:setUTCHours M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+test(function () {
+    var setUTCHours = 0,
+        tz = tizen.time.getCurrentDateTime(),
+        utcHoursAfterSet;
+
+    tz.setUTCHours(setUTCHours);
+    utcHoursAfterSet = tz.getUTCHours();
+
+    assert_equals(utcHoursAfterSet, setUTCHours, "hours should be equal");
+}, 'Time_TZDate_setUTCHours_boundaryLowerLimit');
+
+}
+
+function Time_TZDate_setUTCHours_boundaryUpperLimit() {
+//==== TEST: Time_TZDate_setUTCHours_boundaryUpperLimit
+//==== LABEL Check if TZDate.setUTCHours() called with the greatest possible value works properly
+//==== SPEC Tizen Web API:System:Time:TZDate:setUTCHours M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+test(function () {
+    var setUTCHours = 23,
+        tz = tizen.time.getCurrentDateTime(),
+        utcHoursAfterSet;
+
+    tz.setUTCHours(setUTCHours);
+    utcHoursAfterSet = tz.getUTCHours();
+
+    assert_equals(utcHoursAfterSet, setUTCHours, "hours should be equal");
+}, 'Time_TZDate_setUTCHours_boundaryUpperLimit');
+
+}
+
+function Time_TZDate_setUTCHours_invalidHours() {
+//==== TEST: Time_TZDate_setUTCHours_invalidHours
+//==== LABEL Check if TZDate.setUTCHours() called with wrong string argument doesn't set the hours
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setUTCHours M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var setUTCHours = "abcd",
+        tz = tizen.time.getCurrentDateTime(),
+        utcHoursAfterSet;
+
+    tz.setUTCHours(setUTCHours);
+    utcHoursAfterSet = tz.getUTCHours();
+
+    assert_not_equals(utcHoursAfterSet, setUTCHours, "abcd shouldn't be set to system's UTCHour");
+}, 'Time_TZDate_setUTCHours_invalidHours');
+
+}
+
+function Time_TZDate_setUTCMilliseconds_abnormalDecimal() {
+//==== TEST: Time_TZDate_setUTCMilliseconds_abnormalDecimal
+//==== LABEL Check if TZDate.setUTCMilliseconds() called with decimal don't set the milliseconds
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setUTCMilliseconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var setUTCMs = 100.5,
+        tz = tizen.time.getCurrentDateTime(),
+        utcMsAfterSet;
+
+    tz.setUTCMilliseconds(setUTCMs);
+    utcMsAfterSet = tz.getUTCMilliseconds();
+
+    assert_not_equals(utcMsAfterSet, setUTCMs, "decimal shouldn't be set to system's utcMs");
+}, 'Time_TZDate_setUTCMilliseconds_abnormalDecimal');
+
+}
+
+function Time_TZDate_setUTCMilliseconds_boundaryBiggerThanUpper() {
+//==== TEST: Time_TZDate_setUTCMilliseconds_boundaryBiggerThanUpper
+//==== LABEL Check if TZDate.setUTCMilliseconds() called with value greater than upper boundary works properly
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setUTCMilliseconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var setUTCMs = 1000,
+        tz = tizen.time.getCurrentDateTime(),
+        utcMsAfterSet;
+
+    tz.setUTCMilliseconds(setUTCMs);
+    utcMsAfterSet = tz.getUTCMilliseconds();
+
+    assert_not_equals(utcMsAfterSet, setUTCMs, "1000 shouldn't be set to system's utcMs");
+}, 'Time_TZDate_setUTCMilliseconds_boundaryBiggerThanUpper');
+
+}
+
+function Time_TZDate_setUTCMilliseconds_boundaryLessThanLower() {
+//==== TEST: Time_TZDate_setUTCMilliseconds_boundaryLessThanLower
+//==== LABEL Check if TZDate.setUTCMilliseconds() called with value less than lower boundary works properly
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setUTCMilliseconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var setUTCMs = -1,
+        tz = tizen.time.getCurrentDateTime(),
+        utcMsAfterSet;
+
+    tz.setUTCMilliseconds(setUTCMs);
+    utcMsAfterSet = tz.getUTCMilliseconds();
+
+    assert_not_equals(utcMsAfterSet, setUTCMs, "-1 shouldn't be set to system's utcMs");
+}, 'Time_TZDate_setUTCMilliseconds_boundaryLessThanLower');
+
+}
+
+function Time_TZDate_setUTCMilliseconds_boundaryLowerLimit() {
+//==== TEST: Time_TZDate_setUTCMilliseconds_boundaryLowerLimit
+//==== LABEL Check if TZDate.setUTCMilliseconds() called with the lowest value possible works properly
+//==== SPEC Tizen Web API:System:Time:TZDate:setUTCMilliseconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+test(function () {
+    var setUTCMs = 0,
+        tz = tizen.time.getCurrentDateTime(),
+        utcMsAfterSet;
+
+    tz.setUTCMilliseconds(setUTCMs);
+    utcMsAfterSet = tz.getUTCMilliseconds();
+
+    assert_equals(utcMsAfterSet, setUTCMs, "milliseconds should be equal");
+}, 'Time_TZDate_setUTCMilliseconds_boundaryLowerLimit');
+
+}
+
+function Time_TZDate_setUTCMilliseconds_boundaryUpperLimit() {
+//==== TEST: Time_TZDate_setUTCMilliseconds_boundaryUpperLimit
+//==== LABEL Check if TZDate.setUTCMilliseconds() called with the highest value possible works properly
+//==== SPEC Tizen Web API:System:Time:TZDate:setUTCMilliseconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+test(function () {
+    var setUTCMs = 999,
+        tz = tizen.time.getCurrentDateTime(),
+        utcMsAfterSet;
+
+    tz.setUTCMilliseconds(setUTCMs);
+    utcMsAfterSet = tz.getUTCMilliseconds();
+
+    assert_equals(utcMsAfterSet, setUTCMs, "milliseconds should be equal");
+}, 'Time_TZDate_setUTCMilliseconds_boundaryUpperLimit');
+
+}
+
+function Time_TZDate_setUTCMilliseconds_invalidMilliseconds() {
+//==== TEST: Time_TZDate_setUTCMilliseconds_invalidMilliseconds
+//==== LABEL Check if TZDate.setUTCMilliseconds() called with invalid string argument don't set the milliseconds
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setUTCMilliseconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var setUTCMs = "abcd",
+        tz = tizen.time.getCurrentDateTime(),
+        utcMsAfterSet;
+
+    tz.setUTCMilliseconds(setUTCMs);
+    utcMsAfterSet = tz.getUTCMilliseconds();
+
+    assert_not_equals(utcMsAfterSet, setUTCMs, "abcd shouldn't be set to system's utcMs");
+}, 'Time_TZDate_setUTCMilliseconds_invalidMilliseconds');
+
+}
+
+function Time_TZDate_setUTCMinutes_abnormalDecimal() {
+//==== TEST: Time_TZDate_setUTCMinutes_abnormalDecimal
+//==== LABEL Check if TZDate.setUTCMinutes() called with decimal don't set the milliseconds
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setUTCMinutes M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var setUTCMins = 25.6,
+        tz = tizen.time.getCurrentDateTime(),
+        myDate, utcMinsAfterSet;
+
+    tz.setUTCMinutes(setUTCMins);
+    myDate = new Date();
+    utcMinsAfterSet  = myDate.getUTCMinutes();
+
+    assert_not_equals(utcMinsAfterSet, setUTCMins, "decimal shouldn't be set to system's UTCMinute");
+}, 'Time_TZDate_setUTCMinutes_abnormalDecimal');
+
+}
+
+function Time_TZDate_setUTCMinutes_boundaryBiggerThanUpper() {
+//==== TEST: Time_TZDate_setUTCMinutes_boundaryBiggerThanUpper
+//==== LABEL Check if TZDate.setUTCMinutes() called with value greater than upper limit don't set the minutes
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setUTCMinutes M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var setUTCMins = 60,
+        tz = tizen.time.getCurrentDateTime(),
+        myDate, utcMinsAfterSet;
+
+    tz.setUTCMinutes(setUTCMins);
+    myDate = new Date();
+    utcMinsAfterSet  = myDate.getUTCMinutes();
+
+    assert_not_equals(utcMinsAfterSet, setUTCMins, "60 shouldn't be set to system's UTCMinute");
+}, 'Time_TZDate_setUTCMinutes_boundaryBiggerThanUpper');
+
+}
+
+function Time_TZDate_setUTCMinutes_boundaryLessThanLower() {
+//==== TEST: Time_TZDate_setUTCMinutes_boundaryLessThanLower
+//==== LABEL Check if TZDate.setUTCMinutes() called with value less than lower limit don't set the minutes
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setUTCMinutes M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var setUTCMins = -1,
+        tz = tizen.time.getCurrentDateTime(),
+        myDate, utcMinsAfterSet;
+
+    tz.setUTCMinutes(setUTCMins);
+    myDate = new Date();
+    utcMinsAfterSet  = myDate.getUTCMinutes();
+
+    assert_not_equals(utcMinsAfterSet, setUTCMins, "getUTCMinutes check");
+}, 'Time_TZDate_setUTCMinutes_boundaryLessThanLower');
+
+}
+
+function Time_TZDate_setUTCMinutes_boundaryLowerLimit() {
+//==== TEST: Time_TZDate_setUTCMinutes_boundaryLowerLimit
+//==== LABEL Check if TZDate.setUTCMinutes() called with lowest value possible works properly
+//==== SPEC Tizen Web API:System:Time:TZDate:setUTCMinutes M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+test(function () {
+    var setUTCMins = 0,
+        tz = tizen.time.getCurrentDateTime(),
+        utcMinsAfterSet;
+
+    tz.setUTCMinutes(setUTCMins);
+    utcMinsAfterSet  = tz.getUTCMinutes();
+
+    assert_equals(utcMinsAfterSet, setUTCMins, "Lower limit UTCMinutes 0 could be set correctly");
+}, 'Time_TZDate_setUTCMinutes_boundaryLowerLimit');
+
+}
+
+function Time_TZDate_setUTCMinutes_boundaryUpperLimit() {
+//==== TEST: Time_TZDate_setUTCMinutes_boundaryUpperLimit
+//==== LABEL Check if TZDate.setUTCMinutes() called with highest value possible works properly
+//==== SPEC Tizen Web API:System:Time:TZDate:setUTCMinutes M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+test(function () {
+    var setUTCMins = 59,
+        tz = tizen.time.getCurrentDateTime(),
+        utcMinsAfterSet;
+
+    tz.setUTCMinutes(setUTCMins);
+    utcMinsAfterSet  = tz.getUTCMinutes();
+
+    assert_equals(utcMinsAfterSet, setUTCMins, "uppeer limit UTCMinutes 59 could be set correctly");
+}, 'Time_TZDate_setUTCMinutes_boundaryUpperLimit');
+
+}
+
+function Time_TZDate_setUTCMinutes_invalidMinutes() {
+//==== TEST: Time_TZDate_setUTCMinutes_invalidMinutes
+//==== LABEL Check if TZDate.setUTCMinutes() called with invalid string argument don't set the minutes
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setUTCMinutes M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var setUTCMins = "ab",
+        tz = tizen.time.getCurrentDateTime(),
+        utcMinsAfterSet;
+
+    tz.setUTCMinutes(setUTCMins);
+    utcMinsAfterSet = tz.getUTCMinutes();
+
+    assert_not_equals(utcMinsAfterSet, setUTCMins, "Invalid value ab shouldn't be set to system's UTCMinute");
+}, 'Time_TZDate_setUTCMinutes_invalidMinutes');
+
+}
+
+function Time_TZDate_setUTCMonth_abnormalDecimal() {
+//==== TEST: Time_TZDate_setUTCMonth_abnormalDecimal
+//==== LABEL Check if TZDate.setUTCMonth() called with decimal don't set the milliseconds
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setUTCMonth M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var setUTCMonth = 5.5, tz, utcMonthAfterSet;
+    tz = tizen.time.getCurrentDateTime();
+    tz.setUTCMonth(setUTCMonth);
+    utcMonthAfterSet = tz.getUTCMonth();
+    assert_not_equals(utcMonthAfterSet, setUTCMonth, "Invalid UTCMonth 5.5 shouldn't be set to system's UTCMonth");
+}, 'Time_TZDate_setUTCMonth_abnormalDecimal');
+
+}
+
+function Time_TZDate_setUTCMonth_boundaryBiggerThanUpper() {
+//==== TEST: Time_TZDate_setUTCMonth_boundaryBiggerThanUpper
+//==== LABEL Check if TZDate.setUTCMonth() called with value greater than upper limit don't set the minutes
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setUTCMonth M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var setUTCMonth = 12, tz = tizen.time.getCurrentDateTime(), utcMonthAfterSet;
+    tz.setUTCMonth(setUTCMonth);
+    utcMonthAfterSet = tz.getUTCMonth();
+    assert_not_equals(utcMonthAfterSet, setUTCMonth, "Invalid UTCMonth 12 shouldn't be set to system's UTCMonth");
+}, 'Time_TZDate_setUTCMonth_boundaryBiggerThanUpper');
+
+}
+
+function Time_TZDate_setUTCMonth_boundaryLessThanLower() {
+//==== TEST: Time_TZDate_setUTCMonth_boundaryLessThanLower
+//==== LABEL Check if TZDate.setUTCMonth() called with number less than lower boundary doesn't set the date
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setUTCMonth M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var setUTCMonth = -1, utcMonthAfterSet, tz;
+    tz = tizen.time.getCurrentDateTime();
+    tz.setUTCMonth(setUTCMonth);
+    utcMonthAfterSet = tz.getUTCMonth();
+    assert_not_equals(utcMonthAfterSet, setUTCMonth, "Invalid UTCMonth -1 shouldn't be set to system's UTCMonth");
+}, 'Time_TZDate_setUTCMonth_boundaryLessThanLower');
+
+}
+
+function Time_TZDate_setUTCMonth_boundaryLowerLimit() {
+//==== TEST: Time_TZDate_setUTCMonth_boundaryLowerLimit
+//==== LABEL Check if TZDate.setUTCMonth() called with lowest value possible works properly
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setUTCMonth M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+test(function () {
+    var setUTCMonth = 0, tz, utcMonthAfterSet;
+    tz = tizen.time.getCurrentDateTime();
+    tz.setUTCMonth(setUTCMonth);
+    utcMonthAfterSet = tz.getUTCMonth();
+    assert_equals(utcMonthAfterSet, setUTCMonth, "Lower limit 0 UTCMonth could be set correctly");
+}, 'Time_TZDate_setUTCMonth_boundaryLowerLimit');
+
+}
+
+function Time_TZDate_setUTCMonth_boundaryUpperLimit() {
+//==== TEST: Time_TZDate_setUTCMonth_boundaryUpperLimit
+//==== LABEL Check if TZDate.setUTCMonth() called with highest value possible works properly
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setUTCMonth M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+test(function () {
+    var setUTCMonth = 11, tz, utcMonthAfterSet;
+    tz = tizen.time.getCurrentDateTime();
+    tz.setUTCMonth(setUTCMonth);
+    utcMonthAfterSet = tz.getUTCMonth();
+    assert_equals(utcMonthAfterSet, setUTCMonth, "upper limit 11 UTCMonth could be set correctly");
+}, 'Time_TZDate_setUTCMonth_boundaryUpperLimit');
+
+}
+
+function Time_TZDate_setUTCMonth_invalidMonth() {
+//==== TEST: Time_TZDate_setUTCMonth_invalidMonth
+//==== LABEL Check if TZDate.setUTCMonth() called with invalid string argument don't set the month
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setUTCMonth M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var setUTCMonth = "0100", tz, utcMonthAfterSet;
+    tz = tizen.time.getCurrentDateTime();
+    tz.setUTCMonth(setUTCMonth);
+    utcMonthAfterSet = tz.getUTCMonth();
+
+    assert_not_equals(utcMonthAfterSet, setUTCMonth, "Invalid UTCMonth 0100 shouldn't be set to system's UTCMonth");
+}, 'Time_TZDate_setUTCMonth_invalidMonth');
+
+}
+
+function Time_TZDate_setUTCSeconds_abnormalDecimal() {
+//==== TEST: Time_TZDate_setUTCSeconds_abnormalDecimal
+//==== LABEL Check if TZDate.setUTCSeconds() called with decimal don't set the milliseconds
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setUTCSeconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var setUTCSecs = 5.5, utcSecsAfterSet, tz;
+    tz = tizen.time.getCurrentDateTime();
+    tz.setUTCSeconds(setUTCSecs);
+    utcSecsAfterSet = tz.getUTCSeconds();
+    assert_not_equals(utcSecsAfterSet, setUTCSecs, "decimal shouldn't be set to system's UTCSeconds");
+}, 'Time_TZDate_setUTCSeconds_abnormalDecimal');
+
+}
+
+function Time_TZDate_setUTCSeconds_boundaryBiggerThanUpper() {
+//==== TEST: Time_TZDate_setUTCSeconds_boundaryBiggerThanUpper
+//==== LABEL Check if TZDate.setUTCSeconds() called with value greater than upper limit don't set the minutes
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setUTCSeconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var setUTCSecs = 59, utcSecsAfterSet,
+        tz = tizen.time.getCurrentDateTime();
+    tz.setUTCSeconds(setUTCSecs);
+    utcSecsAfterSet = tz.getUTCSeconds();
+    assert_equals(utcSecsAfterSet, setUTCSecs, "BiggerThanUpper boundary value 60 shouldn't be set to system's UTCSeconds");
+}, 'Time_TZDate_setUTCSeconds_boundaryBiggerThanUpper');
+
+}
+
+function Time_TZDate_setUTCSeconds_boundaryLessThanLower() {
+//==== TEST: Time_TZDate_setUTCSeconds_boundaryLessThanLower
+//==== LABEL Check if TZDate.setUTCSeconds() called with number less than lower boundary doesn't set the date
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setUTCSeconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var setUTCSecs = -1, myDate, utcSecsAfterSet;
+    tizen.time.getCurrentDateTime().setUTCSeconds(setUTCSecs);
+    myDate = new Date();
+    utcSecsAfterSet = myDate.getUTCSeconds();
+    assert_not_equals(utcSecsAfterSet, setUTCSecs, "LessThanLower boundary value -1 shouldn't be set to system's UTCSeconds");
+}, 'Time_TZDate_setUTCSeconds_boundaryLessThanLower');
+
+}
+
+function Time_TZDate_setUTCSeconds_boundaryLowerLimit() {
+//==== TEST: Time_TZDate_setUTCSeconds_boundaryLowerLimit
+//==== LABEL Check if TZDate.setUTCSeconds() called with lowest value possible works properly
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setUTCSeconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+test(function () {
+    var setUTCSecs = 0, tz, utcSecsAfterSet;
+    tz = tizen.time.getCurrentDateTime();
+    tz.setUTCSeconds(0);
+    utcSecsAfterSet = tz.getUTCSeconds();
+    assert_equals(utcSecsAfterSet, setUTCSecs, "Lower limit UTCSecs 0 could be set correctly");
+    assert_type(utcSecsAfterSet, "long", "type check");
+}, 'Time_TZDate_setUTCSeconds_boundaryLowerLimit');
+
+}
+
+function Time_TZDate_setUTCSeconds_boundaryUpperLimit() {
+//==== TEST: Time_TZDate_setUTCSeconds_boundaryUpperLimit
+//==== LABEL Check if TZDate.setUTCSeconds() called with highest value possible works properly
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setUTCSeconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+test(function () {
+    var setUTCSecs = 59, tz, utcSecsAfterSet;
+    tz = tizen.time.getCurrentDateTime();
+    tz.setUTCSeconds(59);
+    utcSecsAfterSet = tz.getUTCSeconds();
+    assert_equals(utcSecsAfterSet, setUTCSecs, "upper limit UTCSecs 59 could be set correctly");
+    assert_type(utcSecsAfterSet, "long", "type check");
+}, 'Time_TZDate_setUTCSeconds_boundaryUpperLimit');
+
+}
+
+function Time_TZDate_setUTCSeconds_invalidSeconds() {
+//==== TEST: Time_TZDate_setUTCSeconds_invalidSeconds
+//==== LABEL Check if TZDate.setUTCSeconds() called with invalid string argument don't set the seconds
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:setUTCSeconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var setUTCSecs = "abc01", utcSecsAfterSet,
+        tz = tizen.time.getCurrentDateTime();
+    tz.setUTCSeconds(setUTCSecs);
+    utcSecsAfterSet = tz.getUTCSeconds();
+    assert_not_equals(utcSecsAfterSet, setUTCSecs, "Invalid UTCSeconds abc01 shouldn't be set to system's UTCSeconds");
+    assert_type(utcSecsAfterSet, "long", "type check");
+}, 'Time_TZDate_setUTCSeconds_invalidSeconds');
+
+}
+
+function Time_TZDate_toTimezone_invalid() {
+//==== TEST: Time_TZDate_toTimezone_invalid
+//==== LABEL Check if TZDate::toTimezone(invalid) method reports error
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:toTimezone M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var tzid, timezone;
+    assert_throws(INVALID_VALUES_EXCEPTION, function () {
+        tzid = "ab";
+        timezone = tizen.time.getCurrentDateTime().toTimezone(tzid);
+    });
+}, 'Time_TZDate_toTimezone_invalid');
+
+}
+
+function Time_TZDate_toTimezone_null() {
+//==== TEST: Time_TZDate_toTimezone_null
+//==== LABEL Check if TZDate::toTimezone(null) method reports error
+//==== PRIORITY P2
+//==== SPEC Tizen Web API:System:Time:TZDate:toTimezone M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var tzid, timezone;
+    assert_throws(INVALID_VALUES_EXCEPTION, function () {
+        tzid = null;
+        timezone = tizen.time.getCurrentDateTime().toTimezone(tzid);
+    });
+}, 'Time_TZDate_toTimezone_null');
+
+}
+
+function Time_TZDate_isDST_false() {
+//==== TEST: Time_TZDate_isDST_false
+//==== LABEL Check if TZDate.isDST() returns false on non DST date
+//==== SPEC Tizen Web API:System:Time:TZDate:isDST M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var td = new tizen.TZDate(2012, 1, 1, 1, 1, 1, 1, "Europe/Berlin");
+    assert_false(td.isDST(), "isDST check");
+}, 'Time_TZDate_isDST_false');
+
+}
+
+function Time_TZDate_isDST_boundaryLowerLimit_true() {
+//==== TEST: Time_TZDate_isDST_boundaryLowerLimit-true
+//==== LABEL Check if TZDate.isDST() returns true on lower DST boundary
+//==== SPEC Tizen Web API:System:Time:TZDate:isDST M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var td = new tizen.TZDate(2012, 2, 25, 2, 0, 0, 0, "Europe/Berlin");
+    assert_true(td.isDST(), "isDST check");
+}, 'Time_TZDate_isDST_boundaryLowerLimit_true');
+
+}
+
+function Time_TZDate_isDST_boundaryUpperLimit_true() {
+//==== TEST: Time_TZDate_isDST_boundaryUpperLimit-true
+//==== LABEL Check if TZDate.isDST() returns true on upper DST boundary
+//==== SPEC Tizen Web API:System:Time:TZDate:isDST M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var td = new tizen.TZDate(2012, 9, 28, 1, 1, 1, 1, "Europe/Berlin");
+    assert_true(td.isDST(), "isDST check");
+}, 'Time_TZDate_isDST_boundaryUpperLimit_true');
+
+}
+
+function Time_TZDate_getPreviousDSTTransition_number() {
+//==== TEST: Time_TZDate_getPreviousDSTTransition_number
+//==== LABEL Check if TZDate.getPreviousDSTTransition() with extra number argument works properly
+//==== PRIORITY P1
+//==== SPEC Tizen Web API:System:Time:TZDate:getPreviousDSTTransition M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var td = new tizen.TZDate(2012, 12, 1, 1, 1, 1, 1, "Europe/Berlin"),
+        prevTr, day, month;
+
+    prevTr = td.getPreviousDSTTransition(123);
+    day = prevTr.getDate();
+    month = prevTr.getMonth();
+    assert_equals(month, 9, "month check");
+    assert_equals(day, 28, "day check");
+}, 'Time_TZDate_getPreviousDSTTransition_number');
+
+}
+
+function Time_TZDate_getPreviousDSTTransition_character() {
+//==== TEST: Time_TZDate_getPreviousDSTTransition_character
+//==== LABEL Check if TZDate.getPreviousDSTTransition() with extra string argument works properly
+//==== PRIORITY P1
+//==== SPEC Tizen Web API:System:Time:TZDate:getPreviousDSTTransition M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var td = new tizen.TZDate(2012, 12, 1, 1, 1, 1, 1, "Europe/Berlin"),
+        prevTr, day, month;
+
+    prevTr = td.getPreviousDSTTransition("abc");
+    day = prevTr.getDate();
+    month = prevTr.getMonth();
+    assert_equals(month, 9, "month check");
+    assert_equals(day, 28, "day check");
+}, 'Time_TZDate_getPreviousDSTTransition_character');
+
+}
+
+function Time_TZDate_getNextDSTTransition_character() {
+//==== TEST: Time_TZDate_getNextDSTTransition_character
+//==== LABEL Check if TZDate.getNextDSSTTransition() works properly with extra string argument
+//==== PRIORITY P1
+//==== SPEC Tizen Web API:System:Time:TZDate:getNextDSTTransition M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var td = new tizen.TZDate(2012, 1, 1, 1, 1, 1, 1, "Europe/Berlin"),
+        nextTr, day, month;
+
+    nextTr = td.getNextDSTTransition("abc");
+    day = nextTr.getDate();
+    month = nextTr.getMonth();
+    assert_equals(month, 2, "month check");
+    assert_equals(day, 25, "day check");
+}, 'Time_TZDate_getNextDSTTransition_character');
+
+}
+
+function Time_TZDate_getNextDSTTransition_number() {
+//==== TEST: Time_TZDate_getNextDSTTransition_number
+//==== LABEL Check if TZDate.getNextDSSTTransition() works properly with extra number argument
+//==== PRIORITY P1
+//==== SPEC Tizen Web API:System:Time:TZDate:getNextDSTTransition M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var td = new tizen.TZDate(2012, 1, 1, 1, 1, 1, 1, "Europe/Berlin"),
+        nextTr, day, month;
+
+    nextTr = td.getNextDSTTransition(123);
+    day = nextTr.getDate();
+    month = nextTr.getMonth();
+    assert_equals(month, 2, "month check");
+    assert_equals(day, 25, "day check");
+}, 'Time_TZDate_getNextDSTTransition_number');
+
+}
+
+function TimeDuration_difference_checkDurationDifference() {
+//==== TEST: TimeDuration_difference_checkDurationDifference
+//==== LABEL Check difference method TimeDuration interface works successfully
+//==== PRIORITY P1
+//==== SPEC Tizen Web API:System:Time:TimeDuration:difference M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA MR
+test(function () {
+    var d1 = null, d2 = null;
+    d1 = new tizen.TimeDuration(1, "DAYS");
+    d2 = new tizen.TimeDuration(2, "DAYS");
+    assert_true(d2.difference(d1) instanceof tizen.TimeDuration, "check type tizen.TimeDuration");
+}, 'TimeDuration_difference_checkDurationDifference');
+
+}
+
+function TimeDuration_equalsTo_checkDurationEqual() {
+//==== TEST: TimeDuration_equalsTo_checkDurationEqual
+//==== LABEL Check equalsTo method TimeDuration interface works successfully
+//==== PRIORITY P1
+//==== SPEC Tizen Web API:System:Time:TimeDuration:equalsTo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA MR
+test(function () {
+    var d1 = null, d2 = null, ret = null;
+    d1 = new tizen.TimeDuration(60, "MINS");
+    d2 = new tizen.TimeDuration(1, "HOURS");
+    ret = d1.equalsTo(d2);
+    assert_equals(ret, true, "equalsTo check");
+}, 'TimeDuration_equalsTo_checkDurationEqual');
+
+}
+
+function TimeDuration_lessThan_checkDurationLower() {
+//==== TEST: TimeDuration_lessThan_checkDurationLower
+//==== LABEL Check lessThan method TimeDuration interface works successfully
+//==== PRIORITY P1
+//==== SPEC Tizen Web API:System:Time:TimeDuration:lessThan M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA MR
+test(function () {
+    var d1 = null, d2 = null, ret = null;
+    d1 = new tizen.TimeDuration(120, "HOURS");
+    d2 = new tizen.TimeDuration(1, "MINS");
+    ret = d1.lessThan(d2);
+    assert_equals(ret, false, "lessThan check");
+}, 'TimeDuration_lessThan_checkDurationLower');
+
+}
+
+function TimeDuration_greaterThan_checkDurationGreater() {
+//==== TEST: TimeDuration_greaterThan_checkDurationGreater
+//==== LABEL Check greaterThan method TimeDuration interface works successfully
+//==== PRIORITY P1
+//==== SPEC Tizen Web API:System:Time:TimeDuration:greaterThan M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA MR
+test(function () {
+    var d1 = null, d2 = null, ret = null;
+    d1 = new tizen.TimeDuration(120, "MINS");  // 120 minutes
+    d2 = new tizen.TimeDuration(1, "HOURS");   // 1 hour
+    ret = d1.greaterThan(d2);
+    assert_equals(ret, true, "greaterThan check");
+}, 'TimeDuration_greaterThan_checkDurationGreater');
+
+}
+
+function TimeUtil_isLeapYear_allZero() {
+//==== TEST: TimeUtil_isLeapYear_allZero
+//==== LABEL Check TimeUtil interface isLeapYear method with parameter zero
+//==== PRIORITY P1
+//==== SPEC Tizen Web API:System:Time:TimeUtil:isLeapYear M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+test(function () {
+    var isLeap = null;
+    isLeap = tizen.time.isLeapYear(0);
+    assert_true(isLeap, "check isLeap");
+}, 'TimeUtil_isLeapYear_allZero');
+
+}
+
+function TimeUtil_isLeapYear_negative() {
+//==== TEST: TimeUtil_isLeapYear_negative
+//==== LABEL Check TimeUtil interface isLeapYear method with parameter negative
+//==== PRIORITY P1
+//==== SPEC Tizen Web API:System:Time:TimeUtil:isLeapYear M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+test(function () {
+    var isLeap = null;
+    isLeap = tizen.time.isLeapYear(-2000);
+    assert_true(isLeap, "check isLeap");
+}, 'TimeUtil_isLeapYear_negative');
+
+}
+
+function TimeUtil_getAvailableTimezones_checkEuropeBerlin() {
+//==== TEST: TimeUtil_getAvailableTimezones_checkEuropeBerlin
+//==== LABEL Check EuropeBerlin is included in available timezones
+//==== PRIORITY P1
+//==== SPEC Tizen Web API:System:Time:TimeUtil:getAvailableTimezones M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA
+test(function () {
+    var tzids = null, timeZone, i;
+    timeZone = false;
+    tzids = tizen.time.getAvailableTimezones();
+    assert_not_equals(tzids.length, 0, "check if tzids.length is greater than 0");
+    for (i = 0; i < tzids.length; i ++) {
+        if (tzids[i] === "Europe/Berlin") {
+            timeZone = true;
+            break;
+        }
+    }
+    assert_true(timeZone, "Europe/Berlin is a time zone");
+}, 'TimeUtil_getAvailableTimezones_checkEuropeBerlin');
+
+}
+
+function TZDate_getDate_checkEqualWithSetDate() {
+//==== TEST: TZDate_getDate_checkEqualWithSetDate
+//==== LABEL Check if getDate value is equal to setDate
+//==== PRIORITY P1
+//==== SPEC Tizen Web API:System:Time:TZDate:setDate M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MAST MMINA
+test(function () {
+    var currentDate = null, day = null;
+    currentDate = tizen.time.getCurrentDateTime();
+    currentDate.setDate(9);
+    day = currentDate.getDate();
+    assert_equals(day, 9, "day chceck");
+}, 'TZDate_getDate_checkEqualWithSetDate');
+
+}
+
+function TZDate_getFullYear_checkEqualWithSetFullYear() {
+//==== TEST: TZDate_getFullYear_checkEqualWithSetFullYear
+//==== LABEL Check if getFullYear value is equal to setFullYear
+//==== PRIORITY P1
+//==== SPEC Tizen Web API:System:Time:TZDate:setFullYear M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MAST MMINA
+test(function () {
+    var currentDate = null, year = null;
+    currentDate = tizen.time.getCurrentDateTime();
+    currentDate.setFullYear(2012);
+    year = currentDate.getFullYear();
+    assert_equals(year, 2012, "year check");
+}, 'TZDate_getFullYear_checkEqualWithSetFullYear');
+
+}
+
+function TZDate_getHours_checkEqualWithSetHours() {
+//==== TEST: TZDate_getHours_checkEqualWithSetHours
+//==== LABEL Check if getHours value is equal to setHours
+//==== PRIORITY P1
+//==== SPEC Tizen Web API:System:Time:TZDate:setHours M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MAST MMINA
+test(function () {
+    var currentDate = null, hour = null;
+    currentDate = tizen.time.getCurrentDateTime();
+    currentDate.setHours(16);
+    hour = currentDate.getHours();
+    assert_equals(hour, 16, "hour check");
+}, 'TZDate_getHours_checkEqualWithSetHours');
+
+}
+
+function TZDate_getMilliseconds_checkEqualWithSetMilliseconds() {
+//==== TEST: TZDate_getMilliseconds_checkEqualWithSetMilliseconds
+//==== LABEL Check if getMilliseconds value is equal to setMilliseconds
+//==== PRIORITY P1
+//==== SPEC Tizen Web API:System:Time:TZDate:setMilliseconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MAST MMINA
+test(function () {
+    var currentDate = null, milliSeconds = null;
+    currentDate = tizen.time.getCurrentDateTime();
+    currentDate.setMilliseconds(666);
+    milliSeconds = currentDate.getMilliseconds();
+    assert_equals(milliSeconds, 666, "milliSeconds check");
+}, 'TZDate_getMilliseconds_checkEqualWithSetMilliseconds');
+
+}
+
+function TZDate_getMinutes_checkEqualWithSetMinutes() {
+//==== TEST: TZDate_getMinutes_checkEqualWithSetMinutes
+//==== LABEL Check if getMinutes value is equal to setMinutes
+//==== PRIORITY P1
+//==== SPEC Tizen Web API:System:Time:TZDate:setMinutes M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MAST MMINA
+test(function () {
+    var currentDate = null, minute = null;
+    currentDate = tizen.time.getCurrentDateTime();
+    currentDate.setMinutes(50);
+    minute = currentDate.getMinutes();
+    assert_equals(minute, 50, "minute check");
+}, 'TZDate_getMinutes_checkEqualWithSetMinutes');
+
+}
+
+function TZDate_getMonth_checkEqualWithSetMonth() {
+//==== TEST: TZDate_getMonth_checkEqualWithSetMonth
+//==== LABEL Check if getMonth value is equal to setMonth
+//==== PRIORITY P1
+//==== SPEC Tizen Web API:System:Time:TZDate:setMonth M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MAST MMINA
+test(function () {
+    var currentDate = null, month = null;
+    currentDate = tizen.time.getCurrentDateTime();
+    currentDate.setMonth(0);
+    month = currentDate.getMonth();
+    assert_equals(month, 0, "month check");
+}, 'TZDate_getMonth_checkEqualWithSetMonth');
+
+}
+
+function TZDate_getSeconds_checkEqualWithSetSeconds() {
+//==== TEST: TZDate_getSeconds_checkEqualWithSetSeconds
+//==== LABEL Check if getSeconds value is equal to setSeconds
+//==== PRIORITY P1
+//==== SPEC Tizen Web API:System:Time:TZDate:setSeconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MAST MMINA
+test(function () {
+    var currentDate = null, second = null;
+    currentDate = tizen.time.getCurrentDateTime();
+    currentDate.setSeconds(0);
+    second = currentDate.getSeconds();
+    assert_equals(second, 0, "second check");
+}, 'TZDate_getSeconds_checkEqualWithSetSeconds');
+
+}
+
+function TZDate_getUTCDate_checkEqualWithSetUTCDate() {
+//==== TEST: TZDate_getUTCDate_checkEqualWithSetUTCDate
+//==== LABEL Check if getUTCDate value is equal to setUTCDate
+//==== PRIORITY P1
+//==== SPEC Tizen Web API:System:Time:TZDate:setUTCDate M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MAST MMINA
+test(function () {
+    var currentDate = null, day = null;
+    currentDate = tizen.time.getCurrentDateTime();
+    currentDate.setUTCDate(9);
+    day = currentDate.getUTCDate();
+    assert_equals(day, 9, "day check");
+}, 'TZDate_getUTCDate_checkEqualWithSetUTCDate');
+
+}
+
+function TZDate_getUTCFullYear_checkEqualWithSetUTCFullYear() {
+//==== TEST: TZDate_getUTCFullYear_checkEqualWithSetUTCFullYear
+//==== LABEL Check if getUTCFullYear value is equal to setUTCFullYear
+//==== PRIORITY P1
+//==== SPEC Tizen Web API:System:Time:TZDate:setUTCFullYear M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MAST MMINA
+test(function () {
+    var currentDate = null, year = null;
+    currentDate = tizen.time.getCurrentDateTime();
+    currentDate.setUTCFullYear(2012);
+    year = currentDate.getUTCFullYear();
+    assert_equals(year, 2012, "year check");
+}, 'TZDate_getUTCFullYear_checkEqualWithSetUTCFullYear');
+
+}
+
+function TZDate_getUTCHours_checkEqualWithSetUTCHours() {
+//==== TEST: TZDate_getUTCHours_checkEqualWithSetUTCHours
+//==== LABEL Check if getUTCHours value is equal to setUTCHours
+//==== PRIORITY P1
+//==== SPEC Tizen Web API:System:Time:TZDate:setUTCHours M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MAST MMINA
+test(function () {
+    var currentDate = null, hour = null;
+    currentDate = tizen.time.getCurrentDateTime();
+    currentDate.setUTCHours(16);
+    hour = currentDate.getUTCHours();
+    assert_equals(hour, 16, "hour check");
+}, 'TZDate_getUTCHours_checkEqualWithSetUTCHours');
+
+}
+
+function TZDate_getUTCMilliseconds_checkEqualWithSetUTCMilliseconds() {
+//==== TEST: TZDate_getUTCMilliseconds_checkEqualWithSetUTCMilliseconds
+//==== LABEL Check if getUTCMilliseconds value is equal to setUTCMilliseconds
+//==== PRIORITY P1
+//==== SPEC Tizen Web API:System:Time:TZDate:setUTCMilliseconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MAST MMINA
+test(function () {
+    var currentDate = null, milliSeconds = null;
+    currentDate = tizen.time.getCurrentDateTime();
+    currentDate.setUTCMilliseconds(666);
+    milliSeconds = currentDate.getUTCMilliseconds();
+    assert_equals(milliSeconds, 666, "milliSeconds check");
+}, 'TZDate_getUTCMilliseconds_checkEqualWithSetUTCMilliseconds');
+
+}
+
+function TZDate_getUTCMinutes_checkEqualWithSetUTCMinutes() {
+//==== TEST: TZDate_getUTCMinutes_checkEqualWithSetUTCMinutes
+//==== LABEL Check if getUTCMinutes value is equal to setUTCMinutes
+//==== PRIORITY P1
+//==== SPEC Tizen Web API:System:Time:TZDate:setUTCMinutes M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MAST MMINA
+test(function () {
+    var currentDate = null, minute = null;
+    currentDate = tizen.time.getCurrentDateTime();
+    currentDate.setUTCMinutes(50);
+    minute = currentDate.getUTCMinutes();
+    assert_equals(minute, 50, "minute check");
+}, 'TZDate_getUTCMinutes_checkEqualWithSetUTCMinutes');
+
+}
+
+function TZDate_getUTCMonth_checkEqualWithSetUTCMonth() {
+//==== TEST: TZDate_getUTCMonth_checkEqualWithSetUTCMonth
+//==== LABEL Check if getUTCMonth value is equal to setUTCMonth
+//==== PRIORITY P1
+//==== SPEC Tizen Web API:System:Time:TZDate:setUTCMonth M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MAST MMINA
+test(function () {
+    var currentDate = null, month = null;
+    currentDate = tizen.time.getCurrentDateTime();
+    currentDate.setUTCMonth(0);
+    month = currentDate.getUTCMonth();
+    assert_equals(month, 0, "month check");
+}, 'TZDate_getUTCMonth_checkEqualWithSetUTCMonth');
+
+}
+
+function TZDate_getUTCSeconds_checkEqualWithSetUTCSeconds() {
+//==== TEST: TZDate_getUTCSeconds_checkEqualWithSetUTCSeconds
+//==== LABEL Check if getUTCSeconds value is equal to getUTCSeconds
+//==== PRIORITY P1
+//==== SPEC Tizen Web API:System:Time:TZDate:setUTCSeconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MAST MMINA
+test(function () {
+    var currentDate = null, second = null;
+    currentDate = tizen.time.getCurrentDateTime();
+    currentDate.setUTCSeconds(0);
+    second = currentDate.getUTCSeconds();
+    assert_equals(second, 0, "second check");
+}, 'TZDate_getUTCSeconds_checkEqualWithSetUTCSeconds');
+
+}
+
+function TZDate_addDuration() {
+//==== TEST: TZDate_addDuration
+//==== LABEL Check if method TZDate::addDuration() works properly
+//==== SPEC: Tizen Web API:System:Time:TZDate:addDuration M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA MR
+test(function () {
+    var currentTZDate, duration, returnedValue;
+    currentTZDate = new tizen.TZDate(2013, 6, 8);
+    duration = new tizen.TimeDuration(1, "DAYS");
+    returnedValue = currentTZDate.addDuration(duration);
+    assert_equals(returnedValue.getDate(), 9, "returnedValue.getDay() check");
+    assert_true(returnedValue instanceof tizen.TZDate, "TZDate check");
+}, 'TZDate_addDuration');
+
+}
+
+function TZDate_addDuration_duration_TypeMismatch() {
+//==== TEST: TZDate_addDuration_duration_TypeMismatch
+//==== LABEL Check if TZDate::addDuration() throws exception when duration argument has wrong type
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:System:Time:TZDate:addDuration M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MC
+test(function () {
+    var currentTZDate, conversionTable, duration, exceptionName, i;
+
+    currentTZDate = tizen.time.getCurrentDateTime();
+    conversionTable = getTypeConversionExceptions("functionObject", false);
+    for (i = 0; i < conversionTable.length; i++) {
+        duration = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+
+        assert_throws({name: exceptionName},
+            function () {
+                currentTZDate.addDuration(duration);
+            }, exceptionName + " should be thrown - given incorrect successCallback.");
+    }
+}, 'TZDate_addDuration_duration_TypeMismatch');
+
+}
+
+function TZDate_addDuration_duration_invalid_obj() {
+//==== TEST: TZDate_addDuration_duration_invalid_obj
+//==== LABEL Check if TZDate::addDuration() throws exception when duration is regular object
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:System:Time:TZDate:addDuration M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MTO
+test(function () {
+    var currentTZDate, currentTimeDuration = [], exceptionName = TYPE_MISMATCH_ERR;
+
+    currentTimeDuration[0] = {length: 2, unit: "MINS"};
+    currentTZDate = tizen.time.getCurrentDateTime();
+    assert_throws(TYPE_MISMATCH_EXCEPTION,
+        function () {
+            currentTZDate.addDuration(currentTimeDuration[0]);
+        }, exceptionName + " should be thrown - given incorrect argument.");
+}, 'TZDate_addDuration_duration_invalid_obj');
+
+}
+
+function TZDate_addDuration_exist() {
+//==== TEST: TZDate_addDuration_exist
+//==== LABEL Check if addDuration() method exists in TimeManager
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TZDate:addDuration M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    assert_true("addDuration" in currentTZDate, "addDuration method exists");
+    check_method_exists(currentTZDate, "addDuration");
+}, 'TZDate_addDuration_exist');
+
+}
+
+function TZDate_addDuration_missarg() {
+//==== TEST: TZDate_addDuration_missarg
+//==== LABEL Check if TZDate::addDuration() method throws exception with missing mandatory argument
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:System:Time:TZDate:addDuration M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMA
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    assert_throws(TYPE_MISMATCH_EXCEPTION,
+        function () {
+            currentTZDate.addDuration();
+        });
+}, 'TZDate_addDuration_missarg');
+
+}
+
+function TZDate_constructor_maximal_with_nonoptional_arguments() {
+//==== TEST: TZDate_constructor_maximal_with_nonoptional_arguments
+//==== LABEL Test whether TZDate(y, m, d, h, m, s, m, timezone) constructor works
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TZDate:constructor C
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA CONSTRM CONSTRA
+test(function () {
+    var year = 2013, month = 2, day = 26, tzdate, hours = 4, minutes = 34,
+        seconds = 12, milliseconds = 100, timezone = "Europe/Berlin";
+    tzdate = new tizen.TZDate(year, month, day, hours, minutes, seconds, milliseconds, timezone);
+    assert_type(tzdate, "object", "type check");
+    assert_equals(tzdate.getFullYear(), 2013, "year check");
+    assert_equals(tzdate.getMonth(), 2, "month check");
+    assert_equals(tzdate.getDay(), 2, "day check");
+    assert_equals(tzdate.getHours(), 4, "hours check");
+    assert_equals(tzdate.getMinutes(), 34, "minutes check");
+    assert_equals(tzdate.getSeconds(), 12, "seconds check");
+    assert_equals(tzdate.getMilliseconds(), 100, "milliseconds check");
+    assert_equals(tzdate.getTimezone(), "Europe/Berlin", "timezone check");
+}, 'TZDate_constructor_maximal_with_nonoptional_arguments');
+
+}
+
+function TZDate_constructor_maximal_with_optional_arguments() {
+//==== TEST: TZDate_constructor_maximal_with_optional_arguments
+//==== LABEL Test whether TZDate(date, timezone) constructor works
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TZDate:constructor C
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA CONSTRM CONSTRA
+test(function () {
+    var timezone = "Europe/Warsaw", date = new Date(2020, 2, 1), tzdate;
+    tzdate = new tizen.TZDate(date, timezone);
+    assert_type(tzdate, "object", "type check");
+    assert_equals(tzdate.getFullYear(), 2020, "date check");
+    assert_equals(tzdate.getTimezone(), "Europe/Warsaw", "timezone check");
+}, 'TZDate_constructor_maximal_with_optional_arguments');
+
+}
+
+function TZDate_constructor_minimal_with_nonoptional_arguments() {
+//==== TEST: TZDate_constructor_minimal_with_nonoptional_arguments
+//==== LABEL Test whether TZDate(y, m, d) constructor works
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TZDate:constructor C
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA CONSTRM CONSTRA
+test(function () {
+    var year = 2013, month = 2, day = 26, tzdate;
+    tzdate = new tizen.TZDate(year, month, day);
+    assert_type(tzdate, "object", "type check");
+    assert_equals(tzdate.getFullYear(), 2013, "year check");
+    assert_equals(tzdate.getMonth(), 2, "month check");
+    assert_equals(tzdate.getDay(), 2, "day check");
+}, 'TZDate_constructor_minimal_with_nonoptional_arguments');
+
+}
+
+function TZDate_constructor_minimal_without_optional_arguments() {
+//==== TEST: TZDate_constructor_minimal_without_optional_arguments
+//==== LABEL Test whether TZDate() constructor without arguments works
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TZDate:constructor C
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA CONSTRM
+test(function () {
+    var tzdate = new tizen.TZDate();
+    assert_type(tzdate, "object", "type check");
+}, 'TZDate_constructor_minimal_without_optional_arguments');
+
+}
+
+function TZDate_difference() {
+//==== TEST: TZDate_difference
+//==== LABEL Check if TZDate::difference() method works
+//==== SPEC: Tizen Web API:System:Time:TZDate:difference M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA MR
+test(function () {
+    var currentTZDate, other, returnedValue, date;
+    currentTZDate = new tizen.TZDate(2013, 6, 8);
+    date = new Date(2013, 3, 4);
+    other = new tizen.TZDate(date);
+    returnedValue = currentTZDate.difference(other);
+    assert_equals(returnedValue.length, 95, "returnedValue.length check");
+    assert_true(returnedValue instanceof tizen.TimeDuration, "TimeDuration chceck");
+}, 'TZDate_difference');
+
+}
+
+function TZDate_difference_exist() {
+//==== TEST: TZDate_difference_exist
+//==== LABEL Check if difference() method exists in TZDate
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TZDate:difference M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    assert_true("difference" in currentTZDate, "difference method exists");
+    check_method_exists(currentTZDate, "difference");
+}, 'TZDate_difference_exist');
+
+}
+
+function TZDate_difference_missarg() {
+//==== TEST: TZDate_difference_missarg
+//==== LABEL Check if TZDate::difference() throws exception with missing missing mandatory argument
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:System:Time:TZDate:difference M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMA
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    assert_throws(TYPE_MISMATCH_EXCEPTION,
+        function () {
+            currentTZDate.difference();
+        });
+}, 'TZDate_difference_missarg');
+
+}
+
+function TZDate_difference_other_TypeMismatch() {
+//==== TEST: TZDate_difference_other_TypeMismatch
+//==== LABEL Check if TZDate::difference() throws exception when other has wrong type
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:System:Time:TZDate:difference M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MC
+test(function () {
+    var currentTZDate, conversionTable, other, exceptionName, i;
+
+    currentTZDate = tizen.time.getCurrentDateTime();
+    conversionTable = getTypeConversionExceptions("enum", false);
+    for (i = 0; i < conversionTable.length; i++) {
+        other = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+
+        assert_throws({name: exceptionName},
+            function () {
+                currentTZDate.difference(other);
+            }, exceptionName + " should be thrown - given incorrect successCallback.");
+    }
+}, 'TZDate_difference_other_TypeMismatch');
+
+}
+
+function TZDate_difference_other_invalid_obj() {
+//==== TEST: TZDate_difference_other_invalid_obj
+//==== LABEL Check if TZDate::difference() throws exception when other is regural object
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:System:Time:TZDate:difference M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MTO
+test(function () {
+    var currentTZDate = [], exceptionName = TYPE_MISMATCH_ERR;
+
+    currentTZDate[0] = tizen.time.getCurrentDateTime();
+    currentTZDate[1] = {};
+    assert_throws(TYPE_MISMATCH_EXCEPTION,
+        function () {
+            currentTZDate[0].difference(currentTZDate[1]);
+        }, exceptionName + " should be thrown - given incorrect argument.");
+}, 'TZDate_difference_other_invalid_obj');
+
+}
+
+function TZDate_earlierThan() {
+//==== TEST: TZDate_earlierThan
+//==== LABEL Check if TZDate::earlierThan() method works
+//==== SPEC: Tizen Web API:System:Time:TZDate:earlierThan M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+test(function () {
+    var currentTZDate, other, returnedValue, date;
+    currentTZDate = tizen.time.getCurrentDateTime();
+    date = new Date(2013, 3, 4);
+    other = new tizen.TZDate(date);
+    returnedValue = currentTZDate.earlierThan(other);
+    assert_false(returnedValue, "false check");
+}, 'TZDate_earlierThan');
+
+}
+
+function TZDate_earlierThan_exist() {
+//==== TEST: TZDate_earlierThan_exist
+//==== LABEL Check if earlierThan() method exists in TZDate
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TZDate:earlierThan M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    assert_true("earlierThan" in currentTZDate, "earlierThan method exists");
+    check_method_exists(currentTZDate, "earlierThan");
+}, 'TZDate_earlierThan_exist');
+
+}
+
+function TZDate_earlierThan_missarg() {
+//==== TEST: TZDate_earlierThan_missarg
+//==== LABEL Check if TZDate::earlierThan() throws exception with missing mandatory argument
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:System:Time:TZDate:earlierThan M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMA
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    assert_throws(TYPE_MISMATCH_EXCEPTION,
+        function () {
+            currentTZDate.earlierThan();
+        });
+}, 'TZDate_earlierThan_missarg');
+
+}
+
+function TZDate_earlierThan_other_TypeMismatch() {
+//==== TEST: TZDate_earlierThan_other_TypeMismatch
+//==== LABEL Check if TZDate::earlierThan() throws exception when other has wrong type
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:System:Time:TZDate:earlierThan M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MC
+test(function () {
+    var currentTZDate, conversionTable, other, exceptionName, i;
+
+    currentTZDate = tizen.time.getCurrentDateTime();
+    conversionTable = getTypeConversionExceptions("functionObject", false);
+    for (i = 0; i < conversionTable.length; i++) {
+        other = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+
+        assert_throws({name: exceptionName},
+            function () {
+                currentTZDate.earlierThan(other);
+            }, exceptionName + " should be thrown - given incorrect successCallback.");
+    }
+}, 'TZDate_earlierThan_other_TypeMismatch');
+
+}
+
+function TZDate_earlierThan_other_invalid_obj() {
+//==== TEST: TZDate_earlierThan_other_invalid_obj
+//==== LABEL Check if TZDate::earlierThan() throws exception when other is regular object
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:System:Time:TZDate:earlierThan M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MTO
+test(function () {
+    var currentTZDate = [], exceptionName = TYPE_MISMATCH_ERR;
+
+    currentTZDate[0] = tizen.time.getCurrentDateTime();
+    currentTZDate[1] = {};
+    assert_throws(TYPE_MISMATCH_EXCEPTION,
+        function () {
+            currentTZDate[0].earlierThan(currentTZDate[1]);
+        }, exceptionName + " should be thrown - given incorrect argument.");
+}, 'TZDate_earlierThan_other_invalid_obj');
+
+}
+
+function TZDate_equalsTo() {
+//==== TEST: TZDate_equalsTo
+//==== LABEL Check if TZDate::equalsTo() method works
+//==== SPEC: Tizen Web API:System:Time:TZDate:equalsTo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA MR
+test(function () {
+    var currentTZDate, other, returnedValue, date;
+    currentTZDate = tizen.time.getCurrentDateTime();
+    date = new Date(2013, 3, 4);
+    other = new tizen.TZDate(date);
+    returnedValue = currentTZDate.equalsTo(other);
+    assert_false(returnedValue, "false check");
+}, 'TZDate_equalsTo');
+
+}
+
+function TZDate_equalsTo_exist() {
+//==== TEST: TZDate_equalsTo_exist
+//==== LABEL Check if equalsTo() method exists in TZDate
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TZDate:equalsTo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    assert_true("equalsTo" in currentTZDate, "equalsTo method exists");
+    check_method_exists(currentTZDate, "equalsTo");
+}, 'TZDate_equalsTo_exist');
+
+}
+
+function TZDate_equalsTo_missarg() {
+//==== TEST: TZDate_equalsTo_missarg
+//==== LABEL Check if TZDate::equalsTo() throws exception with missing mandatory argument
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:System:Time:TZDate:equalsTo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMA
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    assert_throws(TYPE_MISMATCH_EXCEPTION,
+        function () {
+            currentTZDate.equalsTo();
+        });
+}, 'TZDate_equalsTo_missarg');
+
+}
+
+function TZDate_equalsTo_other_TypeMismatch() {
+//==== TEST: TZDate_equalsTo_other_TypeMismatch
+//==== LABEL Check if TZDate::equalsTo() throws exception when other has wrong type
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:System:Time:TZDate:equalsTo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MC
+test(function () {
+    var currentTZDate, conversionTable, other, exceptionName, i;
+
+    currentTZDate = tizen.time.getCurrentDateTime();
+    conversionTable = getTypeConversionExceptions("functionObject", false);
+    for (i = 0; i < conversionTable.length; i++) {
+        other = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+
+        assert_throws({name: exceptionName},
+            function () {
+                currentTZDate.equalsTo(other);
+            }, exceptionName + " should be thrown - given incorrect successCallback.");
+    }
+}, 'TZDate_equalsTo_other_TypeMismatch');
+
+}
+
+function TZDate_equalsTo_other_invalid_obj() {
+//==== TEST: TZDate_equalsTo_other_invalid_obj
+//==== LABEL Check if TZDate::equalsTo() throws exception when other is regural object
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:System:Time:TZDate:equalsTo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MTO
+test(function () {
+    var currentTZDate = [], exceptionName = TYPE_MISMATCH_ERR;
+
+    currentTZDate[0] = tizen.time.getCurrentDateTime();
+    currentTZDate[1] = {};
+    assert_throws(TYPE_MISMATCH_EXCEPTION,
+        function () {
+            currentTZDate[0].equalsTo(currentTZDate[1]);
+        }, exceptionName + " should be thrown - given incorrect argument.");
+}, 'TZDate_equalsTo_other_invalid_obj');
+
+}
+
+function TZDate_exist() {
+//==== TEST: TZDate_exist
+//==== LABEL Test whether the constructor of the TZDate interface is defined
+//==== PRIORITY: P0
+//==== SPEC: Tizen Web API:System:Time:TZDate:constructor C
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA CONSTRF
+test(function () {
+    check_constructor("TZDate");
+}, 'TZDate_exist');
+
+}
+
+function TZDate_extend() {
+//==== TEST: TZDate_extend
+//==== LABEL Test whether the TZDate object can have new attribute added
+//==== PRIORITY: P3
+//==== SPEC: Tizen Web API:System:Time:TZDate:TZDate U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA OBX
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    check_extensibility(currentTZDate);
+}, 'TZDate_extend');
+
+}
+
+function TZDate_getDate() {
+//==== TEST: TZDate_getDate
+//==== LABEL Check if TZDate::getDate() method returns valid number
+//==== SPEC: Tizen Web API:System:Time:TZDate:getDate M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var date = new tizen.TZDate();
+    assert_true((date.getDate() >= 1 && date.getDate() <= 31), "date check");
+    assert_type(date.getDate(), "long", "type check");
+}, 'TZDate_getDate');
+
+}
+
+function TZDate_getDate_for_specific_date() {
+//==== TEST: TZDate_getDate_for_specific_date
+//==== LABEL Check whether Tizen.TZDate.getDate() for specific date
+//==== SPEC Tizen Web API:System:Time:TZDate:getDate M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MR MNA 
+test(function () {
+    var currentTZDate, returnedValue, date;
+    date = new Date(2013, 3, 4);
+    currentTZDate = new tizen.TZDate(date);
+    returnedValue = currentTZDate.getDate();
+    assert_equals(returnedValue, 4, "date check");
+}, 'TZDate_getDate_for_specific_date');
+
+}
+
+function TZDate_getDate_exist() {
+//==== TEST: TZDate_getDate_exist
+//==== LABEL Check if getDate() method exists in TZDate
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TZDate:getDate M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    assert_true("getDate" in currentTZDate, "getDate method exists");
+    check_method_exists(currentTZDate, "getDate");
+}, 'TZDate_getDate_exist');
+
+}
+
+function TZDate_getDate_extra_argument() {
+//==== TEST: TZDate_getDate_extra_argument
+//==== LABEL Check if TZDate::getDate() method accepts extra argument
+//==== SPEC: Tizen Web API:System:Time:TZDate:getDate M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNAEX
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    checkExtraArgument(currentTZDate, "getDate");
+}, 'TZDate_getDate_extra_argument');
+
+}
+
+function TZDate_getDay() {
+//==== TEST: TZDate_getDay
+//==== LABEL Check if TZDate::getDay() method returns valid number
+//==== SPEC: Tizen Web API:System:Time:TZDate:getDay M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var date = new tizen.TZDate();
+    assert_true((date.getDay() >= 0 && date.getDay() <= 6), "data check");
+    assert_type(date.getDay(), "long", "type check");
+}, 'TZDate_getDay');
+
+}
+
+function TZDate_getDay_for_specific_date() {
+//==== TEST: TZDate_getDay_for_specific_date
+//==== LABEL Check whether Tizen.TZDate.getDay() for specific date
+//==== SPEC Tizen Web API:System:Time:TZDate:getDay M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MR MNA
+test(function () {
+    var currentTZDate, returnedValue, date;
+    date = new Date(2013, 2, 27);
+    currentTZDate = new tizen.TZDate(date);
+    returnedValue = currentTZDate.getDay();
+    assert_equals(returnedValue, 3, "day check");
+}, 'TZDate_getDay_for_specific_date');
+
+}
+
+function TZDate_getDay_exist() {
+//==== TEST: TZDate_getDay_exist
+//==== LABEL Check if getDay() method exists in TZDate
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TZDate:getDay M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    assert_true("getDay" in currentTZDate, "getDay method exists");
+    check_method_exists(currentTZDate, "getDay");
+}, 'TZDate_getDay_exist');
+
+}
+
+function TZDate_getDay_extra_argument() {
+//==== TEST: TZDate_getDay_extra_argument
+//==== LABEL Check if TZDate::getDay() method accepts extra argument
+//==== SPEC: Tizen Web API:System:Time:TZDate:getDay M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNAEX
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    checkExtraArgument(currentTZDate, "getDay");
+}, 'TZDate_getDay_extra_argument');
+
+}
+
+function TZDate_getFullYear() {
+//==== TEST: TZDate_getFullYear
+//==== LABEL Check if TZDate::getFullYear() returns valid number
+//==== SPEC: Tizen Web API:System:Time:TZDate:getFullYear M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var date = new tizen.TZDate();
+    assert_true(date.getFullYear() >= 1000 && date.getFullYear() <= 9999, "data check");
+    assert_type(date.getFullYear(), "long", "type check");
+}, 'TZDate_getFullYear');
+
+}
+
+function TZDate_getFullYear_for_specific_date() {
+//==== TEST: TZDate_getFullYear_for_specific_date
+//==== LABEL Check whether Tizen.TZDate.getFullYear() for specific date
+//==== SPEC Tizen Web API:System:Time:TZDate:getFullYear M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MR MNA
+test(function () {
+    var currentTZDate, returnedValue, date;
+    date = new Date(2013, 2, 27);
+    currentTZDate = new tizen.TZDate(date);
+    returnedValue = currentTZDate.getFullYear();
+    assert_equals(returnedValue, 2013, "year check");
+}, 'TZDate_getFullYear_for_specific_date');
+
+}
+
+function TZDate_getFullYear_exist() {
+//==== TEST: TZDate_getFullYear_exist
+//==== LABEL Check if getFullYear() method exists in TZDate
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TZDate:getFullYear M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    assert_true("getFullYear" in currentTZDate, "getFullYear method exists");
+    check_method_exists(currentTZDate, "getFullYear");
+}, 'TZDate_getFullYear_exist');
+
+}
+
+function TZDate_getFullYear_extra_argument() {
+//==== TEST: TZDate_getFullYear_extra_argument
+//==== LABEL Check if TZDate::getFullYear() method accepts extra argument
+//==== SPEC: Tizen Web API:System:Time:TZDate:getFullYear M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNAEX
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    checkExtraArgument(currentTZDate, "getFullYear");
+}, 'TZDate_getFullYear_extra_argument');
+
+}
+
+function TZDate_getHours() {
+//==== TEST: TZDate_getHours
+//==== LABEL Check if TZDate::getHours() returns valid number
+//==== SPEC: Tizen Web API:System:Time:TZDate:getHours M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var date = new tizen.TZDate();
+    assert_true(date.getHours() >= 0 && date.getHours() <= 23, "data check");
+    assert_type(date.getHours(), "long", "type check");
+}, 'TZDate_getHours');
+
+}
+
+function TZDate_getHours_for_specific_date() {
+//==== TEST: TZDate_getHours_for_specific_date
+//==== LABEL Check whether Tizen.TZDate.getHours() for specific date
+//==== SPEC Tizen Web API:System:Time:TZDate:getHours M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MR MNA
+test(function () {
+    var currentTZDate, returnedValue, date;
+    date = new Date(2013, 2, 27, 13);
+    currentTZDate = new tizen.TZDate(date);
+    returnedValue = currentTZDate.getHours();
+    assert_equals(returnedValue, 13, "hours check");
+}, 'TZDate_getHours_for_specific_date');
+
+}
+
+function TZDate_getHours_exist() {
+//==== TEST: TZDate_getHours_exist
+//==== LABEL Check if TZDate::getHours() method exists in TZDate
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TZDate:getHours M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    assert_true("getHours" in currentTZDate, "getHours method exists");
+    check_method_exists(currentTZDate, "getHours");
+}, 'TZDate_getHours_exist');
+
+}
+
+function TZDate_getHours_extra_argument() {
+//==== TEST: TZDate_getHours_extra_argument
+//==== LABEL Check if TZDate::getHours() method accepts extra argument
+//==== SPEC: Tizen Web API:System:Time:TZDate:getHours M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNAEX
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    checkExtraArgument(currentTZDate, "getHours");
+}, 'TZDate_getHours_extra_argument');
+
+}
+
+function TZDate_getMilliseconds() {
+//==== TEST: TZDate_getMilliseconds
+//==== LABEL Check if TZDate::getMilliseconds() returns valid number
+//==== SPEC: Tizen Web API:System:Time:TZDate:getMilliseconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var date = new tizen.TZDate();
+    assert_true(date.getMilliseconds() >= 0 && date.getMilliseconds() <= 999, "data check");
+    assert_type(date.getMilliseconds(), "long", "type check");
+}, 'TZDate_getMilliseconds');
+
+}
+
+function TZDate_getMilliseconds_for_specific_date() {
+//==== TEST: TZDate_getMilliseconds_for_specific_date
+//==== LABEL Check whether Tizen.TZDate.getMilliseconds() for specific date
+//==== SPEC Tizen Web API:System:Time:TZDate:getMilliseconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MR MNA
+test(function () {
+    var currentTZDate, returnedValue, date;
+    date = new Date(2013, 2, 27, 13, 14, 32, 200);
+    currentTZDate = new tizen.TZDate(date);
+    returnedValue = currentTZDate.getMilliseconds();
+    assert_equals(returnedValue, 200, "milliseconds check");
+}, 'TZDate_getMilliseconds_for_specific_date');
+
+}
+
+function TZDate_getMilliseconds_exist() {
+//==== TEST: TZDate_getMilliseconds_exist
+//==== LABEL Check if getMilliseconds() method exists in TZDate
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TZDate:getMilliseconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    assert_true("getMilliseconds" in currentTZDate, "getMilliseconds method exists");
+    check_method_exists(currentTZDate, "getMilliseconds");
+}, 'TZDate_getMilliseconds_exist');
+
+}
+
+function TZDate_getMilliseconds_extra_argument() {
+//==== TEST: TZDate_getMilliseconds_extra_argument
+//==== LABEL Check if TZDate::getMilliseconds() method accepts extra argument
+//==== SPEC: Tizen Web API:System:Time:TZDate:getMilliseconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNAEX
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    checkExtraArgument(currentTZDate, "getMilliseconds");
+}, 'TZDate_getMilliseconds_extra_argument');
+
+}
+
+function TZDate_getMinutes() {
+//==== TEST: TZDate_getMinutes
+//==== LABEL Check if TZDate::getMinutes() returns valid number
+//==== SPEC: Tizen Web API:System:Time:TZDate:getMinutes M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var date = new tizen.TZDate();
+    assert_true(date.getMinutes() >= 0 && date.getMinutes() <= 59, "data check");
+    assert_type(date.getMinutes(), "long", "type check");
+}, 'TZDate_getMinutes');
+
+}
+
+function TZDate_getMinutes_for_specific_date() {
+//==== TEST: TZDate_getMinutes_for_specific_date
+//==== LABEL Check whether Tizen.TZDate.getMinutes() for specific date
+//==== SPEC Tizen Web API:System:Time:TZDate:getMinutes M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MR MNA
+test(function () {
+    var currentTZDate, returnedValue, date;
+    date = new Date(2013, 2, 27, 13, 32);
+    currentTZDate = new tizen.TZDate(date);
+    returnedValue = currentTZDate.getMinutes();
+    assert_equals(returnedValue, 32, "minutes check");
+}, 'TZDate_getMinutes_for_specific_date');
+
+}
+
+function TZDate_getMinutes_exist() {
+//==== TEST: TZDate_getMinutes_exist
+//==== LABEL Check if getMinutes() method exists in TZDate
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TZDate:getMinutes M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    assert_true("getMinutes" in currentTZDate, "getMinutes method exists");
+    check_method_exists(currentTZDate, "getMinutes");
+}, 'TZDate_getMinutes_exist');
+
+}
+
+function TZDate_getMinutes_extra_argument() {
+//==== TEST: TZDate_getMinutes_extra_argument
+//==== LABEL Check if TZDate::getMinutes() method accepts extra argument
+//==== SPEC: Tizen Web API:System:Time:TZDate:getMinutes M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNAEX
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    checkExtraArgument(currentTZDate, "getMinutes");
+}, 'TZDate_getMinutes_extra_argument');
+
+}
+
+function TZDate_getMonth() {
+//==== TEST: TZDate_getMonth
+//==== LABEL Check if TZDate::getMonth() returns valid number
+//==== SPEC: Tizen Web API:System:Time:TZDate:getMonth M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var date = new tizen.TZDate();
+    assert_true(date.getMonth() >= 0 && date.getMonth() <= 11, "data check");
+    assert_type(date.getMonth(), "long", "type check");
+}, 'TZDate_getMonth');
+
+}
+
+function TZDate_getMonth_for_specific_date() {
+//==== TEST: TZDate_getMonth_for_specific_date
+//==== LABEL Check whether Tizen.TZDate.getMonth() for specific date
+//==== SPEC Tizen Web API:System:Time:TZDate:getMonth M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MR MNA
+test(function () {
+    var currentTZDate, returnedValue, date;
+    date = new Date(2013, 2, 27);
+    currentTZDate = new tizen.TZDate(date);
+    returnedValue = currentTZDate.getMonth();
+    assert_equals(returnedValue, 2, "month check");
+}, 'TZDate_getMonth_for_specific_date');
+
+}
+
+function TZDate_getMonth_exist() {
+//==== TEST: TZDate_getMonth_exist
+//==== LABEL Check if getMonth() method exists in TZDate
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TZDate:getMonth M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    assert_true("getMonth" in currentTZDate, "getMonth method exists");
+    check_method_exists(currentTZDate, "getMonth");
+}, 'TZDate_getMonth_exist');
+
+}
+
+function TZDate_getMonth_extra_argument() {
+//==== TEST: TZDate_getMonth_extra_argument
+//==== LABEL Check if TZDate::getMonth() method accepts extra argument
+//==== SPEC: Tizen Web API:System:Time:TZDate:getMonth M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNAEX
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    checkExtraArgument(currentTZDate, "getMonth");
+}, 'TZDate_getMonth_extra_argument');
+
+}
+
+function TZDate_getNextDSTTransition() {
+//==== TEST: TZDate_getNextDSTTransition
+//==== LABEL Check if TZDate::getNextDSTTransition() returns a either date or null
+//==== SPEC: Tizen Web API:System:Time:TZDate:getNextDSTTransition M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var currentTZDate, returnedValue, date;
+    date = new Date(2013, 2, 27);
+    currentTZDate = new tizen.TZDate(date);
+    returnedValue = currentTZDate.getNextDSTTransition();
+    assert_true(returnedValue instanceof tizen.TZDate || returnedValue === null, "data check");
+}, 'TZDate_getNextDSTTransition');
+
+}
+
+function TZDate_getNextDSTTransition_exist() {
+//==== TEST: TZDate_getNextDSTTransition_exist
+//==== LABEL Check if getNextDSTTransition() method exists in TZDate
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TZDate:getNextDSTTransition M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    assert_true("getNextDSTTransition" in currentTZDate, "getNextDSTTransition method exists");
+    check_method_exists(currentTZDate, "getNextDSTTransition");
+}, 'TZDate_getNextDSTTransition_exist');
+
+}
+
+function TZDate_getNextDSTTransition_extra_argument() {
+//==== TEST: TZDate_getNextDSTTransition_extra_argument
+//==== LABEL Check if TZDate::getNextDSTTransition() method accepts extra argument
+//==== SPEC: Tizen Web API:System:Time:TZDate:getNextDSTTransition M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNAEX
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    checkExtraArgument(currentTZDate, "getNextDSTTransition");
+}, 'TZDate_getNextDSTTransition_extra_argument');
+
+}
+
+function TZDate_getPreviousDSTTransition() {
+//==== TEST: TZDate_getPreviousDSTTransition
+//==== LABEL Check if TZDate::getPreviousDSTTransition() returns a either date or null
+//==== SPEC: Tizen Web API:System:Time:TZDate:getPreviousDSTTransition M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var currentTZDate, returnedValue, date;
+    date = new Date(2013, 2, 27);
+    currentTZDate = new tizen.TZDate(date);
+    returnedValue = currentTZDate.getPreviousDSTTransition();
+    assert_true(returnedValue instanceof tizen.TZDate || returnedValue === null, "data check");
+}, 'TZDate_getPreviousDSTTransition');
+
+}
+
+function TZDate_getPreviousDSTTransition_exist() {
+//==== TEST: TZDate_getPreviousDSTTransition_exist
+//==== LABEL Check if getPreviousDSTTransition() method exists in TZDate
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TZDate:getPreviousDSTTransition M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    assert_true("getPreviousDSTTransition" in currentTZDate, "getPreviousDSTTransition method exists");
+    check_method_exists(currentTZDate, "getPreviousDSTTransition");
+}, 'TZDate_getPreviousDSTTransition_exist');
+
+}
+
+function TZDate_getPreviousDSTTransition_extra_argument() {
+//==== TEST: TZDate_getPreviousDSTTransition_extra_argument
+//==== LABEL Check if TZDate::getPreviousDSTTransition() method accepts extra argument
+//==== SPEC: Tizen Web API:System:Time:TZDate:getPreviousDSTTransition M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNAEX
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    checkExtraArgument(currentTZDate, "getPreviousDSTTransition");
+}, 'TZDate_getPreviousDSTTransition_extra_argument');
+
+}
+
+function TZDate_getSeconds() {
+//==== TEST: TZDate_getSeconds
+//==== LABEL Check if TZDate::getSeconds() returns valid number
+//==== SPEC: Tizen Web API:System:Time:TZDate:getSeconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var date = new tizen.TZDate();
+    assert_true(date.getSeconds() >= 0 && date.getSeconds() <= 59, "data check");
+    assert_type(date.getSeconds(), "long", "type check");
+}, 'TZDate_getSeconds');
+
+}
+
+function TZDate_getSeconds_for_specific_date() {
+//==== TEST: TZDate_getSeconds_for_specific_date
+//==== LABEL Check whether Tizen.TZDate.getSeconds() for specific date
+//==== SPEC Tizen Web API:System:Time:TZDate:getSeconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MR MNA
+test(function () {
+    var currentTZDate, returnedValue, date;
+    date = new Date(2013, 2, 27, 11, 32, 25);
+    currentTZDate = new tizen.TZDate(date);
+    returnedValue = currentTZDate.getSeconds();
+    assert_equals(returnedValue, 25, "seconds check");
+}, 'TZDate_getSeconds_for_specific_date');
+
+}
+
+function TZDate_getSeconds_exist() {
+//==== TEST: TZDate_getSeconds_exist
+//==== LABEL Check if getSeconds() method exists in TZDate
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TZDate:getSeconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    assert_true("getSeconds" in currentTZDate, "getSeconds method exists");
+    check_method_exists(currentTZDate, "getSeconds");
+}, 'TZDate_getSeconds_exist');
+
+}
+
+function TZDate_getSeconds_extra_argument() {
+//==== TEST: TZDate_getSeconds_extra_argument
+//==== LABEL Check if TZDate::getSeconds() method accepts extra argument
+//==== SPEC: Tizen Web API:System:Time:TZDate:getSeconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNAEX
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    checkExtraArgument(currentTZDate, "getSeconds");
+}, 'TZDate_getSeconds_extra_argument');
+
+}
+
+function TZDate_getTimezone() {
+//==== TEST: TZDate_getTimezone
+//==== LABEL Check if TZDate::getTimezone() returns a string
+//==== SPEC: Tizen Web API:System:Time:TZDate:getTimezone M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA
+test(function () {
+    var date = new tizen.TZDate();
+    assert_type(date.getTimezone(), "string", "type check");
+}, 'TZDate_getTimezone');
+
+}
+
+function TZDate_getTimezoneAbbreviation() {
+//==== TEST: TZDate_getTimezoneAbbreviation
+//==== LABEL Check if TZDate::getTimezoneAbbreviation() returns a string
+//==== SPEC: Tizen Web API:System:Time:TZDate:getTimezoneAbbreviation M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA
+
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime(), returnedValue;
+    returnedValue = currentTZDate.getTimezoneAbbreviation();
+    assert_type(returnedValue, "string", "type check");
+    assert_not_equals(returnedValue, null, "null check");
+}, 'TZDate_getTimezoneAbbreviation');
+
+}
+
+function TZDate_getTimezoneAbbreviation_exist() {
+//==== TEST: TZDate_getTimezoneAbbreviation_exist
+//==== LABEL Check if getTimezoneAbbreviation() method exists in TZDate
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TZDate:getTimezoneAbbreviation M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    assert_true("getTimezoneAbbreviation" in currentTZDate, "getTimezoneAbbreviation method exists");
+    check_method_exists(currentTZDate, "getTimezoneAbbreviation");
+}, 'TZDate_getTimezoneAbbreviation_exist');
+
+}
+
+function TZDate_getTimezoneAbbreviation_extra_argument() {
+//==== TEST: TZDate_getTimezoneAbbreviation_extra_argument
+//==== LABEL Check if TZDate::getTimezoneAbbreviation() method accepts extra argument
+//==== SPEC: Tizen Web API:System:Time:TZDate:getTimezoneAbbreviation M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNAEX
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    checkExtraArgument(currentTZDate, "getTimezoneAbbreviation");
+}, 'TZDate_getTimezoneAbbreviation_extra_argument');
+
+}
+
+function TZDate_getTimezone_for_specific_timezone() {
+//==== TEST: TZDate_getTimezone_for_specific_timezone
+//==== LABEL Check whether Tizen.TZDate.getTimezone() for specific timezone
+//==== SPEC Tizen Web API:System:Time:TZDate:getTimezone M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+
+test(function () {
+    var currentTZDate, returnedValue;
+    currentTZDate = new tizen.TZDate(null, "Europe/Berlin");
+    returnedValue = currentTZDate.getTimezone();
+    assert_equals(returnedValue, "Europe/Berlin", "timezone check");
+}, 'TZDate_getTimezone_for_specific_timezone');
+
+}
+
+function TZDate_getTimezone_exist() {
+//==== TEST: TZDate_getTimezone_exist
+//==== LABEL Check if getTimezone() method exists in TZDate
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TZDate:getTimezone M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    assert_true("getTimezone" in currentTZDate, "getTimezone method exists");
+    check_method_exists(currentTZDate, "getTimezone");
+}, 'TZDate_getTimezone_exist');
+
+}
+
+function TZDate_getTimezone_extra_argument() {
+//==== TEST: TZDate_getTimezone_extra_argument
+//==== LABEL Check if TZDate::getTimezone() method accepts extra argument
+//==== SPEC: Tizen Web API:System:Time:TZDate:getTimezone M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNAEX
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    checkExtraArgument(currentTZDate, "getTimezone");
+}, 'TZDate_getTimezone_extra_argument');
+
+}
+
+function TZDate_getUTCDate() {
+//==== TEST: TZDate_getUTCDate
+//==== LABEL Check if TZDate::getUTCDate() returns valid number
+//==== SPEC: Tizen Web API:System:Time:TZDate:getUTCDate M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var date = new tizen.TZDate();
+    assert_true(date.getUTCDate() >= 1 && date.getUTCDate() <= 31, "data check");
+    assert_type(date.getUTCDate(), "long", "type check");
+}, 'TZDate_getUTCDate');
+
+}
+
+function TZDate_getUTCDate_for_specific_date() {
+//==== TEST: TZDate_getUTCDate_for_specific_date
+//==== LABEL Check whether Tizen.TZDate.getUTCDate() for specific date
+//==== SPEC Tizen Web API:System:Time:TZDate:getUTCDate M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MR MNA
+test(function () {
+    var currentTZDate, returnedValue, date;
+    date = new Date(2013, 2, 27, 8);
+    currentTZDate = new tizen.TZDate(date);
+    returnedValue = currentTZDate.getUTCDate();
+    assert_equals(returnedValue, 26, "date check");
+}, 'TZDate_getUTCDate_for_specific_date');
+
+}
+
+function TZDate_getUTCDate_exist() {
+//==== TEST: TZDate_getUTCDate_exist
+//==== LABEL Check if getUTCDate() method exists in TZDate
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TZDate:getUTCDate M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    assert_true("getUTCDate" in currentTZDate, "getUTCDate method exists");
+    check_method_exists(currentTZDate, "getUTCDate");
+}, 'TZDate_getUTCDate_exist');
+
+}
+
+function TZDate_getUTCDate_extra_argument() {
+//==== TEST: TZDate_getUTCDate_extra_argument
+//==== LABEL Check if TZDate::getUTCDate() method accepts extra argument
+//==== SPEC: Tizen Web API:System:Time:TZDate:getUTCDate M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNAEX
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    checkExtraArgument(currentTZDate, "getUTCDate");
+}, 'TZDate_getUTCDate_extra_argument');
+
+}
+
+function TZDate_getUTCDay() {
+//==== TEST: TZDate_getUTCDay
+//==== LABEL Check if TZDate::getUTCDay() returns valid number
+//==== SPEC: Tizen Web API:System:Time:TZDate:getUTCDay M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var date = new tizen.TZDate();
+    assert_true(date.getUTCDay() >= 0 && date.getUTCDay() <= 6, "data check");
+    assert_type(date.getUTCDay(), "long", "type check");
+}, 'TZDate_getUTCDay');
+
+}
+
+function TZDate_getUTCDay_for_specific_date() {
+//==== TEST: TZDate_getUTCDay_for_specific_date
+//==== LABEL Check whether Tizen.TZDate.getUTCDay() for specific date
+//==== SPEC Tizen Web API:System:Time:TZDate:getUTCDay M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MR MNA
+test(function () {
+    var currentTZDate, returnedValue, date;
+    date = new Date(2013, 2, 27);
+    currentTZDate = new tizen.TZDate(date);
+    returnedValue = currentTZDate.getUTCDay();
+    assert_equals(returnedValue, 2, "day check");
+}, 'TZDate_getUTCDay_for_specific_date');
+
+}
+
+function TZDate_getUTCDay_exist() {
+//==== TEST: TZDate_getUTCDay_exist
+//==== LABEL Check if getUTCDay() method exists in TZDate
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TZDate:getUTCDay M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    assert_true("getUTCDay" in currentTZDate, "getUTCDay method exists");
+    check_method_exists(currentTZDate, "getUTCDay");
+}, 'TZDate_getUTCDay_exist');
+
+}
+
+function TZDate_getUTCDay_extra_argument() {
+//==== TEST: TZDate_getUTCDay_extra_argument
+//==== LABEL Check if TZDate::getUTCDay() method accepts extra argument
+//==== SPEC: Tizen Web API:System:Time:TZDate:getUTCDay M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNAEX
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    checkExtraArgument(currentTZDate, "getUTCDay");
+}, 'TZDate_getUTCDay_extra_argument');
+
+}
+
+function TZDate_getUTCFullYear() {
+//==== TEST: TZDate_getUTCFullYear
+//==== LABEL Check if TZDate::getUTCFullYear() returns valid number
+//==== SPEC: Tizen Web API:System:Time:TZDate:getUTCFullYear M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var date = new tizen.TZDate();
+    assert_true(date.getUTCFullYear() >= 1000 && date.getUTCFullYear() <= 9999, "data check");
+    assert_type(date.getUTCFullYear(), "long", "type check");
+}, 'TZDate_getUTCFullYear');
+
+}
+
+function TZDate_getUTCFullYear_for_specific_date() {
+//==== TEST: TZDate_getUTCFullYear_for_specific_date
+//==== LABEL Check whether Tizen.TZDate.getUTCFullYear() for specific date
+//==== SPEC Tizen Web API:System:Time:TZDate:getUTCFullYear M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MR MNA
+test(function () {
+    var currentTZDate, returnedValue, date;
+    date = new Date(2013, 2, 27);
+    currentTZDate = new tizen.TZDate(date);
+    returnedValue = currentTZDate.getUTCFullYear();
+    assert_equals(returnedValue, 2013, "year check");
+}, 'TZDate_getUTCFullYear_for_specific_date');
+
+}
+
+function TZDate_getUTCFullYear_exist() {
+//==== TEST: TZDate_getUTCFullYear_exist
+//==== LABEL Check if getUTCFullYear() method exists in TZDate
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TZDate:getUTCFullYear M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    assert_true("getUTCFullYear" in currentTZDate, "getUTCFullYear method exists");
+    check_method_exists(currentTZDate, "getUTCFullYear");
+}, 'TZDate_getUTCFullYear_exist');
+
+}
+
+function TZDate_getUTCFullYear_extra_argument() {
+//==== TEST: TZDate_getUTCFullYear_extra_argument
+//==== LABEL Check if TZDate::getUTCFullYear() method accepts extra argument
+//==== SPEC: Tizen Web API:System:Time:TZDate:getUTCFullYear M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNAEX
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    checkExtraArgument(currentTZDate, "getUTCFullYear");
+}, 'TZDate_getUTCFullYear_extra_argument');
+
+}
+
+function TZDate_getUTCHours() {
+//==== TEST: TZDate_getUTCHours
+//==== LABEL Check if TZDate::getUTCHours() returns valid number
+//==== SPEC: Tizen Web API:System:Time:TZDate:getUTCHours M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var date = new tizen.TZDate();
+    assert_true(date.getUTCHours() >= 0 && date.getUTCHours() <= 23, "data check");
+    assert_type(date.getUTCHours(), "long", "type check");
+}, 'TZDate_getUTCHours');
+
+}
+
+function TZDate_getUTCHours_for_specific_date() {
+//==== TEST: TZDate_getUTCHours_for_specific_date
+//==== LABEL Check whether Tizen.TZDate.getUTCHours() for specific date
+//==== SPEC Tizen Web API:System:Time:TZDate:getUTCHours M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MR MNA
+test(function () {
+    var currentTZDate, returnedValue, date, hour = 18;
+    date = new Date(2013, 2, 27, hour);
+    currentTZDate = new tizen.TZDate(date);
+    returnedValue = currentTZDate.getUTCHours();
+    assert_equals(returnedValue, hour - expected_time_zone_offset, "hours check");
+}, 'TZDate_getUTCHours_for_specific_date');
+
+}
+
+function TZDate_getUTCHours_exist() {
+//==== TEST: TZDate_getUTCHours_exist
+//==== LABEL Check if getUTCHours() method exists in TZDate
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TZDate:getUTCHours M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    assert_true("getUTCHours" in currentTZDate, "getUTCHours method exists");
+    check_method_exists(currentTZDate, "getUTCHours");
+}, 'TZDate_getUTCHours_exist');
+
+}
+
+function TZDate_getUTCHours_extra_argument() {
+//==== TEST: TZDate_getUTCHours_extra_argument
+//==== LABEL Check if method TZDate::getUTCHours() method accepts extra argument
+//==== SPEC: Tizen Web API:System:Time:TZDate:getUTCHours M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNAEX
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    checkExtraArgument(currentTZDate, "getUTCHours");
+}, 'TZDate_getUTCHours_extra_argument');
+
+}
+
+function TZDate_getUTCMilliseconds() {
+//==== TEST: TZDate_getUTCMilliseconds
+//==== LABEL Check if TZDate::getUTCMilliseconds() returns valid number
+//==== SPEC: Tizen Web API:System:Time:TZDate:getUTCMilliseconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var date = new tizen.TZDate();
+    assert_true(date.getUTCMilliseconds() >= 0 && date.getUTCMilliseconds() <= 999, "data check");
+    assert_type(date.getUTCMilliseconds(), "long", "type check");
+}, 'TZDate_getUTCMilliseconds');
+
+}
+
+function TZDate_getUTCMilliseconds_for_specific_date() {
+//==== TEST: TZDate_getUTCMilliseconds_for_specific_date
+//==== LABEL Check whether Tizen.TZDate.getUTCMilliseconds() for specific date
+//==== SPEC Tizen Web API:System:Time:TZDate:getUTCMilliseconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MR MNA
+test(function () {
+    var currentTZDate, returnedValue, date;
+    date = new Date(2013, 2, 27, 18, 43, 26, 78);
+    currentTZDate = new tizen.TZDate(date);
+    returnedValue = currentTZDate.getUTCMilliseconds();
+    assert_equals(returnedValue, 78, "milliseconds check");
+}, 'TZDate_getUTCMilliseconds_for_specific_date');
+
+}
+
+function TZDate_getUTCMilliseconds_exist() {
+//==== TEST: TZDate_getUTCMilliseconds_exist
+//==== LABEL Check if getUTCMilliseconds() method exists in TZDate
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TZDate:getUTCMilliseconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    assert_true("getUTCMilliseconds" in currentTZDate, "getUTCMilliseconds method exists");
+    check_method_exists(currentTZDate, "getUTCMilliseconds");
+}, 'TZDate_getUTCMilliseconds_exist');
+
+}
+
+function TZDate_getUTCMilliseconds_extra_argument() {
+//==== TEST: TZDate_getUTCMilliseconds_extra_argument
+//==== LABEL Check if TZDate::getUTCMilliseconds() method accepts extra argument
+//==== SPEC: Tizen Web API:System:Time:TZDate:getUTCMilliseconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNAEX
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    checkExtraArgument(currentTZDate, "getUTCMilliseconds");
+}, 'TZDate_getUTCMilliseconds_extra_argument');
+
+}
+
+function TZDate_getUTCMinutes() {
+//==== TEST: TZDate_getUTCMinutes
+//==== LABEL Check if TZDate::getUTCMinutes() returns valid number
+//==== SPEC: Tizen Web API:System:Time:TZDate:getUTCMinutes M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var date = new tizen.TZDate();
+    assert_true(date.getUTCMinutes() >= 0 && date.getUTCMinutes() <= 59, "data check");
+    assert_type(date.getUTCMinutes(), "long", "type check");
+}, 'TZDate_getUTCMinutes');
+
+}
+
+function TZDate_getUTCMinutes_for_specific_date() {
+//==== TEST: TZDate_getUTCMinutes_for_specific_date
+//==== LABEL Check whether Tizen.TZDate.getUTCMinutes() for specific date
+//==== SPEC Tizen Web API:System:Time:TZDate:getUTCMinutes M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MR MNA
+test(function () {
+    var currentTZDate, returnedValue, date;
+    date = new Date(2013, 2, 27, 18, 43);
+    currentTZDate = new tizen.TZDate(date);
+    returnedValue = currentTZDate.getUTCMinutes();
+    assert_equals(returnedValue, 43, "minutes check");
+}, 'TZDate_getUTCMinutes_for_specific_date');
+
+}
+
+function TZDate_getUTCMinutes_exist() {
+//==== TEST: TZDate_getUTCMinutes_exist
+//==== LABEL Check if getUTCMinutes() method exists in TZDate
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TZDate:getUTCMinutes M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    assert_true("getUTCMinutes" in currentTZDate, "getUTCMinutes method exists");
+    check_method_exists(currentTZDate, "getUTCMinutes");
+}, 'TZDate_getUTCMinutes_exist');
+
+}
+
+function TZDate_getUTCMinutes_extra_argument() {
+//==== TEST: TZDate_getUTCMinutes_extra_argument
+//==== LABEL Check if TZDate::getUTCMinutes() method accepts extra argument
+//==== SPEC: Tizen Web API:System:Time:TZDate:getUTCMinutes M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNAEX
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    checkExtraArgument(currentTZDate, "getUTCMinutes");
+}, 'TZDate_getUTCMinutes_extra_argument');
+
+}
+
+function TZDate_getUTCMonth() {
+//==== TEST: TZDate_getUTCMonth
+//==== LABEL Check if TZDate::getUTCMonth() returns valid number
+//==== SPEC: Tizen Web API:System:Time:TZDate:getUTCMonth M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var date = new tizen.TZDate();
+    assert_true(date.getUTCMonth() >= 0 && date.getUTCMonth() <= 11, "data check");
+    assert_type(date.getUTCMonth(), "long", "type check");
+}, 'TZDate_getUTCMonth');
+
+}
+
+function TZDate_getUTCMonth_for_specific_date() {
+//==== TEST: TZDate_getUTCMonth_for_specific_date
+//==== LABEL Check whether Tizen.TZDate.getUTCMonth() for specific date
+//==== SPEC Tizen Web API:System:Time:TZDate:getUTCMonth M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MR MNA
+test(function () {
+    var currentTZDate, returnedValue, date;
+    date = new Date(2013, 2, 27);
+    currentTZDate = new tizen.TZDate(date);
+    returnedValue = currentTZDate.getUTCMonth();
+    assert_equals(returnedValue, 2, "month check");
+}, 'TZDate_getUTCMonth_for_specific_date');
+
+}
+
+function TZDate_getUTCMonth_exist() {
+//==== TEST: TZDate_getUTCMonth_exist
+//==== LABEL Check if getUTCMonth() method exists in TZDate
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TZDate:getUTCMonth M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    assert_true("getUTCMonth" in currentTZDate, "getUTCMonth method exists");
+    check_method_exists(currentTZDate, "getUTCMonth");
+}, 'TZDate_getUTCMonth_exist');
+
+}
+
+function TZDate_getUTCMonth_extra_argument() {
+//==== TEST: TZDate_getUTCMonth_extra_argument
+//==== LABEL Check if TZDate::getUTCMonth() method accepts extra argument
+//==== SPEC: Tizen Web API:System:Time:TZDate:getUTCMonth M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNAEX
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    checkExtraArgument(currentTZDate, "getUTCMonth");
+}, 'TZDate_getUTCMonth_extra_argument');
+
+}
+
+function TZDate_getUTCSeconds() {
+//==== TEST: TZDate_getUTCSeconds
+//==== LABEL Check if TZDate::getUTCSeconds() returns valid number
+//==== SPEC: Tizen Web API:System:Time:TZDate:getUTCSeconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var date = new tizen.TZDate();
+    assert_true(date.getUTCSeconds() >= 0 && date.getUTCSeconds() <= 59, "data check");
+    assert_type(date.getUTCSeconds(), "long", "type check");
+}, 'TZDate_getUTCSeconds');
+
+}
+
+function TZDate_getUTCSeconds_for_specific_date() {
+//==== TEST: TZDate_getUTCSeconds_for_specific_date
+//==== LABEL Check whether Tizen.TZDate.getUTCSeconds() for specific date
+//==== SPEC Tizen Web API:System:Time:TZDate:getUTCSeconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MR MNA
+test(function () {
+    var currentTZDate, returnedValue, date;
+    date = new Date(2013, 2, 27, 13, 23, 43);
+    currentTZDate = new tizen.TZDate(date);
+    returnedValue = currentTZDate.getUTCSeconds();
+    assert_equals(returnedValue, 43, "seconds check");
+}, 'TZDate_getUTCSeconds_for_specific_date');
+
+}
+
+function TZDate_getUTCSeconds_exist() {
+//==== TEST: TZDate_getUTCSeconds_exist
+//==== LABEL Check if getUTCSeconds() method exists in TZDate
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TZDate:getUTCSeconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    assert_true("getUTCSeconds" in currentTZDate, "getUTCSeconds method exists");
+    check_method_exists(currentTZDate, "getUTCSeconds");
+}, 'TZDate_getUTCSeconds_exist');
+
+}
+
+function TZDate_getUTCSeconds_extra_argument() {
+//==== TEST: TZDate_getUTCSeconds_extra_argument
+//==== LABEL Check if TZDate::getUTCSeconds() method accepts extra argument
+//==== SPEC: Tizen Web API:System:Time:TZDate:getUTCSeconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNAEX
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    checkExtraArgument(currentTZDate, "getUTCSeconds");
+}, 'TZDate_getUTCSeconds_extra_argument');
+
+}
+
+function TZDate_isDST() {
+//==== TEST: TZDate_isDST
+//==== LABEL Check if TZDate::isDST() method returns boolean
+//==== SPEC: Tizen Web API:System:Time:TZDate:isDST M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MR MNA
+test(function () {
+    var date = new tizen.TZDate();
+    assert_type(date.isDST(), "boolean", "type check");
+}, 'TZDate_isDST');
+
+}
+
+function TZDate_isDST_for_specific_date() {
+//==== TEST: TZDate_isDST_for_specific_date
+//==== LABEL Check whether Tizen.TZDate.isDST() for specific date
+//==== SPEC Tizen Web API:System:Time:TZDate:isDST M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MR MNA
+test(function () {
+    var dateTZDate = new tizen.TZDate(2013, 2, 27, 18, 33), returnedValue;
+    returnedValue = dateTZDate.isDST();
+    assert_false(returnedValue, "false check");
+}, 'TZDate_isDST_for_specific_date');
+
+}
+
+function TZDate_isDST_exist() {
+//==== TEST: TZDate_isDST_exist
+//==== LABEL Check if isDST() method exists in TZDate
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TZDate:isDST M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    assert_true("isDST" in currentTZDate, "isDST method exists");
+    check_method_exists(currentTZDate, "isDST");
+}, 'TZDate_isDST_exist');
+
+}
+
+function TZDate_isDST_extra_argument() {
+//==== TEST: TZDate_isDST_extra_argument
+//==== LABEL Check if TZDate::isDST() method accepts extra argument
+//==== SPEC: Tizen Web API:System:Time:TZDate:isDST M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNAEX
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    checkExtraArgument(currentTZDate, "isDST");
+}, 'TZDate_isDST_extra_argument');
+
+}
+
+function TZDate_laterThan() {
+//==== TEST: TZDate_laterThan
+//==== LABEL Check if TZDate::laterThan() method returns that current date after 2013-03-04
+//==== SPEC: Tizen Web API:System:Time:TZDate:laterThan M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MR MMINA
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime(), date, returnedValue, other;
+    date = new Date(2013, 3, 4);
+    other = new tizen.TZDate(date);
+    returnedValue = currentTZDate.laterThan(other);
+    assert_true(returnedValue, "true check");
+}, 'TZDate_laterThan');
+
+}
+
+function TZDate_laterThan_with_null() {
+//==== TEST: TZDate_laterThan_with_null
+//==== LABEL Check if TZDate::laterThan() throws exception when other is null
+//==== SPEC Tizen Web API:System:Time:TZDate:laterThan M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMA
+test(function () {
+    var date = new tizen.TZDate();
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        date.laterThan();
+    });
+}, 'TZDate_laterThan_with_null');
+
+}
+
+function TZDate_laterThan_exist() {
+//==== TEST: TZDate_laterThan_exist
+//==== LABEL Check if TZDate::laterThan() method exists in TZDate
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TZDate:laterThan M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    assert_true("laterThan" in currentTZDate, "laterThan method exists");
+    check_method_exists(currentTZDate, "laterThan");
+}, 'TZDate_laterThan_exist');
+
+}
+
+function TZDate_laterThan_missarg() {
+//==== TEST: TZDate_laterThan_missarg
+//==== LABEL Check if TZDate::laterThan() method accepts extra argument
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:System:Time:TZDate:laterThan M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMA
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    assert_throws(TYPE_MISMATCH_EXCEPTION,
+        function () {
+            currentTZDate.laterThan();
+        });
+}, 'TZDate_laterThan_missarg');
+
+}
+
+function TZDate_laterThan_other_TypeMismatch() {
+//==== TEST: TZDate_laterThan_other_TypeMismatch
+//==== LABEL Check if TZDate::laterThan() throws exception when other has wrong type
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:System:Time:TZDate:laterThan M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MC
+test(function () {
+    var currentTZDate, conversionTable, other, exceptionName, i;
+
+    currentTZDate = tizen.time.getCurrentDateTime();
+    conversionTable = getTypeConversionExceptions("functionObject", false);
+    for (i = 0; i < conversionTable.length; i++) {
+        other = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+
+        assert_throws({name: exceptionName},
+            function () {
+                currentTZDate.laterThan(other);
+            }, exceptionName + " should be thrown - given incorrect successCallback.");
+    }
+}, 'TZDate_laterThan_other_TypeMismatch');
+
+}
+
+function TZDate_laterThan_other_invalid_obj() {
+//==== TEST: TZDate_laterThan_other_invalid_obj
+//==== LABEL Check if TZDate::laterThan() throws exception when other is regular object
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:System:Time:TZDate:laterThan M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MTO
+test(function () {
+    var currentTZDate = [], exceptionName = TYPE_MISMATCH_ERR;
+
+    currentTZDate[0] = tizen.time.getCurrentDateTime();
+    currentTZDate[1] = {};
+    assert_throws(TYPE_MISMATCH_EXCEPTION,
+        function () {
+            currentTZDate[0].laterThan(currentTZDate[1]);
+        }, exceptionName + " should be thrown - given incorrect argument.");
+}, 'TZDate_laterThan_other_invalid_obj');
+
+}
+
+function TZDate_secondsFromUTC() {
+//==== TEST: TZDate_secondsFromUTC
+//==== LABEL Check if TZDate::secondsFromUTC() returns number
+//==== SPEC: Tizen Web API:System:Time:TZDate:secondsFromUTC M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime(), returnedValue = null;
+    returnedValue = currentTZDate.secondsFromUTC();
+    assert_type(returnedValue, "long", "type check");
+    assert_not_equals(returnedValue, null, "null check");
+}, 'TZDate_secondsFromUTC');
+
+}
+
+function TZDate_secondsFromUTC_for_specific_date() {
+//==== TEST: TZDate_secondsFromUTC_for_specific_date
+//==== LABEL Check whether secondsFromUTC() method correctly gets the number of seconds from UTC offset for the time zone
+//==== SPEC Tizen Web API:System:Time:TZDate:secondsFromUTC M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MR
+test(function () {
+    var expectedData = -1 * expected_time_zone_offset * 60 * 60, i = 0;
+    assert_equals(date.secondsFromUTC(), expectedData, "secondsFromUTC check");
+    for (i = 0; i < testAdditionalParamArray.length; i++) {
+        assert_equals(date.secondsFromUTC(testAdditionalParamArray[i]), expectedData, "secondsFromUTC check " + i);
+    }
+}, 'TZDate_secondsFromUTC_for_specific_date');
+
+}
+
+function TZDate_secondsFromUTC_exist() {
+//==== TEST: TZDate_secondsFromUTC_exist
+//==== LABEL Check if secondsFromUTC() method exists in TZDate
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TZDate:secondsFromUTC M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    assert_true("secondsFromUTC" in currentTZDate, "secondsFromUTC method exists");
+    check_method_exists(currentTZDate, "secondsFromUTC");
+}, 'TZDate_secondsFromUTC_exist');
+
+}
+
+function TZDate_secondsFromUTC_extra_argument() {
+//==== TEST: TZDate_secondsFromUTC_extra_argument
+//==== LABEL Check if TZDate::secondsFromUTC() method accepts extra argument
+//==== SPEC: Tizen Web API:System:Time:TZDate:secondsFromUTC M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNAEX
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    checkExtraArgument(currentTZDate, "secondsFromUTC");
+}, 'TZDate_secondsFromUTC_extra_argument');
+
+}
+
+function TZDate_setDate() {
+//==== TEST: TZDate_setDate
+//==== LABEL Check if TZDate::setDate() method sets day of the month and returns nothing
+//==== SPEC: Tizen Web API:System:Time:TZDate:setDate M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA MAST MR
+test(function () {
+    var currentTZDate, date, returnedValue = null;
+    date = new Date(2013, 2, 27);
+    currentTZDate = new tizen.TZDate(date);
+    returnedValue = currentTZDate.setDate(15);
+    assert_equals(returnedValue, undefined, "setDate() should return undefined.");
+    assert_equals(currentTZDate.getDate(), 15, "value check");
+}, 'TZDate_setDate');
+
+}
+
+function TZDate_setDate_for_specific_date() {
+//==== TEST: TZDate_setDate_for_specific_date
+//==== LABEL Check various arguments for setDate() method
+//==== SPEC Tizen Web API:System:Time:TZDate:setDate M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MAST MMINA
+test(function () {
+    var tmpDate = new tizen.TZDate(2000, 4, 3),
+        cmpDate = new Date(2000, 4, 3),
+        testDataArray           = [1, 12, 21, 30, 31],
+        testInvalidDataArray    = [-1, 32, 123],
+        testName  = "testSetDate()",
+        i;
+
+    for (i = 0; i < testDataArray.length; i++) {
+        tmpDate.setDate(testDataArray[i]);
+        assert_equals(tmpDate.getDate(), testDataArray[i], testName + " data value " + testDataArray[i]);
+    }
+
+    for (i = 0; i < testAdditionalParamArray.length; i++) {
+        tmpDate.setDate(testDataArray[i], testAdditionalParamArray[i]);
+        assert_equals(tmpDate.getDate(), testDataArray[i], testName + " data value " + testDataArray[i]);
+    }
+
+    for (i = 0; i < testInvalidDataArray.length; i++) {
+        tmpDate.setDate(testInvalidDataArray[i]);
+        cmpDate.setDate(testInvalidDataArray[i]);
+        assert_equals(tmpDate.getDate(), cmpDate.getDate(), testName + " data value " + testInvalidDataArray[i]);
+    }
+}, 'TZDate_setDate_for_specific_date');
+
+}
+
+function TZDate_setDate_exist() {
+//==== TEST: TZDate_setDate_exist
+//==== LABEL Check if setDate() method exists in TZDate
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TZDate:setDate M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    assert_true("setDate" in currentTZDate, "setDate method exists");
+    check_method_exists(currentTZDate, "setDate");
+}, 'TZDate_setDate_exist');
+
+}
+
+function TZDate_setFullYear() {
+//==== TEST: TZDate_setFullYear
+//==== LABEL Check if TZDate::setFullYear() method sets year and returns nothing
+//==== SPEC: Tizen Web API:System:Time:TZDate:setFullYear M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA MAST MR
+test(function () {
+    var currentTZDate, date, returnedValue = null;
+    date = new Date(2013, 2, 27);
+    currentTZDate = new tizen.TZDate(date);
+    returnedValue = currentTZDate.setFullYear(2000);
+    assert_equals(returnedValue, undefined, "setFullYear() should return undefined.");
+    assert_equals(currentTZDate.getFullYear(), 2000, "value check");
+}, 'TZDate_setFullYear');
+
+}
+
+function TZDate_setFullYear_exist() {
+//==== TEST: TZDate_setFullYear_exist
+//==== LABEL Check if setFullYear() method exists in TZDate
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TZDate:setFullYear M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    assert_true("setFullYear" in currentTZDate, "setFullYear method exists");
+    check_method_exists(currentTZDate, "setFullYear");
+}, 'TZDate_setFullYear_exist');
+
+}
+
+function TZDate_setHours() {
+//==== TEST: TZDate_setHours
+//==== LABEL Check if TZDate::setHours() method sets hour and returns nothing
+//==== SPEC: Tizen Web API:System:Time:TZDate:setHours M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA MAST MR
+test(function () {
+    var currentTZDate, date, returnedValue = null;
+    date = new Date(2013, 2, 27, 18);
+    currentTZDate = new tizen.TZDate(date);
+    returnedValue = currentTZDate.setHours(11);
+    assert_equals(returnedValue, undefined, "setHours() should return undefined.");
+    assert_equals(currentTZDate.getHours(), 11, "value check");
+}, 'TZDate_setHours');
+
+}
+
+function TZDate_setHours_exist() {
+//==== TEST: TZDate_setHours_exist
+//==== LABEL Check if setHours() method exists in TZDate
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TZDate:setHours M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    assert_true("setHours" in currentTZDate, "setHours method exists");
+    check_method_exists(currentTZDate, "setHours");
+}, 'TZDate_setHours_exist');
+
+}
+
+function TZDate_setMilliseconds() {
+//==== TEST: TZDate_setMilliseconds
+//==== LABEL Check if TZDate::setMilliseconds() method sets milliseconds and returns nothing
+//==== SPEC: Tizen Web API:System:Time:TZDate:setMilliseconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA MAST MR
+test(function () {
+    var currentTZDate, date, returnedValue = null;
+    date = new Date(2013, 2, 27, 18, 42, 48, 100);
+    currentTZDate = new tizen.TZDate(date);
+    returnedValue = currentTZDate.setMilliseconds(431);
+    assert_equals(returnedValue, undefined, "setMilliseconds() should return undefined.");
+    assert_equals(currentTZDate.getMilliseconds(), 431, "value check");
+}, 'TZDate_setMilliseconds');
+
+}
+
+function TZDate_setMilliseconds_exist() {
+//==== TEST: TZDate_setMilliseconds_exist
+//==== LABEL Check if setMilliseconds() method exists in TZDate
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TZDate:setMilliseconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    assert_true("setMilliseconds" in currentTZDate, "setMilliseconds method exists");
+    check_method_exists(currentTZDate, "setMilliseconds");
+}, 'TZDate_setMilliseconds_exist');
+
+}
+
+function TZDate_setMinutes() {
+//==== TEST: TZDate_setMinutes
+//==== LABEL Check if method setMinutes of TZDate works properly.
+//==== SPEC: Tizen Web API:System:Time:TZDate:setMinutes M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA MAST MR
+test(function () {
+    var currentTZDate, date, returnedValue = null;
+    date = new Date(2013, 2, 27, 18, 42);
+    currentTZDate = new tizen.TZDate(date);
+    returnedValue = currentTZDate.setMinutes(31);
+    assert_equals(returnedValue, undefined, "setMinutes() should return undefined.");
+    assert_equals(currentTZDate.getMinutes(), 31, "value check");
+}, 'TZDate_setMinutes');
+
+}
+
+function TZDate_setMinutes_exist() {
+//==== TEST: TZDate_setMinutes_exist
+//==== LABEL Check if setMinutes method exists in TimeManager.
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TZDate:setMinutes M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    assert_true("setMinutes" in currentTZDate, "setMinutes method exists");
+    check_method_exists(currentTZDate, "setMinutes");
+}, 'TZDate_setMinutes_exist');
+
+}
+
+function TZDate_setMonth() {
+//==== TEST: TZDate_setMonth
+//==== LABEL Check if method setMonth of TZDate works properly.
+//==== SPEC: Tizen Web API:System:Time:TZDate:setMonth M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA MAST MR
+test(function () {
+    var currentTZDate, date, returnedValue = null;
+    date = new Date(2013, 2, 27);
+    currentTZDate = new tizen.TZDate(date);
+    returnedValue = currentTZDate.setMonth(5);
+    assert_equals(returnedValue, undefined, "setMonth() should return undefined.");
+    assert_equals(currentTZDate.getMonth(), 5, "value check");
+}, 'TZDate_setMonth');
+
+}
+
+function TZDate_setMonth_exist() {
+//==== TEST: TZDate_setMonth_exist
+//==== LABEL Check if setMonth method exists in TimeManager.
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TZDate:setMonth M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    assert_true("setMonth" in currentTZDate, "setMonth method exists");
+    check_method_exists(currentTZDate, "setMonth");
+}, 'TZDate_setMonth_exist');
+
+}
+
+function TZDate_setSeconds() {
+//==== TEST: TZDate_setSeconds
+//==== LABEL Check if method setSeconds of TZDate works properly.
+//==== SPEC: Tizen Web API:System:Time:TZDate:setSeconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA MAST MR
+test(function () {
+    var currentTZDate, date, returnedValue = null;
+    date = new Date(2013, 2, 27, 3, 23, 54);
+    currentTZDate = new tizen.TZDate(date);
+    returnedValue = currentTZDate.setSeconds(5);
+    assert_equals(returnedValue, undefined, "setSeconds() should return undefined.");
+    assert_equals(currentTZDate.getSeconds(), 5, "value check");
+}, 'TZDate_setSeconds');
+
+}
+
+function TZDate_setSeconds_exist() {
+//==== TEST: TZDate_setSeconds_exist
+//==== LABEL Check if setSeconds method exists in TimeManager.
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TZDate:setSeconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    assert_true("setSeconds" in currentTZDate, "setSeconds method exists");
+    check_method_exists(currentTZDate, "setSeconds");
+}, 'TZDate_setSeconds_exist');
+
+}
+
+function TZDate_setUTCDate() {
+//==== TEST: TZDate_setUTCDate
+//==== LABEL Check if method setUTCDate of TZDate works properly.
+//==== SPEC: Tizen Web API:System:Time:TZDate:setUTCDate M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA MAST MR
+test(function () {
+    var currentTZDate, date, returnedValue = null;
+    date = new Date(2013, 2, 27);
+    currentTZDate = new tizen.TZDate(date);
+    returnedValue = currentTZDate.setUTCDate(31);
+    assert_equals(returnedValue, undefined, "setUTCDate() should return undefined.");
+    assert_equals(currentTZDate.getUTCDate(), 31, "value check");
+}, 'TZDate_setUTCDate');
+
+}
+
+function TZDate_setUTCDate_exist() {
+//==== TEST: TZDate_setUTCDate_exist
+//==== LABEL Check if setUTCDate method exists in TimeManager.
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TZDate:setUTCDate M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    assert_true("setUTCDate" in currentTZDate, "setUTCDate method exists");
+    check_method_exists(currentTZDate, "setUTCDate");
+}, 'TZDate_setUTCDate_exist');
+
+}
+
+function TZDate_setUTCFullYear() {
+//==== TEST: TZDate_setUTCFullYear
+//==== LABEL Check if method setUTCFullYear of TZDate works properly.
+//==== SPEC: Tizen Web API:System:Time:TZDate:setUTCFullYear M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA MAST MR
+test(function () {
+    var currentTZDate, date, returnedValue = null;
+    date = new Date(2013, 2, 27);
+    currentTZDate = new tizen.TZDate(date);
+    returnedValue = currentTZDate.setUTCFullYear(1999);
+    assert_equals(returnedValue, undefined, "setUTCFullYear() should return undefined.");
+    assert_equals(currentTZDate.getUTCFullYear(), 1999, "value check");
+}, 'TZDate_setUTCFullYear');
+
+}
+
+function TZDate_setUTCFullYear_exist() {
+//==== TEST: TZDate_setUTCFullYear_exist
+//==== LABEL Check if setUTCFullYear method exists in TimeManager.
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TZDate:setUTCFullYear M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    assert_true("setUTCFullYear" in currentTZDate, "setUTCFullYear method exists");
+    check_method_exists(currentTZDate, "setUTCFullYear");
+}, 'TZDate_setUTCFullYear_exist');
+
+}
+
+function TZDate_setUTCHours() {
+//==== TEST: TZDate_setUTCHours
+//==== LABEL Check if method setUTCHours of TZDate works properly.
+//==== SPEC: Tizen Web API:System:Time:TZDate:setUTCHours M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA MAST MR
+test(function () {
+    var currentTZDate, date, returnedValue = null;
+    date = new Date(2013, 2, 27, 11);
+    currentTZDate = new tizen.TZDate(date);
+    returnedValue = currentTZDate.setUTCHours(23);
+    assert_equals(returnedValue, undefined, "setUTCHours() should return undefined.");
+    assert_equals(currentTZDate.getUTCHours(), 23, "value check");
+}, 'TZDate_setUTCHours');
+
+}
+
+function TZDate_setUTCHours_exist() {
+//==== TEST: TZDate_setUTCHours_exist
+//==== LABEL Check if setUTCHours method exists in TimeManager.
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TZDate:setUTCHours M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    assert_true("setUTCHours" in currentTZDate, "setUTCHours method exists");
+    check_method_exists(currentTZDate, "setUTCHours");
+}, 'TZDate_setUTCHours_exist');
+
+}
+
+function TZDate_setUTCMilliseconds() {
+//==== TEST: TZDate_setUTCMilliseconds
+//==== LABEL Check if method setUTCMilliseconds of TZDate works properly.
+//==== SPEC: Tizen Web API:System:Time:TZDate:setUTCMilliseconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA MAST MR
+test(function () {
+    var currentTZDate, date, returnedValue = null;
+    date = new Date(2013, 2, 27, 11, 32, 12, 543);
+    currentTZDate = new tizen.TZDate(date);
+    returnedValue = currentTZDate.setUTCMilliseconds(999);
+    assert_equals(returnedValue, undefined, "setUTCMilliseconds() should return undefined.");
+    assert_equals(currentTZDate.getUTCMilliseconds(), 999, "value check");
+}, 'TZDate_setUTCMilliseconds');
+
+}
+
+function TZDate_setUTCMilliseconds_exist() {
+//==== TEST: TZDate_setUTCMilliseconds_exist
+//==== LABEL Check if setUTCMilliseconds method exists in TimeManager.
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TZDate:setUTCMilliseconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    assert_true("setUTCMilliseconds" in currentTZDate, "setUTCMilliseconds method exists");
+    check_method_exists(currentTZDate, "setUTCMilliseconds");
+}, 'TZDate_setUTCMilliseconds_exist');
+
+}
+
+function TZDate_setUTCMinutes() {
+//==== TEST: TZDate_setUTCMinutes
+//==== LABEL Check if method setUTCMinutes of TZDate works properly.
+//==== SPEC: Tizen Web API:System:Time:TZDate:setUTCMinutes M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA MAST MR
+test(function () {
+    var currentTZDate, date, returnedValue = null;
+    date = new Date(2013, 2, 27, 11, 32);
+    currentTZDate = new tizen.TZDate(date);
+    returnedValue = currentTZDate.setUTCMinutes(59);
+    assert_equals(returnedValue, undefined, "setUTCMinutes() should return undefined.");
+    assert_equals(currentTZDate.getUTCMinutes(), 59, "value check");
+}, 'TZDate_setUTCMinutes');
+
+}
+
+function TZDate_setUTCMinutes_exist() {
+//==== TEST: TZDate_setUTCMinutes_exist
+//==== LABEL Check if setUTCMinutes method exists in TimeManager.
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TZDate:setUTCMinutes M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    assert_true("setUTCMinutes" in currentTZDate, "setUTCMinutes method exists");
+    check_method_exists(currentTZDate, "setUTCMinutes");
+}, 'TZDate_setUTCMinutes_exist');
+
+}
+
+function TZDate_setUTCMonth() {
+//==== TEST: TZDate_setUTCMonth
+//==== LABEL Check if method setUTCMonth of TZDate works properly.
+//==== SPEC: Tizen Web API:System:Time:TZDate:setUTCMonth M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA MAST MR
+test(function () {
+    var currentTZDate, date, returnedValue = null;
+    date = new Date(2013, 2, 27);
+    currentTZDate = new tizen.TZDate(date);
+    returnedValue = currentTZDate.setUTCMonth(11);
+    assert_equals(returnedValue, undefined, "setUTCMonth() should return undefined.");
+    assert_equals(currentTZDate.getUTCMonth(), 11, "value check");
+}, 'TZDate_setUTCMonth');
+
+}
+
+function TZDate_setUTCMonth_exist() {
+//==== TEST: TZDate_setUTCMonth_exist
+//==== LABEL Check if setUTCMonth method exists in TimeManager.
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TZDate:setUTCMonth M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    assert_true("setUTCMonth" in currentTZDate, "setUTCMonth method exists");
+    check_method_exists(currentTZDate, "setUTCMonth");
+}, 'TZDate_setUTCMonth_exist');
+
+}
+
+function TZDate_setUTCSeconds() {
+//==== TEST: TZDate_setUTCSeconds
+//==== LABEL Check if method setUTCSeconds of TZDate works properly.
+//==== SPEC: Tizen Web API:System:Time:TZDate:setUTCSeconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA MAST MR
+test(function () {
+    var currentTZDate, date, returnedValue = null;
+    date = new Date(2013, 2, 27, 11, 34, 11);
+    currentTZDate = new tizen.TZDate(date);
+    returnedValue = currentTZDate.setUTCSeconds(0);
+    assert_equals(returnedValue, undefined, "setUTCSeconds() should return undefined.");
+    assert_equals(currentTZDate.getUTCSeconds(), 0, "value check");
+}, 'TZDate_setUTCSeconds');
+
+}
+
+function TZDate_setUTCSeconds_exist() {
+//==== TEST: TZDate_setUTCSeconds_exist
+//==== LABEL Check if setUTCSeconds method exists in TimeManager.
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TZDate:setUTCSeconds M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    assert_true("setUTCSeconds" in currentTZDate, "setUTCSeconds method exists");
+    check_method_exists(currentTZDate, "setUTCSeconds");
+}, 'TZDate_setUTCSeconds_exist');
+
+}
+
+function TZDate_toDateString() {
+//==== TEST: TZDate_toDateString
+//==== LABEL Check if TZDate::ToDateString() method returns non-empty string
+//==== SPEC: Tizen Web API:System:Time:TZDate:toDateString M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime(), returnedValue = null;
+    returnedValue = currentTZDate.toDateString();
+    assert_type(returnedValue, "string", "type check");
+    assert_not_equals(returnedValue, "", "returned");
+}, 'TZDate_toDateString');
+
+}
+
+function TZDate_toDateString_for_specific_date() {
+//==== TEST: TZDate_toDateString_for_specific_date
+//==== LABEL Check whether toDateString() method correctly returns the date portion of a TZDate object as a string
+//==== SPEC Tizen Web API:System:Time:TZDate:toDateString M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA
+test(function () {
+    var expectedDateString = "Friday, November 11, 2011", i = 0, date;
+    date = new tizen.TZDate(2011, 10, 11);
+    assert_equals(date.toDateString(), expectedDateString, this.name);
+    for (i = 0; i < testAdditionalParamArray.length; i++) {
+        assert_equals(date.toDateString(testAdditionalParamArray[i]), expectedDateString, this.name);
+    }
+}, 'TZDate_toDateString_for_specific_date');
+
+}
+
+function TZDate_toDateString_exist() {
+//==== TEST: TZDate_toDateString_exist
+//==== LABEL Check if toDateString method exists in TimeManager.
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TZDate:toDateString M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    assert_true("toDateString" in currentTZDate, "toDateString method exists");
+    check_method_exists(currentTZDate, "toDateString");
+}, 'TZDate_toDateString_exist');
+
+}
+
+function TZDate_toDateString_extra_argument() {
+//==== TEST: TZDate_toDateString_extra_argument
+//==== LABEL Check if method toDateString of TZDate accepts extra argument
+//==== SPEC: Tizen Web API:System:Time:TZDate:toDateString M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNAEX
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    checkExtraArgument(currentTZDate, "toDateString");
+}, 'TZDate_toDateString_extra_argument');
+
+}
+
+function TZDate_toLocalTimezone() {
+//==== TEST: TZDate_toLocalTimezone
+//==== LABEL Check if method toLocalTimezone of TZDate works properly.
+//==== SPEC: Tizen Web API:System:Time:TZDate:toLocalTimezone M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime(), returnedValue = null;
+    returnedValue = currentTZDate.toLocalTimezone();
+    assert_true(returnedValue instanceof tizen.TZDate, "TZDate check");
+}, 'TZDate_toLocalTimezone');
+
+}
+
+function TZDate_toLocalTimezone_for_specific_date() {
+//==== TEST: TZDate_toLocalTimezone_for_specific_date
+//==== LABEL Tizen.TZDate.toLocalTimezone (null) WRONG argument(s)
+//==== SPEC Tizen Web API:System:Time:TZDate:toLocalTimezone M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var date = new tizen.TZDate();
+    date.toLocalTimezone(null);
+}, 'TZDate_toLocalTimezone_for_specific_date');
+
+}
+
+function TZDate_toLocalTimezone_exist() {
+//==== TEST: TZDate_toLocalTimezone_exist
+//==== LABEL Check if toLocalTimezone method exists in TimeManager.
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TZDate:toLocalTimezone M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    assert_true("toLocalTimezone" in currentTZDate, "toLocalTimezone method exists");
+    check_method_exists(currentTZDate, "toLocalTimezone");
+}, 'TZDate_toLocalTimezone_exist');
+
+}
+
+function TZDate_toLocalTimezone_extra_argument() {
+//==== TEST: TZDate_toLocalTimezone_extra_argument
+//==== LABEL Check if method toLocalTimezone of TZDate accepts extra argument
+//==== SPEC: Tizen Web API:System:Time:TZDate:toLocalTimezone M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNAEX
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    checkExtraArgument(currentTZDate, "toLocalTimezone");
+}, 'TZDate_toLocalTimezone_extra_argument');
+
+}
+
+function TZDate_toLocaleDateString() {
+//==== TEST: TZDate_toLocaleDateString
+//==== LABEL Check if TZDate::ToLocaleDateString() method returns non-empty string
+//==== SPEC: Tizen Web API:System:Time:TZDate:toLocaleDateString M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime(), returnedValue = null;
+    returnedValue = currentTZDate.toLocaleDateString();
+    assert_type(returnedValue, "string", "type check");
+    assert_not_equals(returnedValue, "", "returned");
+}, 'TZDate_toLocaleDateString');
+
+}
+
+function TZDate_toLocaleDateString_exist() {
+//==== TEST: TZDate_toLocaleDateString_exist
+//==== LABEL Check if toLocaleDateString method exists in TimeManager.
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TZDate:toLocaleDateString M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    assert_true("toLocaleDateString" in currentTZDate, "toLocaleDateString method exists");
+    check_method_exists(currentTZDate, "toLocaleDateString");
+}, 'TZDate_toLocaleDateString_exist');
+
+}
+
+function TZDate_toLocaleDateString_extra_argument() {
+//==== TEST: TZDate_toLocaleDateString_extra_argument
+//==== LABEL Check if method toLocaleDateString of TZDate accepts extra argument
+//==== SPEC: Tizen Web API:System:Time:TZDate:toLocaleDateString M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNAEX
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    checkExtraArgument(currentTZDate, "toLocaleDateString");
+}, 'TZDate_toLocaleDateString_extra_argument');
+
+}
+
+function TZDate_toLocaleString() {
+//==== TEST: TZDate_toLocaleString
+//==== LABEL Check if TZDate::ToLocaleString() method returns non-empty string
+//==== SPEC: Tizen Web API:System:Time:TZDate:toLocaleString M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime(), returnedValue = null;
+    returnedValue = currentTZDate.toLocaleString();
+    assert_type(returnedValue, "string", "type check");
+    assert_not_equals(returnedValue, "", "returned");
+}, 'TZDate_toLocaleString');
+
+}
+
+function TZDate_toLocaleString_exist() {
+//==== TEST: TZDate_toLocaleString_exist
+//==== LABEL Check if toLocaleString method exists in TimeManager.
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TZDate:toLocaleString M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    assert_true("toLocaleString" in currentTZDate, "toLocaleString method exists");
+    check_method_exists(currentTZDate, "toLocaleString");
+}, 'TZDate_toLocaleString_exist');
+
+}
+
+function TZDate_toLocaleString_extra_argument() {
+//==== TEST: TZDate_toLocaleString_extra_argument
+//==== LABEL Check if method toLocaleString of TZDate accepts extra argument
+//==== SPEC: Tizen Web API:System:Time:TZDate:toLocaleString M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNAEX
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    checkExtraArgument(currentTZDate, "toLocaleString");
+}, 'TZDate_toLocaleString_extra_argument');
+
+}
+
+function TZDate_toLocaleTimeString() {
+//==== TEST: TZDate_toLocaleTimeString
+//==== LABEL Check if TZDate::ToLocaleTimeString() method returns non-empty string
+//==== SPEC: Tizen Web API:System:Time:TZDate:toLocaleTimeString M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime(), returnedValue = null;
+    returnedValue = currentTZDate.toLocaleTimeString();
+    assert_type(returnedValue, "string", "type check");
+    assert_not_equals(returnedValue, "", "returned");
+}, 'TZDate_toLocaleTimeString');
+
+}
+
+function TZDate_toLocaleTimeString_exist() {
+//==== TEST: TZDate_toLocaleTimeString_exist
+//==== LABEL Check if toLocaleTimeString method exists in TimeManager.
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TZDate:toLocaleTimeString M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    assert_true("toLocaleTimeString" in currentTZDate, "toLocaleTimeString method exists");
+    check_method_exists(currentTZDate, "toLocaleTimeString");
+}, 'TZDate_toLocaleTimeString_exist');
+
+}
+
+function TZDate_toLocaleTimeString_extra_argument() {
+//==== TEST: TZDate_toLocaleTimeString_extra_argument
+//==== LABEL Check if method toLocaleTimeString of TZDate accepts extra argument
+//==== SPEC: Tizen Web API:System:Time:TZDate:toLocaleTimeString M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNAEX
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    checkExtraArgument(currentTZDate, "toLocaleTimeString");
+}, 'TZDate_toLocaleTimeString_extra_argument');
+
+}
+
+function TZDate_toString() {
+//==== TEST: TZDate_toString
+//==== LABEL Check if TZDate::ToString() method returns non-empty string
+//==== SPEC: Tizen Web API:System:Time:TZDate:toString M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime(), returnedValue = null;
+    returnedValue = currentTZDate.toString();
+    assert_type(returnedValue, "string", "type check");
+    assert_not_equals(returnedValue, "", "returned");
+}, 'TZDate_toString');
+
+}
+
+function TZDate_toString_exist() {
+//==== TEST: TZDate_toString_exist
+//==== LABEL Check if toString method exists in TimeManager.
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TZDate:toString M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    assert_true("toString" in currentTZDate, "toString method exists");
+    check_method_exists(currentTZDate, "toString");
+}, 'TZDate_toString_exist');
+
+}
+
+function TZDate_toString_extra_argument() {
+//==== TEST: TZDate_toString_extra_argument
+//==== LABEL Check if method toString of TZDate accepts extra argument
+//==== SPEC: Tizen Web API:System:Time:TZDate:toString M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNAEX
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    checkExtraArgument(currentTZDate, "toString");
+}, 'TZDate_toString_extra_argument');
+
+}
+
+function TZDate_toTimeString() {
+//==== TEST: TZDate_toTimeString
+//==== LABEL Check if TZDate::ToTimeString() method returns non-empty string
+//==== SPEC: Tizen Web API:System:Time:TZDate:toTimeString M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime(), returnedValue = null;
+    returnedValue = currentTZDate.toTimeString();
+    assert_type(returnedValue, "string", "type check");
+    assert_not_equals(returnedValue, "", "returned");
+}, 'TZDate_toTimeString');
+
+}
+
+function TZDate_toTimeString_for_specific_date() {
+//==== TEST: TZDate_toTimeString_for_specific_date
+//==== LABEL Check whether toTimeString() method correctly returns the time portion of a TZDate object as a string
+//==== SPEC Tizen Web API:System:Time:TZDate:toTimeString M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    assert_regexp_match(date.toTimeString(), /0?4:55:54( AM)? GMT\+0900 South Korea Time/, this.name);
+}, 'TZDate_toTimeString_for_specific_date');
+
+}
+
+function TZDate_toTimeString_exist() {
+//==== TEST: TZDate_toTimeString_exist
+//==== LABEL Check if toTimeString method exists in TimeManager.
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TZDate:toTimeString M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    assert_true("toTimeString" in currentTZDate, "toTimeString method exists");
+    check_method_exists(currentTZDate, "toTimeString");
+}, 'TZDate_toTimeString_exist');
+
+}
+
+function TZDate_toTimeString_extra_argument() {
+//==== TEST: TZDate_toTimeString_extra_argument
+//==== LABEL Check whether Tizen.TZDate.getMonth() extra argument
+//==== SPEC: Tizen Web API:System:Time:TZDate:toTimeString M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNAEX
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    checkExtraArgument(currentTZDate, "toTimeString");
+}, 'TZDate_toTimeString_extra_argument');
+
+}
+
+function TZDate_toTimezone() {
+//==== TEST: TZDate_toTimezone
+//==== LABEL Check if method toTimezone of TZDate works properly.
+//==== SPEC: Tizen Web API:System:Time:TZDate:toTimezone M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA MR
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime(), returnedValue = null;
+    returnedValue = currentTZDate.toTimezone("Europe/Berlin");
+    assert_true(returnedValue instanceof tizen.TZDate, "TZDate check");
+}, 'TZDate_toTimezone');
+
+}
+
+function TZDate_toTimezone_exist() {
+//==== TEST: TZDate_toTimezone_exist
+//==== LABEL Check if toTimezone method exists in TimeManager.
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TZDate:toTimezone M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    assert_true("toTimezone" in currentTZDate, "toTimezone method exists");
+    check_method_exists(currentTZDate, "toTimezone");
+}, 'TZDate_toTimezone_exist');
+
+}
+
+function TZDate_toUTC() {
+//==== TEST: TZDate_toUTC
+//==== LABEL Check if method toUTC of TZDate works properly.
+//==== SPEC: Tizen Web API:System:Time:TZDate:toUTC M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime(), returnedValue = null;
+    returnedValue = currentTZDate.toUTC();
+    assert_true(returnedValue instanceof tizen.TZDate, "TZDate check");
+}, 'TZDate_toUTC');
+
+}
+
+function TZDate_toUTC_exist() {
+//==== TEST: TZDate_toUTC_exist
+//==== LABEL Check if toUTC method exists in TimeManager.
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TZDate:toUTC M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    assert_true("toUTC" in currentTZDate, "toUTC method exists");
+    check_method_exists(currentTZDate, "toUTC");
+}, 'TZDate_toUTC_exist');
+
+}
+
+function TZDate_toUTC_extra_argument() {
+//==== TEST: TZDate_toUTC_extra_argument
+//==== LABEL Check if method toUTC of TZDate accepts extra argument
+//==== SPEC: Tizen Web API:System:Time:TZDate:toUTC M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNAEX
+test(function () {
+    var currentTZDate = tizen.time.getCurrentDateTime();
+    checkExtraArgument(currentTZDate, "toUTC");
+}, 'TZDate_toUTC_extra_argument');
+
+}
+
+function TimeDuration_constructor_maximal() {
+//==== TEST: TimeDuration_constructor_maximal
+//==== LABEL Test whether the maximal constructor of the TimeDuration interface is defined or not.
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TimeDuration:constructor C
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA CONSTRM CONSTRA
+test(function () {
+    var timeduration = new tizen.TimeDuration(20, "DAYS");
+    assert_true(timeduration instanceof tizen.TimeDuration, "TimeDuration check");
+    assert_type(timeduration, "object", "type check");
+    assert_equals(timeduration.length, 20, "length attribute value check");
+    assert_equals(timeduration.unit, "DAYS", "unit attribute value check");
+}, 'TimeDuration_constructor_maximal');
+
+}
+
+function TimeDuration_constructor_minimal() {
+//==== TEST: TimeDuration_constructor_minimal
+//==== LABEL Test whether the minimal constructor of the TimeDuration interface is defined or not.
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TimeDuration:constructor C
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA CONSTRM CONSTRA
+test(function () {
+    var timeduration = new tizen.TimeDuration(20);
+    assert_true(timeduration instanceof tizen.TimeDuration, "TimeDuration check");
+    assert_type(timeduration, "object", "type check");
+    assert_equals(timeduration.length, 20, "length attribute value check");
+}, 'TimeDuration_constructor_minimal');
+
+}
+
+function TimeDuration_difference() {
+//==== TEST: TimeDuration_difference
+//==== LABEL Check if method difference of TimeDuration works properly.
+//==== SPEC: Tizen Web API:System:Time:TimeDuration:difference M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA MR
+test(function () {
+    var timeDuration1, timeDuration2, returnedValue;
+    timeDuration1 = new tizen.TimeDuration(1, "DAYS");
+    timeDuration2 = new tizen.TimeDuration(60, "DAYS");
+    returnedValue = timeDuration1.difference(timeDuration2);
+    assert_true(returnedValue instanceof tizen.TimeDuration, "TimeDuration check");
+    assert_equals(returnedValue.length, -59, "length check");
+    assert_equals(returnedValue.unit, "DAYS", "length check");
+}, 'TimeDuration_difference');
+
+}
+
+function TimeDuration_difference_exist() {
+//==== TEST: TimeDuration_difference_exist
+//==== LABEL Check if difference method exists in TimeDuration.
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TimeDuration:difference M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    var currentTimeDuration = new tizen.TimeDuration(1, "DAYS");
+    assert_true("difference" in currentTimeDuration, "difference method exists");
+    check_method_exists(currentTimeDuration, "difference");
+}, 'TimeDuration_difference_exist');
+
+}
+
+function TimeDuration_difference_missarg() {
+//==== TEST: TimeDuration_difference_missarg
+//==== LABEL Check if difference method with missing non-optional argument works in TimeDuration
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:System:Time:TimeDuration:difference M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMA
+test(function () {
+    var currentTimeDuration = new tizen.TimeDuration(1, "DAYS");
+    assert_throws(TYPE_MISMATCH_EXCEPTION,
+        function () {
+            currentTimeDuration.difference();
+        });
+}, 'TimeDuration_difference_missarg');
+
+}
+
+function TimeDuration_difference_other_TypeMismatch() {
+//==== TEST: TimeDuration_difference_other_TypeMismatch
+//==== LABEL Check argument difference conversions exception in TimeDuration.
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:System:Time:TimeDuration:difference M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MC
+test(function () {
+    var currentTimeDuration, conversionTable, other, exceptionName, i;
+
+    currentTimeDuration = new tizen.TimeDuration(1, "DAYS");
+    conversionTable = getTypeConversionExceptions("functionObject", false);
+    for (i = 0; i < conversionTable.length; i++) {
+        other = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+
+        assert_throws({name: exceptionName},
+            function () {
+                currentTimeDuration.difference(other);
+            }, exceptionName + " should be thrown - given incorrect successCallback.");
+    }
+}, 'TimeDuration_difference_other_TypeMismatch');
+
+}
+
+function TimeDuration_difference_other_invalid_obj() {
+//==== TEST: TimeDuration_difference_other_invalid_obj
+//==== LABEL Check argument validation in difference method in TimeDuration.
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:System:Time:TimeDuration:difference M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MTO
+test(function () {
+    var currentTimeDuration = [], exceptionName = TYPE_MISMATCH_ERR;
+
+    currentTimeDuration[0] = new tizen.TimeDuration(1, "DAYS");
+    currentTimeDuration[1] = {length: 2, unit: "MINS"};
+    assert_throws({name: exceptionName},
+        function () {
+            currentTimeDuration[0].difference(currentTimeDuration[1]);
+        }, exceptionName + " should be thrown - given incorrect argument.");
+}, 'TimeDuration_difference_other_invalid_obj');
+
+}
+
+function TimeDuration_equalsTo() {
+//==== TEST: TimeDuration_equalsTo
+//==== LABEL Check if method equalsTo of TimeDuration works properly.
+//==== SPEC: Tizen Web API:System:Time:TimeDuration:equalsTo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA MR
+test(function () {
+    var timeDuration1, timeDuration2, returnedValue;
+    timeDuration1 = new tizen.TimeDuration(1, "DAYS");
+    timeDuration2 = new tizen.TimeDuration(60, "DAYS");
+    returnedValue = timeDuration1.equalsTo(timeDuration2);
+    assert_equals(returnedValue, false, "equalsTo value check");
+}, 'TimeDuration_equalsTo');
+
+}
+
+function TimeDuration_equalsTo_exist() {
+//==== TEST: TimeDuration_equalsTo_exist
+//==== LABEL Check if equalsTo method exists in TimeDuration.
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TimeDuration:equalsTo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    var currentTimeDuration = new tizen.TimeDuration(1, "DAYS");
+    assert_true("equalsTo" in currentTimeDuration, "equalsTo method exists");
+    check_method_exists(currentTimeDuration, "equalsTo");
+}, 'TimeDuration_equalsTo_exist');
+
+}
+
+function TimeDuration_equalsTo_missarg() {
+//==== TEST: TimeDuration_equalsTo_missarg
+//==== LABEL Check if equalsTo method with missing non-optional argument works in TimeDuration
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:System:Time:TimeDuration:equalsTo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMA
+test(function () {
+    var currentTimeDuration = new tizen.TimeDuration(1, "DAYS");
+    assert_throws(TYPE_MISMATCH_EXCEPTION,
+        function () {
+            currentTimeDuration.equalsTo();
+        });
+}, 'TimeDuration_equalsTo_missarg');
+
+}
+
+function TimeDuration_equalsTo_other_TypeMismatch() {
+//==== TEST: TimeDuration_equalsTo_other_TypeMismatch
+//==== LABEL Check argument equalsTo conversions exception in TimeDuration.
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:System:Time:TimeDuration:equalsTo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MC
+test(function () {
+    var currentTimeDuration, conversionTable, other, exceptionName, i;
+
+    currentTimeDuration = new tizen.TimeDuration(1, "DAYS");
+    conversionTable = getTypeConversionExceptions("functionObject", false);
+    for (i = 0; i < conversionTable.length; i++) {
+        other = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+
+        assert_throws({name: exceptionName},
+            function () {
+                currentTimeDuration.equalsTo(other);
+            }, exceptionName + " should be thrown - given incorrect successCallback.");
+    }
+}, 'TimeDuration_equalsTo_other_TypeMismatch');
+
+}
+
+function TimeDuration_equalsTo_other_invalid_obj() {
+//==== TEST: TimeDuration_equalsTo_other_invalid_obj
+//==== LABEL Check argument validation in equalsTo method in TimeDuration.
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:System:Time:TimeDuration:equalsTo M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MTO
+test(function () {
+    var currentTimeDuration = [], exceptionName = TYPE_MISMATCH_ERR;
+
+    currentTimeDuration[0] = new tizen.TimeDuration(1, "DAYS");
+    currentTimeDuration[1] = {length: 2, unit: "MINS"};
+    assert_throws(TYPE_MISMATCH_EXCEPTION,
+        function () {
+            currentTimeDuration[0].equalsTo(currentTimeDuration[1]);
+        }, exceptionName + " should be thrown - given incorrect argument.");
+}, 'TimeDuration_equalsTo_other_invalid_obj');
+
+}
+
+function TimeDuration_exist() {
+//==== TEST: TimeDuration_exist
+//==== LABEL Test whether the constructor of the TimeDuration interface is defined or not.
+//==== PRIORITY: P0
+//==== SPEC: Tizen Web API:System:Time:TimeDuration:constructor C
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA CONSTRF
+test(function () {
+    check_constructor("TimeDuration");
+}, 'TimeDuration_exist');
+
+}
+
+function TimeDuration_extend() {
+//==== TEST: TimeDuration_extend
+//==== LABEL Test whether TimeDuration the object can have new attribute added
+//==== PRIORITY: P3
+//==== SPEC: Tizen Web API:System:Time:TimeDuration:TimeDuration U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA OBX
+test(function () {
+    var currentTimeDuration = new tizen.TimeDuration(1, "DAYS");
+    check_extensibility(currentTimeDuration);
+}, 'TimeDuration_extend');
+
+}
+
+function TimeDuration_greaterThan() {
+//==== TEST: TimeDuration_greaterThan
+//==== LABEL Check if method greaterThan of TimeDuration works properly.
+//==== SPEC: Tizen Web API:System:Time:TimeDuration:greaterThan M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA MR
+test(function () {
+    var timeDuration1, timeDuration2, returnedValue;
+    timeDuration1 = new tizen.TimeDuration(1, "DAYS");
+    timeDuration2 = new tizen.TimeDuration(60, "DAYS");
+    returnedValue = timeDuration1.greaterThan(timeDuration2);
+    assert_equals(returnedValue, false, "equalsTo value check");
+}, 'TimeDuration_greaterThan');
+
+}
+
+function TimeDuration_greaterThan_exist() {
+//==== TEST: TimeDuration_greaterThan_exist
+//==== LABEL Check if greaterThan method exists in TimeManager.
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TimeDuration:greaterThan M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    var currentTimeDuration = new tizen.TimeDuration(1, "DAYS");
+    assert_true("greaterThan" in currentTimeDuration, "greaterThan method exists");
+    check_method_exists(currentTimeDuration, "greaterThan");
+}, 'TimeDuration_greaterThan_exist');
+
+}
+
+function TimeDuration_greaterThan_missarg() {
+//==== TEST: TimeDuration_greaterThan_missarg
+//==== LABEL Check if greaterThan method with missing non-optional argument works
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:System:Time:TimeDuration:greaterThan M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMA
+test(function () {
+    var currentTimeDuration = new tizen.TimeDuration(1, "DAYS");
+    assert_throws(TYPE_MISMATCH_EXCEPTION,
+        function () {
+            currentTimeDuration.greaterThan();
+        });
+}, 'TimeDuration_greaterThan_missarg');
+
+}
+
+function TimeDuration_greaterThan_other_TypeMismatch() {
+//==== TEST: TimeDuration_greaterThan_other_TypeMismatch
+//==== LABEL Check argument greaterThan conversions exception.
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:System:Time:TimeDuration:greaterThan M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MC
+test(function () {
+    var currentTimeDuration, conversionTable, other, exceptionName, i;
+
+    currentTimeDuration = new tizen.TimeDuration(1, "DAYS");
+    conversionTable = getTypeConversionExceptions("functionObject", false);
+    for (i = 0; i < conversionTable.length; i++) {
+        other = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+
+        assert_throws({name: exceptionName},
+            function () {
+                currentTimeDuration.greaterThan(other);
+            }, exceptionName + " should be thrown - given incorrect successCallback.");
+    }
+}, 'TimeDuration_greaterThan_other_TypeMismatch');
+
+}
+
+function TimeDuration_greaterThan_other_invalid_obj() {
+//==== TEST: TimeDuration_greaterThan_other_invalid_obj
+//==== LABEL Check argument validation in greaterThan method in TimeDuration.
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:System:Time:TimeDuration:greaterThan M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MTO
+test(function () {
+    var currentTimeDuration = [], exceptionName = TYPE_MISMATCH_ERR;
+
+    currentTimeDuration[0] = new tizen.TimeDuration(1, "DAYS");
+    currentTimeDuration[1] = {length: 2, unit: "MINS"};
+    assert_throws(TYPE_MISMATCH_EXCEPTION,
+        function () {
+            currentTimeDuration[0].greaterThan(currentTimeDuration[1]);
+        }, exceptionName + " should be thrown - given incorrect argument.");
+}, 'TimeDuration_greaterThan_other_invalid_obj');
+
+}
+
+function TimeDuration_length_attribute() {
+//==== TEST: TimeDuration_length_attribute
+//==== LABEL Check existent and type attribute length
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TimeDuration:length A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA AE AT ASG AN
+var timeDuration;
+test(function () {
+    timeDuration = new tizen.TimeDuration(1);
+    assert_equals(timeDuration.length, 1, "Default value is incorrect");
+    check_attribute(timeDuration, "length", 1, "number", 5);
+    timeDuration.length = null;
+    assert_not_equals(timeDuration.length, null, "operation no accept null");
+}, 'TimeDuration_length_attribute');
+
+}
+
+function TimeDuration_lessThan() {
+//==== TEST: TimeDuration_lessThan
+//==== LABEL Check if method lessThan of TimeDuration works properly.
+//==== SPEC: Tizen Web API:System:Time:TimeDuration:lessThan M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA MR
+test(function () {
+    var timeDuration1, timeDuration2, returnedValue;
+    timeDuration1 = new tizen.TimeDuration(1, "DAYS");
+    timeDuration2 = new tizen.TimeDuration(60, "DAYS");
+    returnedValue = timeDuration1.lessThan(timeDuration2);
+    assert_equals(returnedValue, true, "equalsTo value check");
+}, 'TimeDuration_lessThan');
+
+}
+
+function TimeDuration_lessThan_exist() {
+//==== TEST: TimeDuration_lessThan_exist
+//==== LABEL Check if lessThan method exists in TimeManager.
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TimeDuration:lessThan M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    var currentTimeDuration = new tizen.TimeDuration(1, "DAYS");
+    assert_true("lessThan" in currentTimeDuration, "lessThan method exists");
+    check_method_exists(currentTimeDuration, "lessThan");
+}, 'TimeDuration_lessThan_exist');
+
+}
+
+function TimeDuration_lessThan_missarg() {
+//==== TEST: TimeDuration_lessThan_missarg
+//==== LABEL Check if lessThan method with missing non-optional argument works
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:System:Time:TimeDuration:lessThan M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMA
+test(function () {
+    var currentTimeDuration = new tizen.TimeDuration(1, "DAYS");
+    assert_throws(TYPE_MISMATCH_EXCEPTION,
+        function () {
+            currentTimeDuration.lessThan();
+        });
+}, 'TimeDuration_lessThan_missarg');
+
+}
+
+function TimeDuration_lessThan_other_TypeMismatch() {
+//==== TEST: TimeDuration_lessThan_other_TypeMismatch
+//==== LABEL Check argument lessThan conversions exception.
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:System:Time:TimeDuration:lessThan M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MC
+test(function () {
+    var currentTimeDuration, conversionTable, other, exceptionName, i;
+
+    currentTimeDuration = new tizen.TimeDuration(1, "DAYS");
+    conversionTable = getTypeConversionExceptions("functionObject", false);
+    for (i = 0; i < conversionTable.length; i++) {
+        other = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+
+        assert_throws({name: exceptionName},
+            function () {
+                currentTimeDuration.lessThan(other);
+            }, exceptionName + " should be thrown - given incorrect successCallback.");
+    }
+}, 'TimeDuration_lessThan_other_TypeMismatch');
+
+}
+
+function TimeDuration_lessThan_other_invalid_obj() {
+//==== TEST: TimeDuration_lessThan_other_invalid_obj
+//==== LABEL Check argument validation in lessThan method in TimeDuration.
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:System:Time:TimeDuration:lessThan M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MTO
+test(function () {
+    var currentTimeDuration = [], exceptionName = TYPE_MISMATCH_ERR;
+
+    currentTimeDuration[0] = new tizen.TimeDuration(1, "DAYS");
+    currentTimeDuration[1] = {length: 2, unit: "MINS"};
+    assert_throws(TYPE_MISMATCH_EXCEPTION,
+        function () {
+            currentTimeDuration[0].lessThan(currentTimeDuration[1]);
+        }, exceptionName + " should be thrown - given incorrect argument.");
+}, 'TimeDuration_lessThan_other_invalid_obj');
+
+}
+
+function TimeDuration_unit_attribute() {
+//==== TEST: TimeDuration_unit_attribute
+//==== LABEL Check existent and type attribute unit
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TimeDuration:unit A
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA AE AT ASG ADV AN
+var timeDuration;
+test(function () {
+    timeDuration = new tizen.TimeDuration(1, null);
+    assert_equals(timeDuration.unit, "MSECS", "Default value is incorrect");
+    timeDuration = new tizen.TimeDuration(1, "DAYS");
+    assert_equals(timeDuration.unit, "DAYS", "Get value is incorrect");
+    check_attribute(timeDuration, "unit", "DAYS", "string", "SECS");
+    timeDuration.unit = null;
+    assert_not_equals(timeDuration.unit, null, "operation no accept null");
+}, 'TimeDuration_unit_attribute');
+
+}
+
+function TimeUtil_extend() {
+//==== TEST: TimeUtil_extend
+//==== LABEL Test whether the TimeManager object can have new attribute added
+//==== PRIORITY: P3
+//==== SPEC: Tizen Web API:System:Time:TimeUtil:TimeUtil U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA OBX
+test(function () {
+    check_extensibility(tizen.time);
+}, 'TimeUtil_extend');
+
+}
+
+function TimeUtil_getAvailableTimezones() {
+//==== TEST: TimeUtil_getAvailableTimezones
+//==== LABEL Check if method getAvailableTimezones of TimeUtil works properly.
+//==== SPEC: Tizen Web API:System:Time:TimeUtil:getAvailableTimezones M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var returnedValue = null, i;
+    returnedValue = tizen.time.getAvailableTimezones();
+    assert_type(returnedValue, "array", "Timezone array type");
+    assert_not_equals(returnedValue, null, "null check");
+    for (i = 0; i < returnedValue.length; i++) {
+        assert_type(returnedValue[i], "string", "Timezone type - " + i);
+    }
+}, 'TimeUtil_getAvailableTimezones');
+
+}
+
+function TimeUtil_getAvailableTimezones_exist() {
+//==== TEST: TimeUtil_getAvailableTimezones_exist
+//==== LABEL Check if getAvailableTimezones method exists in TimeManager.
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TimeUtil:getAvailableTimezones M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    assert_true("getAvailableTimezones" in tizen.time, "getAvailableTimezones method exists");
+    check_method_exists(tizen.time, "getAvailableTimezones");
+}, 'TimeUtil_getAvailableTimezones_exist');
+
+}
+
+function TimeUtil_getAvailableTimezones_extra_argument() {
+//==== TEST: TimeUtil_getAvailableTimezones_extra_argument
+//==== LABEL Check if method getAvailableTimezones of TimeUtil accepts extra argument
+//==== SPEC: Tizen Web API:System:Time:TimeUtil:getAvailableTimezones M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNAEX
+test(function () {
+    checkExtraArgument(tizen.time, "getAvailableTimezones");
+}, 'TimeUtil_getAvailableTimezones_extra_argument');
+
+}
+
+function TimeUtil_getCurrentDateTime() {
+//==== TEST: TimeUtil_getCurrentDateTime
+//==== LABEL Check if method getCurrentDateTime of TimeUtil works properly.
+//==== SPEC: Tizen Web API:System:Time:TimeUtil:getCurrentDateTime M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA
+test(function () {
+    var returnedValue;
+    returnedValue = tizen.time.getCurrentDateTime();
+    assert_type(returnedValue, "object", "value type");
+    assert_not_equals(returnedValue, null, "null check");
+}, 'TimeUtil_getCurrentDateTime');
+
+}
+
+function TimeUtil_getCurrentDateTime_instanceof() {
+//==== TEST: TimeUtil_getCurrentDateTime_instanceof
+//==== LABEL Check whether getCurrentDateTime() method returns the current date / time correctly
+//==== SPEC Tizen Web API:System:Time:TimeUtil:getCurrentDateTime M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var currentDate = tizen.time.getCurrentDateTime(), i;
+
+    assert_true(currentDate instanceof tizen.TZDate, "testGetCurrentDateTime() date:");
+    for (i = 0; i < testAdditionalParamArray.length; i++) {
+        assert_true(tizen.time.getCurrentDateTime(testAdditionalParamArray[i])  instanceof tizen.TZDate, "testGetCurrentDateTime() date:");
+    }
+}, 'TimeUtil_getCurrentDateTime_instanceof');
+
+}
+
+function TimeUtil_getCurrentDateTime_exist() {
+//==== TEST: TimeUtil_getCurrentDateTime_exist
+//==== LABEL Check if getCurrentDateTime method exists in TimeManager.
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TimeUtil:getCurrentDateTime M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    assert_true("getCurrentDateTime" in tizen.time, "getCurrentDateTime method exists");
+    check_method_exists(tizen.time, "getCurrentDateTime");
+}, 'TimeUtil_getCurrentDateTime_exist');
+
+}
+
+function TimeUtil_getCurrentDateTime_extra_argument() {
+//==== TEST: TimeUtil_getCurrentDateTime_extra_argument
+//==== LABEL Check if method getCurrentDateTime of TimeUtil accepts extra argument
+//==== SPEC: Tizen Web API:System:Time:TimeUtil:getCurrentDateTime M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNAEX
+test(function () {
+    checkExtraArgument(tizen.time, "getCurrentDateTime");
+}, 'TimeUtil_getCurrentDateTime_extra_argument');
+
+}
+
+function TimeUtil_getDateFormat() {
+//==== TEST: TimeUtil_getDateFormat
+//==== LABEL Check if method getDateFormat of TimeUtil works properly.
+//==== SPEC: Tizen Web API:System:Time:TimeUtil:getDateFormat M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MOA MR
+test(function () {
+    var returnedValue, def = "d/m/y", shortformat = true;
+    returnedValue = tizen.time.getDateFormat(shortformat);
+    assert_type(returnedValue, "string", "Timezone type");
+}, 'TimeUtil_getDateFormat');
+
+}
+
+function TimeUtil_getDateFormat_exist() {
+//==== TEST: TimeUtil_getDateFormat_exist
+//==== LABEL Check if getDateFormat method exists in TimeManager.
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TimeUtil:getDateFormat M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    assert_true("getDateFormat" in tizen.time, "getDateFormat method exists");
+    check_method_exists(tizen.time, "getDateFormat");
+}, 'TimeUtil_getDateFormat_exist');
+
+}
+
+function TimeUtil_getLocalTimezone() {
+//==== TEST: TimeUtil_getLocalTimezone
+//==== LABEL Check if method getLocalTimezone of TimeUtil works properly.
+//==== SPEC: Tizen Web API:System:Time:TimeUtil:getLocalTimezone M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNA MR
+test(function () {
+    var returnedValue;
+    returnedValue = tizen.time.getLocalTimezone();
+    assert_type(returnedValue, "string", "Value type");
+    assert_equals(returnedValue, "Asia/Seoul", "Local timezone value");
+}, 'TimeUtil_getLocalTimezone');
+
+}
+
+function TimeUtil_getLocalTimezone_exist() {
+//==== TEST: TimeUtil_getLocalTimezone_exist
+//==== LABEL Check if getLocalTimezone method exists in TimeManager.
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TimeUtil:getLocalTimezone M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    assert_true("getLocalTimezone" in tizen.time, "getLocalTimezone method exists");
+    check_method_exists(tizen.time, "getLocalTimezone");
+}, 'TimeUtil_getLocalTimezone_exist');
+
+}
+
+function TimeUtil_getLocalTimezone_extra_argument() {
+//==== TEST: TimeUtil_getLocalTimezone_extra_argument
+//==== LABEL Check if method getLocalTimezone of TimeUtil accepts extra argument
+//==== SPEC: Tizen Web API:System:Time:TimeUtil:getLocalTimezone M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNAEX
+test(function () {
+    checkExtraArgument(tizen.time, "getLocalTimezone");
+}, 'TimeUtil_getLocalTimezone_extra_argument');
+
+}
+
+function TimeUtil_getTimeFormat_exist() {
+//==== TEST: TimeUtil_getTimeFormat_exist
+//==== LABEL Check if getTimeFormat method exists in TimeManager.
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TimeUtil:getTimeFormat M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    assert_true("getTimeFormat" in tizen.time, "getTimeFormat method exists");
+    check_method_exists(tizen.time, "getTimeFormat");
+}, 'TimeUtil_getTimeFormat_exist');
+
+}
+
+function TimeUtil_getTimeFormat_extra_argument() {
+//==== TEST: TimeUtil_getTimeFormat_extra_argument
+//==== LABEL Check if method getTimeFormat of TimeUtil accepts extra argument
+//==== SPEC: Tizen Web API:System:Time:TimeUtil:getTimeFormat M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MNAEX
+test(function () {
+    checkExtraArgument(tizen.time, "getTimeFormat");
+}, 'TimeUtil_getTimeFormat_extra_argument');
+
+}
+
+function TimeUtil_isLeapYear() {
+//==== TEST: TimeUtil_isLeapYear
+//==== LABEL Check if method isLeapYear of TimeUtil works properly.
+//==== SPEC: Tizen Web API:System:Time:TimeUtil:isLeapYear M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA MR
+test(function () {
+    var returnedValue, yearL = 2012, yearNl = 2013;
+    returnedValue = tizen.time.isLeapYear(yearL);
+    assert_equals(returnedValue, true, "Is leap year");
+    returnedValue = tizen.time.isLeapYear(yearNl);
+    assert_equals(returnedValue, false, "Is not leap year");
+}, 'TimeUtil_isLeapYear');
+
+}
+
+function TimeUtil_isLeapYear_exist() {
+//==== TEST: TimeUtil_isLeapYear_exist
+//==== LABEL Check if isLeapYear method exists in TimeManager.
+//==== PRIORITY: P1
+//==== SPEC: Tizen Web API:System:Time:TimeUtil:isLeapYear M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA ME
+test(function () {
+    assert_true("isLeapYear" in tizen.time, "isLeapYear method exists");
+    check_method_exists(tizen.time, "isLeapYear");
+}, 'TimeUtil_isLeapYear_exist');
+
+}
+
+function TimeUtil_notexist() {
+//==== TEST: TimeUtil_notexist
+//==== LABEL Check if interface TimeUtil exists, it should not.
+//==== PRIORITY: P3
+//==== SPEC: Tizen Web API:System:Time:TimeUtil:TimeUtil U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA NIO
+test(function () {
+    check_no_interface_object("TimeUtil");
+}, 'TimeUtil_notexist');
+
+}
+
+function TZDate_addDuration_invalidLength() {
+//==== TEST: TZDate_addDuration_invalidLength
+//==== LABEL Check TZDate::addDuration() method called with invalid length
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:System:Time:TZDate:addDuration M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+var diff, timeTesting, tz, tdur, tzAfterAdd;
+timeTesting = {f_value: 4.5, f_unit: "HOURS", diff_length: -14400000, diff_unit: "MSECS"};
+test(function () {
+    tz = tizen.time.getCurrentDateTime();
+    tdur = new tizen.TimeDuration(timeTesting.f_value, timeTesting.f_unit);
+    tzAfterAdd = tz.addDuration(tdur);
+    diff = tz.difference(tzAfterAdd);
+    assert_equals(diff.length, timeTesting.diff_length, "TimeDuration: wrong length difference for " +
+        timeTesting.f_value + " " + timeTesting.f_unit);
+    assert_equals(diff.unit, timeTesting.diff_unit, "TimeDuration: wrong unit difference for " + timeTesting.f_value + " " + timeTesting.f_unit);
+}, 'TZDate_addDuration_invalidLength');
+
+}
+
+function TZDate_addDuration_unitDAYS_negative() {
+//==== TEST: TZDate_addDuration_unitDAYS_negative
+//==== LABEL Check addDuration method for unit DAYS and negative length
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:System:Time:TZDate:addDuration M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+var diff, timeTesting, tz, tdur, tzAfterAdd;
+timeTesting = {f_value: -1, f_unit: "DAYS", diff_length: 1, diff_unit: "DAYS"};
+test(function () {
+    tz = tizen.time.getCurrentDateTime();
+    tdur = new tizen.TimeDuration(timeTesting.f_value, timeTesting.f_unit);
+    tzAfterAdd = tz.addDuration(tdur);
+    diff = tz.difference(tzAfterAdd);
+    assert_equals(diff.length, timeTesting.diff_length, "TimeDuration: wrong length difference for " +
+        timeTesting.f_value + " " + timeTesting.f_unit);
+    assert_equals(diff.unit, timeTesting.diff_unit, "TimeDuration: wrong unit difference for " + timeTesting.f_value + " " + timeTesting.f_unit);
+}, 'TZDate_addDuration_unitDAYS_negative');
+
+}
+
+function TZDate_addDuration_unitDAYS_one() {
+//==== TEST: TZDate_addDuration_unitDAYS_one
+//==== LABEL Check addDuration method for unit DAYS and one day
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:System:Time:TZDate:addDuration M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+var diff, timeTesting, tz, tdur, tzAfterAdd;
+timeTesting = {f_value: 1, f_unit: "DAYS", diff_length: -1, diff_unit: "DAYS"};
+test(function () {
+    tz = tizen.time.getCurrentDateTime();
+    tdur = new tizen.TimeDuration(timeTesting.f_value, timeTesting.f_unit);
+    tzAfterAdd = tz.addDuration(tdur);
+    diff = tz.difference(tzAfterAdd);
+    assert_equals(diff.length, timeTesting.diff_length, "TimeDuration: wrong length difference for " +
+        timeTesting.f_value + " " + timeTesting.f_unit);
+    assert_equals(diff.unit, timeTesting.diff_unit, "TimeDuration: wrong unit difference for " + timeTesting.f_value + " " + timeTesting.f_unit);
+}, 'TZDate_addDuration_unitDAYS_one');
+
+}
+
+function TZDate_addDuration_unitDAYS_week() {
+//==== TEST: TZDate_addDuration_unitDAYS_week
+//==== LABEL Check addDuration method for unit DAYS adding week
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:System:Time:TZDate:addDuration M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+var diff, timeTesting, tz, tdur, tzAfterAdd;
+timeTesting = {f_value: 7, f_unit: "DAYS", diff_length: -7, diff_unit: "DAYS"};
+test(function () {
+    tz = tizen.time.getCurrentDateTime();
+    tdur = new tizen.TimeDuration(timeTesting.f_value, timeTesting.f_unit);
+    tzAfterAdd = tz.addDuration(tdur);
+    diff = tz.difference(tzAfterAdd);
+    assert_equals(diff.length, timeTesting.diff_length, "TimeDuration: wrong length difference for " +
+        timeTesting.f_value + " " + timeTesting.f_unit);
+    assert_equals(diff.unit, timeTesting.diff_unit, "TimeDuration: wrong unit difference for " + timeTesting.f_value + " " + timeTesting.f_unit);
+}, 'TZDate_addDuration_unitDAYS_week');
+
+}
+
+function TZDate_addDuration_unitDAYS_year() {
+//==== TEST: TZDate_addDuration_unitDAYS_year
+//==== LABEL Check addDuration method for unit DAYS adding year
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:System:Time:TZDate:addDuration M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+var diff, timeTesting, tz, tdur, tzAfterAdd;
+timeTesting = {f_value: 365, f_unit: "DAYS", diff_length: -365, diff_unit: "DAYS"};
+test(function () {
+    tz = tizen.time.getCurrentDateTime();
+    tdur = new tizen.TimeDuration(timeTesting.f_value, timeTesting.f_unit);
+    tzAfterAdd = tz.addDuration(tdur);
+    diff = tz.difference(tzAfterAdd);
+    assert_equals(diff.length, timeTesting.diff_length, "TimeDuration: wrong length difference for " +
+        timeTesting.f_value + " " + timeTesting.f_unit);
+    assert_equals(diff.unit, timeTesting.diff_unit, "TimeDuration: wrong unit difference for " + timeTesting.f_value + " " + timeTesting.f_unit);
+}, 'TZDate_addDuration_unitDAYS_year');
+
+}
+
+function TZDate_addDuration_unitHOURS() {
+//==== TEST: TZDate_addDuration_unitHOURS
+//==== LABEL Check addDuration method for unit HOURS
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:System:Time:TZDate:addDuration M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+var diff, timeTesting, tz, tdur, tzAfterAdd;
+timeTesting = {f_value: 2, f_unit: "HOURS", diff_length: -7200000, diff_unit: "MSECS"};
+test(function () {
+    tz = tizen.time.getCurrentDateTime();
+    tdur = new tizen.TimeDuration(timeTesting.f_value, timeTesting.f_unit);
+    tzAfterAdd = tz.addDuration(tdur);
+    diff = tz.difference(tzAfterAdd);
+    assert_equals(diff.length, timeTesting.diff_length, "TimeDuration: wrong length difference for " +
+        timeTesting.f_value + " " + timeTesting.f_unit);
+    assert_equals(diff.unit, timeTesting.diff_unit, "TimeDuration: wrong unit difference for " + timeTesting.f_value + " " + timeTesting.f_unit);
+}, 'TZDate_addDuration_unitHOURS');
+
+}
+
+function TZDate_addDuration_unitHOURS_moreThanOneDay() {
+//==== TEST: TZDate_addDuration_unitHOURS_moreThanOneDay
+//==== LABEL Check addDuration method for unit HOURS adding 25 hours
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:System:Time:TZDate:addDuration M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+var diff, timeTesting, tz, tdur, tzAfterAdd;
+timeTesting = {f_value: 25, f_unit: "HOURS", diff_length: -90000000, diff_unit: "MSECS"};
+test(function () {
+    tz = tizen.time.getCurrentDateTime();
+    tdur = new tizen.TimeDuration(timeTesting.f_value, timeTesting.f_unit);
+    tzAfterAdd = tz.addDuration(tdur);
+    diff = tz.difference(tzAfterAdd);
+    assert_equals(diff.length, timeTesting.diff_length, "TimeDuration: wrong length difference for " +
+        timeTesting.f_value + " " + timeTesting.f_unit);
+    assert_equals(diff.unit, timeTesting.diff_unit, "TimeDuration: wrong unit difference for " + timeTesting.f_value + " " + timeTesting.f_unit);
+}, 'TZDate_addDuration_unitHOURS_moreThanOneDay');
+
+}
+
+function TZDate_addDuration_unitHOURS_negative() {
+//==== TEST: TZDate_addDuration_unitHOURS_negative
+//==== LABEL Check addDuration method for unit HOURS and negative length
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:System:Time:TZDate:addDuration M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+var diff, timeTesting, tz, tdur, tzAfterAdd;
+timeTesting = {f_value: -1, f_unit: "HOURS", diff_length: 3600000, diff_unit: "MSECS"};
+test(function () {
+    tz = tizen.time.getCurrentDateTime();
+    tdur = new tizen.TimeDuration(timeTesting.f_value, timeTesting.f_unit);
+    tzAfterAdd = tz.addDuration(tdur);
+    diff = tz.difference(tzAfterAdd);
+    assert_equals(diff.length, timeTesting.diff_length, "TimeDuration: wrong length difference for " +
+        timeTesting.f_value + " " + timeTesting.f_unit);
+    assert_equals(diff.unit, timeTesting.diff_unit, "TimeDuration: wrong unit difference for " + timeTesting.f_value + " " + timeTesting.f_unit);
+}, 'TZDate_addDuration_unitHOURS_negative');
+
+}
+
+function TZDate_addDuration_unitMINS() {
+//==== TEST: TZDate_addDuration_unitMINS
+//==== LABEL Check addDuration method for unit MINS
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:System:Time:TZDate:addDuration M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+var diff, timeTesting, tz, tdur, tzAfterAdd;
+timeTesting = {f_value: 1, f_unit: "MINS", diff_length: -60000, diff_unit: "MSECS"};
+test(function () {
+    tz = tizen.time.getCurrentDateTime();
+    tdur = new tizen.TimeDuration(timeTesting.f_value, timeTesting.f_unit);
+    tzAfterAdd = tz.addDuration(tdur);
+    diff = tz.difference(tzAfterAdd);
+    assert_equals(diff.length, timeTesting.diff_length, "TimeDuration: wrong length difference for " +
+        timeTesting.f_value + " " + timeTesting.f_unit);
+    assert_equals(diff.unit, timeTesting.diff_unit, "TimeDuration: wrong unit difference for " + timeTesting.f_value + " " + timeTesting.f_unit);
+}, 'TZDate_addDuration_unitMINS');
+
+}
+
+function TZDate_addDuration_unitMINS_complexNum() {
+//==== TEST: TZDate_addDuration_unitMINS_complexNum
+//==== LABEL Check addDuration method for unit MINS and length of 5
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:System:Time:TZDate:addDuration M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+var diff, timeTesting, tz, tdur, tzAfterAdd;
+timeTesting = {f_value: 5, f_unit: "MINS", diff_length: -300000, diff_unit: "MSECS"};
+test(function () {
+    tz = tizen.time.getCurrentDateTime();
+    tdur = new tizen.TimeDuration(timeTesting.f_value, timeTesting.f_unit);
+    tzAfterAdd = tz.addDuration(tdur);
+    diff = tz.difference(tzAfterAdd);
+    assert_equals(diff.length, timeTesting.diff_length, "TimeDuration: wrong length difference for " +
+        timeTesting.f_value + " " + timeTesting.f_unit);
+    assert_equals(diff.unit, timeTesting.diff_unit, "TimeDuration: wrong unit difference for " + timeTesting.f_value + " " + timeTesting.f_unit);
+}, 'TZDate_addDuration_unitMINS_complexNum');
+
+}
+
+function TZDate_addDuration_unitMINS_negative() {
+//==== TEST: TZDate_addDuration_unitMINS_negative
+//==== LABEL Check addDuration method for unit MINS and negative length
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:System:Time:TZDate:addDuration M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+var diff, timeTesting, tz, tdur, tzAfterAdd;
+timeTesting = {f_value: -1, f_unit: "MINS", diff_length: 60000, diff_unit: "MSECS"};
+test(function () {
+    tz = tizen.time.getCurrentDateTime();
+    tdur = new tizen.TimeDuration(timeTesting.f_value, timeTesting.f_unit);
+    tzAfterAdd = tz.addDuration(tdur);
+    diff = tz.difference(tzAfterAdd);
+    assert_equals(diff.length, timeTesting.diff_length, "TimeDuration: wrong length difference for " +
+        timeTesting.f_value + " " + timeTesting.f_unit);
+    assert_equals(diff.unit, timeTesting.diff_unit, "TimeDuration: wrong unit difference for " + timeTesting.f_value + " " + timeTesting.f_unit);
+}, 'TZDate_addDuration_unitMINS_negative');
+
+}
+
+function TZDate_addDuration_unitMSECS() {
+//==== TEST: TZDate_addDuration_unitMSECS
+//==== LABEL Check addDuration method for unit MSECS
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:System:Time:TZDate:addDuration M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+var diff, timeTesting, tz, tdur, tzAfterAdd;
+timeTesting = {f_value: 1, f_unit: "MSECS", diff_length: -1, diff_unit: "MSECS"};
+test(function () {
+    tz = tizen.time.getCurrentDateTime();
+    tdur = new tizen.TimeDuration(timeTesting.f_value, timeTesting.f_unit);
+    tzAfterAdd = tz.addDuration(tdur);
+    diff = tz.difference(tzAfterAdd);
+    assert_equals(diff.length, timeTesting.diff_length, "TimeDuration: wrong length difference for " +
+        timeTesting.f_value + " " + timeTesting.f_unit);
+    assert_equals(diff.unit, timeTesting.diff_unit, "TimeDuration: wrong unit difference for " + timeTesting.f_value + " " + timeTesting.f_unit);
+}, 'TZDate_addDuration_unitMSECS');
+
+}
+
+function TZDate_addDuration_unitMSECS_complexNum() {
+//==== TEST: TZDate_addDuration_unitMSECS_complexNum
+//==== LABEL Check addDuration method for unit MSECS and length of 45
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:System:Time:TZDate:addDuration M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+var diff, timeTesting, tz, tdur, tzAfterAdd;
+timeTesting = {f_value: 45, f_unit: "MSECS", diff_length: -45, diff_unit: "MSECS"};
+test(function () {
+    tz = tizen.time.getCurrentDateTime();
+    tdur = new tizen.TimeDuration(timeTesting.f_value, timeTesting.f_unit);
+    tzAfterAdd = tz.addDuration(tdur);
+    diff = tz.difference(tzAfterAdd);
+    assert_equals(diff.length, timeTesting.diff_length, "TimeDuration: wrong length difference for " +
+            timeTesting.f_value + " " + timeTesting.f_unit);
+    assert_equals(diff.unit, timeTesting.diff_unit, "TimeDuration: wrong unit difference for " + timeTesting.f_value + " " + timeTesting.f_unit);
+}, 'TZDate_addDuration_unitMSECS_complexNum');
+
+}
+
+function TZDate_addDuration_unitMSECS_negative() {
+//==== TEST: TZDate_addDuration_unitMSECS_negative
+//==== LABEL Check addDuration method for unit MSECS and negative length
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:System:Time:TZDate:addDuration M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+var diff, timeTesting, tz, tdur, tzAfterAdd;
+timeTesting = {f_value: -1, f_unit: "MSECS", diff_length: 1, diff_unit: "MSECS"};
+test(function () {
+    tz = tizen.time.getCurrentDateTime();
+    tdur = new tizen.TimeDuration(timeTesting.f_value, timeTesting.f_unit);
+    tzAfterAdd = tz.addDuration(tdur);
+    diff = tz.difference(tzAfterAdd);
+    assert_equals(diff.length, timeTesting.diff_length, "TimeDuration: wrong length difference for " +
+        timeTesting.f_value + " " + timeTesting.f_unit);
+    assert_equals(diff.unit, timeTesting.diff_unit, "TimeDuration: wrong unit difference for " + timeTesting.f_value + " " + timeTesting.f_unit);
+}, 'TZDate_addDuration_unitMSECS_negative');
+
+}
+
+function TZDate_addDuration_unitSECS() {
+//==== TEST: TZDate_addDuration_unitSECS
+//==== LABEL Check addDuration method for unit SECS
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:System:Time:TZDate:addDuration M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+var diff, timeTesting, tz, tdur, tzAfterAdd;
+timeTesting = {f_value: 1, f_unit: "SECS", diff_length: -1000, diff_unit: "MSECS"};
+test(function () {
+    tz = tizen.time.getCurrentDateTime();
+    tdur = new tizen.TimeDuration(timeTesting.f_value, timeTesting.f_unit);
+    tzAfterAdd = tz.addDuration(tdur);
+    diff = tz.difference(tzAfterAdd);
+    assert_equals(diff.length, timeTesting.diff_length, "TimeDuration: wrong length difference for " +
+        timeTesting.f_value + " " + timeTesting.f_unit);
+    assert_equals(diff.unit, timeTesting.diff_unit, "TimeDuration: wrong unit difference for " + timeTesting.f_value + " " + timeTesting.f_unit);
+}, 'TZDate_addDuration_unitSECS');
+
+}
+
+function TZDate_addDuration_unitSECS_complexNum() {
+//==== TEST: TZDate_addDuration_unitSECS_complexNum
+//==== LABEL Check addDuration method for unit SECS and length of 45
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:System:Time:TZDate:addDuration M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+var diff, timeTesting, tz, tdur, tzAfterAdd;
+timeTesting = {f_value: 45, f_unit: "SECS", diff_length: -45000, diff_unit: "MSECS"};
+test(function () {
+    tz = tizen.time.getCurrentDateTime();
+    tdur = new tizen.TimeDuration(timeTesting.f_value, timeTesting.f_unit);
+    tzAfterAdd = tz.addDuration(tdur);
+    diff = tz.difference(tzAfterAdd);
+    assert_equals(diff.length, timeTesting.diff_length, "TimeDuration: wrong length difference for " +
+        timeTesting.f_value + " " + timeTesting.f_unit);
+    assert_equals(diff.unit, timeTesting.diff_unit, "TimeDuration: wrong unit difference for " + timeTesting.f_value + " " + timeTesting.f_unit);
+}, 'TZDate_addDuration_unitSECS_complexNum');
+
+}
+
+function TZDate_addDuration_unitSECS_negative() {
+//==== TEST: TZDate_addDuration_unitSECS_negative
+//==== LABEL Check addDuration method for unit SECS and negative length
+//==== PRIORITY: P2
+//==== SPEC: Tizen Web API:System:Time:TZDate:addDuration M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+var diff, timeTesting, tz, tdur, tzAfterAdd;
+timeTesting = {f_value: -1, f_unit: "SECS", diff_length: 1000, diff_unit: "MSECS"};
+test(function () {
+    tz = tizen.time.getCurrentDateTime();
+    tdur = new tizen.TimeDuration(timeTesting.f_value, timeTesting.f_unit);
+    tzAfterAdd = tz.addDuration(tdur);
+    diff = tz.difference(tzAfterAdd);
+    assert_equals(diff.length, timeTesting.diff_length, "TimeDuration: wrong length difference for " +
+        timeTesting.f_value + " " + timeTesting.f_unit);
+    assert_equals(diff.unit, timeTesting.diff_unit, "TimeDuration: wrong unit difference for " + timeTesting.f_value + " " + timeTesting.f_unit);
+}, 'TZDate_addDuration_unitSECS_negative');
+
+}
+
+function Time_TZDate_difference_compareWithPastDate() {
+//==== TEST: Time_TZDate_difference_compareWithPastDate
+//==== LABEL Check if TZDate.difference() with past date works
+//==== PRIORITY P1
+//==== SPEC Tizen Web API:System:Time:TZDate:difference M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+test(function () {
+    var tzNow = new tizen.TZDate(2013, 1, 8),
+        tzPast = new tizen.TZDate(2013, 1, 6),
+        diff;
+
+    diff = tzNow.difference(tzPast);
+    assert_equals(diff.length, 2, "diff.length check");
+    assert_equals(diff.unit, "DAYS", "diff.unit check");
+}, 'Time_TZDate_difference_compareWithPastDate');
+
+}
+
+function Time_TZDate_difference_compareWithPastHour() {
+//==== TEST: Time_TZDate_difference_compareWithPastHour
+//==== LABEL Check if TZDate.difference() with date hour earlier works
+//==== PRIORITY P1
+//==== SPEC Tizen Web API:System:Time:TZDate:difference M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+test(function () {
+    var tzNow = new tizen.TZDate(2013, 1, 8, 10),
+        tzPast = new tizen.TZDate(2013, 1, 8, 5),
+        diff;
+
+    diff = tzNow.difference(tzPast);
+    assert_equals(diff.length, 18000000, "diff.length check"); // 5 hours in msecs
+    assert_equals(diff.unit, "MSECS", "diff.unit check");
+}, 'Time_TZDate_difference_compareWithPastHour');
+
+}
+
+function Time_TZDate_difference_compareWithPastSeconds() {
+//==== TEST: Time_TZDate_difference_compareWithPastSeconds
+//==== LABEL Check if TZDate.difference() with date seconds earlier works
+//==== PRIORITY P1
+//==== SPEC Tizen Web API:System:Time:TZDate:difference M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+test(function () {
+    var tzNow = new tizen.TZDate(2013, 1, 8, 12, 20, 30),
+        tzPast = new tizen.TZDate(2013, 1, 8, 12, 20, 10),
+        diff;
+
+    diff = tzNow.difference(tzPast);
+    assert_equals(diff.length, 20000, "diff.length check");
+    assert_equals(diff.unit, "MSECS", "diff.unit check");
+}, 'Time_TZDate_difference_compareWithPastSeconds');
+
+}
+
+function Time_TZDate_difference_compareWithPastYear() {
+//==== TEST: Time_TZDate_difference_compareWithPastYear
+//==== LABEL Check if TZDate.difference() with date year earlier works
+//==== PRIORITY P1
+//==== SPEC Tizen Web API:System:Time:TZDate:difference M
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA MMINA
+test(function () {
+    var tzNow = new tizen.TZDate(2002, 5, 20),
+        tzPast = new tizen.TZDate(2001, 5, 20),
+        diff;
+
+    diff = tzNow.difference(tzPast);
+    assert_equals(diff.length, 365, "diff.length check");
+    assert_equals(diff.unit, "DAYS", "diff.unit check");
+}, 'Time_TZDate_difference_compareWithPastYear');
+
+}
+
+function Time_in_tizen() {
+//==== TEST: Time_in_tizen
+//==== LABEL Check existent and type attribute time
+//==== PRIORITY: P3
+//==== SPEC: Tizen Web API:System:Time:TimeUtil:TimeUtil U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA OBME
+test(function () {
+    assert_true("time" in tizen, "No time in tizen.");
+    check_readonly(tizen, "time", tizen.time, "object", "Tizen");
+}, 'Time_in_tizen');
+
+}
+
+function TimeManagerObject_notexist() {
+//==== TEST: TimeManagerObject_notexist
+//==== LABEL Check if interface TimeManagerObject exists, it should not.
+//==== PRIORITY: P3
+//==== SPEC: Tizen Web API:System:Time:TimeManagerObject:TimeManagerObject U
+//==== SPEC_URL https://developer.tizen.org/help/topic/org.tizen.web.device.apireference/tizen/time.html
+//==== TEST_CRITERIA NIO
+test(function () {
+    check_no_interface_object("TimeManagerObject");
+}, 'TimeManagerObject_notexist');
+
+}
+
+var moduleName = "tct-time-tizen-tests";
+add_test_case(moduleName, Time_TZDate_toLocaleDateString);
+add_test_case(moduleName, Time_TZDate_getUTCSeconds);
+add_test_case(moduleName, Time_TZDate_getHours);
+add_test_case(moduleName, Time_TZDate_getUTCMilliseconds);
+add_test_case(moduleName, Time_TZDate_toUTC);
+add_test_case(moduleName, Time_TZDate_setSeconds_normal);
+add_test_case(moduleName, Time_TZDate_earlierThan_true);
+add_test_case(moduleName, Time_TZDate_difference_compareWithEqual);
+add_test_case(moduleName, Time_TZDate_setMilliseconds_normal);
+add_test_case(moduleName, Time_TZDate_getUTCFullYear);
+add_test_case(moduleName, Time_TZDate_secondsFromUTC);
+add_test_case(moduleName, Time_TZDate_toLocaleString);
+add_test_case(moduleName, Time_TZDate_setUTCFullYear_normal);
+add_test_case(moduleName, Time_TZDate_setFullYear_normal);
+add_test_case(moduleName, Time_TZDate_getMinutes);
+add_test_case(moduleName, Time_TZDate_getPreviousDSTTransition);
+add_test_case(moduleName, Time_TZDate_setDate_normal);
+add_test_case(moduleName, Time_TZDate_setMinutes_normal);
+add_test_case(moduleName, Time_TZDate_getTimezoneAbbreviation_summerMonth);
+add_test_case(moduleName, Time_TZDate_setUTCMilliseconds_normal);
+add_test_case(moduleName, Time_TZDate_toDateString);
+add_test_case(moduleName, Time_TZDate_getTimezone);
+add_test_case(moduleName, Time_TZDate_toTimeString);
+add_test_case(moduleName, Time_TZDate_toString);
+add_test_case(moduleName, Time_TZDate_getUTCHours);
+add_test_case(moduleName, Time_TZDate_setUTCMinutes_normal);
+add_test_case(moduleName, Time_TZDate_getDay);
+add_test_case(moduleName, Time_TZDate_setUTCMonth_normal);
+add_test_case(moduleName, Time_TZDate_getUTCDay);
+add_test_case(moduleName, Time_TZDate_getMilliseconds);
+add_test_case(moduleName, Time_TZDate_getUTCMinutes);
+add_test_case(moduleName, Time_TZDate_laterThan_true);
+add_test_case(moduleName, Time_TZDate_equalsTo_equal);
+add_test_case(moduleName, Time_TZDate_getMonth);
+add_test_case(moduleName, Time_TZDate_getNextDSTTransition);
+add_test_case(moduleName, Time_TZDate_getUTCMonth);
+add_test_case(moduleName, Time_TZDate_toTimezone);
+add_test_case(moduleName, Time_TZDate_isDST_true);
+add_test_case(moduleName, Time_TZDate_setUTCSeconds_normal);
+add_test_case(moduleName, Time_TZDate_getUTCDate);
+add_test_case(moduleName, Time_TZDate_toLocaleTimeString);
+add_test_case(moduleName, Time_TZDate_setMonth_normal);
+add_test_case(moduleName, Time_TZDate_setUTCHours_normal);
+add_test_case(moduleName, Time_TZDate_getSeconds);
+add_test_case(moduleName, Time_TZDate_getDate);
+add_test_case(moduleName, Time_TZDate_getFullYear);
+add_test_case(moduleName, Time_TZDate_setHours_normal);
+add_test_case(moduleName, Time_TZDate_setUTCDate_normal);
+add_test_case(moduleName, Time_TZDate_difference_compareWithFutureDate);
+add_test_case(moduleName, Time_TZDate_difference_compareWithFutureHour);
+add_test_case(moduleName, Time_TZDate_difference_compareWithFutureSeconds);
+add_test_case(moduleName, Time_TZDate_difference_compareWithFutureYear);
+add_test_case(moduleName, Time_TZDate_difference_compareWithCharacter);
+add_test_case(moduleName, Time_TZDate_earlierThan_falseEqual);
+add_test_case(moduleName, Time_TZDate_earlierThan_falseLater);
+add_test_case(moduleName, Time_TZDate_earlierThan_stringTZDate);
+add_test_case(moduleName, Time_TZDate_earlierThan_number);
+add_test_case(moduleName, Time_TZDate_earlierThan_character);
+add_test_case(moduleName, Time_TZDate_earlierThan_timezone);
+add_test_case(moduleName, Time_TZDate_equalsTo_diff);
+add_test_case(moduleName, Time_TZDate_equalsTo_number);
+add_test_case(moduleName, Time_TZDate_equalsTo_character);
+add_test_case(moduleName, Time_TZDate_laterThan_falseEarlier);
+add_test_case(moduleName, Time_TZDate_laterThan_falseEqual);
+add_test_case(moduleName, Time_TZDate_laterThan_number);
+add_test_case(moduleName, Time_TZDate_laterThan_character);
+add_test_case(moduleName, Time_TZDate_laterThan_timezone);
+add_test_case(moduleName, Time_TZDate_setDate_abnormalDecimal);
+add_test_case(moduleName, Time_TZDate_setDate_boundaryBiggerThanUpper);
+add_test_case(moduleName, Time_TZDate_setDate_boundaryLessThanLower);
+add_test_case(moduleName, Time_TZDate_setDate_boundaryLowerLimit);
+add_test_case(moduleName, Time_TZDate_setDate_boundaryUpperLimit);
+add_test_case(moduleName, Time_TZDate_setDate_invalidDate);
+add_test_case(moduleName, Time_TZDate_setDate_notExistDayForCertainMonth);
+add_test_case(moduleName, Time_TZDate_setDate_notExistDayForFebruaryLeapYear);
+add_test_case(moduleName, Time_TZDate_setDate_notExistDayForFebruaryNotLeapYear);
+add_test_case(moduleName, Time_TZDate_setFullYear_abnormalDecimal);
+add_test_case(moduleName, Time_TZDate_setFullYear_boundaryBiggerThanUpper);
+add_test_case(moduleName, Time_TZDate_setFullYear_boundaryLowerLimit);
+add_test_case(moduleName, Time_TZDate_setFullYear_boundaryUpperLimit);
+add_test_case(moduleName, Time_TZDate_setFullYear_invalidYear);
+add_test_case(moduleName, Time_TZDate_setFullYear_invalidCharYear);
+add_test_case(moduleName, Time_TZDate_setHours_abnormalDecimal);
+add_test_case(moduleName, Time_TZDate_setHours_boundaryBiggerThanUpper);
+add_test_case(moduleName, Time_TZDate_setHours_boundaryLessThanLower);
+add_test_case(moduleName, Time_TZDate_setHours_boundaryLowerLimit);
+add_test_case(moduleName, Time_TZDate_setHours_boundaryUpperLimit);
+add_test_case(moduleName, Time_TZDate_setHours_invalidHours);
+add_test_case(moduleName, Time_TZDate_setMilliseconds_abnormalDecimal);
+add_test_case(moduleName, Time_TZDate_setMilliseconds_boundaryBiggerThanUpper);
+add_test_case(moduleName, Time_TZDate_setMilliseconds_boundaryLessThanLower);
+add_test_case(moduleName, Time_TZDate_setMilliseconds_boundaryLowerLimit);
+add_test_case(moduleName, Time_TZDate_setMilliseconds_boundaryUpperLimit);
+add_test_case(moduleName, Time_TZDate_setMilliseconds_invalidMilliseconds);
+add_test_case(moduleName, Time_TZDate_setMinutes_abnormalDecimal);
+add_test_case(moduleName, Time_TZDate_setMinutes_boundaryLessThanLower);
+add_test_case(moduleName, Time_TZDate_setMinutes_boundaryLowerLimit);
+add_test_case(moduleName, Time_TZDate_setMinutes_boundaryUpperLimit);
+add_test_case(moduleName, Time_TZDate_setMinutes_invalidMinutes);
+add_test_case(moduleName, Time_TZDate_setMonth_abnormalDecimal);
+add_test_case(moduleName, Time_TZDate_setMonth_boundaryBiggerThanUpper);
+add_test_case(moduleName, Time_TZDate_setMonth_boundaryLessThanLower);
+add_test_case(moduleName, Time_TZDate_setMonth_boundaryLowerLimit);
+add_test_case(moduleName, Time_TZDate_setMonth_boundaryUpperLimit);
+add_test_case(moduleName, Time_TZDate_setMonth_invalidMonth);
+add_test_case(moduleName, Time_TZDate_setSeconds_abnormalDecimal);
+add_test_case(moduleName, Time_TZDate_setSeconds_boundaryBiggerThanUpper);
+add_test_case(moduleName, Time_TZDate_setSeconds_boundaryLessThanLower);
+add_test_case(moduleName, Time_TZDate_setSeconds_boundaryLowerLimit);
+add_test_case(moduleName, Time_TZDate_setSeconds_boundaryUpperLimit);
+add_test_case(moduleName, Time_TZDate_setSeconds_invalidSeconds);
+add_test_case(moduleName, Time_TZDate_setUTCDate_abnormalDecimal);
+add_test_case(moduleName, Time_TZDate_setUTCDate_boundaryBiggerThanUpper);
+add_test_case(moduleName, Time_TZDate_setUTCDate_boundaryLessThanLower);
+add_test_case(moduleName, Time_TZDate_setUTCDate_boundaryLowerLimit);
+add_test_case(moduleName, Time_TZDate_setUTCDate_boundaryUpperLimit);
+add_test_case(moduleName, Time_TZDate_setUTCDate_invalidDate);
+add_test_case(moduleName, Time_TZDate_setUTCDate_notExistDayForCertainMonth);
+add_test_case(moduleName, Time_TZDate_setUTCDate_notExistDayForFebruaryLeapYear);
+add_test_case(moduleName, Time_TZDate_setUTCDate_notExistDayForFebruaryNotLeapYear);
+add_test_case(moduleName, Time_TZDate_setUTCFullYear_abnormalDecimal);
+add_test_case(moduleName, Time_TZDate_setUTCFullYear_boundaryBiggerThanUpper);
+add_test_case(moduleName, Time_TZDate_setUTCFullYear_boundaryLowerLimit);
+add_test_case(moduleName, Time_TZDate_setUTCFullYear_boundaryUpperLimit);
+add_test_case(moduleName, Time_TZDate_setUTCFullYear_invalidYear);
+add_test_case(moduleName, Time_TZDate_setUTCFullYear_invalidCharYear);
+add_test_case(moduleName, Time_TZDate_setUTCHours_abnormalDecimal);
+add_test_case(moduleName, Time_TZDate_setUTCHours_boundaryBiggerThanUpper);
+add_test_case(moduleName, Time_TZDate_setUTCHours_boundaryLessThanLower);
+add_test_case(moduleName, Time_TZDate_setUTCHours_boundaryLowerLimit);
+add_test_case(moduleName, Time_TZDate_setUTCHours_boundaryUpperLimit);
+add_test_case(moduleName, Time_TZDate_setUTCHours_invalidHours);
+add_test_case(moduleName, Time_TZDate_setUTCMilliseconds_abnormalDecimal);
+add_test_case(moduleName, Time_TZDate_setUTCMilliseconds_boundaryBiggerThanUpper);
+add_test_case(moduleName, Time_TZDate_setUTCMilliseconds_boundaryLessThanLower);
+add_test_case(moduleName, Time_TZDate_setUTCMilliseconds_boundaryLowerLimit);
+add_test_case(moduleName, Time_TZDate_setUTCMilliseconds_boundaryUpperLimit);
+add_test_case(moduleName, Time_TZDate_setUTCMilliseconds_invalidMilliseconds);
+add_test_case(moduleName, Time_TZDate_setUTCMinutes_abnormalDecimal);
+add_test_case(moduleName, Time_TZDate_setUTCMinutes_boundaryBiggerThanUpper);
+add_test_case(moduleName, Time_TZDate_setUTCMinutes_boundaryLessThanLower);
+add_test_case(moduleName, Time_TZDate_setUTCMinutes_boundaryLowerLimit);
+add_test_case(moduleName, Time_TZDate_setUTCMinutes_boundaryUpperLimit);
+add_test_case(moduleName, Time_TZDate_setUTCMinutes_invalidMinutes);
+add_test_case(moduleName, Time_TZDate_setUTCMonth_abnormalDecimal);
+add_test_case(moduleName, Time_TZDate_setUTCMonth_boundaryBiggerThanUpper);
+add_test_case(moduleName, Time_TZDate_setUTCMonth_boundaryLessThanLower);
+add_test_case(moduleName, Time_TZDate_setUTCMonth_boundaryLowerLimit);
+add_test_case(moduleName, Time_TZDate_setUTCMonth_boundaryUpperLimit);
+add_test_case(moduleName, Time_TZDate_setUTCMonth_invalidMonth);
+add_test_case(moduleName, Time_TZDate_setUTCSeconds_abnormalDecimal);
+add_test_case(moduleName, Time_TZDate_setUTCSeconds_boundaryBiggerThanUpper);
+add_test_case(moduleName, Time_TZDate_setUTCSeconds_boundaryLessThanLower);
+add_test_case(moduleName, Time_TZDate_setUTCSeconds_boundaryLowerLimit);
+add_test_case(moduleName, Time_TZDate_setUTCSeconds_boundaryUpperLimit);
+add_test_case(moduleName, Time_TZDate_setUTCSeconds_invalidSeconds);
+add_test_case(moduleName, Time_TZDate_toTimezone_invalid);
+add_test_case(moduleName, Time_TZDate_toTimezone_null);
+add_test_case(moduleName, Time_TZDate_isDST_false);
+add_test_case(moduleName, Time_TZDate_isDST_boundaryLowerLimit_true);
+add_test_case(moduleName, Time_TZDate_isDST_boundaryUpperLimit_true);
+add_test_case(moduleName, Time_TZDate_getPreviousDSTTransition_number);
+add_test_case(moduleName, Time_TZDate_getPreviousDSTTransition_character);
+add_test_case(moduleName, Time_TZDate_getNextDSTTransition_character);
+add_test_case(moduleName, Time_TZDate_getNextDSTTransition_number);
+add_test_case(moduleName, TimeDuration_difference_checkDurationDifference);
+add_test_case(moduleName, TimeDuration_equalsTo_checkDurationEqual);
+add_test_case(moduleName, TimeDuration_lessThan_checkDurationLower);
+add_test_case(moduleName, TimeDuration_greaterThan_checkDurationGreater);
+add_test_case(moduleName, TimeUtil_isLeapYear_allZero);
+add_test_case(moduleName, TimeUtil_isLeapYear_negative);
+add_test_case(moduleName, TimeUtil_getAvailableTimezones_checkEuropeBerlin);
+add_test_case(moduleName, TZDate_getDate_checkEqualWithSetDate);
+add_test_case(moduleName, TZDate_getFullYear_checkEqualWithSetFullYear);
+add_test_case(moduleName, TZDate_getHours_checkEqualWithSetHours);
+add_test_case(moduleName, TZDate_getMilliseconds_checkEqualWithSetMilliseconds);
+add_test_case(moduleName, TZDate_getMinutes_checkEqualWithSetMinutes);
+add_test_case(moduleName, TZDate_getMonth_checkEqualWithSetMonth);
+add_test_case(moduleName, TZDate_getSeconds_checkEqualWithSetSeconds);
+add_test_case(moduleName, TZDate_getUTCDate_checkEqualWithSetUTCDate);
+add_test_case(moduleName, TZDate_getUTCFullYear_checkEqualWithSetUTCFullYear);
+add_test_case(moduleName, TZDate_getUTCHours_checkEqualWithSetUTCHours);
+add_test_case(moduleName, TZDate_getUTCMilliseconds_checkEqualWithSetUTCMilliseconds);
+add_test_case(moduleName, TZDate_getUTCMinutes_checkEqualWithSetUTCMinutes);
+add_test_case(moduleName, TZDate_getUTCMonth_checkEqualWithSetUTCMonth);
+add_test_case(moduleName, TZDate_getUTCSeconds_checkEqualWithSetUTCSeconds);
+add_test_case(moduleName, TZDate_addDuration);
+add_test_case(moduleName, TZDate_addDuration_duration_TypeMismatch);
+add_test_case(moduleName, TZDate_addDuration_duration_invalid_obj);
+add_test_case(moduleName, TZDate_addDuration_exist);
+add_test_case(moduleName, TZDate_addDuration_missarg);
+add_test_case(moduleName, TZDate_constructor_maximal_with_nonoptional_arguments);
+add_test_case(moduleName, TZDate_constructor_maximal_with_optional_arguments);
+add_test_case(moduleName, TZDate_constructor_minimal_with_nonoptional_arguments);
+add_test_case(moduleName, TZDate_constructor_minimal_without_optional_arguments);
+add_test_case(moduleName, TZDate_difference);
+add_test_case(moduleName, TZDate_difference_exist);
+add_test_case(moduleName, TZDate_difference_missarg);
+add_test_case(moduleName, TZDate_difference_other_TypeMismatch);
+add_test_case(moduleName, TZDate_difference_other_invalid_obj);
+add_test_case(moduleName, TZDate_earlierThan);
+add_test_case(moduleName, TZDate_earlierThan_exist);
+add_test_case(moduleName, TZDate_earlierThan_missarg);
+add_test_case(moduleName, TZDate_earlierThan_other_TypeMismatch);
+add_test_case(moduleName, TZDate_earlierThan_other_invalid_obj);
+add_test_case(moduleName, TZDate_equalsTo);
+add_test_case(moduleName, TZDate_equalsTo_exist);
+add_test_case(moduleName, TZDate_equalsTo_missarg);
+add_test_case(moduleName, TZDate_equalsTo_other_TypeMismatch);
+add_test_case(moduleName, TZDate_equalsTo_other_invalid_obj);
+add_test_case(moduleName, TZDate_exist);
+add_test_case(moduleName, TZDate_extend);
+add_test_case(moduleName, TZDate_getDate);
+add_test_case(moduleName, TZDate_getDate_for_specific_date);
+add_test_case(moduleName, TZDate_getDate_exist);
+add_test_case(moduleName, TZDate_getDate_extra_argument);
+add_test_case(moduleName, TZDate_getDay);
+add_test_case(moduleName, TZDate_getDay_for_specific_date);
+add_test_case(moduleName, TZDate_getDay_exist);
+add_test_case(moduleName, TZDate_getDay_extra_argument);
+add_test_case(moduleName, TZDate_getFullYear);
+add_test_case(moduleName, TZDate_getFullYear_for_specific_date);
+add_test_case(moduleName, TZDate_getFullYear_exist);
+add_test_case(moduleName, TZDate_getFullYear_extra_argument);
+add_test_case(moduleName, TZDate_getHours);
+add_test_case(moduleName, TZDate_getHours_for_specific_date);
+add_test_case(moduleName, TZDate_getHours_exist);
+add_test_case(moduleName, TZDate_getHours_extra_argument);
+add_test_case(moduleName, TZDate_getMilliseconds);
+add_test_case(moduleName, TZDate_getMilliseconds_for_specific_date);
+add_test_case(moduleName, TZDate_getMilliseconds_exist);
+add_test_case(moduleName, TZDate_getMilliseconds_extra_argument);
+add_test_case(moduleName, TZDate_getMinutes);
+add_test_case(moduleName, TZDate_getMinutes_for_specific_date);
+add_test_case(moduleName, TZDate_getMinutes_exist);
+add_test_case(moduleName, TZDate_getMinutes_extra_argument);
+add_test_case(moduleName, TZDate_getMonth);
+add_test_case(moduleName, TZDate_getMonth_for_specific_date);
+add_test_case(moduleName, TZDate_getMonth_exist);
+add_test_case(moduleName, TZDate_getMonth_extra_argument);
+add_test_case(moduleName, TZDate_getNextDSTTransition);
+add_test_case(moduleName, TZDate_getNextDSTTransition_exist);
+add_test_case(moduleName, TZDate_getNextDSTTransition_extra_argument);
+add_test_case(moduleName, TZDate_getPreviousDSTTransition);
+add_test_case(moduleName, TZDate_getPreviousDSTTransition_exist);
+add_test_case(moduleName, TZDate_getPreviousDSTTransition_extra_argument);
+add_test_case(moduleName, TZDate_getSeconds);
+add_test_case(moduleName, TZDate_getSeconds_for_specific_date);
+add_test_case(moduleName, TZDate_getSeconds_exist);
+add_test_case(moduleName, TZDate_getSeconds_extra_argument);
+add_test_case(moduleName, TZDate_getTimezone);
+add_test_case(moduleName, TZDate_getTimezoneAbbreviation);
+add_test_case(moduleName, TZDate_getTimezoneAbbreviation_exist);
+add_test_case(moduleName, TZDate_getTimezoneAbbreviation_extra_argument);
+add_test_case(moduleName, TZDate_getTimezone_for_specific_timezone);
+add_test_case(moduleName, TZDate_getTimezone_exist);
+add_test_case(moduleName, TZDate_getTimezone_extra_argument);
+add_test_case(moduleName, TZDate_getUTCDate);
+add_test_case(moduleName, TZDate_getUTCDate_for_specific_date);
+add_test_case(moduleName, TZDate_getUTCDate_exist);
+add_test_case(moduleName, TZDate_getUTCDate_extra_argument);
+add_test_case(moduleName, TZDate_getUTCDay);
+add_test_case(moduleName, TZDate_getUTCDay_for_specific_date);
+add_test_case(moduleName, TZDate_getUTCDay_exist);
+add_test_case(moduleName, TZDate_getUTCDay_extra_argument);
+add_test_case(moduleName, TZDate_getUTCFullYear);
+add_test_case(moduleName, TZDate_getUTCFullYear_for_specific_date);
+add_test_case(moduleName, TZDate_getUTCFullYear_exist);
+add_test_case(moduleName, TZDate_getUTCFullYear_extra_argument);
+add_test_case(moduleName, TZDate_getUTCHours);
+add_test_case(moduleName, TZDate_getUTCHours_for_specific_date);
+add_test_case(moduleName, TZDate_getUTCHours_exist);
+add_test_case(moduleName, TZDate_getUTCHours_extra_argument);
+add_test_case(moduleName, TZDate_getUTCMilliseconds);
+add_test_case(moduleName, TZDate_getUTCMilliseconds_for_specific_date);
+add_test_case(moduleName, TZDate_getUTCMilliseconds_exist);
+add_test_case(moduleName, TZDate_getUTCMilliseconds_extra_argument);
+add_test_case(moduleName, TZDate_getUTCMinutes);
+add_test_case(moduleName, TZDate_getUTCMinutes_for_specific_date);
+add_test_case(moduleName, TZDate_getUTCMinutes_exist);
+add_test_case(moduleName, TZDate_getUTCMinutes_extra_argument);
+add_test_case(moduleName, TZDate_getUTCMonth);
+add_test_case(moduleName, TZDate_getUTCMonth_for_specific_date);
+add_test_case(moduleName, TZDate_getUTCMonth_exist);
+add_test_case(moduleName, TZDate_getUTCMonth_extra_argument);
+add_test_case(moduleName, TZDate_getUTCSeconds);
+add_test_case(moduleName, TZDate_getUTCSeconds_for_specific_date);
+add_test_case(moduleName, TZDate_getUTCSeconds_exist);
+add_test_case(moduleName, TZDate_getUTCSeconds_extra_argument);
+add_test_case(moduleName, TZDate_isDST);
+add_test_case(moduleName, TZDate_isDST_for_specific_date);
+add_test_case(moduleName, TZDate_isDST_exist);
+add_test_case(moduleName, TZDate_isDST_extra_argument);
+add_test_case(moduleName, TZDate_laterThan);
+add_test_case(moduleName, TZDate_laterThan_with_null);
+add_test_case(moduleName, TZDate_laterThan_exist);
+add_test_case(moduleName, TZDate_laterThan_missarg);
+add_test_case(moduleName, TZDate_laterThan_other_TypeMismatch);
+add_test_case(moduleName, TZDate_laterThan_other_invalid_obj);
+add_test_case(moduleName, TZDate_secondsFromUTC);
+add_test_case(moduleName, TZDate_secondsFromUTC_for_specific_date);
+add_test_case(moduleName, TZDate_secondsFromUTC_exist);
+add_test_case(moduleName, TZDate_secondsFromUTC_extra_argument);
+add_test_case(moduleName, TZDate_setDate);
+add_test_case(moduleName, TZDate_setDate_for_specific_date);
+add_test_case(moduleName, TZDate_setDate_exist);
+add_test_case(moduleName, TZDate_setFullYear);
+add_test_case(moduleName, TZDate_setFullYear_exist);
+add_test_case(moduleName, TZDate_setHours);
+add_test_case(moduleName, TZDate_setHours_exist);
+add_test_case(moduleName, TZDate_setMilliseconds);
+add_test_case(moduleName, TZDate_setMilliseconds_exist);
+add_test_case(moduleName, TZDate_setMinutes);
+add_test_case(moduleName, TZDate_setMinutes_exist);
+add_test_case(moduleName, TZDate_setMonth);
+add_test_case(moduleName, TZDate_setMonth_exist);
+add_test_case(moduleName, TZDate_setSeconds);
+add_test_case(moduleName, TZDate_setSeconds_exist);
+add_test_case(moduleName, TZDate_setUTCDate);
+add_test_case(moduleName, TZDate_setUTCDate_exist);
+add_test_case(moduleName, TZDate_setUTCFullYear);
+add_test_case(moduleName, TZDate_setUTCFullYear_exist);
+add_test_case(moduleName, TZDate_setUTCHours);
+add_test_case(moduleName, TZDate_setUTCHours_exist);
+add_test_case(moduleName, TZDate_setUTCMilliseconds);
+add_test_case(moduleName, TZDate_setUTCMilliseconds_exist);
+add_test_case(moduleName, TZDate_setUTCMinutes);
+add_test_case(moduleName, TZDate_setUTCMinutes_exist);
+add_test_case(moduleName, TZDate_setUTCMonth);
+add_test_case(moduleName, TZDate_setUTCMonth_exist);
+add_test_case(moduleName, TZDate_setUTCSeconds);
+add_test_case(moduleName, TZDate_setUTCSeconds_exist);
+add_test_case(moduleName, TZDate_toDateString);
+add_test_case(moduleName, TZDate_toDateString_for_specific_date);
+add_test_case(moduleName, TZDate_toDateString_exist);
+add_test_case(moduleName, TZDate_toDateString_extra_argument);
+add_test_case(moduleName, TZDate_toLocalTimezone);
+add_test_case(moduleName, TZDate_toLocalTimezone_for_specific_date);
+add_test_case(moduleName, TZDate_toLocalTimezone_exist);
+add_test_case(moduleName, TZDate_toLocalTimezone_extra_argument);
+add_test_case(moduleName, TZDate_toLocaleDateString);
+add_test_case(moduleName, TZDate_toLocaleDateString_exist);
+add_test_case(moduleName, TZDate_toLocaleDateString_extra_argument);
+add_test_case(moduleName, TZDate_toLocaleString);
+add_test_case(moduleName, TZDate_toLocaleString_exist);
+add_test_case(moduleName, TZDate_toLocaleString_extra_argument);
+add_test_case(moduleName, TZDate_toLocaleTimeString);
+add_test_case(moduleName, TZDate_toLocaleTimeString_exist);
+add_test_case(moduleName, TZDate_toLocaleTimeString_extra_argument);
+add_test_case(moduleName, TZDate_toString);
+add_test_case(moduleName, TZDate_toString_exist);
+add_test_case(moduleName, TZDate_toString_extra_argument);
+add_test_case(moduleName, TZDate_toTimeString);
+add_test_case(moduleName, TZDate_toTimeString_for_specific_date);
+add_test_case(moduleName, TZDate_toTimeString_exist);
+add_test_case(moduleName, TZDate_toTimeString_extra_argument);
+add_test_case(moduleName, TZDate_toTimezone);
+add_test_case(moduleName, TZDate_toTimezone_exist);
+add_test_case(moduleName, TZDate_toUTC);
+add_test_case(moduleName, TZDate_toUTC_exist);
+add_test_case(moduleName, TZDate_toUTC_extra_argument);
+add_test_case(moduleName, TimeDuration_constructor_maximal);
+add_test_case(moduleName, TimeDuration_constructor_minimal);
+add_test_case(moduleName, TimeDuration_difference);
+add_test_case(moduleName, TimeDuration_difference_exist);
+add_test_case(moduleName, TimeDuration_difference_missarg);
+add_test_case(moduleName, TimeDuration_difference_other_TypeMismatch);
+add_test_case(moduleName, TimeDuration_difference_other_invalid_obj);
+add_test_case(moduleName, TimeDuration_equalsTo);
+add_test_case(moduleName, TimeDuration_equalsTo_exist);
+add_test_case(moduleName, TimeDuration_equalsTo_missarg);
+add_test_case(moduleName, TimeDuration_equalsTo_other_TypeMismatch);
+add_test_case(moduleName, TimeDuration_equalsTo_other_invalid_obj);
+add_test_case(moduleName, TimeDuration_exist);
+add_test_case(moduleName, TimeDuration_extend);
+add_test_case(moduleName, TimeDuration_greaterThan);
+add_test_case(moduleName, TimeDuration_greaterThan_exist);
+add_test_case(moduleName, TimeDuration_greaterThan_missarg);
+add_test_case(moduleName, TimeDuration_greaterThan_other_TypeMismatch);
+add_test_case(moduleName, TimeDuration_greaterThan_other_invalid_obj);
+add_test_case(moduleName, TimeDuration_length_attribute);
+add_test_case(moduleName, TimeDuration_lessThan);
+add_test_case(moduleName, TimeDuration_lessThan_exist);
+add_test_case(moduleName, TimeDuration_lessThan_missarg);
+add_test_case(moduleName, TimeDuration_lessThan_other_TypeMismatch);
+add_test_case(moduleName, TimeDuration_lessThan_other_invalid_obj);
+add_test_case(moduleName, TimeDuration_unit_attribute);
+add_test_case(moduleName, TimeUtil_extend);
+add_test_case(moduleName, TimeUtil_getAvailableTimezones);
+add_test_case(moduleName, TimeUtil_getAvailableTimezones_exist);
+add_test_case(moduleName, TimeUtil_getAvailableTimezones_extra_argument);
+add_test_case(moduleName, TimeUtil_getCurrentDateTime);
+add_test_case(moduleName, TimeUtil_getCurrentDateTime_instanceof);
+add_test_case(moduleName, TimeUtil_getCurrentDateTime_exist);
+add_test_case(moduleName, TimeUtil_getCurrentDateTime_extra_argument);
+add_test_case(moduleName, TimeUtil_getDateFormat);
+add_test_case(moduleName, TimeUtil_getDateFormat_exist);
+add_test_case(moduleName, TimeUtil_getLocalTimezone);
+add_test_case(moduleName, TimeUtil_getLocalTimezone_exist);
+add_test_case(moduleName, TimeUtil_getLocalTimezone_extra_argument);
+add_test_case(moduleName, TimeUtil_getTimeFormat_exist);
+add_test_case(moduleName, TimeUtil_getTimeFormat_extra_argument);
+add_test_case(moduleName, TimeUtil_isLeapYear);
+add_test_case(moduleName, TimeUtil_isLeapYear_exist);
+add_test_case(moduleName, TimeUtil_notexist);
+add_test_case(moduleName, TZDate_addDuration_invalidLength);
+add_test_case(moduleName, TZDate_addDuration_unitDAYS_negative);
+add_test_case(moduleName, TZDate_addDuration_unitDAYS_one);
+add_test_case(moduleName, TZDate_addDuration_unitDAYS_week);
+add_test_case(moduleName, TZDate_addDuration_unitDAYS_year);
+add_test_case(moduleName, TZDate_addDuration_unitHOURS);
+add_test_case(moduleName, TZDate_addDuration_unitHOURS_moreThanOneDay);
+add_test_case(moduleName, TZDate_addDuration_unitHOURS_negative);
+add_test_case(moduleName, TZDate_addDuration_unitMINS);
+add_test_case(moduleName, TZDate_addDuration_unitMINS_complexNum);
+add_test_case(moduleName, TZDate_addDuration_unitMINS_negative);
+add_test_case(moduleName, TZDate_addDuration_unitMSECS);
+add_test_case(moduleName, TZDate_addDuration_unitMSECS_complexNum);
+add_test_case(moduleName, TZDate_addDuration_unitMSECS_negative);
+add_test_case(moduleName, TZDate_addDuration_unitSECS);
+add_test_case(moduleName, TZDate_addDuration_unitSECS_complexNum);
+add_test_case(moduleName, TZDate_addDuration_unitSECS_negative);
+add_test_case(moduleName, Time_TZDate_difference_compareWithPastDate);
+add_test_case(moduleName, Time_TZDate_difference_compareWithPastHour);
+add_test_case(moduleName, Time_TZDate_difference_compareWithPastSeconds);
+add_test_case(moduleName, Time_TZDate_difference_compareWithPastYear);
+add_test_case(moduleName, Time_in_tizen);
+add_test_case(moduleName, TimeManagerObject_notexist);
diff --git a/webWidgetTCT_device/test/tct/tests/TestWebWidget.js b/webWidgetTCT_device/test/tct/tests/TestWebWidget.js
new file mode 100755 (executable)
index 0000000..5b84492
--- /dev/null
@@ -0,0 +1,397 @@
+/*
+Copyright (c) 2017 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+
+ */
+
+var attribute = "";
+var status_value = "";
+var isRoaming = false;
+var alert = console.log;
+
+var INVALID_VALUES_ERR = {
+    name: "InvalidValuesError"
+};
+var TYPE_MISMATCH_ERR = {
+    name: "TypeMismatchError"
+};
+
+function assert_value_in_range(minValue, maxValue, attributeValue, description) {
+    var expected, epsilon;
+
+    assert_type(attributeValue, "number", "attributeValue is not a number.");
+
+    epsilon = Math.abs((Number(maxValue) - Number(minValue)) / 2);
+    expected = Number(maxValue) - epsilon;
+    assert_approx_equals(attributeValue, expected, epsilon, description)
+}
+
+function WebWidgetContentManager_extend() {
+//==== TEST: WebWidgetContentManager_extend
+//==== LABEL Check if KeyManager object is extendable
+//==== SPEC Tizen Web API:TBD:WebWidget:WebWidgetContentManager:WebWidgetContentManager U
+//==== SPEC_URL TBD
+//==== PRIORITY P3
+//==== TEST_CRITERIA OBX
+test(function () {
+    check_extensibility(tizen.webWidget);
+}, 'WebWidgetContentManager_extend');
+
+}
+
+function WebWidgetContentManager_getContentInfoOfContext() {
+//==== TEST: WebWidgetContentManager_getContentInfoOfContext
+//==== LABEL Check if WebWidgetContentManager::getContentInfoOfContext() method works properly
+//==== SPEC Tizen Web API:TBD:WebWidget:WebWidgetContentManager:getContentInfoOfContext M
+//==== SPEC_URL TBD
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR MNA
+
+test(function () {
+    var retValue = null;
+    var contents =
+    {
+       content1: 'test1',
+       content2: 'test2'
+    };
+
+    tizen.webWidget.setContentInfoOfContext(contents);
+    retValue = tizen.webWidget.getContentInfoOfContext();
+    
+    assert_type(retValue, "object", "getContentInfoOfContext returns wrong value");
+}, 'WebWidgetContentManager_getContentInfoOfContext');
+
+}
+
+function WebWidgetContentManager_getContentInfoOfContext_exist() {
+//==== TEST: WebWidgetContentManager_getContentInfoOfContext_exist
+//==== LABEL Check if WebWidgetContentManager::getContentInfoOfContext() method exists
+//==== SPEC Tizen Web API:TBD:WebWidget:WebWidgetContentManager:getContentInfoOfContext M
+//==== SPEC_URL TBD
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+test(function () {
+    assert_true("getContentInfoOfContext" in tizen.webWidget,
+        "tizen.webWidget.getContentInfoOfContext method exists");
+    check_method_exists(tizen.webWidget, "getContentInfoOfContext");
+}, 'WebWidgetContentManager_getContentInfoOfContext_exist');
+
+}
+
+function WebWidgetContentManager_getContentInfoOfContext_extra_argument() {
+//==== TEST: WebWidgetContentManager_getContentInfoOfContext_extra_argument
+//==== LABEL Check using WebWidgetContentManager::getContentInfoOfContext() method with extra argument
+//==== SPEC Tizen Web API:TBD:WebWidget:WebWidgetContentManager:getContentInfoOfContext M
+//==== SPEC_URL TBD
+//==== PRIORITY P1
+//==== TEST_CRITERIA MNAEX
+
+test(function () {
+    checkExtraArgument(tizen.webWidget , "getContentInfoOfContext");
+}, 'WebWidgetContentManager_getContentInfoOfContext_extra_argument');
+
+}
+
+function WebWidgetContentManager_in_tizen() {
+//==== TEST: WebWidgetContentManager_in_tizen
+//==== LABEL Check if this object exists in tizen
+//==== SPEC Tizen Web API:TBD:WebWidget:WebWidgetContentManager:WebWidgetContentManager U
+//==== SPEC_URL TBD
+//==== PRIORITY P3
+//==== TEST_CRITERIA OBME
+
+test(function () {
+    assert_true("webWidget" in tizen, "No webwidget method in tizen.");
+    check_readonly(tizen, "webWidget", tizen.webWidget, "object", null);
+}, 'WebWidgetContentManager_in_tizen');
+
+}
+
+function WebWidgetContentManager_notexist() {
+//==== TEST: WebWidgetContentManager_notexist
+//==== LABEL Check if interface WebWidgetContentManager exists, it should not.
+//==== SPEC Tizen Web API:TBD:WebWidget:WebWidgetContentManager:WebWidgetContentManager U
+//==== SPEC_URL TBD
+//==== PRIORITY P3
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("WebWidgetContentManager");
+}, 'WebWidgetContentManager_notexist');
+
+}
+
+function WebWidgetContentManager_setContentInfoOfContext() {
+//==== TEST: WebWidgetContentManager_setContentInfoOfContext
+//==== LABEL Check if WebWidgetContentManager::setContentInfoOfContext() method works properly
+//==== SPEC Tizen Web API:TBD:WebWidget:WebWidgetContentManager:setContentInfoOfContext M
+//==== SPEC_URL TBD
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var retValue = null;
+    var contents =
+    {
+       content1: 'test1',
+       content2: 'test2'
+    };
+
+    retValue = tizen.webWidget.setContentInfoOfContext(contents);
+    assert_type(retValue, "boolean", "setContentInfoOfContext returns wrong value");
+}, 'WebWidgetContentManager_setContentInfoOfContext');
+
+}
+
+function WebWidgetContentManager_setContentInfoOfContext_content_TypeMismatch() {
+//==== TEST: WebWidgetContentManager_setContentInfoOfContext_content_TypeMismatch
+//==== LABEL Check if WebWidgetContentManager::setContentInfoOfContext() with incorrect content argument throws an exception
+//==== SPEC Tizen Web API:TBD:WebWidget:WebWidgetContentManager:setContentInfoOfContext M
+//==== SPEC_URL TBD
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+test(function () {
+    var contents = "test";
+    assert_throws(TYPE_MISMATCH_EXCEPTION,
+        function () {
+            tizen.webWidget.setContentInfoOfContext(contents);
+        }, "Calling setContentInfoOfContext without arguments should throw an exception.");
+}, 'WebWidgetContentManager_setContentInfoOfContext_content_TypeMismatch');
+
+}
+
+function WebWidgetContentManager_setContentInfoOfContext_exist() {
+//==== TEST: WebWidgetContentManager_setContentInfoOfContext_exist
+//==== LABEL Check if WebWidgetContentManager::setContentInfoOfContext() method exists
+//==== SPEC Tizen Web API:TBD:WebWidget:WebWidgetContentManager:setContentInfoOfContext M
+//==== SPEC_URL TBD
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    check_method_exists(tizen.webWidget, "setContentInfoOfContext");
+}, 'WebWidgetContentManager_setContentInfoOfContext_exist');
+
+}
+
+function WebWidgetContentManager_setReceiveContentListener() {
+//==== TEST: WebWidgetContentManager_setReceiveContentListener
+//==== LABEL Check if WebWidgetContentManager::setReceiveContentListener() method works properly
+//==== SPEC Tizen Web API:TBD:WebWidget:WebWidgetContentManager:setReceiveContentListener M
+//==== SPEC_URL TBD
+//==== PRIORITY P1
+//==== EXECUTION_TYPE manual
+//==== PRE "f02" widget should be added to home screen.
+//==== STEP Launch DeviceAPI app.
+//==== STEP Click on the Basic.
+//==== STEP If there is no response, kill DeviceAPI app process by command:app_launcher -k Qny4t67cv7.DeviceAPI, then retry
+//==== EXPECT test case is passed.
+//==== ONLOAD_DELAY 120
+//==== TEST_CRITERIA MR
+
+setup({timeout: 120000});
+
+var t = async_test('WebWidgetContentManager_setReceiveContentListener', {timeout: 120000}),
+    WidgetReceiveContentCallback, retValue = null;
+
+t.step(function () {
+    WidgetReceiveContentCallback = t.step_func(function (content) {
+        assert_type(retValue, "object", "setReceiveContentListener returns wrong value");
+        t.done();
+    });
+
+    tizen.webWidget.setReceiveContentListener(WidgetReceiveContentCallback);
+    alert("Launch DeviceAPI app");
+    alert("Click on the Basic");
+    alert("If there is no response, kill DeviceAPI app process by command:app_launcher -k Qny4t67cv7.DeviceAPI, then retry");
+});
+}
+
+function WebWidgetContentManager_setReceiveContentListener_exist() {
+//==== TEST: WebWidgetContentManager_setReceiveContentListener_exist
+//==== LABEL Check if WebWidgetContentManager::setReceiveContentListener() method exists
+//==== SPEC Tizen Web API:TBD:WebWidget:WebWidgetContentManager:setReceiveContentListener M
+//==== SPEC_URL TBD
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    assert_true("setReceiveContentListener" in tizen.webWidget,
+        "tizen.webWidget.setReceiveContentListener method exists");
+    check_method_exists(tizen.webWidget, "setReceiveContentListener");
+}, 'WebWidgetContentManager_setReceiveContentListener_exist');
+
+}
+
+function WebWidgetContentManager_setReceiveContentListener_invalid_cb() {
+//==== TEST: WebWidgetContentManager_setReceiveContentListener_invalid_cb
+//==== LABEL Check if WebWidgetContentManager.setReceiveContentListener method throws exception when WidgetReceiveContentCallback is invalid
+//==== SPEC Tizen Web API:TBD:WebWidget:WebWidgetContentManager:setReceiveContentListener M
+//==== SPEC_URL TBD
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 90000});
+
+var t = async_test('WebWidgetContentManager_setReceiveContentListener_invalid_cb', {timeout: 90000}), WidgetReceiveContentCallback;
+
+t.step(function () {
+    WidgetReceiveContentCallback = {
+        onsuccess: t.step_func(function () {
+            assert_unreached("Invalid WidgetReceiveContentCallback invoked");
+        })
+    };
+
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        tizen.webWidget.setReceiveContentListener(WidgetReceiveContentCallback);
+    }, TYPE_MISMATCH_EXCEPTION + " should be thrown - given incorrect WidgetReceiveContentCallback.");
+    t.done();
+});
+
+}
+
+function WebWidgetContentManager_setReceiveContentListener_listener_TypeMismatch() {
+//==== TEST: WebWidgetContentManager_setReceiveContentListener_listener_TypeMismatch
+//==== LABEL Check if WebWidgetContentManager::setReceiveContentListener() with incorrect listener argument throws an exception
+//==== SPEC Tizen Web API:TBD:WebWidget:WebWidgetContentManager:setReceiveContentListener M
+//==== SPEC_URL TBD
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+test(function () {
+    var WidgetReceiveContentCallback = "test";
+    assert_throws(TYPE_MISMATCH_EXCEPTION,
+        function () {
+            tizen.webWidget.setReceiveContentListener(WidgetReceiveContentCallback);
+        }, "Calling setReceiveContentListener without arguments should throw an exception.");
+}, 'WebWidgetContentManager_setReceiveContentListener_listener_TypeMismatch');
+
+}
+
+function WebWidgetContentManager_unsetReceiveContentListener() {
+//==== TEST: WebWidgetContentManager_unsetReceiveContentListener
+//==== LABEL Check if WebWidgetContentManager::unsetReceiveContentListener() method works properly
+//==== SPEC Tizen Web API:TBD:WebWidget:WebWidgetContentManager:unsetReceiveContentListener M
+//==== SPEC_URL TBD
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR MNA
+
+test(function () {
+    var retValue = null;
+    retValue = tizen.webWidget.unsetReceiveContentListener();
+    assert_type(retValue, "undefined", "unsetReceiveContentListener returns wrong value");
+}, 'WebWidgetContentManager_unsetReceiveContentListener');
+
+}
+
+function WebWidgetContentManager_unsetReceiveContentListener_exist() {
+//==== TEST: WebWidgetContentManager_unsetReceiveContentListener_exist
+//==== LABEL Check if WebWidgetContentManager::unsetReceiveContentListener() method exists
+//==== SPEC Tizen Web API:TBD:WebWidget:WebWidgetContentManager:unsetReceiveContentListener M
+//==== SPEC_URL TBD
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    assert_true("unsetReceiveContentListener" in tizen.webWidget,
+        "tizen.webWidget.unsetReceiveContentListener method exists");
+    check_method_exists(tizen.webWidget, "unsetReceiveContentListener");
+}, 'WebWidgetContentManager_unsetReceiveContentListener_exist');
+
+}
+
+function WebWidgetContentManager_unsetReceiveContentListener_extra_argument() {
+//==== TEST: WebWidgetContentManager_unsetReceiveContentListener_extra_argument
+//==== LABEL Check using WebWidgetContentManager::unsetReceiveContentListener() method with extra argument
+//==== SPEC Tizen Web API:TBD:WebWidget:WebWidgetContentManager:unsetReceiveContentListener M
+//==== SPEC_URL TBD
+//==== PRIORITY P1
+//==== TEST_CRITERIA MNAEX
+
+test(function () {
+    checkExtraArgument(tizen.webWidget , "unsetReceiveContentListener");
+}, 'WebWidgetContentManager_unsetReceiveContentListener_extra_argument');
+
+}
+
+function WidgetReceiveContentCallback_notexist() {
+//==== TEST: WidgetReceiveContentCallback_notexist
+//==== LABEL Check if interface WidgetReceiveContentCallback exists, it should not.
+//==== SPEC Tizen Web API:TBD:WebWidget:WidgetReceiveContentCallback:WidgetReceiveContentCallback U
+//==== SPEC_URL TBD
+//==== PRIORITY P3
+//==== TEST_CRITERIA CBNIO
+
+test(function () {
+    check_no_interface_object("WidgetReceiveContentCallback");
+}, 'WidgetReceiveContentCallback_notexist');
+
+}
+
+function WidgetReceiveContentCallback_onsuccess() {
+//==== TEST: WidgetReceiveContentCallback_onsuccess
+//==== LABEL Test whether WidgetReceiveContentCallback::onsuccess is called with valid argument
+//==== SPEC Tizen Web API:TBD:WebWidget:WidgetReceiveContentCallback:onsuccess M
+//==== SPEC_URL TBD
+//==== PRIORITY P1
+//==== EXECUTION_TYPE manual
+//==== PRE "f02" widget should be added to home screen.
+//==== STEP Launch DeviceAPI app.
+//==== STEP Click on the Basic.
+//==== STEP If there is no response, kill DeviceAPI app process by command:app_launcher -k Qny4t67cv7.DeviceAPI, then retry
+//==== EXPECT test case is passed.
+//==== ONLOAD_DELAY 120
+//==== TEST_CRITERIA CBOA CBT
+
+setup({timeout: 120000});
+
+var t = async_test('WidgetReceiveContentCallback_onsuccess', {timeout: 120000}),
+    WidgetReceiveContentCallback;
+
+t.step(function () {
+    WidgetReceiveContentCallback = t.step_func(function (content) {
+        assert_not_equals(content , null, "Argument should not be null.");
+        assert_type(content, "object", "content should be an object.");
+        t.done();
+    });
+
+    tizen.webWidget.setReceiveContentListener(WidgetReceiveContentCallback);
+    alert("Launch DeviceAPI app");
+    alert("Click on the Basic");
+    alert("If there is no response, kill DeviceAPI app process by command:app_launcher -k Qny4t67cv7.DeviceAPI, then retry");
+});
+
+}
+
+var moduleName = "tct-webwidget-tizen-tests";
+add_test_case(moduleName, WebWidgetContentManager_extend);
+add_test_case(moduleName, WebWidgetContentManager_getContentInfoOfContext);
+add_test_case(moduleName, WebWidgetContentManager_getContentInfoOfContext_exist);
+add_test_case(moduleName, WebWidgetContentManager_getContentInfoOfContext_extra_argument);
+add_test_case(moduleName, WebWidgetContentManager_in_tizen);
+add_test_case(moduleName, WebWidgetContentManager_notexist);
+add_test_case(moduleName, WebWidgetContentManager_setContentInfoOfContext);
+add_test_case(moduleName, WebWidgetContentManager_setContentInfoOfContext_content_TypeMismatch);
+add_test_case(moduleName, WebWidgetContentManager_setContentInfoOfContext_exist);
+add_test_case(moduleName, WebWidgetContentManager_setReceiveContentListener);
+add_test_case(moduleName, WebWidgetContentManager_setReceiveContentListener_exist);
+add_test_case(moduleName, WebWidgetContentManager_setReceiveContentListener_invalid_cb);
+add_test_case(moduleName, WebWidgetContentManager_setReceiveContentListener_listener_TypeMismatch);
+add_test_case(moduleName, WebWidgetContentManager_unsetReceiveContentListener);
+add_test_case(moduleName, WebWidgetContentManager_unsetReceiveContentListener_exist);
+add_test_case(moduleName, WebWidgetContentManager_unsetReceiveContentListener_extra_argument);
+add_test_case(moduleName, WidgetReceiveContentCallback_notexist);
+add_test_case(moduleName, WidgetReceiveContentCallback_onsuccess);
diff --git a/webWidgetTCT_device/test/tct/tests/TestWidgetService.js b/webWidgetTCT_device/test/tct/tests/TestWidgetService.js
new file mode 100755 (executable)
index 0000000..d5894a9
--- /dev/null
@@ -0,0 +1,2054 @@
+/*
+Copyright (c) 2016 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Authors:
+        Wei Ji <wei.ji@samsung.com>
+        Qunfang Lin <qunfang.lin@samsung.com>
+*/
+
+var alert = console.log;
+
+function WidgetServiceManager_getPrimaryWidgetId(){
+
+//==== TEST: WidgetServiceManager_getPrimaryWidgetId
+//==== LABEL Check if WidgetServiceManager::getPrimaryWidgetId method works correctly
+//==== SPEC Tizen Web API:TBD:WidgetService:WidgetServiceManager:getPrimaryWidgetId M
+//==== SPEC_URL TBD
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var pkgId= "Qny4t67cv7", id = "Qny4t67cv7.DeviceAPI.f02", widgetId;
+
+    widgetId = tizen.widgetservice.getPrimaryWidgetId(pkgId);
+    assert_type(widgetId, "string", "widget should be string");
+    assert_equals(widgetId, id, "widgetId should be equal to id.");
+}, "WidgetServiceManager_getPrimaryWidgetId");
+
+}
+
+function WidgetContentCallback_notexist(){
+
+//==== TEST: WidgetContentCallback_notexist
+//==== LABEL Check if interface WidgetContentCallback exists, it should not exists.
+//==== SPEC Tizen Web API:TBD:WidgetService:WidgetContentCallback:WidgetContentCallback U
+//==== SPEC_URL TBD
+//==== PRIORITY P3
+//==== TEST_CRITERIA CBNIO
+
+test(function () {
+    check_no_interface_object("WidgetContentCallback");
+}, "WidgetContentCallback_notexist");
+
+}
+
+function WidgetServiceManager_extend(){
+
+//==== TEST: WidgetServiceManager_extend
+//==== LABEL Check if WidgetServiceManager object is extendable
+//==== SPEC Tizen Web API:TBD:WidgetService:WidgetServiceManager:WidgetServiceManager U
+//==== SPEC_URL TBD
+//==== PRIORITY P3
+//==== TEST_CRITERIA OBX
+
+test(function () {
+    check_extensibility(tizen.widgetservice);
+}, "WidgetServiceManager_extend");
+
+}
+
+function WidgetInstancesCallback_notexist(){
+
+//==== TEST: WidgetInstancesCallback_notexist
+//==== LABEL Check if interface WidgetInstancesCallback exists, it should not exists
+//==== SPEC Tizen Web API:TBD:WidgetService:WidgetInstancesCallback:WidgetInstancesCallback U
+//==== SPEC_URL TBD
+//==== PRIORITY P3
+//==== TEST_CRITERIA CBNIO
+
+test(function () {
+    check_no_interface_object("WidgetInstancesCallback");
+}, "WidgetInstancesCallback_notexist");
+
+}
+
+function Widget_getInstances_with_errorCallback(){
+
+//==== TEST: Widget_getInstances_with_errorCallback
+//==== LABEL Check if Widget::getInstances method works correctly with errorCallback
+//==== SPEC Tizen Web API:TBD:WidgetService:Widget:getInstances M
+//==== SPEC_URL TBD
+//==== PRIORITY P1
+//==== TEST_CRITERIA MOA MR
+
+setup({timeout: 90000});
+
+var t = async_test("Widget_getInstances_with_errorCallback", {timeout: 90000}), widgetSuccessCb, widgetErrorCb, id, widget, retVal;
+
+t.step(function () {
+    widgetErrorCb = t.step_func(function (error) {
+        assert_unreached("Error occured: " + error.name + ": " + error.message);
+    });
+
+    widgetSuccessCb = t.step_func(function (instances) {
+        assert_equals(retVal, undefined, "getInstances() should return undefined.");
+        t.done();
+    });
+
+    id = "Qny4t67cv7.DeviceAPI.f02";
+    widget = tizen.widgetservice.getWidget(id);
+    retVal = widget.getInstances(widgetSuccessCb, widgetErrorCb);
+});
+
+}
+
+function Widget_getInstances_successCallback_TypeMismatch(){
+
+//==== TEST: Widget_getInstances_successCallback_TypeMismatch
+//==== LABEL Check if Widget:getInstances with incorrect successCallback argument throws an exception
+//==== SPEC Tizen Web API:TBD:WidgetService:Widget:getInstances M
+//==== SPEC_URL TBD
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 90000});
+
+var t = async_test("Widget_getInstances_successCallback_TypeMismatch", {timeout: 90000}), i, conversionTable, id, widget;
+
+t.step(function () {
+    id = "Qny4t67cv7.DeviceAPI.f02";
+    widget = tizen.widgetservice.getWidget(id);
+
+    conversionTable = getTypeConversionExceptions("functionObject", false);
+    for (i = 0; i < conversionTable.length; i++) {
+        assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+            widget.getInstances(conversionTable[i][0]);
+        }, "TypeMismatchError exception should be thrown");
+    }
+    t.done();
+});
+
+}
+
+function WidgetArraySuccessCallback_onsuccess(){
+
+//==== TEST: WidgetArraySuccessCallback_onsuccess
+//==== LABEL Test whether WidgetArraySuccessCallback:onsuccess is called with argument of proper type
+//==== SPEC Tizen Web API:TBD:WidgetService:WidgetArraySuccessCallback:onsuccess M
+//==== SPEC_URL TBD
+//==== PRIORITY P1
+//==== TEST_CRITERIA CBOA CBT
+
+setup({timeout: 90000});
+
+var t = async_test("WidgetArraySuccessCallback_onsuccess", {timeout: 90000}), successCB;
+
+t.step(function () {
+    successCB = t.step_func(function (widgets) {
+        assert_type(widgets, "array", "widgets is not an arry");
+        assert_type(widgets[0], "object", "widget is not an object");
+        t.done();
+    });
+
+    tizen.widgetservice.getWidgets(successCB);
+});
+
+}
+
+function Widget_addStateChangeListener_misarg(){
+
+//==== TEST: Widget_addStateChangeListener_misarg
+//==== LABEL Check if Widget::addStateChangeListener throws exception when mandatory params are missing
+//==== SPEC Tizen Web API:TBD:WidgetService:Widget:addStateChangeListener M
+//==== SPEC_URL TBD
+//==== PRIORITY P2
+//==== TEST_CRITERIA MMA
+
+test(function () {
+    var id = "Qny4t67cv7.DeviceAPI.f02", widget;
+
+    widget = tizen.widgetservice.getWidget(id);
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        widget.addStateChangeListener();
+    }, "exception should be thrown when mandatory params are missing");
+}, "Widget_addStateChangeListener_misarg");
+
+}
+
+function Widget_getVariant(){
+
+//==== TEST: Widget_getVariant
+//==== LABEL Check if Widget::getVariant method works correctly
+//==== SPEC Tizen Web API:TBD:WidgetService:Widget:getVariant M
+//==== SPEC_URL TBD
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var id = "Qny4t67cv7.DeviceAPI.f02", widget, retVal;
+
+    widget = tizen.widgetservice.getWidget(id);
+    retVal = widget.getVariant("2x2");
+    assert_type(retVal, "object", "getVariant should return Object");
+}, "Widget_getVariant");
+
+}
+
+function Widget_getVariants(){
+
+//==== TEST: Widget_getVariants
+//==== LABEL Check if Widget::getVariants method works correctly
+//==== SPEC Tizen Web API:TBD:WidgetService:Widget:getVariants M
+//==== SPEC_URL TBD
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR MMINA
+
+setup({timeout: 90000});
+
+var t = async_test("Widget_getVariants", {timeout: 90000}), widgetSuccessCb, id, widget, retVal;
+
+t.step(function () {
+    widgetSuccessCb = t.step_func(function () {
+        assert_equals(retVal, undefined, "getVariants() should return undefined.");
+        t.done();
+    });
+
+    id = "Qny4t67cv7.DeviceAPI.f02";
+    widget = tizen.widgetservice.getWidget(id);
+    retVal = widget.getVariants(widgetSuccessCb);
+});
+
+}
+
+function WidgetInstance_notexist(){
+
+//==== TEST: WidgetInstance_notexist
+//==== LABEL Check if interface WidgetInstance exists, it should not exists
+//==== SPEC Tizen Web API:TBD:WidgetService:WidgetInstance:WidgetInstance U
+//==== SPEC_URL TBD
+//==== PRIORITY P3
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("WidgetInstance");
+}, "WidgetInstance_notexist");
+
+}
+
+function Widget_removeStateChangeListener_exist(){
+
+//==== TEST: Widget_removeStateChangeListener_exist
+//==== LABEL Check if Widget::removeStateChangeListener method exists
+//==== SPEC Tizen Web API:TBD:WidgetService:Widget:removeStateChangeListener M
+//==== SPEC_URL TBD
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    var id = "Qny4t67cv7.DeviceAPI.f02", widget;
+
+    widget = tizen.widgetservice.getWidget(id);
+    check_method_exists(widget, "removeStateChangeListener");
+}, "Widget_removeStateChangeListener_exist");
+
+}
+
+function WidgetSize_extend(){
+
+//==== TEST: WidgetSize_extend
+//==== LABEL Check if WidgetSize object is extendable
+//==== SPEC Tizen Web API:TBD:WidgetService:WidgetSize:WidgetSize U
+//==== SPEC_URL TBD
+//==== PRIORITY P3
+//==== TEST_CRITERIA OBX
+
+test(function () {
+    var sizeType = "4x4", widgetSize;
+
+    widgetSize = tizen.widgetservice.getSize(sizeType);
+    check_extensibility(widgetSize);
+}, "WidgetSize_extend");
+
+}
+
+function Widget_notexist(){
+
+//==== TEST: Widget_notexist
+//==== LABEL Check if interface Widget exists, it should not exists
+//==== SPEC Tizen Web API:TBD:WidgetService:Widget:Widget U
+//==== SPEC_URL TBD
+//==== PRIORITY P3
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("Widget");
+}, "Widget_notexist");
+
+}
+
+function Widget_getInstances_successCallback_invalid_cb(){
+
+//==== TEST: Widget_getInstances_successCallback_invalid_cb
+//==== LABEL Check if Widget:getInstances throws exception when successCallback is invalid
+//==== SPEC Tizen Web API:TBD:WidgetService:Widget:getInstances M
+//==== SPEC_URL TBD
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 90000});
+
+var t = async_test("Widget_getInstances_successCallback_invalid_cb", {timeout: 90000}), invalidCallback, id, widget;
+
+t.step(function () {
+    invalidCallback = {
+        onsuccess: t.step_func(function (instances) {
+            assert_unreached("Invalid success callback should not be invoked");
+        })
+    };
+
+    id = "Qny4t67cv7.DeviceAPI.f02";
+    widget = tizen.widgetservice.getWidget(id);
+
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        widget.getInstances(invalidCallback);
+    }, "Exception should be thrown when given incorrect successCallback");
+    t.done();
+});
+
+}
+
+function Widget_addStateChangeListener_callback_TypeMismatch(){
+
+//==== TEST: Widget_addStateChangeListener_callback_TypeMismatch
+//==== LABEL Check if addStateChangeListener() with incorrect callback argument throws an exception
+//==== SPEC Tizen Web API:TBD:WidgetService:Widget:addStateChangeListener M
+//==== SPEC_URL TBD
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+test(function () {
+    var callback, i, conversionTable, exceptionName, id, widget;
+
+    id = "Qny4t67cv7.DeviceAPI.f02";
+    widget = tizen.widgetservice.getWidget(id);
+    conversionTable = getTypeConversionExceptions("functionObject", false);
+    for (i = 0; i < conversionTable.length; i++) {
+        callback = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+
+        assert_throws({name: exceptionName}, function () {
+            widget.addStateChangeListener(callback);
+        }, "Given incorrect callback.");
+    }
+}, "Widget_addStateChangeListener_callback_TypeMismatch");
+
+}
+
+function Widget_getInstances_errorCallback_invoked_NotFoundError(){
+
+//==== TEST: Widget_getInstances_errorCallback_invoked_NotFoundError
+//==== LABEL Check if getInstances invokes errorCallback with NotFoundError when no widgets added to the screen
+//==== SPEC Tizen Web API:TBD:WidgetService:Widget:getInstances M
+//==== SPEC_URL TBD
+//==== PRIORITY P2
+//==== TEST_CRITERIA MERRCB
+
+setup({timeout: 90000});
+
+var t = async_test("Widget_getInstances_errorCallback_invoked_NotFoundError", {timeout: 90000}), widgetSuccessCb, widgetErrorCb, id, widget;
+
+t.step(function () {
+    widgetErrorCb = t.step_func(function (error) {
+        assert_equals(error.name, "NotFoundError", "Incorrect error name.");
+        t.done();
+    });
+
+    widgetSuccessCb = t.step_func(function (instances) {
+        assert_unreached("successCallback should not be invoked");
+    });
+
+    id = "Qny4t67cv7.DeviceAPI.f03";
+    widget = tizen.widgetservice.getWidget(id);
+    widget.getInstances(widgetSuccessCb, widgetErrorCb);
+});
+
+}
+
+function WidgetServiceManager_getPrimaryWidgetId_exist(){
+
+//==== TEST: WidgetServiceManager_getPrimaryWidgetId_exist
+//==== LABEL Check if WidgetServiceManager::getPrimaryWidgetId method exists
+//==== SPEC Tizen Web API:TBD:WidgetService:WidgetServiceManager:getPrimaryWidgetId M
+//==== SPEC_URL TBD
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    check_method_exists(tizen.widgetservice, "getPrimaryWidgetId");
+}, "WidgetServiceManager_getPrimaryWidgetId_exist");
+
+}
+
+function Widget_extend(){
+
+//==== TEST: Widget_extend
+//==== LABEL Check if Widget object is extendable
+//==== SPEC Tizen Web API:TBD:WidgetService:Widget:Widget U
+//==== SPEC_URL TBD
+//==== PRIORITY P3
+//==== TEST_CRITERIA OBX
+
+test(function () {
+    var id = "Qny4t67cv7.DeviceAPI.f02", widget;
+
+    widget = tizen.widgetservice.getWidget(id);
+    check_extensibility(widget);
+}, "Widget_extend");
+
+}
+
+function Widget_applicationId_attribute(){
+
+//==== TEST: Widget_applicationId_attribute
+//==== LABEL Check if attribute applicationId of Widget exists, has type DOMString and is readonly
+//==== SPEC Tizen Web API:TBD:WidgetService:Widget:applicationId A
+//==== SPEC_URL TBD
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var id = "Qny4t67cv7.DeviceAPI.f02", widget;
+
+    widget = tizen.widgetservice.getWidget(id);
+    check_readonly(widget, "applicationId", widget.applicationId, "string", "org.tizen.contacts");
+}, "Widget_applicationId_attribute");
+
+}
+
+function WidgetVariant_sizeType_attribute(){
+
+//==== TEST: WidgetVariant_sizeType_attribute
+//==== LABEL Check if attribute sizeType of WidgetVariant exists, has type DOMString and is readonly
+//==== SPEC Tizen Web API:TBD:WidgetService:WidgetVariant:sizeType A
+//==== SPEC_URL TBD
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ARO AVL
+
+test(function () {
+    var id = "Qny4t67cv7.DeviceAPI.f02", widget, wdVariant, sizeTypeRange;
+
+    widget = tizen.widgetservice.getWidget(id);
+    wdVariant = widget.getVariant("2x2");
+    check_readonly(wdVariant, "sizeType", wdVariant.sizeType, "string", "5x6");
+
+    sizeTypeRange = ["1x1", "2x1", "2x2", "4x1", "4x2", "4x3", "4x4", "4x5", "4x6", "EASY_1x1", "EASY_3x1", "EASY_3x3", "FULL"];
+    assert_in_array(wdVariant.sizeType, sizeTypeRange, "invalid WidgetSizeType");
+}, "WidgetVariant_sizeType_attribute");
+
+}
+
+function Widget_getVariants_successCallback_invalid_cb(){
+
+//==== TEST: Widget_getVariants_successCallback_invalid_cb
+//==== LABEL Check if Widget:getVariants throws exception when successCallback is invalid
+//==== SPEC Tizen Web API:TBD:WidgetService:Widget:getVariants M
+//==== SPEC_URL TBD
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 90000});
+
+var t = async_test("Widget_getVariants_successCallback_invalid_cb", {timeout: 90000}), invalidCallback, id, widget;
+
+t.step(function () {
+    invalidCallback = {
+        onsuccess: t.step_func(function () {
+            assert_unreached("Invalid success callback should not be invoked");
+        })
+    };
+
+    id = "Qny4t67cv7.DeviceAPI.f02";
+    widget = tizen.widgetservice.getWidget(id);
+
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        widget.getVariants(invalidCallback);
+    }, "Exception should be thrown when given incorrect successCallback");
+    t.done();
+});
+
+}
+
+function WidgetInstancesCallback_onsuccess(){
+
+//==== TEST: WidgetInstancesCallback_onsuccess
+//==== LABEL Test whether WidgetInstancesCallback:onsuccess is called with argument of proper type
+//==== SPEC Tizen Web API:TBD:WidgetService:WidgetInstancesCallback:onsuccess M
+//==== SPEC_URL TBD
+//==== PRIORITY P1
+//==== TEST_CRITERIA CBOA CBT
+
+setup({timeout: 90000});
+
+var t = async_test("WidgetInstancesCallback_onsuccess", {timeout: 90000}), widgetSuccessCb, widgetErrorCb, id, widget;
+
+t.step(function () {
+    widgetErrorCb = t.step_func(function (error) {
+        assert_unreached("Error occured: " + error.name + ": " + error.message);
+    });
+
+    widgetSuccessCb = t.step_func(function (instances) {
+        assert_type(instances, "array", "instances is not an arry");
+        assert_type(instances[0], "object", "WidgetInstance instance is not an object");
+        t.done();
+    });
+
+    id = "Qny4t67cv7.DeviceAPI.f02";
+    widget = tizen.widgetservice.getWidget(id);
+    widget.getInstances(widgetSuccessCb, widgetErrorCb);
+});
+
+}
+
+function WidgetServiceManager_getWidgets_errorCallback_TypeMismatch(){
+
+//==== TEST: WidgetServiceManager_getWidgets_errorCallback_TypeMismatch
+//==== LABEL Check if WidgetServiceManager:getWidgets with incorrect errorCallback argument throws an exception
+//==== SPEC Tizen Web API:TBD:WidgetService:WidgetServiceManager:getWidgets M
+//==== SPEC_URL TBD
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 90000});
+
+var t = async_test("WidgetServiceManager_getWidgets_errorCallback_TypeMismatch", {timeout: 90000}), i, conversionTable, successCB;
+
+t.step(function () {
+    successCB = t.step_func(function(widgets) {
+        assert_unreached("successCallback should not be invoked");
+    });
+
+    conversionTable = getTypeConversionExceptions("functionObject", true);
+    for (i = 0; i < conversionTable.length; i++) {
+        assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+            tizen.widgetservice.getWidgets(successCB, conversionTable[i][0]);
+        }, "TypeMismatchError exception should be thrown");
+    }
+    t.done();
+});
+
+}
+
+function WidgetServiceManager_getWidget_exist(){
+
+//==== TEST: WidgetServiceManager_getWidget_exist
+//==== LABEL Check if WidgetServiceManager::getWidget method exists
+//==== SPEC Tizen Web API:TBD:WidgetService:WidgetServiceManager:getWidget M
+//==== SPEC_URL TBD
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    check_method_exists(tizen.widgetservice, "getWidget");
+}, "WidgetServiceManager_getWidget_exist");
+
+}
+
+function Widget_getName(){
+
+//==== TEST: Widget_getName
+//==== LABEL Check if Widget::getName method works correctly
+//==== SPEC Tizen Web API:TBD:WidgetService:Widget:getName M
+//==== SPEC_URL TBD
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR MMINA
+
+test(function () {
+    var id = "Qny4t67cv7.DeviceAPI.f02", widget, retVal;
+
+    widget = tizen.widgetservice.getWidget(id);
+    retVal = widget.getName();
+    assert_type(retVal, "string", "getName should return string");
+}, "Widget_getName");
+
+}
+
+function WidgetServiceManager_getWidgets_errorCallback_invoked_NotFoundError(){
+
+//==== TEST: WidgetServiceManager_getWidgets_errorCallback_invoked_NotFoundError
+//==== LABEL Check if getWidgets invokes errorCallback with NotFoundError when a widget with the given ID does not exists
+//==== SPEC Tizen Web API:TBD:WidgetService:WidgetServiceManager:getWidgets M
+//==== SPEC_URL TBD
+//==== PRIORITY P2
+//==== TEST_CRITERIA MERRCB
+
+setup({timeout: 90000});
+
+var t = async_test("WidgetServiceManager_getWidgets_errorCallback_invoked_NotFoundError", {timeout: 90000}), successCB, errorCB, packageId = "test.not.exist";
+
+t.step(function () {
+    errorCB = t.step_func(function (error) {
+        assert_equals(error.name, "NotFoundError", "Incorrect error name.");
+        t.done();
+    });
+
+    successCB = t.step_func(function () {
+        assert_unreached("successCallback should not be invoked");
+    });
+
+    tizen.widgetservice.getWidgets(successCB, errorCB, packageId);
+});
+
+}
+
+function WidgetSize_height_attribute(){
+
+//==== TEST: WidgetSize_height_attribute
+//==== LABEL Check if attribute height of WidgetSize exists, has type long and is readonly
+//==== SPEC Tizen Web API:TBD:WidgetService:WidgetSize:height A
+//==== SPEC_URL TBD
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var sizeType = "4x4", widgetSize;
+
+    widgetSize = tizen.widgetservice.getSize(sizeType);
+    check_readonly(widgetSize, "height", widgetSize.height, "long", widgetSize.height + 5);
+}, "WidgetSize_height_attribute");
+
+}
+
+function WidgetServiceManager_getSize_sizeType_TypeMismatch(){
+
+//==== TEST: WidgetServiceManager_getSize_sizeType_TypeMismatch
+//==== LABEL Check if WidgetServiceManager:getSize with incorrect sizeType argument throws an exception
+//==== SPEC Tizen Web API:TBD:WidgetService:WidgetServiceManager:getSize M
+//==== SPEC_URL TBD
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+test(function () {
+    var i, conversionTable;
+
+    conversionTable = getTypeConversionExceptions("enum", false);
+    for (i = 0; i < conversionTable.length; i++) {
+        assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+            tizen.widgetservice.getSize(conversionTable[i][0]);
+        }, "TypeMismatchError exception should be thrown");
+    }
+}, "WidgetServiceManager_getSize_sizeType_TypeMismatch");
+
+}
+
+function WidgetVariantsCallback_onsuccess(){
+
+//==== TEST: WidgetVariantsCallback_onsuccess
+//==== LABEL Test whether WidgetVariantsCallback:onsuccess is called with argument of proper type
+//==== SPEC Tizen Web API:TBD:WidgetService:WidgetVariantsCallback:onsuccess M
+//==== SPEC_URL TBD
+//==== PRIORITY P1
+//==== TEST_CRITERIA CBOA CBT
+
+setup({timeout: 90000});
+
+var t = async_test("WidgetVariantsCallback_onsuccess", {timeout: 90000}), widgetSuccessCb, id, widget;
+
+t.step(function () {
+    widgetSuccessCb = t.step_func(function (instances) {
+        assert_type(instances, "array", "instances is not an arry");
+        assert_type(instances[0], "object", "WidgetVariant instance is not an object");
+        t.done();
+    });
+
+    id = "Qny4t67cv7.DeviceAPI.f02";
+    widget = tizen.widgetservice.getWidget(id);
+    widget.getVariants(widgetSuccessCb);
+});
+
+}
+
+function WidgetArraySuccessCallback_notexist(){
+
+//==== TEST: WidgetArraySuccessCallback_notexist
+//==== LABEL Check if interface WidgetArraySuccessCallback exists, it should not exists
+//==== SPEC Tizen Web API:TBD:WidgetService:WidgetArraySuccessCallback:WidgetArraySuccessCallback U
+//==== SPEC_URL TBD
+//==== PRIORITY P3
+//==== TEST_CRITERIA CBNIO
+
+test(function () {
+    check_no_interface_object("WidgetArraySuccessCallback");
+}, "WidgetArraySuccessCallback_notexist");
+
+}
+
+function WidgetServiceManager_getWidget_NotFoundError(){
+
+//==== TEST: WidgetServiceManager_getWidget_NotFoundError
+//==== LABEL Check if getWidget method throws NotFoundError when widgetId no exists
+//==== SPEC Tizen Web API:TBD:WidgetService:WidgetServiceManager:getWidget M
+//==== SPEC_URL TBD
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+test(function () {
+    var id = "test.not.exist";
+
+    assert_throws(NOT_FOUND_EXCEPTION, function () {
+        tizen.widgetservice.getWidget(id);
+    }, "NotFoundError should be thrown when widgetId not exists");
+}, "WidgetServiceManager_getWidget_NotFoundError");
+
+}
+
+function WidgetServiceManager_getWidgets_successCallback_invalid_cb(){
+
+//==== TEST: WidgetServiceManager_getWidgets_successCallback_invalid_cb
+//==== LABEL Check if WidgetServiceManager:getWidgets throws exception when successCallback is invalid
+//==== SPEC Tizen Web API:TBD:WidgetService:WidgetServiceManager:getWidgets M
+//==== SPEC_URL TBD
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 90000});
+
+var t = async_test("WidgetServiceManager_getWidgets_successCallback_invalid_cb", {timeout: 90000}), invalidCallback;
+
+t.step(function () {
+    invalidCallback = {
+        onsuccess: t.step_func(function (widgets) {
+            assert_unreached("Invalid success callback should not be invoked");
+        })
+    };
+
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        tizen.widgetservice.getWidgets(invalidCallback);
+    }, "Exception should be thrown when given incorrect successCallback");
+    t.done();
+});
+
+}
+
+function WidgetServiceManager_getWidgets_with_packageId(){
+
+//==== TEST: WidgetServiceManager_getWidgets_with_packageId
+//==== LABEL Check if WidgetServiceManager::getWidgets method works correctly with optional params
+//==== SPEC Tizen Web API:TBD:WidgetService:WidgetServiceManager:getWidgets M
+//==== SPEC_URL TBD
+//==== PRIORITY P1
+//==== TEST_CRITERIA MOA MR
+
+setup({timeout: 90000});
+
+var t = async_test("WidgetServiceManager_getWidgets_with_packageId", {timeout: 90000}), successCB, retVal = null, errorCB, packageId = "Qny4t67cv7";
+
+t.step(function () {
+    errorCB = t.step_func(function (error) {
+        assert_unreached("errorCallback should not be invoked");
+    });
+
+    successCB = t.step_func(function (widgets) {
+        assert_equals(retVal, undefined, "getWidgets() should return undefined.");
+        t.done();
+    });
+
+    retVal = tizen.widgetservice.getWidgets(successCB, errorCB, packageId);
+});
+
+}
+
+function WidgetVariant_previewImagePath_attribute(){
+
+//==== TEST: WidgetVariant_previewImagePath_attribute
+//==== LABEL Check if attribute previewImagePath of WidgetVariant exists, has type DOMString and is readonly
+//==== SPEC Tizen Web API:TBD:WidgetService:WidgetVariant:previewImagePath A
+//==== SPEC_URL TBD
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var id = "Qny4t67cv7.DeviceAPI.f02", widget, wdVariant;
+
+    widget = tizen.widgetservice.getWidget(id);
+    wdVariant = widget.getVariant("2x2");
+    check_readonly(wdVariant, "previewImagePath", wdVariant.previewImagePath, "string", wdVariant.previewImagePath + "test");
+}, "WidgetVariant_previewImagePath_attribute");
+
+}
+
+function Widget_getName_exist(){
+
+//==== TEST: Widget_getName_exist
+//==== LABEL Check if Widget::getName method exists
+//==== SPEC Tizen Web API:TBD:WidgetService:Widget:getName M
+//==== SPEC_URL TBD
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    var id = "Qny4t67cv7.DeviceAPI.f02", widget;
+
+    widget = tizen.widgetservice.getWidget(id);
+    check_method_exists(widget, "getName");
+}, "Widget_getName_exist");
+
+}
+
+function WidgetVariant_width_attribute(){
+
+//==== TEST: WidgetVariant_width_attribute
+//==== LABEL Check if attribute width of WidgetVariant exists, has type long and is readonly
+//==== SPEC Tizen Web API:TBD:WidgetService:WidgetVariant:width A
+//==== SPEC_URL TBD
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var id = "Qny4t67cv7.DeviceAPI.f02", widget, wdVariant;
+
+    widget = tizen.widgetservice.getWidget(id);
+    wdVariant = widget.getVariant("2x2");
+    check_readonly(wdVariant, "width", wdVariant.width, "long", wdVariant.width + 5);
+}, "WidgetVariant_width_attribute");
+
+}
+
+function Widget_getVariant_sizeType_TypeMismatch(){
+
+//==== TEST: Widget_getVariant_sizeType_TypeMismatch
+//==== LABEL Check if Widget:getVariant with incorrect sizeType argument throws an exception
+//==== SPEC Tizen Web API:TBD:WidgetService:Widget:getVariant M
+//==== SPEC_URL TBD
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+test(function () {
+    var id = "Qny4t67cv7.DeviceAPI.f02", widget, i, conversionTable;
+
+    widget = tizen.widgetservice.getWidget(id);
+    conversionTable = getTypeConversionExceptions("enum", false);
+    for (i = 0; i < conversionTable.length; i++) {
+        assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+            widget.getVariant(conversionTable[i][0]);
+        }, "TypeMismatchError exception should be thrown");
+    }
+}, "Widget_getVariant_sizeType_TypeMismatch");
+
+}
+
+function Widget_getInstances_errorCallback_TypeMismatch(){
+
+//==== TEST: Widget_getInstances_errorCallback_TypeMismatch
+//==== LABEL Check if Widget:getInstances with incorrect errorCallback argument throws an exception
+//==== SPEC Tizen Web API:TBD:WidgetService:Widget:getInstances M
+//==== SPEC_URL TBD
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 90000});
+
+var t = async_test("Widget_getInstances_errorCallback_TypeMismatch", {timeout: 90000}), i, conversionTable, widgetSuccessCb, id, widget;
+
+t.step(function () {
+    widgetSuccessCb = t.step_func(function(instances) {
+        assert_unreached("successCallback should not be invoked");
+    });
+
+    id = "Qny4t67cv7.DeviceAPI.f02";
+    widget = tizen.widgetservice.getWidget(id);
+
+    conversionTable = getTypeConversionExceptions("functionObject", true);
+    for (i = 0; i < conversionTable.length; i++) {
+        assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+            widget.getInstances(widgetSuccessCb, conversionTable[i][0]);
+        }, "TypeMismatchError exception should be thrown");
+    }
+    t.done();
+});
+
+}
+
+function WidgetServiceManager_getWidgets_successCallback_TypeMismatch(){
+
+//==== TEST: WidgetServiceManager_getWidgets_successCallback_TypeMismatch
+//==== LABEL Check if WidgetServiceManager:getWidgets with incorrect successCallback argument throws an exception
+//==== SPEC Tizen Web API:TBD:WidgetService:WidgetServiceManager:getWidgets M
+//==== SPEC_URL TBD
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 90000});
+
+var t = async_test("WidgetServiceManager_getWidgets_successCallback_TypeMismatch", {timeout: 90000}), i, conversionTable;
+
+t.step(function () {
+    conversionTable = getTypeConversionExceptions("functionObject", false);
+    for (i = 0; i < conversionTable.length; i++) {
+        assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+            tizen.widgetservice.getWidgets(conversionTable[i][0]);
+        }, "TypeMismatchError exception should be thrown");
+    }
+    t.done();
+});
+
+}
+
+function Widget_getVariant_exist(){
+
+//==== TEST: Widget_getVariant_exist
+//==== LABEL Check if Widget::getVariant method exists
+//==== SPEC Tizen Web API:TBD:WidgetService:Widget:getVariant M
+//==== SPEC_URL TBD
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    var id = "Qny4t67cv7.DeviceAPI.f02", widget;
+
+    widget = tizen.widgetservice.getWidget(id);
+    check_method_exists(widget, "getVariant");
+}, "Widget_getVariant_exist");
+
+}
+
+function WidgetChangeCallback_notexist(){
+
+//==== TEST: WidgetChangeCallback_notexist
+//==== LABEL Check if interface WidgetChangeCallback exists, it should not exists.
+//==== SPEC Tizen Web API:TBD:WidgetService:WidgetChangeCallback:WidgetChangeCallback U
+//==== SPEC_URL TBD
+//==== PRIORITY P3
+//==== TEST_CRITERIA CBNIO
+
+test(function () {
+    check_no_interface_object("WidgetChangeCallback");
+}, "WidgetChangeCallback_notexist");
+
+}
+
+function WidgetServiceManager_getWidgets_misarg(){
+
+//==== TEST: WidgetServiceManager_getWidgets_misarg
+//==== LABEL Check if WidgetServiceManager::getWidgets throws exception when mandatory params are missing
+//==== SPEC Tizen Web API:TBD:WidgetService:WidgetServiceManager:getWidgets M
+//==== SPEC_URL TBD
+//==== PRIORITY P2
+//==== TEST_CRITERIA MMA
+
+test(function () {
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        tizen.widgetservice.getWidgets();
+    }, "exception should be thrown when mandatory params are missing");
+}, "WidgetServiceManager_getWidgets_misarg");
+
+}
+
+function WidgetInstance_id_attribute(){
+
+//==== TEST: WidgetInstance_id_attribute
+//==== LABEL Check if attribute id of WidgetInstance exists, has type string and is readonly
+//==== SPEC Tizen Web API:TBD:WidgetService:WidgetInstance:id A
+//==== SPEC_URL TBD
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ARO
+
+setup({timeout: 90000});
+
+var t = async_test("WidgetInstance_id_attribute", {timeout: 90000}), widgetSuccessCb, widgetErrorCb, id, widget, wdInstance;
+
+t.step(function () {
+    widgetErrorCb = t.step_func(function (error) {
+        assert_unreached("getInstances() errorCallback is invoked: " + error.name + " msg: " + error.msg);
+    });
+
+    widgetSuccessCb = t.step_func(function (instances) {
+        wdInstance = instances[0];
+        check_readonly(wdInstance, "id", wdInstance.id, "string", wdInstance.id + "5");
+        t.done();
+    });
+
+    id = "Qny4t67cv7.DeviceAPI.f02";
+    widget = tizen.widgetservice.getWidget(id);
+    widget.getInstances(widgetSuccessCb, widgetErrorCb);
+});
+
+}
+
+function Widget_id_attribute(){
+
+//==== TEST: Widget_id_attribute
+//==== LABEL Check if attribute id of Widget exists, has type DOMString and is readonly
+//==== SPEC Tizen Web API:TBD:WidgetService:Widget:id A
+//==== SPEC_URL TBD
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var id = "Qny4t67cv7.DeviceAPI.f02", widget;
+
+    widget = tizen.widgetservice.getWidget(id);
+    check_readonly(widget, "id", id, "string", "org.tizen.contacts.widget");
+}, "Widget_id_attribute");
+
+}
+
+function WidgetVariantsCallback_notexist(){
+
+//==== TEST: WidgetVariantsCallback_notexist
+//==== LABEL Check if interface WidgetVariantsCallback exists, it should not exists
+//==== SPEC Tizen Web API:TBD:WidgetService:WidgetVariantsCallback:WidgetVariantsCallback U
+//==== SPEC_URL TBD
+//==== PRIORITY P3
+//==== TEST_CRITERIA CBNIO
+
+test(function () {
+    check_no_interface_object("WidgetVariantsCallback");
+}, "WidgetVariantsCallback_notexist");
+
+}
+
+function WidgetInstance_extend(){
+
+//==== TEST: WidgetInstance_extend
+//==== LABEL Check if WidgetInstance object is extendable
+//==== SPEC Tizen Web API:TBD:WidgetService:WidgetInstance:WidgetInstance U
+//==== SPEC_URL TBD
+//==== PRIORITY P3
+//==== TEST_CRITERIA OBX
+
+setup({timeout: 90000});
+
+var t = async_test("WidgetInstance_extend", {timeout: 90000}), widgetSuccessCb, widgetErrorCb, id, widget, wdInstance;
+
+t.step(function () {
+    widgetErrorCb = t.step_func(function (error) {
+        assert_unreached("getInstances() errorCallback is invoked: " + error.name + " msg: " + error.msg);
+    });
+
+    widgetSuccessCb = t.step_func(function (instances) {
+        wdInstance = instances[0];
+        check_extensibility(wdInstance);
+        t.done();
+    });
+
+    id = "Qny4t67cv7.DeviceAPI.f02";
+    widget = tizen.widgetservice.getWidget(id);
+    widget.getInstances(widgetSuccessCb, widgetErrorCb);
+});
+
+}
+
+function WidgetVariant_needsMouseEvents_attribute(){
+
+//==== TEST: WidgetVariant_needsMouseEvents_attribute
+//==== LABEL Check if attribute needsMouseEvents of WidgetVariant exists, has type boolean and is readonly
+//==== SPEC Tizen Web API:TBD:WidgetService:WidgetVariant:needsMouseEvents A
+//==== SPEC_URL TBD
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var id = "Qny4t67cv7.DeviceAPI.f02", widget, wdVariant;
+
+    widget = tizen.widgetservice.getWidget(id);
+    wdVariant = widget.getVariant("2x2");
+    check_readonly(wdVariant, "needsMouseEvents", wdVariant.needsMouseEvents, "boolean", !wdVariant.needsMouseEvents);
+}, "WidgetVariant_needsMouseEvents_attribute");
+
+}
+
+function Widget_removeStateChangeListener(){
+
+//==== TEST: Widget_removeStateChangeListener
+//==== LABEL Check if Widget::removeStateChangeListener method works correctly
+//==== SPEC Tizen Web API:TBD:WidgetService:Widget:removeStateChangeListener M
+//==== SPEC_URL TBD
+//==== PRIORITY P1
+//==== EXECUTION_TYPE manual
+//==== PRE "f01" widget should be added to home screen.
+//==== STEP slide between f01 widget and f02 widget .
+//==== EXPECT test case is passed.
+//==== ONLOAD_DELAY 120
+//==== TEST_CRITERIA MR
+
+setup({timeout: 120000});
+
+var t = async_test("Widget_removeStateChangeListener", {timeout: 120000}), widgetChangeCb, id, widget, watchId, retVal;
+
+t.step(function () {
+    add_result_callback(function () {
+        try {
+            widget.removeStateChangeListener(watchId);
+        } catch (err) {
+        }
+    });
+
+    widgetChangeCb = t.step_func(function () {
+        retVal = widget.removeStateChangeListener(watchId);
+        assert_equals(retVal, undefined, "removeStateChangeListener() should return undefined.");
+        t.done();
+    });
+
+    id = "Qny4t67cv7.DeviceAPI.f01";
+    widget = tizen.widgetservice.getWidget(id);
+    watchId = widget.addStateChangeListener(widgetChangeCb);
+    alert("Please change the state of widget f01 (PAUSE/RESUME)");
+});
+
+}
+
+function WidgetServiceManager_getSize_exist(){
+
+//==== TEST: WidgetServiceManager_getSize_exist
+//==== LABEL Check if WidgetServiceManager::getSize method exists
+//==== SPEC Tizen Web API:TBD:WidgetService:WidgetServiceManager:getSize M
+//==== SPEC_URL TBD
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    check_method_exists(tizen.widgetservice, "getSize");
+}, "WidgetServiceManager_getSize_exist");
+
+}
+
+function WidgetServiceManager_getWidget(){
+
+//==== TEST: WidgetServiceManager_getWidget
+//==== LABEL Check if WidgetServiceManager::getWidget method works correctly
+//==== SPEC Tizen Web API:TBD:WidgetService:WidgetServiceManager:getWidget M
+//==== SPEC_URL TBD
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var id = "Qny4t67cv7.DeviceAPI.f02", widget;
+
+    widget = tizen.widgetservice.getWidget(id);
+    assert_type(widget, "object", "widget should be an object");
+    assert_equals(widget.id, id, "widget id should be equal to id.");
+}, "WidgetServiceManager_getWidget");
+
+}
+
+function Widget_getVariants_successCallback_TypeMismatch(){
+
+//==== TEST: Widget_getVariants_successCallback_TypeMismatch
+//==== LABEL Check if Widget:getVariants with incorrect successCallback argument throws an exception
+//==== SPEC Tizen Web API:TBD:WidgetService:Widget:getVariants M
+//==== SPEC_URL TBD
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 90000});
+
+var t = async_test("Widget_getVariants_successCallback_TypeMismatch", {timeout: 90000}), i, conversionTable, id, widget;
+
+t.step(function () {
+    id = "Qny4t67cv7.DeviceAPI.f02";
+    widget = tizen.widgetservice.getWidget(id);
+
+    conversionTable = getTypeConversionExceptions("functionObject", false);
+    for (i = 0; i < conversionTable.length; i++) {
+        assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+            widget.getVariants(conversionTable[i][0]);
+        }, "TypeMismatchError exception should be thrown");
+    }
+    t.done();
+});
+
+}
+
+function Widget_getVariants_exist(){
+
+//==== TEST: Widget_getVariants_exist
+//==== LABEL Check if Widget::getVariants method exists
+//==== SPEC Tizen Web API:TBD:WidgetService:Widget:getVariants M
+//==== SPEC_URL TBD
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    var id = "Qny4t67cv7.DeviceAPI.f02", widget;
+
+    widget = tizen.widgetservice.getWidget(id);
+    check_method_exists(widget, "getVariants");
+}, "Widget_getVariants_exist");
+
+}
+
+function WidgetServiceManager_notexist(){
+
+//==== TEST: WidgetServiceManager_notexist
+//==== LABEL Check if interface WidgetServiceManager exists, it should not exists
+//==== SPEC Tizen Web API:TBD:WidgetService:WidgetServiceManager:WidgetServiceManager U
+//==== SPEC_URL TBD
+//==== PRIORITY P3
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("WidgetServiceManager");
+}, "WidgetServiceManager_notexist");
+
+}
+
+function Widget_getInstances_exist(){
+
+//==== TEST: Widget_getInstances_exist
+//==== LABEL Check if Widget::getInstances method exists
+//==== SPEC Tizen Web API:TBD:WidgetService:Widget:getInstances M
+//==== SPEC_URL TBD
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    var id = "Qny4t67cv7.DeviceAPI.f02", widget;
+
+    widget = tizen.widgetservice.getWidget(id);
+    check_method_exists(widget, "getInstances");
+}, "Widget_getInstances_exist");
+
+}
+
+function WidgetVariant_needsFrame_attribute(){
+
+//==== TEST: WidgetVariant_needsFrame_attribute
+//==== LABEL Check if attribute needsFrame of WidgetVariant exists, has type boolean and is readonly
+//==== SPEC Tizen Web API:TBD:WidgetService:WidgetVariant:needsFrame A
+//==== SPEC_URL TBD
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var id = "Qny4t67cv7.DeviceAPI.f02", widget, wdVariant;
+
+    widget = tizen.widgetservice.getWidget(id);
+    wdVariant = widget.getVariant("2x2");
+    check_readonly(wdVariant, "needsFrame", wdVariant.needsFrame, "boolean", !wdVariant.needsFrame);
+}, "WidgetVariant_needsFrame_attribute");
+
+}
+
+function WidgetVariant_height_attribute(){
+
+//==== TEST: WidgetVariant_height_attribute
+//==== LABEL Check if attribute height of WidgetVariant exists, has type long and is readonly
+//==== SPEC Tizen Web API:TBD:WidgetService:WidgetVariant:height A
+//==== SPEC_URL TBD
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var id = "Qny4t67cv7.DeviceAPI.f02", widget, wdVariant;
+
+    widget = tizen.widgetservice.getWidget(id);
+    wdVariant = widget.getVariant("2x2");
+    check_readonly(wdVariant, "height", wdVariant.height, "long", wdVariant.height + 5);
+}, "WidgetVariant_height_attribute");
+
+}
+
+function Widget_addStateChangeListener(){
+
+//==== TEST: Widget_addStateChangeListener
+//==== LABEL Check if Widget::addStateChangeListener method works correctly
+//==== SPEC Tizen Web API:TBD:WidgetService:Widget:addStateChangeListener M
+//==== SPEC_URL TBD
+//==== PRIORITY P1
+//==== EXECUTION_TYPE manual
+//==== PRE "f01" widget should be added to home screen.
+//==== STEP slide between f01 widget and f02 widget .
+//==== EXPECT test case is passed.
+//==== ONLOAD_DELAY 120
+//==== TEST_CRITERIA MR
+
+setup({timeout: 120000});
+
+var t = async_test("Widget_addStateChangeListener", {timeout: 120000}), widgetChangeCb, id, widget, watchId;
+
+t.step(function () {
+    add_result_callback(function () {
+        try {
+            widget.removeStateChangeListener(watchId);
+        } catch (err) {
+        }
+    });
+
+    widgetChangeCb = t.step_func(function () {
+        assert_type(watchId, "long", "The type of return value should be Long.");
+        t.done();
+    });
+
+    id = "Qny4t67cv7.DeviceAPI.f01";
+    widget = tizen.widgetservice.getWidget(id);
+    watchId = widget.addStateChangeListener(widgetChangeCb);
+    alert("Please change the state of widget f01 (PAUSE/RESUME)");
+});
+
+}
+
+function Widget_noDisplay_attribute(){
+
+//==== TEST: Widget_noDisplay_attribute
+//==== LABEL Check if attribute noDisplay of Widget exists, has type boolean and is readonly
+//==== SPEC Tizen Web API:TBD:WidgetService:Widget:noDisplay A
+//==== SPEC_URL TBD
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var id = "Qny4t67cv7.DeviceAPI.f02", widget;
+
+    widget = tizen.widgetservice.getWidget(id);
+    check_readonly(widget, "noDisplay", widget.noDisplay, "boolean", !widget.noDisplay);
+}, "Widget_noDisplay_attribute");
+
+}
+
+function Widget_getVariants_misarg(){
+
+//==== TEST: Widget_getVariants_misarg
+//==== LABEL Check if Widget::getVariants throws exception when mandatory params are missing
+//==== SPEC Tizen Web API:TBD:WidgetService:Widget:getVariants M
+//==== SPEC_URL TBD
+//==== PRIORITY P2
+//==== TEST_CRITERIA MMA
+
+test(function () {
+    var id = "Qny4t67cv7.DeviceAPI.f02", widget;
+
+    widget = tizen.widgetservice.getWidget(id);
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        widget.getVariants();
+    }, "exception should be thrown when mandatory params are missing");
+}, "Widget_getVariants_misarg");
+
+}
+
+function WidgetVariant_needsTouchEffect_attribute(){
+
+//==== TEST: WidgetVariant_needsTouchEffect_attribute
+//==== LABEL Check if attribute needsTouchEffect of WidgetVariant exists, has type boolean and is readonly
+//==== SPEC Tizen Web API:TBD:WidgetService:WidgetVariant:needsTouchEffect A
+//==== SPEC_URL TBD
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var id = "Qny4t67cv7.DeviceAPI.f02", widget, wdVariant;
+
+    widget = tizen.widgetservice.getWidget(id);
+    wdVariant = widget.getVariant("2x2");
+    check_readonly(wdVariant, "needsTouchEffect", wdVariant.needsTouchEffect, "boolean", !wdVariant.needsTouchEffect);
+}, "WidgetVariant_needsTouchEffect_attribute");
+
+}
+
+function WidgetServiceManager_getWidgets_errorCallback_invalid_cb(){
+
+//==== TEST: WidgetServiceManager_getWidgets_errorCallback_invalid_cb
+//==== LABEL Check if WidgetServiceManager:getWidgets throws exception when errorCallback is invalid
+//==== SPEC Tizen Web API:TBD:WidgetService:WidgetServiceManager:getWidgets M
+//==== SPEC_URL TBD
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 90000});
+
+var t = async_test("WidgetServiceManager_getWidgets_errorCallback_invalid_cb", {timeout: 90000}), successCB, invalidCallback;
+
+t.step(function () {
+    invalidCallback = {
+        onerror: t.step_func(function (error) {
+            assert_unreached("Invalid errorCallback invoked: " + error.name + " msg: " + error.message);
+        })
+    };
+
+    successCB = t.step_func(function (widgets) {
+        assert_unreached("successCallback should not be invoked");
+    });
+
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        tizen.widgetservice.getWidgets(successCB, invalidCallback);
+    }, "Exception should be thrown when given incorrect errorCallback");
+    t.done();
+});
+
+}
+
+function Widget_packageId_attribute(){
+
+//==== TEST: Widget_packageId_attribute
+//==== LABEL Check if attribute packageId of Widget exists, has type DOMString and is readonly
+//==== SPEC Tizen Web API:TBD:WidgetService:Widget:packageId A
+//==== SPEC_URL TBD
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var id = "Qny4t67cv7.DeviceAPI.f02", widget;
+
+    widget = tizen.widgetservice.getWidget(id);
+    check_readonly(widget, "packageId", widget.packageId, "string", "org.tizen.contacts");
+}, "Widget_packageId_attribute");
+
+}
+
+function WidgetServiceManager_getSize(){
+
+//==== TEST: WidgetServiceManager_getSize
+//==== LABEL Check if WidgetServiceManager::getSize method works correctly
+//==== SPEC Tizen Web API:TBD:WidgetService:WidgetServiceManager:getSize M
+//==== SPEC_URL TBD
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR
+
+test(function () {
+    var sizeType = "4x4", widgetSize;
+
+    widgetSize = tizen.widgetservice.getSize(sizeType);
+    assert_type(widgetSize, "object", "widgetSize should be an object");
+}, "WidgetServiceManager_getSize");
+
+}
+
+function WidgetVariant_notexist(){
+
+//==== TEST: WidgetVariant_notexist
+//==== LABEL Check if interface WidgetVariant exists, it should not exists
+//==== SPEC Tizen Web API:TBD:WidgetService:WidgetVariant:WidgetVariant U
+//==== SPEC_URL TBD
+//==== PRIORITY P3
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("WidgetVariant");
+}, "WidgetVariant_notexist");
+
+}
+
+function Widget_getVariants_errorCallback_TypeMismatch(){
+
+//==== TEST: Widget_getVariants_errorCallback_TypeMismatch
+//==== LABEL Check if Widget:getVariants with incorrect errorCallback argument throws an exception
+//==== SPEC Tizen Web API:TBD:WidgetService:Widget:getVariants M
+//==== SPEC_URL TBD
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+setup({timeout: 90000});
+
+var t = async_test("Widget_getVariants_errorCallback_TypeMismatch", {timeout: 90000}), i, conversionTable, widgetSuccessCb, id, widget;
+
+t.step(function () {
+    widgetSuccessCb = t.step_func(function() {
+        assert_unreached("successCallback should not be invoked");
+    });
+
+    id = "Qny4t67cv7.DeviceAPI.f02";
+    widget = tizen.widgetservice.getWidget(id);
+
+    conversionTable = getTypeConversionExceptions("functionObject", true);
+    for (i = 0; i < conversionTable.length; i++) {
+        assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+            widget.getVariants(widgetSuccessCb, conversionTable[i][0]);
+        }, "TypeMismatchError exception should be thrown");
+    }
+    t.done();
+});
+
+}
+
+function Widget_getInstances_misarg(){
+
+//==== TEST: Widget_getInstances_misarg
+//==== LABEL Check if Widget::getInstances throws exception when mandatory params are missing
+//==== SPEC Tizen Web API:TBD:WidgetService:Widget:getInstances M
+//==== SPEC_URL TBD
+//==== PRIORITY P2
+//==== TEST_CRITERIA MMA
+
+test(function () {
+    var id = "Qny4t67cv7.DeviceAPI.f02", widget;
+
+    widget = tizen.widgetservice.getWidget(id);
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        widget.getInstances();
+    }, "exception should be thrown when mandatory params are missing");
+}, "Widget_getInstances_misarg");
+
+}
+
+function WidgetVariant_extend(){
+
+//==== TEST: WidgetVariant_extend
+//==== LABEL Check if WidgetVariant object is extendable
+//==== SPEC Tizen Web API:TBD:WidgetService:WidgetVariant:WidgetVariant U
+//==== SPEC_URL TBD
+//==== PRIORITY P3
+//==== TEST_CRITERIA OBX
+
+test(function () {
+    var id = "Qny4t67cv7.DeviceAPI.f02", widget, wdVariant;
+
+    widget = tizen.widgetservice.getWidget(id);
+    wdVariant = widget.getVariant("2x2");
+    check_extensibility(wdVariant);
+}, "WidgetVariant_extend");
+
+}
+
+function WidgetServiceManager_in_tizen(){
+
+//==== TEST: WidgetServiceManager_in_tizen
+//==== LABEL Check if WidgetServiceManager exists in tizen
+//==== SPEC Tizen Web API:TBD:WidgetService:WidgetServiceManager:WidgetServiceManager U
+//==== SPEC_URL TBD
+//==== PRIORITY P3
+//==== TEST_CRITERIA OBME
+
+test(function () {
+    assert_true("widgetservice" in tizen, "No widgetservice method in tizen.");
+    check_readonly(tizen, "widgetservice", tizen.widgetservice, "object", null);
+}, "WidgetServiceManager_in_tizen");
+
+}
+
+function WidgetServiceManagerObject_notexist(){
+
+//==== TEST: WidgetServiceManagerObject_notexist
+//==== LABEL Check if interface WidgetServiceManagerObject exists, it should not exists.
+//==== SPEC Tizen Web API:TBD:WidgetService:WidgetServiceManagerObject:WidgetServiceManagerObject U
+//==== SPEC_URL TBD
+//==== PRIORITY P3
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("WidgetServiceManagerObject");
+}, "WidgetServiceManagerObject_notexist");
+
+}
+
+function Widget_getVariants_with_errorCallback(){
+
+//==== TEST: Widget_getVariants_with_errorCallback
+//==== LABEL Check if Widget::getVariants method works correctly with errorCallback
+//==== SPEC Tizen Web API:TBD:WidgetService:Widget:getVariants M
+//==== SPEC_URL TBD
+//==== PRIORITY P1
+//==== TEST_CRITERIA MOA MR
+
+setup({timeout: 90000});
+
+var t = async_test("Widget_getVariants_with_errorCallback", {timeout: 90000}), widgetSuccessCb, widgetErrorCb, id, widget, retVal;
+
+t.step(function () {
+    widgetErrorCb = t.step_func(function (error) {
+        assert_unreached("errorCallback invoked: " + error.code + " msg: " + error.message);
+    });
+
+    widgetSuccessCb = t.step_func(function () {
+        assert_equals(retVal, undefined, "getVariants() should return undefined.");
+        t.done();
+    });
+
+    id = "Qny4t67cv7.DeviceAPI.f02";
+    widget = tizen.widgetservice.getWidget(id);
+    retVal = widget.getVariants(widgetSuccessCb, widgetErrorCb);
+});
+
+}
+
+function Widget_getName_with_locale(){
+
+//==== TEST: Widget_getName_with_locale
+//==== LABEL Check if Widget::getName method works correctly with locale
+//==== SPEC Tizen Web API:TBD:WidgetService:Widget:getName M
+//==== SPEC_URL TBD
+//==== PRIORITY P1
+//==== TEST_CRITERIA MOA MR
+
+test(function () {
+    var id = "Qny4t67cv7.DeviceAPI.f02", widget, retVal;
+
+    widget = tizen.widgetservice.getWidget(id);
+    retVal = widget.getName("en-us");
+    assert_type(retVal, "string", "getName should return string");
+}, "Widget_getName_with_locale");
+
+}
+
+function Widget_getVariants_errorCallback_invalid_cb(){
+
+//==== TEST: Widget_getVariants_errorCallback_invalid_cb
+//==== LABEL Check if WidgetService:getVariants throws exception when errorCallback is invalid
+//==== SPEC Tizen Web API:TBD:WidgetService:Widget:getVariants M
+//==== SPEC_URL TBD
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 90000});
+
+var t = async_test("Widget_getVariants_errorCallback_invalid_cb", {timeout: 90000}), widgetSuccessCb, invalidCallback, id, widget;
+
+t.step(function () {
+    invalidCallback = {
+        onerror: t.step_func(function (error) {
+            assert_unreached("Invalid errorCallback invoked: " + error.name + " msg: " + error.message);
+        })
+    };
+
+    widgetSuccessCb = t.step_func(function () {
+        assert_unreached("successCallback should not be invoked");
+    });
+
+    id = "Qny4t67cv7.DeviceAPI.f02";
+    widget = tizen.widgetservice.getWidget(id);
+
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        widget.getVariants(widgetSuccessCb, invalidCallback);
+    }, "Exception should be thrown when given incorrect errorCallback");
+    t.done();
+});
+
+}
+
+function WidgetContentCallback_onsuccess(){
+
+//==== TEST: WidgetContentCallback_onsuccess
+//==== LABEL Check if onsuccess() is called with valid argument
+//==== SPEC Tizen Web API:TBD:WidgetService:WidgetContentCallback:onsuccess M
+//==== SPEC_URL TBD
+//==== PRIORITY P1
+//==== TEST_CRITERIA CBOA CBT
+
+setup({timeout: 90000});
+
+var t = async_test("WidgetContentCallback_onsuccess", {timeout: 90000}), widgetSuccessCb, widgetErrorCb, id, widget, wdInstance,
+    contentSuccessCb, contentErrorCb;
+
+t.step(function () {
+    widgetErrorCb = t.step_func(function (error) {
+        assert_unreached("getInstances() errorCallback is invoked: " + error.name + " msg: " + error.msg);
+    });
+
+    contentErrorCb = t.step_func(function (error) {
+        assert_unreached("getContent() errorCallback invoked: " + error.name + " msg: " + error.message);
+    });
+
+    contentSuccessCb = t.step_func(function (data) {
+        assert_not_equals(data, null, "data should not be null");
+        assert_not_equals(data, undefined, "data should not be undefined");
+        assert_type(data, "object", "data isn't an object");
+        t.done();
+    });
+
+    widgetSuccessCb = t.step_func(function (instances) {
+        wdInstance = instances[0];
+        wdInstance.getContent(contentSuccessCb, contentErrorCb);
+    });
+
+    id = "Qny4t67cv7.DeviceAPI.f01";
+    widget = tizen.widgetservice.getWidget(id);
+    widget.getInstances(widgetSuccessCb, widgetErrorCb);
+});
+
+}
+
+function Widget_getInstances_errorCallback_invalid_cb(){
+
+//==== TEST: Widget_getInstances_errorCallback_invalid_cb
+//==== LABEL Check if WidgetService:getInstances throws exception when errorCallback is invalid
+//==== SPEC Tizen Web API:TBD:WidgetService:Widget:getInstances M
+//==== SPEC_URL TBD
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTCB
+
+setup({timeout: 90000});
+
+var t = async_test("Widget_getInstances_errorCallback_invalid_cb", {timeout: 90000}), widgetSuccessCb, invalidCallback, id, widget;
+
+t.step(function () {
+    invalidCallback = {
+        onerror: t.step_func(function (error) {
+            assert_unreached("Invalid errorCallback invoked: " + error.name + " msg: " + error.message);
+        })
+    };
+
+    widgetSuccessCb = t.step_func(function (instances) {
+        assert_unreached("successCallback should not be invoked");
+    });
+
+    id = "Qny4t67cv7.DeviceAPI.f02";
+    widget = tizen.widgetservice.getWidget(id);
+
+    assert_throws(TYPE_MISMATCH_EXCEPTION, function () {
+        widget.getInstances(widgetSuccessCb, invalidCallback);
+    }, "Exception should be thrown when given incorrect errorCallback");
+    t.done();
+});
+
+}
+
+function WidgetInstance_widget_attribute(){
+
+//==== TEST: WidgetInstance_widget_attribute
+//==== LABEL Check if attribute widget of WidgetInstance exists, has type object and is readonly
+//==== SPEC Tizen Web API:TBD:WidgetService:WidgetInstance:widget A
+//==== SPEC_URL TBD
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ARO
+
+setup({timeout: 90000});
+
+var t = async_test("WidgetInstance_widget_attribute", {timeout: 90000}), widgetSuccessCb, widgetErrorCb, id, widget, wdInstance;
+
+t.step(function () {
+    widgetErrorCb = t.step_func(function (error) {
+        assert_unreached("getInstances() errorCallback is invoked: " + error.name + " msg: " + error.msg);
+    });
+
+    widgetSuccessCb = t.step_func(function (instances) {
+        wdInstance = instances[0];
+        assert_own_property(wdInstance, "widget", "wdInstance does not own widget property.");
+        assert_type(wdInstance.widget, "object", "widget should be an object");
+        wdInstance.widget = null;
+        assert_not_equals(wdInstance.widget, null, "widget should not be modified");
+        t.done();
+    });
+
+    id = "Qny4t67cv7.DeviceAPI.f02";
+    widget = tizen.widgetservice.getWidget(id);
+    widget.getInstances(widgetSuccessCb, widgetErrorCb);
+});
+
+}
+
+function WidgetServiceManager_getWidgets_exist(){
+
+//==== TEST: WidgetServiceManager_getWidgets_exist
+//==== LABEL Check if WidgetServiceManager::getWidgets method exists
+//==== SPEC Tizen Web API:TBD:WidgetService:WidgetServiceManager:getWidgets M
+//==== SPEC_URL TBD
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    check_method_exists(tizen.widgetservice, "getWidgets");
+}, "WidgetServiceManager_getWidgets_exist");
+
+}
+
+function WidgetSize_notexist(){
+
+//==== TEST: WidgetSize_notexist
+//==== LABEL Check if interface WidgetSize exists, it should not exists
+//==== SPEC Tizen Web API:TBD:WidgetService:WidgetSize:WidgetSize U
+//==== SPEC_URL TBD
+//==== PRIORITY P3
+//==== TEST_CRITERIA NIO
+
+test(function () {
+    check_no_interface_object("WidgetSize");
+}, "WidgetSize_notexist");
+
+}
+
+function WidgetServiceManager_getPrimaryWidgetId_NotFoundError(){
+
+//==== TEST: WidgetServiceManager_getPrimaryWidgetId_NotFoundError
+//==== LABEL Check if getPrimaryWidgetId method throws NotFoundError when the given id does not exist
+//==== SPEC Tizen Web API:TBD:WidgetService:WidgetServiceManager:getPrimaryWidgetId M
+//==== SPEC_URL TBD
+//==== PRIORITY P2
+//==== TEST_CRITERIA MC
+
+test(function () {
+    var pkgId = "test.not.exist";
+
+    assert_throws(NOT_FOUND_EXCEPTION, function () {
+        tizen.widgetservice.getPrimaryWidgetId(pkgId);
+    }, "NotFoundError should be thrown when the given id does not exist");
+}, "WidgetServiceManager_getPrimaryWidgetId_NotFoundError");
+
+}
+
+function Widget_addStateChangeListener_exist(){
+
+//==== TEST: Widget_addStateChangeListener_exist
+//==== LABEL Check if Widget::addStateChangeListener method exists
+//==== SPEC Tizen Web API:TBD:WidgetService:Widget:addStateChangeListener M
+//==== SPEC_URL TBD
+//==== PRIORITY P0
+//==== TEST_CRITERIA ME
+
+test(function () {
+    var id = "Qny4t67cv7.DeviceAPI.f02", widget;
+
+    widget = tizen.widgetservice.getWidget(id);
+    check_method_exists(widget, "addStateChangeListener");
+}, "Widget_addStateChangeListener_exist");
+
+}
+
+function WidgetChangeCallback_onchange(){
+
+//==== TEST: WidgetChangeCallback_onchange
+//==== LABEL Check if onchange() is called with valid argument
+//==== SPEC Tizen Web API:TBD:WidgetService:WidgetChangeCallback:onchange M
+//==== SPEC_URL TBD
+//==== PRIORITY P1
+//==== EXECUTION_TYPE manual
+//==== PRE "f01" widget should be added to home screen.
+//==== STEP slide between f01 widget and f02 widget.
+//==== EXPECT test case is passed.
+//==== ONLOAD_DELAY 120
+//==== TEST_CRITERIA CBOA CBT
+
+setup({timeout: 120000});
+
+var t = async_test("WidgetChangeCallback_onchange", {timeout: 120000}), widgetChangeCb, id, widget, watchId;
+
+t.step(function () {
+    add_result_callback(function () {
+        try {
+            widget.removeStateChangeListener(watchId);
+        } catch (err) {
+        }
+    });
+
+    widgetChangeCb = t.step_func(function (instance, event) {
+        assert_not_equals(instance, null, "instance should not be null");
+        assert_not_equals(instance, undefined, "instance should not be undefined");
+        assert_type(instance, "object", "instance isn't an object");
+        assert_own_property(instance, "widget", "instance doesn't have widget property");
+        assert_own_property(instance, "id", "instance doesn't have id property");
+        assert_not_equals(event, null, "event should not be null");
+        assert_not_equals(event, undefined, "event should not be undefined");
+        assert_type(event, "string", "event isn't an string");
+        eventTypes = ["CREATE", "DESTROY", "PAUSE", "RESUME"];
+        for (var it in eventTypes) {
+            if (event == eventTypes[it])
+                t.done();
+        }
+        assert_unreached("WidgetStateType should be one of :" + eventTypes);
+    });
+
+    id = "Qny4t67cv7.DeviceAPI.f01";
+    widget = tizen.widgetservice.getWidget(id);
+    watchId = widget.addStateChangeListener(widgetChangeCb);
+    alert("Please change the state of widget f01 (PAUSE/RESUME)");
+});
+
+}
+
+function Widget_getInstances(){
+
+//==== TEST: Widget_getInstances
+//==== LABEL Check if Widget::getInstances method works correctly
+//==== SPEC Tizen Web API:TBD:WidgetService:Widget:getInstances M
+//==== SPEC_URL TBD
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR MMINA
+
+setup({timeout: 90000});
+
+var t = async_test("Widget_getInstances", {timeout: 90000}), widgetSuccessCb, id, widget, retVal;
+
+t.step(function () {
+    widgetSuccessCb = t.step_func(function (instances) {
+        assert_equals(retVal, undefined, "getInstances() should return undefined.");
+        t.done();
+    });
+
+    id = "Qny4t67cv7.DeviceAPI.f02";
+    widget = tizen.widgetservice.getWidget(id);
+    retVal = widget.getInstances(widgetSuccessCb);
+});
+
+}
+
+function WidgetSize_width_attribute(){
+
+//==== TEST: WidgetSize_width_attribute
+//==== LABEL Check if attribute width of WidgetSize exists, has type long and is readonly
+//==== SPEC Tizen Web API:TBD:WidgetService:WidgetSize:width A
+//==== SPEC_URL TBD
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var sizeType = "4x4", widgetSize;
+
+    widgetSize = tizen.widgetservice.getSize(sizeType);
+    check_readonly(widgetSize, "width", widgetSize.width, "long", widgetSize.width + 5);
+}, "WidgetSize_width_attribute");
+
+}
+
+function Widget_setupApplicationId_attribute(){
+
+//==== TEST: Widget_setupApplicationId_attribute
+//==== LABEL Check if attribute setupApplicationId of Widget exists, has type DOMString and is readonly
+//==== SPEC Tizen Web API:TBD:WidgetService:Widget:setupApplicationId A
+//==== SPEC_URL TBD
+//==== PRIORITY P1
+//==== TEST_CRITERIA AE AT ARO
+
+test(function () {
+    var id = "Qny4t67cv7.DeviceAPI.f02", widget;
+    widget = tizen.widgetservice.getWidget(id);
+    check_readonly(widget, "setupApplicationId", widget.setupApplicationId, "string", "org.tizen.contacts");
+}, "Widget_setupApplicationId_attribute");
+
+}
+
+function WidgetServiceManager_getWidgets(){
+
+//==== TEST: WidgetServiceManager_getWidgets
+//==== LABEL Check if WidgetServiceManager::getWidgets method works correctly
+//==== SPEC Tizen Web API:TBD:WidgetService:WidgetServiceManager:getWidgets M
+//==== SPEC_URL TBD
+//==== PRIORITY P1
+//==== TEST_CRITERIA MR MMINA
+
+setup({timeout: 90000});
+
+var t = async_test("WidgetServiceManager_getWidgets", {timeout: 90000}), successCB, retVal = null;
+
+t.step(function () {
+    successCB = t.step_func(function (widgets) {
+        assert_equals(retVal, undefined, "getWidgets() should return undefined.");
+        t.done();
+    });
+
+    retVal = tizen.widgetservice.getWidgets(successCB);
+});
+
+}
+
+function Widget_addStateChangeListener_callback_invalid_cb(){
+
+//==== TEST: Widget_addStateChangeListener_callback_invalid_cb
+//==== LABEL Check if addStateChangeListener() throws exception when callback has non callable attribute
+//==== SPEC Tizen Web API:TBD:WidgetService:Widget:addStateChangeListener M
+//==== SPEC_URL TBD
+//==== PRIORITY P2
+//==== TEST_CRITERIA MTL
+
+test(function () {
+    var callback, i, incorrectListener, exceptionName, id, widget;
+
+    id = "Qny4t67cv7.DeviceAPI.f02";
+    widget = tizen.widgetservice.getWidget(id);
+    incorrectListener = getListenerConversionExceptions(["onchange"]);
+    for(i = 0; i < incorrectListener.length; i++) {
+        callback = incorrectListener[i][0];
+        exceptionName = incorrectListener[i][1];
+
+        assert_throws({name: exceptionName}, function () {
+            widget.addStateChangeListener(callback);
+        }, exceptionName + " should be thrown - given incorrect callback.");
+    }
+}, "Widget_addStateChangeListener_callback_invalid_cb");
+
+}
+var moduleName = "tct-widgetservice-tizen-test"
+add_test_case(moduleName,WidgetServiceManager_getPrimaryWidgetId)
+add_test_case(moduleName,WidgetContentCallback_notexist)
+add_test_case(moduleName,WidgetServiceManager_extend)
+add_test_case(moduleName,WidgetInstancesCallback_notexist)
+add_test_case(moduleName,Widget_getInstances_with_errorCallback)
+add_test_case(moduleName,Widget_getInstances_successCallback_TypeMismatch)
+add_test_case(moduleName,WidgetArraySuccessCallback_onsuccess)
+add_test_case(moduleName,Widget_addStateChangeListener_misarg)
+add_test_case(moduleName,Widget_getVariant)
+add_test_case(moduleName,Widget_getVariants)
+add_test_case(moduleName,WidgetInstance_notexist)
+add_test_case(moduleName,Widget_removeStateChangeListener_exist)
+add_test_case(moduleName,WidgetSize_extend)
+add_test_case(moduleName,Widget_notexist)
+add_test_case(moduleName,Widget_getInstances_successCallback_invalid_cb)
+add_test_case(moduleName,Widget_addStateChangeListener_callback_TypeMismatch)
+add_test_case(moduleName,Widget_getInstances_errorCallback_invoked_NotFoundError)
+add_test_case(moduleName,WidgetServiceManager_getPrimaryWidgetId_exist)
+add_test_case(moduleName,Widget_extend)
+add_test_case(moduleName,Widget_applicationId_attribute)
+add_test_case(moduleName,WidgetVariant_sizeType_attribute)
+add_test_case(moduleName,Widget_getVariants_successCallback_invalid_cb)
+add_test_case(moduleName,WidgetInstancesCallback_onsuccess)
+add_test_case(moduleName,WidgetServiceManager_getWidgets_errorCallback_TypeMismatch)
+add_test_case(moduleName,WidgetServiceManager_getWidget_exist)
+add_test_case(moduleName,Widget_getName)
+add_test_case(moduleName,WidgetServiceManager_getWidgets_errorCallback_invoked_NotFoundError)
+add_test_case(moduleName,WidgetSize_height_attribute)
+add_test_case(moduleName,WidgetServiceManager_getSize_sizeType_TypeMismatch)
+add_test_case(moduleName,WidgetVariantsCallback_onsuccess)
+add_test_case(moduleName,WidgetArraySuccessCallback_notexist)
+add_test_case(moduleName,WidgetServiceManager_getWidget_NotFoundError)
+add_test_case(moduleName,WidgetServiceManager_getWidgets_successCallback_invalid_cb)
+add_test_case(moduleName,WidgetServiceManager_getWidgets_with_packageId)
+add_test_case(moduleName,WidgetVariant_previewImagePath_attribute)
+add_test_case(moduleName,Widget_getName_exist)
+add_test_case(moduleName,WidgetVariant_width_attribute)
+add_test_case(moduleName,Widget_getVariant_sizeType_TypeMismatch)
+add_test_case(moduleName,Widget_getInstances_errorCallback_TypeMismatch)
+add_test_case(moduleName,WidgetServiceManager_getWidgets_successCallback_TypeMismatch)
+add_test_case(moduleName,Widget_getVariant_exist)
+add_test_case(moduleName,WidgetChangeCallback_notexist)
+add_test_case(moduleName,WidgetServiceManager_getWidgets_misarg)
+add_test_case(moduleName,WidgetInstance_id_attribute)
+add_test_case(moduleName,Widget_id_attribute)
+add_test_case(moduleName,WidgetVariantsCallback_notexist)
+add_test_case(moduleName,WidgetInstance_extend)
+add_test_case(moduleName,WidgetVariant_needsMouseEvents_attribute)
+add_test_case(moduleName,Widget_removeStateChangeListener)
+add_test_case(moduleName,WidgetServiceManager_getSize_exist)
+add_test_case(moduleName,WidgetServiceManager_getWidget)
+add_test_case(moduleName,Widget_getVariants_successCallback_TypeMismatch)
+add_test_case(moduleName,Widget_getVariants_exist)
+add_test_case(moduleName,WidgetServiceManager_notexist)
+add_test_case(moduleName,Widget_getInstances_exist)
+add_test_case(moduleName,WidgetVariant_needsFrame_attribute)
+add_test_case(moduleName,WidgetVariant_height_attribute)
+add_test_case(moduleName,Widget_addStateChangeListener)
+add_test_case(moduleName,Widget_noDisplay_attribute)
+add_test_case(moduleName,Widget_getVariants_misarg)
+add_test_case(moduleName,WidgetVariant_needsTouchEffect_attribute)
+add_test_case(moduleName,WidgetServiceManager_getWidgets_errorCallback_invalid_cb)
+add_test_case(moduleName,Widget_packageId_attribute)
+add_test_case(moduleName,WidgetServiceManager_getSize)
+add_test_case(moduleName,WidgetVariant_notexist)
+add_test_case(moduleName,Widget_getVariants_errorCallback_TypeMismatch)
+add_test_case(moduleName,Widget_getInstances_misarg)
+add_test_case(moduleName,WidgetVariant_extend)
+add_test_case(moduleName,WidgetServiceManager_in_tizen)
+add_test_case(moduleName,WidgetServiceManagerObject_notexist)
+add_test_case(moduleName,Widget_getVariants_with_errorCallback)
+add_test_case(moduleName,Widget_getName_with_locale)
+add_test_case(moduleName,Widget_getVariants_errorCallback_invalid_cb)
+//add_test_case(moduleName,WidgetContentCallback_onsuccess)
+add_test_case(moduleName,Widget_getInstances_errorCallback_invalid_cb)
+add_test_case(moduleName,WidgetInstance_widget_attribute)
+add_test_case(moduleName,WidgetServiceManager_getWidgets_exist)
+add_test_case(moduleName,WidgetSize_notexist)
+add_test_case(moduleName,WidgetServiceManager_getPrimaryWidgetId_NotFoundError)
+add_test_case(moduleName,Widget_addStateChangeListener_exist)
+add_test_case(moduleName,WidgetChangeCallback_onchange)
+add_test_case(moduleName,Widget_getInstances)
+add_test_case(moduleName,WidgetSize_width_attribute)
+add_test_case(moduleName,Widget_setupApplicationId_attribute)
+add_test_case(moduleName,WidgetServiceManager_getWidgets)
+add_test_case(moduleName,Widget_addStateChangeListener_callback_invalid_cb)
\ No newline at end of file
diff --git a/webWidgetTCT_device/test/tct/tests/TestXMLHttpRequest.js b/webWidgetTCT_device/test/tct/tests/TestXMLHttpRequest.js
new file mode 100755 (executable)
index 0000000..9af52a7
--- /dev/null
@@ -0,0 +1,470 @@
+/*
+ * Copyright (c) 2012 Intel Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * *Redistributions of works must retain the original copyright notice, this list
+ * of conditions and the following disclaimer.
+ * *Redistributions in binary form must reproduce the original copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * *Neither the name of Intel Corporation nor the names of its contributors
+ * may be used to endorse or promote products derived from this work without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors:
+ *       Liu, Shilong <shilongx.liu@intel.com>
+ *       Lin, Wanming <wanmingx.lin@intel.com>
+ *       Fan, Weiwei <weiwix.fan@intel.com>
+ */
+
+
+
+var alert = console.log;
+
+function PassTest(disc) {
+    t.step(function () { assert_true(true, disc); } );
+    t.done();
+}
+
+function FailTest(disc) {
+    t.step(function () { assert_true(false, disc); } );
+    t.done();
+}
+
+function xhr2_XMLHttpRequest_response_responseType_arraybuffer_readyState_DONE() {
+
+setup({timeout:500});
+        var t = async_test("xhr2_XMLHttpRequest_response_responseType_arraybuffer_readyState_DONE");
+
+        //t.step(function fetchStatus(address) {
+            var client = new XMLHttpRequest();
+            client.open("GET", './support/test.xml');
+            client.responseType = "arraybuffer";
+
+            client.onreadystatechange = t.step_func(function () {
+                if (client.readyState == client.DONE) {
+                    var arraybuffer = client.response;
+                    //t.step(function() {
+                        assert_true(arraybuffer && arraybuffer instanceof ArrayBuffer, "XMLHttpRequest.response returns the arraybuffer response");
+                    //});
+                    t.done();
+                }
+            });
+            client.send();
+
+            //client.send();
+        //})
+        //fetchStatus('./support/test.xml');
+}
+
+function xhr2_XMLHttpRequest_response_responseType_blob_readyState_DONE() {
+
+setup({timeout:500});
+        var t = async_test("xhr2_XMLHttpRequest_response_responseType_blob_readyState_DONE");
+
+        function fetchStatus(address) {
+            var client = new XMLHttpRequest();
+            client.open("GET", address);
+            client.responseType = "blob";
+
+            client.onreadystatechange = function () {alert("$$$$$$$$$$"+client.readyState+ " "+client.DONE);
+                if (client.readyState == client.DONE) {
+                    var blob = client.response;
+                    assert_true(blob && blob instanceof Blob, "XMLHttpRequest.response returns the blob response entity");
+                    t.done();
+                }
+            }
+            client.onerror = t.step_func(function () {
+                assert_unreached("the request has failed");
+                t.done();
+            });
+
+            client.send();
+        }
+        fetchStatus('./support/test.xml');
+}
+function xhr2_XMLHttpRequestEventTarget_onloadstart_event() {
+
+setup({timeout:500});
+        var t = async_test("xhr2_XMLHttpRequestEventTarget_onloadstart_event");
+
+        var client = new XMLHttpRequest();
+        client.onloadstart = t.step_func(function () {
+            t.done();
+        });
+        window.setTimeout(t.step_func(function () {
+            assert_true(false, "Check if the onloadend event when the request has successfully completed");
+        }), 2000);
+        client.open("GET", "./support/test.xml");
+        client.send(null);
+}
+
+function xhr2_XMLHttpRequestEventTarget_onloadstart_exist() {
+
+        var xhr2 = new XMLHttpRequest();
+        test(function () {
+            assert_true("onloadstart" in xhr2, "Check if the XMLHttpRequestEventTarget.onloadstart exists");
+}, 'xhr2_XMLHttpRequestEventTarget_onloadstart_exist');
+}
+function xhr2_XMLHttpRequestEventTarget_onprogress_exist() {
+
+        var xhr2 = new XMLHttpRequest();
+        test(function () {
+            assert_true("onprogress" in xhr2, "Check if the XMLHttpRequestEventTarget.onprogress exists");
+}, 'xhr2_XMLHttpRequestEventTarget_onprogress_exist');
+}
+
+function xhr2_XMLHttpRequestEventTarget_onprogress_event() {
+
+setup({timeout:500});
+        var t = async_test("xhr2_XMLHttpRequestEventTarget_onprogress_event");
+
+        var client = new XMLHttpRequest();
+        client.onprogress = t.step_func(function () {
+            t.done();
+        });
+        window.setTimeout(t.step_func(function () {
+            assert_true(false, "Check if the onloadend event when the request has successfully completed");
+        }), 2000);
+        client.open("GET", "./support/test.xml");
+        client.send("null");
+}
+function xhr2_XMLHttpRequestEventTarget_onabort_exist() {
+
+        var xhr2 = new XMLHttpRequest();
+        test(function () {
+            assert_true("onabort" in xhr2, "Check if the XMLHttpRequestEventTarget.onabort exists");
+}, 'xhr2_XMLHttpRequestEventTarget_onabort_exist');
+}
+function xhr2_XMLHttpRequestEventTarget_onerror_exist() {
+
+        var xhr2 = new XMLHttpRequest();
+        test(function () {
+            assert_true("onerror" in xhr2, "Check if the XMLHttpRequestEventTarget.onerror exists");
+}, 'xhr2_XMLHttpRequestEventTarget_onerror_exist');
+}
+function xhr2_XMLHttpRequestEventTarget_onload_exist() {
+
+        var xhr2 = new XMLHttpRequest();
+        test(function () {
+            assert_true("onload" in xhr2, "Check if the XMLHttpRequestEventTarget.onload exists");
+}, 'xhr2_XMLHttpRequestEventTarget_onload_exist');
+}
+function xhr2_XMLHttpRequestEventTarget_onload_event() {
+
+setup({timeout:500});
+        var t = async_test("xhr2_XMLHttpRequestEventTarget_onload_event");
+
+        var client = new XMLHttpRequest();
+        client.onload = t.step_func(function () {
+            t.done();
+        });
+        window.setTimeout(t.step_func(function () {
+            assert_true(false, "Check if the onload event when the request has successfully completed");
+        }), 2000);
+        client.open("GET", "./support/test.xml");
+        client.send("null");
+}
+function xhr2_XMLHttpRequestEventTarget_ontimeout_exist() {
+
+        var xhr2 = new XMLHttpRequest();
+        test(function () {
+            assert_true("ontimeout" in xhr2, "Check if the XMLHttpRequestEventTarget.ontimeout exists");
+}, 'xhr2_XMLHttpRequestEventTarget_ontimeout_exist');
+}
+/*function xhr2_XMLHttpRequestEventTarget_ontimeout_event() {
+
+setup({timeout:500});
+        var t = async_test("xhr2_XMLHttpRequestEventTarget_ontimeout_event");
+
+        var client = new XMLHttpRequest();
+        client.ontimeout = t.step_func(function () {
+            t.done();
+        });
+        window.setTimeout(t.step_func(function () {
+            assert_true(false, "Check if the onloadend event when the request has successfully completed");
+        }), 2000);
+        client.open("GET", "./support/test.xml");
+        //client.send("null");
+}*/
+function xhr2_XMLHttpRequestEventTarget_onloadend_exist() {
+
+        var xhr2 = new XMLHttpRequest();
+        test(function () {
+            assert_true("onloadend" in xhr2, "Check if the XMLHttpRequestEventTarget.onloadend exists");
+}, 'xhr2_XMLHttpRequestEventTarget_onloadend_exist');
+}
+function xhr2_XMLHttpRequestEventTarget_onloadend_event() {
+
+setup({timeout:500});
+        var t = async_test("xhr2_XMLHttpRequestEventTarget_onloadend_event");
+
+        var client = new XMLHttpRequest();
+        client.onloadend = t.step_func(function () {
+            t.done();
+        });
+        window.setTimeout(t.step_func(function () {
+            assert_true(false, "Check if the onloadend event when the request has successfully completed");
+        }), 2000);
+        client.open("GET", "./support/test.xml");
+        client.send("null");
+}
+function xhr2_XMLHttpRequest_onreadystatechange_exist() {
+
+        var xhr2 = new XMLHttpRequest();
+        test(function () {
+            assert_true("onreadystatechange" in xhr2, "Check if the XMLHttpRequest.onreadystatechange exists");
+}, 'xhr2_XMLHttpRequest_onreadystatechange_exist');
+}
+function xhr2_XMLHttpRequest_onreadystatechange_event() {
+
+//setup({timeout:500});
+        var t = async_test("xhr2_XMLHttpRequest_onreadystatechange_event");
+
+        var client = new XMLHttpRequest();
+        client.onreadystatechange = t.step_func(function () {
+            t.done();
+        });
+        window.setTimeout(t.step_func(function () {
+            assert_true(false, "Check if the onreadystatechange event when the request has successfully completed");
+        }), 2000);
+        client.open("GET", "./support/test.xml");
+        //client.send("null");
+}
+
+function xhr2_XMLHttpRequest_readyState_exist() {
+
+        var xhr2 = new XMLHttpRequest();
+        test(function () {
+            assert_true("onreadystatechange" in xhr2, "Check if the XMLHttpRequest.onreadystatechange exists");
+}, 'xhr2_XMLHttpRequest_readyState_exist');
+}
+function xhr2_XMLHttpRequest_readyState_type() {
+
+        var xhr2 = new XMLHttpRequest();
+        test(function () {
+            assert_true(typeof xhr2.readyState === "number", "Check if the XMLHttpRequest.readyState is type of number");
+}, 'xhr2_XMLHttpRequest_readyState_type');
+}
+function xhr2_XMLHttpRequest_timeout_exist() {
+
+        var xhr2 = new XMLHttpRequest();
+        test(function () {
+            assert_true("timeout" in xhr2, "Check if the XMLHttpRequest.timeout exists");
+}, 'xhr2_XMLHttpRequest_timeout_exist');
+}
+function xhr2_XMLHttpRequest_timeout_type() {
+
+        var xhr2 = new XMLHttpRequest();
+        test(function () {
+            assert_true(typeof xhr2.timeout === "number", "Check if the XMLHttpRequest.timeout is type of number");
+}, 'xhr2_XMLHttpRequest_timeout_type');
+}
+function xhr2_XMLHttpRequest_open_exist() {
+
+        test(function () {
+            var client = new XMLHttpRequest();
+            assert_true("open" in client, "Check if xmlhttprequest.open method exists");
+}, 'xhr2_XMLHttpRequest_open_exist');
+}
+function xhr2_XMLHttpRequest_setRequestHeader_exist() {
+
+        test(function () {
+            var client = new XMLHttpRequest();
+            assert_true("setRequestHeader" in client, "XMLHttpRequest Level2 has setRequestHeader method");
+}, 'xhr2_XMLHttpRequest_setRequestHeader_exist');
+}
+function xhr2_XMLHttpRequest_send_Blob() {
+
+        var t = async_test("xhr2_XMLHttpRequest_send_Blob");
+
+        var client = new XMLHttpRequest();
+        try {
+            client.open("GET", "support/test.xml");
+            var blob = new Blob(['Hello!'],{type: 'text/plain'});
+            client.send(blob);
+            t.step(function () {
+                assert_true(true, "send blob data normally");
+            });
+            t.done();
+        } catch (ex) {
+            t.step(function () {
+                assert_true(false, "throw an exception " + ex.name);
+            });
+            t.done();
+        }
+}
+function xhr2_XMLHttpRequest_send_exist() {
+
+        test(function () {
+            var client = new XMLHttpRequest();
+            assert_true("send" in client, "XMLHttpRequest Level2 has send method");
+}, 'xhr2_XMLHttpRequest_send_exist');
+}
+function xhr2_XMLHttpRequest_abort_exist() {
+
+        test(function () {
+            var client = new XMLHttpRequest();
+            assert_true("abort" in client, "XMLHttpRequest Level2 has abort method");
+}, 'xhr2_XMLHttpRequest_abort_exist');
+}
+function xhr2_XMLHttpRequest_status_exist() {
+
+        var xhr2 = new XMLHttpRequest();
+        test(function () {
+            assert_true("status" in xhr2, "Check if the XMLHttpRequest.status exists");
+}, 'xhr2_XMLHttpRequest_status_exist');
+}
+function xhr2_XMLHttpRequest_status_type() {
+
+        var xhr2 = new XMLHttpRequest();
+        test(function () {
+            assert_true(typeof xhr2.status === "number", "Check if the XMLHttpRequest.status is type of number");
+}, 'xhr2_XMLHttpRequest_status_type');
+}
+function xhr2_XMLHttpRequest_response_exist() {
+
+        var xhr2 = new XMLHttpRequest();
+        test(function () {
+            assert_true("response" in xhr2, "Check if the XMLHttpRequest.response exists");
+}, 'xhr2_XMLHttpRequest_response_exist');
+}
+function xhr2_XMLHttpRequest_responseText_exist() {
+
+        var xhr2 = new XMLHttpRequest();
+        test(function () {
+            assert_true("responseText" in xhr2, "Check if XMLHttpRequest Level2 has responseText attribute");
+}, 'xhr2_XMLHttpRequest_responseText_exist');
+}
+function xhr2_XMLHttpRequest_responseText_readonly() {
+        test( function () {
+            var client = new XMLHttpRequest();
+            var initValue = client.responseText;
+            client.responseText = "test";
+            assert_true(client.responseText === initValue && client.responseText != "test", "Check if XMLHttpRequest.responseText is readonly");
+}, 'xhr2_XMLHttpRequest_responseText_readonly');
+}
+function xhr2_XMLHttpRequest_responseText_type() {
+
+        var xhr2 = new XMLHttpRequest();
+        test(function () {
+            assert_true(typeof xhr2.responseText === "string", "Check if XMLHttpRequest.responseText is of type string");
+}, 'xhr2_XMLHttpRequest_responseText_type');
+}
+function xhr2_XMLHttpRequest_statusText_exist() {
+
+        var xhr2 = new XMLHttpRequest();
+        test(function () {
+            assert_true("statusText" in xhr2, "Check if the XMLHttpRequest.statusText exists");
+}, 'xhr2_XMLHttpRequest_statusText_exist');
+}
+function xhr2_XMLHttpRequest_statusText_type() {
+        var xhr2 = new XMLHttpRequest();
+        test(function () {
+            assert_true(typeof xhr2.statusText === "string", "Check if the XMLHttpRequest.statusText is of type string");
+}, 'xhr2_XMLHttpRequest_statusText_type');
+}
+function xhr2_XMLHttpRequest_getResponseHeader_exist() {
+
+        test( function() {
+            var client = new XMLHttpRequest();
+            assert_true("getResponseHeader" in client, "XMLHttpRequest Level2 has getResponseHeader method");
+}, 'xhr2_XMLHttpRequest_getResponseHeader_exist');
+}
+function xhr2_XMLHttpRequest_getAllResponseHeaders_exist() {
+        var xhr2 = new XMLHttpRequest();
+        test(function () {
+            assert_true("getAllResponseHeaders" in xhr2, "Check if XMLHttpRequest Level2 has getAllResponseHeaders method");
+}, 'xhr2_XMLHttpRequest_getAllResponseHeaders_exist');
+}
+//style existence check
+        function hasStyle(name, styles) {
+            var arr = name.split("-");
+            var nameStr = arr[0];
+            for(i = 1; i < arr.length; i++) {
+                nameStr = nameStr + arr[i][0].toUpperCase() + arr[i].slice(1);
+            }
+            //name without prefix
+            if(nameStr in styles) {
+                return true;
+            }
+            //browser prefixes
+            var prefixes = ["ms", "Moz", "moz", "webkit", "O"];
+            //Uppercase first letter
+            nameStr = nameStr[0].toUpperCase() + nameStr.slice(1);
+            for (i in prefixes) {
+                //name with prefix
+                if ((prefixes[i] + nameStr) in styles) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+/*
+function transform_property_exist() {
+        var div = document.getElementById("main");
+        test(function () {
+            assert_true(hasStyle("transform", div.style), "The transform property exists");
+        }, "transform_property_exist");
+}
+function transform_origin_property_exist() {
+        var div = document.getElementById("main");
+        test(function () {
+            assert_true(hasStyle("transform-origin", div.style), "The transform-origin property exists");
+        }, "transform_origin_property_exist");
+} */
+
+var moduleName = "tct-xmlhttprequest-w3c-tests";
+//add_test_case(moduleName, transform_property_exist);
+//add_test_case(moduleName, transform_origin_property_exist);
+//add_test_case(moduleName, transform_property_exist);
+//add_test_case(moduleName, transform_origin_property_exist);
+add_test_case(moduleName, xhr2_XMLHttpRequestEventTarget_onloadstart_exist);
+add_test_case(moduleName, xhr2_XMLHttpRequestEventTarget_onloadstart_event);
+add_test_case(moduleName, xhr2_XMLHttpRequestEventTarget_onprogress_exist);
+add_test_case(moduleName, xhr2_XMLHttpRequestEventTarget_onprogress_event);
+add_test_case(moduleName, xhr2_XMLHttpRequestEventTarget_onabort_exist);
+add_test_case(moduleName, xhr2_XMLHttpRequestEventTarget_onerror_exist);
+add_test_case(moduleName, xhr2_XMLHttpRequestEventTarget_onload_exist);
+add_test_case(moduleName, xhr2_XMLHttpRequestEventTarget_onload_event);
+add_test_case(moduleName, xhr2_XMLHttpRequestEventTarget_ontimeout_exist);
+//add_test_case(moduleName, xhr2_XMLHttpRequestEventTarget_ontimeout_event);
+add_test_case(moduleName, xhr2_XMLHttpRequestEventTarget_onloadend_exist);
+add_test_case(moduleName, xhr2_XMLHttpRequestEventTarget_onloadend_event);
+add_test_case(moduleName, xhr2_XMLHttpRequest_onreadystatechange_exist);
+add_test_case(moduleName, xhr2_XMLHttpRequest_onreadystatechange_event);
+add_test_case(moduleName, xhr2_XMLHttpRequest_readyState_exist);
+add_test_case(moduleName, xhr2_XMLHttpRequest_readyState_type);
+add_test_case(moduleName, xhr2_XMLHttpRequest_timeout_exist);
+add_test_case(moduleName, xhr2_XMLHttpRequest_timeout_type);
+add_test_case(moduleName, xhr2_XMLHttpRequest_open_exist);
+add_test_case(moduleName, xhr2_XMLHttpRequest_send_exist);
+//add_test_case(moduleName, xhr2_XMLHttpRequest_send_Blob);
+add_test_case(moduleName, xhr2_XMLHttpRequest_abort_exist);
+add_test_case(moduleName, xhr2_XMLHttpRequest_status_exist);
+add_test_case(moduleName, xhr2_XMLHttpRequest_status_type);
+add_test_case(moduleName, xhr2_XMLHttpRequest_responseText_exist);
+add_test_case(moduleName, xhr2_XMLHttpRequest_responseText_readonly);
+add_test_case(moduleName, xhr2_XMLHttpRequest_responseText_type);
+//add_test_case(moduleName, xhr2_XMLHttpRequest_setRequestHeader_exist);
+//add_test_case(moduleName, xhr2_XMLHttpRequest_response_exist);
+//add_test_case(moduleName, xhr2_XMLHttpRequest_statusText_exist);
+//add_test_case(moduleName, xhr2_XMLHttpRequest_statusText_type);
+//add_test_case(moduleName, xhr2_XMLHttpRequest_getResponseHeader_exist);
+//add_test_case(moduleName, xhr2_XMLHttpRequest_getAllResponseHeaders_exist);
+//add_test_case(moduleName, xhr2_XMLHttpRequest_response_responseType_arraybuffer_readyState_DONE);
+//add_test_case(moduleName, xhr2_XMLHttpRequest_response_responseType_blob_readyState_DONE);
diff --git a/webWidgetTCT_device/test/tct/tests/generate.sh b/webWidgetTCT_device/test/tct/tests/generate.sh
new file mode 100755 (executable)
index 0000000..f2e2cba
--- /dev/null
@@ -0,0 +1,24 @@
+TCS=$(ls *.html)
+ACCUMULTAED_FILE=TestSensorService.js
+
+echo "" > $ACCUMULTAED_FILE
+
+for tc in $TCS; do
+       CURRENTTC=${tc%.*}
+       cat $tc \
+               | sed "s/document.title/\"$CURRENTTC\"/g" \
+               | sed "s/^<html>$/function $CURRENTTC() {/g" \
+               | sed "s/^<.html>$/}/g" \
+               | sed "s/^<!--/\/*/g" \
+               | sed "s/-->/*\//g" \
+               | sed "s/^<.*>$//g" \
+               >> $ACCUMULTAED_FILE
+done
+
+echo "" >> $ACCUMULTAED_FILE
+echo "var moduleName = \"tct-sensorservice-tizen-tests\";" >> $ACCUMULTAED_FILE
+
+for tc in $TCS; do
+       CURRENTTC=${tc%.*}
+       echo "add_test_case(moduleName, $CURRENTTC);" >> $ACCUMULTAED_FILE
+done
diff --git a/webWidgetTCT_device/test/tct/tests/support/path.js b/webWidgetTCT_device/test/tct/tests/support/path.js
new file mode 100755 (executable)
index 0000000..cfe0667
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+Copyright (c) 2012 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+* Redistributions of works must retain the original copyright notice, this list
+  of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the original copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+* Neither the name of Intel Corporation nor the names of its contributors
+  may be used to endorse or promote products derived from this work without
+  specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Authors:
+        Cao, Jun <junx.cao@intel.com>
+        Fan,Weiwei <weiwix.fan@intel.com>
+
+*/
+
+//port can not use 8000,because 8000 port is used by testkit-lite
+var otherDomain = "http://127.0.0.1:8081";
diff --git a/webWidgetTCT_device/test/tct/tests/support/test.html b/webWidgetTCT_device/test/tct/tests/support/test.html
new file mode 100755 (executable)
index 0000000..dfa5ffa
--- /dev/null
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2012 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+* Redistributions of works must retain the original copyright notice, this list
+  of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the original copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+* Neither the name of Intel Corporation nor the names of its contributors
+  may be used to endorse or promote products derived from this work without
+  specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Authors:
+         Cao, Jun <junx.cao@intel.com>
+
+-->
+
+<html>
+  <head>
+    <title>XMLHttpRequest Test: xhr2_XMLHttpRequestEventTarget_onerror_event</title>
+    <link rel="author" title="Intel" href="http://www.intel.com" />
+    <link rel="help" href="http://www.w3.org/TR/2012/WD-XMLHttpRequest-20121206/#handler-xhr-onerror" />
+    <meta name="flags" content="" />
+    <meta name="assert" content="Check if the onerror event when the request has failed" />
+  </head>
+  <body>
+    test
+  </body>
+</html>
diff --git a/webWidgetTCT_device/test/tct/tests/support/test.xml b/webWidgetTCT_device/test/tct/tests/support/test.xml
new file mode 100755 (executable)
index 0000000..8070fdd
--- /dev/null
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2012 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+* Redistributions of works must retain the original copyright notice, this list
+  of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the original copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+* Neither the name of Intel Corporation nor the names of its contributors
+  may be used to endorse or promote products derived from this work without
+  specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Authors:
+        Cao, Jun <junx.cao@intel.com>
+        Fan,Weiwei <weiwix.fan@intel.com>
+-->
+
+<res>
+ <result>ok</result>
+</res>
diff --git a/webWidgetTCT_device/test/tct/tests/support/test_timeout.xml b/webWidgetTCT_device/test/tct/tests/support/test_timeout.xml
new file mode 100755 (executable)
index 0000000..03b463d
--- /dev/null
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (c) 2012 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+* Redistributions of works must retain the original copyright notice, this list
+  of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the original copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+* Neither the name of Intel Corporation nor the names of its contributors
+  may be used to endorse or promote products derived from this work without
+  specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ Authors:
+        Cao, Jun <junx.cao@intel.com>
+        Fan,Weiwei <weiwix.fan@intel.com>
+-->
+
+<res>
+ <result>okokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokok</result>
+</res>
diff --git a/webWidgetTCT_device/test/utc/README b/webWidgetTCT_device/test/utc/README
new file mode 100755 (executable)
index 0000000..9a17fb2
--- /dev/null
@@ -0,0 +1,6 @@
+Tests and configuration files have been taken from:
+- repository: framework/web/wrt-plugins-tizen,
+- branch: devel/webapi/test,
+- folders: w/UnitTestSE/tests/Config/utc/ and w/UnitTestSE/tests/Tizen/.
+
+This files were not modified and should not be analysed with JSHint.
diff --git a/webWidgetTCT_device/test/utc/changeClockSettingFile.sh b/webWidgetTCT_device/test/utc/changeClockSettingFile.sh
new file mode 100755 (executable)
index 0000000..ec78da3
--- /dev/null
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+
+pushd "${SCRIPT_DIR}/tests" > /dev/null
+
+regionformat=`vconftool get db/menu_widget/regionformat | awk '{print $4}'`
+if [ "$regionformat" == "fr_FR.UTF-8" ]
+then
+    cp -f ClockSettingORA.js ClockSetting.js
+elif [ "$regionformat" == "ru_RU.UTF-8" ]
+then
+    cp -f ClockSettingCIS.js ClockSetting.js
+elif [ "$regionformat" == "ja_JP.UTF-8" ]
+then
+    cp -f ClockSettingDCM.js ClockSetting.js
+else
+    cp -f ClockSettingCommon.js ClockSetting.js
+fi
+
+timezoneID=`vconftool get db/setting/timezone_id | awk '{print $4}'`
+
+echo $timezoneID
+cp ClockSetting.js ClockSetting.js.bk
+sed "s,TZID,"$timezoneID, ClockSetting.js.bk > ClockSetting.js
+rm ClockSetting.js.bk
+
+popd > /dev/null
diff --git a/webWidgetTCT_device/test/utc/common/TestEngine.js b/webWidgetTCT_device/test/utc/common/TestEngine.js
new file mode 100755 (executable)
index 0000000..a89386a
--- /dev/null
@@ -0,0 +1,1337 @@
+/*
+*  wrt-plugins
+*
+* Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+*
+* Contact: Seung Mo Cho <seungm.cho@samsung.com>
+*
+* This library is free software; you can redistribute it and/or modify it under
+* the terms of the GNU Lesser General Public License as published by the
+* Free Software Foundation; either version 2.1 of the License, or (at your
+* option) any later version.
+*
+* This library is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+* License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this library; if not, write to the Free Software Foundation, Inc.,
+* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*
+*/
+/**
+ * This file contains the implementation of test engine class.
+ *
+ * @author      Wojciech Bielawski(w.bielawski@samsung.com)
+ * @author      Pawel Misiak (p.misiak@samsung.com)
+ * @version     0.1
+ */
+
+// This file is a slightly modified version of file: w/UnitTestSE/app/TestEngine.js
+// (repository: framework/web/wrt-plugins-tizen, branch: devel/webapi/test)
+
+// This file should not be analysed with JSHint.
+
+function jsPrint(msg) { console.log(msg);};
+function logFail(msg) { console.log(msg);};
+function logError(msg) { console.log(msg);};
+
+var __startTime = new Date().toISOString().replace(/:/g, '-');
+__startTime = __startTime.substr(0, __startTime.indexOf('.'));
+
+var htmlHeader = '<html><head><style type="text/css">.passed{background-color: lime;} .failed{background-color: red;}</style></head><body>';
+var htmlFooter = '</body></html>';
+
+var TestEngine = {
+       targetUse : false,
+       logText : "",
+       testCaseTimeout : 10 * 1000, //in miliseconds
+       currentCaseTimeout : 10 * 1000,
+       timer : null,
+       interval : 0,
+       countOK : 0,
+       countErr : 0,
+       countException : 0,
+       callbackMutex : 0,
+       callbackMethodName : "",
+       currentTestCase : 0,
+       countAllPassed : 0,
+       countAllFailed : 0,
+       testCasesFailedCount : 0,
+       testCasesPassedCount : 0,
+       testCasesFailed : [],
+       testList : [],
+       finalLog : "\n",
+       testSuccessCallback : null,
+       testErrorCallback : null,
+       testSuiteName : null,
+       testSuiteStats : [],
+       resultLogger : new HTMLTestResultLogger('/tmp/log-utc-' + __startTime + '.html'),
+       summaryRenderer : new HTMLTestSummaryRenderer('/tmp/summary-utc-' + __startTime + '.html'),
+
+       stepsArray : null,
+       stepTimeout : null,
+       currentStep : null,
+       errorType : null,
+       errorField : null,
+
+       /*
+        * Values used only as types representations.
+        */
+       STRING : '',
+       NUMBER : 0,
+       OBJECT : {},
+       ARRAY : [],
+       DATE : new Date(),
+       BOOL : false,
+       FUNCTION : function() {
+       },
+       /*
+        * Error test possible results.
+        */
+       ERROR_TEST_RESULT : {
+               NOT_RUN : -4,
+               NOT_THROWN : -3,
+               BAD_TYPE : -2,
+               BAD_VALUE : -1,
+               OK : 0
+       },
+
+       /**
+        * Prints specified object in a TreeView like structure.
+        * @param obj Object to print.
+        * @param indent Must be undefined (don't pass anything).
+        */
+       dumpObject : function(obj, indent) {
+               if(indent === undefined)
+                       indent = '';
+               else
+                       indent += '   ';
+               var prefix = (indent.length == 0 ? indent : indent + '|--');
+               for(var i in obj) {
+                       if( typeof (obj[i]) == "object") {
+                               TestEngine.log(prefix + i + ":");
+                               TestEngine.dumpObject(obj[i], indent);
+                       } else
+                               TestEngine.log(prefix + i + ": " + obj[i]);
+               }
+       },
+       addTest : function(enabled, testFunc, testName, testPrereq) {
+               if(null == testName) {
+                       testName = "unnamed test"
+               }
+               jsPrint("Add test: " + testName)
+               var data = new Object();
+               data.enabled = enabled;
+               data.testFunc = testFunc;
+               data.testName = testName;
+               data.testPrereq = testPrereq;
+               data.testSuite = TestEngine.testSuiteName;
+               data.failMessage = "";
+               // this.testList.push(testFunc)
+               this.testList.push(data);
+       },
+       setTestSuiteName : function(name, timeout) {
+               this.testSuiteName = name;
+               this.testSuiteStats[name] = new Object();
+               this.testSuiteStats[name].passed = 0;
+               this.testSuiteStats[name].failed = 0;
+               this.testSuiteStats[name].assertsOK = 0;
+               this.testSuiteStats[name].assertsErr = 0;
+               TestEngine.currentCaseTimeout = (timeout === undefined) ? TestEngine.testCaseTimeout : timeout;
+       },
+       log : function(text) {
+               try {
+                       jsPrint(text);
+                       this.logText += text + "<br/>";
+                       this.finalLog += text + "\n";
+                       // document.getElementById(TestEngine.currentTestSuite).innerHTML += text + "<br/>";
+                       //document.getElementById('log').innerHTML += text + "<br/>";
+               } catch(err) {
+                       this.countException++;
+                       logError("   TestEngine.log failure: " + err.message);
+               }
+       },
+       logException : function(text) {
+               try {
+                       logFail(text);
+                       TestEngine.countException++;
+                       TestEngine.log("[EXCEPTION] " + text);
+               } catch(err) {
+                       TestEngine.countException++;
+                       logError("   TestEngine.logErr failure: " + err.message);
+               }
+       },
+       logErr : function(text) {
+               try {
+                       TestEngine.countErr++;
+                       TestEngine.log("[FAILED] " + text);
+                       logFail("[FAILED] " + text);
+                       
+                       TestEngine.testList[TestEngine.currentTestCase-1].failMessage = text;
+                       
+               } catch(err) {
+                       TestEngine.countException++;
+                       logError("   TestEngine.logErr failure: " + err.message);
+               }
+       },
+       logOK : function(text) {
+               try {
+                       TestEngine.countOK++;
+                       TestEngine.log("[OK] " + text);
+               } catch(err) {
+                       TestEngine.countException++;
+                       logError("   TestEngine.logOK failure: " + err.message);
+               }
+       },
+       test : function(text, value) {
+               try {
+                       if( typeof (value) == "undefined") {
+                               TestEngine.logErr("value not defined for test: '" + text + "'");
+                       } else if(!value) {
+                               TestEngine.logErr(text);
+                       } else {
+                               TestEngine.logOK(text);
+                               return true;
+                       }
+               } catch(err) {
+                       TestEngine.countException++;
+                       logError("   TestEngine.test failure: " + err.message);
+               }
+               return false;
+       },
+       assertEqual : function(text, value1, value2){
+               try {
+                       if( typeof (value1) == "undefined") {
+                               TestEngine.logErr("value1 not defined for test: '" + text + "'");
+                       } else if( typeof (value2) == "undefined") {
+                               TestEngine.logErr("value2 not defined for test: '" + text + "'");
+                       }else if(value1 == value2) {
+                               TestEngine.logOK(text +" (value1:[" + value1 + "] value2:[" + value2 + "])");
+                       } else {
+                               TestEngine.logErr(text + " (expected value1:[" + value1 + "] but value2:[" + value2 + "])");
+                               return true;
+                       }
+               } catch(err) {
+                       TestEngine.countException++;
+                       logError("   TestEngine.test failure: " + err.message);
+               }
+               return false;
+       },
+       
+       /**
+        * Sets error type used in every typePresetError check.
+        * @param type Type of an error/exception.
+        */
+       setErrorType : function(type) {
+               TestEngine.errorType = type;
+       },
+       /**
+        * Sets error field used in every typePresetError check.
+        * @param field Name of the field in error structure to check its value.
+        */
+       setErrorField : function(field) {
+               TestEngine.errorField = field;
+       },
+       /**
+        * Sets interval between the end of this case and the start of next case. 
+        * @param interval Interval between the end of this case and the start of next case in milliseconds.
+        */
+       setInterval : function(interval) {
+               TestEngine.interval = interval;
+       },
+       /**
+        * Checks if specified expression throws a specified error.
+        * Expression must be enclosed in a function. Use setErrorType and
+        * setErrorField to set what error to look for.
+        * Error type must be set but if error field is left unset (i.e. null)
+        * then whole exception object is compared to specified value.
+        * @param msg Text to display for this test.
+        * @param fn Function eclosing the expression one wants to verify.
+        * @param value Value of an error/exception one looks for.
+        */
+       testPresetError : function(msg, fn, value) {
+               if(TestEngine.errorType === null) {
+                       TestEngine.logException("testPresetError skipped. Set error type first.");
+                       return;
+               }
+
+               return TestEngine.testError(msg, fn, TestEngine.errorType, TestEngine.errorField, value);
+       },
+       /**
+        * Checks if specified expression throws a specified error.
+        * This is a more general version of testPresetError function.
+        * Expression must be enclosed in a function.
+        * Error type must be set but if error field is left unset (i.e. null)
+        * then whole exception object is compared to specified value.
+        * @param msg Text to display for this test.
+        * @param fn Function eclosing the expression one wants to verify.
+        * @param errType Type of desired error/exception.
+        * @param errField Property from exception structure to look for exception
+        * value.
+        * @param errValue Value of an error/exception one looks for.
+        */
+       testError : function(msg, fn, errType, errField, errValue) {
+               if(errType === null) {
+                       TestEngine.logException("testError skipped. Error type can't be null.");
+                       return TestEngine.ERROR_TEST_RESULT.NOT_RUN;
+               }
+
+               try {
+                       fn();
+                       TestEngine.logErr(msg + ' Exception has not been thrown.');
+                       return TestEngine.ERROR_TEST_RESULT.NOT_THROWN;
+               } catch (ex) {
+                       if( ex instanceof errType) {
+                               var exValue = (errField !== null ? ex[errField] : ex);
+                               if(exValue === errValue) {
+                                       TestEngine.logOK(msg + ' [' + errValue + ':' + ex.message + ']');
+                                       return TestEngine.ERROR_TEST_RESULT.OK;
+                               } else {
+                                       TestEngine.logErr(msg + ' Exception is not of value ' + errValue);
+                                       return TestEngine.ERROR_TEST_RESULT.BAD_VALUE;
+                               }
+                       } else {
+                               TestEngine.logErr(msg + ' Exception is of wrong type.');
+                               return TestEngine.ERROR_TEST_RESULT.BAD_TYPE;
+                       }
+               }
+       },
+       testPresence : function(text, object) {
+               try {
+                       if(object === undefined) {
+                               TestEngine.logErr("value not defined. Name: " + text);
+                       } else {
+                               TestEngine.logOK("object " + text + " present");
+                       }
+               } catch(err) {
+                       TestEngine.countException++;
+                       logError("   TestEngine.testPresence failure: " + err.message);
+               }
+       },
+       /**
+        * Checks whether object implements given property.
+        * In addition it also checks whether any exception (e.g. "Not Supported")
+        * is thrown.
+        * @param object Object to check property for.
+        * @param property Property to look for.
+        * @return True if object implements such property, false otherwise.
+        */
+       testPresence2 : function(object, property) {
+               var result = property in object;
+               if(result) {
+                       TestEngine.logOK("property " + property + " present");
+               } else {
+                       TestEngine.logErr("property " + property + " absent");
+               }
+               return result;
+       },
+       /**
+        * Checks whether mainObj object equals templateObj object, property by
+        * property.
+        * Runs recursively through all the properties of templateObj object and
+        * checks if they exist and are equal to those in mainObj object.
+        * mainObj has to implement no less properties than templateObj.
+        * @param mainObj Object to check for properties implementation.
+        * @param templateObj Object to verify properties against.
+        * @return True if mainObj has at least the same properties as templateObj,
+        *         false otherwise.
+        */
+       checkObjectsEqual : function(mainObj, templateObj) {
+               try {
+                       if((!mainObj && templateObj) || ( typeof (mainObj) != typeof (templateObj))) {
+                               return false;
+                       } else if(isNumber(templateObj) || isString(templateObj) || isBoolean(templateObj)) {
+                               return (mainObj === templateObj);
+                       } else if(isDate(templateObj)) {
+                               return (mainObj.valueOf() === templateObj.valueOf());
+                       } else {
+                               for(var i in templateObj) {
+                                       if(!TestEngine.checkObjectsEqual(mainObj[i], templateObj[i])) {
+                                               return false;
+                                       }
+                               }
+                       }
+               } catch(err) {
+                       TestEngine.logException("TestEngine.checkObjectsEqual failure: " + err.message);
+                       return false;
+               }
+               return true;
+       },
+       // test properties of given object. Steps:
+       // - check name presence
+       // - check default value (if not null value passed)
+       // - check if name is writable
+       //
+       // description of properties array:
+       // [0] - property name
+       // [1] - default value - check if property equals given value
+       //          undefined or null - disable check
+       // [2] - value to do writability test - try to write given value
+       //          undefined or null - don't check writability
+       // [3] - indicates if property should be read-only
+       // [4] - assumed type, undefined value skips this check
+       testProperties : function(object, props) {
+               var result = new Object();
+               try {
+                       for(var i in props) {
+                               var name = props[i][0];
+                               var defaultVal = props[i][1];
+                               var setVal = props[i][2];
+                               var isReadonly = props[i][3];
+                               var type = props[i][4];
+                               var errors = TestEngine.countErr + TestEngine.countException;
+
+                               if(( typeof (name) != "string") || (name == "")) {
+                                       TestEngine.logException("Property name not defined, skipping it.");
+                                       continue;
+                               }
+
+                               result[name] = false;
+                               if(TestEngine.testPresence2(object, name)) {
+                                       if((defaultVal != null) && (defaultVal !== undefined)) {
+                                               var isObjectEqual = TestEngine.checkObjectsEqual(object[name], defaultVal);
+                                               TestEngine.test(name + " default value", isObjectEqual);
+                                       }
+
+                                       if((setVal != null) && (setVal !== undefined)) {
+                                               // try-catch is needed when SetProperty returns 'false'
+                                               if(setVal === defaultVal) {
+                                                       TestEngine.logException("Default value and set value are equal");
+                                                       continue;
+                                               }
+                                               try {
+                                                       object[name] = setVal;
+                                               } catch (e) {
+                                               }
+                                               if( typeof (isReadonly) == "undefined") {
+                                                       TestEngine.test(name + " writability, reason: isReadonly not specified", false);
+                                               }
+                                               if(isReadonly) {
+                                                       TestEngine.test(name + " writability", object[name] != setVal);
+                                               } else {
+                                                       var isObjectEqual = TestEngine.checkObjectsEqual(object[name], setVal);
+                                                       TestEngine.test(name + " writability", isObjectEqual);
+                                               }
+                                       }
+
+                                       if(type !== undefined) {
+                                               var isType = ( typeof (object[name]) == typeof (type));
+                                               if( typeof (type) == 'object') {
+                                                       if(isArray(type)) {
+                                                               isType = isArray(object[name]);
+                                                       } else if(isDate(type)) {
+                                                               isType = isDate(object[name]);
+                                                       }
+                                               }
+                                               TestEngine.test(name + " type check.", isType);
+                                       }
+                               }
+                               if(errors == TestEngine.countErr + TestEngine.countException) {
+                                       result[name] = true;
+                               }
+                       }
+               } catch(err) {
+                       TestEngine.countException++;
+                       logError("   TestEngine.testProperties failure: " + err.message);
+               }
+               return result;
+       },
+       startTestCase : function() {
+               try {
+                       TestEngine.countOK = 0;
+                       TestEngine.countErr = 0;
+                       TestEngine.countException = 0;
+                       TestEngine.timer = setTimeout(TestEngine.timeout, TestEngine.currentCaseTimeout);
+               } catch(err) {
+                       TestEngine.countException++;
+                       logError("   TestEngine.startTestCase failure: " + err.message);
+               }
+
+       },
+       endTestCase : function(testCase) {
+               try {
+                       if(this.timer === null) {
+                               return;
+                       }
+
+                       clearTimeout(this.timer);
+                       this.log("");
+                       var failed = this.countErr || ((this.countOK + this.countErr) < 1) || this.countException;
+                       this.log("Test case " + ( failed ? "FAILED" : "PASSED"));
+                       this.log("Passed: " + this.countOK);
+                       this.log("Failed: " + this.countErr);
+                       if(this.countException) {
+                               this.log("Exception occured!");
+                       }
+
+                       this.countAllPassed += this.countOK;
+                       this.countAllFailed += this.countErr;
+                       this.testSuiteStats[testCase.testSuite].assertsOK += this.countOK;
+                       this.testSuiteStats[testCase.testSuite].assertsErr += this.countErr;
+
+                       if(failed) {
+                               TestEngine.testCasesFailedCount++;
+                               this.testSuiteStats[testCase.testSuite].failed++;
+                               if(isVerbose()) {
+                                       TestEngine.testCasesFailed.push(testCase.testName + ":" + testCase.failMessage);
+                               }
+                               TestEngine.resultLogger.logFail(testCase.testName + ":" + testCase.failMessage);
+                       } else {
+                               TestEngine.testCasesPassedCount++;
+                               this.testSuiteStats[testCase.testSuite].passed++;
+                               TestEngine.resultLogger.logPass(testCase.testName);
+                       }
+                       TestEngine.summaryRenderer.render(TestEngine);
+               } catch(err) {
+                       this.countException++;
+                       logError("   TestEngine.endTestCase failure:" + err.message);
+               }
+       },
+       timeout : function() {
+               try {
+                       TestEngine.callbackMutex = 0;
+                       TestEngine.logErr("Widget run timeout.", false);
+               } catch(err) {
+                       TestEngine.countException++;
+                       logError("   TestEngine.timeout failure:" + err.message);
+               }
+       },
+       /**
+        * Registers callbacks for asynchronous function.
+        *
+        * To avoid finish test case before callbacks will execute it's necessary
+        * to register callbacks in the engine.
+        *
+        * @param methodName Testcase name, suggested asynchronous function name.
+        * @param testSuccessCallback Callback that will be executed on success.
+        * @param testErrorCallback Callback that will be executed on failure.
+        * @param callbacksCount number of callbacks to register.
+        * @return An object with defined functions "successCallback" and "errorCallback" you
+        *          need to pass as arguments to asynchronous function  e.g.
+        *
+        * function success() {  }
+        * function failure() {  }
+        *
+        * {
+        *      var obj = TestEngine.registerCallback("myAsyncFunc", success, failure);
+        *      myAsyncFunc(obj.successCallback, obj.errorCallback);
+        * }
+        */
+       registerCallback : function(methodName, testSuccessCallback, testErrorCallback, callbacksCount) {
+               try {
+                       if(callbacksCount !== undefined && callbacksCount > 0) {
+                               TestEngine.callbackMutex += callbacksCount;
+                       } else {
+                               TestEngine.callbackMutex++;
+                       }
+                       TestEngine.callbackMethodName = methodName;
+                       TestEngine.testSuccessCallback = testSuccessCallback;
+                       TestEngine.testErrorCallback = testErrorCallback;
+
+                       var retObj = new Object();
+                       retObj.callbackMethodName = methodName;
+                       retObj.testSuccessCallback = testSuccessCallback;
+                       retObj.successCallback = function(param) {
+                               try {
+                                       if(( typeof retObj.testSuccessCallback != "undefined") && (retObj.testSuccessCallback !== null)) {
+                                               retObj.testSuccessCallback(param);
+                                       } else {
+                                               TestEngine.logOK(retObj.callbackMethodName + " succeed");
+                                       }
+                               } catch(err) {
+                                       TestEngine.countException++;
+                                       logError("   TestEngine.this.successCallback failure:" + err.message);
+                                       logError("   TestEngine.this.successCallback failure:" + err.stack);
+                               }
+                               TestEngine.callbackMutex--;
+                       };
+
+                       retObj.testErrorCallback = testErrorCallback;
+                       retObj.errorCallback = function(param) {
+                               try {
+                                       if(( typeof retObj.testErrorCallback != "undefined") && (retObj.testErrorCallback !== null)) {
+                                               retObj.testErrorCallback(param);
+                                       } else {
+                                               TestEngine.logErr(retObj.callbackMethodName + " failed");
+                                       }
+                               } catch(err) {
+                                       TestEngine.countException++;
+                                       logError("   TestEngine.retObj.errorCallback failure:" + err.message);
+                                       logError("   TestEngine.retObj.errorCallback failure:" + err.stack);
+                               }
+                               TestEngine.callbackMutex--;
+                       };
+                       return retObj;
+               } catch(err) {
+                       TestEngine.countException++;
+                       logError("   TestEngine.registerCallback failure:" + err.message);
+               }
+       },
+       successCallback : function(params) {
+               TestEngine.log("[Warning] Function TestEngine.successCallback deprecated");
+               try {
+                       TestEngine.callbackMutex--;
+                       if( typeof TestEngine.testSuccessCallback != "undefined") {
+                               TestEngine.testSuccessCallback(params);
+                       } else {
+                               TestEngine.logOK(TestEngine.callbackMethodName + " succeed");
+                       }
+               } catch(err) {
+                       TestEngine.countException++;
+                       logError("   TestEngine.successCallback failure:" + err.message);
+               }
+       },
+       errorCallback : function(params) {
+               TestEngine.log("[Warning] Function TestEngine.errorCallback deprecated");
+               try {
+                       TestEngine.callbackMutex--;
+                       if( typeof TestEngine.testErrorCallback != "undefined") {
+                               TestEngine.testErrorCallback(params);
+                       } else {
+                               TestEngine.logErr(TestEngine.callbackMethodName + " failed");
+                       }
+               } catch(err) {
+                       TestEngine.countException++;
+                       logError("   TestEngine.errorCallback failure:" + err.message);
+               }
+       },
+       waitForCallback : function() {
+               try {
+                       //    while( TestEngine.callbackMutex )
+                       {
+                       }
+               } catch(err) {
+                       TestEngine.countException++;
+                       logError("   TestEngine.waitForCallback failure:" + err.message);
+               }
+       },
+       /*
+        * code - error code which is expected
+        * object - object which will be used to call method
+        * functionName - method name to call
+        * restArguments - rest arguments which will be passed to callback (max arguments = 10)
+        *
+        * example:
+        * TestEngine.catchError(10001, bondi.messaging, findSMSs, succCallback, null, filter)
+        */
+       catchError : function(code, object, functionName, restArguments /* , ... */ ) {
+               try {
+                       TestEngine.log("TestEngine.catchError is DEPRECATED. Please use TestEngine.catchErrorType.");
+                       var error;
+                       try {
+                               var newArgs = []
+                               for(var i = 3; i < arguments.length; i++) {
+                                       newArgs.push(arguments[i])
+                               }
+                               var retVal = null;
+                               //no args
+                               if(arguments.length == 3) {
+                                       retVal = object[functionName]();
+                               }
+                               //1 arg
+                               if(arguments.length == 4) {
+                                       retVal = object[functionName](newArgs[0]);
+                               }
+                               //2 args
+                               if(arguments.length == 5) {
+                                       retVal = object[functionName](newArgs[0], newArgs[1]);
+                               }
+                               //3 args
+                               if(arguments.length == 6) {
+                                       retVal = object[functionName](newArgs[0], newArgs[1], newArgs[2]);
+                               }
+                               // 4 args
+                               if(arguments.length == 7) {
+                                       retVal = object[functionName](newArgs[0], newArgs[1], newArgs[2], newArgs[3]);
+                               }
+                               // 5 args
+                               if(arguments.length == 8) {
+                                       retVal = object[functionName](newArgs[0], newArgs[1], newArgs[2], newArgs[3], newArgs[4]);
+                               }
+                               // 6 args
+                               if(arguments.length == 9) {
+                                       retVal = object[functionName](newArgs[0], newArgs[1], newArgs[2], newArgs[3], newArgs[4], newArgs[5]);
+                               }
+                               // 7 args
+                               if(arguments.length == 10) {
+                                       retVal = object[functionName](newArgs[0], newArgs[1], newArgs[2], newArgs[3], newArgs[4], newArgs[5], newArgs[6]);
+                               }
+                               // 8 args
+                               if(arguments.length == 11) {
+                                       retVal = object[functionName](newArgs[0], newArgs[1], newArgs[2], newArgs[3], newArgs[4], newArgs[5], newArgs[6], newArgs[7]);
+                               }
+                               // 9 args
+                               if(arguments.length == 12) {
+                                       retVal = object[functionName](newArgs[0], newArgs[1], newArgs[2], newArgs[3], newArgs[4], newArgs[5], newArgs[6], newArgs[7], newArgs[8]);
+                               }
+                               // 10 args
+                               if(arguments.length == 13) {
+                                       retVal = object[functionName](newArgs[0], newArgs[1], newArgs[2], newArgs[3], newArgs[4], newArgs[5], newArgs[6], newArgs[7], newArgs[8], newArgs[9]);
+                               }
+
+                               TestEngine.logErr(functionName + " no error thrown");
+                               return retVal;
+                       } catch(error) {
+                               TestEngine.testPresence("<error code from: " + functionName + ">", error.code);
+                               TestEngine.test("Error number", error.code == code);
+                               return;
+                       }
+                       TestEngine.logErr("Function " + functionName + " desn't throw");
+               } catch(err) {
+                       TestEngine.countException++;
+                       logError("   TestEngine.testError failure:" + err.message);
+               }
+       },
+       /*
+        * errorTypeName - attribute name of catched exception to compare with code
+        * code - error code which is expected
+        * object - object which will be used to call method
+        * functionName - method name to call
+        * restArguments - rest arguments which will be passed to callback (max arguments = 10)
+        *
+        * example:
+        * TestEngine.catchErrorType("code", 10001, bondi.messaging, findSMSs, succCallback, null, filter)
+        */
+       catchErrorType : function(errorTypeName, code, object, functionName, restArguments /* , ... */ ) {
+               try {
+                       var error;
+                       try {
+                               var newArgs = []
+                               for(var i = 4; i < arguments.length; i++) {
+                                       newArgs.push(arguments[i])
+                               }
+                               var retVal = null;
+                               if(arguments.length < 4) {
+                                       TestEngine.logErr("Wrong catchErrorType usage.");
+                                       return retVal;
+                               }
+                               //no args
+                               if(arguments.length == 4) {
+                                       retVal = object[functionName]();
+                               }
+                               //1 arg
+                               if(arguments.length == 5) {
+                                       retVal = object[functionName](newArgs[0]);
+                               }
+                               //2 args
+                               if(arguments.length == 6) {
+                                       retVal = object[functionName](newArgs[0], newArgs[1]);
+                               }
+                               //3 args
+                               if(arguments.length == 7) {
+                                       retVal = object[functionName](newArgs[0], newArgs[1], newArgs[2]);
+                               }
+                               // 4 args
+                               if(arguments.length == 8) {
+                                       retVal = object[functionName](newArgs[0], newArgs[1], newArgs[2], newArgs[3]);
+                               }
+                               // 5 args
+                               if(arguments.length == 9) {
+                                       retVal = object[functionName](newArgs[0], newArgs[1], newArgs[2], newArgs[3], newArgs[4]);
+                               }
+                               // 6 args
+                               if(arguments.length == 10) {
+                                       retVal = object[functionName](newArgs[0], newArgs[1], newArgs[2], newArgs[3], newArgs[4], newArgs[5]);
+                               }
+                               // 7 args
+                               if(arguments.length == 11) {
+                                       retVal = object[functionName](newArgs[0], newArgs[1], newArgs[2], newArgs[3], newArgs[4], newArgs[5], newArgs[6]);
+                               }
+                               // 8 args
+                               if(arguments.length == 12) {
+                                       retVal = object[functionName](newArgs[0], newArgs[1], newArgs[2], newArgs[3], newArgs[4], newArgs[5], newArgs[6], newArgs[7]);
+                               }
+                               // 9 args
+                               if(arguments.length == 13) {
+                                       retVal = object[functionName](newArgs[0], newArgs[1], newArgs[2], newArgs[3], newArgs[4], newArgs[5], newArgs[6], newArgs[7], newArgs[8]);
+                               }
+                               // 10 args
+                               if(arguments.length == 14) {
+                                       retVal = object[functionName](newArgs[0], newArgs[1], newArgs[2], newArgs[3], newArgs[4], newArgs[5], newArgs[6], newArgs[7], newArgs[8], newArgs[9]);
+                               }
+
+                               TestEngine.logErr(functionName + " no error thrown");
+                               return retVal;
+                       } catch(error) {
+                               TestEngine.testPresence("<error code from: " + functionName + ">", error[errorTypeName]);
+                               TestEngine.assertEqual("Error number", code, error[errorTypeName]);
+                               return;
+                       }
+                       TestEngine.logErr("Function " + functionName + " desn't throw");
+               } catch(err) {
+                       TestEngine.countException++;
+                       logError("   TestEngine.testError failure:" + err.message);
+               }
+       },
+       /*
+        * code - error type which is expected
+        * object - object which will be used to call method
+        * functionName - method name to call
+        * restArguments - rest arguments which will be passed to callback (max arguments = 10)
+        *
+        * example:
+        * TestEngine.catchErrorJil("INVALID_ARGUMENT", Widget.Telephony, "getCallRecord", null, null)
+        */
+       catchErrorJil : function(code, object, functionName, restArguments /* , ... */ ) {
+               try {
+                       TestEngine.logErr("TestEngine.catchErrorJil is DEPRECATED. Please use TestEngine.catchErrorType.");
+               } catch(err) {
+                       TestEngine.countException++;
+                       logError("   TestEngine.testError failure:" + err.message);
+               }
+       },
+       // Executes step by step functions passed in steps array
+       // and waits after every execution time defined in timeInterval
+       executeSteps : function(steps, timeInterval) {
+               try {
+                       if( typeof (timeInterval) == "undefined") {
+                               timeInterval = 100;
+                               //default value
+                       }
+
+                       TestEngine.stepsArray = steps;
+                       TestEngine.stepTimeout = timeInterval;
+                       TestEngine.currentStep = 0;
+                       TestEngine.executeNextStep();
+               } catch(err) {
+                       TestEngine.countException++;
+                       logError("   TestEngine.executeSteps failure:" + err.message);
+               }
+       },
+       executeNextStep : function() {
+               try {
+                       if(TestEngine.stepsArray && (TestEngine.currentStep < TestEngine.stepsArray.length)) {
+                               if(isArray(TestEngine.stepsArray[TestEngine.currentStep])) {
+                                       TestEngine.stepsArray[ TestEngine.currentStep ][0]();
+                                       setTimeout(TestEngine.executeNextStep, TestEngine.stepsArray[ TestEngine.currentStep ][1]);
+
+                               } else {
+                                       TestEngine.stepsArray[ TestEngine.currentStep ]();
+                                       setTimeout(TestEngine.executeNextStep, TestEngine.stepTimeout);
+                               }
+                               TestEngine.currentStep++;
+                       } else {
+                               TestEngine.currentStep = null;
+                               TestEngine.stepTimeout = null;
+                               TestEngine.stepsArray = null;
+                       }
+               } catch(err) {
+                       TestEngine.countException++;
+                       logError("   TestEngine.executeNextStep failure:" + err.message);
+                       jsPrint("   Current step:" + TestEngine.currentStep);
+
+                       TestEngine.currentStep = null;
+                       TestEngine.stepTimeout = null;
+                       TestEngine.stepsArray = null;
+               }
+       },
+       enumerate : function(obj, level) {
+               try {
+                       if( typeof level == "undefined") {
+                               TestEngine.log(obj + ":");
+                               level = "";
+                       }
+                       for(i in obj) {
+                               if(!( typeof obj[i] == "object" || typeof obj[i] == "array")) {
+                                       TestEngine.log(level + i + " =  " + obj[i]);
+                               } else {
+                                       TestEngine.log(level + i + " =  ");
+                                       TestEngine.enumerate(obj[i], level + "----");
+                               }
+                       }
+               } catch(err) {
+                       TestEngine.countException++;
+                       logError("   TestEngine.enumerate failure:" + err.message);
+               }
+       },
+       doTests : function() {
+               try {
+                       TestEngine.testCasesFailed = [];
+                       TestEngine.test("jsPrint presence", jsPrint);
+                       //TestEngine.test("Widget presence", window.widget);
+                       TestEngine.doNextTestCase();
+               } catch(err) {
+                       TestEngine.countException++;
+                       logError("   TestEngine.doTests failure:" + err.message);
+               }
+       },
+       showSuitesStats : function() {
+               try {
+                       jsPrint("============ Test suites:");
+                       for(var i in this.testSuiteStats) {
+                               jsPrint(i + " - " + this.testSuiteStats[i].passed + " passed, " + this.testSuiteStats[i].failed + " failed," + "   asserts: " + this.testSuiteStats[i].assertsOK + " passed, " + this.testSuiteStats[i].assertsErr + " failed");
+                       }
+               } catch(err) {
+                       logError("   TestEngine.showSuitesStats failure:" + err.message);
+               }
+       },
+       doNextTestCase : function() {
+               try {
+                       if(TestEngine.stepsArray !== null || (TestEngine.callbackMutex > 0)) {
+                               setTimeout(TestEngine.doNextTestCase, 100);
+                               return;
+                       }
+
+                       if(TestEngine.interval > 0) {
+                               setTimeout(TestEngine.doNextTestCase, TestEngine.interval);
+                               TestEngine.interval = 0;
+                               return;
+                       }
+
+                       if(TestEngine.currentTestCase) {
+                               TestEngine.endTestCase(TestEngine.testList[TestEngine.currentTestCase - 1]);
+                       }
+
+                       if(TestEngine.testList.length == TestEngine.currentTestCase) {
+                               jsPrint("============");
+                               jsPrint(TestEngine.finalLog);
+                               TestEngine.showSuitesStats();
+                               jsPrint("============ Summary:");
+                               jsPrint("Test cases all: " + TestEngine.testList.length);
+                               jsPrint("Test cases passed: " + TestEngine.testCasesPassedCount);
+                               jsPrint("Test cases failed: " + TestEngine.testCasesFailedCount);
+                               jsPrint("Asserts passed: " + TestEngine.countAllPassed);
+                               jsPrint("Asserts failed: " + TestEngine.countAllFailed);
+                               if(isVerbose()) {
+                                       jsPrint("============ Failing test cases:");
+                                       for( i = 0; i < TestEngine.testCasesFailed.length; ++i) {
+                                               logError(TestEngine.testCasesFailed[i]);
+                                       }
+                               }
+                               TestEngine.resultLogger.logFinish();
+                               TestEngine.summaryRenderer.render(TestEngine);
+                               if (TestEngine.onFinished) {
+                                       TestEngine.onFinished();
+                               }
+                               return;
+                       }
+
+                       var i = TestEngine.currentTestCase++;
+                       try {
+                               TestEngine.log("");
+                               TestEngine.log("==== Test case: " + TestEngine.testList[i].testName);
+                               TestEngine.startTestCase();
+                               var testPrereq = true;
+                               if(TestEngine.testList[i].testPrereq !== undefined) {
+                                       testPrereq = TestEngine.testList[i].testPrereq();
+                               }
+                               if(testPrereq) {
+                                       if(TestEngine.testList[i].enabled) {
+                                               TestEngine.testList[i].testFunc();
+                                       } else {
+                                               TestEngine.logErr("Test disabled");
+                                       }
+
+                               } else {
+                                       TestEngine.logException("Test case prerequisites unfulfilled.  Skipping it.");
+                               }
+                       } catch(err) {
+                               TestEngine.countException++;
+                               TestEngine.log("   Test case '" + TestEngine.testList[i].testName + "' failed:" + err.message);
+                       }
+                       setTimeout(TestEngine.doNextTestCase, 100);
+               } catch(err) {
+                       logError("   TestEngine.doNextTestCase failure:" + err.message);
+               }
+       },
+       removeResultSaveFile : function(filename) {
+               try {
+                       
+                       //var filename = TestEngine.testSuiteName + ".test";
+                       
+                       tizen.filesystem.resolve("documents", 
+                                       function(fs) {
+                                               fs.deleteFile("documents/" + filename);
+                                       },
+                                       function(e) {
+                                               console.log(err.name + ":" + err.message);
+                                       }, "rw");
+               } catch (err) {
+                       console.log(err.name);
+               }
+       },
+       saveTestResult : function(filename, saveString, needExit) {
+               try {
+                       //var filename = TestEngine.testSuiteName + ".test";
+                       
+                       tizen.filesystem.resolve("documents", 
+                                       function(fs) {
+                                               var f = fs.createFile(filename);
+                                               f.openStream("rw", 
+                                                               function(stream) {
+                                                                       stream.write(saveString);
+                                                                       stream.close();
+                                                                       if (needExit) {
+                                                                               tizen.application.getCurrentApplication().exit();
+                                                                       }
+                                                               },
+                                                               function(e) {
+                                                                       console.log(err.name + ":" + err.message);
+                                                               });
+                                       },
+                                       function(e) {
+                                               console.log(err.name + ":" + err.message);
+                                       }, "rw");
+               } catch (err) {
+                       console.log(err.name);
+               }
+       },
+       doSCMAutoTests : function(SCM) {
+               try {
+                       TestEngine.removeResultSaveFile(TestEngine.testSuiteName + ".test");
+                       TestEngine.removeResultSaveFile(TestEngine.testSuiteName + ".fail");
+
+                       TestEngine.testCasesFailed = [];
+                       TestEngine.test("jsPrint presence", jsPrint);
+                       TestEngine.test("Widget presence", window.widget);
+                       TestEngine.doSCMAutoNextTestCase(SCM);
+               } catch(err) {
+                       TestEngine.countException++;
+                       logError("   TestEngine.doTests failure:" + err.message);
+               }
+       },
+       doSCMAutoNextTestCase : function(SCM) {
+               try {
+                       if(TestEngine.stepsArray !== null || (TestEngine.callbackMutex > 0)) {
+                               setTimeout(TestEngine.doSCMAutoNextTestCase, 100, SCM);
+                               return;
+                       }
+
+                       if(TestEngine.interval > 0) {
+                               setTimeout(TestEngine.doSCMAutoNextTestCase, TestEngine.interval, SCM);
+                               TestEngine.interval = 0;
+                               return;
+                       }
+
+                       if(TestEngine.currentTestCase) {
+                               TestEngine.endTestCase(TestEngine.testList[TestEngine.currentTestCase - 1]);
+                       }
+
+                       if(TestEngine.testList.length == TestEngine.currentTestCase) {
+                               jsPrint("============");
+                               jsPrint(TestEngine.finalLog);
+                               TestEngine.showSuitesStats();
+                               jsPrint("============ Summary:");
+                               jsPrint("Test cases all: " + TestEngine.testList.length);
+                               jsPrint("Test cases passed: " + TestEngine.testCasesPassedCount);
+                               jsPrint("Test cases failed: " + TestEngine.testCasesFailedCount);
+                               jsPrint("Asserts passed: " + TestEngine.countAllPassed);
+                               jsPrint("Asserts failed: " + TestEngine.countAllFailed);
+                               
+                               var failCasesString = "";
+
+                               jsPrint("============ Failing test cases:");
+
+                               for( i = 0; i < TestEngine.testCasesFailed.length; ++i) {
+                                       logError(TestEngine.testCasesFailed[i]);
+                                       failCasesString = failCasesString + TestEngine.testCasesFailed[i] + "\n";
+                                       
+                               }
+
+                               if (failCasesString.length > 0) {
+                                       TestEngine.saveTestResult(TestEngine.testSuiteName + ".fail", failCasesString, false);
+                               }
+
+                               TestEngine.resultLogger.logFinish();
+                               TestEngine.summaryRenderer.render(TestEngine);
+                               
+                               var saveString =  TestEngine.testSuiteName + " : " + 
+                               TestEngine.testCasesPassedCount + "/" +   TestEngine.testList.length + " (Passed/Total)\n";
+                               TestEngine.saveTestResult(TestEngine.testSuiteName + ".test", saveString, SCM);
+
+                       
+                               //tizen.application.getCurrentApplication().exit();
+                               
+                               if (TestEngine.onFinished) {
+                                       TestEngine.onFinished();
+                               }
+                               return;
+                       }
+
+                       var i = TestEngine.currentTestCase++;
+                       try {
+                               TestEngine.log("");
+                               TestEngine.log("==== Test case: " + TestEngine.testList[i].testName);
+                               TestEngine.startTestCase();
+                               var testPrereq = true;
+                               if(TestEngine.testList[i].testPrereq !== undefined) {
+                                       testPrereq = TestEngine.testList[i].testPrereq();
+                               }
+                               if(testPrereq) {
+                                       if(TestEngine.testList[i].enabled) {
+                                               TestEngine.testList[i].testFunc();
+                                       } else {
+                                               TestEngine.logErr("Test disabled");
+                                       }
+
+                               } else {
+                                       TestEngine.logException("Test case prerequisites unfulfilled.  Skipping it.");
+                               }
+                       } catch(err) {
+                               TestEngine.countException++;
+                               TestEngine.log("   Test case '" + TestEngine.testList[i].testName + "' failed:" + err.message);
+                       }
+                       setTimeout(TestEngine.doSCMAutoNextTestCase, 100, SCM);
+               } catch(err) {
+                       logError("   TestEngine.doNextTestCase failure:" + err.message);
+               }
+       },
+
+       doAutoTests : function() {
+               try {
+                       TestEngine.testCasesFailed = [];
+                       TestEngine.test("jsPrint presence", jsPrint);
+                       TestEngine.test("Widget presence", window.widget);
+                       TestEngine.doAutoNextTestCase();
+               } catch(err) {
+                       TestEngine.countException++;
+                       logError("   TestEngine.doTests failure:" + err.message);
+               }
+       },
+       doAutoNextTestCase : function() {
+               try {
+                       if(TestEngine.stepsArray !== null || (TestEngine.callbackMutex > 0)) {
+                               setTimeout(TestEngine.doAutoNextTestCase, 100);
+                               return;
+                       }
+
+                       if(TestEngine.interval > 0) {
+                               setTimeout(TestEngine.doAutoNextTestCase, TestEngine.interval);
+                               TestEngine.interval = 0;
+                               return;
+                       }
+
+                       if(TestEngine.currentTestCase) {
+                               TestEngine.endTestCase(TestEngine.testList[TestEngine.currentTestCase - 1]);
+                       }
+
+                       if(TestEngine.testList.length == TestEngine.currentTestCase) {
+                               jsPrint("============");
+                               jsPrint(TestEngine.finalLog);
+                               TestEngine.showSuitesStats();
+                               jsPrint("============ Summary:");
+                               jsPrint("Test cases all: " + TestEngine.testList.length);
+                               jsPrint("Test cases passed: " + TestEngine.testCasesPassedCount);
+                               jsPrint("Test cases failed: " + TestEngine.testCasesFailedCount);
+                               jsPrint("Asserts passed: " + TestEngine.countAllPassed);
+                               jsPrint("Asserts failed: " + TestEngine.countAllFailed);
+                               
+                               if(isVerbose()) {
+                                       jsPrint("============ Failing test cases:");
+                                       for( i = 0; i < TestEngine.testCasesFailed.length; ++i) {
+                                               logError(TestEngine.testCasesFailed[i]);
+                                       }
+                               }
+                               TestEngine.resultLogger.logFinish();
+                               TestEngine.summaryRenderer.render(TestEngine);
+                               window.close();
+                               if (TestEngine.onFinished) {
+                                       TestEngine.onFinished();
+                               }
+                               return;
+                       }
+
+                       var i = TestEngine.currentTestCase++;
+                       try {
+                               TestEngine.log("");
+                               TestEngine.log("==== Test case: " + TestEngine.testList[i].testName);
+                               TestEngine.startTestCase();
+                               var testPrereq = true;
+                               if(TestEngine.testList[i].testPrereq !== undefined) {
+                                       testPrereq = TestEngine.testList[i].testPrereq();
+                               }
+                               if(testPrereq) {
+                                       if(TestEngine.testList[i].enabled) {
+                                               TestEngine.testList[i].testFunc();
+                                       } else {
+                                               TestEngine.logErr("Test disabled");
+                                       }
+
+                               } else {
+                                       TestEngine.logException("Test case prerequisites unfulfilled.  Skipping it.");
+                               }
+                       } catch(err) {
+                               TestEngine.countException++;
+                               TestEngine.log("   Test case '" + TestEngine.testList[i].testName + "' failed:" + err.message);
+                       }
+                       setTimeout(TestEngine.doAutoNextTestCase, 100);
+               } catch(err) {
+                       logError("   TestEngine.doNextTestCase failure:" + err.message);
+               }
+       }
+};
+
+function isUndefined(val) {
+       if( typeof val == "undefined") {
+               return true;
+       }
+       return false;
+}
+
+function isNull(val) {
+       return val === null;
+}
+
+function isString(val) {
+       if( typeof val == typeof "") {
+               return true;
+       }
+       return false;
+}
+
+function isNumber(val) {
+       if( typeof val == typeof 0) {
+               return true
+       }
+       return false;
+}
+
+function isDate(val) {
+       return ( val instanceof Date);
+}
+
+function isFunction(val) {
+       return ( typeof (val) == 'function');
+}
+
+function isBoolean(val) {
+       if( typeof val == typeof true) {
+               return true
+       }
+       return false;
+}
+
+function isArray(val) {
+       return ( val instanceof Array);
+}
+
+function isObject(val) {
+       return ( val );
+}
+
+function isVerbose() {
+       return (( typeof (VERBOSE) != "undefined") && (VERBOSE === 1));
+}
+
+/**
+ * Tests results logger.
+ */
+function HTMLTestResultLogger(sinkId) {
+       jsPrint('Results are saved to: ' + sinkId);
+
+       /**
+        * Logs a message.
+        * @param message Message to log.
+        * @param status Status of the message (PASSED, FAILED, EXCEPTION).
+        *               By default status is set to PASSED.
+        */
+       this.log = function(message, status) {
+               if(arguments.length < 2)
+                       throw "Not enough number of arguments.";
+               append(createLogEntry(message, status));
+       }
+       /**
+        * Helper functions.
+        */
+       this.logPass = function(message) {
+               if(arguments.length < 1)
+                       throw "Not enough number of arguments.";
+               this.log(message, HTMLTestResultLogger.PASSED);
+       }
+
+       this.logFail = function(message) {
+               if(arguments.length < 1)
+                       throw "Not enough number of arguments.";
+               this.log(message, HTMLTestResultLogger.FAILED);
+       }
+
+       this.logFinish = function() {
+               append(htmlFooter);
+       }
+
+       var createLogEntry = function(message, status) {
+               var entry = '<div class="entry ' + status + '">';
+               entry += message.toString();
+               entry += '</div>';
+               return entry;
+       }
+       
+       function append(data) {
+               fs.appendFileSync(sink, data + '\n');
+       }
+       
+       var fs = require('fs');
+       var id = sinkId;
+       var sink = sinkId;
+
+       append(htmlHeader);
+}
+
+HTMLTestResultLogger.PASSED = "passed";
+HTMLTestResultLogger.FAILED = "failed";
+HTMLTestResultLogger.EXCEPTION = "exception";
+
+/**
+ * Tests summary renderer.
+ */
+function HTMLTestSummaryRenderer(summaryId) {
+       jsPrint('Summary is saved to: ' + summaryId);
+
+       this.render = function(engine) {
+               if(arguments.length < 1)
+                       throw "Not enough arguments.";
+
+               fs.writeFileSync(summary, '');
+               append(htmlHeader);
+               renderSummary(engine);
+               for(var suiteName in engine.testSuiteStats) {
+                       if(!isSuiteStarted(engine.testSuiteStats[suiteName]))
+                               continue;
+                       renderSuite(suiteName, engine.testSuiteStats[suiteName]);
+               }
+               append(htmlFooter);
+       }
+       var isSuiteStarted = function(stats) {
+               return (stats.passed + stats.failed != 0);
+       }
+       var renderSuite = function(name, stats) {
+               var elementId = '_summary_suite_' + name;
+               var text = stats.passed + ' tests (' + stats.assertsOK + ' asserts)' + ' passed, ' + stats.failed + ' tests (' + stats.assertsErr + ' asserts)' + ' failed';
+               var element = '<div id="' + elementId + '">' + name + ': ' + '<span name="stats">' + text + '</span></div>';
+               append(element);
+       }
+       var renderSummary = function(engine) {
+               var run = '<div>Run: <span id="_summary_numberOfRunTests">' + engine.currentTestCase + '</span>';
+               run += ' of <span id="_summary_numberOfAllTests">' + engine.testList.length + '</span> tests</div>';
+               //var current = '<div>Current: <span id="_summary_currentTest">' + 0 + '</span></div>';
+               var passed = '<div>Passed: <span id="_summary_numberOfPassedTests" class="passed">' + engine.testCasesPassedCount + '</span> tests ';
+               passed += '(<span id="_summary_numberOfPassedAsserts" class="passed">' + engine.countAllPassed + '</span> asserts)</div>';
+               var failed = '<div>Failed: <span id="_summary_numberOfFailedTests" class="failed">' + engine.testCasesFailedCount + '</span> tests ';
+               failed += '(<span id="_summary_numberOfFailedAsserts" class="failed">' + engine.countAllFailed + '</span> asserts)</div>';
+               append(run);
+               append(passed);
+               append(failed);
+       }
+       function append(data) {
+               fs.appendFileSync(summary, data + '\n');
+       }
+       var fs = require('fs');
+       var id = summaryId;
+       var summary = summaryId;
+}
+
+GLOBAL.isUndefined = isUndefined;
+GLOBAL.isNull = isNull;
+GLOBAL.isString = isString;
+GLOBAL.isNumber = isNumber;
+GLOBAL.isDate = isDate;
+GLOBAL.isFunction = isFunction;
+GLOBAL.isBoolean = isBoolean;
+GLOBAL.isArray = isArray;
+GLOBAL.isObject = isObject;
+GLOBAL.jsPrint = jsPrint;
+GLOBAL.logFail = logFail;
+GLOBAL.logError = logError;
+module.exports = TestEngine;
diff --git a/webWidgetTCT_device/test/utc/config/ConfigAlarm.js b/webWidgetTCT_device/test/utc/config/ConfigAlarm.js
new file mode 100755 (executable)
index 0000000..44c9847
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * 
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ * PROPRIETARY/CONFIDENTIAL
+ * 
+ * This software is the confidential and proprietary information of SAMSUNG 
+ * ELECTRONICS ("Confidential Information"). You agree and acknowledge that 
+ * this software is owned by Samsung and you shall not disclose such 
+ * Confidential Information and shall use it only in accordance with the terms 
+ * of the license agreement you entered into with SAMSUNG ELECTRONICS. SAMSUNG 
+ * make no representations or warranties about the suitability of the software, 
+ * either express or implied, including but not limited to the implied 
+ * warranties of merchantability, fitness for a particular purpose, or 
+ * non-infringement. SAMSUNG shall not be liable for any damages suffered by 
+ * licensee arising out of or related to this software.
+ * 
+ */
+
+TestEngine.setTestSuiteName("[Alarm]", 60*1000);
+TestEngine.addTest(true, UTC_alarm_constants_P_001, "UTC_alarm_constants_P_001");
+TestEngine.addTest(true, UTC_alarm_presence_P_001, "UTC_alarm_presence_P_001");
+TestEngine.addTest(true, UTC_alarm_AlarmAbsolute_Constructor_P_001, "UTC_alarm_AlarmAbsolute_Constructor_P_001");
+TestEngine.addTest(true, UTC_alarm_AlarmAbsolute_date_P_001, "UTC_alarm_AlarmAbsolute_date_P_001");
+TestEngine.addTest(true, UTC_alarm_AlarmAbsolute_id_P_001, "UTC_alarm_AlarmAbsolute_id_P_001");
+TestEngine.addTest(true, UTC_alarm_AlarmAbsolute_period_P_001, "UTC_alarm_AlarmAbsolute_period_P_001");
+TestEngine.addTest(true, UTC_alarm_AlarmAbsolute_daysOfTheWeek_P_001, "UTC_alarm_AlarmAbsolute_daysOfTheWeek_P_001");
+TestEngine.addTest(true, UTC_alarm_AlarmAbsolute_getNextScheduledDate_P_001, "UTC_alarm_AlarmAbsolute_getNextScheduledDate_P_001");
+TestEngine.addTest(true, UTC_alarm_AlarmAbsolute_getNextScheduledDate_N_001, "UTC_alarm_AlarmAbsolute_getNextScheduledDate_N_001");
+TestEngine.addTest(true, UTC_alarm_add_P_001, "UTC_alarm_add_P_001");
+TestEngine.addTest(true, UTC_alarm_add_P_002, "UTC_alarm_add_P_002");
+TestEngine.addTest(true, UTC_alarm_add_N_001, "UTC_alarm_add_N_001");
+TestEngine.addTest(true, UTC_alarm_add_N_002, "UTC_alarm_add_N_002");
+TestEngine.addTest(true, UTC_alarm_add_N_003, "UTC_alarm_add_N_003");
+TestEngine.addTest(true, UTC_alarm_add_N_004, "UTC_alarm_add_N_004");
+TestEngine.addTest(true, UTC_alarm_AlarmRelative_Constructor_P_001, "UTC_alarm_AlarmRelative_Constructor_P_001");
+TestEngine.addTest(true, UTC_alarm_AlarmRelative_delay_P_001, "UTC_alarm_AlarmRelative_delay_P_001");
+TestEngine.addTest(true, UTC_alarm_AlarmRelative_id_P_001, "UTC_alarm_AlarmRelative_id_P_001");
+TestEngine.addTest(true, UTC_alarm_AlarmRelative_period_P_001, "UTC_alarm_AlarmRelative_period_P_001");
+TestEngine.addTest(true, UTC_alarm_AlarmRelative_getRemainingSeconds_P_001, "UTC_alarm_AlarmRelative_getRemainingSeconds_P_001");
+TestEngine.addTest(true, UTC_alarm_AlarmRelative_getRemainingSeconds_N_001, "UTC_alarm_AlarmRelative_getRemainingSeconds_N_001");
+TestEngine.addTest(true, UTC_alarm_remove_P_001, "UTC_alarm_remove_P_001");
+TestEngine.addTest(true, UTC_alarm_remove_N_001, "UTC_alarm_remove_N_001");
+TestEngine.addTest(true, UTC_alarm_remove_N_002, "UTC_alarm_remove_N_002");
+TestEngine.addTest(true, UTC_alarm_remove_N_003, "UTC_alarm_remove_N_003");
+TestEngine.addTest(true, UTC_alarm_removeAll_P_001, "UTC_alarm_removeAll_P_001");
+TestEngine.addTest(true, UTC_alarm_get_P_001, "UTC_alarm_get_P_001");
+TestEngine.addTest(true, UTC_alarm_get_N_001, "UTC_alarm_get_N_001");
+TestEngine.addTest(true, UTC_alarm_get_N_002, "UTC_alarm_get_N_002");
+TestEngine.addTest(true, UTC_alarm_get_N_003, "UTC_alarm_get_N_003");
+TestEngine.addTest(true, UTC_alarm_getAll_P_001, "UTC_alarm_getAll_P_001");
diff --git a/webWidgetTCT_device/test/utc/config/ConfigApplication.js b/webWidgetTCT_device/test/utc/config/ConfigApplication.js
new file mode 100755 (executable)
index 0000000..270db30
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ * PROPRIETARY/CONFIDENTIAL
+ *
+ * This software is the confidential and proprietary information of SAMSUNG
+ * ELECTRONICS ("Confidential Information"). You agree and acknowledge that
+ * this software is owned by Samsung and you shall not disclose such
+ * Confidential Information and shall use it only in accordance with the terms
+ * of the license agreement you entered into with SAMSUNG ELECTRONICS. SAMSUNG
+ * make no representations or warranties about the suitability of the software,
+ * either express or implied, including but not limited to the implied
+ * warranties of merchantability, fitness for a particular purpose, or
+ * non-infringement. SAMSUNG shall not be liable for any damages suffered by
+ * licensee arising out of or related to this software.
+ *
+ */
+
+
+TestEngine.setTestSuiteName("[Application]");
+
+TestEngine.addTest(true, UTC_application_presence_P_001,       "[Application]UTC_application_presence_P_001");
+TestEngine.addTest(true, UTC_application_presence_P_002,       "[Application]UTC_application_presence_P_002");
+
+TestEngine.addTest(true, UTC_application_getCurrentApplication_P_001,  "[Application]UTC_application_getCurrentApplication_P_001");
+
+TestEngine.addTest(true, UTC_application_getAppsContext_P_001,         "[Application]UTC_application_getAppsContext_P_001");
+TestEngine.addTest(true, UTC_application_getAppsContext_P_002,         "[Application]UTC_application_getAppsContext_P_002");
+TestEngine.addTest(true, UTC_application_getAppsContext_P_003,         "[Application]UTC_application_getAppsContext_P_003");
+//TestEngine.addTest(true, UTC_application_getAppsContext_P_004,       "[Application]UTC_application_getAppsContext_P_004");
+TestEngine.addTest(true, UTC_application_getAppsContext_P_005,         "[Application]UTC_application_getAppsContext_P_005");
+TestEngine.addTest(true, UTC_application_getAppsContext_N_001,         "[Application]UTC_application_getAppsContext_N_001");
+
+TestEngine.addTest(true, UTC_application_getAppsInfo_P_001,    "[Application]UTC_application_getAppsInfo_P_001");
+TestEngine.addTest(true, UTC_application_getAppsInfo_P_002,    "[Application]UTC_application_getAppsInfo_P_002");
+TestEngine.addTest(true, UTC_application_getAppsInfo_P_003,    "[Application]UTC_application_getAppsInfo_P_003");
+//TestEngine.addTest(true, UTC_application_getAppsInfo_P_004,  "[Application]UTC_application_getAppsInfo_P_004");
+TestEngine.addTest(true, UTC_application_getAppsInfo_P_005,    "[Application]UTC_application_getAppsInfo_P_005");
+TestEngine.addTest(true, UTC_application_getAppsInfo_N_001,    "[Application]UTC_application_getAppsInfo_N_001");
+
+TestEngine.addTest(true, UTC_application_getAppContext_P_001,  "[Application]UTC_application_getAppContext_P_001");
+//TestEngine.addTest(true, UTC_application_getAppContext_P_002,        "[Application]UTC_application_getAppContext_P_002");
+TestEngine.addTest(true, UTC_application_getAppContext_P_003,  "[Application]UTC_application_getAppContext_P_003");
+TestEngine.addTest(true, UTC_application_getAppContext_P_004,  "[Application]UTC_application_getAppContext_P_004");
+TestEngine.addTest(true, UTC_application_getAppContext_N_001,  "[Application]UTC_application_getAppContext_N_001");
+
+TestEngine.addTest(true, UTC_application_getAppInfo_P_001,     "[Application]UTC_application_getAppInfo_P_001");
+TestEngine.addTest(true, UTC_application_getAppInfo_P_002,     "[Application]UTC_application_getAppInfo_P_002");
+TestEngine.addTest(true, UTC_application_getAppInfo_P_003,     "[Application]UTC_application_getAppInfo_P_003");
+//TestEngine.addTest(true, UTC_application_getAppInfo_P_004,   "[Application]UTC_application_getAppInfo_P_004");
+TestEngine.addTest(true, UTC_application_getAppInfo_N_001,     "[Application]UTC_application_getAppInfo_N_001");
+
+TestEngine.addTest(true, UTC_application_getAppCerts_P_001,    "[Application]UTC_application_getAppCerts_P_001");
+TestEngine.addTest(true, UTC_application_getAppCerts_P_002,    "[Application]UTC_application_getAppCerts_P_002");
+TestEngine.addTest(true, UTC_application_getAppCerts_P_003,    "[Application]UTC_application_getAppCerts_P_003");
+TestEngine.addTest(true, UTC_application_getAppCerts_P_004,    "[Application]UTC_application_getAppCerts_P_004");
+TestEngine.addTest(true, UTC_application_getAppCerts_N_001,    "[Application]UTC_application_getAppCerts_N_001");
+
+TestEngine.addTest(true, UTC_application_getAppSharedURI_P_001,        "[Application]UTC_application_getAppSharedURI_P_001");
+TestEngine.addTest(true, UTC_application_getAppSharedURI_P_002,        "[Application]UTC_application_getAppSharedURI_P_002");
+TestEngine.addTest(true, UTC_application_getAppSharedURI_P_003,        "[Application]UTC_application_getAppSharedURI_P_003");
+TestEngine.addTest(true, UTC_application_getAppSharedURI_P_004,        "[Application]UTC_application_getAppSharedURI_P_004");
+TestEngine.addTest(true, UTC_application_getAppSharedURI_N_001,        "[Application]UTC_application_getAppSharedURI_N_001");
+
+TestEngine.addTest(true, UTC_application_getAppMetaData_P_001, "[Application]UTC_application_getAppMetaData_P_001");
+TestEngine.addTest(true, UTC_application_getAppMetaData_P_002, "[Application]UTC_application_getAppMetaData_P_002");
+TestEngine.addTest(true, UTC_application_getAppMetaData_P_003, "[Application]UTC_application_getAppMetaData_P_003");
+TestEngine.addTest(true, UTC_application_getAppMetaData_P_004, "[Application]UTC_application_getAppMetaData_P_004");
+TestEngine.addTest(true, UTC_application_getAppMetaData_N_001, "[Application]UTC_application_getAppMetaData_N_001");
+
+TestEngine.addTest(true, UTC_application_addAppInfoEventListener_P_001,        "[Application]UTC_application_addAppInfoEventListener_P_001");
+TestEngine.addTest(true, UTC_application_addAppInfoEventListener_P_002,        "[Application]UTC_application_addAppInfoEventListener_P_002");
+TestEngine.addTest(true, UTC_application_addAppInfoEventListener_P_003,        "[Application]UTC_application_addAppInfoEventListener_P_003");
+TestEngine.addTest(true, UTC_application_addAppInfoEventListener_P_004,        "[Application]UTC_application_addAppInfoEventListener_P_004");
+TestEngine.addTest(true, UTC_application_addAppInfoEventListener_P_005,        "[Application]UTC_application_addAppInfoEventListener_P_005");
+TestEngine.addTest(true, UTC_application_addAppInfoEventListener_P_006,        "[Application]UTC_application_addAppInfoEventListener_P_006");
+TestEngine.addTest(true, UTC_application_addAppInfoEventListener_P_007,        "[Application]UTC_application_addAppInfoEventListener_P_007");
+TestEngine.addTest(true, UTC_application_addAppInfoEventListener_P_008,        "[Application]UTC_application_addAppInfoEventListener_P_008");
+TestEngine.addTest(true, UTC_application_addAppInfoEventListener_N_001,        "[Application]UTC_application_addAppInfoEventListener_N_001");
+TestEngine.addTest(true, UTC_application_removeAppInfoEventListener_N_001,     "[Application]UTC_application_removeAppInfoEventListener_N_001");
+
+TestEngine.addTest(true, UTC_application_construct_ApplicationControlData_P_001,       "[Application]UTC_application_construct_ApplicationControlData_P_001");
+TestEngine.addTest(true, UTC_application_construct_ApplicationControlData_P_002,       "[Application]UTC_application_construct_ApplicationControlData_P_002");
+
+TestEngine.addTest(true, UTC_application_construct_ApplicationControl_P_001,   "[Application]UTC_application_construct_ApplicationControl_P_001");
+TestEngine.addTest(true, UTC_application_construct_ApplicationControl_P_002,   "[Application]UTC_application_construct_ApplicationControl_P_002");
+TestEngine.addTest(true, UTC_application_construct_ApplicationControl_P_003,   "[Application]UTC_application_construct_ApplicationControl_P_003");
+
+TestEngine.addTest(true, UTC_application_field_ApplicationInformation_N_001,   "[Application]UTC_application_field_ApplicationInformation_N_001");
+TestEngine.addTest(true, UTC_application_field_ApplicationContext_N_001,       "[Application]UTC_application_field_ApplicationContext_N_001");
+
+TestEngine.addTest(true, UTC_application_launch_P_001,         "[Application]UTC_application_launch_P_001");
+TestEngine.addTest(true, UTC_application_launch_P_002,         "[Application]UTC_application_launch_P_002");
+TestEngine.addTest(true, UTC_application_launch_P_003,         "[Application]UTC_application_launch_P_003");
+TestEngine.addTest(true, UTC_application_launch_N_001,         "[Application]UTC_application_launch_N_001");
+TestEngine.addTest(true, UTC_application_launch_N_002,         "[Application]UTC_application_launch_N_002");
+TestEngine.addTest(true, UTC_application_launch_N_003,         "[Application]UTC_application_launch_N_003");
+TestEngine.addTest(true, UTC_application_launch_N_004,         "[Application]UTC_application_launch_N_004");
+TestEngine.addTest(true, UTC_application_launch_N_005,         "[Application]UTC_application_launch_N_005");
+TestEngine.addTest(true, UTC_application_launch_N_006,         "[Application]UTC_application_launch_N_006");
+
+TestEngine.addTest(true, UTC_application_kill_P_000,   "[Application]UTC_application_kill_P_000");
+TestEngine.addTest(true, UTC_application_kill_P_001,   "[Application]UTC_application_kill_P_001");
+TestEngine.addTest(true, UTC_application_kill_P_002,   "[Application]UTC_application_kill_P_002");
+
+TestEngine.addTest(true, UTC_application_kill_N_001,   "[Application]UTC_application_kill_N_001");
+TestEngine.addTest(true, UTC_application_kill_N_002,   "[Application]UTC_application_kill_N_002");
+TestEngine.addTest(true, UTC_application_kill_N_003,   "[Application]UTC_application_kill_N_003");
+TestEngine.addTest(true, UTC_application_kill_N_004,   "[Application]UTC_application_kill_N_004");
+TestEngine.addTest(true, UTC_application_kill_N_005,   "[Application]UTC_application_kill_N_005");
+TestEngine.addTest(true, UTC_application_kill_N_006,   "[Application]UTC_application_kill_N_006");
+
+TestEngine.addTest(true, UTC_application_findAppControl_P_001,         "[Application]UTC_application_findAppControl_P_001");
+TestEngine.addTest(true, UTC_application_findAppControl_P_002,         "[Application]UTC_application_findAppControl_P_002");
+TestEngine.addTest(true, UTC_application_findAppControl_P_003,         "[Application]UTC_application_findAppControl_P_003");
+TestEngine.addTest(true, UTC_application_findAppControl_N_001,         "[Application]UTC_application_findAppControl_N_001");
+
+TestEngine.addTest(true, UTC_application_launchAppControl_P_001,       "[Application]UTC_application_launchAppControl_P_001");
+TestEngine.addTest(true, UTC_application_launchAppControl_P_002,       "[Application]UTC_application_launchAppControl_P_002");
+TestEngine.addTest(true, UTC_application_launchAppControl_P_003,       "[Application]UTC_application_launchAppControl_P_003");
+TestEngine.addTest(true, UTC_application_launchAppControl_P_007,       "[Application]UTC_application_launchAppControl_P_007");
+TestEngine.addTest(true, UTC_application_launchAppControl_P_008,       "[Application]UTC_application_launchAppControl_P_008");
+//TestEngine.addTest(true, UTC_application_launchAppControl_P_009,     "[Application]UTC_application_launchAppControl_P_009");
+TestEngine.addTest(true, UTC_application_launchAppControl_N_001,       "[Application]UTC_application_launchAppControl_N_001");
+TestEngine.addTest(true, UTC_application_launchAppControl_N_002,       "[Application]UTC_application_launchAppControl_N_002");
+
+//TestEngine.addTest(true, UTC_application_DCM_1456,   "[Application]UTC_application_DCM_1456");
+
+
+//TestEngine.addTest(true, UTC_application_getRequestedAppControl_P_001,       "[Application]UTC_application_getRequestedAppControl_P_001");
+//TestEngine.addTest(true, UTC_application_getRequestedAppControl_P_002,       "[Application]UTC_application_getRequestedAppControl_P_002");
+
+//TestEngine.addTest(true, UTC_application_exit,       "[Application]UTC_application_exit");
+//TestEngine.addTest(true, UTC_application_hide,       "[Application]UTC_application_hide");
diff --git a/webWidgetTCT_device/test/utc/config/ConfigClock.js b/webWidgetTCT_device/test/utc/config/ConfigClock.js
new file mode 100755 (executable)
index 0000000..dd3ead1
--- /dev/null
@@ -0,0 +1,110 @@
+
+/*
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ * PROPRIETARY/CONFIDENTIAL
+ *
+ * This software is the confidential and proprietary information of SAMSUNG
+ * ELECTRONICS ("Confidential Information"). You agree and acknowledge that
+ * this software is owned by Samsung and you shall not disclose such
+ * Confidential Information and shall use it only in accordance with the terms
+ * of the license agreement you entered into with SAMSUNG ELECTRONICS. SAMSUNG
+ * make no representations or warranties about the suitability of the software,
+ * either express or implied, including but not limited to the implied
+ * warranties of merchantability, fitness for a particular purpose, or
+ * non-infringement. SAMSUNG shall not be liable for any damages suffered by
+ * licensee arising out of or related to this software.
+ *
+ */
+
+TestEngine.setTestSuiteName("[Clock]", 10*1000); //2min time out for callbacks
+
+TestEngine.addTest(true, presenceTest,                                         "UTC_clock_presence_test_P_001");
+TestEngine.addTest(true, testTZDate_001,                                               "UTC_clock_TZDate_P_001");
+TestEngine.addTest(true, testTZDate_002,                                               "UTC_clock_TZDate_P_002")
+TestEngine.addTest(true, checkValidParamTZDate,                                "UTC_clock_checkValidParamTZDate_P_001");
+TestEngine.addTest(true, testTimeDuration,                                     "UTC_clock_TimeDuration_P_001");
+TestEngine.addTest(true, checkValidParamTimeDuration,          "UTC_clock_checkValidParamTimeDuration_P_001");
+
+TestEngine.addTest(true, testGetCurrentDateTime,                       "UTC_clock_getCurrentDateTime_P_001");
+/*TestEngine.addTest(true, testsetCurrentDateTime,                     "UTC_clock_setCurrentDateTime_P_001");
+TestEngine.addTest(true, testsetCurrentDateTime_N,                     "UTC_clock_setCurrentDateTime_N_001");*/
+TestEngine.addTest(true, testGetLocalTimeZone,                         "UTC_clock_getLocalTimeZone_P_001");
+TestEngine.addTest(true, testGetAvailableTimeZones,                    "UTC_clock_getAvailableTimeZones_P_001");
+TestEngine.addTest(true, testGetDateFormat,                                    "UTC_clock_getDateFormat_P_001");
+TestEngine.addTest(true, testGetTimeFormat,                                    "UTC_clock_getTimeFormat_P_001");
+TestEngine.addTest(true, testIsLeapYear,                                       "UTC_clock_isLeapYear_P_001");
+TestEngine.addTest(true, testIsLeapYear_N,                                     "UTC_clock_isLeapYear_N_001");
+TestEngine.addTest(true, testDifference,                                       "UTC_clock_difference_P_001");
+TestEngine.addTest(true, testDifference_N,                                     "UTC_clock_difference_N_001");
+
+TestEngine.addTest(true, testGetDate,                                          "UTC_clock_getDate_P_001");
+TestEngine.addTest(true, testSetDate,                                          "UTC_clock_setDate_P_001");
+TestEngine.addTest(true, testGetDay,                                           "UTC_clock_getDay_P_001");
+TestEngine.addTest(true, testGetFullYear,                                      "UTC_clock_getFullYear_P_001");
+TestEngine.addTest(true, testSetFullYear,                                      "UTC_clock_setFullYear_P_001");
+TestEngine.addTest(true, testGetHours,                                         "UTC_clock_getHours_P_001");
+TestEngine.addTest(true, testSetHours,                                         "UTC_clock_setHours_P_001");
+TestEngine.addTest(true, testGetMilliseconds,                          "UTC_clock_getMilliseconds_P_001");
+TestEngine.addTest(true, testSetMilliseconds,                          "UTC_clock_setMilliseconds_P_001");
+TestEngine.addTest(true, testSetMinutes,                                       "UTC_clock_setMinutes_P_001");
+TestEngine.addTest(true, testGetMinute,                                                "UTC_clock_getMinute_P_001");
+TestEngine.addTest(true, testGetMonth,                                         "UTC_clock_getMonth_P_001");
+TestEngine.addTest(true, testSetMonth,                                         "UTC_clock_setMonth_P_001");
+TestEngine.addTest(true, testGetSeconds,                                       "UTC_clock_getSeconds_P_001");
+TestEngine.addTest(true, testSetSeconds,                                       "UTC_clock_setSeconds_P_001");
+TestEngine.addTest(true, testGetUTCDate,                                       "UTC_clock_getUTCDate_P_001");
+TestEngine.addTest(true, testSetUTCDate,                                       "UTC_clock_setUTCDate_P_001");
+TestEngine.addTest(true, testGetUTCDay,                                                "UTC_clock_getUTCDay_P_001");
+TestEngine.addTest(true, testGetUTCFullYear,                           "UTC_clock_getUTCFullYear_P_001");
+TestEngine.addTest(true, testSetUTCFullYear,                           "UTC_clock_setUTCFullYear_P_001");
+TestEngine.addTest(true, testGetUTCHours,                                      "UTC_clock_getUTCHours_P_001");
+TestEngine.addTest(true, testSetUTCHours,                                      "UTC_clock_setUTCHours_P_001");
+TestEngine.addTest(true, testGetUTCMilliseconds,                       "UTC_clock_getUTCMilliseconds_P_001");
+TestEngine.addTest(true, testSetUTCMilliseconds,                       "UTC_clock_setUTCMilliseconds_P_001");
+TestEngine.addTest(true, testGetUTCMinutes,                                    "UTC_clock_getUTCMinutes_P_001");
+TestEngine.addTest(true, testSetUTCMinutes,                                    "UTC_clock_setUTCMinutes_P_001");
+TestEngine.addTest(true, testGetUTCMonth,                                      "UTC_clock_getUTCMonth_P_001");
+TestEngine.addTest(true, testSetUTCMonth,                                      "UTC_clock_setUTCMonth_P_001");
+TestEngine.addTest(true, testGetUTCSeconds,                                    "UTC_clock_getUTCSeconds_P_001");
+TestEngine.addTest(true, testSetUTCSeconds,                                    "UTC_clock_setUTCSeconds_P_001");
+
+TestEngine.addTest(true, testGetTimezone,                                      "UTC_clock_getTimezone_P_001");
+TestEngine.addTest(true, testToTimezone,                                       "UTC_clock_toTimezone_P_001");
+TestEngine.addTest(true, testToTimezone_N,                                     "UTC_clock_toTimezone_N_001");
+TestEngine.addTest(true, testToLocalTimezone,                          "UTC_clock_toLocalTimezone_P_001");
+TestEngine.addTest(true, testToUTC,                                                    "UTC_clock_toUTC_P_001");
+TestEngine.addTest(true, testTimeDurationDifference,           "UTC_clock_timeDurationDifference_P_001");
+TestEngine.addTest(true, testTimeDurationDifference_N,         "UTC_clock_timeDurationDifference_N_001");
+TestEngine.addTest(true, testTimeDurationEqualsTo,                     "UTC_clock_timeDurationEqualsTo_P_001");
+TestEngine.addTest(true, testTimeDurationEqualsTo_N,           "UTC_clock_timeDurationEqualsTo_N_001");
+TestEngine.addTest(true, testTimeDurationLessThan,                     "UTC_clock_timeDurationLessThan_P_001");
+TestEngine.addTest(true, testTimeDurationLessThan_N,           "UTC_clock_timeDurationLessThan_N_001");
+TestEngine.addTest(true, testTimeDurationGreaterThan,          "UTC_clock_timeDurationGreaterThan_P_001");
+TestEngine.addTest(true, testTimeDurationGreaterThan_N,                "UTC_clock_timeDurationGreaterThan_N_001");
+
+TestEngine.addTest(true, testEqualsTo,                                         "UTC_clock_equalsTo_P_001");
+TestEngine.addTest(true, testEqualsTo_N,                                       "UTC_clock_equalsTo_N_001");
+TestEngine.addTest(true, testEarlierThan,                                      "UTC_clock_earlierThan_P_001");
+TestEngine.addTest(true, testEarlierThan_N,                                    "UTC_clock_earlierThan_N_001");
+TestEngine.addTest(true, testLaterThan,                                                "UTC_clock_laterThan_P_001");
+TestEngine.addTest(true, testLaterThan_N,                                      "UTC_clock_laterThan_N_001");
+TestEngine.addTest(true, testAddDuration,                                      "UTC_clock_addDuration_P_001");
+TestEngine.addTest(true, testAddDuration_N,                                    "UTC_clock_addDuration_N_001");
+
+TestEngine.addTest(true, testToLocaleDateString,                       "UTC_clock_toLocaleDateString_P_001");
+TestEngine.addTest(true, testToLocaleTimeString,                       "UTC_clock_toLocaleTimeString_P_001");
+TestEngine.addTest(true, testToLocaleString,                           "UTC_clock_toLocaleString_P_001");
+TestEngine.addTest(true, testToDateString,                                     "UTC_clock_toDateString_P_001");
+TestEngine.addTest(true, testToTimeString,                                     "UTC_clock_toTimeString_P_001")
+TestEngine.addTest(true, testToString,                                         "UTC_clock_toString_P_001");
+TestEngine.addTest(true, testSecondsFromUTC,                           "UTC_clock_secondsFromUTC_P_001");
+TestEngine.addTest(true, testGetTimezoneAbbreviation,                          "UTC_clock_GetTimezoneAbbreviation_P_001");
+TestEngine.addTest(true, testIsDST,                                                    "UTC_clock_isDST_P_001");
+
+TestEngine.addTest(true, UTC_setDateTimeChangeListener_P_001, "UTC_setDateTimeChangeListener_P_001");
+TestEngine.addTest(true, UTC_setDateTimeChangeListener_N_001, "UTC_setDateTimeChangeListener_N_001");
+TestEngine.addTest(true, UTC_unsetDateTimeChangeListener_P_001, "UTC_unsetDateTimeChangeListener_P_001");
+TestEngine.addTest(true, UTC_setTimezoneChangeListener_P_001, "UTC_setTimezoneChangeListener_P_001");
+TestEngine.addTest(true, UTC_setTimezoneChangeListener_N_001, "UTC_setTimezoneChangeListener_N_001");
+TestEngine.addTest(true, UTC_unsetTimezoneChangeListener_P_001, "UTC_unsetTimezoneChangeListener_P_001");
diff --git a/webWidgetTCT_device/test/utc/config/ConfigContent.js b/webWidgetTCT_device/test/utc/config/ConfigContent.js
new file mode 100755 (executable)
index 0000000..0ef8ccc
--- /dev/null
@@ -0,0 +1,66 @@
+
+TestEngine.setTestSuiteName("[Content]", 60 * 1000); //2min time out for callbacks
+
+TestEngine.addTest(true, UTC_content_getLocalMediaSource_P_001, "[Content] UTC_content_getLocalMediaSource_P_001");
+//--------------------------------------------------------------------------------TestEngine.addTest(true, test_getLocalMediaSourceN, "[Content] test_getLocalMediaSourceN");
+
+TestEngine.addTest(true, UTC_content_getDirectories_P_001, "[Content] UTC_content_getDirectories_P_001");
+TestEngine.addTest(true, UTC_content_getDirectories_N_001, "[Content] UTC_content_getDirectories_N_001");
+
+TestEngine.addTest(true, UTC_content_find_P_001, "[Content] UTC_content_find_P_001");
+TestEngine.addTest(true, UTC_content_find_P_002, "[Content] UTC_content_find_P_002");
+TestEngine.addTest(true, UTC_content_find_P_003, "[Content] UTC_content_find_P_003");
+TestEngine.addTest(true, UTC_content_find_P_004, "[Content] UTC_content_find_P_004");
+TestEngine.addTest(true, UTC_content_find_P_005, "[Content] UTC_content_find_P_005");
+TestEngine.addTest(true, UTC_content_find_P_006, "[Content] UTC_content_find_P_006");
+TestEngine.addTest(true, UTC_content_find_P_007, "[Content] UTC_content_find_P_007");
+TestEngine.addTest(true, UTC_content_find_P_008, "[Content] UTC_content_find_P_008");
+TestEngine.addTest(true, UTC_content_find_sort_by_name_001, "[Content] UTC_content_find_sort_by_name_001");
+
+TestEngine.addTest(true, UTC_content_find_N_001, "[Content] UTC_content_find_N_001");
+TestEngine.addTest(true, UTC_content_update_P_001, "[Content] UTC_content_update_P_001");
+TestEngine.addTest(true, UTC_content_update_P_002, "[Content] UTC_content_update_P_002");
+TestEngine.addTest(true, UTC_content_update_N_001, "[Content] UTC_content_update_N_001");
+TestEngine.addTest(true, UTC_content_updateBatch_P_001, "[Content] UTC_content_updateBatch_P_001");
+TestEngine.addTest(true, UTC_content_updateBatch_N_001, "[Content] UTC_content_updateBatch_N_001");
+
+TestEngine.addTest(true, UTC_content_scanFile_P_001, "[Content] UTC_content_scanFile_P_001");
+TestEngine.addTest(true, UTC_content_scanFile_P_002, "[Content] UTC_content_scanFile_P_002");
+TestEngine.addTest(true, UTC_content_scanFile_N_001, "[Content] UTC_content_scanFile_N_001");
+
+TestEngine.addTest(true, UTC_content_setChangeListener_P_001, "[Content] UTC_content_setChangeListener_P_001");
+TestEngine.addTest(true, UTC_content_setChangeListener_N_001, "[Content] UTC_content_setChangeListener_N_001");
+TestEngine.addTest(true, UTC_content_setChangeListener_N_002, "[Content] UTC_content_setChangeListener_N_002");
+TestEngine.addTest(true, UTC_content_unsetChangeListener_P_001, "[Content] UTC_content_unsetChangeListener_P_001");
+
+TestEngine.addTest(true, UTC_content_createPlaylist_P_001, "[Content] UTC_content_createPlaylist_P_001");
+TestEngine.addTest(true, UTC_content_createPlaylist_N_001, "[Content] UTC_content_createPlaylist_N_001");
+TestEngine.addTest(true, UTC_content_createPlaylist_N_002, "[Content] UTC_content_createPlaylist_N_002");
+TestEngine.addTest(true, UTC_content_getPlaylists_P_001, "[Content] UTC_content_getPlaylists_P_001");
+TestEngine.addTest(true, UTC_content_getPlaylists_N_001, "[Content] UTC_content_getPlaylists_N_001");
+TestEngine.addTest(true, UTC_content_removePlaylist_P_001, "[Content] UTC_content_removePlaylist_P_001");
+TestEngine.addTest(true, UTC_content_removePlaylist_N_001, "[Content] UTC_content_removePlaylist_N_001");
+TestEngine.addTest(true, UTC_content_removePlaylist_N_002, "[Content] UTC_content_removePlaylist_N_002");
+TestEngine.addTest(true, UTC_content_playlist_name_P_001, "[Content] UTC_content_update_P_001");
+TestEngine.addTest(true, UTC_content_playlist_name_N_001, "[Content] UTC_content_playlist_name_N_001");
+TestEngine.addTest(true, UTC_content_playlist_thumbnailURI_P_002, "[Content] UTC_content_playlist_thumbnailURI_P_002");
+TestEngine.addTest(true, UTC_content_playlist_thumbnailURI_N_002, "[Content] UTC_content_playlist_thumbnailURI_N_002");
+TestEngine.addTest(true, UTC_content_add_P_001, "[Content] UTC_content_add_P_001");
+TestEngine.addTest(true, UTC_content_add_N_001, "[Content] UTC_content_add_N_001");
+TestEngine.addTest(true, UTC_content_addBatch_P_001, "[Content] UTC_content_addBatch_P_001");
+TestEngine.addTest(true, UTC_content_addBatch_N_001, "[Content] UTC_content_addBatch_N_001");
+TestEngine.addTest(true, UTC_content_remove_P_001, "[Content] UTC_content_remove_P_001");
+TestEngine.addTest(true, UTC_content_remove_N_001, "[Content] UTC_content_remove_N_001");
+TestEngine.addTest(true, UTC_content_removeBatch_P_001, "[Content] UTC_content_removeBatch_P_001");
+TestEngine.addTest(true, UTC_content_removeBatch_N_001, "[Content] UTC_content_removeBatch_N_001");
+TestEngine.addTest(true, UTC_content_get_P_001, "[Content] UTC_content_get_P_001");
+TestEngine.addTest(true, UTC_content_get_N_001, "[Content] UTC_content_get_N_001");
+TestEngine.addTest(true, UTC_content_setOrder_P_001, "[Content] UTC_content_setOrder_P_001");
+TestEngine.addTest(true, UTC_content_setOrder_N_001, "[Content] UTC_content_setOrder_N_001");
+TestEngine.addTest(true, UTC_content_move_P_001, "[Content] UTC_content_move_P_001");
+TestEngine.addTest(true, UTC_content_move_P_002, "[Content] UTC_content_move_P_002");
+TestEngine.addTest(true, UTC_content_move_P_003, "[Content] UTC_content_move_P_003");
+TestEngine.addTest(true, UTC_content_move_P_004, "[Content] UTC_content_move_P_004");
+TestEngine.addTest(true, UTC_content_move_N_001, "[Content] UTC_content_move_N_001");
+
+TestEngine.addTest(true, UTC_content_Content_isFavorite, "[Content] UTC_content_Content_isFavorite");
diff --git a/webWidgetTCT_device/test/utc/config/ConfigFilesystem.js b/webWidgetTCT_device/test/utc/config/ConfigFilesystem.js
new file mode 100755 (executable)
index 0000000..3b745c4
--- /dev/null
@@ -0,0 +1,106 @@
+
+TestEngine.setTestSuiteName("[Filesystem]", 5*1000);
+TestEngine.addTest(true, UTC_filesystem_resolve_location_P_001,                                "UTC_filesystem_resolve_location_P_001");
+TestEngine.addTest(true, UTC_filesystem_resolve_mode_P_002,                                            "UTC_filesystem_resolve_mode_P_002");
+TestEngine.addTest(true, UTC_filesystem_getstorage_label_P_001,                                "UTC_filesystem_getstorage_label_P_001");
+TestEngine.addTest(true, UTC_filesystem_iststorage_P_001,                                              "UTC_filesystem_iststorage_P_001");
+TestEngine.addTest(true, UTC_filesystem_removestoragestaechangelistener_P_001,          "UTC_filesystem_removestoragestaechangelistener_P_001");
+TestEngine.addTest(true, UTC_filesystem_listfiles_P_001,                                               "UTC_filesystem_listfiles_P_001");
+TestEngine.addTest(true, UTC_filesystem_file_to_uri_P_001,                                                     "UTC_filesystem_file_to_uri_P_001");
+TestEngine.addTest(true, UTC_filesystem_file_listFiles_P_001,                                          "UTC_filesystem_file_listFiles_P_001");
+TestEngine.addTest(true, UTC_filesystem_file_listFiles_P_002,                                                  "UTC_filesystem_file_listFiles_P_002");
+TestEngine.addTest(true, UTC_filesystem_file_openStream_P_001,                                                         "UTC_filesystem_file_openStream_P_001");
+TestEngine.addTest(true, UTC_filesystem_file_openStream_P_002,                                                         "UTC_filesystem_file_openStream_P_002");
+TestEngine.addTest(true, UTC_filesystem_file_readAsText_P_001,                                                         "UTC_filesystem_file_readAsText_P_001");
+TestEngine.addTest(true, UTC_filesystem_file_readAsText_P_002,                                                         "UTC_filesystem_file_readAsText_P_002");
+TestEngine.addTest(true, UTC_filesystem_file_copyTo_P_001,                                                             "UTC_filesystem_file_copyTo_P_001");
+TestEngine.addTest(true, UTC_filesystem_file_copyTo_P_003,                                                             "UTC_filesystem_file_copyTo_P_003");
+TestEngine.addTest(true, UTC_filesystem_file_moveTo_P_001,                                                             "UTC_filesystem_file_moveTo_P_001");
+TestEngine.addTest(true, UTC_filesystem_file_moveTo_P_003,                                                             "UTC_filesystem_file_moveTo_P_003");
+TestEngine.addTest(true, UTC_filesystem_file_createFile_P_001,                                                         "UTC_filesystem_file_createFile_P_001");
+TestEngine.addTest(true, UTC_filesystem_file_createDirectory_P_001,                                    "UTC_filesystem_file_createDirectory_P_001");
+TestEngine.addTest(true, UTC_filesystem_file_resolve_P_001,                                                    "UTC_filesystem_file_resolve_P_001");
+TestEngine.addTest(true, UTC_filesystem_file_deleteDirectory_P_001,                                    "UTC_filesystem_file_deleteDirectory_P_001");
+TestEngine.addTest(true, UTC_filesystem_file_deleteDirectory_P_002,                                    "UTC_filesystem_file_deleteDirectory_P_002");
+TestEngine.addTest(true, UTC_filesystem_file_deleteFile_P_001,                                                         "UTC_filesystem_file_deleteFile_P_001");
+TestEngine.addTest(true, UTC_filesystem_file_deleteFile_P_002,                                                 "UTC_filesystem_file_deleteFile_P_002");
+TestEngine.addTest(true, UTC_filesystem_file_write_read_close_P_001,                                   "UTC_filesystem_file_write_read_close_P_001");
+TestEngine.addTest(true, UTC_filesystem_file_write_readBytes_P_001,                                    "UTC_filesystem_file_write_readBytes_P_001");
+TestEngine.addTest(true, UTC_filesystem_file_write_readBase64_P_001,                                   "UTC_filesystem_file_write_readBase64_P_001");
+TestEngine.addTest(true, UTC_filesystem_resolve_invalid_pram_success_callback_N_001,                                           "UTC_filesystem_resolve_invalid_pram_success_callback_N_001");
+TestEngine.addTest(true, UTC_filesystem_resolve_invalid_pram_error_callback_N_002,                                             "UTC_filesystem_resolve_invalid_pram_error_callback_N_002");
+TestEngine.addTest(true, UTC_filesystem_resolve_invalid_pram_location_N_003,                                                   "UTC_filesystem_resolve_invalid_pram_location_N_003");
+TestEngine.addTest(true, UTC_filesystem_resolve_invalid_pram_mode_N_004,                                                       "UTC_filesystem_resolve_invalid_pram_mode_N_004");
+TestEngine.addTest(true, UTC_filesystem_getstorage_invalid_pram_onsuccess_N_001,                                               "UTC_filesystem_getstorage_invalid_pram_onsuccess_N_001");
+TestEngine.addTest(true, UTC_filesystem_getstorage_invalid_pram_onerror_N_002,                                                 "UTC_filesystem_getstorage_invalid_pram_onerror_N_002");
+TestEngine.addTest(true, UTC_filesystem_getstorage_invalid_pram_label_N_003,                                                   "UTC_filesystem_getstorage_invalid_pram_label_N_003");
+TestEngine.addTest(true, UTC_filesystem_liststorages_invalid_pram_onsuccess_N_001,                                             "UTC_filesystem_liststorages_invalid_pram_onsuccess_N_001");
+TestEngine.addTest(true, UTC_filesystem_liststorages_invalid_pram_onerror_N_002,                                               "UTC_filesystem_liststorages_invalid_pram_onerror_N_002");
+TestEngine.addTest(true, UTC_filesystem_addstoragestatechangelistener_invalid_pram_onsuccess_N_001,            "UTC_filesystem_addstoragestatechangelistener_invalid_pram_onsuccess_N_001");
+TestEngine.addTest(true, UTC_filesystem_addstoragestatechangelistener_invalid_pram_onerror_N_002,              "UTC_filesystem_addstoragestatechangelistener_invalid_pram_onerror_N_002");
+TestEngine.addTest(true, UTC_filesystem_listfiles_invalid_pram_onsuccess_N_001,                                                "UTC_filesystem_listfiles_invalid_pram_onsuccess_N_001");
+TestEngine.addTest(true, UTC_filesystem_listfiles_invalid_pram_onerror_N_002,                                                  "UTC_filesystem_listfiles_invalid_pram_onerror_N_002");
+TestEngine.addTest(true, UTC_filesystem_file_openStream_error_successcb_invalid_param_N_001,                           "UTC_filesystem_file_openStream_error_successcb_invalid_param_N_001");
+TestEngine.addTest(true, UTC_filesystem_file_openStream_error_mode_invalid_param_N_002,                                "UTC_filesystem_file_openStream_error_mode_invalid_param_N_002");
+TestEngine.addTest(true, UTC_filesystem_file_openStream_error_encoding_invalid_param_N_003,                            "UTC_filesystem_file_openStream_error_encoding_invalid_param_N_003");
+TestEngine.addTest(true, UTC_filesystem_file_readAsText_error_successcb_invalid_param_N_001,                           "UTC_filesystem_file_readAsText_error_successcb_invalid_param_N_001");
+TestEngine.addTest(true, UTC_filesystem_file_readAsText_error_errorcb_invalid_param_N_002,                                     "UTC_filesystem_file_readAsText_error_errorcb_invalid_param_N_002");
+TestEngine.addTest(true, UTC_filesystem_file_readAsText_error_encoding_invalid_param_N_003,                            "UTC_filesystem_file_readAsText_error_encoding_invalid_param_N_003");
+TestEngine.addTest(true, UTC_filesystem_file_copyTo_error_successcb_invalid_param_N_001,                               "UTC_filesystem_file_copyTo_error_successcb_invalid_param_N_001");
+TestEngine.addTest(true, UTC_filesystem_file_copyTo_error_errorcb_invalid_param_N_002,                                         "UTC_filesystem_file_copyTo_error_errorcb_invalid_param_N_002");
+TestEngine.addTest(true, UTC_filesystem_file_copyTo_error_filepath_invalid_param_N_003,                                "UTC_filesystem_file_copyTo_error_filepath_invalid_param_N_003");
+TestEngine.addTest(true, UTC_filesystem_file_copyTo_error_destination_invalid_param_N_004,                             "UTC_filesystem_file_copyTo_error_destination_invalid_param_N_004");
+TestEngine.addTest(true, UTC_filesystem_file_moveTo_error_successcb_invalid_param_N_001,                               "UTC_filesystem_file_moveTo_error_successcb_invalid_param_N_001");
+TestEngine.addTest(true, UTC_filesystem_file_moveTo_error_errorcb_invalid_param_N_002,                                         "UTC_filesystem_file_moveTo_error_errorcb_invalid_param_N_002");
+TestEngine.addTest(true, UTC_filesystem_file_moveTo_error_originfile_invalid_param_N_003,                              "UTC_filesystem_file_moveTo_error_originfile_invalid_param_N_003");
+TestEngine.addTest(true, UTC_filesystem_file_resolve_error_dir_invalid_param_N_001,                                            "UTC_filesystem_file_resolve_error_dir_invalid_param_N_001");
+TestEngine.addTest(true, UTC_filesystem_file_deleteDirectory_error_successcb_invalid_param_N_001,              "UTC_filesystem_file_deleteDirectory_error_successcb_invalid_param_N_001");
+TestEngine.addTest(true, UTC_filesystem_file_deleteDirectory_error_errorcb_invalid_param_N_002,                "UTC_filesystem_file_deleteDirectory_error_errorcb_invalid_param_N_002");
+TestEngine.addTest(true, UTC_filesystem_file_deleteDirectory_error_dir_invalid_param_N_003,                            "UTC_filesystem_file_deleteDirectory_error_dir_invalid_param_N_003");
+TestEngine.addTest(true, UTC_filesystem_file_deleteFile_error_successcb_invalid_param_N_001,                           "UTC_filesystem_file_deleteFile_error_successcb_invalid_param_N_001");
+TestEngine.addTest(true, UTC_filesystem_file_deleteFile_error_errorcb_invalid_param_N_002,                                     "UTC_filesystem_file_deleteFile_error_errorcb_invalid_param_N_002");
+TestEngine.addTest(true, UTC_filesystem_file_deleteFile_error_dir_invalid_param_N_003,                                         "UTC_filesystem_file_deleteFile_error_dir_invalid_param_N_003");
+TestEngine.addTest(true, UTC_filesystem_file_read_error_count_invalid_param_N_001,                                                     "UTC_filesystem_file_read_error_count_invalid_param_N_001");
+TestEngine.addTest(true, UTC_filesystem_file_readBytes_error_invalid_param_N_001,                                              "UTC_filesystem_file_readBytes_error_invalid_param_N_001");
+TestEngine.addTest(true, UTC_filesystem_file_writeBytes_error_octect_invalid_param_N_001,                              "UTC_filesystem_file_writeBytes_error_octect_invalid_param_N_001");
+TestEngine.addTest(true, UTC_filesystem_remove_listener_invalid_param_N_001,                                                           "UTC_filesystem_remove_listener_invalid_param_N_001");
+// test with file:///tmp location
+TestEngine.addTest(true, UTC_filesystem_change_test_root_location,                                                     "UTC_filesystem_change_test_root_location");
+TestEngine.addTest(true, UTC_filesystem_shift_jis,                                                                     "UTC_filesystem_shft_jis");
+TestEngine.addTest(true, UTC_filesystem_resolve_location_P_001,                                "UTC_filesystem_resolve_location_P_001");
+TestEngine.addTest(true, UTC_filesystem_resolve_mode_P_002,                                            "UTC_filesystem_resolve_mode_P_002");
+TestEngine.addTest(true, UTC_filesystem_getstorage_label_P_001,                                "UTC_filesystem_getstorage_label_P_001");
+TestEngine.addTest(true, UTC_filesystem_iststorage_P_001,                                              "UTC_filesystem_iststorage_P_001");
+TestEngine.addTest(true, UTC_filesystem_removestoragestaechangelistener_P_001,          "UTC_filesystem_removestoragestaechangelistener_P_001");
+TestEngine.addTest(true, UTC_filesystem_file_to_uri_P_001,                                                     "UTC_filesystem_file_to_uri_P_001");
+TestEngine.addTest(true, UTC_filesystem_file_openStream_P_001,                                                         "UTC_filesystem_file_openStream_P_001");
+TestEngine.addTest(true, UTC_filesystem_file_openStream_P_002,                                                         "UTC_filesystem_file_openStream_P_002");
+TestEngine.addTest(true, UTC_filesystem_file_readAsText_P_001,                                                         "UTC_filesystem_file_readAsText_P_001");
+TestEngine.addTest(true, UTC_filesystem_file_readAsText_P_002,                                                         "UTC_filesystem_file_readAsText_P_002");
+TestEngine.addTest(true, UTC_filesystem_file_copyTo_P_001,                                                             "UTC_filesystem_file_copyTo_P_001");
+TestEngine.addTest(true, UTC_filesystem_file_copyTo_P_003,                                                             "UTC_filesystem_file_copyTo_P_003");
+TestEngine.addTest(true, UTC_filesystem_file_moveTo_P_001,                                                             "UTC_filesystem_file_moveTo_P_001");
+TestEngine.addTest(true, UTC_filesystem_file_moveTo_P_003,                                                             "UTC_filesystem_file_moveTo_P_003");
+TestEngine.addTest(true, UTC_filesystem_file_createFile_P_001,                                                         "UTC_filesystem_file_createFile_P_001");
+TestEngine.addTest(true, UTC_filesystem_file_createDirectory_P_001,                                    "UTC_filesystem_file_createDirectory_P_001");
+TestEngine.addTest(true, UTC_filesystem_file_resolve_P_001,                                                    "UTC_filesystem_file_resolve_P_001");
+TestEngine.addTest(true, UTC_filesystem_file_deleteDirectory_P_001,                                    "UTC_filesystem_file_deleteDirectory_P_001");
+TestEngine.addTest(true, UTC_filesystem_file_deleteDirectory_P_002,                                    "UTC_filesystem_file_deleteDirectory_P_002");
+TestEngine.addTest(true, UTC_filesystem_file_deleteFile_P_001,                                                         "UTC_filesystem_file_deleteFile_P_001");
+TestEngine.addTest(true, UTC_filesystem_file_deleteFile_P_002,                                                 "UTC_filesystem_file_deleteFile_P_002");
+TestEngine.addTest(true, UTC_filesystem_file_write_read_close_P_001,                                   "UTC_filesystem_file_write_read_close_P_001");
+TestEngine.addTest(true, UTC_filesystem_file_write_readBytes_P_001,                                    "UTC_filesystem_file_write_readBytes_P_001");
+TestEngine.addTest(true, UTC_filesystem_file_write_readBase64_P_001,                                   "UTC_filesystem_file_write_readBase64_P_001"); 
+TestEngine.addTest(true, UTC_filesystem_check_invalid_mode,
+       "UTC_filesystem_check_invalid_mode"); 
+TestEngine.addTest(true, UTC_filesystem_invoke_write_permission_api_with_FileOjbect_resolved_as_r,
+       "UTC_filesystem_invoke_write_permission_api_with_FileOjbect_resolved_as_r"); 
+TestEngine.addTest(true, UTC_filesystem_check_sdcard_resolve,
+       "UTC_filesystem_check_sdcard_resolve"); 
+//TestEngine.addTest(true, UTC_filesystem_stupid_resolve_delete,
+//     "UTC_filesystem_stupid_resolve_delete");
+TestEngine.addTest(true, UTC_filesystem_copyTo_moveTo_error,
+       "UTC_filesystem_copyTo_moveTo_error");
+// should be manual test
+//TestEngine.addTest(true, UTC_filesystem_permission_denied_error,
+       //"UTC_filesystem_permission_denied_error");
diff --git a/webWidgetTCT_device/test/utc/config/ConfigHumanActivityMonitor.js b/webWidgetTCT_device/test/utc/config/ConfigHumanActivityMonitor.js
new file mode 100755 (executable)
index 0000000..b226817
--- /dev/null
@@ -0,0 +1,38 @@
+
+/*
+ * 
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ * PROPRIETARY/CONFIDENTIAL
+ * 
+ * This software is the confidential and proprietary information of SAMSUNG 
+ * ELECTRONICS ("Confidential Information"). You agree and acknowledge that 
+ * this software is owned by Samsung and you shall not disclose such 
+ * Confidential Information and shall use it only in accordance with the terms 
+ * of the license agreement you entered into with SAMSUNG ELECTRONICS. SAMSUNG 
+ * make no representations or warranties about the suitability of the software, 
+ * either express or implied, including but not limited to the implied 
+ * warranties of merchantability, fitness for a particular purpose, or 
+ * non-infringement. SAMSUNG shall not be liable for any damages suffered by 
+ * licensee arising out of or related to this software.
+ * 
+ */
+
+
+TestEngine.setTestSuiteName("[HumanActivityMonitor]", 60*1000);  // 2 min time out for callbacks
+TestEngine.addTest(true, UTC_humanactivitymonitor_presence_P_001, "[Tizen][HumanActivityMonitor]UTC_humanactivitymonitor_presence_P_001");
+TestEngine.addTest(true, UTC_HumanActivityMonitor_PEDOMETER_Start_P_001, "[Tizen][HumanActivityMonitor] UTC_HumanActivityMonitor_PEDOMETER_Start_P_001");
+TestEngine.addTest(true, UTC_HumanActivityMonitor_PEDOMETER_Start_P_002, "[Tizen][HumanActivityMonitor] UTC_HumanActivityMonitor_PEDOMETER_Start_P_002");
+TestEngine.addTest(true, UTC_HumanActivityMonitor_PEDOMETER_Start_P_003, "[Tizen][HumanActivityMonitor] UTC_HumanActivityMonitor_PEDOMETER_Start_P_003");
+TestEngine.addTest(true, UTC_HumanActivityMonitor_PEDOMETER_Start_P_004, "[Tizen][HumanActivityMonitor] UTC_HumanActivityMonitor_PEDOMETER_Start_P_004");
+TestEngine.addTest(true, UTC_HumanActivityMonitor_Wrist_up_Start_P_001, "[Tizen][HumanActivityMonitor] UTC_HumanActivityMonitor_Wrist_up_Start_P_001");
+TestEngine.addTest(true, UTC_HumanActivityMonitor_Wrist_up_Start_P_002, "[Tizen][HumanActivityMonitor] UTC_HumanActivityMonitor_Wrist_up_Start_P_002");
+TestEngine.addTest(true, UTC_HumanActivityMonitor_HRM_Start_P_001, "[Tizen][HumanActivityMonitor] UTC_HumanActivityMonitor_HRM_Start_P_001");
+TestEngine.addTest(true, UTC_HumanActivityMonitor_HRM_Start_P_002, "[Tizen][HumanActivityMonitor] UTC_HumanActivityMonitor_HRM_Start_P_002");
+TestEngine.addTest(true, UTC_HumanActivityMonitor_PEDOMETER_Stop_P_001, "[Tizen][HumanActivityMonitor] UTC_HumanActivityMonitor_PEDOMETER_Stop_P_001");
+TestEngine.addTest(true, UTC_HumanActivityMonitor_PEDOMETER_Stop_P_002, "[Tizen][HumanActivityMonitor] UTC_HumanActivityMonitor_PEDOMETER_Stop_P_002");
+TestEngine.addTest(true, UTC_HumanActivityMonitor_Wrist_up_Stop_P_001, "[Tizen][HumanActivityMonitor] UTC_HumanActivityMonitor_Wrist_up_Stop_P_001");
+TestEngine.addTest(true, UTC_HumanActivityMonitor_Wrist_up_Stop_P_002, "[Tizen][HumanActivityMonitor] UTC_HumanActivityMonitor_Wrist_up_Stop_P_002");
+TestEngine.addTest(true, UTC_HumanActivityMonitor_HRM_Stop_P_001, "[Tizen][HumanActivityMonitor] UTC_HumanActivityMonitor_HRM_Stop_P_001");
+TestEngine.addTest(true, UTC_HumanActivityMonitor_HRM_Stop_P_002, "[Tizen][HumanActivityMonitor] UTC_HumanActivityMonitor_HRM_Stop_P_002");
+TestEngine.addTest(true, UTC_HumanActivityMonitor_PEDOMETER_getHumanActivityData_P_001, "[Tizen][HumanActivityMonitor] UTC_HumanActivityMonitor_PEDOMETER_getHumanActivityData_P_001");
+TestEngine.addTest(true, UTC_HumanActivityMonitor_PEDOMETER_getHumanActivityData_P_002, "[Tizen][HumanActivityMonitor] UTC_HumanActivityMonitor_PEDOMETER_getHumanActivityData_P_002");
diff --git a/webWidgetTCT_device/test/utc/config/ConfigMessagePort.js b/webWidgetTCT_device/test/utc/config/ConfigMessagePort.js
new file mode 100755 (executable)
index 0000000..9224c7d
--- /dev/null
@@ -0,0 +1,39 @@
+
+try {
+       (function() {
+               TestEngine.setTestSuiteName("[MessagePort]");
+
+               TestEngine.addTest(true,TestMessagePort.UTC_messagePort_MessagePortManager_P_001, "UTC_messagePort_MessagePortManager_P_001");
+               TestEngine.addTest(true,TestMessagePort.UTC_messagePort_requestLocalMessagePort_P_001, "UTC_messagePort_requestLocalMessagePort_P_001");
+               TestEngine.addTest(true,TestMessagePort.UTC_messagePort_requestLocalMessagePort_N_001, "UTC_messagePort_requestLocalMessagePort_N_001");
+               TestEngine.addTest(true,TestMessagePort.UTC_messagePort_requestTrustedLocalMessagePort_P_001, "UTC_messagePort_requestTrustedLocalMessagePort_P_001");
+               TestEngine.addTest(true,TestMessagePort.UTC_messagePort_requestTrustedLocalMessagePort_N_001, "UTC_messagePort_requestTrustedLocalMessagePort_N_001");
+               TestEngine.addTest(true,TestMessagePort.UTC_messagePort_requestRemoteMessagePort_P_001, "UTC_messagePort_requestRemoteMessagePort_P_001");
+               TestEngine.addTest(true,TestMessagePort.UTC_messagePort_requestRemoteMessagePort_N_001, "UTC_messagePort_requestRemoteMessagePort_N_001");
+               TestEngine.addTest(true,TestMessagePort.UTC_messagePort_requestTrustedRemoteMessagePort_P_001, "UTC_messagePort_requestTrustedRemoteMessagePort_P_001");
+               TestEngine.addTest(true,TestMessagePort.UTC_messagePort_requestTrustedRemoteMessagePort_N_001, "UTC_messagePort_requestTrustedRemoteMessagePort_N_001");
+               TestEngine.addTest(true,TestMessagePort.UTC_messagePort_LocalMessagePort_P_001, "UTC_messagePort_LocalMessagePort_P_001");
+               TestEngine.addTest(true,TestMessagePort.UTC_messagePort_RemoteMessagePort_P_001, "UTC_messagePort_RemoteMessagePort_P_001");
+               TestEngine.addTest(true,TestMessagePort.UTC_messagePort_sendMessage_P_001, "UTC_messagePort_sendMessage_P_001");
+               TestEngine.addTest(true,TestMessagePort.UTC_messagePort_sendMessage_N_001, "UTC_messagePort_sendMessage_N_001");
+               TestEngine.addTest(true,TestMessagePort.UTC_messagePort_addMessagePortListener_P_001, "UTC_messagePort_addMessagePortListener_P_001");
+               TestEngine.addTest(true,TestMessagePort.UTC_messagePort_addMessagePortListener_N_001, "UTC_messagePort_addMessagePortListener_N_001");
+               TestEngine.addTest(true,TestMessagePort.UTC_messagePort_removeMessagePortListener_P_001, "UTC_messagePort_removeMessagePortListener_P_001");
+               TestEngine.addTest(true,TestMessagePort.UTC_messagePort_removeMessagePortListener_N_001, "UTC_messagePort_removeMessagePortListener_N_001");
+               TestEngine.addTest(true,TestMessagePort.UTC_messagePort_receiveMessage_P_001, "UTC_messagePort_receiveMessage_P_001");
+               TestEngine.addTest(true,TestMessagePort.UTC_messagePort_receiveRepliedMessage_P_001, "UTC_messagePort_receiveRepliedMessage_P_001");
+               TestEngine.addTest(true,TestMessagePort.UTC_messagePort_TrustedLocalMessagePort_P_001, "UTC_messagePort_TrustedLocalMessagePort_P_001");
+               TestEngine.addTest(true,TestMessagePort.UTC_messagePort_TrustedRemoteMessagePort_P_001, "UTC_messagePort_TrustedRemoteMessagePort_P_001");
+               TestEngine.addTest(true,TestMessagePort.UTC_messagePort_sendMessageTrusted_P_001, "UTC_messagePort_sendMessageTrusted_P_001");
+               TestEngine.addTest(true,TestMessagePort.UTC_messagePort_sendMessageTrusted_N_001, "UTC_messagePort_sendMessageTrusted_N_001");
+               TestEngine.addTest(true,TestMessagePort.UTC_messagePort_addTrustedMessagePortListener_P_001, "UTC_messagePort_addTrustedMessagePortListener_P_001");
+               TestEngine.addTest(true,TestMessagePort.UTC_messagePort_addTrustedMessagePortListener_N_001, "UTC_messagePort_addTrustedMessagePortListener_N_001");
+               TestEngine.addTest(true,TestMessagePort.UTC_messagePort_removeTrustedMessagePortListener_P_001, "UTC_messagePort_removeTrustedMessagePortListener_P_001");
+               TestEngine.addTest(true,TestMessagePort.UTC_messagePort_removeTrustedMessagePortListener_N_001, "UTC_messagePort_removeTrustedMessagePortListener_N_001");
+               TestEngine.addTest(true,TestMessagePort.UTC_messagePort_receiveMessageTrusted_P_001, "UTC_messagePort_receiveMessageTrusted_P_001");
+               TestEngine.addTest(true,TestMessagePort.UTC_messagePort_receiveRepliedMessageTrusted_P_001, "UTC_messagePort_receiveRepliedMessageTrusted_P_001");
+       })();
+} catch (e) {
+       alert(e.name + ":" + e.message);
+}
+
diff --git a/webWidgetTCT_device/test/utc/config/ConfigPackage.js b/webWidgetTCT_device/test/utc/config/ConfigPackage.js
new file mode 100755 (executable)
index 0000000..dd7f78f
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ * PROPRIETARY/CONFIDENTIAL
+ *
+ * This software is the confidential and proprietary information of SAMSUNG
+ * ELECTRONICS ("Confidential Information"). You agree and acknowledge that
+ * this software is owned by Samsung and you shall not disclose such
+ * Confidential Information and shall use it only in accordance with the terms
+ * of the license agreement you entered into with SAMSUNG ELECTRONICS. SAMSUNG
+ * make no representations or warranties about the suitability of the software,
+ * either express or implied, including but not limited to the implied
+ * warranties of merchantability, fitness for a particular purpose, or
+ * non-infringement. SAMSUNG shall not be liable for any damages suffered by
+ * licensee arising out of or related to this software.
+ *
+ */
+
+
+TestEngine.setTestSuiteName("[Package]", 60 * 1000);
+
+TestEngine.addTest(true, UTC_package_presence_P_001,   "[Package]UTC_package_presence_P_001");
+
+//TestEngine.addTest(true, UTC_package_install_P_001,  "[Package]UTC_package_install_P_001");
+// Install operation is related to user confirm action. That makes some delay and that is why comment out below test.
+//TestEngine.addTest(true, UTC_package_install_P_002,  "[Package]UTC_package_install_P_002");
+//TestEngine.addTest(true, UTC_package_install_P_003,  "[Package]UTC_package_install_P_003");
+TestEngine.addTest(true, UTC_package_install_N_001,    "[Package]UTC_package_install_N_001");
+TestEngine.addTest(true, UTC_package_install_N_002,    "[Package]UTC_package_install_N_002");
+TestEngine.addTest(true, UTC_package_install_N_003,    "[Package]UTC_package_install_N_003");
+TestEngine.addTest(true, UTC_package_install_N_004,    "[Package]UTC_package_install_N_004");
+TestEngine.addTest(true, UTC_package_install_N_005,    "[Package]UTC_package_install_N_005");
+TestEngine.addTest(true, UTC_package_install_N_006,    "[Package]UTC_package_install_N_006");
+
+TestEngine.addTest(true, UTC_package_getPackagesInfo_P_001,    "[Package]UTC_package_getPackagesInfo_P_001");
+TestEngine.addTest(true, UTC_package_getPackagesInfo_P_002,    "[Package]UTC_package_getPackagesInfo_P_002");
+
+//TestEngine.addTest(true, UTC_package_uninstall_P_001,        "[Package]UTC_package_uninstall_P_001");
+//Install operation is related to user confirm action. That makes some delay and that is why comment out below test.
+//TestEngine.addTest(true, UTC_package_uninstall_P_002,        "[Package]UTC_package_uninstall_P_002");
+//TestEngine.addTest(true, UTC_package_uninstall_P_003,        "[Package]UTC_package_uninstall_P_003");
+TestEngine.addTest(true, UTC_package_uninstall_N_001,  "[Package]UTC_package_uninstall_N_001");
+TestEngine.addTest(true, UTC_package_uninstall_N_002,  "[Package]UTC_package_uninstall_N_002");
+TestEngine.addTest(true, UTC_package_uninstall_N_003,  "[Package]UTC_package_uninstall_N_003");
+TestEngine.addTest(true, UTC_package_uninstall_N_004,  "[Package]UTC_package_uninstall_N_004");
+TestEngine.addTest(true, UTC_package_uninstall_N_005,  "[Package]UTC_package_uninstall_N_005");
+TestEngine.addTest(true, UTC_package_uninstall_N_006,  "[Package]UTC_package_uninstall_N_006");
+
+TestEngine.addTest(true, UTC_package_getPackagesInfo_P_003,    "[Package]UTC_package_getPackagesInfo_P_003");
+TestEngine.addTest(true, UTC_package_getPackagesInfo_N_001,    "[Package]UTC_package_getPackagesInfo_N_001");
+
+TestEngine.addTest(true, UTC_package_getPackageInfo_P_001,     "[Package]UTC_package_getPackageInfo_P_001");
+TestEngine.addTest(true, UTC_package_getPackageInfo_P_002,     "[Package]UTC_package_getPackageInfo_P_002");
+TestEngine.addTest(true, UTC_package_getPackageInfo_P_003,     "[Package]UTC_package_getPackageInfo_P_003");
+TestEngine.addTest(true, UTC_package_getPackageInfo_N_001,     "[Package]UTC_package_getPackageInfo_N_001");
+
+TestEngine.addTest(true, UTC_package_setPackageInfoEventListener_P_001,        "[Package]UTC_package_setPackageInfoEventListener_P_001");
+//TestEngine.addTest(true, UTC_package_setPackageInfoEventListener_P_002,      "[Package]UTC_package_setPackageInfoEventListener_P_002");
+//TestEngine.addTest(true, UTC_package_setPackageInfoEventListener_P_003,      "[Package]UTC_package_setPackageInfoEventListener_P_003");
+TestEngine.addTest(true, UTC_package_setPackageInfoEventListener_P_004,        "[Package]UTC_package_setPackageInfoEventListener_P_004");
+TestEngine.addTest(true, UTC_package_setPackageInfoEventListener_P_005,        "[Package]UTC_package_setPackageInfoEventListener_P_005");
+TestEngine.addTest(true, UTC_package_setPackageInfoEventListener_P_006,        "[Package]UTC_package_setPackageInfoEventListener_P_006");
+TestEngine.addTest(true, UTC_package_setPackageInfoEventListener_N_001,        "[Package]UTC_package_setPackageInfoEventListener_N_001");
+
+TestEngine.addTest(true, UTC_package_unsetPackageInfoEventListener_P_001,      "[Package]UTC_package_unsetPackageInfoEventListener_P_001");
+
+TestEngine.addTest(true, UTC_package_field_PackageInformation_N_001,   "[Package]UTC_package_field_PackageInformation_N_001");
\ No newline at end of file
diff --git a/webWidgetTCT_device/test/utc/config/ConfigPower.js b/webWidgetTCT_device/test/utc/config/ConfigPower.js
new file mode 100755 (executable)
index 0000000..57539cb
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * 
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ * PROPRIETARY/CONFIDENTIAL
+ * 
+ * This software is the confidential and proprietary information of SAMSUNG 
+ * ELECTRONICS ("Confidential Information"). You agree and acknowledge that 
+ * this software is owned by Samsung and you shall not disclose such 
+ * Confidential Information and shall use it only in accordance with the terms 
+ * of the license agreement you entered into with SAMSUNG ELECTRONICS. SAMSUNG 
+ * make no representations or warranties about the suitability of the software, 
+ * either express or implied, including but not limited to the implied 
+ * warranties of merchantability, fitness for a particular purpose, or 
+ * non-infringement. SAMSUNG shall not be liable for any damages suffered by 
+ * licensee arising out of or related to this software.
+ * 
+ */
+
+//=============================================================================
+TestEngine.setTestSuiteName("[Power]", 30 * 1000);
+TestEngine.addTest(true, UTC_power_module_presence_P_001, "[Tizen][Power] UTC_power_module_presence_P_001");
+TestEngine.addTest(true, UTC_power_request_P_001, "[Tizen][Power] UTC_power_request_P_001");
+TestEngine.addTest(true, UTC_power_request_N_001, "[Tizen][Power] UTC_power_request_N_001");
+TestEngine.addTest(true, UTC_power_release_N_001, "[Tizen][Power] UTC_power_release_N_001");
+TestEngine.addTest(true, UTC_power_release_P_001, "[Tizen][Power] UTC_power_release_P_001");
+TestEngine.addTest(true, UTC_power_setScreenStateChangeListener_P_001, "[Tizen][Power] UTC_power_setScreenStateChangeListener_P_001");
+TestEngine.addTest(true, UTC_power_setScreenStateChangeListener_N_001, "[Tizen][Power] UTC_power_setScreenStateChangeListener_N_001");
+TestEngine.addTest(true, UTC_power_unsetScreenStateChangeListener_P_001, "[Tizen][Power] UTC_power_unsetScreenStateChangeListener_P_001");
+TestEngine.addTest(true, UTC_power_getScreenBrightness_P_001, "[Tizen][Power] UTC_power_getScreenBrightness_P_001");
+TestEngine.addTest(true, UTC_power_setScreenBrightness_P_001, "[Tizen][Power] UTC_power_setScreenBrightness_P_001");
+TestEngine.addTest(true, UTC_power_setScreenBrightness_N_001, "[Tizen][Power] UTC_power_setScreenBrightness_N_001");
+TestEngine.addTest(true, UTC_power_isScreenOn_P_001, "[Tizen][Power] UTC_power_isScreenOn_P_001");
+TestEngine.addTest(true, UTC_power_restoreScreenBrightness_P_001, "[Tizen][Power] UTC_power_restoreScreenBrightness_P_001");
+TestEngine.addTest(true, UTC_power_turnScreenOff_P_001, "[Tizen][Power] UTC_power_turnScreenOff_P_001");
+TestEngine.addTest(true, UTC_power_turnScreenOn_P_001, "[Tizen][Power] UTC_power_turnScreenOn_P_001");
+//=============================================================================
+
diff --git a/webWidgetTCT_device/test/utc/config/ConfigSystemSetting.js b/webWidgetTCT_device/test/utc/config/ConfigSystemSetting.js
new file mode 100755 (executable)
index 0000000..658989f
--- /dev/null
@@ -0,0 +1,53 @@
+
+/*
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ * PROPRIETARY/CONFIDENTIAL
+ *
+ * This software is the confidential and proprietary information of SAMSUNG
+ * ELECTRONICS ("Confidential Information"). You agree and acknowledge that
+ * this software is owned by Samsung and you shall not disclose such
+ * Confidential Information and shall use it only in accordance with the terms
+ * of the license agreement you entered into with SAMSUNG ELECTRONICS. SAMSUNG
+ * make no representations or warranties about the suitability of the software,
+ * either express or implied, including but not limited to the implied
+ * warranties of merchantability, fitness for a particular purpose, or
+ * non-infringement. SAMSUNG shall not be liable for any damages suffered by
+ * licensee arising out of or related to this software.
+ *
+ */
+
+/**
+ *             Tizen SystemSetting UNIT test
+ */
+
+TestEngine.setTestSuiteName(testModuleName, 30*1000); //2min time out for callbacks
+//TestEngine.addTest(true, presenceTest,       testModuleName + " presence test");
+
+//##### GetServiceMessage Vaild TC
+TestEngine.addTest(true, UTC_systemsetting_getProperty_P_001,  testModuleName + " UTC_systemsetting_getProperty_P_001");
+TestEngine.addTest(true, UTC_systemsetting_getProperty_P_002,  testModuleName + " UTC_systemsetting_getProperty_P_002");
+TestEngine.addTest(true, UTC_systemsetting_getProperty_P_003,  testModuleName + " UTC_systemsetting_getProperty_P_003");
+TestEngine.addTest(true, UTC_systemsetting_getProperty_P_004,  testModuleName + " UTC_systemsetting_getProperty_P_004");
+TestEngine.addTest(true, UTC_systemsetting_getProperty_P_005,  testModuleName + " UTC_systemsetting_getProperty_P_005");
+TestEngine.addTest(true, UTC_systemsetting_getProperty_P_006,  testModuleName + " UTC_systemsetting_getProperty_P_006");
+TestEngine.addTest(true, UTC_systemsetting_getProperty_N_001,  testModuleName + " UTC_systemsetting_getProperty_N_001");
+TestEngine.addTest(true, UTC_systemsetting_getProperty_N_002,  testModuleName + " UTC_systemsetting_getProperty_N_002");
+TestEngine.addTest(true, UTC_systemsetting_getProperty_N_003,  testModuleName + " UTC_systemsetting_getProperty_N_003");
+TestEngine.addTest(true, UTC_systemsetting_getProperty_N_004,  testModuleName + " UTC_systemsetting_getProperty_N_004");
+TestEngine.addTest(true, UTC_systemsetting_getProperty_N_005,  testModuleName + " UTC_systemsetting_getProperty_N_005");
+TestEngine.addTest(true, UTC_systemsetting_getProperty_N_006,  testModuleName + " UTC_systemsetting_getProperty_N_006");
+TestEngine.addTest(true, UTC_systemsetting_getProperty_N_007,  testModuleName + " UTC_systemsetting_getProperty_N_007");
+TestEngine.addTest(true, UTC_systemsetting_setProperty_P_001,  testModuleName + " UTC_systemsetting_setProperty_P_001");
+TestEngine.addTest(true, UTC_systemsetting_setProperty_P_002,  testModuleName + " UTC_systemsetting_setProperty_P_002");
+TestEngine.addTest(true, UTC_systemsetting_setProperty_P_003,  testModuleName + " UTC_systemsetting_setProperty_P_003");
+TestEngine.addTest(true, UTC_systemsetting_setProperty_P_004,  testModuleName + " UTC_systemsetting_setProperty_P_004");
+TestEngine.addTest(true, UTC_systemsetting_setProperty_P_005,  testModuleName + " UTC_systemsetting_setProperty_P_005");
+TestEngine.addTest(true, UTC_systemsetting_setProperty_P_006,  testModuleName + " UTC_systemsetting_setProperty_P_006");
+TestEngine.addTest(true, UTC_systemsetting_setProperty_N_001,  testModuleName + " UTC_systemsetting_setProperty_N_001");
+TestEngine.addTest(true, UTC_systemsetting_setProperty_N_002,  testModuleName + " UTC_systemsetting_setProperty_N_002");
+TestEngine.addTest(true, UTC_systemsetting_setProperty_N_003,  testModuleName + " UTC_systemsetting_setProperty_N_003");
+TestEngine.addTest(true, UTC_systemsetting_setProperty_N_004,  testModuleName + " UTC_systemsetting_setProperty_N_004");
+TestEngine.addTest(true, UTC_systemsetting_setProperty_N_005,  testModuleName + " UTC_systemsetting_setProperty_N_005");
+TestEngine.addTest(true, UTC_systemsetting_setProperty_N_006,  testModuleName + " UTC_systemsetting_setProperty_N_006");
+TestEngine.addTest(true, UTC_systemsetting_setProperty_N_007,  testModuleName + " UTC_systemsetting_setProperty_N_007");
\ No newline at end of file
diff --git a/webWidgetTCT_device/test/utc/config/ConfigSysteminfo.js b/webWidgetTCT_device/test/utc/config/ConfigSysteminfo.js
new file mode 100755 (executable)
index 0000000..948fb45
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * 
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ * PROPRIETARY/CONFIDENTIAL
+ * 
+ * This software is the confidential and proprietary information of SAMSUNG 
+ * ELECTRONICS ("Confidential Information"). You agree and acknowledge that 
+ * this software is owned by Samsung and you shall not disclose such 
+ * Confidential Information and shall use it only in accordance with the terms 
+ * of the license agreement you entered into with SAMSUNG ELECTRONICS. SAMSUNG 
+ * make no representations or warranties about the suitability of the software, 
+ * either express or implied, including but not limited to the implied 
+ * warranties of merchantability, fitness for a particular purpose, or 
+ * non-infringement. SAMSUNG shall not be liable for any damages suffered by 
+ * licensee arising out of or related to this software.
+ * 
+ */
+
+//==============================================================================================================================================
+
+TestEngine.setTestSuiteName("[Systeminfo]", 30*1000);
+
+TestEngine.addTest(true, UTC_systeminfo_presence_P_001, "UTC_systeminfo_presence_P_001");
+
+TestEngine.addTest(true, UTC_systeminfo_getCapabilities_P_001, "UTC_systeminfo_getCapabilites_P_001");
+TestEngine.addTest(true, UTC_systeminfo_getCapabilities_P_002, "UTC_systeminfo_getCapabilites_P_002");
+TestEngine.addTest(true, UTC_systeminfo_getCapabilities_P_003, "UTC_systeminfo_getCapabilites_P_003");
+
+TestEngine.addTest(true, UTC_systeminfo_getPropertyValue_P_001, "UTC_systeminfo_getPropertyValue_P_001");
+TestEngine.addTest(true, UTC_systeminfo_getPropertyValue_P_002, "UTC_systeminfo_getPropertyValue_P_002");
+TestEngine.addTest(true, UTC_systeminfo_getPropertyValue_P_003, "UTC_systeminfo_getPropertyValue_P_003");
+TestEngine.addTest(true, UTC_systeminfo_getPropertyValue_P_004, "UTC_systeminfo_getPropertyValue_P_004");
+TestEngine.addTest(true, UTC_systeminfo_getPropertyValue_P_005, "UTC_systeminfo_getPropertyValue_P_005");
+//TestEngine.addTest(true, UTC_systeminfo_getPropertyValue_P_006, "UTC_systeminfo_getPropertyValue_P_006");
+//TestEngine.addTest(true, UTC_systeminfo_getPropertyValue_P_007, "UTC_systeminfo_getPropertyValue_P_007");
+//TestEngine.addTest(true, UTC_systeminfo_getPropertyValue_P_008, "UTC_systeminfo_getPropertyValue_P_008");
+//TestEngine.addTest(true, UTC_systeminfo_getPropertyValue_P_009, "UTC_systeminfo_getPropertyValue_P_009");
+TestEngine.addTest(true, UTC_systeminfo_getPropertyValue_P_010, "UTC_systeminfo_getPropertyValue_P_010");
+//TestEngine.addTest(true, UTC_systeminfo_getPropertyValue_P_011, "UTC_systeminfo_getPropertyValue_P_011");
+TestEngine.addTest(true, UTC_systeminfo_getPropertyValue_P_012, "UTC_systeminfo_getPropertyValue_P_012");
+
+TestEngine.addTest(true, UTC_systeminfo_getPropertyValue_N_001, "UTC_systeminfo_getPropertyValue_N_001");
+TestEngine.addTest(true, UTC_systeminfo_getPropertyValue_N_002, "UTC_systeminfo_getPropertyValue_N_002");
+TestEngine.addTest(true, UTC_systeminfo_getPropertyValue_N_003, "UTC_systeminfo_getPropertyValue_N_003");
+TestEngine.addTest(true, UTC_systeminfo_getPropertyValue_N_004, "UTC_systeminfo_getPropertyValue_N_004");
+TestEngine.addTest(true, UTC_systeminfo_getPropertyValue_N_005, "UTC_systeminfo_getPropertyValue_N_005");
+TestEngine.addTest(true, UTC_systeminfo_getPropertyValue_N_006, "UTC_systeminfo_getPropertyValue_N_006");
+TestEngine.addTest(true, UTC_systeminfo_getPropertyValue_N_007, "UTC_systeminfo_getPropertyValue_N_007");
+TestEngine.addTest(true, UTC_systeminfo_getPropertyValue_N_008, "UTC_systeminfo_getPropertyValue_N_008");
+TestEngine.addTest(true, UTC_systeminfo_getPropertyValue_N_009, "UTC_systeminfo_getPropertyValue_N_009");
+TestEngine.addTest(true, UTC_systeminfo_getPropertyValue_N_010, "UTC_systeminfo_getPropertyValue_N_010");
+TestEngine.addTest(true, UTC_systeminfo_getPropertyValue_N_011, "UTC_systeminfo_getPropertyValue_N_011");
+TestEngine.addTest(true, UTC_systeminfo_getPropertyValue_N_012, "UTC_systeminfo_getPropertyValue_N_012");
+TestEngine.addTest(true, UTC_systeminfo_getPropertyValue_N_013, "UTC_systeminfo_getPropertyValue_N_013");
+TestEngine.addTest(true, UTC_systeminfo_getPropertyValue_N_014, "UTC_systeminfo_getPropertyValue_N_014");
+TestEngine.addTest(true, UTC_systeminfo_getPropertyValue_N_015, "UTC_systeminfo_getPropertyValue_N_015");
+TestEngine.addTest(true, UTC_systeminfo_getPropertyValue_N_016, "UTC_systeminfo_getPropertyValue_N_016");
+TestEngine.addTest(true, UTC_systeminfo_getPropertyValue_N_017, "UTC_systeminfo_getPropertyValue_N_017");
+TestEngine.addTest(true, UTC_systeminfo_getPropertyValue_N_018, "UTC_systeminfo_getPropertyValue_N_018");
+TestEngine.addTest(true, UTC_systeminfo_getPropertyValue_N_019, "UTC_systeminfo_getPropertyValue_N_019");
+
+TestEngine.addTest(true, UTC_systeminfo_addPropertyValueChangeListener_P_001, "UTC_systeminfo_addPropertyValueChangeListener_P_001");
+TestEngine.addTest(true, UTC_systeminfo_addPropertyValueChangeListener_P_002, "UTC_systeminfo_addPropertyValueChangeListener_P_002");
+TestEngine.addTest(true, UTC_systeminfo_addPropertyValueChangeListener_P_003, "UTC_systeminfo_addPropertyValueChangeListener_P_003");
+TestEngine.addTest(true, UTC_systeminfo_addPropertyValueChangeListener_P_004, "UTC_systeminfo_addPropertyValueChangeListener_P_004");
+//TestEngine.addTest(true, UTC_systeminfo_addPropertyValueChangeListener_P_005, "UTC_systeminfo_addPropertyValueChangeListener_P_005");
+//TestEngine.addTest(true, UTC_systeminfo_addPropertyValueChangeListener_P_006, "UTC_systeminfo_addPropertyValueChangeListener_P_006");
+//TestEngine.addTest(true, UTC_systeminfo_addPropertyValueChangeListener_P_007, "UTC_systeminfo_addPropertyValueChangeListener_P_007");
+//TestEngine.addTest(true, UTC_systeminfo_addPropertyValueChangeListener_P_008, "UTC_systeminfo_addPropertyValueChangeListener_P_008");
+//TestEngine.addTest(true, UTC_systeminfo_addPropertyValueChangeListener_P_009, "UTC_systeminfo_addPropertyValueChangeListener_P_009");
+TestEngine.addTest(true, UTC_systeminfo_addPropertyValueChangeListener_P_010, "UTC_systeminfo_addPropertyValueChangeListener_P_010");
+//TestEngine.addTest(true, UTC_systeminfo_addPropertyValueChangeListener_P_011, "UTC_systeminfo_addPropertyValueChangeListener_P_011");
+
+TestEngine.addTest(true, UTC_systeminfo_addPropertyValueChangeListener_N_001, "UTC_systeminfo_addPropertyValueChangeListener_N_001");
+TestEngine.addTest(true, UTC_systeminfo_addPropertyValueChangeListener_N_002, "UTC_systeminfo_addPropertyValueChangeListener_N_002");
+TestEngine.addTest(true, UTC_systeminfo_addPropertyValueChangeListener_N_003, "UTC_systeminfo_addPropertyValueChangeListener_N_003");
+TestEngine.addTest(true, UTC_systeminfo_addPropertyValueChangeListener_N_004, "UTC_systeminfo_addPropertyValueChangeListener_N_004");
+TestEngine.addTest(true, UTC_systeminfo_addPropertyValueChangeListener_N_005, "UTC_systeminfo_addPropertyValueChangeListener_N_005");
+TestEngine.addTest(true, UTC_systeminfo_addPropertyValueChangeListener_N_006, "UTC_systeminfo_addPropertyValueChangeListener_N_006");
+TestEngine.addTest(true, UTC_systeminfo_addPropertyValueChangeListener_N_007, "UTC_systeminfo_addPropertyValueChangeListener_N_007");
+TestEngine.addTest(true, UTC_systeminfo_addPropertyValueChangeListener_N_008, "UTC_systeminfo_addPropertyValueChangeListener_N_008");
+TestEngine.addTest(true, UTC_systeminfo_addPropertyValueChangeListener_N_009, "UTC_systeminfo_addPropertyValueChangeListener_N_009");
+TestEngine.addTest(true, UTC_systeminfo_addPropertyValueChangeListener_N_010, "UTC_systeminfo_addPropertyValueChangeListener_N_010");
+TestEngine.addTest(true, UTC_systeminfo_addPropertyValueChangeListener_N_011, "UTC_systeminfo_addPropertyValueChangeListener_N_011");
+TestEngine.addTest(true, UTC_systeminfo_addPropertyValueChangeListener_N_012, "UTC_systeminfo_addPropertyValueChangeListener_N_012");
+TestEngine.addTest(true, UTC_systeminfo_addPropertyValueChangeListener_N_013, "UTC_systeminfo_addPropertyValueChangeListener_N_013");
+TestEngine.addTest(true, UTC_systeminfo_addPropertyValueChangeListener_N_014, "UTC_systeminfo_addPropertyValueChangeListener_N_014");
+TestEngine.addTest(true, UTC_systeminfo_addPropertyValueChangeListener_N_015, "UTC_systeminfo_addPropertyValueChangeListener_N_015");
+TestEngine.addTest(true, UTC_systeminfo_addPropertyValueChangeListener_N_016, "UTC_systeminfo_addPropertyValueChangeListener_N_016");
+TestEngine.addTest(true, UTC_systeminfo_addPropertyValueChangeListener_N_017, "UTC_systeminfo_addPropertyValueChangeListener_N_017");
+TestEngine.addTest(true, UTC_systeminfo_addPropertyValueChangeListener_N_018, "UTC_systeminfo_addPropertyValueChangeListener_N_018");
+
+TestEngine.addTest(true, UTC_systeminfo_removePropertyValueChangeListener_P_001, "UTC_systeminfo_removePropertyValueChangeListener_P_001");
+//TestEngine.addTest(true, UTC_systeminfo_removePropertyValueChangeListener_P_002, "UTC_systeminfo_removePropertyValueChangeListener_P_002");
+//TestEngine.addTest(true, UTC_systeminfo_removePropertyValueChangeListener_P_003, "UTC_systeminfo_removePropertyValueChangeListener_P_003");
+
+TestEngine.addTest(true, UTC_systeminfo_removePropertyValueChangeListener_N_001, "UTC_systeminfo_removePropertyValueChangeListener_N_001");
+TestEngine.addTest(true, UTC_systeminfo_removePropertyValueChangeListener_N_002, "UTC_systeminfo_removePropertyValueChangeListener_N_002");
+TestEngine.addTest(true, UTC_systeminfo_removePropertyValueChangeListener_N_003, "UTC_systeminfo_removePropertyValueChangeListener_N_003");
+TestEngine.addTest(true, UTC_systeminfo_removePropertyValueChangeListener_N_004, "UTC_systeminfo_removePropertyValueChangeListener_N_004");
+TestEngine.addTest(true, UTC_systeminfo_removePropertyValueChangeListener_N_005, "UTC_systeminfo_removePropertyValueChangeListener_N_005");
+TestEngine.addTest(true, UTC_systeminfo_removePropertyValueChangeListener_N_006, "UTC_systeminfo_removePropertyValueChangeListener_N_006");
\ No newline at end of file
diff --git a/webWidgetTCT_device/test/utc/tests/ClockSettingCIS.js b/webWidgetTCT_device/test/utc/tests/ClockSettingCIS.js
new file mode 100755 (executable)
index 0000000..006ee36
--- /dev/null
@@ -0,0 +1,31 @@
+
+/*
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ * PROPRIETARY/CONFIDENTIAL
+ *
+ * This software is the confidential and proprietary information of SAMSUNG
+ * ELECTRONICS ("Confidential Information"). You agree and acknowledge that
+ * this software is owned by Samsung and you shall not disclose such
+ * Confidential Information and shall use it only in accordance with the terms
+ * of the license agreement you entered into with SAMSUNG ELECTRONICS. SAMSUNG
+ * make no representations or warranties about the suitability of the software,
+ * either express or implied, including but not limited to the implied
+ * warranties of merchantability, fitness for a particular purpose, or
+ * non-infringement. SAMSUNG shall not be liable for any damages suffered by
+ * licensee arising out of or related to this software.
+ *
+ */
+
+/**
+ *     TimeUtil UNIT test
+ *     @author sangtai.kim, jihwa.park
+ */
+var expectedDefaultDateFormat = "D, d M y 'г'.";
+var expectedShortDateFormat = "d.m.y";
+var expectedDefaultTimeFormat = "h:m:s";
+var expectedLocaleDateString = "пятница, 11 ноября 2011 г.";
+var expectedLocaleTimeString = "4:55:54";
+var expectedLocaleString = "пятница, 11 ноября 2011 г. 4:55:54";
+var expectedLocalTimeZone = "TZID";
+
diff --git a/webWidgetTCT_device/test/utc/tests/ClockSettingCommon.js b/webWidgetTCT_device/test/utc/tests/ClockSettingCommon.js
new file mode 100755 (executable)
index 0000000..99c7282
--- /dev/null
@@ -0,0 +1,35 @@
+
+/*
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ * PROPRIETARY/CONFIDENTIAL
+ *
+ * This software is the confidential and proprietary information of SAMSUNG
+ * ELECTRONICS ("Confidential Information"). You agree and acknowledge that
+ * this software is owned by Samsung and you shall not disclose such
+ * Confidential Information and shall use it only in accordance with the terms
+ * of the license agreement you entered into with SAMSUNG ELECTRONICS. SAMSUNG
+ * make no representations or warranties about the suitability of the software,
+ * either express or implied, including but not limited to the implied
+ * warranties of merchantability, fitness for a particular purpose, or
+ * non-infringement. SAMSUNG shall not be liable for any damages suffered by
+ * licensee arising out of or related to this software.
+ *
+ */
+
+/**
+ *     TimeUtil UNIT test
+ *     @author sangtai.kim, jihwa.park
+ */
+var expectedDefaultDateFormat = "D, d M y";
+var expectedShortDateFormat = "d/m/y";
+var expectedDefaultTimeFormat_12 = "h:m:s ap";
+var expectedDefaultTimeFormat_24 = "h:m:s";
+var expectedLocaleDateString = "Friday, 11 November 2011";
+var expectedLocaleTimeString_12 = "4:55:54 AM";
+var expectedLocaleTimeString_24 = "04:55:54";
+var expectedLocaleString_12 = "Friday, 11 November 2011 4:55:54 AM";
+var expectedLocaleString_24 = "Friday, 11 November 2011 04:55:54";
+var expectedLocalTimeZone = "TZID";
+
+
diff --git a/webWidgetTCT_device/test/utc/tests/ClockSettingDCM.js b/webWidgetTCT_device/test/utc/tests/ClockSettingDCM.js
new file mode 100755 (executable)
index 0000000..2ac2dec
--- /dev/null
@@ -0,0 +1,31 @@
+
+/*
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ * PROPRIETARY/CONFIDENTIAL
+ *
+ * This software is the confidential and proprietary information of SAMSUNG
+ * ELECTRONICS ("Confidential Information"). You agree and acknowledge that
+ * this software is owned by Samsung and you shall not disclose such
+ * Confidential Information and shall use it only in accordance with the terms
+ * of the license agreement you entered into with SAMSUNG ELECTRONICS. SAMSUNG
+ * make no representations or warranties about the suitability of the software,
+ * either express or implied, including but not limited to the implied
+ * warranties of merchantability, fitness for a particular purpose, or
+ * non-infringement. SAMSUNG shall not be liable for any damages suffered by
+ * licensee arising out of or related to this software.
+ *
+ */
+
+/**
+ *     TimeUtil UNIT test
+ *     @author sangtai.kim, jihwa.park
+ */
+var expectedDefaultDateFormat = "y年m月d日(D)";
+var expectedShortDateFormat = "y/m/d";
+var expectedDefaultTimeFormat = "aph:m:s";
+var expectedLocaleDateString = "2011年11月11日(金曜日)";
+var expectedLocaleTimeString = "午前4:55:54";
+var expectedLocaleString = "2011年11月11日(金曜日) 午前4:55:54";
+var expectedLocalTimeZone = "TZID";
+
diff --git a/webWidgetTCT_device/test/utc/tests/ClockSettingORA.js b/webWidgetTCT_device/test/utc/tests/ClockSettingORA.js
new file mode 100755 (executable)
index 0000000..4a7c297
--- /dev/null
@@ -0,0 +1,31 @@
+
+/*
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ * PROPRIETARY/CONFIDENTIAL
+ *
+ * This software is the confidential and proprietary information of SAMSUNG
+ * ELECTRONICS ("Confidential Information"). You agree and acknowledge that
+ * this software is owned by Samsung and you shall not disclose such
+ * Confidential Information and shall use it only in accordance with the terms
+ * of the license agreement you entered into with SAMSUNG ELECTRONICS. SAMSUNG
+ * make no representations or warranties about the suitability of the software,
+ * either express or implied, including but not limited to the implied
+ * warranties of merchantability, fitness for a particular purpose, or
+ * non-infringement. SAMSUNG shall not be liable for any damages suffered by
+ * licensee arising out of or related to this software.
+ *
+ */
+
+/**
+ *     TimeUtil UNIT test
+ *     @author sangtai.kim, jihwa.park
+ */
+var expectedDefaultDateFormat = "D d M y";
+var expectedShortDateFormat = "d/m/y";
+var expectedDefaultTimeFormat = "h:m:s";
+var expectedLocaleDateString = "vendredi 11 novembre 2011";
+var expectedLocaleTimeString = "04:55:54";
+var expectedLocaleString = "vendredi 11 novembre 2011 04:55:54";
+var expectedLocalTimeZone = "TZID";
+
diff --git a/webWidgetTCT_device/test/utc/tests/TestAlarm.js b/webWidgetTCT_device/test/utc/tests/TestAlarm.js
new file mode 100755 (executable)
index 0000000..4c764e1
--- /dev/null
@@ -0,0 +1,710 @@
+/*
+ * 
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ * PROPRIETARY/CONFIDENTIAL
+ * 
+ * This software is the confidential and proprietary information of SAMSUNG 
+ * ELECTRONICS ("Confidential Information"). You agree and acknowledge that 
+ * this software is owned by Samsung and you shall not disclose such 
+ * Confidential Information and shall use it only in accordance with the terms 
+ * of the license agreement you entered into with SAMSUNG ELECTRONICS. SAMSUNG 
+ * make no representations or warranties about the suitability of the software, 
+ * either express or implied, including but not limited to the implied 
+ * warranties of merchantability, fitness for a particular purpose, or 
+ * non-infringement. SAMSUNG shall not be liable for any damages suffered by 
+ * licensee arising out of or related to this software.
+ * 
+ */
+
+
+var alarmManager = tizen.alarm;
+
+var TYPE_MISMATCH_ERR = 'TypeMismatchError';
+var INVALID_VALUES_ERR = 'InvalidValuesError';
+var NOT_SUPPORTED_ERR = 'NotSupportedError';
+var NOT_FOUND_ERR = 'NotFoundError';
+//var UNKNOWN_ERR = 'UnknownError';
+//var PERMISSION_DENIED_ERR = 'PermissionDeniedError';
+
+function UTC_alarm_constants_P_001() {
+       TestEngine.log("UTC_alarm_constants_P_001");
+       TestEngine.assertEqual("tizen.alarm.PERIOD_MINUTE ", 60,  alarmManager.PERIOD_MINUTE );
+       TestEngine.assertEqual("tizen.alarm.PERIOD_HOUR ", 3600,  alarmManager.PERIOD_HOUR );
+       TestEngine.assertEqual("tizen.alarm.PERIOD_DAY ", 86400,  alarmManager.PERIOD_DAY );
+       TestEngine.assertEqual("tizen.alarm.PERIOD_WEEK ", 604800,  alarmManager.PERIOD_WEEK );
+}
+
+function UTC_alarm_presence_P_001()
+{
+       TestEngine.log("UTC_alarm_presence_P_001");
+       try {
+               TestEngine.test("Tizen presence", tizen);
+               TestEngine.test("application presence", tizen.alarm);
+               TestEngine.testPresence("add", tizen.alarm.add);
+               TestEngine.testPresence("remove", tizen.alarm.remove);
+               TestEngine.testPresence("removeAll", tizen.alarm.removeAll);
+               TestEngine.testPresence("get", tizen.alarm.get);
+               TestEngine.testPresence("getAll", tizen.alarm.getAll);
+               TestEngine.testPresence(60, tizen.alarm.PERIOD_MINUTE);
+               TestEngine.testPresence(3600, tizen.alarm.PERIOD_HOUR);
+               TestEngine.testPresence(86400, tizen.alarm.PERIOD_DAY);
+               TestEngine.testPresence(604800, tizen.alarm.PERIOD_WEEK);
+       } catch (err) {
+               TestEngine.test("[Alarm] test_application_presence_p error : " + err.name);
+               TestEngine.test("", false);
+       }
+}
+
+function UTC_alarm_AlarmAbsolute_Constructor_P_001()
+{
+       TestEngine.log("UTC_alarm_AlarmAbsolute_Constructor_P_001");
+       var myDate = new Date();
+       myDate.setSeconds(myDate.getSeconds()+60);
+       var alarm1, alarm2, alarm3, alarm4;
+       try {
+               alarm1 = new tizen.AlarmAbsolute(myDate);
+               alarm2 = new tizen.AlarmAbsolute(myDate, 10);
+               alarm3 = new tizen.AlarmAbsolute(myDate, ["SA", "SU"]);
+               alarm4 = new tizen.AlarmAbsolute(myDate, ["SA", "SU"], 10);
+       } catch(err) {
+               TestEngine.test("Exception : err.name [" + err.name + "] err.msg[" + err.message + "]", false);
+       }
+
+       TestEngine.test("new tizen.AlarmAbsolute()  result = ", !isUndefined(alarm1));
+       TestEngine.test("new tizen.AlarmAbsolute()  result = ", !isUndefined(alarm2));
+       TestEngine.test("new tizen.AlarmAbsolute()  result = ", !isUndefined(alarm3));
+       TestEngine.test("new tizen.AlarmAbsolute()  result = ", !isUndefined(alarm4));
+
+       alarmManager.removeAll();
+}
+
+function UTC_alarm_AlarmAbsolute_Constructor_N_004() {
+       TestEngine.log("UTC_alarm_AlarmAbsolute_Constructor_N_004");
+       var alarm;
+       var myDate = new Date();
+       myDate.setSeconds(myDate.getSeconds()+60);
+       try {
+               // set period as -1
+               alarm = new tizen.AlarmAbsolute(myDate, -1);
+       } catch(err) {
+               TestEngine.test("Exception : new tizen.AlarmAbsolute() err.name [" + err.name + "] err.msg[" + err.message + "]", true);
+               alarmManager.removeAll();
+               return;
+       }
+       TestEngine.test("Exception is not occured", false);
+       alarmManager.removeAll();
+}
+
+function UTC_alarm_AlarmAbsolute_Constructor_N_005() {
+       TestEngine.log("UTC_alarm_AlarmAbsolute_Constructor_N_005");
+       var alarm;
+       var myDate = new Date();
+       myDate.setSeconds(myDate.getSeconds()+60);
+       try {
+               alarm = new tizen.AlarmAbsolute(myDate, undefined);
+       } catch(err) {
+               TestEngine.test("Exception : new tizen.AlarmAbsolute() err.name [" + err.name + "] err.msg[" + err.message + "]", true);
+               alarmManager.removeAll();
+               return;
+       }
+       TestEngine.test("Exception is not occured", false);
+       alarmManager.removeAll();
+}
+
+function UTC_alarm_AlarmAbsolute_Constructor_N_006() {
+       TestEngine.log("UTC_alarm_AlarmAbsolute_Constructor_N_006");
+       var alarm;
+       var myDate = new Date();
+       myDate.setSeconds(myDate.getSeconds()+60);
+       try {
+               alarm = new tizen.AlarmAbsolute(myDate, null);
+       } catch(err) {
+               TestEngine.test("Exception : new tizen.AlarmAbsolute() err.name [" + err.name + "] err.msg[" + err.message + "]", true);
+               alarmManager.removeAll();
+               return;
+       }
+       TestEngine.test("Exception is not occured", false);
+       alarmManager.removeAll();
+}
+
+function UTC_alarm_AlarmAbsolute_Constructor_N_007() {
+       TestEngine.log("UTC_alarm_AlarmAbsolute_Constructor_N_007");
+       var alarm;
+       var myDate = new Date();
+       myDate.setSeconds(myDate.getSeconds()+60);
+       try {
+               alarm = new tizen.AlarmAbsolute(1, 10);
+       } catch(err) {
+               TestEngine.test("Exception : new tizen.AlarmAbsolute() err.name [" + err.name + "] err.msg[" + err.message + "]", true);
+               alarmManager.removeAll();
+               return;
+       }
+       TestEngine.test("Exception is not occured", false);
+       alarmManager.removeAll();
+}
+
+function UTC_alarm_AlarmAbsolute_Constructor_N_008() {
+       TestEngine.log("UTC_alarm_AlarmAbsolute_Constructor_N_008");
+       var alarm;
+       var myDate = new Date();
+
+       myDate.setSeconds(myDate.getSeconds()+60);
+       try {
+               alarm = new tizen.AlarmAbsolute(undefined, 10);
+       } catch(err) {
+               TestEngine.test("Exception : new tizen.AlarmAbsolute() err.name [" + err.name + "] err.msg[" + err.message + "]", true);
+               alarmManager.removeAll();
+               return;
+       }
+       TestEngine.test("Exception is not occured", false);
+       alarmManager.removeAll();
+}
+
+function UTC_alarm_AlarmAbsolute_Constructor_N_009() {
+       TestEngine.log("UTC_alarm_AlarmAbsolute_Constructor_N_009");
+       var alarm;
+       var myDate = new Date();
+       myDate.setSeconds(myDate.getSeconds()+60);
+       try {
+               alarm = new tizen.AlarmAbsolute(null, 10);
+       } catch(err) {
+               TestEngine.test("Exception : new tizen.AlarmAbsolute() err.name [" + err.name + "] err.msg[" + err.message + "]", true);
+               alarmManager.removeAll();
+               return;
+       }
+       TestEngine.test("Exception is not occured", false);
+       alarmManager.removeAll();
+}
+
+function UTC_alarm_AlarmAbsolute_date_P_001() {
+       TestEngine.log("UTC_alarm_AlarmAbsolute_date_P_001");
+       var myDate = new Date();
+       myDate.setMilliseconds(0);
+       myDate.setSeconds(myDate.getSeconds()+60);
+       var alarm1, alarm2, alarm3;
+       try {
+               alarm1 = new tizen.AlarmAbsolute(myDate);
+               alarm2 = new tizen.AlarmAbsolute(myDate, 10);
+               alarm3 = new tizen.AlarmAbsolute(myDate, ["SA", "SU"]);
+       } catch(err) {
+               TestEngine.test("Exception : new tizen.AlarmAbsolute() err.name [" + err.name + "] err.msg[" + err.message + "]", false);
+       }
+
+       TestEngine.test("Check AlarmAbsolute object date atttribute is not undefined result = ", !isUndefined(alarm1.date));
+       TestEngine.test("Check AlarmAbsolute object date atttribute is not undefined result = ", !isUndefined(alarm2.date));
+       TestEngine.test("Check AlarmAbsolute object date atttribute is not undefined result = ", !isUndefined(alarm3.date));
+       TestEngine.test("Check AlarmAbsolute object date atttribute is not null result = ", !isNull(alarm1.date));
+       TestEngine.test("Check AlarmAbsolute object date atttribute is not null result = ", !isNull(alarm2.date));
+       TestEngine.test("Check AlarmAbsolute object date atttribute is not null result = ", !isNull(alarm3.date));
+
+       TestEngine.assertEqual("Check date attirbute value result = ", alarm1.date.getTime(), myDate.getTime());
+       TestEngine.assertEqual("Check date attirbute value result = ", alarm2.date.getTime(), myDate.getTime());
+       TestEngine.assertEqual("Check date attirbute value result = ", alarm3.date.getTime(), myDate.getTime());
+
+       alarmManager.removeAll();
+}
+
+function UTC_alarm_AlarmAbsolute_id_P_001() {
+       TestEngine.log("UTC_alarm_AlarmAbsolute_id_P_001");
+       var myDate = new Date();
+       myDate.setSeconds(myDate.getSeconds()+60);
+       var alarm1, alarm2, alarm3;
+       var alarm4, alarm5, alarm6;
+       try {
+               alarm1 = new tizen.AlarmAbsolute(myDate);
+               alarm2 = new tizen.AlarmAbsolute(myDate, 10);
+               alarm3 = new tizen.AlarmAbsolute(myDate, ["SA", "SU"]);
+
+               alarm4 = new tizen.AlarmAbsolute(myDate);
+               alarm5 = new tizen.AlarmAbsolute(myDate, 10);
+               alarm6 = new tizen.AlarmAbsolute(myDate, ["SA", "SU"]);
+
+               alarmManager.add(alarm4, "tizenutc01.TizenUnitTCApp1");
+               alarmManager.add(alarm5, "tizenutc01.TizenUnitTCApp1");
+               alarmManager.add(alarm6, "tizenutc01.TizenUnitTCApp1");
+
+       } catch(err) {
+               TestEngine.test("Exception : new tizen.AlarmAbsolute() err.name [" + err.name + "] err.msg[" + err.message + "]", false);
+       }
+
+       TestEngine.assertEqual("check AlarmAbsolute object id is null", null, alarm1.id);
+       TestEngine.assertEqual("check AlarmAbsolute object id is null", null, alarm2.id);
+       TestEngine.assertEqual("check AlarmAbsolute object id is null", null, alarm3.id);
+
+       TestEngine.test("check AlarmAbsolute object id is not null", !isNull(alarm4.id));
+       TestEngine.test("check AlarmAbsolute object id is not null", !isNull(alarm5.id));
+       TestEngine.test("check AlarmAbsolute object id is not null", !isNull(alarm6.id));
+
+       TestEngine.test("check AlarmAbsolute object id is not undefined", !isUndefined(alarm4.id));
+       TestEngine.test("check AlarmAbsolute object id is not undefined", !isUndefined(alarm5.id));
+       TestEngine.test("check AlarmAbsolute object id is not undefined", !isUndefined(alarm6.id));
+
+       alarmManager.removeAll();
+}
+
+function UTC_alarm_AlarmAbsolute_period_P_001() {
+       TestEngine.log("UTC_alarm_AlarmAbsolute_period_P_001");
+       var myDate = new Date();
+       myDate.setSeconds(myDate.getSeconds()+60);
+       var alarm1, alarm2;
+       try {
+               alarm1 = new tizen.AlarmAbsolute(myDate, 10);
+               alarm2 = new tizen.AlarmAbsolute(myDate, ["SU"]);
+       } catch(err) {
+               TestEngine.test("Exception : new tizen.AlarmAbsolute() err.name [" + err.name + "] err.msg[" + err.message + "]", false);
+       }
+
+       TestEngine.assertEqual("check AlarmAbsolute object period attribute", 10,  alarm1.period);
+       TestEngine.assertEqual("check AlarmAbsolute object period attribute", null,  alarm2.period);
+
+       alarmManager.removeAll();
+}
+
+function UTC_alarm_AlarmAbsolute_daysOfTheWeek_P_001() {
+       TestEngine.log("UTC_alarm_AlarmAbsolute_daysOfTheWeek_P_001");
+       var myDate = new Date();
+       myDate.setSeconds(myDate.getSeconds()+60);
+       var alarm1, alarm2;
+       try {
+               alarm1 = new tizen.AlarmAbsolute(myDate, ["SU"]);
+               alarm2 = new tizen.AlarmAbsolute(myDate, 10);
+       } catch(err) {
+               TestEngine.test("Exception : new tizen.AlarmAbsolute() err.name [" + err.name + "] err.msg[" + err.message + "]", false);
+       }
+
+       TestEngine.test("check AlarmAbsolute object daysOfTheWeek attribute is not nul result = ", !isNull(alarm1.daysOfTheWeek));
+       TestEngine.test("check AlarmAbsolute object daysOfTheWeek attribute is not nul result = ", !isUndefined(alarm1.daysOfTheWeek));
+       TestEngine.test("check AlarmAbsolute object daysOfTheWeek attribute is array result = ",   isArray(alarm2.daysOfTheWeek));
+       TestEngine.assertEqual("check AlarmAbsolute object daysOfTheWeek attribute", alarm1.daysOfTheWeek[0] , "SU");
+       TestEngine.assertEqual("check AlarmAbsolute object daysOfTheWeek attribute", alarm2.daysOfTheWeek.length , 0);
+
+       alarmManager.removeAll();
+}
+
+function UTC_alarm_AlarmAbsolute_getNextScheduledDate_P_001() {
+       TestEngine.log("UTC_alarm_AlarmAbsolute_getNextScheduledDate_P_001");
+       var myDate = new Date();
+       myDate.setMilliseconds(0);
+       myDate.setSeconds(myDate.getSeconds()+60);
+
+       var alarm;
+       try {
+               alarm = new tizen.AlarmAbsolute(myDate);
+
+               alarmManager.add(alarm, "tizenutc01.TizenUnitTCApp1");
+       } catch(err) {
+               TestEngine.test("Exception : new tizen.AlarmAbsolute() err.name [" + err.name + "] err.msg[" + err.message + "]", false);
+       }
+       TestEngine.assertEqual("check AlarmAbsolute object getNextScheduledDate function()", alarm.getNextScheduledDate().getTime(), myDate.getTime());
+
+       alarmManager.removeAll();
+}
+
+function UTC_alarm_AlarmAbsolute_getNextScheduledDate_N_001() {
+       TestEngine.log("UTC_alarm_AlarmAbsolute_getNextScheduledDate_N_001");
+       var alarm;
+       var myDate = new Date();
+       myDate.setSeconds(myDate.getSeconds()+60);
+       try {
+               alarm = new tizen.AlarmAbsolute(myDate);
+               //call getNextScheduleDate() before add for negative
+               //getNextSceduledDate() must return null
+               TestEngine.assertEqual("new tizen.AlarmAbsolute() alarm.daysOfTheWeek", alarm.getNextScheduledDate(), null);
+       } catch(err) {
+               TestEngine.test("Exception : new tizen.AlarmAbsolute() err.name [" + err.name + "] err.msg[" + err.message + "]", false);
+       }
+       alarmManager.removeAll();
+}
+
+function UTC_alarm_add_P_001() {
+       TestEngine.log("UTC_alarm_add_P_001");
+       var myDate = new Date();
+       myDate.setSeconds(myDate.getSeconds()+60);
+       var alarm1, alarm2, alarm3;
+       try {
+               alarm1 = new tizen.AlarmAbsolute(myDate);
+               alarm2 = new tizen.AlarmAbsolute(myDate, 10);
+               alarm3 = new tizen.AlarmAbsolute(myDate, ["SA", "SU"]);
+
+               TestEngine.test("new tizen.AlarmAbsolute()  result = ", !isUndefined(alarm1));
+               TestEngine.test("new tizen.AlarmAbsolute()  result = ", !isUndefined(alarm2));
+               TestEngine.test("new tizen.AlarmAbsolute()  result = ", !isUndefined(alarm3));
+
+               alarmManager.add(alarm1, "tizenutc01.TizenUnitTCApp1");
+               alarmManager.add(alarm2, "tizenutc01.TizenUnitTCApp1");
+               alarmManager.add(alarm3, "tizenutc01.TizenUnitTCApp1");
+
+               TestEngine.test("tizen.alarm.add AlarmAbsolute result = ", !isNull(alarm1.id));
+               TestEngine.test("tizen.alarm.add AlarmAbsolute result = ", !isNull(alarm2.id));
+               TestEngine.test("tizen.alarm.add AlarmAbsolute result = ", !isNull(alarm3.id));
+       } catch(err) {
+               TestEngine.test("Exception : tizen.alarm.add() err.name [" + err.name + "] err.msg[" + err.message + "]", false);
+       }
+       alarmManager.removeAll();
+}
+
+function UTC_alarm_add_P_002() {
+       TestEngine.log("UTC_alarm_add_P_002");
+       try {
+               var alarm1 = new tizen.AlarmRelative(10);
+
+               TestEngine.test("new tizen.AlarmRelative()  result = ", !isUndefined(alarm1));
+
+               alarmManager.add(alarm1, "tizenutc01.TizenUnitTCApp1", null);
+               TestEngine.test("tizen.alarm.add AlarmRelative result1 = ", !isNull(alarm1.id));
+       } catch(err) {
+               TestEngine.test("Exception : tizen.alarm.add() err.name [" + err.name + "] err.msg[" + err.message + "]", false);
+       }
+       alarmManager.removeAll();
+}
+
+function UTC_alarm_add_N_001() {
+       TestEngine.log("UTC_alarm_add_N_001");
+       var alarm;
+       try {
+               alarmManager.add(1, "tizenutc01.TizenUnitTCApp1");
+       } catch(err) {
+               TestEngine.test("Exception : tizen.alarm.add() err.name [" + err.name + "] err.msg[" + err.message + "]", true);
+               alarmManager.removeAll();
+               return;
+       }
+       TestEngine.test("Exception is nut occured", false);
+       alarmManager.removeAll();
+}
+
+function UTC_alarm_add_N_002() {
+       TestEngine.log("UTC_alarm_add_N_002");
+       try {
+               alarmManager.add(undefined, "tizenutc01.TizenUnitTCApp1");
+       } catch(err) {
+               TestEngine.test("Exception : tizen.alarm.add() err.name [" + err.name + "] err.msg[" + err.message + "]", true);
+               alarmManager.removeAll();
+               return;
+       }
+       TestEngine.test("Exception is nut occured", false);
+       alarmManager.removeAll();
+}
+
+function UTC_alarm_add_N_003() {
+       TestEngine.log("UTC_alarm_add_N_003");
+       var obj;
+       try {
+               alarmManager.add(null, "tizenutc01.TizenUnitTCApp1");
+       } catch(err) {
+               TestEngine.test("Exception : tizen.alarm.add() err.name [" + err.name + "] err.msg[" + err.message + "]", true);
+               alarmManager.removeAll();
+               return;
+       }
+       TestEngine.test("Exception is not occured", false);
+       alarmManager.removeAll();
+}
+
+function UTC_alarm_add_N_004() {
+       TestEngine.log("UTC_alarm_add_N_004");
+       var alarm = new tizen.AlarmRelative(30);
+       TestEngine.test("new tizen.AlarmRelative() result = ", !isUndefined(alarm));
+
+    TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, alarmManager, "add", alarm, "tizenutc01.TizenUnitTCApp1", "");
+    TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, alarmManager, "add", alarm, "tizenutc01.TizenUnitTCApp1", "GG");
+
+       alarmManager.removeAll();
+}
+
+function UTC_alarm_AlarmRelative_Constructor_P_001() {
+       TestEngine.log("UTC_alarm_AlarmRelative_Constructor_P_001");
+       var alarm1, alarm2, alarm3, alarm4;
+       try {
+               alarm1 = new tizen.AlarmRelative(10);
+               alarm2 = new tizen.AlarmRelative(10, 10);
+               alarm3 = new tizen.AlarmRelative(10, 10, 10);
+               alarm4 = new tizen.AlarmRelative(10, undefined);
+       } catch(err) {
+               TestEngine.test("Exception :new tizen.AlarmRelative() err.name [" + err.name + "] err.msg[" + err.message + "]", false);
+       }
+       TestEngine.test("new tizen.AlarmRelative()  result = ", !isUndefined(alarm1));
+       alarmManager.removeAll();
+}
+
+function UTC_alarm_AlarmRelative_delay_P_001() {
+       TestEngine.log("UTC_alarm_AlarmRelative_delay_P_001");
+       var alarm1, alarm2, alarm3;
+       try {
+       alarm1 = new tizen.AlarmRelative(10);
+       alarm2 = new tizen.AlarmRelative(20);
+       alarm3 = new tizen.AlarmRelative(30);
+       } catch(err) {
+               TestEngine.test("Exception :new tizen.AlarmRelative() err.name [" + err.name + "] err.msg[" + err.message + "]", false);
+       }
+
+       TestEngine.test("new tizen.AlarmRelative() result = ", !isUndefined(alarm1));
+       TestEngine.test("new tizen.AlarmRelative() result = ", !isUndefined(alarm2));
+       TestEngine.test("new tizen.AlarmRelative() result = ", !isUndefined(alarm3));
+       TestEngine.assertEqual("new tizen.AlarmRelative() alarm.delay", 10,  alarm1.delay);
+       TestEngine.assertEqual("new tizen.AlarmRelative() alarm.delay", 20,  alarm2.delay);
+       TestEngine.assertEqual("new tizen.AlarmRelative() alarm.delay", 30,  alarm3.delay);
+
+       alarmManager.removeAll();
+}
+
+function UTC_alarm_AlarmRelative_id_P_001() {
+       TestEngine.log("UTC_alarm_AlarmRelative_id_P_001");
+       var alarm1, alarm2;
+       try {
+               alarm1 = new tizen.AlarmRelative(10);
+               alarm2 = new tizen.AlarmRelative(10, 10);
+               TestEngine.test("new tizen.AlarmRelative() result = ", !isUndefined(alarm1));
+               TestEngine.test("new tizen.AlarmRelative() result = ", !isUndefined(alarm2));
+
+               alarmManager.add(alarm1, "tizenutc01.TizenUnitTCApp1");
+               alarmManager.add(alarm2, "tizenutc01.TizenUnitTCApp1");
+
+               TestEngine.test("tizen.alarm.add AlarmRelative result = ", !isNull(alarm1.id));
+               TestEngine.test("tizen.alarm.add AlarmRelative result = ", !isNull(alarm2.id));
+       } catch(err) {
+               TestEngine.test("Exception : tizen.AlarmRelative() err.name [" + err.name + "] err.msg[" + err.message + "]", false);
+       }
+       alarmManager.removeAll();
+}
+
+function UTC_alarm_AlarmRelative_period_P_001() {
+       TestEngine.log("UTC_alarm_AlarmRelative_period_P_001");
+       var alarm1, alarm2;
+       try {
+               alarm1 = new tizen.AlarmRelative(10, 10);
+               alarm2 = new tizen.AlarmRelative(10);
+               TestEngine.test("new tizen.AlarmRelative()  result = ", !isUndefined(alarm1));
+               TestEngine.test("new tizen.AlarmRelative()  result = ", !isUndefined(alarm2));
+               alarmManager.add(alarm1, "tizenutc01.TizenUnitTCApp1");
+               TestEngine.assertEqual("new tizen.AlarmRelative() alarm.date", alarm1.period,  10);
+               TestEngine.test("Check AlarmRelative object.period is null result = ", isNull(alarm2.period));
+       } catch(err) {
+               TestEngine.test("Exception : tizen.AlarmRelative() err.name [" + err.name + "] err.msg[" + err.message + "]", false);
+       }
+       alarmManager.removeAll();
+}
+
+function UTC_alarm_AlarmRelative_getRemainingSeconds_P_001() {
+       TestEngine.log("UTC_alarm_AlarmRelative_getRemainingSeconds_P_001");
+       var alarm;
+       try {
+               alarm = new tizen.AlarmRelative(10);
+               TestEngine.test("new tizen.AlarmRelative()  result = ", !isUndefined(alarm));
+               alarmManager.add(alarm, "tizenutc01.TizenUnitTCApp1");
+               TestEngine.test("new tizen.AlarmRelative()  result = ", !isUndefined(alarm.getRemainingSeconds()));
+       } catch(err) {
+               TestEngine.test("Exception : tizen.alarm.AlarmRelative getRemainingSeconds err.name [" + err.name + "] err.msg[" + err.message + "]", false);
+       }
+       alarmManager.removeAll();
+}
+
+function UTC_alarm_AlarmRelative_getRemainingSeconds_N_001() {
+       TestEngine.log("UTC_alarm_AlarmRelative_getRemainingSeconds_N_001");
+       var alarm;
+       try {
+               alarm = new tizen.AlarmRelative(10);
+               TestEngine.test("new tizen.AlarmRelative()  result = ", isNull(alarm.getRemainingSeconds()));
+               TestEngine.test("new tizen.AlarmRelative()  result = ", isNull(alarm.getRemainingSeconds(10)));
+       } catch(err) {
+               TestEngine.test("Exception : tizen.AlarmRelative getRemainingSeconds err.name [" + err.name + "] err.msg[" + err.message + "]", false);
+       }
+       alarmManager.removeAll();
+}
+
+function UTC_alarm_remove_P_001() {
+       TestEngine.log("UTC_alarm_remove_P_001");
+       var alarm1, alarm2;
+       try {
+               alarm1 = new tizen.AlarmRelative(10, 10);
+               alarm2 = new tizen.AlarmRelative(20, 10);
+               alarmManager.add(alarm1, "tizenutc01.TizenUnitTCApp1");
+               alarmManager.add(alarm2, "tizenutc01.TizenUnitTCApp1");
+               var alarms = tizen.alarm.getAll();
+               TestEngine.assertEqual("Current alarm size", alarms.length,  2);
+               TestEngine.test("testRemoveAlarm = ", !isUndefined(alarm1));
+               TestEngine.test("testRemoveAlarm = ", !isUndefined(alarm2));
+               tizen.alarm.remove(alarm1.id);
+               tizen.alarm.remove(alarm2.id);
+               var alarms2 = tizen.alarm.getAll();
+               TestEngine.assertEqual("Current alarm size", alarms2.length,  0);
+       } catch(err) {
+               TestEngine.test("Exception : tizen.alarm.remove() err.name [" + err.name + "] err.msg[" + err.message + "]", false);
+       }
+       alarmManager.removeAll();
+}
+
+function UTC_alarm_remove_N_001() {
+       TestEngine.log("UTC_alarm_remove_N_001");
+       var alarm;
+       try {
+               tizen.alarm.remove("ABC");
+               var alarms2 = tizen.alarm.getAll();
+               TestEngine.assertEqual("Current alarm size", alarms.length,  0);
+       } catch(err) {
+               TestEngine.test("Exception : tizen.alarm.remove() err.name [" + err.name + "] err.msg[" + err.message + "]", true);
+               return;
+       }
+       TestEngine.test("Exception is not occured", false);
+       alarmManager.removeAll();
+}
+
+function UTC_alarm_remove_N_002() {
+       TestEngine.log("UTC_alarm_remove_N_002");
+       var alarm;
+       try {
+               tizen.alarm.remove(undefined);
+               var alarms2 = tizen.alarm.getAll();
+               TestEngine.assertEqual("Current alarm size", alarms.length,  0);
+       } catch(err) {
+               TestEngine.test("Exception : tizen.alarm.remove() err.name [" + err.name + "] err.msg[" + err.message + "]", true);
+               return;
+       }
+       TestEngine.test("Exception is not occured", false);
+       alarmManager.removeAll();
+}
+
+function UTC_alarm_remove_N_003() {
+       TestEngine.log("UTC_alarm_remove_N_003");
+       var alarm;
+       try {
+               tizen.alarm.remove(null);
+               var alarms2 = tizen.alarm.getAll();
+               TestEngine.assertEqual("Current alarm size", alarms.length,  0);
+       } catch(err) {
+               TestEngine.test("Exception : tizen.alarm.remove() err.name [" + err.name + "] err.msg[" + err.message + "]", true);
+               return;
+       }
+       TestEngine.test("Exception is not occured", false);
+       alarmManager.removeAll();
+}
+
+function UTC_alarm_removeAll_P_001() {
+       TestEngine.log("UTC_alarm_removeAll_P_001");
+       var alarm;
+       try {
+               alarm = new tizen.AlarmRelative(10, 10);
+               alarmManager.add(alarm, "tizenutc01.TizenUnitTCApp1");
+               var alarms = tizen.alarm.getAll();
+               TestEngine.assertEqual("Current alarm size", alarms.length,  1);
+               TestEngine.test("testRemoveAlarm = ", !isUndefined(alarm));
+               tizen.alarm.removeAll(1);
+               tizen.alarm.removeAll();
+               var alarms2 = tizen.alarm.getAll();
+               TestEngine.assertEqual("Current alarm size", alarms2.length,  0);
+       } catch(err) {
+               TestEngine.test("Exception : tizen.alarm.removeAll() err.name [" + err.name + "] err.msg[" + err.message + "]", false);
+       }
+       alarmManager.removeAll();
+}
+
+function UTC_alarm_get_P_001() {
+       TestEngine.log("UTC_alarm_get_P_001");
+       var alarm;
+       try {
+               alarm = new tizen.AlarmRelative(10, 10);
+               alarmManager.add(alarm, "tizenutc01.TizenUnitTCApp1");
+               TestEngine.test("testGetAlarm = ", !isUndefined(alarm));
+
+               TestEngine.log("[Alarm] testGetAlarmP #1");
+               var alarm2 = tizen.alarm.get(alarm.id);
+               TestEngine.log("[Alarm] testGetAlarmP #1");
+               var alarm3 = tizen.alarm.get(alarm.id, 1);
+               TestEngine.test("testGetAlarm = ", !isUndefined(alarm2));
+               TestEngine.test("testGetAlarm = ", !isUndefined(alarm3));
+               TestEngine.assertEqual("Compare id", alarm.id,  alarm2.id);
+       } catch(err) {
+               TestEngine.test("Exception : tizen.alarm.get() err.name [" + err.name + "] err.msg[" + err.message + "]", false);
+       }
+       alarmManager.removeAll();
+}
+
+function UTC_alarm_get_N_001() {
+       TestEngine.log("UTC_alarm_get_N_001");
+       try {
+               var alarm = tizen.alarm.get("ABCD");
+       } catch(err) {
+               TestEngine.test("Exception : tizen.alarm.get() err.name [" + err.name + "] err.msg[" + err.message + "]", true);
+               return;
+       }
+       alarmManager.removeAll();
+}
+
+function UTC_alarm_get_N_002() {
+       TestEngine.log("UTC_alarm_get_N_002");
+       try {
+               var alarm = tizen.alarm.get(undefined);
+       } catch(err) {
+               TestEngine.test("Exception : tizen.alarm.get() err.name [" + err.name + "] err.msg[" + err.message + "]", true);
+               return;
+       }
+       alarmManager.removeAll();
+}
+
+function UTC_alarm_get_N_003() {
+       TestEngine.log("UTC_alarm_get_N_003");
+       try {
+               var alarm = tizen.alarm.get(null);
+       } catch(err) {
+               TestEngine.test("Exception : tizen.alarm.get() err.name [" + err.name + "] err.msg[" + err.message + "]", true);
+               return;
+       }
+       alarmManager.removeAll();
+}
+
+function UTC_alarm_getAll_P_001() {
+       TestEngine.log("UTC_alarm_getAll_P_001");
+       var alarm;
+       try {
+               alarm = new tizen.AlarmRelative(10, 10);
+               alarmManager.add(alarm, "tizenutc01.TizenUnitTCApp1");
+               var alarms = tizen.alarm.getAll();
+               var alarms2 = tizen.alarm.getAll(1);
+               TestEngine.assertEqual("Current alarm size", alarms.length,  1);
+               TestEngine.assertEqual("Compare id", alarm.id,  alarms[0].id);
+               TestEngine.test("testGetAllAlarm = ", !isUndefined(alarm));
+       } catch(err) {
+               TestEngine.test("Exception : tizen.alarm.getAll() err.name [" + err.name + "] err.msg[" + err.message + "]", false);
+       }
+       alarmManager.removeAll();
+}
+
+
+function UTC_alarm_NP() {
+       TestEngine.log("UTC_alarm_NP");
+
+       var myDate = new Date();
+       myDate.setSeconds(myDate.getSeconds()+60);
+       var alarm1, alarm2, alarm3;
+       try {
+               alarm1 = new tizen.AlarmAbsolute(myDate);
+               alarm2 = new tizen.AlarmAbsolute(myDate, 10);
+               alarm3 = new tizen.AlarmAbsolute(myDate, ["SA", "SU"]);
+       } catch(err) {
+               TestEngine.test("Exception : err.name [" + err.name + "] err.msg[" + err.message + "]", false);
+       }
+
+       TestEngine.test("Check AlarmAbsolute object date atttribute is not undefined result = ", !isUndefined(alarm1.date));
+       TestEngine.test("check AlarmAbsolute object id is null", isNull(alarm1.id));
+       TestEngine.assertEqual("check AlarmAbsolute object period attribute", 10,  alarm2.period);
+       TestEngine.assertEqual("check AlarmAbsolute object daysOfTheWeek attribute", alarm3.daysOfTheWeek[0] , "SA");
+
+       var scheduledDate = alarm1.getNextScheduledDate();
+
+       var alarm4, alarm5, alarm6;
+       try {
+               alarm4 = new tizen.AlarmRelative(10);
+               alarm5 = new tizen.AlarmRelative(10, 10);
+       } catch(err) {
+               TestEngine.test("Exception :new tizen.AlarmRelative() err.name [" + err.name + "] err.msg[" + err.message + "]", false);
+       }
+
+       TestEngine.assertEqual("new tizen.AlarmRelative() alarm.delay", 10,  alarm4.delay);
+       TestEngine.test("tizen.alarm.add AlarmRelative result = ", isNull(alarm4.id));
+       TestEngine.assertEqual("new tizen.AlarmRelative() alarm.period", alarm5.period,  10);
+
+       var remaingSeconds = alarm4.getRemainingSeconds();
+
+       var alarms = tizen.alarm.getAll();
+       TestEngine.assertEqual("Current alarm size", alarms.length,  0);
+       
+}
+
diff --git a/webWidgetTCT_device/test/utc/tests/TestApplication.js b/webWidgetTCT_device/test/utc/tests/TestApplication.js
new file mode 100755 (executable)
index 0000000..71ff873
--- /dev/null
@@ -0,0 +1,2325 @@
+/*
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ * PROPRIETARY/CONFIDENTIAL
+ *
+ * This software is the confidential and proprietary information of SAMSUNG
+ * ELECTRONICS ("Confidential Information"). You agree and acknowledge that
+ * this software is owned by Samsung and you shall not disclose such
+ * Confidential Information and shall use it only in accordance with the terms
+ * of the license agreement you entered into with SAMSUNG ELECTRONICS. SAMSUNG
+ * make no representations or warranties about the suitability of the software,
+ * either express or implied, including but not limited to the implied
+ * warranties of merchantability, fitness for a particular purpose, or
+ * non-infringement. SAMSUNG shall not be liable for any damages suffered by
+ * licensee arising out of or related to this software.
+ *
+ */
+
+
+var TYPE_MISMATCH_ERR = 'TypeMismatchError';
+var INVALID_VALUES_ERR = 'InvalidValuesError';
+var NOT_SUPPORTED_ERR = 'NotSupportedError';
+var NOT_FOUND_ERR = 'NotFoundError';
+
+var CURR_APP_ID = 'tizenutc00.UnitTest';
+var CURR_APP_SHARED_DIR = 'file:///opt/usr/apps/tizenutc00/shared';
+var TEST_APP_SHARED_DIR = 'file:///opt/usr/apps/tizenutc01/shared';
+var TEST_NUM = 1234;
+var TEST_STR = "UTC_application_string";
+var TEST_OBJ = new tizen.ApplicationControl("TEST_OPERATION");
+var TEST_FUN = function() {};
+
+var TEST_APP_ID_1 = 'tizenutc01.TizenUnitTCApp1';
+var TEST_APP_ID_2 = 'tizenutc02.TizenUnitTCApp2';
+var TEST_APP_ID_3 = 'tizenutc03.TizenUnitTCApp3';
+var TEST_ILLEGAL_APP_ID_3 = 'NOT_EXIST_APP_ID';
+
+var TEST_APP_CONTROL_OPERATION_1 = "http://tizen.org/appcontrol/operation/test_appcontrol_1";
+var TEST_APP_CONTROL_OPERATION_N = "http://tizen.org/appcontrol/operation/test_appcontrol_N";
+var TEST_APP_CONTROL_OPERATION_2 = "http://tizen.org/appcontrol/operation/test_appcontrol_2";
+var TEST_APP_CONTROL_OPERATION_3 = "http://tizen.org/appcontrol/operation/test_appcontrol_3";
+var TEST_ILLEGAL_APP_CONTROL_OPERATION = "http://tizen.org/appcontrol/operation/no_exist_operation";
+
+/********************************************************************
+ *   Application Interface
+ ********************************************************************/
+
+function onSuccessCB()
+{
+       TestEngine.test("[Application]", true);
+}
+
+function onErrorCB(err)
+{
+       TestEngine.log("error name: " + err.name);
+       TestEngine.log("error code: " + err.code);
+       TestEngine.log("description: " + err.description);
+       TestEngine.log("message: " + err.message);
+
+       TestEngine.test("[Application]", false);
+}
+
+function UTC_application_presence_P_001()
+{
+       TestEngine.log("[Application] UTC_application_presence_P_001 START");
+       try {
+               TestEngine.test("Tizen presence", tizen);
+           TestEngine.test("ApplicationManager presence", tizen.application);
+               TestEngine.testPresence("getCurrentApplication", tizen.application.getCurrentApplication);
+               TestEngine.testPresence("kill", tizen.application.kill);
+               TestEngine.testPresence("launch", tizen.application.launch);
+               TestEngine.testPresence("launchAppcontrol", tizen.application.launchAppControl);
+               TestEngine.testPresence("findAppControl", tizen.application.findAppControl);
+               TestEngine.testPresence("getAppsContext", tizen.application.getAppsContext);
+               TestEngine.testPresence("getAppContext", tizen.application.getAppContext);
+               TestEngine.testPresence("getAppsInfo", tizen.application.getAppsInfo);
+               TestEngine.testPresence("getAppInfo", tizen.application.getAppInfo);
+               TestEngine.testPresence("getAppCerts", tizen.application.getAppCerts);
+               TestEngine.testPresence("getAppSharedURI", tizen.application.getAppSharedURI);
+               TestEngine.testPresence("getAppMetaData", tizen.application.getAppMetaData);
+               TestEngine.testPresence("addAppInfoEventListener", tizen.application.addAppInfoEventListener);
+               TestEngine.testPresence("removeAppInfoEventListener", tizen.application.removeAppInfoEventListener);
+       } catch (err) {
+               TestEngine.test("[Application] UTC_application_application_P_00resence_P_001 error : " + err);
+               TestEngine.test("", false);
+       }
+
+       TestEngine.log("[Application] UTC_application_application_P_00resence_P_001 END");
+}
+
+function UTC_application_presence_P_002()
+{
+       TestEngine.log("[Application] UTC_application_presence_P_002 START");
+       try {
+               var app = tizen.application.getCurrentApplication();
+           TestEngine.test("Application presence", app);
+               TestEngine.testPresence("exit", app.exit);
+               TestEngine.testPresence("hide", app.hide);
+               TestEngine.testPresence("getRequestedAppControl", app.getRequestedAppControl);
+       } catch (err) {
+               TestEngine.test("[Application] UTC_application_presence_P_002 error : " + err);
+               TestEngine.test("", false);
+       }
+
+       TestEngine.log("[Application] UTC_application_application_P_00resence_P_001 END");
+}
+
+
+function UTC_application_getCurrentApplication_P_001()
+{
+       TestEngine.log("[Application] UTC_application_getCurrentApplication_P_001 START");
+       try {
+               var app = tizen.application.getCurrentApplication();
+                                           
+               TestEngine.log("App.appInfo.name = " + app.appInfo.name);
+               TestEngine.log("App.appInfo.id = " + app.appInfo.id);
+
+               if (app.appInfo.id != CURR_APP_ID) {
+                       TestEngine.test("[Application] UTC_application_getCurrentApplication_P_001 err : current id is not same", false);
+               }
+
+               TestEngine.test("[Application] UTC_application_getCurrentApplication_P_001", true);
+       } catch (err) {
+               TestEngine.test("[Application] UTC_application_getCurrentApplication_P_001 error", false);
+       }
+       TestEngine.log("[Application] UTC_application_getCurrentApplication_P_001 END");
+}
+
+function UTC_application_launch_P_001()
+{
+       TestEngine.log("[Application] UTC_application_launch_P_001 START");
+
+       TestEngine.setInterval(1000);
+
+       try {
+               var cbObj = TestEngine.registerCallback("launch", onSuccessCB, onErrorCB);
+               tizen.application.launch(TEST_APP_ID_1, cbObj.successCallback, null);
+       } catch (err) {
+               TestEngine.test("[Application] UTC_application_launch_P_001 error", false);
+       }
+       TestEngine.log("[Application] UTC_application_launch_P_001 END");
+}
+
+function UTC_application_launch_P_002()
+{
+       TestEngine.log("[Application] UTC_application_launch_P_002 START");
+
+       TestEngine.setInterval(1000);
+
+       try {
+               var cbObj = TestEngine.registerCallback("launch", onSuccessCB, onErrorCB);
+               tizen.application.launch(TEST_APP_ID_2, cbObj.successCallback, cbObj.errorCallback);
+       } catch (err) {
+               TestEngine.test("", false);
+       }
+       TestEngine.log("[Application] UTC_application_launch_P_002 END");
+ }
+
+function UTC_application_launch_P_003()
+{
+       TestEngine.log("[Application] UTC_application_launch_P_003 START");
+
+       TestEngine.setInterval(1000);
+
+       try {
+               var cbObj = TestEngine.registerCallback("launch", onSuccessCB, onErrorCB);
+               tizen.application.launch(TEST_APP_ID_3, cbObj.successCallback, cbObj.errorCallback, undefined);
+       } catch (err) {
+               TestEngine.test("", false);
+       }
+       TestEngine.log("[Application] UTC_application_launch_P_003 END");
+}
+
+
+function UTC_application_launch_N_001()
+{
+       TestEngine.log("[Application] UTC_application_launch_N_001 START");
+
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.application, "launch", TEST_APP_ID_3, TEST_NUM,      null);
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.application, "launch", TEST_APP_ID_3, TEST_STR,      null);
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.application, "launch", TEST_APP_ID_3, TEST_OBJ,      null);
+
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.application, "launch", TEST_APP_ID_3, onSuccessCB, TEST_NUM);
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.application, "launch", TEST_APP_ID_3, onSuccessCB, TEST_STR);
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.application, "launch", TEST_APP_ID_3, onSuccessCB, TEST_OBJ);
+
+       TestEngine.log("[Application] UTC_application_launch_N_001 END");
+}
+
+function UTC_application_launch_N_002()
+{
+       TestEngine.log("[Application] UTC_application_launch_N_002 START");
+
+       function notFoundErrorCB(err)
+       {
+               if (err.name == NOT_FOUND_ERR) {
+                       TestEngine.test("[Application] cannot found", true);
+               } else {
+                       TestEngine.test("", false);
+               }
+       }
+
+       try {
+               var cbObj = TestEngine.registerCallback("launch", onSuccessCB, notFoundErrorCB);
+               tizen.application.launch(TEST_ILLEGAL_APP_ID_3, cbObj.successCallback, cbObj.errorCallback);
+       } catch (err) {
+               TestEngine.test("", false);
+       }
+       TestEngine.log("[Application] UTC_application_launch_N_002 END");
+}
+
+function UTC_application_launch_N_003()
+{
+       TestEngine.log("[Application] UTC_application_launch_N_003 START");
+
+       function notFoundErrorCB(err)
+       {
+               if (err.name == NOT_FOUND_ERR) {
+                       TestEngine.test("[Application] cannot found", true);
+               } else {
+                       TestEngine.test("", false);
+               }
+       }
+
+       try {
+               var cbObj = TestEngine.registerCallback("launch", onSuccessCB, notFoundErrorCB);
+               tizen.application.launch(undefined, cbObj.successCallback, cbObj.errorCallback);
+       } catch (err) {
+               TestEngine.test("", false);
+       }
+       TestEngine.log("[Application] UTC_application_launch_N_003 END");
+ }
+
+ function UTC_application_launch_N_004()
+ {
+        TestEngine.log("[Application] UTC_application_launch_N_004 START");
+
+        function notFoundErrorCB(err)
+        {
+                if (err.name == NOT_FOUND_ERR) {
+                        TestEngine.test("[Application] cannot found", true);
+                } else {
+                        TestEngine.test("", false);
+                }
+        }
+
+        try {
+                var cbObj = TestEngine.registerCallback("launch", onSuccessCB, notFoundErrorCB);
+                tizen.application.launch(null, cbObj.successCallback, cbObj.errorCallback);
+        } catch (err) {
+                TestEngine.test("", false);
+        }
+        TestEngine.log("[Application] UTC_application_launch_N_004 END");
+}
+
+function UTC_application_launch_N_005()
+{
+       TestEngine.log("[Application] UTC_application_launch_N_005 START");
+
+       function notFoundErrorCB(err)
+       {
+               if (err.name == NOT_FOUND_ERR) {
+                       TestEngine.test("[Application] cannot found", true);
+               } else {
+                       TestEngine.test("", false);
+               }
+       }
+
+       try {
+               var cbObj = TestEngine.registerCallback("launch", onSuccessCB, notFoundErrorCB);
+               tizen.application.launch(TEST_OBJ, cbObj.successCallback, cbObj.errorCallback);
+       } catch (err) {
+               TestEngine.test("", false);
+       }
+       TestEngine.log("[Application] UTC_application_launch_N_005 END");
+}
+
+function UTC_application_launch_N_006()
+{
+       TestEngine.log("[Application] UTC_application_launch_N_006 START");
+
+       function notFoundErrorCB(err)
+       {
+               if (err.name == NOT_FOUND_ERR) {
+                       TestEngine.test("[Application] cannot found", true);
+               } else {
+                       TestEngine.test("", false);
+               }
+       }
+
+       try {
+               var cbObj = TestEngine.registerCallback("launch", onSuccessCB, notFoundErrorCB);
+               tizen.application.launch(TEST_FUN, cbObj.successCallback, cbObj.errorCallback);
+       } catch (err) {
+               TestEngine.test("", false);
+       }
+       TestEngine.log("[Application] UTC_application_launch_N_006 END");
+}
+
+var TEST_CONTEXT_ID_1;
+var TEST_CONTEXT_ID_2;
+var TEST_CONTEXT_ID_3;
+
+function onAppContextArraySuccessCB(contexts)
+{
+       TestEngine.log("[onAppContextArraySuccessCB][START]");
+
+       try {
+               TestEngine.log("AppContext Array Length = " + contexts.length);
+
+               for(var num=0; num < contexts.length; num++)
+               {
+                       TestEngine.log("AppContext["+num+"].id = "+contexts[num].id);
+                       TestEngine.log("AppContext["+num+"].appId = "+contexts[num].appId);
+                       if (contexts[num].appId == TEST_APP_ID_1) {
+                               TestEngine.log("AppContext["+num+"] is selected");
+                               TEST_CONTEXT_ID_1 = contexts[num].id;
+                       }
+                       if (contexts[num].appId == TEST_APP_ID_2) {
+                               TestEngine.log("AppContext["+num+"] is selected");
+                               TEST_CONTEXT_ID_2 = contexts[num].id;
+                       }
+                       if (contexts[num].appId == TEST_APP_ID_3) {
+                               TestEngine.log("AppContext["+num+"] is selected");
+                               TEST_CONTEXT_ID_3 = contexts[num].id;
+                       }
+               }
+       } catch (ex) {
+               TestEngine.test("[Application] getMemoContext error: " + ex, false);
+       }
+       TestEngine.test("getAppInfo", true);
+       TestEngine.log("[onAppContextArraySuccessCB][END]");
+}
+
+function UTC_application_kill_P_000()
+{
+       TestEngine.log("[Application] UTC_application_kill_P_000 START");
+
+       try {
+               var cbObj = TestEngine.registerCallback("getAppsContext", onAppContextArraySuccessCB, onErrorCB);
+               tizen.application.getAppsContext(cbObj.successCallback, cbObj.errorCallback);
+       } catch (err) {
+               TestEngine.test("[Application] UTC_application_kill_P_000 error : " + err, false);
+       }
+       TestEngine.log("[Application] UTC_application_kill_P_001 END");
+}
+
+function UTC_application_kill_P_001()
+{
+       TestEngine.log("[Application] UTC_application_kill_P_001 START");
+
+       try {
+               var cbObj = TestEngine.registerCallback("kill", onSuccessCB, onErrorCB);
+
+               tizen.application.kill(TEST_CONTEXT_ID_1, cbObj.successCallback, cbObj.errorCallback);
+       } catch (err) {
+               TestEngine.test("[Application] UTC_application_kill_P_001 error : " + err, false);
+       }
+
+       TestEngine.log("[Application] UTC_application_kill_P_001 END");
+}
+
+function UTC_application_kill_P_002()
+{
+       TestEngine.log("[Application] UTC_application_kill_P_002 START");
+       try {
+               var cbObj = TestEngine.registerCallback("kill", onSuccessCB, onErrorCB);
+               TestEngine.log("Context.id to kill: " + TEST_CONTEXT_ID_2);
+
+               tizen.application.kill(TEST_CONTEXT_ID_2, cbObj.successCallback, cbObj.errorCallback);
+       } catch (err) {
+               TestEngine.test("[Application] UTC_application_kill_P_002 error : " + err, false);
+       }
+
+       TestEngine.log("[Application] UTC_application_kill_P_002 END");
+}
+
+function UTC_application_kill_P_004()
+{
+       TestEngine.log("[Application] UTC_application_kill_P_004 START");
+       try {
+               var cbObj = TestEngine.registerCallback("kill", onSuccessCB, onErrorCB);
+
+               function onAppContextArraySuccessCB(contexts)
+               {
+                       TestEngine.log("[onAppContextArraySuccessCB][START]");
+                       var target_id;
+                       
+                       for(var num=0; num < contexts.length; num++)
+                       {
+                               if (contexts[num].appId == TEST_APP_ID_1) {
+                                       TestEngine.log("AppContext["+num+"] is selected");
+                                       target_id = contexts[num].id;
+                               }
+                       }
+                       
+                       tizen.application.kill(target_id, cbObj.successCallback);
+               }
+               
+               tizen.application.getAppsContext(onAppContextArraySuccessCB);
+       } catch (err) {
+               TestEngine.test("[Application] UTC_application_kill_P_004 error : " + err, false);
+       }
+
+       TestEngine.log("[Application] UTC_application_kill_P_004 END");
+}
+
+function UTC_application_kill_N_001()
+{
+       TestEngine.log("[Application] UTC_application_kill_N_001 START");
+
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.application, "kill", TEST_CONTEXT_ID_2, TEST_NUM,    onErrorCB);
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.application, "kill", TEST_CONTEXT_ID_2, TEST_STR,    onErrorCB);
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.application, "kill", TEST_CONTEXT_ID_2 ,TEST_OBJ,    onErrorCB);
+
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.application, "kill", TEST_CONTEXT_ID_2, onSuccessCB, TEST_NUM);
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.application, "kill", TEST_CONTEXT_ID_2, onSuccessCB, TEST_STR);
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.application, "kill", TEST_CONTEXT_ID_2, onSuccessCB, TEST_OBJ);
+
+       TestEngine.log("[Application] UTC_application_kill_N_001 END");
+}
+
+function UTC_application_kill_N_002()
+{
+       TestEngine.log("[Application] UTC_application_kill_N_002 START");
+
+       function foundSuccessCB(err)
+       {
+               TestEngine.test("", false);
+       }
+
+       function notFoundErrorCB(err)
+       {
+               if (err.name == NOT_FOUND_ERR) {
+                       TestEngine.test("[Application] cannot found", true);
+               } else {
+                       TestEngine.test("", false);
+               }
+       }
+
+       try {
+               var cbObj = TestEngine.registerCallback("kill", foundSuccessCB, notFoundErrorCB);
+               tizen.application.kill(TEST_ILLEGAL_APP_ID_3, cbObj.successCallback, cbObj.errorCallback);
+       } catch (err) {
+               TestEngine.test("UTC_application_kill_N_002 exception occrred!!!", false);
+       }
+       TestEngine.log("[Application] UTC_application_kill_N_002 END");
+}
+
+ function UTC_application_kill_N_003()
+ {
+        TestEngine.log("[Application] UTC_application_kill_N_003 START");
+
+        function foundSuccessCB(err)
+        {
+                TestEngine.test("[Application] found success. Fail to test", false);
+        }
+
+        function notFoundErrorCB(err)
+        {
+                if (err.name == NOT_FOUND_ERR) {
+                        TestEngine.test("[Application] cannot found", true);
+                } else {
+                        TestEngine.test("[Application] found success. Fail to test", false);
+                }
+        }
+
+        try {
+                var cbObj = TestEngine.registerCallback("kill", foundSuccessCB, notFoundErrorCB);
+                tizen.application.kill(undefined, cbObj.successCallback, cbObj.errorCallback);
+        } catch (err) {
+                TestEngine.test("", false);
+        }
+        TestEngine.log("[Application] UTC_application_kill_N_003 END");
+}
+
+function UTC_application_kill_N_004()
+{
+       TestEngine.log("[Application] UTC_application_kill_N_004 START");
+
+       function foundSuccessCB(err)
+       {
+               TestEngine.test("", false);
+       }
+
+       function notFoundErrorCB(err)
+       {
+               if (err.name == NOT_FOUND_ERR) {
+                       TestEngine.test("[Application] cannot found", true);
+               } else {
+                       TestEngine.test("", false);
+               }
+       }
+
+       try {
+               var cbObj = TestEngine.registerCallback("kill", foundSuccessCB, notFoundErrorCB);
+               tizen.application.kill(null, cbObj.successCallback, cbObj.errorCallback);
+       } catch (err) {
+               TestEngine.test("", false);
+       }
+       TestEngine.log("[Application] UTC_application_kill_N_004 END");
+ }
+
+function UTC_application_kill_N_005()
+{
+       TestEngine.log("[Application] UTC_application_kill_N_005 START");
+
+       function foundSuccessCB(err)
+       {
+               TestEngine.test("", false);
+       }
+
+       function notFoundErrorCB(err)
+       {
+               if (err.name == NOT_FOUND_ERR) {
+                       TestEngine.test("[Application] cannot found", true);
+               } else {
+                       TestEngine.test("", false);
+               }
+       }
+
+       try {
+               var cbObj = TestEngine.registerCallback("kill", foundSuccessCB, notFoundErrorCB);
+               tizen.application.kill(TEST_OBJ, cbObj.successCallback, cbObj.errorCallback);
+       } catch (err) {
+               TestEngine.test("", false);
+       }
+       TestEngine.log("[Application] UTC_application_kill_N_005 END");
+}
+
+function UTC_application_kill_N_006()
+{
+       TestEngine.log("[Application] UTC_application_kill_N_006 START");
+
+       function foundSuccessCB(err)
+       {
+               TestEngine.test("", false);
+       }
+
+       function notFoundErrorCB(err)
+       {
+               if (err.name == NOT_FOUND_ERR) {
+                       TestEngine.test("[Application] cannot found", true);
+               } else {
+                       TestEngine.test("", false);
+               }
+       }
+
+       try {
+               var cbObj = TestEngine.registerCallback("kill", foundSuccessCB, notFoundErrorCB);
+               tizen.application.kill(TEST_FUN, cbObj.successCallback, cbObj.errorCallback);
+       } catch (err) {
+               TestEngine.test("", false);
+       }
+       TestEngine.log("[Application] UTC_application_kill_N_006 END");
+}
+
+function UTC_application_exit()
+{
+       tizen.application.currentApplication().exit();
+}
+
+function UTC_application_hide()
+{
+       tizen.application.currentApplication().hide();
+}
+
+var appControl1 = new tizen.ApplicationControl(TEST_APP_CONTROL_OPERATION_1);
+var appControl2 = new tizen.ApplicationControl(TEST_APP_CONTROL_OPERATION_2);
+var appControl3 = new tizen.ApplicationControl(TEST_APP_CONTROL_OPERATION_3);
+
+function UTC_application_findAppControl_P_001()
+{
+       TestEngine.log("[Application] UTC_application_launchAppControl_P_001 START");
+       try {
+               var cbObj = TestEngine.registerCallback("findAppControl", onSuccessCB, onErrorCB);
+               tizen.application.findAppControl(appControl1, cbObj.successCallback);
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_launchAppControl_P_001 error : " + err, false);
+       }
+
+       TestEngine.log("[Application] UTC_application_launchAppControl_P_001 END");
+}
+
+function UTC_application_findAppControl_P_002()
+{
+       TestEngine.log("[Application] UTC_application_findAppControl_P_002 START");
+       try {
+               var cbObj = TestEngine.registerCallback("findAppControl", onSuccessCB, onErrorCB);
+               tizen.application.findAppControl(appControl2, cbObj.successCallback, cbObj.errorCallback);
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_findAppControl_P_002 error : " + err, false);
+       }
+
+       TestEngine.log("[Application] UTC_application_findAppControl_P_002 END");
+}
+
+function UTC_application_findAppControl_P_003()
+{
+       TestEngine.log("[Application] UTC_application_findAppControl_P_003 START");
+       try {
+               var cbObj = TestEngine.registerCallback("findAppControl", onSuccessCB, onErrorCB);
+               tizen.application.findAppControl(appControl3, cbObj.successCallback, cbObj.errorCallback, undefined);
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_findAppControl_P_003 error : " + err, false);
+       }
+
+       TestEngine.log("[Application] UTC_application_findAppControl_P_003 END");
+}
+
+function UTC_application_findAppControl_N_001()
+{
+       TestEngine.log("[Application] UTC_application_findAppControl_N_001 START");
+
+       TestEngine.log("First parameter check.");
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR , tizen.application, "findAppControl", null,                onSuccessCB, onErrorCB);
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR , tizen.application, "findAppControl", undefined,   onSuccessCB, onErrorCB);
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR , tizen.application, "findAppControl", TEST_STR,    onSuccessCB, onErrorCB);
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR , tizen.application, "findAppControl", TEST_NUM,    onSuccessCB, onErrorCB);
+
+       TestEngine.log("Second parameter check.");
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR , tizen.application, "findAppControl", appControl1, TEST_STR,       onErrorCB);
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR , tizen.application, "findAppControl", appControl1, TEST_NUM,       onErrorCB);
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR , tizen.application, "findAppControl", appControl1, TEST_OBJ,       onErrorCB);
+
+       TestEngine.log("Third parameter check.");
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR , tizen.application, "findAppControl", appControl1, onSuccessCB, TEST_STR);
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR , tizen.application, "findAppControl", appControl1, onSuccessCB, TEST_NUM);
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR , tizen.application, "findAppControl", appControl1, onSuccessCB, TEST_OBJ);
+
+       TestEngine.log("[Application] UTC_application_findAppControl_N_001 END");
+}
+
+
+function findAndKill(contexts)
+{
+       TestEngine.log("[findAndKill][START]");
+
+       try {
+               TestEngine.log("AppContext Array Length = " + contexts.length);
+
+               for(var num=0; num < contexts.length; num++)
+               {
+                       if ((contexts[num].appId == TEST_APP_ID_1) ||
+                                (contexts[num].appId == TEST_APP_ID_2) ||
+                                (contexts[num].appId == TEST_APP_ID_3)) {
+                               TestEngine.log("kill : id = "+contexts[num].id);
+                               tizen.application.kill(contexts[num].id);
+                       }
+               }
+       } catch (ex) {
+               TestEngine.test("[Application] findAndKill error: " + ex, false);
+       }
+       TestEngine.log("[findAndKill][END]");
+}
+
+function UTC_application_launchAppControl_P_000()
+{
+       TestEngine.log("[Application] UTC_application_launchAppControl_P_000 START");
+
+       TestEngine.setInterval(1000);
+
+       try {
+               var cbObj = TestEngine.registerCallback("launchAppControl", onSuccessCB, onErrorCB);
+               tizen.application.launchAppControl(appControl1, undefined, cbObj.successCallback);
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_launchAppControl_P_000 error : " + err, false);
+       }
+
+       TestEngine.log("[Application] UTC_application_launchAppControl_P_000 END");
+}
+
+function UTC_application_launchAppControl_P_001()
+{
+       TestEngine.log("[Application] UTC_application_launchAppControl_P_001 START");
+
+       TestEngine.setInterval(1000);
+
+       try {
+               var cbObj = TestEngine.registerCallback("launchAppControl", onSuccessCB, onErrorCB);
+
+               var onSuccess = function() {
+                       setTimeout(cbObj.successCallback, 1000);
+               }
+               
+               tizen.application.launchAppControl(appControl1, null, onSuccess);
+               
+               //var cbObj2 = TestEngine.registerCallback("getAppsContext", findAndKill, onErrorCB);
+               //tizen.application.getAppsContext(cbObj2.successCallback, cbObj2.errorCallback);
+
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_launchAppControl_P_001 error : " + err, false);
+       }
+
+       TestEngine.log("[Application] UTC_application_launchAppControl_P_001 END");
+}
+
+function UTC_application_launchAppControl_P_002()
+{
+       TestEngine.log("[Application] UTC_application_launchAppControl_P_002 START");
+
+       TestEngine.setInterval(1000);
+
+       try {
+               var cbObj = TestEngine.registerCallback("launchAppControl", onSuccessCB, onErrorCB);
+
+               var onSuccess = function() {
+                       setTimeout(cbObj.successCallback, 1000);
+               }
+               
+               tizen.application.launchAppControl(appControl2, null, onSuccess, cbObj.errorCallback);
+               //var cbObj2 = TestEngine.registerCallback("getAppsContext", findAndKill, onErrorCB);
+               //tizen.application.getAppsContext(cbObj2.successCallback, cbObj2.errorCallback);               
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_launchAppControl_P_002 error : " + err, false);
+       }
+
+       TestEngine.log("[Application] UTC_application_launchAppControl_P_002 END");
+}
+
+function UTC_application_launchAppControl_P_003()
+{
+       TestEngine.log("[Application] UTC_application_launchAppControl_P_003 START");
+
+       TestEngine.setInterval(1000);
+
+       try {
+               var cbObj = TestEngine.registerCallback("launchAppControl", onSuccessCB, onErrorCB);
+
+               var onSuccess = function() {
+                       setTimeout(cbObj.successCallback, 1000);
+               }
+               
+               tizen.application.launchAppControl(appControl3, TEST_APP_ID_3, onSuccess, cbObj.errorCallback, null);
+               //var cbObj2 = TestEngine.registerCallback("getAppsContext", findAndKill, onErrorCB);
+               //tizen.application.getAppsContext(cbObj2.successCallback, cbObj2.errorCallback);               
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_launchAppControl_P_003 error : " + err, false);
+       }
+
+       TestEngine.log("[Application] UTC_application_launchAppControl_P_003 END");
+}
+
+function UTC_application_launchAppControl_P_004()
+{
+       TestEngine.log("[Application] UTC_application_launchAppControl_P_004 START");
+
+       TestEngine.setInterval(1000);
+
+       var cbObj = TestEngine.registerCallback("launchAppControl", onSuccessCB, onErrorCB);
+
+       var data = [
+               new tizen.ApplicationControlData("key1", ["data1"]),
+               new tizen.ApplicationControlData("key2", ["data2", "data3"])
+       ];
+
+       var replyCB = {
+               onsuccess : function(reply) {
+                       TestEngine.log("[Application] UTC_application_launchAppControl_P_004 replyCB : onSuccess");
+                       for (var i=0; i < reply.length; i++) {
+                               TestEngine.log("[UTC_application_launchAppControl_P_004][REPLY] key("+reply[i].key+"), data("+reply[i].value+")");
+                       }
+                       TestEngine.test("[Application] UTC_application_launchAppControl_P_004", true);
+                       cbObj.successCallback();
+                       //var cbObj2 = TestEngine.registerCallback("getAppsContext", findAndKill, onErrorCB);
+                       //tizen.application.getAppsContext(cbObj2.successCallback, cbObj2.errorCallback);                       
+               },
+               onfailure : function() {
+                       TestEngine.log("[Application] UTC_application_launchAppControl_P_004 replyCB : onFailed");
+                       TestEngine.test("[Application] failed to get the reply from the callee error : " + err, false);
+                       cbObj.errorCallback();
+               }
+       };
+
+       try {
+               var appControl = new tizen.ApplicationControl(
+                       TEST_APP_CONTROL_OPERATION_1,
+                       null,
+                       null,
+                       null,
+                       data);
+
+               tizen.application.launchAppControl(appControl, null,
+                       function() {
+                               TestEngine.log("[Application] UTC_application_launchAppControl_P_004 call success");
+                       },
+                       onErrorCB,
+                       replyCB);
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_launchAppControl_P_004 error : " + err, false);
+       }
+
+       TestEngine.log("[Application] UTC_application_launchAppControl_P_004 END");
+}
+
+function UTC_application_launchAppControl_P_005()
+{
+       TestEngine.log("[Application] UTC_application_launchAppControl_P_005 START");
+
+       TestEngine.setInterval(1000);
+
+       var cbObj = TestEngine.registerCallback("launchAppControl", onSuccessCB, onErrorCB);
+
+       var data = [
+               new tizen.ApplicationControlData("key1", ["data1"]),
+               new tizen.ApplicationControlData("key2", ["data2", "data3"])
+       ];
+
+       var replyCB = {
+               onsuccess : function(reply) {
+                       TestEngine.log("[Application] UTC_application_launchAppControl_P_005 replyCB : onSuccess");
+                       for (var i=0; i < reply.length; i++) {
+                               TestEngine.log("[UTC_application_launchAppControl_P_005][REPLY] key("+reply[i].key+"), data("+reply[i].value+")");
+                       }
+                       TestEngine.test("[Application] UTC_application_launchAppControl_P_005", true);
+                       cbObj.successCallback();
+                       //var cbObj2 = TestEngine.registerCallback("getAppsContext", findAndKill, onErrorCB);
+                       //tizen.application.getAppsContext(cbObj2.successCallback, cbObj2.errorCallback);
+               },
+               onfailure : function() {
+                       TestEngine.log("[Application] UTC_application_launchAppControl_P_005 replyCB : onFailed");
+                       TestEngine.test("[Application] failed to get the reply from the callee error : " + err, false);
+                       cbObj.errorCallback();
+               }
+       };
+
+       try {
+               var appControl = new tizen.ApplicationControl(
+                       TEST_APP_CONTROL_OPERATION_2,
+                       null,
+                       null,
+                       null,
+                       data);
+
+               tizen.application.launchAppControl(appControl, undefined,
+                       function() {
+                               TestEngine.log("[Application] UTC_application_launchAppControl_P_005 call success");
+                       },
+                       onErrorCB,
+                       replyCB);
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_launchAppControl_P_005 error : " + err, false);
+       }
+
+       TestEngine.log("[Application] UTC_application_launchAppControl_P_005 END");
+}
+
+function UTC_application_launchAppControl_P_006()
+{
+       TestEngine.log("[Application] UTC_application_launchAppControl_P_006 START");
+
+       TestEngine.setInterval(1000);
+
+       var cbObj = TestEngine.registerCallback("launchAppControl", onSuccessCB, onErrorCB);
+
+       var data = [
+               new tizen.ApplicationControlData("key1", ["data1"]),
+               new tizen.ApplicationControlData("key2", ["data2", "data3"])
+       ];
+
+       var replyCB = {
+               onsuccess : function(reply) {
+                       TestEngine.log("[Application] UTC_application_launchAppControl_P_006 replyCB : onSuccess");
+                       for (var i=0; i < reply.length; i++) {
+                               TestEngine.log("[UTC_application_launchAppControl_P_004][REPLY] key("+reply[i].key+"), data("+reply[i].value+")");
+                       }
+                       TestEngine.test("[Application] UTC_application_launchAppControl_P_006", true);
+                       cbObj.successCallback();
+                       //var cbObj2 = TestEngine.registerCallback("getAppsContext", findAndKill, onErrorCB);
+                       //tizen.application.getAppsContext(cbObj2.successCallback, cbObj2.errorCallback);
+               },
+               onfailure : function() {
+                       TestEngine.log("[Application] UTC_application_launchAppControl_P_006 replyCB : onFailed");
+                       TestEngine.test("[Application] failed to get the reply from the callee error : " + err, false);
+                       cbObj.errorCallback();
+               }
+       };
+
+       try {
+               var appControl = new tizen.ApplicationControl(
+                       TEST_APP_CONTROL_OPERATION_3,
+                       null,
+                       null,
+                       null,
+                       data);
+
+               tizen.application.launchAppControl(appControl, null,
+                       function() {
+                               TestEngine.log("[Application] UTC_application_launchAppControl_P_006 call success");
+                       },
+                       onErrorCB,
+                       replyCB,
+                       undefined);
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_launchAppControl_P_006 error : " + err, false);
+       }
+
+       TestEngine.log("[Application] UTC_application_launchAppControl_P_006 END");
+}
+
+function UTC_application_launchAppControl_P_007()
+{
+       TestEngine.log("[Application] UTC_application_launchAppControl_P_007 START");
+
+       TestEngine.setInterval(1000);
+
+       var cbObj = TestEngine.registerCallback("launchAppControl", onSuccessCB, onErrorCB);
+
+       var data = [
+               new tizen.ApplicationControlData("key1", ["data1"]),
+               new tizen.ApplicationControlData("key2", ["data2", "data3"])
+       ];
+
+       var replyCB = {
+               onsuccess : function(reply) {
+                       TestEngine.log("[Application] UTC_application_launchAppControl_P_009 replyCB : onSuccess");
+                       for (var i=0; i < reply.length; i++) {
+                               TestEngine.log("[UTC_application_launchAppControl_P_009][REPLY] key("+reply[i].key+"), data("+reply[i].value+")");
+                       }
+                       TestEngine.test("[Application] UTC_application_launchAppControl_P_009", true);
+                       cbObj.successCallback();
+                       //var cbObj2 = TestEngine.registerCallback("getAppsContext", findAndKill, onErrorCB);
+                       //tizen.application.getAppsContext(cbObj2.successCallback, cbObj2.errorCallback);                       
+               }
+       };
+
+       try {
+               var appControl = new tizen.ApplicationControl(
+                       TEST_APP_CONTROL_OPERATION_1,
+                       null,
+                       null,
+                       null,
+                       data);
+
+               tizen.application.launchAppControl(appControl, null,
+                       function() {
+                               TestEngine.log("[Application] UTC_application_launchAppControl_P_007 call success");
+                       },
+                       onErrorCB,
+                       replyCB);
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_launchAppControl_P_007 error : " + err, false);
+       }
+
+       TestEngine.log("[Application] UTC_application_launchAppControl_P_007 END");
+}
+
+function UTC_application_launchAppControl_P_008()
+{
+       TestEngine.log("[Application] UTC_application_launchAppControl_P_008 START");
+
+       TestEngine.setInterval(1000);
+
+       var cbObj = TestEngine.registerCallback("launchAppControl", onSuccessCB, onErrorCB);
+
+       var data = [
+               new tizen.ApplicationControlData("key1", ["data1"]),
+               new tizen.ApplicationControlData("key2", ["data2", "data3"])
+       ];
+
+       var replyCB = {
+       };
+
+       try {
+               var appControl = new tizen.ApplicationControl(
+                       TEST_APP_CONTROL_OPERATION_2,
+                       null,
+                       null,
+                       null,
+                       data);
+
+               tizen.application.launchAppControl(appControl, null,
+                       function() {
+                               TestEngine.log("[Application] UTC_application_launchAppControl_P_008 call success");
+                       },
+                       onErrorCB,
+                       replyCB);
+
+               cbObj.successCallback();
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_launchAppControl_P_008 error : " + err, false);
+       }
+
+       TestEngine.log("[Application] UTC_application_launchAppControl_P_008 END");
+}
+
+function UTC_application_launchAppControl_P_009()
+{
+       TestEngine.log("[Application] UTC_application_launchAppControl_P_009 START");
+
+       TestEngine.setInterval(1000);
+
+       var cbObj = TestEngine.registerCallback("launchAppControl", onSuccessCB, onErrorCB);
+
+       var data = [
+               new tizen.ApplicationControlData("key1", ["data1"]),
+               new tizen.ApplicationControlData("key2", ["data2", "data3"])
+       ];
+
+       var replyCB = {
+               onfailure : function() {
+                       TestEngine.log("[Application] UTC_application_launchAppControl_P_005 replyCB : onFailed");
+                       cbObj.successCallback();
+               }
+       };
+
+       try {
+               var appControl = new tizen.ApplicationControl(
+                       TEST_APP_CONTROL_OPERATION_3,
+                       null,
+                       null,
+                       null,
+                       data);
+
+               tizen.application.launchAppControl(appControl, null,
+                       function() {
+                               TestEngine.log("[Application] UTC_application_launchAppControl_P_009 call success");
+                       },
+                       onErrorCB,
+                       replyCB);
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_launchAppControl_P_009 error : " + err, false);
+       }
+
+       TestEngine.log("[Application] UTC_application_launchAppControl_P_009 END");
+}
+
+function UTC_application_launchAppControl_P_010()
+{
+       TestEngine.log("[Application] UTC_application_launchAppControl_P_010 START");
+
+       TestEngine.setInterval(1000);
+
+       var cbObj = TestEngine.registerCallback("launchAppControl", onSuccessCB, onErrorCB);
+
+       var data = [
+               new tizen.ApplicationControlData("key1", ["data1"]),
+               new tizen.ApplicationControlData("key2", ["data2", "data3"])
+       ];
+
+       var replyCB = {
+               onsuccess : function(reply) {
+                       TestEngine.log("[Application] UTC_application_launchAppControl_P_010 onsuccess : onFailed");
+                       TestEngine.test("[Application] this test should have to get onfailure", false);
+                       cbObj.errorCallback();
+               },
+               onfailure : function() {
+                       TestEngine.log("[Application] UTC_application_launchAppControl_P_010 replyCB : onfailure");
+                       TestEngine.test("[Application] UTC_application_launchAppControl_P_010", true);
+                       cbObj.successCallback();
+               }
+       };
+
+       try {
+               var appControl = new tizen.ApplicationControl(
+                       TEST_APP_CONTROL_OPERATION_N,
+                       null,
+                       null,
+                       null,
+                       data);
+
+               tizen.application.launchAppControl(appControl, null,
+                       function() {
+                               TestEngine.log("[Application] UTC_application_launchAppControl_P_010 call success");
+                       },
+                       onErrorCB,
+                       replyCB);
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_launchAppControl_P_010 error : " + err, false);
+       }
+
+       TestEngine.log("[Application] UTC_application_launchAppControl_P_010 END");
+}
+
+function UTC_application_launchAppControl_P_011()
+{
+       TestEngine.log("[Application] UTC_application_launchAppControl_P_011 START");
+
+       TestEngine.setInterval(1000);
+
+       var cbObj = TestEngine.registerCallback("launchAppControl", onSuccessCB, onErrorCB);
+
+       var data = [
+               new tizen.ApplicationControlData("key1", ["data1"]),
+               new tizen.ApplicationControlData("key2", ["data2", "data3"])
+       ];
+
+       var replyCB = {
+               onsuccess : function(reply) {
+                       TestEngine.log("[Application] UTC_application_launchAppControl_P_011 replyCB : onSuccess");
+                       for (var i=0; i < reply.length; i++) {
+                               TestEngine.log("[UTC_application_launchAppControl_P_011][REPLY] key("+reply[i].key+"), data("+reply[i].value+")");
+                       }
+                       TestEngine.test("[Application] UTC_application_launchAppControl_P_011", true);
+                       cbObj.successCallback();
+               },
+               onfailure : function() {
+                       TestEngine.log("[Application] UTC_application_launchAppControl_P_011 replyCB : onFailed");
+                       TestEngine.test("[Application] failed to get the reply from the callee error : " + err, false);
+                       cbObj.errorCallback();
+               }
+       };
+
+       try {
+               var appControl = new tizen.ApplicationControl(
+                       TEST_APP_CONTROL_OPERATION_2,
+                       null,
+                       null,
+                       null,
+                       data);
+
+               tizen.application.launchAppControl(appControl, null,
+                       function() {
+                               TestEngine.log("[Application] UTC_application_launchAppControl_P_011 call success");
+                       },
+                       onErrorCB,
+                       replyCB);
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_launchAppControl_P_011 error : " + err, false);
+       }
+
+       TestEngine.log("[Application] UTC_application_launchAppControl_P_011 END");
+}
+
+
+function UTC_application_launchAppControl_N_001()
+{
+       TestEngine.log("[Application] UTC_application_launchAppControl_N_001 START");
+
+       TestEngine.log("First parameter check.");
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR , tizen.application, "launchAppControl", null,              null, onSuccessCB, onErrorCB);
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR , tizen.application, "launchAppControl", undefined,         null, onSuccessCB, onErrorCB);
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR , tizen.application, "launchAppControl", TEST_STR,  null, onSuccessCB, onErrorCB);
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR , tizen.application, "launchAppControl", TEST_NUM,  null, onSuccessCB, onErrorCB);
+
+       TestEngine.log("Third parameter check.");
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR , tizen.application, "launchAppControl", appControl1, null, TEST_STR,       onErrorCB);
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR , tizen.application, "launchAppControl", appControl1, null, TEST_NUM,       onErrorCB);
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR , tizen.application, "launchAppControl", appControl1, null, TEST_OBJ,       onErrorCB);
+
+       TestEngine.log("Fourth parameter check.");
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR , tizen.application, "launchAppControl", appControl1, null, onSuccessCB, TEST_STR);
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR , tizen.application, "launchAppControl", appControl1, null, onSuccessCB, TEST_NUM);
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR , tizen.application, "launchAppControl", appControl1, null, onSuccessCB, TEST_OBJ);
+
+       TestEngine.log("Fifth parameter check.");
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR , tizen.application, "launchAppControl", appControl1, null, onSuccessCB, onErrorCB, TEST_STR);
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR , tizen.application, "launchAppControl", appControl1, null, onSuccessCB, onErrorCB, TEST_NUM);
+
+       TestEngine.log("[Application] UTC_application_launchAppControl_N_001 END");
+}
+
+function UTC_application_launchAppControl_N_002()
+{
+       TestEngine.log("[Application] UTC_application_launchAppControl_N_002 START");
+
+       function notFoundErrorCB(err)
+       {
+               if (err.name == NOT_FOUND_ERR) {
+                       TestEngine.test("[Application] cannot found", true);
+               } else {
+                       TestEngine.test("", false);
+               }
+       }
+
+   var appControl = new tizen.ApplicationControl(
+                  TEST_ILLEGAL_APP_CONTROL_OPERATION,
+                  null,
+                  null,
+                  null);
+
+       try {
+               var cbObj = TestEngine.registerCallback("launchAppControl", onSuccessCB, notFoundErrorCB);
+               tizen.application.launchAppControl(appControl, undefined, cbObj.successCallback, cbObj.errorCallback);
+       } catch (err) {
+               TestEngine.test("", false);
+       }
+       TestEngine.log("[Application] UTC_application_launchAppControl_N_002 END");
+}
+
+function UTC_application_getRequestedAppControl_P_001()
+{
+       TestEngine.log("[Application] UTC_application_getRequestedAppControl_P_001 START");
+
+       try {
+               var request = tizen.application.getCurrentApplication().getRequestedAppControl();
+               if (request == null) {
+                       TestEngine.test("[Application] UTC_application_getRequestedAppControl_P_001 Success", true);
+               } else {
+                       TestEngine.test("[Application] UTC_application_getRequestedAppControl_P_001 error : " + err, false);
+               }
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_getRequestedAppControl_P_001 error : " + err, false);
+       }
+
+       TestEngine.log("[Application] UTC_application_getRequestedAppControl_P_001 END");
+}
+
+function UTC_application_getRequestedAppControl_P_002()
+{
+       TestEngine.log("[Application] UTC_application_getRequestedAppControl_P_002 START");
+
+       try {
+               var request = tizen.application.getCurrentApplication().getRequestedAppControl(undefined);
+               if (request == null) {
+                       TestEngine.test("[Application] UTC_application_getRequestedAppControl_P_002 Success", true);
+               } else {
+                       TestEngine.test("[Application] UTC_application_getRequestedAppControl_P_002 error : " + err, false);
+               }
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_getRequestedAppControl_P_002 error : " + err, false);
+       }
+
+       TestEngine.log("[Application] UTC_application_getRequestedAppControl_P_002 END");
+}
+
+var TEST_CONTEXT_ID;
+
+function contextlist(contexts)
+{
+       TestEngine.log("[contextlist][START]");
+
+       try {
+               TestEngine.log("AppContext Array Length = " + contexts.length);
+
+               for(var num=0; num < contexts.length; num++)
+               {
+                       if (num == 0) {
+                               TEST_CONTEXT_ID = contexts[num].id;
+                       }
+                       TestEngine.log("AppContext["+num+"].id = "+contexts[num].id);
+                       TestEngine.log("AppContext["+num+"].appId = "+contexts[num].appId);
+               }
+       } catch (ex) {
+               TestEngine.test("[Application] contextlist error: " + ex, false);
+       }
+       TestEngine.test("contextlist", true);
+       TestEngine.log("[contextlist][END]");
+}
+
+function UTC_application_getAppsContext_P_001()
+{
+       TestEngine.log("[Application] UTC_application_getAppsContext_P_001 START");
+
+       try {
+               var cbObj = TestEngine.registerCallback("getAppsContext", contextlist, onErrorCB);
+               tizen.application.getAppsContext(cbObj.successCallback, cbObj.errorCallback);
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_getAppsContext_P_001 err : " + err, false);
+       }
+
+       TestEngine.log("[Application] UTC_application_getAppsContext_P_001 END");
+}
+
+function UTC_application_getAppsContext_P_002()
+{
+       TestEngine.log("[Application] UTC_application_getAppsContext_P_002 START");
+
+       try {
+               var cbObj = TestEngine.registerCallback("getAppsContext", contextlist, onErrorCB);
+               tizen.application.getAppsContext(cbObj.successCallback);
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_getAppsContext_P_002 err : " + err, false);
+       }
+
+       TestEngine.log("[Application] UTC_application_getAppsContext_P_002 END");
+}
+
+function UTC_application_getAppsContext_P_003()
+{
+       TestEngine.log("[Application] UTC_application_getAppsContext_P_003 START");
+
+       try {
+               var cbObj = TestEngine.registerCallback("getAppsContext", contextlist, onErrorCB);
+               tizen.application.getAppsContext(cbObj.successCallback, null);
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_getAppsContext_P_003 err : " + err, false);
+       }
+
+       TestEngine.log("[Application] UTC_application_getAppsContext_P_003 END");
+}
+
+function UTC_application_getAppsContext_P_005()
+{
+       TestEngine.log("[Application] UTC_application_getAppsContext_P_005 START");
+
+       try {
+               var cbObj = TestEngine.registerCallback("getAppsContext", contextlist, onErrorCB);
+               tizen.application.getAppsContext(cbObj.successCallback, null, undefined);
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_getAppsContext_P_005 err : " + err, false);
+       }
+
+       TestEngine.log("[Application] UTC_application_getAppsContext_P_005 END");
+}
+
+function UTC_application_getAppsContext_N_001()
+{
+       TestEngine.log("[Application] UTC_application_getAppsContext_N_001 START");
+
+       // first parameter
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.application, "getAppsContext", null,         onErrorCB);
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.application, "getAppsContext", undefined,    onErrorCB);
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.application, "getAppsContext", TEST_STR,     onErrorCB);
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.application, "getAppsContext", TEST_NUM,     onErrorCB);
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.application, "getAppsContext", TEST_OBJ,     onErrorCB);
+
+       // second parameter
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.application, "getAppsContext", contextlist, TEST_STR);
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.application, "getAppsContext", contextlist, TEST_NUM);
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.application, "getAppsContext", contextlist, TEST_OBJ);
+
+       TestEngine.log("[Application] UTC_application_getAppsContext_N_001 END");
+}
+
+function infolist(infos)
+{
+       TestEngine.log("[infolist][START]");
+
+       try {
+               TestEngine.log("AppInfo Array Length = " + infos.length);
+
+               for(var num=0; num < infos.length; num++)
+               {
+                       TestEngine.log("AppInfo["+num+"].name = "+infos[num].name);
+                       TestEngine.log("AppInfo["+num+"].id = "+infos[num].id);
+               }
+       } catch (ex) {
+               TestEngine.test("[Application] UTC_application_getAppsInfo error: " + ex, false);
+       }
+       TestEngine.test("UTC_application_getAppsInfo", true);
+       TestEngine.log("[infolist][END]");
+}
+
+function UTC_application_getAppsInfo_P_001()
+{
+       TestEngine.log("[Application] UTC_application_getAppsInfo_P_001 START");
+
+       try {
+               var cbObj = TestEngine.registerCallback("getAppsInfo", infolist, onErrorCB);
+               tizen.application.getAppsInfo(cbObj.successCallback, cbObj.errorCallback);
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_getAppsInfo_P_001 err : " + err, false);
+       }
+
+       TestEngine.log("[Application] UTC_application_getAppsInfo_P_001 END");
+}
+
+function UTC_application_getAppsInfo_P_002()
+{
+       TestEngine.log("[Application] UTC_application_getAppsInfo_P_002 START");
+
+       try {
+               var cbObj = TestEngine.registerCallback("getAppsInfo", infolist, onErrorCB);
+               tizen.application.getAppsInfo(cbObj.successCallback);
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_getAppsInfo_P_002 err : " + err, false);
+       }
+
+       TestEngine.log("[Application] UTC_application_getAppsInfo_P_002 END");
+}
+
+function UTC_application_getAppsInfo_P_003()
+{
+       TestEngine.log("[Application] UTC_application_getAppsInfo_P_003 START");
+
+       try {
+               var cbObj = TestEngine.registerCallback("getAppsInfo", infolist, onErrorCB);
+               tizen.application.getAppsInfo(cbObj.successCallback, null);
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_getAppsInfo_P_003 err : " + err, false);
+       }
+
+       TestEngine.log("[Application] UTC_application_getAppsInfo_P_003 END");
+}
+
+function UTC_application_getAppsInfo_P_005()
+{
+       TestEngine.log("[Application] UTC_application_getAppsInfo_P_005 START");
+
+       try {
+               var cbObj = TestEngine.registerCallback("getAppsInfo", infolist, onErrorCB);
+               tizen.application.getAppsInfo(cbObj.successCallback, null, undefined);
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_getAppsInfo_P_005 err : " + err, false);
+       }
+
+       TestEngine.log("[Application] UTC_application_getAppsInfo_P_005 END");
+}
+
+function UTC_application_getAppsInfo_N_001()
+{
+       TestEngine.log("[Application] UTC_application_getAppsInfo_N_001 START");
+
+       // first parameter
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.application, "getAppsInfo", null,            onErrorCB);
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.application, "getAppsInfo", undefined,       onErrorCB);
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.application, "getAppsInfo", TEST_STR,        onErrorCB);
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.application, "getAppsInfo", TEST_NUM,        onErrorCB);
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.application, "getAppsInfo", TEST_OBJ,        onErrorCB);
+
+       // second parameter
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.application, "getAppsInfo", infolist, TEST_STR);
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.application, "getAppsInfo", infolist, TEST_NUM);
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.application, "getAppsInfo", infolist, TEST_OBJ);
+
+       TestEngine.log("[Application] UTC_application_getAppsInfo_N_001 END");
+}
+
+function UTC_application_getAppContext_P_001()
+{
+       TestEngine.log("[Application] UTC_application_getCurrentApplicationcontext_P_001 START");
+
+       try {
+               var context = tizen.application.getAppContext();
+               if (context.appId != CURR_APP_ID) {
+                       TestEngine.test("[Application] UTC_application_getAppContext_P_001 err : current context is not same", false);
+               }
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_getAppContext_P_001 err : " + err, false);
+       }
+       TestEngine.test("[Application] UTC_application_getCurrentApplicationcontext_P_001", true);
+
+       TestEngine.log("[Application] UTC_application_getCurrentApplicationcontext_P_001 END");
+}
+
+function UTC_application_getAppContext_P_003()
+{
+       TestEngine.log("[Application] UTC_application_getAppContext_P_003 START");
+
+       try {
+               var context = tizen.application.getAppContext(null);
+               if (context.appId != CURR_APP_ID) {
+                       TestEngine.log("[Application] appId : " + context.appId);
+                       TestEngine.log("[Application] curr_app_id : " + CURR_APP_ID);
+                       TestEngine.test("[Application] UTC_application_getAppContext_P_003 err : current context is not same", false);
+               }
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_getAppContext_P_003 err : " + err, false);
+       }
+       TestEngine.test("[Application] UTC_application_getAppContext_P_003", true);
+
+       TestEngine.log("[Application] UTC_application_getAppContext_P_003 END");
+}
+
+function UTC_application_getAppContext_P_004()
+{
+       TestEngine.log("[Application] UTC_application_getAppContext_P_004 START");
+
+       try {
+               var context = tizen.application.getAppContext(TEST_CONTEXT_ID);
+               if (context.id != TEST_CONTEXT_ID) {
+                       TestEngine.log("[Application] appId : " + context.appId);
+                       TestEngine.log("[Application] test context id : " + TEST_CONTEXT_ID);
+                       TestEngine.test("[Application] UTC_application_getAppContext_P_004 err : current context is not same", false);
+               } else {
+                       TestEngine.log("[Application] appId : " + context.appId);
+                       TestEngine.log("[Application] test context id : " + TEST_CONTEXT_ID);
+               }
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_getAppContext_P_004 err : " + err, false);
+       }
+       TestEngine.test("[Application] UTC_application_getAppContext_P_004", true);
+
+       TestEngine.log("[Application] UTC_application_getAppContext_P_004 END");
+}
+
+function UTC_application_getAppContext_N_001()
+{
+       TestEngine.log("[Application] UTC_application_getAppContext_N_001 START");
+
+       TestEngine.catchErrorType("name", NOT_FOUND_ERR, tizen.application, "getAppContext", TEST_OBJ);
+       TestEngine.catchErrorType("name", NOT_FOUND_ERR, tizen.application, "getAppContext", TEST_FUN);
+
+       TestEngine.catchErrorType("name", NOT_FOUND_ERR, tizen.application, "getAppContext", "9999");
+       TestEngine.catchErrorType("name", NOT_FOUND_ERR, tizen.application, "getAppContext", "Hello");
+       TestEngine.catchErrorType("name", NOT_FOUND_ERR, tizen.application, "getAppContext", 9999);
+
+       TestEngine.log("[Application] UTC_application_getAppContext_N_001 END");
+}
+
+function UTC_application_getAppInfo_P_001()
+{
+       TestEngine.log("[Application] UTC_application_getAppInfo_P_001 START");
+
+       try {
+               var info = tizen.application.getAppInfo(CURR_APP_ID);
+               TestEngine.log("AppInfo.name = "+info.name);
+               TestEngine.log("AppInfo.id = "+info.id);
+               if (info.id != CURR_APP_ID) {
+                       TestEngine.test("[Application] UTC_application_getAppInfo_P_001 err : current context is not same", false);
+               }
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_getAppInfo_P_001 err : " + err, false);
+       }
+       TestEngine.test("[Application] UTC_application_getAppInfo_P_001", true);
+
+       TestEngine.log("[Application] UTC_application_getAppInfo_P_001 END");
+}
+
+function UTC_application_getAppInfo_P_002()
+{
+       TestEngine.log("[Application] UTC_application_getAppInfo_P_002 START");
+
+       try {
+               var info = tizen.application.getAppInfo(null);
+               TestEngine.log("AppInfo.name = "+info.name);
+               TestEngine.log("AppInfo.id = "+info.id);
+               if (info.id != CURR_APP_ID) {
+                       TestEngine.test("[Application] UTC_application_getAppInfo_P_002 err : current context is not same", false);
+               }
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_getAppInfo_P_002 err : " + err, false);
+       }
+       TestEngine.test("[Application] UTC_application_getAppInfo_P_002", true);
+
+       TestEngine.log("[Application] UTC_application_getAppInfo_P_002 END");
+}
+
+function UTC_application_getAppInfo_P_003()
+{
+       TestEngine.log("[Application] UTC_application_getAppInfo_P_002 START");
+
+       try {
+               var info = tizen.application.getAppInfo();
+               TestEngine.log("AppInfo.name = "+info.name);
+               TestEngine.log("AppInfo.id = "+info.id);
+               if (info.id != CURR_APP_ID) {
+                       TestEngine.test("[Application] UTC_application_getAppInfo_P_002 err : current context is not same", false);
+               }
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_getAppInfo_P_002 err : " + err, false);
+       }
+       TestEngine.test("[Application] UTC_application_getAppInfo_P_002", true);
+
+       TestEngine.log("[Application] UTC_application_getAppInfo_P_002 END");
+}
+
+function UTC_application_getAppInfo_N_001()
+{
+       TestEngine.log("[Application] UTC_application_getAppInfo_N_001 START");
+
+       TestEngine.catchErrorType("name", NOT_FOUND_ERR, tizen.application, "getAppInfo", TEST_OBJ);
+       TestEngine.catchErrorType("name", NOT_FOUND_ERR, tizen.application, "getAppInfo", TEST_FUN);
+
+       TestEngine.catchErrorType("name", NOT_FOUND_ERR, tizen.application, "getAppInfo", "NO_APP");
+       TestEngine.catchErrorType("name", NOT_FOUND_ERR, tizen.application, "getAppInfo", TEST_NUM);
+
+       TestEngine.log("[Application] UTC_application_getAppInfo_N_001 END");
+}
+
+function UTC_application_getAppCerts_P_001()
+{
+       TestEngine.log("[Application] UTC_application_getAppCerts_P_001 START");
+
+       try {
+               var certs = tizen.application.getAppCerts();
+               TestEngine.log("Certs.length = " + certs.length);
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_getAppCerts_P_001 err : " + err, false);
+       }
+       TestEngine.test("[Application] UTC_application_getAppCerts_P_001", true);
+
+       TestEngine.log("[Application] UTC_application_getAppCerts_P_001 END");
+}
+
+function UTC_application_getAppCerts_P_002()
+{
+       TestEngine.log("[Application] UTC_application_getAppCerts_P_002 START");
+
+       try {
+               var certs = tizen.application.getAppCerts(CURR_APP_ID);
+               TestEngine.log("Certs.length = " + certs.length);
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_getAppCerts_P_002 err : " + err, false);
+       }
+       TestEngine.test("[Application] UTC_application_getAppCerts_P_002", true);
+
+       TestEngine.log("[Application] UTC_application_getAppCerts_P_002 END");
+}
+
+function UTC_application_getAppCerts_P_003()
+{
+       TestEngine.log("[Application] UTC_application_getAppCerts_P_003 START");
+
+       try {
+               var certs = tizen.application.getAppCerts(null);
+               TestEngine.log("Certs.length = " + certs.length);
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_getAppCerts_P_003 err : " + err, false);
+       }
+       TestEngine.test("[Application] UTC_application_getAppCerts_P_003", true);
+
+       TestEngine.log("[Application] UTC_application_getAppCerts_P_003 END");
+}
+
+function UTC_application_getAppCerts_P_004()
+{
+       TestEngine.log("[Application] UTC_application_getAppCerts_P_004 START");
+
+       try {
+               var certs = tizen.application.getAppCerts();
+               var count = 0;
+               TestEngine.log("Cert length" + certs.length);           
+               for (var i = 0; i < certs.length; i++) {
+                       if (certs[i].type == "AUTHOR_ROOT") {
+                               count++;
+                       }
+                       
+                       if (certs[i].type == "DISTRIBUTOR_ROOT") {
+                               count++;
+                       }
+                       
+                       if (certs[i].type == "DISTRIBUTOR2_ROOT") {
+                               count++;
+                       }
+               }
+
+               if (count == 3) {
+                       TestEngine.test("[Application] UTC_application_getAppCerts_P_004", true);
+               } else {
+                       TestEngine.test("[Application] UTC_application_getAppCerts_P_004 count : " + count, false);
+               }
+               
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_getAppCerts_P_004 err : " + err, false);
+       }
+       TestEngine.test("[Application] UTC_application_getAppCerts_P_004", true);
+
+       TestEngine.log("[Application] UTC_application_getAppCerts_P_004 END");
+}
+
+function UTC_application_getAppCerts_N_001()
+{
+       TestEngine.log("[Application] UTC_application_getAppCerts_N_001 START");
+
+       TestEngine.catchErrorType("name", NOT_FOUND_ERR, tizen.application, "getAppCerts", TEST_OBJ);
+       TestEngine.catchErrorType("name", NOT_FOUND_ERR, tizen.application, "getAppCerts", TEST_FUN);
+
+       TestEngine.catchErrorType("name", NOT_FOUND_ERR, tizen.application, "getAppCerts", "NO_APP");
+       TestEngine.catchErrorType("name", NOT_FOUND_ERR, tizen.application, "getAppCerts", TEST_NUM);
+
+       TestEngine.log("[Application] UTC_application_getAppCerts_N_001 END");
+}
+
+function UTC_application_getAppSharedURI_P_001()
+{
+       TestEngine.log("[Application] UTC_application_getAppSharedURI_P_001 START");
+
+       try {
+               var sharedURI = tizen.application.getAppSharedURI();
+               TestEngine.log("sharedURI = "+sharedURI);
+
+               var currSharedURI = "file:///opt/usr/apps/" + tizen.application.getCurrentApplication().appInfo.packageId + "/shared/";
+               if (sharedURI != currSharedURI) {
+                       TestEngine.test("[Application] UTC_application_getAppSharedURI_P_001 err : shared uri is not same", false);
+               }
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_getAppSharedURI_P_001 err : " + err, false);
+       }
+       TestEngine.test("[Application] UTC_application_getAppSharedURI_P_001", true);
+
+       TestEngine.log("[Application] UTC_application_getAppSharedURI_P_001 END");
+}
+
+function UTC_application_getAppSharedURI_P_002()
+{
+       TestEngine.log("[Application] UTC_application_getAppSharedURI_P_002 START");
+
+       try {
+               var sharedURI = tizen.application.getAppSharedURI(null);
+               TestEngine.log("sharedURI = "+sharedURI);
+
+               var currSharedURI = "file:///opt/usr/apps/" + tizen.application.getCurrentApplication().appInfo.packageId + "/shared/";
+               if (sharedURI != currSharedURI) {
+                       TestEngine.test("[Application] UTC_application_getAppSharedURI_P_002 err : shared uri is not same", false);
+               }
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_getAppSharedURI_P_002 err : " + err, false);
+       }
+       TestEngine.test("[Application] UTC_application_getAppSharedURI_P_002", true);
+
+       TestEngine.log("[Application] UTC_application_getAppSharedURI_P_002 END");
+}
+
+function UTC_application_getAppSharedURI_P_003()
+{
+       TestEngine.log("[Application] UTC_application_getAppSharedURI_P_003 START");
+
+       try {
+               var sharedURI = tizen.application.getAppSharedURI(CURR_APP_ID);
+               TestEngine.log("sharedURI = "+sharedURI);
+
+               var currSharedURI = "file:///opt/usr/apps/" + tizen.application.getCurrentApplication().appInfo.packageId + "/shared/";
+               if (sharedURI != currSharedURI) {
+                       TestEngine.test("[Application] UTC_application_getAppSharedURI_P_003 err : shared uri is not same", false);
+               }
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_getAppSharedURI_P_003 err : " + err, false);
+       }
+       TestEngine.test("[Application] UTC_application_getAppSharedURI_P_003", true);
+
+       TestEngine.log("[Application] UTC_application_getAppSharedURI_P_003 END");
+}
+
+function UTC_application_getAppSharedURI_P_004()
+{
+       TestEngine.log("[Application] UTC_application_getAppSharedURI_P_004 START");
+
+       try {
+               var sharedURI = tizen.application.getAppSharedURI(TEST_APP_ID_1);
+               TestEngine.log("sharedURI = "+sharedURI);
+
+               var currSharedURI = "file:///opt/usr/apps/" + tizen.application.getAppInfo(TEST_APP_ID_1).packageId + "/shared/";
+               if (sharedURI != currSharedURI) {
+                       TestEngine.test("[Application] UTC_application_getAppSharedURI_P_004 err : shared uri is not same", false);
+               }
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_getAppSharedURI_P_004 err : " + err, false);
+       }
+       TestEngine.test("[Application] UTC_application_getAppSharedURI_P_004", true);
+
+       TestEngine.log("[Application] UTC_application_getAppSharedURI_P_004 END");
+}
+
+function UTC_application_getAppSharedURI_N_001()
+{
+       TestEngine.log("[Application] UTC_application_getAppSharedURI_N_001 START");
+
+       TestEngine.catchErrorType("name", NOT_FOUND_ERR, tizen.application, "getAppSharedURI", TEST_OBJ);
+       TestEngine.catchErrorType("name", NOT_FOUND_ERR, tizen.application, "getAppSharedURI", TEST_FUN);
+
+       TestEngine.catchErrorType("name", NOT_FOUND_ERR, tizen.application, "getAppSharedURI", "NO_APP");
+       TestEngine.catchErrorType("name", NOT_FOUND_ERR, tizen.application, "getAppSharedURI", TEST_NUM);
+
+       TestEngine.log("[Application] UTC_application_getAppSharedURI_N_001 END");
+}
+
+function UTC_application_getAppMetaData_P_001()
+{
+       TestEngine.log("[Application] UTC_application_getAppMetaData_P_001 START");
+
+       try {
+               var data = tizen.application.getAppMetaData();
+               TestEngine.log("MetaData.length = " + data.length);
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_getAppMetaData_P_001 err : " + err, false);
+       }
+       TestEngine.test("[Application] UTC_application_getAppMetaData_P_001", true);
+
+       TestEngine.log("[Application] UTC_application_getAppMetaData_P_001 END");
+}
+
+function UTC_application_getAppMetaData_P_002()
+{
+       TestEngine.log("[Application] UTC_application_getAppMetaData_P_002 START");
+
+       try {
+               var data = tizen.application.getAppMetaData(CURR_APP_ID);
+               TestEngine.log("MetaData.length = " + data.length);
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_getAppMetaData_P_002 err : " + err, false);
+       }
+       TestEngine.test("[Application] UTC_application_getAppMetaData_P_002", true);
+
+       TestEngine.log("[Application] UTC_application_getAppMetaData_P_002 END");
+}
+
+function UTC_application_getAppMetaData_P_003()
+{
+       TestEngine.log("[Application] UTC_application_getAppMetaData_P_003 START");
+
+       try {
+               var data = tizen.application.getAppMetaData(null);
+               TestEngine.log("MetaData.length = " + data.length);
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_getAppMetaData_P_003 err : " + err, false);
+       }
+       TestEngine.test("[Application] UTC_application_getAppMetaData_P_003", true);
+
+       TestEngine.log("[Application] UTC_application_getAppMetaData_P_003 END");
+}
+
+function UTC_application_getAppMetaData_P_004()
+{
+       TestEngine.log("[Application] UTC_application_getAppMetaData_P_004 START");
+
+       try {
+               var data = tizen.application.getAppMetaData();
+               var count = 0;
+               TestEngine.log("MetaData length" + data.length);
+
+               if (data.length != 1) {
+                       TestEngine.test("[Application] UTC_application_getAppMetaData_P_004 : wrong meta data length : " + data.length, false);
+               }
+
+               if (data[0].key != "meta-key") {
+                       TestEngine.test("[Application] UTC_application_getAppMetaData_P_004 : bad key ", false);
+               }
+
+               if ( data[0].value != "meta-value") {
+                       TestEngine.test("[Application] UTC_application_getAppMetaData_P_004 : bad value ", false);
+               }
+               
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_getAppMetaData_P_004 err : " + err, false);
+       }
+       TestEngine.test("[Application] UTC_application_getAppMetaData_P_004", true);
+
+       TestEngine.log("[Application] UTC_application_getAppMetaData_P_004 END");
+}
+
+function UTC_application_getAppMetaData_N_001()
+{
+       TestEngine.log("[Application] UTC_application_getAppMetaData_N_001 START");
+
+       TestEngine.catchErrorType("name", NOT_FOUND_ERR, tizen.application, "getAppMetaData", TEST_OBJ);
+       TestEngine.catchErrorType("name", NOT_FOUND_ERR, tizen.application, "getAppMetaData", TEST_FUN);
+
+       TestEngine.catchErrorType("name", NOT_FOUND_ERR, tizen.application, "getAppMetaData", "NO_APP");
+       TestEngine.catchErrorType("name", NOT_FOUND_ERR, tizen.application, "getAppMetaData", TEST_NUM);
+
+       TestEngine.log("[Application] UTC_application_getAppMetaData_N_001 END");
+}
+
+
+function printApplicationInformation(appinfo) {
+       TestEngine.log("[printApplicationInformation][START]");
+
+       try {
+               TestEngine.log("appinfo.name = "+appinfo.name);
+               TestEngine.log("appinfo.appId = "+appinfo.appId);
+               TestEngine.log("appinfo.iconPath = "+appinfo.iconPath);
+               TestEngine.log("appinfo.version = "+appinfo.version);
+       } catch (ex){
+               onErrorCB(ex);
+       }
+
+       TestEngine.log("[printApplicationInformation][END]");
+}
+
+var onAppInfoEventCB = {
+       oninstalled : function(appinfo) {
+               TestEngine.log("[onInstalled][START]");
+               try {
+                       printApplicationInformation(appinfo);
+               } catch (ex) {
+                       onErrorCB(ex);
+               }
+               TestEngine.log("[onInstalled][END]");
+       },
+       onupdated : function(appinfo) {
+               TestEngine.log("[onUpdated][START]");
+               try {
+                       printApplicationInformation(appinfo);
+               } catch (ex) {
+                       onErrorCB(ex);
+               }
+               TestEngine.log("[onUpdated][END]");
+       },
+       onuninstalled : function(appid) {
+               TestEngine.log("[onUninstalled][START]");
+               try {
+                       TestEngine.log("[onUninstalled] appid = "+appid);
+               } catch (ex) {
+                       onErrorCB(ex);
+               }
+               TestEngine.log("[onUninstalled][END]");
+       }
+};
+
+function UTC_application_addAppInfoEventListener_P_000()
+{
+       TestEngine.log("[Application] UTC_application_addAppInfoEventListener_P_000 START");
+
+       try {
+               var id = tizen.application.addAppInfoEventListener(onAppInfoEventCB);
+               TestEngine.log("[Application] UTC_application_addAppInfoEventListener_P_000 id : " + id);
+               tizen.application.removeAppInfoEventListener(id);
+
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_addAppInfoEventListener_P_000 err : " + err, false);
+       }
+       TestEngine.test("[Application] UTC_application_addAppInfoEventListener_P_000", true);
+
+       TestEngine.log("[Application] UTC_application_addAppInfoEventListener_P_000 END");
+}
+
+function UTC_application_addAppInfoEventListener_P_001()
+{
+       TestEngine.log("[Application] UTC_application_addAppInfoEventListener_P_001 START");
+
+       try {
+               var id = tizen.application.addAppInfoEventListener(onAppInfoEventCB);
+               TestEngine.log("[Application] UTC_application_addAppInfoEventListener_P_001 id : " + id);
+               //tizen.application.removeAppInfoEventListener(id);
+
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_addAppInfoEventListener_P_001 err : " + err, false);
+       }
+       TestEngine.test("[Application] UTC_application_addAppInfoEventListener_P_001", true);
+
+       TestEngine.log("[Application] UTC_application_addAppInfoEventListener_P_001 END");
+}
+
+function UTC_application_addAppInfoEventListener_P_002()
+{
+       TestEngine.log("[Application] UTC_application_addAppInfoEventListener_P_002 START");
+
+       try {
+               var id = tizen.application.addAppInfoEventListener(onAppInfoEventCB, null);
+               TestEngine.log("[Application] UTC_application_addAppInfoEventListener_P_002 id : " + id);
+
+               //tizen.application.removeAppInfoEventListener(id);
+
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_addAppInfoEventListener_P_002 err : " + err, false);
+       }
+       TestEngine.test("[Application] UTC_application_addAppInfoEventListener_P_002", true);
+
+       TestEngine.log("[Application] UTC_application_addAppInfoEventListener_P_002 END");
+}
+
+function UTC_application_addAppInfoEventListener_P_003()
+{
+       TestEngine.log("[Application] UTC_application_addAppInfoEventListener_P_003 START");
+
+       try {
+               var id = tizen.application.addAppInfoEventListener(onAppInfoEventCB, onErrorCB);
+               TestEngine.log("[Application] UTC_application_addAppInfoEventListener_P_003 id : " + id);
+               //tizen.application.removeAppInfoEventListener(id);
+
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_addAppInfoEventListener_P_003 err : " + err, false);
+       }
+       TestEngine.test("[Application] UTC_application_addAppInfoEventListener_P_003", true);
+
+       TestEngine.log("[Application] UTC_application_addAppInfoEventListener_P_003 END");
+}
+
+function UTC_application_addAppInfoEventListener_P_004()
+{
+       TestEngine.log("[Application] UTC_application_addAppInfoEventListener_P_004 START");
+
+       try {
+               var id = tizen.application.addAppInfoEventListener(onAppInfoEventCB, undefined);
+               TestEngine.log("[Application] UTC_application_addAppInfoEventListener_P_004 id : " + id);
+               //tizen.application.removeAppInfoEventListener(id);
+
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_addAppInfoEventListener_P_004 err : " + err, false);
+       }
+       TestEngine.test("[Application] UTC_application_addAppInfoEventListener_P_004", true);
+
+       TestEngine.log("[Application] UTC_application_addAppInfoEventListener_P_004 END");
+}
+
+function UTC_application_addAppInfoEventListener_P_005()
+{
+       TestEngine.log("[Application] UTC_application_addAppInfoEventListener_P_005 START");
+
+       try {
+               var id = tizen.application.addAppInfoEventListener(onAppInfoEventCB, onErrorCB, undefined);
+               TestEngine.log("[Application] UTC_application_addAppInfoEventListener_P_005 id : " + id);
+               //tizen.application.removeAppInfoEventListener(id);
+
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_addAppInfoEventListener_P_005 err : " + err, false);
+       }
+       TestEngine.test("[Application] UTC_application_addAppInfoEventListener_P_005", true);
+
+       TestEngine.log("[Application] UTC_application_addAppInfoEventListener_P_005 END");
+}
+
+function UTC_application_addAppInfoEventListener_P_006()
+{
+       TestEngine.log("[Application] UTC_application_addAppInfoEventListener_P_006 START");
+
+       try {
+
+               var onAppInfoEventCB = {
+                       oninstalled : function(appinfo) {
+                               TestEngine.log("[onInstalled][START]");
+                               try {
+                                       printApplicationInformation(appinfo);
+                               } catch (ex) {
+                                       onErrorCB(ex);
+                               }
+                               TestEngine.log("[onInstalled][END]");
+                       }
+               };
+               
+               var id = tizen.application.addAppInfoEventListener(onAppInfoEventCB);
+               TestEngine.log("[Application] UTC_application_addAppInfoEventListener_P_006 id : " + id);
+               //tizen.application.removeAppInfoEventListener(id);
+
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_addAppInfoEventListener_P_006 err : " + err, false);
+       }
+       TestEngine.test("[Application] UTC_application_addAppInfoEventListener_P_006", true);
+
+       TestEngine.log("[Application] UTC_application_addAppInfoEventListener_P_006 END");
+}
+
+function UTC_application_addAppInfoEventListener_P_007()
+{
+       TestEngine.log("[Application] UTC_application_addAppInfoEventListener_P_007 START");
+
+       try {
+
+               var onAppInfoEventCB = {
+
+                       onupdated : function(appinfo) {
+                               TestEngine.log("[onUpdated][START]");
+                               try {
+                                       printApplicationInformation(appinfo);
+                               } catch (ex) {
+                                       onErrorCB(ex);
+                               }
+                               TestEngine.log("[onUpdated][END]");
+                       }
+               };
+               
+               var id = tizen.application.addAppInfoEventListener(onAppInfoEventCB);
+               TestEngine.log("[Application] UTC_application_addAppInfoEventListener_P_007 id : " + id);
+               //tizen.application.removeAppInfoEventListener(id);
+
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_addAppInfoEventListener_P_007 err : " + err, false);
+       }
+       TestEngine.test("[Application] UTC_application_addAppInfoEventListener_P_007", true);
+
+       TestEngine.log("[Application] UTC_application_addAppInfoEventListener_P_007 END");
+}
+
+function UTC_application_addAppInfoEventListener_P_008()
+{
+       TestEngine.log("[Application] UTC_application_addAppInfoEventListener_P_008 START");
+
+       try {
+
+               var onAppInfoEventCB = {
+                       onuninstalled : function(appid) {
+                               TestEngine.log("[onUninstalled][START]");
+                               try {
+                                       TestEngine.log("[onUninstalled] appid = "+appid);
+                               } catch (ex) {
+                                       onErrorCB(ex);
+                               }
+                               TestEngine.log("[onUninstalled][END]");
+                       }
+               };
+               
+               var id = tizen.application.addAppInfoEventListener(onAppInfoEventCB);
+               TestEngine.log("[Application] UTC_application_addAppInfoEventListener_P_008 id : " + id);
+               //tizen.application.removeAppInfoEventListener(id);
+
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_addAppInfoEventListener_P_008 err : " + err, false);
+       }
+       TestEngine.test("[Application] UTC_application_addAppInfoEventListener_P_008", true);
+
+       TestEngine.log("[Application] UTC_application_addAppInfoEventListener_P_008 END");
+}
+
+function UTC_application_addAppInfoEventListener_N_001()
+{
+       TestEngine.log("[Application] UTC_application_addAppInfoEventListener_N_001 START");
+
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.application, "addAppInfoEventListener", null);
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.application, "addAppInfoEventListener", undefined);
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.application, "addAppInfoEventListener", TEST_STR);
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.application, "addAppInfoEventListener", TEST_NUM);
+       
+       TestEngine.log("[Application] UTC_application_addAppInfoEventListener_N_001 END");
+}
+
+function UTC_application_removeAppInfoEventListener_N_001()
+{
+       TestEngine.log("[Application] UTC_application_removeAppInfoEventListener_N_001 START");
+       var id = tizen.application.addAppInfoEventListener(onAppInfoEventCB, onErrorCB);
+
+       TestEngine.log("Wrong integer value.");
+       TestEngine.catchErrorType("name", NOT_FOUND_ERR , tizen.application, "removeAppInfoEventListener", -1);
+       TestEngine.catchErrorType("name", NOT_FOUND_ERR , tizen.application, "removeAppInfoEventListener", id+10);
+
+       TestEngine.log("Wrong type.");
+       TestEngine.catchErrorType("name", NOT_FOUND_ERR, tizen.application, "removeAppInfoEventListener", TEST_STR);
+       TestEngine.catchErrorType("name", NOT_FOUND_ERR, tizen.application, "removeAppInfoEventListener", TEST_OBJ);
+       TestEngine.catchErrorType("name", NOT_FOUND_ERR, tizen.application, "removeAppInfoEventListener", TEST_FUN);
+
+       TestEngine.log("[Application] UTC_application_removeAppInfoEventListener_N_001 END");
+}
+
+function UTC_application_construct_ApplicationControlData_P_001()
+{
+       TestEngine.log("[Application] UTC_application_construct_ApplicationControlData_P_001 START");
+
+       try {
+               var data = new tizen.ApplicationControlData("key", ["value"]);
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_construct_ApplicationControlData_P_001 err : " + err, false);
+       }
+       TestEngine.test("[Application] UTC_application_construct_ApplicationControlData_P_001", true);
+       TestEngine.log("[Application] UTC_application_construct_ApplicationControlData_P_001 END");
+}
+
+
+function UTC_application_construct_ApplicationControlData_P_002()
+{
+       TestEngine.log("[Application] UTC_application_construct_ApplicationControlData_P_002 START");
+
+       try {
+               var data = new tizen.ApplicationControlData("key", ["value", "value2"]);
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_construct_ApplicationControlData_P_002 err : " + err, false);
+       }
+       TestEngine.test("[Application] UTC_application_construct_ApplicationControlData_P_002", true);
+       TestEngine.log("[Application] UTC_application_construct_ApplicationControlData_P_002 END");
+}
+
+function UTC_application_construct_ApplicationControl_P_001()
+{
+       TestEngine.log("[Application] UTC_application_construct_ApplicationControl_P_001 START");
+
+       try {
+               var appControl = new tizen.ApplicationControl("operation");
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_construct_ApplicationControl_P_001 err : " + err, false);
+       }
+       TestEngine.test("[Application] UTC_application_construct_ApplicationControl_P_001", true);
+       TestEngine.log("[Application] UTC_application_construct_ApplicationControl_P_001 END");
+}
+
+function UTC_application_construct_ApplicationControl_P_002()
+{
+       TestEngine.log("[Application] UTC_application_construct_ApplicationControl_P_002 START");
+
+       try {
+               var appControl1 = new tizen.ApplicationControl("operation", "uri", "mime", "category", null);
+               var appControl2 = new tizen.ApplicationControl("operation", null, "mime", "category", null);
+               var appControl3 = new tizen.ApplicationControl("operation", null, null, "category", null);
+               var appControl4 = new tizen.ApplicationControl("operation", null, null, null, null);
+               var appControl5 = new tizen.ApplicationControl("operation", undefined, "mime", "category", null);
+               var appControl6 = new tizen.ApplicationControl("operation", undefined, undefined, "category", null);
+               var appControl7 = new tizen.ApplicationControl("operation", undefined, undefined, "category", null);
+               var appControl8 = new tizen.ApplicationControl("operation", "uri", null,  "category", null);
+               var appControl9 = new tizen.ApplicationControl("operation", "uri", undefined,  "category", null);
+               var appControl10 = new tizen.ApplicationControl("operation", "uri", null, null, null);
+               var appControl11 = new tizen.ApplicationControl("operation", "uri", "mime", null, null);
+               var appControl12 = new tizen.ApplicationControl("operation", "uri", "mime", undefined, null);
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_construct_ApplicationControl_P_002 err : " + err, false);
+       }
+       TestEngine.test("[Application] UTC_application_construct_ApplicationControl_P_002", true);
+       TestEngine.log("[Application] UTC_application_construct_ApplicationControl_P_002 END");
+}
+
+function UTC_application_construct_ApplicationControl_P_003()
+{
+       TestEngine.log("[Application] UTC_application_construct_ApplicationControl_P_003 START");
+
+       try {
+               var data = [
+                       new tizen.ApplicationControlData("key1", ["data1"]),
+                       new tizen.ApplicationControlData("key2", ["data2", "data3"])
+               ];
+               var appControl = new tizen.ApplicationControl("operation", "uri", "mime", "category", null);
+               var appControl2 = new tizen.ApplicationControl("operation", "uri", "mime", "category", data);
+               var appControl4 = new tizen.ApplicationControl("operation", "uri", "mime", "category", data, data);
+
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_construct_ApplicationControl_P_003 err : " + err, false);
+       }
+       TestEngine.test("[Application] UTC_application_construct_ApplicationControl_P_003", true);
+       TestEngine.log("[Application] UTC_application_construct_ApplicationControl_P_003 END");
+}
+
+
+function UTC_application_field_ApplicationInformation_N_001()
+{
+       TestEngine.log("[Application] UTC_application_field_ApplicationInformation_N_001 START");
+
+       var info = tizen.application.getAppInfo();
+
+       printApplicationInformation(info);
+
+       var id = info.id;
+       var name = info.name;
+       var iconPath = info.iconPath;
+       var show = info.show;
+       var version = info.version;
+
+       try {
+               info.id = "test";
+               info.name = "UTC_application_N_00ame";
+               info.iconPath = "iconPath";
+               info.version = "version";
+               info.show = true;
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_field_ApplicationInformation_N_001 error : " + err, false);
+       }
+
+       if ((info.id != id) || (info.name != name) || (info.version != version) || (info.iconPath != iconPath) || (info.show != show)) {
+               TestEngine.test("[Application] UTC_application_field_ApplicationInformation_N_001 the value is changed!", false);
+       }
+
+       printApplicationInformation(info);
+
+       TestEngine.test("[Application] UTC_application_field_ApplicationInformation_N_001 success", true);
+       TestEngine.log("[Application] UTC_application_field_ApplicationInformation_N_001 END");
+}
+
+function UTC_application_field_ApplicationContext_N_001()
+{
+       TestEngine.log("[Application] UTC_application_field_ApplicationContext_N_001 START");
+
+       var context = tizen.application.getAppContext();
+       var id = context.id;
+       var appId = context.appId;
+
+       try {
+               context.id = "test";
+               context.appId = "appId";
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_field_ApplicationContext_N_001 error : " + err, false);
+       }
+
+       if ((context.id != id) || (context.appId != appId)) {
+               TestEngine.test("[Application] UTC_application_field_ApplicationContext_N_001 the value is changed!", false);
+       }
+
+       TestEngine.test("[Application] UTC_application_field_ApplicationContext_N_001 success", true);
+       TestEngine.log("[Application] UTC_application_field_ApplicationContext_N_001 END");
+}
+
+function UTC_application_tmp()
+{
+       TestEngine.log("[Application] UTC_application_tmp START");
+       try {
+               var cbObj = TestEngine.registerCallback("launchAppControl", onSuccessCB, onErrorCB);
+               var appControl = new tizen.ApplicationControl("slp.appcontrol.operation.TEST2", null, null);
+
+               tizen.application.launchAppControl(cbObj.successCallback, cbObj.errorCallback, appControl, null);
+       } catch(err) {
+               TestEngine.test("[Application] UTC_application_tmp error : " + err, false);
+       }
+
+       TestEngine.log("[Application] UTC_application_tmp END");
+}
+
+
+function UTC_application_DCM_1456()
+{
+       TestEngine.log("[Application] UTC_application_DCM_1456 START");
+
+       var cbObj = TestEngine.registerCallback("getAppsContext", onSuccessCB, onErrorCB);
+
+       try {
+               var beforeContextArray = new Array();
+
+               var getAfterContextArray = function(ctxArr2) {
+                       TestEngine.log("AfterContextArray Enter");
+
+                       for (var i = 0; i < ctxArr2.length; i++) {
+                               if (beforeContextArray.indexOf(ctxArr2[i].id) == -1) {
+                                       TestEngine.log("Launched App Found : " + ctxArr2[i].appId);
+                                       tizen.application.kill(ctxArr2[i].id,
+                                                       function() {
+                                                               TestEngine.log("Success to Kill ");
+                                                               TestEngine.test("[Application] UTC_application_DCM_1456", true);
+                                                               cbObj.successCallback();
+                                                       },
+                                                       function(e) {
+                                                               TestEngine.log("error : "+e.name);
+                                                               TestEngine.test("[Application] UTC_application_DCM_1456", false);
+                                                               cbObj.onErrorCB();
+                                                       }
+                                       );
+                               }
+                       }
+               }
+
+               var getPrevContextArray = function (contexts) {
+                       // save the current contexts
+                       for (var j = 0; j < contexts.length; j++) {
+                               beforeContextArray[j] = contexts[j].id;
+                       }
+
+                       // launch AppControl with aliased App ID
+                       var appControl = new tizen.ApplicationControl("http://tizen.org/appcontrol/operation/create_content", null, "image/jpeg", null, null);
+                       tizen.application.launchAppControl(appControl,
+                                               "tizen.camera",
+                                               function() {
+                                                       TestEngine.log("launch success");
+                                                       tizen.application.getAppsContext(getAfterContextArray,
+                                                               function(e) {
+                                                                       TestEngine.log("error : "+e.name);
+                                                                       TestEngine.test("[Application] UTC_application_DCM_1456", false);
+                                                                       cbObj.onErrorCB();
+                                                               }
+                                                       );
+                                               },
+                                               function(e) {
+                                                       TestEngine.log("error : "+e.name);
+                                                       TestEngine.test("[Application] UTC_application_DCM_1456", false);
+                                                       cbObj.onErrorCB();
+                                               }
+                       );
+               }
+
+               tizen.application.getAppsContext(getPrevContextArray,
+                               function(e) {
+                                       TestEngine.log("error : "+e.name);
+                                       TestEngine.test("[Application] UTC_application_DCM_1456", false);
+                                       cbObj.onErrorCB();
+                               }
+               );
+       } catch (err) {
+               TestEngine.test("[Application] UTC_application_DCM_1456 error : " + err, false);
+       }
+
+       TestEngine.log("[Application] UTC_application_DCM_1456 END");
+}
+
diff --git a/webWidgetTCT_device/test/utc/tests/TestClock.js b/webWidgetTCT_device/test/utc/tests/TestClock.js
new file mode 100755 (executable)
index 0000000..cbff6d4
--- /dev/null
@@ -0,0 +1,1805 @@
+
+/*
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ * PROPRIETARY/CONFIDENTIAL
+ *
+ * This software is the confidential and proprietary information of SAMSUNG
+ * ELECTRONICS ("Confidential Information"). You agree and acknowledge that
+ * this software is owned by Samsung and you shall not disclose such
+ * Confidential Information and shall use it only in accordance with the terms
+ * of the license agreement you entered into with SAMSUNG ELECTRONICS. SAMSUNG
+ * make no representations or warranties about the suitability of the software,
+ * either express or implied, including but not limited to the implied
+ * warranties of merchantability, fitness for a particular purpose, or
+ * non-infringement. SAMSUNG shall not be liable for any damages suffered by
+ * licensee arising out of or related to this software.
+ *
+ */
+
+/**
+ *     TimeUtil UNIT test
+ *    @author    sangtai.kim, jihwa.park
+ */
+
+//document.write('<script type="text/javascript" src="tests/Tizen/ClockSetting.js"></script>');
+// hack to include file generated by another script
+eval(require('fs').readFileSync(__dirname + '/tests/ClockSetting.js', 'utf-8')+ '');
+
+var UNKNOWN_ERR = "UnknownError";
+var TYPE_MISMATCH_ERR   = "TypeMismatchError";
+var INVALID_VALUES_ERR   = "InvalidValuesError";
+var NOT_FOUND_ERR       = "NotFoundError";
+var PERMISSION_DENIED_ERR = "SecurityError";
+var ERROR_STR = "Error";
+var ERROR_NUM = 3;
+
+var emptyFunction = function() {}
+
+var expected_year       = 2011;
+var expected_month      = 10;
+var expected_date       = 11;
+var expected_hours         = 4;
+var expected_minutes    = 55;
+var expected_seconds    = 54;
+var expected_milliseconds = 12;
+var expected_time_zone    = "Asia/Dubai";//GMT+4
+
+var date = new tizen.TZDate(
+                    expected_year,             //year
+                    expected_month,             //month
+                    expected_date,             //day
+                    expected_hours,             //hours
+                    expected_minutes,         //minutes
+                    expected_seconds,         //seconds
+                    expected_milliseconds,    //milliseconds
+                    expected_time_zone        //timeZone
+            );
+
+// var currentDate = new tizen.TZDate();
+
+function presenceTest()
+{
+    TestEngine.test("Checking tizen.time object", tizen.time);
+}
+
+function testTZDate_001() {
+    try {
+    var JSDate = new Date(expected_year,             //year
+                    expected_month,             //month
+                    expected_date,             //day
+                    expected_hours,             //hours
+                    expected_minutes,         //minutes
+                    expected_seconds,         //seconds
+                    expected_milliseconds    //milliseconds
+                    );
+    var date1 = new tizen.TZDate();
+    var date2 = new tizen.TZDate(null, null);
+    var date2_1 = new tizen.TZDate(null);
+    var date2_2 = new tizen.TZDate(undefined, undefined);
+    var date2_3 = new tizen.TZDate(undefined);
+    var date3 = new tizen.TZDate(JSDate);
+    var date3_1 = new tizen.TZDate(JSDate, null);
+    var date3_2 = new tizen.TZDate(JSDate, undefined);
+    var date4 = new tizen.TZDate(null, expected_time_zone);
+    var date5 = new tizen.TZDate(JSDate, expected_time_zone);
+    var date6 = new tizen.TZDate(expected_year, expected_month, expected_date);
+    var date7 = new tizen.TZDate(expected_year, expected_month, expected_date, expected_hours);
+    var date8 = new tizen.TZDate(expected_year, expected_month, expected_date, expected_hours, expected_minutes);
+    var date9 = new tizen.TZDate(expected_year, expected_month, expected_date, expected_hours, expected_minutes, expected_seconds);
+    var date10 = new tizen.TZDate(expected_year, expected_month, expected_date, expected_hours, expected_minutes, expected_seconds, expected_milliseconds);
+    var date11 = new tizen.TZDate(expected_year, expected_month, expected_date, expected_hours, expected_minutes, expected_seconds, expected_milliseconds, expected_time_zone);
+    var date12 = new tizen.TZDate(expected_year, expected_month, expected_date, null, expected_minutes, expected_seconds, expected_milliseconds, expected_time_zone);
+    var date13 = new tizen.TZDate(expected_year, expected_month, expected_date, expected_hours, null, expected_seconds, expected_milliseconds, expected_time_zone);
+    var date14 = new tizen.TZDate(expected_year, expected_month, expected_date, expected_hours, expected_minutes, null, expected_milliseconds, expected_time_zone);
+    var date15 = new tizen.TZDate(expected_year, expected_month, expected_date, expected_hours, expected_minutes, expected_seconds, null, expected_time_zone);
+    var date16 = new tizen.TZDate(expected_year, expected_month, expected_date, expected_hours, expected_minutes, expected_seconds, expected_milliseconds, null);
+    var date17 = new tizen.TZDate(expected_year, expected_month, expected_date, undefined, expected_minutes, expected_seconds, expected_milliseconds, expected_time_zone);
+    var date18 = new tizen.TZDate(expected_year, expected_month, expected_date, expected_hours, undefined, expected_seconds, expected_milliseconds, expected_time_zone);
+    var date19 = new tizen.TZDate(expected_year, expected_month, expected_date, expected_hours, expected_minutes, undefined, expected_milliseconds, expected_time_zone);
+    var date20 = new tizen.TZDate(expected_year, expected_month, expected_date, expected_hours, expected_minutes, expected_seconds, undefined, expected_time_zone);
+    var date21 = new tizen.TZDate(expected_year, expected_month, expected_date, expected_hours, expected_minutes, expected_seconds, expected_milliseconds, undefined);
+    var date22 = new tizen.TZDate(expected_year, expected_month, expected_date, expected_hours, expected_minutes, expected_seconds, expected_milliseconds, expected_time_zone, ERROR_NUM);
+    var date23 = new tizen.TZDate(expected_year, expected_month, expected_date, expected_hours, expected_minutes, expected_seconds, expected_milliseconds, expected_time_zone, null);
+    var date24 = new tizen.TZDate(expected_year, expected_month, expected_date, expected_hours, expected_minutes, expected_seconds, expected_milliseconds, expected_time_zone, undefined);
+
+    TestEngine.test("testTZDate_001() new tizen.TZDate():", date1 instanceof tizen.TZDate);
+    TestEngine.test("testTZDate_001() new tizen.TZDate(null, null):", date2 instanceof tizen.TZDate);
+    TestEngine.test("testTZDate_001() new tizen.TZDate(null):", date2_1 instanceof tizen.TZDate);
+    TestEngine.test("testTZDate_001() new tizen.TZDate(undefined, undefined):", date2_2 instanceof tizen.TZDate);
+    TestEngine.test("testTZDate_001() new tizen.TZDate(undefined):", date2_3 instanceof tizen.TZDate);
+    TestEngine.test("testTZDate_001() new tizen.TZDate(JSDate) equals to new tizen.TZDate(JSDate, null):", date3.equalsTo(date3_1));
+    TestEngine.test("testTZDate_001() new tizen.TZDate(JSDate) equals to new tizen.TZDate(JSDate, undefined):", date3.equalsTo(date3_2));
+    checkTZDate(7, date3, expected_year, expected_month, expected_date, expected_hours, expected_minutes, expected_seconds, expected_milliseconds);
+    checkTZDate(1, date4, expected_time_zone);
+    TestEngine.test("testTZDate_001() new tizen.TZDate(JSDate, expected_time_zone) equals to date:", date5.equalsTo(date));
+    checkTZDate(8, date5, expected_year, expected_month, expected_date, expected_hours, expected_minutes, expected_seconds, expected_milliseconds, expected_time_zone);
+    checkTZDate(3, date6, expected_year, expected_month, expected_date);
+    checkTZDate(4, date7, expected_year, expected_month, expected_date, expected_hours);
+    checkTZDate(5, date8, expected_year, expected_month, expected_date, expected_hours, expected_minutes);
+    checkTZDate(6, date9, expected_year, expected_month, expected_date, expected_hours, expected_minutes, expected_seconds);
+    checkTZDate(7, date10, expected_year, expected_month, expected_date, expected_hours, expected_minutes, expected_seconds, expected_milliseconds);
+    checkTZDate(8, date11, expected_year, expected_month, expected_date, expected_hours, expected_minutes, expected_seconds, expected_milliseconds, expected_time_zone);
+    checkTZDate(8, date12, expected_year, expected_month, expected_date, 0, expected_minutes, expected_seconds, expected_milliseconds, expected_time_zone);
+    checkTZDate(8, date13, expected_year, expected_month, expected_date, expected_hours, 0, expected_seconds, expected_milliseconds, expected_time_zone);
+    checkTZDate(8, date14, expected_year, expected_month, expected_date, expected_hours, expected_minutes, 0, expected_milliseconds, expected_time_zone);
+    checkTZDate(8, date15, expected_year, expected_month, expected_date, expected_hours, expected_minutes, expected_seconds, 0, expected_time_zone);
+    checkTZDate(7, date16, expected_year, expected_month, expected_date, expected_hours, expected_minutes, expected_seconds, expected_milliseconds);
+    checkTZDate(8, date17, expected_year, expected_month, expected_date, 0, expected_minutes, expected_seconds, expected_milliseconds, expected_time_zone);
+    checkTZDate(8, date18, expected_year, expected_month, expected_date, expected_hours, 0, expected_seconds, expected_milliseconds, expected_time_zone);
+    checkTZDate(8, date19, expected_year, expected_month, expected_date, expected_hours, expected_minutes, 0, expected_milliseconds, expected_time_zone);
+    checkTZDate(8, date20, expected_year, expected_month, expected_date, expected_hours, expected_minutes, expected_seconds, 0, expected_time_zone);
+    checkTZDate(7, date21, expected_year, expected_month, expected_date, expected_hours, expected_minutes, expected_seconds, expected_milliseconds);
+    checkTZDate(8, date22, expected_year, expected_month, expected_date, expected_hours, expected_minutes, expected_seconds, expected_milliseconds, expected_time_zone);
+    checkTZDate(8, date23, expected_year, expected_month, expected_date, expected_hours, expected_minutes, expected_seconds, expected_milliseconds, expected_time_zone);
+    checkTZDate(8, date24, expected_year, expected_month, expected_date, expected_hours, expected_minutes, expected_seconds, expected_milliseconds, expected_time_zone);
+
+    } catch(e) {
+        logError("testTZDate_001 error name:"+ e.name + ",message :" + e.message);
+    }
+}
+
+function checkTZDate(count, paramTZDate, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) {
+    TestEngine.test("checkTZDate() paramTZDate):", paramTZDate instanceof tizen.TZDate);
+    if (count == 0)
+        return;
+
+    switch (count) {
+        case 1:
+            TestEngine.assertEqual("checkTZDate() timezone", arg1, paramTZDate.getTimezone());
+            break;
+        case 3:
+        case 4:
+        case 5:
+        case 6:
+        case 7:
+        case 8:
+            TestEngine.assertEqual("checkTZDate() year", arg1, paramTZDate.getFullYear());
+            TestEngine.assertEqual("checkTZDate() month", arg2, paramTZDate.getMonth());
+            TestEngine.assertEqual("checkTZDate() date", arg3, paramTZDate.getDate());
+            if (count > 3)
+                TestEngine.assertEqual("checkTZDate() hours", arg4, paramTZDate.getHours());
+            if (count > 4)
+                TestEngine.assertEqual("checkTZDate() minutes", arg5, paramTZDate.getMinutes());
+            if (count > 5)
+                TestEngine.assertEqual("checkTZDate() seconds", arg6, paramTZDate.getSeconds());
+            if (count > 6)
+                TestEngine.assertEqual("checkTZDate() milliseconds", arg7, paramTZDate.getMilliseconds());
+            if (count > 7)
+                TestEngine.assertEqual("checkTZDate() timezone", arg8, paramTZDate.getTimezone());
+            break;
+    }
+}
+
+function checkValidParamTZDate() {
+    var invalidDate = null;
+    var validDate = new tizen.TZDate(expected_year, expected_month, expected_date, expected_hours, expected_minutes, expected_seconds, expected_milliseconds);
+
+    try {
+        invalidDate = new tizen.TZDate(ERROR_NUM);
+        TestEngine.test("checkValidParamTZDate() new tizen.TZDate(ERROR_NUM) isTZDate?", invalidDate instanceof tizen.TZDate);
+        TestEngine.test("checkValidParamTZDate() new tizen.TZDate(ERROR_NUM) invalidDate.toString() != 'Invalid Date'", invalidDate.toString() != "Invalid Date");
+        TestEngine.assertEqual("checkValidParamTZDate() new tizen.TZDate(ERROR_NUM) invalidDate.getTimezone()==validDate.getTimezone()", invalidDate.getTimezone(), validDate.getTimezone());
+    } catch (e) {
+        logError("checkValidParamTZDate() new tizen.TZDate(ERROR_NUM) error"+ e.name + ",message :" + e.message);
+    }
+
+    try {
+        invalidDate = new tizen.TZDate(new Date(-2000, 0, 0));
+        TestEngine.test("checkValidParamTZDate() new tizen.TZDate(new Date(-2000, 0, 0)) isTZDate?", invalidDate instanceof tizen.TZDate);
+        TestEngine.test("checkValidParamTZDate() new tizen.TZDate(new Date(-2000, 0, 0)) invalidDate.toString() != 'Invalid Date'", invalidDate.toString() != "Invalid Date");
+        TestEngine.assertEqual("checkValidParamTZDate() new tizen.TZDate(new Date(-2000, 0, 0)) invalidDate.getTimezone()==validDate.getTimezone()", invalidDate.getTimezone(), validDate.getTimezone());
+    } catch (e) {
+        logError("checkValidParamTZDate() new tizen.TZDate(new Date(-2000, 0, 0)) error"+ e.name + ",message :" + e.message);
+    }
+
+    try {
+        invalidDate = new tizen.TZDate(new Date(), ERROR_NUM);
+        TestEngine.test("checkValidParamTZDate() new tizen.TZDate(new Date(), ERROR_NUM) isTZDate?", invalidDate instanceof tizen.TZDate);
+        TestEngine.test("checkValidParamTZDate() new tizen.TZDate(new Date(), ERROR_NUM) invalidDate.toString() != 'Invalid Date'", invalidDate.toString() != "Invalid Date");
+        TestEngine.assertEqual("checkValidParamTZDate() new tizen.TZDate(new Date(), ERROR_NUM) invalidDate.getTimezone()==validDate.getTimezone()", invalidDate.getTimezone(), validDate.getTimezone());
+    } catch (e) {
+        logError("checkValidParamTZDate() new tizen.TZDate(new Date(), ERROR_NUM) error"+ e.name + ",message :" + e.message);
+    }
+
+    try {
+        invalidDate = new tizen.TZDate(expected_year, expected_month, expected_date, expected_hours, expected_minutes, expected_seconds, expected_milliseconds,  ERROR_NUM);
+        compareDate(validDate, invalidDate, validDate.getTimezone());
+    } catch (e) {
+        TestEngine.assertEqual("checkValidParamTZDate() new tizen.TZDate(expected_year, expected_month, expected_date, expected_hours, expected_minutes, expected_seconds, expected_milliseconds, ERROR_NUM) error", e.name, INVALID_VALUES_ERR);
+    }
+}
+
+function testTZDate_002() {
+    var date1 = new Date(0, 0, 0);
+    var date2 = new Date(30, 4, 1, 17, 20, 30, 769);
+    
+    var tzdate1 = new tizen.TZDate(date1, "Europe/London");
+    compareDate(date1, tzdate1, "Europe/London");
+    var tzdate2 = new tizen.TZDate(date1);
+    compareDate(date1, tzdate2);
+    var tzdate3 = new tizen.TZDate(date2, "Europe/London");
+    compareDate(date2, tzdate3, "Europe/London");
+    var tzdate4 = new tizen.TZDate(date2);
+    compareDate(date2, tzdate4);
+
+}
+
+function compareDate(date, tzdate, timezone) {
+    TestEngine.assertEqual("compareDate() year", date.getFullYear(), tzdate.getFullYear());
+    TestEngine.assertEqual("compareDate() month", date.getMonth(), tzdate.getMonth());
+    TestEngine.assertEqual("compareDate() day", date.getDate(), tzdate.getDate());
+    TestEngine.assertEqual("compareDate() hours", date.getHours(), tzdate.getHours());
+    TestEngine.assertEqual("compareDate() mins", date.getMinutes(), tzdate.getMinutes());
+    TestEngine.assertEqual("compareDate() sec", date.getSeconds(), tzdate.getSeconds());
+    TestEngine.assertEqual("compareDate() millisec", date.getMilliseconds(), tzdate.getMilliseconds());
+    if (!isUndefined(timezone))
+        TestEngine.assertEqual("compareDate() timezone", timezone, tzdate.getTimezone());
+}
+
+function testTimeDuration() {
+    var duration1 = new tizen.TimeDuration(20, "MSECS");
+    var duration2 = new tizen.TimeDuration(30, "SECS");
+    var duration3 = new tizen.TimeDuration(20, "MINS");
+    var duration4 = new tizen.TimeDuration(30, "HOURS");
+    var duration5 = new tizen.TimeDuration(20, "DAYS");
+    var duration6 = new tizen.TimeDuration(20);
+    var duration7 = new tizen.TimeDuration(20, null);
+    var duration8 = new tizen.TimeDuration(20, undefined);
+    var duration9 = new tizen.TimeDuration(20, "DAYS", ERROR_NUM);
+    var duration10 = new tizen.TimeDuration(20, "DAYS", null);
+    var duration11 = new tizen.TimeDuration(20, "DAYS", undefined);
+
+    checkTimeDuration(duration1, 20, "MSECS");
+    checkTimeDuration(duration2, 30, "SECS");
+    checkTimeDuration(duration3, 20, "MINS");
+    checkTimeDuration(duration4, 30, "HOURS");
+    checkTimeDuration(duration5, 20, "DAYS");
+    checkTimeDuration(duration6, 20, null);
+    checkTimeDuration(duration7, 20, null);
+    checkTimeDuration(duration8, 20, null);
+    checkTimeDuration(duration9, 20, "DAYS");
+    checkTimeDuration(duration10, 20, "DAYS");
+    checkTimeDuration(duration11, 20, "DAYS");
+
+    duration1.length = duration2.length;
+    duration1.unit = duration2.unit;
+    checkTimeDuration(duration1, duration2.length, duration2.unit);
+}
+
+function checkTimeDuration(duration, expected_length, expected_unit) {
+    TestEngine.test("checkTimeDuration() duration instanceof tizen.TimeDuration :", duration instanceof tizen.TimeDuration);
+    if (isNull(expected_unit))
+        expected_unit = "MSECS";
+
+    TestEngine.testPresence2(duration, "length");
+    TestEngine.testPresence2(duration, "unit");
+    TestEngine.assertEqual("checkTimeDuration() length", expected_length, duration.length);
+    TestEngine.assertEqual("checkTimeDuration() unit", expected_unit, duration.unit);
+}
+
+function checkValidParamTimeDuration(args) {
+    var defaultLength = 0;
+    var defaultUnit = "MSECS";
+    var invalidTimeDuration = null;
+    try {
+        invalidTimeDuration = new tizen.TimeDuration(ERROR_STR);
+        checkTimeDuration(invalidTimeDuration, defaultLength, defaultUnit);
+    } catch (e) {
+        logError("checkValidParamTimeDuration() new tizen.TimeDuration(ERROR_STR) error"+ e.name + ",message :" + e.message);
+    }
+
+    try {
+        invalidTimeDuration = new tizen.TimeDuration(null);
+        checkTimeDuration(invalidTimeDuration, defaultLength, defaultUnit);
+    } catch (e) {
+        logError("checkValidParamTimeDuration() new tizen.TimeDuration(null) error"+ e.name + ",message :" + e.message);
+    }
+
+    try {
+        invalidTimeDuration = new tizen.TimeDuration(undefined);
+        checkTimeDuration(invalidTimeDuration, defaultLength, defaultUnit);
+    } catch (e) {
+        logError("checkValidParamTimeDuration() new tizen.TimeDuration(undefined) error"+ e.name + ",message :" + e.message);
+    }
+
+    try {
+        invalidTimeDuration = new tizen.TimeDuration(ERROR_STR, "SECS");
+        checkTimeDuration(invalidTimeDuration, defaultLength, "SECS");
+    } catch (e) {
+        logError("checkValidParamTimeDuration() new tizen.TimeDuration(ERROR_STR, 'SECS') error"+ e.name + ",message :" + e.message);
+    }
+
+    try {
+        invalidTimeDuration = new tizen.TimeDuration(undefined, "SECS");
+        checkTimeDuration(invalidTimeDuration, defaultLength, "SECS");
+    } catch (e) {
+        logError("checkValidParamTimeDuration() new tizen.TimeDuration(undefined, 'SECS') error"+ e.name + ",message :" + e.message);
+    }
+
+    try {
+        invalidTimeDuration = new tizen.TimeDuration(null, "SECS");
+        checkTimeDuration(invalidTimeDuration, defaultLength, "SECS");
+    } catch (e) {
+        logError("checkValidParamTimeDuration() new tizen.TimeDuration(null, 'SECS') error"+ e.name + ",message :" + e.message);
+    }
+
+    try {
+        invalidTimeDuration = new tizen.TimeDuration(20, "MINUTES");
+        checkTimeDuration(invalidTimeDuration, 20, defaultUnit);
+    } catch (e) {
+        logError("checkValidParamTimeDuration() new tizen.TimeDuration(20, 'MINUTES') error"+ e.name + ",message :" + e.message);
+    }
+
+    try {
+        invalidTimeDuration = new tizen.TimeDuration(20, ERROR_NUM);
+        checkTimeDuration(invalidTimeDuration, 20, defaultUnit);
+    } catch (e) {
+        logError("checkValidParamTimeDuration() new tizen.TimeDuration(20, ERROR_NUM) error"+ e.name + ",message :" + e.message);
+    }
+}
+
+function testGetCurrentDateTime(){
+    var current_dt = tizen.time.getCurrentDateTime();
+    TestEngine.test("testGetCurrentDateTime() date:", current_dt  instanceof tizen.TZDate);
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+    for(var i=0; i<testAdditionalParamArray.length; i++){
+        TestEngine.test("testGetCurrentDateTime() date:", tizen.time.getCurrentDateTime(testAdditionalParamArray[i])  instanceof tizen.TZDate);
+     }
+ }
+/*
+function testsetCurrentDateTime(){
+    try {
+        tizen.time.setCurrentDateTime(new tizen.TZDate(2011, 11, 10, 3, 45, 4));
+        var current_dt = tizen.time.getCurrentDateTime();
+        TestEngine.assertEqual("testGetCurrentDateTime() get year", 2011, current_dt.getFullYear());
+
+        var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+        for(var i=0; i<testAdditionalParamArray.length; i++){
+            tizen.time.setCurrentDateTime(new tizen.TZDate(2011, 11, 10, 3, 45, 4), testAdditionalParamArray[i]);
+            var current_dt = tizen.time.getCurrentDateTime();
+            TestEngine.assertEqual("testGetCurrentDateTime() get year", 2011, current_dt.getFullYear());
+         }
+    } catch (e) {
+        TestEngine.test("testGetCurrentDateTime() expected exception:" + e.name, true);
+    }
+}
+
+function testsetCurrentDateTime_N(){
+    TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.time, "setCurrentDateTime", ERROR_NUM);
+    TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.time, "setCurrentDateTime", null);
+    TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.time, "setCurrentDateTime", undefined);
+}
+*/
+function testGetLocalTimeZone(){
+    var timeZone = tizen.time.getLocalTimezone();
+    //var expectedTimeZone = "Asia/Seoul";
+
+    TestEngine.log(timeZone);
+    TestEngine.test("testGetLocalTimeZone() ", isString(timeZone));
+    if (expectedLocalTimeZone != "TZID")
+        TestEngine.assertEqual("testGetLocalTimeZone() ", expectedLocalTimeZone, timeZone);
+
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+    for(var i=0; i<testAdditionalParamArray.length; i++){
+        var timeZone = tizen.time.getLocalTimezone(testAdditionalParamArray[i]);
+        TestEngine.test("testGetLocalTimeZone() ", isString(timeZone));
+        if (expectedLocalTimeZone != "TZID")
+            TestEngine.assertEqual("testGetLocalTimeZone() ", expectedLocalTimeZone, timeZone);
+     }
+}
+
+function testGetAvailableTimeZones(){
+    var timeZones = tizen.time.getAvailableTimezones();
+
+    TestEngine.test("testGetAvailableTimeZones() ", isArray(timeZones));
+    TestEngine.log("timeZones.length:" + timeZones.length);
+
+    timeZones.forEach(function(tz) {
+         TestEngine.log("timeZones:[" + tz + "]");
+    });
+
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+    for(var i=0; i<testAdditionalParamArray.length; i++){
+        var timeZones = tizen.time.getAvailableTimezones(testAdditionalParamArray[i]);
+        TestEngine.test("testGetAvailableTimeZones() ", isArray(timeZones));
+    }
+}
+
+function testGetDateFormat() {
+    var defaultDateFormat = tizen.time.getDateFormat();
+
+    //var expectedDefaultDateFormat = "D, M d, y";
+    //var expectedShortDateFormat = "m/d/y";
+
+    TestEngine.test("testGetDateFormat() ", isString(defaultDateFormat));
+
+    var shortDateFormat = tizen.time.getDateFormat(null);
+    TestEngine.test("testGetDateFormat() ", isString(shortDateFormat));
+
+    var shortDateFormat1 = tizen.time.getDateFormat(undefined);
+    TestEngine.test("testGetDateFormat() ", isString(shortDateFormat1));
+
+    var shortDateFormat2 = tizen.time.getDateFormat(true);
+    TestEngine.test("testGetDateFormat() ", isString(shortDateFormat2));
+
+    var notShortDateFormat = tizen.time.getDateFormat(false);
+    TestEngine.test("testGetDateFormat() ", isString(notShortDateFormat));
+
+    if (expectedLocalTimeZone != "TZID") {
+        TestEngine.assertEqual("testGetDateFormat() ", expectedDefaultDateFormat, defaultDateFormat);
+        TestEngine.assertEqual("testGetDateFormat() ", expectedDefaultDateFormat, shortDateFormat);
+        TestEngine.assertEqual("testGetDateFormat() ", expectedDefaultDateFormat, shortDateFormat1);
+        TestEngine.assertEqual("testGetDateFormat() ", expectedShortDateFormat, shortDateFormat2);
+        TestEngine.assertEqual("testGetDateFormat() ", expectedDefaultDateFormat, notShortDateFormat);
+    }
+
+
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+    for(var i=0; i<testAdditionalParamArray.length; i++){
+        var notShortDateFormat = tizen.time.getDateFormat(false, testAdditionalParamArray[i]);
+        TestEngine.test("testGetDateFormat() ", isString(notShortDateFormat));
+        if (expectedLocalTimeZone != "TZID")
+            TestEngine.assertEqual("testGetDateFormat() ", expectedDefaultDateFormat, notShortDateFormat);
+    }
+}
+
+function testGetTimeFormat() {
+
+    var defaultTimeFormat = tizen.time.getTimeFormat();
+    TestEngine.test("testGetTimeFormat() ", isString(defaultTimeFormat));
+    if (expectedLocalTimeZone != "TZID") {
+        if ((expectedDefaultTimeFormat_12 == defaultTimeFormat)||(expectedDefaultTimeFormat_24 == defaultTimeFormat)) {
+            TestEngine.test("testGetTimeFormat() defaultTimeFormat", true);
+        } else {
+            TestEngine.test("testGetTimeFormat() defaultTimeFormat", false);
+        }
+    }
+
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+    for(var i=0; i<testAdditionalParamArray.length; i++){
+        var defaultTimeFormat = tizen.time.getTimeFormat(testAdditionalParamArray[i]);
+        TestEngine.test("testGetTimeFormat() ", isString(defaultTimeFormat));
+        if (expectedLocalTimeZone != "TZID") {
+            if ((expectedDefaultTimeFormat_12 == defaultTimeFormat)||(expectedDefaultTimeFormat_24 == defaultTimeFormat)) {
+                TestEngine.test("testGetTimeFormat() defaultTimeFormat", true);
+            } else {
+                TestEngine.test("testGetTimeFormat() defaultTimeFormat", false);
+            }
+        }
+    }
+}
+
+function testIsLeapYear() {
+    var leapYear    = 2012;
+    TestEngine.assertEqual("testIsLeapYear() leapYear",    true, tizen.time.isLeapYear(leapYear));
+}
+
+function testIsLeapYear_N() {
+    var notLeapYear = 2013;
+    TestEngine.assertEqual("testIsLeapYear() notLeapYear", false, tizen.time.isLeapYear(notLeapYear));
+}
+
+function testTimeDurationDifference(){
+    var durationA = new tizen.TimeDuration(2, "DAYS");
+    var durationB = new tizen.TimeDuration(96, "HOURS");
+    var diff = durationB.difference(durationA);
+
+    checkTimeDuration(diff, 2, "DAYS");
+}
+
+function testTimeDurationDifference_N(){
+    var durationA = new tizen.TimeDuration(2, "DAYS");
+    var durationB = new tizen.TimeDuration(96, "HOURS");
+    var diff = durationB.difference(durationA);
+
+    TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, durationB, "difference");
+
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+    for(var i=0; i<testAdditionalParamArray.length; i++){
+        var diff = durationB.difference(durationA, testAdditionalParamArray[i]);
+        checkTimeDuration(diff, 2, "DAYS");
+        TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, durationB, "difference", testAdditionalParamArray[i]);
+    }
+}
+
+function testTimeDurationEqualsTo(){
+    var durationA = new tizen.TimeDuration(2, "DAYS");
+    var durationB = new tizen.TimeDuration(47, "HOURS");
+    var durationC = new tizen.TimeDuration(2880, "MINS");
+
+    TestEngine.test("testTimeDurationEqualsTo() durationB.equalsTo(durationA)", durationB.equalsTo(durationA) == false);
+    TestEngine.test("testTimeDurationEqualsTo() durationA.equalsTo(durationC)", durationA.equalsTo(durationC) == true);
+
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+    for(var i=0; i<testAdditionalParamArray.length; i++){
+        TestEngine.test("testTimeDurationEqualsTo() durationA.equalsTo(durationC, testAdditionalParamArray[i])", durationA.equalsTo(durationC, testAdditionalParamArray[i]) == true);
+    }
+}
+
+function testTimeDurationEqualsTo_N(){
+    var durationA = new tizen.TimeDuration(2, "DAYS");
+    var durationB = new tizen.TimeDuration(47, "HOURS");
+    var durationC = new tizen.TimeDuration(2880, "MINS");
+
+    TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, durationB, "equalsTo");
+
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+    for(var i=0; i<testAdditionalParamArray.length; i++){
+        TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, durationB, "equalsTo", testAdditionalParamArray[i]);
+    }
+}
+
+function testTimeDurationLessThan(){
+    var durationA = new tizen.TimeDuration(2, "DAYS");
+    var durationB = new tizen.TimeDuration(50, "HOURS");
+    var durationC = new tizen.TimeDuration(2880, "MINS");
+
+    TestEngine.test("testTimeDurationLessThan() durationB.lessThan(durationA)", durationB.lessThan(durationA) == false);
+    TestEngine.test("testTimeDurationLessThan() durationA.lessThan(durationB)", durationA.lessThan(durationB) == true);
+    TestEngine.test("testTimeDurationLessThan() durationA.lessThan(durationA)", durationA.lessThan(durationC) == false);
+
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+    for(var i=0; i<testAdditionalParamArray.length; i++){
+        TestEngine.test("testTimeDurationLessThan() durationA.lessThan(durationC, testAdditionalParamArray[i])", durationA.lessThan(durationC, testAdditionalParamArray[i]) == false);
+    }
+}
+
+function testTimeDurationLessThan_N(){
+    var durationA = new tizen.TimeDuration(2, "DAYS");
+    var durationB = new tizen.TimeDuration(50, "HOURS");
+    var durationC = new tizen.TimeDuration(2880, "MINS");
+
+    TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, durationB, "lessThan");
+
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+    for(var i=0; i<testAdditionalParamArray.length; i++){
+        TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, durationB, "lessThan", testAdditionalParamArray[i]);
+    }
+}
+
+function testTimeDurationGreaterThan(){
+    var durationA = new tizen.TimeDuration(2, "DAYS");
+    var durationB = new tizen.TimeDuration(50, "HOURS");
+    var durationC = new tizen.TimeDuration(2880, "MINS");
+
+    TestEngine.test("testTimeDurationGreaterThan() durationB.greaterThan(durationA)", durationB.greaterThan(durationA) == true);
+    TestEngine.test("testTimeDurationGreaterThan() durationA.greaterThan(durationB)", durationA.greaterThan(durationB) == false);
+    TestEngine.test("testTimeDurationGreaterThan() durationA.greaterThan(durationA)", durationA.greaterThan(durationC) == false);
+
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+    for(var i=0; i<testAdditionalParamArray.length; i++){
+        TestEngine.test("testTimeDurationGreaterThan() durationA.greaterThan(durationC, testAdditionalParamArray[i])", durationA.greaterThan(durationC, testAdditionalParamArray[i]) == false);
+    }
+}
+
+function testTimeDurationGreaterThan_N(){
+    var durationA = new tizen.TimeDuration(2, "DAYS");
+    var durationB = new tizen.TimeDuration(50, "HOURS");
+    var durationC = new tizen.TimeDuration(2880, "MINS");
+
+    TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, durationB, "greaterThan");
+
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+    for(var i=0; i<testAdditionalParamArray.length; i++){
+        TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, durationB, "greaterThan", testAdditionalParamArray[i]);
+    }
+}
+
+function testGetDate()
+{
+    TestEngine.test("testGetDate() date:",            isNumber(date.getDate()));
+    TestEngine.test("testGetDate() date value",     date.getDate()==expected_date);
+
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+    for(var i=0; i<testAdditionalParamArray.length; i++){
+        TestEngine.test("testGetDate() date:",            isNumber(date.getDate(testAdditionalParamArray[i])));
+        TestEngine.test("testGetDate() date value",     date.getDate(testAdditionalParamArray[i])==expected_date);
+    }
+}
+
+function testGetDay()
+{
+    var day_min = 0;     //Sunday
+    var day_max = 6;    //Saturday
+
+    TestEngine.test("testGetDay() day type:",                    isNumber(date.getDay()));
+    TestEngine.test("testGetDay() day value test Minimum",     day_min <= date.getDay());
+    TestEngine.test("testGetDay() day value test Maximum",     day_max >= date.getDay());
+
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+    for(var i=0; i<testAdditionalParamArray.length; i++){
+        TestEngine.test("testGetDay() day:",            isNumber(date.getDay(testAdditionalParamArray[i])));
+        TestEngine.test("testGetDay() day value",     date.getDay(testAdditionalParamArray[i])==date.getDay());
+    }
+}
+
+function testGetFullYear()
+{
+    TestEngine.test("testGetFullYear() year type:",        isNumber(date.getFullYear()));
+    TestEngine.test("testGetFullYear() year value",     date.getFullYear() == expected_year);
+
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+    for(var i=0; i<testAdditionalParamArray.length; i++){
+        TestEngine.test("testGetFullYear() year:",            isNumber(date.getFullYear(testAdditionalParamArray[i])));
+        TestEngine.test("testGetFullYear() year value",     date.getFullYear(testAdditionalParamArray[i])==expected_year);
+    }
+}
+
+function testGetHours()
+{
+    var min_hour = 0;
+    var max_hour = 23;
+
+    TestEngine.test("testGetHours() Hour type:",        isNumber(date.getHours()));
+
+    TestEngine.test("testGetHours() Hour value test Minimum",     min_hour <= date.getHours());
+    TestEngine.test("testGetHours() Hour value test Maximum",     max_hour >= date.getHours());
+
+    TestEngine.test("testGetHours() Hour value",     date.getHours()==expected_hours);
+
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+    for(var i=0; i<testAdditionalParamArray.length; i++){
+        TestEngine.test("testGetHours() Hour:",            isNumber(date.getHours(testAdditionalParamArray[i])));
+        TestEngine.test("testGetHours() Hour value",     date.getHours(testAdditionalParamArray[i])==expected_hours);
+    }
+}
+
+function testGetMilliseconds()
+{
+    var min_millisecond = 0;
+    var max_millisecond = 999;
+
+    TestEngine.test("testGetMilliseconds() Millisecond type:",        isNumber(date.getMilliseconds()));
+
+    TestEngine.test("testGetMilliseconds() Millisecond value test Minimum",     min_millisecond <= date.getMilliseconds());
+    TestEngine.test("testGetMilliseconds() Millisecond value test Maximum",     max_millisecond >= date.getMilliseconds());
+
+    TestEngine.test("testGetMilliseconds() Millisecond value",     date.getMilliseconds()==expected_milliseconds);
+
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+    for(var i=0; i<testAdditionalParamArray.length; i++){
+        TestEngine.test("testGetMilliseconds() Millisecond:",            isNumber(date.getMilliseconds(testAdditionalParamArray[i])));
+        TestEngine.test("testGetMilliseconds() Millisecond value",     date.getMilliseconds(testAdditionalParamArray[i])==expected_milliseconds);
+    }
+}
+
+function testGetMinute()
+{
+    var min_minute = 0;
+    var max_minute = 59;
+
+    TestEngine.test("testGetMinute() Minute type:",        isNumber(date.getMinutes()));
+
+    TestEngine.test("testGetMinute() Minute value test Minimum",     min_minute <= date.getMinutes());
+    TestEngine.test("testGetMinute() Minute value test Maximum",     max_minute >= date.getMinutes());
+
+    TestEngine.test("testGetMinute() Minute value",     date.getMinutes()==expected_minutes);
+
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+    for(var i=0; i<testAdditionalParamArray.length; i++){
+        TestEngine.test("testGetMinute() Minute:",            isNumber(date.getMinutes(testAdditionalParamArray[i])));
+        TestEngine.test("testGetMinute() Minute value",     date.getMinutes(testAdditionalParamArray[i])==expected_minutes);
+    }
+}
+
+function testGetMonth()
+{
+    var min_month = 0;
+    var max_month = 11;
+
+    TestEngine.test("testGetMonth() Month type:",        isNumber(date.getMonth()));
+
+    TestEngine.test("testGetMonth() Month value test Minimum",     min_month <= date.getMonth());
+    TestEngine.test("testGetMonth() Month value test Maximum",     max_month >= date.getMonth());
+
+    TestEngine.test("testGetMonth() Month value",     date.getMonth()==expected_month);
+
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+    for(var i=0; i<testAdditionalParamArray.length; i++){
+        TestEngine.test("testGetMonth() Month:",            isNumber(date.getMonth(testAdditionalParamArray[i])));
+        TestEngine.test("testGetMonth() Month value",     date.getMonth(testAdditionalParamArray[i])==expected_month);
+    }
+}
+
+function testGetSeconds()
+{
+    var min_second = 0;
+    var max_second = 59;
+
+    TestEngine.test("testGetSeconds() Second type:",        isNumber(date.getSeconds()));
+
+    TestEngine.test("testGetSeconds() Second value test Minimum",     min_second <= date.getSeconds());
+    TestEngine.test("testGetSeconds() Second value test Maximum",     max_second >= date.getSeconds());
+
+    TestEngine.test("testGetSeconds() Second value",     date.getSeconds()==expected_seconds);
+
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+    for(var i=0; i<testAdditionalParamArray.length; i++){
+        TestEngine.test("testGetSeconds() Second:",            isNumber(date.getSeconds(testAdditionalParamArray[i])));
+        TestEngine.test("testGetSeconds() Second value",     date.getSeconds(testAdditionalParamArray[i])==expected_seconds);
+    }
+}
+
+function testSetDate()
+{
+    var tmpDate = new tizen.TZDate(2000, 4, 3);
+    var cmpDate = new Date(2000, 4, 3);
+
+    var testDataArray          = [1, 12, 21, 30, 31];
+    var testInvalidDataArray   = [-1, 32, 123];
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+
+    var testName = "testSetDate()";
+    var testFunctionName = "setDate";
+
+    for(var i=0; i<testDataArray.length; i++){
+        tmpDate.setDate(testDataArray[i]);
+        TestEngine.test(testName + " data value " + testDataArray[i], tmpDate.getDate() == testDataArray[i]);
+        TestEngine.test(testName + " data value " + testDataArray[i], true);
+    }
+
+    for (var i=0; i<testAdditionalParamArray.length; i++) {
+        tmpDate.setDate(testDataArray[i], testAdditionalParamArray[i]);
+        TestEngine.test(testName + " data value " + testDataArray[i], tmpDate.getDate() == testDataArray[i]);
+        TestEngine.test(testName + " data value " + testDataArray[i], true);
+    }
+
+    for(var i=0; i<testInvalidDataArray.length; i++){
+        tmpDate.setDate(testInvalidDataArray[i]);
+        cmpDate.setDate(testInvalidDataArray[i]);
+        TestEngine.test(testName + " data value " + testInvalidDataArray[i], tmpDate.getDate() == cmpDate.getDate());
+    }
+}
+
+function testSetFullYear() {
+    var tmpDate = new tizen.TZDate(2000, 5, 3);
+    var cmpDate = new Date(2000, 5, 3);
+
+    var testDataArray          = [2011, 1921, 2012];
+    var testInvalidDataArray   = [12345, 23];
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+
+    for(var i=0; i<testDataArray.length; i++){
+        tmpDate.setFullYear(testDataArray[i]);
+        TestEngine.test("testSetFullYear() data value " + testDataArray[i], tmpDate.getFullYear() == testDataArray[i]);
+    }
+
+    for (var i=0; i<testAdditionalParamArray.length; i++) {
+        tmpDate.setFullYear(testDataArray[i], testAdditionalParamArray[i]);
+        TestEngine.test("testSetFullYear() data value " + testDataArray[i], tmpDate.getFullYear() == testDataArray[i]);
+    }
+
+    for(var i=0; i<testInvalidDataArray.length; i++){
+        tmpDate.setFullYear(testInvalidDataArray[i]);
+        cmpDate.setFullYear(testInvalidDataArray[i]);
+        TestEngine.test("testSetFullYear()  data value " + testInvalidDataArray[i] + "(1)" + tmpDate.getFullYear() + "(2)" + cmpDate.getFullYear(), tmpDate.getFullYear() == cmpDate.getFullYear());
+    }
+}
+
+function testSetHours() {
+    var tmpDate = new tizen.TZDate(2000, 5, 3);
+    var cmpDate = new Date(2000, 5, 3);
+
+    var testDataArray          = [0, 1, 12, 23];
+    var testInvalidDataArray   = [-1, 24];
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+
+    for(var i=0; i<testDataArray.length; i++){
+        tmpDate.setHours(testDataArray[i]);
+        TestEngine.test("testSetHours() data value " + testDataArray[i], tmpDate.getHours() == testDataArray[i]);
+    }
+
+    for (var i=0; i<testAdditionalParamArray.length; i++) {
+        tmpDate.setHours(testDataArray[i], testAdditionalParamArray[i]);
+        TestEngine.test("testSetHours() data value " + testDataArray[i], tmpDate.getHours() == testDataArray[i]);
+    }
+
+    for(var i=0; i<testInvalidDataArray.length; i++){
+        tmpDate.setHours(testInvalidDataArray[i]);
+        cmpDate.setHours(testInvalidDataArray[i]);
+        TestEngine.test("testSetHours() data value " + testInvalidDataArray[i], tmpDate.getHours() == cmpDate.getHours());
+    }
+}
+
+function testSetMilliseconds()
+{
+    var tmpDate = new tizen.TZDate(2000, 5, 3);
+    var cmpDate = new Date(2000, 5, 3);
+
+    var testDataArray          = [0, 12, 332, 999];
+    var testInvalidDataArray   = [-1, 1000, 1234];
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+
+    var testName = "testSetMilliseconds()";
+    var testFunctionName = "setMilliseconds";
+
+    for(var i=0; i<testDataArray.length; i++){
+        tmpDate.setMilliseconds(testDataArray[i]);
+        TestEngine.test(testName + " data value " + testDataArray[i], tmpDate.getMilliseconds() == testDataArray[i]);
+    }
+
+    for (var i=0; i<testAdditionalParamArray.length; i++) {
+        tmpDate.setMilliseconds(testDataArray[i], testAdditionalParamArray[i]);
+        TestEngine.test(testName + " data value" + testDataArray[i], tmpDate.getMilliseconds() == testDataArray[i]);
+    }
+
+    for(var i=0; i<testInvalidDataArray.length; i++){
+        tmpDate.setMilliseconds(testInvalidDataArray[i]);
+        cmpDate.setMilliseconds(testInvalidDataArray[i]);
+        TestEngine.test(testName + " data value " + testInvalidDataArray[i], tmpDate.getMilliseconds() == cmpDate.getMilliseconds());
+    }
+
+}
+
+function testSetMinutes () {
+    var tmpDate = new tizen.TZDate(2000, 5, 3);
+    var cmpDate = new Date(2000, 5, 3);
+
+    var testDataArray          = [0, 1, 57, 59];
+    var testInvalidDataArray   = [-1, 60, 1234];
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+
+    var testName          = "testSetMinutes()";
+    var testFunctionName  = "setMinutes";
+
+    for(var i=0; i<testDataArray.length; i++){
+        tmpDate.setMinutes(testDataArray[i]);
+        TestEngine.test(testName + " data value " + testDataArray[i], tmpDate.getMinutes() == testDataArray[i]);
+    }
+
+    for (var i=0; i<testAdditionalParamArray.length; i++) {
+        tmpDate.setMinutes(testDataArray[i], testAdditionalParamArray[i]);
+        TestEngine.test(testName + " data value" + testDataArray[i], tmpDate.getMinutes() == testDataArray[i]);
+    }
+
+    for(var i=0; i<testInvalidDataArray.length; i++){
+        tmpDate.setMinutes(testInvalidDataArray[i]);
+        cmpDate.setMinutes(testInvalidDataArray[i]);
+        TestEngine.test(testName + " data value " + testInvalidDataArray[i], tmpDate.getMinutes() == cmpDate.getMinutes());
+    }
+}
+
+function testSetMonth() {
+      var tmpDate = new tizen.TZDate(2000, 5, 3);
+    var cmpDate = new Date(2000, 5, 3);
+
+    var testDataArray          = [0, 1, 5, 11];
+    var testInvalidDataArray   = [-1, 12, 20];
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+
+    var testName          = "testSetMonth()";
+    var testFunctionName  = "setMonth";
+
+    for(var i=0; i<testDataArray.length; i++){
+        tmpDate.setMonth(testDataArray[i]);
+        TestEngine.test(testName + " data value " + testDataArray[i] + " : " + tmpDate.getMonth(), tmpDate.getMonth() == testDataArray[i]);
+    }
+
+    for (var i=0; i<testAdditionalParamArray.length; i++) {
+        tmpDate.setMonth(testDataArray[i], testAdditionalParamArray[i]);
+        TestEngine.test(testName + " data value " + testDataArray[i] + " : " + tmpDate.getMonth(), tmpDate.getMonth() == testDataArray[i]);
+    }
+
+    for(var i=0; i<testInvalidDataArray.length; i++){
+        tmpDate.setMonth(testInvalidDataArray[i]);
+        cmpDate.setMonth(testInvalidDataArray[i]);
+        TestEngine.test(testName + "  data value " + testInvalidDataArray[i] + "(1)" + tmpDate.getMonth() + "(2)" + cmpDate.getMonth(), tmpDate.getMonth() == cmpDate.getMonth());
+    }
+}
+
+function testSetSeconds() {
+      var tmpDate = new tizen.TZDate(2000, 5, 3);
+    var cmpDate = new Date(2000, 5, 3);
+
+    var testDataArray          = [0, 1, 22, 59];
+    var testInvalidDataArray   = [-1, 60, 70];
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+
+    var testName          = "testSetSeconds()";
+    var testFunctionName  = "setSeconds";
+
+    for(var i=0; i<testAdditionalParamArray.length; i++){
+        tmpDate.setSeconds(testDataArray[i]);
+        TestEngine.test(testName + " data value " + testDataArray[i], tmpDate.getSeconds() == testDataArray[i]);
+    }
+
+    for(var i=0; i<testDataArray.length; i++){
+        tmpDate.setSeconds(testDataArray[i], testAdditionalParamArray[i]);
+        TestEngine.test(testName + " data value " + testDataArray[i], tmpDate.getSeconds() == testDataArray[i]);
+    }
+
+    for(var i=0; i<testInvalidDataArray.length; i++){
+        tmpDate.setSeconds(testInvalidDataArray[i]);
+        cmpDate.setSeconds(testInvalidDataArray[i]);
+        TestEngine.test(testName + " data value " + testInvalidDataArray[i], tmpDate.getSeconds() == cmpDate.getSeconds());
+    }
+}
+
+function testGetUTCDate(){
+    var testName          = "testGetUTCDate()";
+
+    var minData = 1;
+    var maxData = 31;
+    var expectedUTCDate = 11;
+
+    TestEngine.log(date.getUTCDate());
+    TestEngine.test(testName + "isNumber:",        isNumber(date.getUTCDate()));
+
+    TestEngine.test(testName + "test Minimum",     minData <= date.getUTCDate());
+    TestEngine.test(testName + "test Maximum",     maxData >= date.getUTCDate());
+
+    TestEngine.assertEqual(testName + "value",     expectedUTCDate, date.getUTCDate());
+
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+    for(var i=0; i<testAdditionalParamArray.length; i++){
+        TestEngine.assertEqual(testName + "value",     expectedUTCDate, date.getUTCDate(testAdditionalParamArray[i]));
+    }
+
+}
+
+function testSetUTCDate() {
+    var testName          = "testSetUTCDate()";
+
+    var tmpDate = new tizen.TZDate(2000, 5, 3);
+    var cmpDate = new Date(2000, 5, 3);
+
+    var testDataArray          = [1, 1, 22, 31];
+
+    for(var i=0; i<testDataArray.length; i++){
+        tmpDate.setUTCDate(testDataArray[i]);
+        cmpDate.setUTCDate(testDataArray[i]);
+        TestEngine.assertEqual(testName + " data value " + testDataArray[i], cmpDate.getUTCDate(), tmpDate.getUTCDate());
+    }
+
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+    for(var i=0; i<testAdditionalParamArray.length; i++){
+        tmpDate.setUTCDate(testDataArray[i], testAdditionalParamArray[i]);
+        cmpDate.setUTCDate(testDataArray[i]);
+        TestEngine.assertEqual(testName + " data value " + testDataArray[i], cmpDate.getUTCDate(), tmpDate.getUTCDate());
+    }
+
+    var testInvalidDataArray   = [-1, 60, 70];
+    var testFunctionName  = "setUTCDate";
+
+    for(var i=0; i<testInvalidDataArray.length; i++){
+        tmpDate.setUTCDate(testInvalidDataArray[i]);
+        cmpDate.setUTCDate(testInvalidDataArray[i]);
+        TestEngine.test(testName + " data value " + testInvalidDataArray[i], tmpDate.getUTCDate() == cmpDate.getUTCDate());
+    }
+}
+
+function testGetUTCDay(){
+    var testName          = "testGetUTCDay()";
+
+    var minData = 0;
+    var maxData = 6;
+    var expectedValue = 5;
+
+    TestEngine.log(date.getUTCDay());
+    TestEngine.test(testName + "isNumber:",        isNumber(date.getUTCDay()));
+
+    TestEngine.test(testName + "test Minimum",     minData <= date.getUTCDay());
+    TestEngine.test(testName + "test Maximum",     maxData >= date.getUTCDay());
+
+    TestEngine.assertEqual(testName + " value",     expectedValue, date.getUTCDay());
+
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+    for(var i=0; i<testAdditionalParamArray.length; i++){
+        TestEngine.assertEqual(testName + "value",     expectedValue, date.getUTCDay(testAdditionalParamArray[i]));
+    }
+}
+
+function testGetUTCFullYear(){
+    var testName          = "testGetUTCFullYear()";
+
+    TestEngine.test(testName + " year type:",        isNumber(date.getUTCFullYear()));
+    TestEngine.test(testName + " year value",     date.getUTCFullYear() == expected_year);
+
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+    for(var i=0; i<testAdditionalParamArray.length; i++){
+        TestEngine.assertEqual(testName + "value",     expected_year, date.getUTCFullYear(testAdditionalParamArray[i]));
+    }
+}
+
+function testSetUTCFullYear(){
+    var testName = "testSetUTCFullYear()";
+
+    var tmpDate = new tizen.TZDate(2000, 5, 3);
+    var cmpDate = new Date(2000, 5, 3);
+
+    var testDataArray          = [1999, 1234, 2011, 2012];
+    var testInvalidDataArray   = [12345, 23];
+    var testFunctionName  = "setUTCFullYear";
+
+    for(var i=0; i<testDataArray.length; i++){
+        tmpDate.setUTCFullYear(testDataArray[i]);
+        TestEngine.assertEqual(testName + " data value " + testDataArray[i], testDataArray[i], tmpDate.getUTCFullYear());
+    }
+
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+    for(var i=0; i<testAdditionalParamArray.length; i++){
+        tmpDate.setUTCFullYear(testDataArray[i], testAdditionalParamArray[i]);
+        TestEngine.assertEqual(testName + " data value " + testDataArray[i], testDataArray[i], tmpDate.getUTCFullYear());
+    }
+
+    for(var i=0; i<testInvalidDataArray.length; i++){
+        tmpDate.setUTCFullYear(testInvalidDataArray[i]);
+        cmpDate.setUTCFullYear(testInvalidDataArray[i]);
+        TestEngine.test(testName + " data value " + testInvalidDataArray[i], tmpDate.getUTCFullYear() == cmpDate.getUTCFullYear());
+    }
+}
+
+function testGetUTCHours(){
+    var testName          = "testGetUTCHours()";
+
+    var minData = 0;
+    var maxData = 23;
+    var expectedUTCDate = 0;
+
+    TestEngine.log(date.getUTCDate());
+    TestEngine.test(testName + "isNumber:",        isNumber(date.getUTCHours()));
+
+    TestEngine.test(testName + "test Minimum",     minData <= date.getUTCHours());
+    TestEngine.test(testName + "test Maximum",     maxData >= date.getUTCHours());
+
+    TestEngine.assertEqual(testName + "value",     expectedUTCDate, date.getUTCHours());
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+    for(var i=0; i<testAdditionalParamArray.length; i++){
+        TestEngine.assertEqual(testName + "value",     expectedUTCDate, date.getUTCHours(testAdditionalParamArray[i]));
+    }
+}
+
+function testSetUTCHours() {
+    var testName          = "testSetUTCHours()";
+
+    var tmpDate = new tizen.TZDate(2000, 5, 3);
+    var cmpDate = new Date(2000, 5, 3);
+
+    var testDataArray          = [0, 1, 22, 23];
+
+    for(var i=0; i<testDataArray.length; i++){
+        tmpDate.setUTCHours(testDataArray[i]);
+        TestEngine.assertEqual(testName + " data value " + testDataArray[i], testDataArray[i], tmpDate.getUTCHours());
+    }
+
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+    for(var i=0; i<testAdditionalParamArray.length; i++){
+        tmpDate.setUTCHours(testDataArray[i], testAdditionalParamArray[i]);
+        TestEngine.assertEqual(testName + " data value " + testDataArray[i], testDataArray[i], tmpDate.getUTCHours());
+    }
+
+    var testInvalidDataArray   = [-1, 60, 70];
+    var testFunctionName  = "setUTCHours";
+    for(var i=0; i<testInvalidDataArray.length; i++){
+        tmpDate.setUTCHours(testInvalidDataArray[i]);
+        cmpDate.setUTCHours(testInvalidDataArray[i]);
+        TestEngine.test(testName + " data value " + testInvalidDataArray[i], tmpDate.getUTCHours() == cmpDate.getUTCHours());
+    }
+}
+
+function testGetUTCMilliseconds(){
+    var testName          = "testGetUTCMilliseconds()";
+
+    var minData = 0;
+    var maxData = 999;
+    var expectedUTCDate = 12;
+
+    TestEngine.log(date.getUTCMilliseconds());
+    TestEngine.test(testName + "isNumber:",        isNumber(date.getUTCMilliseconds()));
+
+    TestEngine.test(testName + "test Minimum",     minData <= date.getUTCMilliseconds());
+    TestEngine.test(testName + "test Maximum",     maxData >= date.getUTCMilliseconds());
+
+    TestEngine.assertEqual(testName + " value",     expectedUTCDate, date.getUTCMilliseconds());
+
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+    for(var i=0; i<testAdditionalParamArray.length; i++){
+        TestEngine.assertEqual(testName + "value",     expectedUTCDate, date.getUTCMilliseconds(testAdditionalParamArray[i]));
+    }
+}
+
+function testSetUTCMilliseconds() {
+    var testName          = "testSetUTCMilliseconds()";
+
+    var tmpDate = new tizen.TZDate(2000, 5, 3);
+    var cmpDate = new Date(2000, 5, 3);
+
+    var testDataArray          = [0, 22, 123, 999];
+
+    for(var i=0; i<testDataArray.length; i++){
+        tmpDate.setUTCMilliseconds(testDataArray[i]);
+        TestEngine.assertEqual(testName + " data value " + testDataArray[i], testDataArray[i], tmpDate.getUTCMilliseconds());
+    }
+
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+    for(var i=0; i<testAdditionalParamArray.length; i++){
+        tmpDate.setUTCMilliseconds(testDataArray[i], testAdditionalParamArray[i]);
+        TestEngine.assertEqual(testName + " data value " + testDataArray[i], testDataArray[i], tmpDate.getUTCMilliseconds());
+    }
+
+    var testInvalidDataArray   = [-1, 60, 70];
+    var testFunctionName  = "setUTCMilliseconds";
+    for(var i=0; i<testInvalidDataArray.length; i++){
+        tmpDate.setUTCMilliseconds(testInvalidDataArray[i]);
+        cmpDate.setUTCMilliseconds(testInvalidDataArray[i]);
+        TestEngine.test(testName + " data value " + testInvalidDataArray[i], tmpDate.getUTCMilliseconds() == cmpDate.getUTCMilliseconds());
+    }
+}
+
+function testGetUTCMinutes(){
+    var testName          = "testGetUTCMinutes()";
+
+    var minData = 0;
+    var maxData = 59;
+    var expectedUTCDate = 55;
+
+    TestEngine.log(date.getUTCMinutes());
+    TestEngine.test(testName + "isNumber:",        isNumber(date.getUTCMinutes()));
+
+    TestEngine.test(testName + "test Minimum",     minData <= date.getUTCMinutes());
+    TestEngine.test(testName + "test Maximum",     maxData >= date.getUTCMinutes());
+
+    TestEngine.assertEqual(testName + " value",     expectedUTCDate, date.getUTCMinutes());
+
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+    for(var i=0; i<testAdditionalParamArray.length; i++) {
+        TestEngine.assertEqual(testName + "value",     expectedUTCDate, date.getUTCMinutes(testAdditionalParamArray[i]));
+    }
+}
+
+function testSetUTCMinutes() {
+    var testName          = "testSetUTCMinutes()";
+
+    var tmpDate = new tizen.TZDate(2000, 5, 3);
+    var cmpDate = new Date(2000, 5, 3);
+
+    var testDataArray          = [0, 1, 47, 59];
+
+    for(var i=0; i<testDataArray.length; i++){
+        tmpDate.setUTCMinutes(testDataArray[i]);
+        TestEngine.assertEqual(testName + " data value " + testDataArray[i], testDataArray[i], tmpDate.getUTCMinutes());
+    }
+
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+    for(var i=0; i<testAdditionalParamArray.length; i++){
+        tmpDate.setUTCMinutes(testDataArray[i], testAdditionalParamArray[i]);
+        TestEngine.assertEqual(testName + " data value " + testDataArray[i], testDataArray[i], tmpDate.getUTCMinutes());
+    }
+
+    var testInvalidDataArray   = [-1, 60, 70];
+    var testFunctionName  = "setUTCMinutes";
+    for(var i=0; i<testInvalidDataArray.length; i++){
+        tmpDate.setUTCMinutes(testInvalidDataArray[i]);
+        cmpDate.setUTCMinutes(testInvalidDataArray[i]);
+        TestEngine.test(testName + " data value " + testInvalidDataArray[i], tmpDate.getUTCMinutes() == cmpDate.getUTCMinutes());
+    }
+}
+
+function testGetUTCMonth(){
+    var testName          = "testGetUTCMonth()";
+
+    var minData = 0;
+    var maxData = 11;
+    var expectedUTCDate = 10;
+
+    TestEngine.log(date.getUTCMonth());
+    TestEngine.test(testName + "isNumber:",        isNumber(date.getUTCMonth()));
+
+    TestEngine.test(testName + "test Minimum",     minData <= date.getUTCMonth());
+    TestEngine.test(testName + "test Maximum",     maxData >= date.getUTCMonth());
+
+    TestEngine.assertEqual(testName + " value",     expectedUTCDate, date.getUTCMonth());
+
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+    for(var i=0; i<testAdditionalParamArray.length; i++){
+        TestEngine.assertEqual(testName + "value",     expectedUTCDate, date.getUTCMonth(testAdditionalParamArray[i]));
+    }
+}
+
+function testSetUTCMonth() {
+    var testName          = "testSetUTCMonth()";
+
+      var tmpDate = new tizen.TZDate(2000, 5, 3);
+    var cmpDate = new Date(2000, 5, 3);
+
+    var testDataArray          = [0, 1, 10, 11];
+
+    for(var i=0; i<testDataArray.length; i++){
+        tmpDate.setUTCMonth(testDataArray[i]);
+        TestEngine.assertEqual(testName + " data value " + testDataArray[i], testDataArray[i], tmpDate.getUTCMonth());
+    }
+
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+    for(var i=0; i<testAdditionalParamArray.length; i++){
+        tmpDate.setUTCMonth(testDataArray[i], testAdditionalParamArray[i]);
+        TestEngine.assertEqual(testName + " data value " + testDataArray[i], testDataArray[i], tmpDate.getUTCMonth());
+    }
+
+    var testInvalidDataArray   = [-1, 60, 70];
+    var testFunctionName  = "setUTCMonth";
+    for(var i=0; i<testInvalidDataArray.length; i++){
+        tmpDate.setUTCMonth(testInvalidDataArray[i]);
+        cmpDate.setUTCMonth(testInvalidDataArray[i]);
+        TestEngine.test(testName + " data value " + testInvalidDataArray[i], tmpDate.getUTCMonth() == cmpDate.getUTCMonth());
+    }
+}
+
+function testGetUTCSeconds(){
+    var testName          = "testGetUTCSeconds()";
+
+    var minData = 0;
+    var maxData = 59;
+    var expectedUTCDate = 54;
+
+    TestEngine.log(date.getUTCSeconds());
+    TestEngine.test(testName + "isNumber:",        isNumber(date.getUTCSeconds()));
+
+    TestEngine.test(testName + "test Minimum",     minData <= date.getUTCSeconds());
+    TestEngine.test(testName + "test Maximum",     maxData >= date.getUTCSeconds());
+
+    TestEngine.assertEqual(testName + " value",     expectedUTCDate, date.getUTCSeconds());
+
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+    for(var i=0; i<testAdditionalParamArray.length; i++){
+        TestEngine.assertEqual(testName + "value",     expectedUTCDate, date.getUTCSeconds(testAdditionalParamArray[i]));
+    }
+}
+
+function testSetUTCSeconds() {
+    var testName          = "testSetUTCSeconds()";
+
+    var tmpDate = new tizen.TZDate(2000, 5, 3);
+    var cmpDate = new Date(2000, 5, 3);
+
+    var testDataArray          = [0, 1, 50, 59];
+
+    for(var i=0; i<testDataArray.length; i++){
+        tmpDate.setUTCSeconds(testDataArray[i]);
+        TestEngine.assertEqual(testName + " data value " + testDataArray[i], testDataArray[i], tmpDate.getUTCSeconds());
+    }
+
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+    for(var i=0; i<testAdditionalParamArray.length; i++){
+        tmpDate.setUTCSeconds(testDataArray[i], testAdditionalParamArray[i]);
+        TestEngine.assertEqual(testName + " data value " + testDataArray[i], testDataArray[i], tmpDate.getUTCSeconds());
+    }
+
+    var testInvalidDataArray   = [-1, 60, 70];
+    var testFunctionName  = "setUTCSeconds";
+    for(var i=0; i<testInvalidDataArray.length; i++){
+        tmpDate.setUTCSeconds(testInvalidDataArray[i]);
+        cmpDate.setUTCSeconds(testInvalidDataArray[i]);
+        TestEngine.test(testName + " data value " + testInvalidDataArray[i], tmpDate.getUTCSeconds() == cmpDate.getUTCSeconds());
+    }
+}
+
+function testGetTimezone() {
+    var testName          = "testGetTimezone()";
+    var expectedTimezone  = "Asia/Dubai";
+
+    var retTimezone = date.getTimezone();
+    TestEngine.log(testName + "retTimeZone:[" +     isString(retTimezone) + "]");
+    TestEngine.test(testName + "isString:",        isString(retTimezone));
+    TestEngine.assertEqual(testName + "timezone", expectedTimezone, retTimezone);
+
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+    for(var i=0; i<testAdditionalParamArray.length; i++){
+        TestEngine.assertEqual(testName + "timezone", expectedTimezone, date.getTimezone(testAdditionalParamArray[i]));
+    }
+}
+
+function testToTimezone() {
+    var testName = "testToTimezone()";
+    var timezone = "Australia/Sydney";        //GMT+11
+
+    var expectedSydneyHours = 11;
+
+    var retDate = date.toTimezone(timezone);
+
+    try {
+        TestEngine.log("retDate:" + retDate);
+        TestEngine.test(testName + "retDate instanceof tizen.TZDate):",        retDate instanceof tizen.TZDate);
+        TestEngine.assertEqual(testName + "expectedHours", expectedSydneyHours, retDate.getHours());
+
+        var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+        for(var i=0; i<testAdditionalParamArray.length; i++){
+            var retDate = date.toTimezone(timezone, testAdditionalParamArray[i]);
+            TestEngine.assertEqual(testName + "expectedHours", expectedSydneyHours, retDate.getHours());
+        }
+
+    } catch (e) {
+        TestEngine.test("unexpected exception:" + e.name, false);
+    }
+}
+
+function testToTimezone_N() {
+    TestEngine.catchErrorType("name", INVALID_VALUES_ERR, date, "toTimezone");
+    TestEngine.catchErrorType("name", INVALID_VALUES_ERR, date, "toTimezone", ERROR_STR);
+    TestEngine.catchErrorType("name", INVALID_VALUES_ERR, date, "toTimezone", undefined);
+}
+
+function testToLocalTimezone() {
+    var testName = "testToLocalTimezone()";
+    var timezone = "Australia/Sydney";
+
+    //var expectedHours = 9;
+
+    try {
+        var localTimezoneDate = date.toLocalTimezone();//GMT+9
+        TestEngine.test(testName + "localTimezoneDate instanceof tizen.TZDate):",        localTimezoneDate instanceof tizen.TZDate);
+        //TestEngine.assertEqual(testName + "expectedHours", expectedHours, localTimezoneDate.getHours());
+
+        var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+        for(var i=0; i<testAdditionalParamArray.length; i++){
+            var localTimezoneDate = date.toLocalTimezone(testAdditionalParamArray[i]);
+            //TestEngine.assertEqual(testName + "expectedHours", expectedHours, localTimezoneDate.getHours());
+        }
+
+    } catch (e) {
+        TestEngine.test("unexpected exception:" + e.name, false);
+    }
+
+}
+
+
+function testToUTC(){
+    var testName          = "testToUTC()";
+    var utcTime = date.toUTC();
+    var expectedUTCTime;
+    if (tizen.time.getTimeFormat().indexOf("ap") == -1)
+        expectedUTCTime = "Friday, November 11, 2011, 00:55:54 GMT+0000 GMT";
+    else
+        expectedUTCTime = "Friday, November 11, 2011, 12:55:54 AM GMT+0000 GMT";
+
+    TestEngine.log("UTC Time:" + utcTime);
+    TestEngine.test(testName + "isUndefined(retDate):",        !isUndefined(utcTime));
+    TestEngine.assertEqual(testName, expectedUTCTime, utcTime);
+
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+    for(var i=0; i<testAdditionalParamArray.length; i++){
+        var utcTime = date.toUTC(testAdditionalParamArray[i]);
+        TestEngine.assertEqual(testName, expectedUTCTime, utcTime);
+    }
+}
+
+function testDifference(){
+    var testName          = "testDifference()";
+
+    var expectedLength = -127631360;
+    var expectedUnit = "MSECS";
+    var testDate = date.addDuration(new tizen.TimeDuration(expectedLength, expectedUnit));
+
+    var differenceDuration = testDate.difference(date);
+    TestEngine.log("differenceDuration:" + differenceDuration);
+    TestEngine.test(testName + "instanceof tizen.TimeDuration:",        differenceDuration instanceof tizen.TimeDuration);
+    TestEngine.assertEqual(testName + "length",  expectedLength, differenceDuration.length);
+    TestEngine.assertEqual(testName + "unit",  expectedUnit, differenceDuration.unit);
+
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+    for(var i=0; i<testAdditionalParamArray.length; i++){
+        var differenceDuration = testDate.difference(date, testAdditionalParamArray[i]);
+        TestEngine.test(testName + "instanceof tizen.TimeDuration:",        differenceDuration instanceof tizen.TimeDuration);
+        TestEngine.assertEqual(testName + "length",  expectedLength, differenceDuration.length);
+        TestEngine.assertEqual(testName + "unit",  expectedUnit, differenceDuration.unit);
+    }
+}
+
+function testDifference_N(){
+    TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, date, "difference");
+    TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, date, "difference", ERROR_NUM);
+    TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, date, "difference", null);
+    TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, date, "difference", undefined);
+}
+
+function testEqualsTo() {
+    var testName          = "testEqualsTo()";
+
+    var testDate = new tizen.TZDate(
+            expected_year,             //year
+            expected_month,             //month
+            expected_date,             //day
+            expected_hours,             //hours
+            expected_minutes,         //minutes
+            expected_seconds,         //seconds
+            expected_milliseconds,    //milliseconds
+            expected_time_zone        //timeZone
+    );
+
+    var testDate2 = new tizen.TZDate();
+
+    TestEngine.assertEqual(testName, true,  date.equalsTo(testDate));
+    TestEngine.assertEqual(testName, false, date.equalsTo(testDate2));
+
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+    for(var i=0; i<testAdditionalParamArray.length; i++){
+        TestEngine.assertEqual(testName, true,  date.equalsTo(testDate, testAdditionalParamArray[i]));
+    }
+}
+
+function testEqualsTo_N() {
+    TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, date, "equalsTo");
+    TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, date, "equalsTo", ERROR_NUM);
+    TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, date, "equalsTo", null);
+    TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, date, "equalsTo", undefined);
+}
+
+function testEarlierThan() {
+    var testName          = "testEarlierThan()";
+
+    var testDate = new tizen.TZDate(
+            expected_year,             //year
+            expected_month,             //month
+            expected_date,             //day
+            expected_hours + 2,             //hours
+            expected_minutes,         //minutes
+            expected_seconds,         //seconds
+            expected_milliseconds,    //milliseconds
+            expected_time_zone        //timeZone
+    );
+    TestEngine.assertEqual(testName, true,  date.earlierThan(testDate));
+
+    var testDate2 = new tizen.TZDate(
+            expected_year,             //year
+            expected_month,             //month
+            expected_date,             //day
+            expected_hours -1,             //hours
+            expected_minutes,         //minutes
+            expected_seconds,         //seconds
+            expected_milliseconds,    //milliseconds
+            expected_time_zone        //timeZone
+    );
+    TestEngine.assertEqual(testName, false, date.earlierThan(testDate2));
+
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+    for(var i=0; i<testAdditionalParamArray.length; i++){
+        TestEngine.assertEqual(testName, true,  date.earlierThan(testDate, testAdditionalParamArray[i]));
+    }
+}
+
+function testEarlierThan_N() {
+    TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, date, "earlierThan");
+    TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, date, "earlierThan", ERROR_NUM);
+    TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, date, "earlierThan", null);
+    TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, date, "earlierThan", undefined);
+}
+
+function testLaterThan() {
+    var testName          = "testLaterThan()";
+
+    var testDate = new tizen.TZDate(
+            expected_year,             //year
+            expected_month,             //month
+            expected_date,             //day
+            expected_hours + 2,             //hours
+            expected_minutes,         //minutes
+            expected_seconds,         //seconds
+            expected_milliseconds,    //milliseconds
+            expected_time_zone        //timeZone
+    );
+    TestEngine.assertEqual(testName, false,  date.laterThan(testDate));
+
+    var testDate2 = new tizen.TZDate(
+            expected_year,             //year
+            expected_month,             //month
+            expected_date,             //day
+            expected_hours -1,             //hours
+            expected_minutes,         //minutes
+            expected_seconds,         //seconds
+            expected_milliseconds,    //milliseconds
+            expected_time_zone        //timeZone
+    );
+    TestEngine.assertEqual(testName, true, date.laterThan(testDate2));
+
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+    for(var i=0; i<testAdditionalParamArray.length; i++){
+        TestEngine.assertEqual(testName, false,  date.laterThan(testDate, testAdditionalParamArray[i]));
+    }
+}
+
+function testLaterThan_N() {
+    TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, date, "laterThan");
+    TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, date, "laterThan", ERROR_NUM);
+    TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, date, "laterThan", null);
+    TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, date, "laterThan", undefined);
+}
+
+function testAddDuration(){
+    var testName          = "testAddDuration()";
+
+    var testDuration = new tizen.TimeDuration(2, "DAYS");
+
+    var addedDate = date.addDuration(testDuration);
+    var difference = addedDate.difference(date);
+
+    TestEngine.assertEqual(testName, date.getDate()+2, addedDate.getDate());
+    TestEngine.assertEqual(testName, true, difference.equalsTo(testDuration));
+
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+    for(var i=0; i<testAdditionalParamArray.length; i++){
+        var addedDate = date.addDuration(testDuration, testAdditionalParamArray[i]);
+        TestEngine.assertEqual(testName, date.getDate()+2, addedDate.getDate());
+    }
+}
+
+function testAddDuration_N(){
+    TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, date, "addDuration");
+    TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, date, "addDuration", ERROR_NUM);
+    TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, date, "addDuration", null);
+    TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, date, "addDuration", undefined);
+}
+
+function testToLocaleDateString() {
+    var testName          = "testToLocaleDateString()";
+    //var expectedLocaleDateString = "Friday, November 11, 2011";
+    //var expectedLocaleDateString = date.toLocaleDateString();
+    var localeDateString = date.toLocaleDateString();
+    TestEngine.test("testToLocaleDateString() ", isString(localeDateString));
+    if (expectedLocalTimeZone != "TZID")
+        TestEngine.assertEqual(testName, expectedLocaleDateString, localeDateString);
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+    for(var i=0; i<testAdditionalParamArray.length; i++){
+        localeDateString = date.toLocaleDateString(testAdditionalParamArray[i]);
+        TestEngine.test("testToLocaleDateString() ", isString(localeDateString));
+        if (expectedLocalTimeZone != "TZID")
+            TestEngine.assertEqual(testName, expectedLocaleDateString, localeDateString);
+    }
+}
+
+function testToLocaleTimeString() {
+    var testName          = "testToLocaleTimeString()";
+    //var expectedLocaleTimeString = "4:55:54 AM";
+    //var expectedLocaleTimeString = date.toLocaleTimeString();
+    var localeTimeString = date.toLocaleTimeString();
+    TestEngine.test("testToLocaleTimeString() ", isString(localeTimeString));
+    if (expectedLocalTimeZone != "TZID") {
+        if ((expectedLocaleTimeString_12 == localeTimeString)||(expectedLocaleTimeString_24 == localeTimeString)) {
+            TestEngine.test("testToLocaleTimeString()", true);
+        } else {
+            TestEngine.test("testToLocaleTimeString() localeTimeString" + localeTimeString, false);
+        }
+    }
+
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+    for(var i=0; i<testAdditionalParamArray.length; i++){
+        localeTimeString = date.toLocaleTimeString(testAdditionalParamArray[i]);
+        TestEngine.test("testToLocaleTimeString() ", isString(localeTimeString));
+        if (expectedLocalTimeZone != "TZID") {
+            if ((expectedLocaleTimeString_12 == localeTimeString)||(expectedLocaleTimeString_24 == localeTimeString)) {
+                TestEngine.test("testToLocaleTimeString()", true);
+            } else {
+                TestEngine.test("testToLocaleTimeString() localeTimeString" + localeTimeString, false);
+            }
+        }
+    }
+}
+
+function testToLocaleString() {
+    var testName          = "testToLocaleString()";
+    //var expectedLocaleString = "Friday, November 11, 2011 4:55:54 AM";
+    //var expectedLocaleString = date.toLocaleString();
+    var localeString = date.toLocaleString();
+    TestEngine.test("testToLocaleString() ", isString(localeString));
+    if (expectedLocalTimeZone != "TZID") {
+        if ((expectedLocaleString_12 == localeString)||(expectedLocaleString_24 == localeString)) {
+            TestEngine.test("testToLocaleString()", true);
+        } else {
+            TestEngine.test("testToLocaleString() localeString" + localeString, false);
+        }
+    }
+
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+    for(var i=0; i<testAdditionalParamArray.length; i++){
+        localeString = date.toLocaleString(testAdditionalParamArray[i]);
+        TestEngine.test("testToLocaleString() ", isString(localeString));
+        if (expectedLocalTimeZone != "TZID") {
+            if ((expectedLocaleString_12 == localeString)||(expectedLocaleString_24 == localeString)) {
+                TestEngine.test("testToLocaleString()", true);
+            } else {
+                TestEngine.test("testToLocaleString() localeString" + localeString, false);
+            }
+        }
+    }
+}
+
+function testToDateString() {
+    var testName          = "testToDateString()";
+    var expectedDateString = "Friday, November 11, 2011";
+
+    TestEngine.assertEqual(testName, expectedDateString, date.toDateString());
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+    for(var i=0; i<testAdditionalParamArray.length; i++){
+        TestEngine.assertEqual(testName, expectedDateString, date.toDateString(testAdditionalParamArray[i]));
+    }
+}
+
+function testToTimeString() {
+    var testName          = "testToDateString()";
+    var expectedTimeString;
+    if (tizen.time.getTimeFormat().indexOf("ap") == -1)
+        expectedTimeString = "04:55:54 GMT+0400 United Arab Emirates Time";
+    else
+        expectedTimeString = "4:55:54 AM GMT+0400 United Arab Emirates Time";
+
+    TestEngine.assertEqual(testName, expectedTimeString, date.toTimeString());
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+    for(var i=0; i<testAdditionalParamArray.length; i++){
+        TestEngine.assertEqual(testName, expectedTimeString, date.toTimeString(testAdditionalParamArray[i]));
+    }
+}
+
+function testToString() {
+    var testName          = "testToString()";
+    var expectedString;
+    if (tizen.time.getTimeFormat().indexOf("ap") == -1)
+        expectedString = "Friday, November 11, 2011, 04:55:54 GMT+0400 United Arab Emirates Time";
+    else
+        expectedString = "Friday, November 11, 2011, 4:55:54 AM GMT+0400 United Arab Emirates Time";
+
+    TestEngine.assertEqual(testName, expectedString, date.toString());
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+    for(var i=0; i<testAdditionalParamArray.length; i++){
+        TestEngine.assertEqual(testName, expectedString, date.toString(testAdditionalParamArray[i]));
+    }
+}
+
+function testGetTimezoneAbbreviation() {
+    var testName        = "testGetTimezoneAbbreviation()";
+    var expectedString = "CST";
+    var testDate = date.toTimezone("America/Chicago");
+
+    TestEngine.assertEqual(testName, expectedString, testDate.getTimezoneAbbreviation());
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+    for(var i=0; i<testAdditionalParamArray.length; i++){
+        TestEngine.assertEqual(testName, expectedString, testDate.getTimezoneAbbreviation(testAdditionalParamArray[i]));
+    }
+}
+
+function testSecondsFromUTC() {
+    var testName          = "testSecondsFromUTC()";
+    var expectedData = -14400;
+
+    TestEngine.assertEqual(testName, expectedData, date.secondsFromUTC());
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+    for(var i=0; i<testAdditionalParamArray.length; i++){
+        TestEngine.assertEqual(testName, expectedData, date.secondsFromUTC(testAdditionalParamArray[i]));
+    }
+}
+
+function testIsDST() {
+    var testName          = "testIsDST()";
+    var expectedData = false;
+
+    TestEngine.assertEqual(testName, expectedData, date.isDST());
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+    for(var i=0; i<testAdditionalParamArray.length; i++){
+        TestEngine.assertEqual(testName, expectedData, date.isDST(testAdditionalParamArray[i]));
+    }
+}
+
+function testGetPreviousDSTTransition() {
+    var testName          = "testGetPreviousDSTTransition()";
+
+    var testDate = new tizen.TZDate(
+            expected_year,             //year
+            expected_month,         //month
+            expected_date,             //day
+            expected_hours,         //hours
+            expected_minutes,         //minutes
+            expected_seconds,         //seconds
+            expected_milliseconds,    //milliseconds
+            "America/Chicago"        //timeZone
+    );
+
+    var expectedData = 6;
+    var result = testDate.getPreviousDSTTransition();
+
+    TestEngine.assertEqual(testName, true, result instanceof tizen.TZDate);
+    TestEngine.assertEqual(testName, expectedData, result.getDate());
+    TestEngine.test(testName + "isNull(date.getPreviousDSTTransition())",        isNull(date.getPreviousDSTTransition()));
+
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+    for(var i=0; i<testAdditionalParamArray.length; i++){
+        var result = testDate.getPreviousDSTTransition();
+        TestEngine.assertEqual(testName, true, result instanceof tizen.TZDate);
+        TestEngine.assertEqual(testName, expectedData, result.getDate());
+    }
+}
+
+function testGetNextDSTTransition() {
+    var testName          = "testGetNextDSTTransition()";
+
+    var testDate = new tizen.TZDate(
+            expected_year,             //year
+            expected_month,         //month
+            expected_date,             //day
+            expected_hours,         //hours
+            expected_minutes,         //minutes
+            expected_seconds,         //seconds
+            expected_milliseconds,    //milliseconds
+            "America/Chicago"        //timeZone
+    );
+
+    var expectedData = 11;
+    var result = testDate.getNextDSTTransition();
+    TestEngine.assertEqual(testName, true, result instanceof tizen.TZDate);
+    TestEngine.assertEqual(testName, expectedData, result.getDate());
+
+    TestEngine.test(testName + "isNull(date.getPreviousDSTTransition())",        isNull(date.getNextDSTTransition()));
+
+    var testAdditionalParamArray = [ERROR_NUM, null, undefined];
+    for(var i=0; i<testAdditionalParamArray.length; i++){
+        var result = testDate.getNextDSTTransition();
+        TestEngine.assertEqual(testName, true, result instanceof tizen.TZDate);
+        TestEngine.assertEqual(testName, expectedData, result.getDate());
+    }
+}
+
+function UTC_setDateTimeChangeListener_P_001 () {
+    TestEngine.log("UTC_setDateTimeChangeListener_P_001");
+
+    tizen.time.setDateTimeChangeListener(emptyFunction);
+    TestEngine.test("UTC_setDateTimeChangeListener_P_001", true);
+}
+
+function UTC_setDateTimeChangeListener_N_001 () {
+    TestEngine.log("UTC_setDateTimeChangeListener_N_001");
+
+    TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.time, "setDateTimeChangeListener", true);
+    TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.time, "setDateTimeChangeListener", false);
+    TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.time, "setDateTimeChangeListener", NaN);
+    TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.time, "setDateTimeChangeListener", 0);
+    TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.time, "setDateTimeChangeListener", "");
+    TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.time, "setDateTimeChangeListener", "TIZEN");
+    TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.time, "setDateTimeChangeListener", []);
+    TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.time, "setDateTimeChangeListener", { });
+    TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.time, "setDateTimeChangeListener", undefined);
+    TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.time, "setDateTimeChangeListener", null);
+
+    TestEngine.test("UTC_setDateTimeChangeListener_N_001", true);
+}
+
+function UTC_unsetDateTimeChangeListener_P_001 () {
+    TestEngine.log("UTC_unsetDateTimeChangeListener_P_001");
+
+    tizen.time.unsetDateTimeChangeListener();
+    TestEngine.test("UTC_unsetDateTimeChangeListener_P_001", true);
+}
+
+function UTC_setTimezoneChangeListener_P_001 () {
+    TestEngine.log("UTC_setTimezoneChangeListener_P_001");
+
+    try {
+        tizen.time.setTimezoneChangeListener(emptyFunction);
+        TestEngine.test("UTC_setTimezoneChangeListener_P_001", true);
+    } catch (e) {
+        TestEngine.test("UTC_setTimezoneChangeListener_P_001" + e.name + " : " + e.message, false);
+    }
+}
+
+function UTC_setTimezoneChangeListener_N_001 () {
+    TestEngine.log("UTC_setTimezoneChangeListener_N_001");
+
+    TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.time, "setTimezoneChangeListener", true);
+    TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.time, "setTimezoneChangeListener", false);
+    TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.time, "setTimezoneChangeListener", NaN);
+    TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.time, "setTimezoneChangeListener", 0);
+    TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.time, "setTimezoneChangeListener", "");
+    TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.time, "setTimezoneChangeListener", "TIZEN");
+    TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.time, "setTimezoneChangeListener", []);
+    TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.time, "setTimezoneChangeListener", { });
+    TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.time, "setTimezoneChangeListener", undefined);
+    TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.time, "setTimezoneChangeListener", null);
+
+    TestEngine.test("UTC_setTimezoneChangeListener_N_001", true);
+}
+
+function UTC_unsetTimezoneChangeListener_P_001 () {
+    TestEngine.log("UTC_unsetTimezoneChangeListener_P_001");
+    try {
+        tizen.time.unsetTimezoneChangeListener();
+        TestEngine.test("UTC_unsetTimezoneChangeListener_P_001", true);
+    } catch (e) {
+        TestEngine.test("UTC_setTimezoneChangeListener_P_001" + e.name + " : " + e.message, false);
+    }
+}
diff --git a/webWidgetTCT_device/test/utc/tests/TestFilesystem.js b/webWidgetTCT_device/test/utc/tests/TestFilesystem.js
new file mode 100755 (executable)
index 0000000..6c2e1d5
--- /dev/null
@@ -0,0 +1,2187 @@
+
+var TEST_ROOT_LOCATION = 'downloads';
+
+var UNKNOWN_ERR         = "UnknownError";
+var TYPE_MISMATCH_ERR   = "TypeMismatchError";
+var IO_ERR              = "IOError";
+var INVALID_VALUES_ERR  = "InvalidValuesError";
+var SECURITY_ERR        = "SecurityError";
+var NOT_FOUND_ERR       = "NotFoundError";
+
+TestEngine.setErrorType(Object);
+TestEngine.setErrorField('name');
+
+
+function isFileObject(obj) {
+       return ((obj instanceof Object) && (obj.isDirectory !== undefined));
+}
+
+function isFile(obj) {
+       return (isFileObject(obj) && !obj.isDirectory);
+}
+
+function isDir(obj) {
+       return (isFileObject(obj) && obj.isDirectory);
+}
+
+function isFilestream(obj) {
+       return true;
+}
+
+function deleteDirectory(parent, dir) {
+  function on_error(err) {
+    TestEngine.test("deleteDirectory() [" + err.name + "]", false);
+  }
+  function on_success() {
+    TestEngine.test("deleteDirectory()", true);
+  }
+  var cb = TestEngine.registerCallback("deleteDirectory", on_success, on_error);
+  try {
+    parent.deleteDirectory(dir.fullPath, true, cb.successCallback, cb.errorCallback);
+  } catch (e) {
+    TestEngine.test("deleteDirectory() [" + e + "]", false);
+  }
+}
+
+function deleteFile(parent, file) {
+  function on_error(err) {
+    TestEngine.test("deleteFile() [" + err.name + "]", false);
+  }
+  function on_success() {
+    TestEngine.test("deleteFile()", true);
+  }
+  var cb = TestEngine.registerCallback("deleteFile", on_success, on_error);
+  try {
+    parent.deleteFile( file.fullPath, cb.successCallback, cb.errorCallback);
+  } catch (e) {
+    TestEngine.test("deleteFile() [" + e + "]", false);
+  }
+}
+
+// For common behaviour use resolve_root_location
+function resolve_root(on_success_callback, on_error_callback) {
+  var cb = TestEngine.registerCallback("resolve", on_success_callback, on_error_callback);
+tizen.filesystem.resolve(TEST_ROOT_LOCATION, cb.successCallback, cb.errorCallback);
+}
+
+function resolve_root_location(handler) {
+  function on_resolve_error(err) {
+    TestEngine.test("resolve() [" + err.name + "]", false);
+  }
+  function on_resolve_success(file) {
+    TestEngine.test("resolve()", isFileObject(file));
+    handler(file);
+  }
+  var cb = TestEngine.registerCallback("resolve", on_resolve_success, on_resolve_error);
+  tizen.filesystem.resolve(TEST_ROOT_LOCATION, cb.successCallback, cb.errorCallback);
+}
+
+var counter = 1;
+
+function getFileName() {
+  var nr = Math.floor(Math.random() * 1000);
+  var date = new Date();
+  return "test_tizen_filesystem_file_" + nr + "_" + (counter++) + "_"
+         + date.getMinutes() + date.getSeconds() + date.getMilliseconds();
+}
+
+function getDirName() {
+  var nr = Math.floor(Math.random() * 1000);
+  var date = new Date();
+  return "test_tizen_filesystem_dir_" + nr + "_" + (counter++) + "_"
+         + date.getMinutes() + date.getSeconds() + date.getMilliseconds();
+}
+
+function createFileForParent(parent) {
+  var result = parent.createFile(getFileName());
+  TestEngine.test("createFile()", isFile(result));
+  return result;
+}
+
+function createDirForParent(parent) {
+  var result = parent.createDirectory(getDirName());
+  TestEngine.test("createDirectory()", isDir(result));
+  return result;
+}
+
+function testNoExceptionWithMessage(message, fun) {
+  var testResult = true;
+  try {
+    fun();
+  }
+  catch (e) {
+    testResult = false;
+  }
+  TestEngine.test(message, testResult);
+}
+
+function UTC_filesystem_resolve_invalid_pram_success_callback_N_001(){
+       var testName = "UTC_filesystem_resolve_invalid_pram_success_callback";
+
+       function onerror(e) {
+               TestEngine.test("unexpected onerror() <<< e.name:" + e.name, false);
+       }
+
+       var invalid_params = [123, "aaa", true, null, undefined, new Object()];
+
+       for(var i=0; i<invalid_params.length; i++){
+               TestEngine.testPresetError(testName + ":" + invalid_params[i] ,
+                       function() {
+                               tizen.filesystem.resolve(
+                                               TEST_ROOT_LOCATION,
+                                               invalid_params[i],
+                                               function(e) {
+                                                       TestEngine.test("unexpected onerror() <<< e.name:" + e.name, false);
+                                               }       //errorcallback
+                                       );      // resolve
+                       },
+                       TYPE_MISMATCH_ERR
+               );              //testPresetError
+       }
+}
+
+function UTC_filesystem_resolve_invalid_pram_error_callback_N_002(){
+       var testName = "UTC_filesystem_resolve_invalid_pram_error_callback";
+
+       var invalid_params = [123, "aaa", true, new Object()];
+
+       for(var i=0; i<invalid_params.length; i++){
+               TestEngine.testPresetError(testName + ":" + invalid_params[i] ,
+                       function() {
+                               TEST_ROOT_LOCATION,
+                               tizen.filesystem.resolve(function(){
+                                       TestEngine.test("unexpected onsuccess() <<< ", false);
+                               },              //success callback
+                               invalid_params[i]       //error callback
+                               );
+                       },
+                       TYPE_MISMATCH_ERR
+               );      //      testPresetError
+       }
+}
+
+function UTC_filesystem_resolve_invalid_pram_location_N_003(){
+       var testName = "UTC_filesystem_resolve_invalid_pram_location";
+
+       var invalid_params = [123, true, null, undefined, function(){}, new Object()];
+
+       function onresolveSuccess(){
+               TestEngine.test(testName + " unexpected onresolveSuccess() <<< ", false);
+       }
+
+       function onresolveError(e){
+               TestEngine.assertEqual(testName + " expected onresolveError() <<<", NOT_FOUND_ERR, e.name);
+       }
+
+       for(var i=0; i<invalid_params.length; i++){
+               var cb = TestEngine.registerCallback("openStream", onresolveSuccess, onresolveError);
+               tizen.filesystem.resolve(invalid_params[i], cb.successCallback,cb.errorCallback);
+       }
+}
+
+function UTC_filesystem_resolve_invalid_pram_mode_N_004(){
+       var testName = "UTC_filesystem_resolve_invalid_pram_mode";
+
+       var invalid_type_params = [123, true, function(){}, new Object()];
+       for(var i=0; i<invalid_type_params.length; i++){
+               TestEngine.testPresetError(testName + ":" + invalid_type_params[i] ,
+                       function() {
+                               tizen.filesystem.resolve(
+                                               TEST_ROOT_LOCATION,
+                                               function(){
+                                                       TestEngine.test("unexpected onsuccess() <<< " + invalid_value_params[i], false);
+                                               },              //success callback
+                                               function(e) {
+                                                       TestEngine.test("unexpected onerror() <<< e.name:" + e.name, false);
+                                               },      //errorcallback
+                                               invalid_type_params[i]);
+                       },
+                       TYPE_MISMATCH_ERR
+               );      //testPresetError
+       }       //for
+
+       var invalid_value_params = ["k", "abcd"];
+       for(var i=0; i<invalid_value_params.length; i++){
+               TestEngine.testPresetError(testName + ":" + invalid_value_params[i] ,
+                       function() {
+                               tizen.filesystem.resolve(
+                                               TEST_ROOT_LOCATION,
+                                               function(){
+                                                       TestEngine.test("unexpected onsuccess() <<< " + invalid_value_params[i], false);
+                                               },              //success callback
+                                               function(e) {
+                                                       TestEngine.test("unexpected onerror() <<< e.name:" + e.name, false);
+                                               },      //errorcallback
+                                               invalid_value_params[i]);
+                       },
+                       TYPE_MISMATCH_ERR
+               );      //testPresetError
+       }//for
+}
+
+function UTC_filesystem_listStorage_resolve_all_P_001() {
+       tizen.filesystem.listStorages(
+               function(storages) {
+                       console.log(storages.length);
+                       
+                       for (var i = 0; i < storages.length; i++) {
+                               
+                               console.log(storages[i].label);
+                               
+                               tizen.filesystem.resolve(storages[i].label,
+                                       function(f) {
+                                               console.log("resolve ok : " + f.name);
+                                               TestEngine.test("resolve :" + f.name, true);
+                                       },
+                                       function(e) {
+                                               console.log("resolve errror : " + e.name);
+                                               TestEngine.test("resolve :" + e.name, false);
+                                       });     
+                       }
+               },
+               function(e) {
+                       console.log(e.name);
+                       TestEngine.test("resolve :" + e.name, false);
+               });
+}
+
+function UTC_filesystem_getstorage_invalid_pram_onsuccess_N_001() {
+       var testName = "UTC_filesystem_getstorage_invalid_pram_onsuccess";
+
+       var invalid_type_params = [123, "abc", true, null, undefined, new Object()];
+       for(var i=0; i<invalid_type_params.length; i++){
+               TestEngine.testPresetError(testName + ":" + invalid_type_params[i] ,
+                       function() {
+                               tizen.filesystem.getStorage(
+                                               "MMC",
+                                               invalid_type_params[i],                 //success callback
+                                               function(e) {
+                                                       TestEngine.test("unexpected onerror() <<< e.name:" + e.name, false);
+                                               }       //errorcallback
+                                               );
+                       },
+                       TYPE_MISMATCH_ERR
+               );
+       }//for
+}
+
+function UTC_filesystem_getstorage_invalid_pram_onerror_N_002() {
+       var testName = "UTC_filesystem_getstorage_invalid_pram_onerror";
+
+       var invalid_type_params = [123, "abc", true, new Object()];
+       for(var i=0; i<invalid_type_params.length; i++){
+               TestEngine.testPresetError(testName + ":" + invalid_type_params[i] ,
+                       function() {
+                               tizen.filesystem.getStorage(
+                                               "MMC",
+                                               function(){
+                                                       TestEngine.test("unexpected onsuccess() <<< ", false);
+                                               },              //success callback
+                                               invalid_type_params[i]  //errorcallback
+                                               );
+                       },
+                       TYPE_MISMATCH_ERR
+               );
+       }//for
+}
+
+function UTC_filesystem_getstorage_invalid_pram_label_N_003(){
+       var testName = "UTC_filesystem_getstorage_invalid_pram_label";
+
+       var invalid_params = [123, true, null, undefined, function(){}, new Object()];
+
+       function onresolveSuccess(){
+               TestEngine.test(testName + " unexpected onresolveSuccess() <<< ", false);
+       }
+
+       function onresolveError(e){
+               TestEngine.assertEqual(testName + " expected onresolveError() <<<", NOT_FOUND_ERR, e.name);
+       }
+
+       for(var i=0; i<invalid_params.length; i++){
+               var cb = TestEngine.registerCallback("openStream", onresolveSuccess, onresolveError);
+               tizen.filesystem.getStorage(invalid_params[i], cb.successCallback,cb.errorCallback);
+       }
+}
+
+function UTC_filesystem_liststorages_invalid_pram_onsuccess_N_001() {
+       var testName = "UTC_filesystem_liststorages_invalid_pram_onsuccess";
+
+       var invalid_type_params = [123, "abc", true, null, undefined, new Object()];
+       for(var i=0; i<invalid_type_params.length; i++){
+               TestEngine.testPresetError(testName + ":" + invalid_type_params[i] ,
+                       function() {
+                               tizen.filesystem.listStorages(
+                                               invalid_type_params[i],                 //success callback
+                                               function(e) {
+                                                       TestEngine.test("unexpected onerror() <<< e.name:" + e.name, false);
+                                               }       //errorcallback
+                                               );
+                       },
+                       TYPE_MISMATCH_ERR
+               );
+       }//for
+}
+
+function UTC_filesystem_liststorages_invalid_pram_onerror_N_002() {
+       var testName = "UTC_filesystem_liststorages_invalid_pram_onerror";
+
+       var invalid_type_params = [123, "abc", true, new Object()];
+       for(var i=0; i<invalid_type_params.length; i++){
+               TestEngine.testPresetError(testName + ":" + invalid_type_params[i] ,
+                       function() {
+                               tizen.filesystem.listStorages(
+                                               function(){
+                                                       TestEngine.test("unexpected onsuccess() <<< ", false);
+                                               },              //success callback
+                                               invalid_type_params[i]  //errorcallback
+                                               );
+                       },
+                       TYPE_MISMATCH_ERR
+               );
+       }//for
+}
+
+function UTC_filesystem_addstoragestatechangelistener_invalid_pram_onsuccess_N_001() {
+       var testName = "UTC_filesystem_addstoragestatechangelistener_invalid_pram_onsuccess";
+
+       var invalid_type_params = [123, "abc", true, null, undefined, new Object()];
+       for(var i=0; i<invalid_type_params.length; i++){
+               TestEngine.testPresetError(testName + ":" + invalid_type_params[i] ,
+                       function() {
+                               tizen.filesystem.addStorageStateChangeListener(
+                                               invalid_type_params[i],                 //success callback
+                                               function(e) {
+                                                       TestEngine.test("unexpected onerror() <<< e.name:" + e.name, false);
+                                               }       //errorcallback
+                                               );
+                       },
+                       TYPE_MISMATCH_ERR
+               );
+       }//for
+}
+
+function UTC_filesystem_addstoragestatechangelistener_invalid_pram_onerror_N_002() {
+       var testName = "UTC_filesystem_addstoragestatechangelistener_invalid_pram_onerror";
+
+       var invalid_type_params = [123, "abc", true, new Object()];
+       for(var i=0; i<invalid_type_params.length; i++){
+               TestEngine.testPresetError(testName + ":" + invalid_type_params[i] ,
+                       function() {
+                               tizen.filesystem.addStorageStateChangeListener(
+                                               function(){
+                                                       TestEngine.test("unexpected onsuccess() <<< ", false);
+                                               },              //success callback
+                                               invalid_type_params[i]  //errorcallback
+                                               );
+                       },
+                       TYPE_MISMATCH_ERR
+               );
+       }//for
+}
+
+function UTC_filesystem_listfiles_invalid_pram_onsuccess_N_001() {
+       var testName = "UTC_filesystem_listfiles_invalid_pram_onsuccess";
+
+       var invalid_type_params = [123, "abc", true, null, undefined, new Object()];
+        tizen.filesystem.resolve(
+                    "documents",
+                    function(dir){
+                        function onerror(error) {
+                                        TestEngine.test("unexpected onerror() <<< ", false);
+                                }
+
+                               for(var i=0; i<invalid_type_params.length; i++){
+                                       TestEngine.testPresetError(testName + ":" + invalid_type_params[i] ,
+                                               function() { dir.listFiles(invalid_type_params, onerror);}, TYPE_MISMATCH_ERR);
+                               }
+
+                       },function(e){
+                                TestEngine.test("unexpected resolve onerror() <<< ", false);
+                       }, "r");                //resolve
+}
+
+function UTC_filesystem_listfiles_invalid_pram_onerror_N_002() {
+       var testName = "UTC_filesystem_listfiles_invalid_pram_onerror";
+
+       var invalid_type_params = [123, "abc", true, new Object()];
+
+        tizen.filesystem.resolve(
+                    "documents",
+                    function(dir){
+                        function onsuccess(error) {
+                                        TestEngine.test("unexpected onsuccess() <<< ", false);
+                                }
+
+                               for(var i=0; i<invalid_type_params.length; i++){
+                                       TestEngine.testPresetError(testName + ":" + invalid_type_params[i] ,
+                                               function() { dir.listFiles(onsuccess, invalid_type_params);}, TYPE_MISMATCH_ERR);
+                               }
+
+                       },function(e){
+                                TestEngine.test("unexpected resolve onerror() <<< ", false);
+                       }, "r");                //resolve
+
+}
+
+function UTC_filesystem_file_openStream_error_successcb_invalid_param_N_001() {
+       var param = new Array(1,   {}, [], true);
+
+       function on_resolve_error(err) { TestEngine.test("resolve() [" + err.name + "]", false); }
+       function on_resolve_success(file) {
+               var file2 = file.createFile(getFileName());
+
+               function on_openStream_success(stream) {
+                       TestEngine.test("openStream()", isFilestream(stream));
+                       stream.close();
+                       deleteFile(file, file2);
+               }
+
+               function on_openStream_error(err) {
+                       TestEngine.test("openStream() [" + err.name + "]", false);
+               }
+
+               for (var i = 0; i < param.length; i++) {
+                       TestEngine.testPresetError(
+                           "openStream() [TYPE_MISMATCH_ERR]",
+                           function() { stream = file2.openStream("rw", param[i], on_openStream_error); },
+                           TYPE_MISMATCH_ERR
+                 );
+               }
+       }
+       resolve_root(on_resolve_success, on_resolve_error);
+}
+
+function UTC_filesystem_file_openStream_error_mode_invalid_param_N_002() {
+       var param = new Array(1, [], {}, "x", true, function(){});
+
+       function on_resolve_error(err) { TestEngine.test("resolve() [" + err.name + "]", false); }
+       function on_resolve_success(file) {
+               var file2 = file.createFile(getFileName());
+
+               function on_openStream_success(stream) {
+                       TestEngine.test("openStream()", isFilestream(stream));
+                       stream.close();
+                       deleteFile(file, file2);
+               }
+
+               function on_openStream_error(err) {
+                       TestEngine.test("openStream() [" + err.name + "]", false);
+               }
+
+               for (var i = 0; i < param.length; i++) {
+                       TestEngine.testPresetError(
+                           "openStream() [TYPE_MISMATCH_ERR]",
+                           function() { stream = file2.openStream(param[i], on_openStream_success, on_openStream_error); },
+                           TYPE_MISMATCH_ERR
+                 );
+               }
+       }
+       resolve_root(on_resolve_success, on_resolve_error);
+}
+
+function UTC_filesystem_file_openStream_error_encoding_invalid_param_N_003() {
+       var param = new Array(1, [], {}, "333", true, function(){});
+
+       function on_resolve_error(err) { TestEngine.test("resolve() [" + err.name + "]", false); }
+       function on_resolve_success(file) {
+               var file2 = file.createFile(getFileName());
+
+               function on_openStream_success(stream) {
+                       TestEngine.test("openStream()", isFilestream(stream));
+                       stream.close();
+                       deleteFile(file, file2);
+               }
+
+               function on_openStream_error(err) {
+                       TestEngine.test("openStream() [" + err.name + "]", false);
+               }
+
+               for (var i = 0; i < param.length; i++) {
+                       TestEngine.testPresetError(
+                           "openStream() [INVALID_VALUES_ERR]",
+                           function() { stream = file2.openStream("rw", on_openStream_success, on_openStream_error, param[i]); },
+                           TYPE_MISMATCH_ERR
+                 );
+               }
+       }
+       resolve_root(on_resolve_success, on_resolve_error);
+}
+
+function UTC_filesystem_file_readAsText_error_successcb_invalid_param_N_001() {
+       var param = new Array(1, null, undefined, {}, [], true);
+
+       var test_content = "Ala ma kota";
+       function on_resolve_error(err) { TestEngine.test("resolve() [" + err.name + "]", false); }
+       function on_resolve_success(file) {
+               var f = file.createFile(getFileName());
+               TestEngine.test("createFile()", isFile(f));
+
+               function on_openStream_success(stream) {
+                       TestEngine.test("openStream()", isFilestream(stream));
+                       stream.write(test_content);
+                       stream.close();
+                       function on_readAsText_error(err) {
+                               TestEngine.test("readAsText() [" + err.name + "]", false);
+                               deleteFile(file, f);
+                       }
+                       function on_readAsText_success(str) {
+                               TestEngine.test("readAsText()", (str === test_content));
+                               deleteFile(file, f);
+                       }
+
+                       for (var i = 0; i < param.length; i++) {
+                               TestEngine.testPresetError(
+                                   "readAsText() [TYPE_MISMATCH_ERR]",
+                                   function() { f.readAsText(param[i], on_readAsText_error); },
+                                   TYPE_MISMATCH_ERR
+                         );
+                       }
+               }
+               function on_openStream_error(err) {
+                       TestEngine.test("openStream() [" + err.name + "]", false);
+                       deleteFile(file, f);
+               }
+               var cb = TestEngine.registerCallback("openStream", on_openStream_success, on_openStream_error);
+               f.openStream("w", cb.successCallback, cb.errorCallback, "UTF-8");
+       }
+       resolve_root(on_resolve_success, on_resolve_error);
+}
+
+
+function UTC_filesystem_file_readAsText_error_errorcb_invalid_param_N_002() {
+       var param = new Array(1, [], {}, "aa", true);
+
+       var test_content = "Ala ma kota";
+       function on_resolve_error(err) { TestEngine.test("resolve() [" + err.name + "]", false); }
+       function on_resolve_success(file) {
+               var f = file.createFile(getFileName());
+               TestEngine.test("createFile()", isFile(f));
+
+               function on_openStream_success(stream) {
+                       TestEngine.test("openStream()", isFilestream(stream));
+                       stream.write(test_content);
+                       stream.close();
+                       function on_readAsText_error(err) {
+                               TestEngine.test("readAsText() [" + err.name + "]", false);
+                               deleteFile(file, f);
+                       }
+                       function on_readAsText_success(str) {
+                               TestEngine.test("readAsText()", (str === test_content));
+                               deleteFile(file, f);
+                       }
+
+                       for (var i = 0; i < param.length; i++) {
+                               TestEngine.testPresetError(
+                                   "readAsText() [TYPE_MISMATCH_ERR]",
+                                   function() { f.readAsText(on_readAsText_success, param[i]); },
+                                   TYPE_MISMATCH_ERR
+                         );
+                       }
+               }
+               function on_openStream_error(err) {
+                       TestEngine.test("openStream() [" + err.name + "]", false);
+                       deleteFile(file, f);
+               }
+               var cb = TestEngine.registerCallback("openStream", on_openStream_success, on_openStream_error);
+               f.openStream("w", cb.successCallback, cb.errorCallback, "UTF-8");
+       }
+       resolve_root(on_resolve_success, on_resolve_error);
+}
+
+
+function UTC_filesystem_file_readAsText_error_encoding_invalid_param_N_003() {
+       var param = new Array(1, [], {}, true, function(){});
+
+       var test_content = "Ala ma kota";
+       function on_resolve_error(err) { TestEngine.test("resolve() [" + err.name + "]", false); }
+       function on_resolve_success(file) {
+               var f = file.createFile(getFileName());
+               TestEngine.test("createFile()", isFile(f));
+
+               function on_openStream_success(stream) {
+                       TestEngine.test("openStream()", isFilestream(stream));
+                       stream.write(test_content);
+                       stream.close();
+                       function on_readAsText_error(err) {
+                               TestEngine.test("readAsText() [" + err.name + "]", false);
+                               deleteFile(file, f);
+                       }
+                       function on_readAsText_success(str) {
+                               TestEngine.test("readAsText()", (str === test_content));
+                               deleteFile(file, f);
+                       }
+
+                       for (var i = 0; i < param.length; i++) {
+                               TestEngine.testPresetError(
+                                   "readAsText() [TYPE_MISMATCH_ERR]",
+                                   function() { f.readAsText(on_readAsText_success, on_readAsText_error, param[i]); },
+                                   TYPE_MISMATCH_ERR
+                         );
+                       }
+               }
+               function on_openStream_error(err) {
+                       TestEngine.test("openStream() [" + err.name + "]", false);
+                       deleteFile(file, f);
+               }
+               var cb = TestEngine.registerCallback("openStream", on_openStream_success, on_openStream_error);
+               f.openStream("w", cb.successCallback, cb.errorCallback, "UTF-8");
+       }
+       resolve_root(on_resolve_success, on_resolve_error);
+}
+
+function UTC_filesystem_file_copyTo_error_successcb_invalid_param_N_001() {
+       var param = new Array(1, [], {}, "aaa", true);
+
+       var g_file = null;
+       function on_resolve_error(err) { TestEngine.test("resolve() [" + err.name + "]", false); }
+       function on_resolve_success(file) {
+               g_file = file.createFile(getFileName());
+               TestEngine.test("createFile()", isFile(g_file));
+               function on_copyTo_error(err) {
+                       TestEngine.test("copyTo() [" + err.name + "]", false);
+                       deleteFile(file, g_file);
+               }
+               function on_copyTo_success(file2) {
+                       TestEngine.test("copyTo()", isFile(file2));
+                       deleteFile(file, file2);
+                       deleteFile(file, g_file);
+               }
+
+               for (var i = 0; i < param.length; i++) {
+                       TestEngine.testPresetError(
+                           "copyTo() [INVALID_VALUES_ERR]",
+                           function() {
+                               file.copyTo(g_file.fullPath, file.fullPath + "/" + getFileName(), true
+                                               , param[i], on_copyTo_error);
+                           },
+                           TYPE_MISMATCH_ERR
+                 );
+               }
+       }
+       resolve_root(on_resolve_success, on_resolve_error);
+}
+
+function UTC_filesystem_file_copyTo_error_errorcb_invalid_param_N_002() {
+       var param = new Array(1, [], {}, "aaa", true);
+
+       var g_file = null;
+       function on_resolve_error(err) { TestEngine.test("resolve() [" + err.name + "]", false); }
+       function on_resolve_success(file) {
+               g_file = file.createFile(getFileName());
+               TestEngine.test("createFile()", isFile(g_file));
+               function on_copyTo_error(err) {
+                       TestEngine.test("copyTo() [" + err.name + "]", false);
+                       deleteFile(file, g_file);
+               }
+               function on_copyTo_success(file2) {
+                       TestEngine.test("copyTo()", isFile(file2));
+                       deleteFile(file, file2);
+                       deleteFile(file, g_file);
+               }
+
+               for (var i = 0; i < param.length; i++) {
+                       TestEngine.testPresetError(
+                           "copyTo() [TYPE_MISMATCH_ERR]",
+                           function() {
+                               file.copyTo(g_file.fullPath, file.fullPath + "/" + getFileName(), true,
+                                               on_copyTo_success, param[i]);
+                           },
+                           TYPE_MISMATCH_ERR
+                 );
+               }
+       }
+       resolve_root(on_resolve_success, on_resolve_error);
+}
+
+function UTC_filesystem_file_copyTo_error_filepath_invalid_param_N_003() {
+       var param = new Array( 1, 0, null, undefined, {}, "aa");
+       function on_resolve_error(err) { TestEngine.test("resolve() [" + err.name + "]", false); }
+       function on_resolve_success(root) {
+               var dir = createDirForParent(root);
+               var file = createFileForParent(dir);
+               var i = 0;
+               function on_copyTo_error(err) {
+                       TestEngine.test("copyTo() [" + err.name + "]", err.name == NOT_FOUND_ERR);
+                       if (i == param.length - 1)
+                               deleteDirectory(root, dir);
+               }
+               function on_copyTo_success(copy) {
+                       TestEngine.test("copyTo()", false);
+                       TestEngine.test("copyTo()", isDir(copy));
+                       var child = copy.resolve(file.name);
+                       TestEngine.test("copyTo()", isFile(child));
+
+                       if (i == param.length - 1) {
+                               deleteDirectory(root, copy);
+                               deleteDirectory(root, dir);
+                       }
+               }
+               var cb = {};
+               for (i = 0; i < param.length; i++) {
+                       cb[i] = TestEngine.registerCallback("copyTo", on_copyTo_success, on_copyTo_error);
+                       root.copyTo(param[i], root.fullPath + "/" + getDirName(), true,
+                                       cb[i].successCallback, cb[i].errorCallback /*dir.fullPath,*/);
+               }
+       }
+       resolve_root(on_resolve_success, on_resolve_error);
+}
+
+
+/* * does not need tc*/
+function UTC_filesystem_file_copyTo_error_destination_invalid_param_N_004() {
+       TestEngine.test("doesn't need anymore", true);
+       return;
+       
+       var param = new Array( 1, 0, null, undefined, {}, "aa");
+       function on_resolve_error(err) { TestEngine.test("resolve() [" + err.name + "]", false); }
+       function on_resolve_success(root) {
+               var dir = createDirForParent(root);
+               var file = createFileForParent(dir);
+               var i = 0;
+               function on_copyTo_error(err) {
+                       TestEngine.test("copyTo() [" + err.name + "]", err.name == NOT_FOUND_ERR);
+                       if (i == param.length - 1)
+                               deleteDirectory(root, dir);
+               }
+               function on_copyTo_success(copy) {
+                       TestEngine.test("copyTo()", false);
+                       TestEngine.test("copyTo()", isDir(copy));
+                       var child = copy.resolve(file.name);
+                       TestEngine.test("copyTo()", isFile(child));
+
+                       if (i == param.length - 1) {
+                               deleteDirectory(root, copy);
+                               deleteDirectory(root, dir);
+                       }
+               }
+               var cb = {};
+               for (i = 0; i < param.length; i++) {
+                       cb[i] = TestEngine.registerCallback("copyTo", on_copyTo_success, on_copyTo_error);
+                       root.copyTo(dir.fullPath, param[i], true,
+                                       cb[i].successCallback, cb[i].errorCallback);
+               }
+       }
+       resolve_root(on_resolve_success, on_resolve_error);
+}
+
+function UTC_filesystem_file_moveTo_error_successcb_invalid_param_N_001() {
+       var param = new Array(1, [], {}, false, "aa");
+
+       var g_file = null;
+       function on_resolve_error(err) { TestEngine.test("resolve() [" + err.name + "]", false); }
+       function on_resolve_success(file) {
+               g_file = file.createFile(getFileName());
+               TestEngine.test("createFile()", isFile(g_file));
+               function on_moveTo_error(err) {
+                       TestEngine.test("moveTo() [" + err.name + "]", false);
+                       deleteFile(file, g_file);
+               }
+               function on_moveTo_success(file1) {
+                       TestEngine.test("moveTo()", true);
+                       deleteFile(file, file1);
+               }
+
+               for (var i = 0; i < param.length; i++) {
+                       TestEngine.testPresetError(
+                           "mopyTo() [TYPE_MISMATCH_ERR]",
+                           function() {
+                               file.moveTo(g_file.fullPath, file.fullPath + "/" + getFileName(), true,
+                                               param[i], on_moveTo_error);
+                           },
+                           TYPE_MISMATCH_ERR
+                 );
+               }
+       }
+       resolve_root(on_resolve_success, on_resolve_error);
+}
+
+function UTC_filesystem_file_moveTo_error_errorcb_invalid_param_N_002() {
+       var param = new Array(1, {}, [], false, "aa");
+
+       var g_file = null;
+       function on_resolve_error(err) { TestEngine.test("resolve() [" + err.name + "]", false); }
+       function on_resolve_success(file) {
+               g_file = file.createFile(getFileName());
+               TestEngine.test("createFile()", isFile(g_file));
+               function on_moveTo_error(err) {
+                       TestEngine.test("moveTo() [" + err.name + "]", false);
+                       deleteFile(file, g_file);
+               }
+               function on_moveTo_success(file1) {
+                       TestEngine.test("moveTo()", true);
+                       deleteFile(file, file1);
+               }
+
+               for (var i = 0; i < param.length; i++) {
+                       TestEngine.testPresetError(
+                           "mopyTo() [TYPE_MISMATCH_ERR]",
+                           function() {
+                               file.moveTo(g_file.fullPath, file.fullPath + "/" + getFileName(), true,
+                                               on_moveTo_success, param[i]);
+                           },
+                           TYPE_MISMATCH_ERR
+                 );
+               }
+       }
+       resolve_root(on_resolve_success, on_resolve_error);
+}
+
+function UTC_filesystem_file_moveTo_error_originfile_invalid_param_N_003() {
+       var param = new Array(1, 0,  {}, "aa");
+
+       function on_resolve_error(err) { TestEngine.test("resolve() [" + err.name + "]", false); }
+       function on_resolve_success(file) {
+               var i = 0;
+
+               function on_moveTo_error(err) {
+                       TestEngine.test("moveTo()", NOT_FOUND_ERR == err.name);
+               }
+               function on_moveTo_success(file1) {
+                       TestEngine.test("moveTo()", false);
+                       deleteFile(file, file1);
+               }
+               try {
+                       var cb = {};
+
+                       for (i = 0; i < param.length; i++) {
+                               try {
+                                       cb[i] = TestEngine.registerCallback("moveTo", on_moveTo_success, on_moveTo_error);
+                                       file.moveTo(param[i], file.fullPath + "/" + getFileName(), true,
+                                                       cb[i].successCallback, cb[i].errorCallback);
+                               }
+                               catch (e) {
+                                       TestEngine.test("exception " + e.message, false);
+                               }
+                       }
+
+               }
+               catch (exception) {
+                       TestEngine.test("exception " + exception.message, false);
+               }
+       }
+       resolve_root(on_resolve_success, on_resolve_error);
+}
+
+function UTC_filesystem_file_resolve_error_dir_invalid_param_N_001() {
+       var param = new Array(1, "aaa", {}, [], false);
+       function on_resolve_error(err) { TestEngine.test("resolve() [" + err.name + "]", false); }
+       function on_resolve_success(file) {
+               TestEngine.log("Calling createFile() with invalid characters in path. [NULL OBJECT]");
+
+               for (var i = 0; i < param.length; i++) {
+                       try {
+                               var fo = file.resolve(param[i]);
+                       } catch (e) {
+                               // TODO: handle exception
+                               TestEngine.test("coce << " + e.name, true);
+                       }
+               }
+       }
+       resolve_root(on_resolve_success, on_resolve_error);
+}
+
+function UTC_filesystem_file_deleteDirectory_error_successcb_invalid_param_N_001() {
+       var param = new Array(1, "aaa", {}, [], false);
+       function on_resolve_success(root) {
+               var dir = createDirForParent(root);
+
+               function on_deleteDirectory_error(err) {
+                       TestEngine.test("deleteDirectory()", false);
+                       deleteDirectory(root, dir);
+               }
+               function on_deleteDirectory_success() {
+                       TestEngine.test("deleteDirectory()", true);
+               }
+
+               for (var i = 0; i < param.length; i++) {
+                       TestEngine.testPresetError(
+                               "deleteDirecotry [TYPE_MISMATCH_ERR]",
+                               function() {
+                                       root.deleteDirectory( dir.fullPath, true, param[i], on_deleteDirectory_error);
+                               },
+                               TYPE_MISMATCH_ERR
+                       );
+               }
+       }
+       resolve_root_location(on_resolve_success);
+}
+
+
+function UTC_filesystem_file_deleteDirectory_error_errorcb_invalid_param_N_002() {
+       var param = new Array(1, "aaa", {}, [], false);
+       function on_resolve_success(root) {
+               var dir = createDirForParent(root);
+
+               function on_deleteDirectory_error(err) {
+                       TestEngine.test("deleteDirectory()", false);
+                       if (dir == length - 1)
+                               deleteDirectory(root, dir);
+               }
+               function on_deleteDirectory_success() {
+                       TestEngine.test("deleteDirectory()", true);
+               }
+
+               for (var i = 0; i < param.length; i++) {
+                       TestEngine.testPresetError(
+                               "deleteDirecotry [TYPE_MISMATCH_ERR]",
+                               function() {
+                                       root.deleteDirectory(dir.fullPath, true, on_deleteDirectory_success, param[i]);
+                               },
+                               TYPE_MISMATCH_ERR
+                       );
+               }
+       }
+       resolve_root_location(on_resolve_success);
+}
+
+function UTC_filesystem_file_deleteDirectory_error_dir_invalid_param_N_003() {
+       var param = new Array(null, undefined, 1, true, false, "aa");
+       function on_resolve_success(root) {
+               function on_deleteDirectory_success() {
+                               TestEngine.test("deleteDirectory()", false);
+               }
+               function on_deleteDirectory_error(err) {
+                               TestEngine.test("deleteDirectory()", NOT_FOUND_ERR == err.name);
+               }
+
+               var i = 0;
+
+               for (i = 0; i < param.length; i++) {
+                       root.deleteDirectory(param[i], true,on_deleteDirectory_success, on_deleteDirectory_error);
+               }
+       }
+
+       resolve_root_location(on_resolve_success);
+}
+
+function UTC_filesystem_file_deleteFile_error_successcb_invalid_param_N_001() {
+       var param = new Array(1, "aaa", {}, [], false);
+       function on_resolve_error(err) { TestEngine.test("resolve() [" + err.name + "]", false); }
+       function on_resolve_success(file) {
+               var dir = file.createDirectory(getDirName());
+               TestEngine.test("createDirectory()", isDir(dir));
+               function on_deleteFile_error(err) {
+                       deleteDirectory(file, dir);
+               }
+               function on_deleteFile_success() {
+                       TestEngine.test("deleteFile()", false);
+               }
+
+               for (var i = 0; i < param.length; i++) {
+                       TestEngine.testPresetError(
+                               "Call deleteFile() on a directory.",
+                               function(){
+                                       file.deleteFile(dir.fullPath, param[i], on_deleteFile_error);
+                               },
+                               TYPE_MISMATCH_ERR
+                       );
+               }
+               deleteDirectory(file, dir);
+       }
+       resolve_root(on_resolve_success, on_resolve_error);
+}
+
+
+function UTC_filesystem_file_deleteFile_error_errorcb_invalid_param_N_002() {
+       var param = new Array(1, "aaa", {}, [], false);
+       function on_resolve_error(err) { TestEngine.test("resolve() [" + err.name + "]", false); }
+       function on_resolve_success(file) {
+               var dir = file.createDirectory(getDirName());
+               TestEngine.test("createDirectory()", isDir(dir));
+               function on_deleteFile_error(err) {
+                       deleteDirectory(file, dir);
+               }
+               function on_deleteFile_success() {
+                       TestEngine.test("deleteFile()", false);
+               }
+
+               for (var i = 0; i < param.length; i++) {
+                       TestEngine.testPresetError(
+                               "Call deleteFile() on a directory.",
+                               function(){
+                                       file.deleteFile(dir.fullPath, on_deleteFile_success, param[i]);
+                               },
+                               TYPE_MISMATCH_ERR
+                       );
+               }
+               deleteDirectory(file, dir);
+       }
+       resolve_root(on_resolve_success, on_resolve_error);
+}
+
+function UTC_filesystem_file_deleteFile_error_dir_invalid_param_N_003() {
+       var param = new Array(1, null, undefined, "aaa", {}, false);
+       function on_resolve_error(err) { TestEngine.test("resolve() [" + err.name + "]", false); }
+       function on_resolve_success(file) {
+
+               
+               function on_deleteFile_error(err) {
+                       TestEngine.test("deleteFile()", NOT_FOUND_ERR == err.name);
+
+               }
+               function on_deleteFile_success() {
+                       TestEngine.test("deleteFile()", false);
+               }
+
+               var cb = {};
+               for (var i = 0; i < param.length; i++) {
+
+                               cb[i] = TestEngine.registerCallback("deleteFile", on_deleteFile_success,  on_deleteFile_error);
+                               file.deleteFile(param[i], cb[i].successCallback, cb[i].errorCallback);
+                       }
+               
+               }
+       resolve_root(on_resolve_success, on_resolve_error);
+}
+
+
+function UTC_filesystem_file_read_error_count_invalid_param_N_001() {
+       var test_string = "It's alive! Alive!";
+       function on_resolve_error(err) { TestEngine.test("resolve() [" + err.name + "]", false); }
+       function on_resolve_success(file) {
+               var f = file.createFile(getFileName());
+               TestEngine.test("createFile()", isFile(f));
+               function on_openStream_success(stream1) {
+                       TestEngine.test("openStream()", isFilestream(stream1));
+                       stream1.write(test_string, null);
+                       stream1.close(1);
+                       function on_openStream1_success(r_stream) {
+                               TestEngine.test("openStream()", isFilestream(r_stream));
+                               //var read_string = r_stream.read(test_string.length, null);
+                               var param = new Array(0, "aaa", null, undefined);
+
+                               for (var i = 0; i < param.length; i++) {
+                                       TestEngine.testPresetError(
+                                               "stream read.",
+                                               function(){
+                                                       r_stream.read(param[i]);
+                                               },
+                                               INVALID_VALUES_ERR
+                                       );
+                               }
+
+                               r_stream.close();
+                               //TestEngine.test("write()/read()", (read_string === test_string));
+                               deleteFile(file, f);
+                       }
+                       function on_openStream1_error(err) {
+                               TestEngine.test("openStream() [" + err.name + "]", false);
+                       }
+                       var cb = TestEngine.registerCallback("openStream", on_openStream1_success, on_openStream1_error);
+                       f.openStream("r", cb.successCallback, cb.errorCallback, "UTF-8");
+               }
+               function on_openStream_error(err) {
+                       TestEngine.test("openStream() [" + err.name + "]", false);
+               }
+               var cb = TestEngine.registerCallback("openStream", on_openStream_success, on_openStream_error);
+               f.openStream("w", cb.successCallback, cb.errorCallback, "UTF-8");
+       }
+       resolve_root(on_resolve_success, on_resolve_error);
+}
+
+
+function UTC_filesystem_file_readBytes_error_invalid_param_N_001() {
+       var test_string = "It's alive! Alive!";
+       function on_resolve_error(err) { TestEngine.test("resolve() [" + err.name + "]", false); }
+       function on_resolve_success(file) {
+               var f = file.createFile(getFileName());
+               TestEngine.test("createFile()", isFile(f));
+               function on_openStream_success(stream1) {
+                       TestEngine.test("openStream()", isFilestream(stream1));
+                       stream1.write(test_string, null);
+                       stream1.close(1);
+                       function on_openStream1_success(r_stream) {
+                               TestEngine.test("openStream()", isFilestream(r_stream));
+                               //var read_string = r_stream.read(test_string.length, null);
+                               var param = new Array(0, "aaa", null, undefined);
+
+                               for (var i = 0; i < param.length; i++) {
+                                       TestEngine.testPresetError(
+                                               "stream readBytes.",
+                                               function(){
+                                                       r_stream.readBytes(param[i]);
+                                               },
+                                               INVALID_VALUES_ERR
+                                       );
+                               }
+
+                               r_stream.close();
+                               //TestEngine.test("write()/read()", (read_string === test_string));
+                               deleteFile(file, f);
+                       }
+                       function on_openStream1_error(err) {
+                               TestEngine.test("openStream() [" + err.name + "]", false);
+                       }
+                       var cb = TestEngine.registerCallback("openStream", on_openStream1_success, on_openStream1_error);
+                       f.openStream("r", cb.successCallback, cb.errorCallback, "UTF-8");
+               }
+               function on_openStream_error(err) {
+                       TestEngine.test("openStream() [" + err.name + "]", false);
+               }
+               var cb = TestEngine.registerCallback("openStream", on_openStream_success, on_openStream_error);
+               f.openStream("w", cb.successCallback, cb.errorCallback, "UTF-8");
+       }
+       resolve_root(on_resolve_success, on_resolve_error);
+}
+
+
+function UTC_filesystem_file_writeBytes_error_octect_invalid_param_N_001() {
+       var test_string = "It's alive! Alive!";
+       function on_resolve_error(err) { TestEngine.test("resolve() [" + err.name + "]", false); }
+       function on_resolve_success(file) {
+               var f = file.createFile(getFileName());
+               TestEngine.test("createFile()", isFile(f));
+               function on_openStream_success(stream1) {
+                       TestEngine.test("openStream()", isFilestream(stream1));
+
+                       var param = new Array(-1, null, undefined);
+
+                       for (var i = 0; i < param.length; i++) {
+                               TestEngine.testPresetError(
+                                       "stream writeBytes.",
+                                       function(){
+                                               stream1.writeBytes(param[i], null);
+                                       },
+                                       TYPE_MISMATCH_ERR
+                               );
+                       }
+
+                       stream1.close(1);
+                       deleteFile(file, f);
+               }
+               function on_openStream_error(err) {
+                       TestEngine.test("openStream() [" + err.name + "]", false);
+               }
+               var cb = TestEngine.registerCallback("openStream", on_openStream_success, on_openStream_error);
+               f.openStream("w", cb.successCallback, cb.errorCallback, "UTF-8");
+       }
+       resolve_root(on_resolve_success, on_resolve_error);
+}
+
+function UTC_filesystem_remove_listener_invalid_param_N_001() {
+       var invalid_type_params = new Array(09090909090909, null, undefined, "aaa", {}, [], false);
+
+       for(var i=0; i<invalid_type_params.length; i++){
+               TestEngine.testPresetError("UTC_filesystem_remove_listener_invalid_par" + ":" + invalid_type_params[i] ,
+                       function() {
+                               tizen.filesystem.removeStorageStateChangeListener(invalid_type_params[i]);
+                       },
+                       NOT_FOUND_ERR
+               );
+       }//for
+
+}
+
+function UTC_filesystem_resolve_location_P_001(){
+       function on_resolve_error(err) {
+               TestEngine.test("on_resolve_error() [" + err.name + "]", false);
+       }
+       function on_resolve_success(file) {
+               TestEngine.test("on_resolve_success()", isFileObject(file));
+       }
+
+       var validResolveLocation = [TEST_ROOT_LOCATION];
+       
+       for ( var i = 0; i < validResolveLocation.length; i++) {
+               var cb = TestEngine.registerCallback("resolve", on_resolve_success, on_resolve_error);
+               tizen.filesystem.resolve(validResolveLocation[i], cb.successCallback, cb.errorCallback);
+       }
+}
+
+function UTC_filesystem_resolve_mode_P_002(){
+       function on_resolve_error(err) {
+               TestEngine.test("on_resolve_error() [" + err.name + "]", false);
+       }
+       function on_resolve_success(file) {
+               TestEngine.test("on_resolve_success()", isFileObject(file));
+       }
+
+       var validResolveMode = ["r", "rw", "w", "a"];
+       
+       for ( var i = 0; i < validResolveMode.length; i++) {
+               var cb = TestEngine.registerCallback("resolve", on_resolve_success, on_resolve_error);
+               tizen.filesystem.resolve(TEST_ROOT_LOCATION, cb.successCallback, cb.errorCallback, validResolveMode[i]);
+       }
+}
+
+var validInput = ["images", "videos", "music"];
+
+function UTC_filesystem_getstorage_label_P_001(){
+       var testName = "test_filesystem_getstorage_label_P_003";
+       
+       function getStorageSuccess(storage) {
+               TestEngine.assertEqual(testName + " check type", "INTERNAL", storage.type);
+       }
+       
+       function getStorageError(e){
+               TestEngine.test(testName + " unexpected getStorageError() <<< ", false);
+       }
+       
+       for(var i=0; i<validInput.length; i++){
+               var cb = TestEngine.registerCallback("openStream", 
+                               getStorageSuccess, getStorageError);
+               tizen.filesystem.getStorage(validInput[i], cb.successCallback,cb.errorCallback);
+       }
+}
+
+function UTC_filesystem_iststorage_P_001(){
+       var testName = "test_filesystem_liststorage_P_004";
+       
+       function listStorageSuccess(storages) {
+               TestEngine.test("listStorageSuccess check storages", storages.length>0);
+       }
+       
+       function listStorageError(e){
+               TestEngine.test(testName + " unexpected listStorages() <<< ", false);
+       }
+       
+       for(var i=0; i<validInput.length; i++){
+               var cb = TestEngine.registerCallback("openStream", listStorageSuccess, listStorageError);
+               tizen.filesystem.listStorages(cb.successCallback,cb.errorCallback);
+       }
+}
+
+function test_addstoragestaechangelistener_P_005(){
+       
+       tizen.filesystem.addStorageStateChangeListener(function(storage){});
+       
+       TestEngine.test("pass addStorageStateChangeListener", true);
+}
+
+function UTC_filesystem_removestoragestaechangelistener_P_001(){
+       
+       var watchId = tizen.filesystem.addStorageStateChangeListener(function(storage){});
+       tizen.filesystem.removeStorageStateChangeListener(watchId);
+       
+       TestEngine.test("pass removeStorageStateChangeListener", true);
+}
+
+function UTC_filesystem_listfiles_P_001(){
+       var testName = "[test_listfiles]";
+       
+       function listFilesOnsuccess(files){
+               TestEngine.assertEqual(testName + " files.length", 1, files.length);
+               for(var i=0; i<files.length; i++){
+                       TestEngine.log("files.name:" + files[i].name);
+               }
+       }
+       
+       function listFilesOnerror(){
+               TestEngine.test(testName + " unexpected listFilesOnerror", false);
+       }
+
+               var cb = TestEngine.registerCallback("resolve", 
+                       function(dir) {
+                               var listFilesCB = TestEngine.registerCallback("listFiles", listFilesOnsuccess, listFilesOnerror);
+                               dir.listFiles(listFilesCB.successCallback, listFilesCB.errorCallback, {name:"image1.jpg"});
+                       }, function(e) {
+                               TestEngine.test("unexpected resolve onerror() <<< ", false);
+                       }
+               );
+       
+        tizen.filesystem.resolve("images", cb.successCallback,cb.errorCallback, "r");          //resolve
+}
+
+function UTC_filesystem_file_to_uri_P_001() {
+  function on_resolve_error(err) { TestEngine.test("resolve() [" + err.name + "]", false); }
+  function on_resolve_success(file) {
+    var f = file.createFile(getFileName());
+    TestEngine.test("createFile()", isFile(f));
+    var uri = f.toURI(1);
+    TestEngine.test("Call toUri() returns non empty string", isString(uri) && uri.length > 0);
+    TestEngine.log("created uri: " + uri);
+    deleteFile(file, f);
+  }
+  resolve_root(on_resolve_success, on_resolve_error);
+}
+
+function UTC_filesystem_file_listFiles_P_001() {
+       var param = new Array(null);
+       function on_resolve_error(err) { TestEngine.test("resolve() [" + err.name + "]", false); }
+       function on_resolve_success(file) {
+               TestEngine.test("resolve()", isFileObject(file));
+               function on_listFiles_error(err) {
+                       TestEngine.test("listFiles() [" + err.name + "]", false);
+               }
+               function on_listFiles_success(files) {
+                       TestEngine.test("listFiles()", isArray(files));
+               }
+               var cb = {};
+               for (var i = 0; i < param.length; i++) {
+                       cb[i] = TestEngine.registerCallback("listFiles", on_listFiles_success, on_listFiles_error);
+                       file.listFiles(cb[i].successCallback, param[i], param[i], null);
+               }
+       }
+       resolve_root(on_resolve_success, on_resolve_error);
+}
+
+function UTC_filesystem_file_listFiles_P_002() {
+       var param = new Array(1, null, undefined);
+       function on_resolve_error(err) { TestEngine.test("resolve() [" + err.name + "]", false); }
+       function on_resolve_success(file) {
+               TestEngine.test("resolve()", isFileObject(file));
+               function on_listFiles_error(err) {
+                       TestEngine.test("listFiles() [" + err.name + "]", false);
+               }
+               function on_listFiles_success(files) {
+                       TestEngine.test("listFiles()", isArray(files));
+               }
+
+               var cb = {};
+               for (var i = 0; i < param.length; i++) {
+                       cb[i] = TestEngine.registerCallback("listFiles", on_listFiles_success, on_listFiles_error);
+                       file.listFiles(cb[i].successCallback);
+               }
+       }
+       resolve_root(on_resolve_success, on_resolve_error);
+}
+
+
+function UTC_filesystem_file_openStream_P_001() {
+       var param = new Array(null, undefined);
+       
+       function on_resolve_error(err) { TestEngine.test("resolve() [" + err.name + "]", false); }
+       function on_resolve_success(file) {
+               var file2 = file.createFile(getFileName());
+               
+               function on_openStream_success(stream) {
+                       TestEngine.test("openStream()", isFilestream(stream));
+                       stream.close();
+                       deleteFile(file, file2);
+               }
+       
+               function on_openStream_error(err) {
+                       TestEngine.test("openStream() [" + err.name + "]", false);
+               }
+               
+               var cb = TestEngine.registerCallback("openStream", on_openStream_success, on_openStream_error);
+               var stream = file2.openStream("rw", cb.successCallback, cb.errorCallback);
+
+       }
+       resolve_root(on_resolve_success, on_resolve_error);
+}
+
+function UTC_filesystem_file_openStream_P_002() {
+       var param = new Array(null, undefined);
+       
+       function on_resolve_error(err) { TestEngine.test("resolve() [" + err.name + "]", false); }
+       function on_resolve_success(file) {
+               var file2 = file.createFile(getFileName());
+               var cb = {};
+               var stream = {};
+               var i = 0;
+               
+               function on_openStream_success(stream) {
+                       TestEngine.test("openStream()", isFilestream(stream));
+                       stream.close();
+                       if (i == param.length - 1) {
+                               deleteFile(file, file2);
+                       }
+               }
+       
+               function on_openStream_error(err) {
+                       TestEngine.test("openStream() [" + err.name + "]", false);
+               }
+       
+               for (i = 0; i < param.length; i++) {
+                       cb[i] = TestEngine.registerCallback("openStream", on_openStream_success, on_openStream_error);
+                       stream[i] = file2.openStream("rw", cb[i].successCallback, cb[i].errorCallback, param[i], null);
+               }
+       }
+       resolve_root(on_resolve_success, on_resolve_error);
+}
+
+function UTC_filesystem_file_readAsText_P_001() {
+       var test_content = "Ala ma kota";
+       function on_resolve_error(err) { TestEngine.test("resolve() [" + err.name + "]", false); }
+       function on_resolve_success(file) {
+               var f = file.createFile(getFileName());
+               TestEngine.test("createFile()", isFile(f));
+               
+               function on_openStream_success(stream) {
+                       TestEngine.test("openStream()", isFilestream(stream));
+                       stream.write(test_content);
+                       stream.close();
+                       function on_readAsText_error(err) {
+                               TestEngine.test("readAsText() [" + err.name + "]", false);
+                               deleteFile(file, f);
+                       }
+                       function on_readAsText_success(str) {
+                               TestEngine.test("readAsText()", (str === test_content));
+                               deleteFile(file, f);
+                       }
+                       
+                       var cb = TestEngine.registerCallback("readAsText", on_readAsText_success, on_readAsText_error);
+                       f.readAsText(cb.successCallback);
+               }
+               function on_openStream_error(err) {
+                       TestEngine.test("openStream() [" + err.name + "]", false);
+                       deleteFile(file, f);
+               }
+               var cb = TestEngine.registerCallback("openStream", on_openStream_success, on_openStream_error);
+               f.openStream("w", cb.successCallback, cb.errorCallback, "UTF-8");
+       }
+       resolve_root(on_resolve_success, on_resolve_error);
+}
+
+function UTC_filesystem_file_readAsText_P_002() {
+       var param = new Array(null, undefined);
+       
+       var test_content = "Ala ma kota";
+       function on_resolve_error(err) { TestEngine.test("resolve() [" + err.name + "]", false); }
+       function on_resolve_success(file) {
+               var f = file.createFile(getFileName());
+               TestEngine.test("createFile()", isFile(f));
+               
+               function on_openStream_success(stream) {
+                       TestEngine.test("openStream()", isFilestream(stream));
+                       stream.write(test_content);
+                       stream.close();
+                       var counter = 0;
+                       function on_readAsText_error(err) {
+                               TestEngine.test("readAsText() [" + err.name + "]", false);
+                               if (++counter == param.length) {
+                                       deleteFile(file, f);
+                               }
+                       }
+                       function on_readAsText_success(str) {
+                               TestEngine.test("readAsText()", (str === test_content));
+                               if (++counter == param.length) {
+                                       deleteFile(file, f);
+                               }
+                       }
+                       
+                       var cb = {};
+                       for (var i = 0; i < param.length; i++) {
+                               cb[i] = TestEngine.registerCallback("readAsText", on_readAsText_success, on_readAsText_error);
+                               f.readAsText(cb[i].successCallback, cb[i].errorCallback, param[i], null);
+                       }
+               }
+               function on_openStream_error(err) {
+                       TestEngine.test("openStream() [" + err.name + "]", false);
+                       deleteFile(file, f);
+               }
+               var cb = TestEngine.registerCallback("openStream", on_openStream_success, on_openStream_error);
+               f.openStream("w", cb.successCallback, cb.errorCallback, "UTF-8");
+       }
+       resolve_root(on_resolve_success, on_resolve_error);
+}
+
+function UTC_filesystem_file_copyTo_P_001() {
+       var g_file = null;
+       function on_resolve_error(err) { TestEngine.test("resolve() [" + err.name + "]", false); }
+       function on_resolve_success(file) {
+               g_file = file.createFile(getFileName());
+               TestEngine.test("createFile()", isFile(g_file));
+               function on_copyTo_error(err) {
+                       TestEngine.test("copyTo() [" + err.name + "]", false);
+                       deleteFile(file, g_file);
+               }
+               function on_copyTo_success(file2) {
+                       TestEngine.test("copyTo()", isFile(file2));
+                       deleteFile(file, file2);
+                       deleteFile(file, g_file);
+               }
+               
+               try {
+                       file.copyTo(g_file.fullPath, file.fullPath + "/" + getFileName(), false, null, null, null);
+                       TestEngine.test("copy to, no exception", true);
+               }
+               catch (exception) {
+                       TestEngine.test("exception is occured", false);
+               }
+       }
+       resolve_root(on_resolve_success, on_resolve_error);
+}
+
+function UTC_filesystem_file_copyTo_P_003() {
+       var param = new Array(1, 0, null, undefined,  "aa", function(){}, [], {});
+       function on_resolve_success(root) {
+               var dir = createDirForParent(root);
+               var file = createFileForParent(dir);
+               var i = 0;
+               var counter = 0;
+               function on_copyTo_error(err) {
+                       TestEngine.test("copyTo() [" + err.name + "]", false);
+                       if (++counter == param.length) {
+                               deleteDirectory(root, dir);
+                       }
+               }
+               function on_copyTo_success(copy) {
+                       TestEngine.test("copyTo()", true);
+                       if (++counter == param.length) {
+                               deleteDirectory(root, dir);
+                       }
+               }
+               
+               for (i = 0; i < param.length; i++) {
+                       try {
+                               root.copyTo(file.fullPath, dir.fullPath + "/" + getFileName(), param[i], on_copyTo_success, on_copyTo_error);
+                               TestEngine.test("ok, no exception", true);
+                       }
+                       catch (exception) {
+                               TestEngine.test("exception", false);
+                       }
+               }
+       }
+       resolve_root_location(on_resolve_success);
+}
+
+function UTC_filesystem_file_moveTo_P_001() {
+       var g_file = null;
+       function on_resolve_error(err) { TestEngine.test("resolve() [" + err.name + "]", false); }
+       function on_resolve_success(file) {
+               g_file = file.createFile(getFileName());
+               TestEngine.test("createFile()", isFile(g_file));
+               function on_moveTo_error(err) {
+                       TestEngine.test("moveTo() [" + err.name + "]", false);
+                       deleteFile(file, g_file);
+               }
+               function on_moveTo_success(file1) {
+                       TestEngine.test("moveTo()", true);
+                       deleteFile(file, file1);
+               }
+               
+               try {
+                       file.moveTo(g_file.fullPath, file.fullPath + "/" + getFileName(), true, null, null, null);
+                       TestEngine.test("ok, no exception", true);
+               }
+               catch (exception) {
+                       TestEngine.test("exception", false);
+               }
+       }
+       resolve_root(on_resolve_success, on_resolve_error);
+}
+
+
+function UTC_filesystem_file_moveTo_P_003() {
+       var param = new Array([], 1, 0, null, undefined, {}, "aa");
+       
+       function on_resolve_error(err) { TestEngine.test("resolve() [" + err.name + "]", false); }
+       function on_resolve_success(root) {
+               var dir = createDirForParent(root);
+               var i = 0;
+               var counter = 0;
+               function on_moveTo_error(err) {
+                       TestEngine.test("moveTo() [" + err.name + "]", false);
+                       if (++counter == param.length) {
+                               deleteDirectory(root, dir);
+                       }
+               }
+               function on_moveTo_success() {
+                       TestEngine.test("moveTo()", true);
+                       if (++counter == param.length) {
+                               deleteDirectory(root, dir);
+                       }
+               }
+               
+               try {
+                       var cb = {};
+                       
+                       for (i = 0; i < param.length; i++) {
+                               var createdFile = dir.createFile(getFileName());
+                               TestEngine.test("createFile()", isFile(createdFile));
+                               try {
+                                       dir.moveTo(createdFile.fullPath, dir.fullPath + "/" + getFileName(), param[i], on_moveTo_success, on_moveTo_error);
+                                       TestEngine.test("no exception", true);
+                               }
+                               catch (e) {
+                                       TestEngine.test("exception " + exception.message, false);
+                               }
+                       }
+                       
+               }
+               catch (exception) {
+                       TestEngine.test("exception " + exception.message, false);
+               }
+       }
+       resolve_root(on_resolve_success, on_resolve_error);
+}
+
+function UTC_filesystem_file_createFile_P_001() {
+       function on_resolve_error(err) { TestEngine.test("resolve() [" + err.name + "]", false); }
+       function on_resolve_success(file) {
+               var file1 = file.createFile(getFileName(), null);
+               TestEngine.test("createFile()", isFile(file1));
+               deleteFile(file, file1);
+       }
+       resolve_root(on_resolve_success, on_resolve_error);
+}
+
+function UTC_filesystem_file_createDirectory_P_001() {
+       function on_resolve_error(err) { TestEngine.test("resolve() [" + err.name + "]", false); }
+       function on_resolve_success(file) {
+               var dir = file.createDirectory(getDirName(), null);
+               TestEngine.test("createDirectory()", isDir(dir));
+               deleteDirectory(file, dir);
+       }
+       resolve_root(on_resolve_success, on_resolve_error);
+}
+
+function UTC_filesystem_file_resolve_P_001() {
+       function on_resolve_error(err) { TestEngine.test("resolve() [" + err.name + "]", false); }
+       function on_resolve_success(file) {
+               var file1 = file.createFile(getFileName(), null);
+               TestEngine.test("createFile()", isFile(file1));
+               var file2 = file.resolve(file1.name, null);
+               TestEngine.test("resolve()", isFile(file2));
+               deleteFile(file, file1);
+       }
+       resolve_root(on_resolve_success, on_resolve_error);
+}
+
+function UTC_filesystem_file_deleteDirectory_P_001() {
+       function on_resolve_success(root) {
+               var dir = createDirForParent(root);
+               function on_deleteDirectory_success() {
+                       TestEngine.test("deleteDirectory()", true);
+               }
+
+               try {
+                       root.deleteDirectory( dir.fullPath, true, null, null);
+                       TestEngine.test("no exception", true);
+               }
+               catch (e){
+                       TestEngine.test("exception", false);
+               }
+       }
+       resolve_root_location(on_resolve_success);
+}
+
+function UTC_filesystem_file_deleteFile_P_001() {
+       function on_resolve_error(err) { TestEngine.test("resolve() [" + err.name + "]", false); }
+       function on_resolve_success(file) {
+               var f = file.createFile(getFileName());
+               TestEngine.test("createFile()", isFile(f));
+
+               function on_error(err) {
+                         TestEngine.test("deleteFile() [" + err.name + "]", false);
+               }
+               function on_success() {
+                       TestEngine.test("deleteFile()", true);
+               }
+
+               try {
+                       file.deleteFile(f.fullPath, null, null, null);
+                       TestEngine.test("no exception", true);
+               }
+               catch (ex) {
+                       TestEngine.test("exception", false);
+               }
+       }
+       resolve_root(on_resolve_success, on_resolve_error);
+}
+
+
+function UTC_filesystem_file_deleteDirectory_P_002() {
+       var param = new Array(1, null, undefined, true, false, "aa");
+       function on_resolve_success(root) {
+               function on_deleteDirectory_success() {
+                       TestEngine.test("deleteDirectory()", true);
+               }
+               function on_deleteDirectory_error() {
+                       TestEngine.test("deleteDirectory()", false);
+               }
+               
+               var dir = {};
+               var i = 0;
+               var cb = {};
+       
+       
+               for (i = 0; i < param.length; i++) {
+               dir[i] = root.createDirectory(param[i]);
+               cb[i] = TestEngine.registerCallback("deleteDirectory", on_deleteDirectory_success, on_deleteDirectory_error);           
+
+               try {
+                       root.deleteDirectory(dir[i].fullPath, true, cb[i].successCallback, cb[i].errorCallback);
+               }
+               catch (e){
+                       TestEngine.test("exception", false);
+               }
+               }
+       }
+       resolve_root_location(on_resolve_success);
+}
+
+function UTC_filesystem_file_deleteFile_P_002() {
+       var param = new Array(1, null, undefined, true, false, "aa");
+       function on_resolve_error(err) { TestEngine.test("resolve() [" + err.name + "]", false); }
+       function on_resolve_success(file) {
+               var i = 0;
+               var cb = {};
+
+               function on_error(err) {
+                         TestEngine.test("deleteFile() [" + err.name + "]", false);
+               }
+               function on_success() {
+                       TestEngine.test("deleteFile()", true);
+               }
+
+               for (i = 0; i < param.length; i++) {
+                       try {
+                               var f = file.createFile(param[i]);
+                               TestEngine.test("createFile()", isFile(f));
+                               cb[i] = TestEngine.registerCallback("deleteDirectory", on_success, on_error);
+                               file.deleteFile(f.fullPath, cb[i].successCallback, cb[i].errorCallback, null);
+                       }
+                       catch (ex) {
+                               TestEngine.test("exception", false);
+                       }
+               }
+       }
+       resolve_root(on_resolve_success, on_resolve_error);
+}
+
+
+function UTC_filesystem_file_write_read_close_P_001() {
+       var test_string = "It's alive! Alive!";
+       function on_resolve_error(err) { TestEngine.test("resolve() [" + err.name + "]", false); }
+       function on_resolve_success(file) {
+               var f = file.createFile(getFileName());
+               TestEngine.test("createFile()", isFile(f));
+               function on_openStream_success(stream1) {
+                       TestEngine.test("openStream()", isFilestream(stream1));
+                       stream1.write(test_string, null);
+                       stream1.close(1);
+                       function on_openStream1_success(r_stream) {
+                               TestEngine.test("openStream()", isFilestream(r_stream));
+                               var read_string = r_stream.read(test_string.length, null);
+                               r_stream.close();
+                               TestEngine.test("write()/read()", (read_string === test_string));
+                               deleteFile(file, f);
+                       }
+                       function on_openStream1_error(err) {
+                               TestEngine.test("openStream() [" + err.name + "]", false);
+                       }
+                       var cb = TestEngine.registerCallback("openStream", on_openStream1_success, on_openStream1_error);
+                       f.openStream("r", cb.successCallback, cb.errorCallback, "UTF-8");
+               }
+               function on_openStream_error(err) {
+                       TestEngine.test("openStream() [" + err.name + "]", false);
+               }
+               var cb = TestEngine.registerCallback("openStream", on_openStream_success, on_openStream_error);
+               f.openStream("w", cb.successCallback, cb.errorCallback, "UTF-8");
+       }
+       resolve_root(on_resolve_success, on_resolve_error);
+}
+
+
+function UTC_filesystem_file_write_readBytes_P_001() {
+       var test_string = new Array(1,2,3,4,5,6,7);
+       function on_resolve_error(err) { TestEngine.test("resolve() [" + err.name + "]", false); }
+       function on_resolve_success(file) {
+               var f = file.createFile(getFileName());
+               TestEngine.test("createFile()", isFile(f));
+               function on_openStream_success(stream1) {
+                       TestEngine.test("openStream()", isFilestream(stream1));
+                       
+                       stream1.writeBytes(test_string, null);
+                       stream1.close(1);
+                       function on_openStream1_success(r_stream) {
+                               TestEngine.test("openStream()", isFilestream(r_stream));
+                               var read_string = r_stream.readBytes(test_string.length, null);
+                               r_stream.close();
+                               TestEngine.test("readBytes", isArray(read_string));
+                               //TestEngine.test("write()/read()", (read_string === test_string));
+                               deleteFile(file, f);
+                       }
+                       function on_openStream1_error(err) {
+                               TestEngine.test("openStream() [" + err.name + "]", false);
+                       }
+                       var cb = TestEngine.registerCallback("openStream", on_openStream1_success, on_openStream1_error);
+                       f.openStream("r", cb.successCallback, cb.errorCallback, "UTF-8");
+               }
+               function on_openStream_error(err) {
+                       TestEngine.test("openStream() [" + err.name + "]", false);
+               }
+               var cb = TestEngine.registerCallback("openStream", on_openStream_success, on_openStream_error);
+               f.openStream("w", cb.successCallback, cb.errorCallback, "UTF-8");
+       }
+       resolve_root(on_resolve_success, on_resolve_error);
+}
+
+function UTC_filesystem_file_write_readBase64_P_001() {
+               // TIZEN-FILESYSTEM-060: Call write()/readBase64() on a stream.
+       var test_base64 = 'dGVzdA==';
+       var test_string = 'test';
+       function on_resolve_error(err) { TestEngine.test("resolve() [" + err.name + "]", false); }
+       function on_resolve_success(file) {
+               var f = file.createFile(getFileName());
+               TestEngine.test("createFile()", isFile(f));
+               function on_openStream_success(stream) {
+                       TestEngine.test("openStream()", isFilestream(stream));
+                       stream.writeBase64(test_base64, null);
+                       stream.close();
+                       function on_openStream1_success(stream1) {
+                               TestEngine.test("openStream()", isFilestream(stream1));
+                               var read_base64 = stream1.readBase64(100, null);
+                               stream1.close();
+                               TestEngine.test("readBase64()", isString(read_base64));
+                               deleteFile(file, f);
+                       }
+                       function on_openStream1_error(err) {
+                               TestEngine.test("openStream() [" + err.name + "]", false);
+                               deleteFile(file, f);
+                       }
+                       var cb = TestEngine.registerCallback("openStream", on_openStream1_success, on_openStream1_error);
+                       f.openStream("r", cb.successCallback, cb.errorCallback, "UTF-8");
+               }
+               function on_openStream_error(err) {
+                               TestEngine.test("openStream() [" + err.name + "]", false);
+                               deleteFile(file, f);
+               }
+               var cb = TestEngine.registerCallback("openStream", on_openStream_success, on_openStream_error);
+               f.openStream("w", cb.successCallback, cb.errorCallback, "UTF-8");
+       }
+       resolve_root(on_resolve_success, on_resolve_error);
+}
+
+// unit tc addition for smack, filesystem.read
+// using downloads/aaaa.txt
+function UTC_filesystem_file_to_uri_smack_P_001() {
+       function on_resolve_error(err) { TestEngine.test("resolve() [" + err.name + "]", false); }
+       function on_resolve_success(file) {
+               var f = file.resolve("aaaa.txt");
+               var uri = f.toURI();
+               TestEngine.test("to_uri", isString(uri));
+       }
+       resolve_root(on_resolve_success, on_resolve_error);
+}
+
+function UTC_filesystem_file_openStream_read_close_smack_P_001() {
+       function on_resolve_error(err) { TestEngine.test("resolve() [" + err.name + "]", false); }
+       function on_resolve_success(file) {
+               var f = file.resolve("aaaa.txt");
+               function on_openStream_success(stream) {
+                       var read_string = stream.read(100, null);
+                       stream.close();
+                       TestEngine.test("read()", isString(read_string));
+               }
+
+               function on_openStream_error(err) {
+                               TestEngine.test("openStream() [" + err.name + "]", false);
+               }
+               var cb = TestEngine.registerCallback("openStream", on_openStream_success, on_openStream_error);
+               f.openStream("r", cb.successCallback, cb.errorCallback, "UTF-8");
+       }
+       resolve_root(on_resolve_success, on_resolve_error);
+}
+
+function UTC_filesystem_file_openStream_readbytes_close_smack_P_001() {
+       function on_resolve_error(err) { TestEngine.test("resolve() [" + err.name + "]", false); }
+       function on_resolve_success(file) {
+               var f = file.resolve("aaaa.txt");
+               function on_openStream_success(stream) {
+                       var read_bytes = stream.readBytes(100, null);
+                       stream.close();
+                       TestEngine.test("readbytes()", isArray(read_bytes));
+               }
+
+               function on_openStream_error(err) {
+                               TestEngine.test("openStream() [" + err.name + "]", false);
+               }
+               var cb = TestEngine.registerCallback("openStream", on_openStream_success, on_openStream_error);
+               f.openStream("r", cb.successCallback, cb.errorCallback, "UTF-8");
+       }
+       resolve_root(on_resolve_success, on_resolve_error);
+}
+
+function UTC_filesystem_file_openStream_readbase64_close_smack_P_001() {
+       function on_resolve_error(err) { TestEngine.test("resolve() [" + err.name + "]", false); }
+       function on_resolve_success(file) {
+               var f = file.resolve("aaaa.txt");
+               function on_openStream_success(stream) {
+                       var read_base64 = stream.readBase64(100, null);
+                       stream.close();
+                       TestEngine.test("readBase64()", isString(read_base64));
+               }
+
+               function on_openStream_error(err) {
+                               TestEngine.test("openStream() [" + err.name + "]", false);
+               }
+               var cb = TestEngine.registerCallback("openStream", on_openStream_success, on_openStream_error);
+               f.openStream("r", cb.successCallback, cb.errorCallback, "UTF-8");
+       }
+       resolve_root(on_resolve_success, on_resolve_error);
+}
+
+function UTC_filesystem_file_readAsText_smack_P_001() {
+       function on_resolve_error(err) { TestEngine.test("resolve() [" + err.name + "]", false); }
+       function on_resolve_success(file) {
+               var f = file.resolve("aaaa.txt");
+               function on_readastext_success(contents) {
+                       console.log(contents);
+                       TestEngine.test("readAsText()", isString(contents));
+               }
+
+               function on_readastext_error(err) {
+                               TestEngine.test("readAsText() [" + err.name + "]", false);
+               }
+               var cb = TestEngine.registerCallback("readAsText", on_readastext_success, on_readastext_error);
+               f.readAsText(cb.successCallback, cb.errorCallback, "UTF-8");
+       }
+       resolve_root(on_resolve_success, on_resolve_error);     
+}
+
+
+function UTC_filesystem_change_test_root_location() {
+       // dcm-992 issue
+       TEST_ROOT_LOCATION = "file:///home/owner/share/Documents";
+       TestEngine.test("ok location change", true);
+}
+function UTC_filesystem_shift_jis() {
+       var test_string = "It's alive! Alive!";
+
+       function on_resolve_error(err) { TestEngine.test("resolve() [" + err.name + "]", false); }
+       function on_resolve_success(file) {
+               var f = file.createFile(getFileName());
+               TestEngine.test("createFile()", isFile(f));
+               function on_openStream_success(stream1) {
+                       TestEngine.test("openStream()", isFilestream(stream1));
+                       stream1.write(test_string, null);
+                       stream1.close(1);
+                       function on_openStream1_success(r_stream) {
+                               TestEngine.test("openStream()", isFilestream(r_stream));
+                               var read_string = r_stream.read(test_string.length, null);
+                               r_stream.close();
+                               TestEngine.test("write()/read()", (read_string === test_string));
+                               deleteFile(file, f);
+                       }
+                       function on_openStream1_error(err) {
+                               TestEngine.test("openStream() [" + err.name + "]", false);
+                       }
+                       var cb = TestEngine.registerCallback("openStream", on_openStream1_success, on_openStream1_error);
+                       f.openStream("r", cb.successCallback, cb.errorCallback, "SJIS");
+               }
+               function on_openStream_error(err) {
+                       TestEngine.test("openStream() [" + err.name + "]", false);
+               }
+               var cb = TestEngine.registerCallback("openStream", on_openStream_success, on_openStream_error);
+               f.openStream("w", cb.successCallback, cb.errorCallback, "SJIS");
+       }
+       resolve_root(on_resolve_success, on_resolve_error);
+}
+
+function UTC_filesystem_check_invalid_mode() {
+       var resolveArea = ["ringtones", "wgt-package"];
+
+       function on_resolve_error(err) {
+               TestEngine.test("resolve [" + err.name + "]", err.name == INVALID_VALUES_ERR);
+       }
+
+       function on_resolve_success(file) {
+               TestEngine.test("resolve ok, but can not be here", false);
+       }
+
+       var cb = [];
+       var index = 0;
+
+       for (index = 0; index < resolveArea.length; index++) {
+               cb[index] = TestEngine.registerCallback("resolve with invalid mode", 
+                               on_resolve_success, on_resolve_error);
+               tizen.filesystem.resolve(resolveArea[index], 
+                               cb[index].successCallback, cb[index].errorCallback);
+       }
+}
+
+function UTC_filesystem_copyTo_moveTo_error() {
+       function on_resolve_error(err) {
+               TestEngine.test("[" + err.name + "]", err.name == INVALID_VALUES_ERR);
+       }
+
+       function on_resolve_success(file) {
+               TestEngine.test("but can not be here", false);
+       }
+
+
+       tizen.filesystem.resolve("images",
+               function(file) {
+                       var copyToObj = TestEngine.registerCallback("copyTo with r FileOjbect", 
+                                       on_resolve_success, on_resolve_error);
+                       
+                               
+                       file.copyTo("images/image1.jpg", "ringtones/image111.jpg", true, copyToObj.successCallback, copyToObj.errorCallback);
+
+                       var moveToObj = TestEngine.registerCallback("moveTo with r FileOjbect", 
+                                       on_resolve_success, on_resolve_error);
+
+                       file.moveTo("images/image1.jpg", "ringtones/image111.jpg", true, moveToObj.successCallback, moveToObj.errorCallback);
+               },
+
+               function(e) {
+                       TestEngine.test("resolve error", false);
+               }, "rw");
+}
+
+
+function UTC_filesystem_invoke_write_permission_api_with_FileOjbect_resolved_as_r() {
+       function on_resolve_error(err) {
+               TestEngine.test("[" + err.name + "]", err.name == INVALID_VALUES_ERR);
+       }
+
+       function on_resolve_success(file) {
+               TestEngine.test("but can not be here", false);
+       }
+
+
+       tizen.filesystem.resolve("images",
+               function(file) {
+                       var modes = ["rw", "a", "w"];
+                       var openstreamcb = [];
+                       var index = 0;
+                       
+                       try {
+                               file.createFile("aaa.txt");
+                               TestEngine.test("no exception thrown", false);
+
+                       }       
+                       catch (e) {
+                               if (e.name == INVALID_VALUES_ERR)
+                                       TestEngine.test("exception ok : " + INVALID_VALUES_ERR + ":" + e.message,  true);
+                               else
+                                       TestEngine.test("exception name error", false);
+                       }
+       
+                       try {
+                               file.createDirectory("aaaaaaa");
+                               TestEngine.test("no exception thrown", false);
+
+                       }       
+                       catch (e) {
+                               if (e.name == INVALID_VALUES_ERR)
+                                       TestEngine.test("exception ok : " + INVALID_VALUES_ERR, true);
+                               else
+                                       TestEngine.test("exception name error", false);
+                       }
+       
+                       for (index = 0; index < modes.length; index++) {
+                               openstreamcb[index] = TestEngine.registerCallback("open stream with rw", 
+                                       on_resolve_success, on_resolve_error);
+                               try {
+                                       file.openStream(modes[index], openstreamcb[index].successCallback, openstreamcb[index].errorCallback);
+                               } catch (e) {
+                                       TestEngine.test("file.openStream exception: " + e, false);
+                               }
+                       }
+
+/*                     var copyToObj = TestEngine.registerCallback("copyTo with r FileOjbect", 
+                                       on_resolve_success, on_resolve_error);
+                       
+                               
+                       file.copyTo("images/image1.jpg", "images/image111.jpg", true, copyToObj.successCallback, copyToObj.errorCallback);*/
+
+                       var moveToObj = TestEngine.registerCallback("moveTo with r FileOjbect", 
+                                       on_resolve_success, on_resolve_error);
+
+                       file.moveTo("images/image1.jpg", "images/image111.jpg", true, moveToObj.successCallback, moveToObj.errorCallback);
+                       
+                       var deleteFileObj = TestEngine.registerCallback("deleteFile with r FileOjbect", 
+                                       on_resolve_success, on_resolve_error);
+
+                       file.deleteFile("images/image1.jpg", deleteFileObj.successCallback, deleteFileObj.errorCallback);
+
+                       var deleteDirectoryObj = TestEngine.registerCallback("deleteDirecotry with r FileOjbect", 
+                                       on_resolve_success, on_resolve_error);
+
+                       file.deleteDirectory("images", true, deleteDirectoryObj.successCallback, deleteDirectoryObj.errorCallback);
+                       TestEngine.test("ok", true);
+               },
+
+               function(e) {
+                       TestEngine.test("resolve error", false);
+               }, "r");
+}
+
+function UTC_filesystem_check_sdcard_resolve() {
+       var resolveObj;
+
+       var label = "removable_sda1";
+       tizen.filesystem.getStorage(label,
+                       function(storage) {
+                               console.log(storage.state);
+                               if (storage.state == "MOUNTED") {
+                                       resolveObj = TestEngine.registerCallback("resolve sdcard", function(f) {
+                                                       TestEngine.test("resolve sdcard ok", true);
+                                               },
+                                               function(e) {
+                                                       TestEngine.test("resolve sdcard error", false);
+                                               });
+                                       tizen.filesystem.resolve(label, resolveObj.successCallback, resolveObj.errorCallback, "r");
+                               }
+                               else {
+                                       resolveObj = TestEngine.registerCallback("resolve sdcard", function(f) {
+                                                       TestEngine.test("resolve sdcard ok, but error", false);
+                                               },
+                                               function(e) {
+                                                       TestEngine.test("resolve sdcard error: " + e.name + ' - ' + e.message, e.name == NOT_FOUND_ERR);
+                                               });
+                                       tizen.filesystem.resolve(label, resolveObj.successCallback, resolveObj.errorCallback);
+                                       tizen.filesystem.resolve(label+"/a.txt", resolveObj.successCallback, resolveObj.errorCallback);
+                               
+
+
+                               }
+                       },
+                       function(e) {
+                               TestEngine.test("getStorage Error: " + e.name + ' - ' + e.message, false);
+                       });
+}
+
+function UTC_filesystem_stupid_resolve_delete()
+{
+       function on_resolve_error(err) {
+               TestEngine.test("[" + err.name + "]", err.name == NOT_FOUND_ERR);
+       }
+
+       function on_resolve_success(file) {
+               TestEngine.test("but can not be here", false);
+       }
+
+       tizen.filesystem.resolve("images",
+               function(file) {
+       
+                       var deleteFileObj = TestEngine.registerCallback("deleteFile with r FileOjbect", 
+                               on_resolve_success, on_resolve_error);
+
+                       file.deleteFile("documents/a.txt", deleteFileObj.successCallback, deleteFileObj.errorCallback);
+
+                       var deleteDirectoryObj = TestEngine.registerCallback("deleteDirecotry with r FileOjbect", 
+                               on_resolve_success, on_resolve_error);
+
+                       file.deleteDirectory("documents/b", true, deleteDirectoryObj.successCallback, deleteDirectoryObj.errorCallback);
+               },
+               function (e) {
+                       TestEngine.test("getStroage Error", false);
+               }, "rw");
+               
+}
+// manual test function 
+function UTC_filesystem_permission_denied_error()
+{
+       function on_resolve_error(err) {
+               TestEngine.test("[" + err.name + ":" + err.msg + "]", err.name == INVALID_VALUES_ERR);
+       }
+
+       function on_resolve_success(file) {
+               TestEngine.test("but can not be here", false);
+       }
+
+       tizen.filesystem.resolve("documents",
+               function(file) {
+       
+                       var deleteFileObj = TestEngine.registerCallback("deleteFile with r FileOjbect", 
+                               on_resolve_success, on_resolve_error);
+
+                       file.deleteFile("documents/a.txt", deleteFileObj.successCallback, deleteFileObj.errorCallback);
+
+                       var deleteDirectoryObj = TestEngine.registerCallback("deleteDirecotry with r FileOjbect", 
+                               on_resolve_success, on_resolve_error);
+
+                       file.deleteDirectory("documents/b", true, deleteDirectoryObj.successCallback, deleteDirectoryObj.errorCallback);
+               },
+               function (e) {
+                       TestEngine.test("getStroage Error", false);
+               }, "rw");
+               
+}
diff --git a/webWidgetTCT_device/test/utc/tests/TestMessagePort.js b/webWidgetTCT_device/test/utc/tests/TestMessagePort.js
new file mode 100755 (executable)
index 0000000..03648d6
--- /dev/null
@@ -0,0 +1,607 @@
+var TYPE_MISMATCH_ERR = "TypeMismatchError";
+var INVALID_VALUES_ERR = "InvalidValuesError";
+var NOT_FOUND_ERR = "NotFoundError";
+var UNKNOWN_ERR = "UnknownError";
+var NOT_SUPPORTED_ERR = "NotSupportedError";
+var PERMISSION_DENIED_ERR = "SecurityError";
+var INVALID_ACCESS_ERR = "InvalidAccessError";
+
+var currentAppId = "tizenutc00.UnitTest";
+
+//var remotePortUntrusted_appId = "tizenutcmp.MsgPortSvr";
+//var remotePortUntrusted_name = "TEST_TRUSTED_PORT_SIMPLE";
+
+var localPort_name = "UTC_TEST_PORT";
+var localPort_watchId = 0;
+var localPort = null;
+var localPortForReceive_name = "UTC_TEST_PORT_RECEIVE";
+var localPortForReceive = null;
+var remotePort_appId = "tizenutcmp.MsgPortSvr";
+var remotePort_name = "TEST_PORT_SIMPLE";
+var remotePort = null;
+var remotePortForRequest_appId = "tizenutcmp.MsgPortSvr";
+var remotePortForRequest_name = "TEST_PORT_FOR_REQ_CONNECT";
+var remotePortForRequest_key_portName = "PORT_NAME";
+var remotePortForRequest_key_appId = "APP_ID";
+var remotePortForRequest = null;
+
+var localPortTrusted_name = "UTC_TEST_TRUSTED_PORT";
+var localPortTrusted_watchId = 0;
+var localPortTrusted = null;
+var localPortTrustedForReceive_name = "UTC_TEST_TRUSTED_PORT_RECEIVE";
+var localPortTrustedForReceive = null;
+var remotePortTrusted_appId = "tizenutcmp.MsgPortSvr";
+var remotePortTrusted_name = "TEST_TRUSTED_PORT_SIMPLE";
+var remotePortTrusted = null;
+var remotePortTrustedForRequest_appId = "tizenutcmp.MsgPortSvr";
+var remotePortTrustedForRequest_name = "TEST_TRUSTED_PORT_FOR_REQ_CONNECT";
+var remotePortTrustedForRequest_key_portName = "PORT_NAME";
+var remotePortTrustedForRequest_key_appId = "APP_ID";
+var remotePortTrustedForRequest = null;
+
+var TestMessagePort =
+{
+       UTC_messagePort_MessagePortManager_P_001: function()
+       {
+               TestEngine.log("[Start] UTC_messagePort_MessagePortManager_P_001");
+
+               TestEngine.test("Tizen presence", tizen);
+               TestEngine.test("MessagePortManager presence", tizen.messageport);
+               TestEngine.testPresence("MessagePortManager.requestLocalMessagePort presence", tizen.messageport.requestLocalMessagePort);
+               TestEngine.testPresence("MessagePortManager.requestTrustedLocalMessagePort presence", tizen.messageport.requestTrustedLocalMessagePort);
+               TestEngine.testPresence("MessagePortManager.requestRemoteMessagePort presence", tizen.messageport.requestRemoteMessagePort);
+               TestEngine.testPresence("MessagePortManager.requestTrustedRemoteMessagePort presence", tizen.messageport.requestTrustedRemoteMessagePort);
+       },
+
+       UTC_messagePort_requestLocalMessagePort_P_001: function()
+       {
+               TestEngine.log("[Start] UTC_messagePort_requestLocalMessagePort_P_001");
+
+               testNoExceptionWithMessage("requestLocalMessagePort", function() {
+                       localPort = tizen.messageport.requestLocalMessagePort(localPort_name);
+                       TestEngine.test("Got LocalMessagePort", localPort);
+               });
+       },
+
+       UTC_messagePort_requestLocalMessagePort_N_001: function()
+       {
+               TestEngine.log("[Start] UTC_messagePort_requestLocalMessagePort_N_001");
+
+               TestEngine.log("1st parameter check.");
+               TestEngine.catchErrorType("name", INVALID_VALUES_ERR, tizen.messageport, "requestLocalMessagePort", "");
+       },
+
+       UTC_messagePort_requestTrustedLocalMessagePort_P_001: function()
+       {
+               TestEngine.log("[Start] UTC_messagePort_requestTrustedLocalMessagePort_P_001");
+
+               testNoExceptionWithMessage("requestTrustedLocalMessagePort", function() {
+                       localPortTrusted = tizen.messageport.requestTrustedLocalMessagePort(localPortTrusted_name);
+                       TestEngine.test("Found a trusted LocalMessagePort", localPortTrusted);
+               });
+       },
+
+       UTC_messagePort_requestTrustedLocalMessagePort_N_001: function()
+       {
+               TestEngine.log("[Start] UTC_messagePort_requestTrustedLocalMessagePort_N_001");
+
+               TestEngine.log("1st parameter check.");
+               TestEngine.catchErrorType("name", INVALID_VALUES_ERR, tizen.messageport, "requestTrustedLocalMessagePort", "");
+       },
+
+       UTC_messagePort_requestRemoteMessagePort_P_001: function()
+       {
+               TestEngine.log("[Start] UTC_messagePort_requestRemoteMessagePort_P_001");
+
+               testNoExceptionWithMessage("requestLocalMessagePort", function() {
+                       remotePort = tizen.messageport.requestRemoteMessagePort(remotePort_appId, remotePort_name);
+                       TestEngine.test("Found a RemoteMessagePort", remotePort);
+               });
+       },
+
+       UTC_messagePort_requestRemoteMessagePort_N_001: function()
+       {
+               TestEngine.log("[Start] UTC_messagePort_requestRemoteMessagePort_N_001");
+
+               TestEngine.log("Parameter count check.");
+               TestEngine.catchErrorType("name", NOT_FOUND_ERR, tizen.messageport, "requestRemoteMessagePort");
+
+               TestEngine.log("1st parameter check.");
+               TestEngine.catchErrorType("name", NOT_FOUND_ERR, tizen.messageport, "requestRemoteMessagePort", "", remotePort_name);
+               TestEngine.catchErrorType("name", NOT_FOUND_ERR, tizen.messageport, "requestRemoteMessagePort", "aaaaaaaaaa.Wrong", remotePort_name);
+
+               TestEngine.log("2nd parameter check.");
+               TestEngine.catchErrorType("name", NOT_FOUND_ERR, tizen.messageport, "requestRemoteMessagePort", remotePort_appId);
+               TestEngine.catchErrorType("name", NOT_FOUND_ERR, tizen.messageport, "requestRemoteMessagePort", remotePort_appId, "");
+               TestEngine.catchErrorType("name", NOT_FOUND_ERR, tizen.messageport, "requestRemoteMessagePort", remotePort_appId, "NotExist");
+       },
+
+       UTC_messagePort_requestTrustedRemoteMessagePort_P_001: function()
+       {
+               TestEngine.log("[Start] UTC_messagePort_requestTrustedRemoteMessagePort_P_001");
+
+               testNoExceptionWithMessage("requestLocalMessagePort", function() {
+                       remotePortTrusted = tizen.messageport.requestTrustedRemoteMessagePort(remotePortTrusted_appId, remotePortTrusted_name);
+                       TestEngine.test("Found a TrustedRemoteMessagePort", remotePortTrusted);
+               });
+       },
+
+       UTC_messagePort_requestTrustedRemoteMessagePort_N_001: function()
+       {
+               TestEngine.log("[Start] UTC_messagePort_requestTrustedRemoteMessagePort_N_001");
+
+               TestEngine.log("Parameter count check.");
+               TestEngine.catchErrorType("name", NOT_FOUND_ERR, tizen.messageport, "requestTrustedRemoteMessagePort");
+
+               TestEngine.log("1st parameter check.");
+               TestEngine.catchErrorType("name", NOT_FOUND_ERR, tizen.messageport, "requestTrustedRemoteMessagePort", "", remotePortTrusted_name);
+               TestEngine.catchErrorType("name", NOT_FOUND_ERR, tizen.messageport, "requestTrustedRemoteMessagePort", "aaaaaaaaaa.Wrong", remotePortTrusted_name);
+
+               TestEngine.log("2nd parameter check.");
+               TestEngine.catchErrorType("name", NOT_FOUND_ERR, tizen.messageport, "requestTrustedRemoteMessagePort", remotePortTrusted_appId);
+               TestEngine.catchErrorType("name", NOT_FOUND_ERR, tizen.messageport, "requestTrustedRemoteMessagePort", remotePortTrusted_appId, "");
+               TestEngine.catchErrorType("name", NOT_FOUND_ERR, tizen.messageport, "requestTrustedRemoteMessagePort", remotePortTrusted_appId, "NotExist");
+
+//             TestEngine.log("untrusted connection check.");
+//             TestEngine.catchErrorType("name", INVALID_ACCESS_ERR, tizen.messageport, "requestTrustedRemoteMessagePort", remotePortUntrusted_appId, remotePortUntrusted_name);
+       },
+
+       UTC_messagePort_LocalMessagePort_P_001: function()
+       {
+               TestEngine.log("[Start] UTC_messagePort_LocalMessagePort_P_001");
+
+               TestEngine.testPresence("LocalMessagePort.messagePortName presence", localPort.messagePortName);
+               TestEngine.testPresence("LocalMessagePort.isTrusted presence", localPort.isTrusted);
+               TestEngine.testPresence("LocalMessagePort.addMessagePortListener presence", localPort.addMessagePortListener);
+               TestEngine.testPresence("LocalMessagePort.removeMessagePortListener presence", localPort.removeMessagePortListener);
+       },
+
+       UTC_messagePort_RemoteMessagePort_P_001: function()
+       {
+               TestEngine.log("[Start] UTC_messagePort_RemoteMessagePort_P_001");
+
+               TestEngine.testPresence("RemoteMessagePort.messagePortName presence", remotePort.messagePortName);
+               TestEngine.testPresence("RemoteMessagePort.appId presence", remotePort.appId);
+               TestEngine.testPresence("RemoteMessagePort.isTrusted presence", remotePort.isTrusted);
+               TestEngine.testPresence("RemoteMessagePort.sendMessage presence", remotePort.sendMessage);
+       },
+
+       UTC_messagePort_sendMessage_P_001: function()
+       {
+               TestEngine.log("[Start] UTC_messagePort_sendMessage_P_001");
+
+               testNoExceptionWithMessage("sendMessage without localPort", function() {
+                       remotePort.sendMessage( [
+                               { key:"KEY1", value:"value1" },
+                               { key:"KEY2", value:"value2" },
+                               { key:"KEY3", value:"value3" }
+                       ] );
+               } );
+       },
+
+       UTC_messagePort_sendMessage_N_001: function()
+       {
+               TestEngine.log("[Start] UTC_messagePort_sendMessage_N_001");
+
+               TestEngine.log("Parameter count check.");
+               TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, remotePort, "sendMessage");
+
+               TestEngine.log("1st parameter check.");
+               TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, remotePort, "sendMessage", 1);
+               TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, remotePort, "sendMessage", null);
+               TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, remotePort, "sendMessage", undefined);
+
+               var param = [ { key:"KEY", value:"VALUE" } ];
+               TestEngine.log("2nd parameter check.");
+               TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, remotePort, "sendMessage", param, 1);
+               TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, remotePort, "sendMessage", param, {});
+       },
+
+       UTC_messagePort_addMessagePortListener_P_001: function()
+       {
+               TestEngine.log("[Start] UTC_messagePort_addMessagePortListener_P_001");
+
+               testNoExceptionWithMessage("addMessagePortListener", function() {
+                       localPort_watchId = localPort.addMessagePortListener(function(data, localMessagePort) { } );
+               } );
+       },
+
+       UTC_messagePort_addMessagePortListener_N_001: function()
+       {
+               TestEngine.log("[Start] UTC_messagePort_addMessagePortListener_N_001");
+
+               TestEngine.log("Parameter count check.");
+               TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, localPort, "addMessagePortListener");
+
+               TestEngine.log("1st parameter check.");
+               TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, localPort, "addMessagePortListener", 1);
+               TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, localPort, "addMessagePortListener", null);
+               TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, localPort, "addMessagePortListener", undefined);
+       },
+
+       UTC_messagePort_removeMessagePortListener_P_001: function()
+       {
+               TestEngine.log("[Start] UTC_messagePort_removeMessagePortListener_P_001");
+
+               testNoExceptionWithMessage("removeMessagePortListener", function() {
+                       localPort.removeMessagePortListener(localPort_watchId);
+                       localPort_watchId = 0;
+               } );
+       },
+
+       UTC_messagePort_removeMessagePortListener_N_001: function()
+       {
+               TestEngine.log("[Start] UTC_messagePort_removeMessagePortListener_N_001");
+
+               TestEngine.log("Parameter count check.");
+               TestEngine.catchErrorType("name", NOT_FOUND_ERR, localPort, "removeMessagePortListener");
+
+               TestEngine.log("1st parameter check.");
+               TestEngine.catchErrorType("name", NOT_FOUND_ERR, localPort, "removeMessagePortListener", 1);
+               TestEngine.catchErrorType("name", NOT_FOUND_ERR, localPort, "removeMessagePortListener", null);
+               TestEngine.catchErrorType("name", NOT_FOUND_ERR, localPort, "removeMessagePortListener", undefined);
+       },
+
+       UTC_messagePort_receiveMessage_P_001: function()
+       {
+               TestEngine.log("[Start] UTC_messagePort_receiveMessage_P_001");
+
+               function onReceiveCB(data)
+               {
+                       TestEngine.test("Data receive succeeded.", true);
+                       localPort.removeMessagePortListener(localPort_watchId);
+                       localPort_watchId = 0;
+               }
+
+               var objCb = TestEngine.registerCallback("addMessagePortListener",
+                       onReceiveCB,
+                       null,
+                       1);
+
+               localPort_watchId = localPort.addMessagePortListener(objCb.successCallback);
+
+               remotePortForRequest = tizen.messageport.requestRemoteMessagePort(
+                       remotePortForRequest_appId,
+                       remotePortForRequest_name);
+
+               remotePortForRequest.sendMessage( [
+                       { key:remotePortForRequest_key_appId, value:currentAppId },
+                       { key:remotePortForRequest_key_portName, value:localPort_name}
+               ] );
+       },
+
+       UTC_messagePort_receiveRepliedMessage_P_001: function()
+       {
+               TestEngine.log("[Start] UTC_messagePort_receiveRepliedMessage_P_001");
+
+               function onReceiveCB(data)
+               {
+                       TestEngine.test("Data receive succeeded.", true);
+                       localPortForReceive.removeMessagePortListener(localPortForReceive_watchId);
+                       localPortForReceive_watchId = 0;
+               }
+
+               var objCb = TestEngine.registerCallback("addMessagePortListener",
+                       onReceiveCB,
+                       null,
+                       1);
+
+               localPortForReceive = tizen.messageport.requestLocalMessagePort(localPortForReceive_name);
+               localPortForReceive_watchId = localPortForReceive.addMessagePortListener(objCb.successCallback);
+
+               remotePort.sendMessage( [
+                       { key:"KEY1", value:"VALUE1" },
+                       { key:"KEY2", value:"VALUE2" }
+               ], localPortForReceive );
+       },
+
+       UTC_messagePort_TrustedLocalMessagePort_P_001: function()
+       {
+               TestEngine.log("[Start] UTC_messagePort_TrusteLocalMessagePort_P_001");
+
+               TestEngine.testPresence("LocalMessagePort.messagePortName presence", localPortTrusted.messagePortName);
+               TestEngine.testPresence("LocalMessagePort.isTrusted presence", localPortTrusted.isTrusted);
+               TestEngine.testPresence("LocalMessagePort.addMessagePortListener presence", localPortTrusted.addMessagePortListener);
+               TestEngine.testPresence("LocalMessagePort.removeMessagePortListener presence", localPortTrusted.removeMessagePortListener);
+       },
+
+       UTC_messagePort_TrustedRemoteMessagePort_P_001: function()
+       {
+               TestEngine.log("[Start] UTC_messagePort_TrustedRemoteMessagePort_P_001");
+
+               TestEngine.testPresence("RemoteMessagePort.messagePortName presence", remotePortTrusted.messagePortName);
+               TestEngine.testPresence("RemoteMessagePort.appId presence", remotePortTrusted.appId);
+               TestEngine.testPresence("RemoteMessagePort.isTrusted presence", remotePortTrusted.isTrusted);
+               TestEngine.testPresence("RemoteMessagePort.sendMessage presence", remotePortTrusted.sendMessage);
+       },
+
+       UTC_messagePort_sendMessageTrusted_P_001: function()
+       {
+               TestEngine.log("[Start] UTC_messagePort_sendMessageTrusted_P_001");
+
+               testNoExceptionWithMessage("sendMessage without localPortTrusted", function() {
+                       remotePortTrusted.sendMessage( [
+                               { key:"KEY1", value:"value1" },
+                               { key:"KEY2", value:"value2" },
+                               { key:"KEY3", value:"value3" }
+                       ] );
+               } );
+       },
+
+       UTC_messagePort_sendMessageTrusted_N_001: function()
+       {
+               TestEngine.log("[Start] UTC_messagePort_sendMessageTrusted_N_001");
+
+               TestEngine.log("Parameter count check.");
+               TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, remotePortTrusted, "sendMessage");
+
+               TestEngine.log("1st parameter check.");
+               TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, remotePortTrusted, "sendMessage", 1);
+               TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, remotePortTrusted, "sendMessage", null);
+               TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, remotePortTrusted, "sendMessage", undefined);
+
+               var param = [ { key:"KEY", value:"VALUE" } ];
+               TestEngine.log("2nd parameter check.");
+               TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, remotePortTrusted, "sendMessage", param, 1);
+               TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, remotePortTrusted, "sendMessage", param, {});
+       },
+
+       UTC_messagePort_addTrustedMessagePortListener_P_001: function()
+       {
+               TestEngine.log("[Start] UTC_messagePort_addTrustedMessagePortListener_P_001");
+
+               testNoExceptionWithMessage("addMessagePortListener", function() {
+                       localPortTrusted_watchId = localPortTrusted.addMessagePortListener(function(data, trustedLocalMessagePort) { } );
+               } );
+       },
+
+       UTC_messagePort_addTrustedMessagePortListener_N_001: function()
+       {
+               TestEngine.log("[Start] UTC_messagePort_addTrustedMessagePortListener_N_001");
+
+               TestEngine.log("Parameter count check.");
+               TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, localPortTrusted, "addMessagePortListener");
+
+               TestEngine.log("1st parameter check.");
+               TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, localPortTrusted, "addMessagePortListener", 1);
+               TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, localPortTrusted, "addMessagePortListener", null);
+               TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, localPortTrusted, "addMessagePortListener", undefined);
+       },
+
+       UTC_messagePort_removeTrustedMessagePortListener_P_001: function()
+       {
+               TestEngine.log("[Start] UTC_messagePort_removeTrustedMessagePortListener_P_001");
+
+               testNoExceptionWithMessage("removeMessagePortListener", function() {
+                       localPortTrusted.removeMessagePortListener(localPortTrusted_watchId);
+                       localPortTrusted_watchId = 0;
+               } );
+       },
+
+       UTC_messagePort_removeTrustedMessagePortListener_N_001: function()
+       {
+               TestEngine.log("[Start] UTC_messagePort_removeTrustedMessagePortListener_N_001");
+
+               TestEngine.log("Parameter count check.");
+               TestEngine.catchErrorType("name", NOT_FOUND_ERR, localPortTrusted, "removeMessagePortListener");
+
+               TestEngine.log("1st parameter check.");
+               TestEngine.catchErrorType("name", NOT_FOUND_ERR, localPortTrusted, "removeMessagePortListener", 1);
+               TestEngine.catchErrorType("name", NOT_FOUND_ERR, localPortTrusted, "removeMessagePortListener", null);
+               TestEngine.catchErrorType("name", NOT_FOUND_ERR, localPortTrusted, "removeMessagePortListener", undefined);
+       },
+
+       UTC_messagePort_receiveMessageTrusted_P_001: function()
+       {
+               TestEngine.log("[Start] UTC_messagePort_receiveMessageTrusted_P_001");
+
+               function onReceiveCB(data)
+               {
+                       TestEngine.test("Data receive succeeded.", true);
+                       localPortTrusted.removeMessagePortListener(localPortTrusted_watchId);
+                       localPortTrusted_watchId = 0;
+               }
+
+               var objCb = TestEngine.registerCallback("addMessagePortListener",
+                       onReceiveCB,
+                       null,
+                       1);
+
+               localPortTrusted_watchId = localPortTrusted.addMessagePortListener(objCb.successCallback);
+
+               remotePortTrustedForRequest = tizen.messageport.requestTrustedRemoteMessagePort(
+                       remotePortTrustedForRequest_appId,
+                       remotePortTrustedForRequest_name);
+
+               remotePortTrustedForRequest.sendMessage( [
+                       { key:remotePortTrustedForRequest_key_appId, value:currentAppId },
+                       { key:remotePortTrustedForRequest_key_portName, value:localPortTrusted_name}
+               ] );
+       },
+
+       UTC_messagePort_receiveRepliedMessageTrusted_P_001: function()
+       {
+               TestEngine.log("[Start] UTC_messagePort_receiveRepliedMessageTrusted_P_001");
+
+               function onReceiveCB(data)
+               {
+                       TestEngine.test("Data receive succeeded.", true);
+                       localPortTrustedForReceive.removeMessagePortListener(localPortTrustedForReceive_watchId);
+                       localPortTrustedForReceive_watchId = 0;
+               }
+
+               var objCb = TestEngine.registerCallback("addMessagePortListener",
+                       onReceiveCB,
+                       null,
+                       1);
+
+               localPortTrustedForReceive = tizen.messageport.requestTrustedLocalMessagePort(localPortTrustedForReceive_name);
+               localPortTrustedForReceive_watchId = localPortTrustedForReceive.addMessagePortListener(objCb.successCallback);
+
+               remotePortTrusted.sendMessage( [
+                       { key:"KEY1", value:"VALUE1" },
+                       { key:"KEY2", value:"VALUE2" }
+               ], localPortTrustedForReceive );
+       }
+}
+
+//=============================================================================
+
+function testNoExceptionWithMessage(message, fun) {
+       var testResult = true;
+       try
+       {
+               fun();
+       }
+       catch (e)
+       {
+               testResult = false;
+       }
+       TestEngine.test(message, testResult);
+}
+
+function testConstructorNoException(object, constructorName, restArguments /* , ... */ ) {
+       try {
+               var retVal;
+               try {
+                       var newArgs = []
+                       for(var i = 2; i < arguments.length; i++) {
+                               newArgs.push(arguments[i])
+                       }
+                       if(arguments.length < 2) {
+                               TestEngine.logErr("Wrong catchErrorType usage.");
+                               return null;
+                       }
+                       //no args
+                       if(arguments.length == 2) {
+                               retVal = new object[constructorName]();
+                       }
+                       //1 arg
+                       if(arguments.length == 3) {
+                               retVal = new object[constructorName](newArgs[0]);
+                       }
+                       //2 args
+                       if(arguments.length == 4) {
+                               retVal = new object[constructorName](newArgs[0], newArgs[1]);
+                       }
+                       //3 args
+                       if(arguments.length == 5) {
+                               retVal = new object[constructorName](newArgs[0], newArgs[1], newArgs[2]);
+                       }
+                       // 4 args
+                       if(arguments.length == 6) {
+                               retVal = new object[constructorName](newArgs[0], newArgs[1], newArgs[2], newArgs[3]);
+                       }
+                       // 5 args
+                       if(arguments.length == 7) {
+                               retVal = new object[constructorName](newArgs[0], newArgs[1], newArgs[2], newArgs[3], newArgs[4]);
+                       }
+                       // 6 args
+                       if(arguments.length == 8) {
+                               retVal = new object[constructorName](newArgs[0], newArgs[1], newArgs[2], newArgs[3], newArgs[4], newArgs[5]);
+                       }
+                       // 7 args
+                       if(arguments.length == 9) {
+                               retVal = new object[constructorName](newArgs[0], newArgs[1], newArgs[2], newArgs[3], newArgs[4], newArgs[5], newArgs[6]);
+                       }
+                       // 8 args
+                       if(arguments.length == 10) {
+                               retVal = new object[constructorName](newArgs[0], newArgs[1], newArgs[2], newArgs[3], newArgs[4], newArgs[5], newArgs[6], newArgs[7]);
+                       }
+                       // 9 args
+                       if(arguments.length == 11) {
+                               retVal = new object[constructorName](newArgs[0], newArgs[1], newArgs[2], newArgs[3], newArgs[4], newArgs[5], newArgs[6], newArgs[7], newArgs[8]);
+                       }
+                       // 10 args
+                       if(arguments.length == 12) {
+                               retVal = new object[constructorName](newArgs[0], newArgs[1], newArgs[2], newArgs[3], newArgs[4], newArgs[5], newArgs[6], newArgs[7], newArgs[8], newArgs[9]);
+                       }
+
+               } catch(error) {
+                       TestEngine.test("Error thrown while constructing " + constructorName + " : " + error.name, false);
+                       return null;
+               }
+               var isObj = (retVal);
+               TestEngine.test("Constructor creating object.", isObj);
+               if(isObj)
+                       return retVal;
+               else
+                       return null;
+
+       } catch(err) {
+               TestEngine.countException++;
+               logError("   TestEngine.testError failure:" + err.message);
+       }
+}
+
+function catchErrorTypeForConstructor(errorTypeName, type, object, constructorName, restArguments /* , ... */ ) {
+       try {
+               var error;
+               try {
+                       var newArgs = []
+                       for(var i = 4; i < arguments.length; i++) {
+                               newArgs.push(arguments[i])
+                       }
+                       var retVal = null;
+                       if(arguments.length < 4) {
+                               TestEngine.logErr("Wrong catchErrorType usage.");
+                               return retVal;
+                       }
+                       //no args
+                       if(arguments.length == 4) {
+                               retVal = new object[constructorName]();
+                       }
+                       //1 arg
+                       if(arguments.length == 5) {
+                               retVal = new object[constructorName](newArgs[0]);
+                       }
+                       //2 args
+                       if(arguments.length == 6) {
+                               retVal = new object[constructorName](newArgs[0], newArgs[1]);
+                       }
+                       //3 args
+                       if(arguments.length == 7) {
+                               retVal = new object[constructorName](newArgs[0], newArgs[1], newArgs[2]);
+                       }
+                       // 4 args
+                       if(arguments.length == 8) {
+                               retVal = new object[constructorName](newArgs[0], newArgs[1], newArgs[2], newArgs[3]);
+                       }
+                       // 5 args
+                       if(arguments.length == 9) {
+                               retVal = new object[constructorName](newArgs[0], newArgs[1], newArgs[2], newArgs[3], newArgs[4]);
+                       }
+                       // 6 args
+                       if(arguments.length == 10) {
+                               retVal = new object[constructorName](newArgs[0], newArgs[1], newArgs[2], newArgs[3], newArgs[4], newArgs[5]);
+                       }
+                       // 7 args
+                       if(arguments.length == 11) {
+                               retVal = new object[constructorName](newArgs[0], newArgs[1], newArgs[2], newArgs[3], newArgs[4], newArgs[5], newArgs[6]);
+                       }
+                       // 8 args
+                       if(arguments.length == 12) {
+                               retVal = new object[constructorName](newArgs[0], newArgs[1], newArgs[2], newArgs[3], newArgs[4], newArgs[5], newArgs[6], newArgs[7]);
+                       }
+                       // 9 args
+                       if(arguments.length == 13) {
+                               retVal = new object[constructorName](newArgs[0], newArgs[1], newArgs[2], newArgs[3], newArgs[4], newArgs[5], newArgs[6], newArgs[7], newArgs[8]);
+                       }
+                       // 10 args
+                       if(arguments.length == 14) {
+                               retVal = new object[constructorName](newArgs[0], newArgs[1], newArgs[2], newArgs[3], newArgs[4], newArgs[5], newArgs[6], newArgs[7], newArgs[8], newArgs[9]);
+                       }
+
+                       TestEngine.logErr(constructorName + " no error thrown");
+                       return retVal;
+               } catch(error) {
+                       TestEngine.testPresence("<error type from: new " + constructorName + ">", error[errorTypeName]);
+                       TestEngine.test("Error number", error[errorTypeName] == type);
+                       return;
+               }
+               TestEngine.logErr("Function " + constructorName + " desn't throw");
+       } catch(err) {
+               TestEngine.countException++;
+               logError("   TestEngine.testError failure:" + err.message);
+       }
+}
diff --git a/webWidgetTCT_device/test/utc/tests/TestPackage.js b/webWidgetTCT_device/test/utc/tests/TestPackage.js
new file mode 100755 (executable)
index 0000000..140761a
--- /dev/null
@@ -0,0 +1,1097 @@
+/*
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ * PROPRIETARY/CONFIDENTIAL
+ *
+ * This software is the confidential and proprietary information of SAMSUNG
+ * ELECTRONICS ("Confidential Information"). You agree and acknowledge that
+ * this software is owned by Samsung and you shall not disclose such
+ * Confidential Information and shall use it only in accordance with the terms
+ * of the license agreement you entered into with SAMSUNG ELECTRONICS. SAMSUNG
+ * make no representations or warranties about the suitability of the software,
+ * either express or implied, including but not limited to the implied
+ * warranties of merchantability, fitness for a particular purpose, or
+ * non-infringement. SAMSUNG shall not be liable for any damages suffered by
+ * licensee arising out of or related to this software.
+ *
+ */
+
+var TYPE_MISMATCH_ERR = 'TypeMismatchError';
+var NOT_FOUND_ERR = 'NotFoundError';
+
+var CURR_PKG_ID = 'tizenutc00';
+var CURR_APP_ID = 'tizenutc00.PackageUnitTest';
+var TEST_NUM = 1234;
+var TEST_STR = "UTC_TEST_STRING";
+var TEST_OBJ = new tizen.ApplicationControl("TEST_OPERATION");
+var TEST_FUN = function() {};
+
+var TEST_PKG_PATH_1 = '/home/owner/share/PkgTest001.wgt';
+var TEST_PKG_ID_1 = 'PkgTest001';
+var TEST_PKG_PATH_2 = '/home/owner/share/PkgTest002.wgt';
+var TEST_PKG_ID_2 = 'PkgTest002';
+var TEST_PKG_PATH_3 = '/home/owner/share/PkgTest003.wgt';
+var TEST_PKG_ID_3 = 'PkgTest003';
+var TEST_ILLEGAL_PKG_PATH = '/home/owner/share/illegal_widget.wgt';
+var TEST_ILLEGAL_ID = 'illegal';
+
+/********************************************************************
+ *   Package Interface
+ ********************************************************************/
+
+function onSuccessCB()
+{
+       TestEngine.test("[Package]", true);
+}
+
+function onErrorCB(err)
+{
+       TestEngine.log("error name: " + err.name);
+       TestEngine.log("error code: " + err.code);
+       TestEngine.log("description: " + err.description);
+       TestEngine.log("message: " + err.message);
+
+       TestEngine.test("[Package]", false);
+}
+
+var onInstallSuccessCB =
+{
+       onprogress: function(pkg, progress) {
+               TestEngine.log("on progress : " + pkg + " progress : " + progress);
+       },
+       oncomplete: function(pkg) {
+               TestEngine.log("Completed : " + pkg);
+               TestEngine.test("[Package]", true);
+       }
+};
+
+
+function UTC_package_presence_P_001()
+{
+       TestEngine.log("[Package] UTC_package_presence_P_001 START");
+       try {
+               TestEngine.test("Tizen presence", tizen);
+           TestEngine.test("PackageManager presence", tizen.package);
+               TestEngine.testPresence("install", tizen.package.install);
+               TestEngine.testPresence("uninstall", tizen.package.uninstall);
+               TestEngine.testPresence("getPackagesInfo", tizen.package.getPackagesInfo);
+               TestEngine.testPresence("getPackageInfo", tizen.package.getPackageInfo);
+               TestEngine.testPresence("setPackageInfoEventListener", tizen.package.setPackageInfoEventListener);
+               TestEngine.testPresence("unsetPackageInfoEventListener", tizen.package.unsetPackageInfoEventListener);
+       } catch (err) {
+               TestEngine.test("[Package] UTC_package_presence_P_001 error : " + err);
+               TestEngine.test("", false);
+       }
+
+       TestEngine.log("[Package] UTC_package_presence_P_001 END");
+}
+
+function UTC_package_install_P_001()
+{
+       TestEngine.log("[Package] UTC_package_install_P_001 START");
+       var cbObj = TestEngine.registerCallback("install", onSuccessCB, onErrorCB);
+
+       var onInstallSuccessCB =
+       {
+               onprogress: function(pkg, progress) {
+                       TestEngine.log("on progress : " + pkg + " progress : " + progress);
+               },
+               oncomplete: function(pkg) {
+                       TestEngine.log("Completed : " + pkg);
+                       //TestEngine.test("[Package]", true);
+                       cbObj.successCallback();
+               }
+       };      
+       
+       try {
+               tizen.package.install(TEST_PKG_PATH_1, onInstallSuccessCB, null);
+       } catch (err) {
+               TestEngine.test("[Package] UTC_package_install_P_001 error", false);
+       }
+       
+       TestEngine.log("[Package] UTC_package_install_P_001 END");
+}
+
+function UTC_package_install_P_002()
+{
+       TestEngine.log("[Package] UTC_package_install_P_002 START");
+       var cbObj = TestEngine.registerCallback("install", onSuccessCB, onErrorCB);
+
+       var onInstallSuccessCB =
+       {
+               onprogress: function(pkg, progress) {
+                       TestEngine.log("on progress : " + pkg + " progress : " + progress);
+               },
+               oncomplete: function(pkg) {
+                       TestEngine.log("Completed : " + pkg);
+                       //TestEngine.test("[Package]", true);
+                       setTimeout("cbObj.successCallback()", 3000);
+               }
+       };      
+               
+       try {
+               setTimeout("tizen.package.install(TEST_PKG_PATH_2, onInstallSuccessCB, cbObj.errorCallback)", 2000);
+       } catch (err) {
+               TestEngine.test("", false);
+       }
+       
+       TestEngine.log("[Package] UTC_package_install_P_002 END");
+}
+
+function UTC_package_install_P_003()
+{
+       TestEngine.log("[Package] UTC_package_install_P_003 START");
+       var cbObj = TestEngine.registerCallback("install", onSuccessCB, onErrorCB);
+
+       var onInstallSuccessCB =
+       {
+               onprogress: function(pkg, progress) {
+                       TestEngine.log("on progress : " + pkg + " progress : " + progress);
+               },
+               oncomplete: function(pkg) {
+                       TestEngine.log("Completed : " + pkg);
+                       //TestEngine.test("[Package]", true);
+                       setTimeout("cbObj.successCallback()", 3000);
+               }
+       };              
+       try {
+               tizen.package.install(TEST_PKG_PATH_3, onInstallSuccessCB, undefined);
+       } catch (err) {
+               TestEngine.test("", false);
+       }
+       
+       TestEngine.log("[Package] UTC_package_install_P_003 END");
+ }
+
+function UTC_package_install_P_004()
+{
+       TestEngine.log("[Package] UTC_package_install_P_004 START");
+
+       var onInstallSuccessCB =
+       {
+               onprogress: function(pkg, progress) {
+               }
+       };      
+       
+       try {
+               tizen.package.install(TEST_PKG_PATH_1, onInstallSuccessCB);
+       } catch (err) {
+               TestEngine.test("[Package] UTC_package_install_P_004 error", false);
+       }
+       
+       TestEngine.test("[Package] UTC_package_install_P_004 error", true);
+       TestEngine.log("[Package] UTC_package_install_P_004 END");
+}
+
+function UTC_package_install_P_005()
+{
+       TestEngine.log("[Package] UTC_package_install_P_005 START");
+
+       var onInstallSuccessCB =
+       {
+               oncomplete: function(pkg, progress) {
+               }
+       };      
+       
+       try {
+               tizen.package.install(TEST_PKG_PATH_1, onInstallSuccessCB);
+       } catch (err) {
+               TestEngine.test("[Package] UTC_package_install_P_005 error", false);
+       }
+
+       TestEngine.test("[Package] UTC_package_install_P_005", true);
+       TestEngine.log("[Package] UTC_package_install_P_005 END");
+}
+
+
+function UTC_package_install_N_001()
+{
+       TestEngine.log("[Package] UTC_package_install_N_001 START");
+
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.package, "install", TEST_PKG_PATH_1, TEST_NUM,       null);
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.package, "install", TEST_PKG_PATH_1, TEST_STR,       null);
+       //TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.package, "install", TEST_PKG_PATH_1, TEST_OBJ,     null);
+
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.package, "install", TEST_PKG_PATH_1, onInstallSuccessCB, TEST_NUM);
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.package, "install", TEST_PKG_PATH_1, onInstallSuccessCB, TEST_STR);
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.package, "install", TEST_PKG_PATH_1, onInstallSuccessCB, TEST_OBJ);
+
+       TestEngine.log("[Package] UTC_package_install_N_001 END");
+}
+
+
+function UTC_package_install_N_002()
+{
+       TestEngine.log("[Package] UTC_package_install_N_002 START");
+       var cbObj = TestEngine.registerCallback("install", onSuccessCB, notFoundErrorCB);
+
+       var onInstallSuccessCB =
+       {
+               onprogress: function(pkg, progress) {
+                       TestEngine.log("on progress : " + pkg + " progress : " + progress);
+               },
+               oncomplete: function(pkg) {
+                       TestEngine.log("Completed : " + pkg);
+                       cbObj.successCallback();
+               }
+       };
+
+       function notFoundErrorCB(err)
+       {
+               if (err.name == NOT_FOUND_ERR) {
+                       TestEngine.test("[Package] cannot found", true);
+               } else {
+                       TestEngine.test("", false);
+               }
+       }
+
+       try {
+               tizen.package.install(TEST_ILLEGAL_PKG_PATH, onInstallSuccessCB, cbObj.errorCallback);
+       } catch (err) {
+               TestEngine.test("", false);
+       }
+       
+       TestEngine.log("[Package] UTC_package_install_N_002 END");
+}
+
+function UTC_package_install_N_003()
+{
+       TestEngine.log("[Package] UTC_package_install_N_003 START");
+       var cbObj = TestEngine.registerCallback("install", onSuccessCB, notFoundErrorCB);
+
+       var onInstallSuccessCB =
+       {
+               onprogress: function(pkg, progress) {
+                       TestEngine.log("on progress : " + pkg + " progress : " + progress);
+               },
+               oncomplete: function(pkg) {
+                       TestEngine.log("Completed : " + pkg);
+                       cbObj.successCallback();
+               }
+       };
+
+       function notFoundErrorCB(err)
+       {
+               if (err.name == NOT_FOUND_ERR) {
+                       TestEngine.test("[Package] cannot found", true);
+               } else {
+                       TestEngine.test("", false);
+               }
+       }
+
+       try {
+               tizen.package.install(undefined, onInstallSuccessCB, cbObj.errorCallback);
+       } catch (err) {
+               TestEngine.test("", false);
+       }
+       
+       TestEngine.log("[Package] UTC_package_install_N_003 END");
+}
+
+function UTC_package_install_N_004()
+{
+       TestEngine.log("[Package] UTC_package_install_N_004 START");
+       var cbObj = TestEngine.registerCallback("install", onSuccessCB, notFoundErrorCB);
+
+       var onInstallSuccessCB =
+       {
+               onprogress: function(pkg, progress) {
+                       TestEngine.log("on progress : " + pkg + " progress : " + progress);
+               },
+               oncomplete: function(pkg) {
+                       TestEngine.log("Completed : " + pkg);
+                       cbObj.successCallback();
+               }
+       };
+
+       function notFoundErrorCB(err)
+       {
+               if (err.name == NOT_FOUND_ERR) {
+                       TestEngine.test("[Package] cannot found", true);
+               } else {
+                       TestEngine.test("", false);
+               }
+       }
+
+       try {
+               tizen.package.install(null, onInstallSuccessCB, cbObj.errorCallback);
+       } catch (err) {
+               TestEngine.test("", false);
+       }
+       
+       TestEngine.log("[Package] UTC_package_install_N_004 END");
+}
+
+function UTC_package_install_N_005()
+{
+       TestEngine.log("[Package] UTC_package_install_N_005 START");
+       var cbObj = TestEngine.registerCallback("install", onSuccessCB, notFoundErrorCB);
+
+       var onInstallSuccessCB =
+       {
+               onprogress: function(pkg, progress) {
+                       TestEngine.log("on progress : " + pkg + " progress : " + progress);
+               },
+               oncomplete: function(pkg) {
+                       TestEngine.log("Completed : " + pkg);
+                       cbObj.successCallback();
+               }
+       };
+
+       function notFoundErrorCB(err)
+       {
+               if (err.name == NOT_FOUND_ERR) {
+                       TestEngine.test("[Package] cannot found", true);
+               } else {
+                       TestEngine.test("", false);
+               }
+       }
+
+       try {
+               tizen.package.install(TEST_OBJ, onInstallSuccessCB, cbObj.errorCallback);
+       } catch (err) {
+               TestEngine.test("", false);
+       }
+       
+       TestEngine.log("[Package] UTC_package_install_N_005 END");
+}
+
+function UTC_package_install_N_006()
+{
+       TestEngine.log("[Package] UTC_package_install_N_005 START");
+       var cbObj = TestEngine.registerCallback("install", onSuccessCB, notFoundErrorCB);
+
+       var onInstallSuccessCB =
+       {
+               onprogress: function(pkg, progress) {
+                       TestEngine.log("on progress : " + pkg + " progress : " + progress);
+               },
+               oncomplete: function(pkg) {
+                       TestEngine.log("Completed : " + pkg);
+                       cbObj.successCallback();
+               }
+       };
+
+       function notFoundErrorCB(err)
+       {
+               if (err.name == NOT_FOUND_ERR) {
+                       TestEngine.test("[Package] cannot found", true);
+               } else {
+                       TestEngine.test("", false);
+               }
+       }
+
+       try {
+               tizen.package.install(TEST_FUN, onInstallSuccessCB, cbObj.errorCallback);
+       } catch (err) {
+               TestEngine.test("", false);
+       }
+
+       TestEngine.log("[Package] UTC_package_install_N_006 END");
+}
+
+
+
+function UTC_package_uninstall_P_001()
+{
+       TestEngine.log("[Package] UTC_package_uninstall_P_001 START");
+       var cbObj = TestEngine.registerCallback("uninstall", onSuccessCB, onErrorCB);
+
+       var onInstallSuccessCB =
+       {
+               onprogress: function(pkg, progress) {
+                       TestEngine.log("on progress : " + pkg + " progress : " + progress);
+               },
+               oncomplete: function(pkg) {
+                       TestEngine.log("Completed : " + pkg);
+                       //TestEngine.test("[Package]", true);
+                       cbObj.successCallback();
+               }
+       };      
+       
+       try {
+               tizen.package.uninstall(TEST_PKG_ID_1, onInstallSuccessCB, null);
+       } catch (err) {
+               TestEngine.test("[Package] UTC_package_install_P_001 error", false);
+       }
+       TestEngine.log("[Package] UTC_package_uninstall_P_001 END");
+}
+
+function UTC_package_uninstall_P_002()
+{
+       TestEngine.log("[Package] UTC_package_uninstall_P_002 START");
+       var cbObj = TestEngine.registerCallback("uninstall", onSuccessCB, onErrorCB);
+
+       var onInstallSuccessCB =
+       {
+               onprogress: function(pkg, progress) {
+                       TestEngine.log("on progress : " + pkg + " progress : " + progress);
+               },
+               oncomplete: function(pkg) {
+                       TestEngine.log("Completed : " + pkg);
+                       //TestEngine.test("[Package]", true);
+                       cbObj.successCallback();
+               }
+       };      
+       
+       try {
+               tizen.package.uninstall(TEST_PKG_ID_2, onInstallSuccessCB, cbObj.errorCallback);
+       } catch (err) {
+               TestEngine.test("[Package] UTC_package_install_P_001 error", false);
+       }
+       TestEngine.log("[Package] UTC_package_uninstall_P_002 END");
+}
+
+function UTC_package_uninstall_P_003()
+{
+       TestEngine.log("[Package] UTC_package_uninstall_P_003 START");
+       var cbObj = TestEngine.registerCallback("uninstall", onSuccessCB, onErrorCB);
+
+       var onInstallSuccessCB =
+       {
+               onprogress: function(pkg, progress) {
+                       TestEngine.log("on progress : " + pkg + " progress : " + progress);
+               },
+               oncomplete: function(pkg) {
+                       TestEngine.log("Completed : " + pkg);
+                       //TestEngine.test("[Package]", true);
+                       cbObj.successCallback();
+               }
+       };      
+       
+       try {
+               tizen.package.uninstall(TEST_PKG_ID_3, onInstallSuccessCB, undefined);
+       } catch (err) {
+               TestEngine.test("[Package] UTC_package_install_P_001 error", false);
+       }
+       TestEngine.log("[Package] UTC_package_uninstall_P_003 END");
+ }
+
+function UTC_package_uninstall_P_004()
+{
+       TestEngine.log("[Package] UTC_package_uninstall_P_004 START");
+
+       var onInstallSuccessCB =
+       {
+               onprogress: function(pkg, progress) {
+               }
+       };      
+       
+       try {
+               tizen.package.uninstall(TEST_PKG_PATH_1, onInstallSuccessCB);
+       } catch (err) {
+               TestEngine.test("[Package] UTC_package_uninstall_P_004 error", false);
+       }
+       
+       TestEngine.test("[Package] UTC_package_uninstall_P_004 error", true);
+       TestEngine.log("[Package] UTC_package_uninstall_P_004 END");
+}
+
+function UTC_package_uninstall_P_005()
+{
+       TestEngine.log("[Package] UTC_package_uninstall_P_005 START");
+
+       var onInstallSuccessCB =
+       {
+               oncomplete: function(pkg, progress) {
+               }
+       };      
+       
+       try {
+               tizen.package.uninstall(TEST_PKG_PATH_1, onInstallSuccessCB);
+       } catch (err) {
+               TestEngine.test("[Package] UTC_package_uninstall_P_005 error", false);
+       }
+       
+       TestEngine.test("[Package] UTC_package_uninstall_P_005 error", true);
+       TestEngine.log("[Package] UTC_package_uninstall_P_005 END");
+}
+
+function UTC_package_uninstall_N_001()
+{
+       TestEngine.log("[Package] UTC_package_uninstall_N_001 START");
+
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.package, "uninstall", TEST_PKG_ID_1, TEST_NUM,       null);
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.package, "uninstall", TEST_PKG_ID_1, TEST_STR,       null);
+       //TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.package, "uninstall", TEST_PKG_ID_1, TEST_OBJ,     null);
+
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.package, "uninstall", TEST_PKG_ID_1, onInstallSuccessCB, TEST_NUM);
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.package, "uninstall", TEST_PKG_ID_1, onInstallSuccessCB, TEST_STR);
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.package, "uninstall", TEST_PKG_ID_1, onInstallSuccessCB, TEST_OBJ);
+
+       TestEngine.log("[Package] UTC_package_uninstall_N_001 END");
+}
+
+
+function UTC_package_uninstall_N_002()
+{
+       TestEngine.log("[Package] UTC_package_uninstall_N_002 START");
+       var cbObj = TestEngine.registerCallback("uninstall", onSuccessCB, notFoundErrorCB);
+
+       var onInstallSuccessCB =
+       {
+               onprogress: function(pkg, progress) {
+                       TestEngine.log("on progress : " + pkg + " progress : " + progress);
+               },
+               oncomplete: function(pkg) {
+                       TestEngine.log("Completed : " + pkg);
+                       cbObj.successCallback();
+               }
+       };
+
+       function notFoundErrorCB(err)
+       {
+               if (err.name == NOT_FOUND_ERR) {
+                       TestEngine.test("[Package] cannot found", true);
+               } else {
+                       TestEngine.test("", false);
+               }
+       }
+
+       try {
+               tizen.package.uninstall(TEST_ILLEGAL_ID, onInstallSuccessCB, cbObj.errorCallback);
+       } catch (err) {
+               TestEngine.test("", false);
+       }
+       
+       TestEngine.log("[Package] UTC_package_uninstall_N_002 END");
+}
+
+function UTC_package_uninstall_N_003()
+{
+       TestEngine.log("[Package] UTC_package_uninstall_N_003 START");
+       var cbObj = TestEngine.registerCallback("uninstall", onSuccessCB, notFoundErrorCB);
+
+       var onInstallSuccessCB =
+       {
+               onprogress: function(pkg, progress) {
+                       TestEngine.log("on progress : " + pkg + " progress : " + progress);
+               },
+               oncomplete: function(pkg) {
+                       TestEngine.log("Completed : " + pkg);
+                       cbObj.successCallback();
+               }
+       };
+
+       function notFoundErrorCB(err)
+       {
+               if (err.name == NOT_FOUND_ERR) {
+                       TestEngine.test("[Package] cannot found", true);
+               } else {
+                       TestEngine.test("", false);
+               }
+       }
+
+       try {
+               tizen.package.uninstall(undefined, onInstallSuccessCB, cbObj.errorCallback);
+       } catch (err) {
+               TestEngine.test("", false);
+       }
+       
+       TestEngine.log("[Package] UTC_package_uninstall_N_003 END");
+}
+
+function UTC_package_uninstall_N_004()
+{
+       TestEngine.log("[Package] UTC_package_uninstall_N_004 START");
+       var cbObj = TestEngine.registerCallback("uninstall", onSuccessCB, notFoundErrorCB);
+
+       var onInstallSuccessCB =
+       {
+               onprogress: function(pkg, progress) {
+                       TestEngine.log("on progress : " + pkg + " progress : " + progress);
+               },
+               oncomplete: function(pkg) {
+                       TestEngine.log("Completed : " + pkg);
+                       cbObj.successCallback();
+               }
+       };
+
+       function notFoundErrorCB(err)
+       {
+               if (err.name == NOT_FOUND_ERR) {
+                       TestEngine.test("[Package] cannot found", true);
+               } else {
+                       TestEngine.test("", false);
+               }
+       }
+
+       try {
+               tizen.package.uninstall(null, onInstallSuccessCB, cbObj.errorCallback);
+       } catch (err) {
+               TestEngine.test("", false);
+       }
+       
+       TestEngine.log("[Package] UTC_package_uninstall_N_004 END");
+}
+
+function UTC_package_uninstall_N_005()
+{
+       TestEngine.log("[Package] UTC_package_uninstall_N_005 START");
+       var cbObj = TestEngine.registerCallback("uninstall", onSuccessCB, notFoundErrorCB);
+
+       var onInstallSuccessCB =
+       {
+               onprogress: function(pkg, progress) {
+                       TestEngine.log("on progress : " + pkg + " progress : " + progress);
+               },
+               oncomplete: function(pkg) {
+                       TestEngine.log("Completed : " + pkg);
+                       cbObj.successCallback();
+               }
+       };
+
+       function notFoundErrorCB(err)
+       {
+               if (err.name == NOT_FOUND_ERR) {
+                       TestEngine.test("[Package] cannot found", true);
+               } else {
+                       TestEngine.test("", false);
+               }
+       }
+
+       try {
+               tizen.package.uninstall(TEST_OBJ, onInstallSuccessCB, cbObj.errorCallback);
+       } catch (err) {
+               TestEngine.test("", false);
+       }
+       
+       TestEngine.log("[Package] UTC_package_uninstall_N_005 END");
+}
+
+function UTC_package_uninstall_N_006()
+{
+       TestEngine.log("[Package] UTC_package_uninstall_N_005 START");
+       var cbObj = TestEngine.registerCallback("uninstall", onSuccessCB, notFoundErrorCB);
+
+       var onInstallSuccessCB =
+       {
+               onprogress: function(pkg, progress) {
+                       TestEngine.log("on progress : " + pkg + " progress : " + progress);
+               },
+               oncomplete: function(pkg) {
+                       TestEngine.log("Completed : " + pkg);
+                       cbObj.successCallback();
+               }
+       };
+
+       function notFoundErrorCB(err)
+       {
+               if (err.name == NOT_FOUND_ERR) {
+                       TestEngine.test("[Package] cannot found", true);
+               } else {
+                       TestEngine.test("", false);
+               }
+       }
+
+       try {
+               tizen.package.uninstall(TEST_FUN, onInstallSuccessCB, cbObj.errorCallback);
+       } catch (err) {
+               TestEngine.test("", false);
+       }
+       
+       TestEngine.log("[Package] UTC_package_uninstall_N_006 END");
+}
+
+function infolist(infos)
+{
+       TestEngine.log("[infolist][START]");
+
+       try {
+               TestEngine.log("PackageInfo Array Length = " + infos.length);
+/*
+               for(var num=0; num < infos.length; num++)
+               {
+                       TestEngine.log("PackageInfo["+num+"].name = "+infos[num].name);
+                       TestEngine.log("PackageInfo["+num+"].id = "+infos[num].id);
+               }
+*/             
+       } catch (ex) {
+               TestEngine.test("[Package] UTC_package_getAppsInfo error: " + ex, false);
+       }
+       TestEngine.test("UTC_package_getPackagesInfo", true);
+       TestEngine.log("[infolist][END]");
+}
+
+function UTC_package_getPackagesInfo_P_001()
+{
+       TestEngine.log("[Package] UTC_package_getPackagesInfo_P_001 START");
+
+       try {
+               var cbObj = TestEngine.registerCallback("getPackagesInfo", infolist, onErrorCB);
+               tizen.package.getPackagesInfo(cbObj.successCallback, cbObj.errorCallback);
+       } catch(err) {
+               TestEngine.test("[Package] UTC_package_getPackagesInfo_P_001 err : " + err, false);
+       }
+
+       TestEngine.log("[Package] UTC_package_getPackagesInfo_P_001 END");
+}
+
+function UTC_package_getPackagesInfo_P_002()
+{
+       TestEngine.log("[Package] UTC_package_getPackagesInfo_P_002 START");
+
+       try {
+               var cbObj = TestEngine.registerCallback("getPackagesInfo", infolist, onErrorCB);
+               tizen.package.getPackagesInfo(cbObj.successCallback);
+       } catch(err) {
+               TestEngine.test("[Package] UTC_package_getPackagesInfo_P_002 err : " + err, false);
+       }
+
+       TestEngine.log("[Package] UTC_package_getPackagesInfo_P_002 END");
+}
+
+function UTC_package_getPackagesInfo_P_003()
+{
+       TestEngine.log("[Package] UTC_package_getPackagesInfo_P_003 START");
+
+       try {
+               var cbObj = TestEngine.registerCallback("getPackagesInfo", infolist, onErrorCB);
+               tizen.package.getPackagesInfo(cbObj.successCallback, null);
+       } catch(err) {
+               TestEngine.test("[Package] UTC_package_getPackagesInfo_P_003 err : " + err, false);
+       }
+
+       TestEngine.log("[Package] UTC_package_getPackagesInfo_P_003 END");
+}
+
+function UTC_package_getPackagesInfo_N_001()
+{
+       TestEngine.log("[Package] UTC_package_getPackagesInfo_N_001 START");
+
+       try {
+               // first parameter
+               TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.package, "getPackagesInfo", null,            onErrorCB);
+               TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.package, "getPackagesInfo", undefined,       onErrorCB);
+               TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.package, "getPackagesInfo", TEST_STR,        onErrorCB);
+               TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.package, "getPackagesInfo", TEST_NUM,        onErrorCB);
+               TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.package, "getPackagesInfo", TEST_OBJ,        onErrorCB);
+       
+               // second parameter
+               TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.package, "getPackagesInfo", infolist, TEST_STR);
+               TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.package, "getPackagesInfo", infolist, TEST_NUM);
+               TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.package, "getPackagesInfo", infolist, TEST_OBJ);
+       } catch (err) {
+               TestEngine.test("[Package] UTC_package_getPackagesInfo_N_001 err : " + err, false);
+       }
+       TestEngine.log("[Package] UTC_package_getPackagesInfo_N_001 END");
+}
+
+function UTC_package_getPackageInfo_P_001()
+{
+       TestEngine.log("[Package] UTC_package_getPackageInfo_P_001 START");
+
+       try {
+               var info = tizen.package.getPackageInfo(CURR_PKG_ID);
+               //TestEngine.log("PackageInfo.name = "+info.name);
+               //TestEngine.log("PackageInfo.id = "+info.id);
+               if (info.id != CURR_PKG_ID) {
+                       TestEngine.test("[Package] UTC_package_getPackageInfo_P_001 err : current context is not same", false);
+               }
+       } catch(err) {
+               TestEngine.test("[Package] UTC_package_getPackageInfo_P_001 err : " + err, false);
+       }
+       TestEngine.test("[Package] UTC_package_getPackageInfo_P_001", true);
+
+       TestEngine.log("[Package] UTC_package_getPackageInfo_P_001 END");
+}
+
+function UTC_package_getPackageInfo_P_002()
+{
+       TestEngine.log("[Package] UTC_package_getPackageInfo_P_002 START");
+
+       try {
+               var info = tizen.package.getPackageInfo(null);
+               //TestEngine.log("PackageInfo.name = "+info.name);
+               //TestEngine.log("PackageInfo.id = "+info.id);
+               if (info.id != CURR_PKG_ID) {
+                       TestEngine.test("[Package] UTC_package_getPackageInfo_P_002 err : current context is not same", false);
+               }
+       } catch(err) {
+               TestEngine.test("[Package] UTC_package_getPackageInfo_P_002 err : " + err, false);
+       }
+       TestEngine.test("[Package] UTC_package_getPackageInfo_P_002", true);
+
+       TestEngine.log("[Package] UTC_package_getPackageInfo_P_002 END");
+}
+
+function UTC_package_getPackageInfo_P_003()
+{
+       TestEngine.log("[Package] UTC_package_getPackageInfo_P_002 START");
+
+       try {
+               var info = tizen.package.getPackageInfo();
+               //TestEngine.log("PackageInfo.name = "+info.name);
+               //TestEngine.log("PackageInfo.id = "+info.id);
+               if (info.id != CURR_PKG_ID) {
+                       TestEngine.test("[Package] UTC_package_getPackageInfo_P_002 err : current context is not same", false);
+               }
+       } catch(err) {
+               TestEngine.test("[Package] UTC_package_getPackageInfo_P_002 err : " + err, false);
+       }
+       TestEngine.test("[Package] UTC_package_getPackageInfo_P_002", true);
+
+       TestEngine.log("[Package] UTC_package_getPackageInfo_P_002 END");
+}
+
+function UTC_package_getPackageInfo_N_001()
+{
+       TestEngine.log("[Package] UTC_package_getPackageInfo_N_001 START");
+
+       TestEngine.catchErrorType("name", NOT_FOUND_ERR, tizen.package, "getPackageInfo", TEST_ILLEGAL_ID);
+       TestEngine.catchErrorType("name", NOT_FOUND_ERR, tizen.package, "getPackageInfo", TEST_OBJ);
+       TestEngine.catchErrorType("name", NOT_FOUND_ERR, tizen.package, "getPackageInfo", TEST_FUN);
+       TestEngine.catchErrorType("name", NOT_FOUND_ERR, tizen.package, "getPackageInfo", TEST_NUM);
+
+       TestEngine.log("[Package] UTC_package_getPackageInfo_N_001 END");
+}
+
+
+function printPackageInformation(pkginfo) {
+       TestEngine.log("[printPackageInformation][START]");
+
+       try {
+               TestEngine.log("pkginfo.name = "+pkginfo.name);
+               TestEngine.log("pkginfo.appId = "+pkginfo.appId);
+               TestEngine.log("pkginfo.iconPath = "+pkginfo.iconPath);
+               TestEngine.log("pkginfo.version = "+pkginfo.version);
+       } catch (ex){
+               onErrorCB(ex);
+       }
+
+       TestEngine.log("[printPackageInformation][END]");
+}
+
+var onInstallSuccessCB_2 =
+{
+       onprogress: function(pkg, progress) {
+               TestEngine.log("on progress : " + pkg + " progress : " + progress);
+       },
+       oncomplete: function(pkg) {
+               TestEngine.log("Completed : " + pkg);
+       }
+};
+
+
+function UTC_package_setPackageInfoEventListener_P_001()
+{
+       TestEngine.log("[Package] UTC_package_setPackageInfoEventListener_P_001 START");
+
+       var onPackageInfoEventCB = {
+               oninstalled : function(pkginfo) {},
+               onupdated : function(pkginfo) {},
+               onuninstalled : function(pkgid) {}
+       };
+
+       try {
+               tizen.package.setPackageInfoEventListener(onPackageInfoEventCB);
+       } catch(err) {
+               TestEngine.test("[Package] UTC_package_setPackageInfoEventListener_P_001 err : " + err, false);
+       }
+       TestEngine.test("[Package] UTC_package_setPackageInfoEventListener_P_001", true);
+
+       TestEngine.log("[Package] UTC_package_setPackageInfoEventListener_P_001 END");
+}
+
+function UTC_package_setPackageInfoEventListener_P_002()
+{
+       TestEngine.log("[Package] UTC_package_setPackageInfoEventListener_P_002 START");
+       var cbObj = TestEngine.registerCallback("setPackageInfoEventListener", onSuccessCB, onErrorCB);
+       
+       var onPackageInfoEventCB = {
+               oninstalled : function(pkginfo) {
+                       TestEngine.log("[onInstalled][START]");
+                       try {
+                               printPackageInformation(pkginfo);
+                               cbObj.successCallback();
+                               //TestEngine.test("[Package] UTC_package_setPackageInfoEventListener_P_002", true);
+                       } catch (ex) {
+                               onErrorCB(ex);
+                       }
+                       TestEngine.log("[onInstalled][END]");
+               },
+               onupdated : function(pkginfo) {
+                       TestEngine.log("[onupdated][START]");
+                       cbObj.errorCallback();
+                       //TestEngine.test("[Package] UTC_package_setPackageInfoEventListener_P_002", false);
+               },
+               onuninstalled : function(pkgid) {
+                       TestEngine.log("[onuninstalled][START]");
+                       cbObj.errorCallback();
+                       //TestEngine.test("[Package] UTC_package_setPackageInfoEventListener_P_002", false);
+               }
+       };
+
+       try {
+               tizen.package.setPackageInfoEventListener(onPackageInfoEventCB);
+               tizen.package.install(TEST_PKG_PATH_1, onInstallSuccessCB_2);
+
+       } catch(err) {
+               TestEngine.test("[Package] UTC_package_setPackageInfoEventListener_P_002 err : " + err, false);
+       }
+       TestEngine.log("[Package] UTC_package_setPackageInfoEventListener_P_002 END");
+}
+
+function UTC_package_setPackageInfoEventListener_P_003()
+{
+       TestEngine.log("[Package] UTC_package_setPackageInfoEventListener_P_003 START");
+       var cbObj = TestEngine.registerCallback("setPackageInfoEventListener", onSuccessCB, onErrorCB);
+       
+       var onPackageInfoEventCB = {
+               oninstalled : function(pkginfo) {
+                       TestEngine.log("[oninstalled][START]");
+                       cbObj.errorCallback();
+                       //TestEngine.test("[Package] UTC_package_setPackageInfoEventListener_P_003", false);
+               },
+               onupdated : function(pkginfo) {
+                       TestEngine.log("[onupdated][START]");
+                       cbObj.errorCallback();
+                       //TestEngine.test("[Package] UTC_package_setPackageInfoEventListener_P_003", false);
+               },
+               onuninstalled : function(pkgid) {
+                       TestEngine.log("[onuninstalled][START]");
+                       try {
+                               TestEngine.log("[onuninstalled] pkgid : " + pkgid);
+                               //TestEngine.test("[Package] UTC_package_setPackageInfoEventListener_P_003", true);
+                               cbObj.successCallback();
+                       } catch (ex) {
+                               onErrorCB(ex);
+                       }
+                       TestEngine.log("[onuninstalled][END]");         
+               }
+       };
+
+       try {
+               tizen.package.setPackageInfoEventListener(onPackageInfoEventCB);
+               tizen.package.uninstall("PkgTest001", onInstallSuccessCB_2);
+
+       } catch(err) {
+               TestEngine.test("[Package] UTC_package_setPackageInfoEventListener_P_003 err : " + err, false);
+       }
+       TestEngine.log("[Package] UTC_package_setPackageInfoEventListener_P_003 END");
+}
+
+
+function UTC_package_setPackageInfoEventListener_P_004()
+{
+       TestEngine.log("[Package] UTC_package_setPackageInfoEventListener_P_004 START");
+
+       var onPackageInfoEventCB = {
+               oninstalled : function(pkginfo) {}
+       };
+
+       try {
+               tizen.package.setPackageInfoEventListener(onPackageInfoEventCB);
+       } catch(err) {
+               TestEngine.test("[Package] UTC_package_setPackageInfoEventListener_P_004 err : " + err, false);
+       }
+       TestEngine.test("[Package] UTC_package_setPackageInfoEventListener_P_004", true);
+
+       TestEngine.log("[Package] UTC_package_setPackageInfoEventListener_P_004 END");
+}
+
+function UTC_package_setPackageInfoEventListener_P_005()
+{
+       TestEngine.log("[Package] UTC_package_setPackageInfoEventListener_P_005 START");
+
+       var onPackageInfoEventCB = {
+               onupdated : function(pkginfo) {}
+       };
+
+       try {
+               tizen.package.setPackageInfoEventListener(onPackageInfoEventCB);
+       } catch(err) {
+               TestEngine.test("[Package] UTC_package_setPackageInfoEventListener_P_005 err : " + err, false);
+       }
+       TestEngine.test("[Package] UTC_package_setPackageInfoEventListener_P_005", true);
+
+       TestEngine.log("[Package] UTC_package_setPackageInfoEventListener_P_005 END");
+}
+
+function UTC_package_setPackageInfoEventListener_P_006()
+{
+       TestEngine.log("[Package] UTC_package_setPackageInfoEventListener_P_006 START");
+
+       var onPackageInfoEventCB = {
+               onuninstalled : function(pkgid) {}
+       };
+
+       try {
+               tizen.package.setPackageInfoEventListener(onPackageInfoEventCB);
+       } catch(err) {
+               TestEngine.test("[Package] UTC_package_setPackageInfoEventListener_P_006 err : " + err, false);
+       }
+       TestEngine.test("[Package] UTC_package_setPackageInfoEventListener_P_006", true);
+
+       TestEngine.log("[Package] UTC_package_setPackageInfoEventListener_P_006 END");
+}
+
+function UTC_package_setPackageInfoEventListener_N_001()
+{
+       TestEngine.log("[Package] UTC_package_setPackageInfoEventListener_N_001 START");
+
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.package, "setPackageInfoEventListener", null);
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.package, "setPackageInfoEventListener", undefined);
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.package, "setPackageInfoEventListener", TEST_STR);
+       TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.package, "setPackageInfoEventListener", TEST_NUM);
+       //TestEngine.catchErrorType("name", TYPE_MISMATCH_ERR, tizen.package, "setPackageInfoEventListener", TEST_OBJ);
+
+       TestEngine.log("[Package] UTC_package_setPackageInfoEventListener_N_001 END");
+}
+
+// NO unsetPackageInfoEventListener test.
+
+function UTC_package_unsetPackageInfoEventListener_P_001()
+{
+       TestEngine.log("[Package] UTC_package_unsetPackageInfoEventListener_P_001 START");
+
+       var onPackageInfoEventCB = {
+               oninstalled : function(pkginfo) {},
+               onupdated : function(pkginfo) {},
+               onuninstalled : function(pkgid) {}
+       };
+
+       try {
+               tizen.package.setPackageInfoEventListener(onPackageInfoEventCB);
+               tizen.package.unsetPackageInfoEventListener();
+
+       } catch(err) {
+               TestEngine.test("[Package] UTC_package_unsetPackageInfoEventListener_P_001 err : " + err, false);
+       }
+       TestEngine.test("[Package] UTC_package_unsetPackageInfoEventListener_P_001", true);
+
+       TestEngine.log("[Package] UTC_package_unsetPackageInfoEventListener_P_001 END");
+}
+
+function UTC_package_field_PackageInformation_N_001()
+{
+       TestEngine.log("[Package] UTC_package_field_PackageInformation_N_001 START");
+
+       var info = tizen.package.getPackageInfo();
+
+       printPackageInformation(info);
+
+       var id = info.id;
+       var name = info.name;
+       var iconPath = info.iconPath;
+       var version = info.version;
+
+       try {
+               info.id = "test";
+               info.name = "UTC_package_N_00ame";
+               info.iconPath = "/tmp";
+               info.version = "12345";
+       } catch(err) {
+               TestEngine.test("[Package] UTC_package_field_PackageInformation_N_001 error : " + err, false);
+       }
+
+       if ((info.id != id) || (info.name != name) || (info.version != version) || (info.iconPath != iconPath)) {
+               TestEngine.test("[Package] UTC_package_field_PackageInformation_N_001 the value is changed!", false);
+       }
+
+       TestEngine.test("[Package] UTC_package_field_PackageInformation_N_001 success", true);
+       TestEngine.log("[Package] UTC_package_field_PackageInformation_N_001 END");
+}
+
diff --git a/webWidgetTCT_device/test/utc/tests/TestSysteminfo.js b/webWidgetTCT_device/test/utc/tests/TestSysteminfo.js
new file mode 100755 (executable)
index 0000000..8174f53
--- /dev/null
@@ -0,0 +1,1074 @@
+/*
+ * 
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ * PROPRIETARY/CONFIDENTIAL
+ * 
+ * This software is the confidential and proprietary information of SAMSUNG 
+ * ELECTRONICS ("Confidential Information"). You agree and acknowledge that 
+ * this software is owned by Samsung and you shall not disclose such 
+ * Confidential Information and shall use it only in accordance with the terms 
+ * of the license agreement you entered into with SAMSUNG ELECTRONICS. SAMSUNG 
+ * make no representations or warranties about the suitability of the software, 
+ * either express or implied, including but not limited to the implied 
+ * warranties of merchantability, fitness for a particular purpose, or 
+ * non-infringement. SAMSUNG shall not be liable for any damages suffered by 
+ * licensee arising out of or related to this software.
+ * 
+ */
+
+var SysteminfoObj = tizen.systeminfo;
+
+var TYPE_MISMATCH_ERR = "TypeMismatchError";
+var INVALID_VALUES_ERR = "InvalidValuesError";
+var NOT_FOUND_ERR = "NotFoundError";
+var UNKNOWN_ERR = "UnknownError";
+var NOT_SUPPORTED_ERR = "NotSupportedError";
+var PERMISSION_DENIED_ERR = "SecurityError";
+
+function UTC_systeminfo_presence_P_001()
+{
+    TestEngine.test("Checking tizen object", tizen);
+    TestEngine.test("Checking Systeminfo object", SysteminfoObj);
+    TestEngine.test("Checking type of isSupported", isFunction(SysteminfoObj.getCapabilities));
+    TestEngine.test("Checking type of getPropertyValue", isFunction(SysteminfoObj.getPropertyValue));
+    TestEngine.test("Checking type of addPropertyValueChangeListener", isFunction(SysteminfoObj.addPropertyValueChangeListener));
+    TestEngine.test("Checking type of removePropertyValueChangeListener", isFunction(SysteminfoObj.removePropertyValueChangeListener));
+}
+
+function systeminfoErrorCallback(err) {
+       TestEngine.test("ErrCB : err.name [" + err.name + "] err.msg[" + err.message + "]", false);
+}
+
+function systeminfoBatterySuccessCallback(battery) {
+       TestEngine.test("level attribute ", isNumber(battery.level));
+       TestEngine.test("isCharging attribute ", isBoolean(battery.isCharging));
+}
+
+function systeminfoCpuSuccessCallback(cpu) {
+       TestEngine.test("load attribute ", isNumber(cpu.load));
+}
+
+function systeminfoStorageSuccessCallback(storage) {
+       TestEngine.test("type attribute ", isString(storage.units[0].type));
+       TestEngine.test("capacity attribute ", isNumber(storage.units[0].capacity));
+       TestEngine.test("availableCapacity attribute ", isNumber(storage.units[0].availableCapacity));
+       TestEngine.test("isRemoveable attribute ", isBoolean(storage.units[0].isRemoveable));
+}
+
+function systeminfoDisplaySuccessCallback(display) {
+       TestEngine.test("resolutionWidth ", isNumber(display.resolutionWidth));
+       TestEngine.test("resolutionHeight ", isNumber(display.resolutionHeight));
+       TestEngine.test("dotsPerInchWidth ", isNumber(display.dotsPerInchWidth));
+       TestEngine.test("dotsPerInchHeight ", isNumber(display.dotsPerInchHeight));
+       TestEngine.test("physicalWidth ", isNumber(display.physicalWidth));
+       TestEngine.test("physicalHeight ", isNumber(display.physicalHeight));
+       TestEngine.test("brightness ", isNumber(display.brightness));
+}
+
+function systeminfoDeviceOrientationSuccessCallback(deviceorientation) {
+       TestEngine.test("status ", isString(deviceorientation.status));
+}
+
+function systeminfoWifiNetworkSuccessCallback(wifinetwork) {
+       TestEngine.test("status ", isString(wifinetwork.status));
+       TestEngine.test("ipAddress ", isString(wifinetwork.ipAddress));
+       TestEngine.test("ipv6Address ", isString(wifinetwork.ipv6Address));     
+       TestEngine.test("ssid ", isString(wifinetwork.ssid));
+       TestEngine.test("signalStrength ", isNumber(wifinetwork.signalStrength));
+}
+
+function systeminfoCellularNetworkSuccessCallback(cellularnetwork) {
+       TestEngine.test("status ", isString(cellularnetwork.status));
+       TestEngine.test("ipAddress ", isString(cellularnetwork.ipAddress));
+       TestEngine.test("ipv6Address ", isString(cellularnetwork.ipv6Address)); 
+       TestEngine.test("apn ", isString(cellularnetwork.apn));
+       TestEngine.test("mcc ", isNumber(cellularnetwork.mcc));
+       TestEngine.test("mnc ", isNumber(cellularnetwork.mnc));
+       TestEngine.test("lac ", isNumber(cellularnetwork.lac));
+       TestEngine.test("cellId ", isNumber(cellularnetwork.cellId));
+       TestEngine.test("isRoaming ", isBoolean(cellularnetwork.isRoaming));
+       TestEngine.test("isFlightMode ", isBoolean(cellularnetwork.isFlightMode));
+       TestEngine.test("imei ", isString(cellularnetwork.imei));
+}
+
+function systeminfoNetworkSuccessCallback(network) {
+       TestEngine.test("networkType ", isString(network.networkType));
+}
+
+function systeminfoSIMSuccessCallback(sim) {
+       TestEngine.test("operatorName ", isString(sim.operatorName));
+       TestEngine.test("msisdn ", isString(sim.msisdn));
+       TestEngine.test("iccid ", isString(sim.iccid));
+       TestEngine.test("mcc ", isNumber(sim.mcc));
+       TestEngine.test("mnc ", isNumber(sim.mnc));
+       TestEngine.test("msin ", isString(sim.msin));
+       TestEngine.test("spn ", isString(sim.spn));     
+}
+
+function systeminfoBuildSuccessCallback(build) {
+       TestEngine.test("model ", isString(build.model));
+       TestEngine.test("manufacturer ", isString(build.manufacturer));
+}
+
+function systeminfoLocaleSuccessCallback(locale) {
+       TestEngine.test("language ", isString(locale.country));
+       TestEngine.test("country ", isString(locale.country));
+}
+
+function systeminfoPeripheralSuccessCallback(peripheral) {
+       TestEngine.test("isVideoOutputOn ", isBoolean(peripheral.isVideoOutputOn));
+}
+
+function systeminfoInvalidSuccessCallback(value) {
+       TestEngine.logErr("Invaild test is failed");
+}
+
+function systeminfoInvalidValueErrorCallback(err) {
+       TestEngine.assertEqual("Exception check", INVALID_VALUES_ERR, err.name);
+}
+
+function systeminfoInvalidErrorCallback(err) {
+       TestEngine.logErr("Invaild test is failed");
+}
+
+//==============================================================================================================================================
+function UTC_systeminfo_getCapabilities_P_001()
+{
+       try {
+               var deviceCapability = SysteminfoObj.getCapabilities();
+               TestEngine.test("bluetooth ", isBoolean(deviceCapability.bluetooth));
+               TestEngine.test("nfc ", isBoolean(deviceCapability.nfc));
+               TestEngine.test("multiTouchCount ", isNumber(deviceCapability.multiTouchCount));
+               TestEngine.test("inputKeyboard ", isBoolean(deviceCapability.inputKeyboard));
+               TestEngine.test("wifi ", isBoolean(deviceCapability.wifi));
+               TestEngine.test("wifiDirect ", isBoolean(deviceCapability.wifiDirect));
+               TestEngine.test("openglesVersion1_1 ", isBoolean(deviceCapability.openglesVersion1_1));
+               TestEngine.test("openglesVersion2_0 ", isBoolean(deviceCapability.openglesVersion2_0));
+               TestEngine.test("fmRadio ", isBoolean(deviceCapability.fmRadio));
+       } catch(err) {
+               TestEngine.test("Exception : getPropertyValueTest() err.name [" + err.name + "] err.msg[" + err.message + "]", false);
+       }
+}
+
+function UTC_systeminfo_getCapabilities_P_002()
+{
+       try {
+               var deviceCapability = SysteminfoObj.getCapabilities();
+               TestEngine.test("platformVersion ", isString(deviceCapability.platformVersion));
+               TestEngine.test("platformName ", isString(deviceCapability.platformName));
+               //This capability is not supported in wearables
+               //TestEngine.test("nativeApiVersion ", isString(deviceCapability.nativeApiVersion));
+       } catch(err) {
+               TestEngine.test("Exception : getPropertyValueTest() err.name [" + err.name + "] err.msg[" + err.message + "]", false);
+       }
+}
+
+function UTC_systeminfo_getCapabilities_P_003()
+{
+       try {
+               var deviceCapability = SysteminfoObj.getCapabilities();
+               TestEngine.test("cameraFrontFlash ", isBoolean(deviceCapability.cameraFrontFlash));
+               TestEngine.test("cameraBack ", isBoolean(deviceCapability.cameraBack));
+               TestEngine.test("cameraBackFlash ", isBoolean(deviceCapability.cameraBackFlash));
+               TestEngine.test("location ", isBoolean(deviceCapability.location));
+               TestEngine.test("locationGps ", isBoolean(deviceCapability.locationGps));
+               TestEngine.test("locationWps ", isBoolean(deviceCapability.locationWps));
+               TestEngine.test("microphone ", isBoolean(deviceCapability.microphone));
+               TestEngine.test("usbHost ", isBoolean(deviceCapability.usbHost));
+               TestEngine.test("usbAccessory ", isBoolean(deviceCapability.usbAccessory));
+               TestEngine.test("screenOutputRca ", isBoolean(deviceCapability.screenOutputRca));
+               TestEngine.test("screenOutputHdmi ", isBoolean(deviceCapability.screenOutputHdmi));
+               TestEngine.test("platformCoreCpuArch ", isString(deviceCapability.platformCoreCpuArch));
+               TestEngine.test("platformCoreFpuArch ", isString(deviceCapability.platformCoreFpuArch));
+               TestEngine.test("sipVoip ", isBoolean(deviceCapability.sipVoip));
+               //This capability is not supported in wearables
+               //TestEngine.test("duid ", isString(deviceCapability.duid));
+               TestEngine.test("speechRecognition ", isBoolean(deviceCapability.speechRecognition));
+               TestEngine.test("accelerometer ", isBoolean(deviceCapability.accelerometer));
+               TestEngine.test("barometer ", isBoolean(deviceCapability.barometer));
+               TestEngine.test("gyroscope ", isBoolean(deviceCapability.gyroscope));
+               TestEngine.test("magnetometer ", isBoolean(deviceCapability.magnetometer));
+               TestEngine.test("proximity ", isBoolean(deviceCapability.proximity));           
+       } catch(err) {
+               TestEngine.test("Exception : getPropertyValueTest() err.name [" + err.name + "] err.msg[" + err.message + "]", false);
+       }
+}
+
+function UTC_systeminfo_getPropertyValue_P_001()
+{
+       var cb = TestEngine.registerCallback("getPropertyValue", systeminfoBatterySuccessCallback, systeminfoErrorCallback);
+       try {
+               SysteminfoObj.getPropertyValue("BATTERY", cb.successCallback, cb.errorCallback); 
+       } catch(err) {
+               TestEngine.test("Exception : getPropertyValueTest() err.name [" + err.name + "] err.msg[" + err.message + "]", false);
+       }
+}
+
+function UTC_systeminfo_getPropertyValue_P_002()
+{
+       var cb = TestEngine.registerCallback("getPropertyValue", systeminfoCpuSuccessCallback, systeminfoErrorCallback);
+       try {
+               SysteminfoObj.getPropertyValue("CPU", cb.successCallback, cb.errorCallback); 
+       } catch(err) {
+               TestEngine.test("Exception : getPropertyValueTest() err.name [" + err.name + "] err.msg[" + err.message + "]", false);
+       }
+}
+
+function UTC_systeminfo_getPropertyValue_P_003()
+{
+       var cb = TestEngine.registerCallback("getPropertyValue", systeminfoStorageSuccessCallback, systeminfoErrorCallback);
+       try {
+               SysteminfoObj.getPropertyValue("STORAGE", cb.successCallback, cb.errorCallback); 
+       } catch(err) {
+               TestEngine.test("Exception : getPropertyValueTest() err.name [" + err.name + "] err.msg[" + err.message + "]", false);
+       }
+}
+
+function UTC_systeminfo_getPropertyValue_P_004()
+{
+       var cb = TestEngine.registerCallback("getPropertyValue", systeminfoDisplaySuccessCallback, systeminfoErrorCallback);
+       try {
+               SysteminfoObj.getPropertyValue("DISPLAY", cb.successCallback, cb.errorCallback); 
+       } catch(err) {
+               TestEngine.test("Exception : getPropertyValueTest() err.name [" + err.name + "] err.msg[" + err.message + "]", false);
+       }
+}
+
+function UTC_systeminfo_getPropertyValue_P_005()
+{
+       var cb = TestEngine.registerCallback("getPropertyValue", systeminfoDeviceOrientationSuccessCallback, null);
+       try {
+               SysteminfoObj.getPropertyValue("DEVICE_ORIENTATION", cb.successCallback, cb.errorCallback); 
+       } catch(err) {
+               TestEngine.test("Exception : getPropertyValueTest() err.name [" + err.name + "] err.msg[" + err.message + "]", false);
+       }
+}
+
+function UTC_systeminfo_getPropertyValue_P_006()
+{
+       var cb = TestEngine.registerCallback("getPropertyValue", systeminfoWifiNetworkSuccessCallback, undefined);
+       try {
+               SysteminfoObj.getPropertyValue("WIFI_NETWORK", cb.successCallback, cb.errorCallback); 
+       } catch(err) {
+               TestEngine.test("Exception : getPropertyValueTest() err.name [" + err.name + "] err.msg[" + err.message + "]", false);
+       }
+}
+
+function UTC_systeminfo_getPropertyValue_P_007()
+{
+       var cb = TestEngine.registerCallback("getPropertyValue", systeminfoCellularNetworkSuccessCallback, null);
+       try {
+               SysteminfoObj.getPropertyValue("CELLULAR_NETWORK", cb.successCallback, cb.errorCallback); 
+       } catch(err) {
+               TestEngine.test("Exception : getPropertyValueTest() err.name [" + err.name + "] err.msg[" + err.message + "]", false);
+       }
+}
+
+function UTC_systeminfo_getPropertyValue_P_008()
+{
+       var cb = TestEngine.registerCallback("getPropertyValue", systeminfoNetworkSuccessCallback, null);
+       try {
+               SysteminfoObj.getPropertyValue("NETWORK", cb.successCallback, cb.errorCallback); 
+       } catch(err) {
+               TestEngine.test("Exception : getPropertyValueTest() err.name [" + err.name + "] err.msg[" + err.message + "]", false);
+       }
+}
+
+function UTC_systeminfo_getPropertyValue_P_009()
+{
+       var cb = TestEngine.registerCallback("getPropertyValue", systeminfoSIMSuccessCallback, null);
+       try {
+               SysteminfoObj.getPropertyValue("SIM", cb.successCallback, cb.errorCallback); 
+       } catch(err) {
+               TestEngine.test("Exception : getPropertyValueTest() err.name [" + err.name + "] err.msg[" + err.message + "]", false);
+       }
+}
+
+function UTC_systeminfo_getPropertyValue_P_010()
+{
+       var cb = TestEngine.registerCallback("getPropertyValue", systeminfoBuildSuccessCallback, null);
+       try {
+               SysteminfoObj.getPropertyValue("BUILD", cb.successCallback, cb.errorCallback); 
+       } catch(err) {
+               TestEngine.test("Exception : getPropertyValueTest() err.name [" + err.name + "] err.msg[" + err.message + "]", false);
+       }
+}
+
+function UTC_systeminfo_getPropertyValue_P_011()
+{
+       var cb = TestEngine.registerCallback("getPropertyValue", systeminfoLocaleSuccessCallback, null);
+       try {
+               SysteminfoObj.getPropertyValue("LOCALE", cb.successCallback, cb.errorCallback); 
+       } catch(err) {
+               TestEngine.test("Exception : getPropertyValueTest() err.name [" + err.name + "] err.msg[" + err.message + "]", false);
+       }
+}
+
+function UTC_systeminfo_getPropertyValue_P_012()
+{
+       var cb = TestEngine.registerCallback("getPropertyValue", systeminfoPeripheralSuccessCallback, null);
+       try {
+               SysteminfoObj.getPropertyValue("PERIPHERAL", cb.successCallback, cb.errorCallback); 
+       } catch(err) {
+               TestEngine.test("Exception : getPropertyValueTest() err.name [" + err.name + "] err.msg[" + err.message + "]", false);
+       }
+}
+
+function UTC_systeminfo_getPropertyValue_N_001()
+{
+       try {
+               SysteminfoObj.getPropertyValue("Test", systeminfoInvalidSuccessCallback, null); 
+       } catch(err) {
+               TestEngine.assertEqual("Exception check", TYPE_MISMATCH_ERR, err.name);
+       }
+}
+
+function UTC_systeminfo_getPropertyValue_N_002()
+{
+       try {
+               SysteminfoObj.getPropertyValue("", systeminfoInvalidSuccessCallback, null); 
+       } catch(err) {
+               TestEngine.assertEqual("Exception check", TYPE_MISMATCH_ERR, err.name);
+       }
+}
+
+function UTC_systeminfo_getPropertyValue_N_003()
+{
+       try {
+               SysteminfoObj.getPropertyValue(0, systeminfoInvalidSuccessCallback, null); 
+       } catch(err) {
+               TestEngine.assertEqual("Exception check", TYPE_MISMATCH_ERR, err.name);
+       }
+}
+
+function UTC_systeminfo_getPropertyValue_N_004()
+{
+       try {
+               SysteminfoObj.getPropertyValue(true, systeminfoInvalidSuccessCallback, null); 
+       } catch(err) {
+               TestEngine.assertEqual("Exception check", TYPE_MISMATCH_ERR, err.name);
+       }
+}
+
+function UTC_systeminfo_getPropertyValue_N_005()
+{
+       try {
+               SysteminfoObj.getPropertyValue(['a'], systeminfoInvalidSuccessCallback, null); 
+       } catch(err) {
+               TestEngine.assertEqual("Exception check", TYPE_MISMATCH_ERR, err.name);
+       }
+}
+
+function UTC_systeminfo_getPropertyValue_N_006()
+{
+       try {
+               SysteminfoObj.getPropertyValue(undefined, systeminfoInvalidSuccessCallback, null); 
+       } catch(err) {
+               TestEngine.assertEqual("Exception check", TYPE_MISMATCH_ERR, err.name);
+       }
+}
+
+function UTC_systeminfo_getPropertyValue_N_007()
+{
+       try {
+               SysteminfoObj.getPropertyValue(null, systeminfoInvalidSuccessCallback); 
+       } catch(err) {
+               TestEngine.assertEqual("Exception check", TYPE_MISMATCH_ERR, err.name);
+       }
+}
+
+function UTC_systeminfo_getPropertyValue_N_008()
+{
+       try {
+               SysteminfoObj.getPropertyValue("BATTERY"); 
+       } catch(err) {
+               TestEngine.assertEqual("Exception check", TYPE_MISMATCH_ERR, err.name);
+       }
+}
+
+function UTC_systeminfo_getPropertyValue_N_009()
+{
+       try {
+               SysteminfoObj.getPropertyValue(); 
+       } catch(err) {
+               TestEngine.assertEqual("Exception check", TYPE_MISMATCH_ERR, err.name);
+       }
+}
+
+function UTC_systeminfo_getPropertyValue_N_010()
+{
+       try {
+               SysteminfoObj.getPropertyValue("BATTERY", "", systeminfoInvalidValueErrorCallback); 
+       } catch(err) {
+               TestEngine.assertEqual("Exception check", TYPE_MISMATCH_ERR, err.name);
+       }
+}
+
+function UTC_systeminfo_getPropertyValue_N_011()
+{
+       try {
+               SysteminfoObj.getPropertyValue("BATTERY", 0, systeminfoInvalidValueErrorCallback); 
+       } catch(err) {
+               TestEngine.assertEqual("Exception check", TYPE_MISMATCH_ERR, err.name);
+       }
+}
+
+function UTC_systeminfo_getPropertyValue_N_012()
+{
+       try {
+               SysteminfoObj.getPropertyValue(true, systeminfoInvalidValueErrorCallback, "BATTERY"); 
+       } catch(err) {
+               TestEngine.assertEqual("Exception check", TYPE_MISMATCH_ERR, err.name);
+       }
+}
+
+function UTC_systeminfo_getPropertyValue_N_013()
+{
+       try {
+               SysteminfoObj.getPropertyValue("BATTERY", ['a'], systeminfoInvalidValueErrorCallback); 
+       } catch(err) {
+               TestEngine.assertEqual("Exception check", TYPE_MISMATCH_ERR, err.name);
+       }
+}
+
+function UTC_systeminfo_getPropertyValue_N_014()
+{
+       try {
+               SysteminfoObj.getPropertyValue("BATTERY", undefined, systeminfoInvalidValueErrorCallback); 
+       } catch(err) {
+               TestEngine.assertEqual("Exception check", TYPE_MISMATCH_ERR, err.name);
+       }
+}
+
+function UTC_systeminfo_getPropertyValue_N_015()
+{
+       try {
+               SysteminfoObj.getPropertyValue("BATTERY", null, systeminfoInvalidValueErrorCallback); 
+       } catch(err) {
+               TestEngine.assertEqual("Exception check", TYPE_MISMATCH_ERR, err.name);
+       }
+}
+
+function UTC_systeminfo_getPropertyValue_N_016()
+{
+       try {
+               SysteminfoObj.getPropertyValue("BATTERY", systeminfoInvalidSuccessCallback, ""); 
+       } catch(err) {
+               TestEngine.assertEqual("Exception check", TYPE_MISMATCH_ERR, err.name);
+       }
+}
+
+function UTC_systeminfo_getPropertyValue_N_017()
+{
+       try {
+               SysteminfoObj.getPropertyValue("BATTERY", systeminfoInvalidSuccessCallback, 0); 
+       } catch(err) {
+               TestEngine.assertEqual("Exception check", TYPE_MISMATCH_ERR, err.name);
+       }
+}
+
+function UTC_systeminfo_getPropertyValue_N_018()
+{
+       try {
+               SysteminfoObj.getPropertyValue("BATTERY", systeminfoInvalidSuccessCallback, true); 
+       } catch(err) {
+               TestEngine.assertEqual("Exception check", TYPE_MISMATCH_ERR, err.name);
+       }
+}
+
+function UTC_systeminfo_getPropertyValue_N_019()
+{
+       try {
+               SysteminfoObj.getPropertyValue("BATTERY", systeminfoInvalidSuccessCallback, ['a']); 
+       } catch(err) {
+               TestEngine.assertEqual("Exception check", TYPE_MISMATCH_ERR, err.name);
+       }
+}
+
+function UTC_systeminfo_addPropertyValueChangeListener_P_001()
+{
+       try {
+               var value = SysteminfoObj.addPropertyValueChangeListener("BATTERY", systeminfoBatterySuccessCallback, {highThreshold: 0.9}, systeminfoErrorCallback);
+               if (value > 0) {
+                       TestEngine.logOK("Identifier (" + value + ") is valid");
+                       SysteminfoObj.removePropertyValueChangeListener(value);
+               } else {
+                       TestEngine.logErr("Identifier (" + value + ") is not valid");
+               }
+       } catch(err) {
+               TestEngine.test("Exception : addPropertyValueChangeListenerTest() err.name [" + err.name + "] err.msg[" + err.message + "]", false);
+       }
+}
+
+function UTC_systeminfo_addPropertyValueChangeListener_P_002()
+{
+       try {
+               var value = SysteminfoObj.addPropertyValueChangeListener("DISPLAY", systeminfoDisplaySuccessCallback, {lowThreshold: 0.3}, systeminfoErrorCallback);
+               if (value > 0) {
+                       TestEngine.logOK("Identifier (" + value + ") is valid");
+                       SysteminfoObj.removePropertyValueChangeListener(value);
+               } else {
+                       TestEngine.logErr("Identifier (" + value + ") is not valid");
+               }
+       } catch(err) {
+               TestEngine.test("Exception : addPropertyValueChangeListenerTest() err.name [" + err.name + "] err.msg[" + err.message + "]", false);
+       }
+}
+
+function UTC_systeminfo_addPropertyValueChangeListener_P_003()
+{
+       try {
+               var value = SysteminfoObj.addPropertyValueChangeListener("CPU", systeminfoCpuSuccessCallback, {timeout: 10000}, systeminfoErrorCallback);
+               if (value > 0) {
+                       TestEngine.logOK("Identifier (" + value + ") is valid");
+                       SysteminfoObj.removePropertyValueChangeListener(value);
+               } else {
+                       TestEngine.logErr("Identifier (" + value + ") is not valid");
+               }
+       } catch(err) {
+               TestEngine.test("Exception : addPropertyValueChangeListenerTest() err.name [" + err.name + "] err.msg[" + err.message + "]", false);
+       }
+}
+
+function UTC_systeminfo_addPropertyValueChangeListener_P_004()
+{
+       try {
+               var value = SysteminfoObj.addPropertyValueChangeListener("STORAGE", systeminfoStorageSuccessCallback, null, systeminfoErrorCallback);
+               if (value > 0) {
+                       TestEngine.logOK("Identifier (" + value + ") is valid");
+                       SysteminfoObj.removePropertyValueChangeListener(value);
+               } else {
+                       TestEngine.logErr("Identifier (" + value + ") is not valid");
+               }
+       } catch(err) {
+               TestEngine.test("Exception : addPropertyValueChangeListenerTest() err.name [" + err.name + "] err.msg[" + err.message + "]", false);
+       }
+}
+
+function UTC_systeminfo_addPropertyValueChangeListener_P_005()
+{
+       try {
+               var value = SysteminfoObj.addPropertyValueChangeListener("DEVICE_ORIENTATION", systeminfoDeviceOrientationSuccessCallback, null, systeminfoErrorCallback);
+               if (value > 0) {
+                       TestEngine.logOK("Identifier (" + value + ") is valid");
+                       SysteminfoObj.removePropertyValueChangeListener(value);
+               } else {
+                       TestEngine.logErr("Identifier (" + value + ") is not valid");
+               }
+       } catch(err) {
+               TestEngine.test("Exception : addPropertyValueChangeListenerTest() err.name [" + err.name + "] err.msg[" + err.message + "]", false);
+       }
+}
+
+function UTC_systeminfo_addPropertyValueChangeListener_P_006()
+{
+       try {
+               var value = SysteminfoObj.addPropertyValueChangeListener("LOCALE", systeminfoLocaleSuccessCallback, undefined, systeminfoErrorCallback);
+               if (value > 0) {
+                       TestEngine.logOK("Identifier (" + value + ") is valid");
+                       SysteminfoObj.removePropertyValueChangeListener(value);
+               } else {
+                       TestEngine.logErr("Identifier (" + value + ") is not valid");
+               }
+       } catch(err) {
+               TestEngine.test("Exception : addPropertyValueChangeListenerTest() err.name [" + err.name + "] err.msg[" + err.message + "]", false);
+       }
+}
+
+function UTC_systeminfo_addPropertyValueChangeListener_P_007()
+{
+       try {
+               var value = SysteminfoObj.addPropertyValueChangeListener("NETWORK", systeminfoNetworkSuccessCallback, null, null);
+               if (value > 0) {
+                       TestEngine.logOK("Identifier (" + value + ") is valid");
+                       SysteminfoObj.removePropertyValueChangeListener(value);
+               } else {
+                       TestEngine.logErr("Identifier (" + value + ") is not valid");
+               }
+       } catch(err) {
+               TestEngine.test("Exception : addPropertyValueChangeListenerTest() err.name [" + err.name + "] err.msg[" + err.message + "]", false);
+       }
+}
+
+function UTC_systeminfo_addPropertyValueChangeListener_P_008()
+{
+       try {
+               var value = SysteminfoObj.addPropertyValueChangeListener("WIFI_NETWORK", systeminfoWifiNetworkSuccessCallback, null, null);
+               if (value > 0) {
+                       TestEngine.logOK("Identifier (" + value + ") is valid");
+                       SysteminfoObj.removePropertyValueChangeListener(value);
+               } else {
+                       TestEngine.logErr("Identifier (" + value + ") is not valid");
+               }
+       } catch(err) {
+               TestEngine.test("Exception : addPropertyValueChangeListenerTest() err.name [" + err.name + "] err.msg[" + err.message + "]", false);
+       }
+}
+
+function UTC_systeminfo_addPropertyValueChangeListener_P_009()
+{
+       try {
+               var value = SysteminfoObj.addPropertyValueChangeListener("CELLULAR_NETWORK", systeminfoCellularNetworkSuccessCallback, null, null);
+               if (value > 0) {
+                       TestEngine.logOK("Identifier (" + value + ") is valid");
+                       SysteminfoObj.removePropertyValueChangeListener(value);
+               } else {
+                       TestEngine.logErr("Identifier (" + value + ") is not valid");
+               }
+       } catch(err) {
+               TestEngine.test("Exception : addPropertyValueChangeListenerTest() err.name [" + err.name + "] err.msg[" + err.message + "]", false);
+       }
+}
+
+function UTC_systeminfo_addPropertyValueChangeListener_P_010()
+{
+       try {
+               var value = SysteminfoObj.addPropertyValueChangeListener("PERIPHERAL", systeminfoPeripheralSuccessCallback, null, null);
+               if (value > 0) {
+                       TestEngine.logOK("Identifier (" + value + ") is valid");
+                       SysteminfoObj.removePropertyValueChangeListener(value);
+               } else {
+                       TestEngine.logErr("Identifier (" + value + ") is not valid");
+               }
+       } catch(err) {
+               TestEngine.test("Exception : addPropertyValueChangeListenerTest() err.name [" + err.name + "] err.msg[" + err.message + "]", false);
+       }
+}
+
+function UTC_systeminfo_addPropertyValueChangeListener_P_011()
+{
+       try {
+               var value = SysteminfoObj.addPropertyValueChangeListener("SIM", systeminfoSIMSuccessCallback, null, null);
+               if (value > 0) {
+                       TestEngine.logOK("Identifier (" + value + ") is valid");
+                       SysteminfoObj.removePropertyValueChangeListener(value);
+               } else {
+                       TestEngine.logErr("Identifier (" + value + ") is not valid");
+               }
+       } catch(err) {
+               TestEngine.test("Exception : addPropertyValueChangeListenerTest() err.name [" + err.name + "] err.msg[" + err.message + "]", false);
+       }
+}
+
+function UTC_systeminfo_addPropertyValueChangeListener_N_001()
+{
+       try {
+               var value = SysteminfoObj.addPropertyValueChangeListener("Test", systeminfoInvalidSuccessCallback, {highThreshold: 0.9}, systeminfoInvalidErrorCallback);
+               if (value > 0) {
+                       TestEngine.logErr("Identifier (" + value + ") is valid");
+                       SysteminfoObj.removePropertyValueChangeListener(value);
+               } else {
+                       TestEngine.logOK("Identifier (" + value + ") is not valid");
+               }
+       } catch(err) {
+               TestEngine.assertEqual("Exception check", TYPE_MISMATCH_ERR, err.name);
+       }
+}
+
+function UTC_systeminfo_addPropertyValueChangeListener_N_002()
+{
+       try {
+               var value = SysteminfoObj.addPropertyValueChangeListener("", systeminfoInvalidSuccessCallback, {highThreshold: 0.9}, systeminfoInvalidErrorCallback);
+               if (value > 0) {
+                       TestEngine.logErr("Identifier (" + value + ") is valid");
+                       SysteminfoObj.removePropertyValueChangeListener(value);
+               } else {
+                       TestEngine.logOK("Identifier (" + value + ") is not valid");
+               }
+       } catch(err) {
+               TestEngine.assertEqual("Exception check", TYPE_MISMATCH_ERR, err.name);
+       }
+}
+
+function UTC_systeminfo_addPropertyValueChangeListener_N_003()
+{
+       try {
+               var value = SysteminfoObj.addPropertyValueChangeListener(0, systeminfoInvalidSuccessCallback, {highThreshold: 0.9}, systeminfoInvalidErrorCallback);
+               if (value > 0) {
+                       TestEngine.logErr("Identifier (" + value + ") is valid");
+                       SysteminfoObj.removePropertyValueChangeListener(value);
+               } else {
+                       TestEngine.logOK("Identifier (" + value + ") is not valid");
+               }
+       } catch(err) {
+               TestEngine.assertEqual("Exception check", TYPE_MISMATCH_ERR, err.name);
+       }
+}
+
+function UTC_systeminfo_addPropertyValueChangeListener_N_004()
+{
+       try {
+               var value = SysteminfoObj.addPropertyValueChangeListener(true, systeminfoInvalidSuccessCallback, {highThreshold: 0.9}, systeminfoInvalidErrorCallback);
+               if (value > 0) {
+                       TestEngine.logErr("Identifier (" + value + ") is valid");
+                       SysteminfoObj.removePropertyValueChangeListener(value);
+               } else {
+                       TestEngine.logOK("Identifier (" + value + ") is not valid");
+               }
+       } catch(err) {
+               TestEngine.assertEqual("Exception check", TYPE_MISMATCH_ERR, err.name);
+       }
+}
+
+function UTC_systeminfo_addPropertyValueChangeListener_N_005()
+{
+       try {
+               var value = SysteminfoObj.addPropertyValueChangeListener(['a'], systeminfoInvalidSuccessCallback, {highThreshold: 0.9}, systeminfoInvalidErrorCallback);
+               if (value > 0) {
+                       TestEngine.logErr("Identifier (" + value + ") is valid");
+                       SysteminfoObj.removePropertyValueChangeListener(value);
+               } else {
+                       TestEngine.logOK("Identifier (" + value + ") is not valid");
+               }
+       } catch(err) {
+               TestEngine.assertEqual("Exception check", TYPE_MISMATCH_ERR, err.name);
+       }
+}
+
+function UTC_systeminfo_addPropertyValueChangeListener_N_006()
+{
+       try {
+               var value = SysteminfoObj.addPropertyValueChangeListener(undefined, systeminfoInvalidSuccessCallback, {highThreshold: 0.9}, systeminfoInvalidErrorCallback);
+               if (value > 0) {
+                       TestEngine.logErr("Identifier (" + value + ") is valid");
+                       SysteminfoObj.removePropertyValueChangeListener(value);
+               } else {
+                       TestEngine.logOK("Identifier (" + value + ") is not valid");
+               }
+       } catch(err) {
+               TestEngine.assertEqual("Exception check", TYPE_MISMATCH_ERR, err.name);
+       }
+}
+
+function UTC_systeminfo_addPropertyValueChangeListener_N_007()
+{
+       try {
+               var value = SysteminfoObj.addPropertyValueChangeListener(null, systeminfoInvalidSuccessCallback, {highThreshold: 0.9}, systeminfoInvalidErrorCallback);
+               if (value > 0) {
+                       TestEngine.logErr("Identifier (" + value + ") is valid");
+                       SysteminfoObj.removePropertyValueChangeListener(value);
+               } else {
+                       TestEngine.logOK("Identifier (" + value + ") is not valid");
+               }
+       } catch(err) {
+               TestEngine.assertEqual("Exception check", TYPE_MISMATCH_ERR, err.name);
+       }
+}
+
+function UTC_systeminfo_addPropertyValueChangeListener_N_008()
+{
+       try {
+               var value = SysteminfoObj.addPropertyValueChangeListener("BATTERY", systeminfoInvalidSuccessCallback, {highThreshold: 0.9}, "");
+               if (value > 0) {
+                       TestEngine.logErr("Identifier (" + value + ") is valid");
+                       SysteminfoObj.removePropertyValueChangeListener(value);
+               } else {
+                       TestEngine.logOK("Identifier (" + value + ") is not valid");
+               }
+       } catch(err) {
+               TestEngine.assertEqual("Exception check", TYPE_MISMATCH_ERR, err.name);
+       }
+}
+
+function UTC_systeminfo_addPropertyValueChangeListener_N_009()
+{
+       try {
+               var value = SysteminfoObj.addPropertyValueChangeListener("BATTERY", systeminfoInvalidSuccessCallback, {highThreshold: 0.9}, 0);
+               if (value > 0) {
+                       TestEngine.logErr("Identifier (" + value + ") is valid");
+                       SysteminfoObj.removePropertyValueChangeListener(value);
+               } else {
+                       TestEngine.logOK("Identifier (" + value + ") is not valid");
+               }
+       } catch(err) {
+               TestEngine.assertEqual("Exception check", TYPE_MISMATCH_ERR, err.name);
+       }
+}
+
+function UTC_systeminfo_addPropertyValueChangeListener_N_010()
+{
+       try {
+               var value = SysteminfoObj.addPropertyValueChangeListener("BATTERY", systeminfoInvalidSuccessCallback, {highThreshold: 0.9}, true);
+               if (value > 0) {
+                       TestEngine.logErr("Identifier (" + value + ") is valid");
+                       SysteminfoObj.removePropertyValueChangeListener(value);
+               } else {
+                       TestEngine.logOK("Identifier (" + value + ") is not valid");
+               }
+       } catch(err) {
+               TestEngine.assertEqual("Exception check", TYPE_MISMATCH_ERR, err.name);
+       }
+}
+
+function UTC_systeminfo_addPropertyValueChangeListener_N_011()
+{
+       try {
+               var value = SysteminfoObj.addPropertyValueChangeListener("BATTERY", "", {highThreshold: 0.9}, systeminfoErrorCallback);
+               if (value > 0) {
+                       TestEngine.logErr("Identifier (" + value + ") is valid");
+                       SysteminfoObj.removePropertyValueChangeListener(value);
+               } else {
+                       TestEngine.logOK("Identifier (" + value + ") is not valid");
+               }
+       } catch(err) {
+               TestEngine.assertEqual("Exception check", TYPE_MISMATCH_ERR, err.name);
+       }
+}
+
+function UTC_systeminfo_addPropertyValueChangeListener_N_012()
+{
+       try {
+               var value = SysteminfoObj.addPropertyValueChangeListener("BATTERY", 0, {highThreshold: 0.9}, systeminfoErrorCallback);
+               if (value > 0) {
+                       TestEngine.logErr("Identifier (" + value + ") is valid");
+                       SysteminfoObj.removePropertyValueChangeListener(value);
+               } else {
+                       TestEngine.logOK("Identifier (" + value + ") is not valid");
+               }
+       } catch(err) {
+               TestEngine.assertEqual("Exception check", TYPE_MISMATCH_ERR, err.name);
+       }
+}
+
+function UTC_systeminfo_addPropertyValueChangeListener_N_013()
+{
+       try {
+               var value = SysteminfoObj.addPropertyValueChangeListener("BATTERY", true, {highThreshold: 0.9}, systeminfoErrorCallback);
+               if (value > 0) {
+                       TestEngine.logErr("Identifier (" + value + ") is valid");
+                       SysteminfoObj.removePropertyValueChangeListener(value);
+               } else {
+                       TestEngine.logOK("Identifier (" + value + ") is not valid");
+               }
+       } catch(err) {
+               TestEngine.assertEqual("Exception check", TYPE_MISMATCH_ERR, err.name);
+       }
+}
+
+function UTC_systeminfo_addPropertyValueChangeListener_N_014()
+{
+       try {
+               var value = SysteminfoObj.addPropertyValueChangeListener("BATTERY", ['a'], {highThreshold: 0.9}, systeminfoErrorCallback);
+               if (value > 0) {
+                       TestEngine.logErr("Identifier (" + value + ") is valid");
+                       SysteminfoObj.removePropertyValueChangeListener(value);
+               } else {
+                       TestEngine.logOK("Identifier (" + value + ") is not valid");
+               }
+       } catch(err) {
+               TestEngine.assertEqual("Exception check", TYPE_MISMATCH_ERR, err.name);
+       }
+}
+
+function UTC_systeminfo_addPropertyValueChangeListener_N_015()
+{
+       try {
+               var value = SysteminfoObj.addPropertyValueChangeListener("BATTERY", undefined, {highThreshold: 0.9}, systeminfoErrorCallback);
+               if (value > 0) {
+                       TestEngine.logErr("Identifier (" + value + ") is valid");
+                       SysteminfoObj.removePropertyValueChangeListener(value);
+               } else {
+                       TestEngine.logOK("Identifier (" + value + ") is not valid");
+               }
+       } catch(err) {
+               TestEngine.assertEqual("Exception check", TYPE_MISMATCH_ERR, err.name);
+       }
+}
+
+function UTC_systeminfo_addPropertyValueChangeListener_N_016()
+{
+       try {
+               var value = SysteminfoObj.addPropertyValueChangeListener("BATTERY", null, {highThreshold: 0.9}, systeminfoErrorCallback);
+               if (value > 0) {
+                       TestEngine.logErr("Identifier (" + value + ") is valid");
+                       SysteminfoObj.removePropertyValueChangeListener(value);
+               } else {
+                       TestEngine.logOK("Identifier (" + value + ") is not valid");
+               }
+       } catch(err) {
+               TestEngine.assertEqual("Exception check", TYPE_MISMATCH_ERR, err.name);
+       }
+}
+
+function UTC_systeminfo_addPropertyValueChangeListener_N_017()
+{
+       try {
+               var value = SysteminfoObj.addPropertyValueChangeListener("BATTERY");
+               if (value > 0) {
+                       TestEngine.logErr("Identifier (" + value + ") is valid");
+                       SysteminfoObj.removePropertyValueChangeListener(value);
+               } else {
+                       TestEngine.logOK("Identifier (" + value + ") is not valid");
+               }
+       } catch(err) {
+               TestEngine.assertEqual("Exception check", TYPE_MISMATCH_ERR, err.name);
+       }
+}
+
+function UTC_systeminfo_addPropertyValueChangeListener_N_018()
+{
+       try {
+               var value = SysteminfoObj.addPropertyValueChangeListener();
+               if (value > 0) {
+                       TestEngine.logErr("Identifier (" + value + ") is valid");
+                       SysteminfoObj.removePropertyValueChangeListener(value);
+               } else {
+                       TestEngine.logOK("Identifier (" + value + ") is not valid");
+               }
+       } catch(err) {
+               TestEngine.assertEqual("Exception check", TYPE_MISMATCH_ERR, err.name);
+       }
+}
+
+function UTC_systeminfo_removePropertyValueChangeListener_P_001()
+{
+       try {
+               var value = SysteminfoObj.addPropertyValueChangeListener("BATTERY", systeminfoBatterySuccessCallback, null, systeminfoErrorCallback);
+               if (value > 0) {
+                       try {
+                               SysteminfoObj.removePropertyValueChangeListener(value);
+                               TestEngine.logOK("listener is removed");
+                       } catch(err) {
+                               TestEngine.test("Exception : addPropertyValueChangeListenerTest() err.name [" + err.name + "] err.msg[" + err.message + "]", false);
+                       }                               
+               }
+       } catch(err) {
+               TestEngine.test("Exception : addPropertyValueChangeListenerTest() err.name [" + err.name + "] err.msg[" + err.message + "]", false);
+       }
+}
+
+function UTC_systeminfo_removePropertyValueChangeListener_P_002()
+{
+       try {
+               var value = SysteminfoObj.addPropertyValueChangeListener("CELLULAR_NETWORK", systeminfoCellularNetworkSuccessCallback, null, systeminfoErrorCallback);
+               if (value > 0) {
+                       try {
+                               SysteminfoObj.removePropertyValueChangeListener(value);
+                               TestEngine.logOK("listener is removed");
+                       } catch(err) {
+                               TestEngine.test("Exception : addPropertyValueChangeListenerTest() err.name [" + err.name + "] err.msg[" + err.message + "]", false);
+                       }                               
+               }
+       } catch(err) {
+               TestEngine.test("Exception : addPropertyValueChangeListenerTest() err.name [" + err.name + "] err.msg[" + err.message + "]", false);
+       }
+}
+
+function UTC_systeminfo_removePropertyValueChangeListener_P_003()
+{
+       try {
+               var value = SysteminfoObj.addPropertyValueChangeListener("SIM", systeminfoSIMSuccessCallback, null, systeminfoErrorCallback);
+               if (value > 0) {
+                       try {
+                               SysteminfoObj.removePropertyValueChangeListener(value);
+                               TestEngine.logOK("listener is removed");
+                       } catch(err) {
+                               TestEngine.test("Exception : addPropertyValueChangeListenerTest() err.name [" + err.name + "] err.msg[" + err.message + "]", false);
+                       }                               
+               }
+       } catch(err) {
+               TestEngine.test("Exception : addPropertyValueChangeListenerTest() err.name [" + err.name + "] err.msg[" + err.message + "]", false);
+       }
+}
+
+function UTC_systeminfo_removePropertyValueChangeListener_N_001()
+{
+       try {
+               var value = SysteminfoObj.addPropertyValueChangeListener("BATTERY", systeminfoBatterySuccessCallback, null, systeminfoErrorCallback);
+               if (value > 0) {
+                       try {
+                               SysteminfoObj.removePropertyValueChangeListener("");
+                       } catch(err) {
+                               TestEngine.assertEqual("Exception check", INVALID_VALUES_ERR, err.name);
+                               SysteminfoObj.removePropertyValueChangeListener(value);                         
+                       }
+               }
+       } catch(err) {
+               TestEngine.assertEqual("Exception check", INVALID_VALUES_ERR, err.name);
+       }
+}
+
+function UTC_systeminfo_removePropertyValueChangeListener_N_002()
+{
+       try {
+               var value = SysteminfoObj.addPropertyValueChangeListener("BATTERY", systeminfoBatterySuccessCallback, null, systeminfoErrorCallback);
+               if (value > 0) {
+                       try {
+                               SysteminfoObj.removePropertyValueChangeListener(0);
+                       } catch(err) {
+                               TestEngine.assertEqual("Exception check", INVALID_VALUES_ERR, err.name);
+                               SysteminfoObj.removePropertyValueChangeListener(value);                         
+                       }
+               }
+       } catch(err) {
+               TestEngine.test("Exception : addPropertyValueChangeListenerTest() err.name [" + err.name + "] err.msg[" + err.message + "]", false);
+       }
+}
+
+function UTC_systeminfo_removePropertyValueChangeListener_N_003()
+{
+       try {
+               var value = SysteminfoObj.addPropertyValueChangeListener("BATTERY", systeminfoBatterySuccessCallback, null, systeminfoErrorCallback);
+               if (value > 0) {
+                       try {
+                               SysteminfoObj.removePropertyValueChangeListener(false);
+                       } catch(err) {
+                               TestEngine.assertEqual("Exception check", INVALID_VALUES_ERR, err.name);
+                               SysteminfoObj.removePropertyValueChangeListener(value);                         
+                       }
+               }
+       } catch(err) {
+               TestEngine.test("Exception : addPropertyValueChangeListenerTest() err.name [" + err.name + "] err.msg[" + err.message + "]", false);
+       }
+}
+
+function UTC_systeminfo_removePropertyValueChangeListener_N_004()
+{
+       try {
+               var value = SysteminfoObj.addPropertyValueChangeListener("BATTERY", systeminfoBatterySuccessCallback, null, systeminfoErrorCallback);
+               if (value > 0) {
+                       try {
+                               SysteminfoObj.removePropertyValueChangeListener(['a']);
+                       } catch(err) {
+                               TestEngine.assertEqual("Exception check", INVALID_VALUES_ERR, err.name);
+                               SysteminfoObj.removePropertyValueChangeListener(value);                         
+                       }
+               }
+       } catch(err) {
+               TestEngine.test("Exception : addPropertyValueChangeListenerTest() err.name [" + err.name + "] err.msg[" + err.message + "]", false);
+       }
+}
+
+function UTC_systeminfo_removePropertyValueChangeListener_N_005()
+{
+       try {
+               var value = SysteminfoObj.addPropertyValueChangeListener("BATTERY", systeminfoBatterySuccessCallback, null, systeminfoErrorCallback);
+               if (value > 0) {
+                       try {
+                               SysteminfoObj.removePropertyValueChangeListener(undefined);
+                       } catch(err) {
+                               TestEngine.assertEqual("Exception check", INVALID_VALUES_ERR, err.name);
+                               SysteminfoObj.removePropertyValueChangeListener(value);                         
+                       }
+               }
+       } catch(err) {
+               TestEngine.test("Exception : addPropertyValueChangeListenerTest() err.name [" + err.name + "] err.msg[" + err.message + "]", false);
+       }
+}
+
+function UTC_systeminfo_removePropertyValueChangeListener_N_006()
+{
+       try {
+               var value = SysteminfoObj.addPropertyValueChangeListener("BATTERY", systeminfoBatterySuccessCallback, null, systeminfoErrorCallback);
+               if (value > 0) {
+                       try {
+                               SysteminfoObj.removePropertyValueChangeListener(null);
+                       } catch(err) {
+                               TestEngine.assertEqual("Exception check", INVALID_VALUES_ERR, err.name);
+                               SysteminfoObj.removePropertyValueChangeListener(value);                         
+                       }
+               }
+       } catch(err) {
+               TestEngine.test("Exception : addPropertyValueChangeListenerTest() err.name [" + err.name + "] err.msg[" + err.message + "]", false);
+       }
+}
diff --git a/webWidgetTCT_device/test/utc/utc.js b/webWidgetTCT_device/test/utc/utc.js
new file mode 100755 (executable)
index 0000000..819e8e5
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * 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.
+ */
+
+(function() {
+    function runTests() {
+        // gather tests to run
+        var selectedTests = {};
+        for (var i = 0; i < arguments.length; ++i) {
+            var arg = arguments[i];
+            if (!(arg instanceof Array)) {
+                arg = String(arg).split(' ');
+            }
+            for (var j = 0; j < arg.length; ++j) {
+                selectedTests[arg[j].toLowerCase()] = '';
+            }
+        }
+
+        // load node.js modules
+        var fs = require('fs');
+
+        // checks if object is empty
+        function isEmptyObject(object) {
+            for (var prop in object) {
+                if (object.hasOwnProperty(prop)) {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        // constants
+        var configDir = __dirname + '/config/';
+        var testsDir = __dirname + '/tests/';
+        var testRegExp = /^Test(.*)\.js$/;
+        var configPrefix = 'Config';
+        var testPrefix = 'Test';
+        var extension = '.js';
+
+        // find available tests
+        var availableTests = {};
+        var testFiles = fs.readdirSync(testsDir);
+
+        for (var ii = 0; ii < testFiles.length; ++ii) {
+            var match = testRegExp.exec(testFiles[ii]);
+            if (match) {
+                match = match[1];
+                if (fs.existsSync(configDir + configPrefix + match + extension)) {
+                    availableTests[match.toLowerCase()] = match;
+                }
+            }
+        }
+
+        // if no tests are selected, run all
+        if (isEmptyObject(selectedTests)) {
+            selectedTests = availableTests;
+        }
+
+        // load tizen modules
+        if (typeof (tizen) === 'undefined') {
+            require('../common/loader.js')();
+        }
+
+        // load test engine
+        var TestEngine = require('./common/TestEngine.js');
+
+        // configure the clock script
+        require('child_process').exec(__dirname + '/changeClockSettingFile.sh');
+
+        // load tests
+        for (var test in selectedTests) {
+            if (availableTests[test]) {
+                console.log('Adding test: ' + availableTests[test]);
+                (function () {
+                    try {
+                        eval(fs.readFileSync(testsDir + testPrefix +
+                                availableTests[test] + extension, 'utf-8')+ '');
+                        eval(fs.readFileSync(configDir + configPrefix +
+                                availableTests[test] + extension, 'utf-8') + '');
+                    } catch (e) {
+                        console.log('Error while adding ' + availableTests[test] + ': ' + e);
+                        console.log(e.stack);
+                    }
+                })();
+            }
+        }
+
+        // exit the process when testing is finished
+        TestEngine.onFinished = function () {
+            process.exit();
+        };
+        var testFolderName1 = '/home/owner/share/Documents';
+        try {
+            if (!fs.existsSync(testFolderName1)) {
+               fs.mkdirSync(testFolderName1, 0777);
+            }
+        } catch (err) {
+            console.log('Creating ' + testFolderName1 + ' folder failed');
+        }
+        var testFileName1 = '/home/owner/share/Images/image1.jpg';
+        try {
+            if (!fs.existsSync(testFileName1)) {
+               fs.writeFileSync(testFileName1, 'Do I look like an image?');
+            }
+        } catch (err) {
+            console.log('Creating "' + testFileName1 + '" file failed');
+        }
+
+        // run tests
+        TestEngine.doTests();
+    }
+
+    if (!module.parent) {
+        // standalone script
+        runTests(process.argv.slice(2));
+    } else {
+        module.exports = runTests;
+    }
+})();
diff --git a/webWidgetTCT_device/tools/check-coding-style b/webWidgetTCT_device/tools/check-coding-style
new file mode 100755 (executable)
index 0000000..9f97316
--- /dev/null
@@ -0,0 +1,53 @@
+#!/bin/bash
+# Copyright (c) 2013 Intel Corporation. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+if [ ! `which cpplint.py` ]; then
+   echo -e "\nPlease make sure cpplint.py is in your PATH. It is part of depot_tools inside Chromium repository."
+   exit 1
+fi
+
+if [ ! `which gjslint` ]; then
+   echo -e "\nPlease make sure gjslint (Google Closure Lint) is in your PATH."
+   echo -e "You can install it directly by \"sudo easy_install-2.7 http://closure-linter.googlecode.com/files/closure_linter-latest.tar.gz\"."
+   echo -e "Or visit https://developers.google.com/closure/utilities/docs/linter_howto for more information.\n"
+   exit 1
+fi
+
+# Store current dir and change to repository root dir.
+OLD_PWD=$PWD
+SELF_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+cd $SELF_DIR/..
+
+# FIXME(cmarcelo): the exception 'runtime/references' is for system_info/, we
+# need to verify whether is really necessary or should be fixed.
+FILTERS="-readability/streams,-runtime/references"
+
+# TODO(cmarcelo): Skipping directories so we can enable style
+# gradually, since it wasn't enforced before.
+cpplint.py --filter="$FILTERS" $(find . \
+                               ! -path './out*' ! -path './.git*' \
+                               ! -path './demos' ! -path './examples' \
+                               ! -path './packaging' \
+                               ! -name 'XW_Extension*.h' \
+                               ! -name 'picojson.*' \
+                               \( -name '*.h' -o -name '*.cc' \) )
+CPP_RET_VAL=$?
+
+gjslint --strict --nojsdoc --max_line_length 100 --unix_mode $(find . \
+                               ! -path './out*' ! -path './.git*' \
+                               ! -path './packaging' \
+                               ! -name 'jquery*' \
+                               ! -name 'flotr2.*' \
+                               -name '*.js' )
+
+# Return to previous dir and return the code returned by cpplint.py
+JS_RET_VAL=$?
+cd $OLD_PWD
+
+if [ "x$CPP_RET_VAL" = "x0" -a "x$JS_RET_VAL" = "x0" ]; then
+  exit 0
+else
+  exit 1
+fi
diff --git a/webWidgetTCT_device/tools/generate_api.py b/webWidgetTCT_device/tools/generate_api.py
new file mode 100755 (executable)
index 0000000..d9dfc02
--- /dev/null
@@ -0,0 +1,22 @@
+# Copyright (c) 2013 Intel Corporation. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import sys
+import subprocess
+
+TEMPLATE = """\
+extern const char %s[];
+const char %s[] = { %s, 0 };
+"""
+
+js_code = sys.argv[1]
+cmd = "python " + os.path.dirname(__file__) + "/mergejs.py -f" + js_code
+lines = subprocess.check_output(cmd, shell=True)
+c_code = ', '.join(str(ord(c)) for c in lines)
+
+symbol_name = sys.argv[2]
+output = open(sys.argv[3], "w")
+output.write(TEMPLATE % (symbol_name, symbol_name, c_code))
+output.close()
diff --git a/webWidgetTCT_device/tools/generate_manifest.py b/webWidgetTCT_device/tools/generate_manifest.py
new file mode 100755 (executable)
index 0000000..dc366ec
--- /dev/null
@@ -0,0 +1,30 @@
+# Copyright (c) 2013 Intel Corporation. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import sys, os, re, errno
+
+spec = sys.argv[1]
+origin = sys.argv[2]
+
+if len(sys.argv) != 8:
+    print 'Invalid arguments'
+    sys.exit(errno.EINVAL)
+
+if not os.path.isfile(spec) or not os.path.isfile(origin):
+    print 'No such spec(%s) or input xml(%s) file' % (spec, origin)
+    sys.exit(errno.ENOENT)
+
+spec = file(spec).read()
+version = re.search('(?<=Version:).*', spec).group(0).strip()
+package_name = re.search('(?<=%define '+sys.argv[3]+').*', spec).group(0).strip()
+
+template = file(origin).read().replace('@PACKAGE_VERSION@', version)
+template = template.replace('@PACKAGE_NAME@', package_name)
+template = template.replace('@APP_ID@', sys.argv[4])
+template = template.replace('@PACKAGE_EXEC@', sys.argv[5])
+template = template.replace('@PACKAGE_LABEL@', sys.argv[6])
+
+output = open(sys.argv[7], 'w')
+output.write(template)
+output.close()
diff --git a/webWidgetTCT_device/tools/gyp/.gitignore b/webWidgetTCT_device/tools/gyp/.gitignore
new file mode 100755 (executable)
index 0000000..0d20b64
--- /dev/null
@@ -0,0 +1 @@
+*.pyc
diff --git a/webWidgetTCT_device/tools/gyp/AUTHORS b/webWidgetTCT_device/tools/gyp/AUTHORS
new file mode 100755 (executable)
index 0000000..8977761
--- /dev/null
@@ -0,0 +1,8 @@
+# Names should be added to this file like so:
+# Name or Organization <email address>
+
+Google Inc.
+Bloomberg Finance L.P.
+
+Steven Knight <knight@baldmt.com>
+Ryan Norton <rnorton10@gmail.com>
diff --git a/webWidgetTCT_device/tools/gyp/LICENSE b/webWidgetTCT_device/tools/gyp/LICENSE
new file mode 100755 (executable)
index 0000000..ab6b011
--- /dev/null
@@ -0,0 +1,27 @@
+Copyright (c) 2009 Google Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+   * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+   * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/webWidgetTCT_device/tools/gyp/gyp b/webWidgetTCT_device/tools/gyp/gyp
new file mode 100755 (executable)
index 0000000..d52e711
--- /dev/null
@@ -0,0 +1,18 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2009 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import sys
+
+# TODO(mark): sys.path manipulation is some temporary testing stuff.
+try:
+  import gyp
+except ImportError, e:
+  import os.path
+  sys.path.append(os.path.join(os.path.dirname(sys.argv[0]), 'pylib'))
+  import gyp
+
+if __name__ == '__main__':
+  sys.exit(gyp.main(sys.argv[1:]))
diff --git a/webWidgetTCT_device/tools/gyp/gyp.bat b/webWidgetTCT_device/tools/gyp/gyp.bat
new file mode 100755 (executable)
index 0000000..90fbc6d
--- /dev/null
@@ -0,0 +1,5 @@
+@rem Copyright (c) 2009 Google Inc. All rights reserved.\r
+@rem Use of this source code is governed by a BSD-style license that can be\r
+@rem found in the LICENSE file.\r
+\r
+@python "%~dp0/gyp" %*\r
diff --git a/webWidgetTCT_device/tools/gyp/pylib/gyp/MSVSNew.py b/webWidgetTCT_device/tools/gyp/pylib/gyp/MSVSNew.py
new file mode 100755 (executable)
index 0000000..253fe61
--- /dev/null
@@ -0,0 +1,339 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""New implementation of Visual Studio project generation for SCons."""
+
+import os
+import random
+
+import gyp.common
+
+# hashlib is supplied as of Python 2.5 as the replacement interface for md5
+# and other secure hashes.  In 2.6, md5 is deprecated.  Import hashlib if
+# available, avoiding a deprecation warning under 2.6.  Import md5 otherwise,
+# preserving 2.4 compatibility.
+try:
+  import hashlib
+  _new_md5 = hashlib.md5
+except ImportError:
+  import md5
+  _new_md5 = md5.new
+
+
+# Initialize random number generator
+random.seed()
+
+# GUIDs for project types
+ENTRY_TYPE_GUIDS = {
+    'project': '{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}',
+    'folder': '{2150E333-8FDC-42A3-9474-1A3956D46DE8}',
+}
+
+#------------------------------------------------------------------------------
+# Helper functions
+
+
+def MakeGuid(name, seed='msvs_new'):
+  """Returns a GUID for the specified target name.
+
+  Args:
+    name: Target name.
+    seed: Seed for MD5 hash.
+  Returns:
+    A GUID-line string calculated from the name and seed.
+
+  This generates something which looks like a GUID, but depends only on the
+  name and seed.  This means the same name/seed will always generate the same
+  GUID, so that projects and solutions which refer to each other can explicitly
+  determine the GUID to refer to explicitly.  It also means that the GUID will
+  not change when the project for a target is rebuilt.
+  """
+  # Calculate a MD5 signature for the seed and name.
+  d = _new_md5(str(seed) + str(name)).hexdigest().upper()
+  # Convert most of the signature to GUID form (discard the rest)
+  guid = ('{' + d[:8] + '-' + d[8:12] + '-' + d[12:16] + '-' + d[16:20]
+          + '-' + d[20:32] + '}')
+  return guid
+
+#------------------------------------------------------------------------------
+
+
+class MSVSSolutionEntry(object):
+  def __cmp__(self, other):
+    # Sort by name then guid (so things are in order on vs2008).
+    return cmp((self.name, self.get_guid()), (other.name, other.get_guid()))
+
+
+class MSVSFolder(MSVSSolutionEntry):
+  """Folder in a Visual Studio project or solution."""
+
+  def __init__(self, path, name = None, entries = None,
+               guid = None, items = None):
+    """Initializes the folder.
+
+    Args:
+      path: Full path to the folder.
+      name: Name of the folder.
+      entries: List of folder entries to nest inside this folder.  May contain
+          Folder or Project objects.  May be None, if the folder is empty.
+      guid: GUID to use for folder, if not None.
+      items: List of solution items to include in the folder project.  May be
+          None, if the folder does not directly contain items.
+    """
+    if name:
+      self.name = name
+    else:
+      # Use last layer.
+      self.name = os.path.basename(path)
+
+    self.path = path
+    self.guid = guid
+
+    # Copy passed lists (or set to empty lists)
+    self.entries = sorted(list(entries or []))
+    self.items = list(items or [])
+
+    self.entry_type_guid = ENTRY_TYPE_GUIDS['folder']
+
+  def get_guid(self):
+    if self.guid is None:
+      # Use consistent guids for folders (so things don't regenerate).
+      self.guid = MakeGuid(self.path, seed='msvs_folder')
+    return self.guid
+
+
+#------------------------------------------------------------------------------
+
+
+class MSVSProject(MSVSSolutionEntry):
+  """Visual Studio project."""
+
+  def __init__(self, path, name = None, dependencies = None, guid = None,
+               spec = None, build_file = None, config_platform_overrides = None,
+               fixpath_prefix = None):
+    """Initializes the project.
+
+    Args:
+      path: Absolute path to the project file.
+      name: Name of project.  If None, the name will be the same as the base
+          name of the project file.
+      dependencies: List of other Project objects this project is dependent
+          upon, if not None.
+      guid: GUID to use for project, if not None.
+      spec: Dictionary specifying how to build this project.
+      build_file: Filename of the .gyp file that the vcproj file comes from.
+      config_platform_overrides: optional dict of configuration platforms to
+          used in place of the default for this target.
+      fixpath_prefix: the path used to adjust the behavior of _fixpath
+    """
+    self.path = path
+    self.guid = guid
+    self.spec = spec
+    self.build_file = build_file
+    # Use project filename if name not specified
+    self.name = name or os.path.splitext(os.path.basename(path))[0]
+
+    # Copy passed lists (or set to empty lists)
+    self.dependencies = list(dependencies or [])
+
+    self.entry_type_guid = ENTRY_TYPE_GUIDS['project']
+
+    if config_platform_overrides:
+      self.config_platform_overrides = config_platform_overrides
+    else:
+      self.config_platform_overrides = {}
+    self.fixpath_prefix = fixpath_prefix
+    self.msbuild_toolset = None
+
+  def set_dependencies(self, dependencies):
+    self.dependencies = list(dependencies or [])
+
+  def get_guid(self):
+    if self.guid is None:
+      # Set GUID from path
+      # TODO(rspangler): This is fragile.
+      # 1. We can't just use the project filename sans path, since there could
+      #    be multiple projects with the same base name (for example,
+      #    foo/unittest.vcproj and bar/unittest.vcproj).
+      # 2. The path needs to be relative to $SOURCE_ROOT, so that the project
+      #    GUID is the same whether it's included from base/base.sln or
+      #    foo/bar/baz/baz.sln.
+      # 3. The GUID needs to be the same each time this builder is invoked, so
+      #    that we don't need to rebuild the solution when the project changes.
+      # 4. We should be able to handle pre-built project files by reading the
+      #    GUID from the files.
+      self.guid = MakeGuid(self.name)
+    return self.guid
+
+  def set_msbuild_toolset(self, msbuild_toolset):
+    self.msbuild_toolset = msbuild_toolset
+
+#------------------------------------------------------------------------------
+
+
+class MSVSSolution:
+  """Visual Studio solution."""
+
+  def __init__(self, path, version, entries=None, variants=None,
+               websiteProperties=True):
+    """Initializes the solution.
+
+    Args:
+      path: Path to solution file.
+      version: Format version to emit.
+      entries: List of entries in solution.  May contain Folder or Project
+          objects.  May be None, if the folder is empty.
+      variants: List of build variant strings.  If none, a default list will
+          be used.
+      websiteProperties: Flag to decide if the website properties section
+          is generated.
+    """
+    self.path = path
+    self.websiteProperties = websiteProperties
+    self.version = version
+
+    # Copy passed lists (or set to empty lists)
+    self.entries = list(entries or [])
+
+    if variants:
+      # Copy passed list
+      self.variants = variants[:]
+    else:
+      # Use default
+      self.variants = ['Debug|Win32', 'Release|Win32']
+    # TODO(rspangler): Need to be able to handle a mapping of solution config
+    # to project config.  Should we be able to handle variants being a dict,
+    # or add a separate variant_map variable?  If it's a dict, we can't
+    # guarantee the order of variants since dict keys aren't ordered.
+
+
+    # TODO(rspangler): Automatically write to disk for now; should delay until
+    # node-evaluation time.
+    self.Write()
+
+
+  def Write(self, writer=gyp.common.WriteOnDiff):
+    """Writes the solution file to disk.
+
+    Raises:
+      IndexError: An entry appears multiple times.
+    """
+    # Walk the entry tree and collect all the folders and projects.
+    all_entries = set()
+    entries_to_check = self.entries[:]
+    while entries_to_check:
+      e = entries_to_check.pop(0)
+
+      # If this entry has been visited, nothing to do.
+      if e in all_entries:
+        continue
+
+      all_entries.add(e)
+
+      # If this is a folder, check its entries too.
+      if isinstance(e, MSVSFolder):
+        entries_to_check += e.entries
+
+    all_entries = sorted(all_entries)
+
+    # Open file and print header
+    f = writer(self.path)
+    f.write('Microsoft Visual Studio Solution File, '
+            'Format Version %s\r\n' % self.version.SolutionVersion())
+    f.write('# %s\r\n' % self.version.Description())
+
+    # Project entries
+    sln_root = os.path.split(self.path)[0]
+    for e in all_entries:
+      relative_path = gyp.common.RelativePath(e.path, sln_root)
+      # msbuild does not accept an empty folder_name.
+      # use '.' in case relative_path is empty.
+      folder_name = relative_path.replace('/', '\\') or '.'
+      f.write('Project("%s") = "%s", "%s", "%s"\r\n' % (
+          e.entry_type_guid,          # Entry type GUID
+          e.name,                     # Folder name
+          folder_name,                # Folder name (again)
+          e.get_guid(),               # Entry GUID
+      ))
+
+      # TODO(rspangler): Need a way to configure this stuff
+      if self.websiteProperties:
+        f.write('\tProjectSection(WebsiteProperties) = preProject\r\n'
+                '\t\tDebug.AspNetCompiler.Debug = "True"\r\n'
+                '\t\tRelease.AspNetCompiler.Debug = "False"\r\n'
+                '\tEndProjectSection\r\n')
+
+      if isinstance(e, MSVSFolder):
+        if e.items:
+          f.write('\tProjectSection(SolutionItems) = preProject\r\n')
+          for i in e.items:
+            f.write('\t\t%s = %s\r\n' % (i, i))
+          f.write('\tEndProjectSection\r\n')
+
+      if isinstance(e, MSVSProject):
+        if e.dependencies:
+          f.write('\tProjectSection(ProjectDependencies) = postProject\r\n')
+          for d in e.dependencies:
+            f.write('\t\t%s = %s\r\n' % (d.get_guid(), d.get_guid()))
+          f.write('\tEndProjectSection\r\n')
+
+      f.write('EndProject\r\n')
+
+    # Global section
+    f.write('Global\r\n')
+
+    # Configurations (variants)
+    f.write('\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\r\n')
+    for v in self.variants:
+      f.write('\t\t%s = %s\r\n' % (v, v))
+    f.write('\tEndGlobalSection\r\n')
+
+    # Sort config guids for easier diffing of solution changes.
+    config_guids = []
+    config_guids_overrides = {}
+    for e in all_entries:
+      if isinstance(e, MSVSProject):
+        config_guids.append(e.get_guid())
+        config_guids_overrides[e.get_guid()] = e.config_platform_overrides
+    config_guids.sort()
+
+    f.write('\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\r\n')
+    for g in config_guids:
+      for v in self.variants:
+        nv = config_guids_overrides[g].get(v, v)
+        # Pick which project configuration to build for this solution
+        # configuration.
+        f.write('\t\t%s.%s.ActiveCfg = %s\r\n' % (
+            g,              # Project GUID
+            v,              # Solution build configuration
+            nv,             # Project build config for that solution config
+        ))
+
+        # Enable project in this solution configuration.
+        f.write('\t\t%s.%s.Build.0 = %s\r\n' % (
+            g,              # Project GUID
+            v,              # Solution build configuration
+            nv,             # Project build config for that solution config
+        ))
+    f.write('\tEndGlobalSection\r\n')
+
+    # TODO(rspangler): Should be able to configure this stuff too (though I've
+    # never seen this be any different)
+    f.write('\tGlobalSection(SolutionProperties) = preSolution\r\n')
+    f.write('\t\tHideSolutionNode = FALSE\r\n')
+    f.write('\tEndGlobalSection\r\n')
+
+    # Folder mappings
+    # TODO(rspangler): Should omit this section if there are no folders
+    f.write('\tGlobalSection(NestedProjects) = preSolution\r\n')
+    for e in all_entries:
+      if not isinstance(e, MSVSFolder):
+        continue        # Does not apply to projects, only folders
+      for subentry in e.entries:
+        f.write('\t\t%s = %s\r\n' % (subentry.get_guid(), e.get_guid()))
+    f.write('\tEndGlobalSection\r\n')
+
+    f.write('EndGlobal\r\n')
+
+    f.close()
diff --git a/webWidgetTCT_device/tools/gyp/pylib/gyp/MSVSProject.py b/webWidgetTCT_device/tools/gyp/pylib/gyp/MSVSProject.py
new file mode 100755 (executable)
index 0000000..db1ceed
--- /dev/null
@@ -0,0 +1,208 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Visual Studio project reader/writer."""
+
+import gyp.common
+import gyp.easy_xml as easy_xml
+
+#------------------------------------------------------------------------------
+
+
+class Tool(object):
+  """Visual Studio tool."""
+
+  def __init__(self, name, attrs=None):
+    """Initializes the tool.
+
+    Args:
+      name: Tool name.
+      attrs: Dict of tool attributes; may be None.
+    """
+    self._attrs = attrs or {}
+    self._attrs['Name'] = name
+
+  def _GetSpecification(self):
+    """Creates an element for the tool.
+
+    Returns:
+      A new xml.dom.Element for the tool.
+    """
+    return ['Tool', self._attrs]
+
+class Filter(object):
+  """Visual Studio filter - that is, a virtual folder."""
+
+  def __init__(self, name, contents=None):
+    """Initializes the folder.
+
+    Args:
+      name: Filter (folder) name.
+      contents: List of filenames and/or Filter objects contained.
+    """
+    self.name = name
+    self.contents = list(contents or [])
+
+
+#------------------------------------------------------------------------------
+
+
+class Writer(object):
+  """Visual Studio XML project writer."""
+
+  def __init__(self, project_path, version, name, guid=None, platforms=None):
+    """Initializes the project.
+
+    Args:
+      project_path: Path to the project file.
+      version: Format version to emit.
+      name: Name of the project.
+      guid: GUID to use for project, if not None.
+      platforms: Array of string, the supported platforms.  If null, ['Win32']
+    """
+    self.project_path = project_path
+    self.version = version
+    self.name = name
+    self.guid = guid
+
+    # Default to Win32 for platforms.
+    if not platforms:
+      platforms = ['Win32']
+
+    # Initialize the specifications of the various sections.
+    self.platform_section = ['Platforms']
+    for platform in platforms:
+      self.platform_section.append(['Platform', {'Name': platform}])
+    self.tool_files_section = ['ToolFiles']
+    self.configurations_section = ['Configurations']
+    self.files_section = ['Files']
+
+    # Keep a dict keyed on filename to speed up access.
+    self.files_dict = dict()
+
+  def AddToolFile(self, path):
+    """Adds a tool file to the project.
+
+    Args:
+      path: Relative path from project to tool file.
+    """
+    self.tool_files_section.append(['ToolFile', {'RelativePath': path}])
+
+  def _GetSpecForConfiguration(self, config_type, config_name, attrs, tools):
+    """Returns the specification for a configuration.
+
+    Args:
+      config_type: Type of configuration node.
+      config_name: Configuration name.
+      attrs: Dict of configuration attributes; may be None.
+      tools: List of tools (strings or Tool objects); may be None.
+    Returns:
+    """
+    # Handle defaults
+    if not attrs:
+      attrs = {}
+    if not tools:
+      tools = []
+
+    # Add configuration node and its attributes
+    node_attrs = attrs.copy()
+    node_attrs['Name'] = config_name
+    specification = [config_type, node_attrs]
+
+    # Add tool nodes and their attributes
+    if tools:
+      for t in tools:
+        if isinstance(t, Tool):
+          specification.append(t._GetSpecification())
+        else:
+          specification.append(Tool(t)._GetSpecification())
+    return specification
+
+
+  def AddConfig(self, name, attrs=None, tools=None):
+    """Adds a configuration to the project.
+
+    Args:
+      name: Configuration name.
+      attrs: Dict of configuration attributes; may be None.
+      tools: List of tools (strings or Tool objects); may be None.
+    """
+    spec = self._GetSpecForConfiguration('Configuration', name, attrs, tools)
+    self.configurations_section.append(spec)
+
+  def _AddFilesToNode(self, parent, files):
+    """Adds files and/or filters to the parent node.
+
+    Args:
+      parent: Destination node
+      files: A list of Filter objects and/or relative paths to files.
+
+    Will call itself recursively, if the files list contains Filter objects.
+    """
+    for f in files:
+      if isinstance(f, Filter):
+        node = ['Filter', {'Name': f.name}]
+        self._AddFilesToNode(node, f.contents)
+      else:
+        node = ['File', {'RelativePath': f}]
+        self.files_dict[f] = node
+      parent.append(node)
+
+  def AddFiles(self, files):
+    """Adds files to the project.
+
+    Args:
+      files: A list of Filter objects and/or relative paths to files.
+
+    This makes a copy of the file/filter tree at the time of this call.  If you
+    later add files to a Filter object which was passed into a previous call
+    to AddFiles(), it will not be reflected in this project.
+    """
+    self._AddFilesToNode(self.files_section, files)
+    # TODO(rspangler) This also doesn't handle adding files to an existing
+    # filter.  That is, it doesn't merge the trees.
+
+  def AddFileConfig(self, path, config, attrs=None, tools=None):
+    """Adds a configuration to a file.
+
+    Args:
+      path: Relative path to the file.
+      config: Name of configuration to add.
+      attrs: Dict of configuration attributes; may be None.
+      tools: List of tools (strings or Tool objects); may be None.
+
+    Raises:
+      ValueError: Relative path does not match any file added via AddFiles().
+    """
+    # Find the file node with the right relative path
+    parent = self.files_dict.get(path)
+    if not parent:
+      raise ValueError('AddFileConfig: file "%s" not in project.' % path)
+
+    # Add the config to the file node
+    spec = self._GetSpecForConfiguration('FileConfiguration', config, attrs,
+                                         tools)
+    parent.append(spec)
+
+  def WriteIfChanged(self):
+    """Writes the project file."""
+    # First create XML content definition
+    content = [
+        'VisualStudioProject',
+        {'ProjectType': 'Visual C++',
+         'Version': self.version.ProjectVersion(),
+         'Name': self.name,
+         'ProjectGUID': self.guid,
+         'RootNamespace': self.name,
+         'Keyword': 'Win32Proj'
+        },
+        self.platform_section,
+        self.tool_files_section,
+        self.configurations_section,
+        ['References'],  # empty section
+        self.files_section,
+        ['Globals']  # empty section
+    ]
+    easy_xml.WriteXmlIfChanged(content, self.project_path,
+                               encoding="Windows-1252")
diff --git a/webWidgetTCT_device/tools/gyp/pylib/gyp/MSVSSettings.py b/webWidgetTCT_device/tools/gyp/pylib/gyp/MSVSSettings.py
new file mode 100755 (executable)
index 0000000..d0d4990
--- /dev/null
@@ -0,0 +1,1046 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Code to validate and convert settings of the Microsoft build tools.
+
+This file contains code to validate and convert settings of the Microsoft
+build tools.  The function ConvertToMSBuildSettings(), ValidateMSVSSettings(),
+and ValidateMSBuildSettings() are the entry points.
+
+This file was created by comparing the projects created by Visual Studio 2008
+and Visual Studio 2010 for all available settings through the user interface.
+The MSBuild schemas were also considered.  They are typically found in the
+MSBuild install directory, e.g. c:\Program Files (x86)\MSBuild
+"""
+
+import sys
+import re
+
+# Dictionaries of settings validators. The key is the tool name, the value is
+# a dictionary mapping setting names to validation functions.
+_msvs_validators = {}
+_msbuild_validators = {}
+
+
+# A dictionary of settings converters. The key is the tool name, the value is
+# a dictionary mapping setting names to conversion functions.
+_msvs_to_msbuild_converters = {}
+
+
+# Tool name mapping from MSVS to MSBuild.
+_msbuild_name_of_tool = {}
+
+
+class _Tool(object):
+  """Represents a tool used by MSVS or MSBuild.
+
+  Attributes:
+      msvs_name: The name of the tool in MSVS.
+      msbuild_name: The name of the tool in MSBuild.
+  """
+
+  def __init__(self, msvs_name, msbuild_name):
+    self.msvs_name = msvs_name
+    self.msbuild_name = msbuild_name
+
+
+def _AddTool(tool):
+  """Adds a tool to the four dictionaries used to process settings.
+
+  This only defines the tool.  Each setting also needs to be added.
+
+  Args:
+    tool: The _Tool object to be added.
+  """
+  _msvs_validators[tool.msvs_name] = {}
+  _msbuild_validators[tool.msbuild_name] = {}
+  _msvs_to_msbuild_converters[tool.msvs_name] = {}
+  _msbuild_name_of_tool[tool.msvs_name] = tool.msbuild_name
+
+
+def _GetMSBuildToolSettings(msbuild_settings, tool):
+  """Returns an MSBuild tool dictionary.  Creates it if needed."""
+  return msbuild_settings.setdefault(tool.msbuild_name, {})
+
+
+class _Type(object):
+  """Type of settings (Base class)."""
+
+  def ValidateMSVS(self, value):
+    """Verifies that the value is legal for MSVS.
+
+    Args:
+      value: the value to check for this type.
+
+    Raises:
+      ValueError if value is not valid for MSVS.
+    """
+
+  def ValidateMSBuild(self, value):
+    """Verifies that the value is legal for MSBuild.
+
+    Args:
+      value: the value to check for this type.
+
+    Raises:
+      ValueError if value is not valid for MSBuild.
+    """
+
+  def ConvertToMSBuild(self, value):
+    """Returns the MSBuild equivalent of the MSVS value given.
+
+    Args:
+      value: the MSVS value to convert.
+
+    Returns:
+      the MSBuild equivalent.
+
+    Raises:
+      ValueError if value is not valid.
+    """
+    return value
+
+
+class _String(_Type):
+  """A setting that's just a string."""
+
+  def ValidateMSVS(self, value):
+    if not isinstance(value, basestring):
+      raise ValueError('expected string; got %r' % value)
+
+  def ValidateMSBuild(self, value):
+    if not isinstance(value, basestring):
+      raise ValueError('expected string; got %r' % value)
+
+  def ConvertToMSBuild(self, value):
+    # Convert the macros
+    return ConvertVCMacrosToMSBuild(value)
+
+
+class _StringList(_Type):
+  """A settings that's a list of strings."""
+
+  def ValidateMSVS(self, value):
+    if not isinstance(value, basestring) and not isinstance(value, list):
+      raise ValueError('expected string list; got %r' % value)
+
+  def ValidateMSBuild(self, value):
+    if not isinstance(value, basestring) and not isinstance(value, list):
+      raise ValueError('expected string list; got %r' % value)
+
+  def ConvertToMSBuild(self, value):
+    # Convert the macros
+    if isinstance(value, list):
+      return [ConvertVCMacrosToMSBuild(i) for i in value]
+    else:
+      return ConvertVCMacrosToMSBuild(value)
+
+
+class _Boolean(_Type):
+  """Boolean settings, can have the values 'false' or 'true'."""
+
+  def _Validate(self, value):
+    if value != 'true' and value != 'false':
+      raise ValueError('expected bool; got %r' % value)
+
+  def ValidateMSVS(self, value):
+    self._Validate(value)
+
+  def ValidateMSBuild(self, value):
+    self._Validate(value)
+
+  def ConvertToMSBuild(self, value):
+    self._Validate(value)
+    return value
+
+
+class _Integer(_Type):
+  """Integer settings."""
+
+  def __init__(self, msbuild_base=10):
+    _Type.__init__(self)
+    self._msbuild_base = msbuild_base
+
+  def ValidateMSVS(self, value):
+    # Try to convert, this will raise ValueError if invalid.
+    self.ConvertToMSBuild(value)
+
+  def ValidateMSBuild(self, value):
+    # Try to convert, this will raise ValueError if invalid.
+    int(value, self._msbuild_base)
+
+  def ConvertToMSBuild(self, value):
+    msbuild_format = (self._msbuild_base == 10) and '%d' or '0x%04x'
+    return msbuild_format % int(value)
+
+
+class _Enumeration(_Type):
+  """Type of settings that is an enumeration.
+
+  In MSVS, the values are indexes like '0', '1', and '2'.
+  MSBuild uses text labels that are more representative, like 'Win32'.
+
+  Constructor args:
+    label_list: an array of MSBuild labels that correspond to the MSVS index.
+        In the rare cases where MSVS has skipped an index value, None is
+        used in the array to indicate the unused spot.
+    new: an array of labels that are new to MSBuild.
+  """
+
+  def __init__(self, label_list, new=None):
+    _Type.__init__(self)
+    self._label_list = label_list
+    self._msbuild_values = set(value for value in label_list
+                               if value is not None)
+    if new is not None:
+      self._msbuild_values.update(new)
+
+  def ValidateMSVS(self, value):
+    # Try to convert.  It will raise an exception if not valid.
+    self.ConvertToMSBuild(value)
+
+  def ValidateMSBuild(self, value):
+    if value not in self._msbuild_values:
+      raise ValueError('unrecognized enumerated value %s' % value)
+
+  def ConvertToMSBuild(self, value):
+    index = int(value)
+    if index < 0 or index >= len(self._label_list):
+      raise ValueError('index value (%d) not in expected range [0, %d)' %
+                       (index, len(self._label_list)))
+    label = self._label_list[index]
+    if label is None:
+      raise ValueError('converted value for %s not specified.' % value)
+    return label
+
+
+# Instantiate the various generic types.
+_boolean = _Boolean()
+_integer = _Integer()
+# For now, we don't do any special validation on these types:
+_string = _String()
+_file_name = _String()
+_folder_name = _String()
+_file_list = _StringList()
+_folder_list = _StringList()
+_string_list = _StringList()
+# Some boolean settings went from numerical values to boolean.  The
+# mapping is 0: default, 1: false, 2: true.
+_newly_boolean = _Enumeration(['', 'false', 'true'])
+
+
+def _Same(tool, name, setting_type):
+  """Defines a setting that has the same name in MSVS and MSBuild.
+
+  Args:
+    tool: a dictionary that gives the names of the tool for MSVS and MSBuild.
+    name: the name of the setting.
+    setting_type: the type of this setting.
+  """
+  _Renamed(tool, name, name, setting_type)
+
+
+def _Renamed(tool, msvs_name, msbuild_name, setting_type):
+  """Defines a setting for which the name has changed.
+
+  Args:
+    tool: a dictionary that gives the names of the tool for MSVS and MSBuild.
+    msvs_name: the name of the MSVS setting.
+    msbuild_name: the name of the MSBuild setting.
+    setting_type: the type of this setting.
+  """
+
+  def _Translate(value, msbuild_settings):
+    msbuild_tool_settings = _GetMSBuildToolSettings(msbuild_settings, tool)
+    msbuild_tool_settings[msbuild_name] = setting_type.ConvertToMSBuild(value)
+
+  _msvs_validators[tool.msvs_name][msvs_name] = setting_type.ValidateMSVS
+  _msbuild_validators[tool.msbuild_name][msbuild_name] = (
+      setting_type.ValidateMSBuild)
+  _msvs_to_msbuild_converters[tool.msvs_name][msvs_name] = _Translate
+
+
+def _Moved(tool, settings_name, msbuild_tool_name, setting_type):
+  _MovedAndRenamed(tool, settings_name, msbuild_tool_name, settings_name,
+                   setting_type)
+
+
+def _MovedAndRenamed(tool, msvs_settings_name, msbuild_tool_name,
+                     msbuild_settings_name, setting_type):
+  """Defines a setting that may have moved to a new section.
+
+  Args:
+    tool: a dictionary that gives the names of the tool for MSVS and MSBuild.
+    msvs_settings_name: the MSVS name of the setting.
+    msbuild_tool_name: the name of the MSBuild tool to place the setting under.
+    msbuild_settings_name: the MSBuild name of the setting.
+    setting_type: the type of this setting.
+  """
+
+  def _Translate(value, msbuild_settings):
+    tool_settings = msbuild_settings.setdefault(msbuild_tool_name, {})
+    tool_settings[msbuild_settings_name] = setting_type.ConvertToMSBuild(value)
+
+  _msvs_validators[tool.msvs_name][msvs_settings_name] = (
+      setting_type.ValidateMSVS)
+  validator = setting_type.ValidateMSBuild
+  _msbuild_validators[msbuild_tool_name][msbuild_settings_name] = validator
+  _msvs_to_msbuild_converters[tool.msvs_name][msvs_settings_name] = _Translate
+
+
+def _MSVSOnly(tool, name, setting_type):
+  """Defines a setting that is only found in MSVS.
+
+  Args:
+    tool: a dictionary that gives the names of the tool for MSVS and MSBuild.
+    name: the name of the setting.
+    setting_type: the type of this setting.
+  """
+
+  def _Translate(unused_value, unused_msbuild_settings):
+    # Since this is for MSVS only settings, no translation will happen.
+    pass
+
+  _msvs_validators[tool.msvs_name][name] = setting_type.ValidateMSVS
+  _msvs_to_msbuild_converters[tool.msvs_name][name] = _Translate
+
+
+def _MSBuildOnly(tool, name, setting_type):
+  """Defines a setting that is only found in MSBuild.
+
+  Args:
+    tool: a dictionary that gives the names of the tool for MSVS and MSBuild.
+    name: the name of the setting.
+    setting_type: the type of this setting.
+  """
+  _msbuild_validators[tool.msbuild_name][name] = setting_type.ValidateMSBuild
+
+
+def _ConvertedToAdditionalOption(tool, msvs_name, flag):
+  """Defines a setting that's handled via a command line option in MSBuild.
+
+  Args:
+    tool: a dictionary that gives the names of the tool for MSVS and MSBuild.
+    msvs_name: the name of the MSVS setting that if 'true' becomes a flag
+    flag: the flag to insert at the end of the AdditionalOptions
+  """
+
+  def _Translate(value, msbuild_settings):
+    if value == 'true':
+      tool_settings = _GetMSBuildToolSettings(msbuild_settings, tool)
+      if 'AdditionalOptions' in tool_settings:
+        new_flags = '%s %s' % (tool_settings['AdditionalOptions'], flag)
+      else:
+        new_flags = flag
+      tool_settings['AdditionalOptions'] = new_flags
+  _msvs_validators[tool.msvs_name][msvs_name] = _boolean.ValidateMSVS
+  _msvs_to_msbuild_converters[tool.msvs_name][msvs_name] = _Translate
+
+
+def _CustomGeneratePreprocessedFile(tool, msvs_name):
+  def _Translate(value, msbuild_settings):
+    tool_settings = _GetMSBuildToolSettings(msbuild_settings, tool)
+    if value == '0':
+      tool_settings['PreprocessToFile'] = 'false'
+      tool_settings['PreprocessSuppressLineNumbers'] = 'false'
+    elif value == '1':  # /P
+      tool_settings['PreprocessToFile'] = 'true'
+      tool_settings['PreprocessSuppressLineNumbers'] = 'false'
+    elif value == '2':  # /EP /P
+      tool_settings['PreprocessToFile'] = 'true'
+      tool_settings['PreprocessSuppressLineNumbers'] = 'true'
+    else:
+      raise ValueError('value must be one of [0, 1, 2]; got %s' % value)
+  # Create a bogus validator that looks for '0', '1', or '2'
+  msvs_validator = _Enumeration(['a', 'b', 'c']).ValidateMSVS
+  _msvs_validators[tool.msvs_name][msvs_name] = msvs_validator
+  msbuild_validator = _boolean.ValidateMSBuild
+  msbuild_tool_validators = _msbuild_validators[tool.msbuild_name]
+  msbuild_tool_validators['PreprocessToFile'] = msbuild_validator
+  msbuild_tool_validators['PreprocessSuppressLineNumbers'] = msbuild_validator
+  _msvs_to_msbuild_converters[tool.msvs_name][msvs_name] = _Translate
+
+
+fix_vc_macro_slashes_regex_list = ('IntDir', 'OutDir')
+fix_vc_macro_slashes_regex = re.compile(
+  r'(\$\((?:%s)\))(?:[\\/]+)' % "|".join(fix_vc_macro_slashes_regex_list)
+)
+
+def FixVCMacroSlashes(s):
+  """Replace macros which have excessive following slashes.
+
+  These macros are known to have a built-in trailing slash. Furthermore, many
+  scripts hiccup on processing paths with extra slashes in the middle.
+
+  This list is probably not exhaustive.  Add as needed.
+  """
+  if '$' in s:
+    s = fix_vc_macro_slashes_regex.sub(r'\1', s)
+  return s
+
+
+def ConvertVCMacrosToMSBuild(s):
+  """Convert the the MSVS macros found in the string to the MSBuild equivalent.
+
+  This list is probably not exhaustive.  Add as needed.
+  """
+  if '$' in s:
+    replace_map = {
+        '$(ConfigurationName)': '$(Configuration)',
+        '$(InputDir)': '%(RootDir)%(Directory)',
+        '$(InputExt)': '%(Extension)',
+        '$(InputFileName)': '%(Filename)%(Extension)',
+        '$(InputName)': '%(Filename)',
+        '$(InputPath)': '%(FullPath)',
+        '$(ParentName)': '$(ProjectFileName)',
+        '$(PlatformName)': '$(Platform)',
+        '$(SafeInputName)': '%(Filename)',
+    }
+    for old, new in replace_map.iteritems():
+      s = s.replace(old, new)
+    s = FixVCMacroSlashes(s)
+  return s
+
+
+def ConvertToMSBuildSettings(msvs_settings, stderr=sys.stderr):
+  """Converts MSVS settings (VS2008 and earlier) to MSBuild settings (VS2010+).
+
+  Args:
+      msvs_settings: A dictionary.  The key is the tool name.  The values are
+          themselves dictionaries of settings and their values.
+      stderr: The stream receiving the error messages.
+
+  Returns:
+      A dictionary of MSBuild settings.  The key is either the MSBuild tool name
+      or the empty string (for the global settings).  The values are themselves
+      dictionaries of settings and their values.
+  """
+  msbuild_settings = {}
+  for msvs_tool_name, msvs_tool_settings in msvs_settings.iteritems():
+    if msvs_tool_name in _msvs_to_msbuild_converters:
+      msvs_tool = _msvs_to_msbuild_converters[msvs_tool_name]
+      for msvs_setting, msvs_value in msvs_tool_settings.iteritems():
+        if msvs_setting in msvs_tool:
+          # Invoke the translation function.
+          try:
+            msvs_tool[msvs_setting](msvs_value, msbuild_settings)
+          except ValueError, e:
+            print >> stderr, ('Warning: while converting %s/%s to MSBuild, '
+                              '%s' % (msvs_tool_name, msvs_setting, e))
+        else:
+          # We don't know this setting.  Give a warning.
+          print >> stderr, ('Warning: unrecognized setting %s/%s '
+                            'while converting to MSBuild.' %
+                            (msvs_tool_name, msvs_setting))
+    else:
+      print >> stderr, ('Warning: unrecognized tool %s while converting to '
+                        'MSBuild.' % msvs_tool_name)
+  return msbuild_settings
+
+
+def ValidateMSVSSettings(settings, stderr=sys.stderr):
+  """Validates that the names of the settings are valid for MSVS.
+
+  Args:
+      settings: A dictionary.  The key is the tool name.  The values are
+          themselves dictionaries of settings and their values.
+      stderr: The stream receiving the error messages.
+  """
+  _ValidateSettings(_msvs_validators, settings, stderr)
+
+
+def ValidateMSBuildSettings(settings, stderr=sys.stderr):
+  """Validates that the names of the settings are valid for MSBuild.
+
+  Args:
+      settings: A dictionary.  The key is the tool name.  The values are
+          themselves dictionaries of settings and their values.
+      stderr: The stream receiving the error messages.
+  """
+  _ValidateSettings(_msbuild_validators, settings, stderr)
+
+
+def _ValidateSettings(validators, settings, stderr):
+  """Validates that the settings are valid for MSBuild or MSVS.
+
+  We currently only validate the names of the settings, not their values.
+
+  Args:
+      validators: A dictionary of tools and their validators.
+      settings: A dictionary.  The key is the tool name.  The values are
+          themselves dictionaries of settings and their values.
+      stderr: The stream receiving the error messages.
+  """
+  for tool_name in settings:
+    if tool_name in validators:
+      tool_validators = validators[tool_name]
+      for setting, value in settings[tool_name].iteritems():
+        if setting in tool_validators:
+          try:
+            tool_validators[setting](value)
+          except ValueError, e:
+            print >> stderr, ('Warning: for %s/%s, %s' %
+                              (tool_name, setting, e))
+        else:
+          print >> stderr, ('Warning: unrecognized setting %s/%s' %
+                            (tool_name, setting))
+    else:
+      print >> stderr, ('Warning: unrecognized tool %s' % tool_name)
+
+
+# MSVS and MBuild names of the tools.
+_compile = _Tool('VCCLCompilerTool', 'ClCompile')
+_link = _Tool('VCLinkerTool', 'Link')
+_midl = _Tool('VCMIDLTool', 'Midl')
+_rc = _Tool('VCResourceCompilerTool', 'ResourceCompile')
+_lib = _Tool('VCLibrarianTool', 'Lib')
+_manifest = _Tool('VCManifestTool', 'Manifest')
+
+
+_AddTool(_compile)
+_AddTool(_link)
+_AddTool(_midl)
+_AddTool(_rc)
+_AddTool(_lib)
+_AddTool(_manifest)
+# Add sections only found in the MSBuild settings.
+_msbuild_validators[''] = {}
+_msbuild_validators['ProjectReference'] = {}
+_msbuild_validators['ManifestResourceCompile'] = {}
+
+# Descriptions of the compiler options, i.e. VCCLCompilerTool in MSVS and
+# ClCompile in MSBuild.
+# See "c:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\1033\cl.xml" for
+# the schema of the MSBuild ClCompile settings.
+
+# Options that have the same name in MSVS and MSBuild
+_Same(_compile, 'AdditionalIncludeDirectories', _folder_list)  # /I
+_Same(_compile, 'AdditionalOptions', _string_list)
+_Same(_compile, 'AdditionalUsingDirectories', _folder_list)  # /AI
+_Same(_compile, 'AssemblerListingLocation', _file_name)  # /Fa
+_Same(_compile, 'BrowseInformationFile', _file_name)
+_Same(_compile, 'BufferSecurityCheck', _boolean)  # /GS
+_Same(_compile, 'DisableLanguageExtensions', _boolean)  # /Za
+_Same(_compile, 'DisableSpecificWarnings', _string_list)  # /wd
+_Same(_compile, 'EnableFiberSafeOptimizations', _boolean)  # /GT
+_Same(_compile, 'EnablePREfast', _boolean)  # /analyze Visible='false'
+_Same(_compile, 'ExpandAttributedSource', _boolean)  # /Fx
+_Same(_compile, 'FloatingPointExceptions', _boolean)  # /fp:except
+_Same(_compile, 'ForceConformanceInForLoopScope', _boolean)  # /Zc:forScope
+_Same(_compile, 'ForcedIncludeFiles', _file_list)  # /FI
+_Same(_compile, 'ForcedUsingFiles', _file_list)  # /FU
+_Same(_compile, 'GenerateXMLDocumentationFiles', _boolean)  # /doc
+_Same(_compile, 'IgnoreStandardIncludePath', _boolean)  # /X
+_Same(_compile, 'MinimalRebuild', _boolean)  # /Gm
+_Same(_compile, 'OmitDefaultLibName', _boolean)  # /Zl
+_Same(_compile, 'OmitFramePointers', _boolean)  # /Oy
+_Same(_compile, 'PreprocessorDefinitions', _string_list)  # /D
+_Same(_compile, 'ProgramDataBaseFileName', _file_name)  # /Fd
+_Same(_compile, 'RuntimeTypeInfo', _boolean)  # /GR
+_Same(_compile, 'ShowIncludes', _boolean)  # /showIncludes
+_Same(_compile, 'SmallerTypeCheck', _boolean)  # /RTCc
+_Same(_compile, 'StringPooling', _boolean)  # /GF
+_Same(_compile, 'SuppressStartupBanner', _boolean)  # /nologo
+_Same(_compile, 'TreatWChar_tAsBuiltInType', _boolean)  # /Zc:wchar_t
+_Same(_compile, 'UndefineAllPreprocessorDefinitions', _boolean)  # /u
+_Same(_compile, 'UndefinePreprocessorDefinitions', _string_list)  # /U
+_Same(_compile, 'UseFullPaths', _boolean)  # /FC
+_Same(_compile, 'WholeProgramOptimization', _boolean)  # /GL
+_Same(_compile, 'XMLDocumentationFileName', _file_name)
+
+_Same(_compile, 'AssemblerOutput',
+      _Enumeration(['NoListing',
+                    'AssemblyCode',  # /FA
+                    'All',  # /FAcs
+                    'AssemblyAndMachineCode',  # /FAc
+                    'AssemblyAndSourceCode']))  # /FAs
+_Same(_compile, 'BasicRuntimeChecks',
+      _Enumeration(['Default',
+                    'StackFrameRuntimeCheck',  # /RTCs
+                    'UninitializedLocalUsageCheck',  # /RTCu
+                    'EnableFastChecks']))  # /RTC1
+_Same(_compile, 'BrowseInformation',
+      _Enumeration(['false',
+                    'true',  # /FR
+                    'true']))  # /Fr
+_Same(_compile, 'CallingConvention',
+      _Enumeration(['Cdecl',  # /Gd
+                    'FastCall',  # /Gr
+                    'StdCall']))  # /Gz
+_Same(_compile, 'CompileAs',
+      _Enumeration(['Default',
+                    'CompileAsC',  # /TC
+                    'CompileAsCpp']))  # /TP
+_Same(_compile, 'DebugInformationFormat',
+      _Enumeration(['',  # Disabled
+                    'OldStyle',  # /Z7
+                    None,
+                    'ProgramDatabase',  # /Zi
+                    'EditAndContinue']))  # /ZI
+_Same(_compile, 'EnableEnhancedInstructionSet',
+      _Enumeration(['NotSet',
+                    'StreamingSIMDExtensions',  # /arch:SSE
+                    'StreamingSIMDExtensions2']))  # /arch:SSE2
+_Same(_compile, 'ErrorReporting',
+      _Enumeration(['None',  # /errorReport:none
+                    'Prompt',  # /errorReport:prompt
+                    'Queue'],  # /errorReport:queue
+                   new=['Send']))  # /errorReport:send"
+_Same(_compile, 'ExceptionHandling',
+      _Enumeration(['false',
+                    'Sync',  # /EHsc
+                    'Async'],  # /EHa
+                   new=['SyncCThrow']))  # /EHs
+_Same(_compile, 'FavorSizeOrSpeed',
+      _Enumeration(['Neither',
+                    'Speed',  # /Ot
+                    'Size']))  # /Os
+_Same(_compile, 'FloatingPointModel',
+      _Enumeration(['Precise',  # /fp:precise
+                    'Strict',  # /fp:strict
+                    'Fast']))  # /fp:fast
+_Same(_compile, 'InlineFunctionExpansion',
+      _Enumeration(['Default',
+                    'OnlyExplicitInline',  # /Ob1
+                    'AnySuitable'],  # /Ob2
+                   new=['Disabled']))  # /Ob0
+_Same(_compile, 'Optimization',
+      _Enumeration(['Disabled',  # /Od
+                    'MinSpace',  # /O1
+                    'MaxSpeed',  # /O2
+                    'Full']))  # /Ox
+_Same(_compile, 'RuntimeLibrary',
+      _Enumeration(['MultiThreaded',  # /MT
+                    'MultiThreadedDebug',  # /MTd
+                    'MultiThreadedDLL',  # /MD
+                    'MultiThreadedDebugDLL']))  # /MDd
+_Same(_compile, 'StructMemberAlignment',
+      _Enumeration(['Default',
+                    '1Byte',  # /Zp1
+                    '2Bytes',  # /Zp2
+                    '4Bytes',  # /Zp4
+                    '8Bytes',  # /Zp8
+                    '16Bytes']))  # /Zp16
+_Same(_compile, 'WarningLevel',
+      _Enumeration(['TurnOffAllWarnings',  # /W0
+                    'Level1',  # /W1
+                    'Level2',  # /W2
+                    'Level3',  # /W3
+                    'Level4'],  # /W4
+                   new=['EnableAllWarnings']))  # /Wall
+
+# Options found in MSVS that have been renamed in MSBuild.
+_Renamed(_compile, 'EnableFunctionLevelLinking', 'FunctionLevelLinking',
+         _boolean)  # /Gy
+_Renamed(_compile, 'EnableIntrinsicFunctions', 'IntrinsicFunctions',
+         _boolean)  # /Oi
+_Renamed(_compile, 'KeepComments', 'PreprocessKeepComments', _boolean)  # /C
+_Renamed(_compile, 'ObjectFile', 'ObjectFileName', _file_name)  # /Fo
+_Renamed(_compile, 'OpenMP', 'OpenMPSupport', _boolean)  # /openmp
+_Renamed(_compile, 'PrecompiledHeaderThrough', 'PrecompiledHeaderFile',
+         _file_name)  # Used with /Yc and /Yu
+_Renamed(_compile, 'PrecompiledHeaderFile', 'PrecompiledHeaderOutputFile',
+         _file_name)  # /Fp
+_Renamed(_compile, 'UsePrecompiledHeader', 'PrecompiledHeader',
+         _Enumeration(['NotUsing',  # VS recognized '' for this value too.
+                       'Create',   # /Yc
+                       'Use']))  # /Yu
+_Renamed(_compile, 'WarnAsError', 'TreatWarningAsError', _boolean)  # /WX
+
+_ConvertedToAdditionalOption(_compile, 'DefaultCharIsUnsigned', '/J')
+
+# MSVS options not found in MSBuild.
+_MSVSOnly(_compile, 'Detect64BitPortabilityProblems', _boolean)
+_MSVSOnly(_compile, 'UseUnicodeResponseFiles', _boolean)
+
+# MSBuild options not found in MSVS.
+_MSBuildOnly(_compile, 'BuildingInIDE', _boolean)
+_MSBuildOnly(_compile, 'CompileAsManaged',
+             _Enumeration([], new=['false',
+                                   'true',  # /clr
+                                   'Pure',  # /clr:pure
+                                   'Safe',  # /clr:safe
+                                   'OldSyntax']))  # /clr:oldSyntax
+_MSBuildOnly(_compile, 'CreateHotpatchableImage', _boolean)  # /hotpatch
+_MSBuildOnly(_compile, 'MultiProcessorCompilation', _boolean)  # /MP
+_MSBuildOnly(_compile, 'PreprocessOutputPath', _string)  # /Fi
+_MSBuildOnly(_compile, 'ProcessorNumber', _integer)  # the number of processors
+_MSBuildOnly(_compile, 'TrackerLogDirectory', _folder_name)
+_MSBuildOnly(_compile, 'TreatSpecificWarningsAsErrors', _string_list)  # /we
+_MSBuildOnly(_compile, 'UseUnicodeForAssemblerListing', _boolean)  # /FAu
+
+# Defines a setting that needs very customized processing
+_CustomGeneratePreprocessedFile(_compile, 'GeneratePreprocessedFile')
+
+
+# Directives for converting MSVS VCLinkerTool to MSBuild Link.
+# See "c:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\1033\link.xml" for
+# the schema of the MSBuild Link settings.
+
+# Options that have the same name in MSVS and MSBuild
+_Same(_link, 'AdditionalDependencies', _file_list)
+_Same(_link, 'AdditionalLibraryDirectories', _folder_list)  # /LIBPATH
+#  /MANIFESTDEPENDENCY:
+_Same(_link, 'AdditionalManifestDependencies', _file_list)
+_Same(_link, 'AdditionalOptions', _string_list)
+_Same(_link, 'AddModuleNamesToAssembly', _file_list)  # /ASSEMBLYMODULE
+_Same(_link, 'AllowIsolation', _boolean)  # /ALLOWISOLATION
+_Same(_link, 'AssemblyLinkResource', _file_list)  # /ASSEMBLYLINKRESOURCE
+_Same(_link, 'BaseAddress', _string)  # /BASE
+_Same(_link, 'CLRUnmanagedCodeCheck', _boolean)  # /CLRUNMANAGEDCODECHECK
+_Same(_link, 'DelayLoadDLLs', _file_list)  # /DELAYLOAD
+_Same(_link, 'DelaySign', _boolean)  # /DELAYSIGN
+_Same(_link, 'EmbedManagedResourceFile', _file_list)  # /ASSEMBLYRESOURCE
+_Same(_link, 'EnableUAC', _boolean)  # /MANIFESTUAC
+_Same(_link, 'EntryPointSymbol', _string)  # /ENTRY
+_Same(_link, 'ForceSymbolReferences', _file_list)  # /INCLUDE
+_Same(_link, 'FunctionOrder', _file_name)  # /ORDER
+_Same(_link, 'GenerateDebugInformation', _boolean)  # /DEBUG
+_Same(_link, 'GenerateMapFile', _boolean)  # /MAP
+_Same(_link, 'HeapCommitSize', _string)
+_Same(_link, 'HeapReserveSize', _string)  # /HEAP
+_Same(_link, 'IgnoreAllDefaultLibraries', _boolean)  # /NODEFAULTLIB
+_Same(_link, 'IgnoreEmbeddedIDL', _boolean)  # /IGNOREIDL
+_Same(_link, 'ImportLibrary', _file_name)  # /IMPLIB
+_Same(_link, 'KeyContainer', _file_name)  # /KEYCONTAINER
+_Same(_link, 'KeyFile', _file_name)  # /KEYFILE
+_Same(_link, 'ManifestFile', _file_name)  # /ManifestFile
+_Same(_link, 'MapExports', _boolean)  # /MAPINFO:EXPORTS
+_Same(_link, 'MapFileName', _file_name)
+_Same(_link, 'MergedIDLBaseFileName', _file_name)  # /IDLOUT
+_Same(_link, 'MergeSections', _string)  # /MERGE
+_Same(_link, 'MidlCommandFile', _file_name)  # /MIDL
+_Same(_link, 'ModuleDefinitionFile', _file_name)  # /DEF
+_Same(_link, 'OutputFile', _file_name)  # /OUT
+_Same(_link, 'PerUserRedirection', _boolean)
+_Same(_link, 'Profile', _boolean)  # /PROFILE
+_Same(_link, 'ProfileGuidedDatabase', _file_name)  # /PGD
+_Same(_link, 'ProgramDatabaseFile', _file_name)  # /PDB
+_Same(_link, 'RegisterOutput', _boolean)
+_Same(_link, 'SetChecksum', _boolean)  # /RELEASE
+_Same(_link, 'StackCommitSize', _string)
+_Same(_link, 'StackReserveSize', _string)  # /STACK
+_Same(_link, 'StripPrivateSymbols', _file_name)  # /PDBSTRIPPED
+_Same(_link, 'SupportUnloadOfDelayLoadedDLL', _boolean)  # /DELAY:UNLOAD
+_Same(_link, 'SuppressStartupBanner', _boolean)  # /NOLOGO
+_Same(_link, 'SwapRunFromCD', _boolean)  # /SWAPRUN:CD
+_Same(_link, 'TurnOffAssemblyGeneration', _boolean)  # /NOASSEMBLY
+_Same(_link, 'TypeLibraryFile', _file_name)  # /TLBOUT
+_Same(_link, 'TypeLibraryResourceID', _integer)  # /TLBID
+_Same(_link, 'UACUIAccess', _boolean)  # /uiAccess='true'
+_Same(_link, 'Version', _string)  # /VERSION
+
+_Same(_link, 'EnableCOMDATFolding', _newly_boolean)  # /OPT:ICF
+_Same(_link, 'FixedBaseAddress', _newly_boolean)  # /FIXED
+_Same(_link, 'LargeAddressAware', _newly_boolean)  # /LARGEADDRESSAWARE
+_Same(_link, 'OptimizeReferences', _newly_boolean)  # /OPT:REF
+_Same(_link, 'RandomizedBaseAddress', _newly_boolean)  # /DYNAMICBASE
+_Same(_link, 'TerminalServerAware', _newly_boolean)  # /TSAWARE
+
+_subsystem_enumeration = _Enumeration(
+    ['NotSet',
+     'Console',  # /SUBSYSTEM:CONSOLE
+     'Windows',  # /SUBSYSTEM:WINDOWS
+     'Native',  # /SUBSYSTEM:NATIVE
+     'EFI Application',  # /SUBSYSTEM:EFI_APPLICATION
+     'EFI Boot Service Driver',  # /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER
+     'EFI ROM',  # /SUBSYSTEM:EFI_ROM
+     'EFI Runtime',  # /SUBSYSTEM:EFI_RUNTIME_DRIVER
+     'WindowsCE'],  # /SUBSYSTEM:WINDOWSCE
+    new=['POSIX'])  # /SUBSYSTEM:POSIX
+
+_target_machine_enumeration = _Enumeration(
+    ['NotSet',
+     'MachineX86',  # /MACHINE:X86
+     None,
+     'MachineARM',  # /MACHINE:ARM
+     'MachineEBC',  # /MACHINE:EBC
+     'MachineIA64',  # /MACHINE:IA64
+     None,
+     'MachineMIPS',  # /MACHINE:MIPS
+     'MachineMIPS16',  # /MACHINE:MIPS16
+     'MachineMIPSFPU',  # /MACHINE:MIPSFPU
+     'MachineMIPSFPU16',  # /MACHINE:MIPSFPU16
+     None,
+     None,
+     None,
+     'MachineSH4',  # /MACHINE:SH4
+     None,
+     'MachineTHUMB',  # /MACHINE:THUMB
+     'MachineX64'])  # /MACHINE:X64
+
+_Same(_link, 'AssemblyDebug',
+      _Enumeration(['',
+                    'true',  # /ASSEMBLYDEBUG
+                    'false']))  # /ASSEMBLYDEBUG:DISABLE
+_Same(_link, 'CLRImageType',
+      _Enumeration(['Default',
+                    'ForceIJWImage',  # /CLRIMAGETYPE:IJW
+                    'ForcePureILImage',  # /Switch="CLRIMAGETYPE:PURE
+                    'ForceSafeILImage']))  # /Switch="CLRIMAGETYPE:SAFE
+_Same(_link, 'CLRThreadAttribute',
+      _Enumeration(['DefaultThreadingAttribute',  # /CLRTHREADATTRIBUTE:NONE
+                    'MTAThreadingAttribute',  # /CLRTHREADATTRIBUTE:MTA
+                    'STAThreadingAttribute']))  # /CLRTHREADATTRIBUTE:STA
+_Same(_link, 'DataExecutionPrevention',
+      _Enumeration(['',
+                    'false',  # /NXCOMPAT:NO
+                    'true']))  # /NXCOMPAT
+_Same(_link, 'Driver',
+      _Enumeration(['NotSet',
+                    'Driver',  # /Driver
+                    'UpOnly',  # /DRIVER:UPONLY
+                    'WDM']))  # /DRIVER:WDM
+_Same(_link, 'LinkTimeCodeGeneration',
+      _Enumeration(['Default',
+                    'UseLinkTimeCodeGeneration',  # /LTCG
+                    'PGInstrument',  # /LTCG:PGInstrument
+                    'PGOptimization',  # /LTCG:PGOptimize
+                    'PGUpdate']))  # /LTCG:PGUpdate
+_Same(_link, 'ShowProgress',
+      _Enumeration(['NotSet',
+                    'LinkVerbose',  # /VERBOSE
+                    'LinkVerboseLib'],  # /VERBOSE:Lib
+                   new=['LinkVerboseICF',  # /VERBOSE:ICF
+                        'LinkVerboseREF',  # /VERBOSE:REF
+                        'LinkVerboseSAFESEH',  # /VERBOSE:SAFESEH
+                        'LinkVerboseCLR']))  # /VERBOSE:CLR
+_Same(_link, 'SubSystem', _subsystem_enumeration)
+_Same(_link, 'TargetMachine', _target_machine_enumeration)
+_Same(_link, 'UACExecutionLevel',
+      _Enumeration(['AsInvoker',  # /level='asInvoker'
+                    'HighestAvailable',  # /level='highestAvailable'
+                    'RequireAdministrator']))  # /level='requireAdministrator'
+
+
+# Options found in MSVS that have been renamed in MSBuild.
+_Renamed(_link, 'ErrorReporting', 'LinkErrorReporting',
+         _Enumeration(['NoErrorReport',  # /ERRORREPORT:NONE
+                       'PromptImmediately',  # /ERRORREPORT:PROMPT
+                       'QueueForNextLogin'],  # /ERRORREPORT:QUEUE
+                      new=['SendErrorReport']))  # /ERRORREPORT:SEND
+_Renamed(_link, 'IgnoreDefaultLibraryNames', 'IgnoreSpecificDefaultLibraries',
+         _file_list)  # /NODEFAULTLIB
+_Renamed(_link, 'ResourceOnlyDLL', 'NoEntryPoint', _boolean)  # /NOENTRY
+_Renamed(_link, 'SwapRunFromNet', 'SwapRunFromNET', _boolean)  # /SWAPRUN:NET
+
+_Moved(_link, 'GenerateManifest', '', _boolean)
+_Moved(_link, 'IgnoreImportLibrary', '', _boolean)
+_Moved(_link, 'LinkIncremental', '', _newly_boolean)
+_Moved(_link, 'LinkLibraryDependencies', 'ProjectReference', _boolean)
+_Moved(_link, 'UseLibraryDependencyInputs', 'ProjectReference', _boolean)
+
+# MSVS options not found in MSBuild.
+_MSVSOnly(_link, 'OptimizeForWindows98', _newly_boolean)
+_MSVSOnly(_link, 'UseUnicodeResponseFiles', _boolean)
+# TODO(jeanluc) I don't think these are genuine settings but byproducts of Gyp.
+_MSVSOnly(_link, 'AdditionalLibraryDirectories_excluded', _folder_list)
+
+# MSBuild options not found in MSVS.
+_MSBuildOnly(_link, 'BuildingInIDE', _boolean)
+_MSBuildOnly(_link, 'ImageHasSafeExceptionHandlers', _boolean)  # /SAFESEH
+_MSBuildOnly(_link, 'LinkDLL', _boolean)  # /DLL Visible='false'
+_MSBuildOnly(_link, 'LinkStatus', _boolean)  # /LTCG:STATUS
+_MSBuildOnly(_link, 'PreventDllBinding', _boolean)  # /ALLOWBIND
+_MSBuildOnly(_link, 'SupportNobindOfDelayLoadedDLL', _boolean)  # /DELAY:NOBIND
+_MSBuildOnly(_link, 'TrackerLogDirectory', _folder_name)
+_MSBuildOnly(_link, 'TreatLinkerWarningAsErrors', _boolean)  # /WX
+_MSBuildOnly(_link, 'MinimumRequiredVersion', _string)
+_MSBuildOnly(_link, 'MSDOSStubFileName', _file_name)  # /STUB Visible='false'
+_MSBuildOnly(_link, 'SectionAlignment', _integer)  # /ALIGN
+_MSBuildOnly(_link, 'SpecifySectionAttributes', _string)  # /SECTION
+_MSBuildOnly(_link, 'ForceFileOutput',
+             _Enumeration([], new=['Enabled',  # /FORCE
+                                   # /FORCE:MULTIPLE
+                                   'MultiplyDefinedSymbolOnly',
+                                   'UndefinedSymbolOnly']))  # /FORCE:UNRESOLVED
+_MSBuildOnly(_link, 'CreateHotPatchableImage',
+             _Enumeration([], new=['Enabled',  # /FUNCTIONPADMIN
+                                   'X86Image',  # /FUNCTIONPADMIN:5
+                                   'X64Image',  # /FUNCTIONPADMIN:6
+                                   'ItaniumImage']))  # /FUNCTIONPADMIN:16
+_MSBuildOnly(_link, 'CLRSupportLastError',
+             _Enumeration([], new=['Enabled',  # /CLRSupportLastError
+                                   'Disabled',  # /CLRSupportLastError:NO
+                                   # /CLRSupportLastError:SYSTEMDLL
+                                   'SystemDlls']))
+
+
+# Directives for converting VCResourceCompilerTool to ResourceCompile.
+# See "c:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\1033\rc.xml" for
+# the schema of the MSBuild ResourceCompile settings.
+
+_Same(_rc, 'AdditionalOptions', _string_list)
+_Same(_rc, 'AdditionalIncludeDirectories', _folder_list)  # /I
+_Same(_rc, 'Culture', _Integer(msbuild_base=16))
+_Same(_rc, 'IgnoreStandardIncludePath', _boolean)  # /X
+_Same(_rc, 'PreprocessorDefinitions', _string_list)  # /D
+_Same(_rc, 'ResourceOutputFileName', _string)  # /fo
+_Same(_rc, 'ShowProgress', _boolean)  # /v
+# There is no UI in VisualStudio 2008 to set the following properties.
+# However they are found in CL and other tools.  Include them here for
+# completeness, as they are very likely to have the same usage pattern.
+_Same(_rc, 'SuppressStartupBanner', _boolean)  # /nologo
+_Same(_rc, 'UndefinePreprocessorDefinitions', _string_list)  # /u
+
+# MSBuild options not found in MSVS.
+_MSBuildOnly(_rc, 'NullTerminateStrings', _boolean)  # /n
+_MSBuildOnly(_rc, 'TrackerLogDirectory', _folder_name)
+
+
+# Directives for converting VCMIDLTool to Midl.
+# See "c:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\1033\midl.xml" for
+# the schema of the MSBuild Midl settings.
+
+_Same(_midl, 'AdditionalIncludeDirectories', _folder_list)  # /I
+_Same(_midl, 'AdditionalOptions', _string_list)
+_Same(_midl, 'CPreprocessOptions', _string)  # /cpp_opt
+_Same(_midl, 'ErrorCheckAllocations', _boolean)  # /error allocation
+_Same(_midl, 'ErrorCheckBounds', _boolean)  # /error bounds_check
+_Same(_midl, 'ErrorCheckEnumRange', _boolean)  # /error enum
+_Same(_midl, 'ErrorCheckRefPointers', _boolean)  # /error ref
+_Same(_midl, 'ErrorCheckStubData', _boolean)  # /error stub_data
+_Same(_midl, 'GenerateStublessProxies', _boolean)  # /Oicf
+_Same(_midl, 'GenerateTypeLibrary', _boolean)
+_Same(_midl, 'HeaderFileName', _file_name)  # /h
+_Same(_midl, 'IgnoreStandardIncludePath', _boolean)  # /no_def_idir
+_Same(_midl, 'InterfaceIdentifierFileName', _file_name)  # /iid
+_Same(_midl, 'MkTypLibCompatible', _boolean)  # /mktyplib203
+_Same(_midl, 'OutputDirectory', _string)  # /out
+_Same(_midl, 'PreprocessorDefinitions', _string_list)  # /D
+_Same(_midl, 'ProxyFileName', _file_name)  # /proxy
+_Same(_midl, 'RedirectOutputAndErrors', _file_name)  # /o
+_Same(_midl, 'SuppressStartupBanner', _boolean)  # /nologo
+_Same(_midl, 'TypeLibraryName', _file_name)  # /tlb
+_Same(_midl, 'UndefinePreprocessorDefinitions', _string_list)  # /U
+_Same(_midl, 'WarnAsError', _boolean)  # /WX
+
+_Same(_midl, 'DefaultCharType',
+      _Enumeration(['Unsigned',  # /char unsigned
+                    'Signed',  # /char signed
+                    'Ascii']))  # /char ascii7
+_Same(_midl, 'TargetEnvironment',
+      _Enumeration(['NotSet',
+                    'Win32',  # /env win32
+                    'Itanium',  # /env ia64
+                    'X64']))  # /env x64
+_Same(_midl, 'EnableErrorChecks',
+      _Enumeration(['EnableCustom',
+                    'None',  # /error none
+                    'All']))  # /error all
+_Same(_midl, 'StructMemberAlignment',
+      _Enumeration(['NotSet',
+                    '1',  # Zp1
+                    '2',  # Zp2
+                    '4',  # Zp4
+                    '8']))  # Zp8
+_Same(_midl, 'WarningLevel',
+      _Enumeration(['0',  # /W0
+                    '1',  # /W1
+                    '2',  # /W2
+                    '3',  # /W3
+                    '4']))  # /W4
+
+_Renamed(_midl, 'DLLDataFileName', 'DllDataFileName', _file_name)  # /dlldata
+_Renamed(_midl, 'ValidateParameters', 'ValidateAllParameters',
+         _boolean)  # /robust
+
+# MSBuild options not found in MSVS.
+_MSBuildOnly(_midl, 'ApplicationConfigurationMode', _boolean)  # /app_config
+_MSBuildOnly(_midl, 'ClientStubFile', _file_name)  # /cstub
+_MSBuildOnly(_midl, 'GenerateClientFiles',
+             _Enumeration([], new=['Stub',  # /client stub
+                                   'None']))  # /client none
+_MSBuildOnly(_midl, 'GenerateServerFiles',
+             _Enumeration([], new=['Stub',  # /client stub
+                                   'None']))  # /client none
+_MSBuildOnly(_midl, 'LocaleID', _integer)  # /lcid DECIMAL
+_MSBuildOnly(_midl, 'ServerStubFile', _file_name)  # /sstub
+_MSBuildOnly(_midl, 'SuppressCompilerWarnings', _boolean)  # /no_warn
+_MSBuildOnly(_midl, 'TrackerLogDirectory', _folder_name)
+_MSBuildOnly(_midl, 'TypeLibFormat',
+             _Enumeration([], new=['NewFormat',  # /newtlb
+                                   'OldFormat']))  # /oldtlb
+
+
+# Directives for converting VCLibrarianTool to Lib.
+# See "c:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\1033\lib.xml" for
+# the schema of the MSBuild Lib settings.
+
+_Same(_lib, 'AdditionalDependencies', _file_list)
+_Same(_lib, 'AdditionalLibraryDirectories', _folder_list)  # /LIBPATH
+_Same(_lib, 'AdditionalOptions', _string_list)
+_Same(_lib, 'ExportNamedFunctions', _string_list)  # /EXPORT
+_Same(_lib, 'ForceSymbolReferences', _string)  # /INCLUDE
+_Same(_lib, 'IgnoreAllDefaultLibraries', _boolean)  # /NODEFAULTLIB
+_Same(_lib, 'IgnoreSpecificDefaultLibraries', _file_list)  # /NODEFAULTLIB
+_Same(_lib, 'ModuleDefinitionFile', _file_name)  # /DEF
+_Same(_lib, 'OutputFile', _file_name)  # /OUT
+_Same(_lib, 'SuppressStartupBanner', _boolean)  # /NOLOGO
+_Same(_lib, 'UseUnicodeResponseFiles', _boolean)
+_Same(_lib, 'LinkTimeCodeGeneration', _boolean)  # /LTCG
+
+# TODO(jeanluc) _link defines the same value that gets moved to
+# ProjectReference.  We may want to validate that they are consistent.
+_Moved(_lib, 'LinkLibraryDependencies', 'ProjectReference', _boolean)
+
+# TODO(jeanluc) I don't think these are genuine settings but byproducts of Gyp.
+_MSVSOnly(_lib, 'AdditionalLibraryDirectories_excluded', _folder_list)
+
+_MSBuildOnly(_lib, 'DisplayLibrary', _string)  # /LIST Visible='false'
+_MSBuildOnly(_lib, 'ErrorReporting',
+             _Enumeration([], new=['PromptImmediately',  # /ERRORREPORT:PROMPT
+                                   'QueueForNextLogin',  # /ERRORREPORT:QUEUE
+                                   'SendErrorReport',  # /ERRORREPORT:SEND
+                                   'NoErrorReport']))  # /ERRORREPORT:NONE
+_MSBuildOnly(_lib, 'MinimumRequiredVersion', _string)
+_MSBuildOnly(_lib, 'Name', _file_name)  # /NAME
+_MSBuildOnly(_lib, 'RemoveObjects', _file_list)  # /REMOVE
+_MSBuildOnly(_lib, 'SubSystem', _subsystem_enumeration)
+_MSBuildOnly(_lib, 'TargetMachine', _target_machine_enumeration)
+_MSBuildOnly(_lib, 'TrackerLogDirectory', _folder_name)
+_MSBuildOnly(_lib, 'TreatLibWarningAsErrors', _boolean)  # /WX
+_MSBuildOnly(_lib, 'Verbose', _boolean)
+
+
+# Directives for converting VCManifestTool to Mt.
+# See "c:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\1033\mt.xml" for
+# the schema of the MSBuild Lib settings.
+
+# Options that have the same name in MSVS and MSBuild
+_Same(_manifest, 'AdditionalManifestFiles', _file_list)  # /manifest
+_Same(_manifest, 'AdditionalOptions', _string_list)
+_Same(_manifest, 'AssemblyIdentity', _string)  # /identity:
+_Same(_manifest, 'ComponentFileName', _file_name)  # /dll
+_Same(_manifest, 'GenerateCatalogFiles', _boolean)  # /makecdfs
+_Same(_manifest, 'InputResourceManifests', _string)  # /inputresource
+_Same(_manifest, 'OutputManifestFile', _file_name)  # /out
+_Same(_manifest, 'RegistrarScriptFile', _file_name)  # /rgs
+_Same(_manifest, 'ReplacementsFile', _file_name)  # /replacements
+_Same(_manifest, 'SuppressStartupBanner', _boolean)  # /nologo
+_Same(_manifest, 'TypeLibraryFile', _file_name)  # /tlb:
+_Same(_manifest, 'UpdateFileHashes', _boolean)  # /hashupdate
+_Same(_manifest, 'UpdateFileHashesSearchPath', _file_name)
+_Same(_manifest, 'VerboseOutput', _boolean)  # /verbose
+
+# Options that have moved location.
+_MovedAndRenamed(_manifest, 'ManifestResourceFile',
+                 'ManifestResourceCompile',
+                 'ResourceOutputFileName',
+                 _file_name)
+_Moved(_manifest, 'EmbedManifest', '', _boolean)
+
+# MSVS options not found in MSBuild.
+_MSVSOnly(_manifest, 'DependencyInformationFile', _file_name)
+_MSVSOnly(_manifest, 'UseFAT32Workaround', _boolean)
+_MSVSOnly(_manifest, 'UseUnicodeResponseFiles', _boolean)
+
+# MSBuild options not found in MSVS.
+_MSBuildOnly(_manifest, 'EnableDPIAwareness', _boolean)
+_MSBuildOnly(_manifest, 'GenerateCategoryTags', _boolean)  # /category
+_MSBuildOnly(_manifest, 'ManifestFromManagedAssembly',
+             _file_name)  # /managedassemblyname
+_MSBuildOnly(_manifest, 'OutputResourceManifests', _string)  # /outputresource
+_MSBuildOnly(_manifest, 'SuppressDependencyElement', _boolean)  # /nodependency
+_MSBuildOnly(_manifest, 'TrackerLogDirectory', _folder_name)
diff --git a/webWidgetTCT_device/tools/gyp/pylib/gyp/MSVSSettings_test.py b/webWidgetTCT_device/tools/gyp/pylib/gyp/MSVSSettings_test.py
new file mode 100755 (executable)
index 0000000..4e06da3
--- /dev/null
@@ -0,0 +1,1482 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Unit tests for the MSVSSettings.py file."""
+
+import StringIO
+import unittest
+import gyp.MSVSSettings as MSVSSettings
+
+
+class TestSequenceFunctions(unittest.TestCase):
+
+  def setUp(self):
+    self.stderr = StringIO.StringIO()
+
+  def _ExpectedWarnings(self, expected):
+    """Compares recorded lines to expected warnings."""
+    self.stderr.seek(0)
+    actual = self.stderr.read().split('\n')
+    actual = [line for line in actual if line]
+    self.assertEqual(sorted(expected), sorted(actual))
+
+  def testValidateMSVSSettings_tool_names(self):
+    """Tests that only MSVS tool names are allowed."""
+    MSVSSettings.ValidateMSVSSettings(
+        {'VCCLCompilerTool': {},
+         'VCLinkerTool': {},
+         'VCMIDLTool': {},
+         'foo': {},
+         'VCResourceCompilerTool': {},
+         'VCLibrarianTool': {},
+         'VCManifestTool': {},
+         'ClCompile': {}},
+        self.stderr)
+    self._ExpectedWarnings([
+        'Warning: unrecognized tool foo',
+        'Warning: unrecognized tool ClCompile'])
+
+  def testValidateMSVSSettings_settings(self):
+    """Tests that for invalid MSVS settings."""
+    MSVSSettings.ValidateMSVSSettings(
+        {'VCCLCompilerTool': {
+            'AdditionalIncludeDirectories': 'folder1;folder2',
+            'AdditionalOptions': ['string1', 'string2'],
+            'AdditionalUsingDirectories': 'folder1;folder2',
+            'AssemblerListingLocation': 'a_file_name',
+            'AssemblerOutput': '0',
+            'BasicRuntimeChecks': '5',
+            'BrowseInformation': 'fdkslj',
+            'BrowseInformationFile': 'a_file_name',
+            'BufferSecurityCheck': 'true',
+            'CallingConvention': '-1',
+            'CompileAs': '1',
+            'DebugInformationFormat': '2',
+            'DefaultCharIsUnsigned': 'true',
+            'Detect64BitPortabilityProblems': 'true',
+            'DisableLanguageExtensions': 'true',
+            'DisableSpecificWarnings': 'string1;string2',
+            'EnableEnhancedInstructionSet': '1',
+            'EnableFiberSafeOptimizations': 'true',
+            'EnableFunctionLevelLinking': 'true',
+            'EnableIntrinsicFunctions': 'true',
+            'EnablePREfast': 'true',
+            'Enableprefast': 'bogus',
+            'ErrorReporting': '1',
+            'ExceptionHandling': '1',
+            'ExpandAttributedSource': 'true',
+            'FavorSizeOrSpeed': '1',
+            'FloatingPointExceptions': 'true',
+            'FloatingPointModel': '1',
+            'ForceConformanceInForLoopScope': 'true',
+            'ForcedIncludeFiles': 'file1;file2',
+            'ForcedUsingFiles': 'file1;file2',
+            'GeneratePreprocessedFile': '1',
+            'GenerateXMLDocumentationFiles': 'true',
+            'IgnoreStandardIncludePath': 'true',
+            'InlineFunctionExpansion': '1',
+            'KeepComments': 'true',
+            'MinimalRebuild': 'true',
+            'ObjectFile': 'a_file_name',
+            'OmitDefaultLibName': 'true',
+            'OmitFramePointers': 'true',
+            'OpenMP': 'true',
+            'Optimization': '1',
+            'PrecompiledHeaderFile': 'a_file_name',
+            'PrecompiledHeaderThrough': 'a_file_name',
+            'PreprocessorDefinitions': 'string1;string2',
+            'ProgramDataBaseFileName': 'a_file_name',
+            'RuntimeLibrary': '1',
+            'RuntimeTypeInfo': 'true',
+            'ShowIncludes': 'true',
+            'SmallerTypeCheck': 'true',
+            'StringPooling': 'true',
+            'StructMemberAlignment': '1',
+            'SuppressStartupBanner': 'true',
+            'TreatWChar_tAsBuiltInType': 'true',
+            'UndefineAllPreprocessorDefinitions': 'true',
+            'UndefinePreprocessorDefinitions': 'string1;string2',
+            'UseFullPaths': 'true',
+            'UsePrecompiledHeader': '1',
+            'UseUnicodeResponseFiles': 'true',
+            'WarnAsError': 'true',
+            'WarningLevel': '1',
+            'WholeProgramOptimization': 'true',
+            'XMLDocumentationFileName': 'a_file_name',
+            'ZZXYZ': 'bogus'},
+         'VCLinkerTool': {
+             'AdditionalDependencies': 'file1;file2',
+             'AdditionalLibraryDirectories': 'folder1;folder2',
+             'AdditionalManifestDependencies': 'file1;file2',
+             'AdditionalOptions': 'a string1',
+             'AddModuleNamesToAssembly': 'file1;file2',
+             'AllowIsolation': 'true',
+             'AssemblyDebug': '2',
+             'AssemblyLinkResource': 'file1;file2',
+             'BaseAddress': 'a string1',
+             'CLRImageType': '2',
+             'CLRThreadAttribute': '2',
+             'CLRUnmanagedCodeCheck': 'true',
+             'DataExecutionPrevention': '2',
+             'DelayLoadDLLs': 'file1;file2',
+             'DelaySign': 'true',
+             'Driver': '2',
+             'EmbedManagedResourceFile': 'file1;file2',
+             'EnableCOMDATFolding': '2',
+             'EnableUAC': 'true',
+             'EntryPointSymbol': 'a string1',
+             'ErrorReporting': '2',
+             'FixedBaseAddress': '2',
+             'ForceSymbolReferences': 'file1;file2',
+             'FunctionOrder': 'a_file_name',
+             'GenerateDebugInformation': 'true',
+             'GenerateManifest': 'true',
+             'GenerateMapFile': 'true',
+             'HeapCommitSize': 'a string1',
+             'HeapReserveSize': 'a string1',
+             'IgnoreAllDefaultLibraries': 'true',
+             'IgnoreDefaultLibraryNames': 'file1;file2',
+             'IgnoreEmbeddedIDL': 'true',
+             'IgnoreImportLibrary': 'true',
+             'ImportLibrary': 'a_file_name',
+             'KeyContainer': 'a_file_name',
+             'KeyFile': 'a_file_name',
+             'LargeAddressAware': '2',
+             'LinkIncremental': '2',
+             'LinkLibraryDependencies': 'true',
+             'LinkTimeCodeGeneration': '2',
+             'ManifestFile': 'a_file_name',
+             'MapExports': 'true',
+             'MapFileName': 'a_file_name',
+             'MergedIDLBaseFileName': 'a_file_name',
+             'MergeSections': 'a string1',
+             'MidlCommandFile': 'a_file_name',
+             'ModuleDefinitionFile': 'a_file_name',
+             'OptimizeForWindows98': '1',
+             'OptimizeReferences': '2',
+             'OutputFile': 'a_file_name',
+             'PerUserRedirection': 'true',
+             'Profile': 'true',
+             'ProfileGuidedDatabase': 'a_file_name',
+             'ProgramDatabaseFile': 'a_file_name',
+             'RandomizedBaseAddress': '2',
+             'RegisterOutput': 'true',
+             'ResourceOnlyDLL': 'true',
+             'SetChecksum': 'true',
+             'ShowProgress': '2',
+             'StackCommitSize': 'a string1',
+             'StackReserveSize': 'a string1',
+             'StripPrivateSymbols': 'a_file_name',
+             'SubSystem': '2',
+             'SupportUnloadOfDelayLoadedDLL': 'true',
+             'SuppressStartupBanner': 'true',
+             'SwapRunFromCD': 'true',
+             'SwapRunFromNet': 'true',
+             'TargetMachine': '2',
+             'TerminalServerAware': '2',
+             'TurnOffAssemblyGeneration': 'true',
+             'TypeLibraryFile': 'a_file_name',
+             'TypeLibraryResourceID': '33',
+             'UACExecutionLevel': '2',
+             'UACUIAccess': 'true',
+             'UseLibraryDependencyInputs': 'true',
+             'UseUnicodeResponseFiles': 'true',
+             'Version': 'a string1'},
+         'VCMIDLTool': {
+             'AdditionalIncludeDirectories': 'folder1;folder2',
+             'AdditionalOptions': 'a string1',
+             'CPreprocessOptions': 'a string1',
+             'DefaultCharType': '1',
+             'DLLDataFileName': 'a_file_name',
+             'EnableErrorChecks': '1',
+             'ErrorCheckAllocations': 'true',
+             'ErrorCheckBounds': 'true',
+             'ErrorCheckEnumRange': 'true',
+             'ErrorCheckRefPointers': 'true',
+             'ErrorCheckStubData': 'true',
+             'GenerateStublessProxies': 'true',
+             'GenerateTypeLibrary': 'true',
+             'HeaderFileName': 'a_file_name',
+             'IgnoreStandardIncludePath': 'true',
+             'InterfaceIdentifierFileName': 'a_file_name',
+             'MkTypLibCompatible': 'true',
+             'notgood': 'bogus',
+             'OutputDirectory': 'a string1',
+             'PreprocessorDefinitions': 'string1;string2',
+             'ProxyFileName': 'a_file_name',
+             'RedirectOutputAndErrors': 'a_file_name',
+             'StructMemberAlignment': '1',
+             'SuppressStartupBanner': 'true',
+             'TargetEnvironment': '1',
+             'TypeLibraryName': 'a_file_name',
+             'UndefinePreprocessorDefinitions': 'string1;string2',
+             'ValidateParameters': 'true',
+             'WarnAsError': 'true',
+             'WarningLevel': '1'},
+         'VCResourceCompilerTool': {
+             'AdditionalOptions': 'a string1',
+             'AdditionalIncludeDirectories': 'folder1;folder2',
+             'Culture': '1003',
+             'IgnoreStandardIncludePath': 'true',
+             'notgood2': 'bogus',
+             'PreprocessorDefinitions': 'string1;string2',
+             'ResourceOutputFileName': 'a string1',
+             'ShowProgress': 'true',
+             'SuppressStartupBanner': 'true',
+             'UndefinePreprocessorDefinitions': 'string1;string2'},
+         'VCLibrarianTool': {
+             'AdditionalDependencies': 'file1;file2',
+             'AdditionalLibraryDirectories': 'folder1;folder2',
+             'AdditionalOptions': 'a string1',
+             'ExportNamedFunctions': 'string1;string2',
+             'ForceSymbolReferences': 'a string1',
+             'IgnoreAllDefaultLibraries': 'true',
+             'IgnoreSpecificDefaultLibraries': 'file1;file2',
+             'LinkLibraryDependencies': 'true',
+             'ModuleDefinitionFile': 'a_file_name',
+             'OutputFile': 'a_file_name',
+             'SuppressStartupBanner': 'true',
+             'UseUnicodeResponseFiles': 'true'},
+         'VCManifestTool': {
+             'AdditionalManifestFiles': 'file1;file2',
+             'AdditionalOptions': 'a string1',
+             'AssemblyIdentity': 'a string1',
+             'ComponentFileName': 'a_file_name',
+             'DependencyInformationFile': 'a_file_name',
+             'GenerateCatalogFiles': 'true',
+             'InputResourceManifests': 'a string1',
+             'ManifestResourceFile': 'a_file_name',
+             'OutputManifestFile': 'a_file_name',
+             'RegistrarScriptFile': 'a_file_name',
+             'ReplacementsFile': 'a_file_name',
+             'SuppressStartupBanner': 'true',
+             'TypeLibraryFile': 'a_file_name',
+             'UpdateFileHashes': 'truel',
+             'UpdateFileHashesSearchPath': 'a_file_name',
+             'UseFAT32Workaround': 'true',
+             'UseUnicodeResponseFiles': 'true',
+             'VerboseOutput': 'true'}},
+        self.stderr)
+    self._ExpectedWarnings([
+        'Warning: for VCCLCompilerTool/BasicRuntimeChecks, '
+        'index value (5) not in expected range [0, 4)',
+        'Warning: for VCCLCompilerTool/BrowseInformation, '
+        "invalid literal for int() with base 10: 'fdkslj'",
+        'Warning: for VCCLCompilerTool/CallingConvention, '
+        'index value (-1) not in expected range [0, 3)',
+        'Warning: for VCCLCompilerTool/DebugInformationFormat, '
+        'converted value for 2 not specified.',
+        'Warning: unrecognized setting VCCLCompilerTool/Enableprefast',
+        'Warning: unrecognized setting VCCLCompilerTool/ZZXYZ',
+        'Warning: for VCLinkerTool/TargetMachine, '
+        'converted value for 2 not specified.',
+        'Warning: unrecognized setting VCMIDLTool/notgood',
+        'Warning: unrecognized setting VCResourceCompilerTool/notgood2',
+        'Warning: for VCManifestTool/UpdateFileHashes, '
+        "expected bool; got 'truel'"
+        ''])
+
+  def testValidateMSBuildSettings_settings(self):
+    """Tests that for invalid MSBuild settings."""
+    MSVSSettings.ValidateMSBuildSettings(
+        {'ClCompile': {
+            'AdditionalIncludeDirectories': 'folder1;folder2',
+            'AdditionalOptions': ['string1', 'string2'],
+            'AdditionalUsingDirectories': 'folder1;folder2',
+            'AssemblerListingLocation': 'a_file_name',
+            'AssemblerOutput': 'NoListing',
+            'BasicRuntimeChecks': 'StackFrameRuntimeCheck',
+            'BrowseInformation': 'false',
+            'BrowseInformationFile': 'a_file_name',
+            'BufferSecurityCheck': 'true',
+            'BuildingInIDE': 'true',
+            'CallingConvention': 'Cdecl',
+            'CompileAs': 'CompileAsC',
+            'CompileAsManaged': 'Pure',
+            'CreateHotpatchableImage': 'true',
+            'DebugInformationFormat': 'ProgramDatabase',
+            'DisableLanguageExtensions': 'true',
+            'DisableSpecificWarnings': 'string1;string2',
+            'EnableEnhancedInstructionSet': 'StreamingSIMDExtensions',
+            'EnableFiberSafeOptimizations': 'true',
+            'EnablePREfast': 'true',
+            'Enableprefast': 'bogus',
+            'ErrorReporting': 'Prompt',
+            'ExceptionHandling': 'SyncCThrow',
+            'ExpandAttributedSource': 'true',
+            'FavorSizeOrSpeed': 'Neither',
+            'FloatingPointExceptions': 'true',
+            'FloatingPointModel': 'Precise',
+            'ForceConformanceInForLoopScope': 'true',
+            'ForcedIncludeFiles': 'file1;file2',
+            'ForcedUsingFiles': 'file1;file2',
+            'FunctionLevelLinking': 'false',
+            'GenerateXMLDocumentationFiles': 'true',
+            'IgnoreStandardIncludePath': 'true',
+            'InlineFunctionExpansion': 'OnlyExplicitInline',
+            'IntrinsicFunctions': 'false',
+            'MinimalRebuild': 'true',
+            'MultiProcessorCompilation': 'true',
+            'ObjectFileName': 'a_file_name',
+            'OmitDefaultLibName': 'true',
+            'OmitFramePointers': 'true',
+            'OpenMPSupport': 'true',
+            'Optimization': 'Disabled',
+            'PrecompiledHeader': 'NotUsing',
+            'PrecompiledHeaderFile': 'a_file_name',
+            'PrecompiledHeaderOutputFile': 'a_file_name',
+            'PreprocessKeepComments': 'true',
+            'PreprocessorDefinitions': 'string1;string2',
+            'PreprocessOutputPath': 'a string1',
+            'PreprocessSuppressLineNumbers': 'false',
+            'PreprocessToFile': 'false',
+            'ProcessorNumber': '33',
+            'ProgramDataBaseFileName': 'a_file_name',
+            'RuntimeLibrary': 'MultiThreaded',
+            'RuntimeTypeInfo': 'true',
+            'ShowIncludes': 'true',
+            'SmallerTypeCheck': 'true',
+            'StringPooling': 'true',
+            'StructMemberAlignment': '1Byte',
+            'SuppressStartupBanner': 'true',
+            'TrackerLogDirectory': 'a_folder',
+            'TreatSpecificWarningsAsErrors': 'string1;string2',
+            'TreatWarningAsError': 'true',
+            'TreatWChar_tAsBuiltInType': 'true',
+            'UndefineAllPreprocessorDefinitions': 'true',
+            'UndefinePreprocessorDefinitions': 'string1;string2',
+            'UseFullPaths': 'true',
+            'UseUnicodeForAssemblerListing': 'true',
+            'WarningLevel': 'TurnOffAllWarnings',
+            'WholeProgramOptimization': 'true',
+            'XMLDocumentationFileName': 'a_file_name',
+            'ZZXYZ': 'bogus'},
+         'Link': {
+             'AdditionalDependencies': 'file1;file2',
+             'AdditionalLibraryDirectories': 'folder1;folder2',
+             'AdditionalManifestDependencies': 'file1;file2',
+             'AdditionalOptions': 'a string1',
+             'AddModuleNamesToAssembly': 'file1;file2',
+             'AllowIsolation': 'true',
+             'AssemblyDebug': '',
+             'AssemblyLinkResource': 'file1;file2',
+             'BaseAddress': 'a string1',
+             'BuildingInIDE': 'true',
+             'CLRImageType': 'ForceIJWImage',
+             'CLRSupportLastError': 'Enabled',
+             'CLRThreadAttribute': 'MTAThreadingAttribute',
+             'CLRUnmanagedCodeCheck': 'true',
+             'CreateHotPatchableImage': 'X86Image',
+             'DataExecutionPrevention': 'false',
+             'DelayLoadDLLs': 'file1;file2',
+             'DelaySign': 'true',
+             'Driver': 'NotSet',
+             'EmbedManagedResourceFile': 'file1;file2',
+             'EnableCOMDATFolding': 'false',
+             'EnableUAC': 'true',
+             'EntryPointSymbol': 'a string1',
+             'FixedBaseAddress': 'false',
+             'ForceFileOutput': 'Enabled',
+             'ForceSymbolReferences': 'file1;file2',
+             'FunctionOrder': 'a_file_name',
+             'GenerateDebugInformation': 'true',
+             'GenerateMapFile': 'true',
+             'HeapCommitSize': 'a string1',
+             'HeapReserveSize': 'a string1',
+             'IgnoreAllDefaultLibraries': 'true',
+             'IgnoreEmbeddedIDL': 'true',
+             'IgnoreSpecificDefaultLibraries': 'a_file_list',
+             'ImageHasSafeExceptionHandlers': 'true',
+             'ImportLibrary': 'a_file_name',
+             'KeyContainer': 'a_file_name',
+             'KeyFile': 'a_file_name',
+             'LargeAddressAware': 'false',
+             'LinkDLL': 'true',
+             'LinkErrorReporting': 'SendErrorReport',
+             'LinkStatus': 'true',
+             'LinkTimeCodeGeneration': 'UseLinkTimeCodeGeneration',
+             'ManifestFile': 'a_file_name',
+             'MapExports': 'true',
+             'MapFileName': 'a_file_name',
+             'MergedIDLBaseFileName': 'a_file_name',
+             'MergeSections': 'a string1',
+             'MidlCommandFile': 'a_file_name',
+             'MinimumRequiredVersion': 'a string1',
+             'ModuleDefinitionFile': 'a_file_name',
+             'MSDOSStubFileName': 'a_file_name',
+             'NoEntryPoint': 'true',
+             'OptimizeReferences': 'false',
+             'OutputFile': 'a_file_name',
+             'PerUserRedirection': 'true',
+             'PreventDllBinding': 'true',
+             'Profile': 'true',
+             'ProfileGuidedDatabase': 'a_file_name',
+             'ProgramDatabaseFile': 'a_file_name',
+             'RandomizedBaseAddress': 'false',
+             'RegisterOutput': 'true',
+             'SectionAlignment': '33',
+             'SetChecksum': 'true',
+             'ShowProgress': 'LinkVerboseREF',
+             'SpecifySectionAttributes': 'a string1',
+             'StackCommitSize': 'a string1',
+             'StackReserveSize': 'a string1',
+             'StripPrivateSymbols': 'a_file_name',
+             'SubSystem': 'Console',
+             'SupportNobindOfDelayLoadedDLL': 'true',
+             'SupportUnloadOfDelayLoadedDLL': 'true',
+             'SuppressStartupBanner': 'true',
+             'SwapRunFromCD': 'true',
+             'SwapRunFromNET': 'true',
+             'TargetMachine': 'MachineX86',
+             'TerminalServerAware': 'false',
+             'TrackerLogDirectory': 'a_folder',
+             'TreatLinkerWarningAsErrors': 'true',
+             'TurnOffAssemblyGeneration': 'true',
+             'TypeLibraryFile': 'a_file_name',
+             'TypeLibraryResourceID': '33',
+             'UACExecutionLevel': 'AsInvoker',
+             'UACUIAccess': 'true',
+             'Version': 'a string1'},
+         'ResourceCompile': {
+             'AdditionalIncludeDirectories': 'folder1;folder2',
+             'AdditionalOptions': 'a string1',
+             'Culture': '0x236',
+             'IgnoreStandardIncludePath': 'true',
+             'NullTerminateStrings': 'true',
+             'PreprocessorDefinitions': 'string1;string2',
+             'ResourceOutputFileName': 'a string1',
+             'ShowProgress': 'true',
+             'SuppressStartupBanner': 'true',
+             'TrackerLogDirectory': 'a_folder',
+             'UndefinePreprocessorDefinitions': 'string1;string2'},
+         'Midl': {
+             'AdditionalIncludeDirectories': 'folder1;folder2',
+             'AdditionalOptions': 'a string1',
+             'ApplicationConfigurationMode': 'true',
+             'ClientStubFile': 'a_file_name',
+             'CPreprocessOptions': 'a string1',
+             'DefaultCharType': 'Signed',
+             'DllDataFileName': 'a_file_name',
+             'EnableErrorChecks': 'EnableCustom',
+             'ErrorCheckAllocations': 'true',
+             'ErrorCheckBounds': 'true',
+             'ErrorCheckEnumRange': 'true',
+             'ErrorCheckRefPointers': 'true',
+             'ErrorCheckStubData': 'true',
+             'GenerateClientFiles': 'Stub',
+             'GenerateServerFiles': 'None',
+             'GenerateStublessProxies': 'true',
+             'GenerateTypeLibrary': 'true',
+             'HeaderFileName': 'a_file_name',
+             'IgnoreStandardIncludePath': 'true',
+             'InterfaceIdentifierFileName': 'a_file_name',
+             'LocaleID': '33',
+             'MkTypLibCompatible': 'true',
+             'OutputDirectory': 'a string1',
+             'PreprocessorDefinitions': 'string1;string2',
+             'ProxyFileName': 'a_file_name',
+             'RedirectOutputAndErrors': 'a_file_name',
+             'ServerStubFile': 'a_file_name',
+             'StructMemberAlignment': 'NotSet',
+             'SuppressCompilerWarnings': 'true',
+             'SuppressStartupBanner': 'true',
+             'TargetEnvironment': 'Itanium',
+             'TrackerLogDirectory': 'a_folder',
+             'TypeLibFormat': 'NewFormat',
+             'TypeLibraryName': 'a_file_name',
+             'UndefinePreprocessorDefinitions': 'string1;string2',
+             'ValidateAllParameters': 'true',
+             'WarnAsError': 'true',
+             'WarningLevel': '1'},
+         'Lib': {
+             'AdditionalDependencies': 'file1;file2',
+             'AdditionalLibraryDirectories': 'folder1;folder2',
+             'AdditionalOptions': 'a string1',
+             'DisplayLibrary': 'a string1',
+             'ErrorReporting': 'PromptImmediately',
+             'ExportNamedFunctions': 'string1;string2',
+             'ForceSymbolReferences': 'a string1',
+             'IgnoreAllDefaultLibraries': 'true',
+             'IgnoreSpecificDefaultLibraries': 'file1;file2',
+             'LinkTimeCodeGeneration': 'true',
+             'MinimumRequiredVersion': 'a string1',
+             'ModuleDefinitionFile': 'a_file_name',
+             'Name': 'a_file_name',
+             'OutputFile': 'a_file_name',
+             'RemoveObjects': 'file1;file2',
+             'SubSystem': 'Console',
+             'SuppressStartupBanner': 'true',
+             'TargetMachine': 'MachineX86i',
+             'TrackerLogDirectory': 'a_folder',
+             'TreatLibWarningAsErrors': 'true',
+             'UseUnicodeResponseFiles': 'true',
+             'Verbose': 'true'},
+         'Manifest': {
+             'AdditionalManifestFiles': 'file1;file2',
+             'AdditionalOptions': 'a string1',
+             'AssemblyIdentity': 'a string1',
+             'ComponentFileName': 'a_file_name',
+             'EnableDPIAwareness': 'fal',
+             'GenerateCatalogFiles': 'truel',
+             'GenerateCategoryTags': 'true',
+             'InputResourceManifests': 'a string1',
+             'ManifestFromManagedAssembly': 'a_file_name',
+             'notgood3': 'bogus',
+             'OutputManifestFile': 'a_file_name',
+             'OutputResourceManifests': 'a string1',
+             'RegistrarScriptFile': 'a_file_name',
+             'ReplacementsFile': 'a_file_name',
+             'SuppressDependencyElement': 'true',
+             'SuppressStartupBanner': 'true',
+             'TrackerLogDirectory': 'a_folder',
+             'TypeLibraryFile': 'a_file_name',
+             'UpdateFileHashes': 'true',
+             'UpdateFileHashesSearchPath': 'a_file_name',
+             'VerboseOutput': 'true'},
+         'ProjectReference': {
+             'LinkLibraryDependencies': 'true',
+             'UseLibraryDependencyInputs': 'true'},
+         'ManifestResourceCompile': {
+             'ResourceOutputFileName': 'a_file_name'},
+         '': {
+             'EmbedManifest': 'true',
+             'GenerateManifest': 'true',
+             'IgnoreImportLibrary': 'true',
+             'LinkIncremental': 'false'}},
+        self.stderr)
+    self._ExpectedWarnings([
+        'Warning: unrecognized setting ClCompile/Enableprefast',
+        'Warning: unrecognized setting ClCompile/ZZXYZ',
+        'Warning: unrecognized setting Manifest/notgood3',
+        'Warning: for Manifest/GenerateCatalogFiles, '
+        "expected bool; got 'truel'",
+        'Warning: for Lib/TargetMachine, unrecognized enumerated value '
+        'MachineX86i',
+        "Warning: for Manifest/EnableDPIAwareness, expected bool; got 'fal'"])
+
+  def testConvertToMSBuildSettings_empty(self):
+    """Tests an empty conversion."""
+    msvs_settings = {}
+    expected_msbuild_settings = {}
+    actual_msbuild_settings = MSVSSettings.ConvertToMSBuildSettings(
+        msvs_settings,
+        self.stderr)
+    self.assertEqual(expected_msbuild_settings, actual_msbuild_settings)
+    self._ExpectedWarnings([])
+
+  def testConvertToMSBuildSettings_minimal(self):
+    """Tests a minimal conversion."""
+    msvs_settings = {
+        'VCCLCompilerTool': {
+            'AdditionalIncludeDirectories': 'dir1',
+            'AdditionalOptions': '/foo',
+            'BasicRuntimeChecks': '0',
+            },
+        'VCLinkerTool': {
+            'LinkTimeCodeGeneration': '1',
+            'ErrorReporting': '1',
+            'DataExecutionPrevention': '2',
+            },
+        }
+    expected_msbuild_settings = {
+        'ClCompile': {
+            'AdditionalIncludeDirectories': 'dir1',
+            'AdditionalOptions': '/foo',
+            'BasicRuntimeChecks': 'Default',
+            },
+        'Link': {
+            'LinkTimeCodeGeneration': 'UseLinkTimeCodeGeneration',
+            'LinkErrorReporting': 'PromptImmediately',
+            'DataExecutionPrevention': 'true',
+            },
+        }
+    actual_msbuild_settings = MSVSSettings.ConvertToMSBuildSettings(
+        msvs_settings,
+        self.stderr)
+    self.assertEqual(expected_msbuild_settings, actual_msbuild_settings)
+    self._ExpectedWarnings([])
+
+  def testConvertToMSBuildSettings_warnings(self):
+    """Tests conversion that generates warnings."""
+    msvs_settings = {
+        'VCCLCompilerTool': {
+            'AdditionalIncludeDirectories': '1',
+            'AdditionalOptions': '2',
+            # These are incorrect values:
+            'BasicRuntimeChecks': '12',
+            'BrowseInformation': '21',
+            'UsePrecompiledHeader': '13',
+            'GeneratePreprocessedFile': '14'},
+        'VCLinkerTool': {
+            # These are incorrect values:
+            'Driver': '10',
+            'LinkTimeCodeGeneration': '31',
+            'ErrorReporting': '21',
+            'FixedBaseAddress': '6'},
+        'VCResourceCompilerTool': {
+            # Custom
+            'Culture': '1003'}}
+    expected_msbuild_settings = {
+        'ClCompile': {
+            'AdditionalIncludeDirectories': '1',
+            'AdditionalOptions': '2'},
+        'Link': {},
+        'ResourceCompile': {
+            # Custom
+            'Culture': '0x03eb'}}
+    actual_msbuild_settings = MSVSSettings.ConvertToMSBuildSettings(
+        msvs_settings,
+        self.stderr)
+    self.assertEqual(expected_msbuild_settings, actual_msbuild_settings)
+    self._ExpectedWarnings([
+        'Warning: while converting VCCLCompilerTool/BasicRuntimeChecks to '
+        'MSBuild, index value (12) not in expected range [0, 4)',
+        'Warning: while converting VCCLCompilerTool/BrowseInformation to '
+        'MSBuild, index value (21) not in expected range [0, 3)',
+        'Warning: while converting VCCLCompilerTool/UsePrecompiledHeader to '
+        'MSBuild, index value (13) not in expected range [0, 3)',
+        'Warning: while converting VCCLCompilerTool/GeneratePreprocessedFile to '
+        'MSBuild, value must be one of [0, 1, 2]; got 14',
+
+        'Warning: while converting VCLinkerTool/Driver to '
+        'MSBuild, index value (10) not in expected range [0, 4)',
+        'Warning: while converting VCLinkerTool/LinkTimeCodeGeneration to '
+        'MSBuild, index value (31) not in expected range [0, 5)',
+        'Warning: while converting VCLinkerTool/ErrorReporting to '
+        'MSBuild, index value (21) not in expected range [0, 3)',
+        'Warning: while converting VCLinkerTool/FixedBaseAddress to '
+        'MSBuild, index value (6) not in expected range [0, 3)',
+        ])
+
+  def testConvertToMSBuildSettings_full_synthetic(self):
+    """Tests conversion of all the MSBuild settings."""
+    msvs_settings = {
+        'VCCLCompilerTool': {
+            'AdditionalIncludeDirectories': 'folder1;folder2;folder3',
+            'AdditionalOptions': 'a_string',
+            'AdditionalUsingDirectories': 'folder1;folder2;folder3',
+            'AssemblerListingLocation': 'a_file_name',
+            'AssemblerOutput': '0',
+            'BasicRuntimeChecks': '1',
+            'BrowseInformation': '2',
+            'BrowseInformationFile': 'a_file_name',
+            'BufferSecurityCheck': 'true',
+            'CallingConvention': '0',
+            'CompileAs': '1',
+            'DebugInformationFormat': '4',
+            'DefaultCharIsUnsigned': 'true',
+            'Detect64BitPortabilityProblems': 'true',
+            'DisableLanguageExtensions': 'true',
+            'DisableSpecificWarnings': 'd1;d2;d3',
+            'EnableEnhancedInstructionSet': '0',
+            'EnableFiberSafeOptimizations': 'true',
+            'EnableFunctionLevelLinking': 'true',
+            'EnableIntrinsicFunctions': 'true',
+            'EnablePREfast': 'true',
+            'ErrorReporting': '1',
+            'ExceptionHandling': '2',
+            'ExpandAttributedSource': 'true',
+            'FavorSizeOrSpeed': '0',
+            'FloatingPointExceptions': 'true',
+            'FloatingPointModel': '1',
+            'ForceConformanceInForLoopScope': 'true',
+            'ForcedIncludeFiles': 'file1;file2;file3',
+            'ForcedUsingFiles': 'file1;file2;file3',
+            'GeneratePreprocessedFile': '1',
+            'GenerateXMLDocumentationFiles': 'true',
+            'IgnoreStandardIncludePath': 'true',
+            'InlineFunctionExpansion': '2',
+            'KeepComments': 'true',
+            'MinimalRebuild': 'true',
+            'ObjectFile': 'a_file_name',
+            'OmitDefaultLibName': 'true',
+            'OmitFramePointers': 'true',
+            'OpenMP': 'true',
+            'Optimization': '3',
+            'PrecompiledHeaderFile': 'a_file_name',
+            'PrecompiledHeaderThrough': 'a_file_name',
+            'PreprocessorDefinitions': 'd1;d2;d3',
+            'ProgramDataBaseFileName': 'a_file_name',
+            'RuntimeLibrary': '0',
+            'RuntimeTypeInfo': 'true',
+            'ShowIncludes': 'true',
+            'SmallerTypeCheck': 'true',
+            'StringPooling': 'true',
+            'StructMemberAlignment': '1',
+            'SuppressStartupBanner': 'true',
+            'TreatWChar_tAsBuiltInType': 'true',
+            'UndefineAllPreprocessorDefinitions': 'true',
+            'UndefinePreprocessorDefinitions': 'd1;d2;d3',
+            'UseFullPaths': 'true',
+            'UsePrecompiledHeader': '1',
+            'UseUnicodeResponseFiles': 'true',
+            'WarnAsError': 'true',
+            'WarningLevel': '2',
+            'WholeProgramOptimization': 'true',
+            'XMLDocumentationFileName': 'a_file_name'},
+        'VCLinkerTool': {
+            'AdditionalDependencies': 'file1;file2;file3',
+            'AdditionalLibraryDirectories': 'folder1;folder2;folder3',
+            'AdditionalLibraryDirectories_excluded': 'folder1;folder2;folder3',
+            'AdditionalManifestDependencies': 'file1;file2;file3',
+            'AdditionalOptions': 'a_string',
+            'AddModuleNamesToAssembly': 'file1;file2;file3',
+            'AllowIsolation': 'true',
+            'AssemblyDebug': '0',
+            'AssemblyLinkResource': 'file1;file2;file3',
+            'BaseAddress': 'a_string',
+            'CLRImageType': '1',
+            'CLRThreadAttribute': '2',
+            'CLRUnmanagedCodeCheck': 'true',
+            'DataExecutionPrevention': '0',
+            'DelayLoadDLLs': 'file1;file2;file3',
+            'DelaySign': 'true',
+            'Driver': '1',
+            'EmbedManagedResourceFile': 'file1;file2;file3',
+            'EnableCOMDATFolding': '0',
+            'EnableUAC': 'true',
+            'EntryPointSymbol': 'a_string',
+            'ErrorReporting': '0',
+            'FixedBaseAddress': '1',
+            'ForceSymbolReferences': 'file1;file2;file3',
+            'FunctionOrder': 'a_file_name',
+            'GenerateDebugInformation': 'true',
+            'GenerateManifest': 'true',
+            'GenerateMapFile': 'true',
+            'HeapCommitSize': 'a_string',
+            'HeapReserveSize': 'a_string',
+            'IgnoreAllDefaultLibraries': 'true',
+            'IgnoreDefaultLibraryNames': 'file1;file2;file3',
+            'IgnoreEmbeddedIDL': 'true',
+            'IgnoreImportLibrary': 'true',
+            'ImportLibrary': 'a_file_name',
+            'KeyContainer': 'a_file_name',
+            'KeyFile': 'a_file_name',
+            'LargeAddressAware': '2',
+            'LinkIncremental': '1',
+            'LinkLibraryDependencies': 'true',
+            'LinkTimeCodeGeneration': '2',
+            'ManifestFile': 'a_file_name',
+            'MapExports': 'true',
+            'MapFileName': 'a_file_name',
+            'MergedIDLBaseFileName': 'a_file_name',
+            'MergeSections': 'a_string',
+            'MidlCommandFile': 'a_file_name',
+            'ModuleDefinitionFile': 'a_file_name',
+            'OptimizeForWindows98': '1',
+            'OptimizeReferences': '0',
+            'OutputFile': 'a_file_name',
+            'PerUserRedirection': 'true',
+            'Profile': 'true',
+            'ProfileGuidedDatabase': 'a_file_name',
+            'ProgramDatabaseFile': 'a_file_name',
+            'RandomizedBaseAddress': '1',
+            'RegisterOutput': 'true',
+            'ResourceOnlyDLL': 'true',
+            'SetChecksum': 'true',
+            'ShowProgress': '0',
+            'StackCommitSize': 'a_string',
+            'StackReserveSize': 'a_string',
+            'StripPrivateSymbols': 'a_file_name',
+            'SubSystem': '2',
+            'SupportUnloadOfDelayLoadedDLL': 'true',
+            'SuppressStartupBanner': 'true',
+            'SwapRunFromCD': 'true',
+            'SwapRunFromNet': 'true',
+            'TargetMachine': '3',
+            'TerminalServerAware': '2',
+            'TurnOffAssemblyGeneration': 'true',
+            'TypeLibraryFile': 'a_file_name',
+            'TypeLibraryResourceID': '33',
+            'UACExecutionLevel': '1',
+            'UACUIAccess': 'true',
+            'UseLibraryDependencyInputs': 'false',
+            'UseUnicodeResponseFiles': 'true',
+            'Version': 'a_string'},
+        'VCResourceCompilerTool': {
+            'AdditionalIncludeDirectories': 'folder1;folder2;folder3',
+            'AdditionalOptions': 'a_string',
+            'Culture': '1003',
+            'IgnoreStandardIncludePath': 'true',
+            'PreprocessorDefinitions': 'd1;d2;d3',
+            'ResourceOutputFileName': 'a_string',
+            'ShowProgress': 'true',
+            'SuppressStartupBanner': 'true',
+            'UndefinePreprocessorDefinitions': 'd1;d2;d3'},
+        'VCMIDLTool': {
+            'AdditionalIncludeDirectories': 'folder1;folder2;folder3',
+            'AdditionalOptions': 'a_string',
+            'CPreprocessOptions': 'a_string',
+            'DefaultCharType': '0',
+            'DLLDataFileName': 'a_file_name',
+            'EnableErrorChecks': '2',
+            'ErrorCheckAllocations': 'true',
+            'ErrorCheckBounds': 'true',
+            'ErrorCheckEnumRange': 'true',
+            'ErrorCheckRefPointers': 'true',
+            'ErrorCheckStubData': 'true',
+            'GenerateStublessProxies': 'true',
+            'GenerateTypeLibrary': 'true',
+            'HeaderFileName': 'a_file_name',
+            'IgnoreStandardIncludePath': 'true',
+            'InterfaceIdentifierFileName': 'a_file_name',
+            'MkTypLibCompatible': 'true',
+            'OutputDirectory': 'a_string',
+            'PreprocessorDefinitions': 'd1;d2;d3',
+            'ProxyFileName': 'a_file_name',
+            'RedirectOutputAndErrors': 'a_file_name',
+            'StructMemberAlignment': '3',
+            'SuppressStartupBanner': 'true',
+            'TargetEnvironment': '1',
+            'TypeLibraryName': 'a_file_name',
+            'UndefinePreprocessorDefinitions': 'd1;d2;d3',
+            'ValidateParameters': 'true',
+            'WarnAsError': 'true',
+            'WarningLevel': '4'},
+        'VCLibrarianTool': {
+            'AdditionalDependencies': 'file1;file2;file3',
+            'AdditionalLibraryDirectories': 'folder1;folder2;folder3',
+            'AdditionalLibraryDirectories_excluded': 'folder1;folder2;folder3',
+            'AdditionalOptions': 'a_string',
+            'ExportNamedFunctions': 'd1;d2;d3',
+            'ForceSymbolReferences': 'a_string',
+            'IgnoreAllDefaultLibraries': 'true',
+            'IgnoreSpecificDefaultLibraries': 'file1;file2;file3',
+            'LinkLibraryDependencies': 'true',
+            'ModuleDefinitionFile': 'a_file_name',
+            'OutputFile': 'a_file_name',
+            'SuppressStartupBanner': 'true',
+            'UseUnicodeResponseFiles': 'true'},
+        'VCManifestTool': {
+            'AdditionalManifestFiles': 'file1;file2;file3',
+            'AdditionalOptions': 'a_string',
+            'AssemblyIdentity': 'a_string',
+            'ComponentFileName': 'a_file_name',
+            'DependencyInformationFile': 'a_file_name',
+            'EmbedManifest': 'true',
+            'GenerateCatalogFiles': 'true',
+            'InputResourceManifests': 'a_string',
+            'ManifestResourceFile': 'my_name',
+            'OutputManifestFile': 'a_file_name',
+            'RegistrarScriptFile': 'a_file_name',
+            'ReplacementsFile': 'a_file_name',
+            'SuppressStartupBanner': 'true',
+            'TypeLibraryFile': 'a_file_name',
+            'UpdateFileHashes': 'true',
+            'UpdateFileHashesSearchPath': 'a_file_name',
+            'UseFAT32Workaround': 'true',
+            'UseUnicodeResponseFiles': 'true',
+            'VerboseOutput': 'true'}}
+    expected_msbuild_settings = {
+        'ClCompile': {
+            'AdditionalIncludeDirectories': 'folder1;folder2;folder3',
+            'AdditionalOptions': 'a_string /J',
+            'AdditionalUsingDirectories': 'folder1;folder2;folder3',
+            'AssemblerListingLocation': 'a_file_name',
+            'AssemblerOutput': 'NoListing',
+            'BasicRuntimeChecks': 'StackFrameRuntimeCheck',
+            'BrowseInformation': 'true',
+            'BrowseInformationFile': 'a_file_name',
+            'BufferSecurityCheck': 'true',
+            'CallingConvention': 'Cdecl',
+            'CompileAs': 'CompileAsC',
+            'DebugInformationFormat': 'EditAndContinue',
+            'DisableLanguageExtensions': 'true',
+            'DisableSpecificWarnings': 'd1;d2;d3',
+            'EnableEnhancedInstructionSet': 'NotSet',
+            'EnableFiberSafeOptimizations': 'true',
+            'EnablePREfast': 'true',
+            'ErrorReporting': 'Prompt',
+            'ExceptionHandling': 'Async',
+            'ExpandAttributedSource': 'true',
+            'FavorSizeOrSpeed': 'Neither',
+            'FloatingPointExceptions': 'true',
+            'FloatingPointModel': 'Strict',
+            'ForceConformanceInForLoopScope': 'true',
+            'ForcedIncludeFiles': 'file1;file2;file3',
+            'ForcedUsingFiles': 'file1;file2;file3',
+            'FunctionLevelLinking': 'true',
+            'GenerateXMLDocumentationFiles': 'true',
+            'IgnoreStandardIncludePath': 'true',
+            'InlineFunctionExpansion': 'AnySuitable',
+            'IntrinsicFunctions': 'true',
+            'MinimalRebuild': 'true',
+            'ObjectFileName': 'a_file_name',
+            'OmitDefaultLibName': 'true',
+            'OmitFramePointers': 'true',
+            'OpenMPSupport': 'true',
+            'Optimization': 'Full',
+            'PrecompiledHeader': 'Create',
+            'PrecompiledHeaderFile': 'a_file_name',
+            'PrecompiledHeaderOutputFile': 'a_file_name',
+            'PreprocessKeepComments': 'true',
+            'PreprocessorDefinitions': 'd1;d2;d3',
+            'PreprocessSuppressLineNumbers': 'false',
+            'PreprocessToFile': 'true',
+            'ProgramDataBaseFileName': 'a_file_name',
+            'RuntimeLibrary': 'MultiThreaded',
+            'RuntimeTypeInfo': 'true',
+            'ShowIncludes': 'true',
+            'SmallerTypeCheck': 'true',
+            'StringPooling': 'true',
+            'StructMemberAlignment': '1Byte',
+            'SuppressStartupBanner': 'true',
+            'TreatWarningAsError': 'true',
+            'TreatWChar_tAsBuiltInType': 'true',
+            'UndefineAllPreprocessorDefinitions': 'true',
+            'UndefinePreprocessorDefinitions': 'd1;d2;d3',
+            'UseFullPaths': 'true',
+            'WarningLevel': 'Level2',
+            'WholeProgramOptimization': 'true',
+            'XMLDocumentationFileName': 'a_file_name'},
+        'Link': {
+            'AdditionalDependencies': 'file1;file2;file3',
+            'AdditionalLibraryDirectories': 'folder1;folder2;folder3',
+            'AdditionalManifestDependencies': 'file1;file2;file3',
+            'AdditionalOptions': 'a_string',
+            'AddModuleNamesToAssembly': 'file1;file2;file3',
+            'AllowIsolation': 'true',
+            'AssemblyDebug': '',
+            'AssemblyLinkResource': 'file1;file2;file3',
+            'BaseAddress': 'a_string',
+            'CLRImageType': 'ForceIJWImage',
+            'CLRThreadAttribute': 'STAThreadingAttribute',
+            'CLRUnmanagedCodeCheck': 'true',
+            'DataExecutionPrevention': '',
+            'DelayLoadDLLs': 'file1;file2;file3',
+            'DelaySign': 'true',
+            'Driver': 'Driver',
+            'EmbedManagedResourceFile': 'file1;file2;file3',
+            'EnableCOMDATFolding': '',
+            'EnableUAC': 'true',
+            'EntryPointSymbol': 'a_string',
+            'FixedBaseAddress': 'false',
+            'ForceSymbolReferences': 'file1;file2;file3',
+            'FunctionOrder': 'a_file_name',
+            'GenerateDebugInformation': 'true',
+            'GenerateMapFile': 'true',
+            'HeapCommitSize': 'a_string',
+            'HeapReserveSize': 'a_string',
+            'IgnoreAllDefaultLibraries': 'true',
+            'IgnoreEmbeddedIDL': 'true',
+            'IgnoreSpecificDefaultLibraries': 'file1;file2;file3',
+            'ImportLibrary': 'a_file_name',
+            'KeyContainer': 'a_file_name',
+            'KeyFile': 'a_file_name',
+            'LargeAddressAware': 'true',
+            'LinkErrorReporting': 'NoErrorReport',
+            'LinkTimeCodeGeneration': 'PGInstrument',
+            'ManifestFile': 'a_file_name',
+            'MapExports': 'true',
+            'MapFileName': 'a_file_name',
+            'MergedIDLBaseFileName': 'a_file_name',
+            'MergeSections': 'a_string',
+            'MidlCommandFile': 'a_file_name',
+            'ModuleDefinitionFile': 'a_file_name',
+            'NoEntryPoint': 'true',
+            'OptimizeReferences': '',
+            'OutputFile': 'a_file_name',
+            'PerUserRedirection': 'true',
+            'Profile': 'true',
+            'ProfileGuidedDatabase': 'a_file_name',
+            'ProgramDatabaseFile': 'a_file_name',
+            'RandomizedBaseAddress': 'false',
+            'RegisterOutput': 'true',
+            'SetChecksum': 'true',
+            'ShowProgress': 'NotSet',
+            'StackCommitSize': 'a_string',
+            'StackReserveSize': 'a_string',
+            'StripPrivateSymbols': 'a_file_name',
+            'SubSystem': 'Windows',
+            'SupportUnloadOfDelayLoadedDLL': 'true',
+            'SuppressStartupBanner': 'true',
+            'SwapRunFromCD': 'true',
+            'SwapRunFromNET': 'true',
+            'TargetMachine': 'MachineARM',
+            'TerminalServerAware': 'true',
+            'TurnOffAssemblyGeneration': 'true',
+            'TypeLibraryFile': 'a_file_name',
+            'TypeLibraryResourceID': '33',
+            'UACExecutionLevel': 'HighestAvailable',
+            'UACUIAccess': 'true',
+            'Version': 'a_string'},
+        'ResourceCompile': {
+            'AdditionalIncludeDirectories': 'folder1;folder2;folder3',
+            'AdditionalOptions': 'a_string',
+            'Culture': '0x03eb',
+            'IgnoreStandardIncludePath': 'true',
+            'PreprocessorDefinitions': 'd1;d2;d3',
+            'ResourceOutputFileName': 'a_string',
+            'ShowProgress': 'true',
+            'SuppressStartupBanner': 'true',
+            'UndefinePreprocessorDefinitions': 'd1;d2;d3'},
+        'Midl': {
+            'AdditionalIncludeDirectories': 'folder1;folder2;folder3',
+            'AdditionalOptions': 'a_string',
+            'CPreprocessOptions': 'a_string',
+            'DefaultCharType': 'Unsigned',
+            'DllDataFileName': 'a_file_name',
+            'EnableErrorChecks': 'All',
+            'ErrorCheckAllocations': 'true',
+            'ErrorCheckBounds': 'true',
+            'ErrorCheckEnumRange': 'true',
+            'ErrorCheckRefPointers': 'true',
+            'ErrorCheckStubData': 'true',
+            'GenerateStublessProxies': 'true',
+            'GenerateTypeLibrary': 'true',
+            'HeaderFileName': 'a_file_name',
+            'IgnoreStandardIncludePath': 'true',
+            'InterfaceIdentifierFileName': 'a_file_name',
+            'MkTypLibCompatible': 'true',
+            'OutputDirectory': 'a_string',
+            'PreprocessorDefinitions': 'd1;d2;d3',
+            'ProxyFileName': 'a_file_name',
+            'RedirectOutputAndErrors': 'a_file_name',
+            'StructMemberAlignment': '4',
+            'SuppressStartupBanner': 'true',
+            'TargetEnvironment': 'Win32',
+            'TypeLibraryName': 'a_file_name',
+            'UndefinePreprocessorDefinitions': 'd1;d2;d3',
+            'ValidateAllParameters': 'true',
+            'WarnAsError': 'true',
+            'WarningLevel': '4'},
+        'Lib': {
+            'AdditionalDependencies': 'file1;file2;file3',
+            'AdditionalLibraryDirectories': 'folder1;folder2;folder3',
+            'AdditionalOptions': 'a_string',
+            'ExportNamedFunctions': 'd1;d2;d3',
+            'ForceSymbolReferences': 'a_string',
+            'IgnoreAllDefaultLibraries': 'true',
+            'IgnoreSpecificDefaultLibraries': 'file1;file2;file3',
+            'ModuleDefinitionFile': 'a_file_name',
+            'OutputFile': 'a_file_name',
+            'SuppressStartupBanner': 'true',
+            'UseUnicodeResponseFiles': 'true'},
+        'Manifest': {
+            'AdditionalManifestFiles': 'file1;file2;file3',
+            'AdditionalOptions': 'a_string',
+            'AssemblyIdentity': 'a_string',
+            'ComponentFileName': 'a_file_name',
+            'GenerateCatalogFiles': 'true',
+            'InputResourceManifests': 'a_string',
+            'OutputManifestFile': 'a_file_name',
+            'RegistrarScriptFile': 'a_file_name',
+            'ReplacementsFile': 'a_file_name',
+            'SuppressStartupBanner': 'true',
+            'TypeLibraryFile': 'a_file_name',
+            'UpdateFileHashes': 'true',
+            'UpdateFileHashesSearchPath': 'a_file_name',
+            'VerboseOutput': 'true'},
+        'ManifestResourceCompile': {
+            'ResourceOutputFileName': 'my_name'},
+        'ProjectReference': {
+            'LinkLibraryDependencies': 'true',
+            'UseLibraryDependencyInputs': 'false'},
+        '': {
+            'EmbedManifest': 'true',
+            'GenerateManifest': 'true',
+            'IgnoreImportLibrary': 'true',
+            'LinkIncremental': 'false'}}
+    actual_msbuild_settings = MSVSSettings.ConvertToMSBuildSettings(
+        msvs_settings,
+        self.stderr)
+    self.assertEqual(expected_msbuild_settings, actual_msbuild_settings)
+    self._ExpectedWarnings([])
+
+  def testConvertToMSBuildSettings_actual(self):
+    """Tests the conversion of an actual project.
+
+    A VS2008 project with most of the options defined was created through the
+    VS2008 IDE.  It was then converted to VS2010.  The tool settings found in
+    the .vcproj and .vcxproj files were converted to the two dictionaries
+    msvs_settings and expected_msbuild_settings.
+
+    Note that for many settings, the VS2010 converter adds macros like
+    %(AdditionalIncludeDirectories) to make sure than inherited values are
+    included.  Since the Gyp projects we generate do not use inheritance,
+    we removed these macros.  They were:
+        ClCompile:
+            AdditionalIncludeDirectories:  ';%(AdditionalIncludeDirectories)'
+            AdditionalOptions:  ' %(AdditionalOptions)'
+            AdditionalUsingDirectories:  ';%(AdditionalUsingDirectories)'
+            DisableSpecificWarnings: ';%(DisableSpecificWarnings)',
+            ForcedIncludeFiles:  ';%(ForcedIncludeFiles)',
+            ForcedUsingFiles:  ';%(ForcedUsingFiles)',
+            PreprocessorDefinitions:  ';%(PreprocessorDefinitions)',
+            UndefinePreprocessorDefinitions:
+                ';%(UndefinePreprocessorDefinitions)',
+        Link:
+            AdditionalDependencies:  ';%(AdditionalDependencies)',
+            AdditionalLibraryDirectories:  ';%(AdditionalLibraryDirectories)',
+            AdditionalManifestDependencies:
+                ';%(AdditionalManifestDependencies)',
+            AdditionalOptions:  ' %(AdditionalOptions)',
+            AddModuleNamesToAssembly:  ';%(AddModuleNamesToAssembly)',
+            AssemblyLinkResource:  ';%(AssemblyLinkResource)',
+            DelayLoadDLLs:  ';%(DelayLoadDLLs)',
+            EmbedManagedResourceFile:  ';%(EmbedManagedResourceFile)',
+            ForceSymbolReferences:  ';%(ForceSymbolReferences)',
+            IgnoreSpecificDefaultLibraries:
+                ';%(IgnoreSpecificDefaultLibraries)',
+        ResourceCompile:
+            AdditionalIncludeDirectories:  ';%(AdditionalIncludeDirectories)',
+            AdditionalOptions:  ' %(AdditionalOptions)',
+            PreprocessorDefinitions:  ';%(PreprocessorDefinitions)',
+        Manifest:
+            AdditionalManifestFiles:  ';%(AdditionalManifestFiles)',
+            AdditionalOptions:  ' %(AdditionalOptions)',
+            InputResourceManifests:  ';%(InputResourceManifests)',
+    """
+    msvs_settings = {
+        'VCCLCompilerTool': {
+            'AdditionalIncludeDirectories': 'dir1',
+            'AdditionalOptions': '/more',
+            'AdditionalUsingDirectories': 'test',
+            'AssemblerListingLocation': '$(IntDir)\\a',
+            'AssemblerOutput': '1',
+            'BasicRuntimeChecks': '3',
+            'BrowseInformation': '1',
+            'BrowseInformationFile': '$(IntDir)\\e',
+            'BufferSecurityCheck': 'false',
+            'CallingConvention': '1',
+            'CompileAs': '1',
+            'DebugInformationFormat': '4',
+            'DefaultCharIsUnsigned': 'true',
+            'Detect64BitPortabilityProblems': 'true',
+            'DisableLanguageExtensions': 'true',
+            'DisableSpecificWarnings': 'abc',
+            'EnableEnhancedInstructionSet': '1',
+            'EnableFiberSafeOptimizations': 'true',
+            'EnableFunctionLevelLinking': 'true',
+            'EnableIntrinsicFunctions': 'true',
+            'EnablePREfast': 'true',
+            'ErrorReporting': '2',
+            'ExceptionHandling': '2',
+            'ExpandAttributedSource': 'true',
+            'FavorSizeOrSpeed': '2',
+            'FloatingPointExceptions': 'true',
+            'FloatingPointModel': '1',
+            'ForceConformanceInForLoopScope': 'false',
+            'ForcedIncludeFiles': 'def',
+            'ForcedUsingFiles': 'ge',
+            'GeneratePreprocessedFile': '2',
+            'GenerateXMLDocumentationFiles': 'true',
+            'IgnoreStandardIncludePath': 'true',
+            'InlineFunctionExpansion': '1',
+            'KeepComments': 'true',
+            'MinimalRebuild': 'true',
+            'ObjectFile': '$(IntDir)\\b',
+            'OmitDefaultLibName': 'true',
+            'OmitFramePointers': 'true',
+            'OpenMP': 'true',
+            'Optimization': '3',
+            'PrecompiledHeaderFile': '$(IntDir)\\$(TargetName).pche',
+            'PrecompiledHeaderThrough': 'StdAfx.hd',
+            'PreprocessorDefinitions': 'WIN32;_DEBUG;_CONSOLE',
+            'ProgramDataBaseFileName': '$(IntDir)\\vc90b.pdb',
+            'RuntimeLibrary': '3',
+            'RuntimeTypeInfo': 'false',
+            'ShowIncludes': 'true',
+            'SmallerTypeCheck': 'true',
+            'StringPooling': 'true',
+            'StructMemberAlignment': '3',
+            'SuppressStartupBanner': 'false',
+            'TreatWChar_tAsBuiltInType': 'false',
+            'UndefineAllPreprocessorDefinitions': 'true',
+            'UndefinePreprocessorDefinitions': 'wer',
+            'UseFullPaths': 'true',
+            'UsePrecompiledHeader': '0',
+            'UseUnicodeResponseFiles': 'false',
+            'WarnAsError': 'true',
+            'WarningLevel': '3',
+            'WholeProgramOptimization': 'true',
+            'XMLDocumentationFileName': '$(IntDir)\\c'},
+        'VCLinkerTool': {
+            'AdditionalDependencies': 'zx',
+            'AdditionalLibraryDirectories': 'asd',
+            'AdditionalManifestDependencies': 's2',
+            'AdditionalOptions': '/mor2',
+            'AddModuleNamesToAssembly': 'd1',
+            'AllowIsolation': 'false',
+            'AssemblyDebug': '1',
+            'AssemblyLinkResource': 'd5',
+            'BaseAddress': '23423',
+            'CLRImageType': '3',
+            'CLRThreadAttribute': '1',
+            'CLRUnmanagedCodeCheck': 'true',
+            'DataExecutionPrevention': '0',
+            'DelayLoadDLLs': 'd4',
+            'DelaySign': 'true',
+            'Driver': '2',
+            'EmbedManagedResourceFile': 'd2',
+            'EnableCOMDATFolding': '1',
+            'EnableUAC': 'false',
+            'EntryPointSymbol': 'f5',
+            'ErrorReporting': '2',
+            'FixedBaseAddress': '1',
+            'ForceSymbolReferences': 'd3',
+            'FunctionOrder': 'fssdfsd',
+            'GenerateDebugInformation': 'true',
+            'GenerateManifest': 'false',
+            'GenerateMapFile': 'true',
+            'HeapCommitSize': '13',
+            'HeapReserveSize': '12',
+            'IgnoreAllDefaultLibraries': 'true',
+            'IgnoreDefaultLibraryNames': 'flob;flok',
+            'IgnoreEmbeddedIDL': 'true',
+            'IgnoreImportLibrary': 'true',
+            'ImportLibrary': 'f4',
+            'KeyContainer': 'f7',
+            'KeyFile': 'f6',
+            'LargeAddressAware': '2',
+            'LinkIncremental': '0',
+            'LinkLibraryDependencies': 'false',
+            'LinkTimeCodeGeneration': '1',
+            'ManifestFile':
+            '$(IntDir)\\$(TargetFileName).2intermediate.manifest',
+            'MapExports': 'true',
+            'MapFileName': 'd5',
+            'MergedIDLBaseFileName': 'f2',
+            'MergeSections': 'f5',
+            'MidlCommandFile': 'f1',
+            'ModuleDefinitionFile': 'sdsd',
+            'OptimizeForWindows98': '2',
+            'OptimizeReferences': '2',
+            'OutputFile': '$(OutDir)\\$(ProjectName)2.exe',
+            'PerUserRedirection': 'true',
+            'Profile': 'true',
+            'ProfileGuidedDatabase': '$(TargetDir)$(TargetName).pgdd',
+            'ProgramDatabaseFile': 'Flob.pdb',
+            'RandomizedBaseAddress': '1',
+            'RegisterOutput': 'true',
+            'ResourceOnlyDLL': 'true',
+            'SetChecksum': 'false',
+            'ShowProgress': '1',
+            'StackCommitSize': '15',
+            'StackReserveSize': '14',
+            'StripPrivateSymbols': 'd3',
+            'SubSystem': '1',
+            'SupportUnloadOfDelayLoadedDLL': 'true',
+            'SuppressStartupBanner': 'false',
+            'SwapRunFromCD': 'true',
+            'SwapRunFromNet': 'true',
+            'TargetMachine': '1',
+            'TerminalServerAware': '1',
+            'TurnOffAssemblyGeneration': 'true',
+            'TypeLibraryFile': 'f3',
+            'TypeLibraryResourceID': '12',
+            'UACExecutionLevel': '2',
+            'UACUIAccess': 'true',
+            'UseLibraryDependencyInputs': 'true',
+            'UseUnicodeResponseFiles': 'false',
+            'Version': '333'},
+        'VCResourceCompilerTool': {
+            'AdditionalIncludeDirectories': 'f3',
+            'AdditionalOptions': '/more3',
+            'Culture': '3084',
+            'IgnoreStandardIncludePath': 'true',
+            'PreprocessorDefinitions': '_UNICODE;UNICODE2',
+            'ResourceOutputFileName': '$(IntDir)/$(InputName)3.res',
+            'ShowProgress': 'true'},
+        'VCManifestTool': {
+            'AdditionalManifestFiles': 'sfsdfsd',
+            'AdditionalOptions': 'afdsdafsd',
+            'AssemblyIdentity': 'sddfdsadfsa',
+            'ComponentFileName': 'fsdfds',
+            'DependencyInformationFile': '$(IntDir)\\mt.depdfd',
+            'EmbedManifest': 'false',
+            'GenerateCatalogFiles': 'true',
+            'InputResourceManifests': 'asfsfdafs',
+            'ManifestResourceFile':
+            '$(IntDir)\\$(TargetFileName).embed.manifest.resfdsf',
+            'OutputManifestFile': '$(TargetPath).manifestdfs',
+            'RegistrarScriptFile': 'sdfsfd',
+            'ReplacementsFile': 'sdffsd',
+            'SuppressStartupBanner': 'false',
+            'TypeLibraryFile': 'sfsd',
+            'UpdateFileHashes': 'true',
+            'UpdateFileHashesSearchPath': 'sfsd',
+            'UseFAT32Workaround': 'true',
+            'UseUnicodeResponseFiles': 'false',
+            'VerboseOutput': 'true'}}
+    expected_msbuild_settings = {
+        'ClCompile': {
+            'AdditionalIncludeDirectories': 'dir1',
+            'AdditionalOptions': '/more /J',
+            'AdditionalUsingDirectories': 'test',
+            'AssemblerListingLocation': '$(IntDir)a',
+            'AssemblerOutput': 'AssemblyCode',
+            'BasicRuntimeChecks': 'EnableFastChecks',
+            'BrowseInformation': 'true',
+            'BrowseInformationFile': '$(IntDir)e',
+            'BufferSecurityCheck': 'false',
+            'CallingConvention': 'FastCall',
+            'CompileAs': 'CompileAsC',
+            'DebugInformationFormat': 'EditAndContinue',
+            'DisableLanguageExtensions': 'true',
+            'DisableSpecificWarnings': 'abc',
+            'EnableEnhancedInstructionSet': 'StreamingSIMDExtensions',
+            'EnableFiberSafeOptimizations': 'true',
+            'EnablePREfast': 'true',
+            'ErrorReporting': 'Queue',
+            'ExceptionHandling': 'Async',
+            'ExpandAttributedSource': 'true',
+            'FavorSizeOrSpeed': 'Size',
+            'FloatingPointExceptions': 'true',
+            'FloatingPointModel': 'Strict',
+            'ForceConformanceInForLoopScope': 'false',
+            'ForcedIncludeFiles': 'def',
+            'ForcedUsingFiles': 'ge',
+            'FunctionLevelLinking': 'true',
+            'GenerateXMLDocumentationFiles': 'true',
+            'IgnoreStandardIncludePath': 'true',
+            'InlineFunctionExpansion': 'OnlyExplicitInline',
+            'IntrinsicFunctions': 'true',
+            'MinimalRebuild': 'true',
+            'ObjectFileName': '$(IntDir)b',
+            'OmitDefaultLibName': 'true',
+            'OmitFramePointers': 'true',
+            'OpenMPSupport': 'true',
+            'Optimization': 'Full',
+            'PrecompiledHeader': 'NotUsing',  # Actual conversion gives ''
+            'PrecompiledHeaderFile': 'StdAfx.hd',
+            'PrecompiledHeaderOutputFile': '$(IntDir)$(TargetName).pche',
+            'PreprocessKeepComments': 'true',
+            'PreprocessorDefinitions': 'WIN32;_DEBUG;_CONSOLE',
+            'PreprocessSuppressLineNumbers': 'true',
+            'PreprocessToFile': 'true',
+            'ProgramDataBaseFileName': '$(IntDir)vc90b.pdb',
+            'RuntimeLibrary': 'MultiThreadedDebugDLL',
+            'RuntimeTypeInfo': 'false',
+            'ShowIncludes': 'true',
+            'SmallerTypeCheck': 'true',
+            'StringPooling': 'true',
+            'StructMemberAlignment': '4Bytes',
+            'SuppressStartupBanner': 'false',
+            'TreatWarningAsError': 'true',
+            'TreatWChar_tAsBuiltInType': 'false',
+            'UndefineAllPreprocessorDefinitions': 'true',
+            'UndefinePreprocessorDefinitions': 'wer',
+            'UseFullPaths': 'true',
+            'WarningLevel': 'Level3',
+            'WholeProgramOptimization': 'true',
+            'XMLDocumentationFileName': '$(IntDir)c'},
+        'Link': {
+            'AdditionalDependencies': 'zx',
+            'AdditionalLibraryDirectories': 'asd',
+            'AdditionalManifestDependencies': 's2',
+            'AdditionalOptions': '/mor2',
+            'AddModuleNamesToAssembly': 'd1',
+            'AllowIsolation': 'false',
+            'AssemblyDebug': 'true',
+            'AssemblyLinkResource': 'd5',
+            'BaseAddress': '23423',
+            'CLRImageType': 'ForceSafeILImage',
+            'CLRThreadAttribute': 'MTAThreadingAttribute',
+            'CLRUnmanagedCodeCheck': 'true',
+            'DataExecutionPrevention': '',
+            'DelayLoadDLLs': 'd4',
+            'DelaySign': 'true',
+            'Driver': 'UpOnly',
+            'EmbedManagedResourceFile': 'd2',
+            'EnableCOMDATFolding': 'false',
+            'EnableUAC': 'false',
+            'EntryPointSymbol': 'f5',
+            'FixedBaseAddress': 'false',
+            'ForceSymbolReferences': 'd3',
+            'FunctionOrder': 'fssdfsd',
+            'GenerateDebugInformation': 'true',
+            'GenerateMapFile': 'true',
+            'HeapCommitSize': '13',
+            'HeapReserveSize': '12',
+            'IgnoreAllDefaultLibraries': 'true',
+            'IgnoreEmbeddedIDL': 'true',
+            'IgnoreSpecificDefaultLibraries': 'flob;flok',
+            'ImportLibrary': 'f4',
+            'KeyContainer': 'f7',
+            'KeyFile': 'f6',
+            'LargeAddressAware': 'true',
+            'LinkErrorReporting': 'QueueForNextLogin',
+            'LinkTimeCodeGeneration': 'UseLinkTimeCodeGeneration',
+            'ManifestFile': '$(IntDir)$(TargetFileName).2intermediate.manifest',
+            'MapExports': 'true',
+            'MapFileName': 'd5',
+            'MergedIDLBaseFileName': 'f2',
+            'MergeSections': 'f5',
+            'MidlCommandFile': 'f1',
+            'ModuleDefinitionFile': 'sdsd',
+            'NoEntryPoint': 'true',
+            'OptimizeReferences': 'true',
+            'OutputFile': '$(OutDir)$(ProjectName)2.exe',
+            'PerUserRedirection': 'true',
+            'Profile': 'true',
+            'ProfileGuidedDatabase': '$(TargetDir)$(TargetName).pgdd',
+            'ProgramDatabaseFile': 'Flob.pdb',
+            'RandomizedBaseAddress': 'false',
+            'RegisterOutput': 'true',
+            'SetChecksum': 'false',
+            'ShowProgress': 'LinkVerbose',
+            'StackCommitSize': '15',
+            'StackReserveSize': '14',
+            'StripPrivateSymbols': 'd3',
+            'SubSystem': 'Console',
+            'SupportUnloadOfDelayLoadedDLL': 'true',
+            'SuppressStartupBanner': 'false',
+            'SwapRunFromCD': 'true',
+            'SwapRunFromNET': 'true',
+            'TargetMachine': 'MachineX86',
+            'TerminalServerAware': 'false',
+            'TurnOffAssemblyGeneration': 'true',
+            'TypeLibraryFile': 'f3',
+            'TypeLibraryResourceID': '12',
+            'UACExecutionLevel': 'RequireAdministrator',
+            'UACUIAccess': 'true',
+            'Version': '333'},
+        'ResourceCompile': {
+            'AdditionalIncludeDirectories': 'f3',
+            'AdditionalOptions': '/more3',
+            'Culture': '0x0c0c',
+            'IgnoreStandardIncludePath': 'true',
+            'PreprocessorDefinitions': '_UNICODE;UNICODE2',
+            'ResourceOutputFileName': '$(IntDir)%(Filename)3.res',
+            'ShowProgress': 'true'},
+        'Manifest': {
+            'AdditionalManifestFiles': 'sfsdfsd',
+            'AdditionalOptions': 'afdsdafsd',
+            'AssemblyIdentity': 'sddfdsadfsa',
+            'ComponentFileName': 'fsdfds',
+            'GenerateCatalogFiles': 'true',
+            'InputResourceManifests': 'asfsfdafs',
+            'OutputManifestFile': '$(TargetPath).manifestdfs',
+            'RegistrarScriptFile': 'sdfsfd',
+            'ReplacementsFile': 'sdffsd',
+            'SuppressStartupBanner': 'false',
+            'TypeLibraryFile': 'sfsd',
+            'UpdateFileHashes': 'true',
+            'UpdateFileHashesSearchPath': 'sfsd',
+            'VerboseOutput': 'true'},
+        'ProjectReference': {
+            'LinkLibraryDependencies': 'false',
+            'UseLibraryDependencyInputs': 'true'},
+        '': {
+            'EmbedManifest': 'false',
+            'GenerateManifest': 'false',
+            'IgnoreImportLibrary': 'true',
+            'LinkIncremental': ''
+            },
+        'ManifestResourceCompile': {
+            'ResourceOutputFileName':
+            '$(IntDir)$(TargetFileName).embed.manifest.resfdsf'}
+        }
+    actual_msbuild_settings = MSVSSettings.ConvertToMSBuildSettings(
+        msvs_settings,
+        self.stderr)
+    self.assertEqual(expected_msbuild_settings, actual_msbuild_settings)
+    self._ExpectedWarnings([])
+
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/webWidgetTCT_device/tools/gyp/pylib/gyp/MSVSToolFile.py b/webWidgetTCT_device/tools/gyp/pylib/gyp/MSVSToolFile.py
new file mode 100755 (executable)
index 0000000..74e529a
--- /dev/null
@@ -0,0 +1,58 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Visual Studio project reader/writer."""
+
+import gyp.common
+import gyp.easy_xml as easy_xml
+
+
+class Writer(object):
+  """Visual Studio XML tool file writer."""
+
+  def __init__(self, tool_file_path, name):
+    """Initializes the tool file.
+
+    Args:
+      tool_file_path: Path to the tool file.
+      name: Name of the tool file.
+    """
+    self.tool_file_path = tool_file_path
+    self.name = name
+    self.rules_section = ['Rules']
+
+  def AddCustomBuildRule(self, name, cmd, description,
+                         additional_dependencies,
+                         outputs, extensions):
+    """Adds a rule to the tool file.
+
+    Args:
+      name: Name of the rule.
+      description: Description of the rule.
+      cmd: Command line of the rule.
+      additional_dependencies: other files which may trigger the rule.
+      outputs: outputs of the rule.
+      extensions: extensions handled by the rule.
+    """
+    rule = ['CustomBuildRule',
+            {'Name': name,
+             'ExecutionDescription': description,
+             'CommandLine': cmd,
+             'Outputs': ';'.join(outputs),
+             'FileExtensions': ';'.join(extensions),
+             'AdditionalDependencies':
+                 ';'.join(additional_dependencies)
+            }]
+    self.rules_section.append(rule)
+
+  def WriteIfChanged(self):
+    """Writes the tool file."""
+    content = ['VisualStudioToolFile',
+               {'Version': '8.00',
+                'Name': self.name
+               },
+               self.rules_section
+               ]
+    easy_xml.WriteXmlIfChanged(content, self.tool_file_path,
+                               encoding="Windows-1252")
diff --git a/webWidgetTCT_device/tools/gyp/pylib/gyp/MSVSUserFile.py b/webWidgetTCT_device/tools/gyp/pylib/gyp/MSVSUserFile.py
new file mode 100755 (executable)
index 0000000..6c07e9a
--- /dev/null
@@ -0,0 +1,147 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Visual Studio user preferences file writer."""
+
+import os
+import re
+import socket # for gethostname
+
+import gyp.common
+import gyp.easy_xml as easy_xml
+
+
+#------------------------------------------------------------------------------
+
+def _FindCommandInPath(command):
+  """If there are no slashes in the command given, this function
+     searches the PATH env to find the given command, and converts it
+     to an absolute path.  We have to do this because MSVS is looking
+     for an actual file to launch a debugger on, not just a command
+     line.  Note that this happens at GYP time, so anything needing to
+     be built needs to have a full path."""
+  if '/' in command or '\\' in command:
+    # If the command already has path elements (either relative or
+    # absolute), then assume it is constructed properly.
+    return command
+  else:
+    # Search through the path list and find an existing file that
+    # we can access.
+    paths = os.environ.get('PATH','').split(os.pathsep)
+    for path in paths:
+      item = os.path.join(path, command)
+      if os.path.isfile(item) and os.access(item, os.X_OK):
+        return item
+  return command
+
+def _QuoteWin32CommandLineArgs(args):
+  new_args = []
+  for arg in args:
+    # Replace all double-quotes with double-double-quotes to escape
+    # them for cmd shell, and then quote the whole thing if there
+    # are any.
+    if arg.find('"') != -1:
+      arg = '""'.join(arg.split('"'))
+      arg = '"%s"' % arg
+
+    # Otherwise, if there are any spaces, quote the whole arg.
+    elif re.search(r'[ \t\n]', arg):
+      arg = '"%s"' % arg
+    new_args.append(arg)
+  return new_args
+
+class Writer(object):
+  """Visual Studio XML user user file writer."""
+
+  def __init__(self, user_file_path, version, name):
+    """Initializes the user file.
+
+    Args:
+      user_file_path: Path to the user file.
+      version: Version info.
+      name: Name of the user file.
+    """
+    self.user_file_path = user_file_path
+    self.version = version
+    self.name = name
+    self.configurations = {}
+
+  def AddConfig(self, name):
+    """Adds a configuration to the project.
+
+    Args:
+      name: Configuration name.
+    """
+    self.configurations[name] = ['Configuration', {'Name': name}]
+
+  def AddDebugSettings(self, config_name, command, environment = {},
+                       working_directory=""):
+    """Adds a DebugSettings node to the user file for a particular config.
+
+    Args:
+      command: command line to run.  First element in the list is the
+        executable.  All elements of the command will be quoted if
+        necessary.
+      working_directory: other files which may trigger the rule. (optional)
+    """
+    command = _QuoteWin32CommandLineArgs(command)
+
+    abs_command = _FindCommandInPath(command[0])
+
+    if environment and isinstance(environment, dict):
+      env_list = ['%s="%s"' % (key, val)
+                  for (key,val) in environment.iteritems()]
+      environment = ' '.join(env_list)
+    else:
+      environment = ''
+
+    n_cmd = ['DebugSettings',
+             {'Command': abs_command,
+              'WorkingDirectory': working_directory,
+              'CommandArguments': " ".join(command[1:]),
+              'RemoteMachine': socket.gethostname(),
+              'Environment': environment,
+              'EnvironmentMerge': 'true',
+              # Currently these are all "dummy" values that we're just setting
+              # in the default manner that MSVS does it.  We could use some of
+              # these to add additional capabilities, I suppose, but they might
+              # not have parity with other platforms then.
+              'Attach': 'false',
+              'DebuggerType': '3',  # 'auto' debugger
+              'Remote': '1',
+              'RemoteCommand': '',
+              'HttpUrl': '',
+              'PDBPath': '',
+              'SQLDebugging': '',
+              'DebuggerFlavor': '0',
+              'MPIRunCommand': '',
+              'MPIRunArguments': '',
+              'MPIRunWorkingDirectory': '',
+              'ApplicationCommand': '',
+              'ApplicationArguments': '',
+              'ShimCommand': '',
+              'MPIAcceptMode': '',
+              'MPIAcceptFilter': ''
+             }]
+
+    # Find the config, and add it if it doesn't exist.
+    if config_name not in self.configurations:
+      self.AddConfig(config_name)
+
+    # Add the DebugSettings onto the appropriate config.
+    self.configurations[config_name].append(n_cmd)
+
+  def WriteIfChanged(self):
+    """Writes the user file."""
+    configs = ['Configurations']
+    for config, spec in sorted(self.configurations.iteritems()):
+      configs.append(spec)
+
+    content = ['VisualStudioUserFile',
+               {'Version': self.version.ProjectVersion(),
+                'Name': self.name
+               },
+               configs]
+    easy_xml.WriteXmlIfChanged(content, self.user_file_path,
+                               encoding="Windows-1252")
diff --git a/webWidgetTCT_device/tools/gyp/pylib/gyp/MSVSUtil.py b/webWidgetTCT_device/tools/gyp/pylib/gyp/MSVSUtil.py
new file mode 100755 (executable)
index 0000000..62e8d26
--- /dev/null
@@ -0,0 +1,267 @@
+# Copyright (c) 2013 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Utility functions shared amongst the Windows generators."""
+
+import copy
+import os
+
+
+_TARGET_TYPE_EXT = {
+  'executable': '.exe',
+  'loadable_module': '.dll',
+  'shared_library': '.dll',
+}
+
+
+def _GetLargePdbShimCcPath():
+  """Returns the path of the large_pdb_shim.cc file."""
+  this_dir = os.path.abspath(os.path.dirname(__file__))
+  src_dir = os.path.abspath(os.path.join(this_dir, '..', '..'))
+  win_data_dir = os.path.join(src_dir, 'data', 'win')
+  large_pdb_shim_cc = os.path.join(win_data_dir, 'large-pdb-shim.cc')
+  return large_pdb_shim_cc
+
+
+def _DeepCopySomeKeys(in_dict, keys):
+  """Performs a partial deep-copy on |in_dict|, only copying the keys in |keys|.
+
+  Arguments:
+    in_dict: The dictionary to copy.
+    keys: The keys to be copied. If a key is in this list and doesn't exist in
+        |in_dict| this is not an error.
+  Returns:
+    The partially deep-copied dictionary.
+  """
+  d = {}
+  for key in keys:
+    if key not in in_dict:
+      continue
+    d[key] = copy.deepcopy(in_dict[key])
+  return d
+
+
+def _SuffixName(name, suffix):
+  """Add a suffix to the end of a target.
+
+  Arguments:
+    name: name of the target (foo#target)
+    suffix: the suffix to be added
+  Returns:
+    Target name with suffix added (foo_suffix#target)
+  """
+  parts = name.rsplit('#', 1)
+  parts[0] = '%s_%s' % (parts[0], suffix)
+  return '#'.join(parts)
+
+
+def _ShardName(name, number):
+  """Add a shard number to the end of a target.
+
+  Arguments:
+    name: name of the target (foo#target)
+    number: shard number
+  Returns:
+    Target name with shard added (foo_1#target)
+  """
+  return _SuffixName(name, str(number))
+
+
+def ShardTargets(target_list, target_dicts):
+  """Shard some targets apart to work around the linkers limits.
+
+  Arguments:
+    target_list: List of target pairs: 'base/base.gyp:base'.
+    target_dicts: Dict of target properties keyed on target pair.
+  Returns:
+    Tuple of the new sharded versions of the inputs.
+  """
+  # Gather the targets to shard, and how many pieces.
+  targets_to_shard = {}
+  for t in target_dicts:
+    shards = int(target_dicts[t].get('msvs_shard', 0))
+    if shards:
+      targets_to_shard[t] = shards
+  # Shard target_list.
+  new_target_list = []
+  for t in target_list:
+    if t in targets_to_shard:
+      for i in range(targets_to_shard[t]):
+        new_target_list.append(_ShardName(t, i))
+    else:
+      new_target_list.append(t)
+  # Shard target_dict.
+  new_target_dicts = {}
+  for t in target_dicts:
+    if t in targets_to_shard:
+      for i in range(targets_to_shard[t]):
+        name = _ShardName(t, i)
+        new_target_dicts[name] = copy.copy(target_dicts[t])
+        new_target_dicts[name]['target_name'] = _ShardName(
+             new_target_dicts[name]['target_name'], i)
+        sources = new_target_dicts[name].get('sources', [])
+        new_sources = []
+        for pos in range(i, len(sources), targets_to_shard[t]):
+          new_sources.append(sources[pos])
+        new_target_dicts[name]['sources'] = new_sources
+    else:
+      new_target_dicts[t] = target_dicts[t]
+  # Shard dependencies.
+  for t in new_target_dicts:
+    dependencies = copy.copy(new_target_dicts[t].get('dependencies', []))
+    new_dependencies = []
+    for d in dependencies:
+      if d in targets_to_shard:
+        for i in range(targets_to_shard[d]):
+          new_dependencies.append(_ShardName(d, i))
+      else:
+        new_dependencies.append(d)
+    new_target_dicts[t]['dependencies'] = new_dependencies
+
+  return (new_target_list, new_target_dicts)
+
+
+def _GetPdbPath(target_dict, config_name, vars):
+  """Returns the path to the PDB file that will be generated by a given
+  configuration.
+
+  The lookup proceeds as follows:
+    - Look for an explicit path in the VCLinkerTool configuration block.
+    - Look for an 'msvs_large_pdb_path' variable.
+    - Use '<(PRODUCT_DIR)/<(product_name).(exe|dll).pdb' if 'product_name' is
+      specified.
+    - Use '<(PRODUCT_DIR)/<(target_name).(exe|dll).pdb'.
+
+  Arguments:
+    target_dict: The target dictionary to be searched.
+    config_name: The name of the configuration of interest.
+    vars: A dictionary of common GYP variables with generator-specific values.
+  Returns:
+    The path of the corresponding PDB file.
+  """
+  config = target_dict['configurations'][config_name]
+  msvs = config.setdefault('msvs_settings', {})
+
+  linker = msvs.get('VCLinkerTool', {})
+
+  pdb_path = linker.get('ProgramDatabaseFile')
+  if pdb_path:
+    return pdb_path
+
+  variables = target_dict.get('variables', {})
+  pdb_path = variables.get('msvs_large_pdb_path', None)
+  if pdb_path:
+    return pdb_path
+
+
+  pdb_base = target_dict.get('product_name', target_dict['target_name'])
+  pdb_base = '%s%s.pdb' % (pdb_base, _TARGET_TYPE_EXT[target_dict['type']])
+  pdb_path = vars['PRODUCT_DIR'] + '/' + pdb_base
+
+  return pdb_path
+
+
+def InsertLargePdbShims(target_list, target_dicts, vars):
+  """Insert a shim target that forces the linker to use 4KB pagesize PDBs.
+
+  This is a workaround for targets with PDBs greater than 1GB in size, the
+  limit for the 1KB pagesize PDBs created by the linker by default.
+
+  Arguments:
+    target_list: List of target pairs: 'base/base.gyp:base'.
+    target_dicts: Dict of target properties keyed on target pair.
+    vars: A dictionary of common GYP variables with generator-specific values.
+  Returns:
+    Tuple of the shimmed version of the inputs.
+  """
+  # Determine which targets need shimming.
+  targets_to_shim = []
+  for t in target_dicts:
+    target_dict = target_dicts[t]
+
+    # We only want to shim targets that have msvs_large_pdb enabled.
+    if not int(target_dict.get('msvs_large_pdb', 0)):
+      continue
+    # This is intended for executable, shared_library and loadable_module
+    # targets where every configuration is set up to produce a PDB output.
+    # If any of these conditions is not true then the shim logic will fail
+    # below.
+    targets_to_shim.append(t)
+
+  large_pdb_shim_cc = _GetLargePdbShimCcPath()
+
+  for t in targets_to_shim:
+    target_dict = target_dicts[t]
+    target_name = target_dict.get('target_name')
+
+    base_dict = _DeepCopySomeKeys(target_dict,
+          ['configurations', 'default_configuration', 'toolset'])
+
+    # This is the dict for copying the source file (part of the GYP tree)
+    # to the intermediate directory of the project. This is necessary because
+    # we can't always build a relative path to the shim source file (on Windows
+    # GYP and the project may be on different drives), and Ninja hates absolute
+    # paths (it ends up generating the .obj and .obj.d alongside the source
+    # file, polluting GYPs tree).
+    copy_suffix = 'large_pdb_copy'
+    copy_target_name = target_name + '_' + copy_suffix
+    full_copy_target_name = _SuffixName(t, copy_suffix)
+    shim_cc_basename = os.path.basename(large_pdb_shim_cc)
+    shim_cc_dir = vars['SHARED_INTERMEDIATE_DIR'] + '/' + copy_target_name
+    shim_cc_path = shim_cc_dir + '/' + shim_cc_basename
+    copy_dict = copy.deepcopy(base_dict)
+    copy_dict['target_name'] = copy_target_name
+    copy_dict['type'] = 'none'
+    copy_dict['sources'] = [ large_pdb_shim_cc ]
+    copy_dict['copies'] = [{
+      'destination': shim_cc_dir,
+      'files': [ large_pdb_shim_cc ]
+    }]
+
+    # This is the dict for the PDB generating shim target. It depends on the
+    # copy target.
+    shim_suffix = 'large_pdb_shim'
+    shim_target_name = target_name + '_' + shim_suffix
+    full_shim_target_name = _SuffixName(t, shim_suffix)
+    shim_dict = copy.deepcopy(base_dict)
+    shim_dict['target_name'] = shim_target_name
+    shim_dict['type'] = 'static_library'
+    shim_dict['sources'] = [ shim_cc_path ]
+    shim_dict['dependencies'] = [ full_copy_target_name ]
+
+    # Set up the shim to output its PDB to the same location as the final linker
+    # target.
+    for config_name, config in shim_dict.get('configurations').iteritems():
+      pdb_path = _GetPdbPath(target_dict, config_name, vars)
+
+      # A few keys that we don't want to propagate.
+      for key in ['msvs_precompiled_header', 'msvs_precompiled_source', 'test']:
+        config.pop(key, None)
+
+      msvs = config.setdefault('msvs_settings', {})
+
+      # Update the compiler directives in the shim target.
+      compiler = msvs.setdefault('VCCLCompilerTool', {})
+      compiler['DebugInformationFormat'] = '3'
+      compiler['ProgramDataBaseFileName'] = pdb_path
+
+      # Set the explicit PDB path in the appropriate configuration of the
+      # original target.
+      config = target_dict['configurations'][config_name]
+      msvs = config.setdefault('msvs_settings', {})
+      linker = msvs.setdefault('VCLinkerTool', {})
+      linker['GenerateDebugInformation'] = 'true'
+      linker['ProgramDatabaseFile'] = pdb_path
+
+    # Add the new targets. They must go to the beginning of the list so that
+    # the dependency generation works as expected in ninja.
+    target_list.insert(0, full_copy_target_name)
+    target_list.insert(0, full_shim_target_name)
+    target_dicts[full_copy_target_name] = copy_dict
+    target_dicts[full_shim_target_name] = shim_dict
+
+    # Update the original target to depend on the shim target.
+    target_dict.setdefault('dependencies', []).append(full_shim_target_name)
+
+  return (target_list, target_dicts)
\ No newline at end of file
diff --git a/webWidgetTCT_device/tools/gyp/pylib/gyp/MSVSVersion.py b/webWidgetTCT_device/tools/gyp/pylib/gyp/MSVSVersion.py
new file mode 100755 (executable)
index 0000000..2d95cd0
--- /dev/null
@@ -0,0 +1,373 @@
+# Copyright (c) 2013 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Handle version information related to Visual Stuio."""
+
+import errno
+import os
+import re
+import subprocess
+import sys
+import gyp
+
+
+class VisualStudioVersion(object):
+  """Information regarding a version of Visual Studio."""
+
+  def __init__(self, short_name, description,
+               solution_version, project_version, flat_sln, uses_vcxproj,
+               path, sdk_based, default_toolset=None):
+    self.short_name = short_name
+    self.description = description
+    self.solution_version = solution_version
+    self.project_version = project_version
+    self.flat_sln = flat_sln
+    self.uses_vcxproj = uses_vcxproj
+    self.path = path
+    self.sdk_based = sdk_based
+    self.default_toolset = default_toolset
+
+  def ShortName(self):
+    return self.short_name
+
+  def Description(self):
+    """Get the full description of the version."""
+    return self.description
+
+  def SolutionVersion(self):
+    """Get the version number of the sln files."""
+    return self.solution_version
+
+  def ProjectVersion(self):
+    """Get the version number of the vcproj or vcxproj files."""
+    return self.project_version
+
+  def FlatSolution(self):
+    return self.flat_sln
+
+  def UsesVcxproj(self):
+    """Returns true if this version uses a vcxproj file."""
+    return self.uses_vcxproj
+
+  def ProjectExtension(self):
+    """Returns the file extension for the project."""
+    return self.uses_vcxproj and '.vcxproj' or '.vcproj'
+
+  def Path(self):
+    """Returns the path to Visual Studio installation."""
+    return self.path
+
+  def ToolPath(self, tool):
+    """Returns the path to a given compiler tool. """
+    return os.path.normpath(os.path.join(self.path, "VC/bin", tool))
+
+  def DefaultToolset(self):
+    """Returns the msbuild toolset version that will be used in the absence
+    of a user override."""
+    return self.default_toolset
+
+  def SetupScript(self, target_arch):
+    """Returns a command (with arguments) to be used to set up the
+    environment."""
+    # Check if we are running in the SDK command line environment and use
+    # the setup script from the SDK if so. |target_arch| should be either
+    # 'x86' or 'x64'.
+    assert target_arch in ('x86', 'x64')
+    sdk_dir = os.environ.get('WindowsSDKDir')
+    if self.sdk_based and sdk_dir:
+      return [os.path.normpath(os.path.join(sdk_dir, 'Bin/SetEnv.Cmd')),
+              '/' + target_arch]
+    else:
+      # We don't use VC/vcvarsall.bat for x86 because vcvarsall calls
+      # vcvars32, which it can only find if VS??COMNTOOLS is set, which it
+      # isn't always.
+      if target_arch == 'x86':
+        return [os.path.normpath(
+          os.path.join(self.path, 'Common7/Tools/vsvars32.bat'))]
+      else:
+        assert target_arch == 'x64'
+        arg = 'x86_amd64'
+        if (os.environ.get('PROCESSOR_ARCHITECTURE') == 'AMD64' or
+            os.environ.get('PROCESSOR_ARCHITEW6432') == 'AMD64'):
+          # Use the 64-on-64 compiler if we can.
+          arg = 'amd64'
+        return [os.path.normpath(
+            os.path.join(self.path, 'VC/vcvarsall.bat')), arg]
+
+
+def _RegistryQueryBase(sysdir, key, value):
+  """Use reg.exe to read a particular key.
+
+  While ideally we might use the win32 module, we would like gyp to be
+  python neutral, so for instance cygwin python lacks this module.
+
+  Arguments:
+    sysdir: The system subdirectory to attempt to launch reg.exe from.
+    key: The registry key to read from.
+    value: The particular value to read.
+  Return:
+    stdout from reg.exe, or None for failure.
+  """
+  # Skip if not on Windows or Python Win32 setup issue
+  if sys.platform not in ('win32', 'cygwin'):
+    return None
+  # Setup params to pass to and attempt to launch reg.exe
+  cmd = [os.path.join(os.environ.get('WINDIR', ''), sysdir, 'reg.exe'),
+         'query', key]
+  if value:
+    cmd.extend(['/v', value])
+  p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+  # Obtain the stdout from reg.exe, reading to the end so p.returncode is valid
+  # Note that the error text may be in [1] in some cases
+  text = p.communicate()[0]
+  # Check return code from reg.exe; officially 0==success and 1==error
+  if p.returncode:
+    return None
+  return text
+
+
+def _RegistryQuery(key, value=None):
+  """Use reg.exe to read a particular key through _RegistryQueryBase.
+
+  First tries to launch from %WinDir%\Sysnative to avoid WoW64 redirection. If
+  that fails, it falls back to System32.  Sysnative is available on Vista and
+  up and available on Windows Server 2003 and XP through KB patch 942589. Note
+  that Sysnative will always fail if using 64-bit python due to it being a
+  virtual directory and System32 will work correctly in the first place.
+
+  KB 942589 - http://support.microsoft.com/kb/942589/en-us.
+
+  Arguments:
+    key: The registry key.
+    value: The particular registry value to read (optional).
+  Return:
+    stdout from reg.exe, or None for failure.
+  """
+  text = None
+  try:
+    text = _RegistryQueryBase('Sysnative', key, value)
+  except OSError, e:
+    if e.errno == errno.ENOENT:
+      text = _RegistryQueryBase('System32', key, value)
+    else:
+      raise
+  return text
+
+
+def _RegistryGetValue(key, value):
+  """Use reg.exe to obtain the value of a registry key.
+
+  Args:
+    key: The registry key.
+    value: The particular registry value to read.
+  Return:
+    contents of the registry key's value, or None on failure.
+  """
+  text = _RegistryQuery(key, value)
+  if not text:
+    return None
+  # Extract value.
+  match = re.search(r'REG_\w+\s+([^\r]+)\r\n', text)
+  if not match:
+    return None
+  return match.group(1)
+
+
+def _RegistryKeyExists(key):
+  """Use reg.exe to see if a key exists.
+
+  Args:
+    key: The registry key to check.
+  Return:
+    True if the key exists
+  """
+  if not _RegistryQuery(key):
+    return False
+  return True
+
+
+def _CreateVersion(name, path, sdk_based=False):
+  """Sets up MSVS project generation.
+
+  Setup is based off the GYP_MSVS_VERSION environment variable or whatever is
+  autodetected if GYP_MSVS_VERSION is not explicitly specified. If a version is
+  passed in that doesn't match a value in versions python will throw a error.
+  """
+  if path:
+    path = os.path.normpath(path)
+  versions = {
+      '2012': VisualStudioVersion('2012',
+                                  'Visual Studio 2012',
+                                  solution_version='12.00',
+                                  project_version='4.0',
+                                  flat_sln=False,
+                                  uses_vcxproj=True,
+                                  path=path,
+                                  sdk_based=sdk_based,
+                                  default_toolset='v110'),
+      '2012e': VisualStudioVersion('2012e',
+                                   'Visual Studio 2012',
+                                   solution_version='12.00',
+                                   project_version='4.0',
+                                   flat_sln=True,
+                                   uses_vcxproj=True,
+                                   path=path,
+                                   sdk_based=sdk_based,
+                                   default_toolset='v110'),
+      '2010': VisualStudioVersion('2010',
+                                  'Visual Studio 2010',
+                                  solution_version='11.00',
+                                  project_version='4.0',
+                                  flat_sln=False,
+                                  uses_vcxproj=True,
+                                  path=path,
+                                  sdk_based=sdk_based),
+      '2010e': VisualStudioVersion('2010e',
+                                   'Visual Studio 2010',
+                                   solution_version='11.00',
+                                   project_version='4.0',
+                                   flat_sln=True,
+                                   uses_vcxproj=True,
+                                   path=path,
+                                   sdk_based=sdk_based),
+      '2008': VisualStudioVersion('2008',
+                                  'Visual Studio 2008',
+                                  solution_version='10.00',
+                                  project_version='9.00',
+                                  flat_sln=False,
+                                  uses_vcxproj=False,
+                                  path=path,
+                                  sdk_based=sdk_based),
+      '2008e': VisualStudioVersion('2008e',
+                                   'Visual Studio 2008',
+                                   solution_version='10.00',
+                                   project_version='9.00',
+                                   flat_sln=True,
+                                   uses_vcxproj=False,
+                                   path=path,
+                                   sdk_based=sdk_based),
+      '2005': VisualStudioVersion('2005',
+                                  'Visual Studio 2005',
+                                  solution_version='9.00',
+                                  project_version='8.00',
+                                  flat_sln=False,
+                                  uses_vcxproj=False,
+                                  path=path,
+                                  sdk_based=sdk_based),
+      '2005e': VisualStudioVersion('2005e',
+                                   'Visual Studio 2005',
+                                   solution_version='9.00',
+                                   project_version='8.00',
+                                   flat_sln=True,
+                                   uses_vcxproj=False,
+                                   path=path,
+                                   sdk_based=sdk_based),
+  }
+  return versions[str(name)]
+
+
+def _ConvertToCygpath(path):
+  """Convert to cygwin path if we are using cygwin."""
+  if sys.platform == 'cygwin':
+    p = subprocess.Popen(['cygpath', path], stdout=subprocess.PIPE)
+    path = p.communicate()[0].strip()
+  return path
+
+
+def _DetectVisualStudioVersions(versions_to_check, force_express):
+  """Collect the list of installed visual studio versions.
+
+  Returns:
+    A list of visual studio versions installed in descending order of
+    usage preference.
+    Base this on the registry and a quick check if devenv.exe exists.
+    Only versions 8-10 are considered.
+    Possibilities are:
+      2005(e) - Visual Studio 2005 (8)
+      2008(e) - Visual Studio 2008 (9)
+      2010(e) - Visual Studio 2010 (10)
+      2012(e) - Visual Studio 2012 (11)
+    Where (e) is e for express editions of MSVS and blank otherwise.
+  """
+  version_to_year = {
+      '8.0': '2005', '9.0': '2008', '10.0': '2010', '11.0': '2012'}
+  versions = []
+  for version in versions_to_check:
+    # Old method of searching for which VS version is installed
+    # We don't use the 2010-encouraged-way because we also want to get the
+    # path to the binaries, which it doesn't offer.
+    keys = [r'HKLM\Software\Microsoft\VisualStudio\%s' % version,
+            r'HKLM\Software\Wow6432Node\Microsoft\VisualStudio\%s' % version,
+            r'HKLM\Software\Microsoft\VCExpress\%s' % version,
+            r'HKLM\Software\Wow6432Node\Microsoft\VCExpress\%s' % version]
+    for index in range(len(keys)):
+      path = _RegistryGetValue(keys[index], 'InstallDir')
+      if not path:
+        continue
+      path = _ConvertToCygpath(path)
+      # Check for full.
+      full_path = os.path.join(path, 'devenv.exe')
+      express_path = os.path.join(path, 'vcexpress.exe')
+      if not force_express and os.path.exists(full_path):
+        # Add this one.
+        versions.append(_CreateVersion(version_to_year[version],
+            os.path.join(path, '..', '..')))
+      # Check for express.
+      elif os.path.exists(express_path):
+        # Add this one.
+        versions.append(_CreateVersion(version_to_year[version] + 'e',
+            os.path.join(path, '..', '..')))
+
+    # The old method above does not work when only SDK is installed.
+    keys = [r'HKLM\Software\Microsoft\VisualStudio\SxS\VC7',
+            r'HKLM\Software\Wow6432Node\Microsoft\VisualStudio\SxS\VC7']
+    for index in range(len(keys)):
+      path = _RegistryGetValue(keys[index], version)
+      if not path:
+        continue
+      path = _ConvertToCygpath(path)
+      versions.append(_CreateVersion(version_to_year[version] + 'e',
+          os.path.join(path, '..'), sdk_based=True))
+
+  return versions
+
+
+def SelectVisualStudioVersion(version='auto'):
+  """Select which version of Visual Studio projects to generate.
+
+  Arguments:
+    version: Hook to allow caller to force a particular version (vs auto).
+  Returns:
+    An object representing a visual studio project format version.
+  """
+  # In auto mode, check environment variable for override.
+  if version == 'auto':
+    version = os.environ.get('GYP_MSVS_VERSION', 'auto')
+  version_map = {
+    'auto': ('10.0', '9.0', '8.0', '11.0'),
+    '2005': ('8.0',),
+    '2005e': ('8.0',),
+    '2008': ('9.0',),
+    '2008e': ('9.0',),
+    '2010': ('10.0',),
+    '2010e': ('10.0',),
+    '2012': ('11.0',),
+    '2012e': ('11.0',),
+  }
+  override_path = os.environ.get('GYP_MSVS_OVERRIDE_PATH')
+  if override_path:
+    msvs_version = os.environ.get('GYP_MSVS_VERSION')
+    if not msvs_version or 'e' not in msvs_version:
+      raise ValueError('GYP_MSVS_OVERRIDE_PATH requires GYP_MSVS_VERSION to be '
+                       'set to an "e" version (e.g. 2010e)')
+    return _CreateVersion(msvs_version, override_path, sdk_based=True)
+  version = str(version)
+  versions = _DetectVisualStudioVersions(version_map[version], 'e' in version)
+  if not versions:
+    if version == 'auto':
+      # Default to 2005 if we couldn't find anything
+      return _CreateVersion('2005', None)
+    else:
+      return _CreateVersion(version, None)
+  return versions[0]
diff --git a/webWidgetTCT_device/tools/gyp/pylib/gyp/SCons.py b/webWidgetTCT_device/tools/gyp/pylib/gyp/SCons.py
new file mode 100755 (executable)
index 0000000..42d845e
--- /dev/null
@@ -0,0 +1,199 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""
+SCons generator.
+
+This contains class definitions and supporting functions for generating
+pieces of SCons files for the different types of GYP targets.
+"""
+
+import os
+
+
+def WriteList(fp, list, prefix='',
+                        separator=',\n    ',
+                        preamble=None,
+                        postamble=None):
+  fp.write(preamble or '')
+  fp.write((separator or ' ').join([prefix + l for l in list]))
+  fp.write(postamble or '')
+
+
+class TargetBase(object):
+  """
+  Base class for a SCons representation of a GYP target.
+  """
+  is_ignored = False
+  target_prefix = ''
+  target_suffix = ''
+  def __init__(self, spec):
+    self.spec = spec
+  def full_product_name(self):
+    """
+    Returns the full name of the product being built:
+
+      * Uses 'product_name' if it's set, else prefix + 'target_name'.
+      * Prepends 'product_dir' if set.
+      * Appends SCons suffix variables for the target type (or
+        product_extension).
+    """
+    suffix = self.target_suffix
+    product_extension = self.spec.get('product_extension')
+    if product_extension:
+      suffix = '.' + product_extension
+    prefix = self.spec.get('product_prefix', self.target_prefix)
+    name = self.spec['target_name']
+    name = prefix + self.spec.get('product_name', name) + suffix
+    product_dir = self.spec.get('product_dir')
+    if product_dir:
+      name = os.path.join(product_dir, name)
+    else:
+      name = os.path.join(self.out_dir, name)
+    return name
+
+  def write_input_files(self, fp):
+    """
+    Writes the definition of the input files (sources).
+    """
+    sources = self.spec.get('sources')
+    if not sources:
+      fp.write('\ninput_files = []\n')
+      return
+    preamble = '\ninput_files = [\n    '
+    postamble = ',\n]\n'
+    WriteList(fp, map(repr, sources), preamble=preamble, postamble=postamble)
+
+  def builder_call(self):
+    """
+    Returns the actual SCons builder call to build this target.
+    """
+    name = self.full_product_name()
+    return 'env.%s(env.File(%r), input_files)' % (self.builder_name, name)
+  def write_target(self, fp, src_dir='', pre=''):
+    """
+    Writes the lines necessary to build this target.
+    """
+    fp.write('\n' + pre)
+    fp.write('_outputs = %s\n' % self.builder_call())
+    fp.write('target_files.extend(_outputs)\n')
+
+
+class NoneTarget(TargetBase):
+  """
+  A GYP target type of 'none', implicitly or explicitly.
+  """
+  def write_target(self, fp, src_dir='', pre=''):
+    fp.write('\ntarget_files.extend(input_files)\n')
+
+
+class SettingsTarget(TargetBase):
+  """
+  A GYP target type of 'settings'.
+  """
+  is_ignored = True
+
+
+compilable_sources_template = """
+_result = []
+for infile in input_files:
+  if env.compilable(infile):
+    if (type(infile) == type('')
+        and (infile.startswith(%(src_dir)r)
+             or not os.path.isabs(env.subst(infile)))):
+      # Force files below the build directory by replacing all '..'
+      # elements in the path with '__':
+      base, ext = os.path.splitext(os.path.normpath(infile))
+      base = [d == '..' and '__' or d for d in base.split('/')]
+      base = os.path.join(*base)
+      object = '${OBJ_DIR}/${COMPONENT_NAME}/${TARGET_NAME}/' + base
+      if not infile.startswith(%(src_dir)r):
+        infile = %(src_dir)r + infile
+      infile = env.%(name)s(object, infile)[0]
+    else:
+      infile = env.%(name)s(infile)[0]
+  _result.append(infile)
+input_files = _result
+"""
+
+class CompilableSourcesTargetBase(TargetBase):
+  """
+  An abstract base class for targets that compile their source files.
+
+  We explicitly transform compilable files into object files,
+  even though SCons could infer that for us, because we want
+  to control where the object file ends up.  (The implicit rules
+  in SCons always put the object file next to the source file.)
+  """
+  intermediate_builder_name = None
+  def write_target(self, fp, src_dir='', pre=''):
+    if self.intermediate_builder_name is None:
+      raise NotImplementedError
+    if src_dir and not src_dir.endswith('/'):
+      src_dir += '/'
+    variables = {
+        'src_dir': src_dir,
+        'name': self.intermediate_builder_name,
+    }
+    fp.write(compilable_sources_template % variables)
+    super(CompilableSourcesTargetBase, self).write_target(fp)
+
+
+class ProgramTarget(CompilableSourcesTargetBase):
+  """
+  A GYP target type of 'executable'.
+  """
+  builder_name = 'GypProgram'
+  intermediate_builder_name = 'StaticObject'
+  target_prefix = '${PROGPREFIX}'
+  target_suffix = '${PROGSUFFIX}'
+  out_dir = '${TOP_BUILDDIR}'
+
+
+class StaticLibraryTarget(CompilableSourcesTargetBase):
+  """
+  A GYP target type of 'static_library'.
+  """
+  builder_name = 'GypStaticLibrary'
+  intermediate_builder_name = 'StaticObject'
+  target_prefix = '${LIBPREFIX}'
+  target_suffix = '${LIBSUFFIX}'
+  out_dir = '${LIB_DIR}'
+
+
+class SharedLibraryTarget(CompilableSourcesTargetBase):
+  """
+  A GYP target type of 'shared_library'.
+  """
+  builder_name = 'GypSharedLibrary'
+  intermediate_builder_name = 'SharedObject'
+  target_prefix = '${SHLIBPREFIX}'
+  target_suffix = '${SHLIBSUFFIX}'
+  out_dir = '${LIB_DIR}'
+
+
+class LoadableModuleTarget(CompilableSourcesTargetBase):
+  """
+  A GYP target type of 'loadable_module'.
+  """
+  builder_name = 'GypLoadableModule'
+  intermediate_builder_name = 'SharedObject'
+  target_prefix = '${SHLIBPREFIX}'
+  target_suffix = '${SHLIBSUFFIX}'
+  out_dir = '${TOP_BUILDDIR}'
+
+
+TargetMap = {
+  None : NoneTarget,
+  'none' : NoneTarget,
+  'settings' : SettingsTarget,
+  'executable' : ProgramTarget,
+  'static_library' : StaticLibraryTarget,
+  'shared_library' : SharedLibraryTarget,
+  'loadable_module' : LoadableModuleTarget,
+}
+
+
+def Target(spec):
+  return TargetMap[spec.get('type')](spec)
diff --git a/webWidgetTCT_device/tools/gyp/pylib/gyp/__init__.py b/webWidgetTCT_device/tools/gyp/pylib/gyp/__init__.py
new file mode 100755 (executable)
index 0000000..3769c52
--- /dev/null
@@ -0,0 +1,532 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import copy
+import gyp.input
+import optparse
+import os.path
+import re
+import shlex
+import sys
+import traceback
+from gyp.common import GypError
+
+# Default debug modes for GYP
+debug = {}
+
+# List of "official" debug modes, but you can use anything you like.
+DEBUG_GENERAL = 'general'
+DEBUG_VARIABLES = 'variables'
+DEBUG_INCLUDES = 'includes'
+
+
+def DebugOutput(mode, message, *args):
+  if 'all' in gyp.debug or mode in gyp.debug:
+    ctx = ('unknown', 0, 'unknown')
+    try:
+      f = traceback.extract_stack(limit=2)
+      if f:
+        ctx = f[0][:3]
+    except:
+      pass
+    if args:
+      message %= args
+    print '%s:%s:%d:%s %s' % (mode.upper(), os.path.basename(ctx[0]),
+                              ctx[1], ctx[2], message)
+
+def FindBuildFiles():
+  extension = '.gyp'
+  files = os.listdir(os.getcwd())
+  build_files = []
+  for file in files:
+    if file.endswith(extension):
+      build_files.append(file)
+  return build_files
+
+
+def Load(build_files, format, default_variables={},
+         includes=[], depth='.', params=None, check=False,
+         circular_check=True):
+  """
+  Loads one or more specified build files.
+  default_variables and includes will be copied before use.
+  Returns the generator for the specified format and the
+  data returned by loading the specified build files.
+  """
+  if params is None:
+    params = {}
+
+  flavor = None
+  if '-' in format:
+    format, params['flavor'] = format.split('-', 1)
+
+  default_variables = copy.copy(default_variables)
+
+  # Default variables provided by this program and its modules should be
+  # named WITH_CAPITAL_LETTERS to provide a distinct "best practice" namespace,
+  # avoiding collisions with user and automatic variables.
+  default_variables['GENERATOR'] = format
+
+  # Format can be a custom python file, or by default the name of a module
+  # within gyp.generator.
+  if format.endswith('.py'):
+    generator_name = os.path.splitext(format)[0]
+    path, generator_name = os.path.split(generator_name)
+
+    # Make sure the path to the custom generator is in sys.path
+    # Don't worry about removing it once we are done.  Keeping the path
+    # to each generator that is used in sys.path is likely harmless and
+    # arguably a good idea.
+    path = os.path.abspath(path)
+    if path not in sys.path:
+      sys.path.insert(0, path)
+  else:
+    generator_name = 'gyp.generator.' + format
+
+  # These parameters are passed in order (as opposed to by key)
+  # because ActivePython cannot handle key parameters to __import__.
+  generator = __import__(generator_name, globals(), locals(), generator_name)
+  for (key, val) in generator.generator_default_variables.items():
+    default_variables.setdefault(key, val)
+
+  # Give the generator the opportunity to set additional variables based on
+  # the params it will receive in the output phase.
+  if getattr(generator, 'CalculateVariables', None):
+    generator.CalculateVariables(default_variables, params)
+
+  # Give the generator the opportunity to set generator_input_info based on
+  # the params it will receive in the output phase.
+  if getattr(generator, 'CalculateGeneratorInputInfo', None):
+    generator.CalculateGeneratorInputInfo(params)
+
+  # Fetch the generator specific info that gets fed to input, we use getattr
+  # so we can default things and the generators only have to provide what
+  # they need.
+  generator_input_info = {
+    'generator_wants_absolute_build_file_paths':
+        getattr(generator, 'generator_wants_absolute_build_file_paths', False),
+    'generator_handles_variants':
+        getattr(generator, 'generator_handles_variants', False),
+    'non_configuration_keys':
+        getattr(generator, 'generator_additional_non_configuration_keys', []),
+    'path_sections':
+        getattr(generator, 'generator_additional_path_sections', []),
+    'extra_sources_for_rules':
+        getattr(generator, 'generator_extra_sources_for_rules', []),
+    'generator_supports_multiple_toolsets':
+        getattr(generator, 'generator_supports_multiple_toolsets', False),
+    'generator_wants_static_library_dependencies_adjusted':
+        getattr(generator,
+                'generator_wants_static_library_dependencies_adjusted', True),
+    'generator_wants_sorted_dependencies':
+        getattr(generator, 'generator_wants_sorted_dependencies', False),
+  }
+
+  # Process the input specific to this generator.
+  result = gyp.input.Load(build_files, default_variables, includes[:],
+                          depth, generator_input_info, check, circular_check,
+                          params['parallel'])
+  return [generator] + result
+
+def NameValueListToDict(name_value_list):
+  """
+  Takes an array of strings of the form 'NAME=VALUE' and creates a dictionary
+  of the pairs.  If a string is simply NAME, then the value in the dictionary
+  is set to True.  If VALUE can be converted to an integer, it is.
+  """
+  result = { }
+  for item in name_value_list:
+    tokens = item.split('=', 1)
+    if len(tokens) == 2:
+      # If we can make it an int, use that, otherwise, use the string.
+      try:
+        token_value = int(tokens[1])
+      except ValueError:
+        token_value = tokens[1]
+      # Set the variable to the supplied value.
+      result[tokens[0]] = token_value
+    else:
+      # No value supplied, treat it as a boolean and set it.
+      result[tokens[0]] = True
+  return result
+
+def ShlexEnv(env_name):
+  flags = os.environ.get(env_name, [])
+  if flags:
+    flags = shlex.split(flags)
+  return flags
+
+def FormatOpt(opt, value):
+  if opt.startswith('--'):
+    return '%s=%s' % (opt, value)
+  return opt + value
+
+def RegenerateAppendFlag(flag, values, predicate, env_name, options):
+  """Regenerate a list of command line flags, for an option of action='append'.
+
+  The |env_name|, if given, is checked in the environment and used to generate
+  an initial list of options, then the options that were specified on the
+  command line (given in |values|) are appended.  This matches the handling of
+  environment variables and command line flags where command line flags override
+  the environment, while not requiring the environment to be set when the flags
+  are used again.
+  """
+  flags = []
+  if options.use_environment and env_name:
+    for flag_value in ShlexEnv(env_name):
+      value = FormatOpt(flag, predicate(flag_value))
+      if value in flags:
+        flags.remove(value)
+      flags.append(value)
+  if values:
+    for flag_value in values:
+      flags.append(FormatOpt(flag, predicate(flag_value)))
+  return flags
+
+def RegenerateFlags(options):
+  """Given a parsed options object, and taking the environment variables into
+  account, returns a list of flags that should regenerate an equivalent options
+  object (even in the absence of the environment variables.)
+
+  Any path options will be normalized relative to depth.
+
+  The format flag is not included, as it is assumed the calling generator will
+  set that as appropriate.
+  """
+  def FixPath(path):
+    path = gyp.common.FixIfRelativePath(path, options.depth)
+    if not path:
+      return os.path.curdir
+    return path
+
+  def Noop(value):
+    return value
+
+  # We always want to ignore the environment when regenerating, to avoid
+  # duplicate or changed flags in the environment at the time of regeneration.
+  flags = ['--ignore-environment']
+  for name, metadata in options._regeneration_metadata.iteritems():
+    opt = metadata['opt']
+    value = getattr(options, name)
+    value_predicate = metadata['type'] == 'path' and FixPath or Noop
+    action = metadata['action']
+    env_name = metadata['env_name']
+    if action == 'append':
+      flags.extend(RegenerateAppendFlag(opt, value, value_predicate,
+                                        env_name, options))
+    elif action in ('store', None):  # None is a synonym for 'store'.
+      if value:
+        flags.append(FormatOpt(opt, value_predicate(value)))
+      elif options.use_environment and env_name and os.environ.get(env_name):
+        flags.append(FormatOpt(opt, value_predicate(os.environ.get(env_name))))
+    elif action in ('store_true', 'store_false'):
+      if ((action == 'store_true' and value) or
+          (action == 'store_false' and not value)):
+        flags.append(opt)
+      elif options.use_environment and env_name:
+        print >>sys.stderr, ('Warning: environment regeneration unimplemented '
+                             'for %s flag %r env_name %r' % (action, opt,
+                                                             env_name))
+    else:
+      print >>sys.stderr, ('Warning: regeneration unimplemented for action %r '
+                           'flag %r' % (action, opt))
+
+  return flags
+
+class RegeneratableOptionParser(optparse.OptionParser):
+  def __init__(self):
+    self.__regeneratable_options = {}
+    optparse.OptionParser.__init__(self)
+
+  def add_option(self, *args, **kw):
+    """Add an option to the parser.
+
+    This accepts the same arguments as OptionParser.add_option, plus the
+    following:
+      regenerate: can be set to False to prevent this option from being included
+                  in regeneration.
+      env_name: name of environment variable that additional values for this
+                option come from.
+      type: adds type='path', to tell the regenerator that the values of
+            this option need to be made relative to options.depth
+    """
+    env_name = kw.pop('env_name', None)
+    if 'dest' in kw and kw.pop('regenerate', True):
+      dest = kw['dest']
+
+      # The path type is needed for regenerating, for optparse we can just treat
+      # it as a string.
+      type = kw.get('type')
+      if type == 'path':
+        kw['type'] = 'string'
+
+      self.__regeneratable_options[dest] = {
+          'action': kw.get('action'),
+          'type': type,
+          'env_name': env_name,
+          'opt': args[0],
+        }
+
+    optparse.OptionParser.add_option(self, *args, **kw)
+
+  def parse_args(self, *args):
+    values, args = optparse.OptionParser.parse_args(self, *args)
+    values._regeneration_metadata = self.__regeneratable_options
+    return values, args
+
+def gyp_main(args):
+  my_name = os.path.basename(sys.argv[0])
+
+  parser = RegeneratableOptionParser()
+  usage = 'usage: %s [options ...] [build_file ...]'
+  parser.set_usage(usage.replace('%s', '%prog'))
+  parser.add_option('-D', dest='defines', action='append', metavar='VAR=VAL',
+                    env_name='GYP_DEFINES',
+                    help='sets variable VAR to value VAL')
+  parser.add_option('-f', '--format', dest='formats', action='append',
+                    env_name='GYP_GENERATORS', regenerate=False,
+                    help='output formats to generate')
+  parser.add_option('--msvs-version', dest='msvs_version',
+                    regenerate=False,
+                    help='Deprecated; use -G msvs_version=MSVS_VERSION instead')
+  parser.add_option('-I', '--include', dest='includes', action='append',
+                    metavar='INCLUDE', type='path',
+                    help='files to include in all loaded .gyp files')
+  parser.add_option('--depth', dest='depth', metavar='PATH', type='path',
+                    help='set DEPTH gyp variable to a relative path to PATH')
+  parser.add_option('-d', '--debug', dest='debug', metavar='DEBUGMODE',
+                    action='append', default=[], help='turn on a debugging '
+                    'mode for debugging GYP.  Supported modes are "variables", '
+                    '"includes" and "general" or "all" for all of them.')
+  parser.add_option('-S', '--suffix', dest='suffix', default='',
+                    help='suffix to add to generated files')
+  parser.add_option('-G', dest='generator_flags', action='append', default=[],
+                    metavar='FLAG=VAL', env_name='GYP_GENERATOR_FLAGS',
+                    help='sets generator flag FLAG to VAL')
+  parser.add_option('--generator-output', dest='generator_output',
+                    action='store', default=None, metavar='DIR', type='path',
+                    env_name='GYP_GENERATOR_OUTPUT',
+                    help='puts generated build files under DIR')
+  parser.add_option('--ignore-environment', dest='use_environment',
+                    action='store_false', default=True, regenerate=False,
+                    help='do not read options from environment variables')
+  parser.add_option('--check', dest='check', action='store_true',
+                    help='check format of gyp files')
+  parser.add_option('--parallel', action='store_true',
+                    env_name='GYP_PARALLEL',
+                    help='Use multiprocessing for speed (experimental)')
+  parser.add_option('--toplevel-dir', dest='toplevel_dir', action='store',
+                    default=None, metavar='DIR', type='path',
+                    help='directory to use as the root of the source tree')
+  parser.add_option('--build', dest='configs', action='append',
+                    help='configuration for build after project generation')
+  # --no-circular-check disables the check for circular relationships between
+  # .gyp files.  These relationships should not exist, but they've only been
+  # observed to be harmful with the Xcode generator.  Chromium's .gyp files
+  # currently have some circular relationships on non-Mac platforms, so this
+  # option allows the strict behavior to be used on Macs and the lenient
+  # behavior to be used elsewhere.
+  # TODO(mark): Remove this option when http://crbug.com/35878 is fixed.
+  parser.add_option('--no-circular-check', dest='circular_check',
+                    action='store_false', default=True, regenerate=False,
+                    help="don't check for circular relationships between files")
+
+  # We read a few things from ~/.gyp, so set up a var for that.
+  home_vars = ['HOME']
+  if sys.platform in ('cygwin', 'win32'):
+    home_vars.append('USERPROFILE')
+  home = None
+  home_dot_gyp = None
+  for home_var in home_vars:
+    home = os.getenv(home_var)
+    if home != None:
+      home_dot_gyp = os.path.join(home, '.gyp')
+      if not os.path.exists(home_dot_gyp):
+        home_dot_gyp = None
+      else:
+        break
+
+  # TODO(thomasvl): add support for ~/.gyp/defaults
+
+  options, build_files_arg = parser.parse_args(args)
+  build_files = build_files_arg
+
+  if not options.formats:
+    # If no format was given on the command line, then check the env variable.
+    generate_formats = []
+    if options.use_environment:
+      generate_formats = os.environ.get('GYP_GENERATORS', [])
+    if generate_formats:
+      generate_formats = re.split('[\s,]', generate_formats)
+    if generate_formats:
+      options.formats = generate_formats
+    else:
+      # Nothing in the variable, default based on platform.
+      if sys.platform == 'darwin':
+        options.formats = ['xcode']
+      elif sys.platform in ('win32', 'cygwin'):
+        options.formats = ['msvs']
+      else:
+        options.formats = ['make']
+
+  if not options.generator_output and options.use_environment:
+    g_o = os.environ.get('GYP_GENERATOR_OUTPUT')
+    if g_o:
+      options.generator_output = g_o
+
+  if not options.parallel and options.use_environment:
+    p = os.environ.get('GYP_PARALLEL')
+    options.parallel = bool(p and p != '0')
+
+  for mode in options.debug:
+    gyp.debug[mode] = 1
+
+  # Do an extra check to avoid work when we're not debugging.
+  if DEBUG_GENERAL in gyp.debug:
+    DebugOutput(DEBUG_GENERAL, 'running with these options:')
+    for option, value in sorted(options.__dict__.items()):
+      if option[0] == '_':
+        continue
+      if isinstance(value, basestring):
+        DebugOutput(DEBUG_GENERAL, "  %s: '%s'", option, value)
+      else:
+        DebugOutput(DEBUG_GENERAL, "  %s: %s", option, value)
+
+  if not build_files:
+    build_files = FindBuildFiles()
+  if not build_files:
+    raise GypError((usage + '\n\n%s: error: no build_file') %
+                   (my_name, my_name))
+
+  # TODO(mark): Chromium-specific hack!
+  # For Chromium, the gyp "depth" variable should always be a relative path
+  # to Chromium's top-level "src" directory.  If no depth variable was set
+  # on the command line, try to find a "src" directory by looking at the
+  # absolute path to each build file's directory.  The first "src" component
+  # found will be treated as though it were the path used for --depth.
+  if not options.depth:
+    for build_file in build_files:
+      build_file_dir = os.path.abspath(os.path.dirname(build_file))
+      build_file_dir_components = build_file_dir.split(os.path.sep)
+      components_len = len(build_file_dir_components)
+      for index in xrange(components_len - 1, -1, -1):
+        if build_file_dir_components[index] == 'src':
+          options.depth = os.path.sep.join(build_file_dir_components)
+          break
+        del build_file_dir_components[index]
+
+      # If the inner loop found something, break without advancing to another
+      # build file.
+      if options.depth:
+        break
+
+    if not options.depth:
+      raise GypError('Could not automatically locate src directory.  This is'
+                     'a temporary Chromium feature that will be removed.  Use'
+                     '--depth as a workaround.')
+
+  # If toplevel-dir is not set, we assume that depth is the root of our source
+  # tree.
+  if not options.toplevel_dir:
+    options.toplevel_dir = options.depth
+
+  # -D on the command line sets variable defaults - D isn't just for define,
+  # it's for default.  Perhaps there should be a way to force (-F?) a
+  # variable's value so that it can't be overridden by anything else.
+  cmdline_default_variables = {}
+  defines = []
+  if options.use_environment:
+    defines += ShlexEnv('GYP_DEFINES')
+  if options.defines:
+    defines += options.defines
+  cmdline_default_variables = NameValueListToDict(defines)
+  if DEBUG_GENERAL in gyp.debug:
+    DebugOutput(DEBUG_GENERAL,
+                "cmdline_default_variables: %s", cmdline_default_variables)
+
+  # Set up includes.
+  includes = []
+
+  # If ~/.gyp/include.gypi exists, it'll be forcibly included into every
+  # .gyp file that's loaded, before anything else is included.
+  if home_dot_gyp != None:
+    default_include = os.path.join(home_dot_gyp, 'include.gypi')
+    if os.path.exists(default_include):
+      print 'Using overrides found in ' + default_include
+      includes.append(default_include)
+
+  # Command-line --include files come after the default include.
+  if options.includes:
+    includes.extend(options.includes)
+
+  # Generator flags should be prefixed with the target generator since they
+  # are global across all generator runs.
+  gen_flags = []
+  if options.use_environment:
+    gen_flags += ShlexEnv('GYP_GENERATOR_FLAGS')
+  if options.generator_flags:
+    gen_flags += options.generator_flags
+  generator_flags = NameValueListToDict(gen_flags)
+  if DEBUG_GENERAL in gyp.debug.keys():
+    DebugOutput(DEBUG_GENERAL, "generator_flags: %s", generator_flags)
+
+  # TODO: Remove this and the option after we've gotten folks to move to the
+  # generator flag.
+  if options.msvs_version:
+    print >>sys.stderr, \
+      'DEPRECATED: Use generator flag (-G msvs_version=' + \
+      options.msvs_version + ') instead of --msvs-version=' + \
+      options.msvs_version
+    generator_flags['msvs_version'] = options.msvs_version
+
+  # Generate all requested formats (use a set in case we got one format request
+  # twice)
+  for format in set(options.formats):
+    params = {'options': options,
+              'build_files': build_files,
+              'generator_flags': generator_flags,
+              'cwd': os.getcwd(),
+              'build_files_arg': build_files_arg,
+              'gyp_binary': sys.argv[0],
+              'home_dot_gyp': home_dot_gyp,
+              'parallel': options.parallel}
+
+    # Start with the default variables from the command line.
+    [generator, flat_list, targets, data] = Load(build_files, format,
+                                                 cmdline_default_variables,
+                                                 includes, options.depth,
+                                                 params, options.check,
+                                                 options.circular_check)
+
+    # TODO(mark): Pass |data| for now because the generator needs a list of
+    # build files that came in.  In the future, maybe it should just accept
+    # a list, and not the whole data dict.
+    # NOTE: flat_list is the flattened dependency graph specifying the order
+    # that targets may be built.  Build systems that operate serially or that
+    # need to have dependencies defined before dependents reference them should
+    # generate targets in the order specified in flat_list.
+    generator.GenerateOutput(flat_list, targets, data, params)
+
+    if options.configs:
+      valid_configs = targets[flat_list[0]]['configurations'].keys()
+      for conf in options.configs:
+        if conf not in valid_configs:
+          raise GypError('Invalid config specified via --build: %s' % conf)
+      generator.PerformBuild(data, options.configs, params)
+
+  # Done
+  return 0
+
+
+def main(args):
+  try:
+    return gyp_main(args)
+  except GypError, e:
+    sys.stderr.write("gyp: %s\n" % e)
+    return 1
+
+if __name__ == '__main__':
+  sys.exit(main(sys.argv[1:]))
diff --git a/webWidgetTCT_device/tools/gyp/pylib/gyp/common.py b/webWidgetTCT_device/tools/gyp/pylib/gyp/common.py
new file mode 100755 (executable)
index 0000000..e50f51c
--- /dev/null
@@ -0,0 +1,491 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from __future__ import with_statement
+
+import errno
+import filecmp
+import os.path
+import re
+import tempfile
+import sys
+
+
+# A minimal memoizing decorator. It'll blow up if the args aren't immutable,
+# among other "problems".
+class memoize(object):
+  def __init__(self, func):
+    self.func = func
+    self.cache = {}
+  def __call__(self, *args):
+    try:
+      return self.cache[args]
+    except KeyError:
+      result = self.func(*args)
+      self.cache[args] = result
+      return result
+
+
+class GypError(Exception):
+  """Error class representing an error, which is to be presented
+  to the user.  The main entry point will catch and display this.
+  """
+  pass
+
+
+def ExceptionAppend(e, msg):
+  """Append a message to the given exception's message."""
+  if not e.args:
+    e.args = (msg,)
+  elif len(e.args) == 1:
+    e.args = (str(e.args[0]) + ' ' + msg,)
+  else:
+    e.args = (str(e.args[0]) + ' ' + msg,) + e.args[1:]
+
+
+def ParseQualifiedTarget(target):
+  # Splits a qualified target into a build file, target name and toolset.
+
+  # NOTE: rsplit is used to disambiguate the Windows drive letter separator.
+  target_split = target.rsplit(':', 1)
+  if len(target_split) == 2:
+    [build_file, target] = target_split
+  else:
+    build_file = None
+
+  target_split = target.rsplit('#', 1)
+  if len(target_split) == 2:
+    [target, toolset] = target_split
+  else:
+    toolset = None
+
+  return [build_file, target, toolset]
+
+
+def ResolveTarget(build_file, target, toolset):
+  # This function resolves a target into a canonical form:
+  # - a fully defined build file, either absolute or relative to the current
+  # directory
+  # - a target name
+  # - a toolset
+  #
+  # build_file is the file relative to which 'target' is defined.
+  # target is the qualified target.
+  # toolset is the default toolset for that target.
+  [parsed_build_file, target, parsed_toolset] = ParseQualifiedTarget(target)
+
+  if parsed_build_file:
+    if build_file:
+      # If a relative path, parsed_build_file is relative to the directory
+      # containing build_file.  If build_file is not in the current directory,
+      # parsed_build_file is not a usable path as-is.  Resolve it by
+      # interpreting it as relative to build_file.  If parsed_build_file is
+      # absolute, it is usable as a path regardless of the current directory,
+      # and os.path.join will return it as-is.
+      build_file = os.path.normpath(os.path.join(os.path.dirname(build_file),
+                                                 parsed_build_file))
+      # Further (to handle cases like ../cwd), make it relative to cwd)
+      if not os.path.isabs(build_file):
+        build_file = RelativePath(build_file, '.')
+    else:
+      build_file = parsed_build_file
+
+  if parsed_toolset:
+    toolset = parsed_toolset
+
+  return [build_file, target, toolset]
+
+
+def BuildFile(fully_qualified_target):
+  # Extracts the build file from the fully qualified target.
+  return ParseQualifiedTarget(fully_qualified_target)[0]
+
+
+def GetEnvironFallback(var_list, default):
+  """Look up a key in the environment, with fallback to secondary keys
+  and finally falling back to a default value."""
+  for var in var_list:
+    if var in os.environ:
+      return os.environ[var]
+  return default
+
+
+def QualifiedTarget(build_file, target, toolset):
+  # "Qualified" means the file that a target was defined in and the target
+  # name, separated by a colon, suffixed by a # and the toolset name:
+  # /path/to/file.gyp:target_name#toolset
+  fully_qualified = build_file + ':' + target
+  if toolset:
+    fully_qualified = fully_qualified + '#' + toolset
+  return fully_qualified
+
+
+@memoize
+def RelativePath(path, relative_to):
+  # Assuming both |path| and |relative_to| are relative to the current
+  # directory, returns a relative path that identifies path relative to
+  # relative_to.
+
+  # Convert to normalized (and therefore absolute paths).
+  path = os.path.realpath(path)
+  relative_to = os.path.realpath(relative_to)
+
+  # Split the paths into components.
+  path_split = path.split(os.path.sep)
+  relative_to_split = relative_to.split(os.path.sep)
+
+  # Determine how much of the prefix the two paths share.
+  prefix_len = len(os.path.commonprefix([path_split, relative_to_split]))
+
+  # Put enough ".." components to back up out of relative_to to the common
+  # prefix, and then append the part of path_split after the common prefix.
+  relative_split = [os.path.pardir] * (len(relative_to_split) - prefix_len) + \
+                   path_split[prefix_len:]
+
+  if len(relative_split) == 0:
+    # The paths were the same.
+    return ''
+
+  # Turn it back into a string and we're done.
+  return os.path.join(*relative_split)
+
+
+@memoize
+def InvertRelativePath(path, toplevel_dir=None):
+  """Given a path like foo/bar that is relative to toplevel_dir, return
+  the inverse relative path back to the toplevel_dir.
+
+  E.g. os.path.normpath(os.path.join(path, InvertRelativePath(path)))
+  should always produce the empty string, unless the path contains symlinks.
+  """
+  if not path:
+    return path
+  toplevel_dir = '.' if toplevel_dir is None else toplevel_dir
+  return RelativePath(toplevel_dir, os.path.join(toplevel_dir, path))
+
+
+def FixIfRelativePath(path, relative_to):
+  # Like RelativePath but returns |path| unchanged if it is absolute.
+  if os.path.isabs(path):
+    return path
+  return RelativePath(path, relative_to)
+
+
+def UnrelativePath(path, relative_to):
+  # Assuming that |relative_to| is relative to the current directory, and |path|
+  # is a path relative to the dirname of |relative_to|, returns a path that
+  # identifies |path| relative to the current directory.
+  rel_dir = os.path.dirname(relative_to)
+  return os.path.normpath(os.path.join(rel_dir, path))
+
+
+# re objects used by EncodePOSIXShellArgument.  See IEEE 1003.1 XCU.2.2 at
+# http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_02
+# and the documentation for various shells.
+
+# _quote is a pattern that should match any argument that needs to be quoted
+# with double-quotes by EncodePOSIXShellArgument.  It matches the following
+# characters appearing anywhere in an argument:
+#   \t, \n, space  parameter separators
+#   #              comments
+#   $              expansions (quoted to always expand within one argument)
+#   %              called out by IEEE 1003.1 XCU.2.2
+#   &              job control
+#   '              quoting
+#   (, )           subshell execution
+#   *, ?, [        pathname expansion
+#   ;              command delimiter
+#   <, >, |        redirection
+#   =              assignment
+#   {, }           brace expansion (bash)
+#   ~              tilde expansion
+# It also matches the empty string, because "" (or '') is the only way to
+# represent an empty string literal argument to a POSIX shell.
+#
+# This does not match the characters in _escape, because those need to be
+# backslash-escaped regardless of whether they appear in a double-quoted
+# string.
+_quote = re.compile('[\t\n #$%&\'()*;<=>?[{|}~]|^$')
+
+# _escape is a pattern that should match any character that needs to be
+# escaped with a backslash, whether or not the argument matched the _quote
+# pattern.  _escape is used with re.sub to backslash anything in _escape's
+# first match group, hence the (parentheses) in the regular expression.
+#
+# _escape matches the following characters appearing anywhere in an argument:
+#   "  to prevent POSIX shells from interpreting this character for quoting
+#   \  to prevent POSIX shells from interpreting this character for escaping
+#   `  to prevent POSIX shells from interpreting this character for command
+#      substitution
+# Missing from this list is $, because the desired behavior of
+# EncodePOSIXShellArgument is to permit parameter (variable) expansion.
+#
+# Also missing from this list is !, which bash will interpret as the history
+# expansion character when history is enabled.  bash does not enable history
+# by default in non-interactive shells, so this is not thought to be a problem.
+# ! was omitted from this list because bash interprets "\!" as a literal string
+# including the backslash character (avoiding history expansion but retaining
+# the backslash), which would not be correct for argument encoding.  Handling
+# this case properly would also be problematic because bash allows the history
+# character to be changed with the histchars shell variable.  Fortunately,
+# as history is not enabled in non-interactive shells and
+# EncodePOSIXShellArgument is only expected to encode for non-interactive
+# shells, there is no room for error here by ignoring !.
+_escape = re.compile(r'(["\\`])')
+
+def EncodePOSIXShellArgument(argument):
+  """Encodes |argument| suitably for consumption by POSIX shells.
+
+  argument may be quoted and escaped as necessary to ensure that POSIX shells
+  treat the returned value as a literal representing the argument passed to
+  this function.  Parameter (variable) expansions beginning with $ are allowed
+  to remain intact without escaping the $, to allow the argument to contain
+  references to variables to be expanded by the shell.
+  """
+
+  if not isinstance(argument, str):
+    argument = str(argument)
+
+  if _quote.search(argument):
+    quote = '"'
+  else:
+    quote = ''
+
+  encoded = quote + re.sub(_escape, r'\\\1', argument) + quote
+
+  return encoded
+
+
+def EncodePOSIXShellList(list):
+  """Encodes |list| suitably for consumption by POSIX shells.
+
+  Returns EncodePOSIXShellArgument for each item in list, and joins them
+  together using the space character as an argument separator.
+  """
+
+  encoded_arguments = []
+  for argument in list:
+    encoded_arguments.append(EncodePOSIXShellArgument(argument))
+  return ' '.join(encoded_arguments)
+
+
+def DeepDependencyTargets(target_dicts, roots):
+  """Returns the recursive list of target dependencies."""
+  dependencies = set()
+  pending = set(roots)
+  while pending:
+    # Pluck out one.
+    r = pending.pop()
+    # Skip if visited already.
+    if r in dependencies:
+      continue
+    # Add it.
+    dependencies.add(r)
+    # Add its children.
+    spec = target_dicts[r]
+    pending.update(set(spec.get('dependencies', [])))
+    pending.update(set(spec.get('dependencies_original', [])))
+  return list(dependencies - set(roots))
+
+
+def BuildFileTargets(target_list, build_file):
+  """From a target_list, returns the subset from the specified build_file.
+  """
+  return [p for p in target_list if BuildFile(p) == build_file]
+
+
+def AllTargets(target_list, target_dicts, build_file):
+  """Returns all targets (direct and dependencies) for the specified build_file.
+  """
+  bftargets = BuildFileTargets(target_list, build_file)
+  deptargets = DeepDependencyTargets(target_dicts, bftargets)
+  return bftargets + deptargets
+
+
+def WriteOnDiff(filename):
+  """Write to a file only if the new contents differ.
+
+  Arguments:
+    filename: name of the file to potentially write to.
+  Returns:
+    A file like object which will write to temporary file and only overwrite
+    the target if it differs (on close).
+  """
+
+  class Writer:
+    """Wrapper around file which only covers the target if it differs."""
+    def __init__(self):
+      # Pick temporary file.
+      tmp_fd, self.tmp_path = tempfile.mkstemp(
+          suffix='.tmp',
+          prefix=os.path.split(filename)[1] + '.gyp.',
+          dir=os.path.split(filename)[0])
+      try:
+        self.tmp_file = os.fdopen(tmp_fd, 'wb')
+      except Exception:
+        # Don't leave turds behind.
+        os.unlink(self.tmp_path)
+        raise
+
+    def __getattr__(self, attrname):
+      # Delegate everything else to self.tmp_file
+      return getattr(self.tmp_file, attrname)
+
+    def close(self):
+      try:
+        # Close tmp file.
+        self.tmp_file.close()
+        # Determine if different.
+        same = False
+        try:
+          same = filecmp.cmp(self.tmp_path, filename, False)
+        except OSError, e:
+          if e.errno != errno.ENOENT:
+            raise
+
+        if same:
+          # The new file is identical to the old one, just get rid of the new
+          # one.
+          os.unlink(self.tmp_path)
+        else:
+          # The new file is different from the old one, or there is no old one.
+          # Rename the new file to the permanent name.
+          #
+          # tempfile.mkstemp uses an overly restrictive mode, resulting in a
+          # file that can only be read by the owner, regardless of the umask.
+          # There's no reason to not respect the umask here, which means that
+          # an extra hoop is required to fetch it and reset the new file's mode.
+          #
+          # No way to get the umask without setting a new one?  Set a safe one
+          # and then set it back to the old value.
+          umask = os.umask(077)
+          os.umask(umask)
+          os.chmod(self.tmp_path, 0666 & ~umask)
+          if sys.platform == 'win32' and os.path.exists(filename):
+            # NOTE: on windows (but not cygwin) rename will not replace an
+            # existing file, so it must be preceded with a remove. Sadly there
+            # is no way to make the switch atomic.
+            os.remove(filename)
+          os.rename(self.tmp_path, filename)
+      except Exception:
+        # Don't leave turds behind.
+        os.unlink(self.tmp_path)
+        raise
+
+  return Writer()
+
+
+def GetFlavor(params):
+  """Returns |params.flavor| if it's set, the system's default flavor else."""
+  flavors = {
+    'cygwin': 'win',
+    'win32': 'win',
+    'darwin': 'mac',
+  }
+
+  if 'flavor' in params:
+    return params['flavor']
+  if sys.platform in flavors:
+    return flavors[sys.platform]
+  if sys.platform.startswith('sunos'):
+    return 'solaris'
+  if sys.platform.startswith('freebsd'):
+    return 'freebsd'
+  if sys.platform.startswith('openbsd'):
+    return 'openbsd'
+  if sys.platform.startswith('aix'):
+    return 'aix'
+
+  return 'linux'
+
+
+def CopyTool(flavor, out_path):
+  """Finds (mac|sun|win)_tool.gyp in the gyp directory and copies it
+  to |out_path|."""
+  prefix = { 'solaris': 'sun', 'mac': 'mac', 'win': 'win' }.get(flavor, None)
+  if not prefix:
+    return
+
+  # Slurp input file.
+  source_path = os.path.join(
+      os.path.dirname(os.path.abspath(__file__)), '%s_tool.py' % prefix)
+  with open(source_path) as source_file:
+    source = source_file.readlines()
+
+  # Add header and write it out.
+  tool_path = os.path.join(out_path, 'gyp-%s-tool' % prefix)
+  with open(tool_path, 'w') as tool_file:
+    tool_file.write(
+        ''.join([source[0], '# Generated by gyp. Do not edit.\n'] + source[1:]))
+
+  # Make file executable.
+  os.chmod(tool_path, 0755)
+
+
+# From Alex Martelli,
+# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52560
+# ASPN: Python Cookbook: Remove duplicates from a sequence
+# First comment, dated 2001/10/13.
+# (Also in the printed Python Cookbook.)
+
+def uniquer(seq, idfun=None):
+    if idfun is None:
+        idfun = lambda x: x
+    seen = {}
+    result = []
+    for item in seq:
+        marker = idfun(item)
+        if marker in seen: continue
+        seen[marker] = 1
+        result.append(item)
+    return result
+
+
+class CycleError(Exception):
+  """An exception raised when an unexpected cycle is detected."""
+  def __init__(self, nodes):
+    self.nodes = nodes
+  def __str__(self):
+    return 'CycleError: cycle involving: ' + str(self.nodes)
+
+
+def TopologicallySorted(graph, get_edges):
+  """Topologically sort based on a user provided edge definition.
+
+  Args:
+    graph: A list of node names.
+    get_edges: A function mapping from node name to a hashable collection
+               of node names which this node has outgoing edges to.
+  Returns:
+    A list containing all of the node in graph in topological order.
+    It is assumed that calling get_edges once for each node and caching is
+    cheaper than repeatedly calling get_edges.
+  Raises:
+    CycleError in the event of a cycle.
+  Example:
+    graph = {'a': '$(b) $(c)', 'b': 'hi', 'c': '$(b)'}
+    def GetEdges(node):
+      return re.findall(r'\$\(([^))]\)', graph[node])
+    print TopologicallySorted(graph.keys(), GetEdges)
+    ==>
+    ['a', 'c', b']
+  """
+  get_edges = memoize(get_edges)
+  visited = set()
+  visiting = set()
+  ordered_nodes = []
+  def Visit(node):
+    if node in visiting:
+      raise CycleError(visiting)
+    if node in visited:
+      return
+    visited.add(node)
+    visiting.add(node)
+    for neighbor in get_edges(node):
+      Visit(neighbor)
+    visiting.remove(node)
+    ordered_nodes.insert(0, node)
+  for node in sorted(graph):
+    Visit(node)
+  return ordered_nodes
diff --git a/webWidgetTCT_device/tools/gyp/pylib/gyp/common_test.py b/webWidgetTCT_device/tools/gyp/pylib/gyp/common_test.py
new file mode 100755 (executable)
index 0000000..ad6f9a1
--- /dev/null
@@ -0,0 +1,72 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Unit tests for the common.py file."""
+
+import gyp.common
+import unittest
+import sys
+
+
+class TestTopologicallySorted(unittest.TestCase):
+  def test_Valid(self):
+    """Test that sorting works on a valid graph with one possible order."""
+    graph = {
+        'a': ['b', 'c'],
+        'b': [],
+        'c': ['d'],
+        'd': ['b'],
+        }
+    def GetEdge(node):
+      return tuple(graph[node])
+    self.assertEqual(
+      gyp.common.TopologicallySorted(graph.keys(), GetEdge),
+      ['a', 'c', 'd', 'b'])
+
+  def test_Cycle(self):
+    """Test that an exception is thrown on a cyclic graph."""
+    graph = {
+        'a': ['b'],
+        'b': ['c'],
+        'c': ['d'],
+        'd': ['a'],
+        }
+    def GetEdge(node):
+      return tuple(graph[node])
+    self.assertRaises(
+      gyp.common.CycleError, gyp.common.TopologicallySorted,
+      graph.keys(), GetEdge)
+
+
+class TestGetFlavor(unittest.TestCase):
+  """Test that gyp.common.GetFlavor works as intended"""
+  original_platform = ''
+
+  def setUp(self):
+    self.original_platform = sys.platform
+
+  def tearDown(self):
+    sys.platform = self.original_platform
+
+  def assertFlavor(self, expected, argument, param):
+    sys.platform = argument
+    self.assertEqual(expected, gyp.common.GetFlavor(param))
+
+  def test_platform_default(self):
+    self.assertFlavor('freebsd', 'freebsd9' , {})
+    self.assertFlavor('freebsd', 'freebsd10', {})
+    self.assertFlavor('openbsd', 'openbsd5' , {})
+    self.assertFlavor('solaris', 'sunos5'   , {});
+    self.assertFlavor('solaris', 'sunos'    , {});
+    self.assertFlavor('linux'  , 'linux2'   , {});
+    self.assertFlavor('linux'  , 'linux3'   , {});
+
+  def test_param(self):
+    self.assertFlavor('foobar', 'linux2' , {'flavor': 'foobar'})
+
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/webWidgetTCT_device/tools/gyp/pylib/gyp/easy_xml.py b/webWidgetTCT_device/tools/gyp/pylib/gyp/easy_xml.py
new file mode 100755 (executable)
index 0000000..bf949b6
--- /dev/null
@@ -0,0 +1,157 @@
+# Copyright (c) 2011 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import re
+import os
+
+
+def XmlToString(content, encoding='utf-8', pretty=False):
+  """ Writes the XML content to disk, touching the file only if it has changed.
+
+  Visual Studio files have a lot of pre-defined structures.  This function makes
+  it easy to represent these structures as Python data structures, instead of
+  having to create a lot of function calls.
+
+  Each XML element of the content is represented as a list composed of:
+  1. The name of the element, a string,
+  2. The attributes of the element, a dictionary (optional), and
+  3+. The content of the element, if any.  Strings are simple text nodes and
+      lists are child elements.
+
+  Example 1:
+      <test/>
+  becomes
+      ['test']
+
+  Example 2:
+      <myelement a='value1' b='value2'>
+         <childtype>This is</childtype>
+         <childtype>it!</childtype>
+      </myelement>
+
+  becomes
+      ['myelement', {'a':'value1', 'b':'value2'},
+         ['childtype', 'This is'],
+         ['childtype', 'it!'],
+      ]
+
+  Args:
+    content:  The structured content to be converted.
+    encoding: The encoding to report on the first XML line.
+    pretty: True if we want pretty printing with indents and new lines.
+
+  Returns:
+    The XML content as a string.
+  """
+  # We create a huge list of all the elements of the file.
+  xml_parts = ['<?xml version="1.0" encoding="%s"?>' % encoding]
+  if pretty:
+    xml_parts.append('\n')
+  _ConstructContentList(xml_parts, content, pretty)
+
+  # Convert it to a string
+  return ''.join(xml_parts)
+
+
+def _ConstructContentList(xml_parts, specification, pretty, level=0):
+  """ Appends the XML parts corresponding to the specification.
+
+  Args:
+    xml_parts: A list of XML parts to be appended to.
+    specification:  The specification of the element.  See EasyXml docs.
+    pretty: True if we want pretty printing with indents and new lines.
+    level: Indentation level.
+  """
+  # The first item in a specification is the name of the element.
+  if pretty:
+    indentation = '  ' * level
+    new_line = '\n'
+  else:
+    indentation = ''
+    new_line = ''
+  name = specification[0]
+  if not isinstance(name, str):
+    raise Exception('The first item of an EasyXml specification should be '
+                    'a string.  Specification was ' + str(specification))
+  xml_parts.append(indentation + '<' + name)
+
+  # Optionally in second position is a dictionary of the attributes.
+  rest = specification[1:]
+  if rest and isinstance(rest[0], dict):
+    for at, val in sorted(rest[0].iteritems()):
+      xml_parts.append(' %s="%s"' % (at, _XmlEscape(val, attr=True)))
+    rest = rest[1:]
+  if rest:
+    xml_parts.append('>')
+    all_strings = reduce(lambda x, y: x and isinstance(y, str), rest, True)
+    multi_line = not all_strings
+    if multi_line and new_line:
+      xml_parts.append(new_line)
+    for child_spec in rest:
+      # If it's a string, append a text node.
+      # Otherwise recurse over that child definition
+      if isinstance(child_spec, str):
+       xml_parts.append(_XmlEscape(child_spec))
+      else:
+        _ConstructContentList(xml_parts, child_spec, pretty, level + 1)
+    if multi_line and indentation:
+      xml_parts.append(indentation)
+    xml_parts.append('</%s>%s' % (name, new_line))
+  else:
+    xml_parts.append('/>%s' % new_line)
+
+
+def WriteXmlIfChanged(content, path, encoding='utf-8', pretty=False,
+                      win32=False):
+  """ Writes the XML content to disk, touching the file only if it has changed.
+
+  Args:
+    content:  The structured content to be written.
+    path: Location of the file.
+    encoding: The encoding to report on the first line of the XML file.
+    pretty: True if we want pretty printing with indents and new lines.
+  """
+  xml_string = XmlToString(content, encoding, pretty)
+  if win32 and os.linesep != '\r\n':
+    xml_string = xml_string.replace('\n', '\r\n')
+
+  # Get the old content
+  try:
+    f = open(path, 'r')
+    existing = f.read()
+    f.close()
+  except:
+    existing = None
+
+  # It has changed, write it
+  if existing != xml_string:
+    f = open(path, 'w')
+    f.write(xml_string)
+    f.close()
+
+
+_xml_escape_map = {
+    '"': '&quot;',
+    "'": '&apos;',
+    '<': '&lt;',
+    '>': '&gt;',
+    '&': '&amp;',
+    '\n': '&#xA;',
+    '\r': '&#xD;',
+}
+
+
+_xml_escape_re = re.compile(
+    "(%s)" % "|".join(map(re.escape, _xml_escape_map.keys())))
+
+
+def _XmlEscape(value, attr=False):
+  """ Escape a string for inclusion in XML."""
+  def replace(match):
+    m = match.string[match.start() : match.end()]
+    # don't replace single quotes in attrs
+    if attr and m == "'":
+      return m
+    return _xml_escape_map[m]
+  return _xml_escape_re.sub(replace, value)
diff --git a/webWidgetTCT_device/tools/gyp/pylib/gyp/easy_xml_test.py b/webWidgetTCT_device/tools/gyp/pylib/gyp/easy_xml_test.py
new file mode 100755 (executable)
index 0000000..df64354
--- /dev/null
@@ -0,0 +1,103 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2011 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+""" Unit tests for the easy_xml.py file. """
+
+import gyp.easy_xml as easy_xml
+import unittest
+import StringIO
+
+
+class TestSequenceFunctions(unittest.TestCase):
+
+  def setUp(self):
+    self.stderr = StringIO.StringIO()
+
+  def test_EasyXml_simple(self):
+    self.assertEqual(
+      easy_xml.XmlToString(['test']),
+      '<?xml version="1.0" encoding="utf-8"?><test/>')
+
+    self.assertEqual(
+      easy_xml.XmlToString(['test'], encoding='Windows-1252'),
+      '<?xml version="1.0" encoding="Windows-1252"?><test/>')
+
+  def test_EasyXml_simple_with_attributes(self):
+    self.assertEqual(
+      easy_xml.XmlToString(['test2', {'a': 'value1', 'b': 'value2'}]),
+      '<?xml version="1.0" encoding="utf-8"?><test2 a="value1" b="value2"/>')
+
+  def test_EasyXml_escaping(self):
+    original = '<test>\'"\r&\nfoo'
+    converted = '&lt;test&gt;\'&quot;&#xD;&amp;&#xA;foo'
+    converted_apos = converted.replace("'", '&apos;')
+    self.assertEqual(
+      easy_xml.XmlToString(['test3', {'a': original}, original]),
+      '<?xml version="1.0" encoding="utf-8"?><test3 a="%s">%s</test3>' %
+      (converted, converted_apos))
+
+  def test_EasyXml_pretty(self):
+    self.assertEqual(
+      easy_xml.XmlToString(
+          ['test3',
+            ['GrandParent',
+              ['Parent1',
+                ['Child']
+              ],
+              ['Parent2']
+            ]
+          ],
+          pretty=True),
+      '<?xml version="1.0" encoding="utf-8"?>\n'
+      '<test3>\n'
+      '  <GrandParent>\n'
+      '    <Parent1>\n'
+      '      <Child/>\n'
+      '    </Parent1>\n'
+      '    <Parent2/>\n'
+      '  </GrandParent>\n'
+      '</test3>\n')
+
+
+  def test_EasyXml_complex(self):
+    # We want to create:
+    target = (
+      '<?xml version="1.0" encoding="utf-8"?>'
+      '<Project>'
+        '<PropertyGroup Label="Globals">'
+          '<ProjectGuid>{D2250C20-3A94-4FB9-AF73-11BC5B73884B}</ProjectGuid>'
+          '<Keyword>Win32Proj</Keyword>'
+          '<RootNamespace>automated_ui_tests</RootNamespace>'
+        '</PropertyGroup>'
+        '<Import Project="$(VCTargetsPath)\\Microsoft.Cpp.props"/>'
+        '<PropertyGroup '
+            'Condition="\'$(Configuration)|$(Platform)\'=='
+                       '\'Debug|Win32\'" Label="Configuration">'
+          '<ConfigurationType>Application</ConfigurationType>'
+          '<CharacterSet>Unicode</CharacterSet>'
+        '</PropertyGroup>'
+      '</Project>')
+
+    xml = easy_xml.XmlToString(
+        ['Project',
+          ['PropertyGroup', {'Label': 'Globals'},
+            ['ProjectGuid', '{D2250C20-3A94-4FB9-AF73-11BC5B73884B}'],
+            ['Keyword', 'Win32Proj'],
+            ['RootNamespace', 'automated_ui_tests']
+          ],
+          ['Import', {'Project': '$(VCTargetsPath)\\Microsoft.Cpp.props'}],
+          ['PropertyGroup',
+            {'Condition': "'$(Configuration)|$(Platform)'=='Debug|Win32'",
+             'Label': 'Configuration'},
+            ['ConfigurationType', 'Application'],
+            ['CharacterSet', 'Unicode']
+          ]
+        ])
+    self.assertEqual(xml, target)
+
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/webWidgetTCT_device/tools/gyp/pylib/gyp/generator/__init__.py b/webWidgetTCT_device/tools/gyp/pylib/gyp/generator/__init__.py
new file mode 100755 (executable)
index 0000000..e69de29
diff --git a/webWidgetTCT_device/tools/gyp/pylib/gyp/generator/android.py b/webWidgetTCT_device/tools/gyp/pylib/gyp/generator/android.py
new file mode 100755 (executable)
index 0000000..a01ead0
--- /dev/null
@@ -0,0 +1,1099 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Notes:
+#
+# This generates makefiles suitable for inclusion into the Android build system
+# via an Android.mk file. It is based on make.py, the standard makefile
+# generator.
+#
+# The code below generates a separate .mk file for each target, but
+# all are sourced by the top-level GypAndroid.mk.  This means that all
+# variables in .mk-files clobber one another, and furthermore that any
+# variables set potentially clash with other Android build system variables.
+# Try to avoid setting global variables where possible.
+
+import gyp
+import gyp.common
+import gyp.generator.make as make  # Reuse global functions from make backend.
+import os
+import re
+import subprocess
+
+generator_default_variables = {
+  'OS': 'android',
+  'EXECUTABLE_PREFIX': '',
+  'EXECUTABLE_SUFFIX': '',
+  'STATIC_LIB_PREFIX': 'lib',
+  'SHARED_LIB_PREFIX': 'lib',
+  'STATIC_LIB_SUFFIX': '.a',
+  'SHARED_LIB_SUFFIX': '.so',
+  'INTERMEDIATE_DIR': '$(gyp_intermediate_dir)',
+  'SHARED_INTERMEDIATE_DIR': '$(gyp_shared_intermediate_dir)',
+  'PRODUCT_DIR': '$(gyp_shared_intermediate_dir)',
+  'SHARED_LIB_DIR': '$(builddir)/lib.$(TOOLSET)',
+  'LIB_DIR': '$(obj).$(TOOLSET)',
+  'RULE_INPUT_ROOT': '%(INPUT_ROOT)s',  # This gets expanded by Python.
+  'RULE_INPUT_DIRNAME': '%(INPUT_DIRNAME)s',  # This gets expanded by Python.
+  'RULE_INPUT_PATH': '$(RULE_SOURCES)',
+  'RULE_INPUT_EXT': '$(suffix $<)',
+  'RULE_INPUT_NAME': '$(notdir $<)',
+  'CONFIGURATION_NAME': '$(GYP_DEFAULT_CONFIGURATION)',
+}
+
+# Make supports multiple toolsets
+generator_supports_multiple_toolsets = True
+
+
+# Generator-specific gyp specs.
+generator_additional_non_configuration_keys = [
+    # Boolean to declare that this target does not want its name mangled.
+    'android_unmangled_name',
+]
+generator_additional_path_sections = []
+generator_extra_sources_for_rules = []
+
+
+SHARED_FOOTER = """\
+# "gyp_all_modules" is a concatenation of the "gyp_all_modules" targets from
+# all the included sub-makefiles. This is just here to clarify.
+gyp_all_modules:
+"""
+
+header = """\
+# This file is generated by gyp; do not edit.
+
+"""
+
+android_standard_include_paths = set([
+    # JNI_H_INCLUDE in build/core/binary.mk
+    'dalvik/libnativehelper/include/nativehelper',
+    # from SRC_HEADERS in build/core/config.mk
+    'system/core/include',
+    'hardware/libhardware/include',
+    'hardware/libhardware_legacy/include',
+    'hardware/ril/include',
+    'dalvik/libnativehelper/include',
+    'frameworks/native/include',
+    'frameworks/native/opengl/include',
+    'frameworks/base/include',
+    'frameworks/base/opengl/include',
+    'frameworks/base/native/include',
+    'external/skia/include',
+    # TARGET_C_INCLUDES in build/core/combo/TARGET_linux-arm.mk
+    'bionic/libc/arch-arm/include',
+    'bionic/libc/include',
+    'bionic/libstdc++/include',
+    'bionic/libc/kernel/common',
+    'bionic/libc/kernel/arch-arm',
+    'bionic/libm/include',
+    'bionic/libm/include/arm',
+    'bionic/libthread_db/include',
+    ])
+
+
+# Map gyp target types to Android module classes.
+MODULE_CLASSES = {
+    'static_library': 'STATIC_LIBRARIES',
+    'shared_library': 'SHARED_LIBRARIES',
+    'executable': 'EXECUTABLES',
+}
+
+
+def IsCPPExtension(ext):
+  return make.COMPILABLE_EXTENSIONS.get(ext) == 'cxx'
+
+
+def Sourceify(path):
+  """Convert a path to its source directory form. The Android backend does not
+     support options.generator_output, so this function is a noop."""
+  return path
+
+
+# Map from qualified target to path to output.
+# For Android, the target of these maps is a tuple ('static', 'modulename'),
+# ('dynamic', 'modulename'), or ('path', 'some/path') instead of a string,
+# since we link by module.
+target_outputs = {}
+# Map from qualified target to any linkable output.  A subset
+# of target_outputs.  E.g. when mybinary depends on liba, we want to
+# include liba in the linker line; when otherbinary depends on
+# mybinary, we just want to build mybinary first.
+target_link_deps = {}
+
+
+class AndroidMkWriter(object):
+  """AndroidMkWriter packages up the writing of one target-specific Android.mk.
+
+  Its only real entry point is Write(), and is mostly used for namespacing.
+  """
+
+  def __init__(self, android_top_dir):
+    self.android_top_dir = android_top_dir
+
+  def Write(self, qualified_target, relative_target, base_path, output_filename,
+            spec, configs, part_of_all):
+    """The main entry point: writes a .mk file for a single target.
+
+    Arguments:
+      qualified_target: target we're generating
+      relative_target: qualified target name relative to the root
+      base_path: path relative to source root we're building in, used to resolve
+                 target-relative paths
+      output_filename: output .mk file name to write
+      spec, configs: gyp info
+      part_of_all: flag indicating this target is part of 'all'
+    """
+    make.ensure_directory_exists(output_filename)
+
+    self.fp = open(output_filename, 'w')
+
+    self.fp.write(header)
+
+    self.qualified_target = qualified_target
+    self.relative_target = relative_target
+    self.path = base_path
+    self.target = spec['target_name']
+    self.type = spec['type']
+    self.toolset = spec['toolset']
+
+    deps, link_deps = self.ComputeDeps(spec)
+
+    # Some of the generation below can add extra output, sources, or
+    # link dependencies.  All of the out params of the functions that
+    # follow use names like extra_foo.
+    extra_outputs = []
+    extra_sources = []
+
+    self.android_class = MODULE_CLASSES.get(self.type, 'GYP')
+    self.android_module = self.ComputeAndroidModule(spec)
+    (self.android_stem, self.android_suffix) = self.ComputeOutputParts(spec)
+    self.output = self.output_binary = self.ComputeOutput(spec)
+
+    # Standard header.
+    self.WriteLn('include $(CLEAR_VARS)\n')
+
+    # Module class and name.
+    self.WriteLn('LOCAL_MODULE_CLASS := ' + self.android_class)
+    self.WriteLn('LOCAL_MODULE := ' + self.android_module)
+    # Only emit LOCAL_MODULE_STEM if it's different to LOCAL_MODULE.
+    # The library module classes fail if the stem is set. ComputeOutputParts
+    # makes sure that stem == modulename in these cases.
+    if self.android_stem != self.android_module:
+      self.WriteLn('LOCAL_MODULE_STEM := ' + self.android_stem)
+    self.WriteLn('LOCAL_MODULE_SUFFIX := ' + self.android_suffix)
+    self.WriteLn('LOCAL_MODULE_TAGS := optional')
+    if self.toolset == 'host':
+      self.WriteLn('LOCAL_IS_HOST_MODULE := true')
+
+    # Grab output directories; needed for Actions and Rules.
+    self.WriteLn('gyp_intermediate_dir := $(call local-intermediates-dir)')
+    self.WriteLn('gyp_shared_intermediate_dir := '
+                 '$(call intermediates-dir-for,GYP,shared)')
+    self.WriteLn()
+
+    # List files this target depends on so that actions/rules/copies/sources
+    # can depend on the list.
+    # TODO: doesn't pull in things through transitive link deps; needed?
+    target_dependencies = [x[1] for x in deps if x[0] == 'path']
+    self.WriteLn('# Make sure our deps are built first.')
+    self.WriteList(target_dependencies, 'GYP_TARGET_DEPENDENCIES',
+                   local_pathify=True)
+
+    # Actions must come first, since they can generate more OBJs for use below.
+    if 'actions' in spec:
+      self.WriteActions(spec['actions'], extra_sources, extra_outputs)
+
+    # Rules must be early like actions.
+    if 'rules' in spec:
+      self.WriteRules(spec['rules'], extra_sources, extra_outputs)
+
+    if 'copies' in spec:
+      self.WriteCopies(spec['copies'], extra_outputs)
+
+    # GYP generated outputs.
+    self.WriteList(extra_outputs, 'GYP_GENERATED_OUTPUTS', local_pathify=True)
+
+    # Set LOCAL_ADDITIONAL_DEPENDENCIES so that Android's build rules depend
+    # on both our dependency targets and our generated files.
+    self.WriteLn('# Make sure our deps and generated files are built first.')
+    self.WriteLn('LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) '
+                 '$(GYP_GENERATED_OUTPUTS)')
+    self.WriteLn()
+
+    # Sources.
+    if spec.get('sources', []) or extra_sources:
+      self.WriteSources(spec, configs, extra_sources)
+
+    self.WriteTarget(spec, configs, deps, link_deps, part_of_all)
+
+    # Update global list of target outputs, used in dependency tracking.
+    target_outputs[qualified_target] = ('path', self.output_binary)
+
+    # Update global list of link dependencies.
+    if self.type == 'static_library':
+      target_link_deps[qualified_target] = ('static', self.android_module)
+    elif self.type == 'shared_library':
+      target_link_deps[qualified_target] = ('shared', self.android_module)
+
+    self.fp.close()
+    return self.android_module
+
+
+  def WriteActions(self, actions, extra_sources, extra_outputs):
+    """Write Makefile code for any 'actions' from the gyp input.
+
+    extra_sources: a list that will be filled in with newly generated source
+                   files, if any
+    extra_outputs: a list that will be filled in with any outputs of these
+                   actions (used to make other pieces dependent on these
+                   actions)
+    """
+    for action in actions:
+      name = make.StringToMakefileVariable('%s_%s' % (self.relative_target,
+                                                      action['action_name']))
+      self.WriteLn('### Rules for action "%s":' % action['action_name'])
+      inputs = action['inputs']
+      outputs = action['outputs']
+
+      # Build up a list of outputs.
+      # Collect the output dirs we'll need.
+      dirs = set()
+      for out in outputs:
+        if not out.startswith('$'):
+          print ('WARNING: Action for target "%s" writes output to local path '
+                 '"%s".' % (self.target, out))
+        dir = os.path.split(out)[0]
+        if dir:
+          dirs.add(dir)
+      if int(action.get('process_outputs_as_sources', False)):
+        extra_sources += outputs
+
+      # Prepare the actual command.
+      command = gyp.common.EncodePOSIXShellList(action['action'])
+      if 'message' in action:
+        quiet_cmd = 'Gyp action: %s ($@)' % action['message']
+      else:
+        quiet_cmd = 'Gyp action: %s ($@)' % name
+      if len(dirs) > 0:
+        command = 'mkdir -p %s' % ' '.join(dirs) + '; ' + command
+
+      cd_action = 'cd $(gyp_local_path)/%s; ' % self.path
+      command = cd_action + command
+
+      # The makefile rules are all relative to the top dir, but the gyp actions
+      # are defined relative to their containing dir.  This replaces the gyp_*
+      # variables for the action rule with an absolute version so that the
+      # output goes in the right place.
+      # Only write the gyp_* rules for the "primary" output (:1);
+      # it's superfluous for the "extra outputs", and this avoids accidentally
+      # writing duplicate dummy rules for those outputs.
+      main_output = make.QuoteSpaces(self.LocalPathify(outputs[0]))
+      self.WriteLn('%s: gyp_local_path := $(LOCAL_PATH)' % main_output)
+      self.WriteLn('%s: gyp_intermediate_dir := '
+                   '$(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)' %
+                   main_output)
+      self.WriteLn('%s: gyp_shared_intermediate_dir := '
+                   '$(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)' %
+                   main_output)
+
+      # Android's envsetup.sh adds a number of directories to the path including
+      # the built host binary directory. This causes actions/rules invoked by
+      # gyp to sometimes use these instead of system versions, e.g. bison.
+      # The built host binaries may not be suitable, and can cause errors.
+      # So, we remove them from the PATH using the ANDROID_BUILD_PATHS variable
+      # set by envsetup.
+      self.WriteLn('%s: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))'
+                   % main_output)
+
+      for input in inputs:
+        assert ' ' not in input, (
+            "Spaces in action input filenames not supported (%s)"  % input)
+      for output in outputs:
+        assert ' ' not in output, (
+            "Spaces in action output filenames not supported (%s)"  % output)
+
+      self.WriteLn('%s: %s $(GYP_TARGET_DEPENDENCIES)' %
+                   (main_output, ' '.join(map(self.LocalPathify, inputs))))
+      self.WriteLn('\t@echo "%s"' % quiet_cmd)
+      self.WriteLn('\t$(hide)%s\n' % command)
+      for output in outputs[1:]:
+        # Make each output depend on the main output, with an empty command
+        # to force make to notice that the mtime has changed.
+        self.WriteLn('%s: %s ;' % (self.LocalPathify(output), main_output))
+
+      extra_outputs += outputs
+      self.WriteLn()
+
+    self.WriteLn()
+
+
+  def WriteRules(self, rules, extra_sources, extra_outputs):
+    """Write Makefile code for any 'rules' from the gyp input.
+
+    extra_sources: a list that will be filled in with newly generated source
+                   files, if any
+    extra_outputs: a list that will be filled in with any outputs of these
+                   rules (used to make other pieces dependent on these rules)
+    """
+    if len(rules) == 0:
+      return
+    rule_trigger = '%s_rule_trigger' % self.android_module
+
+    did_write_rule = False
+    for rule in rules:
+      if len(rule.get('rule_sources', [])) == 0:
+        continue
+      did_write_rule = True
+      name = make.StringToMakefileVariable('%s_%s' % (self.relative_target,
+                                                      rule['rule_name']))
+      self.WriteLn('\n### Generated for rule "%s":' % name)
+      self.WriteLn('# "%s":' % rule)
+
+      inputs = rule.get('inputs')
+      for rule_source in rule.get('rule_sources', []):
+        (rule_source_dirname, rule_source_basename) = os.path.split(rule_source)
+        (rule_source_root, rule_source_ext) = \
+            os.path.splitext(rule_source_basename)
+
+        outputs = [self.ExpandInputRoot(out, rule_source_root,
+                                        rule_source_dirname)
+                   for out in rule['outputs']]
+
+        dirs = set()
+        for out in outputs:
+          if not out.startswith('$'):
+            print ('WARNING: Rule for target %s writes output to local path %s'
+                   % (self.target, out))
+          dir = os.path.dirname(out)
+          if dir:
+            dirs.add(dir)
+        extra_outputs += outputs
+        if int(rule.get('process_outputs_as_sources', False)):
+          extra_sources.extend(outputs)
+
+        components = []
+        for component in rule['action']:
+          component = self.ExpandInputRoot(component, rule_source_root,
+                                           rule_source_dirname)
+          if '$(RULE_SOURCES)' in component:
+            component = component.replace('$(RULE_SOURCES)',
+                                          rule_source)
+          components.append(component)
+
+        command = gyp.common.EncodePOSIXShellList(components)
+        cd_action = 'cd $(gyp_local_path)/%s; ' % self.path
+        command = cd_action + command
+        if dirs:
+          command = 'mkdir -p %s' % ' '.join(dirs) + '; ' + command
+
+        # We set up a rule to build the first output, and then set up
+        # a rule for each additional output to depend on the first.
+        outputs = map(self.LocalPathify, outputs)
+        main_output = outputs[0]
+        self.WriteLn('%s: gyp_local_path := $(LOCAL_PATH)' % main_output)
+        self.WriteLn('%s: gyp_intermediate_dir := '
+                     '$(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_intermediate_dir)'
+                     % main_output)
+        self.WriteLn('%s: gyp_shared_intermediate_dir := '
+                     '$(GYP_ABS_ANDROID_TOP_DIR)/$(gyp_shared_intermediate_dir)'
+                     % main_output)
+
+        # See explanation in WriteActions.
+        self.WriteLn('%s: export PATH := '
+                     '$(subst $(ANDROID_BUILD_PATHS),,$(PATH))' % main_output)
+
+        main_output_deps = self.LocalPathify(rule_source)
+        if inputs:
+          main_output_deps += ' '
+          main_output_deps += ' '.join([self.LocalPathify(f) for f in inputs])
+
+        self.WriteLn('%s: %s $(GYP_TARGET_DEPENDENCIES)' %
+                     (main_output, main_output_deps))
+        self.WriteLn('\t%s\n' % command)
+        for output in outputs[1:]:
+          self.WriteLn('%s: %s' % (output, main_output))
+        self.WriteLn('.PHONY: %s' % (rule_trigger))
+        self.WriteLn('%s: %s' % (rule_trigger, main_output))
+        self.WriteLn('')
+    if did_write_rule:
+      extra_sources.append(rule_trigger)  # Force all rules to run.
+      self.WriteLn('### Finished generating for all rules')
+      self.WriteLn('')
+
+
+  def WriteCopies(self, copies, extra_outputs):
+    """Write Makefile code for any 'copies' from the gyp input.
+
+    extra_outputs: a list that will be filled in with any outputs of this action
+                   (used to make other pieces dependent on this action)
+    """
+    self.WriteLn('### Generated for copy rule.')
+
+    variable = make.StringToMakefileVariable(self.relative_target + '_copies')
+    outputs = []
+    for copy in copies:
+      for path in copy['files']:
+        # The Android build system does not allow generation of files into the
+        # source tree. The destination should start with a variable, which will
+        # typically be $(gyp_intermediate_dir) or
+        # $(gyp_shared_intermediate_dir). Note that we can't use an assertion
+        # because some of the gyp tests depend on this.
+        if not copy['destination'].startswith('$'):
+          print ('WARNING: Copy rule for target %s writes output to '
+                 'local path %s' % (self.target, copy['destination']))
+
+        # LocalPathify() calls normpath, stripping trailing slashes.
+        path = Sourceify(self.LocalPathify(path))
+        filename = os.path.split(path)[1]
+        output = Sourceify(self.LocalPathify(os.path.join(copy['destination'],
+                                                          filename)))
+
+        self.WriteLn('%s: %s $(GYP_TARGET_DEPENDENCIES) | $(ACP)' %
+                     (output, path))
+        self.WriteLn('\t@echo Copying: $@')
+        self.WriteLn('\t$(hide) mkdir -p $(dir $@)')
+        self.WriteLn('\t$(hide) $(ACP) -r $< $@')
+        self.WriteLn()
+        outputs.append(output)
+    self.WriteLn('%s = %s' % (variable,
+                              ' '.join(map(make.QuoteSpaces, outputs))))
+    extra_outputs.append('$(%s)' % variable)
+    self.WriteLn()
+
+
+  def WriteSourceFlags(self, spec, configs):
+    """Write out the flags and include paths used to compile source files for
+    the current target.
+
+    Args:
+      spec, configs: input from gyp.
+    """
+    config = configs[spec['default_configuration']]
+    extracted_includes = []
+
+    self.WriteLn('\n# Flags passed to both C and C++ files.')
+    cflags, includes_from_cflags = self.ExtractIncludesFromCFlags(
+        config.get('cflags'))
+    extracted_includes.extend(includes_from_cflags)
+    self.WriteList(cflags, 'MY_CFLAGS')
+
+    cflags_c, includes_from_cflags_c = self.ExtractIncludesFromCFlags(
+        config.get('cflags_c'))
+    extracted_includes.extend(includes_from_cflags_c)
+    self.WriteList(cflags_c, 'MY_CFLAGS_C')
+
+    self.WriteList(config.get('defines'), 'MY_DEFS', prefix='-D',
+                   quoter=make.EscapeCppDefine)
+    self.WriteLn('LOCAL_CFLAGS := $(MY_CFLAGS_C) $(MY_CFLAGS) $(MY_DEFS)')
+
+    # Undefine ANDROID for host modules
+    # TODO: the source code should not use macro ANDROID to tell if it's host or
+    # target module.
+    if self.toolset == 'host':
+      self.WriteLn('# Undefine ANDROID for host modules')
+      self.WriteLn('LOCAL_CFLAGS += -UANDROID')
+
+    self.WriteLn('\n# Include paths placed before CFLAGS/CPPFLAGS')
+    includes = list(config.get('include_dirs', []))
+    includes.extend(extracted_includes)
+    includes = map(Sourceify, map(self.LocalPathify, includes))
+    includes = self.NormalizeIncludePaths(includes)
+    self.WriteList(includes, 'LOCAL_C_INCLUDES')
+    self.WriteLn('LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) '
+                                     '$(LOCAL_C_INCLUDES)')
+
+    self.WriteLn('\n# Flags passed to only C++ (and not C) files.')
+    self.WriteList(config.get('cflags_cc'), 'LOCAL_CPPFLAGS')
+
+
+  def WriteSources(self, spec, configs, extra_sources):
+    """Write Makefile code for any 'sources' from the gyp input.
+    These are source files necessary to build the current target.
+    We need to handle shared_intermediate directory source files as
+    a special case by copying them to the intermediate directory and
+    treating them as a genereated sources. Otherwise the Android build
+    rules won't pick them up.
+
+    Args:
+      spec, configs: input from gyp.
+      extra_sources: Sources generated from Actions or Rules.
+    """
+    sources = filter(make.Compilable, spec.get('sources', []))
+    generated_not_sources = [x for x in extra_sources if not make.Compilable(x)]
+    extra_sources = filter(make.Compilable, extra_sources)
+
+    # Determine and output the C++ extension used by these sources.
+    # We simply find the first C++ file and use that extension.
+    all_sources = sources + extra_sources
+    local_cpp_extension = '.cpp'
+    for source in all_sources:
+      (root, ext) = os.path.splitext(source)
+      if IsCPPExtension(ext):
+        local_cpp_extension = ext
+        break
+    if local_cpp_extension != '.cpp':
+      self.WriteLn('LOCAL_CPP_EXTENSION := %s' % local_cpp_extension)
+
+    # We need to move any non-generated sources that are coming from the
+    # shared intermediate directory out of LOCAL_SRC_FILES and put them
+    # into LOCAL_GENERATED_SOURCES. We also need to move over any C++ files
+    # that don't match our local_cpp_extension, since Android will only
+    # generate Makefile rules for a single LOCAL_CPP_EXTENSION.
+    local_files = []
+    for source in sources:
+      (root, ext) = os.path.splitext(source)
+      if '$(gyp_shared_intermediate_dir)' in source:
+        extra_sources.append(source)
+      elif '$(gyp_intermediate_dir)' in source:
+        extra_sources.append(source)
+      elif IsCPPExtension(ext) and ext != local_cpp_extension:
+        extra_sources.append(source)
+      else:
+        local_files.append(os.path.normpath(os.path.join(self.path, source)))
+
+    # For any generated source, if it is coming from the shared intermediate
+    # directory then we add a Make rule to copy them to the local intermediate
+    # directory first. This is because the Android LOCAL_GENERATED_SOURCES
+    # must be in the local module intermediate directory for the compile rules
+    # to work properly. If the file has the wrong C++ extension, then we add
+    # a rule to copy that to intermediates and use the new version.
+    final_generated_sources = []
+    # If a source file gets copied, we still need to add the orginal source
+    # directory as header search path, for GCC searches headers in the
+    # directory that contains the source file by default.
+    origin_src_dirs = []
+    for source in extra_sources:
+      local_file = source
+      if not '$(gyp_intermediate_dir)/' in local_file:
+        basename = os.path.basename(local_file)
+        local_file = '$(gyp_intermediate_dir)/' + basename
+      (root, ext) = os.path.splitext(local_file)
+      if IsCPPExtension(ext) and ext != local_cpp_extension:
+        local_file = root + local_cpp_extension
+      if local_file != source:
+        self.WriteLn('%s: %s' % (local_file, self.LocalPathify(source)))
+        self.WriteLn('\tmkdir -p $(@D); cp $< $@')
+        origin_src_dirs.append(os.path.dirname(source))
+      final_generated_sources.append(local_file)
+
+    # We add back in all of the non-compilable stuff to make sure that the
+    # make rules have dependencies on them.
+    final_generated_sources.extend(generated_not_sources)
+    self.WriteList(final_generated_sources, 'LOCAL_GENERATED_SOURCES')
+
+    origin_src_dirs = gyp.common.uniquer(origin_src_dirs)
+    origin_src_dirs = map(Sourceify, map(self.LocalPathify, origin_src_dirs))
+    self.WriteList(origin_src_dirs, 'GYP_COPIED_SOURCE_ORIGIN_DIRS')
+
+    self.WriteList(local_files, 'LOCAL_SRC_FILES')
+
+    # Write out the flags used to compile the source; this must be done last
+    # so that GYP_COPIED_SOURCE_ORIGIN_DIRS can be used as an include path.
+    self.WriteSourceFlags(spec, configs)
+
+
+  def ComputeAndroidModule(self, spec):
+    """Return the Android module name used for a gyp spec.
+
+    We use the complete qualified target name to avoid collisions between
+    duplicate targets in different directories. We also add a suffix to
+    distinguish gyp-generated module names.
+    """
+
+    if int(spec.get('android_unmangled_name', 0)):
+      assert self.type != 'shared_library' or self.target.startswith('lib')
+      return self.target
+
+    if self.type == 'shared_library':
+      # For reasons of convention, the Android build system requires that all
+      # shared library modules are named 'libfoo' when generating -l flags.
+      prefix = 'lib_'
+    else:
+      prefix = ''
+
+    if spec['toolset'] == 'host':
+      suffix = '_host_gyp'
+    else:
+      suffix = '_gyp'
+
+    if self.path:
+      name = '%s%s_%s%s' % (prefix, self.path, self.target, suffix)
+    else:
+      name = '%s%s%s' % (prefix, self.target, suffix)
+
+    return make.StringToMakefileVariable(name)
+
+
+  def ComputeOutputParts(self, spec):
+    """Return the 'output basename' of a gyp spec, split into filename + ext.
+
+    Android libraries must be named the same thing as their module name,
+    otherwise the linker can't find them, so product_name and so on must be
+    ignored if we are building a library, and the "lib" prepending is
+    not done for Android.
+    """
+    assert self.type != 'loadable_module' # TODO: not supported?
+
+    target = spec['target_name']
+    target_prefix = ''
+    target_ext = ''
+    if self.type == 'static_library':
+      target = self.ComputeAndroidModule(spec)
+      target_ext = '.a'
+    elif self.type == 'shared_library':
+      target = self.ComputeAndroidModule(spec)
+      target_ext = '.so'
+    elif self.type == 'none':
+      target_ext = '.stamp'
+    elif self.type != 'executable':
+      print ("ERROR: What output file should be generated?",
+             "type", self.type, "target", target)
+
+    if self.type != 'static_library' and self.type != 'shared_library':
+      target_prefix = spec.get('product_prefix', target_prefix)
+      target = spec.get('product_name', target)
+      product_ext = spec.get('product_extension')
+      if product_ext:
+        target_ext = '.' + product_ext
+
+    target_stem = target_prefix + target
+    return (target_stem, target_ext)
+
+
+  def ComputeOutputBasename(self, spec):
+    """Return the 'output basename' of a gyp spec.
+
+    E.g., the loadable module 'foobar' in directory 'baz' will produce
+      'libfoobar.so'
+    """
+    return ''.join(self.ComputeOutputParts(spec))
+
+
+  def ComputeOutput(self, spec):
+    """Return the 'output' (full output path) of a gyp spec.
+
+    E.g., the loadable module 'foobar' in directory 'baz' will produce
+      '$(obj)/baz/libfoobar.so'
+    """
+    if self.type == 'executable' and self.toolset == 'host':
+      # We install host executables into shared_intermediate_dir so they can be
+      # run by gyp rules that refer to PRODUCT_DIR.
+      path = '$(gyp_shared_intermediate_dir)'
+    elif self.type == 'shared_library':
+      if self.toolset == 'host':
+        path = '$(HOST_OUT_INTERMEDIATE_LIBRARIES)'
+      else:
+        path = '$(TARGET_OUT_INTERMEDIATE_LIBRARIES)'
+    else:
+      # Other targets just get built into their intermediate dir.
+      if self.toolset == 'host':
+        path = '$(call intermediates-dir-for,%s,%s,true)' % (self.android_class,
+                                                            self.android_module)
+      else:
+        path = '$(call intermediates-dir-for,%s,%s)' % (self.android_class,
+                                                        self.android_module)
+
+    assert spec.get('product_dir') is None # TODO: not supported?
+    return os.path.join(path, self.ComputeOutputBasename(spec))
+
+
+  def NormalizeLdFlags(self, ld_flags):
+    """ Clean up ldflags from gyp file.
+    Remove any ldflags that contain android_top_dir.
+
+    Args:
+      ld_flags: ldflags from gyp files.
+
+    Returns:
+      clean ldflags
+    """
+    clean_ldflags = []
+    for flag in ld_flags:
+      if self.android_top_dir in flag:
+        continue
+      clean_ldflags.append(flag)
+    return clean_ldflags
+
+  def NormalizeIncludePaths(self, include_paths):
+    """ Normalize include_paths.
+    Convert absolute paths to relative to the Android top directory;
+    filter out include paths that are already brought in by the Android build
+    system.
+
+    Args:
+      include_paths: A list of unprocessed include paths.
+    Returns:
+      A list of normalized include paths.
+    """
+    normalized = []
+    for path in include_paths:
+      if path[0] == '/':
+        path = gyp.common.RelativePath(path, self.android_top_dir)
+
+      # Filter out the Android standard search path.
+      if path not in android_standard_include_paths:
+        normalized.append(path)
+    return normalized
+
+  def ExtractIncludesFromCFlags(self, cflags):
+    """Extract includes "-I..." out from cflags
+
+    Args:
+      cflags: A list of compiler flags, which may be mixed with "-I.."
+    Returns:
+      A tuple of lists: (clean_clfags, include_paths). "-I.." is trimmed.
+    """
+    clean_cflags = []
+    include_paths = []
+    if cflags:
+      for flag in cflags:
+        if flag.startswith('-I'):
+          include_paths.append(flag[2:])
+        else:
+          clean_cflags.append(flag)
+
+    return (clean_cflags, include_paths)
+
+  def ComputeAndroidLibraryModuleNames(self, libraries):
+    """Compute the Android module names from libraries, ie spec.get('libraries')
+
+    Args:
+      libraries: the value of spec.get('libraries')
+    Returns:
+      A tuple (static_lib_modules, dynamic_lib_modules)
+    """
+    static_lib_modules = []
+    dynamic_lib_modules = []
+    for libs in libraries:
+      # Libs can have multiple words.
+      for lib in libs.split():
+        # Filter the system libraries, which are added by default by the Android
+        # build system.
+        if (lib == '-lc' or lib == '-lstdc++' or lib == '-lm' or
+            lib.endswith('libgcc.a')):
+          continue
+        match = re.search(r'([^/]+)\.a$', lib)
+        if match:
+          static_lib_modules.append(match.group(1))
+          continue
+        match = re.search(r'([^/]+)\.so$', lib)
+        if match:
+          dynamic_lib_modules.append(match.group(1))
+          continue
+        # "-lstlport" -> libstlport
+        if lib.startswith('-l'):
+          if lib.endswith('_static'):
+            static_lib_modules.append('lib' + lib[2:])
+          else:
+            dynamic_lib_modules.append('lib' + lib[2:])
+    return (static_lib_modules, dynamic_lib_modules)
+
+
+  def ComputeDeps(self, spec):
+    """Compute the dependencies of a gyp spec.
+
+    Returns a tuple (deps, link_deps), where each is a list of
+    filenames that will need to be put in front of make for either
+    building (deps) or linking (link_deps).
+    """
+    deps = []
+    link_deps = []
+    if 'dependencies' in spec:
+      deps.extend([target_outputs[dep] for dep in spec['dependencies']
+                   if target_outputs[dep]])
+      for dep in spec['dependencies']:
+        if dep in target_link_deps:
+          link_deps.append(target_link_deps[dep])
+      deps.extend(link_deps)
+    return (gyp.common.uniquer(deps), gyp.common.uniquer(link_deps))
+
+
+  def WriteTargetFlags(self, spec, configs, link_deps):
+    """Write Makefile code to specify the link flags and library dependencies.
+
+    spec, configs: input from gyp.
+    link_deps: link dependency list; see ComputeDeps()
+    """
+    config = configs[spec['default_configuration']]
+
+    # LDFLAGS
+    ldflags = list(config.get('ldflags', []))
+    static_flags, dynamic_flags = self.ComputeAndroidLibraryModuleNames(
+        ldflags)
+    self.WriteLn('')
+    self.WriteList(self.NormalizeLdFlags(ldflags), 'LOCAL_LDFLAGS')
+
+    # Libraries (i.e. -lfoo)
+    libraries = gyp.common.uniquer(spec.get('libraries', []))
+    static_libs, dynamic_libs = self.ComputeAndroidLibraryModuleNames(
+        libraries)
+
+    # Link dependencies (i.e. libfoo.a, libfoo.so)
+    static_link_deps = [x[1] for x in link_deps if x[0] == 'static']
+    shared_link_deps = [x[1] for x in link_deps if x[0] == 'shared']
+    self.WriteLn('')
+    self.WriteList(static_flags + static_libs + static_link_deps,
+                   'LOCAL_STATIC_LIBRARIES')
+    self.WriteLn('# Enable grouping to fix circular references')
+    self.WriteLn('LOCAL_GROUP_STATIC_LIBRARIES := true')
+    self.WriteLn('')
+    self.WriteList(dynamic_flags + dynamic_libs + shared_link_deps,
+                   'LOCAL_SHARED_LIBRARIES')
+
+
+  def WriteTarget(self, spec, configs, deps, link_deps, part_of_all):
+    """Write Makefile code to produce the final target of the gyp spec.
+
+    spec, configs: input from gyp.
+    deps, link_deps: dependency lists; see ComputeDeps()
+    part_of_all: flag indicating this target is part of 'all'
+    """
+    self.WriteLn('### Rules for final target.')
+
+    if self.type != 'none':
+      self.WriteTargetFlags(spec, configs, link_deps)
+
+    # Add to the set of targets which represent the gyp 'all' target. We use the
+    # name 'gyp_all_modules' as the Android build system doesn't allow the use
+    # of the Make target 'all' and because 'all_modules' is the equivalent of
+    # the Make target 'all' on Android.
+    if part_of_all:
+      self.WriteLn('# Add target alias to "gyp_all_modules" target.')
+      self.WriteLn('.PHONY: gyp_all_modules')
+      self.WriteLn('gyp_all_modules: %s' % self.android_module)
+      self.WriteLn('')
+
+    # Add an alias from the gyp target name to the Android module name. This
+    # simplifies manual builds of the target, and is required by the test
+    # framework.
+    if self.target != self.android_module:
+      self.WriteLn('# Alias gyp target name.')
+      self.WriteLn('.PHONY: %s' % self.target)
+      self.WriteLn('%s: %s' % (self.target, self.android_module))
+      self.WriteLn('')
+
+    # Add the command to trigger build of the target type depending
+    # on the toolset. Ex: BUILD_STATIC_LIBRARY vs. BUILD_HOST_STATIC_LIBRARY
+    # NOTE: This has to come last!
+    modifier = ''
+    if self.toolset == 'host':
+      modifier = 'HOST_'
+    if self.type == 'static_library':
+      self.WriteLn('include $(BUILD_%sSTATIC_LIBRARY)' % modifier)
+    elif self.type == 'shared_library':
+      self.WriteLn('LOCAL_PRELINK_MODULE := false')
+      self.WriteLn('include $(BUILD_%sSHARED_LIBRARY)' % modifier)
+    elif self.type == 'executable':
+      if self.toolset == 'host':
+        self.WriteLn('LOCAL_MODULE_PATH := $(gyp_shared_intermediate_dir)')
+      else:
+        # Don't install target executables for now, as it results in them being
+        # included in ROM. This can be revisited if there's a reason to install
+        # them later.
+        self.WriteLn('LOCAL_UNINSTALLABLE_MODULE := true')
+      self.WriteLn('include $(BUILD_%sEXECUTABLE)' % modifier)
+    else:
+      self.WriteLn('LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp')
+      self.WriteLn('LOCAL_UNINSTALLABLE_MODULE := true')
+      self.WriteLn()
+      self.WriteLn('include $(BUILD_SYSTEM)/base_rules.mk')
+      self.WriteLn()
+      self.WriteLn('$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)')
+      self.WriteLn('\t$(hide) echo "Gyp timestamp: $@"')
+      self.WriteLn('\t$(hide) mkdir -p $(dir $@)')
+      self.WriteLn('\t$(hide) touch $@')
+
+
+  def WriteList(self, value_list, variable=None, prefix='',
+                quoter=make.QuoteIfNecessary, local_pathify=False):
+    """Write a variable definition that is a list of values.
+
+    E.g. WriteList(['a','b'], 'foo', prefix='blah') writes out
+         foo = blaha blahb
+    but in a pretty-printed style.
+    """
+    values = ''
+    if value_list:
+      value_list = [quoter(prefix + l) for l in value_list]
+      if local_pathify:
+        value_list = [self.LocalPathify(l) for l in value_list]
+      values = ' \\\n\t' + ' \\\n\t'.join(value_list)
+    self.fp.write('%s :=%s\n\n' % (variable, values))
+
+
+  def WriteLn(self, text=''):
+    self.fp.write(text + '\n')
+
+
+  def LocalPathify(self, path):
+    """Convert a subdirectory-relative path into a normalized path which starts
+    with the make variable $(LOCAL_PATH) (i.e. the top of the project tree).
+    Absolute paths, or paths that contain variables, are just normalized."""
+    if '$(' in path or os.path.isabs(path):
+      # path is not a file in the project tree in this case, but calling
+      # normpath is still important for trimming trailing slashes.
+      return os.path.normpath(path)
+    local_path = os.path.join('$(LOCAL_PATH)', self.path, path)
+    local_path = os.path.normpath(local_path)
+    # Check that normalizing the path didn't ../ itself out of $(LOCAL_PATH)
+    # - i.e. that the resulting path is still inside the project tree. The
+    # path may legitimately have ended up containing just $(LOCAL_PATH), though,
+    # so we don't look for a slash.
+    assert local_path.startswith('$(LOCAL_PATH)'), (
+           'Path %s attempts to escape from gyp path %s !)' % (path, self.path))
+    return local_path
+
+
+  def ExpandInputRoot(self, template, expansion, dirname):
+    if '%(INPUT_ROOT)s' not in template and '%(INPUT_DIRNAME)s' not in template:
+      return template
+    path = template % {
+        'INPUT_ROOT': expansion,
+        'INPUT_DIRNAME': dirname,
+        }
+    return path
+
+
+def PerformBuild(data, configurations, params):
+  # The android backend only supports the default configuration.
+  options = params['options']
+  makefile = os.path.abspath(os.path.join(options.toplevel_dir,
+                                          'GypAndroid.mk'))
+  env = dict(os.environ)
+  env['ONE_SHOT_MAKEFILE'] = makefile
+  arguments = ['make', '-C', os.environ['ANDROID_BUILD_TOP'], 'gyp_all_modules']
+  print 'Building: %s' % arguments
+  subprocess.check_call(arguments, env=env)
+
+
+def GenerateOutput(target_list, target_dicts, data, params):
+  options = params['options']
+  generator_flags = params.get('generator_flags', {})
+  builddir_name = generator_flags.get('output_dir', 'out')
+  limit_to_target_all = generator_flags.get('limit_to_target_all', False)
+  android_top_dir = os.environ.get('ANDROID_BUILD_TOP')
+  assert android_top_dir, '$ANDROID_BUILD_TOP not set; you need to run lunch.'
+
+  def CalculateMakefilePath(build_file, base_name):
+    """Determine where to write a Makefile for a given gyp file."""
+    # Paths in gyp files are relative to the .gyp file, but we want
+    # paths relative to the source root for the master makefile.  Grab
+    # the path of the .gyp file as the base to relativize against.
+    # E.g. "foo/bar" when we're constructing targets for "foo/bar/baz.gyp".
+    base_path = gyp.common.RelativePath(os.path.dirname(build_file),
+                                        options.depth)
+    # We write the file in the base_path directory.
+    output_file = os.path.join(options.depth, base_path, base_name)
+    assert not options.generator_output, (
+        'The Android backend does not support options.generator_output.')
+    base_path = gyp.common.RelativePath(os.path.dirname(build_file),
+                                        options.toplevel_dir)
+    return base_path, output_file
+
+  # TODO:  search for the first non-'Default' target.  This can go
+  # away when we add verification that all targets have the
+  # necessary configurations.
+  default_configuration = None
+  toolsets = set([target_dicts[target]['toolset'] for target in target_list])
+  for target in target_list:
+    spec = target_dicts[target]
+    if spec['default_configuration'] != 'Default':
+      default_configuration = spec['default_configuration']
+      break
+  if not default_configuration:
+    default_configuration = 'Default'
+
+  srcdir = '.'
+  makefile_name = 'GypAndroid' + options.suffix + '.mk'
+  makefile_path = os.path.join(options.toplevel_dir, makefile_name)
+  assert not options.generator_output, (
+      'The Android backend does not support options.generator_output.')
+  make.ensure_directory_exists(makefile_path)
+  root_makefile = open(makefile_path, 'w')
+
+  root_makefile.write(header)
+
+  # We set LOCAL_PATH just once, here, to the top of the project tree. This
+  # allows all the other paths we use to be relative to the Android.mk file,
+  # as the Android build system expects.
+  root_makefile.write('\nLOCAL_PATH := $(call my-dir)\n')
+
+  # Find the list of targets that derive from the gyp file(s) being built.
+  needed_targets = set()
+  for build_file in params['build_files']:
+    for target in gyp.common.AllTargets(target_list, target_dicts, build_file):
+      needed_targets.add(target)
+
+  build_files = set()
+  include_list = set()
+  android_modules = {}
+  for qualified_target in target_list:
+    build_file, target, toolset = gyp.common.ParseQualifiedTarget(
+        qualified_target)
+    relative_build_file = gyp.common.RelativePath(build_file,
+                                                  options.toplevel_dir)
+    build_files.add(relative_build_file)
+    included_files = data[build_file]['included_files']
+    for included_file in included_files:
+      # The included_files entries are relative to the dir of the build file
+      # that included them, so we have to undo that and then make them relative
+      # to the root dir.
+      relative_include_file = gyp.common.RelativePath(
+          gyp.common.UnrelativePath(included_file, build_file),
+          options.toplevel_dir)
+      abs_include_file = os.path.abspath(relative_include_file)
+      # If the include file is from the ~/.gyp dir, we should use absolute path
+      # so that relocating the src dir doesn't break the path.
+      if (params['home_dot_gyp'] and
+          abs_include_file.startswith(params['home_dot_gyp'])):
+        build_files.add(abs_include_file)
+      else:
+        build_files.add(relative_include_file)
+
+    base_path, output_file = CalculateMakefilePath(build_file,
+        target + '.' + toolset + options.suffix + '.mk')
+
+    spec = target_dicts[qualified_target]
+    configs = spec['configurations']
+
+    part_of_all = (qualified_target in needed_targets and
+                   not int(spec.get('suppress_wildcard', False)))
+    if limit_to_target_all and not part_of_all:
+      continue
+
+    relative_target = gyp.common.QualifiedTarget(relative_build_file, target,
+                                                 toolset)
+    writer = AndroidMkWriter(android_top_dir)
+    android_module = writer.Write(qualified_target, relative_target, base_path,
+                                  output_file, spec, configs,
+                                  part_of_all=part_of_all)
+    if android_module in android_modules:
+      print ('ERROR: Android module names must be unique. The following '
+             'targets both generate Android module name %s.\n  %s\n  %s' %
+             (android_module, android_modules[android_module],
+              qualified_target))
+      return
+    android_modules[android_module] = qualified_target
+
+    # Our root_makefile lives at the source root.  Compute the relative path
+    # from there to the output_file for including.
+    mkfile_rel_path = gyp.common.RelativePath(output_file,
+                                              os.path.dirname(makefile_path))
+    include_list.add(mkfile_rel_path)
+
+  # Some tools need to know the absolute path of the top directory.
+  root_makefile.write('GYP_ABS_ANDROID_TOP_DIR := $(shell pwd)\n')
+  root_makefile.write('GYP_DEFAULT_CONFIGURATION := %s\n' %
+                      default_configuration)
+
+  # Write out the sorted list of includes.
+  root_makefile.write('\n')
+  for include_file in sorted(include_list):
+    root_makefile.write('include $(LOCAL_PATH)/' + include_file + '\n')
+  root_makefile.write('\n')
+
+  root_makefile.write(SHARED_FOOTER)
+
+  root_makefile.close()
diff --git a/webWidgetTCT_device/tools/gyp/pylib/gyp/generator/dump_dependency_json.py b/webWidgetTCT_device/tools/gyp/pylib/gyp/generator/dump_dependency_json.py
new file mode 100755 (executable)
index 0000000..f8480dd
--- /dev/null
@@ -0,0 +1,93 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import collections
+import os
+import gyp
+import gyp.common
+import gyp.msvs_emulation
+import json
+import sys
+
+generator_supports_multiple_toolsets = True
+
+generator_wants_static_library_dependencies_adjusted = False
+
+generator_default_variables = {
+}
+for dirname in ['INTERMEDIATE_DIR', 'SHARED_INTERMEDIATE_DIR', 'PRODUCT_DIR',
+                'LIB_DIR', 'SHARED_LIB_DIR']:
+  # Some gyp steps fail if these are empty(!).
+  generator_default_variables[dirname] = 'dir'
+for unused in ['RULE_INPUT_PATH', 'RULE_INPUT_ROOT', 'RULE_INPUT_NAME',
+               'RULE_INPUT_DIRNAME', 'RULE_INPUT_EXT',
+               'EXECUTABLE_PREFIX', 'EXECUTABLE_SUFFIX',
+               'STATIC_LIB_PREFIX', 'STATIC_LIB_SUFFIX',
+               'SHARED_LIB_PREFIX', 'SHARED_LIB_SUFFIX',
+               'CONFIGURATION_NAME']:
+  generator_default_variables[unused] = ''
+
+
+def CalculateVariables(default_variables, params):
+  generator_flags = params.get('generator_flags', {})
+  for key, val in generator_flags.items():
+    default_variables.setdefault(key, val)
+  default_variables.setdefault('OS', gyp.common.GetFlavor(params))
+
+  flavor = gyp.common.GetFlavor(params)
+  if flavor =='win':
+    # Copy additional generator configuration data from VS, which is shared
+    # by the Windows Ninja generator.
+    import gyp.generator.msvs as msvs_generator
+    generator_additional_non_configuration_keys = getattr(msvs_generator,
+        'generator_additional_non_configuration_keys', [])
+    generator_additional_path_sections = getattr(msvs_generator,
+        'generator_additional_path_sections', [])
+
+    # Set a variable so conditions can be based on msvs_version.
+    msvs_version = gyp.msvs_emulation.GetVSVersion(generator_flags)
+    default_variables['MSVS_VERSION'] = msvs_version.ShortName()
+
+    # To determine processor word size on Windows, in addition to checking
+    # PROCESSOR_ARCHITECTURE (which reflects the word size of the current
+    # process), it is also necessary to check PROCESSOR_ARCHITEW6432 (which
+    # contains the actual word size of the system when running thru WOW64).
+    if ('64' in os.environ.get('PROCESSOR_ARCHITECTURE', '') or
+        '64' in os.environ.get('PROCESSOR_ARCHITEW6432', '')):
+      default_variables['MSVS_OS_BITS'] = 64
+    else:
+      default_variables['MSVS_OS_BITS'] = 32
+
+
+def CalculateGeneratorInputInfo(params):
+  """Calculate the generator specific info that gets fed to input (called by
+  gyp)."""
+  generator_flags = params.get('generator_flags', {})
+  if generator_flags.get('adjust_static_libraries', False):
+    global generator_wants_static_library_dependencies_adjusted
+    generator_wants_static_library_dependencies_adjusted = True
+
+
+def GenerateOutput(target_list, target_dicts, data, params):
+  # Map of target -> list of targets it depends on.
+  edges = {}
+
+  # Queue of targets to visit.
+  targets_to_visit = target_list[:]
+
+  while len(targets_to_visit) > 0:
+    target = targets_to_visit.pop()
+    if target in edges:
+      continue
+    edges[target] = []
+
+    for dep in target_dicts[target].get('dependencies', []):
+      edges[target].append(dep)
+      targets_to_visit.append(dep)
+
+  filename = 'dump.json'
+  f = open(filename, 'w')
+  json.dump(edges, f)
+  f.close()
+  print 'Wrote json to %s.' % filename
diff --git a/webWidgetTCT_device/tools/gyp/pylib/gyp/generator/eclipse.py b/webWidgetTCT_device/tools/gyp/pylib/gyp/generator/eclipse.py
new file mode 100755 (executable)
index 0000000..08425da
--- /dev/null
@@ -0,0 +1,277 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""GYP backend that generates Eclipse CDT settings files.
+
+This backend DOES NOT generate Eclipse CDT projects. Instead, it generates XML
+files that can be imported into an Eclipse CDT project. The XML file contains a
+list of include paths and symbols (i.e. defines).
+
+Because a full .cproject definition is not created by this generator, it's not
+possible to properly define the include dirs and symbols for each file
+individually.  Instead, one set of includes/symbols is generated for the entire
+project.  This works fairly well (and is a vast improvement in general), but may
+still result in a few indexer issues here and there.
+
+This generator has no automated tests, so expect it to be broken.
+"""
+
+from xml.sax.saxutils import escape
+import os.path
+import subprocess
+import gyp
+import gyp.common
+import shlex
+
+generator_wants_static_library_dependencies_adjusted = False
+
+generator_default_variables = {
+}
+
+for dirname in ['INTERMEDIATE_DIR', 'PRODUCT_DIR', 'LIB_DIR', 'SHARED_LIB_DIR']:
+  # Some gyp steps fail if these are empty(!).
+  generator_default_variables[dirname] = 'dir'
+
+for unused in ['RULE_INPUT_PATH', 'RULE_INPUT_ROOT', 'RULE_INPUT_NAME',
+               'RULE_INPUT_DIRNAME', 'RULE_INPUT_EXT',
+               'EXECUTABLE_PREFIX', 'EXECUTABLE_SUFFIX',
+               'STATIC_LIB_PREFIX', 'STATIC_LIB_SUFFIX',
+               'SHARED_LIB_PREFIX', 'SHARED_LIB_SUFFIX',
+               'CONFIGURATION_NAME']:
+  generator_default_variables[unused] = ''
+
+# Include dirs will occasionally use the SHARED_INTERMEDIATE_DIR variable as
+# part of the path when dealing with generated headers.  This value will be
+# replaced dynamically for each configuration.
+generator_default_variables['SHARED_INTERMEDIATE_DIR'] = \
+    '$SHARED_INTERMEDIATE_DIR'
+
+
+def CalculateVariables(default_variables, params):
+  generator_flags = params.get('generator_flags', {})
+  for key, val in generator_flags.items():
+    default_variables.setdefault(key, val)
+  default_variables.setdefault('OS', gyp.common.GetFlavor(params))
+
+
+def CalculateGeneratorInputInfo(params):
+  """Calculate the generator specific info that gets fed to input (called by
+  gyp)."""
+  generator_flags = params.get('generator_flags', {})
+  if generator_flags.get('adjust_static_libraries', False):
+    global generator_wants_static_library_dependencies_adjusted
+    generator_wants_static_library_dependencies_adjusted = True
+
+
+def GetAllIncludeDirectories(target_list, target_dicts,
+                             shared_intermediate_dirs, config_name):
+  """Calculate the set of include directories to be used.
+
+  Returns:
+    A list including all the include_dir's specified for every target followed
+    by any include directories that were added as cflag compiler options.
+  """
+
+  gyp_includes_set = set()
+  compiler_includes_list = []
+
+  for target_name in target_list:
+    target = target_dicts[target_name]
+    if config_name in target['configurations']:
+      config = target['configurations'][config_name]
+
+      # Look for any include dirs that were explicitly added via cflags. This
+      # may be done in gyp files to force certain includes to come at the end.
+      # TODO(jgreenwald): Change the gyp files to not abuse cflags for this, and
+      # remove this.
+      cflags = config['cflags']
+      for cflag in cflags:
+        include_dir = ''
+        if cflag.startswith('-I'):
+          include_dir = cflag[2:]
+        if include_dir and not include_dir in compiler_includes_list:
+          compiler_includes_list.append(include_dir)
+
+      # Find standard gyp include dirs.
+      if config.has_key('include_dirs'):
+        include_dirs = config['include_dirs']
+        for shared_intermediate_dir in shared_intermediate_dirs:
+          for include_dir in include_dirs:
+            include_dir = include_dir.replace('$SHARED_INTERMEDIATE_DIR',
+                                              shared_intermediate_dir)
+            if not os.path.isabs(include_dir):
+              base_dir = os.path.dirname(target_name)
+
+              include_dir = base_dir + '/' + include_dir
+              include_dir = os.path.abspath(include_dir)
+
+            if not include_dir in gyp_includes_set:
+              gyp_includes_set.add(include_dir)
+
+
+  # Generate a list that has all the include dirs.
+  all_includes_list = list(gyp_includes_set)
+  all_includes_list.sort()
+  for compiler_include in compiler_includes_list:
+    if not compiler_include in gyp_includes_set:
+      all_includes_list.append(compiler_include)
+
+  # All done.
+  return all_includes_list
+
+
+def GetCompilerPath(target_list, target_dicts, data):
+  """Determine a command that can be used to invoke the compiler.
+
+  Returns:
+    If this is a gyp project that has explicit make settings, try to determine
+    the compiler from that.  Otherwise, see if a compiler was specified via the
+    CC_target environment variable.
+  """
+
+  # First, see if the compiler is configured in make's settings.
+  build_file, _, _ = gyp.common.ParseQualifiedTarget(target_list[0])
+  make_global_settings_dict = data[build_file].get('make_global_settings', {})
+  for key, value in make_global_settings_dict:
+    if key in ['CC', 'CXX']:
+      return value
+
+  # Check to see if the compiler was specified as an environment variable.
+  for key in ['CC_target', 'CC', 'CXX']:
+    compiler = os.environ.get(key)
+    if compiler:
+      return compiler
+
+  return 'gcc'
+
+
+def GetAllDefines(target_list, target_dicts, data, config_name):
+  """Calculate the defines for a project.
+
+  Returns:
+    A dict that includes explict defines declared in gyp files along with all of
+    the default defines that the compiler uses.
+  """
+
+  # Get defines declared in the gyp files.
+  all_defines = {}
+  for target_name in target_list:
+    target = target_dicts[target_name]
+
+    if config_name in target['configurations']:
+      config = target['configurations'][config_name]
+      for define in config['defines']:
+        split_define = define.split('=', 1)
+        if len(split_define) == 1:
+          split_define.append('1')
+        if split_define[0].strip() in all_defines:
+          # Already defined
+          continue
+
+        all_defines[split_define[0].strip()] = split_define[1].strip()
+
+  # Get default compiler defines (if possible).
+  cc_target = GetCompilerPath(target_list, target_dicts, data)
+  if cc_target:
+    command = shlex.split(cc_target)
+    command.extend(['-E', '-dM', '-'])
+    cpp_proc = subprocess.Popen(args=command, cwd='.',
+                                stdin=subprocess.PIPE, stdout=subprocess.PIPE)
+    cpp_output = cpp_proc.communicate()[0]
+    cpp_lines = cpp_output.split('\n')
+    for cpp_line in cpp_lines:
+      if not cpp_line.strip():
+        continue
+      cpp_line_parts = cpp_line.split(' ', 2)
+      key = cpp_line_parts[1]
+      if len(cpp_line_parts) >= 3:
+        val = cpp_line_parts[2]
+      else:
+        val = '1'
+      all_defines[key] = val
+
+  return all_defines
+
+
+def WriteIncludePaths(out, eclipse_langs, include_dirs):
+  """Write the includes section of a CDT settings export file."""
+
+  out.write('  <section name="org.eclipse.cdt.internal.ui.wizards.' \
+            'settingswizards.IncludePaths">\n')
+  out.write('    <language name="holder for library settings"></language>\n')
+  for lang in eclipse_langs:
+    out.write('    <language name="%s">\n' % lang)
+    for include_dir in include_dirs:
+      out.write('      <includepath workspace_path="false">%s</includepath>\n' %
+                include_dir)
+    out.write('    </language>\n')
+  out.write('  </section>\n')
+
+
+def WriteMacros(out, eclipse_langs, defines):
+  """Write the macros section of a CDT settings export file."""
+
+  out.write('  <section name="org.eclipse.cdt.internal.ui.wizards.' \
+            'settingswizards.Macros">\n')
+  out.write('    <language name="holder for library settings"></language>\n')
+  for lang in eclipse_langs:
+    out.write('    <language name="%s">\n' % lang)
+    for key in sorted(defines.iterkeys()):
+      out.write('      <macro><name>%s</name><value>%s</value></macro>\n' %
+                (escape(key), escape(defines[key])))
+    out.write('    </language>\n')
+  out.write('  </section>\n')
+
+
+def GenerateOutputForConfig(target_list, target_dicts, data, params,
+                            config_name):
+  options = params['options']
+  generator_flags = params.get('generator_flags', {})
+
+  # build_dir: relative path from source root to our output files.
+  # e.g. "out/Debug"
+  build_dir = os.path.join(generator_flags.get('output_dir', 'out'),
+                           config_name)
+
+  toplevel_build = os.path.join(options.toplevel_dir, build_dir)
+  # Ninja uses out/Debug/gen while make uses out/Debug/obj/gen as the
+  # SHARED_INTERMEDIATE_DIR. Include both possible locations.
+  shared_intermediate_dirs = [os.path.join(toplevel_build, 'obj', 'gen'),
+                              os.path.join(toplevel_build, 'gen')]
+
+  if not os.path.exists(toplevel_build):
+    os.makedirs(toplevel_build)
+  out = open(os.path.join(toplevel_build, 'eclipse-cdt-settings.xml'), 'w')
+
+  out.write('<?xml version="1.0" encoding="UTF-8"?>\n')
+  out.write('<cdtprojectproperties>\n')
+
+  eclipse_langs = ['C++ Source File', 'C Source File', 'Assembly Source File',
+                   'GNU C++', 'GNU C', 'Assembly']
+  include_dirs = GetAllIncludeDirectories(target_list, target_dicts,
+                                          shared_intermediate_dirs, config_name)
+  WriteIncludePaths(out, eclipse_langs, include_dirs)
+  defines = GetAllDefines(target_list, target_dicts, data, config_name)
+  WriteMacros(out, eclipse_langs, defines)
+
+  out.write('</cdtprojectproperties>\n')
+  out.close()
+
+
+def GenerateOutput(target_list, target_dicts, data, params):
+  """Generate an XML settings file that can be imported into a CDT project."""
+
+  if params['options'].generator_output:
+    raise NotImplementedError, "--generator_output not implemented for eclipse"
+
+  user_config = params.get('generator_flags', {}).get('config', None)
+  if user_config:
+    GenerateOutputForConfig(target_list, target_dicts, data, params,
+                            user_config)
+  else:
+    config_names = target_dicts[target_list[0]]['configurations'].keys()
+    for config_name in config_names:
+      GenerateOutputForConfig(target_list, target_dicts, data, params,
+                              config_name)
+
diff --git a/webWidgetTCT_device/tools/gyp/pylib/gyp/generator/gypd.py b/webWidgetTCT_device/tools/gyp/pylib/gyp/generator/gypd.py
new file mode 100755 (executable)
index 0000000..22ef57f
--- /dev/null
@@ -0,0 +1,87 @@
+# Copyright (c) 2011 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""gypd output module
+
+This module produces gyp input as its output.  Output files are given the
+.gypd extension to avoid overwriting the .gyp files that they are generated
+from.  Internal references to .gyp files (such as those found in
+"dependencies" sections) are not adjusted to point to .gypd files instead;
+unlike other paths, which are relative to the .gyp or .gypd file, such paths
+are relative to the directory from which gyp was run to create the .gypd file.
+
+This generator module is intended to be a sample and a debugging aid, hence
+the "d" for "debug" in .gypd.  It is useful to inspect the results of the
+various merges, expansions, and conditional evaluations performed by gyp
+and to see a representation of what would be fed to a generator module.
+
+It's not advisable to rename .gypd files produced by this module to .gyp,
+because they will have all merges, expansions, and evaluations already
+performed and the relevant constructs not present in the output; paths to
+dependencies may be wrong; and various sections that do not belong in .gyp
+files such as such as "included_files" and "*_excluded" will be present.
+Output will also be stripped of comments.  This is not intended to be a
+general-purpose gyp pretty-printer; for that, you probably just want to
+run "pprint.pprint(eval(open('source.gyp').read()))", which will still strip
+comments but won't do all of the other things done to this module's output.
+
+The specific formatting of the output generated by this module is subject
+to change.
+"""
+
+
+import gyp.common
+import errno
+import os
+import pprint
+
+
+# These variables should just be spit back out as variable references.
+_generator_identity_variables = [
+  'EXECUTABLE_PREFIX',
+  'EXECUTABLE_SUFFIX',
+  'INTERMEDIATE_DIR',
+  'PRODUCT_DIR',
+  'RULE_INPUT_ROOT',
+  'RULE_INPUT_DIRNAME',
+  'RULE_INPUT_EXT',
+  'RULE_INPUT_NAME',
+  'RULE_INPUT_PATH',
+  'SHARED_INTERMEDIATE_DIR',
+]
+
+# gypd doesn't define a default value for OS like many other generator
+# modules.  Specify "-D OS=whatever" on the command line to provide a value.
+generator_default_variables = {
+}
+
+# gypd supports multiple toolsets
+generator_supports_multiple_toolsets = True
+
+# TODO(mark): This always uses <, which isn't right.  The input module should
+# notify the generator to tell it which phase it is operating in, and this
+# module should use < for the early phase and then switch to > for the late
+# phase.  Bonus points for carrying @ back into the output too.
+for v in _generator_identity_variables:
+  generator_default_variables[v] = '<(%s)' % v
+
+
+def GenerateOutput(target_list, target_dicts, data, params):
+  output_files = {}
+  for qualified_target in target_list:
+    [input_file, target] = \
+        gyp.common.ParseQualifiedTarget(qualified_target)[0:2]
+
+    if input_file[-4:] != '.gyp':
+      continue
+    input_file_stem = input_file[:-4]
+    output_file = input_file_stem + params['options'].suffix + '.gypd'
+
+    if not output_file in output_files:
+      output_files[output_file] = input_file
+
+  for output_file, input_file in output_files.iteritems():
+    output = open(output_file, 'w')
+    pprint.pprint(data[input_file], output)
+    output.close()
diff --git a/webWidgetTCT_device/tools/gyp/pylib/gyp/generator/gypsh.py b/webWidgetTCT_device/tools/gyp/pylib/gyp/generator/gypsh.py
new file mode 100755 (executable)
index 0000000..bd405f4
--- /dev/null
@@ -0,0 +1,56 @@
+# Copyright (c) 2011 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""gypsh output module
+
+gypsh is a GYP shell.  It's not really a generator per se.  All it does is
+fire up an interactive Python session with a few local variables set to the
+variables passed to the generator.  Like gypd, it's intended as a debugging
+aid, to facilitate the exploration of .gyp structures after being processed
+by the input module.
+
+The expected usage is "gyp -f gypsh -D OS=desired_os".
+"""
+
+
+import code
+import sys
+
+
+# All of this stuff about generator variables was lovingly ripped from gypd.py.
+# That module has a much better description of what's going on and why.
+_generator_identity_variables = [
+  'EXECUTABLE_PREFIX',
+  'EXECUTABLE_SUFFIX',
+  'INTERMEDIATE_DIR',
+  'PRODUCT_DIR',
+  'RULE_INPUT_ROOT',
+  'RULE_INPUT_DIRNAME',
+  'RULE_INPUT_EXT',
+  'RULE_INPUT_NAME',
+  'RULE_INPUT_PATH',
+  'SHARED_INTERMEDIATE_DIR',
+]
+
+generator_default_variables = {
+}
+
+for v in _generator_identity_variables:
+  generator_default_variables[v] = '<(%s)' % v
+
+
+def GenerateOutput(target_list, target_dicts, data, params):
+  locals = {
+        'target_list':  target_list,
+        'target_dicts': target_dicts,
+        'data':         data,
+      }
+
+  # Use a banner that looks like the stock Python one and like what
+  # code.interact uses by default, but tack on something to indicate what
+  # locals are available, and identify gypsh.
+  banner='Python %s on %s\nlocals.keys() = %s\ngypsh' % \
+         (sys.version, sys.platform, repr(sorted(locals.keys())))
+
+  code.interact(banner, local=locals)
diff --git a/webWidgetTCT_device/tools/gyp/pylib/gyp/generator/make.py b/webWidgetTCT_device/tools/gyp/pylib/gyp/generator/make.py
new file mode 100755 (executable)
index 0000000..2230d63
--- /dev/null
@@ -0,0 +1,2149 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Notes:
+#
+# This is all roughly based on the Makefile system used by the Linux
+# kernel, but is a non-recursive make -- we put the entire dependency
+# graph in front of make and let it figure it out.
+#
+# The code below generates a separate .mk file for each target, but
+# all are sourced by the top-level Makefile.  This means that all
+# variables in .mk-files clobber one another.  Be careful to use :=
+# where appropriate for immediate evaluation, and similarly to watch
+# that you're not relying on a variable value to last beween different
+# .mk files.
+#
+# TODOs:
+#
+# Global settings and utility functions are currently stuffed in the
+# toplevel Makefile.  It may make sense to generate some .mk files on
+# the side to keep the the files readable.
+
+import os
+import re
+import sys
+import subprocess
+import gyp
+import gyp.common
+import gyp.xcode_emulation
+from gyp.common import GetEnvironFallback
+
+generator_default_variables = {
+  'EXECUTABLE_PREFIX': '',
+  'EXECUTABLE_SUFFIX': '',
+  'STATIC_LIB_PREFIX': 'lib',
+  'SHARED_LIB_PREFIX': 'lib',
+  'STATIC_LIB_SUFFIX': '.a',
+  'INTERMEDIATE_DIR': '$(obj).$(TOOLSET)/$(TARGET)/geni',
+  'SHARED_INTERMEDIATE_DIR': '$(obj)/gen',
+  'PRODUCT_DIR': '$(builddir)',
+  'RULE_INPUT_ROOT': '%(INPUT_ROOT)s',  # This gets expanded by Python.
+  'RULE_INPUT_DIRNAME': '%(INPUT_DIRNAME)s',  # This gets expanded by Python.
+  'RULE_INPUT_PATH': '$(abspath $<)',
+  'RULE_INPUT_EXT': '$(suffix $<)',
+  'RULE_INPUT_NAME': '$(notdir $<)',
+  'CONFIGURATION_NAME': '$(BUILDTYPE)',
+}
+
+# Make supports multiple toolsets
+generator_supports_multiple_toolsets = True
+
+# Request sorted dependencies in the order from dependents to dependencies.
+generator_wants_sorted_dependencies = False
+
+# Placates pylint.
+generator_additional_non_configuration_keys = []
+generator_additional_path_sections = []
+generator_extra_sources_for_rules = []
+
+
+def CalculateVariables(default_variables, params):
+  """Calculate additional variables for use in the build (called by gyp)."""
+  flavor = gyp.common.GetFlavor(params)
+  if flavor == 'mac':
+    default_variables.setdefault('OS', 'mac')
+    default_variables.setdefault('SHARED_LIB_SUFFIX', '.dylib')
+    default_variables.setdefault('SHARED_LIB_DIR',
+                                 generator_default_variables['PRODUCT_DIR'])
+    default_variables.setdefault('LIB_DIR',
+                                 generator_default_variables['PRODUCT_DIR'])
+
+    # Copy additional generator configuration data from Xcode, which is shared
+    # by the Mac Make generator.
+    import gyp.generator.xcode as xcode_generator
+    global generator_additional_non_configuration_keys
+    generator_additional_non_configuration_keys = getattr(xcode_generator,
+        'generator_additional_non_configuration_keys', [])
+    global generator_additional_path_sections
+    generator_additional_path_sections = getattr(xcode_generator,
+        'generator_additional_path_sections', [])
+    global generator_extra_sources_for_rules
+    generator_extra_sources_for_rules = getattr(xcode_generator,
+        'generator_extra_sources_for_rules', [])
+    COMPILABLE_EXTENSIONS.update({'.m': 'objc', '.mm' : 'objcxx'})
+  else:
+    operating_system = flavor
+    if flavor == 'android':
+      operating_system = 'linux'  # Keep this legacy behavior for now.
+    default_variables.setdefault('OS', operating_system)
+    default_variables.setdefault('SHARED_LIB_SUFFIX', '.so')
+    default_variables.setdefault('SHARED_LIB_DIR','$(builddir)/lib.$(TOOLSET)')
+    default_variables.setdefault('LIB_DIR', '$(obj).$(TOOLSET)')
+
+
+def CalculateGeneratorInputInfo(params):
+  """Calculate the generator specific info that gets fed to input (called by
+  gyp)."""
+  generator_flags = params.get('generator_flags', {})
+  android_ndk_version = generator_flags.get('android_ndk_version', None)
+  # Android NDK requires a strict link order.
+  if android_ndk_version:
+    global generator_wants_sorted_dependencies
+    generator_wants_sorted_dependencies = True
+
+
+def ensure_directory_exists(path):
+  dir = os.path.dirname(path)
+  if dir and not os.path.exists(dir):
+    os.makedirs(dir)
+
+
+# The .d checking code below uses these functions:
+# wildcard, sort, foreach, shell, wordlist
+# wildcard can handle spaces, the rest can't.
+# Since I could find no way to make foreach work with spaces in filenames
+# correctly, the .d files have spaces replaced with another character. The .d
+# file for
+#     Chromium\ Framework.framework/foo
+# is for example
+#     out/Release/.deps/out/Release/Chromium?Framework.framework/foo
+# This is the replacement character.
+SPACE_REPLACEMENT = '?'
+
+
+LINK_COMMANDS_LINUX = """\
+quiet_cmd_alink = AR($(TOOLSET)) $@
+cmd_alink = rm -f $@ && $(AR.$(TOOLSET)) crs $@ $(filter %.o,$^)
+
+quiet_cmd_alink_thin = AR($(TOOLSET)) $@
+cmd_alink_thin = rm -f $@ && $(AR.$(TOOLSET)) crsT $@ $(filter %.o,$^)
+
+# Due to circular dependencies between libraries :(, we wrap the
+# special "figure out circular dependencies" flags around the entire
+# input list during linking.
+quiet_cmd_link = LINK($(TOOLSET)) $@
+cmd_link = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ -Wl,--start-group $(LD_INPUTS) -Wl,--end-group $(LIBS)
+
+# We support two kinds of shared objects (.so):
+# 1) shared_library, which is just bundling together many dependent libraries
+# into a link line.
+# 2) loadable_module, which is generating a module intended for dlopen().
+#
+# They differ only slightly:
+# In the former case, we want to package all dependent code into the .so.
+# In the latter case, we want to package just the API exposed by the
+# outermost module.
+# This means shared_library uses --whole-archive, while loadable_module doesn't.
+# (Note that --whole-archive is incompatible with the --start-group used in
+# normal linking.)
+
+# Other shared-object link notes:
+# - Set SONAME to the library filename so our binaries don't reference
+# the local, absolute paths used on the link command-line.
+quiet_cmd_solink = SOLINK($(TOOLSET)) $@
+cmd_solink = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--whole-archive $(LD_INPUTS) -Wl,--no-whole-archive $(LIBS)
+
+quiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@
+cmd_solink_module = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--start-group $(filter-out FORCE_DO_CMD, $^) -Wl,--end-group $(LIBS)
+"""
+
+LINK_COMMANDS_MAC = """\
+quiet_cmd_alink = LIBTOOL-STATIC $@
+cmd_alink = rm -f $@ && ./gyp-mac-tool filter-libtool libtool $(GYP_LIBTOOLFLAGS) -static -o $@ $(filter %.o,$^)
+
+quiet_cmd_link = LINK($(TOOLSET)) $@
+cmd_link = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o "$@" $(LD_INPUTS) $(LIBS)
+
+# TODO(thakis): Find out and document the difference between shared_library and
+# loadable_module on mac.
+quiet_cmd_solink = SOLINK($(TOOLSET)) $@
+cmd_solink = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o "$@" $(LD_INPUTS) $(LIBS)
+
+# TODO(thakis): The solink_module rule is likely wrong. Xcode seems to pass
+# -bundle -single_module here (for osmesa.so).
+quiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@
+cmd_solink_module = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ $(filter-out FORCE_DO_CMD, $^) $(LIBS)
+"""
+
+LINK_COMMANDS_ANDROID = """\
+quiet_cmd_alink = AR($(TOOLSET)) $@
+cmd_alink = rm -f $@ && $(AR.$(TOOLSET)) crs $@ $(filter %.o,$^)
+
+quiet_cmd_alink_thin = AR($(TOOLSET)) $@
+cmd_alink_thin = rm -f $@ && $(AR.$(TOOLSET)) crsT $@ $(filter %.o,$^)
+
+# Due to circular dependencies between libraries :(, we wrap the
+# special "figure out circular dependencies" flags around the entire
+# input list during linking.
+quiet_cmd_link = LINK($(TOOLSET)) $@
+quiet_cmd_link_host = LINK($(TOOLSET)) $@
+cmd_link = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ -Wl,--start-group $(LD_INPUTS) -Wl,--end-group $(LIBS)
+cmd_link_host = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ $(LD_INPUTS) $(LIBS)
+
+# Other shared-object link notes:
+# - Set SONAME to the library filename so our binaries don't reference
+# the local, absolute paths used on the link command-line.
+quiet_cmd_solink = SOLINK($(TOOLSET)) $@
+cmd_solink = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--whole-archive $(LD_INPUTS) -Wl,--no-whole-archive $(LIBS)
+
+quiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@
+cmd_solink_module = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--start-group $(filter-out FORCE_DO_CMD, $^) -Wl,--end-group $(LIBS)
+quiet_cmd_solink_module_host = SOLINK_MODULE($(TOOLSET)) $@
+cmd_solink_module_host = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ $(filter-out FORCE_DO_CMD, $^) $(LIBS)
+"""
+
+
+# Header of toplevel Makefile.
+# This should go into the build tree, but it's easier to keep it here for now.
+SHARED_HEADER = ("""\
+# We borrow heavily from the kernel build setup, though we are simpler since
+# we don't have Kconfig tweaking settings on us.
+
+# The implicit make rules have it looking for RCS files, among other things.
+# We instead explicitly write all the rules we care about.
+# It's even quicker (saves ~200ms) to pass -r on the command line.
+MAKEFLAGS=-r
+
+# The source directory tree.
+srcdir := %(srcdir)s
+abs_srcdir := $(abspath $(srcdir))
+
+# The name of the builddir.
+builddir_name ?= %(builddir)s
+
+# The V=1 flag on command line makes us verbosely print command lines.
+ifdef V
+  quiet=
+else
+  quiet=quiet_
+endif
+
+# Specify BUILDTYPE=Release on the command line for a release build.
+BUILDTYPE ?= %(default_configuration)s
+
+# Directory all our build output goes into.
+# Note that this must be two directories beneath src/ for unit tests to pass,
+# as they reach into the src/ directory for data with relative paths.
+builddir ?= $(builddir_name)/$(BUILDTYPE)
+abs_builddir := $(abspath $(builddir))
+depsdir := $(builddir)/.deps
+
+# Object output directory.
+obj := $(builddir)/obj
+abs_obj := $(abspath $(obj))
+
+# We build up a list of every single one of the targets so we can slurp in the
+# generated dependency rule Makefiles in one pass.
+all_deps :=
+
+%(make_global_settings)s
+
+# C++ apps need to be linked with g++.
+#
+# Note: flock is used to seralize linking. Linking is a memory-intensive
+# process so running parallel links can often lead to thrashing.  To disable
+# the serialization, override LINK via an envrionment variable as follows:
+#
+#   export LINK=g++
+#
+# This will allow make to invoke N linker processes as specified in -jN.
+LINK ?= %(flock)s $(builddir)/linker.lock $(CXX.target)
+
+CC.target ?= %(CC.target)s
+CFLAGS.target ?= $(CFLAGS)
+CXX.target ?= %(CXX.target)s
+CXXFLAGS.target ?= $(CXXFLAGS)
+LINK.target ?= %(LINK.target)s
+LDFLAGS.target ?= $(LDFLAGS)
+AR.target ?= $(AR)
+
+# TODO(evan): move all cross-compilation logic to gyp-time so we don't need
+# to replicate this environment fallback in make as well.
+CC.host ?= %(CC.host)s
+CFLAGS.host ?=
+CXX.host ?= %(CXX.host)s
+CXXFLAGS.host ?=
+LINK.host ?= %(LINK.host)s
+LDFLAGS.host ?=
+AR.host ?= %(AR.host)s
+
+# Define a dir function that can handle spaces.
+# http://www.gnu.org/software/make/manual/make.html#Syntax-of-Functions
+# "leading spaces cannot appear in the text of the first argument as written.
+# These characters can be put into the argument value by variable substitution."
+empty :=
+space := $(empty) $(empty)
+
+# http://stackoverflow.com/questions/1189781/using-make-dir-or-notdir-on-a-path-with-spaces
+replace_spaces = $(subst $(space),""" + SPACE_REPLACEMENT + """,$1)
+unreplace_spaces = $(subst """ + SPACE_REPLACEMENT + """,$(space),$1)
+dirx = $(call unreplace_spaces,$(dir $(call replace_spaces,$1)))
+
+# Flags to make gcc output dependency info.  Note that you need to be
+# careful here to use the flags that ccache and distcc can understand.
+# We write to a dep file on the side first and then rename at the end
+# so we can't end up with a broken dep file.
+depfile = $(depsdir)/$(call replace_spaces,$@).d
+DEPFLAGS = -MMD -MF $(depfile).raw
+
+# We have to fixup the deps output in a few ways.
+# (1) the file output should mention the proper .o file.
+# ccache or distcc lose the path to the target, so we convert a rule of
+# the form:
+#   foobar.o: DEP1 DEP2
+# into
+#   path/to/foobar.o: DEP1 DEP2
+# (2) we want missing files not to cause us to fail to build.
+# We want to rewrite
+#   foobar.o: DEP1 DEP2 \\
+#               DEP3
+# to
+#   DEP1:
+#   DEP2:
+#   DEP3:
+# so if the files are missing, they're just considered phony rules.
+# We have to do some pretty insane escaping to get those backslashes
+# and dollar signs past make, the shell, and sed at the same time.
+# Doesn't work with spaces, but that's fine: .d files have spaces in
+# their names replaced with other characters."""
+r"""
+define fixup_dep
+# The depfile may not exist if the input file didn't have any #includes.
+touch $(depfile).raw
+# Fixup path as in (1).
+sed -e "s|^$(notdir $@)|$@|" $(depfile).raw >> $(depfile)
+# Add extra rules as in (2).
+# We remove slashes and replace spaces with new lines;
+# remove blank lines;
+# delete the first line and append a colon to the remaining lines.
+sed -e 's|\\||' -e 'y| |\n|' $(depfile).raw |\
+  grep -v '^$$'                             |\
+  sed -e 1d -e 's|$$|:|'                     \
+    >> $(depfile)
+rm $(depfile).raw
+endef
+"""
+"""
+# Command definitions:
+# - cmd_foo is the actual command to run;
+# - quiet_cmd_foo is the brief-output summary of the command.
+
+quiet_cmd_cc = CC($(TOOLSET)) $@
+cmd_cc = $(CC.$(TOOLSET)) $(GYP_CFLAGS) $(DEPFLAGS) $(CFLAGS.$(TOOLSET)) -c -o $@ $<
+
+quiet_cmd_cxx = CXX($(TOOLSET)) $@
+cmd_cxx = $(CXX.$(TOOLSET)) $(GYP_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $<
+%(extra_commands)s
+quiet_cmd_touch = TOUCH $@
+cmd_touch = touch $@
+
+quiet_cmd_copy = COPY $@
+# send stderr to /dev/null to ignore messages when linking directories.
+cmd_copy = ln -f "$<" "$@" 2>/dev/null || (rm -rf "$@" && cp -af "$<" "$@")
+
+%(link_commands)s
+"""
+
+r"""
+# Define an escape_quotes function to escape single quotes.
+# This allows us to handle quotes properly as long as we always use
+# use single quotes and escape_quotes.
+escape_quotes = $(subst ','\'',$(1))
+# This comment is here just to include a ' to unconfuse syntax highlighting.
+# Define an escape_vars function to escape '$' variable syntax.
+# This allows us to read/write command lines with shell variables (e.g.
+# $LD_LIBRARY_PATH), without triggering make substitution.
+escape_vars = $(subst $$,$$$$,$(1))
+# Helper that expands to a shell command to echo a string exactly as it is in
+# make. This uses printf instead of echo because printf's behaviour with respect
+# to escape sequences is more portable than echo's across different shells
+# (e.g., dash, bash).
+exact_echo = printf '%%s\n' '$(call escape_quotes,$(1))'
+"""
+"""
+# Helper to compare the command we're about to run against the command
+# we logged the last time we ran the command.  Produces an empty
+# string (false) when the commands match.
+# Tricky point: Make has no string-equality test function.
+# The kernel uses the following, but it seems like it would have false
+# positives, where one string reordered its arguments.
+#   arg_check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) \\
+#                       $(filter-out $(cmd_$@), $(cmd_$(1))))
+# We instead substitute each for the empty string into the other, and
+# say they're equal if both substitutions produce the empty string.
+# .d files contain """ + SPACE_REPLACEMENT + \
+                   """ instead of spaces, take that into account.
+command_changed = $(or $(subst $(cmd_$(1)),,$(cmd_$(call replace_spaces,$@))),\\
+                       $(subst $(cmd_$(call replace_spaces,$@)),,$(cmd_$(1))))
+
+# Helper that is non-empty when a prerequisite changes.
+# Normally make does this implicitly, but we force rules to always run
+# so we can check their command lines.
+#   $? -- new prerequisites
+#   $| -- order-only dependencies
+prereq_changed = $(filter-out FORCE_DO_CMD,$(filter-out $|,$?))
+
+# Helper that executes all postbuilds until one fails.
+define do_postbuilds
+  @E=0;\\
+  for p in $(POSTBUILDS); do\\
+    eval $$p;\\
+    E=$$?;\\
+    if [ $$E -ne 0 ]; then\\
+      break;\\
+    fi;\\
+  done;\\
+  if [ $$E -ne 0 ]; then\\
+    rm -rf "$@";\\
+    exit $$E;\\
+  fi
+endef
+
+# do_cmd: run a command via the above cmd_foo names, if necessary.
+# Should always run for a given target to handle command-line changes.
+# Second argument, if non-zero, makes it do asm/C/C++ dependency munging.
+# Third argument, if non-zero, makes it do POSTBUILDS processing.
+# Note: We intentionally do NOT call dirx for depfile, since it contains """ + \
+                                                     SPACE_REPLACEMENT + """ for
+# spaces already and dirx strips the """ + SPACE_REPLACEMENT + \
+                                     """ characters.
+define do_cmd
+$(if $(or $(command_changed),$(prereq_changed)),
+  @$(call exact_echo,  $($(quiet)cmd_$(1)))
+  @mkdir -p "$(call dirx,$@)" "$(dir $(depfile))"
+  $(if $(findstring flock,$(word %(flock_index)d,$(cmd_$1))),
+    @$(cmd_$(1))
+    @echo "  $(quiet_cmd_$(1)): Finished",
+    @$(cmd_$(1))
+  )
+  @$(call exact_echo,$(call escape_vars,cmd_$(call replace_spaces,$@) := $(cmd_$(1)))) > $(depfile)
+  @$(if $(2),$(fixup_dep))
+  $(if $(and $(3), $(POSTBUILDS)),
+    $(call do_postbuilds)
+  )
+)
+endef
+
+# Declare the "%(default_target)s" target first so it is the default,
+# even though we don't have the deps yet.
+.PHONY: %(default_target)s
+%(default_target)s:
+
+# make looks for ways to re-generate included makefiles, but in our case, we
+# don't have a direct way. Explicitly telling make that it has nothing to do
+# for them makes it go faster.
+%%.d: ;
+
+# Use FORCE_DO_CMD to force a target to run.  Should be coupled with
+# do_cmd.
+.PHONY: FORCE_DO_CMD
+FORCE_DO_CMD:
+
+""")
+
+SHARED_HEADER_MAC_COMMANDS = """
+quiet_cmd_objc = CXX($(TOOLSET)) $@
+cmd_objc = $(CC.$(TOOLSET)) $(GYP_OBJCFLAGS) $(DEPFLAGS) -c -o $@ $<
+
+quiet_cmd_objcxx = CXX($(TOOLSET)) $@
+cmd_objcxx = $(CXX.$(TOOLSET)) $(GYP_OBJCXXFLAGS) $(DEPFLAGS) -c -o $@ $<
+
+# Commands for precompiled header files.
+quiet_cmd_pch_c = CXX($(TOOLSET)) $@
+cmd_pch_c = $(CC.$(TOOLSET)) $(GYP_PCH_CFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $<
+quiet_cmd_pch_cc = CXX($(TOOLSET)) $@
+cmd_pch_cc = $(CC.$(TOOLSET)) $(GYP_PCH_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $<
+quiet_cmd_pch_m = CXX($(TOOLSET)) $@
+cmd_pch_m = $(CC.$(TOOLSET)) $(GYP_PCH_OBJCFLAGS) $(DEPFLAGS) -c -o $@ $<
+quiet_cmd_pch_mm = CXX($(TOOLSET)) $@
+cmd_pch_mm = $(CC.$(TOOLSET)) $(GYP_PCH_OBJCXXFLAGS) $(DEPFLAGS) -c -o $@ $<
+
+# gyp-mac-tool is written next to the root Makefile by gyp.
+# Use $(4) for the command, since $(2) and $(3) are used as flag by do_cmd
+# already.
+quiet_cmd_mac_tool = MACTOOL $(4) $<
+cmd_mac_tool = ./gyp-mac-tool $(4) $< "$@"
+
+quiet_cmd_mac_package_framework = PACKAGE FRAMEWORK $@
+cmd_mac_package_framework = ./gyp-mac-tool package-framework "$@" $(4)
+
+quiet_cmd_infoplist = INFOPLIST $@
+cmd_infoplist = $(CC.$(TOOLSET)) -E -P -Wno-trigraphs -x c $(INFOPLIST_DEFINES) "$<" -o "$@"
+"""
+
+SHARED_HEADER_SUN_COMMANDS = """
+# gyp-sun-tool is written next to the root Makefile by gyp.
+# Use $(4) for the command, since $(2) and $(3) are used as flag by do_cmd
+# already.
+quiet_cmd_sun_tool = SUNTOOL $(4) $<
+cmd_sun_tool = ./gyp-sun-tool $(4) $< "$@"
+"""
+
+
+def WriteRootHeaderSuffixRules(writer):
+  extensions = sorted(COMPILABLE_EXTENSIONS.keys(), key=str.lower)
+
+  writer.write('# Suffix rules, putting all outputs into $(obj).\n')
+  for ext in extensions:
+    writer.write('$(obj).$(TOOLSET)/%%.o: $(srcdir)/%%%s FORCE_DO_CMD\n' % ext)
+    writer.write('\t@$(call do_cmd,%s,1)\n' % COMPILABLE_EXTENSIONS[ext])
+
+  writer.write('\n# Try building from generated source, too.\n')
+  for ext in extensions:
+    writer.write(
+        '$(obj).$(TOOLSET)/%%.o: $(obj).$(TOOLSET)/%%%s FORCE_DO_CMD\n' % ext)
+    writer.write('\t@$(call do_cmd,%s,1)\n' % COMPILABLE_EXTENSIONS[ext])
+  writer.write('\n')
+  for ext in extensions:
+    writer.write('$(obj).$(TOOLSET)/%%.o: $(obj)/%%%s FORCE_DO_CMD\n' % ext)
+    writer.write('\t@$(call do_cmd,%s,1)\n' % COMPILABLE_EXTENSIONS[ext])
+  writer.write('\n')
+
+
+SHARED_HEADER_SUFFIX_RULES_COMMENT1 = ("""\
+# Suffix rules, putting all outputs into $(obj).
+""")
+
+
+SHARED_HEADER_SUFFIX_RULES_COMMENT2 = ("""\
+# Try building from generated source, too.
+""")
+
+
+SHARED_FOOTER = """\
+# "all" is a concatenation of the "all" targets from all the included
+# sub-makefiles. This is just here to clarify.
+all:
+
+# Add in dependency-tracking rules.  $(all_deps) is the list of every single
+# target in our tree. Only consider the ones with .d (dependency) info:
+d_files := $(wildcard $(foreach f,$(all_deps),$(depsdir)/$(f).d))
+ifneq ($(d_files),)
+  include $(d_files)
+endif
+"""
+
+header = """\
+# This file is generated by gyp; do not edit.
+
+"""
+
+# Maps every compilable file extension to the do_cmd that compiles it.
+COMPILABLE_EXTENSIONS = {
+  '.c': 'cc',
+  '.cc': 'cxx',
+  '.cpp': 'cxx',
+  '.cxx': 'cxx',
+  '.s': 'cc',
+  '.S': 'cc',
+}
+
+def Compilable(filename):
+  """Return true if the file is compilable (should be in OBJS)."""
+  for res in (filename.endswith(e) for e in COMPILABLE_EXTENSIONS):
+    if res:
+      return True
+  return False
+
+
+def Linkable(filename):
+  """Return true if the file is linkable (should be on the link line)."""
+  return filename.endswith('.o')
+
+
+def Target(filename):
+  """Translate a compilable filename to its .o target."""
+  return os.path.splitext(filename)[0] + '.o'
+
+
+def EscapeShellArgument(s):
+  """Quotes an argument so that it will be interpreted literally by a POSIX
+     shell. Taken from
+     http://stackoverflow.com/questions/35817/whats-the-best-way-to-escape-ossystem-calls-in-python
+     """
+  return "'" + s.replace("'", "'\\''") + "'"
+
+
+def EscapeMakeVariableExpansion(s):
+  """Make has its own variable expansion syntax using $. We must escape it for
+     string to be interpreted literally."""
+  return s.replace('$', '$$')
+
+
+def EscapeCppDefine(s):
+  """Escapes a CPP define so that it will reach the compiler unaltered."""
+  s = EscapeShellArgument(s)
+  s = EscapeMakeVariableExpansion(s)
+  # '#' characters must be escaped even embedded in a string, else Make will
+  # treat it as the start of a comment.
+  return s.replace('#', r'\#')
+
+
+def QuoteIfNecessary(string):
+  """TODO: Should this ideally be replaced with one or more of the above
+     functions?"""
+  if '"' in string:
+    string = '"' + string.replace('"', '\\"') + '"'
+  return string
+
+
+def StringToMakefileVariable(string):
+  """Convert a string to a value that is acceptable as a make variable name."""
+  return re.sub('[^a-zA-Z0-9_]', '_', string)
+
+
+srcdir_prefix = ''
+def Sourceify(path):
+  """Convert a path to its source directory form."""
+  if '$(' in path:
+    return path
+  if os.path.isabs(path):
+    return path
+  return srcdir_prefix + path
+
+
+def QuoteSpaces(s, quote=r'\ '):
+  return s.replace(' ', quote)
+
+
+# Map from qualified target to path to output.
+target_outputs = {}
+# Map from qualified target to any linkable output.  A subset
+# of target_outputs.  E.g. when mybinary depends on liba, we want to
+# include liba in the linker line; when otherbinary depends on
+# mybinary, we just want to build mybinary first.
+target_link_deps = {}
+
+
+class MakefileWriter:
+  """MakefileWriter packages up the writing of one target-specific foobar.mk.
+
+  Its only real entry point is Write(), and is mostly used for namespacing.
+  """
+
+  def __init__(self, generator_flags, flavor):
+    self.generator_flags = generator_flags
+    self.flavor = flavor
+
+    self.suffix_rules_srcdir = {}
+    self.suffix_rules_objdir1 = {}
+    self.suffix_rules_objdir2 = {}
+
+    # Generate suffix rules for all compilable extensions.
+    for ext in COMPILABLE_EXTENSIONS.keys():
+      # Suffix rules for source folder.
+      self.suffix_rules_srcdir.update({ext: ("""\
+$(obj).$(TOOLSET)/$(TARGET)/%%.o: $(srcdir)/%%%s FORCE_DO_CMD
+       @$(call do_cmd,%s,1)
+""" % (ext, COMPILABLE_EXTENSIONS[ext]))})
+
+      # Suffix rules for generated source files.
+      self.suffix_rules_objdir1.update({ext: ("""\
+$(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj).$(TOOLSET)/%%%s FORCE_DO_CMD
+       @$(call do_cmd,%s,1)
+""" % (ext, COMPILABLE_EXTENSIONS[ext]))})
+      self.suffix_rules_objdir2.update({ext: ("""\
+$(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj)/%%%s FORCE_DO_CMD
+       @$(call do_cmd,%s,1)
+""" % (ext, COMPILABLE_EXTENSIONS[ext]))})
+
+
+  def Write(self, qualified_target, base_path, output_filename, spec, configs,
+            part_of_all):
+    """The main entry point: writes a .mk file for a single target.
+
+    Arguments:
+      qualified_target: target we're generating
+      base_path: path relative to source root we're building in, used to resolve
+                 target-relative paths
+      output_filename: output .mk file name to write
+      spec, configs: gyp info
+      part_of_all: flag indicating this target is part of 'all'
+    """
+    ensure_directory_exists(output_filename)
+
+    self.fp = open(output_filename, 'w')
+
+    self.fp.write(header)
+
+    self.qualified_target = qualified_target
+    self.path = base_path
+    self.target = spec['target_name']
+    self.type = spec['type']
+    self.toolset = spec['toolset']
+
+    self.is_mac_bundle = gyp.xcode_emulation.IsMacBundle(self.flavor, spec)
+    if self.flavor == 'mac':
+      self.xcode_settings = gyp.xcode_emulation.XcodeSettings(spec)
+    else:
+      self.xcode_settings = None
+
+    deps, link_deps = self.ComputeDeps(spec)
+
+    # Some of the generation below can add extra output, sources, or
+    # link dependencies.  All of the out params of the functions that
+    # follow use names like extra_foo.
+    extra_outputs = []
+    extra_sources = []
+    extra_link_deps = []
+    extra_mac_bundle_resources = []
+    mac_bundle_deps = []
+
+    if self.is_mac_bundle:
+      self.output = self.ComputeMacBundleOutput(spec)
+      self.output_binary = self.ComputeMacBundleBinaryOutput(spec)
+    else:
+      self.output = self.output_binary = self.ComputeOutput(spec)
+
+    self.is_standalone_static_library = bool(
+        spec.get('standalone_static_library', 0))
+    self._INSTALLABLE_TARGETS = ('executable', 'loadable_module',
+                                 'shared_library')
+    if (self.is_standalone_static_library or
+        self.type in self._INSTALLABLE_TARGETS):
+      self.alias = os.path.basename(self.output)
+      install_path = self._InstallableTargetInstallPath()
+    else:
+      self.alias = self.output
+      install_path = self.output
+
+    self.WriteLn("TOOLSET := " + self.toolset)
+    self.WriteLn("TARGET := " + self.target)
+
+    # Actions must come first, since they can generate more OBJs for use below.
+    if 'actions' in spec:
+      self.WriteActions(spec['actions'], extra_sources, extra_outputs,
+                        extra_mac_bundle_resources, part_of_all)
+
+    # Rules must be early like actions.
+    if 'rules' in spec:
+      self.WriteRules(spec['rules'], extra_sources, extra_outputs,
+                      extra_mac_bundle_resources, part_of_all)
+
+    if 'copies' in spec:
+      self.WriteCopies(spec['copies'], extra_outputs, part_of_all)
+
+    # Bundle resources.
+    if self.is_mac_bundle:
+      all_mac_bundle_resources = (
+          spec.get('mac_bundle_resources', []) + extra_mac_bundle_resources)
+      self.WriteMacBundleResources(all_mac_bundle_resources, mac_bundle_deps)
+      self.WriteMacInfoPlist(mac_bundle_deps)
+
+    # Sources.
+    all_sources = spec.get('sources', []) + extra_sources
+    if all_sources:
+      self.WriteSources(
+          configs, deps, all_sources, extra_outputs,
+          extra_link_deps, part_of_all,
+          gyp.xcode_emulation.MacPrefixHeader(
+              self.xcode_settings, lambda p: Sourceify(self.Absolutify(p)),
+              self.Pchify))
+      sources = filter(Compilable, all_sources)
+      if sources:
+        self.WriteLn(SHARED_HEADER_SUFFIX_RULES_COMMENT1)
+        extensions = set([os.path.splitext(s)[1] for s in sources])
+        for ext in extensions:
+          if ext in self.suffix_rules_srcdir:
+            self.WriteLn(self.suffix_rules_srcdir[ext])
+        self.WriteLn(SHARED_HEADER_SUFFIX_RULES_COMMENT2)
+        for ext in extensions:
+          if ext in self.suffix_rules_objdir1:
+            self.WriteLn(self.suffix_rules_objdir1[ext])
+        for ext in extensions:
+          if ext in self.suffix_rules_objdir2:
+            self.WriteLn(self.suffix_rules_objdir2[ext])
+        self.WriteLn('# End of this set of suffix rules')
+
+        # Add dependency from bundle to bundle binary.
+        if self.is_mac_bundle:
+          mac_bundle_deps.append(self.output_binary)
+
+    self.WriteTarget(spec, configs, deps, extra_link_deps + link_deps,
+                     mac_bundle_deps, extra_outputs, part_of_all)
+
+    # Update global list of target outputs, used in dependency tracking.
+    target_outputs[qualified_target] = install_path
+
+    # Update global list of link dependencies.
+    if self.type in ('static_library', 'shared_library'):
+      target_link_deps[qualified_target] = self.output_binary
+
+    # Currently any versions have the same effect, but in future the behavior
+    # could be different.
+    if self.generator_flags.get('android_ndk_version', None):
+      self.WriteAndroidNdkModuleRule(self.target, all_sources, link_deps)
+
+    self.fp.close()
+
+
+  def WriteSubMake(self, output_filename, makefile_path, targets, build_dir):
+    """Write a "sub-project" Makefile.
+
+    This is a small, wrapper Makefile that calls the top-level Makefile to build
+    the targets from a single gyp file (i.e. a sub-project).
+
+    Arguments:
+      output_filename: sub-project Makefile name to write
+      makefile_path: path to the top-level Makefile
+      targets: list of "all" targets for this sub-project
+      build_dir: build output directory, relative to the sub-project
+    """
+    ensure_directory_exists(output_filename)
+    self.fp = open(output_filename, 'w')
+    self.fp.write(header)
+    # For consistency with other builders, put sub-project build output in the
+    # sub-project dir (see test/subdirectory/gyptest-subdir-all.py).
+    self.WriteLn('export builddir_name ?= %s' %
+                 os.path.join(os.path.dirname(output_filename), build_dir))
+    self.WriteLn('.PHONY: all')
+    self.WriteLn('all:')
+    if makefile_path:
+      makefile_path = ' -C ' + makefile_path
+    self.WriteLn('\t$(MAKE)%s %s' % (makefile_path, ' '.join(targets)))
+    self.fp.close()
+
+
+  def WriteActions(self, actions, extra_sources, extra_outputs,
+                   extra_mac_bundle_resources, part_of_all):
+    """Write Makefile code for any 'actions' from the gyp input.
+
+    extra_sources: a list that will be filled in with newly generated source
+                   files, if any
+    extra_outputs: a list that will be filled in with any outputs of these
+                   actions (used to make other pieces dependent on these
+                   actions)
+    part_of_all: flag indicating this target is part of 'all'
+    """
+    env = self.GetSortedXcodeEnv()
+    for action in actions:
+      name = StringToMakefileVariable('%s_%s' % (self.qualified_target,
+                                                 action['action_name']))
+      self.WriteLn('### Rules for action "%s":' % action['action_name'])
+      inputs = action['inputs']
+      outputs = action['outputs']
+
+      # Build up a list of outputs.
+      # Collect the output dirs we'll need.
+      dirs = set()
+      for out in outputs:
+        dir = os.path.split(out)[0]
+        if dir:
+          dirs.add(dir)
+      if int(action.get('process_outputs_as_sources', False)):
+        extra_sources += outputs
+      if int(action.get('process_outputs_as_mac_bundle_resources', False)):
+        extra_mac_bundle_resources += outputs
+
+      # Write the actual command.
+      action_commands = action['action']
+      if self.flavor == 'mac':
+        action_commands = [gyp.xcode_emulation.ExpandEnvVars(command, env)
+                          for command in action_commands]
+      command = gyp.common.EncodePOSIXShellList(action_commands)
+      if 'message' in action:
+        self.WriteLn('quiet_cmd_%s = ACTION %s $@' % (name, action['message']))
+      else:
+        self.WriteLn('quiet_cmd_%s = ACTION %s $@' % (name, name))
+      if len(dirs) > 0:
+        command = 'mkdir -p %s' % ' '.join(dirs) + '; ' + command
+
+      cd_action = 'cd %s; ' % Sourceify(self.path or '.')
+
+      # command and cd_action get written to a toplevel variable called
+      # cmd_foo. Toplevel variables can't handle things that change per
+      # makefile like $(TARGET), so hardcode the target.
+      command = command.replace('$(TARGET)', self.target)
+      cd_action = cd_action.replace('$(TARGET)', self.target)
+
+      # Set LD_LIBRARY_PATH in case the action runs an executable from this
+      # build which links to shared libs from this build.
+      # actions run on the host, so they should in theory only use host
+      # libraries, but until everything is made cross-compile safe, also use
+      # target libraries.
+      # TODO(piman): when everything is cross-compile safe, remove lib.target
+      self.WriteLn('cmd_%s = LD_LIBRARY_PATH=$(builddir)/lib.host:'
+                   '$(builddir)/lib.target:$$LD_LIBRARY_PATH; '
+                   'export LD_LIBRARY_PATH; '
+                   '%s%s'
+                   % (name, cd_action, command))
+      self.WriteLn()
+      outputs = map(self.Absolutify, outputs)
+      # The makefile rules are all relative to the top dir, but the gyp actions
+      # are defined relative to their containing dir.  This replaces the obj
+      # variable for the action rule with an absolute version so that the output
+      # goes in the right place.
+      # Only write the 'obj' and 'builddir' rules for the "primary" output (:1);
+      # it's superfluous for the "extra outputs", and this avoids accidentally
+      # writing duplicate dummy rules for those outputs.
+      # Same for environment.
+      self.WriteLn("%s: obj := $(abs_obj)" % QuoteSpaces(outputs[0]))
+      self.WriteLn("%s: builddir := $(abs_builddir)" % QuoteSpaces(outputs[0]))
+      self.WriteSortedXcodeEnv(outputs[0], self.GetSortedXcodeEnv())
+
+      for input in inputs:
+        assert ' ' not in input, (
+            "Spaces in action input filenames not supported (%s)"  % input)
+      for output in outputs:
+        assert ' ' not in output, (
+            "Spaces in action output filenames not supported (%s)"  % output)
+
+      # See the comment in WriteCopies about expanding env vars.
+      outputs = [gyp.xcode_emulation.ExpandEnvVars(o, env) for o in outputs]
+      inputs = [gyp.xcode_emulation.ExpandEnvVars(i, env) for i in inputs]
+
+      self.WriteDoCmd(outputs, map(Sourceify, map(self.Absolutify, inputs)),
+                      part_of_all=part_of_all, command=name)
+
+      # Stuff the outputs in a variable so we can refer to them later.
+      outputs_variable = 'action_%s_outputs' % name
+      self.WriteLn('%s := %s' % (outputs_variable, ' '.join(outputs)))
+      extra_outputs.append('$(%s)' % outputs_variable)
+      self.WriteLn()
+
+    self.WriteLn()
+
+
+  def WriteRules(self, rules, extra_sources, extra_outputs,
+                 extra_mac_bundle_resources, part_of_all):
+    """Write Makefile code for any 'rules' from the gyp input.
+
+    extra_sources: a list that will be filled in with newly generated source
+                   files, if any
+    extra_outputs: a list that will be filled in with any outputs of these
+                   rules (used to make other pieces dependent on these rules)
+    part_of_all: flag indicating this target is part of 'all'
+    """
+    env = self.GetSortedXcodeEnv()
+    for rule in rules:
+      name = StringToMakefileVariable('%s_%s' % (self.qualified_target,
+                                                 rule['rule_name']))
+      count = 0
+      self.WriteLn('### Generated for rule %s:' % name)
+
+      all_outputs = []
+
+      for rule_source in rule.get('rule_sources', []):
+        dirs = set()
+        (rule_source_dirname, rule_source_basename) = os.path.split(rule_source)
+        (rule_source_root, rule_source_ext) = \
+            os.path.splitext(rule_source_basename)
+
+        outputs = [self.ExpandInputRoot(out, rule_source_root,
+                                        rule_source_dirname)
+                   for out in rule['outputs']]
+
+        for out in outputs:
+          dir = os.path.dirname(out)
+          if dir:
+            dirs.add(dir)
+        if int(rule.get('process_outputs_as_sources', False)):
+          extra_sources += outputs
+        if int(rule.get('process_outputs_as_mac_bundle_resources', False)):
+          extra_mac_bundle_resources += outputs
+        inputs = map(Sourceify, map(self.Absolutify, [rule_source] +
+                                    rule.get('inputs', [])))
+        actions = ['$(call do_cmd,%s_%d)' % (name, count)]
+
+        if name == 'resources_grit':
+          # HACK: This is ugly.  Grit intentionally doesn't touch the
+          # timestamp of its output file when the file doesn't change,
+          # which is fine in hash-based dependency systems like scons
+          # and forge, but not kosher in the make world.  After some
+          # discussion, hacking around it here seems like the least
+          # amount of pain.
+          actions += ['@touch --no-create $@']
+
+        # See the comment in WriteCopies about expanding env vars.
+        outputs = [gyp.xcode_emulation.ExpandEnvVars(o, env) for o in outputs]
+        inputs = [gyp.xcode_emulation.ExpandEnvVars(i, env) for i in inputs]
+
+        outputs = map(self.Absolutify, outputs)
+        all_outputs += outputs
+        # Only write the 'obj' and 'builddir' rules for the "primary" output
+        # (:1); it's superfluous for the "extra outputs", and this avoids
+        # accidentally writing duplicate dummy rules for those outputs.
+        self.WriteLn('%s: obj := $(abs_obj)' % outputs[0])
+        self.WriteLn('%s: builddir := $(abs_builddir)' % outputs[0])
+        self.WriteMakeRule(outputs, inputs + ['FORCE_DO_CMD'], actions)
+        for output in outputs:
+          assert ' ' not in output, (
+              "Spaces in rule filenames not yet supported (%s)"  % output)
+        self.WriteLn('all_deps += %s' % ' '.join(outputs))
+
+        action = [self.ExpandInputRoot(ac, rule_source_root,
+                                       rule_source_dirname)
+                  for ac in rule['action']]
+        mkdirs = ''
+        if len(dirs) > 0:
+          mkdirs = 'mkdir -p %s; ' % ' '.join(dirs)
+        cd_action = 'cd %s; ' % Sourceify(self.path or '.')
+
+        # action, cd_action, and mkdirs get written to a toplevel variable
+        # called cmd_foo. Toplevel variables can't handle things that change
+        # per makefile like $(TARGET), so hardcode the target.
+        if self.flavor == 'mac':
+          action = [gyp.xcode_emulation.ExpandEnvVars(command, env)
+                    for command in action]
+        action = gyp.common.EncodePOSIXShellList(action)
+        action = action.replace('$(TARGET)', self.target)
+        cd_action = cd_action.replace('$(TARGET)', self.target)
+        mkdirs = mkdirs.replace('$(TARGET)', self.target)
+
+        # Set LD_LIBRARY_PATH in case the rule runs an executable from this
+        # build which links to shared libs from this build.
+        # rules run on the host, so they should in theory only use host
+        # libraries, but until everything is made cross-compile safe, also use
+        # target libraries.
+        # TODO(piman): when everything is cross-compile safe, remove lib.target
+        self.WriteLn(
+            "cmd_%(name)s_%(count)d = LD_LIBRARY_PATH="
+              "$(builddir)/lib.host:$(builddir)/lib.target:$$LD_LIBRARY_PATH; "
+              "export LD_LIBRARY_PATH; "
+              "%(cd_action)s%(mkdirs)s%(action)s" % {
+          'action': action,
+          'cd_action': cd_action,
+          'count': count,
+          'mkdirs': mkdirs,
+          'name': name,
+        })
+        self.WriteLn(
+            'quiet_cmd_%(name)s_%(count)d = RULE %(name)s_%(count)d $@' % {
+          'count': count,
+          'name': name,
+        })
+        self.WriteLn()
+        count += 1
+
+      outputs_variable = 'rule_%s_outputs' % name
+      self.WriteList(all_outputs, outputs_variable)
+      extra_outputs.append('$(%s)' % outputs_variable)
+
+      self.WriteLn('### Finished generating for rule: %s' % name)
+      self.WriteLn()
+    self.WriteLn('### Finished generating for all rules')
+    self.WriteLn('')
+
+
+  def WriteCopies(self, copies, extra_outputs, part_of_all):
+    """Write Makefile code for any 'copies' from the gyp input.
+
+    extra_outputs: a list that will be filled in with any outputs of this action
+                   (used to make other pieces dependent on this action)
+    part_of_all: flag indicating this target is part of 'all'
+    """
+    self.WriteLn('### Generated for copy rule.')
+
+    variable = StringToMakefileVariable(self.qualified_target + '_copies')
+    outputs = []
+    for copy in copies:
+      for path in copy['files']:
+        # Absolutify() may call normpath, and will strip trailing slashes.
+        path = Sourceify(self.Absolutify(path))
+        filename = os.path.split(path)[1]
+        output = Sourceify(self.Absolutify(os.path.join(copy['destination'],
+                                                        filename)))
+
+        # If the output path has variables in it, which happens in practice for
+        # 'copies', writing the environment as target-local doesn't work,
+        # because the variables are already needed for the target name.
+        # Copying the environment variables into global make variables doesn't
+        # work either, because then the .d files will potentially contain spaces
+        # after variable expansion, and .d file handling cannot handle spaces.
+        # As a workaround, manually expand variables at gyp time. Since 'copies'
+        # can't run scripts, there's no need to write the env then.
+        # WriteDoCmd() will escape spaces for .d files.
+        env = self.GetSortedXcodeEnv()
+        output = gyp.xcode_emulation.ExpandEnvVars(output, env)
+        path = gyp.xcode_emulation.ExpandEnvVars(path, env)
+        self.WriteDoCmd([output], [path], 'copy', part_of_all)
+        outputs.append(output)
+    self.WriteLn('%s = %s' % (variable, ' '.join(map(QuoteSpaces, outputs))))
+    extra_outputs.append('$(%s)' % variable)
+    self.WriteLn()
+
+
+  def WriteMacBundleResources(self, resources, bundle_deps):
+    """Writes Makefile code for 'mac_bundle_resources'."""
+    self.WriteLn('### Generated for mac_bundle_resources')
+
+    for output, res in gyp.xcode_emulation.GetMacBundleResources(
+        generator_default_variables['PRODUCT_DIR'], self.xcode_settings,
+        map(Sourceify, map(self.Absolutify, resources))):
+      self.WriteDoCmd([output], [res], 'mac_tool,,,copy-bundle-resource',
+                      part_of_all=True)
+      bundle_deps.append(output)
+
+
+  def WriteMacInfoPlist(self, bundle_deps):
+    """Write Makefile code for bundle Info.plist files."""
+    info_plist, out, defines, extra_env = gyp.xcode_emulation.GetMacInfoPlist(
+        generator_default_variables['PRODUCT_DIR'], self.xcode_settings,
+        lambda p: Sourceify(self.Absolutify(p)))
+    if not info_plist:
+      return
+    if defines:
+      # Create an intermediate file to store preprocessed results.
+      intermediate_plist = ('$(obj).$(TOOLSET)/$(TARGET)/' +
+          os.path.basename(info_plist))
+      self.WriteList(defines, intermediate_plist + ': INFOPLIST_DEFINES', '-D',
+          quoter=EscapeCppDefine)
+      self.WriteMakeRule([intermediate_plist], [info_plist],
+          ['$(call do_cmd,infoplist)',
+           # "Convert" the plist so that any weird whitespace changes from the
+           # preprocessor do not affect the XML parser in mac_tool.
+           '@plutil -convert xml1 $@ $@'])
+      info_plist = intermediate_plist
+    # plists can contain envvars and substitute them into the file.
+    self.WriteSortedXcodeEnv(
+        out, self.GetSortedXcodeEnv(additional_settings=extra_env))
+    self.WriteDoCmd([out], [info_plist], 'mac_tool,,,copy-info-plist',
+                    part_of_all=True)
+    bundle_deps.append(out)
+
+
+  def WriteSources(self, configs, deps, sources,
+                   extra_outputs, extra_link_deps,
+                   part_of_all, precompiled_header):
+    """Write Makefile code for any 'sources' from the gyp input.
+    These are source files necessary to build the current target.
+
+    configs, deps, sources: input from gyp.
+    extra_outputs: a list of extra outputs this action should be dependent on;
+                   used to serialize action/rules before compilation
+    extra_link_deps: a list that will be filled in with any outputs of
+                     compilation (to be used in link lines)
+    part_of_all: flag indicating this target is part of 'all'
+    """
+
+    # Write configuration-specific variables for CFLAGS, etc.
+    for configname in sorted(configs.keys()):
+      config = configs[configname]
+      self.WriteList(config.get('defines'), 'DEFS_%s' % configname, prefix='-D',
+          quoter=EscapeCppDefine)
+
+      if self.flavor == 'mac':
+        cflags = self.xcode_settings.GetCflags(configname)
+        cflags_c = self.xcode_settings.GetCflagsC(configname)
+        cflags_cc = self.xcode_settings.GetCflagsCC(configname)
+        cflags_objc = self.xcode_settings.GetCflagsObjC(configname)
+        cflags_objcc = self.xcode_settings.GetCflagsObjCC(configname)
+      else:
+        cflags = config.get('cflags')
+        cflags_c = config.get('cflags_c')
+        cflags_cc = config.get('cflags_cc')
+
+      self.WriteLn("# Flags passed to all source files.");
+      self.WriteList(cflags, 'CFLAGS_%s' % configname)
+      self.WriteLn("# Flags passed to only C files.");
+      self.WriteList(cflags_c, 'CFLAGS_C_%s' % configname)
+      self.WriteLn("# Flags passed to only C++ files.");
+      self.WriteList(cflags_cc, 'CFLAGS_CC_%s' % configname)
+      if self.flavor == 'mac':
+        self.WriteLn("# Flags passed to only ObjC files.");
+        self.WriteList(cflags_objc, 'CFLAGS_OBJC_%s' % configname)
+        self.WriteLn("# Flags passed to only ObjC++ files.");
+        self.WriteList(cflags_objcc, 'CFLAGS_OBJCC_%s' % configname)
+      includes = config.get('include_dirs')
+      if includes:
+        includes = map(Sourceify, map(self.Absolutify, includes))
+      self.WriteList(includes, 'INCS_%s' % configname, prefix='-I')
+
+    compilable = filter(Compilable, sources)
+    objs = map(self.Objectify, map(self.Absolutify, map(Target, compilable)))
+    self.WriteList(objs, 'OBJS')
+
+    for obj in objs:
+      assert ' ' not in obj, (
+          "Spaces in object filenames not supported (%s)"  % obj)
+    self.WriteLn('# Add to the list of files we specially track '
+                 'dependencies for.')
+    self.WriteLn('all_deps += $(OBJS)')
+    self.WriteLn()
+
+    # Make sure our dependencies are built first.
+    if deps:
+      self.WriteMakeRule(['$(OBJS)'], deps,
+                         comment = 'Make sure our dependencies are built '
+                                   'before any of us.',
+                         order_only = True)
+
+    # Make sure the actions and rules run first.
+    # If they generate any extra headers etc., the per-.o file dep tracking
+    # will catch the proper rebuilds, so order only is still ok here.
+    if extra_outputs:
+      self.WriteMakeRule(['$(OBJS)'], extra_outputs,
+                         comment = 'Make sure our actions/rules run '
+                                   'before any of us.',
+                         order_only = True)
+
+    pchdeps = precompiled_header.GetObjDependencies(compilable, objs )
+    if pchdeps:
+      self.WriteLn('# Dependencies from obj files to their precompiled headers')
+      for source, obj, gch in pchdeps:
+        self.WriteLn('%s: %s' % (obj, gch))
+      self.WriteLn('# End precompiled header dependencies')
+
+    if objs:
+      extra_link_deps.append('$(OBJS)')
+      self.WriteLn("""\
+# CFLAGS et al overrides must be target-local.
+# See "Target-specific Variable Values" in the GNU Make manual.""")
+      self.WriteLn("$(OBJS): TOOLSET := $(TOOLSET)")
+      self.WriteLn("$(OBJS): GYP_CFLAGS := "
+                   "$(DEFS_$(BUILDTYPE)) "
+                   "$(INCS_$(BUILDTYPE)) "
+                   "%s " % precompiled_header.GetInclude('c') +
+                   "$(CFLAGS_$(BUILDTYPE)) "
+                   "$(CFLAGS_C_$(BUILDTYPE))")
+      self.WriteLn("$(OBJS): GYP_CXXFLAGS := "
+                   "$(DEFS_$(BUILDTYPE)) "
+                   "$(INCS_$(BUILDTYPE)) "
+                   "%s " % precompiled_header.GetInclude('cc') +
+                   "$(CFLAGS_$(BUILDTYPE)) "
+                   "$(CFLAGS_CC_$(BUILDTYPE))")
+      if self.flavor == 'mac':
+        self.WriteLn("$(OBJS): GYP_OBJCFLAGS := "
+                     "$(DEFS_$(BUILDTYPE)) "
+                     "$(INCS_$(BUILDTYPE)) "
+                     "%s " % precompiled_header.GetInclude('m') +
+                     "$(CFLAGS_$(BUILDTYPE)) "
+                     "$(CFLAGS_C_$(BUILDTYPE)) "
+                     "$(CFLAGS_OBJC_$(BUILDTYPE))")
+        self.WriteLn("$(OBJS): GYP_OBJCXXFLAGS := "
+                     "$(DEFS_$(BUILDTYPE)) "
+                     "$(INCS_$(BUILDTYPE)) "
+                     "%s " % precompiled_header.GetInclude('mm') +
+                     "$(CFLAGS_$(BUILDTYPE)) "
+                     "$(CFLAGS_CC_$(BUILDTYPE)) "
+                     "$(CFLAGS_OBJCC_$(BUILDTYPE))")
+
+    self.WritePchTargets(precompiled_header.GetPchBuildCommands())
+
+    # If there are any object files in our input file list, link them into our
+    # output.
+    extra_link_deps += filter(Linkable, sources)
+
+    self.WriteLn()
+
+  def WritePchTargets(self, pch_commands):
+    """Writes make rules to compile prefix headers."""
+    if not pch_commands:
+      return
+
+    for gch, lang_flag, lang, input in pch_commands:
+      extra_flags = {
+        'c': '$(CFLAGS_C_$(BUILDTYPE))',
+        'cc': '$(CFLAGS_CC_$(BUILDTYPE))',
+        'm': '$(CFLAGS_C_$(BUILDTYPE)) $(CFLAGS_OBJC_$(BUILDTYPE))',
+        'mm': '$(CFLAGS_CC_$(BUILDTYPE)) $(CFLAGS_OBJCC_$(BUILDTYPE))',
+      }[lang]
+      var_name = {
+        'c': 'GYP_PCH_CFLAGS',
+        'cc': 'GYP_PCH_CXXFLAGS',
+        'm': 'GYP_PCH_OBJCFLAGS',
+        'mm': 'GYP_PCH_OBJCXXFLAGS',
+      }[lang]
+      self.WriteLn("%s: %s := %s " % (gch, var_name, lang_flag) +
+                   "$(DEFS_$(BUILDTYPE)) "
+                   "$(INCS_$(BUILDTYPE)) "
+                   "$(CFLAGS_$(BUILDTYPE)) " +
+                   extra_flags)
+
+      self.WriteLn('%s: %s FORCE_DO_CMD' % (gch, input))
+      self.WriteLn('\t@$(call do_cmd,pch_%s,1)' % lang)
+      self.WriteLn('')
+      assert ' ' not in gch, (
+          "Spaces in gch filenames not supported (%s)"  % gch)
+      self.WriteLn('all_deps += %s' % gch)
+      self.WriteLn('')
+
+
+  def ComputeOutputBasename(self, spec):
+    """Return the 'output basename' of a gyp spec.
+
+    E.g., the loadable module 'foobar' in directory 'baz' will produce
+      'libfoobar.so'
+    """
+    assert not self.is_mac_bundle
+
+    if self.flavor == 'mac' and self.type in (
+        'static_library', 'executable', 'shared_library', 'loadable_module'):
+      return self.xcode_settings.GetExecutablePath()
+
+    target = spec['target_name']
+    target_prefix = ''
+    target_ext = ''
+    if self.type == 'static_library':
+      if target[:3] == 'lib':
+        target = target[3:]
+      target_prefix = 'lib'
+      target_ext = '.a'
+    elif self.type in ('loadable_module', 'shared_library'):
+      if target[:3] == 'lib':
+        target = target[3:]
+      target_prefix = 'lib'
+      target_ext = '.so'
+    elif self.type == 'none':
+      target = '%s.stamp' % target
+    elif self.type != 'executable':
+      print ("ERROR: What output file should be generated?",
+             "type", self.type, "target", target)
+
+    target_prefix = spec.get('product_prefix', target_prefix)
+    target = spec.get('product_name', target)
+    product_ext = spec.get('product_extension')
+    if product_ext:
+      target_ext = '.' + product_ext
+
+    return target_prefix + target + target_ext
+
+
+  def _InstallImmediately(self):
+    return self.toolset == 'target' and self.flavor == 'mac' and self.type in (
+          'static_library', 'executable', 'shared_library', 'loadable_module')
+
+
+  def ComputeOutput(self, spec):
+    """Return the 'output' (full output path) of a gyp spec.
+
+    E.g., the loadable module 'foobar' in directory 'baz' will produce
+      '$(obj)/baz/libfoobar.so'
+    """
+    assert not self.is_mac_bundle
+
+    path = os.path.join('$(obj).' + self.toolset, self.path)
+    if self.type == 'executable' or self._InstallImmediately():
+      path = '$(builddir)'
+    path = spec.get('product_dir', path)
+    return os.path.join(path, self.ComputeOutputBasename(spec))
+
+
+  def ComputeMacBundleOutput(self, spec):
+    """Return the 'output' (full output path) to a bundle output directory."""
+    assert self.is_mac_bundle
+    path = generator_default_variables['PRODUCT_DIR']
+    return os.path.join(path, self.xcode_settings.GetWrapperName())
+
+
+  def ComputeMacBundleBinaryOutput(self, spec):
+    """Return the 'output' (full output path) to the binary in a bundle."""
+    path = generator_default_variables['PRODUCT_DIR']
+    return os.path.join(path, self.xcode_settings.GetExecutablePath())
+
+
+  def ComputeDeps(self, spec):
+    """Compute the dependencies of a gyp spec.
+
+    Returns a tuple (deps, link_deps), where each is a list of
+    filenames that will need to be put in front of make for either
+    building (deps) or linking (link_deps).
+    """
+    deps = []
+    link_deps = []
+    if 'dependencies' in spec:
+      deps.extend([target_outputs[dep] for dep in spec['dependencies']
+                   if target_outputs[dep]])
+      for dep in spec['dependencies']:
+        if dep in target_link_deps:
+          link_deps.append(target_link_deps[dep])
+      deps.extend(link_deps)
+      # TODO: It seems we need to transitively link in libraries (e.g. -lfoo)?
+      # This hack makes it work:
+      # link_deps.extend(spec.get('libraries', []))
+    return (gyp.common.uniquer(deps), gyp.common.uniquer(link_deps))
+
+
+  def WriteDependencyOnExtraOutputs(self, target, extra_outputs):
+    self.WriteMakeRule([self.output_binary], extra_outputs,
+                       comment = 'Build our special outputs first.',
+                       order_only = True)
+
+
+  def WriteTarget(self, spec, configs, deps, link_deps, bundle_deps,
+                  extra_outputs, part_of_all):
+    """Write Makefile code to produce the final target of the gyp spec.
+
+    spec, configs: input from gyp.
+    deps, link_deps: dependency lists; see ComputeDeps()
+    extra_outputs: any extra outputs that our target should depend on
+    part_of_all: flag indicating this target is part of 'all'
+    """
+
+    self.WriteLn('### Rules for final target.')
+
+    if extra_outputs:
+      self.WriteDependencyOnExtraOutputs(self.output_binary, extra_outputs)
+      self.WriteMakeRule(extra_outputs, deps,
+                         comment=('Preserve order dependency of '
+                                  'special output on deps.'),
+                         order_only = True)
+
+    target_postbuilds = {}
+    if self.type != 'none':
+      for configname in sorted(configs.keys()):
+        config = configs[configname]
+        if self.flavor == 'mac':
+          ldflags = self.xcode_settings.GetLdflags(configname,
+              generator_default_variables['PRODUCT_DIR'],
+              lambda p: Sourceify(self.Absolutify(p)))
+
+          # TARGET_POSTBUILDS_$(BUILDTYPE) is added to postbuilds later on.
+          gyp_to_build = gyp.common.InvertRelativePath(self.path)
+          target_postbuild = self.xcode_settings.GetTargetPostbuilds(
+              configname,
+              QuoteSpaces(os.path.normpath(os.path.join(gyp_to_build,
+                                                        self.output))),
+              QuoteSpaces(os.path.normpath(os.path.join(gyp_to_build,
+                                                        self.output_binary))))
+          if target_postbuild:
+            target_postbuilds[configname] = target_postbuild
+        else:
+          ldflags = config.get('ldflags', [])
+          # Compute an rpath for this output if needed.
+          if any(dep.endswith('.so') or '.so.' in dep for dep in deps):
+            # We want to get the literal string "$ORIGIN" into the link command,
+            # so we need lots of escaping.
+            ldflags.append(r'-Wl,-rpath=\$$ORIGIN/lib.%s/' % self.toolset)
+            ldflags.append(r'-Wl,-rpath-link=\$(builddir)/lib.%s/' %
+                           self.toolset)
+        self.WriteList(ldflags, 'LDFLAGS_%s' % configname)
+        if self.flavor == 'mac':
+          self.WriteList(self.xcode_settings.GetLibtoolflags(configname),
+                         'LIBTOOLFLAGS_%s' % configname)
+      libraries = spec.get('libraries')
+      if libraries:
+        # Remove duplicate entries
+        libraries = gyp.common.uniquer(libraries)
+        if self.flavor == 'mac':
+          libraries = self.xcode_settings.AdjustLibraries(libraries)
+      self.WriteList(libraries, 'LIBS')
+      self.WriteLn('%s: GYP_LDFLAGS := $(LDFLAGS_$(BUILDTYPE))' %
+          QuoteSpaces(self.output_binary))
+      self.WriteLn('%s: LIBS := $(LIBS)' % QuoteSpaces(self.output_binary))
+
+      if self.flavor == 'mac':
+        self.WriteLn('%s: GYP_LIBTOOLFLAGS := $(LIBTOOLFLAGS_$(BUILDTYPE))' %
+            QuoteSpaces(self.output_binary))
+
+    # Postbuild actions. Like actions, but implicitly depend on the target's
+    # output.
+    postbuilds = []
+    if self.flavor == 'mac':
+      if target_postbuilds:
+        postbuilds.append('$(TARGET_POSTBUILDS_$(BUILDTYPE))')
+      postbuilds.extend(
+          gyp.xcode_emulation.GetSpecPostbuildCommands(spec))
+
+    if postbuilds:
+      # Envvars may be referenced by TARGET_POSTBUILDS_$(BUILDTYPE),
+      # so we must output its definition first, since we declare variables
+      # using ":=".
+      self.WriteSortedXcodeEnv(self.output, self.GetSortedXcodePostbuildEnv())
+
+      for configname in target_postbuilds:
+        self.WriteLn('%s: TARGET_POSTBUILDS_%s := %s' %
+            (QuoteSpaces(self.output),
+             configname,
+             gyp.common.EncodePOSIXShellList(target_postbuilds[configname])))
+
+      # Postbuilds expect to be run in the gyp file's directory, so insert an
+      # implicit postbuild to cd to there.
+      postbuilds.insert(0, gyp.common.EncodePOSIXShellList(['cd', self.path]))
+      for i in xrange(len(postbuilds)):
+        if not postbuilds[i].startswith('$'):
+          postbuilds[i] = EscapeShellArgument(postbuilds[i])
+      self.WriteLn('%s: builddir := $(abs_builddir)' % QuoteSpaces(self.output))
+      self.WriteLn('%s: POSTBUILDS := %s' % (
+          QuoteSpaces(self.output), ' '.join(postbuilds)))
+
+    # A bundle directory depends on its dependencies such as bundle resources
+    # and bundle binary. When all dependencies have been built, the bundle
+    # needs to be packaged.
+    if self.is_mac_bundle:
+      # If the framework doesn't contain a binary, then nothing depends
+      # on the actions -- make the framework depend on them directly too.
+      self.WriteDependencyOnExtraOutputs(self.output, extra_outputs)
+
+      # Bundle dependencies. Note that the code below adds actions to this
+      # target, so if you move these two lines, move the lines below as well.
+      self.WriteList(map(QuoteSpaces, bundle_deps), 'BUNDLE_DEPS')
+      self.WriteLn('%s: $(BUNDLE_DEPS)' % QuoteSpaces(self.output))
+
+      # After the framework is built, package it. Needs to happen before
+      # postbuilds, since postbuilds depend on this.
+      if self.type in ('shared_library', 'loadable_module'):
+        self.WriteLn('\t@$(call do_cmd,mac_package_framework,,,%s)' %
+            self.xcode_settings.GetFrameworkVersion())
+
+      # Bundle postbuilds can depend on the whole bundle, so run them after
+      # the bundle is packaged, not already after the bundle binary is done.
+      if postbuilds:
+        self.WriteLn('\t@$(call do_postbuilds)')
+      postbuilds = []  # Don't write postbuilds for target's output.
+
+      # Needed by test/mac/gyptest-rebuild.py.
+      self.WriteLn('\t@true  # No-op, used by tests')
+
+      # Since this target depends on binary and resources which are in
+      # nested subfolders, the framework directory will be older than
+      # its dependencies usually. To prevent this rule from executing
+      # on every build (expensive, especially with postbuilds), expliclity
+      # update the time on the framework directory.
+      self.WriteLn('\t@touch -c %s' % QuoteSpaces(self.output))
+
+    if postbuilds:
+      assert not self.is_mac_bundle, ('Postbuilds for bundles should be done '
+          'on the bundle, not the binary (target \'%s\')' % self.target)
+      assert 'product_dir' not in spec, ('Postbuilds do not work with '
+          'custom product_dir')
+
+    if self.type == 'executable':
+      self.WriteLn('%s: LD_INPUTS := %s' % (
+          QuoteSpaces(self.output_binary),
+          ' '.join(map(QuoteSpaces, link_deps))))
+      if self.toolset == 'host' and self.flavor == 'android':
+        self.WriteDoCmd([self.output_binary], link_deps, 'link_host',
+                        part_of_all, postbuilds=postbuilds)
+      else:
+        self.WriteDoCmd([self.output_binary], link_deps, 'link', part_of_all,
+                        postbuilds=postbuilds)
+
+    elif self.type == 'static_library':
+      for link_dep in link_deps:
+        assert ' ' not in link_dep, (
+            "Spaces in alink input filenames not supported (%s)"  % link_dep)
+      if (self.flavor not in ('mac', 'openbsd', 'win') and not
+          self.is_standalone_static_library):
+        self.WriteDoCmd([self.output_binary], link_deps, 'alink_thin',
+                        part_of_all, postbuilds=postbuilds)
+      else:
+        self.WriteDoCmd([self.output_binary], link_deps, 'alink', part_of_all,
+                        postbuilds=postbuilds)
+    elif self.type == 'shared_library':
+      self.WriteLn('%s: LD_INPUTS := %s' % (
+            QuoteSpaces(self.output_binary),
+            ' '.join(map(QuoteSpaces, link_deps))))
+      self.WriteDoCmd([self.output_binary], link_deps, 'solink', part_of_all,
+                      postbuilds=postbuilds)
+    elif self.type == 'loadable_module':
+      for link_dep in link_deps:
+        assert ' ' not in link_dep, (
+            "Spaces in module input filenames not supported (%s)"  % link_dep)
+      if self.toolset == 'host' and self.flavor == 'android':
+        self.WriteDoCmd([self.output_binary], link_deps, 'solink_module_host',
+                        part_of_all, postbuilds=postbuilds)
+      else:
+        self.WriteDoCmd(
+            [self.output_binary], link_deps, 'solink_module', part_of_all,
+            postbuilds=postbuilds)
+    elif self.type == 'none':
+      # Write a stamp line.
+      self.WriteDoCmd([self.output_binary], deps, 'touch', part_of_all,
+                      postbuilds=postbuilds)
+    else:
+      print "WARNING: no output for", self.type, target
+
+    # Add an alias for each target (if there are any outputs).
+    # Installable target aliases are created below.
+    if ((self.output and self.output != self.target) and
+        (self.type not in self._INSTALLABLE_TARGETS)):
+      self.WriteMakeRule([self.target], [self.output],
+                         comment='Add target alias', phony = True)
+      if part_of_all:
+        self.WriteMakeRule(['all'], [self.target],
+                           comment = 'Add target alias to "all" target.',
+                           phony = True)
+
+    # Add special-case rules for our installable targets.
+    # 1) They need to install to the build dir or "product" dir.
+    # 2) They get shortcuts for building (e.g. "make chrome").
+    # 3) They are part of "make all".
+    if (self.type in self._INSTALLABLE_TARGETS or
+        self.is_standalone_static_library):
+      if self.type == 'shared_library':
+        file_desc = 'shared library'
+      elif self.type == 'static_library':
+        file_desc = 'static library'
+      else:
+        file_desc = 'executable'
+      install_path = self._InstallableTargetInstallPath()
+      installable_deps = [self.output]
+      if (self.flavor == 'mac' and not 'product_dir' in spec and
+          self.toolset == 'target'):
+        # On mac, products are created in install_path immediately.
+        assert install_path == self.output, '%s != %s' % (
+            install_path, self.output)
+
+      # Point the target alias to the final binary output.
+      self.WriteMakeRule([self.target], [install_path],
+                         comment='Add target alias', phony = True)
+      if install_path != self.output:
+        assert not self.is_mac_bundle  # See comment a few lines above.
+        self.WriteDoCmd([install_path], [self.output], 'copy',
+                        comment = 'Copy this to the %s output path.' %
+                        file_desc, part_of_all=part_of_all)
+        installable_deps.append(install_path)
+      if self.output != self.alias and self.alias != self.target:
+        self.WriteMakeRule([self.alias], installable_deps,
+                           comment = 'Short alias for building this %s.' %
+                           file_desc, phony = True)
+      if part_of_all:
+        self.WriteMakeRule(['all'], [install_path],
+                           comment = 'Add %s to "all" target.' % file_desc,
+                           phony = True)
+
+
+  def WriteList(self, value_list, variable=None, prefix='',
+                quoter=QuoteIfNecessary):
+    """Write a variable definition that is a list of values.
+
+    E.g. WriteList(['a','b'], 'foo', prefix='blah') writes out
+         foo = blaha blahb
+    but in a pretty-printed style.
+    """
+    values = ''
+    if value_list:
+      value_list = [quoter(prefix + l) for l in value_list]
+      values = ' \\\n\t' + ' \\\n\t'.join(value_list)
+    self.fp.write('%s :=%s\n\n' % (variable, values))
+
+
+  def WriteDoCmd(self, outputs, inputs, command, part_of_all, comment=None,
+                 postbuilds=False):
+    """Write a Makefile rule that uses do_cmd.
+
+    This makes the outputs dependent on the command line that was run,
+    as well as support the V= make command line flag.
+    """
+    suffix = ''
+    if postbuilds:
+      assert ',' not in command
+      suffix = ',,1'  # Tell do_cmd to honor $POSTBUILDS
+    self.WriteMakeRule(outputs, inputs,
+                       actions = ['$(call do_cmd,%s%s)' % (command, suffix)],
+                       comment = comment,
+                       force = True)
+    # Add our outputs to the list of targets we read depfiles from.
+    # all_deps is only used for deps file reading, and for deps files we replace
+    # spaces with ? because escaping doesn't work with make's $(sort) and
+    # other functions.
+    outputs = [QuoteSpaces(o, SPACE_REPLACEMENT) for o in outputs]
+    self.WriteLn('all_deps += %s' % ' '.join(outputs))
+
+
+  def WriteMakeRule(self, outputs, inputs, actions=None, comment=None,
+                    order_only=False, force=False, phony=False):
+    """Write a Makefile rule, with some extra tricks.
+
+    outputs: a list of outputs for the rule (note: this is not directly
+             supported by make; see comments below)
+    inputs: a list of inputs for the rule
+    actions: a list of shell commands to run for the rule
+    comment: a comment to put in the Makefile above the rule (also useful
+             for making this Python script's code self-documenting)
+    order_only: if true, makes the dependency order-only
+    force: if true, include FORCE_DO_CMD as an order-only dep
+    phony: if true, the rule does not actually generate the named output, the
+           output is just a name to run the rule
+    """
+    outputs = map(QuoteSpaces, outputs)
+    inputs = map(QuoteSpaces, inputs)
+
+    if comment:
+      self.WriteLn('# ' + comment)
+    if phony:
+      self.WriteLn('.PHONY: ' + ' '.join(outputs))
+    # TODO(evanm): just make order_only a list of deps instead of these hacks.
+    if order_only:
+      order_insert = '| '
+      pick_output = ' '.join(outputs)
+    else:
+      order_insert = ''
+      pick_output = outputs[0]
+    if force:
+      force_append = ' FORCE_DO_CMD'
+    else:
+      force_append = ''
+    if actions:
+      self.WriteLn("%s: TOOLSET := $(TOOLSET)" % outputs[0])
+    self.WriteLn('%s: %s%s%s' % (pick_output, order_insert, ' '.join(inputs),
+                                 force_append))
+    if actions:
+      for action in actions:
+        self.WriteLn('\t%s' % action)
+    if not order_only and len(outputs) > 1:
+      # If we have more than one output, a rule like
+      #   foo bar: baz
+      # that for *each* output we must run the action, potentially
+      # in parallel.  That is not what we're trying to write -- what
+      # we want is that we run the action once and it generates all
+      # the files.
+      # http://www.gnu.org/software/hello/manual/automake/Multiple-Outputs.html
+      # discusses this problem and has this solution:
+      # 1) Write the naive rule that would produce parallel runs of
+      # the action.
+      # 2) Make the outputs seralized on each other, so we won't start
+      # a parallel run until the first run finishes, at which point
+      # we'll have generated all the outputs and we're done.
+      self.WriteLn('%s: %s' % (' '.join(outputs[1:]), outputs[0]))
+      # Add a dummy command to the "extra outputs" rule, otherwise make seems to
+      # think these outputs haven't (couldn't have?) changed, and thus doesn't
+      # flag them as changed (i.e. include in '$?') when evaluating dependent
+      # rules, which in turn causes do_cmd() to skip running dependent commands.
+      self.WriteLn('%s: ;' % (' '.join(outputs[1:])))
+    self.WriteLn()
+
+
+  def WriteAndroidNdkModuleRule(self, module_name, all_sources, link_deps):
+    """Write a set of LOCAL_XXX definitions for Android NDK.
+
+    These variable definitions will be used by Android NDK but do nothing for
+    non-Android applications.
+
+    Arguments:
+      module_name: Android NDK module name, which must be unique among all
+          module names.
+      all_sources: A list of source files (will be filtered by Compilable).
+      link_deps: A list of link dependencies, which must be sorted in
+          the order from dependencies to dependents.
+    """
+    if self.type not in ('executable', 'shared_library', 'static_library'):
+      return
+
+    self.WriteLn('# Variable definitions for Android applications')
+    self.WriteLn('include $(CLEAR_VARS)')
+    self.WriteLn('LOCAL_MODULE := ' + module_name)
+    self.WriteLn('LOCAL_CFLAGS := $(CFLAGS_$(BUILDTYPE)) '
+                 '$(DEFS_$(BUILDTYPE)) '
+                 # LOCAL_CFLAGS is applied to both of C and C++.  There is
+                 # no way to specify $(CFLAGS_C_$(BUILDTYPE)) only for C
+                 # sources.
+                 '$(CFLAGS_C_$(BUILDTYPE)) '
+                 # $(INCS_$(BUILDTYPE)) includes the prefix '-I' while
+                 # LOCAL_C_INCLUDES does not expect it.  So put it in
+                 # LOCAL_CFLAGS.
+                 '$(INCS_$(BUILDTYPE))')
+    # LOCAL_CXXFLAGS is obsolete and LOCAL_CPPFLAGS is preferred.
+    self.WriteLn('LOCAL_CPPFLAGS := $(CFLAGS_CC_$(BUILDTYPE))')
+    self.WriteLn('LOCAL_C_INCLUDES :=')
+    self.WriteLn('LOCAL_LDLIBS := $(LDFLAGS_$(BUILDTYPE)) $(LIBS)')
+
+    # Detect the C++ extension.
+    cpp_ext = {'.cc': 0, '.cpp': 0, '.cxx': 0}
+    default_cpp_ext = '.cpp'
+    for filename in all_sources:
+      ext = os.path.splitext(filename)[1]
+      if ext in cpp_ext:
+        cpp_ext[ext] += 1
+        if cpp_ext[ext] > cpp_ext[default_cpp_ext]:
+          default_cpp_ext = ext
+    self.WriteLn('LOCAL_CPP_EXTENSION := ' + default_cpp_ext)
+
+    self.WriteList(map(self.Absolutify, filter(Compilable, all_sources)),
+                   'LOCAL_SRC_FILES')
+
+    # Filter out those which do not match prefix and suffix and produce
+    # the resulting list without prefix and suffix.
+    def DepsToModules(deps, prefix, suffix):
+      modules = []
+      for filepath in deps:
+        filename = os.path.basename(filepath)
+        if filename.startswith(prefix) and filename.endswith(suffix):
+          modules.append(filename[len(prefix):-len(suffix)])
+      return modules
+
+    # Retrieve the default value of 'SHARED_LIB_SUFFIX'
+    params = {'flavor': 'linux'}
+    default_variables = {}
+    CalculateVariables(default_variables, params)
+
+    self.WriteList(
+        DepsToModules(link_deps,
+                      generator_default_variables['SHARED_LIB_PREFIX'],
+                      default_variables['SHARED_LIB_SUFFIX']),
+        'LOCAL_SHARED_LIBRARIES')
+    self.WriteList(
+        DepsToModules(link_deps,
+                      generator_default_variables['STATIC_LIB_PREFIX'],
+                      generator_default_variables['STATIC_LIB_SUFFIX']),
+        'LOCAL_STATIC_LIBRARIES')
+
+    if self.type == 'executable':
+      self.WriteLn('include $(BUILD_EXECUTABLE)')
+    elif self.type == 'shared_library':
+      self.WriteLn('include $(BUILD_SHARED_LIBRARY)')
+    elif self.type == 'static_library':
+      self.WriteLn('include $(BUILD_STATIC_LIBRARY)')
+    self.WriteLn()
+
+
+  def WriteLn(self, text=''):
+    self.fp.write(text + '\n')
+
+
+  def GetSortedXcodeEnv(self, additional_settings=None):
+    return gyp.xcode_emulation.GetSortedXcodeEnv(
+        self.xcode_settings, "$(abs_builddir)",
+        os.path.join("$(abs_srcdir)", self.path), "$(BUILDTYPE)",
+        additional_settings)
+
+
+  def GetSortedXcodePostbuildEnv(self):
+    # CHROMIUM_STRIP_SAVE_FILE is a chromium-specific hack.
+    # TODO(thakis): It would be nice to have some general mechanism instead.
+    strip_save_file = self.xcode_settings.GetPerTargetSetting(
+        'CHROMIUM_STRIP_SAVE_FILE', '')
+    # Even if strip_save_file is empty, explicitly write it. Else a postbuild
+    # might pick up an export from an earlier target.
+    return self.GetSortedXcodeEnv(
+        additional_settings={'CHROMIUM_STRIP_SAVE_FILE': strip_save_file})
+
+
+  def WriteSortedXcodeEnv(self, target, env):
+    for k, v in env:
+      # For
+      #  foo := a\ b
+      # the escaped space does the right thing. For
+      #  export foo := a\ b
+      # it does not -- the backslash is written to the env as literal character.
+      # So don't escape spaces in |env[k]|.
+      self.WriteLn('%s: export %s := %s' % (QuoteSpaces(target), k, v))
+
+
+  def Objectify(self, path):
+    """Convert a path to its output directory form."""
+    if '$(' in path:
+      path = path.replace('$(obj)/', '$(obj).%s/$(TARGET)/' % self.toolset)
+    if not '$(obj)' in path:
+      path = '$(obj).%s/$(TARGET)/%s' % (self.toolset, path)
+    return path
+
+
+  def Pchify(self, path, lang):
+    """Convert a prefix header path to its output directory form."""
+    path = self.Absolutify(path)
+    if '$(' in path:
+      path = path.replace('$(obj)/', '$(obj).%s/$(TARGET)/pch-%s' %
+                          (self.toolset, lang))
+      return path
+    return '$(obj).%s/$(TARGET)/pch-%s/%s' % (self.toolset, lang, path)
+
+
+  def Absolutify(self, path):
+    """Convert a subdirectory-relative path into a base-relative path.
+    Skips over paths that contain variables."""
+    if '$(' in path:
+      # Don't call normpath in this case, as it might collapse the
+      # path too aggressively if it features '..'. However it's still
+      # important to strip trailing slashes.
+      return path.rstrip('/')
+    return os.path.normpath(os.path.join(self.path, path))
+
+
+  def ExpandInputRoot(self, template, expansion, dirname):
+    if '%(INPUT_ROOT)s' not in template and '%(INPUT_DIRNAME)s' not in template:
+      return template
+    path = template % {
+        'INPUT_ROOT': expansion,
+        'INPUT_DIRNAME': dirname,
+        }
+    return path
+
+
+  def _InstallableTargetInstallPath(self):
+    """Returns the location of the final output for an installable target."""
+    # Xcode puts shared_library results into PRODUCT_DIR, and some gyp files
+    # rely on this. Emulate this behavior for mac.
+    if (self.type == 'shared_library' and
+        (self.flavor != 'mac' or self.toolset != 'target')):
+      # Install all shared libs into a common directory (per toolset) for
+      # convenient access with LD_LIBRARY_PATH.
+      return '$(builddir)/lib.%s/%s' % (self.toolset, self.alias)
+    return '$(builddir)/' + self.alias
+
+
+def WriteAutoRegenerationRule(params, root_makefile, makefile_name,
+                              build_files):
+  """Write the target to regenerate the Makefile."""
+  options = params['options']
+  build_files_args = [gyp.common.RelativePath(filename, options.toplevel_dir)
+                      for filename in params['build_files_arg']]
+  gyp_binary = gyp.common.FixIfRelativePath(params['gyp_binary'],
+                                            options.toplevel_dir)
+  if not gyp_binary.startswith(os.sep):
+    gyp_binary = os.path.join('.', gyp_binary)
+  root_makefile.write(
+      "quiet_cmd_regen_makefile = ACTION Regenerating $@\n"
+      "cmd_regen_makefile = %(cmd)s\n"
+      "%(makefile_name)s: %(deps)s\n"
+      "\t$(call do_cmd,regen_makefile)\n\n" % {
+          'makefile_name': makefile_name,
+          'deps': ' '.join(map(Sourceify, build_files)),
+          'cmd': gyp.common.EncodePOSIXShellList(
+                     [gyp_binary, '-fmake'] +
+                     gyp.RegenerateFlags(options) +
+                     build_files_args)})
+
+
+def PerformBuild(data, configurations, params):
+  options = params['options']
+  for config in configurations:
+    arguments = ['make']
+    if options.toplevel_dir and options.toplevel_dir != '.':
+      arguments += '-C', options.toplevel_dir
+    arguments.append('BUILDTYPE=' + config)
+    print 'Building [%s]: %s' % (config, arguments)
+    subprocess.check_call(arguments)
+
+
+def GenerateOutput(target_list, target_dicts, data, params):
+  options = params['options']
+  flavor = gyp.common.GetFlavor(params)
+  generator_flags = params.get('generator_flags', {})
+  builddir_name = generator_flags.get('output_dir', 'out')
+  android_ndk_version = generator_flags.get('android_ndk_version', None)
+  default_target = generator_flags.get('default_target', 'all')
+
+  def CalculateMakefilePath(build_file, base_name):
+    """Determine where to write a Makefile for a given gyp file."""
+    # Paths in gyp files are relative to the .gyp file, but we want
+    # paths relative to the source root for the master makefile.  Grab
+    # the path of the .gyp file as the base to relativize against.
+    # E.g. "foo/bar" when we're constructing targets for "foo/bar/baz.gyp".
+    base_path = gyp.common.RelativePath(os.path.dirname(build_file),
+                                        options.depth)
+    # We write the file in the base_path directory.
+    output_file = os.path.join(options.depth, base_path, base_name)
+    if options.generator_output:
+      output_file = os.path.join(options.generator_output, output_file)
+    base_path = gyp.common.RelativePath(os.path.dirname(build_file),
+                                        options.toplevel_dir)
+    return base_path, output_file
+
+  # TODO:  search for the first non-'Default' target.  This can go
+  # away when we add verification that all targets have the
+  # necessary configurations.
+  default_configuration = None
+  toolsets = set([target_dicts[target]['toolset'] for target in target_list])
+  for target in target_list:
+    spec = target_dicts[target]
+    if spec['default_configuration'] != 'Default':
+      default_configuration = spec['default_configuration']
+      break
+  if not default_configuration:
+    default_configuration = 'Default'
+
+  srcdir = '.'
+  makefile_name = 'Makefile' + options.suffix
+  makefile_path = os.path.join(options.toplevel_dir, makefile_name)
+  if options.generator_output:
+    global srcdir_prefix
+    makefile_path = os.path.join(options.generator_output, makefile_path)
+    srcdir = gyp.common.RelativePath(srcdir, options.generator_output)
+    srcdir_prefix = '$(srcdir)/'
+
+  flock_command= 'flock'
+  header_params = {
+      'default_target': default_target,
+      'builddir': builddir_name,
+      'default_configuration': default_configuration,
+      'flock': flock_command,
+      'flock_index': 1,
+      'link_commands': LINK_COMMANDS_LINUX,
+      'extra_commands': '',
+      'srcdir': srcdir,
+    }
+  if flavor == 'mac':
+    flock_command = './gyp-mac-tool flock'
+    header_params.update({
+        'flock': flock_command,
+        'flock_index': 2,
+        'link_commands': LINK_COMMANDS_MAC,
+        'extra_commands': SHARED_HEADER_MAC_COMMANDS,
+    })
+  elif flavor == 'android':
+    header_params.update({
+        'link_commands': LINK_COMMANDS_ANDROID,
+    })
+  elif flavor == 'solaris':
+    header_params.update({
+        'flock': './gyp-sun-tool flock',
+        'flock_index': 2,
+        'extra_commands': SHARED_HEADER_SUN_COMMANDS,
+    })
+  elif flavor == 'freebsd':
+    # Note: OpenBSD has sysutils/flock. lockf seems to be FreeBSD specific.
+    header_params.update({
+        'flock': 'lockf',
+    })
+
+  header_params.update({
+    'CC.target':   GetEnvironFallback(('CC_target', 'CC'), '$(CC)'),
+    'AR.target':   GetEnvironFallback(('AR_target', 'AR'), '$(AR)'),
+    'CXX.target':  GetEnvironFallback(('CXX_target', 'CXX'), '$(CXX)'),
+    'LINK.target': GetEnvironFallback(('LD_target', 'LD'), '$(LINK)'),
+    'CC.host':     GetEnvironFallback(('CC_host',), 'gcc'),
+    'AR.host':     GetEnvironFallback(('AR_host',), 'ar'),
+    'CXX.host':    GetEnvironFallback(('CXX_host',), 'g++'),
+    'LINK.host':   GetEnvironFallback(('LD_host',), 'g++'),
+  })
+
+  build_file, _, _ = gyp.common.ParseQualifiedTarget(target_list[0])
+  make_global_settings_array = data[build_file].get('make_global_settings', [])
+  wrappers = {}
+  wrappers['LINK'] = '%s $(builddir)/linker.lock' % flock_command
+  for key, value in make_global_settings_array:
+    if key.endswith('_wrapper'):
+      wrappers[key[:-len('_wrapper')]] = '$(abspath %s)' % value
+  make_global_settings = ''
+  for key, value in make_global_settings_array:
+    if re.match('.*_wrapper', key):
+      continue
+    if value[0] != '$':
+      value = '$(abspath %s)' % value
+    wrapper = wrappers.get(key)
+    if wrapper:
+      value = '%s %s' % (wrapper, value)
+      del wrappers[key]
+    if key in ('CC', 'CC.host', 'CXX', 'CXX.host'):
+      make_global_settings += (
+          'ifneq (,$(filter $(origin %s), undefined default))\n' % key)
+      # Let gyp-time envvars win over global settings.
+      if key in os.environ:
+        value = os.environ[key]
+      make_global_settings += '  %s = %s\n' % (key, value)
+      make_global_settings += 'endif\n'
+    else:
+      make_global_settings += '%s ?= %s\n' % (key, value)
+  # TODO(ukai): define cmd when only wrapper is specified in
+  # make_global_settings.
+
+  header_params['make_global_settings'] = make_global_settings
+
+  ensure_directory_exists(makefile_path)
+  root_makefile = open(makefile_path, 'w')
+  root_makefile.write(SHARED_HEADER % header_params)
+  # Currently any versions have the same effect, but in future the behavior
+  # could be different.
+  if android_ndk_version:
+    root_makefile.write(
+        '# Define LOCAL_PATH for build of Android applications.\n'
+        'LOCAL_PATH := $(call my-dir)\n'
+        '\n')
+  for toolset in toolsets:
+    root_makefile.write('TOOLSET := %s\n' % toolset)
+    WriteRootHeaderSuffixRules(root_makefile)
+
+  # Put build-time support tools next to the root Makefile.
+  dest_path = os.path.dirname(makefile_path)
+  gyp.common.CopyTool(flavor, dest_path)
+
+  # Find the list of targets that derive from the gyp file(s) being built.
+  needed_targets = set()
+  for build_file in params['build_files']:
+    for target in gyp.common.AllTargets(target_list, target_dicts, build_file):
+      needed_targets.add(target)
+
+  build_files = set()
+  include_list = set()
+  for qualified_target in target_list:
+    build_file, target, toolset = gyp.common.ParseQualifiedTarget(
+        qualified_target)
+
+    this_make_global_settings = data[build_file].get('make_global_settings', [])
+    assert make_global_settings_array == this_make_global_settings, (
+        "make_global_settings needs to be the same for all targets.")
+
+    build_files.add(gyp.common.RelativePath(build_file, options.toplevel_dir))
+    included_files = data[build_file]['included_files']
+    for included_file in included_files:
+      # The included_files entries are relative to the dir of the build file
+      # that included them, so we have to undo that and then make them relative
+      # to the root dir.
+      relative_include_file = gyp.common.RelativePath(
+          gyp.common.UnrelativePath(included_file, build_file),
+          options.toplevel_dir)
+      abs_include_file = os.path.abspath(relative_include_file)
+      # If the include file is from the ~/.gyp dir, we should use absolute path
+      # so that relocating the src dir doesn't break the path.
+      if (params['home_dot_gyp'] and
+          abs_include_file.startswith(params['home_dot_gyp'])):
+        build_files.add(abs_include_file)
+      else:
+        build_files.add(relative_include_file)
+
+    base_path, output_file = CalculateMakefilePath(build_file,
+        target + '.' + toolset + options.suffix + '.mk')
+
+    spec = target_dicts[qualified_target]
+    configs = spec['configurations']
+
+    if flavor == 'mac':
+      gyp.xcode_emulation.MergeGlobalXcodeSettingsToSpec(data[build_file], spec)
+
+    writer = MakefileWriter(generator_flags, flavor)
+    writer.Write(qualified_target, base_path, output_file, spec, configs,
+                 part_of_all=qualified_target in needed_targets)
+
+    # Our root_makefile lives at the source root.  Compute the relative path
+    # from there to the output_file for including.
+    mkfile_rel_path = gyp.common.RelativePath(output_file,
+                                              os.path.dirname(makefile_path))
+    include_list.add(mkfile_rel_path)
+
+  # Write out per-gyp (sub-project) Makefiles.
+  depth_rel_path = gyp.common.RelativePath(options.depth, os.getcwd())
+  for build_file in build_files:
+    # The paths in build_files were relativized above, so undo that before
+    # testing against the non-relativized items in target_list and before
+    # calculating the Makefile path.
+    build_file = os.path.join(depth_rel_path, build_file)
+    gyp_targets = [target_dicts[target]['target_name'] for target in target_list
+                   if target.startswith(build_file) and
+                   target in needed_targets]
+    # Only generate Makefiles for gyp files with targets.
+    if not gyp_targets:
+      continue
+    base_path, output_file = CalculateMakefilePath(build_file,
+        os.path.splitext(os.path.basename(build_file))[0] + '.Makefile')
+    makefile_rel_path = gyp.common.RelativePath(os.path.dirname(makefile_path),
+                                                os.path.dirname(output_file))
+    writer.WriteSubMake(output_file, makefile_rel_path, gyp_targets,
+                        builddir_name)
+
+
+  # Write out the sorted list of includes.
+  root_makefile.write('\n')
+  for include_file in sorted(include_list):
+    # We wrap each .mk include in an if statement so users can tell make to
+    # not load a file by setting NO_LOAD.  The below make code says, only
+    # load the .mk file if the .mk filename doesn't start with a token in
+    # NO_LOAD.
+    root_makefile.write(
+        "ifeq ($(strip $(foreach prefix,$(NO_LOAD),\\\n"
+        "    $(findstring $(join ^,$(prefix)),\\\n"
+        "                 $(join ^," + include_file + ")))),)\n")
+    root_makefile.write("  include " + include_file + "\n")
+    root_makefile.write("endif\n")
+  root_makefile.write('\n')
+
+  if (not generator_flags.get('standalone')
+      and generator_flags.get('auto_regeneration', True)):
+    WriteAutoRegenerationRule(params, root_makefile, makefile_name, build_files)
+
+  root_makefile.write(SHARED_FOOTER)
+
+  root_makefile.close()
diff --git a/webWidgetTCT_device/tools/gyp/pylib/gyp/generator/msvs.py b/webWidgetTCT_device/tools/gyp/pylib/gyp/generator/msvs.py
new file mode 100755 (executable)
index 0000000..51acf2e
--- /dev/null
@@ -0,0 +1,3117 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import copy
+import ntpath
+import os
+import posixpath
+import re
+import subprocess
+import sys
+
+import gyp.common
+import gyp.easy_xml as easy_xml
+import gyp.MSVSNew as MSVSNew
+import gyp.MSVSProject as MSVSProject
+import gyp.MSVSSettings as MSVSSettings
+import gyp.MSVSToolFile as MSVSToolFile
+import gyp.MSVSUserFile as MSVSUserFile
+import gyp.MSVSUtil as MSVSUtil
+import gyp.MSVSVersion as MSVSVersion
+from gyp.common import GypError
+
+
+# Regular expression for validating Visual Studio GUIDs.  If the GUID
+# contains lowercase hex letters, MSVS will be fine. However,
+# IncrediBuild BuildConsole will parse the solution file, but then
+# silently skip building the target causing hard to track down errors.
+# Note that this only happens with the BuildConsole, and does not occur
+# if IncrediBuild is executed from inside Visual Studio.  This regex
+# validates that the string looks like a GUID with all uppercase hex
+# letters.
+VALID_MSVS_GUID_CHARS = re.compile('^[A-F0-9\-]+$')
+
+
+generator_default_variables = {
+    'EXECUTABLE_PREFIX': '',
+    'EXECUTABLE_SUFFIX': '.exe',
+    'STATIC_LIB_PREFIX': '',
+    'SHARED_LIB_PREFIX': '',
+    'STATIC_LIB_SUFFIX': '.lib',
+    'SHARED_LIB_SUFFIX': '.dll',
+    'INTERMEDIATE_DIR': '$(IntDir)',
+    'SHARED_INTERMEDIATE_DIR': '$(OutDir)obj/global_intermediate',
+    'OS': 'win',
+    'PRODUCT_DIR': '$(OutDir)',
+    'LIB_DIR': '$(OutDir)lib',
+    'RULE_INPUT_ROOT': '$(InputName)',
+    'RULE_INPUT_DIRNAME': '$(InputDir)',
+    'RULE_INPUT_EXT': '$(InputExt)',
+    'RULE_INPUT_NAME': '$(InputFileName)',
+    'RULE_INPUT_PATH': '$(InputPath)',
+    'CONFIGURATION_NAME': '$(ConfigurationName)',
+}
+
+
+# The msvs specific sections that hold paths
+generator_additional_path_sections = [
+    'msvs_cygwin_dirs',
+    'msvs_props',
+]
+
+
+generator_additional_non_configuration_keys = [
+    'msvs_cygwin_dirs',
+    'msvs_cygwin_shell',
+    'msvs_large_pdb',
+    'msvs_shard',
+]
+
+
+# List of precompiled header related keys.
+precomp_keys = [
+    'msvs_precompiled_header',
+    'msvs_precompiled_source',
+]
+
+
+cached_username = None
+
+
+cached_domain = None
+
+
+# TODO(gspencer): Switch the os.environ calls to be
+# win32api.GetDomainName() and win32api.GetUserName() once the
+# python version in depot_tools has been updated to work on Vista
+# 64-bit.
+def _GetDomainAndUserName():
+  if sys.platform not in ('win32', 'cygwin'):
+    return ('DOMAIN', 'USERNAME')
+  global cached_username
+  global cached_domain
+  if not cached_domain or not cached_username:
+    domain = os.environ.get('USERDOMAIN')
+    username = os.environ.get('USERNAME')
+    if not domain or not username:
+      call = subprocess.Popen(['net', 'config', 'Workstation'],
+                              stdout=subprocess.PIPE)
+      config = call.communicate()[0]
+      username_re = re.compile('^User name\s+(\S+)', re.MULTILINE)
+      username_match = username_re.search(config)
+      if username_match:
+        username = username_match.group(1)
+      domain_re = re.compile('^Logon domain\s+(\S+)', re.MULTILINE)
+      domain_match = domain_re.search(config)
+      if domain_match:
+        domain = domain_match.group(1)
+    cached_domain = domain
+    cached_username = username
+  return (cached_domain, cached_username)
+
+fixpath_prefix = None
+
+
+def _NormalizedSource(source):
+  """Normalize the path.
+
+  But not if that gets rid of a variable, as this may expand to something
+  larger than one directory.
+
+  Arguments:
+      source: The path to be normalize.d
+
+  Returns:
+      The normalized path.
+  """
+  normalized = os.path.normpath(source)
+  if source.count('$') == normalized.count('$'):
+    source = normalized
+  return source
+
+
+def _FixPath(path):
+  """Convert paths to a form that will make sense in a vcproj file.
+
+  Arguments:
+    path: The path to convert, may contain / etc.
+  Returns:
+    The path with all slashes made into backslashes.
+  """
+  if fixpath_prefix and path and not os.path.isabs(path) and not path[0] == '$':
+    path = os.path.join(fixpath_prefix, path)
+  path = path.replace('/', '\\')
+  path = _NormalizedSource(path)
+  if path and path[-1] == '\\':
+    path = path[:-1]
+  return path
+
+
+def _FixPaths(paths):
+  """Fix each of the paths of the list."""
+  return [_FixPath(i) for i in paths]
+
+
+def _ConvertSourcesToFilterHierarchy(sources, prefix=None, excluded=None,
+                                     list_excluded=True):
+  """Converts a list split source file paths into a vcproj folder hierarchy.
+
+  Arguments:
+    sources: A list of source file paths split.
+    prefix: A list of source file path layers meant to apply to each of sources.
+    excluded: A set of excluded files.
+
+  Returns:
+    A hierarchy of filenames and MSVSProject.Filter objects that matches the
+    layout of the source tree.
+    For example:
+    _ConvertSourcesToFilterHierarchy([['a', 'bob1.c'], ['b', 'bob2.c']],
+                                     prefix=['joe'])
+    -->
+    [MSVSProject.Filter('a', contents=['joe\\a\\bob1.c']),
+     MSVSProject.Filter('b', contents=['joe\\b\\bob2.c'])]
+  """
+  if not prefix: prefix = []
+  result = []
+  excluded_result = []
+  folders = dict()
+  # Gather files into the final result, excluded, or folders.
+  for s in sources:
+    if len(s) == 1:
+      filename = _NormalizedSource('\\'.join(prefix + s))
+      if filename in excluded:
+        excluded_result.append(filename)
+      else:
+        result.append(filename)
+    else:
+      if not folders.get(s[0]):
+        folders[s[0]] = []
+      folders[s[0]].append(s[1:])
+  # Add a folder for excluded files.
+  if excluded_result and list_excluded:
+    excluded_folder = MSVSProject.Filter('_excluded_files',
+                                         contents=excluded_result)
+    result.append(excluded_folder)
+  # Populate all the folders.
+  for f in folders:
+    contents = _ConvertSourcesToFilterHierarchy(folders[f], prefix=prefix + [f],
+                                                excluded=excluded,
+                                                list_excluded=list_excluded)
+    contents = MSVSProject.Filter(f, contents=contents)
+    result.append(contents)
+
+  return result
+
+
+def _ToolAppend(tools, tool_name, setting, value, only_if_unset=False):
+  if not value: return
+  _ToolSetOrAppend(tools, tool_name, setting, value, only_if_unset)
+
+
+def _ToolSetOrAppend(tools, tool_name, setting, value, only_if_unset=False):
+  # TODO(bradnelson): ugly hack, fix this more generally!!!
+  if 'Directories' in setting or 'Dependencies' in setting:
+    if type(value) == str:
+      value = value.replace('/', '\\')
+    else:
+      value = [i.replace('/', '\\') for i in value]
+  if not tools.get(tool_name):
+    tools[tool_name] = dict()
+  tool = tools[tool_name]
+  if tool.get(setting):
+    if only_if_unset: return
+    if type(tool[setting]) == list:
+      tool[setting] += value
+    else:
+      raise TypeError(
+          'Appending "%s" to a non-list setting "%s" for tool "%s" is '
+          'not allowed, previous value: %s' % (
+              value, setting, tool_name, str(tool[setting])))
+  else:
+    tool[setting] = value
+
+
+def _ConfigPlatform(config_data):
+  return config_data.get('msvs_configuration_platform', 'Win32')
+
+
+def _ConfigBaseName(config_name, platform_name):
+  if config_name.endswith('_' + platform_name):
+    return config_name[0:-len(platform_name) - 1]
+  else:
+    return config_name
+
+
+def _ConfigFullName(config_name, config_data):
+  platform_name = _ConfigPlatform(config_data)
+  return '%s|%s' % (_ConfigBaseName(config_name, platform_name), platform_name)
+
+
+def _BuildCommandLineForRuleRaw(spec, cmd, cygwin_shell, has_input_path,
+                                quote_cmd, do_setup_env):
+
+  if [x for x in cmd if '$(InputDir)' in x]:
+    input_dir_preamble = (
+      'set INPUTDIR=$(InputDir)\n'
+      'set INPUTDIR=%INPUTDIR:$(ProjectDir)=%\n'
+      'set INPUTDIR=%INPUTDIR:~0,-1%\n'
+      )
+  else:
+    input_dir_preamble = ''
+
+  if cygwin_shell:
+    # Find path to cygwin.
+    cygwin_dir = _FixPath(spec.get('msvs_cygwin_dirs', ['.'])[0])
+    # Prepare command.
+    direct_cmd = cmd
+    direct_cmd = [i.replace('$(IntDir)',
+                            '`cygpath -m "${INTDIR}"`') for i in direct_cmd]
+    direct_cmd = [i.replace('$(OutDir)',
+                            '`cygpath -m "${OUTDIR}"`') for i in direct_cmd]
+    direct_cmd = [i.replace('$(InputDir)',
+                            '`cygpath -m "${INPUTDIR}"`') for i in direct_cmd]
+    if has_input_path:
+      direct_cmd = [i.replace('$(InputPath)',
+                              '`cygpath -m "${INPUTPATH}"`')
+                    for i in direct_cmd]
+    direct_cmd = ['\\"%s\\"' % i.replace('"', '\\\\\\"') for i in direct_cmd]
+    # direct_cmd = gyp.common.EncodePOSIXShellList(direct_cmd)
+    direct_cmd = ' '.join(direct_cmd)
+    # TODO(quote):  regularize quoting path names throughout the module
+    cmd = ''
+    if do_setup_env:
+      cmd += 'call "$(ProjectDir)%(cygwin_dir)s\\setup_env.bat" && '
+    cmd += 'set CYGWIN=nontsec&& '
+    if direct_cmd.find('NUMBER_OF_PROCESSORS') >= 0:
+      cmd += 'set /a NUMBER_OF_PROCESSORS_PLUS_1=%%NUMBER_OF_PROCESSORS%%+1&& '
+    if direct_cmd.find('INTDIR') >= 0:
+      cmd += 'set INTDIR=$(IntDir)&& '
+    if direct_cmd.find('OUTDIR') >= 0:
+      cmd += 'set OUTDIR=$(OutDir)&& '
+    if has_input_path and direct_cmd.find('INPUTPATH') >= 0:
+      cmd += 'set INPUTPATH=$(InputPath) && '
+    cmd += 'bash -c "%(cmd)s"'
+    cmd = cmd % {'cygwin_dir': cygwin_dir,
+                 'cmd': direct_cmd}
+    return input_dir_preamble + cmd
+  else:
+    # Convert cat --> type to mimic unix.
+    if cmd[0] == 'cat':
+      command = ['type']
+    else:
+      command = [cmd[0].replace('/', '\\')]
+    # Add call before command to ensure that commands can be tied together one
+    # after the other without aborting in Incredibuild, since IB makes a bat
+    # file out of the raw command string, and some commands (like python) are
+    # actually batch files themselves.
+    command.insert(0, 'call')
+    # Fix the paths
+    # TODO(quote): This is a really ugly heuristic, and will miss path fixing
+    #              for arguments like "--arg=path" or "/opt:path".
+    # If the argument starts with a slash or dash, it's probably a command line
+    # switch
+    arguments = [i if (i[:1] in "/-") else _FixPath(i) for i in cmd[1:]]
+    arguments = [i.replace('$(InputDir)', '%INPUTDIR%') for i in arguments]
+    arguments = [MSVSSettings.FixVCMacroSlashes(i) for i in arguments]
+    if quote_cmd:
+      # Support a mode for using cmd directly.
+      # Convert any paths to native form (first element is used directly).
+      # TODO(quote):  regularize quoting path names throughout the module
+      arguments = ['"%s"' % i for i in arguments]
+    # Collapse into a single command.
+    return input_dir_preamble + ' '.join(command + arguments)
+
+
+def _BuildCommandLineForRule(spec, rule, has_input_path, do_setup_env):
+  # Currently this weird argument munging is used to duplicate the way a
+  # python script would need to be run as part of the chrome tree.
+  # Eventually we should add some sort of rule_default option to set this
+  # per project. For now the behavior chrome needs is the default.
+  mcs = rule.get('msvs_cygwin_shell')
+  if mcs is None:
+    mcs = int(spec.get('msvs_cygwin_shell', 1))
+  elif isinstance(mcs, str):
+    mcs = int(mcs)
+  quote_cmd = int(rule.get('msvs_quote_cmd', 1))
+  return _BuildCommandLineForRuleRaw(spec, rule['action'], mcs, has_input_path,
+                                     quote_cmd, do_setup_env=do_setup_env)
+
+
+def _AddActionStep(actions_dict, inputs, outputs, description, command):
+  """Merge action into an existing list of actions.
+
+  Care must be taken so that actions which have overlapping inputs either don't
+  get assigned to the same input, or get collapsed into one.
+
+  Arguments:
+    actions_dict: dictionary keyed on input name, which maps to a list of
+      dicts describing the actions attached to that input file.
+    inputs: list of inputs
+    outputs: list of outputs
+    description: description of the action
+    command: command line to execute
+  """
+  # Require there to be at least one input (call sites will ensure this).
+  assert inputs
+
+  action = {
+      'inputs': inputs,
+      'outputs': outputs,
+      'description': description,
+      'command': command,
+  }
+
+  # Pick where to stick this action.
+  # While less than optimal in terms of build time, attach them to the first
+  # input for now.
+  chosen_input = inputs[0]
+
+  # Add it there.
+  if chosen_input not in actions_dict:
+    actions_dict[chosen_input] = []
+  actions_dict[chosen_input].append(action)
+
+
+def _AddCustomBuildToolForMSVS(p, spec, primary_input,
+                               inputs, outputs, description, cmd):
+  """Add a custom build tool to execute something.
+
+  Arguments:
+    p: the target project
+    spec: the target project dict
+    primary_input: input file to attach the build tool to
+    inputs: list of inputs
+    outputs: list of outputs
+    description: description of the action
+    cmd: command line to execute
+  """
+  inputs = _FixPaths(inputs)
+  outputs = _FixPaths(outputs)
+  tool = MSVSProject.Tool(
+      'VCCustomBuildTool',
+      {'Description': description,
+       'AdditionalDependencies': ';'.join(inputs),
+       'Outputs': ';'.join(outputs),
+       'CommandLine': cmd,
+      })
+  # Add to the properties of primary input for each config.
+  for config_name, c_data in spec['configurations'].iteritems():
+    p.AddFileConfig(_FixPath(primary_input),
+                    _ConfigFullName(config_name, c_data), tools=[tool])
+
+
+def _AddAccumulatedActionsToMSVS(p, spec, actions_dict):
+  """Add actions accumulated into an actions_dict, merging as needed.
+
+  Arguments:
+    p: the target project
+    spec: the target project dict
+    actions_dict: dictionary keyed on input name, which maps to a list of
+        dicts describing the actions attached to that input file.
+  """
+  for primary_input in actions_dict:
+    inputs = set()
+    outputs = set()
+    descriptions = []
+    commands = []
+    for action in actions_dict[primary_input]:
+      inputs.update(set(action['inputs']))
+      outputs.update(set(action['outputs']))
+      descriptions.append(action['description'])
+      commands.append(action['command'])
+    # Add the custom build step for one input file.
+    description = ', and also '.join(descriptions)
+    command = '\r\n'.join(commands)
+    _AddCustomBuildToolForMSVS(p, spec,
+                               primary_input=primary_input,
+                               inputs=inputs,
+                               outputs=outputs,
+                               description=description,
+                               cmd=command)
+
+
+def _RuleExpandPath(path, input_file):
+  """Given the input file to which a rule applied, string substitute a path.
+
+  Arguments:
+    path: a path to string expand
+    input_file: the file to which the rule applied.
+  Returns:
+    The string substituted path.
+  """
+  path = path.replace('$(InputName)',
+                      os.path.splitext(os.path.split(input_file)[1])[0])
+  path = path.replace('$(InputDir)', os.path.dirname(input_file))
+  path = path.replace('$(InputExt)',
+                      os.path.splitext(os.path.split(input_file)[1])[1])
+  path = path.replace('$(InputFileName)', os.path.split(input_file)[1])
+  path = path.replace('$(InputPath)', input_file)
+  return path
+
+
+def _FindRuleTriggerFiles(rule, sources):
+  """Find the list of files which a particular rule applies to.
+
+  Arguments:
+    rule: the rule in question
+    sources: the set of all known source files for this project
+  Returns:
+    The list of sources that trigger a particular rule.
+  """
+  rule_ext = rule['extension']
+  return [s for s in sources if s.endswith('.' + rule_ext)]
+
+
+def _RuleInputsAndOutputs(rule, trigger_file):
+  """Find the inputs and outputs generated by a rule.
+
+  Arguments:
+    rule: the rule in question.
+    trigger_file: the main trigger for this rule.
+  Returns:
+    The pair of (inputs, outputs) involved in this rule.
+  """
+  raw_inputs = _FixPaths(rule.get('inputs', []))
+  raw_outputs = _FixPaths(rule.get('outputs', []))
+  inputs = set()
+  outputs = set()
+  inputs.add(trigger_file)
+  for i in raw_inputs:
+    inputs.add(_RuleExpandPath(i, trigger_file))
+  for o in raw_outputs:
+    outputs.add(_RuleExpandPath(o, trigger_file))
+  return (inputs, outputs)
+
+
+def _GenerateNativeRulesForMSVS(p, rules, output_dir, spec, options):
+  """Generate a native rules file.
+
+  Arguments:
+    p: the target project
+    rules: the set of rules to include
+    output_dir: the directory in which the project/gyp resides
+    spec: the project dict
+    options: global generator options
+  """
+  rules_filename = '%s%s.rules' % (spec['target_name'],
+                                   options.suffix)
+  rules_file = MSVSToolFile.Writer(os.path.join(output_dir, rules_filename),
+                                   spec['target_name'])
+  # Add each rule.
+  for r in rules:
+    rule_name = r['rule_name']
+    rule_ext = r['extension']
+    inputs = _FixPaths(r.get('inputs', []))
+    outputs = _FixPaths(r.get('outputs', []))
+    # Skip a rule with no action and no inputs.
+    if 'action' not in r and not r.get('rule_sources', []):
+      continue
+    cmd = _BuildCommandLineForRule(spec, r, has_input_path=True,
+                                   do_setup_env=True)
+    rules_file.AddCustomBuildRule(name=rule_name,
+                                  description=r.get('message', rule_name),
+                                  extensions=[rule_ext],
+                                  additional_dependencies=inputs,
+                                  outputs=outputs,
+                                  cmd=cmd)
+  # Write out rules file.
+  rules_file.WriteIfChanged()
+
+  # Add rules file to project.
+  p.AddToolFile(rules_filename)
+
+
+def _Cygwinify(path):
+  path = path.replace('$(OutDir)', '$(OutDirCygwin)')
+  path = path.replace('$(IntDir)', '$(IntDirCygwin)')
+  return path
+
+
+def _GenerateExternalRules(rules, output_dir, spec,
+                           sources, options, actions_to_add):
+  """Generate an external makefile to do a set of rules.
+
+  Arguments:
+    rules: the list of rules to include
+    output_dir: path containing project and gyp files
+    spec: project specification data
+    sources: set of sources known
+    options: global generator options
+    actions_to_add: The list of actions we will add to.
+  """
+  filename = '%s_rules%s.mk' % (spec['target_name'], options.suffix)
+  mk_file = gyp.common.WriteOnDiff(os.path.join(output_dir, filename))
+  # Find cygwin style versions of some paths.
+  mk_file.write('OutDirCygwin:=$(shell cygpath -u "$(OutDir)")\n')
+  mk_file.write('IntDirCygwin:=$(shell cygpath -u "$(IntDir)")\n')
+  # Gather stuff needed to emit all: target.
+  all_inputs = set()
+  all_outputs = set()
+  all_output_dirs = set()
+  first_outputs = []
+  for rule in rules:
+    trigger_files = _FindRuleTriggerFiles(rule, sources)
+    for tf in trigger_files:
+      inputs, outputs = _RuleInputsAndOutputs(rule, tf)
+      all_inputs.update(set(inputs))
+      all_outputs.update(set(outputs))
+      # Only use one target from each rule as the dependency for
+      # 'all' so we don't try to build each rule multiple times.
+      first_outputs.append(list(outputs)[0])
+      # Get the unique output directories for this rule.
+      output_dirs = [os.path.split(i)[0] for i in outputs]
+      for od in output_dirs:
+        all_output_dirs.add(od)
+  first_outputs_cyg = [_Cygwinify(i) for i in first_outputs]
+  # Write out all: target, including mkdir for each output directory.
+  mk_file.write('all: %s\n' % ' '.join(first_outputs_cyg))
+  for od in all_output_dirs:
+    if od:
+      mk_file.write('\tmkdir -p `cygpath -u "%s"`\n' % od)
+  mk_file.write('\n')
+  # Define how each output is generated.
+  for rule in rules:
+    trigger_files = _FindRuleTriggerFiles(rule, sources)
+    for tf in trigger_files:
+      # Get all the inputs and outputs for this rule for this trigger file.
+      inputs, outputs = _RuleInputsAndOutputs(rule, tf)
+      inputs = [_Cygwinify(i) for i in inputs]
+      outputs = [_Cygwinify(i) for i in outputs]
+      # Prepare the command line for this rule.
+      cmd = [_RuleExpandPath(c, tf) for c in rule['action']]
+      cmd = ['"%s"' % i for i in cmd]
+      cmd = ' '.join(cmd)
+      # Add it to the makefile.
+      mk_file.write('%s: %s\n' % (' '.join(outputs), ' '.join(inputs)))
+      mk_file.write('\t%s\n\n' % cmd)
+  # Close up the file.
+  mk_file.close()
+
+  # Add makefile to list of sources.
+  sources.add(filename)
+  # Add a build action to call makefile.
+  cmd = ['make',
+         'OutDir=$(OutDir)',
+         'IntDir=$(IntDir)',
+         '-j', '${NUMBER_OF_PROCESSORS_PLUS_1}',
+         '-f', filename]
+  cmd = _BuildCommandLineForRuleRaw(spec, cmd, True, False, True, True)
+  # Insert makefile as 0'th input, so it gets the action attached there,
+  # as this is easier to understand from in the IDE.
+  all_inputs = list(all_inputs)
+  all_inputs.insert(0, filename)
+  _AddActionStep(actions_to_add,
+                 inputs=_FixPaths(all_inputs),
+                 outputs=_FixPaths(all_outputs),
+                 description='Running external rules for %s' %
+                     spec['target_name'],
+                 command=cmd)
+
+
+def _EscapeEnvironmentVariableExpansion(s):
+  """Escapes % characters.
+
+  Escapes any % characters so that Windows-style environment variable
+  expansions will leave them alone.
+  See http://connect.microsoft.com/VisualStudio/feedback/details/106127/cl-d-name-text-containing-percentage-characters-doesnt-compile
+  to understand why we have to do this.
+
+  Args:
+      s: The string to be escaped.
+
+  Returns:
+      The escaped string.
+  """
+  s = s.replace('%', '%%')
+  return s
+
+
+quote_replacer_regex = re.compile(r'(\\*)"')
+
+
+def _EscapeCommandLineArgumentForMSVS(s):
+  """Escapes a Windows command-line argument.
+
+  So that the Win32 CommandLineToArgv function will turn the escaped result back
+  into the original string.
+  See http://msdn.microsoft.com/en-us/library/17w5ykft.aspx
+  ("Parsing C++ Command-Line Arguments") to understand why we have to do
+  this.
+
+  Args:
+      s: the string to be escaped.
+  Returns:
+      the escaped string.
+  """
+
+  def _Replace(match):
+    # For a literal quote, CommandLineToArgv requires an odd number of
+    # backslashes preceding it, and it produces half as many literal backslashes
+    # (rounded down). So we need to produce 2n+1 backslashes.
+    return 2 * match.group(1) + '\\"'
+
+  # Escape all quotes so that they are interpreted literally.
+  s = quote_replacer_regex.sub(_Replace, s)
+  # Now add unescaped quotes so that any whitespace is interpreted literally.
+  s = '"' + s + '"'
+  return s
+
+
+delimiters_replacer_regex = re.compile(r'(\\*)([,;]+)')
+
+
+def _EscapeVCProjCommandLineArgListItem(s):
+  """Escapes command line arguments for MSVS.
+
+  The VCProj format stores string lists in a single string using commas and
+  semi-colons as separators, which must be quoted if they are to be
+  interpreted literally. However, command-line arguments may already have
+  quotes, and the VCProj parser is ignorant of the backslash escaping
+  convention used by CommandLineToArgv, so the command-line quotes and the
+  VCProj quotes may not be the same quotes. So to store a general
+  command-line argument in a VCProj list, we need to parse the existing
+  quoting according to VCProj's convention and quote any delimiters that are
+  not already quoted by that convention. The quotes that we add will also be
+  seen by CommandLineToArgv, so if backslashes precede them then we also have
+  to escape those backslashes according to the CommandLineToArgv
+  convention.
+
+  Args:
+      s: the string to be escaped.
+  Returns:
+      the escaped string.
+  """
+
+  def _Replace(match):
+    # For a non-literal quote, CommandLineToArgv requires an even number of
+    # backslashes preceding it, and it produces half as many literal
+    # backslashes. So we need to produce 2n backslashes.
+    return 2 * match.group(1) + '"' + match.group(2) + '"'
+
+  segments = s.split('"')
+  # The unquoted segments are at the even-numbered indices.
+  for i in range(0, len(segments), 2):
+    segments[i] = delimiters_replacer_regex.sub(_Replace, segments[i])
+  # Concatenate back into a single string
+  s = '"'.join(segments)
+  if len(segments) % 2 == 0:
+    # String ends while still quoted according to VCProj's convention. This
+    # means the delimiter and the next list item that follow this one in the
+    # .vcproj file will be misinterpreted as part of this item. There is nothing
+    # we can do about this. Adding an extra quote would correct the problem in
+    # the VCProj but cause the same problem on the final command-line. Moving
+    # the item to the end of the list does works, but that's only possible if
+    # there's only one such item. Let's just warn the user.
+    print >> sys.stderr, ('Warning: MSVS may misinterpret the odd number of ' +
+                          'quotes in ' + s)
+  return s
+
+
+def _EscapeCppDefineForMSVS(s):
+  """Escapes a CPP define so that it will reach the compiler unaltered."""
+  s = _EscapeEnvironmentVariableExpansion(s)
+  s = _EscapeCommandLineArgumentForMSVS(s)
+  s = _EscapeVCProjCommandLineArgListItem(s)
+  # cl.exe replaces literal # characters with = in preprocesor definitions for
+  # some reason. Octal-encode to work around that.
+  s = s.replace('#', '\\%03o' % ord('#'))
+  return s
+
+
+quote_replacer_regex2 = re.compile(r'(\\+)"')
+
+
+def _EscapeCommandLineArgumentForMSBuild(s):
+  """Escapes a Windows command-line argument for use by MSBuild."""
+
+  def _Replace(match):
+    return (len(match.group(1)) / 2 * 4) * '\\' + '\\"'
+
+  # Escape all quotes so that they are interpreted literally.
+  s = quote_replacer_regex2.sub(_Replace, s)
+  return s
+
+
+def _EscapeMSBuildSpecialCharacters(s):
+  escape_dictionary = {
+      '%': '%25',
+      '$': '%24',
+      '@': '%40',
+      "'": '%27',
+      ';': '%3B',
+      '?': '%3F',
+      '*': '%2A'
+      }
+  result = ''.join([escape_dictionary.get(c, c) for c in s])
+  return result
+
+
+def _EscapeCppDefineForMSBuild(s):
+  """Escapes a CPP define so that it will reach the compiler unaltered."""
+  s = _EscapeEnvironmentVariableExpansion(s)
+  s = _EscapeCommandLineArgumentForMSBuild(s)
+  s = _EscapeMSBuildSpecialCharacters(s)
+  # cl.exe replaces literal # characters with = in preprocesor definitions for
+  # some reason. Octal-encode to work around that.
+  s = s.replace('#', '\\%03o' % ord('#'))
+  return s
+
+
+def _GenerateRulesForMSVS(p, output_dir, options, spec,
+                          sources, excluded_sources,
+                          actions_to_add):
+  """Generate all the rules for a particular project.
+
+  Arguments:
+    p: the project
+    output_dir: directory to emit rules to
+    options: global options passed to the generator
+    spec: the specification for this project
+    sources: the set of all known source files in this project
+    excluded_sources: the set of sources excluded from normal processing
+    actions_to_add: deferred list of actions to add in
+  """
+  rules = spec.get('rules', [])
+  rules_native = [r for r in rules if not int(r.get('msvs_external_rule', 0))]
+  rules_external = [r for r in rules if int(r.get('msvs_external_rule', 0))]
+
+  # Handle rules that use a native rules file.
+  if rules_native:
+    _GenerateNativeRulesForMSVS(p, rules_native, output_dir, spec, options)
+
+  # Handle external rules (non-native rules).
+  if rules_external:
+    _GenerateExternalRules(rules_external, output_dir, spec,
+                           sources, options, actions_to_add)
+  _AdjustSourcesForRules(rules, sources, excluded_sources)
+
+
+def _AdjustSourcesForRules(rules, sources, excluded_sources):
+  # Add outputs generated by each rule (if applicable).
+  for rule in rules:
+    # Done if not processing outputs as sources.
+    if int(rule.get('process_outputs_as_sources', False)):
+      # Add in the outputs from this rule.
+      trigger_files = _FindRuleTriggerFiles(rule, sources)
+      for trigger_file in trigger_files:
+        inputs, outputs = _RuleInputsAndOutputs(rule, trigger_file)
+        inputs = set(_FixPaths(inputs))
+        outputs = set(_FixPaths(outputs))
+        inputs.remove(_FixPath(trigger_file))
+        sources.update(inputs)
+        excluded_sources.update(inputs)
+        sources.update(outputs)
+
+
+def _FilterActionsFromExcluded(excluded_sources, actions_to_add):
+  """Take inputs with actions attached out of the list of exclusions.
+
+  Arguments:
+    excluded_sources: list of source files not to be built.
+    actions_to_add: dict of actions keyed on source file they're attached to.
+  Returns:
+    excluded_sources with files that have actions attached removed.
+  """
+  must_keep = set(_FixPaths(actions_to_add.keys()))
+  return [s for s in excluded_sources if s not in must_keep]
+
+
+def _GetDefaultConfiguration(spec):
+  return spec['configurations'][spec['default_configuration']]
+
+
+def _GetGuidOfProject(proj_path, spec):
+  """Get the guid for the project.
+
+  Arguments:
+    proj_path: Path of the vcproj or vcxproj file to generate.
+    spec: The target dictionary containing the properties of the target.
+  Returns:
+    the guid.
+  Raises:
+    ValueError: if the specified GUID is invalid.
+  """
+  # Pluck out the default configuration.
+  default_config = _GetDefaultConfiguration(spec)
+  # Decide the guid of the project.
+  guid = default_config.get('msvs_guid')
+  if guid:
+    if VALID_MSVS_GUID_CHARS.match(guid) is None:
+      raise ValueError('Invalid MSVS guid: "%s".  Must match regex: "%s".' %
+                       (guid, VALID_MSVS_GUID_CHARS.pattern))
+    guid = '{%s}' % guid
+  guid = guid or MSVSNew.MakeGuid(proj_path)
+  return guid
+
+
+def _GetMsbuildToolsetOfProject(proj_path, spec, version):
+  """Get the platform toolset for the project.
+
+  Arguments:
+    proj_path: Path of the vcproj or vcxproj file to generate.
+    spec: The target dictionary containing the properties of the target.
+    version: The MSVSVersion object.
+  Returns:
+    the platform toolset string or None.
+  """
+  # Pluck out the default configuration.
+  default_config = _GetDefaultConfiguration(spec)
+  toolset = default_config.get('msbuild_toolset')
+  if not toolset and version.DefaultToolset():
+    toolset = version.DefaultToolset()
+  return toolset
+
+
+def _GenerateProject(project, options, version, generator_flags):
+  """Generates a vcproj file.
+
+  Arguments:
+    project: the MSVSProject object.
+    options: global generator options.
+    version: the MSVSVersion object.
+    generator_flags: dict of generator-specific flags.
+  Returns:
+    A list of source files that cannot be found on disk.
+  """
+  default_config = _GetDefaultConfiguration(project.spec)
+
+  # Skip emitting anything if told to with msvs_existing_vcproj option.
+  if default_config.get('msvs_existing_vcproj'):
+    return []
+
+  if version.UsesVcxproj():
+    return _GenerateMSBuildProject(project, options, version, generator_flags)
+  else:
+    return _GenerateMSVSProject(project, options, version, generator_flags)
+
+
+def _GenerateMSVSProject(project, options, version, generator_flags):
+  """Generates a .vcproj file.  It may create .rules and .user files too.
+
+  Arguments:
+    project: The project object we will generate the file for.
+    options: Global options passed to the generator.
+    version: The VisualStudioVersion object.
+    generator_flags: dict of generator-specific flags.
+  """
+  spec = project.spec
+  vcproj_dir = os.path.dirname(project.path)
+  if vcproj_dir and not os.path.exists(vcproj_dir):
+    os.makedirs(vcproj_dir)
+
+  platforms = _GetUniquePlatforms(spec)
+  p = MSVSProject.Writer(project.path, version, spec['target_name'],
+                         project.guid, platforms)
+
+  # Get directory project file is in.
+  project_dir = os.path.split(project.path)[0]
+  gyp_path = _NormalizedSource(project.build_file)
+  relative_path_of_gyp_file = gyp.common.RelativePath(gyp_path, project_dir)
+
+  config_type = _GetMSVSConfigurationType(spec, project.build_file)
+  for config_name, config in spec['configurations'].iteritems():
+    _AddConfigurationToMSVSProject(p, spec, config_type, config_name, config)
+
+  # Prepare list of sources and excluded sources.
+  gyp_file = os.path.split(project.build_file)[1]
+  sources, excluded_sources = _PrepareListOfSources(spec, generator_flags,
+                                                    gyp_file)
+
+  # Add rules.
+  actions_to_add = {}
+  _GenerateRulesForMSVS(p, project_dir, options, spec,
+                        sources, excluded_sources,
+                        actions_to_add)
+  list_excluded = generator_flags.get('msvs_list_excluded_files', True)
+  sources, excluded_sources, excluded_idl = (
+      _AdjustSourcesAndConvertToFilterHierarchy(
+          spec, options, project_dir, sources, excluded_sources, list_excluded))
+
+  # Add in files.
+  missing_sources = _VerifySourcesExist(sources, project_dir)
+  p.AddFiles(sources)
+
+  _AddToolFilesToMSVS(p, spec)
+  _HandlePreCompiledHeaders(p, sources, spec)
+  _AddActions(actions_to_add, spec, relative_path_of_gyp_file)
+  _AddCopies(actions_to_add, spec)
+  _WriteMSVSUserFile(project.path, version, spec)
+
+  # NOTE: this stanza must appear after all actions have been decided.
+  # Don't excluded sources with actions attached, or they won't run.
+  excluded_sources = _FilterActionsFromExcluded(
+      excluded_sources, actions_to_add)
+  _ExcludeFilesFromBeingBuilt(p, spec, excluded_sources, excluded_idl,
+                              list_excluded)
+  _AddAccumulatedActionsToMSVS(p, spec, actions_to_add)
+
+  # Write it out.
+  p.WriteIfChanged()
+
+  return missing_sources
+
+
+def _GetUniquePlatforms(spec):
+  """Returns the list of unique platforms for this spec, e.g ['win32', ...].
+
+  Arguments:
+    spec: The target dictionary containing the properties of the target.
+  Returns:
+    The MSVSUserFile object created.
+  """
+  # Gather list of unique platforms.
+  platforms = set()
+  for configuration in spec['configurations']:
+    platforms.add(_ConfigPlatform(spec['configurations'][configuration]))
+  platforms = list(platforms)
+  return platforms
+
+
+def _CreateMSVSUserFile(proj_path, version, spec):
+  """Generates a .user file for the user running this Gyp program.
+
+  Arguments:
+    proj_path: The path of the project file being created.  The .user file
+               shares the same path (with an appropriate suffix).
+    version: The VisualStudioVersion object.
+    spec: The target dictionary containing the properties of the target.
+  Returns:
+    The MSVSUserFile object created.
+  """
+  (domain, username) = _GetDomainAndUserName()
+  vcuser_filename = '.'.join([proj_path, domain, username, 'user'])
+  user_file = MSVSUserFile.Writer(vcuser_filename, version,
+                                  spec['target_name'])
+  return user_file
+
+
+def _GetMSVSConfigurationType(spec, build_file):
+  """Returns the configuration type for this project.
+
+  It's a number defined by Microsoft.  May raise an exception.
+
+  Args:
+      spec: The target dictionary containing the properties of the target.
+      build_file: The path of the gyp file.
+  Returns:
+      An integer, the configuration type.
+  """
+  try:
+    config_type = {
+        'executable': '1',  # .exe
+        'shared_library': '2',  # .dll
+        'loadable_module': '2',  # .dll
+        'static_library': '4',  # .lib
+        'none': '10',  # Utility type
+        }[spec['type']]
+  except KeyError:
+    if spec.get('type'):
+      raise GypError('Target type %s is not a valid target type for '
+                     'target %s in %s.' %
+                     (spec['type'], spec['target_name'], build_file))
+    else:
+      raise GypError('Missing type field for target %s in %s.' %
+                     (spec['target_name'], build_file))
+  return config_type
+
+
+def _AddConfigurationToMSVSProject(p, spec, config_type, config_name, config):
+  """Adds a configuration to the MSVS project.
+
+  Many settings in a vcproj file are specific to a configuration.  This
+  function the main part of the vcproj file that's configuration specific.
+
+  Arguments:
+    p: The target project being generated.
+    spec: The target dictionary containing the properties of the target.
+    config_type: The configuration type, a number as defined by Microsoft.
+    config_name: The name of the configuration.
+    config: The dictionnary that defines the special processing to be done
+            for this configuration.
+  """
+  # Get the information for this configuration
+  include_dirs, resource_include_dirs = _GetIncludeDirs(config)
+  libraries = _GetLibraries(spec)
+  out_file, vc_tool, _ = _GetOutputFilePathAndTool(spec, msbuild=False)
+  defines = _GetDefines(config)
+  defines = [_EscapeCppDefineForMSVS(d) for d in defines]
+  disabled_warnings = _GetDisabledWarnings(config)
+  prebuild = config.get('msvs_prebuild')
+  postbuild = config.get('msvs_postbuild')
+  def_file = _GetModuleDefinition(spec)
+  precompiled_header = config.get('msvs_precompiled_header')
+
+  # Prepare the list of tools as a dictionary.
+  tools = dict()
+  # Add in user specified msvs_settings.
+  msvs_settings = config.get('msvs_settings', {})
+  MSVSSettings.ValidateMSVSSettings(msvs_settings)
+
+  # Prevent default library inheritance from the environment.
+  _ToolAppend(tools, 'VCLinkerTool', 'AdditionalDependencies', ['$(NOINHERIT)'])
+
+  for tool in msvs_settings:
+    settings = config['msvs_settings'][tool]
+    for setting in settings:
+      _ToolAppend(tools, tool, setting, settings[setting])
+  # Add the information to the appropriate tool
+  _ToolAppend(tools, 'VCCLCompilerTool',
+              'AdditionalIncludeDirectories', include_dirs)
+  _ToolAppend(tools, 'VCResourceCompilerTool',
+              'AdditionalIncludeDirectories', resource_include_dirs)
+  # Add in libraries.
+  _ToolAppend(tools, 'VCLinkerTool', 'AdditionalDependencies', libraries)
+  if out_file:
+    _ToolAppend(tools, vc_tool, 'OutputFile', out_file, only_if_unset=True)
+  # Add defines.
+  _ToolAppend(tools, 'VCCLCompilerTool', 'PreprocessorDefinitions', defines)
+  _ToolAppend(tools, 'VCResourceCompilerTool', 'PreprocessorDefinitions',
+              defines)
+  # Change program database directory to prevent collisions.
+  _ToolAppend(tools, 'VCCLCompilerTool', 'ProgramDataBaseFileName',
+              '$(IntDir)$(ProjectName)\\vc80.pdb', only_if_unset=True)
+  # Add disabled warnings.
+  _ToolAppend(tools, 'VCCLCompilerTool',
+              'DisableSpecificWarnings', disabled_warnings)
+  # Add Pre-build.
+  _ToolAppend(tools, 'VCPreBuildEventTool', 'CommandLine', prebuild)
+  # Add Post-build.
+  _ToolAppend(tools, 'VCPostBuildEventTool', 'CommandLine', postbuild)
+  # Turn on precompiled headers if appropriate.
+  if precompiled_header:
+    precompiled_header = os.path.split(precompiled_header)[1]
+    _ToolAppend(tools, 'VCCLCompilerTool', 'UsePrecompiledHeader', '2')
+    _ToolAppend(tools, 'VCCLCompilerTool',
+                'PrecompiledHeaderThrough', precompiled_header)
+    _ToolAppend(tools, 'VCCLCompilerTool',
+                'ForcedIncludeFiles', precompiled_header)
+  # Loadable modules don't generate import libraries;
+  # tell dependent projects to not expect one.
+  if spec['type'] == 'loadable_module':
+    _ToolAppend(tools, 'VCLinkerTool', 'IgnoreImportLibrary', 'true')
+  # Set the module definition file if any.
+  if def_file:
+    _ToolAppend(tools, 'VCLinkerTool', 'ModuleDefinitionFile', def_file)
+
+  _AddConfigurationToMSVS(p, spec, tools, config, config_type, config_name)
+
+
+def _GetIncludeDirs(config):
+  """Returns the list of directories to be used for #include directives.
+
+  Arguments:
+    config: The dictionnary that defines the special processing to be done
+            for this configuration.
+  Returns:
+    The list of directory paths.
+  """
+  # TODO(bradnelson): include_dirs should really be flexible enough not to
+  #                   require this sort of thing.
+  include_dirs = (
+      config.get('include_dirs', []) +
+      config.get('msvs_system_include_dirs', []))
+  resource_include_dirs = config.get('resource_include_dirs', include_dirs)
+  include_dirs = _FixPaths(include_dirs)
+  resource_include_dirs = _FixPaths(resource_include_dirs)
+  return include_dirs, resource_include_dirs
+
+
+def _GetLibraries(spec):
+  """Returns the list of libraries for this configuration.
+
+  Arguments:
+    spec: The target dictionary containing the properties of the target.
+  Returns:
+    The list of directory paths.
+  """
+  libraries = spec.get('libraries', [])
+  # Strip out -l, as it is not used on windows (but is needed so we can pass
+  # in libraries that are assumed to be in the default library path).
+  # Also remove duplicate entries, leaving only the last duplicate, while
+  # preserving order.
+  found = set()
+  unique_libraries_list = []
+  for entry in reversed(libraries):
+    library = re.sub('^\-l', '', entry)
+    if not os.path.splitext(library)[1]:
+      library += '.lib'
+    if library not in found:
+      found.add(library)
+      unique_libraries_list.append(library)
+  unique_libraries_list.reverse()
+  return unique_libraries_list
+
+
+def _GetOutputFilePathAndTool(spec, msbuild):
+  """Returns the path and tool to use for this target.
+
+  Figures out the path of the file this spec will create and the name of
+  the VC tool that will create it.
+
+  Arguments:
+    spec: The target dictionary containing the properties of the target.
+  Returns:
+    A triple of (file path, name of the vc tool, name of the msbuild tool)
+  """
+  # Select a name for the output file.
+  out_file = ''
+  vc_tool = ''
+  msbuild_tool = ''
+  output_file_map = {
+      'executable': ('VCLinkerTool', 'Link', '$(OutDir)', '.exe'),
+      'shared_library': ('VCLinkerTool', 'Link', '$(OutDir)', '.dll'),
+      'loadable_module': ('VCLinkerTool', 'Link', '$(OutDir)', '.dll'),
+      'static_library': ('VCLibrarianTool', 'Lib', '$(OutDir)lib\\', '.lib'),
+  }
+  output_file_props = output_file_map.get(spec['type'])
+  if output_file_props and int(spec.get('msvs_auto_output_file', 1)):
+    vc_tool, msbuild_tool, out_dir, suffix = output_file_props
+    if spec.get('standalone_static_library', 0):
+      out_dir = '$(OutDir)'
+    out_dir = spec.get('product_dir', out_dir)
+    product_extension = spec.get('product_extension')
+    if product_extension:
+      suffix = '.' + product_extension
+    elif msbuild:
+      suffix = '$(TargetExt)'
+    prefix = spec.get('product_prefix', '')
+    product_name = spec.get('product_name', '$(ProjectName)')
+    out_file = ntpath.join(out_dir, prefix + product_name + suffix)
+  return out_file, vc_tool, msbuild_tool
+
+
+def _GetDefines(config):
+  """Returns the list of preprocessor definitions for this configuation.
+
+  Arguments:
+    config: The dictionnary that defines the special processing to be done
+            for this configuration.
+  Returns:
+    The list of preprocessor definitions.
+  """
+  defines = []
+  for d in config.get('defines', []):
+    if type(d) == list:
+      fd = '='.join([str(dpart) for dpart in d])
+    else:
+      fd = str(d)
+    defines.append(fd)
+  return defines
+
+
+def _GetDisabledWarnings(config):
+  return [str(i) for i in config.get('msvs_disabled_warnings', [])]
+
+
+def _GetModuleDefinition(spec):
+  def_file = ''
+  if spec['type'] in ['shared_library', 'loadable_module', 'executable']:
+    def_files = [s for s in spec.get('sources', []) if s.endswith('.def')]
+    if len(def_files) == 1:
+      def_file = _FixPath(def_files[0])
+    elif def_files:
+      raise ValueError(
+          'Multiple module definition files in one target, target %s lists '
+          'multiple .def files: %s' % (
+              spec['target_name'], ' '.join(def_files)))
+  return def_file
+
+
+def _ConvertToolsToExpectedForm(tools):
+  """Convert tools to a form expected by Visual Studio.
+
+  Arguments:
+    tools: A dictionnary of settings; the tool name is the key.
+  Returns:
+    A list of Tool objects.
+  """
+  tool_list = []
+  for tool, settings in tools.iteritems():
+    # Collapse settings with lists.
+    settings_fixed = {}
+    for setting, value in settings.iteritems():
+      if type(value) == list:
+        if ((tool == 'VCLinkerTool' and
+             setting == 'AdditionalDependencies') or
+            setting == 'AdditionalOptions'):
+          settings_fixed[setting] = ' '.join(value)
+        else:
+          settings_fixed[setting] = ';'.join(value)
+      else:
+        settings_fixed[setting] = value
+    # Add in this tool.
+    tool_list.append(MSVSProject.Tool(tool, settings_fixed))
+  return tool_list
+
+
+def _AddConfigurationToMSVS(p, spec, tools, config, config_type, config_name):
+  """Add to the project file the configuration specified by config.
+
+  Arguments:
+    p: The target project being generated.
+    spec: the target project dict.
+    tools: A dictionnary of settings; the tool name is the key.
+    config: The dictionnary that defines the special processing to be done
+            for this configuration.
+    config_type: The configuration type, a number as defined by Microsoft.
+    config_name: The name of the configuration.
+  """
+  attributes = _GetMSVSAttributes(spec, config, config_type)
+  # Add in this configuration.
+  tool_list = _ConvertToolsToExpectedForm(tools)
+  p.AddConfig(_ConfigFullName(config_name, config),
+              attrs=attributes, tools=tool_list)
+
+
+def _GetMSVSAttributes(spec, config, config_type):
+  # Prepare configuration attributes.
+  prepared_attrs = {}
+  source_attrs = config.get('msvs_configuration_attributes', {})
+  for a in source_attrs:
+    prepared_attrs[a] = source_attrs[a]
+  # Add props files.
+  vsprops_dirs = config.get('msvs_props', [])
+  vsprops_dirs = _FixPaths(vsprops_dirs)
+  if vsprops_dirs:
+    prepared_attrs['InheritedPropertySheets'] = ';'.join(vsprops_dirs)
+  # Set configuration type.
+  prepared_attrs['ConfigurationType'] = config_type
+  output_dir = prepared_attrs.get('OutputDirectory',
+                                  '$(SolutionDir)$(ConfigurationName)')
+  prepared_attrs['OutputDirectory'] = _FixPath(output_dir) + '\\'
+  if 'IntermediateDirectory' not in prepared_attrs:
+    intermediate = '$(ConfigurationName)\\obj\\$(ProjectName)'
+    prepared_attrs['IntermediateDirectory'] = _FixPath(intermediate) + '\\'
+  else:
+    intermediate = _FixPath(prepared_attrs['IntermediateDirectory']) + '\\'
+    intermediate = MSVSSettings.FixVCMacroSlashes(intermediate)
+    prepared_attrs['IntermediateDirectory'] = intermediate
+  return prepared_attrs
+
+
+def _AddNormalizedSources(sources_set, sources_array):
+  sources = [_NormalizedSource(s) for s in sources_array]
+  sources_set.update(set(sources))
+
+
+def _PrepareListOfSources(spec, generator_flags, gyp_file):
+  """Prepare list of sources and excluded sources.
+
+  Besides the sources specified directly in the spec, adds the gyp file so
+  that a change to it will cause a re-compile. Also adds appropriate sources
+  for actions and copies. Assumes later stage will un-exclude files which
+  have custom build steps attached.
+
+  Arguments:
+    spec: The target dictionary containing the properties of the target.
+    gyp_file: The name of the gyp file.
+  Returns:
+    A pair of (list of sources, list of excluded sources).
+    The sources will be relative to the gyp file.
+  """
+  sources = set()
+  _AddNormalizedSources(sources, spec.get('sources', []))
+  excluded_sources = set()
+  # Add in the gyp file.
+  if not generator_flags.get('standalone'):
+    sources.add(gyp_file)
+
+  # Add in 'action' inputs and outputs.
+  for a in spec.get('actions', []):
+    inputs = a['inputs']
+    inputs = [_NormalizedSource(i) for i in inputs]
+    # Add all inputs to sources and excluded sources.
+    inputs = set(inputs)
+    sources.update(inputs)
+    excluded_sources.update(inputs)
+    if int(a.get('process_outputs_as_sources', False)):
+      _AddNormalizedSources(sources, a.get('outputs', []))
+  # Add in 'copies' inputs and outputs.
+  for cpy in spec.get('copies', []):
+    _AddNormalizedSources(sources, cpy.get('files', []))
+  return (sources, excluded_sources)
+
+
+def _AdjustSourcesAndConvertToFilterHierarchy(
+    spec, options, gyp_dir, sources, excluded_sources, list_excluded):
+  """Adjusts the list of sources and excluded sources.
+
+  Also converts the sets to lists.
+
+  Arguments:
+    spec: The target dictionary containing the properties of the target.
+    options: Global generator options.
+    gyp_dir: The path to the gyp file being processed.
+    sources: A set of sources to be included for this project.
+    excluded_sources: A set of sources to be excluded for this project.
+  Returns:
+    A trio of (list of sources, list of excluded sources,
+               path of excluded IDL file)
+  """
+  # Exclude excluded sources coming into the generator.
+  excluded_sources.update(set(spec.get('sources_excluded', [])))
+  # Add excluded sources into sources for good measure.
+  sources.update(excluded_sources)
+  # Convert to proper windows form.
+  # NOTE: sources goes from being a set to a list here.
+  # NOTE: excluded_sources goes from being a set to a list here.
+  sources = _FixPaths(sources)
+  # Convert to proper windows form.
+  excluded_sources = _FixPaths(excluded_sources)
+
+  excluded_idl = _IdlFilesHandledNonNatively(spec, sources)
+
+  precompiled_related = _GetPrecompileRelatedFiles(spec)
+  # Find the excluded ones, minus the precompiled header related ones.
+  fully_excluded = [i for i in excluded_sources if i not in precompiled_related]
+
+  # Convert to folders and the right slashes.
+  sources = [i.split('\\') for i in sources]
+  sources = _ConvertSourcesToFilterHierarchy(sources, excluded=fully_excluded,
+                                             list_excluded=list_excluded)
+
+  return sources, excluded_sources, excluded_idl
+
+
+def _IdlFilesHandledNonNatively(spec, sources):
+  # If any non-native rules use 'idl' as an extension exclude idl files.
+  # Gather a list here to use later.
+  using_idl = False
+  for rule in spec.get('rules', []):
+    if rule['extension'] == 'idl' and int(rule.get('msvs_external_rule', 0)):
+      using_idl = True
+      break
+  if using_idl:
+    excluded_idl = [i for i in sources if i.endswith('.idl')]
+  else:
+    excluded_idl = []
+  return excluded_idl
+
+
+def _GetPrecompileRelatedFiles(spec):
+  # Gather a list of precompiled header related sources.
+  precompiled_related = []
+  for _, config in spec['configurations'].iteritems():
+    for k in precomp_keys:
+      f = config.get(k)
+      if f:
+        precompiled_related.append(_FixPath(f))
+  return precompiled_related
+
+
+def _ExcludeFilesFromBeingBuilt(p, spec, excluded_sources, excluded_idl,
+                                list_excluded):
+  exclusions = _GetExcludedFilesFromBuild(spec, excluded_sources, excluded_idl)
+  for file_name, excluded_configs in exclusions.iteritems():
+    if (not list_excluded and
+            len(excluded_configs) == len(spec['configurations'])):
+      # If we're not listing excluded files, then they won't appear in the
+      # project, so don't try to configure them to be excluded.
+      pass
+    else:
+      for config_name, config in excluded_configs:
+        p.AddFileConfig(file_name, _ConfigFullName(config_name, config),
+                        {'ExcludedFromBuild': 'true'})
+
+
+def _GetExcludedFilesFromBuild(spec, excluded_sources, excluded_idl):
+  exclusions = {}
+  # Exclude excluded sources from being built.
+  for f in excluded_sources:
+    excluded_configs = []
+    for config_name, config in spec['configurations'].iteritems():
+      precomped = [_FixPath(config.get(i, '')) for i in precomp_keys]
+      # Don't do this for ones that are precompiled header related.
+      if f not in precomped:
+        excluded_configs.append((config_name, config))
+    exclusions[f] = excluded_configs
+  # If any non-native rules use 'idl' as an extension exclude idl files.
+  # Exclude them now.
+  for f in excluded_idl:
+    excluded_configs = []
+    for config_name, config in spec['configurations'].iteritems():
+      excluded_configs.append((config_name, config))
+    exclusions[f] = excluded_configs
+  return exclusions
+
+
+def _AddToolFilesToMSVS(p, spec):
+  # Add in tool files (rules).
+  tool_files = set()
+  for _, config in spec['configurations'].iteritems():
+    for f in config.get('msvs_tool_files', []):
+      tool_files.add(f)
+  for f in tool_files:
+    p.AddToolFile(f)
+
+
+def _HandlePreCompiledHeaders(p, sources, spec):
+  # Pre-compiled header source stubs need a different compiler flag
+  # (generate precompiled header) and any source file not of the same
+  # kind (i.e. C vs. C++) as the precompiled header source stub needs
+  # to have use of precompiled headers disabled.
+  extensions_excluded_from_precompile = []
+  for config_name, config in spec['configurations'].iteritems():
+    source = config.get('msvs_precompiled_source')
+    if source:
+      source = _FixPath(source)
+      # UsePrecompiledHeader=1 for if using precompiled headers.
+      tool = MSVSProject.Tool('VCCLCompilerTool',
+                              {'UsePrecompiledHeader': '1'})
+      p.AddFileConfig(source, _ConfigFullName(config_name, config),
+                      {}, tools=[tool])
+      basename, extension = os.path.splitext(source)
+      if extension == '.c':
+        extensions_excluded_from_precompile = ['.cc', '.cpp', '.cxx']
+      else:
+        extensions_excluded_from_precompile = ['.c']
+  def DisableForSourceTree(source_tree):
+    for source in source_tree:
+      if isinstance(source, MSVSProject.Filter):
+        DisableForSourceTree(source.contents)
+      else:
+        basename, extension = os.path.splitext(source)
+        if extension in extensions_excluded_from_precompile:
+          for config_name, config in spec['configurations'].iteritems():
+            tool = MSVSProject.Tool('VCCLCompilerTool',
+                                    {'UsePrecompiledHeader': '0',
+                                     'ForcedIncludeFiles': '$(NOINHERIT)'})
+            p.AddFileConfig(_FixPath(source),
+                            _ConfigFullName(config_name, config),
+                            {}, tools=[tool])
+  # Do nothing if there was no precompiled source.
+  if extensions_excluded_from_precompile:
+    DisableForSourceTree(sources)
+
+
+def _AddActions(actions_to_add, spec, relative_path_of_gyp_file):
+  # Add actions.
+  actions = spec.get('actions', [])
+  # Don't setup_env every time. When all the actions are run together in one
+  # batch file in VS, the PATH will grow too long.
+  # Membership in this set means that the cygwin environment has been set up,
+  # and does not need to be set up again.
+  have_setup_env = set()
+  for a in actions:
+    # Attach actions to the gyp file if nothing else is there.
+    inputs = a.get('inputs') or [relative_path_of_gyp_file]
+    attached_to = inputs[0]
+    need_setup_env = attached_to not in have_setup_env
+    cmd = _BuildCommandLineForRule(spec, a, has_input_path=False,
+                                   do_setup_env=need_setup_env)
+    have_setup_env.add(attached_to)
+    # Add the action.
+    _AddActionStep(actions_to_add,
+                   inputs=inputs,
+                   outputs=a.get('outputs', []),
+                   description=a.get('message', a['action_name']),
+                   command=cmd)
+
+
+def _WriteMSVSUserFile(project_path, version, spec):
+  # Add run_as and test targets.
+  if 'run_as' in spec:
+    run_as = spec['run_as']
+    action = run_as.get('action', [])
+    environment = run_as.get('environment', [])
+    working_directory = run_as.get('working_directory', '.')
+  elif int(spec.get('test', 0)):
+    action = ['$(TargetPath)', '--gtest_print_time']
+    environment = []
+    working_directory = '.'
+  else:
+    return  # Nothing to add
+  # Write out the user file.
+  user_file = _CreateMSVSUserFile(project_path, version, spec)
+  for config_name, c_data in spec['configurations'].iteritems():
+    user_file.AddDebugSettings(_ConfigFullName(config_name, c_data),
+                               action, environment, working_directory)
+  user_file.WriteIfChanged()
+
+
+def _AddCopies(actions_to_add, spec):
+  copies = _GetCopies(spec)
+  for inputs, outputs, cmd, description in copies:
+    _AddActionStep(actions_to_add, inputs=inputs, outputs=outputs,
+                   description=description, command=cmd)
+
+
+def _GetCopies(spec):
+  copies = []
+  # Add copies.
+  for cpy in spec.get('copies', []):
+    for src in cpy.get('files', []):
+      dst = os.path.join(cpy['destination'], os.path.basename(src))
+      # _AddCustomBuildToolForMSVS() will call _FixPath() on the inputs and
+      # outputs, so do the same for our generated command line.
+      if src.endswith('/'):
+        src_bare = src[:-1]
+        base_dir = posixpath.split(src_bare)[0]
+        outer_dir = posixpath.split(src_bare)[1]
+        cmd = 'cd "%s" && xcopy /e /f /y "%s" "%s\\%s\\"' % (
+            _FixPath(base_dir), outer_dir, _FixPath(dst), outer_dir)
+        copies.append(([src], ['dummy_copies', dst], cmd,
+                       'Copying %s to %s' % (src, dst)))
+      else:
+        cmd = 'mkdir "%s" 2>nul & set ERRORLEVEL=0 & copy /Y "%s" "%s"' % (
+            _FixPath(cpy['destination']), _FixPath(src), _FixPath(dst))
+        copies.append(([src], [dst], cmd, 'Copying %s to %s' % (src, dst)))
+  return copies
+
+
+def _GetPathDict(root, path):
+  # |path| will eventually be empty (in the recursive calls) if it was initially
+  # relative; otherwise it will eventually end up as '\', 'D:\', etc.
+  if not path or path.endswith(os.sep):
+    return root
+  parent, folder = os.path.split(path)
+  parent_dict = _GetPathDict(root, parent)
+  if folder not in parent_dict:
+    parent_dict[folder] = dict()
+  return parent_dict[folder]
+
+
+def _DictsToFolders(base_path, bucket, flat):
+  # Convert to folders recursively.
+  children = []
+  for folder, contents in bucket.iteritems():
+    if type(contents) == dict:
+      folder_children = _DictsToFolders(os.path.join(base_path, folder),
+                                        contents, flat)
+      if flat:
+        children += folder_children
+      else:
+        folder_children = MSVSNew.MSVSFolder(os.path.join(base_path, folder),
+                                             name='(' + folder + ')',
+                                             entries=folder_children)
+        children.append(folder_children)
+    else:
+      children.append(contents)
+  return children
+
+
+def _CollapseSingles(parent, node):
+  # Recursively explorer the tree of dicts looking for projects which are
+  # the sole item in a folder which has the same name as the project. Bring
+  # such projects up one level.
+  if (type(node) == dict and
+      len(node) == 1 and
+      node.keys()[0] == parent + '.vcproj'):
+    return node[node.keys()[0]]
+  if type(node) != dict:
+    return node
+  for child in node:
+    node[child] = _CollapseSingles(child, node[child])
+  return node
+
+
+def _GatherSolutionFolders(sln_projects, project_objects, flat):
+  root = {}
+  # Convert into a tree of dicts on path.
+  for p in sln_projects:
+    gyp_file, target = gyp.common.ParseQualifiedTarget(p)[0:2]
+    gyp_dir = os.path.dirname(gyp_file)
+    path_dict = _GetPathDict(root, gyp_dir)
+    path_dict[target + '.vcproj'] = project_objects[p]
+  # Walk down from the top until we hit a folder that has more than one entry.
+  # In practice, this strips the top-level "src/" dir from the hierarchy in
+  # the solution.
+  while len(root) == 1 and type(root[root.keys()[0]]) == dict:
+    root = root[root.keys()[0]]
+  # Collapse singles.
+  root = _CollapseSingles('', root)
+  # Merge buckets until everything is a root entry.
+  return _DictsToFolders('', root, flat)
+
+
+def _GetPathOfProject(qualified_target, spec, options, msvs_version):
+  default_config = _GetDefaultConfiguration(spec)
+  proj_filename = default_config.get('msvs_existing_vcproj')
+  if not proj_filename:
+    proj_filename = (spec['target_name'] + options.suffix +
+                     msvs_version.ProjectExtension())
+
+  build_file = gyp.common.BuildFile(qualified_target)
+  proj_path = os.path.join(os.path.dirname(build_file), proj_filename)
+  fix_prefix = None
+  if options.generator_output:
+    project_dir_path = os.path.dirname(os.path.abspath(proj_path))
+    proj_path = os.path.join(options.generator_output, proj_path)
+    fix_prefix = gyp.common.RelativePath(project_dir_path,
+                                         os.path.dirname(proj_path))
+  return proj_path, fix_prefix
+
+
+def _GetPlatformOverridesOfProject(spec):
+  # Prepare a dict indicating which project configurations are used for which
+  # solution configurations for this target.
+  config_platform_overrides = {}
+  for config_name, c in spec['configurations'].iteritems():
+    config_fullname = _ConfigFullName(config_name, c)
+    platform = c.get('msvs_target_platform', _ConfigPlatform(c))
+    fixed_config_fullname = '%s|%s' % (
+        _ConfigBaseName(config_name, _ConfigPlatform(c)), platform)
+    config_platform_overrides[config_fullname] = fixed_config_fullname
+  return config_platform_overrides
+
+
+def _CreateProjectObjects(target_list, target_dicts, options, msvs_version):
+  """Create a MSVSProject object for the targets found in target list.
+
+  Arguments:
+    target_list: the list of targets to generate project objects for.
+    target_dicts: the dictionary of specifications.
+    options: global generator options.
+    msvs_version: the MSVSVersion object.
+  Returns:
+    A set of created projects, keyed by target.
+  """
+  global fixpath_prefix
+  # Generate each project.
+  projects = {}
+  for qualified_target in target_list:
+    spec = target_dicts[qualified_target]
+    if spec['toolset'] != 'target':
+      raise GypError(
+          'Multiple toolsets not supported in msvs build (target %s)' %
+          qualified_target)
+    proj_path, fixpath_prefix = _GetPathOfProject(qualified_target, spec,
+                                                  options, msvs_version)
+    guid = _GetGuidOfProject(proj_path, spec)
+    overrides = _GetPlatformOverridesOfProject(spec)
+    build_file = gyp.common.BuildFile(qualified_target)
+    # Create object for this project.
+    obj = MSVSNew.MSVSProject(
+        proj_path,
+        name=spec['target_name'],
+        guid=guid,
+        spec=spec,
+        build_file=build_file,
+        config_platform_overrides=overrides,
+        fixpath_prefix=fixpath_prefix)
+    # Set project toolset if any (MS build only)
+    if msvs_version.UsesVcxproj():
+      obj.set_msbuild_toolset(
+          _GetMsbuildToolsetOfProject(proj_path, spec, msvs_version))
+    projects[qualified_target] = obj
+  # Set all the dependencies
+  for project in projects.values():
+    deps = project.spec.get('dependencies', [])
+    deps = [projects[d] for d in deps]
+    project.set_dependencies(deps)
+  return projects
+
+
+def CalculateVariables(default_variables, params):
+  """Generated variables that require params to be known."""
+
+  generator_flags = params.get('generator_flags', {})
+
+  # Select project file format version (if unset, default to auto detecting).
+  msvs_version = MSVSVersion.SelectVisualStudioVersion(
+      generator_flags.get('msvs_version', 'auto'))
+  # Stash msvs_version for later (so we don't have to probe the system twice).
+  params['msvs_version'] = msvs_version
+
+  # Set a variable so conditions can be based on msvs_version.
+  default_variables['MSVS_VERSION'] = msvs_version.ShortName()
+
+  # To determine processor word size on Windows, in addition to checking
+  # PROCESSOR_ARCHITECTURE (which reflects the word size of the current
+  # process), it is also necessary to check PROCESSOR_ARCITEW6432 (which
+  # contains the actual word size of the system when running thru WOW64).
+  if (os.environ.get('PROCESSOR_ARCHITECTURE', '').find('64') >= 0 or
+      os.environ.get('PROCESSOR_ARCHITEW6432', '').find('64') >= 0):
+    default_variables['MSVS_OS_BITS'] = 64
+  else:
+    default_variables['MSVS_OS_BITS'] = 32
+
+
+def PerformBuild(data, configurations, params):
+  options = params['options']
+  msvs_version = params['msvs_version']
+  devenv = os.path.join(msvs_version.path, 'Common7', 'IDE', 'devenv.com')
+
+  for build_file, build_file_dict in data.iteritems():
+    (build_file_root, build_file_ext) = os.path.splitext(build_file)
+    if build_file_ext != '.gyp':
+      continue
+    sln_path = build_file_root + options.suffix + '.sln'
+    if options.generator_output:
+      sln_path = os.path.join(options.generator_output, sln_path)
+
+  for config in configurations:
+    arguments = [devenv, sln_path, '/Build', config]
+    print 'Building [%s]: %s' % (config, arguments)
+    rtn = subprocess.check_call(arguments)
+
+
+def GenerateOutput(target_list, target_dicts, data, params):
+  """Generate .sln and .vcproj files.
+
+  This is the entry point for this generator.
+  Arguments:
+    target_list: List of target pairs: 'base/base.gyp:base'.
+    target_dicts: Dict of target properties keyed on target pair.
+    data: Dictionary containing per .gyp data.
+  """
+  global fixpath_prefix
+
+  options = params['options']
+
+  # Get the project file format version back out of where we stashed it in
+  # GeneratorCalculatedVariables.
+  msvs_version = params['msvs_version']
+
+  generator_flags = params.get('generator_flags', {})
+
+  # Optionally shard targets marked with 'msvs_shard': SHARD_COUNT.
+  (target_list, target_dicts) = MSVSUtil.ShardTargets(target_list, target_dicts)
+
+  # Optionally use the large PDB workaround for targets marked with
+  # 'msvs_large_pdb': 1.
+  (target_list, target_dicts) = MSVSUtil.InsertLargePdbShims(
+        target_list, target_dicts, generator_default_variables)
+
+  # Prepare the set of configurations.
+  configs = set()
+  for qualified_target in target_list:
+    spec = target_dicts[qualified_target]
+    for config_name, config in spec['configurations'].iteritems():
+      configs.add(_ConfigFullName(config_name, config))
+  configs = list(configs)
+
+  # Figure out all the projects that will be generated and their guids
+  project_objects = _CreateProjectObjects(target_list, target_dicts, options,
+                                          msvs_version)
+
+  # Generate each project.
+  missing_sources = []
+  for project in project_objects.values():
+    fixpath_prefix = project.fixpath_prefix
+    missing_sources.extend(_GenerateProject(project, options, msvs_version,
+                                            generator_flags))
+  fixpath_prefix = None
+
+  for build_file in data:
+    # Validate build_file extension
+    if not build_file.endswith('.gyp'):
+      continue
+    sln_path = os.path.splitext(build_file)[0] + options.suffix + '.sln'
+    if options.generator_output:
+      sln_path = os.path.join(options.generator_output, sln_path)
+    # Get projects in the solution, and their dependents.
+    sln_projects = gyp.common.BuildFileTargets(target_list, build_file)
+    sln_projects += gyp.common.DeepDependencyTargets(target_dicts, sln_projects)
+    # Create folder hierarchy.
+    root_entries = _GatherSolutionFolders(
+        sln_projects, project_objects, flat=msvs_version.FlatSolution())
+    # Create solution.
+    sln = MSVSNew.MSVSSolution(sln_path,
+                               entries=root_entries,
+                               variants=configs,
+                               websiteProperties=False,
+                               version=msvs_version)
+    sln.Write()
+
+  if missing_sources:
+    error_message = "Missing input files:\n" + \
+                    '\n'.join(set(missing_sources))
+    if generator_flags.get('msvs_error_on_missing_sources', False):
+      raise GypError(error_message)
+    else:
+      print >> sys.stdout, "Warning: " + error_message
+
+
+def _GenerateMSBuildFiltersFile(filters_path, source_files,
+                                extension_to_rule_name):
+  """Generate the filters file.
+
+  This file is used by Visual Studio to organize the presentation of source
+  files into folders.
+
+  Arguments:
+      filters_path: The path of the file to be created.
+      source_files: The hierarchical structure of all the sources.
+      extension_to_rule_name: A dictionary mapping file extensions to rules.
+  """
+  filter_group = []
+  source_group = []
+  _AppendFiltersForMSBuild('', source_files, extension_to_rule_name,
+                           filter_group, source_group)
+  if filter_group:
+    content = ['Project',
+               {'ToolsVersion': '4.0',
+                'xmlns': 'http://schemas.microsoft.com/developer/msbuild/2003'
+               },
+               ['ItemGroup'] + filter_group,
+               ['ItemGroup'] + source_group
+              ]
+    easy_xml.WriteXmlIfChanged(content, filters_path, pretty=True, win32=True)
+  elif os.path.exists(filters_path):
+    # We don't need this filter anymore.  Delete the old filter file.
+    os.unlink(filters_path)
+
+
+def _AppendFiltersForMSBuild(parent_filter_name, sources,
+                             extension_to_rule_name,
+                             filter_group, source_group):
+  """Creates the list of filters and sources to be added in the filter file.
+
+  Args:
+      parent_filter_name: The name of the filter under which the sources are
+          found.
+      sources: The hierarchy of filters and sources to process.
+      extension_to_rule_name: A dictionary mapping file extensions to rules.
+      filter_group: The list to which filter entries will be appended.
+      source_group: The list to which source entries will be appeneded.
+  """
+  for source in sources:
+    if isinstance(source, MSVSProject.Filter):
+      # We have a sub-filter.  Create the name of that sub-filter.
+      if not parent_filter_name:
+        filter_name = source.name
+      else:
+        filter_name = '%s\\%s' % (parent_filter_name, source.name)
+      # Add the filter to the group.
+      filter_group.append(
+          ['Filter', {'Include': filter_name},
+           ['UniqueIdentifier', MSVSNew.MakeGuid(source.name)]])
+      # Recurse and add its dependents.
+      _AppendFiltersForMSBuild(filter_name, source.contents,
+                               extension_to_rule_name,
+                               filter_group, source_group)
+    else:
+      # It's a source.  Create a source entry.
+      _, element = _MapFileToMsBuildSourceType(source, extension_to_rule_name)
+      source_entry = [element, {'Include': source}]
+      # Specify the filter it is part of, if any.
+      if parent_filter_name:
+        source_entry.append(['Filter', parent_filter_name])
+      source_group.append(source_entry)
+
+
+def _MapFileToMsBuildSourceType(source, extension_to_rule_name):
+  """Returns the group and element type of the source file.
+
+  Arguments:
+      source: The source file name.
+      extension_to_rule_name: A dictionary mapping file extensions to rules.
+
+  Returns:
+      A pair of (group this file should be part of, the label of element)
+  """
+  _, ext = os.path.splitext(source)
+  if ext in extension_to_rule_name:
+    group = 'rule'
+    element = extension_to_rule_name[ext]
+  elif ext in ['.cc', '.cpp', '.c', '.cxx']:
+    group = 'compile'
+    element = 'ClCompile'
+  elif ext in ['.h', '.hxx']:
+    group = 'include'
+    element = 'ClInclude'
+  elif ext == '.rc':
+    group = 'resource'
+    element = 'ResourceCompile'
+  elif ext == '.idl':
+    group = 'midl'
+    element = 'Midl'
+  else:
+    group = 'none'
+    element = 'None'
+  return (group, element)
+
+
+def _GenerateRulesForMSBuild(output_dir, options, spec,
+                             sources, excluded_sources,
+                             props_files_of_rules, targets_files_of_rules,
+                             actions_to_add, extension_to_rule_name):
+  # MSBuild rules are implemented using three files: an XML file, a .targets
+  # file and a .props file.
+  # See http://blogs.msdn.com/b/vcblog/archive/2010/04/21/quick-help-on-vs2010-custom-build-rule.aspx
+  # for more details.
+  rules = spec.get('rules', [])
+  rules_native = [r for r in rules if not int(r.get('msvs_external_rule', 0))]
+  rules_external = [r for r in rules if int(r.get('msvs_external_rule', 0))]
+
+  msbuild_rules = []
+  for rule in rules_native:
+    # Skip a rule with no action and no inputs.
+    if 'action' not in rule and not rule.get('rule_sources', []):
+      continue
+    msbuild_rule = MSBuildRule(rule, spec)
+    msbuild_rules.append(msbuild_rule)
+    extension_to_rule_name[msbuild_rule.extension] = msbuild_rule.rule_name
+  if msbuild_rules:
+    base = spec['target_name'] + options.suffix
+    props_name = base + '.props'
+    targets_name = base + '.targets'
+    xml_name = base + '.xml'
+
+    props_files_of_rules.add(props_name)
+    targets_files_of_rules.add(targets_name)
+
+    props_path = os.path.join(output_dir, props_name)
+    targets_path = os.path.join(output_dir, targets_name)
+    xml_path = os.path.join(output_dir, xml_name)
+
+    _GenerateMSBuildRulePropsFile(props_path, msbuild_rules)
+    _GenerateMSBuildRuleTargetsFile(targets_path, msbuild_rules)
+    _GenerateMSBuildRuleXmlFile(xml_path, msbuild_rules)
+
+  if rules_external:
+    _GenerateExternalRules(rules_external, output_dir, spec,
+                           sources, options, actions_to_add)
+  _AdjustSourcesForRules(rules, sources, excluded_sources)
+
+
+class MSBuildRule(object):
+  """Used to store information used to generate an MSBuild rule.
+
+  Attributes:
+    rule_name: The rule name, sanitized to use in XML.
+    target_name: The name of the target.
+    after_targets: The name of the AfterTargets element.
+    before_targets: The name of the BeforeTargets element.
+    depends_on: The name of the DependsOn element.
+    compute_output: The name of the ComputeOutput element.
+    dirs_to_make: The name of the DirsToMake element.
+    inputs: The name of the _inputs element.
+    tlog: The name of the _tlog element.
+    extension: The extension this rule applies to.
+    description: The message displayed when this rule is invoked.
+    additional_dependencies: A string listing additional dependencies.
+    outputs: The outputs of this rule.
+    command: The command used to run the rule.
+  """
+
+  def __init__(self, rule, spec):
+    self.display_name = rule['rule_name']
+    # Assure that the rule name is only characters and numbers
+    self.rule_name = re.sub(r'\W', '_', self.display_name)
+    # Create the various element names, following the example set by the
+    # Visual Studio 2008 to 2010 conversion.  I don't know if VS2010
+    # is sensitive to the exact names.
+    self.target_name = '_' + self.rule_name
+    self.after_targets = self.rule_name + 'AfterTargets'
+    self.before_targets = self.rule_name + 'BeforeTargets'
+    self.depends_on = self.rule_name + 'DependsOn'
+    self.compute_output = 'Compute%sOutput' % self.rule_name
+    self.dirs_to_make = self.rule_name + 'DirsToMake'
+    self.inputs = self.rule_name + '_inputs'
+    self.tlog = self.rule_name + '_tlog'
+    self.extension = rule['extension']
+    if not self.extension.startswith('.'):
+      self.extension = '.' + self.extension
+
+    self.description = MSVSSettings.ConvertVCMacrosToMSBuild(
+        rule.get('message', self.rule_name))
+    old_additional_dependencies = _FixPaths(rule.get('inputs', []))
+    self.additional_dependencies = (
+        ';'.join([MSVSSettings.ConvertVCMacrosToMSBuild(i)
+                  for i in old_additional_dependencies]))
+    old_outputs = _FixPaths(rule.get('outputs', []))
+    self.outputs = ';'.join([MSVSSettings.ConvertVCMacrosToMSBuild(i)
+                             for i in old_outputs])
+    old_command = _BuildCommandLineForRule(spec, rule, has_input_path=True,
+                                           do_setup_env=True)
+    self.command = MSVSSettings.ConvertVCMacrosToMSBuild(old_command)
+
+
+def _GenerateMSBuildRulePropsFile(props_path, msbuild_rules):
+  """Generate the .props file."""
+  content = ['Project',
+             {'xmlns': 'http://schemas.microsoft.com/developer/msbuild/2003'}]
+  for rule in msbuild_rules:
+    content.extend([
+        ['PropertyGroup',
+         {'Condition': "'$(%s)' == '' and '$(%s)' == '' and "
+          "'$(ConfigurationType)' != 'Makefile'" % (rule.before_targets,
+                                                    rule.after_targets)
+         },
+         [rule.before_targets, 'Midl'],
+         [rule.after_targets, 'CustomBuild'],
+        ],
+        ['PropertyGroup',
+         [rule.depends_on,
+          {'Condition': "'$(ConfigurationType)' != 'Makefile'"},
+          '_SelectedFiles;$(%s)' % rule.depends_on
+         ],
+        ],
+        ['ItemDefinitionGroup',
+         [rule.rule_name,
+          ['CommandLineTemplate', rule.command],
+          ['Outputs', rule.outputs],
+          ['ExecutionDescription', rule.description],
+          ['AdditionalDependencies', rule.additional_dependencies],
+         ],
+        ]
+    ])
+  easy_xml.WriteXmlIfChanged(content, props_path, pretty=True, win32=True)
+
+
+def _GenerateMSBuildRuleTargetsFile(targets_path, msbuild_rules):
+  """Generate the .targets file."""
+  content = ['Project',
+             {'xmlns': 'http://schemas.microsoft.com/developer/msbuild/2003'
+             }
+            ]
+  item_group = [
+      'ItemGroup',
+      ['PropertyPageSchema',
+       {'Include': '$(MSBuildThisFileDirectory)$(MSBuildThisFileName).xml'}
+      ]
+    ]
+  for rule in msbuild_rules:
+    item_group.append(
+        ['AvailableItemName',
+         {'Include': rule.rule_name},
+         ['Targets', rule.target_name],
+        ])
+  content.append(item_group)
+
+  for rule in msbuild_rules:
+    content.append(
+        ['UsingTask',
+         {'TaskName': rule.rule_name,
+          'TaskFactory': 'XamlTaskFactory',
+          'AssemblyName': 'Microsoft.Build.Tasks.v4.0'
+         },
+         ['Task', '$(MSBuildThisFileDirectory)$(MSBuildThisFileName).xml'],
+        ])
+  for rule in msbuild_rules:
+    rule_name = rule.rule_name
+    target_outputs = '%%(%s.Outputs)' % rule_name
+    target_inputs = ('%%(%s.Identity);%%(%s.AdditionalDependencies);'
+                     '$(MSBuildProjectFile)') % (rule_name, rule_name)
+    rule_inputs = '%%(%s.Identity)' % rule_name
+    extension_condition = ("'%(Extension)'=='.obj' or "
+                           "'%(Extension)'=='.res' or "
+                           "'%(Extension)'=='.rsc' or "
+                           "'%(Extension)'=='.lib'")
+    remove_section = [
+        'ItemGroup',
+        {'Condition': "'@(SelectedFiles)' != ''"},
+        [rule_name,
+         {'Remove': '@(%s)' % rule_name,
+          'Condition': "'%(Identity)' != '@(SelectedFiles)'"
+         }
+        ]
+    ]
+    inputs_section = [
+        'ItemGroup',
+        [rule.inputs, {'Include': '%%(%s.AdditionalDependencies)' % rule_name}]
+    ]
+    logging_section = [
+        'ItemGroup',
+        [rule.tlog,
+         {'Include': '%%(%s.Outputs)' % rule_name,
+          'Condition': ("'%%(%s.Outputs)' != '' and "
+                        "'%%(%s.ExcludedFromBuild)' != 'true'" %
+                        (rule_name, rule_name))
+         },
+         ['Source', "@(%s, '|')" % rule_name],
+         ['Inputs', "@(%s -> '%%(Fullpath)', ';')" % rule.inputs],
+        ],
+    ]
+    message_section = [
+        'Message',
+        {'Importance': 'High',
+         'Text': '%%(%s.ExecutionDescription)' % rule_name
+        }
+    ]
+    write_tlog_section = [
+        'WriteLinesToFile',
+        {'Condition': "'@(%s)' != '' and '%%(%s.ExcludedFromBuild)' != "
+         "'true'" % (rule.tlog, rule.tlog),
+         'File': '$(IntDir)$(ProjectName).write.1.tlog',
+         'Lines': "^%%(%s.Source);@(%s->'%%(Fullpath)')" % (rule.tlog,
+                                                            rule.tlog)
+        }
+    ]
+    read_tlog_section = [
+        'WriteLinesToFile',
+        {'Condition': "'@(%s)' != '' and '%%(%s.ExcludedFromBuild)' != "
+         "'true'" % (rule.tlog, rule.tlog),
+         'File': '$(IntDir)$(ProjectName).read.1.tlog',
+         'Lines': "^%%(%s.Source);%%(%s.Inputs)" % (rule.tlog, rule.tlog)
+        }
+    ]
+    command_and_input_section = [
+        rule_name,
+        {'Condition': "'@(%s)' != '' and '%%(%s.ExcludedFromBuild)' != "
+         "'true'" % (rule_name, rule_name),
+         'CommandLineTemplate': '%%(%s.CommandLineTemplate)' % rule_name,
+         'AdditionalOptions': '%%(%s.AdditionalOptions)' % rule_name,
+         'Inputs': rule_inputs
+        }
+    ]
+    content.extend([
+        ['Target',
+         {'Name': rule.target_name,
+          'BeforeTargets': '$(%s)' % rule.before_targets,
+          'AfterTargets': '$(%s)' % rule.after_targets,
+          'Condition': "'@(%s)' != ''" % rule_name,
+          'DependsOnTargets': '$(%s);%s' % (rule.depends_on,
+                                            rule.compute_output),
+          'Outputs': target_outputs,
+          'Inputs': target_inputs
+         },
+         remove_section,
+         inputs_section,
+         logging_section,
+         message_section,
+         write_tlog_section,
+         read_tlog_section,
+         command_and_input_section,
+        ],
+        ['PropertyGroup',
+         ['ComputeLinkInputsTargets',
+          '$(ComputeLinkInputsTargets);',
+          '%s;' % rule.compute_output
+         ],
+         ['ComputeLibInputsTargets',
+          '$(ComputeLibInputsTargets);',
+          '%s;' % rule.compute_output
+         ],
+        ],
+        ['Target',
+         {'Name': rule.compute_output,
+          'Condition': "'@(%s)' != ''" % rule_name
+         },
+         ['ItemGroup',
+          [rule.dirs_to_make,
+           {'Condition': "'@(%s)' != '' and "
+            "'%%(%s.ExcludedFromBuild)' != 'true'" % (rule_name, rule_name),
+            'Include': '%%(%s.Outputs)' % rule_name
+           }
+          ],
+          ['Link',
+           {'Include': '%%(%s.Identity)' % rule.dirs_to_make,
+            'Condition': extension_condition
+           }
+          ],
+          ['Lib',
+           {'Include': '%%(%s.Identity)' % rule.dirs_to_make,
+            'Condition': extension_condition
+           }
+          ],
+          ['ImpLib',
+           {'Include': '%%(%s.Identity)' % rule.dirs_to_make,
+            'Condition': extension_condition
+           }
+          ],
+         ],
+         ['MakeDir',
+          {'Directories': ("@(%s->'%%(RootDir)%%(Directory)')" %
+                           rule.dirs_to_make)
+          }
+         ]
+        ],
+    ])
+  easy_xml.WriteXmlIfChanged(content, targets_path, pretty=True, win32=True)
+
+
+def _GenerateMSBuildRuleXmlFile(xml_path, msbuild_rules):
+  # Generate the .xml file
+  content = [
+      'ProjectSchemaDefinitions',
+      {'xmlns': ('clr-namespace:Microsoft.Build.Framework.XamlTypes;'
+                 'assembly=Microsoft.Build.Framework'),
+       'xmlns:x': 'http://schemas.microsoft.com/winfx/2006/xaml',
+       'xmlns:sys': 'clr-namespace:System;assembly=mscorlib',
+       'xmlns:transformCallback':
+       'Microsoft.Cpp.Dev10.ConvertPropertyCallback'
+      }
+  ]
+  for rule in msbuild_rules:
+    content.extend([
+        ['Rule',
+         {'Name': rule.rule_name,
+          'PageTemplate': 'tool',
+          'DisplayName': rule.display_name,
+          'Order': '200'
+         },
+         ['Rule.DataSource',
+          ['DataSource',
+           {'Persistence': 'ProjectFile',
+            'ItemType': rule.rule_name
+           }
+          ]
+         ],
+         ['Rule.Categories',
+          ['Category',
+           {'Name': 'General'},
+           ['Category.DisplayName',
+            ['sys:String', 'General'],
+           ],
+          ],
+          ['Category',
+           {'Name': 'Command Line',
+            'Subtype': 'CommandLine'
+           },
+           ['Category.DisplayName',
+            ['sys:String', 'Command Line'],
+           ],
+          ],
+         ],
+         ['StringListProperty',
+          {'Name': 'Inputs',
+           'Category': 'Command Line',
+           'IsRequired': 'true',
+           'Switch': ' '
+          },
+          ['StringListProperty.DataSource',
+           ['DataSource',
+            {'Persistence': 'ProjectFile',
+             'ItemType': rule.rule_name,
+             'SourceType': 'Item'
+            }
+           ]
+          ],
+         ],
+         ['StringProperty',
+          {'Name': 'CommandLineTemplate',
+           'DisplayName': 'Command Line',
+           'Visible': 'False',
+           'IncludeInCommandLine': 'False'
+          }
+         ],
+         ['DynamicEnumProperty',
+          {'Name': rule.before_targets,
+           'Category': 'General',
+           'EnumProvider': 'Targets',
+           'IncludeInCommandLine': 'False'
+          },
+          ['DynamicEnumProperty.DisplayName',
+           ['sys:String', 'Execute Before'],
+          ],
+          ['DynamicEnumProperty.Description',
+           ['sys:String', 'Specifies the targets for the build customization'
+            ' to run before.'
+           ],
+          ],
+          ['DynamicEnumProperty.ProviderSettings',
+           ['NameValuePair',
+            {'Name': 'Exclude',
+             'Value': '^%s|^Compute' % rule.before_targets
+            }
+           ]
+          ],
+          ['DynamicEnumProperty.DataSource',
+           ['DataSource',
+            {'Persistence': 'ProjectFile',
+             'HasConfigurationCondition': 'true'
+            }
+           ]
+          ],
+         ],
+         ['DynamicEnumProperty',
+          {'Name': rule.after_targets,
+           'Category': 'General',
+           'EnumProvider': 'Targets',
+           'IncludeInCommandLine': 'False'
+          },
+          ['DynamicEnumProperty.DisplayName',
+           ['sys:String', 'Execute After'],
+          ],
+          ['DynamicEnumProperty.Description',
+           ['sys:String', ('Specifies the targets for the build customization'
+                           ' to run after.')
+           ],
+          ],
+          ['DynamicEnumProperty.ProviderSettings',
+           ['NameValuePair',
+            {'Name': 'Exclude',
+             'Value': '^%s|^Compute' % rule.after_targets
+            }
+           ]
+          ],
+          ['DynamicEnumProperty.DataSource',
+           ['DataSource',
+            {'Persistence': 'ProjectFile',
+             'ItemType': '',
+             'HasConfigurationCondition': 'true'
+            }
+           ]
+          ],
+         ],
+         ['StringListProperty',
+          {'Name': 'Outputs',
+           'DisplayName': 'Outputs',
+           'Visible': 'False',
+           'IncludeInCommandLine': 'False'
+          }
+         ],
+         ['StringProperty',
+          {'Name': 'ExecutionDescription',
+           'DisplayName': 'Execution Description',
+           'Visible': 'False',
+           'IncludeInCommandLine': 'False'
+          }
+         ],
+         ['StringListProperty',
+          {'Name': 'AdditionalDependencies',
+           'DisplayName': 'Additional Dependencies',
+           'IncludeInCommandLine': 'False',
+           'Visible': 'false'
+          }
+         ],
+         ['StringProperty',
+          {'Subtype': 'AdditionalOptions',
+           'Name': 'AdditionalOptions',
+           'Category': 'Command Line'
+          },
+          ['StringProperty.DisplayName',
+           ['sys:String', 'Additional Options'],
+          ],
+          ['StringProperty.Description',
+           ['sys:String', 'Additional Options'],
+          ],
+         ],
+        ],
+        ['ItemType',
+         {'Name': rule.rule_name,
+          'DisplayName': rule.display_name
+         }
+        ],
+        ['FileExtension',
+         {'Name': '*' + rule.extension,
+          'ContentType': rule.rule_name
+         }
+        ],
+        ['ContentType',
+         {'Name': rule.rule_name,
+          'DisplayName': '',
+          'ItemType': rule.rule_name
+         }
+        ]
+    ])
+  easy_xml.WriteXmlIfChanged(content, xml_path, pretty=True, win32=True)
+
+
+def _GetConfigurationAndPlatform(name, settings):
+  configuration = name.rsplit('_', 1)[0]
+  platform = settings.get('msvs_configuration_platform', 'Win32')
+  return (configuration, platform)
+
+
+def _GetConfigurationCondition(name, settings):
+  return (r"'$(Configuration)|$(Platform)'=='%s|%s'" %
+          _GetConfigurationAndPlatform(name, settings))
+
+
+def _GetMSBuildProjectConfigurations(configurations):
+  group = ['ItemGroup', {'Label': 'ProjectConfigurations'}]
+  for (name, settings) in sorted(configurations.iteritems()):
+    configuration, platform = _GetConfigurationAndPlatform(name, settings)
+    designation = '%s|%s' % (configuration, platform)
+    group.append(
+        ['ProjectConfiguration', {'Include': designation},
+         ['Configuration', configuration],
+         ['Platform', platform]])
+  return [group]
+
+
+def _GetMSBuildGlobalProperties(spec, guid, gyp_file_name):
+  namespace = os.path.splitext(gyp_file_name)[0]
+  return [
+      ['PropertyGroup', {'Label': 'Globals'},
+       ['ProjectGuid', guid],
+       ['Keyword', 'Win32Proj'],
+       ['RootNamespace', namespace],
+      ]
+  ]
+
+
+def _GetMSBuildConfigurationDetails(spec, build_file):
+  properties = {}
+  for name, settings in spec['configurations'].iteritems():
+    msbuild_attributes = _GetMSBuildAttributes(spec, settings, build_file)
+    condition = _GetConfigurationCondition(name, settings)
+    character_set = msbuild_attributes.get('CharacterSet')
+    _AddConditionalProperty(properties, condition, 'ConfigurationType',
+                            msbuild_attributes['ConfigurationType'])
+    if character_set:
+      _AddConditionalProperty(properties, condition, 'CharacterSet',
+                              character_set)
+  return _GetMSBuildPropertyGroup(spec, 'Configuration', properties)
+
+
+def _GetMSBuildLocalProperties(msbuild_toolset):
+  # Currently the only local property we support is PlatformToolset
+  properties = {}
+  if msbuild_toolset:
+    properties = [
+        ['PropertyGroup', {'Label': 'Locals'},
+          ['PlatformToolset', msbuild_toolset],
+        ]
+      ]
+  return properties
+
+
+def _GetMSBuildPropertySheets(configurations):
+  user_props = r'$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props'
+  additional_props = {}
+  props_specified = False
+  for name, settings in sorted(configurations.iteritems()):
+    configuration = _GetConfigurationCondition(name, settings)
+    if settings.has_key('msbuild_props'):
+      additional_props[configuration] = _FixPaths(settings['msbuild_props'])
+      props_specified = True
+    else:
+     additional_props[configuration] = ''
+
+  if not props_specified:
+    return [
+        ['ImportGroup',
+         {'Label': 'PropertySheets'},
+         ['Import',
+          {'Project': user_props,
+           'Condition': "exists('%s')" % user_props,
+           'Label': 'LocalAppDataPlatform'
+          }
+         ]
+        ]
+    ]
+  else:
+    sheets = []
+    for condition, props in additional_props.iteritems():
+      import_group = [
+        'ImportGroup',
+        {'Label': 'PropertySheets',
+         'Condition': condition
+        },
+        ['Import',
+         {'Project': user_props,
+          'Condition': "exists('%s')" % user_props,
+          'Label': 'LocalAppDataPlatform'
+         }
+        ]
+      ]
+      for props_file in props:
+        import_group.append(['Import', {'Project':props_file}])
+      sheets.append(import_group)
+    return sheets
+
+def _ConvertMSVSBuildAttributes(spec, config, build_file):
+  config_type = _GetMSVSConfigurationType(spec, build_file)
+  msvs_attributes = _GetMSVSAttributes(spec, config, config_type)
+  msbuild_attributes = {}
+  for a in msvs_attributes:
+    if a in ['IntermediateDirectory', 'OutputDirectory']:
+      directory = MSVSSettings.ConvertVCMacrosToMSBuild(msvs_attributes[a])
+      if not directory.endswith('\\'):
+        directory += '\\'
+      msbuild_attributes[a] = directory
+    elif a == 'CharacterSet':
+      msbuild_attributes[a] = _ConvertMSVSCharacterSet(msvs_attributes[a])
+    elif a == 'ConfigurationType':
+      msbuild_attributes[a] = _ConvertMSVSConfigurationType(msvs_attributes[a])
+    else:
+      print 'Warning: Do not know how to convert MSVS attribute ' + a
+  return msbuild_attributes
+
+
+def _ConvertMSVSCharacterSet(char_set):
+  if char_set.isdigit():
+    char_set = {
+        '0': 'MultiByte',
+        '1': 'Unicode',
+        '2': 'MultiByte',
+    }[char_set]
+  return char_set
+
+
+def _ConvertMSVSConfigurationType(config_type):
+  if config_type.isdigit():
+    config_type = {
+        '1': 'Application',
+        '2': 'DynamicLibrary',
+        '4': 'StaticLibrary',
+        '10': 'Utility'
+    }[config_type]
+  return config_type
+
+
+def _GetMSBuildAttributes(spec, config, build_file):
+  if 'msbuild_configuration_attributes' not in config:
+    msbuild_attributes = _ConvertMSVSBuildAttributes(spec, config, build_file)
+
+  else:
+    config_type = _GetMSVSConfigurationType(spec, build_file)
+    config_type = _ConvertMSVSConfigurationType(config_type)
+    msbuild_attributes = config.get('msbuild_configuration_attributes', {})
+    msbuild_attributes.setdefault('ConfigurationType', config_type)
+    output_dir = msbuild_attributes.get('OutputDirectory',
+                                      '$(SolutionDir)$(Configuration)')
+    msbuild_attributes['OutputDirectory'] = _FixPath(output_dir) + '\\'
+    if 'IntermediateDirectory' not in msbuild_attributes:
+      intermediate = _FixPath('$(Configuration)') + '\\'
+      msbuild_attributes['IntermediateDirectory'] = intermediate
+    if 'CharacterSet' in msbuild_attributes:
+      msbuild_attributes['CharacterSet'] = _ConvertMSVSCharacterSet(
+          msbuild_attributes['CharacterSet'])
+  if 'TargetName' not in msbuild_attributes:
+    prefix = spec.get('product_prefix', '')
+    product_name = spec.get('product_name', '$(ProjectName)')
+    target_name = prefix + product_name
+    msbuild_attributes['TargetName'] = target_name
+
+  # Make sure that 'TargetPath' matches 'Lib.OutputFile' or 'Link.OutputFile'
+  # (depending on the tool used) to avoid MSB8012 warning.
+  msbuild_tool_map = {
+      'executable': 'Link',
+      'shared_library': 'Link',
+      'loadable_module': 'Link',
+      'static_library': 'Lib',
+  }
+  msbuild_tool = msbuild_tool_map.get(spec['type'])
+  if msbuild_tool:
+    msbuild_settings = config['finalized_msbuild_settings']
+    out_file = msbuild_settings[msbuild_tool].get('OutputFile')
+    if out_file:
+      msbuild_attributes['TargetPath'] = _FixPath(out_file)
+
+  return msbuild_attributes
+
+
+def _GetMSBuildConfigurationGlobalProperties(spec, configurations, build_file):
+  # TODO(jeanluc) We could optimize out the following and do it only if
+  # there are actions.
+  # TODO(jeanluc) Handle the equivalent of setting 'CYGWIN=nontsec'.
+  new_paths = []
+  cygwin_dirs = spec.get('msvs_cygwin_dirs', ['.'])[0]
+  if cygwin_dirs:
+    cyg_path = '$(MSBuildProjectDirectory)\\%s\\bin\\' % _FixPath(cygwin_dirs)
+    new_paths.append(cyg_path)
+    # TODO(jeanluc) Change the convention to have both a cygwin_dir and a
+    # python_dir.
+    python_path = cyg_path.replace('cygwin\\bin', 'python_26')
+    new_paths.append(python_path)
+    if new_paths:
+      new_paths = '$(ExecutablePath);' + ';'.join(new_paths)
+
+  properties = {}
+  for (name, configuration) in sorted(configurations.iteritems()):
+    condition = _GetConfigurationCondition(name, configuration)
+    attributes = _GetMSBuildAttributes(spec, configuration, build_file)
+    msbuild_settings = configuration['finalized_msbuild_settings']
+    _AddConditionalProperty(properties, condition, 'IntDir',
+                            attributes['IntermediateDirectory'])
+    _AddConditionalProperty(properties, condition, 'OutDir',
+                            attributes['OutputDirectory'])
+    _AddConditionalProperty(properties, condition, 'TargetName',
+                            attributes['TargetName'])
+
+    if attributes.get('TargetPath'):
+      _AddConditionalProperty(properties, condition, 'TargetPath',
+                              attributes['TargetPath'])
+
+    if new_paths:
+      _AddConditionalProperty(properties, condition, 'ExecutablePath',
+                              new_paths)
+    tool_settings = msbuild_settings.get('', {})
+    for name, value in sorted(tool_settings.iteritems()):
+      formatted_value = _GetValueFormattedForMSBuild('', name, value)
+      _AddConditionalProperty(properties, condition, name, formatted_value)
+  return _GetMSBuildPropertyGroup(spec, None, properties)
+
+
+def _AddConditionalProperty(properties, condition, name, value):
+  """Adds a property / conditional value pair to a dictionary.
+
+  Arguments:
+    properties: The dictionary to be modified.  The key is the name of the
+        property.  The value is itself a dictionary; its key is the value and
+        the value a list of condition for which this value is true.
+    condition: The condition under which the named property has the value.
+    name: The name of the property.
+    value: The value of the property.
+  """
+  if name not in properties:
+    properties[name] = {}
+  values = properties[name]
+  if value not in values:
+    values[value] = []
+  conditions = values[value]
+  conditions.append(condition)
+
+
+# Regex for msvs variable references ( i.e. $(FOO) ).
+MSVS_VARIABLE_REFERENCE = re.compile('\$\(([a-zA-Z_][a-zA-Z0-9_]*)\)')
+
+
+def _GetMSBuildPropertyGroup(spec, label, properties):
+  """Returns a PropertyGroup definition for the specified properties.
+
+  Arguments:
+    spec: The target project dict.
+    label: An optional label for the PropertyGroup.
+    properties: The dictionary to be converted.  The key is the name of the
+        property.  The value is itself a dictionary; its key is the value and
+        the value a list of condition for which this value is true.
+  """
+  group = ['PropertyGroup']
+  if label:
+    group.append({'Label': label})
+  num_configurations = len(spec['configurations'])
+  def GetEdges(node):
+    # Use a definition of edges such that user_of_variable -> used_varible.
+    # This happens to be easier in this case, since a variable's
+    # definition contains all variables it references in a single string.
+    edges = set()
+    for value in sorted(properties[node].keys()):
+      # Add to edges all $(...) references to variables.
+      #
+      # Variable references that refer to names not in properties are excluded
+      # These can exist for instance to refer built in definitions like
+      # $(SolutionDir).
+      #
+      # Self references are ignored. Self reference is used in a few places to
+      # append to the default value. I.e. PATH=$(PATH);other_path
+      edges.update(set([v for v in MSVS_VARIABLE_REFERENCE.findall(value)
+                        if v in properties and v != node]))
+    return edges
+  properties_ordered = gyp.common.TopologicallySorted(
+      properties.keys(), GetEdges)
+  # Walk properties in the reverse of a topological sort on
+  # user_of_variable -> used_variable as this ensures variables are
+  # defined before they are used.
+  # NOTE: reverse(topsort(DAG)) = topsort(reverse_edges(DAG))
+  for name in reversed(properties_ordered):
+    values = properties[name]
+    for value, conditions in sorted(values.iteritems()):
+      if len(conditions) == num_configurations:
+        # If the value is the same all configurations,
+        # just add one unconditional entry.
+        group.append([name, value])
+      else:
+        for condition in conditions:
+          group.append([name, {'Condition': condition}, value])
+  return [group]
+
+
+def _GetMSBuildToolSettingsSections(spec, configurations):
+  groups = []
+  for (name, configuration) in sorted(configurations.iteritems()):
+    msbuild_settings = configuration['finalized_msbuild_settings']
+    group = ['ItemDefinitionGroup',
+             {'Condition': _GetConfigurationCondition(name, configuration)}
+            ]
+    for tool_name, tool_settings in sorted(msbuild_settings.iteritems()):
+      # Skip the tool named '' which is a holder of global settings handled
+      # by _GetMSBuildConfigurationGlobalProperties.
+      if tool_name:
+        if tool_settings:
+          tool = [tool_name]
+          for name, value in sorted(tool_settings.iteritems()):
+            formatted_value = _GetValueFormattedForMSBuild(tool_name, name,
+                                                           value)
+            tool.append([name, formatted_value])
+          group.append(tool)
+    groups.append(group)
+  return groups
+
+
+def _FinalizeMSBuildSettings(spec, configuration):
+  if 'msbuild_settings' in configuration:
+    converted = False
+    msbuild_settings = configuration['msbuild_settings']
+    MSVSSettings.ValidateMSBuildSettings(msbuild_settings)
+  else:
+    converted = True
+    msvs_settings = configuration.get('msvs_settings', {})
+    msbuild_settings = MSVSSettings.ConvertToMSBuildSettings(msvs_settings)
+  include_dirs, resource_include_dirs = _GetIncludeDirs(configuration)
+  libraries = _GetLibraries(spec)
+  out_file, _, msbuild_tool = _GetOutputFilePathAndTool(spec, msbuild=True)
+  defines = _GetDefines(configuration)
+  if converted:
+    # Visual Studio 2010 has TR1
+    defines = [d for d in defines if d != '_HAS_TR1=0']
+    # Warn of ignored settings
+    ignored_settings = ['msvs_prebuild', 'msvs_postbuild', 'msvs_tool_files']
+    for ignored_setting in ignored_settings:
+      value = configuration.get(ignored_setting)
+      if value:
+        print ('Warning: The automatic conversion to MSBuild does not handle '
+               '%s.  Ignoring setting of %s' % (ignored_setting, str(value)))
+
+  defines = [_EscapeCppDefineForMSBuild(d) for d in defines]
+  disabled_warnings = _GetDisabledWarnings(configuration)
+  # TODO(jeanluc) Validate & warn that we don't translate
+  # prebuild = configuration.get('msvs_prebuild')
+  # postbuild = configuration.get('msvs_postbuild')
+  def_file = _GetModuleDefinition(spec)
+  precompiled_header = configuration.get('msvs_precompiled_header')
+
+  # Add the information to the appropriate tool
+  # TODO(jeanluc) We could optimize and generate these settings only if
+  # the corresponding files are found, e.g. don't generate ResourceCompile
+  # if you don't have any resources.
+  _ToolAppend(msbuild_settings, 'ClCompile',
+              'AdditionalIncludeDirectories', include_dirs)
+  _ToolAppend(msbuild_settings, 'ResourceCompile',
+              'AdditionalIncludeDirectories', resource_include_dirs)
+  # Add in libraries, note that even for empty libraries, we want this
+  # set, to prevent inheriting default libraries from the enviroment.
+  _ToolSetOrAppend(msbuild_settings, 'Link', 'AdditionalDependencies',
+                  libraries)
+  if out_file:
+    _ToolAppend(msbuild_settings, msbuild_tool, 'OutputFile', out_file,
+                only_if_unset=True)
+  # Add defines.
+  _ToolAppend(msbuild_settings, 'ClCompile',
+              'PreprocessorDefinitions', defines)
+  _ToolAppend(msbuild_settings, 'ResourceCompile',
+              'PreprocessorDefinitions', defines)
+  # Add disabled warnings.
+  _ToolAppend(msbuild_settings, 'ClCompile',
+              'DisableSpecificWarnings', disabled_warnings)
+  # Turn on precompiled headers if appropriate.
+  if precompiled_header:
+    precompiled_header = os.path.split(precompiled_header)[1]
+    _ToolAppend(msbuild_settings, 'ClCompile', 'PrecompiledHeader', 'Use')
+    _ToolAppend(msbuild_settings, 'ClCompile',
+                'PrecompiledHeaderFile', precompiled_header)
+    _ToolAppend(msbuild_settings, 'ClCompile',
+                'ForcedIncludeFiles', precompiled_header)
+  # Loadable modules don't generate import libraries;
+  # tell dependent projects to not expect one.
+  if spec['type'] == 'loadable_module':
+    _ToolAppend(msbuild_settings, '', 'IgnoreImportLibrary', 'true')
+  # Set the module definition file if any.
+  if def_file:
+    _ToolAppend(msbuild_settings, 'Link', 'ModuleDefinitionFile', def_file)
+  configuration['finalized_msbuild_settings'] = msbuild_settings
+
+
+def _GetValueFormattedForMSBuild(tool_name, name, value):
+  if type(value) == list:
+    # For some settings, VS2010 does not automatically extends the settings
+    # TODO(jeanluc) Is this what we want?
+    if name in ['AdditionalIncludeDirectories',
+                'AdditionalLibraryDirectories',
+                'AdditionalOptions',
+                'DelayLoadDLLs',
+                'DisableSpecificWarnings',
+                'PreprocessorDefinitions']:
+      value.append('%%(%s)' % name)
+    # For most tools, entries in a list should be separated with ';' but some
+    # settings use a space.  Check for those first.
+    exceptions = {
+        'ClCompile': ['AdditionalOptions'],
+        'Link': ['AdditionalOptions'],
+        'Lib': ['AdditionalOptions']}
+    if tool_name in exceptions and name in exceptions[tool_name]:
+      char = ' '
+    else:
+      char = ';'
+    formatted_value = char.join(
+        [MSVSSettings.ConvertVCMacrosToMSBuild(i) for i in value])
+  else:
+    formatted_value = MSVSSettings.ConvertVCMacrosToMSBuild(value)
+  return formatted_value
+
+
+def _VerifySourcesExist(sources, root_dir):
+  """Verifies that all source files exist on disk.
+
+  Checks that all regular source files, i.e. not created at run time,
+  exist on disk.  Missing files cause needless recompilation but no otherwise
+  visible errors.
+
+  Arguments:
+    sources: A recursive list of Filter/file names.
+    root_dir: The root directory for the relative path names.
+  Returns:
+    A list of source files that cannot be found on disk.
+  """
+  missing_sources = []
+  for source in sources:
+    if isinstance(source, MSVSProject.Filter):
+      missing_sources.extend(_VerifySourcesExist(source.contents, root_dir))
+    else:
+      if '$' not in source:
+        full_path = os.path.join(root_dir, source)
+        if not os.path.exists(full_path):
+          missing_sources.append(full_path)
+  return missing_sources
+
+
+def _GetMSBuildSources(spec, sources, exclusions, extension_to_rule_name,
+                       actions_spec, sources_handled_by_action, list_excluded):
+  groups = ['none', 'midl', 'include', 'compile', 'resource', 'rule']
+  grouped_sources = {}
+  for g in groups:
+    grouped_sources[g] = []
+
+  _AddSources2(spec, sources, exclusions, grouped_sources,
+               extension_to_rule_name, sources_handled_by_action, list_excluded)
+  sources = []
+  for g in groups:
+    if grouped_sources[g]:
+      sources.append(['ItemGroup'] + grouped_sources[g])
+  if actions_spec:
+    sources.append(['ItemGroup'] + actions_spec)
+  return sources
+
+
+def _AddSources2(spec, sources, exclusions, grouped_sources,
+                 extension_to_rule_name, sources_handled_by_action,
+                 list_excluded):
+  extensions_excluded_from_precompile = []
+  for source in sources:
+    if isinstance(source, MSVSProject.Filter):
+      _AddSources2(spec, source.contents, exclusions, grouped_sources,
+                   extension_to_rule_name, sources_handled_by_action,
+                   list_excluded)
+    else:
+      if not source in sources_handled_by_action:
+        detail = []
+        excluded_configurations = exclusions.get(source, [])
+        if len(excluded_configurations) == len(spec['configurations']):
+          detail.append(['ExcludedFromBuild', 'true'])
+        else:
+          for config_name, configuration in sorted(excluded_configurations):
+            condition = _GetConfigurationCondition(config_name, configuration)
+            detail.append(['ExcludedFromBuild',
+                           {'Condition': condition},
+                           'true'])
+        # Add precompile if needed
+        for config_name, configuration in spec['configurations'].iteritems():
+          precompiled_source = configuration.get('msvs_precompiled_source', '')
+          if precompiled_source != '':
+            precompiled_source = _FixPath(precompiled_source)
+            if not extensions_excluded_from_precompile:
+              # If the precompiled header is generated by a C source, we must
+              # not try to use it for C++ sources, and vice versa.
+              basename, extension = os.path.splitext(precompiled_source)
+              if extension == '.c':
+                extensions_excluded_from_precompile = ['.cc', '.cpp', '.cxx']
+              else:
+                extensions_excluded_from_precompile = ['.c']
+
+          if precompiled_source == source:
+            condition = _GetConfigurationCondition(config_name, configuration)
+            detail.append(['PrecompiledHeader',
+                           {'Condition': condition},
+                           'Create'
+                          ])
+          else:
+            # Turn off precompiled header usage for source files of a
+            # different type than the file that generated the
+            # precompiled header.
+            for extension in extensions_excluded_from_precompile:
+              if source.endswith(extension):
+                detail.append(['PrecompiledHeader', ''])
+                detail.append(['ForcedIncludeFiles', ''])
+
+        group, element = _MapFileToMsBuildSourceType(source,
+                                                     extension_to_rule_name)
+        grouped_sources[group].append([element, {'Include': source}] + detail)
+
+
+def _GetMSBuildProjectReferences(project):
+  references = []
+  if project.dependencies:
+    group = ['ItemGroup']
+    for dependency in project.dependencies:
+      guid = dependency.guid
+      project_dir = os.path.split(project.path)[0]
+      relative_path = gyp.common.RelativePath(dependency.path, project_dir)
+      project_ref = ['ProjectReference',
+          {'Include': relative_path},
+          ['Project', guid],
+          ['ReferenceOutputAssembly', 'false']
+          ]
+      for config in dependency.spec.get('configurations', {}).itervalues():
+        # If it's disabled in any config, turn it off in the reference.
+        if config.get('msvs_2010_disable_uldi_when_referenced', 0):
+          project_ref.append(['UseLibraryDependencyInputs', 'false'])
+          break
+      group.append(project_ref)
+    references.append(group)
+  return references
+
+
+def _GenerateMSBuildProject(project, options, version, generator_flags):
+  spec = project.spec
+  configurations = spec['configurations']
+  project_dir, project_file_name = os.path.split(project.path)
+  msbuildproj_dir = os.path.dirname(project.path)
+  if msbuildproj_dir and not os.path.exists(msbuildproj_dir):
+    os.makedirs(msbuildproj_dir)
+  # Prepare list of sources and excluded sources.
+  gyp_path = _NormalizedSource(project.build_file)
+  relative_path_of_gyp_file = gyp.common.RelativePath(gyp_path, project_dir)
+
+  gyp_file = os.path.split(project.build_file)[1]
+  sources, excluded_sources = _PrepareListOfSources(spec, generator_flags,
+                                                    gyp_file)
+  # Add rules.
+  actions_to_add = {}
+  props_files_of_rules = set()
+  targets_files_of_rules = set()
+  extension_to_rule_name = {}
+  list_excluded = generator_flags.get('msvs_list_excluded_files', True)
+  _GenerateRulesForMSBuild(project_dir, options, spec,
+                           sources, excluded_sources,
+                           props_files_of_rules, targets_files_of_rules,
+                           actions_to_add, extension_to_rule_name)
+  sources, excluded_sources, excluded_idl = (
+      _AdjustSourcesAndConvertToFilterHierarchy(spec, options,
+                                                project_dir, sources,
+                                                excluded_sources,
+                                                list_excluded))
+  _AddActions(actions_to_add, spec, project.build_file)
+  _AddCopies(actions_to_add, spec)
+
+  # NOTE: this stanza must appear after all actions have been decided.
+  # Don't excluded sources with actions attached, or they won't run.
+  excluded_sources = _FilterActionsFromExcluded(
+      excluded_sources, actions_to_add)
+
+  exclusions = _GetExcludedFilesFromBuild(spec, excluded_sources, excluded_idl)
+  actions_spec, sources_handled_by_action = _GenerateActionsForMSBuild(
+      spec, actions_to_add)
+
+  _GenerateMSBuildFiltersFile(project.path + '.filters', sources,
+                              extension_to_rule_name)
+  missing_sources = _VerifySourcesExist(sources, project_dir)
+
+  for configuration in configurations.itervalues():
+    _FinalizeMSBuildSettings(spec, configuration)
+
+  # Add attributes to root element
+
+  import_default_section = [
+      ['Import', {'Project': r'$(VCTargetsPath)\Microsoft.Cpp.Default.props'}]]
+  import_cpp_props_section = [
+      ['Import', {'Project': r'$(VCTargetsPath)\Microsoft.Cpp.props'}]]
+  import_cpp_targets_section = [
+      ['Import', {'Project': r'$(VCTargetsPath)\Microsoft.Cpp.targets'}]]
+  macro_section = [['PropertyGroup', {'Label': 'UserMacros'}]]
+
+  content = [
+      'Project',
+      {'xmlns': 'http://schemas.microsoft.com/developer/msbuild/2003',
+       'ToolsVersion': version.ProjectVersion(),
+       'DefaultTargets': 'Build'
+      }]
+
+  content += _GetMSBuildProjectConfigurations(configurations)
+  content += _GetMSBuildGlobalProperties(spec, project.guid, project_file_name)
+  content += import_default_section
+  content += _GetMSBuildConfigurationDetails(spec, project.build_file)
+  content += _GetMSBuildLocalProperties(project.msbuild_toolset)
+  content += import_cpp_props_section
+  content += _GetMSBuildExtensions(props_files_of_rules)
+  content += _GetMSBuildPropertySheets(configurations)
+  content += macro_section
+  content += _GetMSBuildConfigurationGlobalProperties(spec, configurations,
+                                                      project.build_file)
+  content += _GetMSBuildToolSettingsSections(spec, configurations)
+  content += _GetMSBuildSources(
+      spec, sources, exclusions, extension_to_rule_name, actions_spec,
+      sources_handled_by_action, list_excluded)
+  content += _GetMSBuildProjectReferences(project)
+  content += import_cpp_targets_section
+  content += _GetMSBuildExtensionTargets(targets_files_of_rules)
+
+  # TODO(jeanluc) File a bug to get rid of runas.  We had in MSVS:
+  # has_run_as = _WriteMSVSUserFile(project.path, version, spec)
+
+  easy_xml.WriteXmlIfChanged(content, project.path, pretty=True, win32=True)
+
+  return missing_sources
+
+
+def _GetMSBuildExtensions(props_files_of_rules):
+  extensions = ['ImportGroup', {'Label': 'ExtensionSettings'}]
+  for props_file in props_files_of_rules:
+    extensions.append(['Import', {'Project': props_file}])
+  return [extensions]
+
+
+def _GetMSBuildExtensionTargets(targets_files_of_rules):
+  targets_node = ['ImportGroup', {'Label': 'ExtensionTargets'}]
+  for targets_file in sorted(targets_files_of_rules):
+    targets_node.append(['Import', {'Project': targets_file}])
+  return [targets_node]
+
+
+def _GenerateActionsForMSBuild(spec, actions_to_add):
+  """Add actions accumulated into an actions_to_add, merging as needed.
+
+  Arguments:
+    spec: the target project dict
+    actions_to_add: dictionary keyed on input name, which maps to a list of
+        dicts describing the actions attached to that input file.
+
+  Returns:
+    A pair of (action specification, the sources handled by this action).
+  """
+  sources_handled_by_action = set()
+  actions_spec = []
+  for primary_input, actions in actions_to_add.iteritems():
+    inputs = set()
+    outputs = set()
+    descriptions = []
+    commands = []
+    for action in actions:
+      inputs.update(set(action['inputs']))
+      outputs.update(set(action['outputs']))
+      descriptions.append(action['description'])
+      cmd = action['command']
+      # For most actions, add 'call' so that actions that invoke batch files
+      # return and continue executing.  msbuild_use_call provides a way to
+      # disable this but I have not seen any adverse effect from doing that
+      # for everything.
+      if action.get('msbuild_use_call', True):
+        cmd = 'call ' + cmd
+      commands.append(cmd)
+    # Add the custom build action for one input file.
+    description = ', and also '.join(descriptions)
+
+    # We can't join the commands simply with && because the command line will
+    # get too long. See also _AddActions: cygwin's setup_env mustn't be called
+    # for every invocation or the command that sets the PATH will grow too
+    # long.
+    command = (
+        '\r\nif %errorlevel% neq 0 exit /b %errorlevel%\r\n'.join(commands))
+    _AddMSBuildAction(spec,
+                      primary_input,
+                      inputs,
+                      outputs,
+                      command,
+                      description,
+                      sources_handled_by_action,
+                      actions_spec)
+  return actions_spec, sources_handled_by_action
+
+
+def _AddMSBuildAction(spec, primary_input, inputs, outputs, cmd, description,
+                      sources_handled_by_action, actions_spec):
+  command = MSVSSettings.ConvertVCMacrosToMSBuild(cmd)
+  primary_input = _FixPath(primary_input)
+  inputs_array = _FixPaths(inputs)
+  outputs_array = _FixPaths(outputs)
+  additional_inputs = ';'.join([i for i in inputs_array
+                                if i != primary_input])
+  outputs = ';'.join(outputs_array)
+  sources_handled_by_action.add(primary_input)
+  action_spec = ['CustomBuild', {'Include': primary_input}]
+  action_spec.extend(
+      # TODO(jeanluc) 'Document' for all or just if as_sources?
+      [['FileType', 'Document'],
+       ['Command', command],
+       ['Message', description],
+       ['Outputs', outputs]
+      ])
+  if additional_inputs:
+    action_spec.append(['AdditionalInputs', additional_inputs])
+  actions_spec.append(action_spec)
diff --git a/webWidgetTCT_device/tools/gyp/pylib/gyp/generator/msvs_test.py b/webWidgetTCT_device/tools/gyp/pylib/gyp/generator/msvs_test.py
new file mode 100755 (executable)
index 0000000..c0b021d
--- /dev/null
@@ -0,0 +1,37 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+""" Unit tests for the msvs.py file. """
+
+import gyp.generator.msvs as msvs
+import unittest
+import StringIO
+
+
+class TestSequenceFunctions(unittest.TestCase):
+
+  def setUp(self):
+    self.stderr = StringIO.StringIO()
+
+  def test_GetLibraries(self):
+    self.assertEqual(
+      msvs._GetLibraries({}),
+      [])
+    self.assertEqual(
+      msvs._GetLibraries({'libraries': []}),
+      [])
+    self.assertEqual(
+      msvs._GetLibraries({'other':'foo', 'libraries': ['a.lib']}),
+      ['a.lib'])
+    self.assertEqual(
+      msvs._GetLibraries({'libraries': ['-la']}),
+      ['a.lib'])
+    self.assertEqual(
+      msvs._GetLibraries({'libraries': ['a.lib', 'b.lib', 'c.lib', '-lb.lib',
+                                   '-lb.lib', 'd.lib', 'a.lib']}),
+      ['c.lib', 'b.lib', 'd.lib', 'a.lib'])
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/webWidgetTCT_device/tools/gyp/pylib/gyp/generator/ninja.py b/webWidgetTCT_device/tools/gyp/pylib/gyp/generator/ninja.py
new file mode 100755 (executable)
index 0000000..619ac39
--- /dev/null
@@ -0,0 +1,1820 @@
+# Copyright (c) 2013 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import copy
+import hashlib
+import multiprocessing
+import os.path
+import re
+import signal
+import subprocess
+import sys
+import gyp
+import gyp.common
+import gyp.msvs_emulation
+import gyp.MSVSUtil as MSVSUtil
+import gyp.xcode_emulation
+
+from gyp.common import GetEnvironFallback
+import gyp.ninja_syntax as ninja_syntax
+
+generator_default_variables = {
+  'EXECUTABLE_PREFIX': '',
+  'EXECUTABLE_SUFFIX': '',
+  'STATIC_LIB_PREFIX': 'lib',
+  'STATIC_LIB_SUFFIX': '.a',
+  'SHARED_LIB_PREFIX': 'lib',
+
+  # Gyp expects the following variables to be expandable by the build
+  # system to the appropriate locations.  Ninja prefers paths to be
+  # known at gyp time.  To resolve this, introduce special
+  # variables starting with $! and $| (which begin with a $ so gyp knows it
+  # should be treated specially, but is otherwise an invalid
+  # ninja/shell variable) that are passed to gyp here but expanded
+  # before writing out into the target .ninja files; see
+  # ExpandSpecial.
+  # $! is used for variables that represent a path and that can only appear at
+  # the start of a string, while $| is used for variables that can appear
+  # anywhere in a string.
+  'INTERMEDIATE_DIR': '$!INTERMEDIATE_DIR',
+  'SHARED_INTERMEDIATE_DIR': '$!PRODUCT_DIR/gen',
+  'PRODUCT_DIR': '$!PRODUCT_DIR',
+  'CONFIGURATION_NAME': '$|CONFIGURATION_NAME',
+
+  # Special variables that may be used by gyp 'rule' targets.
+  # We generate definitions for these variables on the fly when processing a
+  # rule.
+  'RULE_INPUT_ROOT': '${root}',
+  'RULE_INPUT_DIRNAME': '${dirname}',
+  'RULE_INPUT_PATH': '${source}',
+  'RULE_INPUT_EXT': '${ext}',
+  'RULE_INPUT_NAME': '${name}',
+}
+
+# Placates pylint.
+generator_additional_non_configuration_keys = []
+generator_additional_path_sections = []
+generator_extra_sources_for_rules = []
+
+# TODO: figure out how to not build extra host objects in the non-cross-compile
+# case when this is enabled, and enable unconditionally.
+generator_supports_multiple_toolsets = (
+  os.environ.get('GYP_CROSSCOMPILE') or
+  os.environ.get('AR_host') or
+  os.environ.get('CC_host') or
+  os.environ.get('CXX_host') or
+  os.environ.get('AR_target') or
+  os.environ.get('CC_target') or
+  os.environ.get('CXX_target'))
+
+
+def StripPrefix(arg, prefix):
+  if arg.startswith(prefix):
+    return arg[len(prefix):]
+  return arg
+
+
+def QuoteShellArgument(arg, flavor):
+  """Quote a string such that it will be interpreted as a single argument
+  by the shell."""
+  # Rather than attempting to enumerate the bad shell characters, just
+  # whitelist common OK ones and quote anything else.
+  if re.match(r'^[a-zA-Z0-9_=.\\/-]+$', arg):
+    return arg  # No quoting necessary.
+  if flavor == 'win':
+    return gyp.msvs_emulation.QuoteForRspFile(arg)
+  return "'" + arg.replace("'", "'" + '"\'"' + "'")  + "'"
+
+
+def Define(d, flavor):
+  """Takes a preprocessor define and returns a -D parameter that's ninja- and
+  shell-escaped."""
+  if flavor == 'win':
+    # cl.exe replaces literal # characters with = in preprocesor definitions for
+    # some reason. Octal-encode to work around that.
+    d = d.replace('#', '\\%03o' % ord('#'))
+  return QuoteShellArgument(ninja_syntax.escape('-D' + d), flavor)
+
+
+class Target:
+  """Target represents the paths used within a single gyp target.
+
+  Conceptually, building a single target A is a series of steps:
+
+  1) actions/rules/copies  generates source/resources/etc.
+  2) compiles              generates .o files
+  3) link                  generates a binary (library/executable)
+  4) bundle                merges the above in a mac bundle
+
+  (Any of these steps can be optional.)
+
+  From a build ordering perspective, a dependent target B could just
+  depend on the last output of this series of steps.
+
+  But some dependent commands sometimes need to reach inside the box.
+  For example, when linking B it needs to get the path to the static
+  library generated by A.
+
+  This object stores those paths.  To keep things simple, member
+  variables only store concrete paths to single files, while methods
+  compute derived values like "the last output of the target".
+  """
+  def __init__(self, type):
+    # Gyp type ("static_library", etc.) of this target.
+    self.type = type
+    # File representing whether any input dependencies necessary for
+    # dependent actions have completed.
+    self.preaction_stamp = None
+    # File representing whether any input dependencies necessary for
+    # dependent compiles have completed.
+    self.precompile_stamp = None
+    # File representing the completion of actions/rules/copies, if any.
+    self.actions_stamp = None
+    # Path to the output of the link step, if any.
+    self.binary = None
+    # Path to the file representing the completion of building the bundle,
+    # if any.
+    self.bundle = None
+    # On Windows, incremental linking requires linking against all the .objs
+    # that compose a .lib (rather than the .lib itself). That list is stored
+    # here.
+    self.component_objs = None
+    # Windows only. The import .lib is the output of a build step, but
+    # because dependents only link against the lib (not both the lib and the
+    # dll) we keep track of the import library here.
+    self.import_lib = None
+
+  def Linkable(self):
+    """Return true if this is a target that can be linked against."""
+    return self.type in ('static_library', 'shared_library')
+
+  def UsesToc(self, flavor):
+    """Return true if the target should produce a restat rule based on a TOC
+    file."""
+    # For bundles, the .TOC should be produced for the binary, not for
+    # FinalOutput(). But the naive approach would put the TOC file into the
+    # bundle, so don't do this for bundles for now.
+    if flavor == 'win' or self.bundle:
+      return False
+    return self.type in ('shared_library', 'loadable_module')
+
+  def PreActionInput(self, flavor):
+    """Return the path, if any, that should be used as a dependency of
+    any dependent action step."""
+    if self.UsesToc(flavor):
+      return self.FinalOutput() + '.TOC'
+    return self.FinalOutput() or self.preaction_stamp
+
+  def PreCompileInput(self):
+    """Return the path, if any, that should be used as a dependency of
+    any dependent compile step."""
+    return self.actions_stamp or self.precompile_stamp
+
+  def FinalOutput(self):
+    """Return the last output of the target, which depends on all prior
+    steps."""
+    return self.bundle or self.binary or self.actions_stamp
+
+
+# A small discourse on paths as used within the Ninja build:
+# All files we produce (both at gyp and at build time) appear in the
+# build directory (e.g. out/Debug).
+#
+# Paths within a given .gyp file are always relative to the directory
+# containing the .gyp file.  Call these "gyp paths".  This includes
+# sources as well as the starting directory a given gyp rule/action
+# expects to be run from.  We call the path from the source root to
+# the gyp file the "base directory" within the per-.gyp-file
+# NinjaWriter code.
+#
+# All paths as written into the .ninja files are relative to the build
+# directory.  Call these paths "ninja paths".
+#
+# We translate between these two notions of paths with two helper
+# functions:
+#
+# - GypPathToNinja translates a gyp path (i.e. relative to the .gyp file)
+#   into the equivalent ninja path.
+#
+# - GypPathToUniqueOutput translates a gyp path into a ninja path to write
+#   an output file; the result can be namespaced such that it is unique
+#   to the input file name as well as the output target name.
+
+class NinjaWriter:
+  def __init__(self, qualified_target, target_outputs, base_dir, build_dir,
+               output_file, flavor, toplevel_dir=None):
+    """
+    base_dir: path from source root to directory containing this gyp file,
+              by gyp semantics, all input paths are relative to this
+    build_dir: path from source root to build output
+    toplevel_dir: path to the toplevel directory
+    """
+
+    self.qualified_target = qualified_target
+    self.target_outputs = target_outputs
+    self.base_dir = base_dir
+    self.build_dir = build_dir
+    self.ninja = ninja_syntax.Writer(output_file)
+    self.flavor = flavor
+    self.abs_build_dir = None
+    if toplevel_dir is not None:
+      self.abs_build_dir = os.path.abspath(os.path.join(toplevel_dir,
+                                                        build_dir))
+    self.obj_ext = '.obj' if flavor == 'win' else '.o'
+    if flavor == 'win':
+      # See docstring of msvs_emulation.GenerateEnvironmentFiles().
+      self.win_env = {}
+      for arch in ('x86', 'x64'):
+        self.win_env[arch] = 'environment.' + arch
+
+    # Relative path from build output dir to base dir.
+    build_to_top = gyp.common.InvertRelativePath(build_dir, toplevel_dir)
+    self.build_to_base = os.path.join(build_to_top, base_dir)
+    # Relative path from base dir to build dir.
+    base_to_top = gyp.common.InvertRelativePath(base_dir, toplevel_dir)
+    self.base_to_build = os.path.join(base_to_top, build_dir)
+
+  def ExpandSpecial(self, path, product_dir=None):
+    """Expand specials like $!PRODUCT_DIR in |path|.
+
+    If |product_dir| is None, assumes the cwd is already the product
+    dir.  Otherwise, |product_dir| is the relative path to the product
+    dir.
+    """
+
+    PRODUCT_DIR = '$!PRODUCT_DIR'
+    if PRODUCT_DIR in path:
+      if product_dir:
+        path = path.replace(PRODUCT_DIR, product_dir)
+      else:
+        path = path.replace(PRODUCT_DIR + '/', '')
+        path = path.replace(PRODUCT_DIR + '\\', '')
+        path = path.replace(PRODUCT_DIR, '.')
+
+    INTERMEDIATE_DIR = '$!INTERMEDIATE_DIR'
+    if INTERMEDIATE_DIR in path:
+      int_dir = self.GypPathToUniqueOutput('gen')
+      # GypPathToUniqueOutput generates a path relative to the product dir,
+      # so insert product_dir in front if it is provided.
+      path = path.replace(INTERMEDIATE_DIR,
+                          os.path.join(product_dir or '', int_dir))
+
+    CONFIGURATION_NAME = '$|CONFIGURATION_NAME'
+    path = path.replace(CONFIGURATION_NAME, self.config_name)
+
+    return path
+
+  def ExpandRuleVariables(self, path, root, dirname, source, ext, name):
+    if self.flavor == 'win':
+      path = self.msvs_settings.ConvertVSMacros(
+          path, config=self.config_name)
+    path = path.replace(generator_default_variables['RULE_INPUT_ROOT'], root)
+    path = path.replace(generator_default_variables['RULE_INPUT_DIRNAME'],
+                        dirname)
+    path = path.replace(generator_default_variables['RULE_INPUT_PATH'], source)
+    path = path.replace(generator_default_variables['RULE_INPUT_EXT'], ext)
+    path = path.replace(generator_default_variables['RULE_INPUT_NAME'], name)
+    return path
+
+  def GypPathToNinja(self, path, env=None):
+    """Translate a gyp path to a ninja path, optionally expanding environment
+    variable references in |path| with |env|.
+
+    See the above discourse on path conversions."""
+    if env:
+      if self.flavor == 'mac':
+        path = gyp.xcode_emulation.ExpandEnvVars(path, env)
+      elif self.flavor == 'win':
+        path = gyp.msvs_emulation.ExpandMacros(path, env)
+    if path.startswith('$!'):
+      expanded = self.ExpandSpecial(path)
+      if self.flavor == 'win':
+        expanded = os.path.normpath(expanded)
+      return expanded
+    if '$|' in path:
+      path =  self.ExpandSpecial(path)
+    assert '$' not in path, path
+    return os.path.normpath(os.path.join(self.build_to_base, path))
+
+  def GypPathToUniqueOutput(self, path, qualified=True):
+    """Translate a gyp path to a ninja path for writing output.
+
+    If qualified is True, qualify the resulting filename with the name
+    of the target.  This is necessary when e.g. compiling the same
+    path twice for two separate output targets.
+
+    See the above discourse on path conversions."""
+
+    path = self.ExpandSpecial(path)
+    assert not path.startswith('$'), path
+
+    # Translate the path following this scheme:
+    #   Input: foo/bar.gyp, target targ, references baz/out.o
+    #   Output: obj/foo/baz/targ.out.o (if qualified)
+    #           obj/foo/baz/out.o (otherwise)
+    #     (and obj.host instead of obj for cross-compiles)
+    #
+    # Why this scheme and not some other one?
+    # 1) for a given input, you can compute all derived outputs by matching
+    #    its path, even if the input is brought via a gyp file with '..'.
+    # 2) simple files like libraries and stamps have a simple filename.
+
+    obj = 'obj'
+    if self.toolset != 'target':
+      obj += '.' + self.toolset
+
+    path_dir, path_basename = os.path.split(path)
+    if qualified:
+      path_basename = self.name + '.' + path_basename
+    return os.path.normpath(os.path.join(obj, self.base_dir, path_dir,
+                                         path_basename))
+
+  def WriteCollapsedDependencies(self, name, targets):
+    """Given a list of targets, return a path for a single file
+    representing the result of building all the targets or None.
+
+    Uses a stamp file if necessary."""
+
+    assert targets == filter(None, targets), targets
+    if len(targets) == 0:
+      return None
+    if len(targets) > 1:
+      stamp = self.GypPathToUniqueOutput(name + '.stamp')
+      targets = self.ninja.build(stamp, 'stamp', targets)
+      self.ninja.newline()
+    return targets[0]
+
+  def WriteSpec(self, spec, config_name, generator_flags,
+      case_sensitive_filesystem):
+    """The main entry point for NinjaWriter: write the build rules for a spec.
+
+    Returns a Target object, which represents the output paths for this spec.
+    Returns None if there are no outputs (e.g. a settings-only 'none' type
+    target)."""
+
+    self.config_name = config_name
+    self.name = spec['target_name']
+    self.toolset = spec['toolset']
+    config = spec['configurations'][config_name]
+    self.target = Target(spec['type'])
+    self.is_standalone_static_library = bool(
+        spec.get('standalone_static_library', 0))
+
+    self.is_mac_bundle = gyp.xcode_emulation.IsMacBundle(self.flavor, spec)
+    self.xcode_settings = self.msvs_settings = None
+    if self.flavor == 'mac':
+      self.xcode_settings = gyp.xcode_emulation.XcodeSettings(spec)
+    if self.flavor == 'win':
+      self.msvs_settings = gyp.msvs_emulation.MsvsSettings(spec,
+                                                           generator_flags)
+      arch = self.msvs_settings.GetArch(config_name)
+      self.ninja.variable('arch', self.win_env[arch])
+
+    # Compute predepends for all rules.
+    # actions_depends is the dependencies this target depends on before running
+    # any of its action/rule/copy steps.
+    # compile_depends is the dependencies this target depends on before running
+    # any of its compile steps.
+    actions_depends = []
+    compile_depends = []
+    # TODO(evan): it is rather confusing which things are lists and which
+    # are strings.  Fix these.
+    if 'dependencies' in spec:
+      for dep in spec['dependencies']:
+        if dep in self.target_outputs:
+          target = self.target_outputs[dep]
+          actions_depends.append(target.PreActionInput(self.flavor))
+          compile_depends.append(target.PreCompileInput())
+      actions_depends = filter(None, actions_depends)
+      compile_depends = filter(None, compile_depends)
+      actions_depends = self.WriteCollapsedDependencies('actions_depends',
+                                                        actions_depends)
+      compile_depends = self.WriteCollapsedDependencies('compile_depends',
+                                                        compile_depends)
+      self.target.preaction_stamp = actions_depends
+      self.target.precompile_stamp = compile_depends
+
+    # Write out actions, rules, and copies.  These must happen before we
+    # compile any sources, so compute a list of predependencies for sources
+    # while we do it.
+    extra_sources = []
+    mac_bundle_depends = []
+    self.target.actions_stamp = self.WriteActionsRulesCopies(
+        spec, extra_sources, actions_depends, mac_bundle_depends)
+
+    # If we have actions/rules/copies, we depend directly on those, but
+    # otherwise we depend on dependent target's actions/rules/copies etc.
+    # We never need to explicitly depend on previous target's link steps,
+    # because no compile ever depends on them.
+    compile_depends_stamp = (self.target.actions_stamp or compile_depends)
+
+    # Write out the compilation steps, if any.
+    link_deps = []
+    sources = spec.get('sources', []) + extra_sources
+    if sources:
+      pch = None
+      if self.flavor == 'win':
+        gyp.msvs_emulation.VerifyMissingSources(
+            sources, self.abs_build_dir, generator_flags, self.GypPathToNinja)
+        pch = gyp.msvs_emulation.PrecompiledHeader(
+            self.msvs_settings, config_name, self.GypPathToNinja,
+            self.GypPathToUniqueOutput, self.obj_ext)
+      else:
+        pch = gyp.xcode_emulation.MacPrefixHeader(
+            self.xcode_settings, self.GypPathToNinja,
+            lambda path, lang: self.GypPathToUniqueOutput(path + '-' + lang))
+      link_deps = self.WriteSources(
+          config_name, config, sources, compile_depends_stamp, pch,
+          case_sensitive_filesystem, spec)
+      # Some actions/rules output 'sources' that are already object files.
+      link_deps += [self.GypPathToNinja(f)
+          for f in sources if f.endswith(self.obj_ext)]
+
+    if self.flavor == 'win' and self.target.type == 'static_library':
+      self.target.component_objs = link_deps
+
+    # Write out a link step, if needed.
+    output = None
+    if link_deps or self.target.actions_stamp or actions_depends:
+      output = self.WriteTarget(spec, config_name, config, link_deps,
+                                self.target.actions_stamp or actions_depends)
+      if self.is_mac_bundle:
+        mac_bundle_depends.append(output)
+
+    # Bundle all of the above together, if needed.
+    if self.is_mac_bundle:
+      output = self.WriteMacBundle(spec, mac_bundle_depends)
+
+    if not output:
+      return None
+
+    assert self.target.FinalOutput(), output
+    return self.target
+
+  def _WinIdlRule(self, source, prebuild, outputs):
+    """Handle the implicit VS .idl rule for one source file. Fills |outputs|
+    with files that are generated."""
+    outdir, output, vars, flags = self.msvs_settings.GetIdlBuildData(
+        source, self.config_name)
+    outdir = self.GypPathToNinja(outdir)
+    def fix_path(path, rel=None):
+      path = os.path.join(outdir, path)
+      dirname, basename = os.path.split(source)
+      root, ext = os.path.splitext(basename)
+      path = self.ExpandRuleVariables(
+          path, root, dirname, source, ext, basename)
+      if rel:
+        path = os.path.relpath(path, rel)
+      return path
+    vars = [(name, fix_path(value, outdir)) for name, value in vars]
+    output = [fix_path(p) for p in output]
+    vars.append(('outdir', outdir))
+    vars.append(('idlflags', flags))
+    input = self.GypPathToNinja(source)
+    self.ninja.build(output, 'idl', input,
+        variables=vars, order_only=prebuild)
+    outputs.extend(output)
+
+  def WriteWinIdlFiles(self, spec, prebuild):
+    """Writes rules to match MSVS's implicit idl handling."""
+    assert self.flavor == 'win'
+    if self.msvs_settings.HasExplicitIdlRules(spec):
+      return []
+    outputs = []
+    for source in filter(lambda x: x.endswith('.idl'), spec['sources']):
+      self._WinIdlRule(source, prebuild, outputs)
+    return outputs
+
+  def WriteActionsRulesCopies(self, spec, extra_sources, prebuild,
+                              mac_bundle_depends):
+    """Write out the Actions, Rules, and Copies steps.  Return a path
+    representing the outputs of these steps."""
+    outputs = []
+    extra_mac_bundle_resources = []
+
+    if 'actions' in spec:
+      outputs += self.WriteActions(spec['actions'], extra_sources, prebuild,
+                                   extra_mac_bundle_resources)
+    if 'rules' in spec:
+      outputs += self.WriteRules(spec['rules'], extra_sources, prebuild,
+                                 extra_mac_bundle_resources)
+    if 'copies' in spec:
+      outputs += self.WriteCopies(spec['copies'], prebuild, mac_bundle_depends)
+
+    if 'sources' in spec and self.flavor == 'win':
+      outputs += self.WriteWinIdlFiles(spec, prebuild)
+
+    stamp = self.WriteCollapsedDependencies('actions_rules_copies', outputs)
+
+    if self.is_mac_bundle:
+      mac_bundle_resources = spec.get('mac_bundle_resources', []) + \
+                             extra_mac_bundle_resources
+      self.WriteMacBundleResources(mac_bundle_resources, mac_bundle_depends)
+      self.WriteMacInfoPlist(mac_bundle_depends)
+
+    return stamp
+
+  def GenerateDescription(self, verb, message, fallback):
+    """Generate and return a description of a build step.
+
+    |verb| is the short summary, e.g. ACTION or RULE.
+    |message| is a hand-written description, or None if not available.
+    |fallback| is the gyp-level name of the step, usable as a fallback.
+    """
+    if self.toolset != 'target':
+      verb += '(%s)' % self.toolset
+    if message:
+      return '%s %s' % (verb, self.ExpandSpecial(message))
+    else:
+      return '%s %s: %s' % (verb, self.name, fallback)
+
+  def WriteActions(self, actions, extra_sources, prebuild,
+                   extra_mac_bundle_resources):
+    # Actions cd into the base directory.
+    env = self.GetSortedXcodeEnv()
+    if self.flavor == 'win':
+      env = self.msvs_settings.GetVSMacroEnv(
+          '$!PRODUCT_DIR', config=self.config_name)
+    all_outputs = []
+    for action in actions:
+      # First write out a rule for the action.
+      name = '%s_%s' % (action['action_name'],
+                        hashlib.md5(self.qualified_target).hexdigest())
+      description = self.GenerateDescription('ACTION',
+                                             action.get('message', None),
+                                             name)
+      is_cygwin = (self.msvs_settings.IsRuleRunUnderCygwin(action)
+                   if self.flavor == 'win' else False)
+      args = action['action']
+      rule_name, _ = self.WriteNewNinjaRule(name, args, description,
+                                            is_cygwin, env=env)
+
+      inputs = [self.GypPathToNinja(i, env) for i in action['inputs']]
+      if int(action.get('process_outputs_as_sources', False)):
+        extra_sources += action['outputs']
+      if int(action.get('process_outputs_as_mac_bundle_resources', False)):
+        extra_mac_bundle_resources += action['outputs']
+      outputs = [self.GypPathToNinja(o, env) for o in action['outputs']]
+
+      # Then write out an edge using the rule.
+      self.ninja.build(outputs, rule_name, inputs,
+                       order_only=prebuild)
+      all_outputs += outputs
+
+      self.ninja.newline()
+
+    return all_outputs
+
+  def WriteRules(self, rules, extra_sources, prebuild,
+                 extra_mac_bundle_resources):
+    env = self.GetSortedXcodeEnv()
+    all_outputs = []
+    for rule in rules:
+      # First write out a rule for the rule action.
+      name = '%s_%s' % (rule['rule_name'],
+                        hashlib.md5(self.qualified_target).hexdigest())
+      # Skip a rule with no action and no inputs.
+      if 'action' not in rule and not rule.get('rule_sources', []):
+        continue
+      args = rule['action']
+      description = self.GenerateDescription(
+          'RULE',
+          rule.get('message', None),
+          ('%s ' + generator_default_variables['RULE_INPUT_PATH']) % name)
+      is_cygwin = (self.msvs_settings.IsRuleRunUnderCygwin(rule)
+                   if self.flavor == 'win' else False)
+      rule_name, args = self.WriteNewNinjaRule(
+          name, args, description, is_cygwin, env=env)
+
+      # TODO: if the command references the outputs directly, we should
+      # simplify it to just use $out.
+
+      # Rules can potentially make use of some special variables which
+      # must vary per source file.
+      # Compute the list of variables we'll need to provide.
+      special_locals = ('source', 'root', 'dirname', 'ext', 'name')
+      needed_variables = set(['source'])
+      for argument in args:
+        for var in special_locals:
+          if ('${%s}' % var) in argument:
+            needed_variables.add(var)
+
+      def cygwin_munge(path):
+        if is_cygwin:
+          return path.replace('\\', '/')
+        return path
+
+      # For each source file, write an edge that generates all the outputs.
+      for source in rule.get('rule_sources', []):
+        dirname, basename = os.path.split(source)
+        root, ext = os.path.splitext(basename)
+
+        # Gather the list of inputs and outputs, expanding $vars if possible.
+        outputs = [self.ExpandRuleVariables(o, root, dirname,
+                                            source, ext, basename)
+                   for o in rule['outputs']]
+        inputs = [self.ExpandRuleVariables(i, root, dirname,
+                                           source, ext, basename)
+                  for i in rule.get('inputs', [])]
+
+        if int(rule.get('process_outputs_as_sources', False)):
+          extra_sources += outputs
+        if int(rule.get('process_outputs_as_mac_bundle_resources', False)):
+          extra_mac_bundle_resources += outputs
+
+        extra_bindings = []
+        for var in needed_variables:
+          if var == 'root':
+            extra_bindings.append(('root', cygwin_munge(root)))
+          elif var == 'dirname':
+            extra_bindings.append(('dirname', cygwin_munge(dirname)))
+          elif var == 'source':
+            # '$source' is a parameter to the rule action, which means
+            # it shouldn't be converted to a Ninja path.  But we don't
+            # want $!PRODUCT_DIR in there either.
+            source_expanded = self.ExpandSpecial(source, self.base_to_build)
+            extra_bindings.append(('source', cygwin_munge(source_expanded)))
+          elif var == 'ext':
+            extra_bindings.append(('ext', ext))
+          elif var == 'name':
+            extra_bindings.append(('name', cygwin_munge(basename)))
+          else:
+            assert var == None, repr(var)
+
+        inputs = [self.GypPathToNinja(i, env) for i in inputs]
+        outputs = [self.GypPathToNinja(o, env) for o in outputs]
+        extra_bindings.append(('unique_name',
+            hashlib.md5(outputs[0]).hexdigest()))
+        self.ninja.build(outputs, rule_name, self.GypPathToNinja(source),
+                         implicit=inputs,
+                         order_only=prebuild,
+                         variables=extra_bindings)
+
+        all_outputs.extend(outputs)
+
+    return all_outputs
+
+  def WriteCopies(self, copies, prebuild, mac_bundle_depends):
+    outputs = []
+    env = self.GetSortedXcodeEnv()
+    for copy in copies:
+      for path in copy['files']:
+        # Normalize the path so trailing slashes don't confuse us.
+        path = os.path.normpath(path)
+        basename = os.path.split(path)[1]
+        src = self.GypPathToNinja(path, env)
+        dst = self.GypPathToNinja(os.path.join(copy['destination'], basename),
+                                  env)
+        outputs += self.ninja.build(dst, 'copy', src, order_only=prebuild)
+        if self.is_mac_bundle:
+          # gyp has mac_bundle_resources to copy things into a bundle's
+          # Resources folder, but there's no built-in way to copy files to other
+          # places in the bundle. Hence, some targets use copies for this. Check
+          # if this file is copied into the current bundle, and if so add it to
+          # the bundle depends so that dependent targets get rebuilt if the copy
+          # input changes.
+          if dst.startswith(self.xcode_settings.GetBundleContentsFolderPath()):
+            mac_bundle_depends.append(dst)
+
+    return outputs
+
+  def WriteMacBundleResources(self, resources, bundle_depends):
+    """Writes ninja edges for 'mac_bundle_resources'."""
+    for output, res in gyp.xcode_emulation.GetMacBundleResources(
+        self.ExpandSpecial(generator_default_variables['PRODUCT_DIR']),
+        self.xcode_settings, map(self.GypPathToNinja, resources)):
+      self.ninja.build(output, 'mac_tool', res,
+                       variables=[('mactool_cmd', 'copy-bundle-resource')])
+      bundle_depends.append(output)
+
+  def WriteMacInfoPlist(self, bundle_depends):
+    """Write build rules for bundle Info.plist files."""
+    info_plist, out, defines, extra_env = gyp.xcode_emulation.GetMacInfoPlist(
+        self.ExpandSpecial(generator_default_variables['PRODUCT_DIR']),
+        self.xcode_settings, self.GypPathToNinja)
+    if not info_plist:
+      return
+    if defines:
+      # Create an intermediate file to store preprocessed results.
+      intermediate_plist = self.GypPathToUniqueOutput(
+          os.path.basename(info_plist))
+      defines = ' '.join([Define(d, self.flavor) for d in defines])
+      info_plist = self.ninja.build(intermediate_plist, 'infoplist', info_plist,
+                                    variables=[('defines',defines)])
+
+    env = self.GetSortedXcodeEnv(additional_settings=extra_env)
+    env = self.ComputeExportEnvString(env)
+
+    self.ninja.build(out, 'mac_tool', info_plist,
+                     variables=[('mactool_cmd', 'copy-info-plist'),
+                                ('env', env)])
+    bundle_depends.append(out)
+
+  def WriteSources(self, config_name, config, sources, predepends,
+                   precompiled_header, case_sensitive_filesystem, spec):
+    """Write build rules to compile all of |sources|."""
+    if self.toolset == 'host':
+      self.ninja.variable('ar', '$ar_host')
+      self.ninja.variable('cc', '$cc_host')
+      self.ninja.variable('cxx', '$cxx_host')
+      self.ninja.variable('ld', '$ld_host')
+
+    extra_defines = []
+    if self.flavor == 'mac':
+      cflags = self.xcode_settings.GetCflags(config_name)
+      cflags_c = self.xcode_settings.GetCflagsC(config_name)
+      cflags_cc = self.xcode_settings.GetCflagsCC(config_name)
+      cflags_objc = ['$cflags_c'] + \
+                    self.xcode_settings.GetCflagsObjC(config_name)
+      cflags_objcc = ['$cflags_cc'] + \
+                     self.xcode_settings.GetCflagsObjCC(config_name)
+    elif self.flavor == 'win':
+      cflags = self.msvs_settings.GetCflags(config_name)
+      cflags_c = self.msvs_settings.GetCflagsC(config_name)
+      cflags_cc = self.msvs_settings.GetCflagsCC(config_name)
+      extra_defines = self.msvs_settings.GetComputedDefines(config_name)
+      pdbpath = self.msvs_settings.GetCompilerPdbName(
+          config_name, self.ExpandSpecial)
+      if not pdbpath:
+        obj = 'obj'
+        if self.toolset != 'target':
+          obj += '.' + self.toolset
+        pdbpath = os.path.normpath(os.path.join(obj, self.base_dir,
+                                                self.name + '.pdb'))
+      self.WriteVariableList('pdbname', [pdbpath])
+      self.WriteVariableList('pchprefix', [self.name])
+    else:
+      cflags = config.get('cflags', [])
+      cflags_c = config.get('cflags_c', [])
+      cflags_cc = config.get('cflags_cc', [])
+
+    defines = config.get('defines', []) + extra_defines
+    self.WriteVariableList('defines', [Define(d, self.flavor) for d in defines])
+    if self.flavor == 'win':
+      self.WriteVariableList('rcflags',
+          [QuoteShellArgument(self.ExpandSpecial(f), self.flavor)
+           for f in self.msvs_settings.GetRcflags(config_name,
+                                                  self.GypPathToNinja)])
+
+    include_dirs = config.get('include_dirs', [])
+    if self.flavor == 'win':
+      include_dirs = self.msvs_settings.AdjustIncludeDirs(include_dirs,
+                                                          config_name)
+    self.WriteVariableList('includes',
+        [QuoteShellArgument('-I' + self.GypPathToNinja(i), self.flavor)
+         for i in include_dirs])
+
+    pch_commands = precompiled_header.GetPchBuildCommands()
+    if self.flavor == 'mac':
+      self.WriteVariableList('cflags_pch_c',
+                             [precompiled_header.GetInclude('c')])
+      self.WriteVariableList('cflags_pch_cc',
+                             [precompiled_header.GetInclude('cc')])
+      self.WriteVariableList('cflags_pch_objc',
+                             [precompiled_header.GetInclude('m')])
+      self.WriteVariableList('cflags_pch_objcc',
+                             [precompiled_header.GetInclude('mm')])
+
+    self.WriteVariableList('cflags', map(self.ExpandSpecial, cflags))
+    self.WriteVariableList('cflags_c', map(self.ExpandSpecial, cflags_c))
+    self.WriteVariableList('cflags_cc', map(self.ExpandSpecial, cflags_cc))
+    if self.flavor == 'mac':
+      self.WriteVariableList('cflags_objc', map(self.ExpandSpecial,
+                                                cflags_objc))
+      self.WriteVariableList('cflags_objcc', map(self.ExpandSpecial,
+                                                 cflags_objcc))
+    self.ninja.newline()
+    outputs = []
+    for source in sources:
+      filename, ext = os.path.splitext(source)
+      ext = ext[1:]
+      obj_ext = self.obj_ext
+      if ext in ('cc', 'cpp', 'cxx'):
+        command = 'cxx'
+      elif ext == 'c' or (ext == 'S' and self.flavor != 'win'):
+        command = 'cc'
+      elif ext == 's' and self.flavor != 'win':  # Doesn't generate .o.d files.
+        command = 'cc_s'
+      elif (self.flavor == 'win' and ext == 'asm' and
+            self.msvs_settings.GetArch(config_name) == 'x86' and
+            not self.msvs_settings.HasExplicitAsmRules(spec)):
+        # Asm files only get auto assembled for x86 (not x64).
+        command = 'asm'
+        # Add the _asm suffix as msvs is capable of handling .cc and
+        # .asm files of the same name without collision.
+        obj_ext = '_asm.obj'
+      elif self.flavor == 'mac' and ext == 'm':
+        command = 'objc'
+      elif self.flavor == 'mac' and ext == 'mm':
+        command = 'objcxx'
+      elif self.flavor == 'win' and ext == 'rc':
+        command = 'rc'
+        obj_ext = '.res'
+      else:
+        # Ignore unhandled extensions.
+        continue
+      input = self.GypPathToNinja(source)
+      output = self.GypPathToUniqueOutput(filename + obj_ext)
+      # Ninja's depfile handling gets confused when the case of a filename
+      # changes on a case-insensitive file system. To work around that, always
+      # convert .o filenames to lowercase on such file systems. See
+      # https://github.com/martine/ninja/issues/402 for details.
+      if not case_sensitive_filesystem:
+        output = output.lower()
+      implicit = precompiled_header.GetObjDependencies([input], [output])
+      variables = []
+      if self.flavor == 'win':
+        variables, output, implicit = precompiled_header.GetFlagsModifications(
+            input, output, implicit, command, cflags_c, cflags_cc,
+            self.ExpandSpecial)
+      self.ninja.build(output, command, input,
+                       implicit=[gch for _, _, gch in implicit],
+                       order_only=predepends, variables=variables)
+      outputs.append(output)
+
+    self.WritePchTargets(pch_commands)
+
+    self.ninja.newline()
+    return outputs
+
+  def WritePchTargets(self, pch_commands):
+    """Writes ninja rules to compile prefix headers."""
+    if not pch_commands:
+      return
+
+    for gch, lang_flag, lang, input in pch_commands:
+      var_name = {
+        'c': 'cflags_pch_c',
+        'cc': 'cflags_pch_cc',
+        'm': 'cflags_pch_objc',
+        'mm': 'cflags_pch_objcc',
+      }[lang]
+
+      map = { 'c': 'cc', 'cc': 'cxx', 'm': 'objc', 'mm': 'objcxx', }
+      cmd = map.get(lang)
+      self.ninja.build(gch, cmd, input, variables=[(var_name, lang_flag)])
+
+  def WriteLink(self, spec, config_name, config, link_deps):
+    """Write out a link step. Fills out target.binary. """
+
+    command = {
+      'executable':      'link',
+      'loadable_module': 'solink_module',
+      'shared_library':  'solink',
+    }[spec['type']]
+
+    implicit_deps = set()
+    solibs = set()
+
+    if 'dependencies' in spec:
+      # Two kinds of dependencies:
+      # - Linkable dependencies (like a .a or a .so): add them to the link line.
+      # - Non-linkable dependencies (like a rule that generates a file
+      #   and writes a stamp file): add them to implicit_deps
+      extra_link_deps = set()
+      for dep in spec['dependencies']:
+        target = self.target_outputs.get(dep)
+        if not target:
+          continue
+        linkable = target.Linkable()
+        if linkable:
+          if (self.flavor == 'win' and
+              target.component_objs and
+              self.msvs_settings.IsUseLibraryDependencyInputs(config_name)):
+            extra_link_deps |= set(target.component_objs)
+          elif self.flavor == 'win' and target.import_lib:
+            extra_link_deps.add(target.import_lib)
+          elif target.UsesToc(self.flavor):
+            solibs.add(target.binary)
+            implicit_deps.add(target.binary + '.TOC')
+          else:
+            extra_link_deps.add(target.binary)
+
+        final_output = target.FinalOutput()
+        if not linkable or final_output != target.binary:
+          implicit_deps.add(final_output)
+
+      link_deps.extend(list(extra_link_deps))
+
+    extra_bindings = []
+    if self.is_mac_bundle:
+      output = self.ComputeMacBundleBinaryOutput()
+    else:
+      output = self.ComputeOutput(spec)
+      extra_bindings.append(('postbuilds',
+                             self.GetPostbuildCommand(spec, output, output)))
+
+    is_executable = spec['type'] == 'executable'
+    if self.flavor == 'mac':
+      ldflags = self.xcode_settings.GetLdflags(config_name,
+          self.ExpandSpecial(generator_default_variables['PRODUCT_DIR']),
+          self.GypPathToNinja)
+    elif self.flavor == 'win':
+      manifest_name = self.GypPathToUniqueOutput(
+          self.ComputeOutputFileName(spec))
+      ldflags, manifest_files = self.msvs_settings.GetLdflags(config_name,
+          self.GypPathToNinja, self.ExpandSpecial, manifest_name, is_executable)
+      self.WriteVariableList('manifests', manifest_files)
+    else:
+      ldflags = config.get('ldflags', [])
+      if is_executable and len(solibs):
+        rpath = 'lib/'
+        if self.toolset != 'target':
+          rpath += self.toolset
+        ldflags.append('-Wl,-rpath=\$$ORIGIN/%s' % rpath)
+        ldflags.append('-Wl,-rpath-link=%s' % rpath)
+    self.WriteVariableList('ldflags',
+                           gyp.common.uniquer(map(self.ExpandSpecial,
+                                                  ldflags)))
+
+    libraries = gyp.common.uniquer(map(self.ExpandSpecial,
+                                       spec.get('libraries', [])))
+    if self.flavor == 'mac':
+      libraries = self.xcode_settings.AdjustLibraries(libraries)
+    elif self.flavor == 'win':
+      libraries = self.msvs_settings.AdjustLibraries(libraries)
+    self.WriteVariableList('libs', libraries)
+
+    self.target.binary = output
+
+    if command in ('solink', 'solink_module'):
+      extra_bindings.append(('soname', os.path.split(output)[1]))
+      extra_bindings.append(('lib',
+                            gyp.common.EncodePOSIXShellArgument(output)))
+      if self.flavor == 'win':
+        extra_bindings.append(('dll', output))
+        if '/NOENTRY' not in ldflags:
+          self.target.import_lib = output + '.lib'
+          extra_bindings.append(('implibflag',
+                                 '/IMPLIB:%s' % self.target.import_lib))
+          output = [output, self.target.import_lib]
+      else:
+        output = [output, output + '.TOC']
+
+    if len(solibs):
+      extra_bindings.append(('solibs', gyp.common.EncodePOSIXShellList(solibs)))
+
+    self.ninja.build(output, command, link_deps,
+                     implicit=list(implicit_deps),
+                     variables=extra_bindings)
+
+  def WriteTarget(self, spec, config_name, config, link_deps, compile_deps):
+    if spec['type'] == 'none':
+      # TODO(evan): don't call this function for 'none' target types, as
+      # it doesn't do anything, and we fake out a 'binary' with a stamp file.
+      self.target.binary = compile_deps
+    elif spec['type'] == 'static_library':
+      self.target.binary = self.ComputeOutput(spec)
+      variables = []
+      postbuild = self.GetPostbuildCommand(
+          spec, self.target.binary, self.target.binary)
+      if postbuild:
+        variables.append(('postbuilds', postbuild))
+      if self.xcode_settings:
+        variables.append(('libtool_flags',
+                          self.xcode_settings.GetLibtoolflags(config_name)))
+      if (self.flavor not in ('mac', 'win') and not
+          self.is_standalone_static_library):
+        self.ninja.build(self.target.binary, 'alink_thin', link_deps,
+                         order_only=compile_deps, variables=variables)
+      else:
+        if self.msvs_settings:
+          libflags = self.msvs_settings.GetLibFlags(config_name,
+                                                    self.GypPathToNinja)
+          variables.append(('libflags', libflags))
+        self.ninja.build(self.target.binary, 'alink', link_deps,
+                         order_only=compile_deps, variables=variables)
+    else:
+      self.WriteLink(spec, config_name, config, link_deps)
+    return self.target.binary
+
+  def WriteMacBundle(self, spec, mac_bundle_depends):
+    assert self.is_mac_bundle
+    package_framework = spec['type'] in ('shared_library', 'loadable_module')
+    output = self.ComputeMacBundleOutput()
+    postbuild = self.GetPostbuildCommand(spec, output, self.target.binary,
+                                         is_command_start=not package_framework)
+    variables = []
+    if postbuild:
+      variables.append(('postbuilds', postbuild))
+    if package_framework:
+      variables.append(('version', self.xcode_settings.GetFrameworkVersion()))
+      self.ninja.build(output, 'package_framework', mac_bundle_depends,
+                       variables=variables)
+    else:
+      self.ninja.build(output, 'stamp', mac_bundle_depends,
+                       variables=variables)
+    self.target.bundle = output
+    return output
+
+  def GetSortedXcodeEnv(self, additional_settings=None):
+    """Returns the variables Xcode would set for build steps."""
+    assert self.abs_build_dir
+    abs_build_dir = self.abs_build_dir
+    return gyp.xcode_emulation.GetSortedXcodeEnv(
+        self.xcode_settings, abs_build_dir,
+        os.path.join(abs_build_dir, self.build_to_base), self.config_name,
+        additional_settings)
+
+  def GetSortedXcodePostbuildEnv(self):
+    """Returns the variables Xcode would set for postbuild steps."""
+    postbuild_settings = {}
+    # CHROMIUM_STRIP_SAVE_FILE is a chromium-specific hack.
+    # TODO(thakis): It would be nice to have some general mechanism instead.
+    strip_save_file = self.xcode_settings.GetPerTargetSetting(
+        'CHROMIUM_STRIP_SAVE_FILE')
+    if strip_save_file:
+      postbuild_settings['CHROMIUM_STRIP_SAVE_FILE'] = strip_save_file
+    return self.GetSortedXcodeEnv(additional_settings=postbuild_settings)
+
+  def GetPostbuildCommand(self, spec, output, output_binary,
+                          is_command_start=False):
+    """Returns a shell command that runs all the postbuilds, and removes
+    |output| if any of them fails. If |is_command_start| is False, then the
+    returned string will start with ' && '."""
+    if not self.xcode_settings or spec['type'] == 'none' or not output:
+      return ''
+    output = QuoteShellArgument(output, self.flavor)
+    target_postbuilds = self.xcode_settings.GetTargetPostbuilds(
+        self.config_name,
+        os.path.normpath(os.path.join(self.base_to_build, output)),
+        QuoteShellArgument(
+            os.path.normpath(os.path.join(self.base_to_build, output_binary)),
+            self.flavor),
+        quiet=True)
+    postbuilds = gyp.xcode_emulation.GetSpecPostbuildCommands(spec, quiet=True)
+    postbuilds = target_postbuilds + postbuilds
+    if not postbuilds:
+      return ''
+    # Postbuilds expect to be run in the gyp file's directory, so insert an
+    # implicit postbuild to cd to there.
+    postbuilds.insert(0, gyp.common.EncodePOSIXShellList(
+        ['cd', self.build_to_base]))
+    env = self.ComputeExportEnvString(self.GetSortedXcodePostbuildEnv())
+    # G will be non-null if any postbuild fails. Run all postbuilds in a
+    # subshell.
+    commands = env + ' (' + \
+        ' && '.join([ninja_syntax.escape(command) for command in postbuilds])
+    command_string = (commands + '); G=$$?; '
+                      # Remove the final output if any postbuild failed.
+                      '((exit $$G) || rm -rf %s) ' % output + '&& exit $$G)')
+    if is_command_start:
+      return '(' + command_string + ' && '
+    else:
+      return '$ && (' + command_string
+
+  def ComputeExportEnvString(self, env):
+    """Given an environment, returns a string looking like
+        'export FOO=foo; export BAR="${FOO} bar;'
+    that exports |env| to the shell."""
+    export_str = []
+    for k, v in env:
+      export_str.append('export %s=%s;' %
+          (k, ninja_syntax.escape(gyp.common.EncodePOSIXShellArgument(v))))
+    return ' '.join(export_str)
+
+  def ComputeMacBundleOutput(self):
+    """Return the 'output' (full output path) to a bundle output directory."""
+    assert self.is_mac_bundle
+    path = self.ExpandSpecial(generator_default_variables['PRODUCT_DIR'])
+    return os.path.join(path, self.xcode_settings.GetWrapperName())
+
+  def ComputeMacBundleBinaryOutput(self):
+    """Return the 'output' (full output path) to the binary in a bundle."""
+    assert self.is_mac_bundle
+    path = self.ExpandSpecial(generator_default_variables['PRODUCT_DIR'])
+    return os.path.join(path, self.xcode_settings.GetExecutablePath())
+
+  def ComputeOutputFileName(self, spec, type=None):
+    """Compute the filename of the final output for the current target."""
+    if not type:
+      type = spec['type']
+
+    default_variables = copy.copy(generator_default_variables)
+    CalculateVariables(default_variables, {'flavor': self.flavor})
+
+    # Compute filename prefix: the product prefix, or a default for
+    # the product type.
+    DEFAULT_PREFIX = {
+      'loadable_module': default_variables['SHARED_LIB_PREFIX'],
+      'shared_library': default_variables['SHARED_LIB_PREFIX'],
+      'static_library': default_variables['STATIC_LIB_PREFIX'],
+      'executable': default_variables['EXECUTABLE_PREFIX'],
+      }
+    prefix = spec.get('product_prefix', DEFAULT_PREFIX.get(type, ''))
+
+    # Compute filename extension: the product extension, or a default
+    # for the product type.
+    DEFAULT_EXTENSION = {
+        'loadable_module': default_variables['SHARED_LIB_SUFFIX'],
+        'shared_library': default_variables['SHARED_LIB_SUFFIX'],
+        'static_library': default_variables['STATIC_LIB_SUFFIX'],
+        'executable': default_variables['EXECUTABLE_SUFFIX'],
+      }
+    extension = spec.get('product_extension')
+    if extension:
+      extension = '.' + extension
+    else:
+      extension = DEFAULT_EXTENSION.get(type, '')
+
+    if 'product_name' in spec:
+      # If we were given an explicit name, use that.
+      target = spec['product_name']
+    else:
+      # Otherwise, derive a name from the target name.
+      target = spec['target_name']
+      if prefix == 'lib':
+        # Snip out an extra 'lib' from libs if appropriate.
+        target = StripPrefix(target, 'lib')
+
+    if type in ('static_library', 'loadable_module', 'shared_library',
+                        'executable'):
+      return '%s%s%s' % (prefix, target, extension)
+    elif type == 'none':
+      return '%s.stamp' % target
+    else:
+      raise Exception('Unhandled output type %s' % type)
+
+  def ComputeOutput(self, spec, type=None):
+    """Compute the path for the final output of the spec."""
+    assert not self.is_mac_bundle or type
+
+    if not type:
+      type = spec['type']
+
+    if self.flavor == 'win':
+      override = self.msvs_settings.GetOutputName(self.config_name,
+                                                  self.ExpandSpecial)
+      if override:
+        return override
+
+    if self.flavor == 'mac' and type in (
+        'static_library', 'executable', 'shared_library', 'loadable_module'):
+      filename = self.xcode_settings.GetExecutablePath()
+    else:
+      filename = self.ComputeOutputFileName(spec, type)
+
+    if 'product_dir' in spec:
+      path = os.path.join(spec['product_dir'], filename)
+      return self.ExpandSpecial(path)
+
+    # Some products go into the output root, libraries go into shared library
+    # dir, and everything else goes into the normal place.
+    type_in_output_root = ['executable', 'loadable_module']
+    if self.flavor == 'mac' and self.toolset == 'target':
+      type_in_output_root += ['shared_library', 'static_library']
+    elif self.flavor == 'win' and self.toolset == 'target':
+      type_in_output_root += ['shared_library']
+
+    if type in type_in_output_root or self.is_standalone_static_library:
+      return filename
+    elif type == 'shared_library':
+      libdir = 'lib'
+      if self.toolset != 'target':
+        libdir = os.path.join('lib', '%s' % self.toolset)
+      return os.path.join(libdir, filename)
+    else:
+      return self.GypPathToUniqueOutput(filename, qualified=False)
+
+  def WriteVariableList(self, var, values):
+    assert not isinstance(values, str)
+    if values is None:
+      values = []
+    self.ninja.variable(var, ' '.join(values))
+
+  def WriteNewNinjaRule(self, name, args, description, is_cygwin, env):
+    """Write out a new ninja "rule" statement for a given command.
+
+    Returns the name of the new rule, and a copy of |args| with variables
+    expanded."""
+
+    if self.flavor == 'win':
+      args = [self.msvs_settings.ConvertVSMacros(
+                  arg, self.base_to_build, config=self.config_name)
+              for arg in args]
+      description = self.msvs_settings.ConvertVSMacros(
+          description, config=self.config_name)
+    elif self.flavor == 'mac':
+      # |env| is an empty list on non-mac.
+      args = [gyp.xcode_emulation.ExpandEnvVars(arg, env) for arg in args]
+      description = gyp.xcode_emulation.ExpandEnvVars(description, env)
+
+    # TODO: we shouldn't need to qualify names; we do it because
+    # currently the ninja rule namespace is global, but it really
+    # should be scoped to the subninja.
+    rule_name = self.name
+    if self.toolset == 'target':
+      rule_name += '.' + self.toolset
+    rule_name += '.' + name
+    rule_name = re.sub('[^a-zA-Z0-9_]', '_', rule_name)
+
+    # Remove variable references, but not if they refer to the magic rule
+    # variables.  This is not quite right, as it also protects these for
+    # actions, not just for rules where they are valid. Good enough.
+    protect = [ '${root}', '${dirname}', '${source}', '${ext}', '${name}' ]
+    protect = '(?!' + '|'.join(map(re.escape, protect)) + ')'
+    description = re.sub(protect + r'\$', '_', description)
+
+    # gyp dictates that commands are run from the base directory.
+    # cd into the directory before running, and adjust paths in
+    # the arguments to point to the proper locations.
+    rspfile = None
+    rspfile_content = None
+    args = [self.ExpandSpecial(arg, self.base_to_build) for arg in args]
+    if self.flavor == 'win':
+      rspfile = rule_name + '.$unique_name.rsp'
+      # The cygwin case handles this inside the bash sub-shell.
+      run_in = '' if is_cygwin else ' ' + self.build_to_base
+      if is_cygwin:
+        rspfile_content = self.msvs_settings.BuildCygwinBashCommandLine(
+            args, self.build_to_base)
+      else:
+        rspfile_content = gyp.msvs_emulation.EncodeRspFileList(args)
+      command = ('%s gyp-win-tool action-wrapper $arch ' % sys.executable +
+                 rspfile + run_in)
+    else:
+      env = self.ComputeExportEnvString(env)
+      command = gyp.common.EncodePOSIXShellList(args)
+      command = 'cd %s; ' % self.build_to_base + env + command
+
+    # GYP rules/actions express being no-ops by not touching their outputs.
+    # Avoid executing downstream dependencies in this case by specifying
+    # restat=1 to ninja.
+    self.ninja.rule(rule_name, command, description, restat=True,
+                    rspfile=rspfile, rspfile_content=rspfile_content)
+    self.ninja.newline()
+
+    return rule_name, args
+
+
+def CalculateVariables(default_variables, params):
+  """Calculate additional variables for use in the build (called by gyp)."""
+  global generator_additional_non_configuration_keys
+  global generator_additional_path_sections
+  flavor = gyp.common.GetFlavor(params)
+  if flavor == 'mac':
+    default_variables.setdefault('OS', 'mac')
+    default_variables.setdefault('SHARED_LIB_SUFFIX', '.dylib')
+    default_variables.setdefault('SHARED_LIB_DIR',
+                                 generator_default_variables['PRODUCT_DIR'])
+    default_variables.setdefault('LIB_DIR',
+                                 generator_default_variables['PRODUCT_DIR'])
+
+    # Copy additional generator configuration data from Xcode, which is shared
+    # by the Mac Ninja generator.
+    import gyp.generator.xcode as xcode_generator
+    generator_additional_non_configuration_keys = getattr(xcode_generator,
+        'generator_additional_non_configuration_keys', [])
+    generator_additional_path_sections = getattr(xcode_generator,
+        'generator_additional_path_sections', [])
+    global generator_extra_sources_for_rules
+    generator_extra_sources_for_rules = getattr(xcode_generator,
+        'generator_extra_sources_for_rules', [])
+  elif flavor == 'win':
+    default_variables.setdefault('OS', 'win')
+    default_variables['EXECUTABLE_SUFFIX'] = '.exe'
+    default_variables['STATIC_LIB_PREFIX'] = ''
+    default_variables['STATIC_LIB_SUFFIX'] = '.lib'
+    default_variables['SHARED_LIB_PREFIX'] = ''
+    default_variables['SHARED_LIB_SUFFIX'] = '.dll'
+    generator_flags = params.get('generator_flags', {})
+
+    # Copy additional generator configuration data from VS, which is shared
+    # by the Windows Ninja generator.
+    import gyp.generator.msvs as msvs_generator
+    generator_additional_non_configuration_keys = getattr(msvs_generator,
+        'generator_additional_non_configuration_keys', [])
+    generator_additional_path_sections = getattr(msvs_generator,
+        'generator_additional_path_sections', [])
+
+    # Set a variable so conditions can be based on msvs_version.
+    msvs_version = gyp.msvs_emulation.GetVSVersion(generator_flags)
+    default_variables['MSVS_VERSION'] = msvs_version.ShortName()
+
+    # To determine processor word size on Windows, in addition to checking
+    # PROCESSOR_ARCHITECTURE (which reflects the word size of the current
+    # process), it is also necessary to check PROCESSOR_ARCHITEW6432 (which
+    # contains the actual word size of the system when running thru WOW64).
+    if ('64' in os.environ.get('PROCESSOR_ARCHITECTURE', '') or
+        '64' in os.environ.get('PROCESSOR_ARCHITEW6432', '')):
+      default_variables['MSVS_OS_BITS'] = 64
+    else:
+      default_variables['MSVS_OS_BITS'] = 32
+  else:
+    operating_system = flavor
+    if flavor == 'android':
+      operating_system = 'linux'  # Keep this legacy behavior for now.
+    default_variables.setdefault('OS', operating_system)
+    default_variables.setdefault('SHARED_LIB_SUFFIX', '.so')
+    default_variables.setdefault('SHARED_LIB_DIR',
+                                 os.path.join('$!PRODUCT_DIR', 'lib'))
+    default_variables.setdefault('LIB_DIR',
+                                 os.path.join('$!PRODUCT_DIR', 'obj'))
+
+
+def OpenOutput(path, mode='w'):
+  """Open |path| for writing, creating directories if necessary."""
+  try:
+    os.makedirs(os.path.dirname(path))
+  except OSError:
+    pass
+  return open(path, mode)
+
+
+def CommandWithWrapper(cmd, wrappers, prog):
+  wrapper = wrappers.get(cmd, '')
+  if wrapper:
+    return wrapper + ' ' + prog
+  return prog
+
+
+def GenerateOutputForConfig(target_list, target_dicts, data, params,
+                            config_name):
+  options = params['options']
+  flavor = gyp.common.GetFlavor(params)
+  generator_flags = params.get('generator_flags', {})
+
+  # generator_dir: relative path from pwd to where make puts build files.
+  # Makes migrating from make to ninja easier, ninja doesn't put anything here.
+  generator_dir = os.path.relpath(params['options'].generator_output or '.')
+
+  # output_dir: relative path from generator_dir to the build directory.
+  output_dir = generator_flags.get('output_dir', 'out')
+
+  # build_dir: relative path from source root to our output files.
+  # e.g. "out/Debug"
+  build_dir = os.path.normpath(os.path.join(generator_dir,
+                                            output_dir,
+                                            config_name))
+
+  toplevel_build = os.path.join(options.toplevel_dir, build_dir)
+
+  master_ninja = ninja_syntax.Writer(
+      OpenOutput(os.path.join(toplevel_build, 'build.ninja')),
+      width=120)
+  case_sensitive_filesystem = not os.path.exists(
+      os.path.join(toplevel_build, 'BUILD.NINJA'))
+
+  # Put build-time support tools in out/{config_name}.
+  gyp.common.CopyTool(flavor, toplevel_build)
+
+  # Grab make settings for CC/CXX.
+  # The rules are
+  # - The priority from low to high is gcc/g++, the 'make_global_settings' in
+  #   gyp, the environment variable.
+  # - If there is no 'make_global_settings' for CC.host/CXX.host or
+  #   'CC_host'/'CXX_host' enviroment variable, cc_host/cxx_host should be set
+  #   to cc/cxx.
+  if flavor == 'win':
+    cc = 'cl.exe'
+    cxx = 'cl.exe'
+    ld = 'link.exe'
+    gyp.msvs_emulation.GenerateEnvironmentFiles(
+        toplevel_build, generator_flags, OpenOutput)
+    ld_host = '$ld'
+  else:
+    cc = 'gcc'
+    cxx = 'g++'
+    ld = '$cxx'
+    ld_host = '$cxx_host'
+
+  cc_host = None
+  cxx_host = None
+  cc_host_global_setting = None
+  cxx_host_global_setting = None
+
+  build_file, _, _ = gyp.common.ParseQualifiedTarget(target_list[0])
+  make_global_settings = data[build_file].get('make_global_settings', [])
+  build_to_root = gyp.common.InvertRelativePath(build_dir,
+                                                options.toplevel_dir)
+  flock = 'flock'
+  if flavor == 'mac':
+    flock = './gyp-mac-tool flock'
+  wrappers = {}
+  if flavor != 'win':
+    wrappers['LINK'] = flock + ' linker.lock'
+  for key, value in make_global_settings:
+    if key == 'CC':
+      cc = os.path.join(build_to_root, value)
+    if key == 'CXX':
+      cxx = os.path.join(build_to_root, value)
+    if key == 'LD':
+      ld = os.path.join(build_to_root, value)
+    if key == 'CC.host':
+      cc_host = os.path.join(build_to_root, value)
+      cc_host_global_setting = value
+    if key == 'CXX.host':
+      cxx_host = os.path.join(build_to_root, value)
+      cxx_host_global_setting = value
+    if key == 'LD.host':
+      ld_host = os.path.join(build_to_root, value)
+    if key.endswith('_wrapper'):
+      wrappers[key[:-len('_wrapper')]] = os.path.join(build_to_root, value)
+
+  cc = GetEnvironFallback(['CC_target', 'CC'], cc)
+  master_ninja.variable('cc', CommandWithWrapper('CC', wrappers, cc))
+  cxx = GetEnvironFallback(['CXX_target', 'CXX'], cxx)
+  master_ninja.variable('cxx', CommandWithWrapper('CXX', wrappers, cxx))
+  ld = GetEnvironFallback(['LD_target', 'LD'], ld)
+
+  if not cc_host:
+    cc_host = cc
+  if not cxx_host:
+    cxx_host = cxx
+
+  if flavor == 'win':
+    master_ninja.variable('ld', ld)
+    master_ninja.variable('idl', 'midl.exe')
+    master_ninja.variable('ar', 'lib.exe')
+    master_ninja.variable('rc', 'rc.exe')
+    master_ninja.variable('asm', 'ml.exe')
+    master_ninja.variable('mt', 'mt.exe')
+    master_ninja.variable('use_dep_database', '1')
+  else:
+    master_ninja.variable('ld', CommandWithWrapper('LINK', wrappers, ld))
+    master_ninja.variable('ar', GetEnvironFallback(['AR_target', 'AR'], 'ar'))
+
+  master_ninja.variable('ar_host', GetEnvironFallback(['AR_host'], 'ar'))
+  cc_host = GetEnvironFallback(['CC_host'], cc_host)
+  cxx_host = GetEnvironFallback(['CXX_host'], cxx_host)
+  ld_host = GetEnvironFallback(['LD_host'], ld_host)
+
+  # The environment variable could be used in 'make_global_settings', like
+  # ['CC.host', '$(CC)'] or ['CXX.host', '$(CXX)'], transform them here.
+  if '$(CC)' in cc_host and cc_host_global_setting:
+    cc_host = cc_host_global_setting.replace('$(CC)', cc)
+  if '$(CXX)' in cxx_host and cxx_host_global_setting:
+    cxx_host = cxx_host_global_setting.replace('$(CXX)', cxx)
+  master_ninja.variable('cc_host',
+                        CommandWithWrapper('CC.host', wrappers, cc_host))
+  master_ninja.variable('cxx_host',
+                        CommandWithWrapper('CXX.host', wrappers, cxx_host))
+  if flavor == 'win':
+    master_ninja.variable('ld_host', ld_host)
+  else:
+    master_ninja.variable('ld_host', CommandWithWrapper(
+        'LINK', wrappers, ld_host))
+
+  master_ninja.newline()
+
+  deps = None
+  if int(generator_flags.get('use_deps', '0')) and flavor != 'win':
+    deps = 'gcc'
+
+  if flavor != 'win':
+    master_ninja.rule(
+      'cc',
+      description='CC $out',
+      command=('$cc -MMD -MF $out.d $defines $includes $cflags $cflags_c '
+              '$cflags_pch_c -c $in -o $out'),
+      depfile='$out.d',
+      deps=deps)
+    master_ninja.rule(
+      'cc_s',
+      description='CC $out',
+      command=('$cc $defines $includes $cflags $cflags_c '
+              '$cflags_pch_c -c $in -o $out'))
+    master_ninja.rule(
+      'cxx',
+      description='CXX $out',
+      command=('$cxx -MMD -MF $out.d $defines $includes $cflags $cflags_cc '
+              '$cflags_pch_cc -c $in -o $out'),
+      depfile='$out.d',
+      deps=deps)
+  else:
+    cc_command = ('ninja -t msvc -o $out -e $arch '
+                  '-- '
+                  '$cc /nologo /showIncludes /FC '
+                  '@$out.rsp /c $in /Fo$out /Fd$pdbname ')
+    cxx_command = ('ninja -t msvc -o $out -e $arch '
+                   '-- '
+                   '$cxx /nologo /showIncludes /FC '
+                   '@$out.rsp /c $in /Fo$out /Fd$pdbname ')
+    master_ninja.rule(
+      'cc',
+      description='CC $out',
+      command=cc_command,
+      depfile='$out.d',
+      rspfile='$out.rsp',
+      rspfile_content='$defines $includes $cflags $cflags_c')
+    master_ninja.rule(
+      'cxx',
+      description='CXX $out',
+      command=cxx_command,
+      depfile='$out.d',
+      rspfile='$out.rsp',
+      rspfile_content='$defines $includes $cflags $cflags_cc')
+    master_ninja.rule(
+      'idl',
+      description='IDL $in',
+      command=('%s gyp-win-tool midl-wrapper $arch $outdir '
+               '$tlb $h $dlldata $iid $proxy $in '
+               '$idlflags' % sys.executable))
+    master_ninja.rule(
+      'rc',
+      description='RC $in',
+      # Note: $in must be last otherwise rc.exe complains.
+      command=('%s gyp-win-tool rc-wrapper '
+               '$arch $rc $defines $includes $rcflags /fo$out $in' %
+               sys.executable))
+    master_ninja.rule(
+      'asm',
+      description='ASM $in',
+      command=('%s gyp-win-tool asm-wrapper '
+               '$arch $asm $defines $includes /c /Fo $out $in' %
+               sys.executable))
+
+  if flavor != 'mac' and flavor != 'win':
+    master_ninja.rule(
+      'alink',
+      description='AR $out',
+      command='rm -f $out && $ar rcs $out $in')
+    master_ninja.rule(
+      'alink_thin',
+      description='AR $out',
+      command='rm -f $out && $ar rcsT $out $in')
+
+    # This allows targets that only need to depend on $lib's API to declare an
+    # order-only dependency on $lib.TOC and avoid relinking such downstream
+    # dependencies when $lib changes only in non-public ways.
+    # The resulting string leaves an uninterpolated %{suffix} which
+    # is used in the final substitution below.
+    mtime_preserving_solink_base = (
+        'if [ ! -e $lib -o ! -e ${lib}.TOC ]; then '
+        '%(solink)s && %(extract_toc)s > ${lib}.TOC; else '
+        '%(solink)s && %(extract_toc)s > ${lib}.tmp && '
+        'if ! cmp -s ${lib}.tmp ${lib}.TOC; then mv ${lib}.tmp ${lib}.TOC ; '
+        'fi; fi'
+        % { 'solink':
+              '$ld -shared $ldflags -o $lib -Wl,-soname=$soname %(suffix)s',
+            'extract_toc':
+              ('{ readelf -d ${lib} | grep SONAME ; '
+               'nm -gD -f p ${lib} | cut -f1-2 -d\' \'; }')})
+
+    master_ninja.rule(
+      'solink',
+      description='SOLINK $lib',
+      restat=True,
+      command=(mtime_preserving_solink_base % {
+          'suffix': '-Wl,--whole-archive $in $solibs -Wl,--no-whole-archive '
+          '$libs'}))
+    master_ninja.rule(
+      'solink_module',
+      description='SOLINK(module) $lib',
+      restat=True,
+      command=(mtime_preserving_solink_base % {
+          'suffix': '-Wl,--start-group $in $solibs -Wl,--end-group $libs'}))
+    master_ninja.rule(
+      'link',
+      description='LINK $out',
+      command=('$ld $ldflags -o $out '
+               '-Wl,--start-group $in $solibs -Wl,--end-group $libs'))
+  elif flavor == 'win':
+    master_ninja.rule(
+        'alink',
+        description='LIB $out',
+        command=('%s gyp-win-tool link-wrapper $arch '
+                 '$ar /nologo /ignore:4221 /OUT:$out @$out.rsp' %
+                 sys.executable),
+        rspfile='$out.rsp',
+        rspfile_content='$in_newline $libflags')
+    dlldesc = 'LINK(DLL) $dll'
+    dllcmd = ('%s gyp-win-tool link-wrapper $arch '
+              '$ld /nologo $implibflag /DLL /OUT:$dll '
+              '/PDB:$dll.pdb @$dll.rsp' % sys.executable)
+    dllcmd += (' && %s gyp-win-tool manifest-wrapper $arch '
+               'cmd /c if exist $dll.manifest del $dll.manifest' %
+               sys.executable)
+    dllcmd += (' && %s gyp-win-tool manifest-wrapper $arch '
+               '$mt -nologo -manifest $manifests -out:$dll.manifest' %
+               sys.executable)
+    master_ninja.rule('solink', description=dlldesc, command=dllcmd,
+                      rspfile='$dll.rsp',
+                      rspfile_content='$libs $in_newline $ldflags',
+                      restat=True)
+    master_ninja.rule('solink_module', description=dlldesc, command=dllcmd,
+                      rspfile='$dll.rsp',
+                      rspfile_content='$libs $in_newline $ldflags',
+                      restat=True)
+    # Note that ldflags goes at the end so that it has the option of
+    # overriding default settings earlier in the command line.
+    master_ninja.rule(
+        'link',
+        description='LINK $out',
+        command=('%s gyp-win-tool link-wrapper $arch '
+                 '$ld /nologo /OUT:$out /PDB:$out.pdb @$out.rsp && '
+                 '%s gyp-win-tool manifest-wrapper $arch '
+                 'cmd /c if exist $out.manifest del $out.manifest && '
+                 '%s gyp-win-tool manifest-wrapper $arch '
+                 '$mt -nologo -manifest $manifests -out:$out.manifest' %
+                 (sys.executable, sys.executable, sys.executable)),
+        rspfile='$out.rsp',
+        rspfile_content='$in_newline $libs $ldflags')
+  else:
+    master_ninja.rule(
+      'objc',
+      description='OBJC $out',
+      command=('$cc -MMD -MF $out.d $defines $includes $cflags $cflags_objc '
+               '$cflags_pch_objc -c $in -o $out'),
+      depfile='$out.d',
+      deps=deps)
+    master_ninja.rule(
+      'objcxx',
+      description='OBJCXX $out',
+      command=('$cxx -MMD -MF $out.d $defines $includes $cflags $cflags_objcc '
+               '$cflags_pch_objcc -c $in -o $out'),
+      depfile='$out.d',
+      deps=deps)
+    master_ninja.rule(
+      'alink',
+      description='LIBTOOL-STATIC $out, POSTBUILDS',
+      command='rm -f $out && '
+              './gyp-mac-tool filter-libtool libtool $libtool_flags '
+              '-static -o $out $in'
+              '$postbuilds')
+
+    # Record the public interface of $lib in $lib.TOC. See the corresponding
+    # comment in the posix section above for details.
+    mtime_preserving_solink_base = (
+        'if [ ! -e $lib -o ! -e ${lib}.TOC ] || '
+             # Always force dependent targets to relink if this library
+             # reexports something. Handling this correctly would require
+             # recursive TOC dumping but this is rare in practice, so punt.
+             'otool -l $lib | grep -q LC_REEXPORT_DYLIB ; then '
+          '%(solink)s && %(extract_toc)s > ${lib}.TOC; '
+        'else '
+          '%(solink)s && %(extract_toc)s > ${lib}.tmp && '
+          'if ! cmp -s ${lib}.tmp ${lib}.TOC; then '
+            'mv ${lib}.tmp ${lib}.TOC ; '
+          'fi; '
+        'fi'
+        % { 'solink': '$ld -shared $ldflags -o $lib %(suffix)s',
+            'extract_toc':
+              '{ otool -l $lib | grep LC_ID_DYLIB -A 5; '
+              'nm -gP $lib | cut -f1-2 -d\' \' | grep -v U$$; true; }'})
+
+    # TODO(thakis): The solink_module rule is likely wrong. Xcode seems to pass
+    # -bundle -single_module here (for osmesa.so).
+    master_ninja.rule(
+      'solink',
+      description='SOLINK $lib, POSTBUILDS',
+      restat=True,
+      command=(mtime_preserving_solink_base % {
+          'suffix': '$in $solibs $libs$postbuilds'}))
+    master_ninja.rule(
+      'solink_module',
+      description='SOLINK(module) $lib, POSTBUILDS',
+      restat=True,
+      command=(mtime_preserving_solink_base % {
+          'suffix': '$in $solibs $libs$postbuilds'}))
+
+    master_ninja.rule(
+      'link',
+      description='LINK $out, POSTBUILDS',
+      command=('$ld $ldflags -o $out '
+               '$in $solibs $libs$postbuilds'))
+    master_ninja.rule(
+      'infoplist',
+      description='INFOPLIST $out',
+      command=('$cc -E -P -Wno-trigraphs -x c $defines $in -o $out && '
+               'plutil -convert xml1 $out $out'))
+    master_ninja.rule(
+      'mac_tool',
+      description='MACTOOL $mactool_cmd $in',
+      command='$env ./gyp-mac-tool $mactool_cmd $in $out')
+    master_ninja.rule(
+      'package_framework',
+      description='PACKAGE FRAMEWORK $out, POSTBUILDS',
+      command='./gyp-mac-tool package-framework $out $version$postbuilds '
+              '&& touch $out')
+  if flavor == 'win':
+    master_ninja.rule(
+      'stamp',
+      description='STAMP $out',
+      command='%s gyp-win-tool stamp $out' % sys.executable)
+    master_ninja.rule(
+      'copy',
+      description='COPY $in $out',
+      command='%s gyp-win-tool recursive-mirror $in $out' % sys.executable)
+  else:
+    master_ninja.rule(
+      'stamp',
+      description='STAMP $out',
+      command='${postbuilds}touch $out')
+    master_ninja.rule(
+      'copy',
+      description='COPY $in $out',
+      command='ln -f $in $out 2>/dev/null || (rm -rf $out && cp -af $in $out)')
+  master_ninja.newline()
+
+  all_targets = set()
+  for build_file in params['build_files']:
+    for target in gyp.common.AllTargets(target_list,
+                                        target_dicts,
+                                        os.path.normpath(build_file)):
+      all_targets.add(target)
+  all_outputs = set()
+
+  # target_outputs is a map from qualified target name to a Target object.
+  target_outputs = {}
+  # target_short_names is a map from target short name to a list of Target
+  # objects.
+  target_short_names = {}
+  for qualified_target in target_list:
+    # qualified_target is like: third_party/icu/icu.gyp:icui18n#target
+    build_file, name, toolset = \
+        gyp.common.ParseQualifiedTarget(qualified_target)
+
+    this_make_global_settings = data[build_file].get('make_global_settings', [])
+    assert make_global_settings == this_make_global_settings, (
+        "make_global_settings needs to be the same for all targets.")
+
+    spec = target_dicts[qualified_target]
+    if flavor == 'mac':
+      gyp.xcode_emulation.MergeGlobalXcodeSettingsToSpec(data[build_file], spec)
+
+    build_file = gyp.common.RelativePath(build_file, options.toplevel_dir)
+
+    base_path = os.path.dirname(build_file)
+    obj = 'obj'
+    if toolset != 'target':
+      obj += '.' + toolset
+    output_file = os.path.join(obj, base_path, name + '.ninja')
+
+    abs_build_dir = os.path.abspath(toplevel_build)
+    writer = NinjaWriter(qualified_target, target_outputs, base_path, build_dir,
+                         OpenOutput(os.path.join(toplevel_build, output_file)),
+                         flavor, toplevel_dir=options.toplevel_dir)
+    master_ninja.subninja(output_file)
+
+    target = writer.WriteSpec(
+        spec, config_name, generator_flags, case_sensitive_filesystem)
+    if target:
+      if name != target.FinalOutput() and spec['toolset'] == 'target':
+        target_short_names.setdefault(name, []).append(target)
+      target_outputs[qualified_target] = target
+      if qualified_target in all_targets:
+        all_outputs.add(target.FinalOutput())
+
+  if target_short_names:
+    # Write a short name to build this target.  This benefits both the
+    # "build chrome" case as well as the gyp tests, which expect to be
+    # able to run actions and build libraries by their short name.
+    master_ninja.newline()
+    master_ninja.comment('Short names for targets.')
+    for short_name in target_short_names:
+      master_ninja.build(short_name, 'phony', [x.FinalOutput() for x in
+                                               target_short_names[short_name]])
+
+  if all_outputs:
+    master_ninja.newline()
+    master_ninja.build('all', 'phony', list(all_outputs))
+    master_ninja.default(generator_flags.get('default_target', 'all'))
+
+
+def PerformBuild(data, configurations, params):
+  options = params['options']
+  for config in configurations:
+    builddir = os.path.join(options.toplevel_dir, 'out', config)
+    arguments = ['ninja', '-C', builddir]
+    print 'Building [%s]: %s' % (config, arguments)
+    subprocess.check_call(arguments)
+
+
+def CallGenerateOutputForConfig(arglist):
+  # Ignore the interrupt signal so that the parent process catches it and
+  # kills all multiprocessing children.
+  signal.signal(signal.SIGINT, signal.SIG_IGN)
+
+  (target_list, target_dicts, data, params, config_name) = arglist
+  GenerateOutputForConfig(target_list, target_dicts, data, params, config_name)
+
+
+def GenerateOutput(target_list, target_dicts, data, params):
+  user_config = params.get('generator_flags', {}).get('config', None)
+  if gyp.common.GetFlavor(params) == 'win':
+    target_list, target_dicts = MSVSUtil.ShardTargets(target_list, target_dicts)
+    target_list, target_dicts = MSVSUtil.InsertLargePdbShims(
+        target_list, target_dicts, generator_default_variables)
+
+  if user_config:
+    GenerateOutputForConfig(target_list, target_dicts, data, params,
+                            user_config)
+  else:
+    config_names = target_dicts[target_list[0]]['configurations'].keys()
+    if params['parallel']:
+      try:
+        pool = multiprocessing.Pool(len(config_names))
+        arglists = []
+        for config_name in config_names:
+          arglists.append(
+              (target_list, target_dicts, data, params, config_name))
+          pool.map(CallGenerateOutputForConfig, arglists)
+      except KeyboardInterrupt, e:
+        pool.terminate()
+        raise e
+    else:
+      for config_name in config_names:
+        GenerateOutputForConfig(target_list, target_dicts, data, params,
+                                config_name)
diff --git a/webWidgetTCT_device/tools/gyp/pylib/gyp/generator/ninja_test.py b/webWidgetTCT_device/tools/gyp/pylib/gyp/generator/ninja_test.py
new file mode 100755 (executable)
index 0000000..90dd153
--- /dev/null
@@ -0,0 +1,44 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+""" Unit tests for the ninja.py file. """
+
+import gyp.generator.ninja as ninja
+import unittest
+import StringIO
+import sys
+import TestCommon
+
+
+class TestPrefixesAndSuffixes(unittest.TestCase):
+  if sys.platform in ('win32', 'cygwin'):
+    def test_BinaryNamesWindows(self):
+      writer = ninja.NinjaWriter('foo', 'wee', '.', '.', 'ninja.build', 'win')
+      spec = { 'target_name': 'wee' }
+      self.assertTrue(writer.ComputeOutputFileName(spec, 'executable').
+          endswith('.exe'))
+      self.assertTrue(writer.ComputeOutputFileName(spec, 'shared_library').
+          endswith('.dll'))
+      self.assertTrue(writer.ComputeOutputFileName(spec, 'static_library').
+          endswith('.lib'))
+
+  if sys.platform == 'linux2':
+    def test_BinaryNamesLinux(self):
+      writer = ninja.NinjaWriter('foo', 'wee', '.', '.', 'ninja.build', 'linux')
+      spec = { 'target_name': 'wee' }
+      self.assertTrue('.' not in writer.ComputeOutputFileName(spec,
+                                                              'executable'))
+      self.assertTrue(writer.ComputeOutputFileName(spec, 'shared_library').
+          startswith('lib'))
+      self.assertTrue(writer.ComputeOutputFileName(spec, 'static_library').
+          startswith('lib'))
+      self.assertTrue(writer.ComputeOutputFileName(spec, 'shared_library').
+          endswith('.so'))
+      self.assertTrue(writer.ComputeOutputFileName(spec, 'static_library').
+          endswith('.a'))
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/webWidgetTCT_device/tools/gyp/pylib/gyp/generator/scons.py b/webWidgetTCT_device/tools/gyp/pylib/gyp/generator/scons.py
new file mode 100755 (executable)
index 0000000..fe7cb58
--- /dev/null
@@ -0,0 +1,1072 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import gyp
+import gyp.common
+import gyp.SCons as SCons
+import os.path
+import pprint
+import re
+import subprocess
+
+
+# TODO:  remove when we delete the last WriteList() call in this module
+WriteList = SCons.WriteList
+
+
+generator_default_variables = {
+    'EXECUTABLE_PREFIX': '',
+    'EXECUTABLE_SUFFIX': '',
+    'STATIC_LIB_PREFIX': '${LIBPREFIX}',
+    'SHARED_LIB_PREFIX': '${SHLIBPREFIX}',
+    'STATIC_LIB_SUFFIX': '${LIBSUFFIX}',
+    'SHARED_LIB_SUFFIX': '${SHLIBSUFFIX}',
+    'INTERMEDIATE_DIR': '${INTERMEDIATE_DIR}',
+    'SHARED_INTERMEDIATE_DIR': '${SHARED_INTERMEDIATE_DIR}',
+    'OS': 'linux',
+    'PRODUCT_DIR': '$TOP_BUILDDIR',
+    'SHARED_LIB_DIR': '$LIB_DIR',
+    'LIB_DIR': '$LIB_DIR',
+    'RULE_INPUT_ROOT': '${SOURCE.filebase}',
+    'RULE_INPUT_DIRNAME': '${SOURCE.dir}',
+    'RULE_INPUT_EXT': '${SOURCE.suffix}',
+    'RULE_INPUT_NAME': '${SOURCE.file}',
+    'RULE_INPUT_PATH': '${SOURCE.abspath}',
+    'CONFIGURATION_NAME': '${CONFIG_NAME}',
+}
+
+# Tell GYP how to process the input for us.
+generator_handles_variants = True
+generator_wants_absolute_build_file_paths = True
+
+
+def FixPath(path, prefix):
+  if not os.path.isabs(path) and not path[0] == '$':
+    path = prefix + path
+  return path
+
+
+header = """\
+# This file is generated; do not edit.
+"""
+
+
+_alias_template = """
+if GetOption('verbose'):
+  _action = Action([%(action)s])
+else:
+  _action = Action([%(action)s], %(message)s)
+_outputs = env.Alias(
+  ['_%(target_name)s_action'],
+  %(inputs)s,
+  _action
+)
+env.AlwaysBuild(_outputs)
+"""
+
+_run_as_template = """
+if GetOption('verbose'):
+  _action = Action([%(action)s])
+else:
+  _action = Action([%(action)s], %(message)s)
+"""
+
+_run_as_template_suffix = """
+_run_as_target = env.Alias('run_%(target_name)s', target_files, _action)
+env.Requires(_run_as_target, [
+    Alias('%(target_name)s'),
+])
+env.AlwaysBuild(_run_as_target)
+"""
+
+_command_template = """
+if GetOption('verbose'):
+  _action = Action([%(action)s])
+else:
+  _action = Action([%(action)s], %(message)s)
+_outputs = env.Command(
+  %(outputs)s,
+  %(inputs)s,
+  _action
+)
+"""
+
+# This is copied from the default SCons action, updated to handle symlinks.
+_copy_action_template = """
+import shutil
+import SCons.Action
+
+def _copy_files_or_dirs_or_symlinks(dest, src):
+  SCons.Node.FS.invalidate_node_memos(dest)
+  if SCons.Util.is_List(src) and os.path.isdir(dest):
+    for file in src:
+      shutil.copy2(file, dest)
+    return 0
+  elif os.path.islink(src):
+    linkto = os.readlink(src)
+    os.symlink(linkto, dest)
+    return 0
+  elif os.path.isfile(src):
+    return shutil.copy2(src, dest)
+  else:
+    return shutil.copytree(src, dest, 1)
+
+def _copy_files_or_dirs_or_symlinks_str(dest, src):
+  return 'Copying %s to %s ...' % (src, dest)
+
+GYPCopy = SCons.Action.ActionFactory(_copy_files_or_dirs_or_symlinks,
+                                     _copy_files_or_dirs_or_symlinks_str,
+                                     convert=str)
+"""
+
+_rule_template = """
+%(name)s_additional_inputs = %(inputs)s
+%(name)s_outputs = %(outputs)s
+def %(name)s_emitter(target, source, env):
+  return (%(name)s_outputs, source + %(name)s_additional_inputs)
+if GetOption('verbose'):
+  %(name)s_action = Action([%(action)s])
+else:
+  %(name)s_action = Action([%(action)s], %(message)s)
+env['BUILDERS']['%(name)s'] = Builder(action=%(name)s_action,
+                                      emitter=%(name)s_emitter)
+
+_outputs = []
+_processed_input_files = []
+for infile in input_files:
+  if (type(infile) == type('')
+      and not os.path.isabs(infile)
+      and not infile[0] == '$'):
+    infile = %(src_dir)r + infile
+  if str(infile).endswith('.%(extension)s'):
+    _generated = env.%(name)s(infile)
+    env.Precious(_generated)
+    _outputs.append(_generated)
+    %(process_outputs_as_sources_line)s
+  else:
+    _processed_input_files.append(infile)
+prerequisites.extend(_outputs)
+input_files = _processed_input_files
+"""
+
+_spawn_hack = """
+import re
+import SCons.Platform.posix
+needs_shell = re.compile('["\\'><!^&]')
+def gyp_spawn(sh, escape, cmd, args, env):
+  def strip_scons_quotes(arg):
+    if arg[0] == '"' and arg[-1] == '"':
+      return arg[1:-1]
+    return arg
+  stripped_args = [strip_scons_quotes(a) for a in args]
+  if needs_shell.search(' '.join(stripped_args)):
+    return SCons.Platform.posix.exec_spawnvpe([sh, '-c', ' '.join(args)], env)
+  else:
+    return SCons.Platform.posix.exec_spawnvpe(stripped_args, env)
+"""
+
+
+def EscapeShellArgument(s):
+  """Quotes an argument so that it will be interpreted literally by a POSIX
+     shell. Taken from
+     http://stackoverflow.com/questions/35817/whats-the-best-way-to-escape-ossystem-calls-in-python
+     """
+  return "'" + s.replace("'", "'\\''") + "'"
+
+
+def InvertNaiveSConsQuoting(s):
+  """SCons tries to "help" with quoting by naively putting double-quotes around
+     command-line arguments containing space or tab, which is broken for all
+     but trivial cases, so we undo it. (See quote_spaces() in Subst.py)"""
+  if ' ' in s or '\t' in s:
+    # Then SCons will put double-quotes around this, so add our own quotes
+    # to close its quotes at the beginning and end.
+    s = '"' + s + '"'
+  return s
+
+
+def EscapeSConsVariableExpansion(s):
+  """SCons has its own variable expansion syntax using $. We must escape it for
+    strings to be interpreted literally. For some reason this requires four
+    dollar signs, not two, even without the shell involved."""
+  return s.replace('$', '$$$$')
+
+
+def EscapeCppDefine(s):
+  """Escapes a CPP define so that it will reach the compiler unaltered."""
+  s = EscapeShellArgument(s)
+  s = InvertNaiveSConsQuoting(s)
+  s = EscapeSConsVariableExpansion(s)
+  return s
+
+
+def GenerateConfig(fp, config, indent='', src_dir=''):
+  """
+  Generates SCons dictionary items for a gyp configuration.
+
+  This provides the main translation between the (lower-case) gyp settings
+  keywords and the (upper-case) SCons construction variables.
+  """
+  var_mapping = {
+      'ASFLAGS' : 'asflags',
+      'CCFLAGS' : 'cflags',
+      'CFLAGS' : 'cflags_c',
+      'CXXFLAGS' : 'cflags_cc',
+      'CPPDEFINES' : 'defines',
+      'CPPPATH' : 'include_dirs',
+      # Add the ldflags value to $LINKFLAGS, but not $SHLINKFLAGS.
+      # SCons defines $SHLINKFLAGS to incorporate $LINKFLAGS, so
+      # listing both here would case 'ldflags' to get appended to
+      # both, and then have it show up twice on the command line.
+      'LINKFLAGS' : 'ldflags',
+  }
+  postamble='\n%s],\n' % indent
+  for scons_var in sorted(var_mapping.keys()):
+      gyp_var = var_mapping[scons_var]
+      value = config.get(gyp_var)
+      if value:
+        if gyp_var in ('defines',):
+          value = [EscapeCppDefine(v) for v in value]
+        if gyp_var in ('include_dirs',):
+          if src_dir and not src_dir.endswith('/'):
+            src_dir += '/'
+          result = []
+          for v in value:
+            v = FixPath(v, src_dir)
+            # Force SCons to evaluate the CPPPATH directories at
+            # SConscript-read time, so delayed evaluation of $SRC_DIR
+            # doesn't point it to the --generator-output= directory.
+            result.append('env.Dir(%r)' % v)
+          value = result
+        else:
+          value = map(repr, value)
+        WriteList(fp,
+                  value,
+                  prefix=indent,
+                  preamble='%s%s = [\n    ' % (indent, scons_var),
+                  postamble=postamble)
+
+
+def GenerateSConscript(output_filename, spec, build_file, build_file_data):
+  """
+  Generates a SConscript file for a specific target.
+
+  This generates a SConscript file suitable for building any or all of
+  the target's configurations.
+
+  A SConscript file may be called multiple times to generate targets for
+  multiple configurations.  Consequently, it needs to be ready to build
+  the target for any requested configuration, and therefore contains
+  information about the settings for all configurations (generated into
+  the SConscript file at gyp configuration time) as well as logic for
+  selecting (at SCons build time) the specific configuration being built.
+
+  The general outline of a generated SConscript file is:
+
+    --  Header
+
+    --  Import 'env'.  This contains a $CONFIG_NAME construction
+        variable that specifies what configuration to build
+        (e.g. Debug, Release).
+
+    --  Configurations.  This is a dictionary with settings for
+        the different configurations (Debug, Release) under which this
+        target can be built.  The values in the dictionary are themselves
+        dictionaries specifying what construction variables should added
+        to the local copy of the imported construction environment
+        (Append), should be removed (FilterOut), and should outright
+        replace the imported values (Replace).
+
+    --  Clone the imported construction environment and update
+        with the proper configuration settings.
+
+    --  Initialize the lists of the targets' input files and prerequisites.
+
+    --  Target-specific actions and rules.  These come after the
+        input file and prerequisite initializations because the
+        outputs of the actions and rules may affect the input file
+        list (process_outputs_as_sources) and get added to the list of
+        prerequisites (so that they're guaranteed to be executed before
+        building the target).
+
+    --  Call the Builder for the target itself.
+
+    --  Arrange for any copies to be made into installation directories.
+
+    --  Set up the {name} Alias (phony Node) for the target as the
+        primary handle for building all of the target's pieces.
+
+    --  Use env.Require() to make sure the prerequisites (explicitly
+        specified, but also including the actions and rules) are built
+        before the target itself.
+
+    --  Return the {name} Alias to the calling SConstruct file
+        so it can be added to the list of default targets.
+  """
+  scons_target = SCons.Target(spec)
+
+  gyp_dir = os.path.dirname(output_filename)
+  if not gyp_dir:
+      gyp_dir = '.'
+  gyp_dir = os.path.abspath(gyp_dir)
+
+  output_dir = os.path.dirname(output_filename)
+  src_dir = build_file_data['_DEPTH']
+  src_dir_rel = gyp.common.RelativePath(src_dir, output_dir)
+  subdir = gyp.common.RelativePath(os.path.dirname(build_file), src_dir)
+  src_subdir = '$SRC_DIR/' + subdir
+  src_subdir_ = src_subdir + '/'
+
+  component_name = os.path.splitext(os.path.basename(build_file))[0]
+  target_name = spec['target_name']
+
+  if not os.path.exists(gyp_dir):
+    os.makedirs(gyp_dir)
+  fp = open(output_filename, 'w')
+  fp.write(header)
+
+  fp.write('\nimport os\n')
+  fp.write('\nImport("env")\n')
+
+  #
+  fp.write('\n')
+  fp.write('env = env.Clone(COMPONENT_NAME=%s,\n' % repr(component_name))
+  fp.write('                TARGET_NAME=%s)\n' % repr(target_name))
+
+  #
+  for config in spec['configurations'].itervalues():
+    if config.get('scons_line_length'):
+      fp.write(_spawn_hack)
+      break
+
+  #
+  indent = ' ' * 12
+  fp.write('\n')
+  fp.write('configurations = {\n')
+  for config_name, config in spec['configurations'].iteritems():
+    fp.write('    \'%s\' : {\n' % config_name)
+
+    fp.write('        \'Append\' : dict(\n')
+    GenerateConfig(fp, config, indent, src_subdir)
+    libraries = spec.get('libraries')
+    if libraries:
+      WriteList(fp,
+                map(repr, libraries),
+                prefix=indent,
+                preamble='%sLIBS = [\n    ' % indent,
+                postamble='\n%s],\n' % indent)
+    fp.write('        ),\n')
+
+    fp.write('        \'FilterOut\' : dict(\n' )
+    for key, var in config.get('scons_remove', {}).iteritems():
+      fp.write('             %s = %s,\n' % (key, repr(var)))
+    fp.write('        ),\n')
+
+    fp.write('        \'Replace\' : dict(\n' )
+    scons_settings = config.get('scons_variable_settings', {})
+    for key in sorted(scons_settings.keys()):
+      val = pprint.pformat(scons_settings[key])
+      fp.write('             %s = %s,\n' % (key, val))
+    if 'c++' in spec.get('link_languages', []):
+      fp.write('             %s = %s,\n' % ('LINK', repr('$CXX')))
+    if config.get('scons_line_length'):
+      fp.write('             SPAWN = gyp_spawn,\n')
+    fp.write('        ),\n')
+
+    fp.write('        \'ImportExternal\' : [\n' )
+    for var in config.get('scons_import_variables', []):
+      fp.write('             %s,\n' % repr(var))
+    fp.write('        ],\n')
+
+    fp.write('        \'PropagateExternal\' : [\n' )
+    for var in config.get('scons_propagate_variables', []):
+      fp.write('             %s,\n' % repr(var))
+    fp.write('        ],\n')
+
+    fp.write('    },\n')
+  fp.write('}\n')
+
+  fp.write('\n'
+           'config = configurations[env[\'CONFIG_NAME\']]\n'
+           'env.Append(**config[\'Append\'])\n'
+           'env.FilterOut(**config[\'FilterOut\'])\n'
+           'env.Replace(**config[\'Replace\'])\n')
+
+  fp.write('\n'
+           '# Scons forces -fPIC for SHCCFLAGS on some platforms.\n'
+           '# Disable that so we can control it from cflags in gyp.\n'
+           '# Note that Scons itself is inconsistent with its -fPIC\n'
+           '# setting. SHCCFLAGS forces -fPIC, and SHCFLAGS does not.\n'
+           '# This will make SHCCFLAGS consistent with SHCFLAGS.\n'
+           'env[\'SHCCFLAGS\'] = [\'$CCFLAGS\']\n')
+
+  fp.write('\n'
+           'for _var in config[\'ImportExternal\']:\n'
+           '  if _var in ARGUMENTS:\n'
+           '    env[_var] = ARGUMENTS[_var]\n'
+           '  elif _var in os.environ:\n'
+           '    env[_var] = os.environ[_var]\n'
+           'for _var in config[\'PropagateExternal\']:\n'
+           '  if _var in ARGUMENTS:\n'
+           '    env[_var] = ARGUMENTS[_var]\n'
+           '  elif _var in os.environ:\n'
+           '    env[\'ENV\'][_var] = os.environ[_var]\n')
+
+  fp.write('\n'
+           "env['ENV']['LD_LIBRARY_PATH'] = env.subst('$LIB_DIR')\n")
+
+  #
+  #fp.write("\nif env.has_key('CPPPATH'):\n")
+  #fp.write("  env['CPPPATH'] = map(env.Dir, env['CPPPATH'])\n")
+
+  variants = spec.get('variants', {})
+  for setting in sorted(variants.keys()):
+    if_fmt = 'if ARGUMENTS.get(%s) not in (None, \'0\'):\n'
+    fp.write('\n')
+    fp.write(if_fmt % repr(setting.upper()))
+    fp.write('  env.AppendUnique(\n')
+    GenerateConfig(fp, variants[setting], indent, src_subdir)
+    fp.write('  )\n')
+
+  #
+  scons_target.write_input_files(fp)
+
+  fp.write('\n')
+  fp.write('target_files = []\n')
+  prerequisites = spec.get('scons_prerequisites', [])
+  fp.write('prerequisites = %s\n' % pprint.pformat(prerequisites))
+
+  actions = spec.get('actions', [])
+  for action in actions:
+    a = ['cd', src_subdir, '&&'] + action['action']
+    message = action.get('message')
+    if message:
+      message = repr(message)
+    inputs = [FixPath(f, src_subdir_) for f in action.get('inputs', [])]
+    outputs = [FixPath(f, src_subdir_) for f in action.get('outputs', [])]
+    if outputs:
+      template = _command_template
+    else:
+      template = _alias_template
+    fp.write(template % {
+                 'inputs' : pprint.pformat(inputs),
+                 'outputs' : pprint.pformat(outputs),
+                 'action' : pprint.pformat(a),
+                 'message' : message,
+                 'target_name': target_name,
+             })
+    if int(action.get('process_outputs_as_sources', 0)):
+      fp.write('input_files.extend(_outputs)\n')
+    fp.write('prerequisites.extend(_outputs)\n')
+    fp.write('target_files.extend(_outputs)\n')
+
+  rules = spec.get('rules', [])
+  for rule in rules:
+    name = re.sub('[^a-zA-Z0-9_]', '_', rule['rule_name'])
+    message = rule.get('message')
+    if message:
+        message = repr(message)
+    if int(rule.get('process_outputs_as_sources', 0)):
+      poas_line = '_processed_input_files.extend(_generated)'
+    else:
+      poas_line = '_processed_input_files.append(infile)'
+    inputs = [FixPath(f, src_subdir_) for f in rule.get('inputs', [])]
+    outputs = [FixPath(f, src_subdir_) for f in rule.get('outputs', [])]
+    # Skip a rule with no action and no inputs.
+    if 'action' not in rule and not rule.get('rule_sources', []):
+      continue
+    a = ['cd', src_subdir, '&&'] + rule['action']
+    fp.write(_rule_template % {
+                 'inputs' : pprint.pformat(inputs),
+                 'outputs' : pprint.pformat(outputs),
+                 'action' : pprint.pformat(a),
+                 'extension' : rule['extension'],
+                 'name' : name,
+                 'message' : message,
+                 'process_outputs_as_sources_line' : poas_line,
+                 'src_dir' : src_subdir_,
+             })
+
+  scons_target.write_target(fp, src_subdir)
+
+  copies = spec.get('copies', [])
+  if copies:
+    fp.write(_copy_action_template)
+  for copy in copies:
+    destdir = None
+    files = None
+    try:
+      destdir = copy['destination']
+    except KeyError, e:
+      gyp.common.ExceptionAppend(
+        e,
+        "Required 'destination' key missing for 'copies' in %s." % build_file)
+      raise
+    try:
+      files = copy['files']
+    except KeyError, e:
+      gyp.common.ExceptionAppend(
+        e, "Required 'files' key missing for 'copies' in %s." % build_file)
+      raise
+    if not files:
+      # TODO:  should probably add a (suppressible) warning;
+      # a null file list may be unintentional.
+      continue
+    if not destdir:
+      raise Exception(
+        "Required 'destination' key is empty for 'copies' in %s." % build_file)
+
+    fmt = ('\n'
+           '_outputs = env.Command(%s,\n'
+           '    %s,\n'
+           '    GYPCopy(\'$TARGET\', \'$SOURCE\'))\n')
+    for f in copy['files']:
+      # Remove trailing separators so basename() acts like Unix basename and
+      # always returns the last element, whether a file or dir. Without this,
+      # only the contents, not the directory itself, are copied (and nothing
+      # might be copied if dest already exists, since scons thinks nothing needs
+      # to be done).
+      dest = os.path.join(destdir, os.path.basename(f.rstrip(os.sep)))
+      f = FixPath(f, src_subdir_)
+      dest = FixPath(dest, src_subdir_)
+      fp.write(fmt % (repr(dest), repr(f)))
+      fp.write('target_files.extend(_outputs)\n')
+
+  run_as = spec.get('run_as')
+  if run_as:
+    action = run_as.get('action', [])
+    working_directory = run_as.get('working_directory')
+    if not working_directory:
+      working_directory = gyp_dir
+    else:
+      if not os.path.isabs(working_directory):
+        working_directory = os.path.normpath(os.path.join(gyp_dir,
+                                                          working_directory))
+    if run_as.get('environment'):
+      for (key, val) in run_as.get('environment').iteritems():
+        action = ['%s="%s"' % (key, val)] + action
+    action = ['cd', '"%s"' % working_directory, '&&'] + action
+    fp.write(_run_as_template % {
+      'action' : pprint.pformat(action),
+      'message' : run_as.get('message', ''),
+    })
+
+  fmt = "\ngyp_target = env.Alias('%s', target_files)\n"
+  fp.write(fmt % target_name)
+
+  dependencies = spec.get('scons_dependencies', [])
+  if dependencies:
+    WriteList(fp, dependencies, preamble='dependencies = [\n    ',
+                                postamble='\n]\n')
+    fp.write('env.Requires(target_files, dependencies)\n')
+    fp.write('env.Requires(gyp_target, dependencies)\n')
+    fp.write('for prerequisite in prerequisites:\n')
+    fp.write('  env.Requires(prerequisite, dependencies)\n')
+  fp.write('env.Requires(gyp_target, prerequisites)\n')
+
+  if run_as:
+    fp.write(_run_as_template_suffix % {
+      'target_name': target_name,
+    })
+
+  fp.write('Return("gyp_target")\n')
+
+  fp.close()
+
+
+#############################################################################
+# TEMPLATE BEGIN
+
+_wrapper_template = """\
+
+__doc__ = '''
+Wrapper configuration for building this entire "solution,"
+including all the specific targets in various *.scons files.
+'''
+
+import os
+import sys
+
+import SCons.Environment
+import SCons.Util
+
+def GetProcessorCount():
+  '''
+  Detects the number of CPUs on the system. Adapted form:
+  http://codeliberates.blogspot.com/2008/05/detecting-cpuscores-in-python.html
+  '''
+  # Linux, Unix and Mac OS X:
+  if hasattr(os, 'sysconf'):
+    if os.sysconf_names.has_key('SC_NPROCESSORS_ONLN'):
+      # Linux and Unix or Mac OS X with python >= 2.5:
+      return os.sysconf('SC_NPROCESSORS_ONLN')
+    else:  # Mac OS X with Python < 2.5:
+      return int(os.popen2("sysctl -n hw.ncpu")[1].read())
+  # Windows:
+  if os.environ.has_key('NUMBER_OF_PROCESSORS'):
+    return max(int(os.environ.get('NUMBER_OF_PROCESSORS', '1')), 1)
+  return 1  # Default
+
+# Support PROGRESS= to show progress in different ways.
+p = ARGUMENTS.get('PROGRESS')
+if p == 'spinner':
+  Progress(['/\\r', '|\\r', '\\\\\\r', '-\\r'],
+           interval=5,
+           file=open('/dev/tty', 'w'))
+elif p == 'name':
+  Progress('$TARGET\\r', overwrite=True, file=open('/dev/tty', 'w'))
+
+# Set the default -j value based on the number of processors.
+SetOption('num_jobs', GetProcessorCount() + 1)
+
+# Have SCons use its cached dependency information.
+SetOption('implicit_cache', 1)
+
+# Only re-calculate MD5 checksums if a timestamp has changed.
+Decider('MD5-timestamp')
+
+# Since we set the -j value by default, suppress SCons warnings about being
+# unable to support parallel build on versions of Python with no threading.
+default_warnings = ['no-no-parallel-support']
+SetOption('warn', default_warnings + GetOption('warn'))
+
+AddOption('--mode', nargs=1, dest='conf_list', default=[],
+          action='append', help='Configuration to build.')
+
+AddOption('--verbose', dest='verbose', default=False,
+          action='store_true', help='Verbose command-line output.')
+
+
+#
+sconscript_file_map = %(sconscript_files)s
+
+class LoadTarget:
+  '''
+  Class for deciding if a given target sconscript is to be included
+  based on a list of included target names, optionally prefixed with '-'
+  to exclude a target name.
+  '''
+  def __init__(self, load):
+    '''
+    Initialize a class with a list of names for possible loading.
+
+    Arguments:
+      load:  list of elements in the LOAD= specification
+    '''
+    self.included = set([c for c in load if not c.startswith('-')])
+    self.excluded = set([c[1:] for c in load if c.startswith('-')])
+
+    if not self.included:
+      self.included = set(['all'])
+
+  def __call__(self, target):
+    '''
+    Returns True if the specified target's sconscript file should be
+    loaded, based on the initialized included and excluded lists.
+    '''
+    return (target in self.included or
+            ('all' in self.included and not target in self.excluded))
+
+if 'LOAD' in ARGUMENTS:
+  load = ARGUMENTS['LOAD'].split(',')
+else:
+  load = []
+load_target = LoadTarget(load)
+
+sconscript_files = []
+for target, sconscript in sconscript_file_map.iteritems():
+  if load_target(target):
+    sconscript_files.append(sconscript)
+
+
+target_alias_list= []
+
+conf_list = GetOption('conf_list')
+if conf_list:
+    # In case the same --mode= value was specified multiple times.
+    conf_list = list(set(conf_list))
+else:
+    conf_list = [%(default_configuration)r]
+
+sconsbuild_dir = Dir(%(sconsbuild_dir)s)
+
+
+def FilterOut(self, **kw):
+  kw = SCons.Environment.copy_non_reserved_keywords(kw)
+  for key, val in kw.items():
+    envval = self.get(key, None)
+    if envval is None:
+      # No existing variable in the environment, so nothing to delete.
+      continue
+
+    for vremove in val:
+      # Use while not if, so we can handle duplicates.
+      while vremove in envval:
+        envval.remove(vremove)
+
+    self[key] = envval
+
+    # TODO(sgk): SCons.Environment.Append() has much more logic to deal
+    # with various types of values.  We should handle all those cases in here
+    # too.  (If variable is a dict, etc.)
+
+
+non_compilable_suffixes = {
+    'LINUX' : set([
+        '.bdic',
+        '.css',
+        '.dat',
+        '.fragment',
+        '.gperf',
+        '.h',
+        '.hh',
+        '.hpp',
+        '.html',
+        '.hxx',
+        '.idl',
+        '.in',
+        '.in0',
+        '.in1',
+        '.js',
+        '.mk',
+        '.rc',
+        '.sigs',
+        '',
+    ]),
+    'WINDOWS' : set([
+        '.h',
+        '.hh',
+        '.hpp',
+        '.dat',
+        '.idl',
+        '.in',
+        '.in0',
+        '.in1',
+    ]),
+}
+
+def compilable(env, file):
+  base, ext = os.path.splitext(str(file))
+  if ext in non_compilable_suffixes[env['TARGET_PLATFORM']]:
+    return False
+  return True
+
+def compilable_files(env, sources):
+  return [x for x in sources if compilable(env, x)]
+
+def GypProgram(env, target, source, *args, **kw):
+  source = compilable_files(env, source)
+  result = env.Program(target, source, *args, **kw)
+  if env.get('INCREMENTAL'):
+    env.Precious(result)
+  return result
+
+def GypTestProgram(env, target, source, *args, **kw):
+  source = compilable_files(env, source)
+  result = env.Program(target, source, *args, **kw)
+  if env.get('INCREMENTAL'):
+    env.Precious(*result)
+  return result
+
+def GypLibrary(env, target, source, *args, **kw):
+  source = compilable_files(env, source)
+  result = env.Library(target, source, *args, **kw)
+  return result
+
+def GypLoadableModule(env, target, source, *args, **kw):
+  source = compilable_files(env, source)
+  result = env.LoadableModule(target, source, *args, **kw)
+  return result
+
+def GypStaticLibrary(env, target, source, *args, **kw):
+  source = compilable_files(env, source)
+  result = env.StaticLibrary(target, source, *args, **kw)
+  return result
+
+def GypSharedLibrary(env, target, source, *args, **kw):
+  source = compilable_files(env, source)
+  result = env.SharedLibrary(target, source, *args, **kw)
+  if env.get('INCREMENTAL'):
+    env.Precious(result)
+  return result
+
+def add_gyp_methods(env):
+  env.AddMethod(GypProgram)
+  env.AddMethod(GypTestProgram)
+  env.AddMethod(GypLibrary)
+  env.AddMethod(GypLoadableModule)
+  env.AddMethod(GypStaticLibrary)
+  env.AddMethod(GypSharedLibrary)
+
+  env.AddMethod(FilterOut)
+
+  env.AddMethod(compilable)
+
+
+base_env = Environment(
+    tools = %(scons_tools)s,
+    INTERMEDIATE_DIR='$OBJ_DIR/${COMPONENT_NAME}/_${TARGET_NAME}_intermediate',
+    LIB_DIR='$TOP_BUILDDIR/lib',
+    OBJ_DIR='$TOP_BUILDDIR/obj',
+    SCONSBUILD_DIR=sconsbuild_dir.abspath,
+    SHARED_INTERMEDIATE_DIR='$OBJ_DIR/_global_intermediate',
+    SRC_DIR=Dir(%(src_dir)r),
+    TARGET_PLATFORM='LINUX',
+    TOP_BUILDDIR='$SCONSBUILD_DIR/$CONFIG_NAME',
+    LIBPATH=['$LIB_DIR'],
+)
+
+if not GetOption('verbose'):
+  base_env.SetDefault(
+      ARCOMSTR='Creating library $TARGET',
+      ASCOMSTR='Assembling $TARGET',
+      CCCOMSTR='Compiling $TARGET',
+      CONCATSOURCECOMSTR='ConcatSource $TARGET',
+      CXXCOMSTR='Compiling $TARGET',
+      LDMODULECOMSTR='Building loadable module $TARGET',
+      LINKCOMSTR='Linking $TARGET',
+      MANIFESTCOMSTR='Updating manifest for $TARGET',
+      MIDLCOMSTR='Compiling IDL $TARGET',
+      PCHCOMSTR='Precompiling $TARGET',
+      RANLIBCOMSTR='Indexing $TARGET',
+      RCCOMSTR='Compiling resource $TARGET',
+      SHCCCOMSTR='Compiling $TARGET',
+      SHCXXCOMSTR='Compiling $TARGET',
+      SHLINKCOMSTR='Linking $TARGET',
+      SHMANIFESTCOMSTR='Updating manifest for $TARGET',
+  )
+
+add_gyp_methods(base_env)
+
+for conf in conf_list:
+  env = base_env.Clone(CONFIG_NAME=conf)
+  SConsignFile(env.File('$TOP_BUILDDIR/.sconsign').abspath)
+  for sconscript in sconscript_files:
+    target_alias = env.SConscript(sconscript, exports=['env'])
+    if target_alias:
+      target_alias_list.extend(target_alias)
+
+Default(Alias('all', target_alias_list))
+
+help_fmt = '''
+Usage: hammer [SCONS_OPTIONS] [VARIABLES] [TARGET] ...
+
+Local command-line build options:
+  --mode=CONFIG             Configuration to build:
+                              --mode=Debug [default]
+                              --mode=Release
+  --verbose                 Print actual executed command lines.
+
+Supported command-line build variables:
+  LOAD=[module,...]         Comma-separated list of components to load in the
+                              dependency graph ('-' prefix excludes)
+  PROGRESS=type             Display a progress indicator:
+                              name:  print each evaluated target name
+                              spinner:  print a spinner every 5 targets
+
+The following TARGET names can also be used as LOAD= module names:
+
+%%s
+'''
+
+if GetOption('help'):
+  def columnar_text(items, width=78, indent=2, sep=2):
+    result = []
+    colwidth = max(map(len, items)) + sep
+    cols = (width - indent) / colwidth
+    if cols < 1:
+      cols = 1
+    rows = (len(items) + cols - 1) / cols
+    indent = '%%*s' %% (indent, '')
+    sep = indent
+    for row in xrange(0, rows):
+      result.append(sep)
+      for i in xrange(row, len(items), rows):
+        result.append('%%-*s' %% (colwidth, items[i]))
+      sep = '\\n' + indent
+    result.append('\\n')
+    return ''.join(result)
+
+  load_list = set(sconscript_file_map.keys())
+  target_aliases = set(map(str, target_alias_list))
+
+  common = load_list and target_aliases
+  load_only = load_list - common
+  target_only = target_aliases - common
+  help_text = [help_fmt %% columnar_text(sorted(list(common)))]
+  if target_only:
+    fmt = "The following are additional TARGET names:\\n\\n%%s\\n"
+    help_text.append(fmt %% columnar_text(sorted(list(target_only))))
+  if load_only:
+    fmt = "The following are additional LOAD= module names:\\n\\n%%s\\n"
+    help_text.append(fmt %% columnar_text(sorted(list(load_only))))
+  Help(''.join(help_text))
+"""
+
+# TEMPLATE END
+#############################################################################
+
+
+def GenerateSConscriptWrapper(build_file, build_file_data, name,
+                              output_filename, sconscript_files,
+                              default_configuration):
+  """
+  Generates the "wrapper" SConscript file (analogous to the Visual Studio
+  solution) that calls all the individual target SConscript files.
+  """
+  output_dir = os.path.dirname(output_filename)
+  src_dir = build_file_data['_DEPTH']
+  src_dir_rel = gyp.common.RelativePath(src_dir, output_dir)
+  if not src_dir_rel:
+    src_dir_rel = '.'
+  scons_settings = build_file_data.get('scons_settings', {})
+  sconsbuild_dir = scons_settings.get('sconsbuild_dir', '#')
+  scons_tools = scons_settings.get('tools', ['default'])
+
+  sconscript_file_lines = ['dict(']
+  for target in sorted(sconscript_files.keys()):
+    sconscript = sconscript_files[target]
+    sconscript_file_lines.append('    %s = %r,' % (target, sconscript))
+  sconscript_file_lines.append(')')
+
+  fp = open(output_filename, 'w')
+  fp.write(header)
+  fp.write(_wrapper_template % {
+               'default_configuration' : default_configuration,
+               'name' : name,
+               'scons_tools' : repr(scons_tools),
+               'sconsbuild_dir' : repr(sconsbuild_dir),
+               'sconscript_files' : '\n'.join(sconscript_file_lines),
+               'src_dir' : src_dir_rel,
+           })
+  fp.close()
+
+  # Generate the SConstruct file that invokes the wrapper SConscript.
+  dir, fname = os.path.split(output_filename)
+  SConstruct = os.path.join(dir, 'SConstruct')
+  fp = open(SConstruct, 'w')
+  fp.write(header)
+  fp.write('SConscript(%s)\n' % repr(fname))
+  fp.close()
+
+
+def TargetFilename(target, build_file=None, output_suffix=''):
+  """Returns the .scons file name for the specified target.
+  """
+  if build_file is None:
+    build_file, target = gyp.common.ParseQualifiedTarget(target)[:2]
+  output_file = os.path.join(os.path.dirname(build_file),
+                             target + output_suffix + '.scons')
+  return output_file
+
+
+def PerformBuild(data, configurations, params):
+  options = params['options']
+
+  # Due to the way we test gyp on the chromium typbots
+  # we need to look for 'scons.py' as well as the more common 'scons'
+  # TODO(sbc): update the trybots to have a more normal install
+  # of scons.
+  scons = 'scons'
+  paths = os.environ['PATH'].split(os.pathsep)
+  for scons_name in ['scons', 'scons.py']:
+    for path in paths:
+      test_scons = os.path.join(path, scons_name)
+      print 'looking for: %s' % test_scons
+      if os.path.exists(test_scons):
+        print "found scons: %s" % scons
+        scons = test_scons
+        break
+
+  for config in configurations:
+    arguments = [scons, '-C', options.toplevel_dir, '--mode=%s' % config]
+    print "Building [%s]: %s" % (config, arguments)
+    subprocess.check_call(arguments)
+
+
+def GenerateOutput(target_list, target_dicts, data, params):
+  """
+  Generates all the output files for the specified targets.
+  """
+  options = params['options']
+
+  if options.generator_output:
+    def output_path(filename):
+      return filename.replace(params['cwd'], options.generator_output)
+  else:
+    def output_path(filename):
+      return filename
+
+  default_configuration = None
+
+  for qualified_target in target_list:
+    spec = target_dicts[qualified_target]
+    if spec['toolset'] != 'target':
+      raise Exception(
+          'Multiple toolsets not supported in scons build (target %s)' %
+          qualified_target)
+    scons_target = SCons.Target(spec)
+    if scons_target.is_ignored:
+      continue
+
+    # TODO:  assumes the default_configuration of the first target
+    # non-Default target is the correct default for all targets.
+    # Need a better model for handle variation between targets.
+    if (not default_configuration and
+        spec['default_configuration'] != 'Default'):
+      default_configuration = spec['default_configuration']
+
+    build_file, target = gyp.common.ParseQualifiedTarget(qualified_target)[:2]
+    output_file = TargetFilename(target, build_file, options.suffix)
+    if options.generator_output:
+      output_file = output_path(output_file)
+
+    if not spec.has_key('libraries'):
+      spec['libraries'] = []
+
+    # Add dependent static library targets to the 'libraries' value.
+    deps = spec.get('dependencies', [])
+    spec['scons_dependencies'] = []
+    for d in deps:
+      td = target_dicts[d]
+      target_name = td['target_name']
+      spec['scons_dependencies'].append("Alias('%s')" % target_name)
+      if td['type'] in ('static_library', 'shared_library'):
+        libname = td.get('product_name', target_name)
+        spec['libraries'].append('lib' + libname)
+      if td['type'] == 'loadable_module':
+        prereqs = spec.get('scons_prerequisites', [])
+        # TODO:  parameterize with <(SHARED_LIBRARY_*) variables?
+        td_target = SCons.Target(td)
+        td_target.target_prefix = '${SHLIBPREFIX}'
+        td_target.target_suffix = '${SHLIBSUFFIX}'
+
+    GenerateSConscript(output_file, spec, build_file, data[build_file])
+
+  if not default_configuration:
+    default_configuration = 'Default'
+
+  for build_file in sorted(data.keys()):
+    path, ext = os.path.splitext(build_file)
+    if ext != '.gyp':
+      continue
+    output_dir, basename = os.path.split(path)
+    output_filename  = path + '_main' + options.suffix + '.scons'
+
+    all_targets = gyp.common.AllTargets(target_list, target_dicts, build_file)
+    sconscript_files = {}
+    for t in all_targets:
+      scons_target = SCons.Target(target_dicts[t])
+      if scons_target.is_ignored:
+        continue
+      bf, target = gyp.common.ParseQualifiedTarget(t)[:2]
+      target_filename = TargetFilename(target, bf, options.suffix)
+      tpath = gyp.common.RelativePath(target_filename, output_dir)
+      sconscript_files[target] = tpath
+
+    output_filename = output_path(output_filename)
+    if sconscript_files:
+      GenerateSConscriptWrapper(build_file, data[build_file], basename,
+                                output_filename, sconscript_files,
+                                default_configuration)
diff --git a/webWidgetTCT_device/tools/gyp/pylib/gyp/generator/xcode.py b/webWidgetTCT_device/tools/gyp/pylib/gyp/generator/xcode.py
new file mode 100755 (executable)
index 0000000..ca3b01e
--- /dev/null
@@ -0,0 +1,1239 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import filecmp
+import gyp.common
+import gyp.xcodeproj_file
+import errno
+import os
+import sys
+import posixpath
+import re
+import shutil
+import subprocess
+import tempfile
+
+
+# Project files generated by this module will use _intermediate_var as a
+# custom Xcode setting whose value is a DerivedSources-like directory that's
+# project-specific and configuration-specific.  The normal choice,
+# DERIVED_FILE_DIR, is target-specific, which is thought to be too restrictive
+# as it is likely that multiple targets within a single project file will want
+# to access the same set of generated files.  The other option,
+# PROJECT_DERIVED_FILE_DIR, is unsuitable because while it is project-specific,
+# it is not configuration-specific.  INTERMEDIATE_DIR is defined as
+# $(PROJECT_DERIVED_FILE_DIR)/$(CONFIGURATION).
+_intermediate_var = 'INTERMEDIATE_DIR'
+
+# SHARED_INTERMEDIATE_DIR is the same, except that it is shared among all
+# targets that share the same BUILT_PRODUCTS_DIR.
+_shared_intermediate_var = 'SHARED_INTERMEDIATE_DIR'
+
+_library_search_paths_var = 'LIBRARY_SEARCH_PATHS'
+
+generator_default_variables = {
+  'EXECUTABLE_PREFIX': '',
+  'EXECUTABLE_SUFFIX': '',
+  'STATIC_LIB_PREFIX': 'lib',
+  'SHARED_LIB_PREFIX': 'lib',
+  'STATIC_LIB_SUFFIX': '.a',
+  'SHARED_LIB_SUFFIX': '.dylib',
+  # INTERMEDIATE_DIR is a place for targets to build up intermediate products.
+  # It is specific to each build environment.  It is only guaranteed to exist
+  # and be constant within the context of a project, corresponding to a single
+  # input file.  Some build environments may allow their intermediate directory
+  # to be shared on a wider scale, but this is not guaranteed.
+  'INTERMEDIATE_DIR': '$(%s)' % _intermediate_var,
+  'OS': 'mac',
+  'PRODUCT_DIR': '$(BUILT_PRODUCTS_DIR)',
+  'LIB_DIR': '$(BUILT_PRODUCTS_DIR)',
+  'RULE_INPUT_ROOT': '$(INPUT_FILE_BASE)',
+  'RULE_INPUT_EXT': '$(INPUT_FILE_SUFFIX)',
+  'RULE_INPUT_NAME': '$(INPUT_FILE_NAME)',
+  'RULE_INPUT_PATH': '$(INPUT_FILE_PATH)',
+  'RULE_INPUT_DIRNAME': '$(INPUT_FILE_DIRNAME)',
+  'SHARED_INTERMEDIATE_DIR': '$(%s)' % _shared_intermediate_var,
+  'CONFIGURATION_NAME': '$(CONFIGURATION)',
+}
+
+# The Xcode-specific sections that hold paths.
+generator_additional_path_sections = [
+  'mac_bundle_resources',
+  'mac_framework_headers',
+  'mac_framework_private_headers',
+  # 'mac_framework_dirs', input already handles _dirs endings.
+]
+
+# The Xcode-specific keys that exist on targets and aren't moved down to
+# configurations.
+generator_additional_non_configuration_keys = [
+  'mac_bundle',
+  'mac_bundle_resources',
+  'mac_framework_headers',
+  'mac_framework_private_headers',
+  'xcode_create_dependents_test_runner',
+]
+
+# We want to let any rules apply to files that are resources also.
+generator_extra_sources_for_rules = [
+  'mac_bundle_resources',
+  'mac_framework_headers',
+  'mac_framework_private_headers',
+]
+
+# Xcode's standard set of library directories, which don't need to be duplicated
+# in LIBRARY_SEARCH_PATHS. This list is not exhaustive, but that's okay.
+xcode_standard_library_dirs = frozenset([
+  '$(SDKROOT)/usr/lib',
+  '$(SDKROOT)/usr/local/lib',
+])
+
+def CreateXCConfigurationList(configuration_names):
+  xccl = gyp.xcodeproj_file.XCConfigurationList({'buildConfigurations': []})
+  if len(configuration_names) == 0:
+    configuration_names = ['Default']
+  for configuration_name in configuration_names:
+    xcbc = gyp.xcodeproj_file.XCBuildConfiguration({
+        'name': configuration_name})
+    xccl.AppendProperty('buildConfigurations', xcbc)
+  xccl.SetProperty('defaultConfigurationName', configuration_names[0])
+  return xccl
+
+
+class XcodeProject(object):
+  def __init__(self, gyp_path, path, build_file_dict):
+    self.gyp_path = gyp_path
+    self.path = path
+    self.project = gyp.xcodeproj_file.PBXProject(path=path)
+    projectDirPath = gyp.common.RelativePath(
+                         os.path.dirname(os.path.abspath(self.gyp_path)),
+                         os.path.dirname(path) or '.')
+    self.project.SetProperty('projectDirPath', projectDirPath)
+    self.project_file = \
+        gyp.xcodeproj_file.XCProjectFile({'rootObject': self.project})
+    self.build_file_dict = build_file_dict
+
+    # TODO(mark): add destructor that cleans up self.path if created_dir is
+    # True and things didn't complete successfully.  Or do something even
+    # better with "try"?
+    self.created_dir = False
+    try:
+      os.makedirs(self.path)
+      self.created_dir = True
+    except OSError, e:
+      if e.errno != errno.EEXIST:
+        raise
+
+  def Finalize1(self, xcode_targets, serialize_all_tests):
+    # Collect a list of all of the build configuration names used by the
+    # various targets in the file.  It is very heavily advised to keep each
+    # target in an entire project (even across multiple project files) using
+    # the same set of configuration names.
+    configurations = []
+    for xct in self.project.GetProperty('targets'):
+      xccl = xct.GetProperty('buildConfigurationList')
+      xcbcs = xccl.GetProperty('buildConfigurations')
+      for xcbc in xcbcs:
+        name = xcbc.GetProperty('name')
+        if name not in configurations:
+          configurations.append(name)
+
+    # Replace the XCConfigurationList attached to the PBXProject object with
+    # a new one specifying all of the configuration names used by the various
+    # targets.
+    try:
+      xccl = CreateXCConfigurationList(configurations)
+      self.project.SetProperty('buildConfigurationList', xccl)
+    except:
+      sys.stderr.write("Problem with gyp file %s\n" % self.gyp_path)
+      raise
+
+    # The need for this setting is explained above where _intermediate_var is
+    # defined.  The comments below about wanting to avoid project-wide build
+    # settings apply here too, but this needs to be set on a project-wide basis
+    # so that files relative to the _intermediate_var setting can be displayed
+    # properly in the Xcode UI.
+    #
+    # Note that for configuration-relative files such as anything relative to
+    # _intermediate_var, for the purposes of UI tree view display, Xcode will
+    # only resolve the configuration name once, when the project file is
+    # opened.  If the active build configuration is changed, the project file
+    # must be closed and reopened if it is desired for the tree view to update.
+    # This is filed as Apple radar 6588391.
+    xccl.SetBuildSetting(_intermediate_var,
+                         '$(PROJECT_DERIVED_FILE_DIR)/$(CONFIGURATION)')
+    xccl.SetBuildSetting(_shared_intermediate_var,
+                         '$(SYMROOT)/DerivedSources/$(CONFIGURATION)')
+
+    # Set user-specified project-wide build settings and config files.  This
+    # is intended to be used very sparingly.  Really, almost everything should
+    # go into target-specific build settings sections.  The project-wide
+    # settings are only intended to be used in cases where Xcode attempts to
+    # resolve variable references in a project context as opposed to a target
+    # context, such as when resolving sourceTree references while building up
+    # the tree tree view for UI display.
+    # Any values set globally are applied to all configurations, then any
+    # per-configuration values are applied.
+    for xck, xcv in self.build_file_dict.get('xcode_settings', {}).iteritems():
+      xccl.SetBuildSetting(xck, xcv)
+    if 'xcode_config_file' in self.build_file_dict:
+      config_ref = self.project.AddOrGetFileInRootGroup(
+          self.build_file_dict['xcode_config_file'])
+      xccl.SetBaseConfiguration(config_ref)
+    build_file_configurations = self.build_file_dict.get('configurations', {})
+    if build_file_configurations:
+      for config_name in configurations:
+        build_file_configuration_named = \
+            build_file_configurations.get(config_name, {})
+        if build_file_configuration_named:
+          xcc = xccl.ConfigurationNamed(config_name)
+          for xck, xcv in build_file_configuration_named.get('xcode_settings',
+                                                             {}).iteritems():
+            xcc.SetBuildSetting(xck, xcv)
+          if 'xcode_config_file' in build_file_configuration_named:
+            config_ref = self.project.AddOrGetFileInRootGroup(
+                build_file_configurations[config_name]['xcode_config_file'])
+            xcc.SetBaseConfiguration(config_ref)
+
+    # Sort the targets based on how they appeared in the input.
+    # TODO(mark): Like a lot of other things here, this assumes internal
+    # knowledge of PBXProject - in this case, of its "targets" property.
+
+    # ordinary_targets are ordinary targets that are already in the project
+    # file. run_test_targets are the targets that run unittests and should be
+    # used for the Run All Tests target.  support_targets are the action/rule
+    # targets used by GYP file targets, just kept for the assert check.
+    ordinary_targets = []
+    run_test_targets = []
+    support_targets = []
+
+    # targets is full list of targets in the project.
+    targets = []
+
+    # does the it define it's own "all"?
+    has_custom_all = False
+
+    # targets_for_all is the list of ordinary_targets that should be listed
+    # in this project's "All" target.  It includes each non_runtest_target
+    # that does not have suppress_wildcard set.
+    targets_for_all = []
+
+    for target in self.build_file_dict['targets']:
+      target_name = target['target_name']
+      toolset = target['toolset']
+      qualified_target = gyp.common.QualifiedTarget(self.gyp_path, target_name,
+                                                    toolset)
+      xcode_target = xcode_targets[qualified_target]
+      # Make sure that the target being added to the sorted list is already in
+      # the unsorted list.
+      assert xcode_target in self.project._properties['targets']
+      targets.append(xcode_target)
+      ordinary_targets.append(xcode_target)
+      if xcode_target.support_target:
+        support_targets.append(xcode_target.support_target)
+        targets.append(xcode_target.support_target)
+
+      if not int(target.get('suppress_wildcard', False)):
+        targets_for_all.append(xcode_target)
+
+      if target_name.lower() == 'all':
+        has_custom_all = True;
+
+      # If this target has a 'run_as' attribute, add its target to the
+      # targets, and add it to the test targets.
+      if target.get('run_as'):
+        # Make a target to run something.  It should have one
+        # dependency, the parent xcode target.
+        xccl = CreateXCConfigurationList(configurations)
+        run_target = gyp.xcodeproj_file.PBXAggregateTarget({
+              'name':                   'Run ' + target_name,
+              'productName':            xcode_target.GetProperty('productName'),
+              'buildConfigurationList': xccl,
+            },
+            parent=self.project)
+        run_target.AddDependency(xcode_target)
+
+        command = target['run_as']
+        script = ''
+        if command.get('working_directory'):
+          script = script + 'cd "%s"\n' % \
+                   gyp.xcodeproj_file.ConvertVariablesToShellSyntax(
+                       command.get('working_directory'))
+
+        if command.get('environment'):
+          script = script + "\n".join(
+            ['export %s="%s"' %
+             (key, gyp.xcodeproj_file.ConvertVariablesToShellSyntax(val))
+             for (key, val) in command.get('environment').iteritems()]) + "\n"
+
+        # Some test end up using sockets, files on disk, etc. and can get
+        # confused if more then one test runs at a time.  The generator
+        # flag 'xcode_serialize_all_test_runs' controls the forcing of all
+        # tests serially.  It defaults to True.  To get serial runs this
+        # little bit of python does the same as the linux flock utility to
+        # make sure only one runs at a time.
+        command_prefix = ''
+        if serialize_all_tests:
+          command_prefix = \
+"""python -c "import fcntl, subprocess, sys
+file = open('$TMPDIR/GYP_serialize_test_runs', 'a')
+fcntl.flock(file.fileno(), fcntl.LOCK_EX)
+sys.exit(subprocess.call(sys.argv[1:]))" """
+
+        # If we were unable to exec for some reason, we want to exit
+        # with an error, and fixup variable references to be shell
+        # syntax instead of xcode syntax.
+        script = script + 'exec ' + command_prefix + '%s\nexit 1\n' % \
+                 gyp.xcodeproj_file.ConvertVariablesToShellSyntax(
+                     gyp.common.EncodePOSIXShellList(command.get('action')))
+
+        ssbp = gyp.xcodeproj_file.PBXShellScriptBuildPhase({
+              'shellScript':      script,
+              'showEnvVarsInLog': 0,
+            })
+        run_target.AppendProperty('buildPhases', ssbp)
+
+        # Add the run target to the project file.
+        targets.append(run_target)
+        run_test_targets.append(run_target)
+        xcode_target.test_runner = run_target
+
+
+    # Make sure that the list of targets being replaced is the same length as
+    # the one replacing it, but allow for the added test runner targets.
+    assert len(self.project._properties['targets']) == \
+      len(ordinary_targets) + len(support_targets)
+
+    self.project._properties['targets'] = targets
+
+    # Get rid of unnecessary levels of depth in groups like the Source group.
+    self.project.RootGroupsTakeOverOnlyChildren(True)
+
+    # Sort the groups nicely.  Do this after sorting the targets, because the
+    # Products group is sorted based on the order of the targets.
+    self.project.SortGroups()
+
+    # Create an "All" target if there's more than one target in this project
+    # file and the project didn't define its own "All" target.  Put a generated
+    # "All" target first so that people opening up the project for the first
+    # time will build everything by default.
+    if len(targets_for_all) > 1 and not has_custom_all:
+      xccl = CreateXCConfigurationList(configurations)
+      all_target = gyp.xcodeproj_file.PBXAggregateTarget(
+          {
+            'buildConfigurationList': xccl,
+            'name':                   'All',
+          },
+          parent=self.project)
+
+      for target in targets_for_all:
+        all_target.AddDependency(target)
+
+      # TODO(mark): This is evil because it relies on internal knowledge of
+      # PBXProject._properties.  It's important to get the "All" target first,
+      # though.
+      self.project._properties['targets'].insert(0, all_target)
+
+    # The same, but for run_test_targets.
+    if len(run_test_targets) > 1:
+      xccl = CreateXCConfigurationList(configurations)
+      run_all_tests_target = gyp.xcodeproj_file.PBXAggregateTarget(
+          {
+            'buildConfigurationList': xccl,
+            'name':                   'Run All Tests',
+          },
+          parent=self.project)
+      for run_test_target in run_test_targets:
+        run_all_tests_target.AddDependency(run_test_target)
+
+      # Insert after the "All" target, which must exist if there is more than
+      # one run_test_target.
+      self.project._properties['targets'].insert(1, run_all_tests_target)
+
+  def Finalize2(self, xcode_targets, xcode_target_to_target_dict):
+    # Finalize2 needs to happen in a separate step because the process of
+    # updating references to other projects depends on the ordering of targets
+    # within remote project files.  Finalize1 is responsible for sorting duty,
+    # and once all project files are sorted, Finalize2 can come in and update
+    # these references.
+
+    # To support making a "test runner" target that will run all the tests
+    # that are direct dependents of any given target, we look for
+    # xcode_create_dependents_test_runner being set on an Aggregate target,
+    # and generate a second target that will run the tests runners found under
+    # the marked target.
+    for bf_tgt in self.build_file_dict['targets']:
+      if int(bf_tgt.get('xcode_create_dependents_test_runner', 0)):
+        tgt_name = bf_tgt['target_name']
+        toolset = bf_tgt['toolset']
+        qualified_target = gyp.common.QualifiedTarget(self.gyp_path,
+                                                      tgt_name, toolset)
+        xcode_target = xcode_targets[qualified_target]
+        if isinstance(xcode_target, gyp.xcodeproj_file.PBXAggregateTarget):
+          # Collect all the run test targets.
+          all_run_tests = []
+          pbxtds = xcode_target.GetProperty('dependencies')
+          for pbxtd in pbxtds:
+            pbxcip = pbxtd.GetProperty('targetProxy')
+            dependency_xct = pbxcip.GetProperty('remoteGlobalIDString')
+            if hasattr(dependency_xct, 'test_runner'):
+              all_run_tests.append(dependency_xct.test_runner)
+
+          # Directly depend on all the runners as they depend on the target
+          # that builds them.
+          if len(all_run_tests) > 0:
+            run_all_target = gyp.xcodeproj_file.PBXAggregateTarget({
+                  'name':        'Run %s Tests' % tgt_name,
+                  'productName': tgt_name,
+                },
+                parent=self.project)
+            for run_test_target in all_run_tests:
+              run_all_target.AddDependency(run_test_target)
+
+            # Insert the test runner after the related target.
+            idx = self.project._properties['targets'].index(xcode_target)
+            self.project._properties['targets'].insert(idx + 1, run_all_target)
+
+    # Update all references to other projects, to make sure that the lists of
+    # remote products are complete.  Otherwise, Xcode will fill them in when
+    # it opens the project file, which will result in unnecessary diffs.
+    # TODO(mark): This is evil because it relies on internal knowledge of
+    # PBXProject._other_pbxprojects.
+    for other_pbxproject in self.project._other_pbxprojects.keys():
+      self.project.AddOrGetProjectReference(other_pbxproject)
+
+    self.project.SortRemoteProductReferences()
+
+    # Give everything an ID.
+    self.project_file.ComputeIDs()
+
+    # Make sure that no two objects in the project file have the same ID.  If
+    # multiple objects wind up with the same ID, upon loading the file, Xcode
+    # will only recognize one object (the last one in the file?) and the
+    # results are unpredictable.
+    self.project_file.EnsureNoIDCollisions()
+
+  def Write(self):
+    # Write the project file to a temporary location first.  Xcode watches for
+    # changes to the project file and presents a UI sheet offering to reload
+    # the project when it does change.  However, in some cases, especially when
+    # multiple projects are open or when Xcode is busy, things don't work so
+    # seamlessly.  Sometimes, Xcode is able to detect that a project file has
+    # changed but can't unload it because something else is referencing it.
+    # To mitigate this problem, and to avoid even having Xcode present the UI
+    # sheet when an open project is rewritten for inconsequential changes, the
+    # project file is written to a temporary file in the xcodeproj directory
+    # first.  The new temporary file is then compared to the existing project
+    # file, if any.  If they differ, the new file replaces the old; otherwise,
+    # the new project file is simply deleted.  Xcode properly detects a file
+    # being renamed over an open project file as a change and so it remains
+    # able to present the "project file changed" sheet under this system.
+    # Writing to a temporary file first also avoids the possible problem of
+    # Xcode rereading an incomplete project file.
+    (output_fd, new_pbxproj_path) = \
+        tempfile.mkstemp(suffix='.tmp', prefix='project.pbxproj.gyp.',
+                         dir=self.path)
+
+    try:
+      output_file = os.fdopen(output_fd, 'wb')
+
+      self.project_file.Print(output_file)
+      output_file.close()
+
+      pbxproj_path = os.path.join(self.path, 'project.pbxproj')
+
+      same = False
+      try:
+        same = filecmp.cmp(pbxproj_path, new_pbxproj_path, False)
+      except OSError, e:
+        if e.errno != errno.ENOENT:
+          raise
+
+      if same:
+        # The new file is identical to the old one, just get rid of the new
+        # one.
+        os.unlink(new_pbxproj_path)
+      else:
+        # The new file is different from the old one, or there is no old one.
+        # Rename the new file to the permanent name.
+        #
+        # tempfile.mkstemp uses an overly restrictive mode, resulting in a
+        # file that can only be read by the owner, regardless of the umask.
+        # There's no reason to not respect the umask here, which means that
+        # an extra hoop is required to fetch it and reset the new file's mode.
+        #
+        # No way to get the umask without setting a new one?  Set a safe one
+        # and then set it back to the old value.
+        umask = os.umask(077)
+        os.umask(umask)
+
+        os.chmod(new_pbxproj_path, 0666 & ~umask)
+        os.rename(new_pbxproj_path, pbxproj_path)
+
+    except Exception:
+      # Don't leave turds behind.  In fact, if this code was responsible for
+      # creating the xcodeproj directory, get rid of that too.
+      os.unlink(new_pbxproj_path)
+      if self.created_dir:
+        shutil.rmtree(self.path, True)
+      raise
+
+
+cached_xcode_version = None
+def InstalledXcodeVersion():
+  """Fetches the installed version of Xcode, returns empty string if it is
+  unable to figure it out."""
+
+  global cached_xcode_version
+  if not cached_xcode_version is None:
+    return cached_xcode_version
+
+  # Default to an empty string
+  cached_xcode_version = ''
+
+  # Collect the xcodebuild's version information.
+  try:
+    import subprocess
+    cmd = ['/usr/bin/xcodebuild', '-version']
+    proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
+    xcodebuild_version_info = proc.communicate()[0]
+    # Any error, return empty string
+    if proc.returncode:
+      xcodebuild_version_info = ''
+  except OSError:
+    # We failed to launch the tool
+    xcodebuild_version_info = ''
+
+  # Pull out the Xcode version itself.
+  match_line = re.search('^Xcode (.*)$', xcodebuild_version_info, re.MULTILINE)
+  if match_line:
+    cached_xcode_version = match_line.group(1)
+  # Done!
+  return cached_xcode_version
+
+
+def AddSourceToTarget(source, type, pbxp, xct):
+  # TODO(mark): Perhaps source_extensions and library_extensions can be made a
+  # little bit fancier.
+  source_extensions = ['c', 'cc', 'cpp', 'cxx', 'm', 'mm', 's']
+
+  # .o is conceptually more of a "source" than a "library," but Xcode thinks
+  # of "sources" as things to compile and "libraries" (or "frameworks") as
+  # things to link with. Adding an object file to an Xcode target's frameworks
+  # phase works properly.
+  library_extensions = ['a', 'dylib', 'framework', 'o']
+
+  basename = posixpath.basename(source)
+  (root, ext) = posixpath.splitext(basename)
+  if ext:
+    ext = ext[1:].lower()
+
+  if ext in source_extensions and type != 'none':
+    xct.SourcesPhase().AddFile(source)
+  elif ext in library_extensions and type != 'none':
+    xct.FrameworksPhase().AddFile(source)
+  else:
+    # Files that aren't added to a sources or frameworks build phase can still
+    # go into the project file, just not as part of a build phase.
+    pbxp.AddOrGetFileInRootGroup(source)
+
+
+def AddResourceToTarget(resource, pbxp, xct):
+  # TODO(mark): Combine with AddSourceToTarget above?  Or just inline this call
+  # where it's used.
+  xct.ResourcesPhase().AddFile(resource)
+
+
+def AddHeaderToTarget(header, pbxp, xct, is_public):
+  # TODO(mark): Combine with AddSourceToTarget above?  Or just inline this call
+  # where it's used.
+  settings = '{ATTRIBUTES = (%s, ); }' % ('Private', 'Public')[is_public]
+  xct.HeadersPhase().AddFile(header, settings)
+
+
+_xcode_variable_re = re.compile('(\$\((.*?)\))')
+def ExpandXcodeVariables(string, expansions):
+  """Expands Xcode-style $(VARIABLES) in string per the expansions dict.
+
+  In some rare cases, it is appropriate to expand Xcode variables when a
+  project file is generated.  For any substring $(VAR) in string, if VAR is a
+  key in the expansions dict, $(VAR) will be replaced with expansions[VAR].
+  Any $(VAR) substring in string for which VAR is not a key in the expansions
+  dict will remain in the returned string.
+  """
+
+  matches = _xcode_variable_re.findall(string)
+  if matches == None:
+    return string
+
+  matches.reverse()
+  for match in matches:
+    (to_replace, variable) = match
+    if not variable in expansions:
+      continue
+
+    replacement = expansions[variable]
+    string = re.sub(re.escape(to_replace), replacement, string)
+
+  return string
+
+
+def EscapeXCodeArgument(s):
+  """We must escape the arguments that we give to XCode so that it knows not to
+     split on spaces and to respect backslash and quote literals."""
+  s = s.replace('\\', '\\\\')
+  s = s.replace('"', '\\"')
+  return '"' + s + '"'
+
+
+
+def PerformBuild(data, configurations, params):
+  options = params['options']
+
+  for build_file, build_file_dict in data.iteritems():
+    (build_file_root, build_file_ext) = os.path.splitext(build_file)
+    if build_file_ext != '.gyp':
+      continue
+    xcodeproj_path = build_file_root + options.suffix + '.xcodeproj'
+    if options.generator_output:
+      xcodeproj_path = os.path.join(options.generator_output, xcodeproj_path)
+
+  for config in configurations:
+    arguments = ['xcodebuild', '-project', xcodeproj_path]
+    arguments += ['-configuration', config]
+    print "Building [%s]: %s" % (config, arguments)
+    subprocess.check_call(arguments)
+
+
+def GenerateOutput(target_list, target_dicts, data, params):
+  options = params['options']
+  generator_flags = params.get('generator_flags', {})
+  parallel_builds = generator_flags.get('xcode_parallel_builds', True)
+  serialize_all_tests = \
+      generator_flags.get('xcode_serialize_all_test_runs', True)
+  project_version = generator_flags.get('xcode_project_version', None)
+  skip_excluded_files = \
+      not generator_flags.get('xcode_list_excluded_files', True)
+  xcode_projects = {}
+  for build_file, build_file_dict in data.iteritems():
+    (build_file_root, build_file_ext) = os.path.splitext(build_file)
+    if build_file_ext != '.gyp':
+      continue
+    xcodeproj_path = build_file_root + options.suffix + '.xcodeproj'
+    if options.generator_output:
+      xcodeproj_path = os.path.join(options.generator_output, xcodeproj_path)
+    xcp = XcodeProject(build_file, xcodeproj_path, build_file_dict)
+    xcode_projects[build_file] = xcp
+    pbxp = xcp.project
+
+    if parallel_builds:
+      pbxp.SetProperty('attributes',
+                       {'BuildIndependentTargetsInParallel': 'YES'})
+    if project_version:
+      xcp.project_file.SetXcodeVersion(project_version)
+
+    # Add gyp/gypi files to project
+    if not generator_flags.get('standalone'):
+      main_group = pbxp.GetProperty('mainGroup')
+      build_group = gyp.xcodeproj_file.PBXGroup({'name': 'Build'})
+      main_group.AppendChild(build_group)
+      for included_file in build_file_dict['included_files']:
+        build_group.AddOrGetFileByPath(included_file, False)
+
+  xcode_targets = {}
+  xcode_target_to_target_dict = {}
+  for qualified_target in target_list:
+    [build_file, target_name, toolset] = \
+        gyp.common.ParseQualifiedTarget(qualified_target)
+
+    spec = target_dicts[qualified_target]
+    if spec['toolset'] != 'target':
+      raise Exception(
+          'Multiple toolsets not supported in xcode build (target %s)' %
+          qualified_target)
+    configuration_names = [spec['default_configuration']]
+    for configuration_name in sorted(spec['configurations'].keys()):
+      if configuration_name not in configuration_names:
+        configuration_names.append(configuration_name)
+    xcp = xcode_projects[build_file]
+    pbxp = xcp.project
+
+    # Set up the configurations for the target according to the list of names
+    # supplied.
+    xccl = CreateXCConfigurationList(configuration_names)
+
+    # Create an XCTarget subclass object for the target. The type with
+    # "+bundle" appended will be used if the target has "mac_bundle" set.
+    # loadable_modules not in a mac_bundle are mapped to
+    # com.googlecode.gyp.xcode.bundle, a pseudo-type that xcode.py interprets
+    # to create a single-file mh_bundle.
+    _types = {
+      'executable':             'com.apple.product-type.tool',
+      'loadable_module':        'com.googlecode.gyp.xcode.bundle',
+      'shared_library':         'com.apple.product-type.library.dynamic',
+      'static_library':         'com.apple.product-type.library.static',
+      'executable+bundle':      'com.apple.product-type.application',
+      'loadable_module+bundle': 'com.apple.product-type.bundle',
+      'shared_library+bundle':  'com.apple.product-type.framework',
+    }
+
+    target_properties = {
+      'buildConfigurationList': xccl,
+      'name':                   target_name,
+    }
+
+    type = spec['type']
+    is_bundle = int(spec.get('mac_bundle', 0))
+    if type != 'none':
+      type_bundle_key = type
+      if is_bundle:
+        type_bundle_key += '+bundle'
+      xctarget_type = gyp.xcodeproj_file.PBXNativeTarget
+      try:
+        target_properties['productType'] = _types[type_bundle_key]
+      except KeyError, e:
+        gyp.common.ExceptionAppend(e, "-- unknown product type while "
+                                   "writing target %s" % target_name)
+        raise
+    else:
+      xctarget_type = gyp.xcodeproj_file.PBXAggregateTarget
+      assert not is_bundle, (
+          'mac_bundle targets cannot have type none (target "%s")' %
+          target_name)
+
+    target_product_name = spec.get('product_name')
+    if target_product_name is not None:
+      target_properties['productName'] = target_product_name
+
+    xct = xctarget_type(target_properties, parent=pbxp,
+                        force_outdir=spec.get('product_dir'),
+                        force_prefix=spec.get('product_prefix'),
+                        force_extension=spec.get('product_extension'))
+    pbxp.AppendProperty('targets', xct)
+    xcode_targets[qualified_target] = xct
+    xcode_target_to_target_dict[xct] = spec
+
+    spec_actions = spec.get('actions', [])
+    spec_rules = spec.get('rules', [])
+
+    # Xcode has some "issues" with checking dependencies for the "Compile
+    # sources" step with any source files/headers generated by actions/rules.
+    # To work around this, if a target is building anything directly (not
+    # type "none"), then a second target is used to run the GYP actions/rules
+    # and is made a dependency of this target.  This way the work is done
+    # before the dependency checks for what should be recompiled.
+    support_xct = None
+    if type != 'none' and (spec_actions or spec_rules):
+      support_xccl = CreateXCConfigurationList(configuration_names);
+      support_target_properties = {
+        'buildConfigurationList': support_xccl,
+        'name':                   target_name + ' Support',
+      }
+      if target_product_name:
+        support_target_properties['productName'] = \
+            target_product_name + ' Support'
+      support_xct = \
+          gyp.xcodeproj_file.PBXAggregateTarget(support_target_properties,
+                                                parent=pbxp)
+      pbxp.AppendProperty('targets', support_xct)
+      xct.AddDependency(support_xct)
+    # Hang the support target off the main target so it can be tested/found
+    # by the generator during Finalize.
+    xct.support_target = support_xct
+
+    prebuild_index = 0
+
+    # Add custom shell script phases for "actions" sections.
+    for action in spec_actions:
+      # There's no need to write anything into the script to ensure that the
+      # output directories already exist, because Xcode will look at the
+      # declared outputs and automatically ensure that they exist for us.
+
+      # Do we have a message to print when this action runs?
+      message = action.get('message')
+      if message:
+        message = 'echo note: ' + gyp.common.EncodePOSIXShellArgument(message)
+      else:
+        message = ''
+
+      # Turn the list into a string that can be passed to a shell.
+      action_string = gyp.common.EncodePOSIXShellList(action['action'])
+
+      # Convert Xcode-type variable references to sh-compatible environment
+      # variable references.
+      message_sh = gyp.xcodeproj_file.ConvertVariablesToShellSyntax(message)
+      action_string_sh = gyp.xcodeproj_file.ConvertVariablesToShellSyntax(
+        action_string)
+
+      script = ''
+      # Include the optional message
+      if message_sh:
+        script += message_sh + '\n'
+      # Be sure the script runs in exec, and that if exec fails, the script
+      # exits signalling an error.
+      script += 'exec ' + action_string_sh + '\nexit 1\n'
+      ssbp = gyp.xcodeproj_file.PBXShellScriptBuildPhase({
+            'inputPaths': action['inputs'],
+            'name': 'Action "' + action['action_name'] + '"',
+            'outputPaths': action['outputs'],
+            'shellScript': script,
+            'showEnvVarsInLog': 0,
+          })
+
+      if support_xct:
+        support_xct.AppendProperty('buildPhases', ssbp)
+      else:
+        # TODO(mark): this assumes too much knowledge of the internals of
+        # xcodeproj_file; some of these smarts should move into xcodeproj_file
+        # itself.
+        xct._properties['buildPhases'].insert(prebuild_index, ssbp)
+        prebuild_index = prebuild_index + 1
+
+      # TODO(mark): Should verify that at most one of these is specified.
+      if int(action.get('process_outputs_as_sources', False)):
+        for output in action['outputs']:
+          AddSourceToTarget(output, type, pbxp, xct)
+
+      if int(action.get('process_outputs_as_mac_bundle_resources', False)):
+        for output in action['outputs']:
+          AddResourceToTarget(output, pbxp, xct)
+
+    # tgt_mac_bundle_resources holds the list of bundle resources so
+    # the rule processing can check against it.
+    if is_bundle:
+      tgt_mac_bundle_resources = spec.get('mac_bundle_resources', [])
+    else:
+      tgt_mac_bundle_resources = []
+
+    # Add custom shell script phases driving "make" for "rules" sections.
+    #
+    # Xcode's built-in rule support is almost powerful enough to use directly,
+    # but there are a few significant deficiencies that render them unusable.
+    # There are workarounds for some of its inadequacies, but in aggregate,
+    # the workarounds added complexity to the generator, and some workarounds
+    # actually require input files to be crafted more carefully than I'd like.
+    # Consequently, until Xcode rules are made more capable, "rules" input
+    # sections will be handled in Xcode output by shell script build phases
+    # performed prior to the compilation phase.
+    #
+    # The following problems with Xcode rules were found.  The numbers are
+    # Apple radar IDs.  I hope that these shortcomings are addressed, I really
+    # liked having the rules handled directly in Xcode during the period that
+    # I was prototyping this.
+    #
+    # 6588600 Xcode compiles custom script rule outputs too soon, compilation
+    #         fails.  This occurs when rule outputs from distinct inputs are
+    #         interdependent.  The only workaround is to put rules and their
+    #         inputs in a separate target from the one that compiles the rule
+    #         outputs.  This requires input file cooperation and it means that
+    #         process_outputs_as_sources is unusable.
+    # 6584932 Need to declare that custom rule outputs should be excluded from
+    #         compilation.  A possible workaround is to lie to Xcode about a
+    #         rule's output, giving it a dummy file it doesn't know how to
+    #         compile.  The rule action script would need to touch the dummy.
+    # 6584839 I need a way to declare additional inputs to a custom rule.
+    #         A possible workaround is a shell script phase prior to
+    #         compilation that touches a rule's primary input files if any
+    #         would-be additional inputs are newer than the output.  Modifying
+    #         the source tree - even just modification times - feels dirty.
+    # 6564240 Xcode "custom script" build rules always dump all environment
+    #         variables.  This is a low-prioroty problem and is not a
+    #         show-stopper.
+    rules_by_ext = {}
+    for rule in spec_rules:
+      rules_by_ext[rule['extension']] = rule
+
+      # First, some definitions:
+      #
+      # A "rule source" is a file that was listed in a target's "sources"
+      # list and will have a rule applied to it on the basis of matching the
+      # rule's "extensions" attribute.  Rule sources are direct inputs to
+      # rules.
+      #
+      # Rule definitions may specify additional inputs in their "inputs"
+      # attribute.  These additional inputs are used for dependency tracking
+      # purposes.
+      #
+      # A "concrete output" is a rule output with input-dependent variables
+      # resolved.  For example, given a rule with:
+      #   'extension': 'ext', 'outputs': ['$(INPUT_FILE_BASE).cc'],
+      # if the target's "sources" list contained "one.ext" and "two.ext",
+      # the "concrete output" for rule input "two.ext" would be "two.cc".  If
+      # a rule specifies multiple outputs, each input file that the rule is
+      # applied to will have the same number of concrete outputs.
+      #
+      # If any concrete outputs are outdated or missing relative to their
+      # corresponding rule_source or to any specified additional input, the
+      # rule action must be performed to generate the concrete outputs.
+
+      # concrete_outputs_by_rule_source will have an item at the same index
+      # as the rule['rule_sources'] that it corresponds to.  Each item is a
+      # list of all of the concrete outputs for the rule_source.
+      concrete_outputs_by_rule_source = []
+
+      # concrete_outputs_all is a flat list of all concrete outputs that this
+      # rule is able to produce, given the known set of input files
+      # (rule_sources) that apply to it.
+      concrete_outputs_all = []
+
+      # messages & actions are keyed by the same indices as rule['rule_sources']
+      # and concrete_outputs_by_rule_source.  They contain the message and
+      # action to perform after resolving input-dependent variables.  The
+      # message is optional, in which case None is stored for each rule source.
+      messages = []
+      actions = []
+
+      for rule_source in rule.get('rule_sources', []):
+        rule_source_dirname, rule_source_basename = \
+            posixpath.split(rule_source)
+        (rule_source_root, rule_source_ext) = \
+            posixpath.splitext(rule_source_basename)
+
+        # These are the same variable names that Xcode uses for its own native
+        # rule support.  Because Xcode's rule engine is not being used, they
+        # need to be expanded as they are written to the makefile.
+        rule_input_dict = {
+          'INPUT_FILE_BASE':   rule_source_root,
+          'INPUT_FILE_SUFFIX': rule_source_ext,
+          'INPUT_FILE_NAME':   rule_source_basename,
+          'INPUT_FILE_PATH':   rule_source,
+          'INPUT_FILE_DIRNAME': rule_source_dirname,
+        }
+
+        concrete_outputs_for_this_rule_source = []
+        for output in rule.get('outputs', []):
+          # Fortunately, Xcode and make both use $(VAR) format for their
+          # variables, so the expansion is the only transformation necessary.
+          # Any remaning $(VAR)-type variables in the string can be given
+          # directly to make, which will pick up the correct settings from
+          # what Xcode puts into the environment.
+          concrete_output = ExpandXcodeVariables(output, rule_input_dict)
+          concrete_outputs_for_this_rule_source.append(concrete_output)
+
+          # Add all concrete outputs to the project.
+          pbxp.AddOrGetFileInRootGroup(concrete_output)
+
+        concrete_outputs_by_rule_source.append( \
+            concrete_outputs_for_this_rule_source)
+        concrete_outputs_all.extend(concrete_outputs_for_this_rule_source)
+
+        # TODO(mark): Should verify that at most one of these is specified.
+        if int(rule.get('process_outputs_as_sources', False)):
+          for output in concrete_outputs_for_this_rule_source:
+            AddSourceToTarget(output, type, pbxp, xct)
+
+        # If the file came from the mac_bundle_resources list or if the rule
+        # is marked to process outputs as bundle resource, do so.
+        was_mac_bundle_resource = rule_source in tgt_mac_bundle_resources
+        if was_mac_bundle_resource or \
+            int(rule.get('process_outputs_as_mac_bundle_resources', False)):
+          for output in concrete_outputs_for_this_rule_source:
+            AddResourceToTarget(output, pbxp, xct)
+
+        # Do we have a message to print when this rule runs?
+        message = rule.get('message')
+        if message:
+          message = gyp.common.EncodePOSIXShellArgument(message)
+          message = ExpandXcodeVariables(message, rule_input_dict)
+        messages.append(message)
+
+        # Turn the list into a string that can be passed to a shell.
+        action_string = gyp.common.EncodePOSIXShellList(rule['action'])
+
+        action = ExpandXcodeVariables(action_string, rule_input_dict)
+        actions.append(action)
+
+      if len(concrete_outputs_all) > 0:
+        # TODO(mark): There's a possibilty for collision here.  Consider
+        # target "t" rule "A_r" and target "t_A" rule "r".
+        makefile_name = '%s.make' % re.sub(
+            '[^a-zA-Z0-9_]', '_' , '%s_%s' % (target_name, rule['rule_name']))
+        makefile_path = os.path.join(xcode_projects[build_file].path,
+                                     makefile_name)
+        # TODO(mark): try/close?  Write to a temporary file and swap it only
+        # if it's got changes?
+        makefile = open(makefile_path, 'wb')
+
+        # make will build the first target in the makefile by default.  By
+        # convention, it's called "all".  List all (or at least one)
+        # concrete output for each rule source as a prerequisite of the "all"
+        # target.
+        makefile.write('all: \\\n')
+        for concrete_output_index in \
+            xrange(0, len(concrete_outputs_by_rule_source)):
+          # Only list the first (index [0]) concrete output of each input
+          # in the "all" target.  Otherwise, a parallel make (-j > 1) would
+          # attempt to process each input multiple times simultaneously.
+          # Otherwise, "all" could just contain the entire list of
+          # concrete_outputs_all.
+          concrete_output = \
+              concrete_outputs_by_rule_source[concrete_output_index][0]
+          if concrete_output_index == len(concrete_outputs_by_rule_source) - 1:
+            eol = ''
+          else:
+            eol = ' \\'
+          makefile.write('    %s%s\n' % (concrete_output, eol))
+
+        for (rule_source, concrete_outputs, message, action) in \
+            zip(rule['rule_sources'], concrete_outputs_by_rule_source,
+                messages, actions):
+          makefile.write('\n')
+
+          # Add a rule that declares it can build each concrete output of a
+          # rule source.  Collect the names of the directories that are
+          # required.
+          concrete_output_dirs = []
+          for concrete_output_index in xrange(0, len(concrete_outputs)):
+            concrete_output = concrete_outputs[concrete_output_index]
+            if concrete_output_index == 0:
+              bol = ''
+            else:
+              bol = '    '
+            makefile.write('%s%s \\\n' % (bol, concrete_output))
+
+            concrete_output_dir = posixpath.dirname(concrete_output)
+            if (concrete_output_dir and
+                concrete_output_dir not in concrete_output_dirs):
+              concrete_output_dirs.append(concrete_output_dir)
+
+          makefile.write('    : \\\n')
+
+          # The prerequisites for this rule are the rule source itself and
+          # the set of additional rule inputs, if any.
+          prerequisites = [rule_source]
+          prerequisites.extend(rule.get('inputs', []))
+          for prerequisite_index in xrange(0, len(prerequisites)):
+            prerequisite = prerequisites[prerequisite_index]
+            if prerequisite_index == len(prerequisites) - 1:
+              eol = ''
+            else:
+              eol = ' \\'
+            makefile.write('    %s%s\n' % (prerequisite, eol))
+
+          # Make sure that output directories exist before executing the rule
+          # action.
+          if len(concrete_output_dirs) > 0:
+            makefile.write('\t@mkdir -p "%s"\n' %
+                           '" "'.join(concrete_output_dirs))
+
+          # The rule message and action have already had the necessary variable
+          # substitutions performed.
+          if message:
+            # Mark it with note: so Xcode picks it up in build output.
+            makefile.write('\t@echo note: %s\n' % message)
+          makefile.write('\t%s\n' % action)
+
+        makefile.close()
+
+        # It might be nice to ensure that needed output directories exist
+        # here rather than in each target in the Makefile, but that wouldn't
+        # work if there ever was a concrete output that had an input-dependent
+        # variable anywhere other than in the leaf position.
+
+        # Don't declare any inputPaths or outputPaths.  If they're present,
+        # Xcode will provide a slight optimization by only running the script
+        # phase if any output is missing or outdated relative to any input.
+        # Unfortunately, it will also assume that all outputs are touched by
+        # the script, and if the outputs serve as files in a compilation
+        # phase, they will be unconditionally rebuilt.  Since make might not
+        # rebuild everything that could be declared here as an output, this
+        # extra compilation activity is unnecessary.  With inputPaths and
+        # outputPaths not supplied, make will always be called, but it knows
+        # enough to not do anything when everything is up-to-date.
+
+        # To help speed things up, pass -j COUNT to make so it does some work
+        # in parallel.  Don't use ncpus because Xcode will build ncpus targets
+        # in parallel and if each target happens to have a rules step, there
+        # would be ncpus^2 things going.  With a machine that has 2 quad-core
+        # Xeons, a build can quickly run out of processes based on
+        # scheduling/other tasks, and randomly failing builds are no good.
+        script = \
+"""JOB_COUNT="$(/usr/sbin/sysctl -n hw.ncpu)"
+if [ "${JOB_COUNT}" -gt 4 ]; then
+  JOB_COUNT=4
+fi
+exec "${DEVELOPER_BIN_DIR}/make" -f "${PROJECT_FILE_PATH}/%s" -j "${JOB_COUNT}"
+exit 1
+""" % makefile_name
+        ssbp = gyp.xcodeproj_file.PBXShellScriptBuildPhase({
+              'name': 'Rule "' + rule['rule_name'] + '"',
+              'shellScript': script,
+              'showEnvVarsInLog': 0,
+            })
+
+        if support_xct:
+          support_xct.AppendProperty('buildPhases', ssbp)
+        else:
+          # TODO(mark): this assumes too much knowledge of the internals of
+          # xcodeproj_file; some of these smarts should move into xcodeproj_file
+          # itself.
+          xct._properties['buildPhases'].insert(prebuild_index, ssbp)
+          prebuild_index = prebuild_index + 1
+
+      # Extra rule inputs also go into the project file.  Concrete outputs were
+      # already added when they were computed.
+      groups = ['inputs', 'inputs_excluded']
+      if skip_excluded_files:
+        groups = [x for x in groups if not x.endswith('_excluded')]
+      for group in groups:
+        for item in rule.get(group, []):
+          pbxp.AddOrGetFileInRootGroup(item)
+
+    # Add "sources".
+    for source in spec.get('sources', []):
+      (source_root, source_extension) = posixpath.splitext(source)
+      if source_extension[1:] not in rules_by_ext:
+        # AddSourceToTarget will add the file to a root group if it's not
+        # already there.
+        AddSourceToTarget(source, type, pbxp, xct)
+      else:
+        pbxp.AddOrGetFileInRootGroup(source)
+
+    # Add "mac_bundle_resources" and "mac_framework_private_headers" if
+    # it's a bundle of any type.
+    if is_bundle:
+      for resource in tgt_mac_bundle_resources:
+        (resource_root, resource_extension) = posixpath.splitext(resource)
+        if resource_extension[1:] not in rules_by_ext:
+          AddResourceToTarget(resource, pbxp, xct)
+        else:
+          pbxp.AddOrGetFileInRootGroup(resource)
+
+      for header in spec.get('mac_framework_private_headers', []):
+        AddHeaderToTarget(header, pbxp, xct, False)
+
+    # Add "mac_framework_headers". These can be valid for both frameworks
+    # and static libraries.
+    if is_bundle or type == 'static_library':
+      for header in spec.get('mac_framework_headers', []):
+        AddHeaderToTarget(header, pbxp, xct, True)
+
+    # Add "copies".
+    pbxcp_dict = {}
+    for copy_group in spec.get('copies', []):
+      dest = copy_group['destination']
+      if dest[0] not in ('/', '$'):
+        # Relative paths are relative to $(SRCROOT).
+        dest = '$(SRCROOT)/' + dest
+
+      # Coalesce multiple "copies" sections in the same target with the same
+      # "destination" property into the same PBXCopyFilesBuildPhase, otherwise
+      # they'll wind up with ID collisions.
+      pbxcp = pbxcp_dict.get(dest, None)
+      if pbxcp is None:
+        pbxcp = gyp.xcodeproj_file.PBXCopyFilesBuildPhase({
+              'name': 'Copy to ' + copy_group['destination']
+            },
+            parent=xct)
+        pbxcp.SetDestination(dest)
+
+        # TODO(mark): The usual comment about this knowing too much about
+        # gyp.xcodeproj_file internals applies.
+        xct._properties['buildPhases'].insert(prebuild_index, pbxcp)
+
+        pbxcp_dict[dest] = pbxcp
+
+      for file in copy_group['files']:
+        pbxcp.AddFile(file)
+
+    # Excluded files can also go into the project file.
+    if not skip_excluded_files:
+      for key in ['sources', 'mac_bundle_resources', 'mac_framework_headers',
+                  'mac_framework_private_headers']:
+        excluded_key = key + '_excluded'
+        for item in spec.get(excluded_key, []):
+          pbxp.AddOrGetFileInRootGroup(item)
+
+    # So can "inputs" and "outputs" sections of "actions" groups.
+    groups = ['inputs', 'inputs_excluded', 'outputs', 'outputs_excluded']
+    if skip_excluded_files:
+      groups = [x for x in groups if not x.endswith('_excluded')]
+    for action in spec.get('actions', []):
+      for group in groups:
+        for item in action.get(group, []):
+          # Exclude anything in BUILT_PRODUCTS_DIR.  They're products, not
+          # sources.
+          if not item.startswith('$(BUILT_PRODUCTS_DIR)/'):
+            pbxp.AddOrGetFileInRootGroup(item)
+
+    for postbuild in spec.get('postbuilds', []):
+      action_string_sh = gyp.common.EncodePOSIXShellList(postbuild['action'])
+      script = 'exec ' + action_string_sh + '\nexit 1\n'
+
+      # Make the postbuild step depend on the output of ld or ar from this
+      # target. Apparently putting the script step after the link step isn't
+      # sufficient to ensure proper ordering in all cases. With an input
+      # declared but no outputs, the script step should run every time, as
+      # desired.
+      ssbp = gyp.xcodeproj_file.PBXShellScriptBuildPhase({
+            'inputPaths': ['$(BUILT_PRODUCTS_DIR)/$(EXECUTABLE_PATH)'],
+            'name': 'Postbuild "' + postbuild['postbuild_name'] + '"',
+            'shellScript': script,
+            'showEnvVarsInLog': 0,
+          })
+      xct.AppendProperty('buildPhases', ssbp)
+
+    # Add dependencies before libraries, because adding a dependency may imply
+    # adding a library.  It's preferable to keep dependencies listed first
+    # during a link phase so that they can override symbols that would
+    # otherwise be provided by libraries, which will usually include system
+    # libraries.  On some systems, ld is finicky and even requires the
+    # libraries to be ordered in such a way that unresolved symbols in
+    # earlier-listed libraries may only be resolved by later-listed libraries.
+    # The Mac linker doesn't work that way, but other platforms do, and so
+    # their linker invocations need to be constructed in this way.  There's
+    # no compelling reason for Xcode's linker invocations to differ.
+
+    if 'dependencies' in spec:
+      for dependency in spec['dependencies']:
+        xct.AddDependency(xcode_targets[dependency])
+        # The support project also gets the dependencies (in case they are
+        # needed for the actions/rules to work).
+        if support_xct:
+          support_xct.AddDependency(xcode_targets[dependency])
+
+    if 'libraries' in spec:
+      for library in spec['libraries']:
+        xct.FrameworksPhase().AddFile(library)
+        # Add the library's directory to LIBRARY_SEARCH_PATHS if necessary.
+        # I wish Xcode handled this automatically.
+        library_dir = posixpath.dirname(library)
+        if library_dir not in xcode_standard_library_dirs and (
+            not xct.HasBuildSetting(_library_search_paths_var) or
+            library_dir not in xct.GetBuildSetting(_library_search_paths_var)):
+          xct.AppendBuildSetting(_library_search_paths_var, library_dir)
+
+    for configuration_name in configuration_names:
+      configuration = spec['configurations'][configuration_name]
+      xcbc = xct.ConfigurationNamed(configuration_name)
+      for include_dir in configuration.get('mac_framework_dirs', []):
+        xcbc.AppendBuildSetting('FRAMEWORK_SEARCH_PATHS', include_dir)
+      for include_dir in configuration.get('include_dirs', []):
+        xcbc.AppendBuildSetting('HEADER_SEARCH_PATHS', include_dir)
+      if 'defines' in configuration:
+        for define in configuration['defines']:
+          set_define = EscapeXCodeArgument(define)
+          xcbc.AppendBuildSetting('GCC_PREPROCESSOR_DEFINITIONS', set_define)
+      if 'xcode_settings' in configuration:
+        for xck, xcv in configuration['xcode_settings'].iteritems():
+          xcbc.SetBuildSetting(xck, xcv)
+      if 'xcode_config_file' in configuration:
+        config_ref = pbxp.AddOrGetFileInRootGroup(
+            configuration['xcode_config_file'])
+        xcbc.SetBaseConfiguration(config_ref)
+
+  build_files = []
+  for build_file, build_file_dict in data.iteritems():
+    if build_file.endswith('.gyp'):
+      build_files.append(build_file)
+
+  for build_file in build_files:
+    xcode_projects[build_file].Finalize1(xcode_targets, serialize_all_tests)
+
+  for build_file in build_files:
+    xcode_projects[build_file].Finalize2(xcode_targets,
+                                         xcode_target_to_target_dict)
+
+  for build_file in build_files:
+    xcode_projects[build_file].Write()
diff --git a/webWidgetTCT_device/tools/gyp/pylib/gyp/input.py b/webWidgetTCT_device/tools/gyp/pylib/gyp/input.py
new file mode 100755 (executable)
index 0000000..e419072
--- /dev/null
@@ -0,0 +1,2683 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from compiler.ast import Const
+from compiler.ast import Dict
+from compiler.ast import Discard
+from compiler.ast import List
+from compiler.ast import Module
+from compiler.ast import Node
+from compiler.ast import Stmt
+import compiler
+import copy
+import gyp.common
+import multiprocessing
+import optparse
+import os.path
+import re
+import shlex
+import signal
+import subprocess
+import sys
+import threading
+import time
+from gyp.common import GypError
+
+
+# A list of types that are treated as linkable.
+linkable_types = ['executable', 'shared_library', 'loadable_module']
+
+# A list of sections that contain links to other targets.
+dependency_sections = ['dependencies', 'export_dependent_settings']
+
+# base_path_sections is a list of sections defined by GYP that contain
+# pathnames.  The generators can provide more keys, the two lists are merged
+# into path_sections, but you should call IsPathSection instead of using either
+# list directly.
+base_path_sections = [
+  'destination',
+  'files',
+  'include_dirs',
+  'inputs',
+  'libraries',
+  'outputs',
+  'sources',
+]
+path_sections = []
+
+is_path_section_charset = set('=+?!')
+is_path_section_match_re = re.compile('_(dir|file|path)s?$')
+
+def IsPathSection(section):
+  # If section ends in one of these characters, it's applied to a section
+  # without the trailing characters.  '/' is notably absent from this list,
+  # because there's no way for a regular expression to be treated as a path.
+  while section[-1:] in is_path_section_charset:
+    section = section[:-1]
+  return section in path_sections or is_path_section_match_re.search(section)
+
+# base_non_configuraiton_keys is a list of key names that belong in the target
+# itself and should not be propagated into its configurations.  It is merged
+# with a list that can come from the generator to
+# create non_configuration_keys.
+base_non_configuration_keys = [
+  # Sections that must exist inside targets and not configurations.
+  'actions',
+  'configurations',
+  'copies',
+  'default_configuration',
+  'dependencies',
+  'dependencies_original',
+  'link_languages',
+  'libraries',
+  'postbuilds',
+  'product_dir',
+  'product_extension',
+  'product_name',
+  'product_prefix',
+  'rules',
+  'run_as',
+  'sources',
+  'standalone_static_library',
+  'suppress_wildcard',
+  'target_name',
+  'toolset',
+  'toolsets',
+  'type',
+  'variants',
+
+  # Sections that can be found inside targets or configurations, but that
+  # should not be propagated from targets into their configurations.
+  'variables',
+]
+non_configuration_keys = []
+
+# Keys that do not belong inside a configuration dictionary.
+invalid_configuration_keys = [
+  'actions',
+  'all_dependent_settings',
+  'configurations',
+  'dependencies',
+  'direct_dependent_settings',
+  'libraries',
+  'link_settings',
+  'sources',
+  'standalone_static_library',
+  'target_name',
+  'type',
+]
+
+# Controls how the generator want the build file paths.
+absolute_build_file_paths = False
+
+# Controls whether or not the generator supports multiple toolsets.
+multiple_toolsets = False
+
+
+def GetIncludedBuildFiles(build_file_path, aux_data, included=None):
+  """Return a list of all build files included into build_file_path.
+
+  The returned list will contain build_file_path as well as all other files
+  that it included, either directly or indirectly.  Note that the list may
+  contain files that were included into a conditional section that evaluated
+  to false and was not merged into build_file_path's dict.
+
+  aux_data is a dict containing a key for each build file or included build
+  file.  Those keys provide access to dicts whose "included" keys contain
+  lists of all other files included by the build file.
+
+  included should be left at its default None value by external callers.  It
+  is used for recursion.
+
+  The returned list will not contain any duplicate entries.  Each build file
+  in the list will be relative to the current directory.
+  """
+
+  if included == None:
+    included = []
+
+  if build_file_path in included:
+    return included
+
+  included.append(build_file_path)
+
+  for included_build_file in aux_data[build_file_path].get('included', []):
+    GetIncludedBuildFiles(included_build_file, aux_data, included)
+
+  return included
+
+
+def CheckedEval(file_contents):
+  """Return the eval of a gyp file.
+
+  The gyp file is restricted to dictionaries and lists only, and
+  repeated keys are not allowed.
+
+  Note that this is slower than eval() is.
+  """
+
+  ast = compiler.parse(file_contents)
+  assert isinstance(ast, Module)
+  c1 = ast.getChildren()
+  assert c1[0] is None
+  assert isinstance(c1[1], Stmt)
+  c2 = c1[1].getChildren()
+  assert isinstance(c2[0], Discard)
+  c3 = c2[0].getChildren()
+  assert len(c3) == 1
+  return CheckNode(c3[0], [])
+
+
+def CheckNode(node, keypath):
+  if isinstance(node, Dict):
+    c = node.getChildren()
+    dict = {}
+    for n in range(0, len(c), 2):
+      assert isinstance(c[n], Const)
+      key = c[n].getChildren()[0]
+      if key in dict:
+        raise GypError("Key '" + key + "' repeated at level " +
+              repr(len(keypath) + 1) + " with key path '" +
+              '.'.join(keypath) + "'")
+      kp = list(keypath)  # Make a copy of the list for descending this node.
+      kp.append(key)
+      dict[key] = CheckNode(c[n + 1], kp)
+    return dict
+  elif isinstance(node, List):
+    c = node.getChildren()
+    children = []
+    for index, child in enumerate(c):
+      kp = list(keypath)  # Copy list.
+      kp.append(repr(index))
+      children.append(CheckNode(child, kp))
+    return children
+  elif isinstance(node, Const):
+    return node.getChildren()[0]
+  else:
+    raise TypeError, "Unknown AST node at key path '" + '.'.join(keypath) + \
+         "': " + repr(node)
+
+
+def LoadOneBuildFile(build_file_path, data, aux_data, variables, includes,
+                     is_target, check):
+  if build_file_path in data:
+    return data[build_file_path]
+
+  if os.path.exists(build_file_path):
+    build_file_contents = open(build_file_path).read()
+  else:
+    raise GypError("%s not found (cwd: %s)" % (build_file_path, os.getcwd()))
+
+  build_file_data = None
+  try:
+    if check:
+      build_file_data = CheckedEval(build_file_contents)
+    else:
+      build_file_data = eval(build_file_contents, {'__builtins__': None},
+                             None)
+  except SyntaxError, e:
+    e.filename = build_file_path
+    raise
+  except Exception, e:
+    gyp.common.ExceptionAppend(e, 'while reading ' + build_file_path)
+    raise
+
+  if not isinstance(build_file_data, dict):
+    raise GypError("%s does not evaluate to a dictionary." % build_file_path)
+
+  data[build_file_path] = build_file_data
+  aux_data[build_file_path] = {}
+
+  # Scan for includes and merge them in.
+  try:
+    if is_target:
+      LoadBuildFileIncludesIntoDict(build_file_data, build_file_path, data,
+                                    aux_data, variables, includes, check)
+    else:
+      LoadBuildFileIncludesIntoDict(build_file_data, build_file_path, data,
+                                    aux_data, variables, None, check)
+  except Exception, e:
+    gyp.common.ExceptionAppend(e,
+                               'while reading includes of ' + build_file_path)
+    raise
+
+  return build_file_data
+
+
+def LoadBuildFileIncludesIntoDict(subdict, subdict_path, data, aux_data,
+                                  variables, includes, check):
+  includes_list = []
+  if includes != None:
+    includes_list.extend(includes)
+  if 'includes' in subdict:
+    for include in subdict['includes']:
+      # "include" is specified relative to subdict_path, so compute the real
+      # path to include by appending the provided "include" to the directory
+      # in which subdict_path resides.
+      relative_include = \
+          os.path.normpath(os.path.join(os.path.dirname(subdict_path), include))
+      includes_list.append(relative_include)
+    # Unhook the includes list, it's no longer needed.
+    del subdict['includes']
+
+  # Merge in the included files.
+  for include in includes_list:
+    if not 'included' in aux_data[subdict_path]:
+      aux_data[subdict_path]['included'] = []
+    aux_data[subdict_path]['included'].append(include)
+
+    gyp.DebugOutput(gyp.DEBUG_INCLUDES, "Loading Included File: '%s'", include)
+
+    MergeDicts(subdict,
+               LoadOneBuildFile(include, data, aux_data, variables, None,
+                                False, check),
+               subdict_path, include)
+
+  # Recurse into subdictionaries.
+  for k, v in subdict.iteritems():
+    if v.__class__ == dict:
+      LoadBuildFileIncludesIntoDict(v, subdict_path, data, aux_data, variables,
+                                    None, check)
+    elif v.__class__ == list:
+      LoadBuildFileIncludesIntoList(v, subdict_path, data, aux_data, variables,
+                                    check)
+
+
+# This recurses into lists so that it can look for dicts.
+def LoadBuildFileIncludesIntoList(sublist, sublist_path, data, aux_data,
+                                  variables, check):
+  for item in sublist:
+    if item.__class__ == dict:
+      LoadBuildFileIncludesIntoDict(item, sublist_path, data, aux_data,
+                                    variables, None, check)
+    elif item.__class__ == list:
+      LoadBuildFileIncludesIntoList(item, sublist_path, data, aux_data,
+                                    variables, check)
+
+# Processes toolsets in all the targets. This recurses into condition entries
+# since they can contain toolsets as well.
+def ProcessToolsetsInDict(data):
+  if 'targets' in data:
+    target_list = data['targets']
+    new_target_list = []
+    for target in target_list:
+      # If this target already has an explicit 'toolset', and no 'toolsets'
+      # list, don't modify it further.
+      if 'toolset' in target and 'toolsets' not in target:
+        new_target_list.append(target)
+        continue
+      if multiple_toolsets:
+        toolsets = target.get('toolsets', ['target'])
+      else:
+        toolsets = ['target']
+      # Make sure this 'toolsets' definition is only processed once.
+      if 'toolsets' in target:
+        del target['toolsets']
+      if len(toolsets) > 0:
+        # Optimization: only do copies if more than one toolset is specified.
+        for build in toolsets[1:]:
+          new_target = copy.deepcopy(target)
+          new_target['toolset'] = build
+          new_target_list.append(new_target)
+        target['toolset'] = toolsets[0]
+        new_target_list.append(target)
+    data['targets'] = new_target_list
+  if 'conditions' in data:
+    for condition in data['conditions']:
+      if isinstance(condition, list):
+        for condition_dict in condition[1:]:
+          ProcessToolsetsInDict(condition_dict)
+
+
+# TODO(mark): I don't love this name.  It just means that it's going to load
+# a build file that contains targets and is expected to provide a targets dict
+# that contains the targets...
+def LoadTargetBuildFile(build_file_path, data, aux_data, variables, includes,
+                        depth, check, load_dependencies):
+  # If depth is set, predefine the DEPTH variable to be a relative path from
+  # this build file's directory to the directory identified by depth.
+  if depth:
+    # TODO(dglazkov) The backslash/forward-slash replacement at the end is a
+    # temporary measure. This should really be addressed by keeping all paths
+    # in POSIX until actual project generation.
+    d = gyp.common.RelativePath(depth, os.path.dirname(build_file_path))
+    if d == '':
+      variables['DEPTH'] = '.'
+    else:
+      variables['DEPTH'] = d.replace('\\', '/')
+
+  # If the generator needs absolue paths, then do so.
+  if absolute_build_file_paths:
+    build_file_path = os.path.abspath(build_file_path)
+
+  if build_file_path in data['target_build_files']:
+    # Already loaded.
+    return False
+  data['target_build_files'].add(build_file_path)
+
+  gyp.DebugOutput(gyp.DEBUG_INCLUDES,
+                  "Loading Target Build File '%s'", build_file_path)
+
+  build_file_data = LoadOneBuildFile(build_file_path, data, aux_data, variables,
+                                     includes, True, check)
+
+  # Store DEPTH for later use in generators.
+  build_file_data['_DEPTH'] = depth
+
+  # Set up the included_files key indicating which .gyp files contributed to
+  # this target dict.
+  if 'included_files' in build_file_data:
+    raise GypError(build_file_path + ' must not contain included_files key')
+
+  included = GetIncludedBuildFiles(build_file_path, aux_data)
+  build_file_data['included_files'] = []
+  for included_file in included:
+    # included_file is relative to the current directory, but it needs to
+    # be made relative to build_file_path's directory.
+    included_relative = \
+        gyp.common.RelativePath(included_file,
+                                os.path.dirname(build_file_path))
+    build_file_data['included_files'].append(included_relative)
+
+  # Do a first round of toolsets expansion so that conditions can be defined
+  # per toolset.
+  ProcessToolsetsInDict(build_file_data)
+
+  # Apply "pre"/"early" variable expansions and condition evaluations.
+  ProcessVariablesAndConditionsInDict(
+      build_file_data, PHASE_EARLY, variables, build_file_path)
+
+  # Since some toolsets might have been defined conditionally, perform
+  # a second round of toolsets expansion now.
+  ProcessToolsetsInDict(build_file_data)
+
+  # Look at each project's target_defaults dict, and merge settings into
+  # targets.
+  if 'target_defaults' in build_file_data:
+    if 'targets' not in build_file_data:
+      raise GypError("Unable to find targets in build file %s" %
+                     build_file_path)
+
+    index = 0
+    while index < len(build_file_data['targets']):
+      # This procedure needs to give the impression that target_defaults is
+      # used as defaults, and the individual targets inherit from that.
+      # The individual targets need to be merged into the defaults.  Make
+      # a deep copy of the defaults for each target, merge the target dict
+      # as found in the input file into that copy, and then hook up the
+      # copy with the target-specific data merged into it as the replacement
+      # target dict.
+      old_target_dict = build_file_data['targets'][index]
+      new_target_dict = copy.deepcopy(build_file_data['target_defaults'])
+      MergeDicts(new_target_dict, old_target_dict,
+                 build_file_path, build_file_path)
+      build_file_data['targets'][index] = new_target_dict
+      index += 1
+
+    # No longer needed.
+    del build_file_data['target_defaults']
+
+  # Look for dependencies.  This means that dependency resolution occurs
+  # after "pre" conditionals and variable expansion, but before "post" -
+  # in other words, you can't put a "dependencies" section inside a "post"
+  # conditional within a target.
+
+  dependencies = []
+  if 'targets' in build_file_data:
+    for target_dict in build_file_data['targets']:
+      if 'dependencies' not in target_dict:
+        continue
+      for dependency in target_dict['dependencies']:
+        dependencies.append(
+            gyp.common.ResolveTarget(build_file_path, dependency, None)[0])
+
+  if load_dependencies:
+    for dependency in dependencies:
+      try:
+        LoadTargetBuildFile(dependency, data, aux_data, variables,
+                            includes, depth, check, load_dependencies)
+      except Exception, e:
+        gyp.common.ExceptionAppend(
+          e, 'while loading dependencies of %s' % build_file_path)
+        raise
+  else:
+    return (build_file_path, dependencies)
+
+
+def CallLoadTargetBuildFile(global_flags,
+                            build_file_path, data,
+                            aux_data, variables,
+                            includes, depth, check):
+  """Wrapper around LoadTargetBuildFile for parallel processing.
+
+     This wrapper is used when LoadTargetBuildFile is executed in
+     a worker process.
+  """
+
+  try:
+    signal.signal(signal.SIGINT, signal.SIG_IGN)
+
+    # Apply globals so that the worker process behaves the same.
+    for key, value in global_flags.iteritems():
+      globals()[key] = value
+
+    # Save the keys so we can return data that changed.
+    data_keys = set(data)
+    aux_data_keys = set(aux_data)
+
+    result = LoadTargetBuildFile(build_file_path, data,
+                                 aux_data, variables,
+                                 includes, depth, check, False)
+    if not result:
+      return result
+
+    (build_file_path, dependencies) = result
+
+    data_out = {}
+    for key in data:
+      if key == 'target_build_files':
+        continue
+      if key not in data_keys:
+        data_out[key] = data[key]
+    aux_data_out = {}
+    for key in aux_data:
+      if key not in aux_data_keys:
+        aux_data_out[key] = aux_data[key]
+
+    # This gets serialized and sent back to the main process via a pipe.
+    # It's handled in LoadTargetBuildFileCallback.
+    return (build_file_path,
+            data_out,
+            aux_data_out,
+            dependencies)
+  except Exception, e:
+    print >>sys.stderr, 'Exception: ', e
+    return None
+
+
+class ParallelProcessingError(Exception):
+  pass
+
+
+class ParallelState(object):
+  """Class to keep track of state when processing input files in parallel.
+
+  If build files are loaded in parallel, use this to keep track of
+  state during farming out and processing parallel jobs. It's stored
+  in a global so that the callback function can have access to it.
+  """
+
+  def __init__(self):
+    # The multiprocessing pool.
+    self.pool = None
+    # The condition variable used to protect this object and notify
+    # the main loop when there might be more data to process.
+    self.condition = None
+    # The "data" dict that was passed to LoadTargetBuildFileParallel
+    self.data = None
+    # The "aux_data" dict that was passed to LoadTargetBuildFileParallel
+    self.aux_data = None
+    # The number of parallel calls outstanding; decremented when a response
+    # was received.
+    self.pending = 0
+    # The set of all build files that have been scheduled, so we don't
+    # schedule the same one twice.
+    self.scheduled = set()
+    # A list of dependency build file paths that haven't been scheduled yet.
+    self.dependencies = []
+    # Flag to indicate if there was an error in a child process.
+    self.error = False
+
+  def LoadTargetBuildFileCallback(self, result):
+    """Handle the results of running LoadTargetBuildFile in another process.
+    """
+    self.condition.acquire()
+    if not result:
+      self.error = True
+      self.condition.notify()
+      self.condition.release()
+      return
+    (build_file_path0, data0, aux_data0, dependencies0) = result
+    self.data['target_build_files'].add(build_file_path0)
+    for key in data0:
+      self.data[key] = data0[key]
+    for key in aux_data0:
+      self.aux_data[key] = aux_data0[key]
+    for new_dependency in dependencies0:
+      if new_dependency not in self.scheduled:
+        self.scheduled.add(new_dependency)
+        self.dependencies.append(new_dependency)
+    self.pending -= 1
+    self.condition.notify()
+    self.condition.release()
+
+
+def LoadTargetBuildFileParallel(build_file_path, data, aux_data,
+                                variables, includes, depth, check):
+  parallel_state = ParallelState()
+  parallel_state.condition = threading.Condition()
+  parallel_state.dependencies = [build_file_path]
+  parallel_state.scheduled = set([build_file_path])
+  parallel_state.pending = 0
+  parallel_state.data = data
+  parallel_state.aux_data = aux_data
+
+  try:
+    parallel_state.condition.acquire()
+    while parallel_state.dependencies or parallel_state.pending:
+      if parallel_state.error:
+        print >>sys.stderr, (
+            '\n'
+            'Note: an error occurred while running gyp using multiprocessing.\n'
+            'For more verbose output, set GYP_PARALLEL=0 in your environment.\n'
+            'If the error only occurs when GYP_PARALLEL=1, '
+            'please report a bug!')
+        break
+      if not parallel_state.dependencies:
+        parallel_state.condition.wait()
+        continue
+
+      dependency = parallel_state.dependencies.pop()
+
+      parallel_state.pending += 1
+      data_in = {}
+      data_in['target_build_files'] = data['target_build_files']
+      aux_data_in = {}
+      global_flags = {
+        'path_sections': globals()['path_sections'],
+        'non_configuration_keys': globals()['non_configuration_keys'],
+        'absolute_build_file_paths': globals()['absolute_build_file_paths'],
+        'multiple_toolsets': globals()['multiple_toolsets']}
+
+      if not parallel_state.pool:
+        parallel_state.pool = multiprocessing.Pool(8)
+      parallel_state.pool.apply_async(
+          CallLoadTargetBuildFile,
+          args = (global_flags, dependency,
+                  data_in, aux_data_in,
+                  variables, includes, depth, check),
+          callback = parallel_state.LoadTargetBuildFileCallback)
+  except KeyboardInterrupt, e:
+    parallel_state.pool.terminate()
+    raise e
+
+  parallel_state.condition.release()
+  if parallel_state.error:
+    sys.exit()
+
+
+# Look for the bracket that matches the first bracket seen in a
+# string, and return the start and end as a tuple.  For example, if
+# the input is something like "<(foo <(bar)) blah", then it would
+# return (1, 13), indicating the entire string except for the leading
+# "<" and trailing " blah".
+LBRACKETS= set('{[(')
+BRACKETS = {'}': '{', ']': '[', ')': '('}
+def FindEnclosingBracketGroup(input_str):
+  stack = []
+  start = -1
+  for index, char in enumerate(input_str):
+    if char in LBRACKETS:
+      stack.append(char)
+      if start == -1:
+        start = index
+    elif char in BRACKETS:
+      if not stack:
+        return (-1, -1)
+      if stack.pop() != BRACKETS[char]:
+        return (-1, -1)
+      if not stack:
+        return (start, index + 1)
+  return (-1, -1)
+
+
+canonical_int_re = re.compile('(0|-?[1-9][0-9]*)$')
+
+
+def IsStrCanonicalInt(string):
+  """Returns True if |string| is in its canonical integer form.
+
+  The canonical form is such that str(int(string)) == string.
+  """
+  return isinstance(string, str) and canonical_int_re.match(string)
+
+
+# This matches things like "<(asdf)", "<!(cmd)", "<!@(cmd)", "<|(list)",
+# "<!interpreter(arguments)", "<([list])", and even "<([)" and "<(<())".
+# In the last case, the inner "<()" is captured in match['content'].
+early_variable_re = re.compile(
+    '(?P<replace>(?P<type><(?:(?:!?@?)|\|)?)'
+    '(?P<command_string>[-a-zA-Z0-9_.]+)?'
+    '\((?P<is_array>\s*\[?)'
+    '(?P<content>.*?)(\]?)\))')
+
+# This matches the same as early_variable_re, but with '>' instead of '<'.
+late_variable_re = re.compile(
+    '(?P<replace>(?P<type>>(?:(?:!?@?)|\|)?)'
+    '(?P<command_string>[-a-zA-Z0-9_.]+)?'
+    '\((?P<is_array>\s*\[?)'
+    '(?P<content>.*?)(\]?)\))')
+
+# This matches the same as early_variable_re, but with '^' instead of '<'.
+latelate_variable_re = re.compile(
+    '(?P<replace>(?P<type>[\^](?:(?:!?@?)|\|)?)'
+    '(?P<command_string>[-a-zA-Z0-9_.]+)?'
+    '\((?P<is_array>\s*\[?)'
+    '(?P<content>.*?)(\]?)\))')
+
+# Global cache of results from running commands so they don't have to be run
+# more then once.
+cached_command_results = {}
+
+
+def FixupPlatformCommand(cmd):
+  if sys.platform == 'win32':
+    if type(cmd) == list:
+      cmd = [re.sub('^cat ', 'type ', cmd[0])] + cmd[1:]
+    else:
+      cmd = re.sub('^cat ', 'type ', cmd)
+  return cmd
+
+
+PHASE_EARLY = 0
+PHASE_LATE = 1
+PHASE_LATELATE = 2
+
+
+def ExpandVariables(input, phase, variables, build_file):
+  # Look for the pattern that gets expanded into variables
+  if phase == PHASE_EARLY:
+    variable_re = early_variable_re
+    expansion_symbol = '<'
+  elif phase == PHASE_LATE:
+    variable_re = late_variable_re
+    expansion_symbol = '>'
+  elif phase == PHASE_LATELATE:
+    variable_re = latelate_variable_re
+    expansion_symbol = '^'
+  else:
+    assert False
+
+  input_str = str(input)
+  if IsStrCanonicalInt(input_str):
+    return int(input_str)
+
+  # Do a quick scan to determine if an expensive regex search is warranted.
+  if expansion_symbol not in input_str:
+    return input_str
+
+  # Get the entire list of matches as a list of MatchObject instances.
+  # (using findall here would return strings instead of MatchObjects).
+  matches = list(variable_re.finditer(input_str))
+  if not matches:
+    return input_str
+
+  output = input_str
+  # Reverse the list of matches so that replacements are done right-to-left.
+  # That ensures that earlier replacements won't mess up the string in a
+  # way that causes later calls to find the earlier substituted text instead
+  # of what's intended for replacement.
+  matches.reverse()
+  for match_group in matches:
+    match = match_group.groupdict()
+    gyp.DebugOutput(gyp.DEBUG_VARIABLES, "Matches: %r", match)
+    # match['replace'] is the substring to look for, match['type']
+    # is the character code for the replacement type (< > <! >! <| >| <@
+    # >@ <!@ >!@), match['is_array'] contains a '[' for command
+    # arrays, and match['content'] is the name of the variable (< >)
+    # or command to run (<! >!). match['command_string'] is an optional
+    # command string. Currently, only 'pymod_do_main' is supported.
+
+    # run_command is true if a ! variant is used.
+    run_command = '!' in match['type']
+    command_string = match['command_string']
+
+    # file_list is true if a | variant is used.
+    file_list = '|' in match['type']
+
+    # Capture these now so we can adjust them later.
+    replace_start = match_group.start('replace')
+    replace_end = match_group.end('replace')
+
+    # Find the ending paren, and re-evaluate the contained string.
+    (c_start, c_end) = FindEnclosingBracketGroup(input_str[replace_start:])
+
+    # Adjust the replacement range to match the entire command
+    # found by FindEnclosingBracketGroup (since the variable_re
+    # probably doesn't match the entire command if it contained
+    # nested variables).
+    replace_end = replace_start + c_end
+
+    # Find the "real" replacement, matching the appropriate closing
+    # paren, and adjust the replacement start and end.
+    replacement = input_str[replace_start:replace_end]
+
+    # Figure out what the contents of the variable parens are.
+    contents_start = replace_start + c_start + 1
+    contents_end = replace_end - 1
+    contents = input_str[contents_start:contents_end]
+
+    # Do filter substitution now for <|().
+    # Admittedly, this is different than the evaluation order in other
+    # contexts. However, since filtration has no chance to run on <|(),
+    # this seems like the only obvious way to give them access to filters.
+    if file_list:
+      processed_variables = copy.deepcopy(variables)
+      ProcessListFiltersInDict(contents, processed_variables)
+      # Recurse to expand variables in the contents
+      contents = ExpandVariables(contents, phase,
+                                 processed_variables, build_file)
+    else:
+      # Recurse to expand variables in the contents
+      contents = ExpandVariables(contents, phase, variables, build_file)
+
+    # Strip off leading/trailing whitespace so that variable matches are
+    # simpler below (and because they are rarely needed).
+    contents = contents.strip()
+
+    # expand_to_list is true if an @ variant is used.  In that case,
+    # the expansion should result in a list.  Note that the caller
+    # is to be expecting a list in return, and not all callers do
+    # because not all are working in list context.  Also, for list
+    # expansions, there can be no other text besides the variable
+    # expansion in the input string.
+    expand_to_list = '@' in match['type'] and input_str == replacement
+
+    if run_command or file_list:
+      # Find the build file's directory, so commands can be run or file lists
+      # generated relative to it.
+      build_file_dir = os.path.dirname(build_file)
+      if build_file_dir == '':
+        # If build_file is just a leaf filename indicating a file in the
+        # current directory, build_file_dir might be an empty string.  Set
+        # it to None to signal to subprocess.Popen that it should run the
+        # command in the current directory.
+        build_file_dir = None
+
+    # Support <|(listfile.txt ...) which generates a file
+    # containing items from a gyp list, generated at gyp time.
+    # This works around actions/rules which have more inputs than will
+    # fit on the command line.
+    if file_list:
+      if type(contents) == list:
+        contents_list = contents
+      else:
+        contents_list = contents.split(' ')
+      replacement = contents_list[0]
+      path = replacement
+      if build_file_dir and not os.path.isabs(path):
+        path = os.path.join(build_file_dir, path)
+      f = gyp.common.WriteOnDiff(path)
+      for i in contents_list[1:]:
+        f.write('%s\n' % i)
+      f.close()
+
+    elif run_command:
+      use_shell = True
+      if match['is_array']:
+        contents = eval(contents)
+        use_shell = False
+
+      # Check for a cached value to avoid executing commands, or generating
+      # file lists more than once.
+      # TODO(http://code.google.com/p/gyp/issues/detail?id=112): It is
+      # possible that the command being invoked depends on the current
+      # directory. For that case the syntax needs to be extended so that the
+      # directory is also used in cache_key (it becomes a tuple).
+      # TODO(http://code.google.com/p/gyp/issues/detail?id=111): In theory,
+      # someone could author a set of GYP files where each time the command
+      # is invoked it produces different output by design. When the need
+      # arises, the syntax should be extended to support no caching off a
+      # command's output so it is run every time.
+      cache_key = str(contents)
+      cached_value = cached_command_results.get(cache_key, None)
+      if cached_value is None:
+        gyp.DebugOutput(gyp.DEBUG_VARIABLES,
+                        "Executing command '%s' in directory '%s'",
+                        contents, build_file_dir)
+
+        replacement = ''
+
+        if command_string == 'pymod_do_main':
+          # <!pymod_do_main(modulename param eters) loads |modulename| as a
+          # python module and then calls that module's DoMain() function,
+          # passing ["param", "eters"] as a single list argument. For modules
+          # that don't load quickly, this can be faster than
+          # <!(python modulename param eters). Do this in |build_file_dir|.
+          oldwd = os.getcwd()  # Python doesn't like os.open('.'): no fchdir.
+          if build_file_dir:  # build_file_dir may be None (see above).
+            os.chdir(build_file_dir)
+          try:
+
+            parsed_contents = shlex.split(contents)
+            try:
+              py_module = __import__(parsed_contents[0])
+            except ImportError as e:
+              raise GypError("Error importing pymod_do_main"
+                             "module (%s): %s" % (parsed_contents[0], e))
+            replacement = str(py_module.DoMain(parsed_contents[1:])).rstrip()
+          finally:
+            os.chdir(oldwd)
+          assert replacement != None
+        elif command_string:
+          raise GypError("Unknown command string '%s' in '%s'." %
+                         (command_string, contents))
+        else:
+          # Fix up command with platform specific workarounds.
+          contents = FixupPlatformCommand(contents)
+          p = subprocess.Popen(contents, shell=use_shell,
+                               stdout=subprocess.PIPE,
+                               stderr=subprocess.PIPE,
+                               stdin=subprocess.PIPE,
+                               cwd=build_file_dir)
+
+          p_stdout, p_stderr = p.communicate('')
+
+          if p.wait() != 0 or p_stderr:
+            sys.stderr.write(p_stderr)
+            # Simulate check_call behavior, since check_call only exists
+            # in python 2.5 and later.
+            raise GypError("Call to '%s' returned exit status %d." %
+                           (contents, p.returncode))
+          replacement = p_stdout.rstrip()
+
+        cached_command_results[cache_key] = replacement
+      else:
+        gyp.DebugOutput(gyp.DEBUG_VARIABLES,
+                        "Had cache value for command '%s' in directory '%s'",
+                        contents,build_file_dir)
+        replacement = cached_value
+
+    else:
+      if not contents in variables:
+        if contents[-1] in ['!', '/']:
+          # In order to allow cross-compiles (nacl) to happen more naturally,
+          # we will allow references to >(sources/) etc. to resolve to
+          # and empty list if undefined. This allows actions to:
+          # 'action!': [
+          #   '>@(_sources!)',
+          # ],
+          # 'action/': [
+          #   '>@(_sources/)',
+          # ],
+          replacement = []
+        else:
+          raise GypError('Undefined variable ' + contents +
+                         ' in ' + build_file)
+      else:
+        replacement = variables[contents]
+
+    if isinstance(replacement, list):
+      for item in replacement:
+        if (not contents[-1] == '/' and
+            not isinstance(item, str) and not isinstance(item, int)):
+          raise GypError('Variable ' + contents +
+                         ' must expand to a string or list of strings; ' +
+                         'list contains a ' +
+                         item.__class__.__name__)
+      # Run through the list and handle variable expansions in it.  Since
+      # the list is guaranteed not to contain dicts, this won't do anything
+      # with conditions sections.
+      ProcessVariablesAndConditionsInList(replacement, phase, variables,
+                                          build_file)
+    elif not isinstance(replacement, str) and \
+         not isinstance(replacement, int):
+          raise GypError('Variable ' + contents +
+                         ' must expand to a string or list of strings; ' +
+                         'found a ' + replacement.__class__.__name__)
+
+    if expand_to_list:
+      # Expanding in list context.  It's guaranteed that there's only one
+      # replacement to do in |input_str| and that it's this replacement.  See
+      # above.
+      if isinstance(replacement, list):
+        # If it's already a list, make a copy.
+        output = replacement[:]
+      else:
+        # Split it the same way sh would split arguments.
+        output = shlex.split(str(replacement))
+    else:
+      # Expanding in string context.
+      encoded_replacement = ''
+      if isinstance(replacement, list):
+        # When expanding a list into string context, turn the list items
+        # into a string in a way that will work with a subprocess call.
+        #
+        # TODO(mark): This isn't completely correct.  This should
+        # call a generator-provided function that observes the
+        # proper list-to-argument quoting rules on a specific
+        # platform instead of just calling the POSIX encoding
+        # routine.
+        encoded_replacement = gyp.common.EncodePOSIXShellList(replacement)
+      else:
+        encoded_replacement = replacement
+
+      output = output[:replace_start] + str(encoded_replacement) + \
+               output[replace_end:]
+    # Prepare for the next match iteration.
+    input_str = output
+
+  # Look for more matches now that we've replaced some, to deal with
+  # expanding local variables (variables defined in the same
+  # variables block as this one).
+  gyp.DebugOutput(gyp.DEBUG_VARIABLES, "Found output %r, recursing.", output)
+  if isinstance(output, list):
+    if output and isinstance(output[0], list):
+      # Leave output alone if it's a list of lists.
+      # We don't want such lists to be stringified.
+      pass
+    else:
+      new_output = []
+      for item in output:
+        new_output.append(
+            ExpandVariables(item, phase, variables, build_file))
+      output = new_output
+  else:
+    output = ExpandVariables(output, phase, variables, build_file)
+
+  # Convert all strings that are canonically-represented integers into integers.
+  if isinstance(output, list):
+    for index in xrange(0, len(output)):
+      if IsStrCanonicalInt(output[index]):
+        output[index] = int(output[index])
+  elif IsStrCanonicalInt(output):
+    output = int(output)
+
+  return output
+
+
+def ProcessConditionsInDict(the_dict, phase, variables, build_file):
+  # Process a 'conditions' or 'target_conditions' section in the_dict,
+  # depending on phase.
+  # early -> conditions
+  # late -> target_conditions
+  # latelate -> no conditions
+  #
+  # Each item in a conditions list consists of cond_expr, a string expression
+  # evaluated as the condition, and true_dict, a dict that will be merged into
+  # the_dict if cond_expr evaluates to true.  Optionally, a third item,
+  # false_dict, may be present.  false_dict is merged into the_dict if
+  # cond_expr evaluates to false.
+  #
+  # Any dict merged into the_dict will be recursively processed for nested
+  # conditionals and other expansions, also according to phase, immediately
+  # prior to being merged.
+
+  if phase == PHASE_EARLY:
+    conditions_key = 'conditions'
+  elif phase == PHASE_LATE:
+    conditions_key = 'target_conditions'
+  elif phase == PHASE_LATELATE:
+    return
+  else:
+    assert False
+
+  if not conditions_key in the_dict:
+    return
+
+  conditions_list = the_dict[conditions_key]
+  # Unhook the conditions list, it's no longer needed.
+  del the_dict[conditions_key]
+
+  for condition in conditions_list:
+    if not isinstance(condition, list):
+      raise GypError(conditions_key + ' must be a list')
+    if len(condition) != 2 and len(condition) != 3:
+      # It's possible that condition[0] won't work in which case this
+      # attempt will raise its own IndexError.  That's probably fine.
+      raise GypError(conditions_key + ' ' + condition[0] +
+                     ' must be length 2 or 3, not ' + str(len(condition)))
+
+    [cond_expr, true_dict] = condition[0:2]
+    false_dict = None
+    if len(condition) == 3:
+      false_dict = condition[2]
+
+    # Do expansions on the condition itself.  Since the conditon can naturally
+    # contain variable references without needing to resort to GYP expansion
+    # syntax, this is of dubious value for variables, but someone might want to
+    # use a command expansion directly inside a condition.
+    cond_expr_expanded = ExpandVariables(cond_expr, phase, variables,
+                                         build_file)
+    if not isinstance(cond_expr_expanded, str) and \
+       not isinstance(cond_expr_expanded, int):
+      raise ValueError, \
+            'Variable expansion in this context permits str and int ' + \
+            'only, found ' + expanded.__class__.__name__
+
+    try:
+      ast_code = compile(cond_expr_expanded, '<string>', 'eval')
+
+      if eval(ast_code, {'__builtins__': None}, variables):
+        merge_dict = true_dict
+      else:
+        merge_dict = false_dict
+    except SyntaxError, e:
+      syntax_error = SyntaxError('%s while evaluating condition \'%s\' in %s '
+                                 'at character %d.' %
+                                 (str(e.args[0]), e.text, build_file, e.offset),
+                                 e.filename, e.lineno, e.offset, e.text)
+      raise syntax_error
+    except NameError, e:
+      gyp.common.ExceptionAppend(e, 'while evaluating condition \'%s\' in %s' %
+                                 (cond_expr_expanded, build_file))
+      raise GypError(e)
+
+    if merge_dict != None:
+      # Expand variables and nested conditinals in the merge_dict before
+      # merging it.
+      ProcessVariablesAndConditionsInDict(merge_dict, phase,
+                                          variables, build_file)
+
+      MergeDicts(the_dict, merge_dict, build_file, build_file)
+
+
+def LoadAutomaticVariablesFromDict(variables, the_dict):
+  # Any keys with plain string values in the_dict become automatic variables.
+  # The variable name is the key name with a "_" character prepended.
+  for key, value in the_dict.iteritems():
+    if isinstance(value, str) or isinstance(value, int) or \
+       isinstance(value, list):
+      variables['_' + key] = value
+
+
+def LoadVariablesFromVariablesDict(variables, the_dict, the_dict_key):
+  # Any keys in the_dict's "variables" dict, if it has one, becomes a
+  # variable.  The variable name is the key name in the "variables" dict.
+  # Variables that end with the % character are set only if they are unset in
+  # the variables dict.  the_dict_key is the name of the key that accesses
+  # the_dict in the_dict's parent dict.  If the_dict's parent is not a dict
+  # (it could be a list or it could be parentless because it is a root dict),
+  # the_dict_key will be None.
+  for key, value in the_dict.get('variables', {}).iteritems():
+    if not isinstance(value, str) and not isinstance(value, int) and \
+       not isinstance(value, list):
+      continue
+
+    if key.endswith('%'):
+      variable_name = key[:-1]
+      if variable_name in variables:
+        # If the variable is already set, don't set it.
+        continue
+      if the_dict_key is 'variables' and variable_name in the_dict:
+        # If the variable is set without a % in the_dict, and the_dict is a
+        # variables dict (making |variables| a varaibles sub-dict of a
+        # variables dict), use the_dict's definition.
+        value = the_dict[variable_name]
+    else:
+      variable_name = key
+
+    variables[variable_name] = value
+
+
+def ProcessVariablesAndConditionsInDict(the_dict, phase, variables_in,
+                                        build_file, the_dict_key=None):
+  """Handle all variable and command expansion and conditional evaluation.
+
+  This function is the public entry point for all variable expansions and
+  conditional evaluations.  The variables_in dictionary will not be modified
+  by this function.
+  """
+
+  # Make a copy of the variables_in dict that can be modified during the
+  # loading of automatics and the loading of the variables dict.
+  variables = variables_in.copy()
+  LoadAutomaticVariablesFromDict(variables, the_dict)
+
+  if 'variables' in the_dict:
+    # Make sure all the local variables are added to the variables
+    # list before we process them so that you can reference one
+    # variable from another.  They will be fully expanded by recursion
+    # in ExpandVariables.
+    for key, value in the_dict['variables'].iteritems():
+      variables[key] = value
+
+    # Handle the associated variables dict first, so that any variable
+    # references within can be resolved prior to using them as variables.
+    # Pass a copy of the variables dict to avoid having it be tainted.
+    # Otherwise, it would have extra automatics added for everything that
+    # should just be an ordinary variable in this scope.
+    ProcessVariablesAndConditionsInDict(the_dict['variables'], phase,
+                                        variables, build_file, 'variables')
+
+  LoadVariablesFromVariablesDict(variables, the_dict, the_dict_key)
+
+  for key, value in the_dict.iteritems():
+    # Skip "variables", which was already processed if present.
+    if key != 'variables' and isinstance(value, str):
+      expanded = ExpandVariables(value, phase, variables, build_file)
+      if not isinstance(expanded, str) and not isinstance(expanded, int):
+        raise ValueError, \
+              'Variable expansion in this context permits str and int ' + \
+              'only, found ' + expanded.__class__.__name__ + ' for ' + key
+      the_dict[key] = expanded
+
+  # Variable expansion may have resulted in changes to automatics.  Reload.
+  # TODO(mark): Optimization: only reload if no changes were made.
+  variables = variables_in.copy()
+  LoadAutomaticVariablesFromDict(variables, the_dict)
+  LoadVariablesFromVariablesDict(variables, the_dict, the_dict_key)
+
+  # Process conditions in this dict.  This is done after variable expansion
+  # so that conditions may take advantage of expanded variables.  For example,
+  # if the_dict contains:
+  #   {'type':       '<(library_type)',
+  #    'conditions': [['_type=="static_library"', { ... }]]},
+  # _type, as used in the condition, will only be set to the value of
+  # library_type if variable expansion is performed before condition
+  # processing.  However, condition processing should occur prior to recursion
+  # so that variables (both automatic and "variables" dict type) may be
+  # adjusted by conditions sections, merged into the_dict, and have the
+  # intended impact on contained dicts.
+  #
+  # This arrangement means that a "conditions" section containing a "variables"
+  # section will only have those variables effective in subdicts, not in
+  # the_dict.  The workaround is to put a "conditions" section within a
+  # "variables" section.  For example:
+  #   {'conditions': [['os=="mac"', {'variables': {'define': 'IS_MAC'}}]],
+  #    'defines':    ['<(define)'],
+  #    'my_subdict': {'defines': ['<(define)']}},
+  # will not result in "IS_MAC" being appended to the "defines" list in the
+  # current scope but would result in it being appended to the "defines" list
+  # within "my_subdict".  By comparison:
+  #   {'variables': {'conditions': [['os=="mac"', {'define': 'IS_MAC'}]]},
+  #    'defines':    ['<(define)'],
+  #    'my_subdict': {'defines': ['<(define)']}},
+  # will append "IS_MAC" to both "defines" lists.
+
+  # Evaluate conditions sections, allowing variable expansions within them
+  # as well as nested conditionals.  This will process a 'conditions' or
+  # 'target_conditions' section, perform appropriate merging and recursive
+  # conditional and variable processing, and then remove the conditions section
+  # from the_dict if it is present.
+  ProcessConditionsInDict(the_dict, phase, variables, build_file)
+
+  # Conditional processing may have resulted in changes to automatics or the
+  # variables dict.  Reload.
+  variables = variables_in.copy()
+  LoadAutomaticVariablesFromDict(variables, the_dict)
+  LoadVariablesFromVariablesDict(variables, the_dict, the_dict_key)
+
+  # Recurse into child dicts, or process child lists which may result in
+  # further recursion into descendant dicts.
+  for key, value in the_dict.iteritems():
+    # Skip "variables" and string values, which were already processed if
+    # present.
+    if key == 'variables' or isinstance(value, str):
+      continue
+    if isinstance(value, dict):
+      # Pass a copy of the variables dict so that subdicts can't influence
+      # parents.
+      ProcessVariablesAndConditionsInDict(value, phase, variables,
+                                          build_file, key)
+    elif isinstance(value, list):
+      # The list itself can't influence the variables dict, and
+      # ProcessVariablesAndConditionsInList will make copies of the variables
+      # dict if it needs to pass it to something that can influence it.  No
+      # copy is necessary here.
+      ProcessVariablesAndConditionsInList(value, phase, variables,
+                                          build_file)
+    elif not isinstance(value, int):
+      raise TypeError, 'Unknown type ' + value.__class__.__name__ + \
+                       ' for ' + key
+
+
+def ProcessVariablesAndConditionsInList(the_list, phase, variables,
+                                        build_file):
+  # Iterate using an index so that new values can be assigned into the_list.
+  index = 0
+  while index < len(the_list):
+    item = the_list[index]
+    if isinstance(item, dict):
+      # Make a copy of the variables dict so that it won't influence anything
+      # outside of its own scope.
+      ProcessVariablesAndConditionsInDict(item, phase, variables, build_file)
+    elif isinstance(item, list):
+      ProcessVariablesAndConditionsInList(item, phase, variables, build_file)
+    elif isinstance(item, str):
+      expanded = ExpandVariables(item, phase, variables, build_file)
+      if isinstance(expanded, str) or isinstance(expanded, int):
+        the_list[index] = expanded
+      elif isinstance(expanded, list):
+        the_list[index:index+1] = expanded
+        index += len(expanded)
+
+        # index now identifies the next item to examine.  Continue right now
+        # without falling into the index increment below.
+        continue
+      else:
+        raise ValueError, \
+              'Variable expansion in this context permits strings and ' + \
+              'lists only, found ' + expanded.__class__.__name__ + ' at ' + \
+              index
+    elif not isinstance(item, int):
+      raise TypeError, 'Unknown type ' + item.__class__.__name__ + \
+                       ' at index ' + index
+    index = index + 1
+
+
+def BuildTargetsDict(data):
+  """Builds a dict mapping fully-qualified target names to their target dicts.
+
+  |data| is a dict mapping loaded build files by pathname relative to the
+  current directory.  Values in |data| are build file contents.  For each
+  |data| value with a "targets" key, the value of the "targets" key is taken
+  as a list containing target dicts.  Each target's fully-qualified name is
+  constructed from the pathname of the build file (|data| key) and its
+  "target_name" property.  These fully-qualified names are used as the keys
+  in the returned dict.  These keys provide access to the target dicts,
+  the dicts in the "targets" lists.
+  """
+
+  targets = {}
+  for build_file in data['target_build_files']:
+    for target in data[build_file].get('targets', []):
+      target_name = gyp.common.QualifiedTarget(build_file,
+                                               target['target_name'],
+                                               target['toolset'])
+      if target_name in targets:
+        raise GypError('Duplicate target definitions for ' + target_name)
+      targets[target_name] = target
+
+  return targets
+
+
+def QualifyDependencies(targets):
+  """Make dependency links fully-qualified relative to the current directory.
+
+  |targets| is a dict mapping fully-qualified target names to their target
+  dicts.  For each target in this dict, keys known to contain dependency
+  links are examined, and any dependencies referenced will be rewritten
+  so that they are fully-qualified and relative to the current directory.
+  All rewritten dependencies are suitable for use as keys to |targets| or a
+  similar dict.
+  """
+
+  all_dependency_sections = [dep + op
+                             for dep in dependency_sections
+                             for op in ('', '!', '/')]
+
+  for target, target_dict in targets.iteritems():
+    target_build_file = gyp.common.BuildFile(target)
+    toolset = target_dict['toolset']
+    for dependency_key in all_dependency_sections:
+      dependencies = target_dict.get(dependency_key, [])
+      for index in xrange(0, len(dependencies)):
+        dep_file, dep_target, dep_toolset = gyp.common.ResolveTarget(
+            target_build_file, dependencies[index], toolset)
+        if not multiple_toolsets:
+          # Ignore toolset specification in the dependency if it is specified.
+          dep_toolset = toolset
+        dependency = gyp.common.QualifiedTarget(dep_file,
+                                                dep_target,
+                                                dep_toolset)
+        dependencies[index] = dependency
+
+        # Make sure anything appearing in a list other than "dependencies" also
+        # appears in the "dependencies" list.
+        if dependency_key != 'dependencies' and \
+           dependency not in target_dict['dependencies']:
+          raise GypError('Found ' + dependency + ' in ' + dependency_key +
+                         ' of ' + target + ', but not in dependencies')
+
+
+def ExpandWildcardDependencies(targets, data):
+  """Expands dependencies specified as build_file:*.
+
+  For each target in |targets|, examines sections containing links to other
+  targets.  If any such section contains a link of the form build_file:*, it
+  is taken as a wildcard link, and is expanded to list each target in
+  build_file.  The |data| dict provides access to build file dicts.
+
+  Any target that does not wish to be included by wildcard can provide an
+  optional "suppress_wildcard" key in its target dict.  When present and
+  true, a wildcard dependency link will not include such targets.
+
+  All dependency names, including the keys to |targets| and the values in each
+  dependency list, must be qualified when this function is called.
+  """
+
+  for target, target_dict in targets.iteritems():
+    toolset = target_dict['toolset']
+    target_build_file = gyp.common.BuildFile(target)
+    for dependency_key in dependency_sections:
+      dependencies = target_dict.get(dependency_key, [])
+
+      # Loop this way instead of "for dependency in" or "for index in xrange"
+      # because the dependencies list will be modified within the loop body.
+      index = 0
+      while index < len(dependencies):
+        (dependency_build_file, dependency_target, dependency_toolset) = \
+            gyp.common.ParseQualifiedTarget(dependencies[index])
+        if dependency_target != '*' and dependency_toolset != '*':
+          # Not a wildcard.  Keep it moving.
+          index = index + 1
+          continue
+
+        if dependency_build_file == target_build_file:
+          # It's an error for a target to depend on all other targets in
+          # the same file, because a target cannot depend on itself.
+          raise GypError('Found wildcard in ' + dependency_key + ' of ' +
+                         target + ' referring to same build file')
+
+        # Take the wildcard out and adjust the index so that the next
+        # dependency in the list will be processed the next time through the
+        # loop.
+        del dependencies[index]
+        index = index - 1
+
+        # Loop through the targets in the other build file, adding them to
+        # this target's list of dependencies in place of the removed
+        # wildcard.
+        dependency_target_dicts = data[dependency_build_file]['targets']
+        for dependency_target_dict in dependency_target_dicts:
+          if int(dependency_target_dict.get('suppress_wildcard', False)):
+            continue
+          dependency_target_name = dependency_target_dict['target_name']
+          if (dependency_target != '*' and
+              dependency_target != dependency_target_name):
+            continue
+          dependency_target_toolset = dependency_target_dict['toolset']
+          if (dependency_toolset != '*' and
+              dependency_toolset != dependency_target_toolset):
+            continue
+          dependency = gyp.common.QualifiedTarget(dependency_build_file,
+                                                  dependency_target_name,
+                                                  dependency_target_toolset)
+          index = index + 1
+          dependencies.insert(index, dependency)
+
+        index = index + 1
+
+
+def Unify(l):
+  """Removes duplicate elements from l, keeping the first element."""
+  seen = {}
+  return [seen.setdefault(e, e) for e in l if e not in seen]
+
+
+def RemoveDuplicateDependencies(targets):
+  """Makes sure every dependency appears only once in all targets's dependency
+  lists."""
+  for target_name, target_dict in targets.iteritems():
+    for dependency_key in dependency_sections:
+      dependencies = target_dict.get(dependency_key, [])
+      if dependencies:
+        target_dict[dependency_key] = Unify(dependencies)
+
+
+def Filter(l, item):
+  """Removes item from l."""
+  res = {}
+  return [res.setdefault(e, e) for e in l if e != item]
+
+
+def RemoveSelfDependencies(targets):
+  """Remove self dependencies from targets that have the prune_self_dependency
+  variable set."""
+  for target_name, target_dict in targets.iteritems():
+    for dependency_key in dependency_sections:
+      dependencies = target_dict.get(dependency_key, [])
+      if dependencies:
+        for t in dependencies:
+          if t == target_name:
+            if targets[t].get('variables', {}).get('prune_self_dependency', 0):
+              target_dict[dependency_key] = Filter(dependencies, target_name)
+
+
+class DependencyGraphNode(object):
+  """
+
+  Attributes:
+    ref: A reference to an object that this DependencyGraphNode represents.
+    dependencies: List of DependencyGraphNodes on which this one depends.
+    dependents: List of DependencyGraphNodes that depend on this one.
+  """
+
+  class CircularException(GypError):
+    pass
+
+  def __init__(self, ref):
+    self.ref = ref
+    self.dependencies = []
+    self.dependents = []
+
+  def FlattenToList(self):
+    # flat_list is the sorted list of dependencies - actually, the list items
+    # are the "ref" attributes of DependencyGraphNodes.  Every target will
+    # appear in flat_list after all of its dependencies, and before all of its
+    # dependents.
+    flat_list = []
+
+    # in_degree_zeros is the list of DependencyGraphNodes that have no
+    # dependencies not in flat_list.  Initially, it is a copy of the children
+    # of this node, because when the graph was built, nodes with no
+    # dependencies were made implicit dependents of the root node.
+    in_degree_zeros = set(self.dependents[:])
+
+    while in_degree_zeros:
+      # Nodes in in_degree_zeros have no dependencies not in flat_list, so they
+      # can be appended to flat_list.  Take these nodes out of in_degree_zeros
+      # as work progresses, so that the next node to process from the list can
+      # always be accessed at a consistent position.
+      node = in_degree_zeros.pop()
+      flat_list.append(node.ref)
+
+      # Look at dependents of the node just added to flat_list.  Some of them
+      # may now belong in in_degree_zeros.
+      for node_dependent in node.dependents:
+        is_in_degree_zero = True
+        for node_dependent_dependency in node_dependent.dependencies:
+          if not node_dependent_dependency.ref in flat_list:
+            # The dependent one or more dependencies not in flat_list.  There
+            # will be more chances to add it to flat_list when examining
+            # it again as a dependent of those other dependencies, provided
+            # that there are no cycles.
+            is_in_degree_zero = False
+            break
+
+        if is_in_degree_zero:
+          # All of the dependent's dependencies are already in flat_list.  Add
+          # it to in_degree_zeros where it will be processed in a future
+          # iteration of the outer loop.
+          in_degree_zeros.add(node_dependent)
+
+    return flat_list
+
+  def DirectDependencies(self, dependencies=None):
+    """Returns a list of just direct dependencies."""
+    if dependencies == None:
+      dependencies = []
+
+    for dependency in self.dependencies:
+      # Check for None, corresponding to the root node.
+      if dependency.ref != None and dependency.ref not in dependencies:
+        dependencies.append(dependency.ref)
+
+    return dependencies
+
+  def _AddImportedDependencies(self, targets, dependencies=None):
+    """Given a list of direct dependencies, adds indirect dependencies that
+    other dependencies have declared to export their settings.
+
+    This method does not operate on self.  Rather, it operates on the list
+    of dependencies in the |dependencies| argument.  For each dependency in
+    that list, if any declares that it exports the settings of one of its
+    own dependencies, those dependencies whose settings are "passed through"
+    are added to the list.  As new items are added to the list, they too will
+    be processed, so it is possible to import settings through multiple levels
+    of dependencies.
+
+    This method is not terribly useful on its own, it depends on being
+    "primed" with a list of direct dependencies such as one provided by
+    DirectDependencies.  DirectAndImportedDependencies is intended to be the
+    public entry point.
+    """
+
+    if dependencies == None:
+      dependencies = []
+
+    index = 0
+    while index < len(dependencies):
+      dependency = dependencies[index]
+      dependency_dict = targets[dependency]
+      # Add any dependencies whose settings should be imported to the list
+      # if not already present.  Newly-added items will be checked for
+      # their own imports when the list iteration reaches them.
+      # Rather than simply appending new items, insert them after the
+      # dependency that exported them.  This is done to more closely match
+      # the depth-first method used by DeepDependencies.
+      add_index = 1
+      for imported_dependency in \
+          dependency_dict.get('export_dependent_settings', []):
+        if imported_dependency not in dependencies:
+          dependencies.insert(index + add_index, imported_dependency)
+          add_index = add_index + 1
+      index = index + 1
+
+    return dependencies
+
+  def DirectAndImportedDependencies(self, targets, dependencies=None):
+    """Returns a list of a target's direct dependencies and all indirect
+    dependencies that a dependency has advertised settings should be exported
+    through the dependency for.
+    """
+
+    dependencies = self.DirectDependencies(dependencies)
+    return self._AddImportedDependencies(targets, dependencies)
+
+  def DeepDependencies(self, dependencies=None):
+    """Returns a list of all of a target's dependencies, recursively."""
+    if dependencies == None:
+      dependencies = []
+
+    for dependency in self.dependencies:
+      # Check for None, corresponding to the root node.
+      if dependency.ref != None and dependency.ref not in dependencies:
+        dependencies.append(dependency.ref)
+        dependency.DeepDependencies(dependencies)
+
+    return dependencies
+
+  def LinkDependencies(self, targets, dependencies=None, initial=True):
+    """Returns a list of dependency targets that are linked into this target.
+
+    This function has a split personality, depending on the setting of
+    |initial|.  Outside callers should always leave |initial| at its default
+    setting.
+
+    When adding a target to the list of dependencies, this function will
+    recurse into itself with |initial| set to False, to collect dependencies
+    that are linked into the linkable target for which the list is being built.
+    """
+    if dependencies == None:
+      dependencies = []
+
+    # Check for None, corresponding to the root node.
+    if self.ref == None:
+      return dependencies
+
+    # It's kind of sucky that |targets| has to be passed into this function,
+    # but that's presently the easiest way to access the target dicts so that
+    # this function can find target types.
+
+    if 'target_name' not in targets[self.ref]:
+      raise GypError("Missing 'target_name' field in target.")
+
+    if 'type' not in targets[self.ref]:
+      raise GypError("Missing 'type' field in target %s" %
+                     targets[self.ref]['target_name'])
+
+    target_type = targets[self.ref]['type']
+
+    is_linkable = target_type in linkable_types
+
+    if initial and not is_linkable:
+      # If this is the first target being examined and it's not linkable,
+      # return an empty list of link dependencies, because the link
+      # dependencies are intended to apply to the target itself (initial is
+      # True) and this target won't be linked.
+      return dependencies
+
+    # Don't traverse 'none' targets if explicitly excluded.
+    if (target_type == 'none' and
+        not targets[self.ref].get('dependencies_traverse', True)):
+      if self.ref not in dependencies:
+        dependencies.append(self.ref)
+      return dependencies
+
+    # Executables and loadable modules are already fully and finally linked.
+    # Nothing else can be a link dependency of them, there can only be
+    # dependencies in the sense that a dependent target might run an
+    # executable or load the loadable_module.
+    if not initial and target_type in ('executable', 'loadable_module'):
+      return dependencies
+
+    # The target is linkable, add it to the list of link dependencies.
+    if self.ref not in dependencies:
+      dependencies.append(self.ref)
+      if initial or not is_linkable:
+        # If this is a subsequent target and it's linkable, don't look any
+        # further for linkable dependencies, as they'll already be linked into
+        # this target linkable.  Always look at dependencies of the initial
+        # target, and always look at dependencies of non-linkables.
+        for dependency in self.dependencies:
+          dependency.LinkDependencies(targets, dependencies, False)
+
+    return dependencies
+
+
+def BuildDependencyList(targets):
+  # Create a DependencyGraphNode for each target.  Put it into a dict for easy
+  # access.
+  dependency_nodes = {}
+  for target, spec in targets.iteritems():
+    if target not in dependency_nodes:
+      dependency_nodes[target] = DependencyGraphNode(target)
+
+  # Set up the dependency links.  Targets that have no dependencies are treated
+  # as dependent on root_node.
+  root_node = DependencyGraphNode(None)
+  for target, spec in targets.iteritems():
+    target_node = dependency_nodes[target]
+    target_build_file = gyp.common.BuildFile(target)
+    dependencies = spec.get('dependencies')
+    if not dependencies:
+      target_node.dependencies = [root_node]
+      root_node.dependents.append(target_node)
+    else:
+      for dependency in dependencies:
+        dependency_node = dependency_nodes.get(dependency)
+        if not dependency_node:
+          raise GypError("Dependency '%s' not found while "
+                         "trying to load target %s" % (dependency, target))
+        target_node.dependencies.append(dependency_node)
+        dependency_node.dependents.append(target_node)
+
+  flat_list = root_node.FlattenToList()
+
+  # If there's anything left unvisited, there must be a circular dependency
+  # (cycle).  If you need to figure out what's wrong, look for elements of
+  # targets that are not in flat_list.
+  if len(flat_list) != len(targets):
+    raise DependencyGraphNode.CircularException(
+        'Some targets not reachable, cycle in dependency graph detected: ' +
+        ' '.join(set(flat_list) ^ set(targets)))
+
+  return [dependency_nodes, flat_list]
+
+
+def VerifyNoGYPFileCircularDependencies(targets):
+  # Create a DependencyGraphNode for each gyp file containing a target.  Put
+  # it into a dict for easy access.
+  dependency_nodes = {}
+  for target in targets.iterkeys():
+    build_file = gyp.common.BuildFile(target)
+    if not build_file in dependency_nodes:
+      dependency_nodes[build_file] = DependencyGraphNode(build_file)
+
+  # Set up the dependency links.
+  for target, spec in targets.iteritems():
+    build_file = gyp.common.BuildFile(target)
+    build_file_node = dependency_nodes[build_file]
+    target_dependencies = spec.get('dependencies', [])
+    for dependency in target_dependencies:
+      try:
+        dependency_build_file = gyp.common.BuildFile(dependency)
+      except GypError, e:
+        gyp.common.ExceptionAppend(
+            e, 'while computing dependencies of .gyp file %s' % build_file)
+        raise
+
+      if dependency_build_file == build_file:
+        # A .gyp file is allowed to refer back to itself.
+        continue
+      dependency_node = dependency_nodes.get(dependency_build_file)
+      if not dependency_node:
+        raise GypError("Dependancy '%s' not found" % dependency_build_file)
+      if dependency_node not in build_file_node.dependencies:
+        build_file_node.dependencies.append(dependency_node)
+        dependency_node.dependents.append(build_file_node)
+
+
+  # Files that have no dependencies are treated as dependent on root_node.
+  root_node = DependencyGraphNode(None)
+  for build_file_node in dependency_nodes.itervalues():
+    if len(build_file_node.dependencies) == 0:
+      build_file_node.dependencies.append(root_node)
+      root_node.dependents.append(build_file_node)
+
+  flat_list = root_node.FlattenToList()
+
+  # If there's anything left unvisited, there must be a circular dependency
+  # (cycle).
+  if len(flat_list) != len(dependency_nodes):
+    bad_files = []
+    for file in dependency_nodes.iterkeys():
+      if not file in flat_list:
+        bad_files.append(file)
+    raise DependencyGraphNode.CircularException, \
+        'Some files not reachable, cycle in .gyp file dependency graph ' + \
+        'detected involving some or all of: ' + \
+        ' '.join(bad_files)
+
+
+def DoDependentSettings(key, flat_list, targets, dependency_nodes):
+  # key should be one of all_dependent_settings, direct_dependent_settings,
+  # or link_settings.
+
+  for target in flat_list:
+    target_dict = targets[target]
+    build_file = gyp.common.BuildFile(target)
+
+    if key == 'all_dependent_settings':
+      dependencies = dependency_nodes[target].DeepDependencies()
+    elif key == 'direct_dependent_settings':
+      dependencies = \
+          dependency_nodes[target].DirectAndImportedDependencies(targets)
+    elif key == 'link_settings':
+      dependencies = dependency_nodes[target].LinkDependencies(targets)
+    else:
+      raise GypError("DoDependentSettings doesn't know how to determine "
+                      'dependencies for ' + key)
+
+    for dependency in dependencies:
+      dependency_dict = targets[dependency]
+      if not key in dependency_dict:
+        continue
+      dependency_build_file = gyp.common.BuildFile(dependency)
+      MergeDicts(target_dict, dependency_dict[key],
+                 build_file, dependency_build_file)
+
+
+def AdjustStaticLibraryDependencies(flat_list, targets, dependency_nodes,
+                                    sort_dependencies):
+  # Recompute target "dependencies" properties.  For each static library
+  # target, remove "dependencies" entries referring to other static libraries,
+  # unless the dependency has the "hard_dependency" attribute set.  For each
+  # linkable target, add a "dependencies" entry referring to all of the
+  # target's computed list of link dependencies (including static libraries
+  # if no such entry is already present.
+  for target in flat_list:
+    target_dict = targets[target]
+    target_type = target_dict['type']
+
+    if target_type == 'static_library':
+      if not 'dependencies' in target_dict:
+        continue
+
+      target_dict['dependencies_original'] = target_dict.get(
+          'dependencies', [])[:]
+
+      # A static library should not depend on another static library unless
+      # the dependency relationship is "hard," which should only be done when
+      # a dependent relies on some side effect other than just the build
+      # product, like a rule or action output. Further, if a target has a
+      # non-hard dependency, but that dependency exports a hard dependency,
+      # the non-hard dependency can safely be removed, but the exported hard
+      # dependency must be added to the target to keep the same dependency
+      # ordering.
+      dependencies = \
+          dependency_nodes[target].DirectAndImportedDependencies(targets)
+      index = 0
+      while index < len(dependencies):
+        dependency = dependencies[index]
+        dependency_dict = targets[dependency]
+
+        # Remove every non-hard static library dependency and remove every
+        # non-static library dependency that isn't a direct dependency.
+        if (dependency_dict['type'] == 'static_library' and \
+            not dependency_dict.get('hard_dependency', False)) or \
+           (dependency_dict['type'] != 'static_library' and \
+            not dependency in target_dict['dependencies']):
+          # Take the dependency out of the list, and don't increment index
+          # because the next dependency to analyze will shift into the index
+          # formerly occupied by the one being removed.
+          del dependencies[index]
+        else:
+          index = index + 1
+
+      # Update the dependencies. If the dependencies list is empty, it's not
+      # needed, so unhook it.
+      if len(dependencies) > 0:
+        target_dict['dependencies'] = dependencies
+      else:
+        del target_dict['dependencies']
+
+    elif target_type in linkable_types:
+      # Get a list of dependency targets that should be linked into this
+      # target.  Add them to the dependencies list if they're not already
+      # present.
+
+      link_dependencies = dependency_nodes[target].LinkDependencies(targets)
+      for dependency in link_dependencies:
+        if dependency == target:
+          continue
+        if not 'dependencies' in target_dict:
+          target_dict['dependencies'] = []
+        if not dependency in target_dict['dependencies']:
+          target_dict['dependencies'].append(dependency)
+      # Sort the dependencies list in the order from dependents to dependencies.
+      # e.g. If A and B depend on C and C depends on D, sort them in A, B, C, D.
+      # Note: flat_list is already sorted in the order from dependencies to
+      # dependents.
+      if sort_dependencies and 'dependencies' in target_dict:
+        target_dict['dependencies'] = [dep for dep in reversed(flat_list)
+                                       if dep in target_dict['dependencies']]
+
+
+# Initialize this here to speed up MakePathRelative.
+exception_re = re.compile(r'''["']?[-/$<>^]''')
+
+
+def MakePathRelative(to_file, fro_file, item):
+  # If item is a relative path, it's relative to the build file dict that it's
+  # coming from.  Fix it up to make it relative to the build file dict that
+  # it's going into.
+  # Exception: any |item| that begins with these special characters is
+  # returned without modification.
+  #   /   Used when a path is already absolute (shortcut optimization;
+  #       such paths would be returned as absolute anyway)
+  #   $   Used for build environment variables
+  #   -   Used for some build environment flags (such as -lapr-1 in a
+  #       "libraries" section)
+  #   <   Used for our own variable and command expansions (see ExpandVariables)
+  #   >   Used for our own variable and command expansions (see ExpandVariables)
+  #   ^   Used for our own variable and command expansions (see ExpandVariables)
+  #
+  #   "/' Used when a value is quoted.  If these are present, then we
+  #       check the second character instead.
+  #
+  if to_file == fro_file or exception_re.match(item):
+    return item
+  else:
+    # TODO(dglazkov) The backslash/forward-slash replacement at the end is a
+    # temporary measure. This should really be addressed by keeping all paths
+    # in POSIX until actual project generation.
+    ret = os.path.normpath(os.path.join(
+        gyp.common.RelativePath(os.path.dirname(fro_file),
+                                os.path.dirname(to_file)),
+                                item)).replace('\\', '/')
+    if item[-1] == '/':
+      ret += '/'
+    return ret
+
+def MergeLists(to, fro, to_file, fro_file, is_paths=False, append=True):
+  # Python documentation recommends objects which do not support hash
+  # set this value to None. Python library objects follow this rule.
+  is_hashable = lambda val: val.__hash__
+
+  # If x is hashable, returns whether x is in s. Else returns whether x is in l.
+  def is_in_set_or_list(x, s, l):
+    if is_hashable(x):
+      return x in s
+    return x in l
+
+  prepend_index = 0
+
+  # Make membership testing of hashables in |to| (in particular, strings)
+  # faster.
+  hashable_to_set = set(x for x in to if is_hashable(x))
+  for item in fro:
+    singleton = False
+    if isinstance(item, str) or isinstance(item, int):
+      # The cheap and easy case.
+      if is_paths:
+        to_item = MakePathRelative(to_file, fro_file, item)
+      else:
+        to_item = item
+
+      if not isinstance(item, str) or not item.startswith('-'):
+        # Any string that doesn't begin with a "-" is a singleton - it can
+        # only appear once in a list, to be enforced by the list merge append
+        # or prepend.
+        singleton = True
+    elif isinstance(item, dict):
+      # Make a copy of the dictionary, continuing to look for paths to fix.
+      # The other intelligent aspects of merge processing won't apply because
+      # item is being merged into an empty dict.
+      to_item = {}
+      MergeDicts(to_item, item, to_file, fro_file)
+    elif isinstance(item, list):
+      # Recurse, making a copy of the list.  If the list contains any
+      # descendant dicts, path fixing will occur.  Note that here, custom
+      # values for is_paths and append are dropped; those are only to be
+      # applied to |to| and |fro|, not sublists of |fro|.  append shouldn't
+      # matter anyway because the new |to_item| list is empty.
+      to_item = []
+      MergeLists(to_item, item, to_file, fro_file)
+    else:
+      raise TypeError, \
+          'Attempt to merge list item of unsupported type ' + \
+          item.__class__.__name__
+
+    if append:
+      # If appending a singleton that's already in the list, don't append.
+      # This ensures that the earliest occurrence of the item will stay put.
+      if not singleton or not is_in_set_or_list(to_item, hashable_to_set, to):
+        to.append(to_item)
+        if is_hashable(to_item):
+          hashable_to_set.add(to_item)
+    else:
+      # If prepending a singleton that's already in the list, remove the
+      # existing instance and proceed with the prepend.  This ensures that the
+      # item appears at the earliest possible position in the list.
+      while singleton and to_item in to:
+        to.remove(to_item)
+
+      # Don't just insert everything at index 0.  That would prepend the new
+      # items to the list in reverse order, which would be an unwelcome
+      # surprise.
+      to.insert(prepend_index, to_item)
+      if is_hashable(to_item):
+        hashable_to_set.add(to_item)
+      prepend_index = prepend_index + 1
+
+
+def MergeDicts(to, fro, to_file, fro_file):
+  # I wanted to name the parameter "from" but it's a Python keyword...
+  for k, v in fro.iteritems():
+    # It would be nice to do "if not k in to: to[k] = v" but that wouldn't give
+    # copy semantics.  Something else may want to merge from the |fro| dict
+    # later, and having the same dict ref pointed to twice in the tree isn't
+    # what anyone wants considering that the dicts may subsequently be
+    # modified.
+    if k in to:
+      bad_merge = False
+      if isinstance(v, str) or isinstance(v, int):
+        if not (isinstance(to[k], str) or isinstance(to[k], int)):
+          bad_merge = True
+      elif v.__class__ != to[k].__class__:
+        bad_merge = True
+
+      if bad_merge:
+        raise TypeError, \
+            'Attempt to merge dict value of type ' + v.__class__.__name__ + \
+            ' into incompatible type ' + to[k].__class__.__name__ + \
+            ' for key ' + k
+    if isinstance(v, str) or isinstance(v, int):
+      # Overwrite the existing value, if any.  Cheap and easy.
+      is_path = IsPathSection(k)
+      if is_path:
+        to[k] = MakePathRelative(to_file, fro_file, v)
+      else:
+        to[k] = v
+    elif isinstance(v, dict):
+      # Recurse, guaranteeing copies will be made of objects that require it.
+      if not k in to:
+        to[k] = {}
+      MergeDicts(to[k], v, to_file, fro_file)
+    elif isinstance(v, list):
+      # Lists in dicts can be merged with different policies, depending on
+      # how the key in the "from" dict (k, the from-key) is written.
+      #
+      # If the from-key has          ...the to-list will have this action
+      # this character appended:...     applied when receiving the from-list:
+      #                           =  replace
+      #                           +  prepend
+      #                           ?  set, only if to-list does not yet exist
+      #                      (none)  append
+      #
+      # This logic is list-specific, but since it relies on the associated
+      # dict key, it's checked in this dict-oriented function.
+      ext = k[-1]
+      append = True
+      if ext == '=':
+        list_base = k[:-1]
+        lists_incompatible = [list_base, list_base + '?']
+        to[list_base] = []
+      elif ext == '+':
+        list_base = k[:-1]
+        lists_incompatible = [list_base + '=', list_base + '?']
+        append = False
+      elif ext == '?':
+        list_base = k[:-1]
+        lists_incompatible = [list_base, list_base + '=', list_base + '+']
+      else:
+        list_base = k
+        lists_incompatible = [list_base + '=', list_base + '?']
+
+      # Some combinations of merge policies appearing together are meaningless.
+      # It's stupid to replace and append simultaneously, for example.  Append
+      # and prepend are the only policies that can coexist.
+      for list_incompatible in lists_incompatible:
+        if list_incompatible in fro:
+          raise GypError('Incompatible list policies ' + k + ' and ' +
+                         list_incompatible)
+
+      if list_base in to:
+        if ext == '?':
+          # If the key ends in "?", the list will only be merged if it doesn't
+          # already exist.
+          continue
+        if not isinstance(to[list_base], list):
+          # This may not have been checked above if merging in a list with an
+          # extension character.
+          raise TypeError, \
+              'Attempt to merge dict value of type ' + v.__class__.__name__ + \
+              ' into incompatible type ' + to[list_base].__class__.__name__ + \
+              ' for key ' + list_base + '(' + k + ')'
+      else:
+        to[list_base] = []
+
+      # Call MergeLists, which will make copies of objects that require it.
+      # MergeLists can recurse back into MergeDicts, although this will be
+      # to make copies of dicts (with paths fixed), there will be no
+      # subsequent dict "merging" once entering a list because lists are
+      # always replaced, appended to, or prepended to.
+      is_paths = IsPathSection(list_base)
+      MergeLists(to[list_base], v, to_file, fro_file, is_paths, append)
+    else:
+      raise TypeError, \
+          'Attempt to merge dict value of unsupported type ' + \
+          v.__class__.__name__ + ' for key ' + k
+
+
+def MergeConfigWithInheritance(new_configuration_dict, build_file,
+                               target_dict, configuration, visited):
+  # Skip if previously visted.
+  if configuration in visited:
+    return
+
+  # Look at this configuration.
+  configuration_dict = target_dict['configurations'][configuration]
+
+  # Merge in parents.
+  for parent in configuration_dict.get('inherit_from', []):
+    MergeConfigWithInheritance(new_configuration_dict, build_file,
+                               target_dict, parent, visited + [configuration])
+
+  # Merge it into the new config.
+  MergeDicts(new_configuration_dict, configuration_dict,
+             build_file, build_file)
+
+  # Drop abstract.
+  if 'abstract' in new_configuration_dict:
+    del new_configuration_dict['abstract']
+
+
+def SetUpConfigurations(target, target_dict):
+  # key_suffixes is a list of key suffixes that might appear on key names.
+  # These suffixes are handled in conditional evaluations (for =, +, and ?)
+  # and rules/exclude processing (for ! and /).  Keys with these suffixes
+  # should be treated the same as keys without.
+  key_suffixes = ['=', '+', '?', '!', '/']
+
+  build_file = gyp.common.BuildFile(target)
+
+  # Provide a single configuration by default if none exists.
+  # TODO(mark): Signal an error if default_configurations exists but
+  # configurations does not.
+  if not 'configurations' in target_dict:
+    target_dict['configurations'] = {'Default': {}}
+  if not 'default_configuration' in target_dict:
+    concrete = [i for i in target_dict['configurations'].iterkeys()
+                if not target_dict['configurations'][i].get('abstract')]
+    target_dict['default_configuration'] = sorted(concrete)[0]
+
+  for configuration in target_dict['configurations'].keys():
+    old_configuration_dict = target_dict['configurations'][configuration]
+    # Skip abstract configurations (saves work only).
+    if old_configuration_dict.get('abstract'):
+      continue
+    # Configurations inherit (most) settings from the enclosing target scope.
+    # Get the inheritance relationship right by making a copy of the target
+    # dict.
+    new_configuration_dict = copy.deepcopy(target_dict)
+
+    # Take out the bits that don't belong in a "configurations" section.
+    # Since configuration setup is done before conditional, exclude, and rules
+    # processing, be careful with handling of the suffix characters used in
+    # those phases.
+    delete_keys = []
+    for key in new_configuration_dict:
+      key_ext = key[-1:]
+      if key_ext in key_suffixes:
+        key_base = key[:-1]
+      else:
+        key_base = key
+      if key_base in non_configuration_keys:
+        delete_keys.append(key)
+
+    for key in delete_keys:
+      del new_configuration_dict[key]
+
+    # Merge in configuration (with all its parents first).
+    MergeConfigWithInheritance(new_configuration_dict, build_file,
+                               target_dict, configuration, [])
+
+    # Put the new result back into the target dict as a configuration.
+    target_dict['configurations'][configuration] = new_configuration_dict
+
+  # Now drop all the abstract ones.
+  for configuration in target_dict['configurations'].keys():
+    old_configuration_dict = target_dict['configurations'][configuration]
+    if old_configuration_dict.get('abstract'):
+      del target_dict['configurations'][configuration]
+
+  # Now that all of the target's configurations have been built, go through
+  # the target dict's keys and remove everything that's been moved into a
+  # "configurations" section.
+  delete_keys = []
+  for key in target_dict:
+    key_ext = key[-1:]
+    if key_ext in key_suffixes:
+      key_base = key[:-1]
+    else:
+      key_base = key
+    if not key_base in non_configuration_keys:
+      delete_keys.append(key)
+  for key in delete_keys:
+    del target_dict[key]
+
+  # Check the configurations to see if they contain invalid keys.
+  for configuration in target_dict['configurations'].keys():
+    configuration_dict = target_dict['configurations'][configuration]
+    for key in configuration_dict.keys():
+      if key in invalid_configuration_keys:
+        raise GypError('%s not allowed in the %s configuration, found in '
+                       'target %s' % (key, configuration, target))
+
+
+
+def ProcessListFiltersInDict(name, the_dict):
+  """Process regular expression and exclusion-based filters on lists.
+
+  An exclusion list is in a dict key named with a trailing "!", like
+  "sources!".  Every item in such a list is removed from the associated
+  main list, which in this example, would be "sources".  Removed items are
+  placed into a "sources_excluded" list in the dict.
+
+  Regular expression (regex) filters are contained in dict keys named with a
+  trailing "/", such as "sources/" to operate on the "sources" list.  Regex
+  filters in a dict take the form:
+    'sources/': [ ['exclude', '_(linux|mac|win)\\.cc$'],
+                  ['include', '_mac\\.cc$'] ],
+  The first filter says to exclude all files ending in _linux.cc, _mac.cc, and
+  _win.cc.  The second filter then includes all files ending in _mac.cc that
+  are now or were once in the "sources" list.  Items matching an "exclude"
+  filter are subject to the same processing as would occur if they were listed
+  by name in an exclusion list (ending in "!").  Items matching an "include"
+  filter are brought back into the main list if previously excluded by an
+  exclusion list or exclusion regex filter.  Subsequent matching "exclude"
+  patterns can still cause items to be excluded after matching an "include".
+  """
+
+  # Look through the dictionary for any lists whose keys end in "!" or "/".
+  # These are lists that will be treated as exclude lists and regular
+  # expression-based exclude/include lists.  Collect the lists that are
+  # needed first, looking for the lists that they operate on, and assemble
+  # then into |lists|.  This is done in a separate loop up front, because
+  # the _included and _excluded keys need to be added to the_dict, and that
+  # can't be done while iterating through it.
+
+  lists = []
+  del_lists = []
+  for key, value in the_dict.iteritems():
+    operation = key[-1]
+    if operation != '!' and operation != '/':
+      continue
+
+    if not isinstance(value, list):
+      raise ValueError, name + ' key ' + key + ' must be list, not ' + \
+                        value.__class__.__name__
+
+    list_key = key[:-1]
+    if list_key not in the_dict:
+      # This happens when there's a list like "sources!" but no corresponding
+      # "sources" list.  Since there's nothing for it to operate on, queue up
+      # the "sources!" list for deletion now.
+      del_lists.append(key)
+      continue
+
+    if not isinstance(the_dict[list_key], list):
+      raise ValueError, name + ' key ' + list_key + \
+                        ' must be list, not ' + \
+                        value.__class__.__name__ + ' when applying ' + \
+                        {'!': 'exclusion', '/': 'regex'}[operation]
+
+    if not list_key in lists:
+      lists.append(list_key)
+
+  # Delete the lists that are known to be unneeded at this point.
+  for del_list in del_lists:
+    del the_dict[del_list]
+
+  for list_key in lists:
+    the_list = the_dict[list_key]
+
+    # Initialize the list_actions list, which is parallel to the_list.  Each
+    # item in list_actions identifies whether the corresponding item in
+    # the_list should be excluded, unconditionally preserved (included), or
+    # whether no exclusion or inclusion has been applied.  Items for which
+    # no exclusion or inclusion has been applied (yet) have value -1, items
+    # excluded have value 0, and items included have value 1.  Includes and
+    # excludes override previous actions.  All items in list_actions are
+    # initialized to -1 because no excludes or includes have been processed
+    # yet.
+    list_actions = list((-1,) * len(the_list))
+
+    exclude_key = list_key + '!'
+    if exclude_key in the_dict:
+      for exclude_item in the_dict[exclude_key]:
+        for index in xrange(0, len(the_list)):
+          if exclude_item == the_list[index]:
+            # This item matches the exclude_item, so set its action to 0
+            # (exclude).
+            list_actions[index] = 0
+
+      # The "whatever!" list is no longer needed, dump it.
+      del the_dict[exclude_key]
+
+    regex_key = list_key + '/'
+    if regex_key in the_dict:
+      for regex_item in the_dict[regex_key]:
+        [action, pattern] = regex_item
+        pattern_re = re.compile(pattern)
+
+        if action == 'exclude':
+          # This item matches an exclude regex, so set its value to 0 (exclude).
+          action_value = 0
+        elif action == 'include':
+          # This item matches an include regex, so set its value to 1 (include).
+          action_value = 1
+        else:
+          # This is an action that doesn't make any sense.
+          raise ValueError, 'Unrecognized action ' + action + ' in ' + name + \
+                            ' key ' + regex_key
+
+        for index in xrange(0, len(the_list)):
+          list_item = the_list[index]
+          if list_actions[index] == action_value:
+            # Even if the regex matches, nothing will change so continue (regex
+            # searches are expensive).
+            continue
+          if pattern_re.search(list_item):
+            # Regular expression match.
+            list_actions[index] = action_value
+
+      # The "whatever/" list is no longer needed, dump it.
+      del the_dict[regex_key]
+
+    # Add excluded items to the excluded list.
+    #
+    # Note that exclude_key ("sources!") is different from excluded_key
+    # ("sources_excluded").  The exclude_key list is input and it was already
+    # processed and deleted; the excluded_key list is output and it's about
+    # to be created.
+    excluded_key = list_key + '_excluded'
+    if excluded_key in the_dict:
+      raise GypError(name + ' key ' + excluded_key +
+                     ' must not be present prior '
+                     ' to applying exclusion/regex filters for ' + list_key)
+
+    excluded_list = []
+
+    # Go backwards through the list_actions list so that as items are deleted,
+    # the indices of items that haven't been seen yet don't shift.  That means
+    # that things need to be prepended to excluded_list to maintain them in the
+    # same order that they existed in the_list.
+    for index in xrange(len(list_actions) - 1, -1, -1):
+      if list_actions[index] == 0:
+        # Dump anything with action 0 (exclude).  Keep anything with action 1
+        # (include) or -1 (no include or exclude seen for the item).
+        excluded_list.insert(0, the_list[index])
+        del the_list[index]
+
+    # If anything was excluded, put the excluded list into the_dict at
+    # excluded_key.
+    if len(excluded_list) > 0:
+      the_dict[excluded_key] = excluded_list
+
+  # Now recurse into subdicts and lists that may contain dicts.
+  for key, value in the_dict.iteritems():
+    if isinstance(value, dict):
+      ProcessListFiltersInDict(key, value)
+    elif isinstance(value, list):
+      ProcessListFiltersInList(key, value)
+
+
+def ProcessListFiltersInList(name, the_list):
+  for item in the_list:
+    if isinstance(item, dict):
+      ProcessListFiltersInDict(name, item)
+    elif isinstance(item, list):
+      ProcessListFiltersInList(name, item)
+
+
+def ValidateTargetType(target, target_dict):
+  """Ensures the 'type' field on the target is one of the known types.
+
+  Arguments:
+    target: string, name of target.
+    target_dict: dict, target spec.
+
+  Raises an exception on error.
+  """
+  VALID_TARGET_TYPES = ('executable', 'loadable_module',
+                        'static_library', 'shared_library',
+                        'none')
+  target_type = target_dict.get('type', None)
+  if target_type not in VALID_TARGET_TYPES:
+    raise GypError("Target %s has an invalid target type '%s'.  "
+                   "Must be one of %s." %
+                   (target, target_type, '/'.join(VALID_TARGET_TYPES)))
+  if (target_dict.get('standalone_static_library', 0) and
+      not target_type == 'static_library'):
+    raise GypError('Target %s has type %s but standalone_static_library flag is'
+                   ' only valid for static_library type.' % (target,
+                                                             target_type))
+
+
+def ValidateSourcesInTarget(target, target_dict, build_file):
+  # TODO: Check if MSVC allows this for loadable_module targets.
+  if target_dict.get('type', None) not in ('static_library', 'shared_library'):
+    return
+  sources = target_dict.get('sources', [])
+  basenames = {}
+  for source in sources:
+    name, ext = os.path.splitext(source)
+    is_compiled_file = ext in [
+        '.c', '.cc', '.cpp', '.cxx', '.m', '.mm', '.s', '.S']
+    if not is_compiled_file:
+      continue
+    basename = os.path.basename(name)  # Don't include extension.
+    basenames.setdefault(basename, []).append(source)
+
+  error = ''
+  for basename, files in basenames.iteritems():
+    if len(files) > 1:
+      error += '  %s: %s\n' % (basename, ' '.join(files))
+
+  if error:
+    print('static library %s has several files with the same basename:\n' %
+          target + error + 'Some build systems, e.g. MSVC08, '
+          'cannot handle that.')
+    raise GypError('Duplicate basenames in sources section, see list above')
+
+
+def ValidateRulesInTarget(target, target_dict, extra_sources_for_rules):
+  """Ensures that the rules sections in target_dict are valid and consistent,
+  and determines which sources they apply to.
+
+  Arguments:
+    target: string, name of target.
+    target_dict: dict, target spec containing "rules" and "sources" lists.
+    extra_sources_for_rules: a list of keys to scan for rule matches in
+        addition to 'sources'.
+  """
+
+  # Dicts to map between values found in rules' 'rule_name' and 'extension'
+  # keys and the rule dicts themselves.
+  rule_names = {}
+  rule_extensions = {}
+
+  rules = target_dict.get('rules', [])
+  for rule in rules:
+    # Make sure that there's no conflict among rule names and extensions.
+    rule_name = rule['rule_name']
+    if rule_name in rule_names:
+      raise GypError('rule %s exists in duplicate, target %s' %
+                     (rule_name, target))
+    rule_names[rule_name] = rule
+
+    rule_extension = rule['extension']
+    if rule_extension in rule_extensions:
+      raise GypError(('extension %s associated with multiple rules, ' +
+                      'target %s rules %s and %s') %
+                     (rule_extension, target,
+                      rule_extensions[rule_extension]['rule_name'],
+                      rule_name))
+    rule_extensions[rule_extension] = rule
+
+    # Make sure rule_sources isn't already there.  It's going to be
+    # created below if needed.
+    if 'rule_sources' in rule:
+      raise GypError(
+            'rule_sources must not exist in input, target %s rule %s' %
+            (target, rule_name))
+    extension = rule['extension']
+
+    rule_sources = []
+    source_keys = ['sources']
+    source_keys.extend(extra_sources_for_rules)
+    for source_key in source_keys:
+      for source in target_dict.get(source_key, []):
+        (source_root, source_extension) = os.path.splitext(source)
+        if source_extension.startswith('.'):
+          source_extension = source_extension[1:]
+        if source_extension == extension:
+          rule_sources.append(source)
+
+    if len(rule_sources) > 0:
+      rule['rule_sources'] = rule_sources
+
+
+def ValidateRunAsInTarget(target, target_dict, build_file):
+  target_name = target_dict.get('target_name')
+  run_as = target_dict.get('run_as')
+  if not run_as:
+    return
+  if not isinstance(run_as, dict):
+    raise GypError("The 'run_as' in target %s from file %s should be a "
+                   "dictionary." %
+                   (target_name, build_file))
+  action = run_as.get('action')
+  if not action:
+    raise GypError("The 'run_as' in target %s from file %s must have an "
+                   "'action' section." %
+                   (target_name, build_file))
+  if not isinstance(action, list):
+    raise GypError("The 'action' for 'run_as' in target %s from file %s "
+                   "must be a list." %
+                   (target_name, build_file))
+  working_directory = run_as.get('working_directory')
+  if working_directory and not isinstance(working_directory, str):
+    raise GypError("The 'working_directory' for 'run_as' in target %s "
+                   "in file %s should be a string." %
+                   (target_name, build_file))
+  environment = run_as.get('environment')
+  if environment and not isinstance(environment, dict):
+    raise GypError("The 'environment' for 'run_as' in target %s "
+                   "in file %s should be a dictionary." %
+                   (target_name, build_file))
+
+
+def ValidateActionsInTarget(target, target_dict, build_file):
+  '''Validates the inputs to the actions in a target.'''
+  target_name = target_dict.get('target_name')
+  actions = target_dict.get('actions', [])
+  for action in actions:
+    action_name = action.get('action_name')
+    if not action_name:
+      raise GypError("Anonymous action in target %s.  "
+                     "An action must have an 'action_name' field." %
+                     target_name)
+    inputs = action.get('inputs', None)
+    if inputs is None:
+      raise GypError('Action in target %s has no inputs.' % target_name)
+    action_command = action.get('action')
+    if action_command and not action_command[0]:
+      raise GypError("Empty action as command in target %s." % target_name)
+
+
+def TurnIntIntoStrInDict(the_dict):
+  """Given dict the_dict, recursively converts all integers into strings.
+  """
+  # Use items instead of iteritems because there's no need to try to look at
+  # reinserted keys and their associated values.
+  for k, v in the_dict.items():
+    if isinstance(v, int):
+      v = str(v)
+      the_dict[k] = v
+    elif isinstance(v, dict):
+      TurnIntIntoStrInDict(v)
+    elif isinstance(v, list):
+      TurnIntIntoStrInList(v)
+
+    if isinstance(k, int):
+      the_dict[str(k)] = v
+      del the_dict[k]
+
+
+def TurnIntIntoStrInList(the_list):
+  """Given list the_list, recursively converts all integers into strings.
+  """
+  for index in xrange(0, len(the_list)):
+    item = the_list[index]
+    if isinstance(item, int):
+      the_list[index] = str(item)
+    elif isinstance(item, dict):
+      TurnIntIntoStrInDict(item)
+    elif isinstance(item, list):
+      TurnIntIntoStrInList(item)
+
+
+def VerifyNoCollidingTargets(targets):
+  """Verify that no two targets in the same directory share the same name.
+
+  Arguments:
+    targets: A list of targets in the form 'path/to/file.gyp:target_name'.
+  """
+  # Keep a dict going from 'subdirectory:target_name' to 'foo.gyp'.
+  used = {}
+  for target in targets:
+    # Separate out 'path/to/file.gyp, 'target_name' from
+    # 'path/to/file.gyp:target_name'.
+    path, name = target.rsplit(':', 1)
+    # Separate out 'path/to', 'file.gyp' from 'path/to/file.gyp'.
+    subdir, gyp = os.path.split(path)
+    # Use '.' for the current directory '', so that the error messages make
+    # more sense.
+    if not subdir:
+      subdir = '.'
+    # Prepare a key like 'path/to:target_name'.
+    key = subdir + ':' + name
+    if key in used:
+      # Complain if this target is already used.
+      raise GypError('Duplicate target name "%s" in directory "%s" used both '
+                     'in "%s" and "%s".' % (name, subdir, gyp, used[key]))
+    used[key] = gyp
+
+
+def Load(build_files, variables, includes, depth, generator_input_info, check,
+         circular_check, parallel):
+  # Set up path_sections and non_configuration_keys with the default data plus
+  # the generator-specifc data.
+  global path_sections
+  path_sections = base_path_sections[:]
+  path_sections.extend(generator_input_info['path_sections'])
+
+  global non_configuration_keys
+  non_configuration_keys = base_non_configuration_keys[:]
+  non_configuration_keys.extend(generator_input_info['non_configuration_keys'])
+
+  # TODO(mark) handle variants if the generator doesn't want them directly.
+  generator_handles_variants = \
+      generator_input_info['generator_handles_variants']
+
+  global absolute_build_file_paths
+  absolute_build_file_paths = \
+      generator_input_info['generator_wants_absolute_build_file_paths']
+
+  global multiple_toolsets
+  multiple_toolsets = generator_input_info[
+      'generator_supports_multiple_toolsets']
+
+  # A generator can have other lists (in addition to sources) be processed
+  # for rules.
+  extra_sources_for_rules = generator_input_info['extra_sources_for_rules']
+
+  # Load build files.  This loads every target-containing build file into
+  # the |data| dictionary such that the keys to |data| are build file names,
+  # and the values are the entire build file contents after "early" or "pre"
+  # processing has been done and includes have been resolved.
+  # NOTE: data contains both "target" files (.gyp) and "includes" (.gypi), as
+  # well as meta-data (e.g. 'included_files' key). 'target_build_files' keeps
+  # track of the keys corresponding to "target" files.
+  data = {'target_build_files': set()}
+  aux_data = {}
+  for build_file in build_files:
+    # Normalize paths everywhere.  This is important because paths will be
+    # used as keys to the data dict and for references between input files.
+    build_file = os.path.normpath(build_file)
+    try:
+      if parallel:
+        print >>sys.stderr, 'Using parallel processing.'
+        LoadTargetBuildFileParallel(build_file, data, aux_data,
+                                    variables, includes, depth, check)
+      else:
+        LoadTargetBuildFile(build_file, data, aux_data,
+                            variables, includes, depth, check, True)
+    except Exception, e:
+      gyp.common.ExceptionAppend(e, 'while trying to load %s' % build_file)
+      raise
+
+  # Build a dict to access each target's subdict by qualified name.
+  targets = BuildTargetsDict(data)
+
+  # Fully qualify all dependency links.
+  QualifyDependencies(targets)
+
+  # Remove self-dependencies from targets that have 'prune_self_dependencies'
+  # set to 1.
+  RemoveSelfDependencies(targets)
+
+  # Expand dependencies specified as build_file:*.
+  ExpandWildcardDependencies(targets, data)
+
+  # Apply exclude (!) and regex (/) list filters only for dependency_sections.
+  for target_name, target_dict in targets.iteritems():
+    tmp_dict = {}
+    for key_base in dependency_sections:
+      for op in ('', '!', '/'):
+        key = key_base + op
+        if key in target_dict:
+          tmp_dict[key] = target_dict[key]
+          del target_dict[key]
+    ProcessListFiltersInDict(target_name, tmp_dict)
+    # Write the results back to |target_dict|.
+    for key in tmp_dict:
+      target_dict[key] = tmp_dict[key]
+
+  # Make sure every dependency appears at most once.
+  RemoveDuplicateDependencies(targets)
+
+  if circular_check:
+    # Make sure that any targets in a.gyp don't contain dependencies in other
+    # .gyp files that further depend on a.gyp.
+    VerifyNoGYPFileCircularDependencies(targets)
+
+  [dependency_nodes, flat_list] = BuildDependencyList(targets)
+
+  # Check that no two targets in the same directory have the same name.
+  VerifyNoCollidingTargets(flat_list)
+
+  # Handle dependent settings of various types.
+  for settings_type in ['all_dependent_settings',
+                        'direct_dependent_settings',
+                        'link_settings']:
+    DoDependentSettings(settings_type, flat_list, targets, dependency_nodes)
+
+    # Take out the dependent settings now that they've been published to all
+    # of the targets that require them.
+    for target in flat_list:
+      if settings_type in targets[target]:
+        del targets[target][settings_type]
+
+  # Make sure static libraries don't declare dependencies on other static
+  # libraries, but that linkables depend on all unlinked static libraries
+  # that they need so that their link steps will be correct.
+  gii = generator_input_info
+  if gii['generator_wants_static_library_dependencies_adjusted']:
+    AdjustStaticLibraryDependencies(flat_list, targets, dependency_nodes,
+                                    gii['generator_wants_sorted_dependencies'])
+
+  # Apply "post"/"late"/"target" variable expansions and condition evaluations.
+  for target in flat_list:
+    target_dict = targets[target]
+    build_file = gyp.common.BuildFile(target)
+    ProcessVariablesAndConditionsInDict(
+        target_dict, PHASE_LATE, variables, build_file)
+
+  # Move everything that can go into a "configurations" section into one.
+  for target in flat_list:
+    target_dict = targets[target]
+    SetUpConfigurations(target, target_dict)
+
+  # Apply exclude (!) and regex (/) list filters.
+  for target in flat_list:
+    target_dict = targets[target]
+    ProcessListFiltersInDict(target, target_dict)
+
+  # Apply "latelate" variable expansions and condition evaluations.
+  for target in flat_list:
+    target_dict = targets[target]
+    build_file = gyp.common.BuildFile(target)
+    ProcessVariablesAndConditionsInDict(
+        target_dict, PHASE_LATELATE, variables, build_file)
+
+  # Make sure that the rules make sense, and build up rule_sources lists as
+  # needed.  Not all generators will need to use the rule_sources lists, but
+  # some may, and it seems best to build the list in a common spot.
+  # Also validate actions and run_as elements in targets.
+  for target in flat_list:
+    target_dict = targets[target]
+    build_file = gyp.common.BuildFile(target)
+    ValidateTargetType(target, target_dict)
+    # TODO(thakis): Get vpx_scale/arm/scalesystemdependent.c to be renamed to
+    #               scalesystemdependent_arm_additions.c or similar.
+    if 'arm' not in variables.get('target_arch', ''):
+      ValidateSourcesInTarget(target, target_dict, build_file)
+    ValidateRulesInTarget(target, target_dict, extra_sources_for_rules)
+    ValidateRunAsInTarget(target, target_dict, build_file)
+    ValidateActionsInTarget(target, target_dict, build_file)
+
+  # Generators might not expect ints.  Turn them into strs.
+  TurnIntIntoStrInDict(data)
+
+  # TODO(mark): Return |data| for now because the generator needs a list of
+  # build files that came in.  In the future, maybe it should just accept
+  # a list, and not the whole data dict.
+  return [flat_list, targets, data]
diff --git a/webWidgetTCT_device/tools/gyp/pylib/gyp/mac_tool.py b/webWidgetTCT_device/tools/gyp/pylib/gyp/mac_tool.py
new file mode 100755 (executable)
index 0000000..c06e3be
--- /dev/null
@@ -0,0 +1,223 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Utility functions to perform Xcode-style build steps.
+
+These functions are executed via gyp-mac-tool when using the Makefile generator.
+"""
+
+import fcntl
+import os
+import plistlib
+import re
+import shutil
+import string
+import subprocess
+import sys
+
+
+def main(args):
+  executor = MacTool()
+  exit_code = executor.Dispatch(args)
+  if exit_code is not None:
+    sys.exit(exit_code)
+
+
+class MacTool(object):
+  """This class performs all the Mac tooling steps. The methods can either be
+  executed directly, or dispatched from an argument list."""
+
+  def Dispatch(self, args):
+    """Dispatches a string command to a method."""
+    if len(args) < 1:
+      raise Exception("Not enough arguments")
+
+    method = "Exec%s" % self._CommandifyName(args[0])
+    return getattr(self, method)(*args[1:])
+
+  def _CommandifyName(self, name_string):
+    """Transforms a tool name like copy-info-plist to CopyInfoPlist"""
+    return name_string.title().replace('-', '')
+
+  def ExecCopyBundleResource(self, source, dest):
+    """Copies a resource file to the bundle/Resources directory, performing any
+    necessary compilation on each resource."""
+    extension = os.path.splitext(source)[1].lower()
+    if os.path.isdir(source):
+      # Copy tree.
+      if os.path.exists(dest):
+        shutil.rmtree(dest)
+      shutil.copytree(source, dest)
+    elif extension == '.xib':
+      return self._CopyXIBFile(source, dest)
+    elif extension == '.strings':
+      self._CopyStringsFile(source, dest)
+    else:
+      shutil.copyfile(source, dest)
+
+  def _CopyXIBFile(self, source, dest):
+    """Compiles a XIB file with ibtool into a binary plist in the bundle."""
+    tools_dir = os.environ.get('DEVELOPER_BIN_DIR', '/usr/bin')
+    args = [os.path.join(tools_dir, 'ibtool'), '--errors', '--warnings',
+        '--notices', '--output-format', 'human-readable-text', '--compile',
+        dest, source]
+    ibtool_section_re = re.compile(r'/\*.*\*/')
+    ibtool_re = re.compile(r'.*note:.*is clipping its content')
+    ibtoolout = subprocess.Popen(args, stdout=subprocess.PIPE)
+    current_section_header = None
+    for line in ibtoolout.stdout:
+      if ibtool_section_re.match(line):
+        current_section_header = line
+      elif not ibtool_re.match(line):
+        if current_section_header:
+          sys.stdout.write(current_section_header)
+          current_section_header = None
+        sys.stdout.write(line)
+    return ibtoolout.returncode
+
+  def _CopyStringsFile(self, source, dest):
+    """Copies a .strings file using iconv to reconvert the input into UTF-16."""
+    input_code = self._DetectInputEncoding(source) or "UTF-8"
+
+    # Xcode's CpyCopyStringsFile / builtin-copyStrings seems to call
+    # CFPropertyListCreateFromXMLData() behind the scenes; at least it prints
+    #     CFPropertyListCreateFromXMLData(): Old-style plist parser: missing
+    #     semicolon in dictionary.
+    # on invalid files. Do the same kind of validation.
+    import CoreFoundation
+    s = open(source).read()
+    d = CoreFoundation.CFDataCreate(None, s, len(s))
+    _, error = CoreFoundation.CFPropertyListCreateFromXMLData(None, d, 0, None)
+    if error:
+      return
+
+    fp = open(dest, 'w')
+    args = ['/usr/bin/iconv', '--from-code', input_code, '--to-code',
+        'UTF-16', source]
+    subprocess.call(args, stdout=fp)
+    fp.close()
+
+  def _DetectInputEncoding(self, file_name):
+    """Reads the first few bytes from file_name and tries to guess the text
+    encoding. Returns None as a guess if it can't detect it."""
+    fp = open(file_name, 'rb')
+    try:
+      header = fp.read(3)
+    except e:
+      fp.close()
+      return None
+    fp.close()
+    if header.startswith("\xFE\xFF"):
+      return "UTF-16BE"
+    elif header.startswith("\xFF\xFE"):
+      return "UTF-16LE"
+    elif header.startswith("\xEF\xBB\xBF"):
+      return "UTF-8"
+    else:
+      return None
+
+  def ExecCopyInfoPlist(self, source, dest):
+    """Copies the |source| Info.plist to the destination directory |dest|."""
+    # Read the source Info.plist into memory.
+    fd = open(source, 'r')
+    lines = fd.read()
+    fd.close()
+
+    # Go through all the environment variables and replace them as variables in
+    # the file.
+    for key in os.environ:
+      if key.startswith('_'):
+        continue
+      evar = '${%s}' % key
+      lines = string.replace(lines, evar, os.environ[key])
+
+    # Write out the file with variables replaced.
+    fd = open(dest, 'w')
+    fd.write(lines)
+    fd.close()
+
+    # Now write out PkgInfo file now that the Info.plist file has been
+    # "compiled".
+    self._WritePkgInfo(dest)
+
+  def _WritePkgInfo(self, info_plist):
+    """This writes the PkgInfo file from the data stored in Info.plist."""
+    plist = plistlib.readPlist(info_plist)
+    if not plist:
+      return
+
+    # Only create PkgInfo for executable types.
+    package_type = plist['CFBundlePackageType']
+    if package_type != 'APPL':
+      return
+
+    # The format of PkgInfo is eight characters, representing the bundle type
+    # and bundle signature, each four characters. If that is missing, four
+    # '?' characters are used instead.
+    signature_code = plist.get('CFBundleSignature', '????')
+    if len(signature_code) != 4:  # Wrong length resets everything, too.
+      signature_code = '?' * 4
+
+    dest = os.path.join(os.path.dirname(info_plist), 'PkgInfo')
+    fp = open(dest, 'w')
+    fp.write('%s%s' % (package_type, signature_code))
+    fp.close()
+
+  def ExecFlock(self, lockfile, *cmd_list):
+    """Emulates the most basic behavior of Linux's flock(1)."""
+    # Rely on exception handling to report errors.
+    fd = os.open(lockfile, os.O_RDONLY|os.O_NOCTTY|os.O_CREAT, 0o666)
+    fcntl.flock(fd, fcntl.LOCK_EX)
+    return subprocess.call(cmd_list)
+
+  def ExecFilterLibtool(self, *cmd_list):
+    """Calls libtool and filters out 'libtool: file: foo.o has no symbols'."""
+    libtool_re = re.compile(r'^libtool: file: .* has no symbols$')
+    libtoolout = subprocess.Popen(cmd_list, stderr=subprocess.PIPE)
+    _, err = libtoolout.communicate()
+    for line in err.splitlines():
+      if not libtool_re.match(line):
+        print >>sys.stderr, line
+    return libtoolout.returncode
+
+  def ExecPackageFramework(self, framework, version):
+    """Takes a path to Something.framework and the Current version of that and
+    sets up all the symlinks."""
+    # Find the name of the binary based on the part before the ".framework".
+    binary = os.path.basename(framework).split('.')[0]
+
+    CURRENT = 'Current'
+    RESOURCES = 'Resources'
+    VERSIONS = 'Versions'
+
+    if not os.path.exists(os.path.join(framework, VERSIONS, version, binary)):
+      # Binary-less frameworks don't seem to contain symlinks (see e.g.
+      # chromium's out/Debug/org.chromium.Chromium.manifest/ bundle).
+      return
+
+    # Move into the framework directory to set the symlinks correctly.
+    pwd = os.getcwd()
+    os.chdir(framework)
+
+    # Set up the Current version.
+    self._Relink(version, os.path.join(VERSIONS, CURRENT))
+
+    # Set up the root symlinks.
+    self._Relink(os.path.join(VERSIONS, CURRENT, binary), binary)
+    self._Relink(os.path.join(VERSIONS, CURRENT, RESOURCES), RESOURCES)
+
+    # Back to where we were before!
+    os.chdir(pwd)
+
+  def _Relink(self, dest, link):
+    """Creates a symlink to |dest| named |link|. If |link| already exists,
+    it is overwritten."""
+    if os.path.lexists(link):
+      os.remove(link)
+    os.symlink(dest, link)
+
+
+if __name__ == '__main__':
+  sys.exit(main(sys.argv[1:]))
diff --git a/webWidgetTCT_device/tools/gyp/pylib/gyp/msvs_emulation.py b/webWidgetTCT_device/tools/gyp/pylib/gyp/msvs_emulation.py
new file mode 100755 (executable)
index 0000000..bc2afca
--- /dev/null
@@ -0,0 +1,771 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""
+This module helps emulate Visual Studio 2008 behavior on top of other
+build systems, primarily ninja.
+"""
+
+import os
+import re
+import subprocess
+import sys
+
+import gyp.MSVSVersion
+
+windows_quoter_regex = re.compile(r'(\\*)"')
+
+def QuoteForRspFile(arg):
+  """Quote a command line argument so that it appears as one argument when
+  processed via cmd.exe and parsed by CommandLineToArgvW (as is typical for
+  Windows programs)."""
+  # See http://goo.gl/cuFbX and http://goo.gl/dhPnp including the comment
+  # threads. This is actually the quoting rules for CommandLineToArgvW, not
+  # for the shell, because the shell doesn't do anything in Windows. This
+  # works more or less because most programs (including the compiler, etc.)
+  # use that function to handle command line arguments.
+
+  # For a literal quote, CommandLineToArgvW requires 2n+1 backslashes
+  # preceding it, and results in n backslashes + the quote. So we substitute
+  # in 2* what we match, +1 more, plus the quote.
+  arg = windows_quoter_regex.sub(lambda mo: 2 * mo.group(1) + '\\"', arg)
+
+  # %'s also need to be doubled otherwise they're interpreted as batch
+  # positional arguments. Also make sure to escape the % so that they're
+  # passed literally through escaping so they can be singled to just the
+  # original %. Otherwise, trying to pass the literal representation that
+  # looks like an environment variable to the shell (e.g. %PATH%) would fail.
+  arg = arg.replace('%', '%%')
+
+  # These commands are used in rsp files, so no escaping for the shell (via ^)
+  # is necessary.
+
+  # Finally, wrap the whole thing in quotes so that the above quote rule
+  # applies and whitespace isn't a word break.
+  return '"' + arg + '"'
+
+
+def EncodeRspFileList(args):
+  """Process a list of arguments using QuoteCmdExeArgument."""
+  # Note that the first argument is assumed to be the command. Don't add
+  # quotes around it because then built-ins like 'echo', etc. won't work.
+  # Take care to normpath only the path in the case of 'call ../x.bat' because
+  # otherwise the whole thing is incorrectly interpreted as a path and not
+  # normalized correctly.
+  if not args: return ''
+  if args[0].startswith('call '):
+    call, program = args[0].split(' ', 1)
+    program = call + ' ' + os.path.normpath(program)
+  else:
+    program = os.path.normpath(args[0])
+  return program + ' ' + ' '.join(QuoteForRspFile(arg) for arg in args[1:])
+
+
+def _GenericRetrieve(root, default, path):
+  """Given a list of dictionary keys |path| and a tree of dicts |root|, find
+  value at path, or return |default| if any of the path doesn't exist."""
+  if not root:
+    return default
+  if not path:
+    return root
+  return _GenericRetrieve(root.get(path[0]), default, path[1:])
+
+
+def _AddPrefix(element, prefix):
+  """Add |prefix| to |element| or each subelement if element is iterable."""
+  if element is None:
+    return element
+  # Note, not Iterable because we don't want to handle strings like that.
+  if isinstance(element, list) or isinstance(element, tuple):
+    return [prefix + e for e in element]
+  else:
+    return prefix + element
+
+
+def _DoRemapping(element, map):
+  """If |element| then remap it through |map|. If |element| is iterable then
+  each item will be remapped. Any elements not found will be removed."""
+  if map is not None and element is not None:
+    if not callable(map):
+      map = map.get # Assume it's a dict, otherwise a callable to do the remap.
+    if isinstance(element, list) or isinstance(element, tuple):
+      element = filter(None, [map(elem) for elem in element])
+    else:
+      element = map(element)
+  return element
+
+
+def _AppendOrReturn(append, element):
+  """If |append| is None, simply return |element|. If |append| is not None,
+  then add |element| to it, adding each item in |element| if it's a list or
+  tuple."""
+  if append is not None and element is not None:
+    if isinstance(element, list) or isinstance(element, tuple):
+      append.extend(element)
+    else:
+      append.append(element)
+  else:
+    return element
+
+
+def _FindDirectXInstallation():
+  """Try to find an installation location for the DirectX SDK. Check for the
+  standard environment variable, and if that doesn't exist, try to find
+  via the registry. May return None if not found in either location."""
+  # Return previously calculated value, if there is one
+  if hasattr(_FindDirectXInstallation, 'dxsdk_dir'):
+    return _FindDirectXInstallation.dxsdk_dir
+
+  dxsdk_dir = os.environ.get('DXSDK_DIR')
+  if not dxsdk_dir:
+    # Setup params to pass to and attempt to launch reg.exe.
+    cmd = ['reg.exe', 'query', r'HKLM\Software\Microsoft\DirectX', '/s']
+    p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+    for line in p.communicate()[0].splitlines():
+      if 'InstallPath' in line:
+        dxsdk_dir = line.split('    ')[3] + "\\"
+
+  # Cache return value
+  _FindDirectXInstallation.dxsdk_dir = dxsdk_dir
+  return dxsdk_dir
+
+
+class MsvsSettings(object):
+  """A class that understands the gyp 'msvs_...' values (especially the
+  msvs_settings field). They largely correpond to the VS2008 IDE DOM. This
+  class helps map those settings to command line options."""
+
+  def __init__(self, spec, generator_flags):
+    self.spec = spec
+    self.vs_version = GetVSVersion(generator_flags)
+    self.dxsdk_dir = _FindDirectXInstallation()
+
+    # Try to find an installation location for the Windows DDK by checking
+    # the WDK_DIR environment variable, may be None.
+    self.wdk_dir = os.environ.get('WDK_DIR')
+
+    supported_fields = [
+        ('msvs_configuration_attributes', dict),
+        ('msvs_settings', dict),
+        ('msvs_system_include_dirs', list),
+        ('msvs_disabled_warnings', list),
+        ('msvs_precompiled_header', str),
+        ('msvs_precompiled_source', str),
+        ('msvs_configuration_platform', str),
+        ('msvs_target_platform', str),
+        ]
+    configs = spec['configurations']
+    for field, default in supported_fields:
+      setattr(self, field, {})
+      for configname, config in configs.iteritems():
+        getattr(self, field)[configname] = config.get(field, default())
+
+    self.msvs_cygwin_dirs = spec.get('msvs_cygwin_dirs', ['.'])
+
+  def GetVSMacroEnv(self, base_to_build=None, config=None):
+    """Get a dict of variables mapping internal VS macro names to their gyp
+    equivalents."""
+    target_platform = 'Win32' if self.GetArch(config) == 'x86' else 'x64'
+    replacements = {
+        '$(OutDir)\\': base_to_build + '\\' if base_to_build else '',
+        '$(IntDir)': '$!INTERMEDIATE_DIR',
+        '$(InputPath)': '${source}',
+        '$(InputName)': '${root}',
+        '$(ProjectName)': self.spec['target_name'],
+        '$(PlatformName)': target_platform,
+        '$(ProjectDir)\\': '',
+    }
+    # '$(VSInstallDir)' and '$(VCInstallDir)' are available when and only when
+    # Visual Studio is actually installed.
+    if self.vs_version.Path():
+      replacements['$(VSInstallDir)'] = self.vs_version.Path()
+      replacements['$(VCInstallDir)'] = os.path.join(self.vs_version.Path(),
+                                                     'VC') + '\\'
+    # Chromium uses DXSDK_DIR in include/lib paths, but it may or may not be
+    # set. This happens when the SDK is sync'd via src-internal, rather than
+    # by typical end-user installation of the SDK. If it's not set, we don't
+    # want to leave the unexpanded variable in the path, so simply strip it.
+    replacements['$(DXSDK_DIR)'] = self.dxsdk_dir if self.dxsdk_dir else ''
+    replacements['$(WDK_DIR)'] = self.wdk_dir if self.wdk_dir else ''
+    return replacements
+
+  def ConvertVSMacros(self, s, base_to_build=None, config=None):
+    """Convert from VS macro names to something equivalent."""
+    env = self.GetVSMacroEnv(base_to_build, config=config)
+    return ExpandMacros(s, env)
+
+  def AdjustLibraries(self, libraries):
+    """Strip -l from library if it's specified with that."""
+    return [lib[2:] if lib.startswith('-l') else lib for lib in libraries]
+
+  def _GetAndMunge(self, field, path, default, prefix, append, map):
+    """Retrieve a value from |field| at |path| or return |default|. If
+    |append| is specified, and the item is found, it will be appended to that
+    object instead of returned. If |map| is specified, results will be
+    remapped through |map| before being returned or appended."""
+    result = _GenericRetrieve(field, default, path)
+    result = _DoRemapping(result, map)
+    result = _AddPrefix(result, prefix)
+    return _AppendOrReturn(append, result)
+
+  class _GetWrapper(object):
+    def __init__(self, parent, field, base_path, append=None):
+      self.parent = parent
+      self.field = field
+      self.base_path = [base_path]
+      self.append = append
+    def __call__(self, name, map=None, prefix='', default=None):
+      return self.parent._GetAndMunge(self.field, self.base_path + [name],
+          default=default, prefix=prefix, append=self.append, map=map)
+
+  def GetArch(self, config):
+    """Get architecture based on msvs_configuration_platform and
+    msvs_target_platform. Returns either 'x86' or 'x64'."""
+    configuration_platform = self.msvs_configuration_platform.get(config, '')
+    platform = self.msvs_target_platform.get(config, '')
+    if not platform: # If no specific override, use the configuration's.
+      platform = configuration_platform
+    # Map from platform to architecture.
+    return {'Win32': 'x86', 'x64': 'x64'}.get(platform, 'x86')
+
+  def _TargetConfig(self, config):
+    """Returns the target-specific configuration."""
+    # There's two levels of architecture/platform specification in VS. The
+    # first level is globally for the configuration (this is what we consider
+    # "the" config at the gyp level, which will be something like 'Debug' or
+    # 'Release_x64'), and a second target-specific configuration, which is an
+    # override for the global one. |config| is remapped here to take into
+    # account the local target-specific overrides to the global configuration.
+    arch = self.GetArch(config)
+    if arch == 'x64' and not config.endswith('_x64'):
+      config += '_x64'
+    if arch == 'x86' and config.endswith('_x64'):
+      config = config.rsplit('_', 1)[0]
+    return config
+
+  def _Setting(self, path, config,
+              default=None, prefix='', append=None, map=None):
+    """_GetAndMunge for msvs_settings."""
+    return self._GetAndMunge(
+        self.msvs_settings[config], path, default, prefix, append, map)
+
+  def _ConfigAttrib(self, path, config,
+                   default=None, prefix='', append=None, map=None):
+    """_GetAndMunge for msvs_configuration_attributes."""
+    return self._GetAndMunge(
+        self.msvs_configuration_attributes[config],
+        path, default, prefix, append, map)
+
+  def AdjustIncludeDirs(self, include_dirs, config):
+    """Updates include_dirs to expand VS specific paths, and adds the system
+    include dirs used for platform SDK and similar."""
+    config = self._TargetConfig(config)
+    includes = include_dirs + self.msvs_system_include_dirs[config]
+    includes.extend(self._Setting(
+      ('VCCLCompilerTool', 'AdditionalIncludeDirectories'), config, default=[]))
+    return [self.ConvertVSMacros(p, config=config) for p in includes]
+
+  def GetComputedDefines(self, config):
+    """Returns the set of defines that are injected to the defines list based
+    on other VS settings."""
+    config = self._TargetConfig(config)
+    defines = []
+    if self._ConfigAttrib(['CharacterSet'], config) == '1':
+      defines.extend(('_UNICODE', 'UNICODE'))
+    if self._ConfigAttrib(['CharacterSet'], config) == '2':
+      defines.append('_MBCS')
+    defines.extend(self._Setting(
+        ('VCCLCompilerTool', 'PreprocessorDefinitions'), config, default=[]))
+    return defines
+
+  def GetCompilerPdbName(self, config, expand_special):
+    """Get the pdb file name that should be used for compiler invocations, or
+    None if there's no explicit name specified."""
+    config = self._TargetConfig(config)
+    pdbname = self._Setting(
+        ('VCCLCompilerTool', 'ProgramDataBaseFileName'), config)
+    if pdbname:
+      pdbname = expand_special(self.ConvertVSMacros(pdbname))
+    return pdbname
+
+  def GetOutputName(self, config, expand_special):
+    """Gets the explicitly overridden output name for a target or returns None
+    if it's not overridden."""
+    config = self._TargetConfig(config)
+    type = self.spec['type']
+    root = 'VCLibrarianTool' if type == 'static_library' else 'VCLinkerTool'
+    # TODO(scottmg): Handle OutputDirectory without OutputFile.
+    output_file = self._Setting((root, 'OutputFile'), config)
+    if output_file:
+      output_file = expand_special(self.ConvertVSMacros(
+          output_file, config=config))
+    return output_file
+
+  def GetPDBName(self, config, expand_special):
+    """Gets the explicitly overridden pdb name for a target or returns None
+    if it's not overridden."""
+    config = self._TargetConfig(config)
+    output_file = self._Setting(('VCLinkerTool', 'ProgramDatabaseFile'), config)
+    if output_file:
+      output_file = expand_special(self.ConvertVSMacros(
+          output_file, config=config))
+    return output_file
+
+  def GetCflags(self, config):
+    """Returns the flags that need to be added to .c and .cc compilations."""
+    config = self._TargetConfig(config)
+    cflags = []
+    cflags.extend(['/wd' + w for w in self.msvs_disabled_warnings[config]])
+    cl = self._GetWrapper(self, self.msvs_settings[config],
+                          'VCCLCompilerTool', append=cflags)
+    cl('Optimization',
+       map={'0': 'd', '1': '1', '2': '2', '3': 'x'}, prefix='/O')
+    cl('InlineFunctionExpansion', prefix='/Ob')
+    cl('OmitFramePointers', map={'false': '-', 'true': ''}, prefix='/Oy')
+    cl('EnableIntrinsicFunctions', map={'false': '-', 'true': ''}, prefix='/Oi')
+    cl('FavorSizeOrSpeed', map={'1': 't', '2': 's'}, prefix='/O')
+    cl('WholeProgramOptimization', map={'true': '/GL'})
+    cl('WarningLevel', prefix='/W')
+    cl('WarnAsError', map={'true': '/WX'})
+    cl('DebugInformationFormat',
+        map={'1': '7', '3': 'i', '4': 'I'}, prefix='/Z')
+    cl('RuntimeTypeInfo', map={'true': '/GR', 'false': '/GR-'})
+    cl('EnableFunctionLevelLinking', map={'true': '/Gy', 'false': '/Gy-'})
+    cl('MinimalRebuild', map={'true': '/Gm'})
+    cl('BufferSecurityCheck', map={'true': '/GS', 'false': '/GS-'})
+    cl('BasicRuntimeChecks', map={'1': 's', '2': 'u', '3': '1'}, prefix='/RTC')
+    cl('RuntimeLibrary',
+        map={'0': 'T', '1': 'Td', '2': 'D', '3': 'Dd'}, prefix='/M')
+    cl('ExceptionHandling', map={'1': 'sc','2': 'a'}, prefix='/EH')
+    cl('DefaultCharIsUnsigned', map={'true': '/J'})
+    cl('TreatWChar_tAsBuiltInType',
+        map={'false': '-', 'true': ''}, prefix='/Zc:wchar_t')
+    cl('EnablePREfast', map={'true': '/analyze'})
+    cl('AdditionalOptions', prefix='')
+    cflags.extend(['/FI' + f for f in self._Setting(
+        ('VCCLCompilerTool', 'ForcedIncludeFiles'), config, default=[])])
+    # ninja handles parallelism by itself, don't have the compiler do it too.
+    cflags = filter(lambda x: not x.startswith('/MP'), cflags)
+    return cflags
+
+  def GetPrecompiledHeader(self, config, gyp_to_build_path):
+    """Returns an object that handles the generation of precompiled header
+    build steps."""
+    config = self._TargetConfig(config)
+    return _PchHelper(self, config, gyp_to_build_path)
+
+  def _GetPchFlags(self, config, extension):
+    """Get the flags to be added to the cflags for precompiled header support.
+    """
+    config = self._TargetConfig(config)
+    # The PCH is only built once by a particular source file. Usage of PCH must
+    # only be for the same language (i.e. C vs. C++), so only include the pch
+    # flags when the language matches.
+    if self.msvs_precompiled_header[config]:
+      source_ext = os.path.splitext(self.msvs_precompiled_source[config])[1]
+      if _LanguageMatchesForPch(source_ext, extension):
+        pch = os.path.split(self.msvs_precompiled_header[config])[1]
+        return ['/Yu' + pch, '/FI' + pch, '/Fp${pchprefix}.' + pch + '.pch']
+    return  []
+
+  def GetCflagsC(self, config):
+    """Returns the flags that need to be added to .c compilations."""
+    config = self._TargetConfig(config)
+    return self._GetPchFlags(config, '.c')
+
+  def GetCflagsCC(self, config):
+    """Returns the flags that need to be added to .cc compilations."""
+    config = self._TargetConfig(config)
+    return ['/TP'] + self._GetPchFlags(config, '.cc')
+
+  def _GetAdditionalLibraryDirectories(self, root, config, gyp_to_build_path):
+    """Get and normalize the list of paths in AdditionalLibraryDirectories
+    setting."""
+    config = self._TargetConfig(config)
+    libpaths = self._Setting((root, 'AdditionalLibraryDirectories'),
+                             config, default=[])
+    libpaths = [os.path.normpath(
+                    gyp_to_build_path(self.ConvertVSMacros(p, config=config)))
+                for p in libpaths]
+    return ['/LIBPATH:"' + p + '"' for p in libpaths]
+
+  def GetLibFlags(self, config, gyp_to_build_path):
+    """Returns the flags that need to be added to lib commands."""
+    config = self._TargetConfig(config)
+    libflags = []
+    lib = self._GetWrapper(self, self.msvs_settings[config],
+                          'VCLibrarianTool', append=libflags)
+    libflags.extend(self._GetAdditionalLibraryDirectories(
+        'VCLibrarianTool', config, gyp_to_build_path))
+    lib('LinkTimeCodeGeneration', map={'true': '/LTCG'})
+    lib('AdditionalOptions')
+    return libflags
+
+  def _GetDefFileAsLdflags(self, spec, ldflags, gyp_to_build_path):
+    """.def files get implicitly converted to a ModuleDefinitionFile for the
+    linker in the VS generator. Emulate that behaviour here."""
+    def_file = ''
+    if spec['type'] in ('shared_library', 'loadable_module', 'executable'):
+      def_files = [s for s in spec.get('sources', []) if s.endswith('.def')]
+      if len(def_files) == 1:
+        ldflags.append('/DEF:"%s"' % gyp_to_build_path(def_files[0]))
+      elif len(def_files) > 1:
+        raise Exception("Multiple .def files")
+
+  def GetLdflags(self, config, gyp_to_build_path, expand_special,
+                 manifest_base_name, is_executable):
+    """Returns the flags that need to be added to link commands, and the
+    manifest files."""
+    config = self._TargetConfig(config)
+    ldflags = []
+    ld = self._GetWrapper(self, self.msvs_settings[config],
+                          'VCLinkerTool', append=ldflags)
+    self._GetDefFileAsLdflags(self.spec, ldflags, gyp_to_build_path)
+    ld('GenerateDebugInformation', map={'true': '/DEBUG'})
+    ld('TargetMachine', map={'1': 'X86', '17': 'X64'}, prefix='/MACHINE:')
+    ldflags.extend(self._GetAdditionalLibraryDirectories(
+        'VCLinkerTool', config, gyp_to_build_path))
+    ld('DelayLoadDLLs', prefix='/DELAYLOAD:')
+    out = self.GetOutputName(config, expand_special)
+    if out:
+      ldflags.append('/OUT:' + out)
+    pdb = self.GetPDBName(config, expand_special)
+    if pdb:
+      ldflags.append('/PDB:' + pdb)
+    ld('AdditionalOptions', prefix='')
+    ld('SubSystem', map={'1': 'CONSOLE', '2': 'WINDOWS'}, prefix='/SUBSYSTEM:')
+    ld('TerminalServerAware', map={'1': ':NO', '2': ''}, prefix='/TSAWARE')
+    ld('LinkIncremental', map={'1': ':NO', '2': ''}, prefix='/INCREMENTAL')
+    ld('FixedBaseAddress', map={'1': ':NO', '2': ''}, prefix='/FIXED')
+    ld('RandomizedBaseAddress',
+        map={'1': ':NO', '2': ''}, prefix='/DYNAMICBASE')
+    ld('DataExecutionPrevention',
+        map={'1': ':NO', '2': ''}, prefix='/NXCOMPAT')
+    ld('OptimizeReferences', map={'1': 'NOREF', '2': 'REF'}, prefix='/OPT:')
+    ld('EnableCOMDATFolding', map={'1': 'NOICF', '2': 'ICF'}, prefix='/OPT:')
+    ld('LinkTimeCodeGeneration', map={'1': '/LTCG'})
+    ld('IgnoreDefaultLibraryNames', prefix='/NODEFAULTLIB:')
+    ld('ResourceOnlyDLL', map={'true': '/NOENTRY'})
+    ld('EntryPointSymbol', prefix='/ENTRY:')
+    ld('Profile', map={'true': '/PROFILE'})
+    ld('LargeAddressAware',
+        map={'1': ':NO', '2': ''}, prefix='/LARGEADDRESSAWARE')
+    # TODO(scottmg): This should sort of be somewhere else (not really a flag).
+    ld('AdditionalDependencies', prefix='')
+
+    # If the base address is not specifically controlled, DYNAMICBASE should
+    # be on by default.
+    base_flags = filter(lambda x: 'DYNAMICBASE' in x or x == '/FIXED',
+                        ldflags)
+    if not base_flags:
+      ldflags.append('/DYNAMICBASE')
+
+    # If the NXCOMPAT flag has not been specified, default to on. Despite the
+    # documentation that says this only defaults to on when the subsystem is
+    # Vista or greater (which applies to the linker), the IDE defaults it on
+    # unless it's explicitly off.
+    if not filter(lambda x: 'NXCOMPAT' in x, ldflags):
+      ldflags.append('/NXCOMPAT')
+
+    have_def_file = filter(lambda x: x.startswith('/DEF:'), ldflags)
+    manifest_flags, intermediate_manifest_file = self._GetLdManifestFlags(
+        config, manifest_base_name, is_executable and not have_def_file)
+    ldflags.extend(manifest_flags)
+    manifest_files = self._GetAdditionalManifestFiles(config, gyp_to_build_path)
+    manifest_files.append(intermediate_manifest_file)
+
+    return ldflags, manifest_files
+
+  def _GetLdManifestFlags(self, config, name, allow_isolation):
+    """Returns the set of flags that need to be added to the link to generate
+    a default manifest, as well as the name of the generated file."""
+    # Add manifest flags that mirror the defaults in VS. Chromium dev builds
+    # do not currently use any non-default settings, but we could parse
+    # VCManifestTool blocks if Chromium or other projects need them in the
+    # future. Of particular note, we do not yet support EmbedManifest because
+    # it complicates incremental linking.
+    output_name = name + '.intermediate.manifest'
+    flags = [
+      '/MANIFEST',
+      '/ManifestFile:' + output_name,
+      '''/MANIFESTUAC:"level='asInvoker' uiAccess='false'"'''
+    ]
+    if allow_isolation:
+      flags.append('/ALLOWISOLATION')
+    return flags, output_name
+
+  def _GetAdditionalManifestFiles(self, config, gyp_to_build_path):
+    """Gets additional manifest files that are added to the default one
+    generated by the linker."""
+    files = self._Setting(('VCManifestTool', 'AdditionalManifestFiles'), config,
+                          default=[])
+    if (self._Setting(
+        ('VCManifestTool', 'EmbedManifest'), config, default='') == 'true'):
+      print 'gyp/msvs_emulation.py: "EmbedManifest: true" not yet supported.'
+    if isinstance(files, str):
+      files = files.split(';')
+    return [os.path.normpath(
+                gyp_to_build_path(self.ConvertVSMacros(f, config=config)))
+            for f in files]
+
+  def IsUseLibraryDependencyInputs(self, config):
+    """Returns whether the target should be linked via Use Library Dependency
+    Inputs (using component .objs of a given .lib)."""
+    config = self._TargetConfig(config)
+    uldi = self._Setting(('VCLinkerTool', 'UseLibraryDependencyInputs'), config)
+    return uldi == 'true'
+
+  def GetRcflags(self, config, gyp_to_ninja_path):
+    """Returns the flags that need to be added to invocations of the resource
+    compiler."""
+    config = self._TargetConfig(config)
+    rcflags = []
+    rc = self._GetWrapper(self, self.msvs_settings[config],
+        'VCResourceCompilerTool', append=rcflags)
+    rc('AdditionalIncludeDirectories', map=gyp_to_ninja_path, prefix='/I')
+    rcflags.append('/I' + gyp_to_ninja_path('.'))
+    rc('PreprocessorDefinitions', prefix='/d')
+    # /l arg must be in hex without leading '0x'
+    rc('Culture', prefix='/l', map=lambda x: hex(int(x))[2:])
+    return rcflags
+
+  def BuildCygwinBashCommandLine(self, args, path_to_base):
+    """Build a command line that runs args via cygwin bash. We assume that all
+    incoming paths are in Windows normpath'd form, so they need to be
+    converted to posix style for the part of the command line that's passed to
+    bash. We also have to do some Visual Studio macro emulation here because
+    various rules use magic VS names for things. Also note that rules that
+    contain ninja variables cannot be fixed here (for example ${source}), so
+    the outer generator needs to make sure that the paths that are written out
+    are in posix style, if the command line will be used here."""
+    cygwin_dir = os.path.normpath(
+        os.path.join(path_to_base, self.msvs_cygwin_dirs[0]))
+    cd = ('cd %s' % path_to_base).replace('\\', '/')
+    args = [a.replace('\\', '/').replace('"', '\\"') for a in args]
+    args = ["'%s'" % a.replace("'", "'\\''") for a in args]
+    bash_cmd = ' '.join(args)
+    cmd = (
+        'call "%s\\setup_env.bat" && set CYGWIN=nontsec && ' % cygwin_dir +
+        'bash -c "%s ; %s"' % (cd, bash_cmd))
+    return cmd
+
+  def IsRuleRunUnderCygwin(self, rule):
+    """Determine if an action should be run under cygwin. If the variable is
+    unset, or set to 1 we use cygwin."""
+    return int(rule.get('msvs_cygwin_shell',
+                        self.spec.get('msvs_cygwin_shell', 1))) != 0
+
+  def _HasExplicitRuleForExtension(self, spec, extension):
+    """Determine if there's an explicit rule for a particular extension."""
+    for rule in spec.get('rules', []):
+      if rule['extension'] == extension:
+        return True
+    return False
+
+  def HasExplicitIdlRules(self, spec):
+    """Determine if there's an explicit rule for idl files. When there isn't we
+    need to generate implicit rules to build MIDL .idl files."""
+    return self._HasExplicitRuleForExtension(spec, 'idl')
+
+  def HasExplicitAsmRules(self, spec):
+    """Determine if there's an explicit rule for asm files. When there isn't we
+    need to generate implicit rules to assemble .asm files."""
+    return self._HasExplicitRuleForExtension(spec, 'asm')
+
+  def GetIdlBuildData(self, source, config):
+    """Determine the implicit outputs for an idl file. Returns output
+    directory, outputs, and variables and flags that are required."""
+    config = self._TargetConfig(config)
+    midl_get = self._GetWrapper(self, self.msvs_settings[config], 'VCMIDLTool')
+    def midl(name, default=None):
+      return self.ConvertVSMacros(midl_get(name, default=default),
+                                  config=config)
+    tlb = midl('TypeLibraryName', default='${root}.tlb')
+    header = midl('HeaderFileName', default='${root}.h')
+    dlldata = midl('DLLDataFileName', default='dlldata.c')
+    iid = midl('InterfaceIdentifierFileName', default='${root}_i.c')
+    proxy = midl('ProxyFileName', default='${root}_p.c')
+    # Note that .tlb is not included in the outputs as it is not always
+    # generated depending on the content of the input idl file.
+    outdir = midl('OutputDirectory', default='')
+    output = [header, dlldata, iid, proxy]
+    variables = [('tlb', tlb),
+                 ('h', header),
+                 ('dlldata', dlldata),
+                 ('iid', iid),
+                 ('proxy', proxy)]
+    # TODO(scottmg): Are there configuration settings to set these flags?
+    target_platform = 'win32' if self.GetArch(config) == 'x86' else 'x64'
+    flags = ['/char', 'signed', '/env', target_platform, '/Oicf']
+    return outdir, output, variables, flags
+
+
+def _LanguageMatchesForPch(source_ext, pch_source_ext):
+  c_exts = ('.c',)
+  cc_exts = ('.cc', '.cxx', '.cpp')
+  return ((source_ext in c_exts and pch_source_ext in c_exts) or
+          (source_ext in cc_exts and pch_source_ext in cc_exts))
+
+
+class PrecompiledHeader(object):
+  """Helper to generate dependencies and build rules to handle generation of
+  precompiled headers. Interface matches the GCH handler in xcode_emulation.py.
+  """
+  def __init__(
+      self, settings, config, gyp_to_build_path, gyp_to_unique_output, obj_ext):
+    self.settings = settings
+    self.config = config
+    pch_source = self.settings.msvs_precompiled_source[self.config]
+    self.pch_source = gyp_to_build_path(pch_source)
+    filename, _ = os.path.splitext(pch_source)
+    self.output_obj = gyp_to_unique_output(filename + obj_ext).lower()
+
+  def _PchHeader(self):
+    """Get the header that will appear in an #include line for all source
+    files."""
+    return os.path.split(self.settings.msvs_precompiled_header[self.config])[1]
+
+  def GetObjDependencies(self, sources, objs):
+    """Given a list of sources files and the corresponding object files,
+    returns a list of the pch files that should be depended upon. The
+    additional wrapping in the return value is for interface compatability
+    with make.py on Mac, and xcode_emulation.py."""
+    if not self._PchHeader():
+      return []
+    pch_ext = os.path.splitext(self.pch_source)[1]
+    for source in sources:
+      if _LanguageMatchesForPch(os.path.splitext(source)[1], pch_ext):
+        return [(None, None, self.output_obj)]
+    return []
+
+  def GetPchBuildCommands(self):
+    """Not used on Windows as there are no additional build steps required
+    (instead, existing steps are modified in GetFlagsModifications below)."""
+    return []
+
+  def GetFlagsModifications(self, input, output, implicit, command,
+                            cflags_c, cflags_cc, expand_special):
+    """Get the modified cflags and implicit dependencies that should be used
+    for the pch compilation step."""
+    if input == self.pch_source:
+      pch_output = ['/Yc' + self._PchHeader()]
+      if command == 'cxx':
+        return ([('cflags_cc', map(expand_special, cflags_cc + pch_output))],
+                self.output_obj, [])
+      elif command == 'cc':
+        return ([('cflags_c', map(expand_special, cflags_c + pch_output))],
+                self.output_obj, [])
+    return [], output, implicit
+
+
+vs_version = None
+def GetVSVersion(generator_flags):
+  global vs_version
+  if not vs_version:
+    vs_version = gyp.MSVSVersion.SelectVisualStudioVersion(
+        generator_flags.get('msvs_version', 'auto'))
+  return vs_version
+
+def _GetVsvarsSetupArgs(generator_flags, arch):
+  vs = GetVSVersion(generator_flags)
+  return vs.SetupScript()
+
+def ExpandMacros(string, expansions):
+  """Expand $(Variable) per expansions dict. See MsvsSettings.GetVSMacroEnv
+  for the canonical way to retrieve a suitable dict."""
+  if '$' in string:
+    for old, new in expansions.iteritems():
+      assert '$(' not in new, new
+      string = string.replace(old, new)
+  return string
+
+def _ExtractImportantEnvironment(output_of_set):
+  """Extracts environment variables required for the toolchain to run from
+  a textual dump output by the cmd.exe 'set' command."""
+  envvars_to_save = (
+      'goma_.*', # TODO(scottmg): This is ugly, but needed for goma.
+      'include',
+      'lib',
+      'libpath',
+      'path',
+      'pathext',
+      'systemroot',
+      'temp',
+      'tmp',
+      )
+  env = {}
+  for line in output_of_set.splitlines():
+    for envvar in envvars_to_save:
+      if re.match(envvar + '=', line.lower()):
+        var, setting = line.split('=', 1)
+        if envvar == 'path':
+          # Our own rules (for running gyp-win-tool) and other actions in
+          # Chromium rely on python being in the path. Add the path to this
+          # python here so that if it's not in the path when ninja is run
+          # later, python will still be found.
+          setting = os.path.dirname(sys.executable) + os.pathsep + setting
+        env[var.upper()] = setting
+        break
+  for required in ('SYSTEMROOT', 'TEMP', 'TMP'):
+    if required not in env:
+      raise Exception('Environment variable "%s" '
+                      'required to be set to valid path' % required)
+  return env
+
+def _FormatAsEnvironmentBlock(envvar_dict):
+  """Format as an 'environment block' directly suitable for CreateProcess.
+  Briefly this is a list of key=value\0, terminated by an additional \0. See
+  CreateProcess documentation for more details."""
+  block = ''
+  nul = '\0'
+  for key, value in envvar_dict.iteritems():
+    block += key + '=' + value + nul
+  block += nul
+  return block
+
+def GenerateEnvironmentFiles(toplevel_build_dir, generator_flags, open_out):
+  """It's not sufficient to have the absolute path to the compiler, linker,
+  etc. on Windows, as those tools rely on .dlls being in the PATH. We also
+  need to support both x86 and x64 compilers within the same build (to support
+  msvs_target_platform hackery). Different architectures require a different
+  compiler binary, and different supporting environment variables (INCLUDE,
+  LIB, LIBPATH). So, we extract the environment here, wrap all invocations
+  of compiler tools (cl, link, lib, rc, midl, etc.) via win_tool.py which
+  sets up the environment, and then we do not prefix the compiler with
+  an absolute path, instead preferring something like "cl.exe" in the rule
+  which will then run whichever the environment setup has put in the path.
+  When the following procedure to generate environment files does not
+  meet your requirement (e.g. for custom toolchains), you can pass
+  "-G ninja_use_custom_environment_files" to the gyp to suppress file
+  generation and use custom environment files prepared by yourself."""
+  if generator_flags.get('ninja_use_custom_environment_files', 0):
+    return
+  vs = GetVSVersion(generator_flags)
+  for arch in ('x86', 'x64'):
+    args = vs.SetupScript(arch)
+    args.extend(('&&', 'set'))
+    popen = subprocess.Popen(
+        args, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+    variables, _ = popen.communicate()
+    env = _ExtractImportantEnvironment(variables)
+    env_block = _FormatAsEnvironmentBlock(env)
+    f = open_out(os.path.join(toplevel_build_dir, 'environment.' + arch), 'wb')
+    f.write(env_block)
+    f.close()
+
+def VerifyMissingSources(sources, build_dir, generator_flags, gyp_to_ninja):
+  """Emulate behavior of msvs_error_on_missing_sources present in the msvs
+  generator: Check that all regular source files, i.e. not created at run time,
+  exist on disk. Missing files cause needless recompilation when building via
+  VS, and we want this check to match for people/bots that build using ninja,
+  so they're not surprised when the VS build fails."""
+  if int(generator_flags.get('msvs_error_on_missing_sources', 0)):
+    no_specials = filter(lambda x: '$' not in x, sources)
+    relative = [os.path.join(build_dir, gyp_to_ninja(s)) for s in no_specials]
+    missing = filter(lambda x: not os.path.exists(x), relative)
+    if missing:
+      # They'll look like out\Release\..\..\stuff\things.cc, so normalize the
+      # path for a slightly less crazy looking output.
+      cleaned_up = [os.path.normpath(x) for x in missing]
+      raise Exception('Missing input files:\n%s' % '\n'.join(cleaned_up))
diff --git a/webWidgetTCT_device/tools/gyp/pylib/gyp/ninja_syntax.py b/webWidgetTCT_device/tools/gyp/pylib/gyp/ninja_syntax.py
new file mode 100755 (executable)
index 0000000..d2948f0
--- /dev/null
@@ -0,0 +1,160 @@
+# This file comes from
+#   https://github.com/martine/ninja/blob/master/misc/ninja_syntax.py
+# Do not edit!  Edit the upstream one instead.
+
+"""Python module for generating .ninja files.
+
+Note that this is emphatically not a required piece of Ninja; it's
+just a helpful utility for build-file-generation systems that already
+use Python.
+"""
+
+import textwrap
+import re
+
+def escape_path(word):
+    return word.replace('$ ','$$ ').replace(' ','$ ').replace(':', '$:')
+
+class Writer(object):
+    def __init__(self, output, width=78):
+        self.output = output
+        self.width = width
+
+    def newline(self):
+        self.output.write('\n')
+
+    def comment(self, text):
+        for line in textwrap.wrap(text, self.width - 2):
+            self.output.write('# ' + line + '\n')
+
+    def variable(self, key, value, indent=0):
+        if value is None:
+            return
+        if isinstance(value, list):
+            value = ' '.join(filter(None, value))  # Filter out empty strings.
+        self._line('%s = %s' % (key, value), indent)
+
+    def pool(self, name, depth):
+        self._line('pool %s' % name)
+        self.variable('depth', depth, indent=1)
+
+    def rule(self, name, command, description=None, depfile=None,
+             generator=False, pool=None, restat=False, rspfile=None,
+             rspfile_content=None, deps=None):
+        self._line('rule %s' % name)
+        self.variable('command', command, indent=1)
+        if description:
+            self.variable('description', description, indent=1)
+        if depfile:
+            self.variable('depfile', depfile, indent=1)
+        if generator:
+            self.variable('generator', '1', indent=1)
+        if pool:
+            self.variable('pool', pool, indent=1)
+        if restat:
+            self.variable('restat', '1', indent=1)
+        if rspfile:
+            self.variable('rspfile', rspfile, indent=1)
+        if rspfile_content:
+            self.variable('rspfile_content', rspfile_content, indent=1)
+        if deps:
+            self.variable('deps', deps, indent=1)
+
+    def build(self, outputs, rule, inputs=None, implicit=None, order_only=None,
+              variables=None):
+        outputs = self._as_list(outputs)
+        all_inputs = self._as_list(inputs)[:]
+        out_outputs = list(map(escape_path, outputs))
+        all_inputs = list(map(escape_path, all_inputs))
+
+        if implicit:
+            implicit = map(escape_path, self._as_list(implicit))
+            all_inputs.append('|')
+            all_inputs.extend(implicit)
+        if order_only:
+            order_only = map(escape_path, self._as_list(order_only))
+            all_inputs.append('||')
+            all_inputs.extend(order_only)
+
+        self._line('build %s: %s' % (' '.join(out_outputs),
+                                        ' '.join([rule] + all_inputs)))
+
+        if variables:
+            if isinstance(variables, dict):
+                iterator = iter(variables.items())
+            else:
+                iterator = iter(variables)
+
+            for key, val in iterator:
+                self.variable(key, val, indent=1)
+
+        return outputs
+
+    def include(self, path):
+        self._line('include %s' % path)
+
+    def subninja(self, path):
+        self._line('subninja %s' % path)
+
+    def default(self, paths):
+        self._line('default %s' % ' '.join(self._as_list(paths)))
+
+    def _count_dollars_before_index(self, s, i):
+      """Returns the number of '$' characters right in front of s[i]."""
+      dollar_count = 0
+      dollar_index = i - 1
+      while dollar_index > 0 and s[dollar_index] == '$':
+        dollar_count += 1
+        dollar_index -= 1
+      return dollar_count
+
+    def _line(self, text, indent=0):
+        """Write 'text' word-wrapped at self.width characters."""
+        leading_space = '  ' * indent
+        while len(leading_space) + len(text) > self.width:
+            # The text is too wide; wrap if possible.
+
+            # Find the rightmost space that would obey our width constraint and
+            # that's not an escaped space.
+            available_space = self.width - len(leading_space) - len(' $')
+            space = available_space
+            while True:
+              space = text.rfind(' ', 0, space)
+              if space < 0 or \
+                 self._count_dollars_before_index(text, space) % 2 == 0:
+                break
+
+            if space < 0:
+                # No such space; just use the first unescaped space we can find.
+                space = available_space - 1
+                while True:
+                  space = text.find(' ', space + 1)
+                  if space < 0 or \
+                     self._count_dollars_before_index(text, space) % 2 == 0:
+                    break
+            if space < 0:
+                # Give up on breaking.
+                break
+
+            self.output.write(leading_space + text[0:space] + ' $\n')
+            text = text[space+1:]
+
+            # Subsequent lines are continuations, so indent them.
+            leading_space = '  ' * (indent+2)
+
+        self.output.write(leading_space + text + '\n')
+
+    def _as_list(self, input):
+        if input is None:
+            return []
+        if isinstance(input, list):
+            return input
+        return [input]
+
+
+def escape(string):
+    """Escape a string such that it can be embedded into a Ninja file without
+    further interpretation."""
+    assert '\n' not in string, 'Ninja syntax does not allow newlines'
+    # We only have one special metacharacter: '$'.
+    return string.replace('$', '$$')
diff --git a/webWidgetTCT_device/tools/gyp/pylib/gyp/sun_tool.py b/webWidgetTCT_device/tools/gyp/pylib/gyp/sun_tool.py
new file mode 100755 (executable)
index 0000000..90d59c8
--- /dev/null
@@ -0,0 +1,51 @@
+#!/usr/bin/env python
+# Copyright (c) 2011 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""These functions are executed via gyp-sun-tool when using the Makefile
+generator."""
+
+import fcntl
+import os
+import struct
+import subprocess
+import sys
+
+
+def main(args):
+  executor = SunTool()
+  executor.Dispatch(args)
+
+
+class SunTool(object):
+  """This class performs all the SunOS tooling steps. The methods can either be
+  executed directly, or dispatched from an argument list."""
+
+  def Dispatch(self, args):
+    """Dispatches a string command to a method."""
+    if len(args) < 1:
+      raise Exception("Not enough arguments")
+
+    method = "Exec%s" % self._CommandifyName(args[0])
+    getattr(self, method)(*args[1:])
+
+  def _CommandifyName(self, name_string):
+    """Transforms a tool name like copy-info-plist to CopyInfoPlist"""
+    return name_string.title().replace('-', '')
+
+  def ExecFlock(self, lockfile, *cmd_list):
+    """Emulates the most basic behavior of Linux's flock(1)."""
+    # Rely on exception handling to report errors.
+    # Note that the stock python on SunOS has a bug
+    # where fcntl.flock(fd, LOCK_EX) always fails
+    # with EBADF, that's why we use this F_SETLK
+    # hack instead.
+    fd = os.open(lockfile, os.O_WRONLY|os.O_NOCTTY|os.O_CREAT, 0666)
+    op = struct.pack('hhllhhl', fcntl.F_WRLCK, 0, 0, 0, 0, 0, 0)
+    fcntl.fcntl(fd, fcntl.F_SETLK, op)
+    return subprocess.call(cmd_list)
+
+
+if __name__ == '__main__':
+  sys.exit(main(sys.argv[1:]))
diff --git a/webWidgetTCT_device/tools/gyp/pylib/gyp/win_tool.py b/webWidgetTCT_device/tools/gyp/pylib/gyp/win_tool.py
new file mode 100755 (executable)
index 0000000..7b06573
--- /dev/null
@@ -0,0 +1,193 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Utility functions for Windows builds.
+
+These functions are executed via gyp-win-tool when using the ninja generator.
+"""
+
+from ctypes import windll, wintypes
+import os
+import shutil
+import subprocess
+import sys
+
+BASE_DIR = os.path.dirname(os.path.abspath(__file__))
+
+
+def main(args):
+  executor = WinTool()
+  exit_code = executor.Dispatch(args)
+  if exit_code is not None:
+    sys.exit(exit_code)
+
+
+class LinkLock(object):
+  """A flock-style lock to limit the number of concurrent links to one.
+
+  Uses a session-local mutex based on the file's directory.
+  """
+  def __enter__(self):
+    name = 'Local\\%s' % BASE_DIR.replace('\\', '_').replace(':', '_')
+    self.mutex = windll.kernel32.CreateMutexW(
+        wintypes.c_int(0),
+        wintypes.c_int(0),
+        wintypes.create_unicode_buffer(name))
+    assert self.mutex
+    result = windll.kernel32.WaitForSingleObject(
+        self.mutex, wintypes.c_int(0xFFFFFFFF))
+    # 0x80 means another process was killed without releasing the mutex, but
+    # that this process has been given ownership. This is fine for our
+    # purposes.
+    assert result in (0, 0x80), (
+        "%s, %s" % (result, windll.kernel32.GetLastError()))
+
+  def __exit__(self, type, value, traceback):
+    windll.kernel32.ReleaseMutex(self.mutex)
+    windll.kernel32.CloseHandle(self.mutex)
+
+
+class WinTool(object):
+  """This class performs all the Windows tooling steps. The methods can either
+  be executed directly, or dispatched from an argument list."""
+
+  def Dispatch(self, args):
+    """Dispatches a string command to a method."""
+    if len(args) < 1:
+      raise Exception("Not enough arguments")
+
+    method = "Exec%s" % self._CommandifyName(args[0])
+    return getattr(self, method)(*args[1:])
+
+  def _CommandifyName(self, name_string):
+    """Transforms a tool name like recursive-mirror to RecursiveMirror."""
+    return name_string.title().replace('-', '')
+
+  def _GetEnv(self, arch):
+    """Gets the saved environment from a file for a given architecture."""
+    # The environment is saved as an "environment block" (see CreateProcess
+    # and msvs_emulation for details). We convert to a dict here.
+    # Drop last 2 NULs, one for list terminator, one for trailing vs. separator.
+    pairs = open(arch).read()[:-2].split('\0')
+    kvs = [item.split('=', 1) for item in pairs]
+    return dict(kvs)
+
+  def ExecStamp(self, path):
+    """Simple stamp command."""
+    open(path, 'w').close()
+
+  def ExecRecursiveMirror(self, source, dest):
+    """Emulation of rm -rf out && cp -af in out."""
+    if os.path.exists(dest):
+      if os.path.isdir(dest):
+        shutil.rmtree(dest)
+      else:
+        os.unlink(dest)
+    if os.path.isdir(source):
+      shutil.copytree(source, dest)
+    else:
+      shutil.copy2(source, dest)
+
+  def ExecLinkWrapper(self, arch, *args):
+    """Filter diagnostic output from link that looks like:
+    '   Creating library ui.dll.lib and object ui.dll.exp'
+    This happens when there are exports from the dll or exe.
+    """
+    with LinkLock():
+      env = self._GetEnv(arch)
+      popen = subprocess.Popen(args, shell=True, env=env,
+                               stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+      out, _ = popen.communicate()
+      for line in out.splitlines():
+        if not line.startswith('   Creating library '):
+          print line
+      return popen.returncode
+
+  def ExecManifestWrapper(self, arch, *args):
+    """Run manifest tool with environment set. Strip out undesirable warning
+    (some XML blocks are recognized by the OS loader, but not the manifest
+    tool)."""
+    env = self._GetEnv(arch)
+    popen = subprocess.Popen(args, shell=True, env=env,
+                             stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+    out, _ = popen.communicate()
+    for line in out.splitlines():
+      if line and 'manifest authoring warning 81010002' not in line:
+        print line
+    return popen.returncode
+
+  def ExecMidlWrapper(self, arch, outdir, tlb, h, dlldata, iid, proxy, idl,
+                      *flags):
+    """Filter noisy filenames output from MIDL compile step that isn't
+    quietable via command line flags.
+    """
+    args = ['midl', '/nologo'] + list(flags) + [
+        '/out', outdir,
+        '/tlb', tlb,
+        '/h', h,
+        '/dlldata', dlldata,
+        '/iid', iid,
+        '/proxy', proxy,
+        idl]
+    env = self._GetEnv(arch)
+    popen = subprocess.Popen(args, shell=True, env=env,
+                             stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+    out, _ = popen.communicate()
+    # Filter junk out of stdout, and write filtered versions. Output we want
+    # to filter is pairs of lines that look like this:
+    # Processing C:\Program Files (x86)\Microsoft SDKs\...\include\objidl.idl
+    # objidl.idl
+    lines = out.splitlines()
+    prefix = 'Processing '
+    processing = set(os.path.basename(x) for x in lines if x.startswith(prefix))
+    for line in lines:
+      if not line.startswith(prefix) and line not in processing:
+        print line
+    return popen.returncode
+
+  def ExecAsmWrapper(self, arch, *args):
+    """Filter logo banner from invocations of asm.exe."""
+    env = self._GetEnv(arch)
+    # MSVS doesn't assemble x64 asm files.
+    if arch == 'environment.x64':
+      return 0
+    popen = subprocess.Popen(args, shell=True, env=env,
+                             stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+    out, _ = popen.communicate()
+    for line in out.splitlines():
+      if (not line.startswith('Copyright (C) Microsoft Corporation') and
+          not line.startswith('Microsoft (R) Macro Assembler') and
+          not line.startswith(' Assembling: ') and
+          line):
+        print line
+    return popen.returncode
+
+  def ExecRcWrapper(self, arch, *args):
+    """Filter logo banner from invocations of rc.exe. Older versions of RC
+    don't support the /nologo flag."""
+    env = self._GetEnv(arch)
+    popen = subprocess.Popen(args, shell=True, env=env,
+                             stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+    out, _ = popen.communicate()
+    for line in out.splitlines():
+      if (not line.startswith('Microsoft (R) Windows (R) Resource Compiler') and
+          not line.startswith('Copyright (C) Microsoft Corporation') and
+          line):
+        print line
+    return popen.returncode
+
+  def ExecActionWrapper(self, arch, rspfile, *dir):
+    """Runs an action command line from a response file using the environment
+    for |arch|. If |dir| is supplied, use that as the working directory."""
+    env = self._GetEnv(arch)
+    args = open(rspfile).read()
+    dir = dir[0] if dir else None
+    popen = subprocess.Popen(args, shell=True, env=env, cwd=dir)
+    popen.wait()
+    return popen.returncode
+
+if __name__ == '__main__':
+  sys.exit(main(sys.argv[1:]))
diff --git a/webWidgetTCT_device/tools/gyp/pylib/gyp/xcode_emulation.py b/webWidgetTCT_device/tools/gyp/pylib/gyp/xcode_emulation.py
new file mode 100755 (executable)
index 0000000..b2aab98
--- /dev/null
@@ -0,0 +1,1084 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""
+This module contains classes that help to emulate xcodebuild behavior on top of
+other build systems, such as make and ninja.
+"""
+
+import gyp.common
+import os.path
+import re
+import shlex
+import subprocess
+import sys
+from gyp.common import GypError
+
+class XcodeSettings(object):
+  """A class that understands the gyp 'xcode_settings' object."""
+
+  # Populated lazily by _SdkPath(). Shared by all XcodeSettings, so cached
+  # at class-level for efficiency.
+  _sdk_path_cache = {}
+
+  def __init__(self, spec):
+    self.spec = spec
+
+    # Per-target 'xcode_settings' are pushed down into configs earlier by gyp.
+    # This means self.xcode_settings[config] always contains all settings
+    # for that config -- the per-target settings as well. Settings that are
+    # the same for all configs are implicitly per-target settings.
+    self.xcode_settings = {}
+    configs = spec['configurations']
+    for configname, config in configs.iteritems():
+      self.xcode_settings[configname] = config.get('xcode_settings', {})
+
+    # This is only non-None temporarily during the execution of some methods.
+    self.configname = None
+
+    # Used by _AdjustLibrary to match .a and .dylib entries in libraries.
+    self.library_re = re.compile(r'^lib([^/]+)\.(a|dylib)$')
+
+  def _Settings(self):
+    assert self.configname
+    return self.xcode_settings[self.configname]
+
+  def _Test(self, test_key, cond_key, default):
+    return self._Settings().get(test_key, default) == cond_key
+
+  def _Appendf(self, lst, test_key, format_str, default=None):
+    if test_key in self._Settings():
+      lst.append(format_str % str(self._Settings()[test_key]))
+    elif default:
+      lst.append(format_str % str(default))
+
+  def _WarnUnimplemented(self, test_key):
+    if test_key in self._Settings():
+      print 'Warning: Ignoring not yet implemented key "%s".' % test_key
+
+  def _IsBundle(self):
+    return int(self.spec.get('mac_bundle', 0)) != 0
+
+  def GetFrameworkVersion(self):
+    """Returns the framework version of the current target. Only valid for
+    bundles."""
+    assert self._IsBundle()
+    return self.GetPerTargetSetting('FRAMEWORK_VERSION', default='A')
+
+  def GetWrapperExtension(self):
+    """Returns the bundle extension (.app, .framework, .plugin, etc).  Only
+    valid for bundles."""
+    assert self._IsBundle()
+    if self.spec['type'] in ('loadable_module', 'shared_library'):
+      default_wrapper_extension = {
+        'loadable_module': 'bundle',
+        'shared_library': 'framework',
+      }[self.spec['type']]
+      wrapper_extension = self.GetPerTargetSetting(
+          'WRAPPER_EXTENSION', default=default_wrapper_extension)
+      return '.' + self.spec.get('product_extension', wrapper_extension)
+    elif self.spec['type'] == 'executable':
+      return '.app'
+    else:
+      assert False, "Don't know extension for '%s', target '%s'" % (
+          self.spec['type'], self.spec['target_name'])
+
+  def GetProductName(self):
+    """Returns PRODUCT_NAME."""
+    return self.spec.get('product_name', self.spec['target_name'])
+
+  def GetFullProductName(self):
+    """Returns FULL_PRODUCT_NAME."""
+    if self._IsBundle():
+      return self.GetWrapperName()
+    else:
+      return self._GetStandaloneBinaryPath()
+
+  def GetWrapperName(self):
+    """Returns the directory name of the bundle represented by this target.
+    Only valid for bundles."""
+    assert self._IsBundle()
+    return self.GetProductName() + self.GetWrapperExtension()
+
+  def GetBundleContentsFolderPath(self):
+    """Returns the qualified path to the bundle's contents folder. E.g.
+    Chromium.app/Contents or Foo.bundle/Versions/A. Only valid for bundles."""
+    assert self._IsBundle()
+    if self.spec['type'] == 'shared_library':
+      return os.path.join(
+          self.GetWrapperName(), 'Versions', self.GetFrameworkVersion())
+    else:
+      # loadable_modules have a 'Contents' folder like executables.
+      return os.path.join(self.GetWrapperName(), 'Contents')
+
+  def GetBundleResourceFolder(self):
+    """Returns the qualified path to the bundle's resource folder. E.g.
+    Chromium.app/Contents/Resources. Only valid for bundles."""
+    assert self._IsBundle()
+    return os.path.join(self.GetBundleContentsFolderPath(), 'Resources')
+
+  def GetBundlePlistPath(self):
+    """Returns the qualified path to the bundle's plist file. E.g.
+    Chromium.app/Contents/Info.plist. Only valid for bundles."""
+    assert self._IsBundle()
+    if self.spec['type'] in ('executable', 'loadable_module'):
+      return os.path.join(self.GetBundleContentsFolderPath(), 'Info.plist')
+    else:
+      return os.path.join(self.GetBundleContentsFolderPath(),
+                          'Resources', 'Info.plist')
+
+  def GetProductType(self):
+    """Returns the PRODUCT_TYPE of this target."""
+    if self._IsBundle():
+      return {
+        'executable': 'com.apple.product-type.application',
+        'loadable_module': 'com.apple.product-type.bundle',
+        'shared_library': 'com.apple.product-type.framework',
+      }[self.spec['type']]
+    else:
+      return {
+        'executable': 'com.apple.product-type.tool',
+        'loadable_module': 'com.apple.product-type.library.dynamic',
+        'shared_library': 'com.apple.product-type.library.dynamic',
+        'static_library': 'com.apple.product-type.library.static',
+      }[self.spec['type']]
+
+  def GetMachOType(self):
+    """Returns the MACH_O_TYPE of this target."""
+    # Weird, but matches Xcode.
+    if not self._IsBundle() and self.spec['type'] == 'executable':
+      return ''
+    return {
+      'executable': 'mh_execute',
+      'static_library': 'staticlib',
+      'shared_library': 'mh_dylib',
+      'loadable_module': 'mh_bundle',
+    }[self.spec['type']]
+
+  def _GetBundleBinaryPath(self):
+    """Returns the name of the bundle binary of by this target.
+    E.g. Chromium.app/Contents/MacOS/Chromium. Only valid for bundles."""
+    assert self._IsBundle()
+    if self.spec['type'] in ('shared_library'):
+      path = self.GetBundleContentsFolderPath()
+    elif self.spec['type'] in ('executable', 'loadable_module'):
+      path = os.path.join(self.GetBundleContentsFolderPath(), 'MacOS')
+    return os.path.join(path, self.GetExecutableName())
+
+  def _GetStandaloneExecutableSuffix(self):
+    if 'product_extension' in self.spec:
+      return '.' + self.spec['product_extension']
+    return {
+      'executable': '',
+      'static_library': '.a',
+      'shared_library': '.dylib',
+      'loadable_module': '.so',
+    }[self.spec['type']]
+
+  def _GetStandaloneExecutablePrefix(self):
+    return self.spec.get('product_prefix', {
+      'executable': '',
+      'static_library': 'lib',
+      'shared_library': 'lib',
+      # Non-bundled loadable_modules are called foo.so for some reason
+      # (that is, .so and no prefix) with the xcode build -- match that.
+      'loadable_module': '',
+    }[self.spec['type']])
+
+  def _GetStandaloneBinaryPath(self):
+    """Returns the name of the non-bundle binary represented by this target.
+    E.g. hello_world. Only valid for non-bundles."""
+    assert not self._IsBundle()
+    assert self.spec['type'] in (
+        'executable', 'shared_library', 'static_library', 'loadable_module'), (
+        'Unexpected type %s' % self.spec['type'])
+    target = self.spec['target_name']
+    if self.spec['type'] == 'static_library':
+      if target[:3] == 'lib':
+        target = target[3:]
+    elif self.spec['type'] in ('loadable_module', 'shared_library'):
+      if target[:3] == 'lib':
+        target = target[3:]
+
+    target_prefix = self._GetStandaloneExecutablePrefix()
+    target = self.spec.get('product_name', target)
+    target_ext = self._GetStandaloneExecutableSuffix()
+    return target_prefix + target + target_ext
+
+  def GetExecutableName(self):
+    """Returns the executable name of the bundle represented by this target.
+    E.g. Chromium."""
+    if self._IsBundle():
+      return self.spec.get('product_name', self.spec['target_name'])
+    else:
+      return self._GetStandaloneBinaryPath()
+
+  def GetExecutablePath(self):
+    """Returns the directory name of the bundle represented by this target. E.g.
+    Chromium.app/Contents/MacOS/Chromium."""
+    if self._IsBundle():
+      return self._GetBundleBinaryPath()
+    else:
+      return self._GetStandaloneBinaryPath()
+
+  def _GetSdkVersionInfoItem(self, sdk, infoitem):
+    job = subprocess.Popen(['xcodebuild', '-version', '-sdk', sdk, infoitem],
+                           stdout=subprocess.PIPE)
+    out = job.communicate()[0]
+    if job.returncode != 0:
+      sys.stderr.write(out + '\n')
+      raise GypError('Error %d running xcodebuild' % job.returncode)
+    return out.rstrip('\n')
+
+  def _SdkPath(self):
+    sdk_root = self.GetPerTargetSetting('SDKROOT', default='macosx')
+    if sdk_root.startswith('/'):
+      return sdk_root
+    if sdk_root not in XcodeSettings._sdk_path_cache:
+      XcodeSettings._sdk_path_cache[sdk_root] = self._GetSdkVersionInfoItem(
+          sdk_root, 'Path')
+    return XcodeSettings._sdk_path_cache[sdk_root]
+
+  def _AppendPlatformVersionMinFlags(self, lst):
+    self._Appendf(lst, 'MACOSX_DEPLOYMENT_TARGET', '-mmacosx-version-min=%s')
+    if 'IPHONEOS_DEPLOYMENT_TARGET' in self._Settings():
+      # TODO: Implement this better?
+      sdk_path_basename = os.path.basename(self._SdkPath())
+      if sdk_path_basename.lower().startswith('iphonesimulator'):
+        self._Appendf(lst, 'IPHONEOS_DEPLOYMENT_TARGET',
+                      '-mios-simulator-version-min=%s')
+      else:
+        self._Appendf(lst, 'IPHONEOS_DEPLOYMENT_TARGET',
+                      '-miphoneos-version-min=%s')
+
+  def GetCflags(self, configname):
+    """Returns flags that need to be added to .c, .cc, .m, and .mm
+    compilations."""
+    # This functions (and the similar ones below) do not offer complete
+    # emulation of all xcode_settings keys. They're implemented on demand.
+
+    self.configname = configname
+    cflags = []
+
+    sdk_root = self._SdkPath()
+    if 'SDKROOT' in self._Settings():
+      cflags.append('-isysroot %s' % sdk_root)
+
+    if self._Test('CLANG_WARN_CONSTANT_CONVERSION', 'YES', default='NO'):
+      cflags.append('-Wconstant-conversion')
+
+    if self._Test('GCC_CHAR_IS_UNSIGNED_CHAR', 'YES', default='NO'):
+      cflags.append('-funsigned-char')
+
+    if self._Test('GCC_CW_ASM_SYNTAX', 'YES', default='YES'):
+      cflags.append('-fasm-blocks')
+
+    if 'GCC_DYNAMIC_NO_PIC' in self._Settings():
+      if self._Settings()['GCC_DYNAMIC_NO_PIC'] == 'YES':
+        cflags.append('-mdynamic-no-pic')
+    else:
+      pass
+      # TODO: In this case, it depends on the target. xcode passes
+      # mdynamic-no-pic by default for executable and possibly static lib
+      # according to mento
+
+    if self._Test('GCC_ENABLE_PASCAL_STRINGS', 'YES', default='YES'):
+      cflags.append('-mpascal-strings')
+
+    self._Appendf(cflags, 'GCC_OPTIMIZATION_LEVEL', '-O%s', default='s')
+
+    if self._Test('GCC_GENERATE_DEBUGGING_SYMBOLS', 'YES', default='YES'):
+      dbg_format = self._Settings().get('DEBUG_INFORMATION_FORMAT', 'dwarf')
+      if dbg_format == 'dwarf':
+        cflags.append('-gdwarf-2')
+      elif dbg_format == 'stabs':
+        raise NotImplementedError('stabs debug format is not supported yet.')
+      elif dbg_format == 'dwarf-with-dsym':
+        cflags.append('-gdwarf-2')
+      else:
+        raise NotImplementedError('Unknown debug format %s' % dbg_format)
+
+    if self._Test('GCC_SYMBOLS_PRIVATE_EXTERN', 'YES', default='NO'):
+      cflags.append('-fvisibility=hidden')
+
+    if self._Test('GCC_TREAT_WARNINGS_AS_ERRORS', 'YES', default='NO'):
+      cflags.append('-Werror')
+
+    if self._Test('GCC_WARN_ABOUT_MISSING_NEWLINE', 'YES', default='NO'):
+      cflags.append('-Wnewline-eof')
+
+    self._AppendPlatformVersionMinFlags(cflags)
+
+    # TODO:
+    if self._Test('COPY_PHASE_STRIP', 'YES', default='NO'):
+      self._WarnUnimplemented('COPY_PHASE_STRIP')
+    self._WarnUnimplemented('GCC_DEBUGGING_SYMBOLS')
+    self._WarnUnimplemented('GCC_ENABLE_OBJC_EXCEPTIONS')
+
+    # TODO: This is exported correctly, but assigning to it is not supported.
+    self._WarnUnimplemented('MACH_O_TYPE')
+    self._WarnUnimplemented('PRODUCT_TYPE')
+
+    archs = self._Settings().get('ARCHS', ['i386'])
+    if len(archs) != 1:
+      # TODO: Supporting fat binaries will be annoying.
+      self._WarnUnimplemented('ARCHS')
+      archs = ['i386']
+    cflags.append('-arch ' + archs[0])
+
+    if archs[0] in ('i386', 'x86_64'):
+      if self._Test('GCC_ENABLE_SSE3_EXTENSIONS', 'YES', default='NO'):
+        cflags.append('-msse3')
+      if self._Test('GCC_ENABLE_SUPPLEMENTAL_SSE3_INSTRUCTIONS', 'YES',
+                    default='NO'):
+        cflags.append('-mssse3')  # Note 3rd 's'.
+      if self._Test('GCC_ENABLE_SSE41_EXTENSIONS', 'YES', default='NO'):
+        cflags.append('-msse4.1')
+      if self._Test('GCC_ENABLE_SSE42_EXTENSIONS', 'YES', default='NO'):
+        cflags.append('-msse4.2')
+
+    cflags += self._Settings().get('WARNING_CFLAGS', [])
+
+    config = self.spec['configurations'][self.configname]
+    framework_dirs = config.get('mac_framework_dirs', [])
+    for directory in framework_dirs:
+      cflags.append('-F' + directory.replace('$(SDKROOT)', sdk_root))
+
+    self.configname = None
+    return cflags
+
+  def GetCflagsC(self, configname):
+    """Returns flags that need to be added to .c, and .m compilations."""
+    self.configname = configname
+    cflags_c = []
+    self._Appendf(cflags_c, 'GCC_C_LANGUAGE_STANDARD', '-std=%s')
+    cflags_c += self._Settings().get('OTHER_CFLAGS', [])
+    self.configname = None
+    return cflags_c
+
+  def GetCflagsCC(self, configname):
+    """Returns flags that need to be added to .cc, and .mm compilations."""
+    self.configname = configname
+    cflags_cc = []
+
+    clang_cxx_language_standard = self._Settings().get(
+        'CLANG_CXX_LANGUAGE_STANDARD')
+    # Note: Don't make c++0x to c++11 so that c++0x can be used with older
+    # clangs that don't understand c++11 yet (like Xcode 4.2's).
+    if clang_cxx_language_standard:
+      cflags_cc.append('-std=%s' % clang_cxx_language_standard)
+
+    self._Appendf(cflags_cc, 'CLANG_CXX_LIBRARY', '-stdlib=%s')
+
+    if self._Test('GCC_ENABLE_CPP_RTTI', 'NO', default='YES'):
+      cflags_cc.append('-fno-rtti')
+    if self._Test('GCC_ENABLE_CPP_EXCEPTIONS', 'NO', default='YES'):
+      cflags_cc.append('-fno-exceptions')
+    if self._Test('GCC_INLINES_ARE_PRIVATE_EXTERN', 'YES', default='NO'):
+      cflags_cc.append('-fvisibility-inlines-hidden')
+    if self._Test('GCC_THREADSAFE_STATICS', 'NO', default='YES'):
+      cflags_cc.append('-fno-threadsafe-statics')
+    # Note: This flag is a no-op for clang, it only has an effect for gcc.
+    if self._Test('GCC_WARN_ABOUT_INVALID_OFFSETOF_MACRO', 'NO', default='YES'):
+      cflags_cc.append('-Wno-invalid-offsetof')
+
+    other_ccflags = []
+
+    for flag in self._Settings().get('OTHER_CPLUSPLUSFLAGS', ['$(inherited)']):
+      # TODO: More general variable expansion. Missing in many other places too.
+      if flag in ('$inherited', '$(inherited)', '${inherited}'):
+        flag = '$OTHER_CFLAGS'
+      if flag in ('$OTHER_CFLAGS', '$(OTHER_CFLAGS)', '${OTHER_CFLAGS}'):
+        other_ccflags += self._Settings().get('OTHER_CFLAGS', [])
+      else:
+        other_ccflags.append(flag)
+    cflags_cc += other_ccflags
+
+    self.configname = None
+    return cflags_cc
+
+  def _AddObjectiveCGarbageCollectionFlags(self, flags):
+    gc_policy = self._Settings().get('GCC_ENABLE_OBJC_GC', 'unsupported')
+    if gc_policy == 'supported':
+      flags.append('-fobjc-gc')
+    elif gc_policy == 'required':
+      flags.append('-fobjc-gc-only')
+
+  def GetCflagsObjC(self, configname):
+    """Returns flags that need to be added to .m compilations."""
+    self.configname = configname
+    cflags_objc = []
+
+    self._AddObjectiveCGarbageCollectionFlags(cflags_objc)
+
+    self.configname = None
+    return cflags_objc
+
+  def GetCflagsObjCC(self, configname):
+    """Returns flags that need to be added to .mm compilations."""
+    self.configname = configname
+    cflags_objcc = []
+    self._AddObjectiveCGarbageCollectionFlags(cflags_objcc)
+    if self._Test('GCC_OBJC_CALL_CXX_CDTORS', 'YES', default='NO'):
+      cflags_objcc.append('-fobjc-call-cxx-cdtors')
+    self.configname = None
+    return cflags_objcc
+
+  def GetInstallNameBase(self):
+    """Return DYLIB_INSTALL_NAME_BASE for this target."""
+    # Xcode sets this for shared_libraries, and for nonbundled loadable_modules.
+    if (self.spec['type'] != 'shared_library' and
+        (self.spec['type'] != 'loadable_module' or self._IsBundle())):
+      return None
+    install_base = self.GetPerTargetSetting(
+        'DYLIB_INSTALL_NAME_BASE',
+        default='/Library/Frameworks' if self._IsBundle() else '/usr/local/lib')
+    return install_base
+
+  def _StandardizePath(self, path):
+    """Do :standardizepath processing for path."""
+    # I'm not quite sure what :standardizepath does. Just call normpath(),
+    # but don't let @executable_path/../foo collapse to foo.
+    if '/' in path:
+      prefix, rest = '', path
+      if path.startswith('@'):
+        prefix, rest = path.split('/', 1)
+      rest = os.path.normpath(rest)  # :standardizepath
+      path = os.path.join(prefix, rest)
+    return path
+
+  def GetInstallName(self):
+    """Return LD_DYLIB_INSTALL_NAME for this target."""
+    # Xcode sets this for shared_libraries, and for nonbundled loadable_modules.
+    if (self.spec['type'] != 'shared_library' and
+        (self.spec['type'] != 'loadable_module' or self._IsBundle())):
+      return None
+
+    default_install_name = \
+        '$(DYLIB_INSTALL_NAME_BASE:standardizepath)/$(EXECUTABLE_PATH)'
+    install_name = self.GetPerTargetSetting(
+        'LD_DYLIB_INSTALL_NAME', default=default_install_name)
+
+    # Hardcode support for the variables used in chromium for now, to
+    # unblock people using the make build.
+    if '$' in install_name:
+      assert install_name in ('$(DYLIB_INSTALL_NAME_BASE:standardizepath)/'
+          '$(WRAPPER_NAME)/$(PRODUCT_NAME)', default_install_name), (
+          'Variables in LD_DYLIB_INSTALL_NAME are not generally supported '
+          'yet in target \'%s\' (got \'%s\')' %
+              (self.spec['target_name'], install_name))
+
+      install_name = install_name.replace(
+          '$(DYLIB_INSTALL_NAME_BASE:standardizepath)',
+          self._StandardizePath(self.GetInstallNameBase()))
+      if self._IsBundle():
+        # These are only valid for bundles, hence the |if|.
+        install_name = install_name.replace(
+            '$(WRAPPER_NAME)', self.GetWrapperName())
+        install_name = install_name.replace(
+            '$(PRODUCT_NAME)', self.GetProductName())
+      else:
+        assert '$(WRAPPER_NAME)' not in install_name
+        assert '$(PRODUCT_NAME)' not in install_name
+
+      install_name = install_name.replace(
+          '$(EXECUTABLE_PATH)', self.GetExecutablePath())
+    return install_name
+
+  def _MapLinkerFlagFilename(self, ldflag, gyp_to_build_path):
+    """Checks if ldflag contains a filename and if so remaps it from
+    gyp-directory-relative to build-directory-relative."""
+    # This list is expanded on demand.
+    # They get matched as:
+    #   -exported_symbols_list file
+    #   -Wl,exported_symbols_list file
+    #   -Wl,exported_symbols_list,file
+    LINKER_FILE = '(\S+)'
+    WORD = '\S+'
+    linker_flags = [
+      ['-exported_symbols_list', LINKER_FILE],    # Needed for NaCl.
+      ['-unexported_symbols_list', LINKER_FILE],
+      ['-reexported_symbols_list', LINKER_FILE],
+      ['-sectcreate', WORD, WORD, LINKER_FILE],   # Needed for remoting.
+    ]
+    for flag_pattern in linker_flags:
+      regex = re.compile('(?:-Wl,)?' + '[ ,]'.join(flag_pattern))
+      m = regex.match(ldflag)
+      if m:
+        ldflag = ldflag[:m.start(1)] + gyp_to_build_path(m.group(1)) + \
+                 ldflag[m.end(1):]
+    # Required for ffmpeg (no idea why they don't use LIBRARY_SEARCH_PATHS,
+    # TODO(thakis): Update ffmpeg.gyp):
+    if ldflag.startswith('-L'):
+      ldflag = '-L' + gyp_to_build_path(ldflag[len('-L'):])
+    return ldflag
+
+  def GetLdflags(self, configname, product_dir, gyp_to_build_path):
+    """Returns flags that need to be passed to the linker.
+
+    Args:
+        configname: The name of the configuration to get ld flags for.
+        product_dir: The directory where products such static and dynamic
+            libraries are placed. This is added to the library search path.
+        gyp_to_build_path: A function that converts paths relative to the
+            current gyp file to paths relative to the build direcotry.
+    """
+    self.configname = configname
+    ldflags = []
+
+    # The xcode build is relative to a gyp file's directory, and OTHER_LDFLAGS
+    # can contain entries that depend on this. Explicitly absolutify these.
+    for ldflag in self._Settings().get('OTHER_LDFLAGS', []):
+      ldflags.append(self._MapLinkerFlagFilename(ldflag, gyp_to_build_path))
+
+    if self._Test('DEAD_CODE_STRIPPING', 'YES', default='NO'):
+      ldflags.append('-Wl,-dead_strip')
+
+    if self._Test('PREBINDING', 'YES', default='NO'):
+      ldflags.append('-Wl,-prebind')
+
+    self._Appendf(
+        ldflags, 'DYLIB_COMPATIBILITY_VERSION', '-compatibility_version %s')
+    self._Appendf(
+        ldflags, 'DYLIB_CURRENT_VERSION', '-current_version %s')
+
+    self._AppendPlatformVersionMinFlags(ldflags)
+
+    if 'SDKROOT' in self._Settings():
+      ldflags.append('-isysroot ' + self._SdkPath())
+
+    for library_path in self._Settings().get('LIBRARY_SEARCH_PATHS', []):
+      ldflags.append('-L' + gyp_to_build_path(library_path))
+
+    if 'ORDER_FILE' in self._Settings():
+      ldflags.append('-Wl,-order_file ' +
+                     '-Wl,' + gyp_to_build_path(
+                                  self._Settings()['ORDER_FILE']))
+
+    archs = self._Settings().get('ARCHS', ['i386'])
+    if len(archs) != 1:
+      # TODO: Supporting fat binaries will be annoying.
+      self._WarnUnimplemented('ARCHS')
+      archs = ['i386']
+    ldflags.append('-arch ' + archs[0])
+
+    # Xcode adds the product directory by default.
+    ldflags.append('-L' + product_dir)
+
+    install_name = self.GetInstallName()
+    if install_name:
+      ldflags.append('-install_name ' + install_name.replace(' ', r'\ '))
+
+    for rpath in self._Settings().get('LD_RUNPATH_SEARCH_PATHS', []):
+      ldflags.append('-Wl,-rpath,' + rpath)
+
+    config = self.spec['configurations'][self.configname]
+    framework_dirs = config.get('mac_framework_dirs', [])
+    for directory in framework_dirs:
+      ldflags.append('-F' + directory.replace('$(SDKROOT)', self._SdkPath()))
+
+    self.configname = None
+    return ldflags
+
+  def GetLibtoolflags(self, configname):
+    """Returns flags that need to be passed to the static linker.
+
+    Args:
+        configname: The name of the configuration to get ld flags for.
+    """
+    self.configname = configname
+    libtoolflags = []
+
+    for libtoolflag in self._Settings().get('OTHER_LDFLAGS', []):
+      libtoolflags.append(libtoolflag)
+    # TODO(thakis): ARCHS?
+
+    self.configname = None
+    return libtoolflags
+
+  def GetPerTargetSettings(self):
+    """Gets a list of all the per-target settings. This will only fetch keys
+    whose values are the same across all configurations."""
+    first_pass = True
+    result = {}
+    for configname in sorted(self.xcode_settings.keys()):
+      if first_pass:
+        result = dict(self.xcode_settings[configname])
+        first_pass = False
+      else:
+        for key, value in self.xcode_settings[configname].iteritems():
+          if key not in result:
+            continue
+          elif result[key] != value:
+            del result[key]
+    return result
+
+  def GetPerTargetSetting(self, setting, default=None):
+    """Tries to get xcode_settings.setting from spec. Assumes that the setting
+       has the same value in all configurations and throws otherwise."""
+    first_pass = True
+    result = None
+    for configname in sorted(self.xcode_settings.keys()):
+      if first_pass:
+        result = self.xcode_settings[configname].get(setting, None)
+        first_pass = False
+      else:
+        assert result == self.xcode_settings[configname].get(setting, None), (
+            "Expected per-target setting for '%s', got per-config setting "
+            "(target %s)" % (setting, spec['target_name']))
+    if result is None:
+      return default
+    return result
+
+  def _GetStripPostbuilds(self, configname, output_binary, quiet):
+    """Returns a list of shell commands that contain the shell commands
+    neccessary to strip this target's binary. These should be run as postbuilds
+    before the actual postbuilds run."""
+    self.configname = configname
+
+    result = []
+    if (self._Test('DEPLOYMENT_POSTPROCESSING', 'YES', default='NO') and
+        self._Test('STRIP_INSTALLED_PRODUCT', 'YES', default='NO')):
+
+      default_strip_style = 'debugging'
+      if self._IsBundle():
+        default_strip_style = 'non-global'
+      elif self.spec['type'] == 'executable':
+        default_strip_style = 'all'
+
+      strip_style = self._Settings().get('STRIP_STYLE', default_strip_style)
+      strip_flags = {
+        'all': '',
+        'non-global': '-x',
+        'debugging': '-S',
+      }[strip_style]
+
+      explicit_strip_flags = self._Settings().get('STRIPFLAGS', '')
+      if explicit_strip_flags:
+        strip_flags += ' ' + _NormalizeEnvVarReferences(explicit_strip_flags)
+
+      if not quiet:
+        result.append('echo STRIP\\(%s\\)' % self.spec['target_name'])
+      result.append('strip %s %s' % (strip_flags, output_binary))
+
+    self.configname = None
+    return result
+
+  def _GetDebugInfoPostbuilds(self, configname, output, output_binary, quiet):
+    """Returns a list of shell commands that contain the shell commands
+    neccessary to massage this target's debug information. These should be run
+    as postbuilds before the actual postbuilds run."""
+    self.configname = configname
+
+    # For static libraries, no dSYMs are created.
+    result = []
+    if (self._Test('GCC_GENERATE_DEBUGGING_SYMBOLS', 'YES', default='YES') and
+        self._Test(
+            'DEBUG_INFORMATION_FORMAT', 'dwarf-with-dsym', default='dwarf') and
+        self.spec['type'] != 'static_library'):
+      if not quiet:
+        result.append('echo DSYMUTIL\\(%s\\)' % self.spec['target_name'])
+      result.append('dsymutil %s -o %s' % (output_binary, output + '.dSYM'))
+
+    self.configname = None
+    return result
+
+  def GetTargetPostbuilds(self, configname, output, output_binary, quiet=False):
+    """Returns a list of shell commands that contain the shell commands
+    to run as postbuilds for this target, before the actual postbuilds."""
+    # dSYMs need to build before stripping happens.
+    return (
+        self._GetDebugInfoPostbuilds(configname, output, output_binary, quiet) +
+        self._GetStripPostbuilds(configname, output_binary, quiet))
+
+  def _AdjustLibrary(self, library):
+    if library.endswith('.framework'):
+      l = '-framework ' + os.path.splitext(os.path.basename(library))[0]
+    else:
+      m = self.library_re.match(library)
+      if m:
+        l = '-l' + m.group(1)
+      else:
+        l = library
+    return l.replace('$(SDKROOT)', self._SdkPath())
+
+  def AdjustLibraries(self, libraries):
+    """Transforms entries like 'Cocoa.framework' in libraries into entries like
+    '-framework Cocoa', 'libcrypto.dylib' into '-lcrypto', etc.
+    """
+    libraries = [ self._AdjustLibrary(library) for library in libraries]
+    return libraries
+
+
+class MacPrefixHeader(object):
+  """A class that helps with emulating Xcode's GCC_PREFIX_HEADER feature.
+
+  This feature consists of several pieces:
+  * If GCC_PREFIX_HEADER is present, all compilations in that project get an
+    additional |-include path_to_prefix_header| cflag.
+  * If GCC_PRECOMPILE_PREFIX_HEADER is present too, then the prefix header is
+    instead compiled, and all other compilations in the project get an
+    additional |-include path_to_compiled_header| instead.
+    + Compiled prefix headers have the extension gch. There is one gch file for
+      every language used in the project (c, cc, m, mm), since gch files for
+      different languages aren't compatible.
+    + gch files themselves are built with the target's normal cflags, but they
+      obviously don't get the |-include| flag. Instead, they need a -x flag that
+      describes their language.
+    + All o files in the target need to depend on the gch file, to make sure
+      it's built before any o file is built.
+
+  This class helps with some of these tasks, but it needs help from the build
+  system for writing dependencies to the gch files, for writing build commands
+  for the gch files, and for figuring out the location of the gch files.
+  """
+  def __init__(self, xcode_settings,
+               gyp_path_to_build_path, gyp_path_to_build_output):
+    """If xcode_settings is None, all methods on this class are no-ops.
+
+    Args:
+        gyp_path_to_build_path: A function that takes a gyp-relative path,
+            and returns a path relative to the build directory.
+        gyp_path_to_build_output: A function that takes a gyp-relative path and
+            a language code ('c', 'cc', 'm', or 'mm'), and that returns a path
+            to where the output of precompiling that path for that language
+            should be placed (without the trailing '.gch').
+    """
+    # This doesn't support per-configuration prefix headers. Good enough
+    # for now.
+    self.header = None
+    self.compile_headers = False
+    if xcode_settings:
+      self.header = xcode_settings.GetPerTargetSetting('GCC_PREFIX_HEADER')
+      self.compile_headers = xcode_settings.GetPerTargetSetting(
+          'GCC_PRECOMPILE_PREFIX_HEADER', default='NO') != 'NO'
+    self.compiled_headers = {}
+    if self.header:
+      if self.compile_headers:
+        for lang in ['c', 'cc', 'm', 'mm']:
+          self.compiled_headers[lang] = gyp_path_to_build_output(
+              self.header, lang)
+      self.header = gyp_path_to_build_path(self.header)
+
+  def GetInclude(self, lang):
+    """Gets the cflags to include the prefix header for language |lang|."""
+    if self.compile_headers and lang in self.compiled_headers:
+      return '-include %s' % self.compiled_headers[lang]
+    elif self.header:
+      return '-include %s' % self.header
+    else:
+      return ''
+
+  def _Gch(self, lang):
+    """Returns the actual file name of the prefix header for language |lang|."""
+    assert self.compile_headers
+    return self.compiled_headers[lang] + '.gch'
+
+  def GetObjDependencies(self, sources, objs):
+    """Given a list of source files and the corresponding object files, returns
+    a list of (source, object, gch) tuples, where |gch| is the build-directory
+    relative path to the gch file each object file depends on.  |compilable[i]|
+    has to be the source file belonging to |objs[i]|."""
+    if not self.header or not self.compile_headers:
+      return []
+
+    result = []
+    for source, obj in zip(sources, objs):
+      ext = os.path.splitext(source)[1]
+      lang = {
+        '.c': 'c',
+        '.cpp': 'cc', '.cc': 'cc', '.cxx': 'cc',
+        '.m': 'm',
+        '.mm': 'mm',
+      }.get(ext, None)
+      if lang:
+        result.append((source, obj, self._Gch(lang)))
+    return result
+
+  def GetPchBuildCommands(self):
+    """Returns [(path_to_gch, language_flag, language, header)].
+    |path_to_gch| and |header| are relative to the build directory.
+    """
+    if not self.header or not self.compile_headers:
+      return []
+    return [
+      (self._Gch('c'), '-x c-header', 'c', self.header),
+      (self._Gch('cc'), '-x c++-header', 'cc', self.header),
+      (self._Gch('m'), '-x objective-c-header', 'm', self.header),
+      (self._Gch('mm'), '-x objective-c++-header', 'mm', self.header),
+    ]
+
+
+def MergeGlobalXcodeSettingsToSpec(global_dict, spec):
+  """Merges the global xcode_settings dictionary into each configuration of the
+  target represented by spec. For keys that are both in the global and the local
+  xcode_settings dict, the local key gets precendence.
+  """
+  # The xcode generator special-cases global xcode_settings and does something
+  # that amounts to merging in the global xcode_settings into each local
+  # xcode_settings dict.
+  global_xcode_settings = global_dict.get('xcode_settings', {})
+  for config in spec['configurations'].values():
+    if 'xcode_settings' in config:
+      new_settings = global_xcode_settings.copy()
+      new_settings.update(config['xcode_settings'])
+      config['xcode_settings'] = new_settings
+
+
+def IsMacBundle(flavor, spec):
+  """Returns if |spec| should be treated as a bundle.
+
+  Bundles are directories with a certain subdirectory structure, instead of
+  just a single file. Bundle rules do not produce a binary but also package
+  resources into that directory."""
+  is_mac_bundle = (int(spec.get('mac_bundle', 0)) != 0 and flavor == 'mac')
+  if is_mac_bundle:
+    assert spec['type'] != 'none', (
+        'mac_bundle targets cannot have type none (target "%s")' %
+        spec['target_name'])
+  return is_mac_bundle
+
+
+def GetMacBundleResources(product_dir, xcode_settings, resources):
+  """Yields (output, resource) pairs for every resource in |resources|.
+  Only call this for mac bundle targets.
+
+  Args:
+      product_dir: Path to the directory containing the output bundle,
+          relative to the build directory.
+      xcode_settings: The XcodeSettings of the current target.
+      resources: A list of bundle resources, relative to the build directory.
+  """
+  dest = os.path.join(product_dir,
+                      xcode_settings.GetBundleResourceFolder())
+  for res in resources:
+    output = dest
+
+    # The make generator doesn't support it, so forbid it everywhere
+    # to keep the generators more interchangable.
+    assert ' ' not in res, (
+      "Spaces in resource filenames not supported (%s)"  % res)
+
+    # Split into (path,file).
+    res_parts = os.path.split(res)
+
+    # Now split the path into (prefix,maybe.lproj).
+    lproj_parts = os.path.split(res_parts[0])
+    # If the resource lives in a .lproj bundle, add that to the destination.
+    if lproj_parts[1].endswith('.lproj'):
+      output = os.path.join(output, lproj_parts[1])
+
+    output = os.path.join(output, res_parts[1])
+    # Compiled XIB files are referred to by .nib.
+    if output.endswith('.xib'):
+      output = output[0:-3] + 'nib'
+
+    yield output, res
+
+
+def GetMacInfoPlist(product_dir, xcode_settings, gyp_path_to_build_path):
+  """Returns (info_plist, dest_plist, defines, extra_env), where:
+  * |info_plist| is the sourc plist path, relative to the
+    build directory,
+  * |dest_plist| is the destination plist path, relative to the
+    build directory,
+  * |defines| is a list of preprocessor defines (empty if the plist
+    shouldn't be preprocessed,
+  * |extra_env| is a dict of env variables that should be exported when
+    invoking |mac_tool copy-info-plist|.
+
+  Only call this for mac bundle targets.
+
+  Args:
+      product_dir: Path to the directory containing the output bundle,
+          relative to the build directory.
+      xcode_settings: The XcodeSettings of the current target.
+      gyp_to_build_path: A function that converts paths relative to the
+          current gyp file to paths relative to the build direcotry.
+  """
+  info_plist = xcode_settings.GetPerTargetSetting('INFOPLIST_FILE')
+  if not info_plist:
+    return None, None, [], {}
+
+  # The make generator doesn't support it, so forbid it everywhere
+  # to keep the generators more interchangable.
+  assert ' ' not in info_plist, (
+    "Spaces in Info.plist filenames not supported (%s)"  % info_plist)
+
+  info_plist = gyp_path_to_build_path(info_plist)
+
+  # If explicitly set to preprocess the plist, invoke the C preprocessor and
+  # specify any defines as -D flags.
+  if xcode_settings.GetPerTargetSetting(
+      'INFOPLIST_PREPROCESS', default='NO') == 'YES':
+    # Create an intermediate file based on the path.
+    defines = shlex.split(xcode_settings.GetPerTargetSetting(
+        'INFOPLIST_PREPROCESSOR_DEFINITIONS', default=''))
+  else:
+    defines = []
+
+  dest_plist = os.path.join(product_dir, xcode_settings.GetBundlePlistPath())
+  extra_env = xcode_settings.GetPerTargetSettings()
+
+  return info_plist, dest_plist, defines, extra_env
+
+
+def _GetXcodeEnv(xcode_settings, built_products_dir, srcroot, configuration,
+                additional_settings=None):
+  """Return the environment variables that Xcode would set. See
+  http://developer.apple.com/library/mac/#documentation/DeveloperTools/Reference/XcodeBuildSettingRef/1-Build_Setting_Reference/build_setting_ref.html#//apple_ref/doc/uid/TP40003931-CH3-SW153
+  for a full list.
+
+  Args:
+      xcode_settings: An XcodeSettings object. If this is None, this function
+          returns an empty dict.
+      built_products_dir: Absolute path to the built products dir.
+      srcroot: Absolute path to the source root.
+      configuration: The build configuration name.
+      additional_settings: An optional dict with more values to add to the
+          result.
+  """
+  if not xcode_settings: return {}
+
+  # This function is considered a friend of XcodeSettings, so let it reach into
+  # its implementation details.
+  spec = xcode_settings.spec
+
+  # These are filled in on a as-needed basis.
+  env = {
+    'BUILT_PRODUCTS_DIR' : built_products_dir,
+    'CONFIGURATION' : configuration,
+    'PRODUCT_NAME' : xcode_settings.GetProductName(),
+    # See /Developer/Platforms/MacOSX.platform/Developer/Library/Xcode/Specifications/MacOSX\ Product\ Types.xcspec for FULL_PRODUCT_NAME
+    'SRCROOT' : srcroot,
+    'SOURCE_ROOT': '${SRCROOT}',
+    # This is not true for static libraries, but currently the env is only
+    # written for bundles:
+    'TARGET_BUILD_DIR' : built_products_dir,
+    'TEMP_DIR' : '${TMPDIR}',
+  }
+  if xcode_settings.GetPerTargetSetting('SDKROOT'):
+    env['SDKROOT'] = xcode_settings._SdkPath()
+  else:
+    env['SDKROOT'] = ''
+
+  if spec['type'] in (
+      'executable', 'static_library', 'shared_library', 'loadable_module'):
+    env['EXECUTABLE_NAME'] = xcode_settings.GetExecutableName()
+    env['EXECUTABLE_PATH'] = xcode_settings.GetExecutablePath()
+    env['FULL_PRODUCT_NAME'] = xcode_settings.GetFullProductName()
+    mach_o_type = xcode_settings.GetMachOType()
+    if mach_o_type:
+      env['MACH_O_TYPE'] = mach_o_type
+    env['PRODUCT_TYPE'] = xcode_settings.GetProductType()
+  if xcode_settings._IsBundle():
+    env['CONTENTS_FOLDER_PATH'] = \
+      xcode_settings.GetBundleContentsFolderPath()
+    env['UNLOCALIZED_RESOURCES_FOLDER_PATH'] = \
+        xcode_settings.GetBundleResourceFolder()
+    env['INFOPLIST_PATH'] = xcode_settings.GetBundlePlistPath()
+    env['WRAPPER_NAME'] = xcode_settings.GetWrapperName()
+
+  install_name = xcode_settings.GetInstallName()
+  if install_name:
+    env['LD_DYLIB_INSTALL_NAME'] = install_name
+  install_name_base = xcode_settings.GetInstallNameBase()
+  if install_name_base:
+    env['DYLIB_INSTALL_NAME_BASE'] = install_name_base
+
+  if not additional_settings:
+    additional_settings = {}
+  else:
+    # Flatten lists to strings.
+    for k in additional_settings:
+      if not isinstance(additional_settings[k], str):
+        additional_settings[k] = ' '.join(additional_settings[k])
+  additional_settings.update(env)
+
+  for k in additional_settings:
+    additional_settings[k] = _NormalizeEnvVarReferences(additional_settings[k])
+
+  return additional_settings
+
+
+def _NormalizeEnvVarReferences(str):
+  """Takes a string containing variable references in the form ${FOO}, $(FOO),
+  or $FOO, and returns a string with all variable references in the form ${FOO}.
+  """
+  # $FOO -> ${FOO}
+  str = re.sub(r'\$([a-zA-Z_][a-zA-Z0-9_]*)', r'${\1}', str)
+
+  # $(FOO) -> ${FOO}
+  matches = re.findall(r'(\$\(([a-zA-Z0-9\-_]+)\))', str)
+  for match in matches:
+    to_replace, variable = match
+    assert '$(' not in match, '$($(FOO)) variables not supported: ' + match
+    str = str.replace(to_replace, '${' + variable + '}')
+
+  return str
+
+
+def ExpandEnvVars(string, expansions):
+  """Expands ${VARIABLES}, $(VARIABLES), and $VARIABLES in string per the
+  expansions list. If the variable expands to something that references
+  another variable, this variable is expanded as well if it's in env --
+  until no variables present in env are left."""
+  for k, v in reversed(expansions):
+    string = string.replace('${' + k + '}', v)
+    string = string.replace('$(' + k + ')', v)
+    string = string.replace('$' + k, v)
+  return string
+
+
+def _TopologicallySortedEnvVarKeys(env):
+  """Takes a dict |env| whose values are strings that can refer to other keys,
+  for example env['foo'] = '$(bar) and $(baz)'. Returns a list L of all keys of
+  env such that key2 is after key1 in L if env[key2] refers to env[key1].
+
+  Throws an Exception in case of dependency cycles.
+  """
+  # Since environment variables can refer to other variables, the evaluation
+  # order is important. Below is the logic to compute the dependency graph
+  # and sort it.
+  regex = re.compile(r'\$\{([a-zA-Z0-9\-_]+)\}')
+  def GetEdges(node):
+    # Use a definition of edges such that user_of_variable -> used_varible.
+    # This happens to be easier in this case, since a variable's
+    # definition contains all variables it references in a single string.
+    # We can then reverse the result of the topological sort at the end.
+    # Since: reverse(topsort(DAG)) = topsort(reverse_edges(DAG))
+    matches = set([v for v in regex.findall(env[node]) if v in env])
+    for dependee in matches:
+      assert '${' not in dependee, 'Nested variables not supported: ' + dependee
+    return matches
+
+  try:
+    # Topologically sort, and then reverse, because we used an edge definition
+    # that's inverted from the expected result of this function (see comment
+    # above).
+    order = gyp.common.TopologicallySorted(env.keys(), GetEdges)
+    order.reverse()
+    return order
+  except gyp.common.CycleError, e:
+    raise GypError(
+        'Xcode environment variables are cyclically dependent: ' + str(e.nodes))
+
+
+def GetSortedXcodeEnv(xcode_settings, built_products_dir, srcroot,
+                      configuration, additional_settings=None):
+  env = _GetXcodeEnv(xcode_settings, built_products_dir, srcroot, configuration,
+                    additional_settings)
+  return [(key, env[key]) for key in _TopologicallySortedEnvVarKeys(env)]
+
+
+def GetSpecPostbuildCommands(spec, quiet=False):
+  """Returns the list of postbuilds explicitly defined on |spec|, in a form
+  executable by a shell."""
+  postbuilds = []
+  for postbuild in spec.get('postbuilds', []):
+    if not quiet:
+      postbuilds.append('echo POSTBUILD\\(%s\\) %s' % (
+            spec['target_name'], postbuild['postbuild_name']))
+    postbuilds.append(gyp.common.EncodePOSIXShellList(postbuild['action']))
+  return postbuilds
diff --git a/webWidgetTCT_device/tools/gyp/pylib/gyp/xcodeproj_file.py b/webWidgetTCT_device/tools/gyp/pylib/gyp/xcodeproj_file.py
new file mode 100755 (executable)
index 0000000..47712a7
--- /dev/null
@@ -0,0 +1,2870 @@
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Xcode project file generator.
+
+This module is both an Xcode project file generator and a documentation of the
+Xcode project file format.  Knowledge of the project file format was gained
+based on extensive experience with Xcode, and by making changes to projects in
+Xcode.app and observing the resultant changes in the associated project files.
+
+XCODE PROJECT FILES
+
+The generator targets the file format as written by Xcode 3.2 (specifically,
+3.2.6), but past experience has taught that the format has not changed
+significantly in the past several years, and future versions of Xcode are able
+to read older project files.
+
+Xcode project files are "bundled": the project "file" from an end-user's
+perspective is actually a directory with an ".xcodeproj" extension.  The
+project file from this module's perspective is actually a file inside this
+directory, always named "project.pbxproj".  This file contains a complete
+description of the project and is all that is needed to use the xcodeproj.
+Other files contained in the xcodeproj directory are simply used to store
+per-user settings, such as the state of various UI elements in the Xcode
+application.
+
+The project.pbxproj file is a property list, stored in a format almost
+identical to the NeXTstep property list format.  The file is able to carry
+Unicode data, and is encoded in UTF-8.  The root element in the property list
+is a dictionary that contains several properties of minimal interest, and two
+properties of immense interest.  The most important property is a dictionary
+named "objects".  The entire structure of the project is represented by the
+children of this property.  The objects dictionary is keyed by unique 96-bit
+values represented by 24 uppercase hexadecimal characters.  Each value in the
+objects dictionary is itself a dictionary, describing an individual object.
+
+Each object in the dictionary is a member of a class, which is identified by
+the "isa" property of each object.  A variety of classes are represented in a
+project file.  Objects can refer to other objects by ID, using the 24-character
+hexadecimal object key.  A project's objects form a tree, with a root object
+of class PBXProject at the root.  As an example, the PBXProject object serves
+as parent to an XCConfigurationList object defining the build configurations
+used in the project, a PBXGroup object serving as a container for all files
+referenced in the project, and a list of target objects, each of which defines
+a target in the project.  There are several different types of target object,
+such as PBXNativeTarget and PBXAggregateTarget.  In this module, this
+relationship is expressed by having each target type derive from an abstract
+base named XCTarget.
+
+The project.pbxproj file's root dictionary also contains a property, sibling to
+the "objects" dictionary, named "rootObject".  The value of rootObject is a
+24-character object key referring to the root PBXProject object in the
+objects dictionary.
+
+In Xcode, every file used as input to a target or produced as a final product
+of a target must appear somewhere in the hierarchy rooted at the PBXGroup
+object referenced by the PBXProject's mainGroup property.  A PBXGroup is
+generally represented as a folder in the Xcode application.  PBXGroups can
+contain other PBXGroups as well as PBXFileReferences, which are pointers to
+actual files.
+
+Each XCTarget contains a list of build phases, represented in this module by
+the abstract base XCBuildPhase.  Examples of concrete XCBuildPhase derivations
+are PBXSourcesBuildPhase and PBXFrameworksBuildPhase, which correspond to the
+"Compile Sources" and "Link Binary With Libraries" phases displayed in the
+Xcode application.  Files used as input to these phases (for example, source
+files in the former case and libraries and frameworks in the latter) are
+represented by PBXBuildFile objects, referenced by elements of "files" lists
+in XCTarget objects.  Each PBXBuildFile object refers to a PBXBuildFile
+object as a "weak" reference: it does not "own" the PBXBuildFile, which is
+owned by the root object's mainGroup or a descendant group.  In most cases, the
+layer of indirection between an XCBuildPhase and a PBXFileReference via a
+PBXBuildFile appears extraneous, but there's actually one reason for this:
+file-specific compiler flags are added to the PBXBuildFile object so as to
+allow a single file to be a member of multiple targets while having distinct
+compiler flags for each.  These flags can be modified in the Xcode applciation
+in the "Build" tab of a File Info window.
+
+When a project is open in the Xcode application, Xcode will rewrite it.  As
+such, this module is careful to adhere to the formatting used by Xcode, to
+avoid insignificant changes appearing in the file when it is used in the
+Xcode application.  This will keep version control repositories happy, and
+makes it possible to compare a project file used in Xcode to one generated by
+this module to determine if any significant changes were made in the
+application.
+
+Xcode has its own way of assigning 24-character identifiers to each object,
+which is not duplicated here.  Because the identifier only is only generated
+once, when an object is created, and is then left unchanged, there is no need
+to attempt to duplicate Xcode's behavior in this area.  The generator is free
+to select any identifier, even at random, to refer to the objects it creates,
+and Xcode will retain those identifiers and use them when subsequently
+rewriting the project file.  However, the generator would choose new random
+identifiers each time the project files are generated, leading to difficulties
+comparing "used" project files to "pristine" ones produced by this module,
+and causing the appearance of changes as every object identifier is changed
+when updated projects are checked in to a version control repository.  To
+mitigate this problem, this module chooses identifiers in a more deterministic
+way, by hashing a description of each object as well as its parent and ancestor
+objects.  This strategy should result in minimal "shift" in IDs as successive
+generations of project files are produced.
+
+THIS MODULE
+
+This module introduces several classes, all derived from the XCObject class.
+Nearly all of the "brains" are built into the XCObject class, which understands
+how to create and modify objects, maintain the proper tree structure, compute
+identifiers, and print objects.  For the most part, classes derived from
+XCObject need only provide a _schema class object, a dictionary that
+expresses what properties objects of the class may contain.
+
+Given this structure, it's possible to build a minimal project file by creating
+objects of the appropriate types and making the proper connections:
+
+  config_list = XCConfigurationList()
+  group = PBXGroup()
+  project = PBXProject({'buildConfigurationList': config_list,
+                        'mainGroup': group})
+
+With the project object set up, it can be added to an XCProjectFile object.
+XCProjectFile is a pseudo-class in the sense that it is a concrete XCObject
+subclass that does not actually correspond to a class type found in a project
+file.  Rather, it is used to represent the project file's root dictionary.
+Printing an XCProjectFile will print the entire project file, including the
+full "objects" dictionary.
+
+  project_file = XCProjectFile({'rootObject': project})
+  project_file.ComputeIDs()
+  project_file.Print()
+
+Xcode project files are always encoded in UTF-8.  This module will accept
+strings of either the str class or the unicode class.  Strings of class str
+are assumed to already be encoded in UTF-8.  Obviously, if you're just using
+ASCII, you won't encounter difficulties because ASCII is a UTF-8 subset.
+Strings of class unicode are handled properly and encoded in UTF-8 when
+a project file is output.
+"""
+
+import gyp.common
+import posixpath
+import re
+import struct
+import sys
+
+# hashlib is supplied as of Python 2.5 as the replacement interface for sha
+# and other secure hashes.  In 2.6, sha is deprecated.  Import hashlib if
+# available, avoiding a deprecation warning under 2.6.  Import sha otherwise,
+# preserving 2.4 compatibility.
+try:
+  import hashlib
+  _new_sha1 = hashlib.sha1
+except ImportError:
+  import sha
+  _new_sha1 = sha.new
+
+
+# See XCObject._EncodeString.  This pattern is used to determine when a string
+# can be printed unquoted.  Strings that match this pattern may be printed
+# unquoted.  Strings that do not match must be quoted and may be further
+# transformed to be properly encoded.  Note that this expression matches the
+# characters listed with "+", for 1 or more occurrences: if a string is empty,
+# it must not match this pattern, because it needs to be encoded as "".
+_unquoted = re.compile('^[A-Za-z0-9$./_]+$')
+
+# Strings that match this pattern are quoted regardless of what _unquoted says.
+# Oddly, Xcode will quote any string with a run of three or more underscores.
+_quoted = re.compile('___')
+
+# This pattern should match any character that needs to be escaped by
+# XCObject._EncodeString.  See that function.
+_escaped = re.compile('[\\\\"]|[^ -~]')
+
+
+# Used by SourceTreeAndPathFromPath
+_path_leading_variable = re.compile('^\$\((.*?)\)(/(.*))?$')
+
+def SourceTreeAndPathFromPath(input_path):
+  """Given input_path, returns a tuple with sourceTree and path values.
+
+  Examples:
+    input_path     (source_tree, output_path)
+    '$(VAR)/path'  ('VAR', 'path')
+    '$(VAR)'       ('VAR', None)
+    'path'         (None, 'path')
+  """
+
+  source_group_match = _path_leading_variable.match(input_path)
+  if source_group_match:
+    source_tree = source_group_match.group(1)
+    output_path = source_group_match.group(3)  # This may be None.
+  else:
+    source_tree = None
+    output_path = input_path
+
+  return (source_tree, output_path)
+
+def ConvertVariablesToShellSyntax(input_string):
+  return re.sub('\$\((.*?)\)', '${\\1}', input_string)
+
+class XCObject(object):
+  """The abstract base of all class types used in Xcode project files.
+
+  Class variables:
+    _schema: A dictionary defining the properties of this class.  The keys to
+             _schema are string property keys as used in project files.  Values
+             are a list of four or five elements:
+             [ is_list, property_type, is_strong, is_required, default ]
+             is_list: True if the property described is a list, as opposed
+                      to a single element.
+             property_type: The type to use as the value of the property,
+                            or if is_list is True, the type to use for each
+                            element of the value's list.  property_type must
+                            be an XCObject subclass, or one of the built-in
+                            types str, int, or dict.
+             is_strong: If property_type is an XCObject subclass, is_strong
+                        is True to assert that this class "owns," or serves
+                        as parent, to the property value (or, if is_list is
+                        True, values).  is_strong must be False if
+                        property_type is not an XCObject subclass.
+             is_required: True if the property is required for the class.
+                          Note that is_required being True does not preclude
+                          an empty string ("", in the case of property_type
+                          str) or list ([], in the case of is_list True) from
+                          being set for the property.
+             default: Optional.  If is_requried is True, default may be set
+                      to provide a default value for objects that do not supply
+                      their own value.  If is_required is True and default
+                      is not provided, users of the class must supply their own
+                      value for the property.
+             Note that although the values of the array are expressed in
+             boolean terms, subclasses provide values as integers to conserve
+             horizontal space.
+    _should_print_single_line: False in XCObject.  Subclasses whose objects
+                               should be written to the project file in the
+                               alternate single-line format, such as
+                               PBXFileReference and PBXBuildFile, should
+                               set this to True.
+    _encode_transforms: Used by _EncodeString to encode unprintable characters.
+                        The index into this list is the ordinal of the
+                        character to transform; each value is a string
+                        used to represent the character in the output.  XCObject
+                        provides an _encode_transforms list suitable for most
+                        XCObject subclasses.
+    _alternate_encode_transforms: Provided for subclasses that wish to use
+                                  the alternate encoding rules.  Xcode seems
+                                  to use these rules when printing objects in
+                                  single-line format.  Subclasses that desire
+                                  this behavior should set _encode_transforms
+                                  to _alternate_encode_transforms.
+    _hashables: A list of XCObject subclasses that can be hashed by ComputeIDs
+                to construct this object's ID.  Most classes that need custom
+                hashing behavior should do it by overriding Hashables,
+                but in some cases an object's parent may wish to push a
+                hashable value into its child, and it can do so by appending
+                to _hashables.
+  Attributes:
+    id: The object's identifier, a 24-character uppercase hexadecimal string.
+        Usually, objects being created should not set id until the entire
+        project file structure is built.  At that point, UpdateIDs() should
+        be called on the root object to assign deterministic values for id to
+        each object in the tree.
+    parent: The object's parent.  This is set by a parent XCObject when a child
+            object is added to it.
+    _properties: The object's property dictionary.  An object's properties are
+                 described by its class' _schema variable.
+  """
+
+  _schema = {}
+  _should_print_single_line = False
+
+  # See _EncodeString.
+  _encode_transforms = []
+  i = 0
+  while i < ord(' '):
+    _encode_transforms.append('\\U%04x' % i)
+    i = i + 1
+  _encode_transforms[7] = '\\a'
+  _encode_transforms[8] = '\\b'
+  _encode_transforms[9] = '\\t'
+  _encode_transforms[10] = '\\n'
+  _encode_transforms[11] = '\\v'
+  _encode_transforms[12] = '\\f'
+  _encode_transforms[13] = '\\n'
+
+  _alternate_encode_transforms = list(_encode_transforms)
+  _alternate_encode_transforms[9] = chr(9)
+  _alternate_encode_transforms[10] = chr(10)
+  _alternate_encode_transforms[11] = chr(11)
+
+  def __init__(self, properties=None, id=None, parent=None):
+    self.id = id
+    self.parent = parent
+    self._properties = {}
+    self._hashables = []
+    self._SetDefaultsFromSchema()
+    self.UpdateProperties(properties)
+
+  def __repr__(self):
+    try:
+      name = self.Name()
+    except NotImplementedError:
+      return '<%s at 0x%x>' % (self.__class__.__name__, id(self))
+    return '<%s %r at 0x%x>' % (self.__class__.__name__, name, id(self))
+
+  def Copy(self):
+    """Make a copy of this object.
+
+    The new object will have its own copy of lists and dicts.  Any XCObject
+    objects owned by this object (marked "strong") will be copied in the
+    new object, even those found in lists.  If this object has any weak
+    references to other XCObjects, the same references are added to the new
+    object without making a copy.
+    """
+
+    that = self.__class__(id=self.id, parent=self.parent)
+    for key, value in self._properties.iteritems():
+      is_strong = self._schema[key][2]
+
+      if isinstance(value, XCObject):
+        if is_strong:
+          new_value = value.Copy()
+          new_value.parent = that
+          that._properties[key] = new_value
+        else:
+          that._properties[key] = value
+      elif isinstance(value, str) or isinstance(value, unicode) or \
+           isinstance(value, int):
+        that._properties[key] = value
+      elif isinstance(value, list):
+        if is_strong:
+          # If is_strong is True, each element is an XCObject, so it's safe to
+          # call Copy.
+          that._properties[key] = []
+          for item in value:
+            new_item = item.Copy()
+            new_item.parent = that
+            that._properties[key].append(new_item)
+        else:
+          that._properties[key] = value[:]
+      elif isinstance(value, dict):
+        # dicts are never strong.
+        if is_strong:
+          raise TypeError, 'Strong dict for key ' + key + ' in ' + \
+                           self.__class__.__name__
+        else:
+          that._properties[key] = value.copy()
+      else:
+        raise TypeError, 'Unexpected type ' + value.__class__.__name__ + \
+                         ' for key ' + key + ' in ' + self.__class__.__name__
+
+    return that
+
+  def Name(self):
+    """Return the name corresponding to an object.
+
+    Not all objects necessarily need to be nameable, and not all that do have
+    a "name" property.  Override as needed.
+    """
+
+    # If the schema indicates that "name" is required, try to access the
+    # property even if it doesn't exist.  This will result in a KeyError
+    # being raised for the property that should be present, which seems more
+    # appropriate than NotImplementedError in this case.
+    if 'name' in self._properties or \
+        ('name' in self._schema and self._schema['name'][3]):
+      return self._properties['name']
+
+    raise NotImplementedError, \
+          self.__class__.__name__ + ' must implement Name'
+
+  def Comment(self):
+    """Return a comment string for the object.
+
+    Most objects just use their name as the comment, but PBXProject uses
+    different values.
+
+    The returned comment is not escaped and does not have any comment marker
+    strings applied to it.
+    """
+
+    return self.Name()
+
+  def Hashables(self):
+    hashables = [self.__class__.__name__]
+
+    name = self.Name()
+    if name != None:
+      hashables.append(name)
+
+    hashables.extend(self._hashables)
+
+    return hashables
+
+  def HashablesForChild(self):
+    return None
+
+  def ComputeIDs(self, recursive=True, overwrite=True, seed_hash=None):
+    """Set "id" properties deterministically.
+
+    An object's "id" property is set based on a hash of its class type and
+    name, as well as the class type and name of all ancestor objects.  As
+    such, it is only advisable to call ComputeIDs once an entire project file
+    tree is built.
+
+    If recursive is True, recurse into all descendant objects and update their
+    hashes.
+
+    If overwrite is True, any existing value set in the "id" property will be
+    replaced.
+    """
+
+    def _HashUpdate(hash, data):
+      """Update hash with data's length and contents.
+
+      If the hash were updated only with the value of data, it would be
+      possible for clowns to induce collisions by manipulating the names of
+      their objects.  By adding the length, it's exceedingly less likely that
+      ID collisions will be encountered, intentionally or not.
+      """
+
+      hash.update(struct.pack('>i', len(data)))
+      hash.update(data)
+
+    if seed_hash is None:
+      seed_hash = _new_sha1()
+
+    hash = seed_hash.copy()
+
+    hashables = self.Hashables()
+    assert len(hashables) > 0
+    for hashable in hashables:
+      _HashUpdate(hash, hashable)
+
+    if recursive:
+      hashables_for_child = self.HashablesForChild()
+      if hashables_for_child is None:
+        child_hash = hash
+      else:
+        assert len(hashables_for_child) > 0
+        child_hash = seed_hash.copy()
+        for hashable in hashables_for_child:
+          _HashUpdate(child_hash, hashable)
+
+      for child in self.Children():
+        child.ComputeIDs(recursive, overwrite, child_hash)
+
+    if overwrite or self.id is None:
+      # Xcode IDs are only 96 bits (24 hex characters), but a SHA-1 digest is
+      # is 160 bits.  Instead of throwing out 64 bits of the digest, xor them
+      # into the portion that gets used.
+      assert hash.digest_size % 4 == 0
+      digest_int_count = hash.digest_size / 4
+      digest_ints = struct.unpack('>' + 'I' * digest_int_count, hash.digest())
+      id_ints = [0, 0, 0]
+      for index in xrange(0, digest_int_count):
+        id_ints[index % 3] ^= digest_ints[index]
+      self.id = '%08X%08X%08X' % tuple(id_ints)
+
+  def EnsureNoIDCollisions(self):
+    """Verifies that no two objects have the same ID.  Checks all descendants.
+    """
+
+    ids = {}
+    descendants = self.Descendants()
+    for descendant in descendants:
+      if descendant.id in ids:
+        other = ids[descendant.id]
+        raise KeyError, \
+              'Duplicate ID %s, objects "%s" and "%s" in "%s"' % \
+              (descendant.id, str(descendant._properties),
+               str(other._properties), self._properties['rootObject'].Name())
+      ids[descendant.id] = descendant
+
+  def Children(self):
+    """Returns a list of all of this object's owned (strong) children."""
+
+    children = []
+    for property, attributes in self._schema.iteritems():
+      (is_list, property_type, is_strong) = attributes[0:3]
+      if is_strong and property in self._properties:
+        if not is_list:
+          children.append(self._properties[property])
+        else:
+          children.extend(self._properties[property])
+    return children
+
+  def Descendants(self):
+    """Returns a list of all of this object's descendants, including this
+    object.
+    """
+
+    children = self.Children()
+    descendants = [self]
+    for child in children:
+      descendants.extend(child.Descendants())
+    return descendants
+
+  def PBXProjectAncestor(self):
+    # The base case for recursion is defined at PBXProject.PBXProjectAncestor.
+    if self.parent:
+      return self.parent.PBXProjectAncestor()
+    return None
+
+  def _EncodeComment(self, comment):
+    """Encodes a comment to be placed in the project file output, mimicing
+    Xcode behavior.
+    """
+
+    # This mimics Xcode behavior by wrapping the comment in "/*" and "*/".  If
+    # the string already contains a "*/", it is turned into "(*)/".  This keeps
+    # the file writer from outputting something that would be treated as the
+    # end of a comment in the middle of something intended to be entirely a
+    # comment.
+
+    return '/* ' + comment.replace('*/', '(*)/') + ' */'
+
+  def _EncodeTransform(self, match):
+    # This function works closely with _EncodeString.  It will only be called
+    # by re.sub with match.group(0) containing a character matched by the
+    # the _escaped expression.
+    char = match.group(0)
+
+    # Backslashes (\) and quotation marks (") are always replaced with a
+    # backslash-escaped version of the same.  Everything else gets its
+    # replacement from the class' _encode_transforms array.
+    if char == '\\':
+      return '\\\\'
+    if char == '"':
+      return '\\"'
+    return self._encode_transforms[ord(char)]
+
+  def _EncodeString(self, value):
+    """Encodes a string to be placed in the project file output, mimicing
+    Xcode behavior.
+    """
+
+    # Use quotation marks when any character outside of the range A-Z, a-z, 0-9,
+    # $ (dollar sign), . (period), and _ (underscore) is present.  Also use
+    # quotation marks to represent empty strings.
+    #
+    # Escape " (double-quote) and \ (backslash) by preceding them with a
+    # backslash.
+    #
+    # Some characters below the printable ASCII range are encoded specially:
+    #     7 ^G BEL is encoded as "\a"
+    #     8 ^H BS  is encoded as "\b"
+    #    11 ^K VT  is encoded as "\v"
+    #    12 ^L NP  is encoded as "\f"
+    #   127 ^? DEL is passed through as-is without escaping
+    #  - In PBXFileReference and PBXBuildFile objects:
+    #     9 ^I HT  is passed through as-is without escaping
+    #    10 ^J NL  is passed through as-is without escaping
+    #    13 ^M CR  is passed through as-is without escaping
+    #  - In other objects:
+    #     9 ^I HT  is encoded as "\t"
+    #    10 ^J NL  is encoded as "\n"
+    #    13 ^M CR  is encoded as "\n" rendering it indistinguishable from
+    #              10 ^J NL
+    # All other nonprintable characters within the ASCII range (0 through 127
+    # inclusive) are encoded as "\U001f" referring to the Unicode code point in
+    # hexadecimal.  For example, character 14 (^N SO) is encoded as "\U000e".
+    # Characters above the ASCII range are passed through to the output encoded
+    # as UTF-8 without any escaping.  These mappings are contained in the
+    # class' _encode_transforms list.
+
+    if _unquoted.search(value) and not _quoted.search(value):
+      return value
+
+    return '"' + _escaped.sub(self._EncodeTransform, value) + '"'
+
+  def _XCPrint(self, file, tabs, line):
+    file.write('\t' * tabs + line)
+
+  def _XCPrintableValue(self, tabs, value, flatten_list=False):
+    """Returns a representation of value that may be printed in a project file,
+    mimicing Xcode's behavior.
+
+    _XCPrintableValue can handle str and int values, XCObjects (which are
+    made printable by returning their id property), and list and dict objects
+    composed of any of the above types.  When printing a list or dict, and
+    _should_print_single_line is False, the tabs parameter is used to determine
+    how much to indent the lines corresponding to the items in the list or
+    dict.
+
+    If flatten_list is True, single-element lists will be transformed into
+    strings.
+    """
+
+    printable = ''
+    comment = None
+
+    if self._should_print_single_line:
+      sep = ' '
+      element_tabs = ''
+      end_tabs = ''
+    else:
+      sep = '\n'
+      element_tabs = '\t' * (tabs + 1)
+      end_tabs = '\t' * tabs
+
+    if isinstance(value, XCObject):
+      printable += value.id
+      comment = value.Comment()
+    elif isinstance(value, str):
+      printable += self._EncodeString(value)
+    elif isinstance(value, unicode):
+      printable += self._EncodeString(value.encode('utf-8'))
+    elif isinstance(value, int):
+      printable += str(value)
+    elif isinstance(value, list):
+      if flatten_list and len(value) <= 1:
+        if len(value) == 0:
+          printable += self._EncodeString('')
+        else:
+          printable += self._EncodeString(value[0])
+      else:
+        printable = '(' + sep
+        for item in value:
+          printable += element_tabs + \
+                       self._XCPrintableValue(tabs + 1, item, flatten_list) + \
+                       ',' + sep
+        printable += end_tabs + ')'
+    elif isinstance(value, dict):
+      printable = '{' + sep
+      for item_key, item_value in sorted(value.iteritems()):
+        printable += element_tabs + \
+            self._XCPrintableValue(tabs + 1, item_key, flatten_list) + ' = ' + \
+            self._XCPrintableValue(tabs + 1, item_value, flatten_list) + ';' + \
+            sep
+      printable += end_tabs + '}'
+    else:
+      raise TypeError, "Can't make " + value.__class__.__name__ + ' printable'
+
+    if comment != None:
+      printable += ' ' + self._EncodeComment(comment)
+
+    return printable
+
+  def _XCKVPrint(self, file, tabs, key, value):
+    """Prints a key and value, members of an XCObject's _properties dictionary,
+    to file.
+
+    tabs is an int identifying the indentation level.  If the class'
+    _should_print_single_line variable is True, tabs is ignored and the
+    key-value pair will be followed by a space insead of a newline.
+    """
+
+    if self._should_print_single_line:
+      printable = ''
+      after_kv = ' '
+    else:
+      printable = '\t' * tabs
+      after_kv = '\n'
+
+    # Xcode usually prints remoteGlobalIDString values in PBXContainerItemProxy
+    # objects without comments.  Sometimes it prints them with comments, but
+    # the majority of the time, it doesn't.  To avoid unnecessary changes to
+    # the project file after Xcode opens it, don't write comments for
+    # remoteGlobalIDString.  This is a sucky hack and it would certainly be
+    # cleaner to extend the schema to indicate whether or not a comment should
+    # be printed, but since this is the only case where the problem occurs and
+    # Xcode itself can't seem to make up its mind, the hack will suffice.
+    #
+    # Also see PBXContainerItemProxy._schema['remoteGlobalIDString'].
+    if key == 'remoteGlobalIDString' and isinstance(self,
+                                                    PBXContainerItemProxy):
+      value_to_print = value.id
+    else:
+      value_to_print = value
+
+    # PBXBuildFile's settings property is represented in the output as a dict,
+    # but a hack here has it represented as a string. Arrange to strip off the
+    # quotes so that it shows up in the output as expected.
+    if key == 'settings' and isinstance(self, PBXBuildFile):
+      strip_value_quotes = True
+    else:
+      strip_value_quotes = False
+
+    # In another one-off, let's set flatten_list on buildSettings properties
+    # of XCBuildConfiguration objects, because that's how Xcode treats them.
+    if key == 'buildSettings' and isinstance(self, XCBuildConfiguration):
+      flatten_list = True
+    else:
+      flatten_list = False
+
+    try:
+      printable_key = self._XCPrintableValue(tabs, key, flatten_list)
+      printable_value = self._XCPrintableValue(tabs, value_to_print,
+                                               flatten_list)
+      if strip_value_quotes and len(printable_value) > 1 and \
+          printable_value[0] == '"' and printable_value[-1] == '"':
+        printable_value = printable_value[1:-1]
+      printable += printable_key + ' = ' + printable_value + ';' + after_kv
+    except TypeError, e:
+      gyp.common.ExceptionAppend(e,
+                                 'while printing key "%s"' % key)
+      raise
+
+    self._XCPrint(file, 0, printable)
+
+  def Print(self, file=sys.stdout):
+    """Prints a reprentation of this object to file, adhering to Xcode output
+    formatting.
+    """
+
+    self.VerifyHasRequiredProperties()
+
+    if self._should_print_single_line:
+      # When printing an object in a single line, Xcode doesn't put any space
+      # between the beginning of a dictionary (or presumably a list) and the
+      # first contained item, so you wind up with snippets like
+      #   ...CDEF = {isa = PBXFileReference; fileRef = 0123...
+      # If it were me, I would have put a space in there after the opening
+      # curly, but I guess this is just another one of those inconsistencies
+      # between how Xcode prints PBXFileReference and PBXBuildFile objects as
+      # compared to other objects.  Mimic Xcode's behavior here by using an
+      # empty string for sep.
+      sep = ''
+      end_tabs = 0
+    else:
+      sep = '\n'
+      end_tabs = 2
+
+    # Start the object.  For example, '\t\tPBXProject = {\n'.
+    self._XCPrint(file, 2, self._XCPrintableValue(2, self) + ' = {' + sep)
+
+    # "isa" isn't in the _properties dictionary, it's an intrinsic property
+    # of the class which the object belongs to.  Xcode always outputs "isa"
+    # as the first element of an object dictionary.
+    self._XCKVPrint(file, 3, 'isa', self.__class__.__name__)
+
+    # The remaining elements of an object dictionary are sorted alphabetically.
+    for property, value in sorted(self._properties.iteritems()):
+      self._XCKVPrint(file, 3, property, value)
+
+    # End the object.
+    self._XCPrint(file, end_tabs, '};\n')
+
+  def UpdateProperties(self, properties, do_copy=False):
+    """Merge the supplied properties into the _properties dictionary.
+
+    The input properties must adhere to the class schema or a KeyError or
+    TypeError exception will be raised.  If adding an object of an XCObject
+    subclass and the schema indicates a strong relationship, the object's
+    parent will be set to this object.
+
+    If do_copy is True, then lists, dicts, strong-owned XCObjects, and
+    strong-owned XCObjects in lists will be copied instead of having their
+    references added.
+    """
+
+    if properties is None:
+      return
+
+    for property, value in properties.iteritems():
+      # Make sure the property is in the schema.
+      if not property in self._schema:
+        raise KeyError, property + ' not in ' + self.__class__.__name__
+
+      # Make sure the property conforms to the schema.
+      (is_list, property_type, is_strong) = self._schema[property][0:3]
+      if is_list:
+        if value.__class__ != list:
+          raise TypeError, \
+                property + ' of ' + self.__class__.__name__ + \
+                ' must be list, not ' + value.__class__.__name__
+        for item in value:
+          if not isinstance(item, property_type) and \
+             not (item.__class__ == unicode and property_type == str):
+            # Accept unicode where str is specified.  str is treated as
+            # UTF-8-encoded.
+            raise TypeError, \
+                  'item of ' + property + ' of ' + self.__class__.__name__ + \
+                  ' must be ' + property_type.__name__ + ', not ' + \
+                  item.__class__.__name__
+      elif not isinstance(value, property_type) and \
+           not (value.__class__ == unicode and property_type == str):
+        # Accept unicode where str is specified.  str is treated as
+        # UTF-8-encoded.
+        raise TypeError, \
+              property + ' of ' + self.__class__.__name__ + ' must be ' + \
+              property_type.__name__ + ', not ' + value.__class__.__name__
+
+      # Checks passed, perform the assignment.
+      if do_copy:
+        if isinstance(value, XCObject):
+          if is_strong:
+            self._properties[property] = value.Copy()
+          else:
+            self._properties[property] = value
+        elif isinstance(value, str) or isinstance(value, unicode) or \
+             isinstance(value, int):
+          self._properties[property] = value
+        elif isinstance(value, list):
+          if is_strong:
+            # If is_strong is True, each element is an XCObject, so it's safe
+            # to call Copy.
+            self._properties[property] = []
+            for item in value:
+              self._properties[property].append(item.Copy())
+          else:
+            self._properties[property] = value[:]
+        elif isinstance(value, dict):
+          self._properties[property] = value.copy()
+        else:
+          raise TypeError, "Don't know how to copy a " + \
+                           value.__class__.__name__ + ' object for ' + \
+                           property + ' in ' + self.__class__.__name__
+      else:
+        self._properties[property] = value
+
+      # Set up the child's back-reference to this object.  Don't use |value|
+      # any more because it may not be right if do_copy is true.
+      if is_strong:
+        if not is_list:
+          self._properties[property].parent = self
+        else:
+          for item in self._properties[property]:
+            item.parent = self
+
+  def HasProperty(self, key):
+    return key in self._properties
+
+  def GetProperty(self, key):
+    return self._properties[key]
+
+  def SetProperty(self, key, value):
+    self.UpdateProperties({key: value})
+
+  def DelProperty(self, key):
+    if key in self._properties:
+      del self._properties[key]
+
+  def AppendProperty(self, key, value):
+    # TODO(mark): Support ExtendProperty too (and make this call that)?
+
+    # Schema validation.
+    if not key in self._schema:
+      raise KeyError, key + ' not in ' + self.__class__.__name__
+
+    (is_list, property_type, is_strong) = self._schema[key][0:3]
+    if not is_list:
+      raise TypeError, key + ' of ' + self.__class__.__name__ + ' must be list'
+    if not isinstance(value, property_type):
+      raise TypeError, 'item of ' + key + ' of ' + self.__class__.__name__ + \
+                       ' must be ' + property_type.__name__ + ', not ' + \
+                       value.__class__.__name__
+
+    # If the property doesn't exist yet, create a new empty list to receive the
+    # item.
+    if not key in self._properties:
+      self._properties[key] = []
+
+    # Set up the ownership link.
+    if is_strong:
+      value.parent = self
+
+    # Store the item.
+    self._properties[key].append(value)
+
+  def VerifyHasRequiredProperties(self):
+    """Ensure that all properties identified as required by the schema are
+    set.
+    """
+
+    # TODO(mark): A stronger verification mechanism is needed.  Some
+    # subclasses need to perform validation beyond what the schema can enforce.
+    for property, attributes in self._schema.iteritems():
+      (is_list, property_type, is_strong, is_required) = attributes[0:4]
+      if is_required and not property in self._properties:
+        raise KeyError, self.__class__.__name__ + ' requires ' + property
+
+  def _SetDefaultsFromSchema(self):
+    """Assign object default values according to the schema.  This will not
+    overwrite properties that have already been set."""
+
+    defaults = {}
+    for property, attributes in self._schema.iteritems():
+      (is_list, property_type, is_strong, is_required) = attributes[0:4]
+      if is_required and len(attributes) >= 5 and \
+          not property in self._properties:
+        default = attributes[4]
+
+        defaults[property] = default
+
+    if len(defaults) > 0:
+      # Use do_copy=True so that each new object gets its own copy of strong
+      # objects, lists, and dicts.
+      self.UpdateProperties(defaults, do_copy=True)
+
+
+class XCHierarchicalElement(XCObject):
+  """Abstract base for PBXGroup and PBXFileReference.  Not represented in a
+  project file."""
+
+  # TODO(mark): Do name and path belong here?  Probably so.
+  # If path is set and name is not, name may have a default value.  Name will
+  # be set to the basename of path, if the basename of path is different from
+  # the full value of path.  If path is already just a leaf name, name will
+  # not be set.
+  _schema = XCObject._schema.copy()
+  _schema.update({
+    'comments':       [0, str, 0, 0],
+    'fileEncoding':   [0, str, 0, 0],
+    'includeInIndex': [0, int, 0, 0],
+    'indentWidth':    [0, int, 0, 0],
+    'lineEnding':     [0, int, 0, 0],
+    'sourceTree':     [0, str, 0, 1, '<group>'],
+    'tabWidth':       [0, int, 0, 0],
+    'usesTabs':       [0, int, 0, 0],
+    'wrapsLines':     [0, int, 0, 0],
+  })
+
+  def __init__(self, properties=None, id=None, parent=None):
+    # super
+    XCObject.__init__(self, properties, id, parent)
+    if 'path' in self._properties and not 'name' in self._properties:
+      path = self._properties['path']
+      name = posixpath.basename(path)
+      if name != '' and path != name:
+        self.SetProperty('name', name)
+
+    if 'path' in self._properties and \
+        (not 'sourceTree' in self._properties or \
+         self._properties['sourceTree'] == '<group>'):
+      # If the pathname begins with an Xcode variable like "$(SDKROOT)/", take
+      # the variable out and make the path be relative to that variable by
+      # assigning the variable name as the sourceTree.
+      (source_tree, path) = SourceTreeAndPathFromPath(self._properties['path'])
+      if source_tree != None:
+        self._properties['sourceTree'] = source_tree
+      if path != None:
+        self._properties['path'] = path
+      if source_tree != None and path is None and \
+         not 'name' in self._properties:
+        # The path was of the form "$(SDKROOT)" with no path following it.
+        # This object is now relative to that variable, so it has no path
+        # attribute of its own.  It does, however, keep a name.
+        del self._properties['path']
+        self._properties['name'] = source_tree
+
+  def Name(self):
+    if 'name' in self._properties:
+      return self._properties['name']
+    elif 'path' in self._properties:
+      return self._properties['path']
+    else:
+      # This happens in the case of the root PBXGroup.
+      return None
+
+  def Hashables(self):
+    """Custom hashables for XCHierarchicalElements.
+
+    XCHierarchicalElements are special.  Generally, their hashes shouldn't
+    change if the paths don't change.  The normal XCObject implementation of
+    Hashables adds a hashable for each object, which means that if
+    the hierarchical structure changes (possibly due to changes caused when
+    TakeOverOnlyChild runs and encounters slight changes in the hierarchy),
+    the hashes will change.  For example, if a project file initially contains
+    a/b/f1 and a/b becomes collapsed into a/b, f1 will have a single parent
+    a/b.  If someone later adds a/f2 to the project file, a/b can no longer be
+    collapsed, and f1 winds up with parent b and grandparent a.  That would
+    be sufficient to change f1's hash.
+
+    To counteract this problem, hashables for all XCHierarchicalElements except
+    for the main group (which has neither a name nor a path) are taken to be
+    just the set of path components.  Because hashables are inherited from
+    parents, this provides assurance that a/b/f1 has the same set of hashables
+    whether its parent is b or a/b.
+
+    The main group is a special case.  As it is permitted to have no name or
+    path, it is permitted to use the standard XCObject hash mechanism.  This
+    is not considered a problem because there can be only one main group.
+    """
+
+    if self == self.PBXProjectAncestor()._properties['mainGroup']:
+      # super
+      return XCObject.Hashables(self)
+
+    hashables = []
+
+    # Put the name in first, ensuring that if TakeOverOnlyChild collapses
+    # children into a top-level group like "Source", the name always goes
+    # into the list of hashables without interfering with path components.
+    if 'name' in self._properties:
+      # Make it less likely for people to manipulate hashes by following the
+      # pattern of always pushing an object type value onto the list first.
+      hashables.append(self.__class__.__name__ + '.name')
+      hashables.append(self._properties['name'])
+
+    # NOTE: This still has the problem that if an absolute path is encountered,
+    # including paths with a sourceTree, they'll still inherit their parents'
+    # hashables, even though the paths aren't relative to their parents.  This
+    # is not expected to be much of a problem in practice.
+    path = self.PathFromSourceTreeAndPath()
+    if path != None:
+      components = path.split(posixpath.sep)
+      for component in components:
+        hashables.append(self.__class__.__name__ + '.path')
+        hashables.append(component)
+
+    hashables.extend(self._hashables)
+
+    return hashables
+
+  def Compare(self, other):
+    # Allow comparison of these types.  PBXGroup has the highest sort rank;
+    # PBXVariantGroup is treated as equal to PBXFileReference.
+    valid_class_types = {
+      PBXFileReference: 'file',
+      PBXGroup:         'group',
+      PBXVariantGroup:  'file',
+    }
+    self_type = valid_class_types[self.__class__]
+    other_type = valid_class_types[other.__class__]
+
+    if self_type == other_type:
+      # If the two objects are of the same sort rank, compare their names.
+      return cmp(self.Name(), other.Name())
+
+    # Otherwise, sort groups before everything else.
+    if self_type == 'group':
+      return -1
+    return 1
+
+  def CompareRootGroup(self, other):
+    # This function should be used only to compare direct children of the
+    # containing PBXProject's mainGroup.  These groups should appear in the
+    # listed order.
+    # TODO(mark): "Build" is used by gyp.generator.xcode, perhaps the
+    # generator should have a way of influencing this list rather than having
+    # to hardcode for the generator here.
+    order = ['Source', 'Intermediates', 'Projects', 'Frameworks', 'Products',
+             'Build']
+
+    # If the groups aren't in the listed order, do a name comparison.
+    # Otherwise, groups in the listed order should come before those that
+    # aren't.
+    self_name = self.Name()
+    other_name = other.Name()
+    self_in = isinstance(self, PBXGroup) and self_name in order
+    other_in = isinstance(self, PBXGroup) and other_name in order
+    if not self_in and not other_in:
+      return self.Compare(other)
+    if self_name in order and not other_name in order:
+      return -1
+    if other_name in order and not self_name in order:
+      return 1
+
+    # If both groups are in the listed order, go by the defined order.
+    self_index = order.index(self_name)
+    other_index = order.index(other_name)
+    if self_index < other_index:
+      return -1
+    if self_index > other_index:
+      return 1
+    return 0
+
+  def PathFromSourceTreeAndPath(self):
+    # Turn the object's sourceTree and path properties into a single flat
+    # string of a form comparable to the path parameter.  If there's a
+    # sourceTree property other than "<group>", wrap it in $(...) for the
+    # comparison.
+    components = []
+    if self._properties['sourceTree'] != '<group>':
+      components.append('$(' + self._properties['sourceTree'] + ')')
+    if 'path' in self._properties:
+      components.append(self._properties['path'])
+
+    if len(components) > 0:
+      return posixpath.join(*components)
+
+    return None
+
+  def FullPath(self):
+    # Returns a full path to self relative to the project file, or relative
+    # to some other source tree.  Start with self, and walk up the chain of
+    # parents prepending their paths, if any, until no more parents are
+    # available (project-relative path) or until a path relative to some
+    # source tree is found.
+    xche = self
+    path = None
+    while isinstance(xche, XCHierarchicalElement) and \
+          (path is None or \
+           (not path.startswith('/') and not path.startswith('$'))):
+      this_path = xche.PathFromSourceTreeAndPath()
+      if this_path != None and path != None:
+        path = posixpath.join(this_path, path)
+      elif this_path != None:
+        path = this_path
+      xche = xche.parent
+
+    return path
+
+
+class PBXGroup(XCHierarchicalElement):
+  """
+  Attributes:
+    _children_by_path: Maps pathnames of children of this PBXGroup to the
+      actual child XCHierarchicalElement objects.
+    _variant_children_by_name_and_path: Maps (name, path) tuples of
+      PBXVariantGroup children to the actual child PBXVariantGroup objects.
+  """
+
+  _schema = XCHierarchicalElement._schema.copy()
+  _schema.update({
+    'children': [1, XCHierarchicalElement, 1, 1, []],
+    'name':     [0, str,                   0, 0],
+    'path':     [0, str,                   0, 0],
+  })
+
+  def __init__(self, properties=None, id=None, parent=None):
+    # super
+    XCHierarchicalElement.__init__(self, properties, id, parent)
+    self._children_by_path = {}
+    self._variant_children_by_name_and_path = {}
+    for child in self._properties.get('children', []):
+      self._AddChildToDicts(child)
+
+  def Hashables(self):
+    # super
+    hashables = XCHierarchicalElement.Hashables(self)
+
+    # It is not sufficient to just rely on name and parent to build a unique
+    # hashable : a node could have two child PBXGroup sharing a common name.
+    # To add entropy the hashable is enhanced with the names of all its
+    # children.
+    for child in self._properties.get('children', []):
+      child_name = child.Name()
+      if child_name != None:
+        hashables.append(child_name)
+
+    return hashables
+
+  def HashablesForChild(self):
+    # To avoid a circular reference the hashables used to compute a child id do
+    # not include the child names.
+    return XCHierarchicalElement.Hashables(self)
+
+  def _AddChildToDicts(self, child):
+    # Sets up this PBXGroup object's dicts to reference the child properly.
+    child_path = child.PathFromSourceTreeAndPath()
+    if child_path:
+      if child_path in self._children_by_path:
+        raise ValueError, 'Found multiple children with path ' + child_path
+      self._children_by_path[child_path] = child
+
+    if isinstance(child, PBXVariantGroup):
+      child_name = child._properties.get('name', None)
+      key = (child_name, child_path)
+      if key in self._variant_children_by_name_and_path:
+        raise ValueError, 'Found multiple PBXVariantGroup children with ' + \
+                          'name ' + str(child_name) + ' and path ' + \
+                          str(child_path)
+      self._variant_children_by_name_and_path[key] = child
+
+  def AppendChild(self, child):
+    # Callers should use this instead of calling
+    # AppendProperty('children', child) directly because this function
+    # maintains the group's dicts.
+    self.AppendProperty('children', child)
+    self._AddChildToDicts(child)
+
+  def GetChildByName(self, name):
+    # This is not currently optimized with a dict as GetChildByPath is because
+    # it has few callers.  Most callers probably want GetChildByPath.  This
+    # function is only useful to get children that have names but no paths,
+    # which is rare.  The children of the main group ("Source", "Products",
+    # etc.) is pretty much the only case where this likely to come up.
+    #
+    # TODO(mark): Maybe this should raise an error if more than one child is
+    # present with the same name.
+    if not 'children' in self._properties:
+      return None
+
+    for child in self._properties['children']:
+      if child.Name() == name:
+        return child
+
+    return None
+
+  def GetChildByPath(self, path):
+    if not path:
+      return None
+
+    if path in self._children_by_path:
+      return self._children_by_path[path]
+
+    return None
+
+  def GetChildByRemoteObject(self, remote_object):
+    # This method is a little bit esoteric.  Given a remote_object, which
+    # should be a PBXFileReference in another project file, this method will
+    # return this group's PBXReferenceProxy object serving as a local proxy
+    # for the remote PBXFileReference.
+    #
+    # This function might benefit from a dict optimization as GetChildByPath
+    # for some workloads, but profiling shows that it's not currently a
+    # problem.
+    if not 'children' in self._properties:
+      return None
+
+    for child in self._properties['children']:
+      if not isinstance(child, PBXReferenceProxy):
+        continue
+
+      container_proxy = child._properties['remoteRef']
+      if container_proxy._properties['remoteGlobalIDString'] == remote_object:
+        return child
+
+    return None
+
+  def AddOrGetFileByPath(self, path, hierarchical):
+    """Returns an existing or new file reference corresponding to path.
+
+    If hierarchical is True, this method will create or use the necessary
+    hierarchical group structure corresponding to path.  Otherwise, it will
+    look in and create an item in the current group only.
+
+    If an existing matching reference is found, it is returned, otherwise, a
+    new one will be created, added to the correct group, and returned.
+
+    If path identifies a directory by virtue of carrying a trailing slash,
+    this method returns a PBXFileReference of "folder" type.  If path
+    identifies a variant, by virtue of it identifying a file inside a directory
+    with an ".lproj" extension, this method returns a PBXVariantGroup
+    containing the variant named by path, and possibly other variants.  For
+    all other paths, a "normal" PBXFileReference will be returned.
+    """
+
+    # Adding or getting a directory?  Directories end with a trailing slash.
+    is_dir = False
+    if path.endswith('/'):
+      is_dir = True
+    path = posixpath.normpath(path)
+    if is_dir:
+      path = path + '/'
+
+    # Adding or getting a variant?  Variants are files inside directories
+    # with an ".lproj" extension.  Xcode uses variants for localization.  For
+    # a variant path/to/Language.lproj/MainMenu.nib, put a variant group named
+    # MainMenu.nib inside path/to, and give it a variant named Language.  In
+    # this example, grandparent would be set to path/to and parent_root would
+    # be set to Language.
+    variant_name = None
+    parent = posixpath.dirname(path)
+    grandparent = posixpath.dirname(parent)
+    parent_basename = posixpath.basename(parent)
+    (parent_root, parent_ext) = posixpath.splitext(parent_basename)
+    if parent_ext == '.lproj':
+      variant_name = parent_root
+    if grandparent == '':
+      grandparent = None
+
+    # Putting a directory inside a variant group is not currently supported.
+    assert not is_dir or variant_name is None
+
+    path_split = path.split(posixpath.sep)
+    if len(path_split) == 1 or \
+       ((is_dir or variant_name != None) and len(path_split) == 2) or \
+       not hierarchical:
+      # The PBXFileReference or PBXVariantGroup will be added to or gotten from
+      # this PBXGroup, no recursion necessary.
+      if variant_name is None:
+        # Add or get a PBXFileReference.
+        file_ref = self.GetChildByPath(path)
+        if file_ref != None:
+          assert file_ref.__class__ == PBXFileReference
+        else:
+          file_ref = PBXFileReference({'path': path})
+          self.AppendChild(file_ref)
+      else:
+        # Add or get a PBXVariantGroup.  The variant group name is the same
+        # as the basename (MainMenu.nib in the example above).  grandparent
+        # specifies the path to the variant group itself, and path_split[-2:]
+        # is the path of the specific variant relative to its group.
+        variant_group_name = posixpath.basename(path)
+        variant_group_ref = self.AddOrGetVariantGroupByNameAndPath(
+            variant_group_name, grandparent)
+        variant_path = posixpath.sep.join(path_split[-2:])
+        variant_ref = variant_group_ref.GetChildByPath(variant_path)
+        if variant_ref != None:
+          assert variant_ref.__class__ == PBXFileReference
+        else:
+          variant_ref = PBXFileReference({'name': variant_name,
+                                          'path': variant_path})
+          variant_group_ref.AppendChild(variant_ref)
+        # The caller is interested in the variant group, not the specific
+        # variant file.
+        file_ref = variant_group_ref
+      return file_ref
+    else:
+      # Hierarchical recursion.  Add or get a PBXGroup corresponding to the
+      # outermost path component, and then recurse into it, chopping off that
+      # path component.
+      next_dir = path_split[0]
+      group_ref = self.GetChildByPath(next_dir)
+      if group_ref != None:
+        assert group_ref.__class__ == PBXGroup
+      else:
+        group_ref = PBXGroup({'path': next_dir})
+        self.AppendChild(group_ref)
+      return group_ref.AddOrGetFileByPath(posixpath.sep.join(path_split[1:]),
+                                          hierarchical)
+
+  def AddOrGetVariantGroupByNameAndPath(self, name, path):
+    """Returns an existing or new PBXVariantGroup for name and path.
+
+    If a PBXVariantGroup identified by the name and path arguments is already
+    present as a child of this object, it is returned.  Otherwise, a new
+    PBXVariantGroup with the correct properties is created, added as a child,
+    and returned.
+
+    This method will generally be called by AddOrGetFileByPath, which knows
+    when to create a variant group based on the structure of the pathnames
+    passed to it.
+    """
+
+    key = (name, path)
+    if key in self._variant_children_by_name_and_path:
+      variant_group_ref = self._variant_children_by_name_and_path[key]
+      assert variant_group_ref.__class__ == PBXVariantGroup
+      return variant_group_ref
+
+    variant_group_properties = {'name': name}
+    if path != None:
+      variant_group_properties['path'] = path
+    variant_group_ref = PBXVariantGroup(variant_group_properties)
+    self.AppendChild(variant_group_ref)
+
+    return variant_group_ref
+
+  def TakeOverOnlyChild(self, recurse=False):
+    """If this PBXGroup has only one child and it's also a PBXGroup, take
+    it over by making all of its children this object's children.
+
+    This function will continue to take over only children when those children
+    are groups.  If there are three PBXGroups representing a, b, and c, with
+    c inside b and b inside a, and a and b have no other children, this will
+    result in a taking over both b and c, forming a PBXGroup for a/b/c.
+
+    If recurse is True, this function will recurse into children and ask them
+    to collapse themselves by taking over only children as well.  Assuming
+    an example hierarchy with files at a/b/c/d1, a/b/c/d2, and a/b/c/d3/e/f
+    (d1, d2, and f are files, the rest are groups), recursion will result in
+    a group for a/b/c containing a group for d3/e.
+    """
+
+    # At this stage, check that child class types are PBXGroup exactly,
+    # instead of using isinstance.  The only subclass of PBXGroup,
+    # PBXVariantGroup, should not participate in reparenting in the same way:
+    # reparenting by merging different object types would be wrong.
+    while len(self._properties['children']) == 1 and \
+          self._properties['children'][0].__class__ == PBXGroup:
+      # Loop to take over the innermost only-child group possible.
+
+      child = self._properties['children'][0]
+
+      # Assume the child's properties, including its children.  Save a copy
+      # of this object's old properties, because they'll still be needed.
+      # This object retains its existing id and parent attributes.
+      old_properties = self._properties
+      self._properties = child._properties
+      self._children_by_path = child._children_by_path
+
+      if not 'sourceTree' in self._properties or \
+         self._properties['sourceTree'] == '<group>':
+        # The child was relative to its parent.  Fix up the path.  Note that
+        # children with a sourceTree other than "<group>" are not relative to
+        # their parents, so no path fix-up is needed in that case.
+        if 'path' in old_properties:
+          if 'path' in self._properties:
+            # Both the original parent and child have paths set.
+            self._properties['path'] = posixpath.join(old_properties['path'],
+                                                      self._properties['path'])
+          else:
+            # Only the original parent has a path, use it.
+            self._properties['path'] = old_properties['path']
+        if 'sourceTree' in old_properties:
+          # The original parent had a sourceTree set, use it.
+          self._properties['sourceTree'] = old_properties['sourceTree']
+
+      # If the original parent had a name set, keep using it.  If the original
+      # parent didn't have a name but the child did, let the child's name
+      # live on.  If the name attribute seems unnecessary now, get rid of it.
+      if 'name' in old_properties and old_properties['name'] != None and \
+         old_properties['name'] != self.Name():
+        self._properties['name'] = old_properties['name']
+      if 'name' in self._properties and 'path' in self._properties and \
+         self._properties['name'] == self._properties['path']:
+        del self._properties['name']
+
+      # Notify all children of their new parent.
+      for child in self._properties['children']:
+        child.parent = self
+
+    # If asked to recurse, recurse.
+    if recurse:
+      for child in self._properties['children']:
+        if child.__class__ == PBXGroup:
+          child.TakeOverOnlyChild(recurse)
+
+  def SortGroup(self):
+    self._properties['children'] = \
+        sorted(self._properties['children'], cmp=lambda x,y: x.Compare(y))
+
+    # Recurse.
+    for child in self._properties['children']:
+      if isinstance(child, PBXGroup):
+        child.SortGroup()
+
+
+class XCFileLikeElement(XCHierarchicalElement):
+  # Abstract base for objects that can be used as the fileRef property of
+  # PBXBuildFile.
+
+  def PathHashables(self):
+    # A PBXBuildFile that refers to this object will call this method to
+    # obtain additional hashables specific to this XCFileLikeElement.  Don't
+    # just use this object's hashables, they're not specific and unique enough
+    # on their own (without access to the parent hashables.)  Instead, provide
+    # hashables that identify this object by path by getting its hashables as
+    # well as the hashables of ancestor XCHierarchicalElement objects.
+
+    hashables = []
+    xche = self
+    while xche != None and isinstance(xche, XCHierarchicalElement):
+      xche_hashables = xche.Hashables()
+      for index in xrange(0, len(xche_hashables)):
+        hashables.insert(index, xche_hashables[index])
+      xche = xche.parent
+    return hashables
+
+
+class XCContainerPortal(XCObject):
+  # Abstract base for objects that can be used as the containerPortal property
+  # of PBXContainerItemProxy.
+  pass
+
+
+class XCRemoteObject(XCObject):
+  # Abstract base for objects that can be used as the remoteGlobalIDString
+  # property of PBXContainerItemProxy.
+  pass
+
+
+class PBXFileReference(XCFileLikeElement, XCContainerPortal, XCRemoteObject):
+  _schema = XCFileLikeElement._schema.copy()
+  _schema.update({
+    'explicitFileType':  [0, str, 0, 0],
+    'lastKnownFileType': [0, str, 0, 0],
+    'name':              [0, str, 0, 0],
+    'path':              [0, str, 0, 1],
+  })
+
+  # Weird output rules for PBXFileReference.
+  _should_print_single_line = True
+  # super
+  _encode_transforms = XCFileLikeElement._alternate_encode_transforms
+
+  def __init__(self, properties=None, id=None, parent=None):
+    # super
+    XCFileLikeElement.__init__(self, properties, id, parent)
+    if 'path' in self._properties and self._properties['path'].endswith('/'):
+      self._properties['path'] = self._properties['path'][:-1]
+      is_dir = True
+    else:
+      is_dir = False
+
+    if 'path' in self._properties and \
+        not 'lastKnownFileType' in self._properties and \
+        not 'explicitFileType' in self._properties:
+      # TODO(mark): This is the replacement for a replacement for a quick hack.
+      # It is no longer incredibly sucky, but this list needs to be extended.
+      extension_map = {
+        'a':           'archive.ar',
+        'app':         'wrapper.application',
+        'bdic':        'file',
+        'bundle':      'wrapper.cfbundle',
+        'c':           'sourcecode.c.c',
+        'cc':          'sourcecode.cpp.cpp',
+        'cpp':         'sourcecode.cpp.cpp',
+        'css':         'text.css',
+        'cxx':         'sourcecode.cpp.cpp',
+        'dylib':       'compiled.mach-o.dylib',
+        'framework':   'wrapper.framework',
+        'h':           'sourcecode.c.h',
+        'hxx':         'sourcecode.cpp.h',
+        'icns':        'image.icns',
+        'java':        'sourcecode.java',
+        'js':          'sourcecode.javascript',
+        'm':           'sourcecode.c.objc',
+        'mm':          'sourcecode.cpp.objcpp',
+        'nib':         'wrapper.nib',
+        'o':           'compiled.mach-o.objfile',
+        'pdf':         'image.pdf',
+        'pl':          'text.script.perl',
+        'plist':       'text.plist.xml',
+        'pm':          'text.script.perl',
+        'png':         'image.png',
+        'py':          'text.script.python',
+        'r':           'sourcecode.rez',
+        'rez':         'sourcecode.rez',
+        's':           'sourcecode.asm',
+        'storyboard':  'file.storyboard',
+        'strings':     'text.plist.strings',
+        'ttf':         'file',
+        'xcconfig':    'text.xcconfig',
+        'xcdatamodel': 'wrapper.xcdatamodel',
+        'xib':         'file.xib',
+        'y':           'sourcecode.yacc',
+      }
+
+      if is_dir:
+        file_type = 'folder'
+      else:
+        basename = posixpath.basename(self._properties['path'])
+        (root, ext) = posixpath.splitext(basename)
+        # Check the map using a lowercase extension.
+        # TODO(mark): Maybe it should try with the original case first and fall
+        # back to lowercase, in case there are any instances where case
+        # matters.  There currently aren't.
+        if ext != '':
+          ext = ext[1:].lower()
+
+        # TODO(mark): "text" is the default value, but "file" is appropriate
+        # for unrecognized files not containing text.  Xcode seems to choose
+        # based on content.
+        file_type = extension_map.get(ext, 'text')
+
+      self._properties['lastKnownFileType'] = file_type
+
+
+class PBXVariantGroup(PBXGroup, XCFileLikeElement):
+  """PBXVariantGroup is used by Xcode to represent localizations."""
+  # No additions to the schema relative to PBXGroup.
+  pass
+
+
+# PBXReferenceProxy is also an XCFileLikeElement subclass.  It is defined below
+# because it uses PBXContainerItemProxy, defined below.
+
+
+class XCBuildConfiguration(XCObject):
+  _schema = XCObject._schema.copy()
+  _schema.update({
+    'baseConfigurationReference': [0, PBXFileReference, 0, 0],
+    'buildSettings':              [0, dict, 0, 1, {}],
+    'name':                       [0, str,  0, 1],
+  })
+
+  def HasBuildSetting(self, key):
+    return key in self._properties['buildSettings']
+
+  def GetBuildSetting(self, key):
+    return self._properties['buildSettings'][key]
+
+  def SetBuildSetting(self, key, value):
+    # TODO(mark): If a list, copy?
+    self._properties['buildSettings'][key] = value
+
+  def AppendBuildSetting(self, key, value):
+    if not key in self._properties['buildSettings']:
+      self._properties['buildSettings'][key] = []
+    self._properties['buildSettings'][key].append(value)
+
+  def DelBuildSetting(self, key):
+    if key in self._properties['buildSettings']:
+      del self._properties['buildSettings'][key]
+
+  def SetBaseConfiguration(self, value):
+    self._properties['baseConfigurationReference'] = value
+
+class XCConfigurationList(XCObject):
+  # _configs is the default list of configurations.
+  _configs = [ XCBuildConfiguration({'name': 'Debug'}),
+               XCBuildConfiguration({'name': 'Release'}) ]
+
+  _schema = XCObject._schema.copy()
+  _schema.update({
+    'buildConfigurations':           [1, XCBuildConfiguration, 1, 1, _configs],
+    'defaultConfigurationIsVisible': [0, int,                  0, 1, 1],
+    'defaultConfigurationName':      [0, str,                  0, 1, 'Release'],
+  })
+
+  def Name(self):
+    return 'Build configuration list for ' + \
+           self.parent.__class__.__name__ + ' "' + self.parent.Name() + '"'
+
+  def ConfigurationNamed(self, name):
+    """Convenience accessor to obtain an XCBuildConfiguration by name."""
+    for configuration in self._properties['buildConfigurations']:
+      if configuration._properties['name'] == name:
+        return configuration
+
+    raise KeyError, name
+
+  def DefaultConfiguration(self):
+    """Convenience accessor to obtain the default XCBuildConfiguration."""
+    return self.ConfigurationNamed(self._properties['defaultConfigurationName'])
+
+  def HasBuildSetting(self, key):
+    """Determines the state of a build setting in all XCBuildConfiguration
+    child objects.
+
+    If all child objects have key in their build settings, and the value is the
+    same in all child objects, returns 1.
+
+    If no child objects have the key in their build settings, returns 0.
+
+    If some, but not all, child objects have the key in their build settings,
+    or if any children have different values for the key, returns -1.
+    """
+
+    has = None
+    value = None
+    for configuration in self._properties['buildConfigurations']:
+      configuration_has = configuration.HasBuildSetting(key)
+      if has is None:
+        has = configuration_has
+      elif has != configuration_has:
+        return -1
+
+      if configuration_has:
+        configuration_value = configuration.GetBuildSetting(key)
+        if value is None:
+          value = configuration_value
+        elif value != configuration_value:
+          return -1
+
+    if not has:
+      return 0
+
+    return 1
+
+  def GetBuildSetting(self, key):
+    """Gets the build setting for key.
+
+    All child XCConfiguration objects must have the same value set for the
+    setting, or a ValueError will be raised.
+    """
+
+    # TODO(mark): This is wrong for build settings that are lists.  The list
+    # contents should be compared (and a list copy returned?)
+
+    value = None
+    for configuration in self._properties['buildConfigurations']:
+      configuration_value = configuration.GetBuildSetting(key)
+      if value is None:
+        value = configuration_value
+      else:
+        if value != configuration_value:
+          raise ValueError, 'Variant values for ' + key
+
+    return value
+
+  def SetBuildSetting(self, key, value):
+    """Sets the build setting for key to value in all child
+    XCBuildConfiguration objects.
+    """
+
+    for configuration in self._properties['buildConfigurations']:
+      configuration.SetBuildSetting(key, value)
+
+  def AppendBuildSetting(self, key, value):
+    """Appends value to the build setting for key, which is treated as a list,
+    in all child XCBuildConfiguration objects.
+    """
+
+    for configuration in self._properties['buildConfigurations']:
+      configuration.AppendBuildSetting(key, value)
+
+  def DelBuildSetting(self, key):
+    """Deletes the build setting key from all child XCBuildConfiguration
+    objects.
+    """
+
+    for configuration in self._properties['buildConfigurations']:
+      configuration.DelBuildSetting(key)
+
+  def SetBaseConfiguration(self, value):
+    """Sets the build configuration in all child XCBuildConfiguration objects.
+    """
+
+    for configuration in self._properties['buildConfigurations']:
+      configuration.SetBaseConfiguration(value)
+
+
+class PBXBuildFile(XCObject):
+  _schema = XCObject._schema.copy()
+  _schema.update({
+    'fileRef':  [0, XCFileLikeElement, 0, 1],
+    'settings': [0, str,               0, 0],  # hack, it's a dict
+  })
+
+  # Weird output rules for PBXBuildFile.
+  _should_print_single_line = True
+  _encode_transforms = XCObject._alternate_encode_transforms
+
+  def Name(self):
+    # Example: "main.cc in Sources"
+    return self._properties['fileRef'].Name() + ' in ' + self.parent.Name()
+
+  def Hashables(self):
+    # super
+    hashables = XCObject.Hashables(self)
+
+    # It is not sufficient to just rely on Name() to get the
+    # XCFileLikeElement's name, because that is not a complete pathname.
+    # PathHashables returns hashables unique enough that no two
+    # PBXBuildFiles should wind up with the same set of hashables, unless
+    # someone adds the same file multiple times to the same target.  That
+    # would be considered invalid anyway.
+    hashables.extend(self._properties['fileRef'].PathHashables())
+
+    return hashables
+
+
+class XCBuildPhase(XCObject):
+  """Abstract base for build phase classes.  Not represented in a project
+  file.
+
+  Attributes:
+    _files_by_path: A dict mapping each path of a child in the files list by
+      path (keys) to the corresponding PBXBuildFile children (values).
+    _files_by_xcfilelikeelement: A dict mapping each XCFileLikeElement (keys)
+      to the corresponding PBXBuildFile children (values).
+  """
+
+  # TODO(mark): Some build phase types, like PBXShellScriptBuildPhase, don't
+  # actually have a "files" list.  XCBuildPhase should not have "files" but
+  # another abstract subclass of it should provide this, and concrete build
+  # phase types that do have "files" lists should be derived from that new
+  # abstract subclass.  XCBuildPhase should only provide buildActionMask and
+  # runOnlyForDeploymentPostprocessing, and not files or the various
+  # file-related methods and attributes.
+
+  _schema = XCObject._schema.copy()
+  _schema.update({
+    'buildActionMask':                    [0, int,          0, 1, 0x7fffffff],
+    'files':                              [1, PBXBuildFile, 1, 1, []],
+    'runOnlyForDeploymentPostprocessing': [0, int,          0, 1, 0],
+  })
+
+  def __init__(self, properties=None, id=None, parent=None):
+    # super
+    XCObject.__init__(self, properties, id, parent)
+
+    self._files_by_path = {}
+    self._files_by_xcfilelikeelement = {}
+    for pbxbuildfile in self._properties.get('files', []):
+      self._AddBuildFileToDicts(pbxbuildfile)
+
+  def FileGroup(self, path):
+    # Subclasses must override this by returning a two-element tuple.  The
+    # first item in the tuple should be the PBXGroup to which "path" should be
+    # added, either as a child or deeper descendant.  The second item should
+    # be a boolean indicating whether files should be added into hierarchical
+    # groups or one single flat group.
+    raise NotImplementedError, \
+          self.__class__.__name__ + ' must implement FileGroup'
+
+  def _AddPathToDict(self, pbxbuildfile, path):
+    """Adds path to the dict tracking paths belonging to this build phase.
+
+    If the path is already a member of this build phase, raises an exception.
+    """
+
+    if path in self._files_by_path:
+      raise ValueError, 'Found multiple build files with path ' + path
+    self._files_by_path[path] = pbxbuildfile
+
+  def _AddBuildFileToDicts(self, pbxbuildfile, path=None):
+    """Maintains the _files_by_path and _files_by_xcfilelikeelement dicts.
+
+    If path is specified, then it is the path that is being added to the
+    phase, and pbxbuildfile must contain either a PBXFileReference directly
+    referencing that path, or it must contain a PBXVariantGroup that itself
+    contains a PBXFileReference referencing the path.
+
+    If path is not specified, either the PBXFileReference's path or the paths
+    of all children of the PBXVariantGroup are taken as being added to the
+    phase.
+
+    If the path is already present in the phase, raises an exception.
+
+    If the PBXFileReference or PBXVariantGroup referenced by pbxbuildfile
+    are already present in the phase, referenced by a different PBXBuildFile
+    object, raises an exception.  This does not raise an exception when
+    a PBXFileReference or PBXVariantGroup reappear and are referenced by the
+    same PBXBuildFile that has already introduced them, because in the case
+    of PBXVariantGroup objects, they may correspond to multiple paths that are
+    not all added simultaneously.  When this situation occurs, the path needs
+    to be added to _files_by_path, but nothing needs to change in
+    _files_by_xcfilelikeelement, and the caller should have avoided adding
+    the PBXBuildFile if it is already present in the list of children.
+    """
+
+    xcfilelikeelement = pbxbuildfile._properties['fileRef']
+
+    paths = []
+    if path != None:
+      # It's best when the caller provides the path.
+      if isinstance(xcfilelikeelement, PBXVariantGroup):
+        paths.append(path)
+    else:
+      # If the caller didn't provide a path, there can be either multiple
+      # paths (PBXVariantGroup) or one.
+      if isinstance(xcfilelikeelement, PBXVariantGroup):
+        for variant in xcfilelikeelement._properties['children']:
+          paths.append(variant.FullPath())
+      else:
+        paths.append(xcfilelikeelement.FullPath())
+
+    # Add the paths first, because if something's going to raise, the
+    # messages provided by _AddPathToDict are more useful owing to its
+    # having access to a real pathname and not just an object's Name().
+    for a_path in paths:
+      self._AddPathToDict(pbxbuildfile, a_path)
+
+    # If another PBXBuildFile references this XCFileLikeElement, there's a
+    # problem.
+    if xcfilelikeelement in self._files_by_xcfilelikeelement and \
+       self._files_by_xcfilelikeelement[xcfilelikeelement] != pbxbuildfile:
+      raise ValueError, 'Found multiple build files for ' + \
+                        xcfilelikeelement.Name()
+    self._files_by_xcfilelikeelement[xcfilelikeelement] = pbxbuildfile
+
+  def AppendBuildFile(self, pbxbuildfile, path=None):
+    # Callers should use this instead of calling
+    # AppendProperty('files', pbxbuildfile) directly because this function
+    # maintains the object's dicts.  Better yet, callers can just call AddFile
+    # with a pathname and not worry about building their own PBXBuildFile
+    # objects.
+    self.AppendProperty('files', pbxbuildfile)
+    self._AddBuildFileToDicts(pbxbuildfile, path)
+
+  def AddFile(self, path, settings=None):
+    (file_group, hierarchical) = self.FileGroup(path)
+    file_ref = file_group.AddOrGetFileByPath(path, hierarchical)
+
+    if file_ref in self._files_by_xcfilelikeelement and \
+       isinstance(file_ref, PBXVariantGroup):
+      # There's already a PBXBuildFile in this phase corresponding to the
+      # PBXVariantGroup.  path just provides a new variant that belongs to
+      # the group.  Add the path to the dict.
+      pbxbuildfile = self._files_by_xcfilelikeelement[file_ref]
+      self._AddBuildFileToDicts(pbxbuildfile, path)
+    else:
+      # Add a new PBXBuildFile to get file_ref into the phase.
+      if settings is None:
+        pbxbuildfile = PBXBuildFile({'fileRef': file_ref})
+      else:
+        pbxbuildfile = PBXBuildFile({'fileRef': file_ref, 'settings': settings})
+      self.AppendBuildFile(pbxbuildfile, path)
+
+
+class PBXHeadersBuildPhase(XCBuildPhase):
+  # No additions to the schema relative to XCBuildPhase.
+
+  def Name(self):
+    return 'Headers'
+
+  def FileGroup(self, path):
+    return self.PBXProjectAncestor().RootGroupForPath(path)
+
+
+class PBXResourcesBuildPhase(XCBuildPhase):
+  # No additions to the schema relative to XCBuildPhase.
+
+  def Name(self):
+    return 'Resources'
+
+  def FileGroup(self, path):
+    return self.PBXProjectAncestor().RootGroupForPath(path)
+
+
+class PBXSourcesBuildPhase(XCBuildPhase):
+  # No additions to the schema relative to XCBuildPhase.
+
+  def Name(self):
+    return 'Sources'
+
+  def FileGroup(self, path):
+    return self.PBXProjectAncestor().RootGroupForPath(path)
+
+
+class PBXFrameworksBuildPhase(XCBuildPhase):
+  # No additions to the schema relative to XCBuildPhase.
+
+  def Name(self):
+    return 'Frameworks'
+
+  def FileGroup(self, path):
+    (root, ext) = posixpath.splitext(path)
+    if ext != '':
+      ext = ext[1:].lower()
+    if ext == 'o':
+      # .o files are added to Xcode Frameworks phases, but conceptually aren't
+      # frameworks, they're more like sources or intermediates. Redirect them
+      # to show up in one of those other groups.
+      return self.PBXProjectAncestor().RootGroupForPath(path)
+    else:
+      return (self.PBXProjectAncestor().FrameworksGroup(), False)
+
+
+class PBXShellScriptBuildPhase(XCBuildPhase):
+  _schema = XCBuildPhase._schema.copy()
+  _schema.update({
+    'inputPaths':       [1, str, 0, 1, []],
+    'name':             [0, str, 0, 0],
+    'outputPaths':      [1, str, 0, 1, []],
+    'shellPath':        [0, str, 0, 1, '/bin/sh'],
+    'shellScript':      [0, str, 0, 1],
+    'showEnvVarsInLog': [0, int, 0, 0],
+  })
+
+  def Name(self):
+    if 'name' in self._properties:
+      return self._properties['name']
+
+    return 'ShellScript'
+
+
+class PBXCopyFilesBuildPhase(XCBuildPhase):
+  _schema = XCBuildPhase._schema.copy()
+  _schema.update({
+    'dstPath':          [0, str, 0, 1],
+    'dstSubfolderSpec': [0, int, 0, 1],
+    'name':             [0, str, 0, 0],
+  })
+
+  # path_tree_re matches "$(DIR)/path" or just "$(DIR)".  Match group 1 is
+  # "DIR", match group 3 is "path" or None.
+  path_tree_re = re.compile('^\\$\\((.*)\\)(/(.*)|)$')
+
+  # path_tree_to_subfolder maps names of Xcode variables to the associated
+  # dstSubfolderSpec property value used in a PBXCopyFilesBuildPhase object.
+  path_tree_to_subfolder = {
+    'BUILT_PRODUCTS_DIR': 16,  # Products Directory
+    # Other types that can be chosen via the Xcode UI.
+    # TODO(mark): Map Xcode variable names to these.
+    # : 1,  # Wrapper
+    # : 6,  # Executables: 6
+    # : 7,  # Resources
+    # : 15,  # Java Resources
+    # : 10,  # Frameworks
+    # : 11,  # Shared Frameworks
+    # : 12,  # Shared Support
+    # : 13,  # PlugIns
+  }
+
+  def Name(self):
+    if 'name' in self._properties:
+      return self._properties['name']
+
+    return 'CopyFiles'
+
+  def FileGroup(self, path):
+    return self.PBXProjectAncestor().RootGroupForPath(path)
+
+  def SetDestination(self, path):
+    """Set the dstSubfolderSpec and dstPath properties from path.
+
+    path may be specified in the same notation used for XCHierarchicalElements,
+    specifically, "$(DIR)/path".
+    """
+
+    path_tree_match = self.path_tree_re.search(path)
+    if path_tree_match:
+      # Everything else needs to be relative to an Xcode variable.
+      path_tree = path_tree_match.group(1)
+      relative_path = path_tree_match.group(3)
+
+      if path_tree in self.path_tree_to_subfolder:
+        subfolder = self.path_tree_to_subfolder[path_tree]
+        if relative_path is None:
+          relative_path = ''
+      else:
+        # The path starts with an unrecognized Xcode variable
+        # name like $(SRCROOT).  Xcode will still handle this
+        # as an "absolute path" that starts with the variable.
+        subfolder = 0
+        relative_path = path
+    elif path.startswith('/'):
+      # Special case.  Absolute paths are in dstSubfolderSpec 0.
+      subfolder = 0
+      relative_path = path[1:]
+    else:
+      raise ValueError, 'Can\'t use path %s in a %s' % \
+                        (path, self.__class__.__name__)
+
+    self._properties['dstPath'] = relative_path
+    self._properties['dstSubfolderSpec'] = subfolder
+
+
+class PBXBuildRule(XCObject):
+  _schema = XCObject._schema.copy()
+  _schema.update({
+    'compilerSpec': [0, str, 0, 1],
+    'filePatterns': [0, str, 0, 0],
+    'fileType':     [0, str, 0, 1],
+    'isEditable':   [0, int, 0, 1, 1],
+    'outputFiles':  [1, str, 0, 1, []],
+    'script':       [0, str, 0, 0],
+  })
+
+  def Name(self):
+    # Not very inspired, but it's what Xcode uses.
+    return self.__class__.__name__
+
+  def Hashables(self):
+    # super
+    hashables = XCObject.Hashables(self)
+
+    # Use the hashables of the weak objects that this object refers to.
+    hashables.append(self._properties['fileType'])
+    if 'filePatterns' in self._properties:
+      hashables.append(self._properties['filePatterns'])
+    return hashables
+
+
+class PBXContainerItemProxy(XCObject):
+  # When referencing an item in this project file, containerPortal is the
+  # PBXProject root object of this project file.  When referencing an item in
+  # another project file, containerPortal is a PBXFileReference identifying
+  # the other project file.
+  #
+  # When serving as a proxy to an XCTarget (in this project file or another),
+  # proxyType is 1.  When serving as a proxy to a PBXFileReference (in another
+  # project file), proxyType is 2.  Type 2 is used for references to the
+  # producs of the other project file's targets.
+  #
+  # Xcode is weird about remoteGlobalIDString.  Usually, it's printed without
+  # a comment, indicating that it's tracked internally simply as a string, but
+  # sometimes it's printed with a comment (usually when the object is initially
+  # created), indicating that it's tracked as a project file object at least
+  # sometimes.  This module always tracks it as an object, but contains a hack
+  # to prevent it from printing the comment in the project file output.  See
+  # _XCKVPrint.
+  _schema = XCObject._schema.copy()
+  _schema.update({
+    'containerPortal':      [0, XCContainerPortal, 0, 1],
+    'proxyType':            [0, int,               0, 1],
+    'remoteGlobalIDString': [0, XCRemoteObject,    0, 1],
+    'remoteInfo':           [0, str,               0, 1],
+  })
+
+  def __repr__(self):
+    props = self._properties
+    name = '%s.gyp:%s' % (props['containerPortal'].Name(), props['remoteInfo'])
+    return '<%s %r at 0x%x>' % (self.__class__.__name__, name, id(self))
+
+  def Name(self):
+    # Admittedly not the best name, but it's what Xcode uses.
+    return self.__class__.__name__
+
+  def Hashables(self):
+    # super
+    hashables = XCObject.Hashables(self)
+
+    # Use the hashables of the weak objects that this object refers to.
+    hashables.extend(self._properties['containerPortal'].Hashables())
+    hashables.extend(self._properties['remoteGlobalIDString'].Hashables())
+    return hashables
+
+
+class PBXTargetDependency(XCObject):
+  # The "target" property accepts an XCTarget object, and obviously not
+  # NoneType.  But XCTarget is defined below, so it can't be put into the
+  # schema yet.  The definition of PBXTargetDependency can't be moved below
+  # XCTarget because XCTarget's own schema references PBXTargetDependency.
+  # Python doesn't deal well with this circular relationship, and doesn't have
+  # a real way to do forward declarations.  To work around, the type of
+  # the "target" property is reset below, after XCTarget is defined.
+  #
+  # At least one of "name" and "target" is required.
+  _schema = XCObject._schema.copy()
+  _schema.update({
+    'name':        [0, str,                   0, 0],
+    'target':      [0, None.__class__,        0, 0],
+    'targetProxy': [0, PBXContainerItemProxy, 1, 1],
+  })
+
+  def __repr__(self):
+    name = self._properties.get('name') or self._properties['target'].Name()
+    return '<%s %r at 0x%x>' % (self.__class__.__name__, name, id(self))
+
+  def Name(self):
+    # Admittedly not the best name, but it's what Xcode uses.
+    return self.__class__.__name__
+
+  def Hashables(self):
+    # super
+    hashables = XCObject.Hashables(self)
+
+    # Use the hashables of the weak objects that this object refers to.
+    hashables.extend(self._properties['targetProxy'].Hashables())
+    return hashables
+
+
+class PBXReferenceProxy(XCFileLikeElement):
+  _schema = XCFileLikeElement._schema.copy()
+  _schema.update({
+    'fileType':  [0, str,                   0, 1],
+    'path':      [0, str,                   0, 1],
+    'remoteRef': [0, PBXContainerItemProxy, 1, 1],
+  })
+
+
+class XCTarget(XCRemoteObject):
+  # An XCTarget is really just an XCObject, the XCRemoteObject thing is just
+  # to allow PBXProject to be used in the remoteGlobalIDString property of
+  # PBXContainerItemProxy.
+  #
+  # Setting a "name" property at instantiation may also affect "productName",
+  # which may in turn affect the "PRODUCT_NAME" build setting in children of
+  # "buildConfigurationList".  See __init__ below.
+  _schema = XCRemoteObject._schema.copy()
+  _schema.update({
+    'buildConfigurationList': [0, XCConfigurationList, 1, 1,
+                               XCConfigurationList()],
+    'buildPhases':            [1, XCBuildPhase,        1, 1, []],
+    'dependencies':           [1, PBXTargetDependency, 1, 1, []],
+    'name':                   [0, str,                 0, 1],
+    'productName':            [0, str,                 0, 1],
+  })
+
+  def __init__(self, properties=None, id=None, parent=None,
+               force_outdir=None, force_prefix=None, force_extension=None):
+    # super
+    XCRemoteObject.__init__(self, properties, id, parent)
+
+    # Set up additional defaults not expressed in the schema.  If a "name"
+    # property was supplied, set "productName" if it is not present.  Also set
+    # the "PRODUCT_NAME" build setting in each configuration, but only if
+    # the setting is not present in any build configuration.
+    if 'name' in self._properties:
+      if not 'productName' in self._properties:
+        self.SetProperty('productName', self._properties['name'])
+
+    if 'productName' in self._properties:
+      if 'buildConfigurationList' in self._properties:
+        configs = self._properties['buildConfigurationList']
+        if configs.HasBuildSetting('PRODUCT_NAME') == 0:
+          configs.SetBuildSetting('PRODUCT_NAME',
+                                  self._properties['productName'])
+
+  def AddDependency(self, other):
+    pbxproject = self.PBXProjectAncestor()
+    other_pbxproject = other.PBXProjectAncestor()
+    if pbxproject == other_pbxproject:
+      # Add a dependency to another target in the same project file.
+      container = PBXContainerItemProxy({'containerPortal':      pbxproject,
+                                         'proxyType':            1,
+                                         'remoteGlobalIDString': other,
+                                         'remoteInfo':           other.Name()})
+      dependency = PBXTargetDependency({'target':      other,
+                                        'targetProxy': container})
+      self.AppendProperty('dependencies', dependency)
+    else:
+      # Add a dependency to a target in a different project file.
+      other_project_ref = \
+          pbxproject.AddOrGetProjectReference(other_pbxproject)[1]
+      container = PBXContainerItemProxy({
+            'containerPortal':      other_project_ref,
+            'proxyType':            1,
+            'remoteGlobalIDString': other,
+            'remoteInfo':           other.Name(),
+          })
+      dependency = PBXTargetDependency({'name':        other.Name(),
+                                        'targetProxy': container})
+      self.AppendProperty('dependencies', dependency)
+
+  # Proxy all of these through to the build configuration list.
+
+  def ConfigurationNamed(self, name):
+    return self._properties['buildConfigurationList'].ConfigurationNamed(name)
+
+  def DefaultConfiguration(self):
+    return self._properties['buildConfigurationList'].DefaultConfiguration()
+
+  def HasBuildSetting(self, key):
+    return self._properties['buildConfigurationList'].HasBuildSetting(key)
+
+  def GetBuildSetting(self, key):
+    return self._properties['buildConfigurationList'].GetBuildSetting(key)
+
+  def SetBuildSetting(self, key, value):
+    return self._properties['buildConfigurationList'].SetBuildSetting(key, \
+                                                                      value)
+
+  def AppendBuildSetting(self, key, value):
+    return self._properties['buildConfigurationList'].AppendBuildSetting(key, \
+                                                                         value)
+
+  def DelBuildSetting(self, key):
+    return self._properties['buildConfigurationList'].DelBuildSetting(key)
+
+
+# Redefine the type of the "target" property.  See PBXTargetDependency._schema
+# above.
+PBXTargetDependency._schema['target'][1] = XCTarget
+
+
+class PBXNativeTarget(XCTarget):
+  # buildPhases is overridden in the schema to be able to set defaults.
+  #
+  # NOTE: Contrary to most objects, it is advisable to set parent when
+  # constructing PBXNativeTarget.  A parent of an XCTarget must be a PBXProject
+  # object.  A parent reference is required for a PBXNativeTarget during
+  # construction to be able to set up the target defaults for productReference,
+  # because a PBXBuildFile object must be created for the target and it must
+  # be added to the PBXProject's mainGroup hierarchy.
+  _schema = XCTarget._schema.copy()
+  _schema.update({
+    'buildPhases':      [1, XCBuildPhase,     1, 1,
+                         [PBXSourcesBuildPhase(), PBXFrameworksBuildPhase()]],
+    'buildRules':       [1, PBXBuildRule,     1, 1, []],
+    'productReference': [0, PBXFileReference, 0, 1],
+    'productType':      [0, str,              0, 1],
+  })
+
+  # Mapping from Xcode product-types to settings.  The settings are:
+  #  filetype : used for explicitFileType in the project file
+  #  prefix : the prefix for the file name
+  #  suffix : the suffix for the filen ame
+  _product_filetypes = {
+    'com.apple.product-type.application':     ['wrapper.application',
+                                               '', '.app'],
+    'com.apple.product-type.bundle':          ['wrapper.cfbundle',
+                                               '', '.bundle'],
+    'com.apple.product-type.framework':       ['wrapper.framework',
+                                               '', '.framework'],
+    'com.apple.product-type.library.dynamic': ['compiled.mach-o.dylib',
+                                               'lib', '.dylib'],
+    'com.apple.product-type.library.static':  ['archive.ar',
+                                               'lib', '.a'],
+    'com.apple.product-type.tool':            ['compiled.mach-o.executable',
+                                               '', ''],
+    'com.googlecode.gyp.xcode.bundle':        ['compiled.mach-o.dylib',
+                                               '', '.so'],
+  }
+
+  def __init__(self, properties=None, id=None, parent=None,
+               force_outdir=None, force_prefix=None, force_extension=None):
+    # super
+    XCTarget.__init__(self, properties, id, parent)
+
+    if 'productName' in self._properties and \
+       'productType' in self._properties and \
+       not 'productReference' in self._properties and \
+       self._properties['productType'] in self._product_filetypes:
+      products_group = None
+      pbxproject = self.PBXProjectAncestor()
+      if pbxproject != None:
+        products_group = pbxproject.ProductsGroup()
+
+      if products_group != None:
+        (filetype, prefix, suffix) = \
+            self._product_filetypes[self._properties['productType']]
+        # Xcode does not have a distinct type for loadable modules that are
+        # pure BSD targets (not in a bundle wrapper). GYP allows such modules
+        # to be specified by setting a target type to loadable_module without
+        # having mac_bundle set. These are mapped to the pseudo-product type
+        # com.googlecode.gyp.xcode.bundle.
+        #
+        # By picking up this special type and converting it to a dynamic
+        # library (com.apple.product-type.library.dynamic) with fix-ups,
+        # single-file loadable modules can be produced.
+        #
+        # MACH_O_TYPE is changed to mh_bundle to produce the proper file type
+        # (as opposed to mh_dylib). In order for linking to succeed,
+        # DYLIB_CURRENT_VERSION and DYLIB_COMPATIBILITY_VERSION must be
+        # cleared. They are meaningless for type mh_bundle.
+        #
+        # Finally, the .so extension is forcibly applied over the default
+        # (.dylib), unless another forced extension is already selected.
+        # .dylib is plainly wrong, and .bundle is used by loadable_modules in
+        # bundle wrappers (com.apple.product-type.bundle). .so seems an odd
+        # choice because it's used as the extension on many other systems that
+        # don't distinguish between linkable shared libraries and non-linkable
+        # loadable modules, but there's precedent: Python loadable modules on
+        # Mac OS X use an .so extension.
+        if self._properties['productType'] == 'com.googlecode.gyp.xcode.bundle':
+          self._properties['productType'] = \
+              'com.apple.product-type.library.dynamic'
+          self.SetBuildSetting('MACH_O_TYPE', 'mh_bundle')
+          self.SetBuildSetting('DYLIB_CURRENT_VERSION', '')
+          self.SetBuildSetting('DYLIB_COMPATIBILITY_VERSION', '')
+          if force_extension is None:
+            force_extension = suffix[1:]
+
+        if force_extension is not None:
+          # If it's a wrapper (bundle), set WRAPPER_EXTENSION.
+          if filetype.startswith('wrapper.'):
+            self.SetBuildSetting('WRAPPER_EXTENSION', force_extension)
+          else:
+            # Extension override.
+            suffix = '.' + force_extension
+            self.SetBuildSetting('EXECUTABLE_EXTENSION', force_extension)
+
+          if filetype.startswith('compiled.mach-o.executable'):
+            product_name = self._properties['productName']
+            product_name += suffix
+            suffix = ''
+            self.SetProperty('productName', product_name)
+            self.SetBuildSetting('PRODUCT_NAME', product_name)
+
+        # Xcode handles most prefixes based on the target type, however there
+        # are exceptions.  If a "BSD Dynamic Library" target is added in the
+        # Xcode UI, Xcode sets EXECUTABLE_PREFIX.  This check duplicates that
+        # behavior.
+        if force_prefix is not None:
+          prefix = force_prefix
+        if filetype.startswith('wrapper.'):
+          self.SetBuildSetting('WRAPPER_PREFIX', prefix)
+        else:
+          self.SetBuildSetting('EXECUTABLE_PREFIX', prefix)
+
+        if force_outdir is not None:
+          self.SetBuildSetting('TARGET_BUILD_DIR', force_outdir)
+
+        # TODO(tvl): Remove the below hack.
+        #    http://code.google.com/p/gyp/issues/detail?id=122
+
+        # Some targets include the prefix in the target_name.  These targets
+        # really should just add a product_name setting that doesn't include
+        # the prefix.  For example:
+        #  target_name = 'libevent', product_name = 'event'
+        # This check cleans up for them.
+        product_name = self._properties['productName']
+        prefix_len = len(prefix)
+        if prefix_len and (product_name[:prefix_len] == prefix):
+          product_name = product_name[prefix_len:]
+          self.SetProperty('productName', product_name)
+          self.SetBuildSetting('PRODUCT_NAME', product_name)
+
+        ref_props = {
+          'explicitFileType': filetype,
+          'includeInIndex':   0,
+          'path':             prefix + product_name + suffix,
+          'sourceTree':       'BUILT_PRODUCTS_DIR',
+        }
+        file_ref = PBXFileReference(ref_props)
+        products_group.AppendChild(file_ref)
+        self.SetProperty('productReference', file_ref)
+
+  def GetBuildPhaseByType(self, type):
+    if not 'buildPhases' in self._properties:
+      return None
+
+    the_phase = None
+    for phase in self._properties['buildPhases']:
+      if isinstance(phase, type):
+        # Some phases may be present in multiples in a well-formed project file,
+        # but phases like PBXSourcesBuildPhase may only be present singly, and
+        # this function is intended as an aid to GetBuildPhaseByType.  Loop
+        # over the entire list of phases and assert if more than one of the
+        # desired type is found.
+        assert the_phase is None
+        the_phase = phase
+
+    return the_phase
+
+  def HeadersPhase(self):
+    headers_phase = self.GetBuildPhaseByType(PBXHeadersBuildPhase)
+    if headers_phase is None:
+      headers_phase = PBXHeadersBuildPhase()
+
+      # The headers phase should come before the resources, sources, and
+      # frameworks phases, if any.
+      insert_at = len(self._properties['buildPhases'])
+      for index in xrange(0, len(self._properties['buildPhases'])):
+        phase = self._properties['buildPhases'][index]
+        if isinstance(phase, PBXResourcesBuildPhase) or \
+           isinstance(phase, PBXSourcesBuildPhase) or \
+           isinstance(phase, PBXFrameworksBuildPhase):
+          insert_at = index
+          break
+
+      self._properties['buildPhases'].insert(insert_at, headers_phase)
+      headers_phase.parent = self
+
+    return headers_phase
+
+  def ResourcesPhase(self):
+    resources_phase = self.GetBuildPhaseByType(PBXResourcesBuildPhase)
+    if resources_phase is None:
+      resources_phase = PBXResourcesBuildPhase()
+
+      # The resources phase should come before the sources and frameworks
+      # phases, if any.
+      insert_at = len(self._properties['buildPhases'])
+      for index in xrange(0, len(self._properties['buildPhases'])):
+        phase = self._properties['buildPhases'][index]
+        if isinstance(phase, PBXSourcesBuildPhase) or \
+           isinstance(phase, PBXFrameworksBuildPhase):
+          insert_at = index
+          break
+
+      self._properties['buildPhases'].insert(insert_at, resources_phase)
+      resources_phase.parent = self
+
+    return resources_phase
+
+  def SourcesPhase(self):
+    sources_phase = self.GetBuildPhaseByType(PBXSourcesBuildPhase)
+    if sources_phase is None:
+      sources_phase = PBXSourcesBuildPhase()
+      self.AppendProperty('buildPhases', sources_phase)
+
+    return sources_phase
+
+  def FrameworksPhase(self):
+    frameworks_phase = self.GetBuildPhaseByType(PBXFrameworksBuildPhase)
+    if frameworks_phase is None:
+      frameworks_phase = PBXFrameworksBuildPhase()
+      self.AppendProperty('buildPhases', frameworks_phase)
+
+    return frameworks_phase
+
+  def AddDependency(self, other):
+    # super
+    XCTarget.AddDependency(self, other)
+
+    static_library_type = 'com.apple.product-type.library.static'
+    shared_library_type = 'com.apple.product-type.library.dynamic'
+    framework_type = 'com.apple.product-type.framework'
+    if isinstance(other, PBXNativeTarget) and \
+       'productType' in self._properties and \
+       self._properties['productType'] != static_library_type and \
+       'productType' in other._properties and \
+       (other._properties['productType'] == static_library_type or \
+        ((other._properties['productType'] == shared_library_type or \
+          other._properties['productType'] == framework_type) and \
+         ((not other.HasBuildSetting('MACH_O_TYPE')) or
+          other.GetBuildSetting('MACH_O_TYPE') != 'mh_bundle'))):
+
+      file_ref = other.GetProperty('productReference')
+
+      pbxproject = self.PBXProjectAncestor()
+      other_pbxproject = other.PBXProjectAncestor()
+      if pbxproject != other_pbxproject:
+        other_project_product_group = \
+            pbxproject.AddOrGetProjectReference(other_pbxproject)[0]
+        file_ref = other_project_product_group.GetChildByRemoteObject(file_ref)
+
+      self.FrameworksPhase().AppendProperty('files',
+                                            PBXBuildFile({'fileRef': file_ref}))
+
+
+class PBXAggregateTarget(XCTarget):
+  pass
+
+
+class PBXProject(XCContainerPortal):
+  # A PBXProject is really just an XCObject, the XCContainerPortal thing is
+  # just to allow PBXProject to be used in the containerPortal property of
+  # PBXContainerItemProxy.
+  """
+
+  Attributes:
+    path: "sample.xcodeproj".  TODO(mark) Document me!
+    _other_pbxprojects: A dictionary, keyed by other PBXProject objects.  Each
+                        value is a reference to the dict in the
+                        projectReferences list associated with the keyed
+                        PBXProject.
+  """
+
+  _schema = XCContainerPortal._schema.copy()
+  _schema.update({
+    'attributes':             [0, dict,                0, 0],
+    'buildConfigurationList': [0, XCConfigurationList, 1, 1,
+                               XCConfigurationList()],
+    'compatibilityVersion':   [0, str,                 0, 1, 'Xcode 3.2'],
+    'hasScannedForEncodings': [0, int,                 0, 1, 1],
+    'mainGroup':              [0, PBXGroup,            1, 1, PBXGroup()],
+    'projectDirPath':         [0, str,                 0, 1, ''],
+    'projectReferences':      [1, dict,                0, 0],
+    'projectRoot':            [0, str,                 0, 1, ''],
+    'targets':                [1, XCTarget,            1, 1, []],
+  })
+
+  def __init__(self, properties=None, id=None, parent=None, path=None):
+    self.path = path
+    self._other_pbxprojects = {}
+    # super
+    return XCContainerPortal.__init__(self, properties, id, parent)
+
+  def Name(self):
+    name = self.path
+    if name[-10:] == '.xcodeproj':
+      name = name[:-10]
+    return posixpath.basename(name)
+
+  def Path(self):
+    return self.path
+
+  def Comment(self):
+    return 'Project object'
+
+  def Children(self):
+    # super
+    children = XCContainerPortal.Children(self)
+
+    # Add children that the schema doesn't know about.  Maybe there's a more
+    # elegant way around this, but this is the only case where we need to own
+    # objects in a dictionary (that is itself in a list), and three lines for
+    # a one-off isn't that big a deal.
+    if 'projectReferences' in self._properties:
+      for reference in self._properties['projectReferences']:
+        children.append(reference['ProductGroup'])
+
+    return children
+
+  def PBXProjectAncestor(self):
+    return self
+
+  def _GroupByName(self, name):
+    if not 'mainGroup' in self._properties:
+      self.SetProperty('mainGroup', PBXGroup())
+
+    main_group = self._properties['mainGroup']
+    group = main_group.GetChildByName(name)
+    if group is None:
+      group = PBXGroup({'name': name})
+      main_group.AppendChild(group)
+
+    return group
+
+  # SourceGroup and ProductsGroup are created by default in Xcode's own
+  # templates.
+  def SourceGroup(self):
+    return self._GroupByName('Source')
+
+  def ProductsGroup(self):
+    return self._GroupByName('Products')
+
+  # IntermediatesGroup is used to collect source-like files that are generated
+  # by rules or script phases and are placed in intermediate directories such
+  # as DerivedSources.
+  def IntermediatesGroup(self):
+    return self._GroupByName('Intermediates')
+
+  # FrameworksGroup and ProjectsGroup are top-level groups used to collect
+  # frameworks and projects.
+  def FrameworksGroup(self):
+    return self._GroupByName('Frameworks')
+
+  def ProjectsGroup(self):
+    return self._GroupByName('Projects')
+
+  def RootGroupForPath(self, path):
+    """Returns a PBXGroup child of this object to which path should be added.
+
+    This method is intended to choose between SourceGroup and
+    IntermediatesGroup on the basis of whether path is present in a source
+    directory or an intermediates directory.  For the purposes of this
+    determination, any path located within a derived file directory such as
+    PROJECT_DERIVED_FILE_DIR is treated as being in an intermediates
+    directory.
+
+    The returned value is a two-element tuple.  The first element is the
+    PBXGroup, and the second element specifies whether that group should be
+    organized hierarchically (True) or as a single flat list (False).
+    """
+
+    # TODO(mark): make this a class variable and bind to self on call?
+    # Also, this list is nowhere near exhaustive.
+    # INTERMEDIATE_DIR and SHARED_INTERMEDIATE_DIR are used by
+    # gyp.generator.xcode.  There should probably be some way for that module
+    # to push the names in, rather than having to hard-code them here.
+    source_tree_groups = {
+      'DERIVED_FILE_DIR':         (self.IntermediatesGroup, True),
+      'INTERMEDIATE_DIR':         (self.IntermediatesGroup, True),
+      'PROJECT_DERIVED_FILE_DIR': (self.IntermediatesGroup, True),
+      'SHARED_INTERMEDIATE_DIR':  (self.IntermediatesGroup, True),
+    }
+
+    (source_tree, path) = SourceTreeAndPathFromPath(path)
+    if source_tree != None and source_tree in source_tree_groups:
+      (group_func, hierarchical) = source_tree_groups[source_tree]
+      group = group_func()
+      return (group, hierarchical)
+
+    # TODO(mark): make additional choices based on file extension.
+
+    return (self.SourceGroup(), True)
+
+  def AddOrGetFileInRootGroup(self, path):
+    """Returns a PBXFileReference corresponding to path in the correct group
+    according to RootGroupForPath's heuristics.
+
+    If an existing PBXFileReference for path exists, it will be returned.
+    Otherwise, one will be created and returned.
+    """
+
+    (group, hierarchical) = self.RootGroupForPath(path)
+    return group.AddOrGetFileByPath(path, hierarchical)
+
+  def RootGroupsTakeOverOnlyChildren(self, recurse=False):
+    """Calls TakeOverOnlyChild for all groups in the main group."""
+
+    for group in self._properties['mainGroup']._properties['children']:
+      if isinstance(group, PBXGroup):
+        group.TakeOverOnlyChild(recurse)
+
+  def SortGroups(self):
+    # Sort the children of the mainGroup (like "Source" and "Products")
+    # according to their defined order.
+    self._properties['mainGroup']._properties['children'] = \
+        sorted(self._properties['mainGroup']._properties['children'],
+               cmp=lambda x,y: x.CompareRootGroup(y))
+
+    # Sort everything else by putting group before files, and going
+    # alphabetically by name within sections of groups and files.  SortGroup
+    # is recursive.
+    for group in self._properties['mainGroup']._properties['children']:
+      if not isinstance(group, PBXGroup):
+        continue
+
+      if group.Name() == 'Products':
+        # The Products group is a special case.  Instead of sorting
+        # alphabetically, sort things in the order of the targets that
+        # produce the products.  To do this, just build up a new list of
+        # products based on the targets.
+        products = []
+        for target in self._properties['targets']:
+          if not isinstance(target, PBXNativeTarget):
+            continue
+          product = target._properties['productReference']
+          # Make sure that the product is already in the products group.
+          assert product in group._properties['children']
+          products.append(product)
+
+        # Make sure that this process doesn't miss anything that was already
+        # in the products group.
+        assert len(products) == len(group._properties['children'])
+        group._properties['children'] = products
+      else:
+        group.SortGroup()
+
+  def AddOrGetProjectReference(self, other_pbxproject):
+    """Add a reference to another project file (via PBXProject object) to this
+    one.
+
+    Returns [ProductGroup, ProjectRef].  ProductGroup is a PBXGroup object in
+    this project file that contains a PBXReferenceProxy object for each
+    product of each PBXNativeTarget in the other project file.  ProjectRef is
+    a PBXFileReference to the other project file.
+
+    If this project file already references the other project file, the
+    existing ProductGroup and ProjectRef are returned.  The ProductGroup will
+    still be updated if necessary.
+    """
+
+    if not 'projectReferences' in self._properties:
+      self._properties['projectReferences'] = []
+
+    product_group = None
+    project_ref = None
+
+    if not other_pbxproject in self._other_pbxprojects:
+      # This project file isn't yet linked to the other one.  Establish the
+      # link.
+      product_group = PBXGroup({'name': 'Products'})
+
+      # ProductGroup is strong.
+      product_group.parent = self
+
+      # There's nothing unique about this PBXGroup, and if left alone, it will
+      # wind up with the same set of hashables as all other PBXGroup objects
+      # owned by the projectReferences list.  Add the hashables of the
+      # remote PBXProject that it's related to.
+      product_group._hashables.extend(other_pbxproject.Hashables())
+
+      # The other project reports its path as relative to the same directory
+      # that this project's path is relative to.  The other project's path
+      # is not necessarily already relative to this project.  Figure out the
+      # pathname that this project needs to use to refer to the other one.
+      this_path = posixpath.dirname(self.Path())
+      projectDirPath = self.GetProperty('projectDirPath')
+      if projectDirPath:
+        if posixpath.isabs(projectDirPath[0]):
+          this_path = projectDirPath
+        else:
+          this_path = posixpath.join(this_path, projectDirPath)
+      other_path = gyp.common.RelativePath(other_pbxproject.Path(), this_path)
+
+      # ProjectRef is weak (it's owned by the mainGroup hierarchy).
+      project_ref = PBXFileReference({
+            'lastKnownFileType': 'wrapper.pb-project',
+            'path':              other_path,
+            'sourceTree':        'SOURCE_ROOT',
+          })
+      self.ProjectsGroup().AppendChild(project_ref)
+
+      ref_dict = {'ProductGroup': product_group, 'ProjectRef': project_ref}
+      self._other_pbxprojects[other_pbxproject] = ref_dict
+      self.AppendProperty('projectReferences', ref_dict)
+
+      # Xcode seems to sort this list case-insensitively
+      self._properties['projectReferences'] = \
+          sorted(self._properties['projectReferences'], cmp=lambda x,y:
+                 cmp(x['ProjectRef'].Name().lower(),
+                     y['ProjectRef'].Name().lower()))
+    else:
+      # The link already exists.  Pull out the relevnt data.
+      project_ref_dict = self._other_pbxprojects[other_pbxproject]
+      product_group = project_ref_dict['ProductGroup']
+      project_ref = project_ref_dict['ProjectRef']
+
+    self._SetUpProductReferences(other_pbxproject, product_group, project_ref)
+
+    return [product_group, project_ref]
+
+  def _SetUpProductReferences(self, other_pbxproject, product_group,
+                              project_ref):
+    # TODO(mark): This only adds references to products in other_pbxproject
+    # when they don't exist in this pbxproject.  Perhaps it should also
+    # remove references from this pbxproject that are no longer present in
+    # other_pbxproject.  Perhaps it should update various properties if they
+    # change.
+    for target in other_pbxproject._properties['targets']:
+      if not isinstance(target, PBXNativeTarget):
+        continue
+
+      other_fileref = target._properties['productReference']
+      if product_group.GetChildByRemoteObject(other_fileref) is None:
+        # Xcode sets remoteInfo to the name of the target and not the name
+        # of its product, despite this proxy being a reference to the product.
+        container_item = PBXContainerItemProxy({
+              'containerPortal':      project_ref,
+              'proxyType':            2,
+              'remoteGlobalIDString': other_fileref,
+              'remoteInfo':           target.Name()
+            })
+        # TODO(mark): Does sourceTree get copied straight over from the other
+        # project?  Can the other project ever have lastKnownFileType here
+        # instead of explicitFileType?  (Use it if so?)  Can path ever be
+        # unset?  (I don't think so.)  Can other_fileref have name set, and
+        # does it impact the PBXReferenceProxy if so?  These are the questions
+        # that perhaps will be answered one day.
+        reference_proxy = PBXReferenceProxy({
+              'fileType':   other_fileref._properties['explicitFileType'],
+              'path':       other_fileref._properties['path'],
+              'sourceTree': other_fileref._properties['sourceTree'],
+              'remoteRef':  container_item,
+            })
+
+        product_group.AppendChild(reference_proxy)
+
+  def SortRemoteProductReferences(self):
+    # For each remote project file, sort the associated ProductGroup in the
+    # same order that the targets are sorted in the remote project file.  This
+    # is the sort order used by Xcode.
+
+    def CompareProducts(x, y, remote_products):
+      # x and y are PBXReferenceProxy objects.  Go through their associated
+      # PBXContainerItem to get the remote PBXFileReference, which will be
+      # present in the remote_products list.
+      x_remote = x._properties['remoteRef']._properties['remoteGlobalIDString']
+      y_remote = y._properties['remoteRef']._properties['remoteGlobalIDString']
+      x_index = remote_products.index(x_remote)
+      y_index = remote_products.index(y_remote)
+
+      # Use the order of each remote PBXFileReference in remote_products to
+      # determine the sort order.
+      return cmp(x_index, y_index)
+
+    for other_pbxproject, ref_dict in self._other_pbxprojects.iteritems():
+      # Build up a list of products in the remote project file, ordered the
+      # same as the targets that produce them.
+      remote_products = []
+      for target in other_pbxproject._properties['targets']:
+        if not isinstance(target, PBXNativeTarget):
+          continue
+        remote_products.append(target._properties['productReference'])
+
+      # Sort the PBXReferenceProxy children according to the list of remote
+      # products.
+      product_group = ref_dict['ProductGroup']
+      product_group._properties['children'] = sorted(
+          product_group._properties['children'],
+          cmp=lambda x, y: CompareProducts(x, y, remote_products))
+
+
+class XCProjectFile(XCObject):
+  _schema = XCObject._schema.copy()
+  _schema.update({
+    'archiveVersion': [0, int,        0, 1, 1],
+    'classes':        [0, dict,       0, 1, {}],
+    'objectVersion':  [0, int,        0, 1, 45],
+    'rootObject':     [0, PBXProject, 1, 1],
+  })
+
+  def SetXcodeVersion(self, version):
+    version_to_object_version = {
+      '2.4': 45,
+      '3.0': 45,
+      '3.1': 45,
+      '3.2': 46,
+    }
+    if not version in version_to_object_version:
+      supported_str = ', '.join(sorted(version_to_object_version.keys()))
+      raise Exception(
+          'Unsupported Xcode version %s (supported: %s)' %
+          ( version, supported_str ) )
+    compatibility_version = 'Xcode %s' % version
+    self._properties['rootObject'].SetProperty('compatibilityVersion',
+                                               compatibility_version)
+    self.SetProperty('objectVersion', version_to_object_version[version]);
+
+  def ComputeIDs(self, recursive=True, overwrite=True, hash=None):
+    # Although XCProjectFile is implemented here as an XCObject, it's not a
+    # proper object in the Xcode sense, and it certainly doesn't have its own
+    # ID.  Pass through an attempt to update IDs to the real root object.
+    if recursive:
+      self._properties['rootObject'].ComputeIDs(recursive, overwrite, hash)
+
+  def Print(self, file=sys.stdout):
+    self.VerifyHasRequiredProperties()
+
+    # Add the special "objects" property, which will be caught and handled
+    # separately during printing.  This structure allows a fairly standard
+    # loop do the normal printing.
+    self._properties['objects'] = {}
+    self._XCPrint(file, 0, '// !$*UTF8*$!\n')
+    if self._should_print_single_line:
+      self._XCPrint(file, 0, '{ ')
+    else:
+      self._XCPrint(file, 0, '{\n')
+    for property, value in sorted(self._properties.iteritems(),
+                                  cmp=lambda x, y: cmp(x, y)):
+      if property == 'objects':
+        self._PrintObjects(file)
+      else:
+        self._XCKVPrint(file, 1, property, value)
+    self._XCPrint(file, 0, '}\n')
+    del self._properties['objects']
+
+  def _PrintObjects(self, file):
+    if self._should_print_single_line:
+      self._XCPrint(file, 0, 'objects = {')
+    else:
+      self._XCPrint(file, 1, 'objects = {\n')
+
+    objects_by_class = {}
+    for object in self.Descendants():
+      if object == self:
+        continue
+      class_name = object.__class__.__name__
+      if not class_name in objects_by_class:
+        objects_by_class[class_name] = []
+      objects_by_class[class_name].append(object)
+
+    for class_name in sorted(objects_by_class):
+      self._XCPrint(file, 0, '\n')
+      self._XCPrint(file, 0, '/* Begin ' + class_name + ' section */\n')
+      for object in sorted(objects_by_class[class_name],
+                           cmp=lambda x, y: cmp(x.id, y.id)):
+        object.Print(file)
+      self._XCPrint(file, 0, '/* End ' + class_name + ' section */\n')
+
+    if self._should_print_single_line:
+      self._XCPrint(file, 0, '}; ')
+    else:
+      self._XCPrint(file, 1, '};\n')
diff --git a/webWidgetTCT_device/tools/gyp/pylib/gyp/xml_fix.py b/webWidgetTCT_device/tools/gyp/pylib/gyp/xml_fix.py
new file mode 100755 (executable)
index 0000000..5de8481
--- /dev/null
@@ -0,0 +1,69 @@
+# Copyright (c) 2011 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Applies a fix to CR LF TAB handling in xml.dom.
+
+Fixes this: http://code.google.com/p/chromium/issues/detail?id=76293
+Working around this: http://bugs.python.org/issue5752
+TODO(bradnelson): Consider dropping this when we drop XP support.
+"""
+
+
+import xml.dom.minidom
+
+
+def _Replacement_write_data(writer, data, is_attrib=False):
+  """Writes datachars to writer."""
+  data = data.replace("&", "&amp;").replace("<", "&lt;")
+  data = data.replace("\"", "&quot;").replace(">", "&gt;")
+  if is_attrib:
+    data = data.replace(
+        "\r", "&#xD;").replace(
+        "\n", "&#xA;").replace(
+        "\t", "&#x9;")
+  writer.write(data)
+
+
+def _Replacement_writexml(self, writer, indent="", addindent="", newl=""):
+  # indent = current indentation
+  # addindent = indentation to add to higher levels
+  # newl = newline string
+  writer.write(indent+"<" + self.tagName)
+
+  attrs = self._get_attributes()
+  a_names = attrs.keys()
+  a_names.sort()
+
+  for a_name in a_names:
+    writer.write(" %s=\"" % a_name)
+    _Replacement_write_data(writer, attrs[a_name].value, is_attrib=True)
+    writer.write("\"")
+  if self.childNodes:
+    writer.write(">%s" % newl)
+    for node in self.childNodes:
+      node.writexml(writer, indent + addindent, addindent, newl)
+    writer.write("%s</%s>%s" % (indent, self.tagName, newl))
+  else:
+    writer.write("/>%s" % newl)
+
+
+class XmlFix(object):
+  """Object to manage temporary patching of xml.dom.minidom."""
+
+  def __init__(self):
+    # Preserve current xml.dom.minidom functions.
+    self.write_data = xml.dom.minidom._write_data
+    self.writexml = xml.dom.minidom.Element.writexml
+    # Inject replacement versions of a function and a method.
+    xml.dom.minidom._write_data = _Replacement_write_data
+    xml.dom.minidom.Element.writexml = _Replacement_writexml
+
+  def Cleanup(self):
+    if self.write_data:
+      xml.dom.minidom._write_data = self.write_data
+      xml.dom.minidom.Element.writexml = self.writexml
+      self.write_data = None
+
+  def __del__(self):
+    self.Cleanup()
diff --git a/webWidgetTCT_device/tools/gyp/pylintrc b/webWidgetTCT_device/tools/gyp/pylintrc
new file mode 100755 (executable)
index 0000000..d7c23d2
--- /dev/null
@@ -0,0 +1,307 @@
+[MASTER]
+
+# Specify a configuration file.
+#rcfile=
+
+# Python code to execute, usually for sys.path manipulation such as
+# pygtk.require().
+#init-hook=
+
+# Profiled execution.
+profile=no
+
+# Add files or directories to the blacklist. They should be base names, not
+# paths.
+ignore=CVS
+
+# Pickle collected data for later comparisons.
+persistent=yes
+
+# List of plugins (as comma separated values of python modules names) to load,
+# usually to register additional checkers.
+load-plugins=
+
+
+[MESSAGES CONTROL]
+
+# Enable the message, report, category or checker with the given id(s). You can
+# either give multiple identifier separated by comma (,) or put this option
+# multiple time.
+#enable=
+
+# Disable the message, report, category or checker with the given id(s). You
+# can either give multiple identifier separated by comma (,) or put this option
+# multiple time (only on the command line, not in the configuration file where
+# it should appear only once).
+# C0103: Invalid name "NN" (should match [a-z_][a-z0-9_]{2,30}$)
+# C0111: Missing docstring
+# C0302: Too many lines in module (NN)
+# R0902: Too many instance attributes (N/7)
+# R0903: Too few public methods (N/2)
+# R0904: Too many public methods (NN/20)
+# R0912: Too many branches (NN/12)
+# R0913: Too many arguments (N/5)
+# R0914: Too many local variables (NN/15)
+# R0915: Too many statements (NN/50)
+# W0141: Used builtin function 'map'
+# W0142: Used * or ** magic
+# W0232: Class has no __init__ method
+# W0511: TODO
+# W0603: Using the global statement
+#
+# These should be enabled eventually:
+# C0112: Empty docstring
+# C0301: Line too long (NN/80)
+# C0321: More than one statement on single line
+# C0322: Operator not preceded by a space
+# C0323: Operator not followed by a space
+# C0324: Comma not followed by a space
+# E0101: Explicit return in __init__
+# E0102: function already defined line NN
+# E1002: Use of super on an old style class
+# E1101: Instance of 'XX' has no 'YY' member
+# E1103: Instance of 'XX' has no 'XX' member (but some types could not be inferred)
+# E0602: Undefined variable 'XX'
+# F0401: Unable to import 'XX'
+# R0201: Method could be a function
+# R0801: Similar lines in N files
+# W0102: Dangerous default value {} as argument
+# W0104: Statement seems to have no effect
+# W0105: String statement has no effect
+# W0108: Lambda may not be necessary
+# W0201: Attribute 'XX' defined outside __init__
+# W0212: Access to a protected member XX of a client class
+# W0221: Arguments number differs from overridden method
+# W0223: Method 'XX' is abstract in class 'YY' but is not overridden
+# W0231: __init__ method from base class 'XX' is not called
+# W0301: Unnecessary semicolon
+# W0311: Bad indentation. Found NN spaces, expected NN
+# W0401: Wildcard import XX
+# W0402: Uses of a deprecated module 'string'
+# W0403: Relative import 'XX', should be 'YY.XX'
+# W0404: Reimport 'XX' (imported line NN)
+# W0601: Global variable 'XX' undefined at the module level
+# W0602: Using global for 'XX' but no assignment is done
+# W0611: Unused import pprint
+# W0612: Unused variable 'XX'
+# W0613: Unused argument 'XX'
+# W0614: Unused import XX from wildcard import
+# W0621: Redefining name 'XX' from outer scope (line NN)
+# W0622: Redefining built-in 'NN'
+# W0631: Using possibly undefined loop variable 'XX'
+# W0701: Raising a string exception
+# W0702: No exception type(s) specified
+disable=C0103,C0111,C0302,R0902,R0903,R0904,R0912,R0913,R0914,R0915,W0141,W0142,W0232,W0511,W0603,C0112,C0301,C0321,C0322,C0323,C0324,E0101,E0102,E1002,E1101,E1103,E0602,F0401,R0201,R0801,W0102,W0104,W0105,W0108,W0201,W0212,W0221,W0223,W0231,W0301,W0311,W0401,W0402,W0403,W0404,W0601,W0602,W0611,W0612,W0613,W0614,W0621,W0622,W0631,W0701,W0702
+
+
+[REPORTS]
+
+# Set the output format. Available formats are text, parseable, colorized, msvs
+# (visual studio) and html
+output-format=text
+
+# Include message's id in output
+include-ids=yes
+
+# Put messages in a separate file for each module / package specified on the
+# command line instead of printing them on stdout. Reports (if any) will be
+# written in a file name "pylint_global.[txt|html]".
+files-output=no
+
+# Tells whether to display a full report or only the messages
+reports=no
+
+# Python expression which should return a note less than 10 (10 is the highest
+# note). You have access to the variables errors warning, statement which
+# respectively contain the number of errors / warnings messages and the total
+# number of statements analyzed. This is used by the global evaluation report
+# (RP0004).
+evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
+
+# Add a comment according to your evaluation note. This is used by the global
+# evaluation report (RP0004).
+comment=no
+
+
+[VARIABLES]
+
+# Tells whether we should check for unused import in __init__ files.
+init-import=no
+
+# A regular expression matching the beginning of the name of dummy variables
+# (i.e. not used).
+dummy-variables-rgx=_|dummy
+
+# List of additional names supposed to be defined in builtins. Remember that
+# you should avoid to define new builtins when possible.
+additional-builtins=
+
+
+[TYPECHECK]
+
+# Tells whether missing members accessed in mixin class should be ignored. A
+# mixin class is detected if its name ends with "mixin" (case insensitive).
+ignore-mixin-members=yes
+
+# List of classes names for which member attributes should not be checked
+# (useful for classes with attributes dynamically set).
+ignored-classes=SQLObject
+
+# When zope mode is activated, add a predefined set of Zope acquired attributes
+# to generated-members.
+zope=no
+
+# List of members which are set dynamically and missed by pylint inference
+# system, and so shouldn't trigger E0201 when accessed. Python regular
+# expressions are accepted.
+generated-members=REQUEST,acl_users,aq_parent
+
+
+[MISCELLANEOUS]
+
+# List of note tags to take in consideration, separated by a comma.
+notes=FIXME,XXX,TODO
+
+
+[SIMILARITIES]
+
+# Minimum lines number of a similarity.
+min-similarity-lines=4
+
+# Ignore comments when computing similarities.
+ignore-comments=yes
+
+# Ignore docstrings when computing similarities.
+ignore-docstrings=yes
+
+
+[FORMAT]
+
+# Maximum number of characters on a single line.
+max-line-length=80
+
+# Maximum number of lines in a module
+max-module-lines=1000
+
+# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
+# tab).
+indent-string='  '
+
+
+[BASIC]
+
+# Required attributes for module, separated by a comma
+required-attributes=
+
+# List of builtins function names that should not be used, separated by a comma
+bad-functions=map,filter,apply,input
+
+# Regular expression which should only match correct module names
+module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
+
+# Regular expression which should only match correct module level names
+const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$
+
+# Regular expression which should only match correct class names
+class-rgx=[A-Z_][a-zA-Z0-9]+$
+
+# Regular expression which should only match correct function names
+function-rgx=[a-z_][a-z0-9_]{2,30}$
+
+# Regular expression which should only match correct method names
+method-rgx=[a-z_][a-z0-9_]{2,30}$
+
+# Regular expression which should only match correct instance attribute names
+attr-rgx=[a-z_][a-z0-9_]{2,30}$
+
+# Regular expression which should only match correct argument names
+argument-rgx=[a-z_][a-z0-9_]{2,30}$
+
+# Regular expression which should only match correct variable names
+variable-rgx=[a-z_][a-z0-9_]{2,30}$
+
+# Regular expression which should only match correct list comprehension /
+# generator expression variable names
+inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
+
+# Good variable names which should always be accepted, separated by a comma
+good-names=i,j,k,ex,Run,_
+
+# Bad variable names which should always be refused, separated by a comma
+bad-names=foo,bar,baz,toto,tutu,tata
+
+# Regular expression which should only match functions or classes name which do
+# not require a docstring
+no-docstring-rgx=__.*__
+
+
+[DESIGN]
+
+# Maximum number of arguments for function / method
+max-args=5
+
+# Argument names that match this expression will be ignored. Default to name
+# with leading underscore
+ignored-argument-names=_.*
+
+# Maximum number of locals for function / method body
+max-locals=15
+
+# Maximum number of return / yield for function / method body
+max-returns=6
+
+# Maximum number of branch for function / method body
+max-branchs=12
+
+# Maximum number of statements in function / method body
+max-statements=50
+
+# Maximum number of parents for a class (see R0901).
+max-parents=7
+
+# Maximum number of attributes for a class (see R0902).
+max-attributes=7
+
+# Minimum number of public methods for a class (see R0903).
+min-public-methods=2
+
+# Maximum number of public methods for a class (see R0904).
+max-public-methods=20
+
+
+[CLASSES]
+
+# List of interface methods to ignore, separated by a comma. This is used for
+# instance to not check methods defines in Zope's Interface base class.
+ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by
+
+# List of method names used to declare (i.e. assign) instance attributes.
+defining-attr-methods=__init__,__new__,setUp
+
+# List of valid names for the first argument in a class method.
+valid-classmethod-first-arg=cls
+
+
+[IMPORTS]
+
+# Deprecated modules which should not be used, separated by a comma
+deprecated-modules=regsub,string,TERMIOS,Bastion,rexec
+
+# Create a graph of every (i.e. internal and external) dependencies in the
+# given file (report RP0402 must not be disabled)
+import-graph=
+
+# Create a graph of external dependencies in the given file (report RP0402 must
+# not be disabled)
+ext-import-graph=
+
+# Create a graph of internal dependencies in the given file (report RP0402 must
+# not be disabled)
+int-import-graph=
+
+
+[EXCEPTIONS]
+
+# Exceptions that will emit a warning when being caught. Defaults to
+# "Exception"
+overgeneral-exceptions=Exception
diff --git a/webWidgetTCT_device/tools/increment-version.py b/webWidgetTCT_device/tools/increment-version.py
new file mode 100755 (executable)
index 0000000..3fde918
--- /dev/null
@@ -0,0 +1,78 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2013 Intel Corporation. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""
+increment-version.py -- Bump Canary version number across all required files.
+
+tizen-extensions-crosswalk's versioning scheme is "MAJOR.MINOR". Incrementing
+the version for a new Canary will monotonically increase the MINOR number.
+canary version will monotonically increase the BUILD number.
+
+This tool is a fork of Crosswalk's increment-version.py, tuned for t-e-c's
+versioning scheme.
+"""
+
+import optparse
+import os
+import re
+import sys
+
+
+def PathFromRoot(path):
+  """
+  Returns the absolute path to |path|, which is supposed to be relative to the
+  repository's root directory.
+  """
+  return os.path.join(os.path.abspath(os.path.dirname(__file__)), '..', path)
+
+
+def IncrementVersions(replacements):
+  """
+  |replacements| is a dictionary whose keys are files (relative to the root of
+  the repository) and values are regular expresions that match a section in the
+  file with the version number we want to increase.
+
+  The regular expression is expected to have 2 groups, the first matching
+  whatever precedes the version number and needs to stay the same, and the
+  second matching the number itself.
+
+  Each of the files specified will be overwritten with new version numbers.
+  """
+  for path, regexp in replacements.iteritems():
+    # The paths are always relative to the repository's root directory.
+    path = PathFromRoot(path)
+
+    def _ReplacementFunction(match_obj):
+      version_number = int(match_obj.group(2))
+      return '%s%s' % (match_obj.group(1), version_number + 1)
+
+    contents = re.sub(regexp, _ReplacementFunction, open(path).read())
+    open(path, 'w').write(contents)
+
+
+def Main():
+  option_parser = optparse.OptionParser()
+  option_parser.add_option(
+    '', '--type', choices=('canary',), dest='release_type',
+    help='What part of the version number must be increased. \"canary\" '
+         'increases the minor version.')
+  options, _ = option_parser.parse_args()
+
+  if options.release_type == 'canary':
+    replacements = {
+      'VERSION': r'(MINOR=)(\d+)',
+      'packaging/tizen-extensions-crosswalk.spec': r'(Version:\s+\d+\.)(\d+)',
+    }
+    IncrementVersions(replacements)
+  else:
+    print '--type is a required argument and has not been specified. Exiting.'
+    return 1
+
+  return 0
+
+
+if __name__ == '__main__':
+  sys.exit(Main())
diff --git a/webWidgetTCT_device/tools/js_minimize.py b/webWidgetTCT_device/tools/js_minimize.py
new file mode 100755 (executable)
index 0000000..f78126f
--- /dev/null
@@ -0,0 +1,7 @@
+#!/usr/bin/python
+
+import slimit
+
+def minimize(code):
+   return slimit.minify(code)
+
diff --git a/webWidgetTCT_device/tools/launcher/WebServiceTest/config.xml b/webWidgetTCT_device/tools/launcher/WebServiceTest/config.xml
new file mode 100755 (executable)
index 0000000..c273ceb
--- /dev/null
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<widget xmlns="http://www.w3.org/ns/widgets" xmlns:tizen="http://tizen.org/ns/widgets" id="http://yourdomain/WebServiceTest" version="1.0.0" viewmodes="maximized">
+    <tizen:application id="tizenutc00.WebServiceTest" package="tizenutc00" required_version="2.4" />
+    <content src="index.html" />
+    <feature name="http://tizen.org/feature/screen.size.all" />
+    <icon src="icon.png" />
+    <name>WebServiceTest</name>
+    <name xml:lang="en-us">WebServiceTest</name>
+
+    <tizen:privilege name="http://tizen.org/privilege/alarm"/>
+    <tizen:privilege name="http://tizen.org/privilege/application.info"/>
+    <tizen:privilege name="http://tizen.org/privilege/application.launch"/>
+    <tizen:privilege name="http://tizen.org/privilege/appmanager.certificate"/>
+    <tizen:privilege name="http://tizen.org/privilege/appmanager.kill"/>
+    <tizen:privilege name="http://tizen.org/privilege/content.read"/>
+    <tizen:privilege name="http://tizen.org/privilege/content.write"/>
+    <tizen:privilege name="http://tizen.org/privilege/datacontrol.consumer"/>
+    <tizen:privilege name="http://tizen.org/privilege/filesystem.read"/>
+    <tizen:privilege name="http://tizen.org/privilege/filesystem.write"/>
+    <tizen:privilege name="http://tizen.org/privilege/package.info"/>
+    <tizen:privilege name="http://tizen.org/privilege/packagemanager.install"/>
+    <tizen:privilege name="http://tizen.org/privilege/system"/>
+    <tizen:privilege name="http://tizen.org/privilege/telephony"/>
+<!--
+    <tizen:privilege name="http://tizen.org/privilege/alarm"/>
+    <tizen:privilege name="http://tizen.org/privilege/application.info"/>
+    <tizen:privilege name="http://tizen.org/privilege/application.launch"/>
+    <tizen:privilege name="http://tizen.org/privilege/appmanager.certificate"/>
+    <tizen:privilege name="http://tizen.org/privilege/appmanager.kill"/>
+    <tizen:privilege name="http://tizen.org/privilege/bluetooth.admin"/>
+    <tizen:privilege name="http://tizen.org/privilege/bluetooth.gap"/>
+    <tizen:privilege name="http://tizen.org/privilege/bluetooth.health"/>
+    <tizen:privilege name="http://tizen.org/privilege/bluetooth.spp"/>
+    <tizen:privilege name="http://tizen.org/privilege/bluetoothmanager"/>
+    <tizen:privilege name="http://tizen.org/privilege/bookmark.read"/>
+    <tizen:privilege name="http://tizen.org/privilege/bookmark.write"/>
+    <tizen:privilege name="http://tizen.org/privilege/calendar.read"/>
+    <tizen:privilege name="http://tizen.org/privilege/calendar.write"/>
+    <tizen:privilege name="http://tizen.org/privilege/callhistory.read"/>
+    <tizen:privilege name="http://tizen.org/privilege/callhistory.write"/>
+    <tizen:privilege name="http://tizen.org/privilege/contact.read"/>
+    <tizen:privilege name="http://tizen.org/privilege/contact.write"/>
+    <tizen:privilege name="http://tizen.org/privilege/content.read"/>
+    <tizen:privilege name="http://tizen.org/privilege/content.write"/>
+    <tizen:privilege name="http://tizen.org/privilege/datacontrol.consumer"/>
+    <tizen:privilege name="http://tizen.org/privilege/datasync"/>
+    <tizen:privilege name="http://tizen.org/privilege/download"/>
+    <tizen:privilege name="http://tizen.org/privilege/filesystem.read"/>
+    <tizen:privilege name="http://tizen.org/privilege/filesystem.write"/>
+    <tizen:privilege name="http://tizen.org/privilege/fullscreen"/>
+    <tizen:privilege name="http://tizen.org/privilege/healthinfo"/>
+    <tizen:privilege name="http://tizen.org/privilege/location"/>
+    <tizen:privilege name="http://tizen.org/privilege/mediacapture"/>
+    <tizen:privilege name="http://tizen.org/privilege/medicalinfo"/>
+    <tizen:privilege name="http://tizen.org/privilege/messaging.read"/>
+    <tizen:privilege name="http://tizen.org/privilege/messaging.write"/>
+    <tizen:privilege name="http://tizen.org/privilege/networkbearerselection"/>
+    <tizen:privilege name="http://tizen.org/privilege/nfc.admin"/>
+    <tizen:privilege name="http://tizen.org/privilege/nfc.common"/>
+    <tizen:privilege name="http://tizen.org/privilege/nfc.p2p"/>
+    <tizen:privilege name="http://tizen.org/privilege/nfc.tag"/>
+    <tizen:privilege name="http://tizen.org/privilege/notification"/>
+    <tizen:privilege name="http://tizen.org/privilege/package.info"/>
+    <tizen:privilege name="http://tizen.org/privilege/packagemanager.install"/>
+    <tizen:privilege name="http://tizen.org/privilege/power"/>
+    <tizen:privilege name="http://tizen.org/privilege/push"/>
+    <tizen:privilege name="http://tizen.org/privilege/secureelement"/>
+    <tizen:privilege name="http://tizen.org/privilege/setting"/>
+    <tizen:privilege name="http://tizen.org/privilege/system"/>
+    <tizen:privilege name="http://tizen.org/privilege/systemmanager"/>
+    <tizen:privilege name="http://tizen.org/privilege/unlimitedstorage"/>
+    <tizen:privilege name="http://tizen.org/privilege/websetting"/>
+
+    <tizen:privilege name="http://tizen.org/privilege/application.kill"/>
+    <tizen:privilege name="http://tizen.org/privilege/application.read"/>
+    <tizen:privilege name="http://tizen.org/privilege/messaging.send"/>
+    <tizen:privilege name="http://tizen.org/privilege/notification.read"/>
+    <tizen:privilege name="http://tizen.org/privilege/notification.write"/>
+    <tizen:privilege name="http://tizen.org/privilege/systeminfo"/>
+    <tizen:privilege name="http://developer.samsung.com/privilege/connection"/>
+-->
+
+    <tizen:service id="tizenutc00.UnitTest">
+        <tizen:service-content src="service/service.js" />
+        <tizen:service-name>WebService-UnitTest</tizen:service-name>
+        <tizen:service-icon src="icon.png" />
+        <tizen:service-description>WebService-UnitTest</tizen:service-description>
+        <tizen:content src="service/service.js" />
+        <tizen:name>WebService-UnitTest</tizen:name>
+        <tizen:icon src="icon.png" />
+        <tizen:description>WebService-UnitTest</tizen:description>
+        <tizen:metadata key="meta-key" value="meta-value"/>
+        <tizen:category name="http://tizen.org/category/service"/>
+    </tizen:service>
+
+    <tizen:service id="tizenutcmp.MsgPortSvr">
+        <tizen:service-content src="service/message-port.js" />
+        <tizen:service-name>WebService-MsgPortSvr</tizen:service-name>
+        <tizen:service-icon src="icon.png" />
+        <tizen:service-description>WebService-MsgPortSvr</tizen:service-description>
+        <tizen:content src="service/message-port.js" />
+        <tizen:name>WebService-MsgPortSvr</tizen:name>
+        <tizen:icon src="icon.png" />
+        <tizen:description>WebService-MsgPortSvr</tizen:description>
+    </tizen:service>
+</widget>
diff --git a/webWidgetTCT_device/tools/launcher/WebServiceTest/css/style.css b/webWidgetTCT_device/tools/launcher/WebServiceTest/css/style.css
new file mode 100755 (executable)
index 0000000..3d6d94f
--- /dev/null
@@ -0,0 +1,35 @@
+* {
+    font-family: Verdana, Lucida Sans, Arial, Helvetica, sans-serif;
+}
+
+body {
+    margin: 0px auto;
+    background-color:#222;
+}
+
+.contents {
+    display: flex;
+    display: -webkit-flex;
+    box-sizing: border-box;
+    -webkit-box-sizing: border-box;
+    height:320px;
+}
+
+.content-padding {
+    margin-top: 16px;
+    margin-bottom: 16px;
+    padding-left: 16px;
+    padding-right: 16px;
+}
+
+.content_text {
+    font-weight:bold;
+    font-size:5em;
+    color:#fff;
+}
+
+.ui-page-active{display:block}
+.ui-header{position:relative;width:100%;height:3.466666666666667rem;line-height:3.466666666666667rem;background-color:#4b4237;border-bottom:1px solid #6b563d}
+.ui-title{color:#fff;font-size:2rem;white-space:nowrap;margin:0;padding-left:1.0666666666666667rem;padding-right:1.0666666666666667rem}
+.ui-content{width:auto;height:100%;overflow:auto;-webkit-overflow-scrolling:touch;-moz-overflow-scrolling:touch;-o-overflow-scrolling:touch;-ms-overflow-scrolling:touch;overflow-scrolling:touch}
+.btnStyle{height:120px;width:100%;font-size:45px}
diff --git a/webWidgetTCT_device/tools/launcher/WebServiceTest/icon.png b/webWidgetTCT_device/tools/launcher/WebServiceTest/icon.png
new file mode 100755 (executable)
index 0000000..1f02568
Binary files /dev/null and b/webWidgetTCT_device/tools/launcher/WebServiceTest/icon.png differ
diff --git a/webWidgetTCT_device/tools/launcher/WebServiceTest/index.html b/webWidgetTCT_device/tools/launcher/WebServiceTest/index.html
new file mode 100755 (executable)
index 0000000..eadeacd
--- /dev/null
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <meta name="viewport" content="width=device-width,user-scalable=no"/>
+    <title>WebServiceTest</title>
+    <link rel="stylesheet"  href="css/style.css">
+</head>
+<body>
+    <div class="ui-page ui-page-active" id="main">
+        <header class="ui-header">
+            <h2 class="ui-title">Web Service Test</h2>
+        </header>
+        <div class="ui-content content-padding">
+            <div><button type="button" class="btnStyle" onclick="start();">Service START</button></div>
+            <div><button type="button" class="btnStyle" onclick="kill();">Service KILL</button></div>
+        </div>
+    </div>
+</body>
+<script src="js/app.js"></script>
+<script>startService('tizenutcmp.MsgPortSvr');</script>
+</html>
diff --git a/webWidgetTCT_device/tools/launcher/WebServiceTest/js/app.js b/webWidgetTCT_device/tools/launcher/WebServiceTest/js/app.js
new file mode 100755 (executable)
index 0000000..3de2ba2
--- /dev/null
@@ -0,0 +1,58 @@
+(function () {
+    window.addEventListener('tizenhwkey', function(ev) {
+        if (ev.keyName == 'back') {
+            var page = document.getElementsByClassName('ui-page-active')[0],
+            pageid = page ? page.id : '';
+            if (pageid === 'main') {
+                tizen.application.getCurrentApplication().exit();
+            } else {
+                window.history.back();
+            }
+        }
+    });
+}());
+
+var services = ['tizenutc00.UnitTest'];
+
+function startService(service) {
+    console.log('Launching ' + service);
+    tizen.application.launchAppControl(
+            new tizen.ApplicationControl('http://tizen.org/appcontrol/operation/service'),
+            service,
+            function() { console.log('Launch success: ' + service); },
+            function(e) { console.log('Launch failed: ' + service + ' - ' + e.message); }
+    );
+}
+
+function killService(context) {
+    console.log('Killing ' + context.appId);
+    tizen.application.kill(
+            context.id,
+            function() { console.log('Kill success: ' + context.appId); },
+            function(e) { console.log('Kill failed: ' + context.appId + ' - ' + e.message); }
+    );
+}
+
+function start() {
+    console.log('start');
+
+    for (var i = 0; i < services.length; ++i) {
+        startService(services[i]);
+    }
+}
+
+function kill() {
+    console.log('kill');
+
+    function onRunningAppsContext(contexts) {
+        for (var i = 0; i < contexts.length; ++i) {
+            for (var j = 0; j < services.length; ++j) {
+                if (contexts[i].appId == services[j]) {
+                    killService(contexts[i]);
+                }
+            }
+        }
+    }
+
+    tizen.application.getAppsContext(onRunningAppsContext);
+}
diff --git a/webWidgetTCT_device/tools/launcher/WebServiceTest/service/message-port.js b/webWidgetTCT_device/tools/launcher/WebServiceTest/service/message-port.js
new file mode 100755 (executable)
index 0000000..57bcc55
--- /dev/null
@@ -0,0 +1,290 @@
+(function() {
+    var messagePortSimple;
+    var messagePortForReq;
+    var messagePortSimpleTrusted;
+    var messagePortForReqTrusted;
+
+    function getValue(data, key) {
+        for (var i in data) {
+            if (data[i].key == key) {
+                return data[i].value;
+            }
+        }
+
+        return undefined;
+    }
+
+    function createMessagePortSimple() {
+        console.log('Creating TEST_PORT_SIMPLE');
+
+        var messagePort;
+
+        try {
+            messagePort = tizen.messageport.requestLocalMessagePort('TEST_PORT_SIMPLE');
+        } catch (e) {
+            console.log('Failed to create TEST_PORT_SIMPLE: ' + e);
+            return null;
+        }
+
+        console.log('TEST_PORT_SIMPLE created');
+
+        function onreceived(data, remoteMsgPort) {
+            console.logd('========= Callback ==========');
+            console.logd(' port : ' + messagePort.messagePortName);
+            console.logd(' data :');
+
+            for (var i in data) {
+                console.logd('   { key:"' + data[i].key + '", value:"' + data[i].value + '"}');
+            }
+
+            if (remoteMsgPort) {
+                console.logd(' remoteMessagePort : {name:' + remoteMsgPort.messagePortName + ', appId:' + remoteMsgPort.appId + '}');
+
+                console.logd('Replying to remote.');
+                try {
+                    remoteMsgPort.sendMessage(
+                        [
+                            { key : 'PORT_NAME', value : 'TEST_PORT_SIMPLE'},
+                            { key : 'MESSAGE', value : 'Call succeed'}
+                        ]);
+                } catch (e) {
+                    console.log('Failed to reply to remote: ' + e);
+                }
+            }
+        }
+
+        console.log('Registering listener for TEST_PORT_SIMPLE');
+
+        try {
+            messagePort.addMessagePortListener(onreceived);
+        } catch (e) {
+            console.log('Failed to register listener for TEST_PORT_SIMPLE: ' + e);
+            return null;
+        }
+
+        console.log('Listener for TEST_PORT_SIMPLE registered');
+
+        return messagePort;
+    }
+
+    function createMessagePortForReq() {
+        console.log('Creating TEST_PORT_FOR_REQ_CONNECT');
+
+        var messagePort;
+
+        try {
+            messagePort = tizen.messageport.requestLocalMessagePort('TEST_PORT_FOR_REQ_CONNECT');
+        } catch (e) {
+            console.log('Failed to create TEST_PORT_FOR_REQ_CONNECT: ' + e);
+            return null;
+        }
+
+        console.log('TEST_PORT_FOR_REQ_CONNECT created');
+
+        function onreceived(data) {
+            console.logd('========= Callback ==========');
+            console.logd(' port : ' + messagePort.messagePortName);
+            console.logd(' remoteMessagePort : null');
+            console.logd(' data :');
+
+            for (var i in data) {
+                console.logd('   { key:"' + data[i].key + '", value:"' + data[i].value + '"}');
+            }
+
+            var portName = getValue(data, 'PORT_NAME');
+
+            if (!portName) {
+                console.logd('PORT_NAME was not set.');
+                console.logd('=============================');
+            }
+
+            var appId = getValue(data, 'APP_ID');
+
+            if (!appId) {
+                console.logd('APP_ID was not set.');
+                console.logd('=============================');
+            }
+
+            console.logd('Request remote');
+            var remote = tizen.messageport.requestRemoteMessagePort(appId, portName);
+
+            console.logd('Request local');
+            var local = tizen.messageport.requestLocalMessagePort('SERVER_REPLY_PORT');
+
+            console.logd('Replying to remote.');
+            try{
+                remote.sendMessage(
+                    [
+                        { key : 'PORT_NAME', value : 'TEST_PORT_FOR_REQ_CONNECT'},
+                        { key : 'MESSAGE', value : 'Call!!!'}
+                    ], local);
+            } catch (e) {
+                console.log('Failed to reply to remote: ' + e);
+            }
+        }
+
+        console.log('Registering listener for TEST_PORT_FOR_REQ_CONNECT');
+
+        try {
+            messagePort.addMessagePortListener(onreceived);
+        } catch (e) {
+            console.log('Failed to register listener for TEST_PORT_FOR_REQ_CONNECT: ' + e);
+            return null;
+        }
+
+        console.log('Listener for TEST_PORT_FOR_REQ_CONNECT registered');
+
+        return messagePort;
+    }
+
+    function createMessagePortSimpleTrusted() {
+        console.log('Creating TEST_TRUSTED_PORT_SIMPLE');
+
+        var messagePort;
+
+        try {
+            messagePort = tizen.messageport.requestTrustedLocalMessagePort('TEST_TRUSTED_PORT_SIMPLE');
+        } catch (e) {
+            console.log('Failed to create TEST_TRUSTED_PORT_SIMPLE: ' + e);
+            return null;
+        }
+
+        console.log('TEST_TRUSTED_PORT_SIMPLE created');
+
+        function onreceived(data, remoteMsgPort) {
+            console.logd('========= Callback ==========');
+            console.logd(' port : ' + messagePort.messagePortName);
+            console.logd(' data :');
+
+            for (var i in data) {
+                console.logd('   { key:"' + data[i].key + '", value:"' + data[i].value + '"}');
+            }
+
+            if (remoteMsgPort) {
+                console.logd(' remoteMessagePort : {name:' + remoteMsgPort.messagePortName + ', appId:' + remoteMsgPort.appId + '}');
+
+                console.logd('Replying to remote.');
+                try {
+                    remoteMsgPort.sendMessage(
+                        [
+                            { key : 'PORT_NAME', value : 'TEST_TRUSTED_PORT_SIMPLE'},
+                            { key : 'MESSAGE', value : 'Call succeed'}
+                        ]);
+                } catch (e) {
+                    console.log('Failed to reply to remote: ' + e);
+                }
+            }
+        }
+
+        console.log('Registering listener for TEST_TRUSTED_PORT_SIMPLE');
+
+        try {
+            messagePort.addMessagePortListener(onreceived);
+        } catch (e) {
+            console.log('Failed to register listener for TEST_TRUSTED_PORT_SIMPLE: ' + e);
+            return null;
+        }
+
+        console.log('Listener for TEST_TRUSTED_PORT_SIMPLE registered');
+
+        return messagePort;
+    }
+
+    function createMessagePortForReqTrusted() {
+        console.log('Creating TEST_TRUSTED_PORT_FOR_REQ_CONNECT');
+
+        var messagePort;
+
+        try {
+            messagePort = tizen.messageport.requestTrustedLocalMessagePort('TEST_TRUSTED_PORT_FOR_REQ_CONNECT');
+        } catch (e) {
+            console.log('Failed to create TEST_TRUSTED_PORT_FOR_REQ_CONNECT: ' + e);
+            return null;
+        }
+
+        console.log('TEST_TRUSTED_PORT_FOR_REQ_CONNECT created');
+
+        function onreceived(data) {
+            console.logd('========= Callback ==========');
+            console.logd(' port : ' + messagePort.messagePortName);
+            console.logd(' remoteMessagePort : null');
+            console.logd(' data :');
+
+            for (var i in data) {
+                console.logd('   { key:"' + data[i].key + '", value:"' + data[i].value + '"}');
+            }
+
+            var portName = getValue(data, 'PORT_NAME');
+
+            if (!portName) {
+                console.logd('PORT_NAME was not set.');
+                console.logd('=============================');
+            }
+
+            var appId = getValue(data, 'APP_ID');
+
+            if (!appId) {
+                console.logd('APP_ID was not set.');
+                console.logd('=============================');
+            }
+
+            console.logd('Request remote');
+            var remote = tizen.messageport.requestTrustedRemoteMessagePort(appId, portName);
+
+            console.logd('Request local');
+            var local = tizen.messageport.requestTrustedLocalMessagePort('SERVER_REPLY_TRUSTED_PORT');
+
+            console.logd('Replying to remote.');
+            try {
+                remote.sendMessage(
+                    [
+                        { key : 'PORT_NAME', value : 'TEST_TRUSTED_PORT_FOR_REQ_CONNECT'},
+                        { key : 'MESSAGE', value : 'Call!!!'}
+                    ], local);
+            } catch (e) {
+                console.log('Failed to reply to remote: ' + e);
+            }
+        }
+
+        console.log('Registering listener for TEST_TRUSTED_PORT_FOR_REQ_CONNECT');
+
+        try {
+            messagePort.addMessagePortListener(onreceived);
+        } catch (e) {
+            console.log('Failed to register listener for TEST_TRUSTED_PORT_FOR_REQ_CONNECT: ' + e);
+            return null;
+        }
+
+        console.log('Listener for TEST_TRUSTED_PORT_FOR_REQ_CONNECT registered');
+
+        return messagePort;
+    }
+
+    function startServer() {
+        console.log('Starting UTC MessagePort server...');
+        messagePortSimple = createMessagePortSimple();
+        messagePortForReq = createMessagePortForReq();
+        messagePortSimpleTrusted = createMessagePortSimpleTrusted();
+        messagePortForReqTrusted = createMessagePortForReqTrusted();
+
+        if (messagePortSimple && messagePortForReq && messagePortSimpleTrusted && messagePortForReqTrusted) {
+            console.log('UTC MessagePort server is READY');
+        } else {
+            console.log('Failed to start UTC MessagePort server!!!');
+        }
+    }
+    var serviceName = 'tizenutcmp.MsgPortSvr';
+    function onRequest() {
+        console.log(serviceName + ' - onRequest');
+        startServer();
+    }
+    module.exports.onStart = function () {
+        console.log(serviceName + ' - onStart');
+    };
+    module.exports.onRequest = onRequest;
+    module.exports.onService = onRequest;
+    module.exports.onExit = function () {
+        console.log(serviceName + ' - onExit');
+    };
+})();
+
diff --git a/webWidgetTCT_device/tools/launcher/WebServiceTest/service/service.js b/webWidgetTCT_device/tools/launcher/WebServiceTest/service/service.js
new file mode 100755 (executable)
index 0000000..aa2d2b0
--- /dev/null
@@ -0,0 +1,22 @@
+(function() {
+    var serviceName = 'tizenutc00.UnitTest';
+    var userScript = '/tmp/index.js';
+    function onRequest() {
+        console.log(serviceName + ' - onRequest');
+        if (require('fs').existsSync(userScript)) {
+            console.log('Using override script "' + userScript + '"');
+            require(userScript);
+        } else {
+            console.log('Launching embedded tests.');
+            require('./test/index.js');
+        }
+    }
+    module.exports.onStart = function () {
+        console.log(serviceName + ' - onStart');
+    };
+    module.exports.onRequest = onRequest;
+    module.exports.onService = onRequest;
+    module.exports.onExit = function () {
+        console.log(serviceName + ' - onExit');
+    };
+})();
diff --git a/webWidgetTCT_device/tools/launcher/deploy.sh b/webWidgetTCT_device/tools/launcher/deploy.sh
new file mode 100755 (executable)
index 0000000..0e4a909
--- /dev/null
@@ -0,0 +1,216 @@
+#!/bin/bash
+
+HELP_DIR="packaging"
+SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+
+DIR="${SCRIPT_DIR}"
+while [ "$DIR" != "/" ]; do
+    DIR=`dirname $DIR`
+
+    if [ -d "$DIR/$HELP_DIR" ]; then
+        PROJECT_DIR=$DIR
+        break;
+    fi
+done
+
+if [ ! "$PROJECT_DIR" ]; then
+    echo "Couldn't find project directory!"
+    exit 1;
+fi
+
+# functions
+function sign_wgt() {
+    # $1 : "platform", "partner-operator", "partner" or "public"
+    # $2 : name of widget file for signing
+    if [ "$1" == "" ]
+    then
+        DIST="public"
+    else
+        DIST="$1"
+    fi
+    DIST_SIGN_FILE="${SCRIPT_DIR}/sign/certificates/tizen-distributor-$DIST-signer.p12"
+    DIST_SIGN_PASSWD="tizenpkcs12passfordsigner"
+    AUTHOR_SIGN_FILE="${SCRIPT_DIR}/sign/certificates/author/author-tizen-webapi.p12"
+    AUTHOR_SIGN_PASSWD="tizenwebapi101"
+    DIST2_ORANGE_TEST_SIGN_FILE="${SCRIPT_DIR}/sign/certificates/OrangeLabs-Test-Android.p12"
+    DIST2_ORANGE_TEST_SIGN_PASSWD="0rangeLabs"
+    if [ ! -e $DIST_SIGN_FILE ]
+    then
+        echo "Wrong sign file"
+        return -1
+    fi
+
+    WGT_FILE=$2
+
+    if [ ! -e $WGT_FILE ]
+    then
+        echo "Wrong widget file"
+        return -1
+    fi
+
+    WGT_TMP_FILE="$WGT_FILE.tmp"
+
+    if [ "$DIST" == "platform" ]
+    then
+        ${SCRIPT_DIR}/sign/hash-signer.sh -a $AUTHOR_SIGN_FILE -pa $AUTHOR_SIGN_PASSWD -d $DIST_SIGN_FILE -pd $DIST_SIGN_PASSWD -d2 $DIST2_ORANGE_TEST_SIGN_FILE -pd2 $DIST2_ORANGE_TEST_SIGN_PASSWD -i $WGT_FILE -o $WGT_TMP_FILE
+    else
+        ${SCRIPT_DIR}/sign/hash-signer.sh -a $AUTHOR_SIGN_FILE -pa $AUTHOR_SIGN_PASSWD -d $DIST_SIGN_FILE -pd $DIST_SIGN_PASSWD -i $WGT_FILE -o $WGT_TMP_FILE
+    fi
+
+    rm $WGT_FILE
+    mv $WGT_TMP_FILE $WGT_FILE
+}
+
+function setup_names() {
+    SRC_DIR="$1"
+    WIDGET_NAME="${SRC_DIR}.wgt"
+}
+
+function package_wgt() {
+    setup_names "$1"
+
+    echo "Building ${WIDGET_NAME}"
+
+    # move to correct folder
+    pushd ${SRC_DIR} > /dev/null
+
+    # create widget
+    zip "${WIDGET_NAME}" -r *
+
+    # move back to the previous folder
+    popd > /dev/null
+
+    # sign
+    sign_wgt platform "${WIDGET_NAME}"
+}
+
+function install_wgt() {
+    setup_names "$1"
+
+    echo "Installing ${WIDGET_NAME}"
+
+    # install
+    sdb root off
+    sdb install "${WIDGET_NAME}"
+
+    # remove widget
+    rm "${WIDGET_NAME}"
+}
+
+function push_wgt() {
+    setup_names "$1"
+
+    echo "Pushing ${WIDGET_NAME} to $2"
+
+    # push
+    sdb root on
+    sdb push "${WIDGET_NAME}" $2
+
+    # remove widget
+    rm "${WIDGET_NAME}"
+}
+
+function package_install_wgt() {
+    package_wgt "$1"
+    install_wgt "$1"
+}
+
+function package_push_wgt() {
+    package_wgt "$1"
+    push_wgt "$1" "$2"
+}
+
+case $1 in
+all) EXEC="ALL" ;;
+tools) EXEC="ALL-TOOLS" ;;
+tct-tools) EXEC="TCT-TOOLS" ;;
+utc-tools) EXEC="UTC-TOOLS" ;;
+launcher) EXEC="LAUNCHER" ;;
+*) EXEC="ALL" ;;
+esac
+
+INST_TOOLS_APPS=()
+PUSH_TOOLS_APPS=()
+COPY_TOOLS_FILES=()
+
+function prepare_tools() {
+    INSTALL_DIR="$1/install"
+    PUSH_DIR="$1/push"
+    COPY_DIR="$1/copy"
+
+    for DIR in "${SCRIPT_DIR}/${INSTALL_DIR}"/*
+    do
+        if [ -d ${DIR} ]
+        then
+            INST_TOOLS_APPS+=("${INSTALL_DIR}"/$(basename ${DIR}))
+        fi
+    done
+
+    for DIR in "${SCRIPT_DIR}/${PUSH_DIR}"/*
+    do
+        if [ -d ${DIR} ]
+        then
+            PUSH_TOOLS_APPS+=("${PUSH_DIR}"/$(basename ${DIR}))
+        fi
+    done
+
+    if [ -d "${SCRIPT_DIR}/${COPY_DIR}" ]
+    then
+        COPY_TOOLS_FILES+=("${COPY_DIR}")
+    fi
+}
+
+if [ "$EXEC" == "ALL" -o "$EXEC" == "ALL-TOOLS" -o "$EXEC" == "UTC-TOOLS" ]
+then
+    prepare_tools "utc"
+fi
+
+if [ "$EXEC" == "ALL" -o "$EXEC" == "ALL-TOOLS" -o "$EXEC" == "TCT-TOOLS" ]
+then
+    prepare_tools "tct"
+fi
+
+# install helper apps
+for APP in ${INST_TOOLS_APPS[@]}
+do
+    WGT_DIR="${SCRIPT_DIR}/${APP}"
+    package_install_wgt "${WGT_DIR}"
+done
+
+# push helper apps
+PUSH_TARGET_DIR="/home/owner/share"
+for APP in ${PUSH_TOOLS_APPS[@]}
+do
+    WGT_DIR="${SCRIPT_DIR}/${APP}"
+    package_push_wgt "${WGT_DIR}" "${PUSH_TARGET_DIR}"
+done
+
+# copy files
+for DIR in ${COPY_TOOLS_FILES[@]}
+do
+    sdb push "${SCRIPT_DIR}/${DIR}" /
+done
+
+if [ "$EXEC" == "ALL" -o "$EXEC" == "LAUNCHER" ]
+then
+    # install launcher
+    LAUNCHER_NAME="WebServiceTest"
+    LAUNCHER_DIR="${SCRIPT_DIR}/${LAUNCHER_NAME}"
+    TEST_DIR_NAME="test"
+    TESTS_DIR_SRC="${PROJECT_DIR}/${TEST_DIR_NAME}"
+    TESTS_DIR_DST="${LAUNCHER_DIR}/service/${TEST_DIR_NAME}"
+
+    # copy tests to widget folder
+    cp -R "${TESTS_DIR_SRC}" "${TESTS_DIR_DST}"
+
+    # package widget
+    package_wgt "${LAUNCHER_DIR}"
+
+    # remove copied tests
+    rm -rf "${TESTS_DIR_DST}"
+
+    # install the widget
+    install_wgt "${LAUNCHER_DIR}"
+fi
+
+echo "Done"
diff --git a/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/Documents/tizen_WebAPI_test_dummy b/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/Documents/tizen_WebAPI_test_dummy
new file mode 100755 (executable)
index 0000000..e69de29
diff --git a/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/Downloads/tizen_WebAPI_test_dummy b/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/Downloads/tizen_WebAPI_test_dummy
new file mode 100755 (executable)
index 0000000..e69de29
diff --git a/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/Images/webapi-tizen-messaging-test_image.jpg b/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/Images/webapi-tizen-messaging-test_image.jpg
new file mode 100755 (executable)
index 0000000..7a57964
Binary files /dev/null and b/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/Images/webapi-tizen-messaging-test_image.jpg differ
diff --git a/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/Music/webapi-tizen-messaging-test_noise.mp3 b/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/Music/webapi-tizen-messaging-test_noise.mp3
new file mode 100755 (executable)
index 0000000..d4d1659
Binary files /dev/null and b/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/Music/webapi-tizen-messaging-test_noise.mp3 differ
diff --git a/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/Sounds/tizen_WebAPI_test_dummy b/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/Sounds/tizen_WebAPI_test_dummy
new file mode 100755 (executable)
index 0000000..e69de29
diff --git a/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/Videos/tizen_WebAPI_test_dummy b/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/Videos/tizen_WebAPI_test_dummy
new file mode 100755 (executable)
index 0000000..e69de29
diff --git a/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_audio_default.mp3 b/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_audio_default.mp3
new file mode 100755 (executable)
index 0000000..c41d536
Binary files /dev/null and b/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_audio_default.mp3 differ
diff --git a/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_audio_lyrics.mp3 b/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_audio_lyrics.mp3
new file mode 100755 (executable)
index 0000000..28d6324
Binary files /dev/null and b/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_audio_lyrics.mp3 differ
diff --git a/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_audio_no_tag.mp3 b/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_audio_no_tag.mp3
new file mode 100755 (executable)
index 0000000..7aa44e8
Binary files /dev/null and b/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_audio_no_tag.mp3 differ
diff --git a/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_image_default.jpg b/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_image_default.jpg
new file mode 100755 (executable)
index 0000000..c090428
Binary files /dev/null and b/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_image_default.jpg differ
diff --git a/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_image_geolocation.jpg b/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_image_geolocation.jpg
new file mode 100755 (executable)
index 0000000..6abe1ed
Binary files /dev/null and b/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_image_geolocation.jpg differ
diff --git a/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_image_orientation_1.jpg b/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_image_orientation_1.jpg
new file mode 100755 (executable)
index 0000000..1326236
Binary files /dev/null and b/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_image_orientation_1.jpg differ
diff --git a/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_image_orientation_2.jpg b/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_image_orientation_2.jpg
new file mode 100755 (executable)
index 0000000..d9336b5
Binary files /dev/null and b/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_image_orientation_2.jpg differ
diff --git a/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_image_orientation_3.jpg b/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_image_orientation_3.jpg
new file mode 100755 (executable)
index 0000000..330c088
Binary files /dev/null and b/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_image_orientation_3.jpg differ
diff --git a/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_image_orientation_4.jpg b/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_image_orientation_4.jpg
new file mode 100755 (executable)
index 0000000..8aaed3f
Binary files /dev/null and b/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_image_orientation_4.jpg differ
diff --git a/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_image_orientation_5.jpg b/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_image_orientation_5.jpg
new file mode 100755 (executable)
index 0000000..945a83d
Binary files /dev/null and b/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_image_orientation_5.jpg differ
diff --git a/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_image_orientation_6.jpg b/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_image_orientation_6.jpg
new file mode 100755 (executable)
index 0000000..da8c2c3
Binary files /dev/null and b/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_image_orientation_6.jpg differ
diff --git a/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_image_orientation_7.jpg b/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_image_orientation_7.jpg
new file mode 100755 (executable)
index 0000000..dfa93ca
Binary files /dev/null and b/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_image_orientation_7.jpg differ
diff --git a/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_image_orientation_8.jpg b/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_image_orientation_8.jpg
new file mode 100755 (executable)
index 0000000..6fdd2e8
Binary files /dev/null and b/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_image_orientation_8.jpg differ
diff --git a/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_video.mp4 b/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_video.mp4
new file mode 100755 (executable)
index 0000000..e203ae2
Binary files /dev/null and b/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_video.mp4 differ
diff --git a/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_video_tagged.mp4 b/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_video_tagged.mp4
new file mode 100755 (executable)
index 0000000..a6b7048
Binary files /dev/null and b/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-content-tizen-tests/tct-content-tizen-tests_video_tagged.mp4 differ
diff --git a/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-systemsetting-tizen-tests/tct-systemsetting-tizen-tests_audio.mp3 b/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-systemsetting-tizen-tests/tct-systemsetting-tizen-tests_audio.mp3
new file mode 100755 (executable)
index 0000000..81a860f
Binary files /dev/null and b/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-systemsetting-tizen-tests/tct-systemsetting-tizen-tests_audio.mp3 differ
diff --git a/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-systemsetting-tizen-tests/tct-systemsetting-tizen-tests_image.jpg b/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-systemsetting-tizen-tests/tct-systemsetting-tizen-tests_image.jpg
new file mode 100755 (executable)
index 0000000..68a4019
Binary files /dev/null and b/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct-systemsetting-tizen-tests/tct-systemsetting-tizen-tests_image.jpg differ
diff --git a/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct/preconfigure.js b/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/tct/preconfigure.js
new file mode 100755 (executable)
index 0000000..7a66644
--- /dev/null
@@ -0,0 +1,21 @@
+(function() {
+    var BT_REMOTE_DEVICE_ADDRESS = "00:02:60:00:05:63";
+    var BT_REMOTE_DEVICE_NAME = "Tcthelper";
+    var EMAIL_RECIPIENT_1 = "123@intel.com";
+    var EMAIL_RECIPIENT_2 = "456@intel.com";
+    var MMS_RECIPIENT_1 = "123456789";
+    var MMS_RECIPIENT_2 = "987654321";
+    var SMS_RECIPIENT_1 = "123456789";
+    var SMS_RECIPIENT_2 = "987654321";
+
+    module.exports = {
+        BT_REMOTE_DEVICE_ADDRESS : BT_REMOTE_DEVICE_ADDRESS,
+        BT_REMOTE_DEVICE_NAME : BT_REMOTE_DEVICE_NAME,
+        EMAIL_RECIPIENT_1 : EMAIL_RECIPIENT_1,
+        EMAIL_RECIPIENT_2 : EMAIL_RECIPIENT_2,
+        MMS_RECIPIENT_1 : MMS_RECIPIENT_1,
+        MMS_RECIPIENT_2 : MMS_RECIPIENT_2,
+        SMS_RECIPIENT_1 : SMS_RECIPIENT_1,
+        SMS_RECIPIENT_2 : SMS_RECIPIENT_2
+    };
+})();
diff --git a/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/webapi-tizen-contact-test_image1.png b/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/webapi-tizen-contact-test_image1.png
new file mode 100755 (executable)
index 0000000..59bb774
Binary files /dev/null and b/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/webapi-tizen-contact-test_image1.png differ
diff --git a/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/webapi-tizen-contact-test_image2.png b/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/webapi-tizen-contact-test_image2.png
new file mode 100755 (executable)
index 0000000..4eba09a
Binary files /dev/null and b/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/webapi-tizen-contact-test_image2.png differ
diff --git a/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/webapi-tizen-contact-test_ring1.mp3 b/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/webapi-tizen-contact-test_ring1.mp3
new file mode 100755 (executable)
index 0000000..81a860f
Binary files /dev/null and b/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/webapi-tizen-contact-test_ring1.mp3 differ
diff --git a/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/webapi-tizen-contact-test_ring2.mp3 b/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/webapi-tizen-contact-test_ring2.mp3
new file mode 100755 (executable)
index 0000000..d4d1659
Binary files /dev/null and b/webWidgetTCT_device/tools/launcher/tct/copy/opt/usr/media/webapi-tizen-contact-test_ring2.mp3 differ
diff --git a/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/appcontrol_exit.html b/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/appcontrol_exit.html
new file mode 100755 (executable)
index 0000000..9e980f5
--- /dev/null
@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+
+<!--
+
+Copyright (c) 2013 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+
+
+Authors:
+        Junghyuk Park <junghyuk.park@samsung.com>
+
+
+-->
+
+<html>
+<head>
+<meta charset="utf-8" />
+<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
+<meta name="description" content="tct-application-tizen-tests"/>
+
+<title>TCTAppControl</title>
+
+    <link rel="stylesheet" type="text/css" href="css/style.css"/>
+</head>
+
+<body>
+<header>
+    <hgroup>
+      <h1>TCTAppControl</h1>
+      <h2>appcontrol_exit.html</h2>
+      <h3 id="info"></h3>
+    </hgroup>
+</header>
+
+<script type="text/javascript">
+var application, request, timeout = 1000;
+
+application = tizen.application.getCurrentApplication();
+request = application.getRequestedAppControl();
+
+if (request) {
+    if (request.appControl.data[0].key === "timeout") {
+        timeout = parseInt(request.appControl.data[0].value[0]);
+    }
+
+    request.replyResult();
+
+    setTimeout(function () {
+        application.exit();
+    }, timeout);
+
+} else  {
+    document.getElementById("info").innerHTML="RequestedAppControl not found";
+}
+
+</script>
+</body>
+</html>
diff --git a/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/appcontrol_launch.html b/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/appcontrol_launch.html
new file mode 100755 (executable)
index 0000000..8013411
--- /dev/null
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+
+<!--
+
+Copyright (c) 2013 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+
+
+Authors:
+            Junghyuk Park <junghyuk.park@samsung.com>
+
+
+-->
+
+<html>
+<head>
+    <meta charset="utf-8" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
+    <meta name="description" content="tct-application-tizen-tests"/>
+
+    <title>TCTAppControl</title>
+
+    <link rel="stylesheet" type="text/css" href="css/style.css"/>
+</head>
+
+<body>
+  <header>
+    <hgroup>
+      <h1>TCTAppControl</h1>
+      <h2>appcontrol_launch.html</h2>
+    </hgroup>
+  </header>
+</body>
+</html>
diff --git a/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/appcontrol_launch_explicit.html b/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/appcontrol_launch_explicit.html
new file mode 100755 (executable)
index 0000000..8013411
--- /dev/null
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+
+<!--
+
+Copyright (c) 2013 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+
+
+Authors:
+            Junghyuk Park <junghyuk.park@samsung.com>
+
+
+-->
+
+<html>
+<head>
+    <meta charset="utf-8" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
+    <meta name="description" content="tct-application-tizen-tests"/>
+
+    <title>TCTAppControl</title>
+
+    <link rel="stylesheet" type="text/css" href="css/style.css"/>
+</head>
+
+<body>
+  <header>
+    <hgroup>
+      <h1>TCTAppControl</h1>
+      <h2>appcontrol_launch.html</h2>
+    </hgroup>
+  </header>
+</body>
+</html>
diff --git a/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/appcontrol_reply_failure.html b/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/appcontrol_reply_failure.html
new file mode 100755 (executable)
index 0000000..bd4d597
--- /dev/null
@@ -0,0 +1,77 @@
+<!DOCTYPE html>
+
+<!--
+
+Copyright (c) 2013 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+
+
+Authors:
+            Junghyuk Park <junghyuk.park@samsung.com>
+
+
+-->
+
+<html>
+<head>
+    <meta charset="utf-8" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
+    <meta name="description" content="tct-application-tizen-tests"/>
+
+    <title>TCTAppControl</title>
+
+    <link rel="stylesheet" type="text/css" href="css/style.css"/>
+</head>
+
+<body>
+  <header>
+    <hgroup>
+      <h1>TCTAppControl</h1>
+      <h2>appcontrol_reply_failure.html</h2>
+      <h3 id="info"></h3>
+    </hgroup>
+  </header>
+
+<script type="text/javascript">
+    var application, request, dataArray, tests = {};
+
+    tests["RequestedApplicationControl_replyFailure"] = function (request) {
+        request.replyFailure();
+    };
+
+    // check only null because not able to invoke replyFailure() multiple times
+    tests["RequestedApplicationControl_replyFailure_extra_argument"] = function (request) {
+        request.replyFailure(null);
+    };
+
+    application = tizen.application.getCurrentApplication();
+    request = application.getRequestedAppControl();
+
+    if (request) {
+        dataArray = request.appControl.data;
+
+        if (dataArray.length > 0 && dataArray[0].key === "testName") {
+            tests[dataArray[0].value[0]](request);
+        } else {
+            request.replyFailure();
+        }
+    } else  {
+        document.getElementById("info").innerHTML="RequestedAppControl not found";
+    }
+
+</script>  
+
+</body>
+</html>
diff --git a/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/appcontrol_reply_result.html b/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/appcontrol_reply_result.html
new file mode 100755 (executable)
index 0000000..c1374c8
--- /dev/null
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+
+<!--
+
+Copyright (c) 2013 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+
+
+Authors:
+            Junghyuk Park <junghyuk.park@samsung.com>
+
+
+-->
+
+<html>
+<head>
+    <meta charset="utf-8" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
+    <meta name="description" content="tct-application-tizen-tests"/>
+
+    <title>TCTAppControl</title>
+
+    <link rel="stylesheet" type="text/css" href="css/style.css"/>
+</head>
+
+<body>
+  <header>
+    <hgroup>
+      <h1>TCTAppControl</h1>
+      <h2>appcontrol_reply_result.html</h2>
+      <h3 id="info"></h3>
+    </hgroup>
+  </header>
+
+<script type="text/javascript">
+    var application, request;
+    application = tizen.application.getCurrentApplication();
+    request = application.getRequestedAppControl();
+
+    if (request) {
+        request.replyResult();
+    } else  {
+        document.getElementById("info").innerHTML="RequestedAppControl not found";
+    }
+</script>  
+
+</body>
+</html>
diff --git a/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/appcontrol_reply_result_with_data.html b/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/appcontrol_reply_result_with_data.html
new file mode 100755 (executable)
index 0000000..839e943
--- /dev/null
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+
+<!--
+
+Copyright (c) 2013 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+
+
+Authors:
+            Junghyuk Park <junghyuk.park@samsung.com>
+
+
+-->
+
+<html>
+<head>
+    <meta charset="utf-8" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
+    <meta name="description" content="tct-application-tizen-tests"/>
+
+    <title>TCTAppControl</title>
+
+    <link rel="stylesheet" type="text/css" href="css/style.css"/>
+</head>
+
+<body>
+  <header>
+    <hgroup>
+      <h1>TCTAppControl</h1>
+      <h2>appcontrol_reply_result_with_data.html</h2>
+      <h3 id="info"></h3>
+    </hgroup>
+  </header>
+
+<script type="text/javascript">
+    var application, request;
+    application = tizen.application.getCurrentApplication();
+    request = application.getRequestedAppControl();
+
+    if (request) {
+        request.replyResult(request.appControl.data);
+    } else  {
+        document.getElementById("info").innerHTML="RequestedAppControl not found";
+    }
+</script>  
+
+</body>
+</html>
diff --git a/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/appcontrol_run_test.html b/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/appcontrol_run_test.html
new file mode 100755 (executable)
index 0000000..eecbabc
--- /dev/null
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+
+<!--
+
+Copyright (c) 2013 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+
+
+Authors:
+            Junghyuk Park <junghyuk.park@samsung.com>
+
+
+-->
+
+<html>
+<head>
+    <meta charset="utf-8" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
+    <meta name="description" content="tct-application-tizen-tests"/>
+
+    <title>appcontrol_run_test</title>
+
+    <link rel="stylesheet" type="text/css" href="css/style.css"/>
+    <script src="resources/testharness.js"></script>
+    <script src="resources/testharnessreport.js"></script>
+    <script src="resources/unitcommon.js"></script>
+</head>
+
+<body>
+<div id="log"></div>
+<script type="text/javascript">
+
+var application, requestedAppControl, testName, resultData;
+
+add_result_callback(function (result) {
+    resultData = [
+        new tizen.ApplicationControlData("status", [result.status]),
+        new tizen.ApplicationControlData("message", [result.message])
+    ];
+
+    requestedAppControl.replyResult(resultData);
+});
+
+application = tizen.application.getCurrentApplication();
+requestedAppControl = application.getRequestedAppControl();
+testName = requestedAppControl.appControl.uri.substring("tct://".length);
+
+document.write("<script language=\"javascript\" src=\"tests/" + testName + ".js\"><\/script>");
+</script>
+</body>
+</html>
diff --git a/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/config.xml b/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/config.xml
new file mode 100755 (executable)
index 0000000..019cd55
--- /dev/null
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<widget xmlns="http://www.w3.org/ns/widgets" xmlns:tizen="http://tizen.org/ns/widgets" id="http://tizen.org/TCTAppControl" version="1.0.0" viewmodes="maximized">
+    <access origin="*" subdomains="true"/>
+    <tizen:app-control>
+        <tizen:src name="appcontrol_launch.html"/>
+        <tizen:operation name="http://tizen.org/appcontrol/operation/tct/launch"/>
+    </tizen:app-control>
+    <tizen:app-control>
+        <tizen:src name="appcontrol_launch.html"/>
+        <tizen:operation name="http://tizen.org/appcontrol/operation/tct/launch"/>
+        <tizen:uri name="tct"/>
+    </tizen:app-control>
+    <tizen:app-control>
+        <tizen:src name="appcontrol_launch.html"/>
+        <tizen:operation name="http://tizen.org/appcontrol/operation/tct/launch"/>
+        <tizen:mime name="text/html"/>
+    </tizen:app-control>
+    <tizen:app-control>
+        <tizen:src name="appcontrol_launch.html"/>
+        <tizen:operation name="http://tizen.org/appcontrol/operation/tct/launch"/>
+        <tizen:uri name="tct"/>
+        <tizen:mime name="text/html"/>
+    </tizen:app-control>
+    <tizen:app-control>
+        <tizen:src name="appcontrol_launch_explicit.html"/>
+        <tizen:operation name="http://tizen.org/appcontrol/operation/tct/launch/explicit"/>
+        <tizen:uri name="tct"/>
+        <tizen:mime name="text/html"/>
+    </tizen:app-control>
+    <tizen:app-control>
+        <tizen:src name="appcontrol_reply_result.html"/>
+        <tizen:operation name="http://tizen.org/appcontrol/operation/tct/reply_result"/>
+    </tizen:app-control>
+    <tizen:app-control>
+        <tizen:src name="appcontrol_reply_result_with_data.html"/>
+        <tizen:operation name="http://tizen.org/appcontrol/operation/tct/reply_result/data"/>
+    </tizen:app-control>
+    <tizen:app-control>
+        <tizen:src name="appcontrol_reply_failure.html"/>
+        <tizen:operation name="http://tizen.org/appcontrol/operation/tct/reply_failure"/>
+    </tizen:app-control>
+    <tizen:app-control>
+        <tizen:src name="appcontrol_run_test.html"/>
+        <tizen:operation name="http://tizen.org/appcontrol/operation/tct/run_test"/>
+        <tizen:uri name="tct"/>
+        <tizen:mime name="application/javascript"/>
+    </tizen:app-control>
+    <tizen:app-control>
+        <tizen:src name="appcontrol_exit.html"/>
+        <tizen:operation name="http://tizen.org/appcontrol/operation/tct/exit"/>
+    </tizen:app-control>
+    <tizen:application id="api1appli1.TCTAppControl" package="api1appli1" required_version="3.0"/>
+    <content src="index.html"/>
+    <icon src="icon.png"/>
+    <name>TCTAppControl</name>
+    <tizen:metadata key="testKey1" value="testValue1"/>
+    <tizen:metadata key="testKey2" value="testValue2"/>
+    <tizen:setting screen-orientation="landscape" background-support="enable"/>
+</widget>
diff --git a/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/css/style.css b/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/css/style.css
new file mode 100755 (executable)
index 0000000..63e4bfb
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+
+Copyright (c) 2013 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+
+
+Authors:
+            Junghyuk Park <junghyuk.park@samsung.com>
+
+
+*/
+
+* {
+    font-family: Lucida Sans, Arial, Helvetica, sans-serif;
+}
+
+body {
+    margin: 0px auto;
+}
+
+header h1 {
+    font-size: 36px;
+    margin: 0px;
+}
+
+header h2 {
+    font-size: 18px;
+    margin: 0px;
+    color: #888;
+    font-style: italic;
+}
+
+nav ul {
+    list-style: none;
+    padding: 0px;
+    display: block;
+    clear: right;
+    background-color: #666;
+    padding-left: 4px;
+    height: 24px;
+}
+
+nav ul li {
+    display: inline;
+    padding: 0px 20px 5px 10px;
+    height: 24px;
+    border-right: 1px solid #ccc;
+}
+
+nav ul li a {
+    color: #EFD3D3;
+    text-decoration: none;
+    font-size: 13px;
+    font-weight: bold;
+}
+
+nav ul li a:hover {
+    color: #fff;
+}
+
+article > header h1 {
+    font-size: 20px;
+    margin-left: 14px;
+}
+
+article > header h1 a {
+    color: #993333;
+}
+
+article > header h1 img {
+    vertical-align:middle;
+}
+
+article > section header h1 {
+    font-size: 16px;
+}
+
+article p {
+    clear: both;
+}
+
+footer p {
+    text-align: center;
+    font-size: 12px;
+    color: #888;
+    margin-top: 24px;
+}
diff --git a/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/icon.png b/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/icon.png
new file mode 100755 (executable)
index 0000000..c22cfa8
Binary files /dev/null and b/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/icon.png differ
diff --git a/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/index.html b/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/index.html
new file mode 100755 (executable)
index 0000000..b01c436
--- /dev/null
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+
+<!--
+
+Copyright (c) 2013 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+
+
+Authors:
+            Junghyuk Park <junghyuk.park@samsung.com>
+
+
+-->
+
+<html>
+<head>
+    <meta charset="utf-8" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
+    <meta name="description" content="tct-application-tizen-tests"/>
+
+    <title>TCTAppControl</title>
+
+    <link rel="stylesheet" type="text/css" href="css/style.css"/>
+</head>
+
+<body>
+  <header>
+    <hgroup>
+      <h1>TCTAppControl</h1>
+      <h2>index.html</h2>
+    </hgroup>
+  </header>
+</body>
+</html>
diff --git a/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/resources/COPYING b/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/resources/COPYING
new file mode 100755 (executable)
index 0000000..bd84625
--- /dev/null
@@ -0,0 +1,12 @@
+All test files under this folder except COPYING, Makefile.am and blacklist.* come from
+https://github.com/w3c/testharness.js (commit 81649066b179216eed02dfb58f631eb8bb6c7629)
+without any modification besides the necessary adjustment on reference path to test harness
+
+These tests are copyright by W3C and/or the author listed in the test
+file. The tests are dual-licensed under the W3C Test Suite License:
+http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+and the BSD 3-clause License:
+http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+under W3C's test suite licensing policy:
+http://www.w3.org/Consortium/Legal/2008/04-testsuite-copyright
+
diff --git a/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/resources/blacklist.clamshell b/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/resources/blacklist.clamshell
new file mode 100755 (executable)
index 0000000..b5bf744
--- /dev/null
@@ -0,0 +1,113 @@
+/* Clamshell does not support methods, the list format:  interface.method */
+
+var not_support_list = [
+       "Application.launch",
+       "Application.kill",
+       "Application.exit",
+       "Application.launchService",
+       "Application.getApplicationService",
+       "Application.getCurrentApplicationContext",
+       "Application.getApplicationsInformation",
+       "Application.addApplicationInformationEventListener",
+       "Application.removeApplicationInformationEventListener",
+
+       /*  Bluetooth */
+       "BluetoothManager.getDefaultAdapter",
+       "BluetoothAdapter.setName",
+       "BluetoothAdapter.setPowered",
+       "BluetoothAdapter.setVisible",
+       "BluetoothAdapter.discoverDevices",
+       "BluetoothAdapter.stopDiscovery",
+       "BluetoothAdapter.getKnownDevices",
+       "BluetoothAdapter.getDevice",
+       "BluetoothAdapter.createBonding",
+       "BluetoothAdapter.destroyBonding",
+       "BluetoothAdapter.registerRFCOMMServiceByUUID",
+       "BluetoothDevice.connectToServiceByUUID",
+       "BluetoothServiceHandler.unregister",
+
+       /* Time */
+       "TimeUtil.getCurrentDateTime",
+       "TimeUtil.setCurrentDateTime",
+       "TimeUtil.getLocalTimezone",
+       "TimeUtil.getAvailableTimezones",
+       "TimeUtil.getDateFormat",
+       "TimeUtil.getTimeFormat",
+       "TimeUtil.isLeapYear",
+       "TZDate.getTimezoneAbbreviation",
+       "TZDate.secondsFromUTC",
+       "TZDate.isDST",
+       "TZDate.getPreviousDSTTransition",
+       "TZDate.getNextDSTTransition",
+
+       /* Call */
+       "CallHistory.Find",
+       "CallHistory.Remove",
+       "CallHistory.removeBatch",
+       "CallHistory.removeAll",
+       "CallHistory.deleteRecording",
+       "CallHistory.addListener",
+       "CallHistory.removeListener",
+
+       /* Calendar */
+       "CalendarManager.getCalendars",
+       "Calendar.add",
+       "Calendar.addBatch",
+       "Calendar.update",
+       "Calendar.updateBatch",
+       "Calendar.remove",
+       "Calendar.removeBatch",
+       "Calendar.find",
+       "Calendar.addChangeListener",
+       "Calendar.removeChangeListener",
+       "CalendarEvent.expandRecurrence",
+
+       /* Contact */
+       "AddressBook.Add",
+       "AddressBook.addBatch",
+       "AddressBook.update",
+       "AddressBook.updateBatch",
+       "AddressBook.remove",
+       "AddressBook.removeBatch",
+       "AddressBook.find",
+       "AddressBook.addChangeListener",
+       "Contact.convertToString",
+
+       /* Filesystem */
+       "FileSystemManager.Resolve",
+       "FileSystemManager.getStorage",
+       "FileSystemManager.listStorages",
+       "FileSystemManager.addStorageStateChangeListener",
+       "File.toURI",
+       "File.listFiles",
+       "File.openStream",
+       "File.readAsText",
+       "File.copyTo",
+       "File.moveTo",
+       "File.deleteDirectory",
+       "File.deleteFile",
+
+       /* Messaging */
+       "MessageService.sendMessage",
+       "MessageStorage.addDraftMessage",
+       "MessageStorage.findMessages",
+       "MessageStorage.removeMessages",
+       "MessageStorage.updateMessages",
+       "MessageStorage.findConversations",
+       "MessageStorage.removeConversations",
+       "MessageStorage.findFolders",
+       "MessageStorage.addMessagesChangeListener",
+       "MessageStorage.addConversationsChangeListener",
+       "MessageStorage.addFoldersChangeListener",
+       "MessageStorage.removeChangeListener",
+
+       /* POI */
+       "POIProvider.remove",
+
+       /* Media-Capture */
+       "capture",
+
+       /* Vibration */
+       "Vibration"
+];
+
diff --git a/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/resources/blacklist.default b/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/resources/blacklist.default
new file mode 100755 (executable)
index 0000000..4670187
--- /dev/null
@@ -0,0 +1,5 @@
+/* default blacklist.js, just a placeholder:  interface.method */
+
+var not_support_list = [
+];
+
diff --git a/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/resources/blacklist.js b/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/resources/blacklist.js
new file mode 100755 (executable)
index 0000000..4670187
--- /dev/null
@@ -0,0 +1,5 @@
+/* default blacklist.js, just a placeholder:  interface.method */
+
+var not_support_list = [
+];
+
diff --git a/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/resources/testharness.css b/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/resources/testharness.css
new file mode 100755 (executable)
index 0000000..365084f
--- /dev/null
@@ -0,0 +1,92 @@
+html {
+    font-family:DejaVu Sans, Bitstream Vera Sans, Arial, Sans;
+}
+
+#log .warning,
+#log .warning a {
+  color: black;
+  background: yellow;
+}
+
+#log .error,
+#log .error a {
+  color: white;
+  background: red;
+}
+
+#log pre {
+  border: 1px solid black;
+  padding: 1em;
+}
+
+section#summary {
+    margin-bottom:1em;
+}
+
+table#results {
+    border-collapse:collapse;
+    table-layout:fixed;
+    width:100%;
+}
+
+table#results th:first-child,
+table#results td:first-child {
+    width:4em;
+}
+
+table#results th:last-child,
+table#results td:last-child {
+    width:50%;
+}
+
+table#results.assertions th:last-child,
+table#results.assertions td:last-child {
+    width:35%;
+}
+
+table#results th {
+    padding:0;
+    padding-bottom:0.5em;
+    border-bottom:medium solid black;
+}
+
+table#results td {
+    padding:1em;
+    padding-bottom:0.5em;
+    border-bottom:thin solid black;
+}
+
+tr.pass > td:first-child {
+    color:green;
+}
+
+tr.fail > td:first-child {
+    color:red;
+}
+
+tr.timeout > td:first-child {
+    color:red;
+}
+
+tr.notrun > td:first-child {
+    color:blue;
+}
+
+.pass > td:first-child, .fail > td:first-child, .timeout > td:first-child, .notrun > td:first-child {
+    font-variant:small-caps;
+}
+
+table#results span {
+    display:block;
+}
+
+table#results span.expected {
+    font-family:DejaVu Sans Mono, Bitstream Vera Sans Mono, Monospace;
+    white-space:pre;
+}
+
+table#results span.actual {
+    font-family:DejaVu Sans Mono, Bitstream Vera Sans Mono, Monospace;
+    white-space:pre;
+}
+
diff --git a/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/resources/testharness.js b/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/resources/testharness.js
new file mode 100755 (executable)
index 0000000..69acd7f
--- /dev/null
@@ -0,0 +1,2237 @@
+/*
+Distributed under both the W3C Test Suite License [1] and the W3C
+3-clause BSD License [2]. To contribute to a W3C Test Suite, see the
+policies and contribution forms [3].
+
+[1] http://www.w3.org/Consortium/Legal/2008/04-testsuite-license
+[2] http://www.w3.org/Consortium/Legal/2008/03-bsd-license
+[3] http://www.w3.org/2004/10/27-testcases
+*/
+
+/*
+ * == Introduction ==
+ *
+ * This file provides a framework for writing testcases. It is intended to
+ * provide a convenient API for making common assertions, and to work both
+ * for testing synchronous and asynchronous DOM features in a way that
+ * promotes clear, robust, tests.
+ *
+ * == Basic Usage ==
+ *
+ * To use this file, import the script and the testharnessreport script into
+ * the test document:
+ * <script src="/resources/testharness.js"></script>
+ * <script src="/resources/testharnessreport.js"></script>
+ *
+ * Within each file one may define one or more tests. Each test is atomic
+ * in the sense that a single test has a single result (pass/fail/timeout).
+ * Within each test one may have a number of asserts. The test fails at the
+ * first failing assert, and the remainder of the test is (typically) not run.
+ *
+ * If the file containing the tests is a HTML file with an element of id "log"
+ * this will be populated with a table containing the test results after all
+ * the tests have run.
+ *
+ * NOTE: By default tests must be created before the load event fires. For ways
+ *       to create tests after the load event, see "Determining when all tests
+ *       are complete", below
+ *
+ * == Synchronous Tests ==
+ *
+ * To create a synchronous test use the test() function:
+ *
+ * test(test_function, name, properties)
+ *
+ * test_function is a function that contains the code to test. For example a
+ * trivial passing test would be:
+ *
+ * test(function() {assert_true(true)}, "assert_true with true")
+ *
+ * The function passed in is run in the test() call.
+ *
+ * properties is an object that overrides default test properties. The
+ * recognised properties are:
+ *    timeout - the test timeout in ms
+ *
+ * e.g.
+ * test(test_function, "Sample test", {timeout:1000})
+ *
+ * would run test_function with a timeout of 1s.
+ *
+ * Additionally, test-specific metadata can be passed in the properties. These
+ * are used when the individual test has different metadata from that stored 
+ * in the <head>.
+ * The recognized metadata properties are:
+ *
+ *    help - The url of the part of the specification being tested
+ *
+ *    assert - A human readable description of what the test is attempting 
+ *             to prove
+ *
+ *    author - Name and contact information for the author of the test in the
+ *             format: "Name <email_addr>" or "Name http://contact/url"
+ *
+ * == Asynchronous Tests ==
+ *
+ * Testing asynchronous features is somewhat more complex since the result of
+ * a test may depend on one or more events or other callbacks. The API provided
+ * for testing these features is indended to be rather low-level but hopefully
+ * applicable to many situations.
+ *
+ * To create a test, one starts by getting a Test object using async_test:
+ *
+ * async_test(name, properties)
+ *
+ * e.g.
+ * var t = async_test("Simple async test")
+ *
+ * Assertions can be added to the test by calling the step method of the test
+ * object with a function containing the test assertions:
+ *
+ * t.step(function() {assert_true(true)});
+ *
+ * When all the steps are complete, the done() method must be called:
+ *
+ * t.done();
+ *
+ * As a convenience, async_test can also takes a function as first argument.
+ * This function is called with the test object as both its `this` object and
+ * first argument. The above example can be rewritten as:
+ *
+ * async_test(function(t) {
+ *     object.some_event = function() {
+ *         t.step(function (){assert_true(true); t.done();});
+ *     };
+ * }, "Simple async test");
+ *
+ * which avoids cluttering the global scope with references to async
+ * tests instances.
+ *
+ * The properties argument is identical to that for test().
+ *
+ * In many cases it is convenient to run a step in response to an event or a
+ * callback. A convenient method of doing this is through the step_func method
+ * which returns a function that, when called runs a test step. For example
+ *
+ * object.some_event = t.step_func(function(e) {assert_true(e.a)});
+ *
+ * == Making assertions ==
+ *
+ * Functions for making assertions start assert_
+ * The best way to get a list is to look in this file for functions names
+ * matching that pattern. The general signature is
+ *
+ * assert_something(actual, expected, description)
+ *
+ * although not all assertions precisely match this pattern e.g. assert_true
+ * only takes actual and description as arguments.
+ *
+ * The description parameter is used to present more useful error messages when
+ * a test fails
+ *
+ * NOTE: All asserts must be located in a test() or a step of an async_test().
+ *       asserts outside these places won't be detected correctly by the harness
+ *       and may cause a file to stop testing.
+ *
+ * == Setup ==
+ *
+ * Sometimes tests require non-trivial setup that may fail. For this purpose
+ * there is a setup() function, that may be called with one or two arguments.
+ * The two argument version is:
+ *
+ * setup(func, properties)
+ *
+ * The one argument versions may omit either argument.
+ * func is a function to be run synchronously. setup() becomes a no-op once
+ * any tests have returned results. Properties are global properties of the test
+ * harness. Currently recognised properties are:
+ *
+ * timeout - The time in ms after which the harness should stop waiting for
+ *           tests to complete (this is different to the per-test timeout
+ *           because async tests do not start their timer until .step is called)
+ *
+ * explicit_done - Wait for an explicit call to done() before declaring all
+ *                 tests complete (see below)
+ *
+ * output_document - The document to which results should be logged. By default
+ *                   this is the current document but could be an ancestor
+ *                   document in some cases e.g. a SVG test loaded in an HTML
+ *                   wrapper
+ *
+ * explicit_timeout - disable file timeout; only stop waiting for results
+ *                    when the timeout() function is called (typically for
+ *                    use when integrating with some existing test framework
+ *                    that has its own timeout mechanism).
+ *
+ * == Determining when all tests are complete ==
+ *
+ * By default the test harness will assume there are no more results to come
+ * when:
+ * 1) There are no Test objects that have been created but not completed
+ * 2) The load event on the document has fired
+ *
+ * This behaviour can be overridden by setting the explicit_done property to
+ * true in a call to setup(). If explicit_done is true, the test harness will
+ * not assume it is done until the global done() function is called. Once done()
+ * is called, the two conditions above apply like normal.
+ *
+ * == Generating tests ==
+ *
+ * NOTE: this functionality may be removed
+ *
+ * There are scenarios in which is is desirable to create a large number of
+ * (synchronous) tests that are internally similar but vary in the parameters
+ * used. To make this easier, the generate_tests function allows a single
+ * function to be called with each set of parameters in a list:
+ *
+ * generate_tests(test_function, parameter_lists, properties)
+ *
+ * For example:
+ *
+ * generate_tests(assert_equals, [
+ *     ["Sum one and one", 1+1, 2],
+ *     ["Sum one and zero", 1+0, 1]
+ *     ])
+ *
+ * Is equivalent to:
+ *
+ * test(function() {assert_equals(1+1, 2)}, "Sum one and one")
+ * test(function() {assert_equals(1+0, 1)}, "Sum one and zero")
+ *
+ * Note that the first item in each parameter list corresponds to the name of
+ * the test.
+ *
+ * The properties argument is identical to that for test(). This may be a 
+ * single object (used for all generated tests) or an array.
+ *
+ * == Callback API ==
+ *
+ * The framework provides callbacks corresponding to 3 events:
+ *
+ * start - happens when the first Test is created
+ * result - happens when a test result is recieved
+ * complete - happens when all results are recieved
+ *
+ * The page defining the tests may add callbacks for these events by calling
+ * the following methods:
+ *
+ *   add_start_callback(callback) - callback called with no arguments
+ *   add_result_callback(callback) - callback called with a test argument
+ *   add_completion_callback(callback) - callback called with an array of tests
+ *                                       and an status object
+ *
+ * tests have the following properties:
+ *   status: A status code. This can be compared to the PASS, FAIL, TIMEOUT and
+ *           NOTRUN properties on the test object
+ *   message: A message indicating the reason for failure. In the future this
+ *            will always be a string
+ *
+ *  The status object gives the overall status of the harness. It has the
+ *  following properties:
+ *    status: Can be compared to the OK, ERROR and TIMEOUT properties
+ *    message: An error message set when the status is ERROR
+ *
+ * == External API ==
+ *
+ * In order to collect the results of multiple pages containing tests, the test
+ * harness will, when loaded in a nested browsing context, attempt to call
+ * certain functions in each ancestor and opener browsing context:
+ *
+ * start - start_callback
+ * result - result_callback
+ * complete - completion_callback
+ *
+ * These are given the same arguments as the corresponding internal callbacks
+ * described above.
+ *
+ * == External API through cross-document messaging ==
+ *
+ * Where supported, the test harness will also send messages using
+ * cross-document messaging to each ancestor and opener browsing context. Since
+ * it uses the wildcard keyword (*), cross-origin communication is enabled and
+ * script on different origins can collect the results.
+ *
+ * This API follows similar conventions as those described above only slightly
+ * modified to accommodate message event API. Each message is sent by the harness
+ * is passed a single vanilla object, available as the `data` property of the
+ * event object. These objects are structures as follows:
+ *
+ * start - { type: "start" }
+ * result - { type: "result", test: Test }
+ * complete - { type: "complete", tests: [Test, ...], status: TestsStatus }
+ *
+ * == List of assertions ==
+ *
+ * assert_true(actual, description)
+ *   asserts that /actual/ is strictly true
+ *
+ * assert_false(actual, description)
+ *   asserts that /actual/ is strictly false
+ *
+ * assert_equals(actual, expected, description)
+ *   asserts that /actual/ is the same value as /expected/
+ *
+ * assert_not_equals(actual, expected, description)
+ *   asserts that /actual/ is a different value to /expected/. Yes, this means
+ *   that "expected" is a misnomer
+ *
+ * assert_in_array(actual, expected, description)
+ *   asserts that /expected/ is an Array, and /actual/ is equal to one of the
+ *   members -- expected.indexOf(actual) != -1
+ *
+ * assert_array_equals(actual, expected, description)
+ *   asserts that /actual/ and /expected/ have the same length and the value of
+ *   each indexed property in /actual/ is the strictly equal to the corresponding
+ *   property value in /expected/
+ *
+ * assert_approx_equals(actual, expected, epsilon, description)
+ *   asserts that /actual/ is a number within +/- /epsilon/ of /expected/
+ *
+ * assert_less_than(actual, expected, description)
+ *   asserts that /actual/ is a number less than /expected/
+ *
+ * assert_greater_than(actual, expected, description)
+ *   asserts that /actual/ is a number greater than /expected/
+ *
+ * assert_less_than_equal(actual, expected, description)
+ *   asserts that /actual/ is a number less than or equal to /expected/
+ *
+ * assert_greater_than_equal(actual, expected, description)
+ *   asserts that /actual/ is a number greater than or equal to /expected/
+ *
+ * assert_regexp_match(actual, expected, description)
+ *   asserts that /actual/ matches the regexp /expected/
+ *
+ * assert_class_string(object, class_name, description)
+ *   asserts that the class string of /object/ as returned in
+ *   Object.prototype.toString is equal to /class_name/.
+ *
+ * assert_own_property(object, property_name, description)
+ *   assert that object has own property property_name
+ *
+ * assert_inherits(object, property_name, description)
+ *   assert that object does not have an own property named property_name
+ *   but that property_name is present in the prototype chain for object
+ *
+ * assert_idl_attribute(object, attribute_name, description)
+ *   assert that an object that is an instance of some interface has the
+ *   attribute attribute_name following the conditions specified by WebIDL
+ *
+ * assert_readonly(object, property_name, description)
+ *   assert that property property_name on object is readonly
+ *
+ * assert_throws(code, func, description)
+ *   code - the expected exception:
+ *     o string: the thrown exception must be a DOMException with the given
+ *               name, e.g., "TimeoutError" (for compatibility with existing
+ *               tests, a constant is also supported, e.g., "TIMEOUT_ERR")
+ *     o object: the thrown exception must have a property called "name" that
+ *               matches code.name
+ *     o null:   allow any exception (in general, one of the options above
+ *               should be used)
+ *   func - a function that should throw
+ *
+ * assert_unreached(description)
+ *   asserts if called. Used to ensure that some codepath is *not* taken e.g.
+ *   an event does not fire.
+ *
+ * assert_any(assert_func, actual, expected_array, extra_arg_1, ... extra_arg_N)
+ *   asserts that one assert_func(actual, expected_array_N, extra_arg1, ..., extra_arg_N)
+ *   is true for some expected_array_N in expected_array. This only works for assert_func
+ *   with signature assert_func(actual, expected, args_1, ..., args_N). Note that tests
+ *   with multiple allowed pass conditions are bad practice unless the spec specifically
+ *   allows multiple behaviours. Test authors should not use this method simply to hide 
+ *   UA bugs.
+ *
+ * assert_exists(object, property_name, description)
+ *   *** deprecated ***
+ *   asserts that object has an own property property_name
+ *
+ * assert_not_exists(object, property_name, description)
+ *   *** deprecated ***
+ *   assert that object does not have own property property_name
+ */
+
+(function ()
+{
+    var debug = false;
+    // default timeout is 5 seconds, test can override if needed
+    var settings = {
+      output:true,
+      timeout:5000,
+      test_timeout:2000
+    };
+
+    var xhtml_ns = "http://www.w3.org/1999/xhtml";
+
+    // script_prefix is used by Output.prototype.show_results() to figure out
+    // where to get testharness.css from.  It's enclosed in an extra closure to
+    // not pollute the library's namespace with variables like "src".
+    var script_prefix = null;
+    (function ()
+    {
+        var scripts = document.getElementsByTagName("script");
+        for (var i = 0; i < scripts.length; i++)
+        {
+            if (scripts[i].src)
+            {
+                var src = scripts[i].src;
+            }
+            else if (scripts[i].href)
+            {
+                //SVG case
+                var src = scripts[i].href.baseVal;
+            }
+            if (src && src.slice(src.length - "testharness.js".length) === "testharness.js")
+            {
+                script_prefix = src.slice(0, src.length - "testharness.js".length);
+                break;
+            }
+        }
+    })();
+
+    /*
+     * API functions
+     */
+
+    var name_counter = 0;
+    function next_default_name()
+    {
+        //Don't use document.title to work around an Opera bug in XHTML documents
+        var prefix = document.getElementsByTagName("title").length > 0 ?
+                         document.getElementsByTagName("title")[0].firstChild.data :
+                         "Untitled";
+        var suffix = name_counter > 0 ? " " + name_counter : "";
+        name_counter++;
+        return prefix + suffix;
+    }
+
+    function test(func, name, properties)
+    {
+        var test_name = name ? name : next_default_name();
+        properties = properties ? properties : {};
+        var test_obj = new Test(test_name, properties);
+        test_obj.step(func);
+        if (test_obj.status === test_obj.NOTRUN) {
+            test_obj.done();
+        }
+    }
+
+    function async_test(func, name, properties)
+    {
+        if (typeof func !== "function") {
+            properties = name;
+            name = func;
+            func = null;
+        }
+        var test_name = name ? name : next_default_name();
+        properties = properties ? properties : {};
+        var test_obj = new Test(test_name, properties);
+        if (func) {
+            test_obj.step(func, test_obj, test_obj);
+        }
+        return test_obj;
+    }
+
+    function setup(func_or_properties, maybe_properties)
+    {
+        var func = null;
+        var properties = {};
+        if (arguments.length === 2) {
+            func = func_or_properties;
+            properties = maybe_properties;
+        } else if (func_or_properties instanceof Function){
+            func = func_or_properties;
+        } else {
+            properties = func_or_properties;
+        }
+        tests.setup(func, properties);
+        output.setup(properties);
+    }
+
+    function done() {
+        tests.end_wait();
+    }
+
+    function generate_tests(func, args, properties) {
+        forEach(args, function(x, i)
+                {
+                    var name = x[0];
+                    test(function()
+                         {
+                             func.apply(this, x.slice(1));
+                         }, 
+                         name, 
+                         Array.isArray(properties) ? properties[i] : properties);
+                });
+    }
+
+    function on_event(object, event, callback)
+    {
+      object.addEventListener(event, callback, false);
+    }
+
+    expose(test, 'test');
+    expose(async_test, 'async_test');
+    expose(generate_tests, 'generate_tests');
+    expose(setup, 'setup');
+    expose(done, 'done');
+    expose(on_event, 'on_event');
+
+    /*
+     * Return a string truncated to the given length, with ... added at the end
+     * if it was longer.
+     */
+    function truncate(s, len)
+    {
+        if (s.length > len) {
+            return s.substring(0, len - 3) + "...";
+        }
+        return s;
+    }
+
+    /*
+     * Convert a value to a nice, human-readable string
+     */
+    function format_value(val)
+    {
+        if (Array.isArray(val))
+        {
+            return "[" + val.map(format_value).join(", ") + "]";
+        }
+
+        switch (typeof val)
+        {
+        case "string":
+            val = val.replace("\\", "\\\\");
+            for (var i = 0; i < 32; i++)
+            {
+                var replace = "\\";
+                switch (i) {
+                case 0: replace += "0"; break;
+                case 1: replace += "x01"; break;
+                case 2: replace += "x02"; break;
+                case 3: replace += "x03"; break;
+                case 4: replace += "x04"; break;
+                case 5: replace += "x05"; break;
+                case 6: replace += "x06"; break;
+                case 7: replace += "x07"; break;
+                case 8: replace += "b"; break;
+                case 9: replace += "t"; break;
+                case 10: replace += "n"; break;
+                case 11: replace += "v"; break;
+                case 12: replace += "f"; break;
+                case 13: replace += "r"; break;
+                case 14: replace += "x0e"; break;
+                case 15: replace += "x0f"; break;
+                case 16: replace += "x10"; break;
+                case 17: replace += "x11"; break;
+                case 18: replace += "x12"; break;
+                case 19: replace += "x13"; break;
+                case 20: replace += "x14"; break;
+                case 21: replace += "x15"; break;
+                case 22: replace += "x16"; break;
+                case 23: replace += "x17"; break;
+                case 24: replace += "x18"; break;
+                case 25: replace += "x19"; break;
+                case 26: replace += "x1a"; break;
+                case 27: replace += "x1b"; break;
+                case 28: replace += "x1c"; break;
+                case 29: replace += "x1d"; break;
+                case 30: replace += "x1e"; break;
+                case 31: replace += "x1f"; break;
+                }
+                val = val.replace(RegExp(String.fromCharCode(i), "g"), replace);
+            }
+            return '"' + val.replace(/"/g, '\\"') + '"';
+        case "boolean":
+        case "undefined":
+            return String(val);
+        case "number":
+            // In JavaScript, -0 === 0 and String(-0) == "0", so we have to
+            // special-case.
+            if (val === -0 && 1/val === -Infinity)
+            {
+                return "-0";
+            }
+            return String(val);
+        case "object":
+            if (val === null)
+            {
+                return "null";
+            }
+
+            // Special-case Node objects, since those come up a lot in my tests.  I
+            // ignore namespaces.  I use duck-typing instead of instanceof, because
+            // instanceof doesn't work if the node is from another window (like an
+            // iframe's contentWindow):
+            // http://www.w3.org/Bugs/Public/show_bug.cgi?id=12295
+            if ("nodeType" in val
+            && "nodeName" in val
+            && "nodeValue" in val
+            && "childNodes" in val)
+            {
+                switch (val.nodeType)
+                {
+                case Node.ELEMENT_NODE:
+                    var ret = "<" + val.tagName.toLowerCase();
+                    for (var i = 0; i < val.attributes.length; i++)
+                    {
+                        ret += " " + val.attributes[i].name + '="' + val.attributes[i].value + '"';
+                    }
+                    ret += ">" + val.innerHTML + "</" + val.tagName.toLowerCase() + ">";
+                    return "Element node " + truncate(ret, 60);
+                case Node.TEXT_NODE:
+                    return 'Text node "' + truncate(val.data, 60) + '"';
+                case Node.PROCESSING_INSTRUCTION_NODE:
+                    return "ProcessingInstruction node with target " + format_value(truncate(val.target, 60)) + " and data " + format_value(truncate(val.data, 60));
+                case Node.COMMENT_NODE:
+                    return "Comment node <!--" + truncate(val.data, 60) + "-->";
+                case Node.DOCUMENT_NODE:
+                    return "Document node with " + val.childNodes.length + (val.childNodes.length == 1 ? " child" : " children");
+                case Node.DOCUMENT_TYPE_NODE:
+                    return "DocumentType node";
+                case Node.DOCUMENT_FRAGMENT_NODE:
+                    return "DocumentFragment node with " + val.childNodes.length + (val.childNodes.length == 1 ? " child" : " children");
+                default:
+                    return "Node object of unknown type";
+                }
+            }
+
+            // Fall through to default
+        default:
+            return typeof val + ' "' + truncate(String(val), 60) + '"';
+        }
+    }
+    expose(format_value, "format_value");
+
+    /*
+     * Assertions
+     */
+
+    function assert_true(actual, description)
+    {
+        assert(actual === true, "assert_true", description,
+                                "expected true got ${actual}", {actual:actual});
+    };
+    expose(assert_true, "assert_true");
+
+    function assert_false(actual, description)
+    {
+        assert(actual === false, "assert_false", description,
+                                 "expected false got ${actual}", {actual:actual});
+    };
+    expose(assert_false, "assert_false");
+
+    function same_value(x, y) {
+        if (y !== y)
+        {
+            //NaN case
+            return x !== x;
+        }
+        else if (x === 0 && y === 0) {
+            //Distinguish +0 and -0
+            return 1/x === 1/y;
+        }
+        else
+        {
+            //typical case
+            return x === y;
+        }
+    }
+
+    function assert_equals(actual, expected, description)
+    {
+         /*
+          * Test if two primitives are equal or two objects
+          * are the same object
+          */
+        if (typeof actual != typeof expected)
+        {
+            assert(false, "assert_equals", description,
+                          "expected (" + typeof expected + ") ${expected} but got (" + typeof actual + ") ${actual}",
+                          {expected:expected, actual:actual});
+            return;
+        }
+        assert(same_value(actual, expected), "assert_equals", description,
+                                             "expected ${expected} but got ${actual}",
+                                             {expected:expected, actual:actual});
+    };
+    expose(assert_equals, "assert_equals");
+
+    function assert_not_equals(actual, expected, description)
+    {
+         /*
+          * Test if two primitives are unequal or two objects
+          * are different objects
+          */
+        assert(!same_value(actual, expected), "assert_not_equals", description,
+                                              "got disallowed value ${actual}",
+                                              {actual:actual});
+    };
+    expose(assert_not_equals, "assert_not_equals");
+
+    function assert_in_array(actual, expected, description)
+    {
+        assert(expected.indexOf(actual) != -1, "assert_in_array", description,
+                                               "value ${actual} not in array ${expected}",
+                                               {actual:actual, expected:expected});
+    }
+    expose(assert_in_array, "assert_in_array");
+
+    function assert_object_equals(actual, expected, description)
+    {
+         //This needs to be improved a great deal
+         function check_equal(actual, expected, stack)
+         {
+             stack.push(actual);
+
+             var p;
+             for (p in actual)
+             {
+                 assert(expected.hasOwnProperty(p), "assert_object_equals", description,
+                                                    "unexpected property ${p}", {p:p});
+
+                 if (typeof actual[p] === "object" && actual[p] !== null)
+                 {
+                     if (stack.indexOf(actual[p]) === -1)
+                     {
+                         check_equal(actual[p], expected[p], stack);
+                     }
+                 }
+                 else
+                 {
+                     assert(same_value(actual[p], expected[p]), "assert_object_equals", description,
+                                                       "property ${p} expected ${expected} got ${actual}",
+                                                       {p:p, expected:expected, actual:actual});
+                 }
+             }
+             for (p in expected)
+             {
+                 assert(actual.hasOwnProperty(p),
+                        "assert_object_equals", description,
+                        "expected property ${p} missing", {p:p});
+             }
+             stack.pop();
+         }
+         check_equal(actual, expected, []);
+    };
+    expose(assert_object_equals, "assert_object_equals");
+
+    function assert_array_equals(actual, expected, description)
+    {
+        assert(actual.length === expected.length,
+               "assert_array_equals", description,
+               "lengths differ, expected ${expected} got ${actual}",
+               {expected:expected.length, actual:actual.length});
+
+        for (var i=0; i < actual.length; i++)
+        {
+            assert(actual.hasOwnProperty(i) === expected.hasOwnProperty(i),
+                   "assert_array_equals", description,
+                   "property ${i}, property expected to be $expected but was $actual",
+                   {i:i, expected:expected.hasOwnProperty(i) ? "present" : "missing",
+                   actual:actual.hasOwnProperty(i) ? "present" : "missing"});
+            assert(same_value(expected[i], actual[i]),
+                   "assert_array_equals", description,
+                   "property ${i}, expected ${expected} but got ${actual}",
+                   {i:i, expected:expected[i], actual:actual[i]});
+        }
+    }
+    expose(assert_array_equals, "assert_array_equals");
+
+    function assert_approx_equals(actual, expected, epsilon, description)
+    {
+        /*
+         * Test if two primitive numbers are equal withing +/- epsilon
+         */
+        assert(typeof actual === "number",
+               "assert_approx_equals", description,
+               "expected a number but got a ${type_actual}",
+               {type_actual:typeof actual});
+
+        assert(Math.abs(actual - expected) <= epsilon,
+               "assert_approx_equals", description,
+               "expected ${expected} +/- ${epsilon} but got ${actual}",
+               {expected:expected, actual:actual, epsilon:epsilon});
+    };
+    expose(assert_approx_equals, "assert_approx_equals");
+
+    function assert_less_than(actual, expected, description)
+    {
+        /*
+         * Test if a primitive number is less than another
+         */
+        assert(typeof actual === "number",
+               "assert_less_than", description,
+               "expected a number but got a ${type_actual}",
+               {type_actual:typeof actual});
+
+        assert(actual < expected,
+               "assert_less_than", description,
+               "expected a number less than ${expected} but got ${actual}",
+               {expected:expected, actual:actual});
+    };
+    expose(assert_less_than, "assert_less_than");
+
+    function assert_greater_than(actual, expected, description)
+    {
+        /*
+         * Test if a primitive number is greater than another
+         */
+        assert(typeof actual === "number",
+               "assert_greater_than", description,
+               "expected a number but got a ${type_actual}",
+               {type_actual:typeof actual});
+
+        assert(actual > expected,
+               "assert_greater_than", description,
+               "expected a number greater than ${expected} but got ${actual}",
+               {expected:expected, actual:actual});
+    };
+    expose(assert_greater_than, "assert_greater_than");
+
+    function assert_less_than_equal(actual, expected, description)
+    {
+        /*
+         * Test if a primitive number is less than or equal to another
+         */
+        assert(typeof actual === "number",
+               "assert_less_than_equal", description,
+               "expected a number but got a ${type_actual}",
+               {type_actual:typeof actual});
+
+        assert(actual <= expected,
+               "assert_less_than", description,
+               "expected a number less than or equal to ${expected} but got ${actual}",
+               {expected:expected, actual:actual});
+    };
+    expose(assert_less_than_equal, "assert_less_than_equal");
+
+    function assert_greater_than_equal(actual, expected, description)
+    {
+        /*
+         * Test if a primitive number is greater than or equal to another
+         */
+        assert(typeof actual === "number",
+               "assert_greater_than_equal", description,
+               "expected a number but got a ${type_actual}",
+               {type_actual:typeof actual});
+
+        assert(actual >= expected,
+               "assert_greater_than_equal", description,
+               "expected a number greater than or equal to ${expected} but got ${actual}",
+               {expected:expected, actual:actual});
+    };
+    expose(assert_greater_than_equal, "assert_greater_than_equal");
+
+    function assert_regexp_match(actual, expected, description) {
+        /*
+         * Test if a string (actual) matches a regexp (expected)
+         */
+        assert(expected.test(actual),
+               "assert_regexp_match", description,
+               "expected ${expected} but got ${actual}",
+               {expected:expected, actual:actual});
+    }
+    expose(assert_regexp_match, "assert_regexp_match");
+
+    function assert_class_string(object, class_string, description) {
+        assert_equals({}.toString.call(object), "[object " + class_string + "]",
+                      description);
+    }
+    expose(assert_class_string, "assert_class_string");
+
+
+    function _assert_own_property(name) {
+        return function(object, property_name, description)
+        {
+            assert(object.hasOwnProperty(property_name),
+                   name, description,
+                   "expected property ${p} missing", {p:property_name});
+        };
+    }
+    expose(_assert_own_property("assert_exists"), "assert_exists");
+    expose(_assert_own_property("assert_own_property"), "assert_own_property");
+
+    function assert_not_exists(object, property_name, description)
+    {
+        assert(!object.hasOwnProperty(property_name),
+               "assert_not_exists", description,
+               "unexpected property ${p} found", {p:property_name});
+    };
+    expose(assert_not_exists, "assert_not_exists");
+
+    function _assert_inherits(name) {
+        return function (object, property_name, description)
+        {
+            assert(typeof object === "object",
+                   name, description,
+                   "provided value is not an object");
+
+            assert("hasOwnProperty" in object,
+                   name, description,
+                   "provided value is an object but has no hasOwnProperty method");
+
+            assert(!object.hasOwnProperty(property_name),
+                   name, description,
+                   "property ${p} found on object expected in prototype chain",
+                   {p:property_name});
+
+            assert(property_name in object,
+                   name, description,
+                   "property ${p} not found in prototype chain",
+                   {p:property_name});
+        };
+    }
+    expose(_assert_inherits("assert_inherits"), "assert_inherits");
+    expose(_assert_inherits("assert_idl_attribute"), "assert_idl_attribute");
+
+    function assert_readonly(object, property_name, description)
+    {
+         var initial_value = object[property_name];
+         try {
+             //Note that this can have side effects in the case where
+             //the property has PutForwards
+             object[property_name] = initial_value + "a"; //XXX use some other value here?
+             assert(same_value(object[property_name], initial_value),
+                    "assert_readonly", description,
+                    "changing property ${p} succeeded",
+                    {p:property_name});
+         }
+         finally
+         {
+             object[property_name] = initial_value;
+         }
+    };
+    expose(assert_readonly, "assert_readonly");
+
+    function assert_throws(code, func, description)
+    {
+        try
+        {
+            func.call(this);
+            assert(false, "assert_throws", description,
+                   "${func} did not throw", {func:func});
+        }
+        catch(e)
+        {
+            if (e instanceof AssertionError) {
+                throw(e);
+            }
+            if (code === null)
+            {
+                return;
+            }
+            if (typeof code === "object")
+            {
+                assert(typeof e == "object" && "name" in e && e.name == code.name,
+                       "assert_throws", description,
+                       "${func} threw ${actual} (${actual_name}) expected ${expected} (${expected_name})",
+                                    {func:func, actual:e, actual_name:e.name,
+                                     expected:code,
+                                     expected_name:code.name});
+                return;
+            }
+
+            var code_name_map = {
+                INDEX_SIZE_ERR: 'IndexSizeError',
+                HIERARCHY_REQUEST_ERR: 'HierarchyRequestError',
+                WRONG_DOCUMENT_ERR: 'WrongDocumentError',
+                INVALID_CHARACTER_ERR: 'InvalidCharacterError',
+                NO_MODIFICATION_ALLOWED_ERR: 'NoModificationAllowedError',
+                NOT_FOUND_ERR: 'NotFoundError',
+                NOT_SUPPORTED_ERR: 'NotSupportedError',
+                INVALID_STATE_ERR: 'InvalidStateError',
+                SYNTAX_ERR: 'SyntaxError',
+                INVALID_MODIFICATION_ERR: 'InvalidModificationError',
+                NAMESPACE_ERR: 'NamespaceError',
+                INVALID_ACCESS_ERR: 'InvalidAccessError',
+                TYPE_MISMATCH_ERR: 'TypeMismatchError',
+                SECURITY_ERR: 'SecurityError',
+                NETWORK_ERR: 'NetworkError',
+                ABORT_ERR: 'AbortError',
+                URL_MISMATCH_ERR: 'URLMismatchError',
+                QUOTA_EXCEEDED_ERR: 'QuotaExceededError',
+                TIMEOUT_ERR: 'TimeoutError',
+                INVALID_NODE_TYPE_ERR: 'InvalidNodeTypeError',
+                DATA_CLONE_ERR: 'DataCloneError'
+            };
+
+            var name = code in code_name_map ? code_name_map[code] : code;
+
+            var name_code_map = {
+                IndexSizeError: 1,
+                HierarchyRequestError: 3,
+                WrongDocumentError: 4,
+                InvalidCharacterError: 5,
+                NoModificationAllowedError: 7,
+                NotFoundError: 8,
+                NotSupportedError: 9,
+                InvalidStateError: 11,
+                SyntaxError: 12,
+                InvalidModificationError: 13,
+                NamespaceError: 14,
+                InvalidAccessError: 15,
+                TypeMismatchError: 17,
+                SecurityError: 18,
+                NetworkError: 19,
+                AbortError: 20,
+                URLMismatchError: 21,
+                QuotaExceededError: 22,
+                TimeoutError: 23,
+                InvalidNodeTypeError: 24,
+                DataCloneError: 25,
+
+                UnknownError: 0,
+                ConstraintError: 0,
+                DataError: 0,
+                TransactionInactiveError: 0,
+                ReadOnlyError: 0,
+                VersionError: 0
+            };
+
+            if (!(name in name_code_map))
+            {
+                throw new AssertionError('Test bug: unrecognized DOMException code "' + code + '" passed to assert_throws()');
+            }
+
+            var required_props = { code: name_code_map[name] };
+
+            if (required_props.code === 0
+            || ("name" in e && e.name !== e.name.toUpperCase() && e.name !== "DOMException"))
+            {
+                // New style exception: also test the name property.
+                required_props.name = name;
+            }
+
+            //We'd like to test that e instanceof the appropriate interface,
+            //but we can't, because we don't know what window it was created
+            //in.  It might be an instanceof the appropriate interface on some
+            //unknown other window.  TODO: Work around this somehow?
+
+            assert(typeof e == "object",
+                   "assert_throws", description,
+                   "${func} threw ${e} with type ${type}, not an object",
+                   {func:func, e:e, type:typeof e});
+
+            for (var prop in required_props)
+            {
+                assert(typeof e == "object" && prop in e && e[prop] == required_props[prop],
+                       "assert_throws", description,
+                       "${func} threw ${e} that is not a DOMException " + code + ": property ${prop} is equal to ${actual}, expected ${expected}",
+                       {func:func, e:e, prop:prop, actual:e[prop], expected:required_props[prop]});
+            }
+        }
+    }
+    expose(assert_throws, "assert_throws");
+
+    function assert_unreached(description) {
+         assert(false, "assert_unreached", description,
+                "Reached unreachable code");
+    }
+    expose(assert_unreached, "assert_unreached");
+
+    function assert_any(assert_func, actual, expected_array) 
+    {
+        var args = [].slice.call(arguments, 3)
+        var errors = []
+        var passed = false;
+        forEach(expected_array, 
+                function(expected)
+                {
+                    try {
+                        assert_func.apply(this, [actual, expected].concat(args))
+                        passed = true;
+                    } catch(e) {
+                        errors.push(e.message);
+                    }
+                });
+        if (!passed) {
+            throw new AssertionError(errors.join("\n\n"));
+        }
+    }
+    expose(assert_any, "assert_any");
+
+    function Test(name, properties)
+    {
+        this.name = name;
+        this.status = this.NOTRUN;
+        this.timeout_id = null;
+        this.is_done = false;
+
+        this.properties = properties;
+        this.timeout_length = properties.timeout ? properties.timeout : settings.test_timeout;
+
+        this.message = null;
+
+        var this_obj = this;
+        this.steps = [];
+
+        tests.push(this);
+    }
+
+    Test.statuses = {
+        PASS:0,
+        FAIL:1,
+        TIMEOUT:2,
+        NOTRUN:3
+    };
+
+    Test.prototype = merge({}, Test.statuses);
+
+    Test.prototype.structured_clone = function()
+    {
+        if(!this._structured_clone)
+        {
+            var msg = this.message;
+            msg = msg ? String(msg) : msg;
+            this._structured_clone = merge({
+                name:String(this.name),
+                status:this.status,
+                message:msg
+            }, Test.statuses);
+        }
+        return this._structured_clone;
+    };
+
+    Test.prototype.step = function(func, this_obj)
+    {
+        //In case the test has already failed
+        if (this.status !== this.NOTRUN)
+        {
+          return;
+        }
+
+        tests.started = true;
+
+        if (this.timeout_id === null) {
+            this.set_timeout();
+        }
+
+        this.steps.push(func);
+
+        if (arguments.length === 1)
+        {
+            this_obj = this;
+        }
+
+        try
+        {
+            return func.apply(this_obj, Array.prototype.slice.call(arguments, 2));
+        }
+        catch(e)
+        {
+            //This can happen if something called synchronously invoked another
+            //step
+            if (this.status !== this.NOTRUN)
+            {
+                return;
+            }
+            this.status = this.FAIL;
+            this.message = (typeof e === "object" && e !== null) ? e.message : e;
+            if (typeof e.stack != "undefined" && typeof e.message == "string") {
+                //Try to make it more informative for some exceptions, at least
+                //in Gecko and WebKit.  This results in a stack dump instead of
+                //just errors like "Cannot read property 'parentNode' of null"
+                //or "root is null".  Makes it a lot longer, of course.
+                this.message += "(stack: " + e.stack + ")";
+            }
+            this.done();
+            if (debug && e.constructor !== AssertionError) {
+                throw e;
+            }
+        }
+    };
+
+    Test.prototype.step_func = function(func, this_obj)
+    {
+        var test_this = this;
+
+        if (arguments.length === 1)
+        {
+            this_obj = test_this;
+        }
+
+        return function()
+        {
+            test_this.step.apply(test_this, [func, this_obj].concat(
+                Array.prototype.slice.call(arguments)));
+        };
+    };
+
+    Test.prototype.step_func_done = function(func, this_obj)
+    {
+        var test_this = this;
+
+        if (arguments.length === 1)
+        {
+            this_obj = test_this;
+        }
+
+        return function()
+        {
+            test_this.step.apply(test_this, [func, this_obj].concat(
+                Array.prototype.slice.call(arguments)));
+            test_this.done();
+        };
+    };
+
+    Test.prototype.set_timeout = function()
+    {
+        var this_obj = this;
+        this.timeout_id = setTimeout(function()
+                                     {
+                                         this_obj.timeout();
+                                     }, this.timeout_length);
+    };
+
+    Test.prototype.timeout = function()
+    {
+        this.status = this.TIMEOUT;
+        this.timeout_id = null;
+        this.message = "Test timed out";
+        this.done();
+    };
+
+    Test.prototype.done = function()
+    {
+        if (this.is_done) {
+            return;
+        }
+        clearTimeout(this.timeout_id);
+        if (this.status === this.NOTRUN)
+        {
+            this.status = this.PASS;
+        }
+        this.is_done = true;
+        tests.result(this);
+    };
+
+
+    /*
+     * Harness
+     */
+
+    function TestsStatus()
+    {
+        this.status = null;
+        this.message = null;
+    }
+
+    TestsStatus.statuses = {
+        OK:0,
+        ERROR:1,
+        TIMEOUT:2
+    };
+
+    TestsStatus.prototype = merge({}, TestsStatus.statuses);
+
+    TestsStatus.prototype.structured_clone = function()
+    {
+        if(!this._structured_clone)
+        {
+            var msg = this.message;
+            msg = msg ? String(msg) : msg;
+            this._structured_clone = merge({
+                status:this.status,
+                message:msg
+            }, TestsStatus.statuses);
+        }
+        return this._structured_clone;
+    };
+
+    function Tests()
+    {
+        this.tests = [];
+        this.num_pending = 0;
+
+        this.phases = {
+            INITIAL:0,
+            SETUP:1,
+            HAVE_TESTS:2,
+            HAVE_RESULTS:3,
+            COMPLETE:4
+        };
+        this.phase = this.phases.INITIAL;
+
+        this.properties = {};
+
+        //All tests can't be done until the load event fires
+        this.all_loaded = false;
+        this.wait_for_finish = false;
+        this.processing_callbacks = false;
+
+        this.timeout_length = settings.timeout;
+        this.timeout_id = null;
+
+        this.start_callbacks = [];
+        this.test_done_callbacks = [];
+        this.all_done_callbacks = [];
+
+        this.status = new TestsStatus();
+
+        var this_obj = this;
+
+        on_event(window, "load",
+                 function()
+                 {
+                     this_obj.all_loaded = true;
+                     if (this_obj.all_done())
+                     {
+                         this_obj.complete();
+                     }
+                 });
+
+        this.set_timeout();
+    }
+
+    Tests.prototype.setup = function(func, properties)
+    {
+        if (this.phase >= this.phases.HAVE_RESULTS)
+        {
+            return;
+        }
+        if (this.phase < this.phases.SETUP)
+        {
+            this.phase = this.phases.SETUP;
+        }
+
+        for (var p in properties)
+        {
+            if (properties.hasOwnProperty(p))
+            {
+                this.properties[p] = properties[p];
+            }
+        }
+
+        if (properties.timeout)
+        {
+            this.timeout_length = properties.timeout;
+        }
+        if (properties.explicit_done)
+        {
+            this.wait_for_finish = true;
+        }
+        if (properties.explicit_timeout) {
+            this.timeout_length = null;
+        }
+
+        if (func)
+        {
+            try
+            {
+                func();
+            } catch(e)
+            {
+                this.status.status = this.status.ERROR;
+                this.status.message = e;
+            };
+        }
+        this.set_timeout();
+    };
+
+    Tests.prototype.set_timeout = function()
+    {
+        var this_obj = this;
+        clearTimeout(this.timeout_id);
+        if (this.timeout_length !== null)
+        {
+            this.timeout_id = setTimeout(function() {
+                                             this_obj.timeout();
+                                         }, this.timeout_length);
+        }
+    };
+
+    Tests.prototype.timeout = function() {
+        this.status.status = this.status.TIMEOUT;
+        this.complete();
+    };
+
+    Tests.prototype.end_wait = function()
+    {
+        this.wait_for_finish = false;
+        if (this.all_done()) {
+            this.complete();
+        }
+    };
+
+    Tests.prototype.push = function(test)
+    {
+        if (this.phase < this.phases.HAVE_TESTS) {
+            this.start();
+        }
+        this.num_pending++;
+        this.tests.push(test);
+    };
+
+    Tests.prototype.all_done = function() {
+        return (this.all_loaded && this.num_pending === 0 &&
+                !this.wait_for_finish && !this.processing_callbacks);
+    };
+
+    Tests.prototype.start = function() {
+        this.phase = this.phases.HAVE_TESTS;
+        this.notify_start();
+    };
+
+    Tests.prototype.notify_start = function() {
+        var this_obj = this;
+        forEach (this.start_callbacks,
+                 function(callback)
+                 {
+                     callback(this_obj.properties);
+                 });
+        forEach_windows(
+                function(w, is_same_origin)
+                {
+                    if(is_same_origin && w.start_callback)
+                    {
+                        try
+                        {
+                            w.start_callback(this_obj.properties);
+                        }
+                        catch(e)
+                        {
+                            if (debug)
+                            {
+                                throw(e);
+                            }
+                        }
+                    }
+                    if (supports_post_message(w) && w !== self)
+                    {
+                        w.postMessage({
+                            type: "start",
+                            properties: this_obj.properties
+                        }, "*");
+                    }
+                });
+    };
+
+    Tests.prototype.result = function(test)
+    {
+        if (this.phase > this.phases.HAVE_RESULTS)
+        {
+            return;
+        }
+        this.phase = this.phases.HAVE_RESULTS;
+        this.num_pending--;
+        this.notify_result(test);
+    };
+
+    Tests.prototype.notify_result = function(test) {
+        var this_obj = this;
+        this.processing_callbacks = true;
+        forEach(this.test_done_callbacks,
+                function(callback)
+                {
+                    callback(test, this_obj);
+                });
+
+        forEach_windows(
+                function(w, is_same_origin)
+                {
+                    if(is_same_origin && w.result_callback)
+                    {
+                        try
+                        {
+                            w.result_callback(test);
+                        }
+                        catch(e)
+                        {
+                            if(debug) {
+                                throw e;
+                            }
+                        }
+                    }
+                    if (supports_post_message(w) && w !== self)
+                    {
+                        w.postMessage({
+                            type: "result",
+                            test: test.structured_clone()
+                        }, "*");
+                    }
+                });
+        this.processing_callbacks = false;
+        if (this_obj.all_done())
+        {
+            this_obj.complete();
+        }
+    };
+
+    Tests.prototype.complete = function() {
+        if (this.phase === this.phases.COMPLETE) {
+            return;
+        }
+        this.phase = this.phases.COMPLETE;
+        var this_obj = this;
+        this.tests.forEach(
+            function(x)
+            {
+                if(x.status === x.NOTRUN)
+                {
+                    this_obj.notify_result(x);
+                }
+            }
+        );
+        this.notify_complete();
+    };
+
+    Tests.prototype.notify_complete = function()
+    {
+        clearTimeout(this.timeout_id);
+        var this_obj = this;
+        var tests = map(this_obj.tests,
+                        function(test)
+                        {
+                            return test.structured_clone();
+                        });
+        if (this.status.status === null)
+        {
+            this.status.status = this.status.OK;
+        }
+
+        forEach (this.all_done_callbacks,
+                 function(callback)
+                 {
+                     callback(this_obj.tests, this_obj.status);
+                 });
+
+        forEach_windows(
+                function(w, is_same_origin)
+                {
+                    if(is_same_origin && w.completion_callback)
+                    {
+                        try
+                        {
+                            w.completion_callback(this_obj.tests, this_obj.status);
+                        }
+                        catch(e)
+                        {
+                            if (debug)
+                            {
+                                throw e;
+                            }
+                        }
+                    }
+                    if (supports_post_message(w) && w !== self)
+                    {
+                        w.postMessage({
+                            type: "complete",
+                            tests: tests,
+                            status: this_obj.status.structured_clone()
+                        }, "*");
+                    }
+                });
+    };
+
+    var tests = new Tests();
+
+    function timeout() {
+        if (tests.timeout_length === null)
+        {
+            tests.timeout();
+        }
+    }
+    expose(timeout, 'timeout');
+
+    function add_start_callback(callback) {
+        tests.start_callbacks.push(callback);
+    }
+
+    function add_result_callback(callback)
+    {
+        tests.test_done_callbacks.push(callback);
+    }
+
+    function add_completion_callback(callback)
+    {
+       tests.all_done_callbacks.push(callback);
+    }
+
+    expose(add_start_callback, 'add_start_callback');
+    expose(add_result_callback, 'add_result_callback');
+    expose(add_completion_callback, 'add_completion_callback');
+
+    /*
+     * Output listener
+    */
+
+    function Output() {
+      this.output_document = document;
+      this.output_node = null;
+      this.done_count = 0;
+      this.enabled = settings.output;
+      this.phase = this.INITIAL;
+    }
+
+    Output.prototype.INITIAL = 0;
+    Output.prototype.STARTED = 1;
+    Output.prototype.HAVE_RESULTS = 2;
+    Output.prototype.COMPLETE = 3;
+
+    Output.prototype.setup = function(properties) {
+        if (this.phase > this.INITIAL) {
+            return;
+        }
+
+        //If output is disabled in testharnessreport.js the test shouldn't be
+        //able to override that
+        this.enabled = this.enabled && (properties.hasOwnProperty("output") ?
+                                        properties.output : settings.output);
+    };
+
+    Output.prototype.init = function(properties)
+    {
+        if (this.phase >= this.STARTED) {
+            return;
+        }
+        if (properties.output_document) {
+            this.output_document = properties.output_document;
+        } else {
+            this.output_document = document;
+        }
+        this.phase = this.STARTED;
+    };
+
+    Output.prototype.resolve_log = function()
+    {
+        var output_document;
+        if (typeof this.output_document === "function")
+        {
+            output_document = this.output_document.apply(undefined);
+        } else
+        {
+            output_document = this.output_document;
+        }
+        if (!output_document)
+        {
+            return;
+        }
+        var node = output_document.getElementById("log");
+        if (node)
+        {
+            this.output_document = output_document;
+            this.output_node = node;
+        }
+    };
+
+    Output.prototype.show_status = function(test)
+    {
+        if (this.phase < this.STARTED)
+        {
+            this.init();
+        }
+        if (!this.enabled)
+        {
+            return;
+        }
+        if (this.phase < this.HAVE_RESULTS)
+        {
+            this.resolve_log();
+            this.phase = this.HAVE_RESULTS;
+        }
+        this.done_count++;
+        if (this.output_node)
+        {
+            if (this.done_count < 100
+            || (this.done_count < 1000 && this.done_count % 100 == 0)
+            || this.done_count % 1000 == 0) {
+                this.output_node.textContent = "Running, "
+                    + this.done_count + " complete, "
+                    + tests.num_pending + " remain";
+            }
+        }
+    };
+
+    Output.prototype.show_results = function (tests, harness_status)
+    {
+        if (this.phase >= this.COMPLETE) {
+            return;
+        }
+        if (!this.enabled)
+        {
+            return;
+        }
+        if (!this.output_node) {
+            this.resolve_log();
+        }
+        this.phase = this.COMPLETE;
+
+        var log = this.output_node;
+        if (!log)
+        {
+            return;
+        }
+        var output_document = this.output_document;
+
+        while (log.lastChild)
+        {
+            log.removeChild(log.lastChild);
+        }
+
+        if (script_prefix != null) {
+            var stylesheet = output_document.createElementNS(xhtml_ns, "link");
+            stylesheet.setAttribute("rel", "stylesheet");
+            stylesheet.setAttribute("href", script_prefix + "testharness.css");
+            var heads = output_document.getElementsByTagName("head");
+            if (heads.length) {
+                heads[0].appendChild(stylesheet);
+            }
+        }
+
+        var status_text = {};
+        status_text[Test.prototype.PASS] = "Pass";
+        status_text[Test.prototype.FAIL] = "Fail";
+        status_text[Test.prototype.TIMEOUT] = "Timeout";
+        status_text[Test.prototype.NOTRUN] = "Not Run";
+
+        var status_number = {};
+        forEach(tests, function(test) {
+                    var status = status_text[test.status];
+                    if (status_number.hasOwnProperty(status))
+                    {
+                        status_number[status] += 1;
+                    } else {
+                        status_number[status] = 1;
+                    }
+                });
+
+        function status_class(status)
+        {
+            return status.replace(/\s/g, '').toLowerCase();
+        }
+
+        var summary_template = ["section", {"id":"summary"},
+                                ["h2", {}, "Summary"],
+                                ["p", {}, "Found ${num_tests} tests"],
+                                function(vars) {
+                                    var rv = [["div", {}]];
+                                    var i=0;
+                                    while (status_text.hasOwnProperty(i)) {
+                                        if (status_number.hasOwnProperty(status_text[i])) {
+                                            var status = status_text[i];
+                                            rv[0].push(["div", {"class":status_class(status)},
+                                                        ["label", {},
+                                                         ["input", {type:"checkbox", checked:"checked"}],
+                                                         status_number[status] + " " + status]]);
+                                        }
+                                        i++;
+                                    }
+                                    return rv;
+                                }];
+
+        log.appendChild(render(summary_template, {num_tests:tests.length}, output_document));
+
+        forEach(output_document.querySelectorAll("section#summary label"),
+                function(element)
+                {
+                    on_event(element, "click",
+                             function(e)
+                             {
+                                 if (output_document.getElementById("results") === null)
+                                 {
+                                     e.preventDefault();
+                                     return;
+                                 }
+                                 var result_class = element.parentNode.getAttribute("class");
+                                 var style_element = output_document.querySelector("style#hide-" + result_class);
+                                 var input_element = element.querySelector("input");
+                                 if (!style_element && !input_element.checked) {
+                                     style_element = output_document.createElementNS(xhtml_ns, "style");
+                                     style_element.id = "hide-" + result_class;
+                                     style_element.textContent = "table#results > tbody > tr."+result_class+"{display:none}";
+                                     output_document.body.appendChild(style_element);
+                                 } else if (style_element && input_element.checked) {
+                                     style_element.parentNode.removeChild(style_element);
+                                 }
+                             });
+                });
+
+        // This use of innerHTML plus manual escaping is not recommended in
+        // general, but is necessary here for performance.  Using textContent
+        // on each individual <td> adds tens of seconds of execution time for
+        // large test suites (tens of thousands of tests).
+        function escape_html(s)
+        {
+            return s.replace(/\&/g, "&amp;")
+                .replace(/</g, "&lt;")
+                .replace(/"/g, "&quot;")
+                .replace(/'/g, "&#39;");
+        }
+
+        function has_assertions()
+        {
+            for (var i = 0; i < tests.length; i++) {
+                if (tests[i].properties.hasOwnProperty("assert")) {
+                    return true;
+                }
+            }
+            return false;
+        }
+        
+        function get_assertion(test)
+        {
+            if (test.properties.hasOwnProperty("assert")) {
+                if (Array.isArray(test.properties.assert)) {
+                    return test.properties.assert.join(' ');
+                }
+                return test.properties.assert;
+            }
+            return '';
+        }
+        
+        log.appendChild(document.createElementNS(xhtml_ns, "section"));
+        var assertions = has_assertions();
+        var html = "<h2>Details</h2><table id='results' " + (assertions ? "class='assertions'" : "" ) + ">"
+            + "<thead><tr><th>Result</th><th>Test Name</th>"
+            + (assertions ? "<th>Assertion</th>" : "")
+            + "<th>Message</th></tr></thead>"
+            + "<tbody>";
+        for (var i = 0; i < tests.length; i++) {
+            html += '<tr class="'
+                + escape_html(status_class(status_text[tests[i].status]))
+                + '"><td>'
+                + escape_html(status_text[tests[i].status])
+                + "</td><td>"
+                + escape_html(tests[i].name)
+                + "</td><td>"
+                + (assertions ? escape_html(get_assertion(tests[i])) + "</td><td>" : "")
+                + escape_html(tests[i].message ? tests[i].message : " ")
+                + "</td></tr>";
+        }
+        html += "</tbody></table>";
+        try {
+            log.lastChild.innerHTML = html;
+        } catch (e) {
+            log.appendChild(document.createElementNS(xhtml_ns, "p"))
+               .textContent = "Setting innerHTML for the log threw an exception.";
+            log.appendChild(document.createElementNS(xhtml_ns, "pre"))
+               .textContent = html;
+        }
+    };
+
+    var output = new Output();
+    add_start_callback(function (properties) {output.init(properties);});
+    add_result_callback(function (test) {output.show_status(tests);});
+    add_completion_callback(function (tests, harness_status) {output.show_results(tests, harness_status);});
+
+    /*
+     * Template code
+     *
+     * A template is just a javascript structure. An element is represented as:
+     *
+     * [tag_name, {attr_name:attr_value}, child1, child2]
+     *
+     * the children can either be strings (which act like text nodes), other templates or
+     * functions (see below)
+     *
+     * A text node is represented as
+     *
+     * ["{text}", value]
+     *
+     * String values have a simple substitution syntax; ${foo} represents a variable foo.
+     *
+     * It is possible to embed logic in templates by using a function in a place where a
+     * node would usually go. The function must either return part of a template or null.
+     *
+     * In cases where a set of nodes are required as output rather than a single node
+     * with children it is possible to just use a list
+     * [node1, node2, node3]
+     *
+     * Usage:
+     *
+     * render(template, substitutions) - take a template and an object mapping
+     * variable names to parameters and return either a DOM node or a list of DOM nodes
+     *
+     * substitute(template, substitutions) - take a template and variable mapping object,
+     * make the variable substitutions and return the substituted template
+     *
+     */
+
+    function is_single_node(template)
+    {
+        return typeof template[0] === "string";
+    }
+
+    function substitute(template, substitutions)
+    {
+        if (typeof template === "function") {
+            var replacement = template(substitutions);
+            if (replacement)
+            {
+                var rv = substitute(replacement, substitutions);
+                return rv;
+            }
+            else
+            {
+                return null;
+            }
+        }
+        else if (is_single_node(template))
+        {
+            return substitute_single(template, substitutions);
+        }
+        else
+        {
+            return filter(map(template, function(x) {
+                                  return substitute(x, substitutions);
+                              }), function(x) {return x !== null;});
+        }
+    }
+
+    function substitute_single(template, substitutions)
+    {
+        var substitution_re = /\${([^ }]*)}/g;
+
+        function do_substitution(input) {
+            var components = input.split(substitution_re);
+            var rv = [];
+            for (var i=0; i<components.length; i+=2)
+            {
+                rv.push(components[i]);
+                if (components[i+1])
+                {
+                    rv.push(String(substitutions[components[i+1]]));
+                }
+            }
+            return rv;
+        }
+
+        var rv = [];
+        rv.push(do_substitution(String(template[0])).join(""));
+
+        if (template[0] === "{text}") {
+            substitute_children(template.slice(1), rv);
+        } else {
+            substitute_attrs(template[1], rv);
+            substitute_children(template.slice(2), rv);
+        }
+
+        function substitute_attrs(attrs, rv)
+        {
+            rv[1] = {};
+            for (var name in template[1])
+            {
+                if (attrs.hasOwnProperty(name))
+                {
+                    var new_name = do_substitution(name).join("");
+                    var new_value = do_substitution(attrs[name]).join("");
+                    rv[1][new_name] = new_value;
+                };
+            }
+        }
+
+        function substitute_children(children, rv)
+        {
+            for (var i=0; i<children.length; i++)
+            {
+                if (children[i] instanceof Object) {
+                    var replacement = substitute(children[i], substitutions);
+                    if (replacement !== null)
+                    {
+                        if (is_single_node(replacement))
+                        {
+                            rv.push(replacement);
+                        }
+                        else
+                        {
+                            extend(rv, replacement);
+                        }
+                    }
+                }
+                else
+                {
+                    extend(rv, do_substitution(String(children[i])));
+                }
+            }
+            return rv;
+        }
+
+        return rv;
+    }
+
+ function make_dom_single(template, doc)
+ {
+     var output_document = doc || document;
+     if (template[0] === "{text}")
+     {
+         var element = output_document.createTextNode("");
+         for (var i=1; i<template.length; i++)
+         {
+             element.data += template[i];
+         }
+     }
+     else
+     {
+         var element = output_document.createElementNS(xhtml_ns, template[0]);
+         for (var name in template[1]) {
+             if (template[1].hasOwnProperty(name))
+             {
+                 element.setAttribute(name, template[1][name]);
+             }
+         }
+         for (var i=2; i<template.length; i++)
+         {
+             if (template[i] instanceof Object)
+             {
+                 var sub_element = make_dom(template[i]);
+                 element.appendChild(sub_element);
+             }
+             else
+             {
+                 var text_node = output_document.createTextNode(template[i]);
+                 element.appendChild(text_node);
+             }
+         }
+     }
+
+     return element;
+ }
+
+
+
+ function make_dom(template, substitutions, output_document)
+    {
+        if (is_single_node(template))
+        {
+            return make_dom_single(template, output_document);
+        }
+        else
+        {
+            return map(template, function(x) {
+                           return make_dom_single(x, output_document);
+                       });
+        }
+    }
+
+ function render(template, substitutions, output_document)
+    {
+        return make_dom(substitute(template, substitutions), output_document);
+    }
+
+    /*
+     * Utility funcions
+     */
+    function assert(expected_true, function_name, description, error, substitutions)
+    {
+        if (expected_true !== true)
+        {
+            throw new AssertionError(make_message(function_name, description,
+                                                  error, substitutions));
+        }
+    }
+
+    function AssertionError(message)
+    {
+        this.message = message;
+    }
+
+    function make_message(function_name, description, error, substitutions)
+    {
+        for (var p in substitutions) {
+            if (substitutions.hasOwnProperty(p)) {
+                substitutions[p] = format_value(substitutions[p]);
+            }
+        }
+        var node_form = substitute(["{text}", "${function_name}: ${description}" + error],
+                                   merge({function_name:function_name,
+                                          description:(description?description + " ":"")},
+                                          substitutions));
+        return node_form.slice(1).join("");
+    }
+
+    function filter(array, callable, thisObj) {
+        var rv = [];
+        for (var i=0; i<array.length; i++)
+        {
+            if (array.hasOwnProperty(i))
+            {
+                var pass = callable.call(thisObj, array[i], i, array);
+                if (pass) {
+                    rv.push(array[i]);
+                }
+            }
+        }
+        return rv;
+    }
+
+    function map(array, callable, thisObj)
+    {
+        var rv = [];
+        rv.length = array.length;
+        for (var i=0; i<array.length; i++)
+        {
+            if (array.hasOwnProperty(i))
+            {
+                rv[i] = callable.call(thisObj, array[i], i, array);
+            }
+        }
+        return rv;
+    }
+
+    function extend(array, items)
+    {
+        Array.prototype.push.apply(array, items);
+    }
+
+    function forEach (array, callback, thisObj)
+    {
+        for (var i=0; i<array.length; i++)
+        {
+            if (array.hasOwnProperty(i))
+            {
+                callback.call(thisObj, array[i], i, array);
+            }
+        }
+    }
+
+    function merge(a,b)
+    {
+        var rv = {};
+        var p;
+        for (p in a)
+        {
+            rv[p] = a[p];
+        }
+        for (p in b) {
+            rv[p] = b[p];
+        }
+        return rv;
+    }
+
+    function expose(object, name)
+    {
+        var components = name.split(".");
+        var target = window;
+        for (var i=0; i<components.length - 1; i++)
+        {
+            if (!(components[i] in target))
+            {
+                target[components[i]] = {};
+            }
+            target = target[components[i]];
+        }
+        target[components[components.length - 1]] = object;
+    }
+
+    function forEach_windows(callback) {
+        // Iterate of the the windows [self ... top, opener]. The callback is passed
+        // two objects, the first one is the windows object itself, the second one
+        // is a boolean indicating whether or not its on the same origin as the
+        // current window.
+        var cache = forEach_windows.result_cache;
+        if (!cache) {
+            cache = [[self, true]];
+            var w = self;
+            var i = 0;
+            var so;
+            var origins = location.ancestorOrigins;
+            while (w != w.parent)
+            {
+                w = w.parent;
+                // In WebKit, calls to parent windows' properties that aren't on the same
+                // origin cause an error message to be displayed in the error console but
+                // don't throw an exception. This is a deviation from the current HTML5
+                // spec. See: https://bugs.webkit.org/show_bug.cgi?id=43504
+                // The problem with WebKit's behavior is that it pollutes the error console
+                // with error messages that can't be caught.
+                //
+                // This issue can be mitigated by relying on the (for now) proprietary
+                // `location.ancestorOrigins` property which returns an ordered list of
+                // the origins of enclosing windows. See:
+                // http://trac.webkit.org/changeset/113945.
+                if(origins) {
+                    so = (location.origin == origins[i]);
+                }
+                else
+                {
+                    so = is_same_origin(w);
+                }
+                cache.push([w, so]);
+                i++;
+            }
+            w = window.opener;
+            if(w)
+            {
+                // window.opener isn't included in the `location.ancestorOrigins` prop.
+                // We'll just have to deal with a simple check and an error msg on WebKit
+                // browsers in this case.
+                cache.push([w, is_same_origin(w)]);
+            }
+            forEach_windows.result_cache = cache;
+        }
+
+        forEach(cache,
+                function(a)
+                {
+                    callback.apply(null, a);
+                });
+    }
+
+    function is_same_origin(w) {
+        try {
+            'random_prop' in w;
+            return true;
+        } catch(e) {
+            return false;
+        }
+    }
+
+    function supports_post_message(w)
+    {
+        var supports;
+        var type;
+        // Given IE  implements postMessage across nested iframes but not across
+        // windows or tabs, you can't infer cross-origin communication from the presence
+        // of postMessage on the current window object only.
+        //
+        // Touching the postMessage prop on a window can throw if the window is
+        // not from the same origin AND post message is not supported in that
+        // browser. So just doing an existence test here won't do, you also need
+        // to wrap it in a try..cacth block.
+        try
+        {
+            type = typeof w.postMessage;
+            if (type === "function")
+            {
+                supports = true;
+            }
+            // IE8 supports postMessage, but implements it as a host object which
+            // returns "object" as its `typeof`.
+            else if (type === "object")
+            {
+                supports = true;
+            }
+            // This is the case where postMessage isn't supported AND accessing a
+            // window property across origins does NOT throw (e.g. old Safari browser).
+            else
+            {
+                supports = false;
+            }
+        }
+        catch(e) {
+            // This is the case where postMessage isn't supported AND accessing a
+            // window property across origins throws (e.g. old Firefox browser).
+            supports = false;
+        }
+        return supports;
+    }
+})();
+
+/*
+ *For blacklist
+ */
+
+function is_platform_supported(name)
+{
+    var ret = true;
+
+    if (not_support_list.indexOf(name) >= 0)
+        ret = false;
+
+    return ret;
+}
+
+// vim: set expandtab shiftwidth=4 tabstop=4:
diff --git a/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/resources/testharnessreport.js b/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/resources/testharnessreport.js
new file mode 100755 (executable)
index 0000000..fa73347
--- /dev/null
@@ -0,0 +1,380 @@
+/*
+ * This file is intended for vendors to implement
+ * code needed to integrate testharness.js tests with their own test systems.
+ *
+ * The default implementation extracts metadata from the tests and validates 
+ * it against the cached version that should be present in the test source 
+ * file. If the cache is not found or is out of sync, source code suitable for
+ * caching the metadata is optionally generated.
+ *
+ * The cached metadata is present for extraction by test processing tools that
+ * are unable to execute javascript.
+ *
+ * Metadata is attached to tests via the properties parameter in the test
+ * constructor. See testharness.js for details.
+ *
+ * Typically test system integration will attach callbacks when each test has
+ * run, using add_result_callback(callback(test)), or when the whole test file
+ * has completed, using 
+ * add_completion_callback(callback(tests, harness_status)).
+ *
+ * For more documentation about the callback functions and the
+ * parameters they are called with see testharness.js
+ */
+
+
+
+var metadata_generator = {
+
+    currentMetadata: {},
+    cachedMetadata: false,
+    metadataProperties: ['help', 'assert', 'author'],
+    
+    error: function(message) {
+        var messageElement = document.createElement('p');
+        messageElement.setAttribute('class', 'error');
+        this.appendText(messageElement, message);
+        
+        var summary = document.getElementById('summary');
+        if (summary) {
+            summary.parentNode.insertBefore(messageElement, summary);
+        }
+        else {
+            document.body.appendChild(messageElement);
+        }
+    },
+
+    /**
+     * Ensure property value has contact information
+     */
+    validateContact: function(test, propertyName) {
+        var result = true;
+        var value = test.properties[propertyName];
+        var values = Array.isArray(value) ? value : [value];
+        for (var index = 0; index < values.length; index++) {
+            value = values[index];
+            var re = /(\S+)(\s*)<(.*)>(.*)/;
+            if (! re.test(value)) {
+                re = /(\S+)(\s+)(http[s]?:\/\/)(.*)/
+                if (! re.test(value)) {
+                    this.error('Metadata property "' + propertyName + 
+                        '" for test: "' + test.name +
+                        '" must have name and contact information ' +
+                        '("name <email>" or "name http(s)://")');
+                    result = false;
+                }
+            }
+        }
+        return result;
+    },
+    
+    /**
+     * Extract metadata from test object
+     */
+    extractFromTest: function(test) {
+        var testMetadata = {};
+        // filter out metadata from other properties in test
+        for (var metaIndex = 0; metaIndex < this.metadataProperties.length;
+             metaIndex++) {
+            var meta = this.metadataProperties[metaIndex];
+            if (test.properties.hasOwnProperty(meta)) {
+                if ('author' == meta) {
+                    this.validateContact(test, meta);
+                }
+                testMetadata[meta] = test.properties[meta];
+            }
+        }
+        return testMetadata;
+    },
+    
+    /**
+     * Compare cached metadata to extracted metadata
+     */
+    validateCache: function() {
+        for (var testName in this.currentMetadata) {
+            if (! this.cachedMetadata.hasOwnProperty(testName)) {
+                return false;
+            }
+            var testMetadata = this.currentMetadata[testName];
+            var cachedTestMetadata = this.cachedMetadata[testName];
+            delete this.cachedMetadata[testName];
+            
+            for (var metaIndex = 0; metaIndex < this.metadataProperties.length;
+                 metaIndex++) {
+                var meta = this.metadataProperties[metaIndex];
+                if (cachedTestMetadata.hasOwnProperty(meta) && 
+                    testMetadata.hasOwnProperty(meta)) {
+                    if (Array.isArray(cachedTestMetadata[meta])) {
+                      if (! Array.isArray(testMetadata[meta])) {
+                          return false;
+                      }
+                      if (cachedTestMetadata[meta].length == 
+                          testMetadata[meta].length) {
+                          for (var index = 0; 
+                               index < cachedTestMetadata[meta].length; 
+                               index++) {
+                              if (cachedTestMetadata[meta][index] != 
+                                  testMetadata[meta][index]) {
+                                  return false;
+                              }
+                          }
+                      }
+                      else {
+                          return false;
+                      }
+                    }
+                    else {
+                      if (Array.isArray(testMetadata[meta])) {
+                        return false;
+                      }
+                      if (cachedTestMetadata[meta] != testMetadata[meta]) {
+                        return false;
+                      }
+                    }
+                }
+                else if (cachedTestMetadata.hasOwnProperty(meta) || 
+                         testMetadata.hasOwnProperty(meta)) {
+                    return false;
+                }
+            }
+        }
+        for (var testName in this.cachedMetadata) {
+            return false;
+        }
+        return true;
+    },
+  
+    appendText: function(elemement, text) {
+        elemement.appendChild(document.createTextNode(text));
+    },
+  
+    jsonifyArray: function(arrayValue, indent) {
+        var output = '[';
+
+        if (1 == arrayValue.length) {
+            output += JSON.stringify(arrayValue[0]);
+        }
+        else {
+            for (var index = 0; index < arrayValue.length; index++) {
+                if (0 < index) {
+                    output += ',\n  ' + indent;
+                }
+                output += JSON.stringify(arrayValue[index]);
+            }
+        }
+        output += ']';
+        return output;
+    },
+    
+    jsonifyObject: function(objectValue, indent) {
+        var output = '{';
+        
+        var count = 0;
+        for (var property in objectValue) {
+            ++count;
+            if (Array.isArray(objectValue[property]) || 
+                ('object' == typeof(value))) {
+                ++count;
+            }
+        }
+        if (1 == count) {
+            for (var property in objectValue) {
+                output += ' "' + property + '": '
+                          + JSON.stringify(objectValue[property])
+                          + ' ';
+            }
+        }
+        else {
+            var first = true;
+            for (var property in objectValue) {
+                if (! first) {
+                    output += ',';
+                }
+                first = false;
+                output += '\n  ' + indent + '"' + property + '": ';
+                var value = objectValue[property];
+                if (Array.isArray(value)) {
+                    output += this.jsonifyArray(value, indent + 
+                        '                '.substr(0, 5 + property.length));
+                }
+                else if ('object' == typeof(value)) {
+                    output += this.jsonifyObject(value, indent + '  ');
+                }
+                else {
+                    output += JSON.stringify(value);
+                }
+            }
+            if (1 < output.length) {
+                output += '\n' + indent;
+            }
+        }
+        output += '}';
+        return output;
+    },
+  
+    /**
+     * Generate javascript source code for captured metadata
+     * Metadata is in pretty-printed JSON format
+     */
+    generateSource: function() {
+        var source = 
+            '<script id="metadata_cache">/*\n' + 
+            this.jsonifyObject(this.currentMetadata, '') + '\n' + 
+            '*/</script>\n';
+        return source;
+    },
+    
+    /**
+     * Add element containing metadata source code
+     */
+    addSourceElement: function(event) {
+        var sourceWrapper = document.createElement('div');
+        sourceWrapper.setAttribute('id', 'metadata_source');
+
+        var instructions = document.createElement('p');
+        if (this.cachedMetadata) {
+            this.appendText(instructions, 
+                'Replace the existing <script id="metadata_cache"> element ' + 
+                'in the test\'s <head> with the following:');
+        }
+        else {
+            this.appendText(instructions, 
+                'Copy the following into the <head> element of the test ' +
+                'or the test\'s metadata sidecar file:');
+        }
+        sourceWrapper.appendChild(instructions);
+        
+        var sourceElement = document.createElement('pre');
+        this.appendText(sourceElement, this.generateSource());
+
+        sourceWrapper.appendChild(sourceElement);
+        
+        var messageElement = document.getElementById('metadata_issue');
+        messageElement.parentNode.insertBefore(sourceWrapper, 
+                                               messageElement.nextSibling);
+        messageElement.parentNode.removeChild(messageElement);
+
+        (event.preventDefault) ? event.preventDefault() : 
+                                 event.returnValue = false;
+    },
+    
+    /**
+     * Extract the metadata cache from the cache element if present
+     */
+    getCachedMetadata: function() {
+        var cacheElement = document.getElementById('metadata_cache');
+        
+        if (cacheElement) {
+            var cacheText = cacheElement.firstChild.nodeValue;
+            var openBrace = cacheText.indexOf('{');
+            var closeBrace = cacheText.lastIndexOf('}');
+            if ((-1 < openBrace) && (-1 < closeBrace)) {
+                cacheText = cacheText.slice(openBrace, closeBrace + 1);
+                try {
+                    this.cachedMetadata = JSON.parse(cacheText);
+                }
+                catch (exc) {
+                    this.cachedMetadata = 'Invalid JSON in Cached metadata. ';
+                }
+            }
+            else {
+                this.cachedMetadata = 'Metadata not found in cache element. ';
+            }
+        }
+    },
+    
+    /**
+     * Main entry point, extract metadata from tests, compare to cached version
+     * if present.
+     * If cache not present or differs from extrated metadata, generate an error
+     */
+    process: function(tests, harness_status) {
+        for (var index = 0; index < tests.length; index++) {
+            var test = tests[index];
+            if (this.currentMetadata.hasOwnProperty(test.name)) {
+                this.error('Duplicate test name: ' + test.name);
+            }
+            else {
+                this.currentMetadata[test.name] = this.extractFromTest(test);
+            }
+        }
+
+        this.getCachedMetadata();
+        
+        var message = null;
+        var messageClass = 'warning';
+        var showSource = false;
+        
+        if (0 == tests.length) {
+            if (this.cachedMetadata) {
+                message = 'Cached metadata present but no tests. ';
+            }
+        }
+        else if (1 == tests.length) {
+            if (this.cachedMetadata) {
+                message = 'Single test files should not have cached metadata. ';
+            }
+            else {
+                var testMetadata = this.currentMetadata[tests[0].name];
+                var hasMetadata = false;
+                for (var meta in testMetadata) {
+                    hasMetadata |= testMetadata.hasOwnProperty(meta);
+                }
+                if (hasMetadata) {
+                    message = 'Single tests should not have metadata. ' +
+                              'Move metadata to <head>. ';
+                }
+            }
+        }
+        else {
+            if (this.cachedMetadata) {
+                messageClass = 'error';
+                if ('string' == typeof(this.cachedMetadata)) {
+                    message = this.cachedMetadata;
+                    showSource = true;
+                }
+                else if (! this.validateCache()) {
+                    message = 'Cached metadata out of sync. ';
+                    showSource = true;
+                }
+            }
+        }
+        
+        if (message) {
+            var messageElement = document.createElement('p');
+            messageElement.setAttribute('id', 'metadata_issue');
+            messageElement.setAttribute('class', messageClass);
+            this.appendText(messageElement, message);
+            
+            if (showSource) {
+                var link = document.createElement('a');
+                this.appendText(link, 'Click for source code.');
+                link.setAttribute('href', '#');
+                link.setAttribute('onclick', 
+                                  'metadata_generator.addSourceElement(event)');
+                messageElement.appendChild(link);
+            }
+            
+            var summary = document.getElementById('summary');
+            if (summary) {
+                summary.parentNode.insertBefore(messageElement, summary);
+            }
+            else {
+                var log = document.getElementById('log');
+                if (log) {
+                    log.appendChild(messageElement);
+                }
+            }
+        }
+    },
+
+    setup: function() {
+        add_completion_callback(
+            function (tests, harness_status) { 
+                metadata_generator.process(tests, harness_status)
+            });
+    }
+}
+
+metadata_generator.setup();
+// vim: set expandtab shiftwidth=4 tabstop=4:
diff --git a/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/resources/unitcommon.js b/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/resources/unitcommon.js
new file mode 100755 (executable)
index 0000000..31c63ae
--- /dev/null
@@ -0,0 +1,562 @@
+/*
+
+Copyright (c) 2013 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+
+
+Authors:
+
+ */
+
+
+MIN_BYTE = -128;
+MAX_BYTE = 127;
+MIN_OCTET = 0;
+MAX_OCTET = 255;
+MIN_SHORT = -32768;
+MAX_SHORT = 32767;
+MIN_UNSIGNED_SHORT = 0;
+MAX_UNSIGNED_SHORT = 65535;
+MIN_LONG = -2147483648;
+MAX_LONG = 2147483647;
+MIN_UNSIGNED_LONG = 0;
+MAX_UNSIGNED_LONG = 4294967295;
+MIN_LONG_LONG = -9223372036854775808;
+MAX_LONG_LONG = 9223372036854775807;
+MIN_UNSIGNED_LONG_LONG = 0;
+MAX_UNSIGNED_LONG_LONG = 18446744073709551615;
+
+TYPE_MISMATCH_EXCEPTION = {name: 'TypeMismatchError'};
+NOT_FOUND_EXCEPTION = {name: 'NotFoundError'};
+INVALID_VALUES_EXCEPTION = {name: 'InvalidValuesError'};
+IO_EXCEPTION = {name: 'IOError'};
+SECURITY_EXCEPTION = {name: 'SecurityError'};
+
+
+(function () {
+   var head_src = document.head.innerHTML;
+   if (head_src.search(/\/testharness.js\W/) === -1) {
+       document.write('<script language="javascript" src="../resources/testharness.js"></script>\n');
+   }
+   if (head_src.search(/\/testharnessreport.js\W/) === -1) {
+       document.write('<script language="javascript" src="../resources/testharnessreport.js"></script>\n');
+   }
+})();
+
+var _registered_types = {};
+
+function _resolve_registered_type(type) {
+    while (type in _registered_types) {
+        type = _registered_types[type];
+    }
+    return type;
+}
+
+/**
+ * Method checks extra argument for none argument method.
+ * The only check is that method will not throw an exception.
+ * Example usage:
+ * checkExtraArgument(tizen.notification, "removeAll");
+ *
+ * @param object object
+ * @param methodName string - name of the method
+ */
+function checkExtraArgument(object, methodName) {
+    var extraArgument = [
+        null,
+        undefined,
+        "Tizen",
+        1,
+        false,
+        ["one", "two"],
+        {argument: 1},
+        function () {}
+    ], i;
+
+    for (i = 0; i < extraArgument.length; i++) {
+        object[methodName](extraArgument[i]);
+    }
+}
+
+/**
+ * Method to validate conversion.
+ * Example usage:
+ *   conversionTable = getTypeConversionExceptions("functionObject", true);
+ *   for(i = 0; i < conversionTable.length; i++) {
+ *       errorCallback = conversionTable[i][0];
+ *       exceptionName = conversionTable[i][1];
+ *
+ *       assert_throws({name : exceptionName},
+ *       function () {
+ *           tizen.systemsetting.setProperty("HOME_SCREEN",
+ *               propertyValue, successCallback, errorCallback);
+ *       }, exceptionName + " should be thrown - given incorrect errorCallback.");
+ *   }
+ *
+ * @param conversionType
+ * @param isOptional
+ * @returns table of tables which contain value (index 0) and exceptionName (index 1)
+ *
+ */
+function getTypeConversionExceptions(conversionType, isOptional) {
+    var exceptionName = "TypeMismatchError",
+        conversionTable;
+    switch (conversionType) {
+        case "enum":
+            conversionTable = [
+                [undefined, exceptionName],
+                [null, exceptionName],
+                [0, exceptionName],
+                [true, exceptionName],
+                ["dummyInvalidEnumValue", exceptionName],
+                [{ }, exceptionName]
+            ];
+            break;
+        case "double":
+            conversionTable = [
+                [undefined, exceptionName],
+                [NaN, exceptionName],
+                [Number.POSITIVE_INFINITY, exceptionName],
+                [Number.NEGATIVE_INFINITY, exceptionName],
+                ["TIZEN", exceptionName],
+                [{ name : "TIZEN" }, exceptionName],
+                [function () { }, exceptionName]
+            ];
+            break;
+        case "object":
+            conversionTable = [
+                [true, exceptionName],
+                [false, exceptionName],
+                [NaN, exceptionName],
+                [0, exceptionName],
+                ["", exceptionName],
+                ["TIZEN", exceptionName],
+                [undefined, exceptionName]
+            ];
+            if (!isOptional) {
+                conversionTable.push([null, exceptionName]);
+            }
+            break;
+        case "functionObject":
+            conversionTable = [
+                [true, exceptionName],
+                [false, exceptionName],
+                [NaN, exceptionName],
+                [0, exceptionName],
+                ["", exceptionName],
+                ["TIZEN", exceptionName],
+                [[], exceptionName],
+                [{ }, exceptionName],
+                [undefined, exceptionName]
+            ];
+            if (!isOptional) {
+                conversionTable.push([null, exceptionName]);
+            }
+            break;
+        case "array":
+            conversionTable = [
+                [true, exceptionName],
+                [false, exceptionName],
+                [NaN, exceptionName],
+                [0, exceptionName],
+                ["", exceptionName],
+                ["TIZEN", exceptionName],
+                [{ }, exceptionName],
+                [function () { }, exceptionName],
+                [undefined, exceptionName]
+            ];
+            if (!isOptional) {
+                conversionTable.push([null, exceptionName]);
+            }
+            break;
+        case "dictionary":
+            conversionTable = [
+                [true, exceptionName],
+                [false, exceptionName],
+                [NaN, exceptionName],
+                [0, exceptionName],
+                ["", exceptionName],
+                ["TIZEN", exceptionName],
+                [undefined, exceptionName]
+            ];
+            if (!isOptional) {
+                conversionTable.push([null, exceptionName]);
+            }
+            break;
+        default:
+            assert_unreached("Fix your test. Wrong conversionType '" + conversionType + "'.");
+    };
+
+    return conversionTable;
+}
+
+
+function assert_type(obj, type, description) {
+    var org_type = type, prop_name, prop_type, prop_value;
+
+    type = _resolve_registered_type(type);
+
+    if (typeof (type) === 'string') {
+        type = type.toLowerCase();
+        switch (type) {
+            case 'object':
+            case 'string':
+            case 'number':
+            case 'function':
+            case 'boolean':
+            case 'undefined':
+            case 'xml':
+                assert_equals(typeof (obj), type, description);
+                break;
+            case 'null':
+                assert_true(obj === null, description);
+                break;
+            case 'array':
+                assert_true(Array.isArray(obj), description);
+                break;
+            case 'date':
+                assert_true(obj instanceof Date, description);
+                break;
+            case 'byte':
+                assert_equals(typeof (obj), 'number', description);
+                assert_greater_than_equal(obj, MIN_BYTE, description + " - value too low.");
+                assert_less_than_equal(obj, MAX_BYTE, description + " - value too high.");
+                assert_equals(Math.abs(obj % 1), 0, description + " - value is not an integer.");
+                break;
+            case 'octet':
+                assert_equals(typeof (obj), 'number', description);
+                assert_greater_than_equal(obj, MIN_OCTET, description + " - value too low.");
+                assert_less_than_equal(obj, MAX_OCTET, description + " - value too high.");
+                assert_equals(obj % 1, 0, description + " - value is not an integer.");
+                break;
+            case 'short':
+                assert_equals(typeof (obj), 'number', description);
+                assert_greater_than_equal(obj, MIN_SHORT, description + " - value too low.");
+                assert_less_than_equal(obj, MAX_SHORT, description + " - value too high.");
+                assert_equals(Math.abs(obj % 1), 0, description + " - value is not an integer.");
+                break;
+            case 'unsigned short':
+                assert_equals(typeof (obj), 'number', description);
+                assert_greater_than_equal(obj, MIN_UNSIGNED_SHORT, description + " - value too low.");
+                assert_less_than_equal(obj, MAX_UNSIGNED_SHORT, description + " - value too high.");
+                assert_equals(obj % 1, 0, description + " - value is not an integer.");
+                break;
+            case 'long':
+                assert_equals(typeof (obj), 'number', description);
+                assert_greater_than_equal(obj, MIN_LONG, description + " - value too low.");
+                assert_less_than_equal(obj, MAX_LONG, description + " - value too high.");
+                assert_equals(Math.abs(obj % 1), 0, description + " - value is not an integer.");
+                break;
+            case 'unsigned long':
+                assert_equals(typeof (obj), 'number', description);
+                assert_greater_than_equal(obj, MIN_UNSIGNED_LONG, description + " - value too low.");
+                assert_less_than_equal(obj, MAX_UNSIGNED_LONG, description + " - value too high.");
+                assert_equals(obj % 1, 0, description + " - value is not an integer.");
+                break;
+            case 'long long':
+                assert_equals(typeof (obj), 'number', description);
+                assert_greater_than_equal(obj, MIN_LONG_LONG, description + " - value too low.");
+                assert_less_than_equal(obj, MAX_LONG_LONG, description + " - value too high.");
+                assert_equals(Math.abs(obj % 1), 0, description + " - value is not an integer.");
+                break;
+            case 'unsigned long long':
+                assert_equals(typeof (obj), 'number', description);
+                assert_greater_than_equal(obj, MIN_UNSIGNED_LONG_LONG, description + " - value too low.");
+                assert_less_than_equal(obj, MAX_UNSIGNED_LONG_LONG, description + " - value too high.");
+                assert_equals(obj % 1, 0, description + " - value is not an integer.");
+                break;
+            case 'double':
+                assert_equals(typeof (obj), 'number', description);
+                break;
+            default:
+                assert_unreached('Fix your test. Wrong type \'' + org_type + '\'');
+        }
+    } else if (typeof (type) === 'function') {
+        assert_true(obj instanceof type, description);
+    } else if (typeof (type) === 'object') {
+        for (prop_name in type) {
+            prop_type = type[prop_name];
+            if (prop_type === 'function') {
+                assert_inherits(obj, prop_name);
+                assert_equals(typeof obj[prop_name], prop_type, 'Object should have method ' + prop_name);
+            } else {
+                assert_own_property(obj, prop_name);
+            }
+        }
+    } else {
+        assert_unreached('Fix your test. Wrong type ' + org_type);
+    }
+}
+
+function register_type(alias, type_spec) {
+    _registered_types[alias] = type_spec;
+}
+
+/**
+ * Method to check if attribute is const.
+ * Example usage:
+ * check_const(tizen.bluetooth.deviceMinor, 'TOY_DOLL', 0x03, 'number', 0x29B);
+ *
+ * @param obj  object to test which  has const attribute
+ * @param attributeName attribute name.
+ * @param expectedValue expected value of provided attribute name
+ * @param expectedType expected type of provided attribute name
+ * @param valueToAssign value to assign in order to check if attribute value can be modified
+ */
+function check_const(obj, attributeName, expectedValue, expectedType, valueToAssign) {
+    var tmp;
+    if (expectedValue === valueToAssign) {
+        assert_unreached("Fix your test. The same values given for "  + attributeName +
+            " in 'value' and 'valueToSet' arguments.");
+    }
+    if (typeof (attributeName) === "string") {
+        assert_true(attributeName in obj, "Name " + attributeName + " doesn't exist in provided object.");
+        assert_equals(obj[attributeName], expectedValue, "Value of " + attributeName + " is diffrent.");
+        if (typeof (expectedType) !== "undefined") {
+            if (expectedValue === null) {
+                assert_type(obj[attributeName], "object", "Type of " + attributeName + " is different.");
+            } else {
+                assert_type(obj[attributeName], expectedType, "Type of " + attributeName + " is different.");
+            }
+        } else {
+            assert_unreached("Fix your test. Wrong type " + expectedType);
+        }
+        tmp = obj[attributeName];
+        obj[attributeName] = valueToAssign;
+        assert_equals(obj[attributeName], tmp, attributeName + " can be modified.");
+    } else {
+        assert_unreached("Fix your test. Wrong type of name " + typeof (attributeName));
+    }
+}
+
+/**
+ * Method to check if attribute is readonly.
+ * Example usage:
+ * check_readonly(statusNotification, "postedTime", null, 'object', new Date());
+ *
+ * @param obj  object to test which  has readonly attribute
+ * @param attributeName attribute name.
+ * @param expectedValue expected value of provided attribute name
+ * @param expectedType expected type of provided attribute name
+ * @param valueToAssign value to assign in order to check if attribute value can be modified
+ */
+function check_readonly(obj, attributeName, expectedValue, expectedType, valueToAssign) {
+    check_const(obj, attributeName, expectedValue, expectedType, valueToAssign);
+}
+
+/**
+ * Method to check if attribute can be set to null.
+ * Example usage:
+ * check_not_nullable(syncInfo, "mode");
+ *
+ * @param obj object to test which has not nullable attribute
+ * @param attributeName attribute name.
+ */
+function check_not_nullable(obj, attributeName)
+{   var old_value = obj[attributeName];
+    obj[attributeName] = null;
+    assert_not_equals(obj[attributeName], null, "Attribute " + attributeName + " can be set to null.");
+    obj[attributeName] = old_value;
+}
+
+/**
+ * Method to check NoInterfaceObject
+ * Example usage:
+ * check_no_interface_object("BluetoothAdapter")
+ *
+ * @param interfaceName interface name
+ */
+function check_no_interface_object(interfaceName) {
+    assert_throws({name: "TypeError"}, function () {
+        tizen[interfaceName]();
+    },"Wrong call as a function");
+    assert_throws({name: "TypeError"}, function () {
+        new tizen[interfaceName]();
+    },"Wrong call as a new function");
+    assert_throws({name: "TypeError"}, function () {
+        ({}) instanceof tizen[interfaceName];
+    },"instanceof exception");
+    assert_equals(tizen[interfaceName], undefined, interfaceName + " is not undefined.");
+}
+
+
+/**
+ * Method to check Constructors
+ * Example usage:
+ * check_constructor("BluetoothAdapter")
+ *
+ * @param constructorName constructor name
+ */
+
+function check_constructor(constructorName) {
+    assert_true(constructorName in tizen, "No " + constructorName + " in tizen.");
+    assert_false({} instanceof tizen[constructorName],"Custom object is not instance of " + constructorName);
+    assert_throws({
+        name: "TypeError"
+    }, function () {
+        tizen[constructorName]();
+    }, "Constructor called as function.");
+}
+
+/**
+ * Method to check if given method can be overridden in a given object - (TEMPORARY REMOVED).
+ * That method also checks if given method exists in a given object.
+ * Example usage:
+ * check_method_exists(tizen.notification, "get");
+ *
+ * @param obj object with method
+ * @param methodName name of the method to check.
+ */
+function check_method_exists(obj, methodName) {
+    assert_type(obj[methodName], 'function', "Method does not exist.");
+}
+
+/**
+ * Method to check extensibility of given object.
+ * Method checks if new attribute and method can be added.
+ * Example usage:
+ * check_extensibility(tizen.notification);
+ *
+ * @param obj object to check
+ */
+function check_extensibility(obj) {
+    var dummyAttribute = "dummyAttributeValue", dummyMethodResult = "dummyMethodResultValue";
+    obj.newDummyMethod = function() {
+        return dummyMethodResult;
+    }
+    assert_equals(obj.newDummyMethod(), dummyMethodResult, "Incorrect result from added method.");
+
+    obj.newDummyAttribute = dummyAttribute;
+    assert_equals(obj.newDummyAttribute, dummyAttribute, "Incorrect result from added attribute.");
+}
+
+/**
+ * Method to check if attribute can be modify.
+ * Example usage:
+ * check_attr(downloadRequest, "fileName", default_val, "string", "file_name.html");
+ *
+ * @param obj  object to test which has not readonly attribute
+ * @param attributeName attribute name.
+ * @param expectedValue expected value of provided attribute name
+ * @param expectedType expected type of provided attribute name
+ * @param valueToAssign value to assign in order to check if attribute value can be modified
+ */
+function check_attribute(obj, attributeName, expectedValue, expectedType, valueToAssign) {
+    if (expectedValue === valueToAssign) {
+        assert_unreached("Fix your test. The same values given for "  + attributeName +
+            " in 'value' and 'valueToSet' arguments.");
+    }
+    if (typeof (attributeName) === "string") {
+        assert_true(attributeName in obj, "Name " + attributeName + " doesn't exist in provided object.");
+        assert_equals(obj[attributeName], expectedValue, "Value of " + attributeName + " is diffrent.");
+        if (typeof (expectedType) !== "undefined") {
+            if (expectedValue === null) {
+                assert_type(obj[attributeName], "object", "Type of " + attributeName + " is different.");
+            } else {
+                assert_type(obj[attributeName], expectedType, "Type of " + attributeName + " is different.");
+            }
+        } else {
+            assert_unreached("Fix your test. Wrong type " + expectedType);
+        }
+        obj[attributeName] = valueToAssign;
+        assert_equals(obj[attributeName], valueToAssign, attributeName + " can be modified.");
+    } else {
+        assert_unreached("Fix your test. Wrong type of name " + typeof (attributeName));
+    }
+}
+
+/**
+ * Method to check if whole array can be overwritten with an invalid value.
+ * Sample usage:
+ * check_invalid_array_assignments(message, "to", false);
+ *
+ * @param obj object which has the array as its property
+ * @param array name of the array to check
+ * @param isNullable indicates if the array can be null
+ */
+function check_invalid_array_assignments(obj, array, isNullable) {
+    var args = [undefined, true, false, NaN, 0, "TIZEN", {}, function () {}],
+        val = obj[array], i;
+
+    if (!isNullable) {
+        obj[array] = null;
+        assert_not_equals(obj[array], null, "Non-nullable array was set to null");
+        assert_type(obj[array], "array", "Non-nullable array type changed after assigning null");
+        assert_equals(obj[array].toString(), val.toString(), "Non-nullable array contents changed after assigning null");
+    }
+
+    for (i = 0 ; i < args.length ; i++) {
+        obj[array] = args[i];
+        assert_type(obj[array], "array", "Array type changed after assigning an invalid value");
+        assert_equals(obj[array].toString(), val.toString(), "Array contents changed after assigning an invalid value");
+    }
+}
+
+/**
+ * Method to check if an object can be overwritten with an invalid value.
+ * Sample usage:
+ * check_invalid_object_assignments(message, "body", false);
+ *
+ * @param parentObj object which has the 'obj' object as its property
+ * @param obj name of the object to check
+ * @param isNullable indicates if the object can be null
+ */
+function check_invalid_obj_assignments(parentObj, obj, isNullable) {
+    var args = [undefined, true, false, NaN, 0, "TIZEN", function () {}],
+        val = parentObj[obj], i;
+
+    if (!isNullable) {
+        parentObj[obj] = null;
+        assert_equals(parentObj[obj], val, "Non-nullable obj was modified after assigning null");
+    }
+
+    for (i = 0 ; i < args.length ; i++) {
+        parentObj[obj] = args[i];
+        assert_equals(parentObj[obj], val, "The object was set to " + args[i]);
+    }
+}
+
+/**
+ * Method to validate conversion for listeners.
+ * Example usage:
+ * incorrectListeners = getListenerConversionExceptions(["oninstalled", "onupdated", "onuninstalled"]);
+ * for(i = 0; i < incorrectListeners.length; i++) {
+ *     packageInformationEventCallback  = incorrectListeners[i][0];
+ *     exceptionName = incorrectListeners[i][1];
+ *     assert_throws({name : exceptionName},
+ *        function () {
+ *             tizen.package.setPackageInfoEventListener(packageInformationEventCallback);
+ *         }, exceptionName + " should be thrown - given incorrect successCallback.");
+ * }
+ *
+ *
+ * @param callbackNames Array with names
+ * @returns {Array} table of tables which contain incorrect listener (index 0) and exceptionName (index 1)
+ *
+ */
+function getListenerConversionExceptions(callbackNames) {
+    var result = [], conversionTable, i, j, listenerName;
+    conversionTable = getTypeConversionExceptions("functionObject", false);
+
+    for (i = 0; i < callbackNames.length; i++) {
+        for (j = 0; j < conversionTable.length; j++) {
+            listenerName = {};
+            listenerName[callbackNames[i]] = conversionTable[j][0];
+            result.push([listenerName, conversionTable[j][1]]);
+        }
+    }
+
+    return result;
+}
diff --git a/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/tests/Application_getRequestedAppControl.js b/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/tests/Application_getRequestedAppControl.js
new file mode 100755 (executable)
index 0000000..93744f6
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+Copyright (c) 2013 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Authors:
+        Krzysztof Lachacz <k.lachacz@samsung.com>
+        Junghyuk Park <junghyuk.park@samsung.com>
+
+*/
+
+test(function () {
+    var reqAppControl = tizen.application.getCurrentApplication().getRequestedAppControl(),
+        appControl;
+
+    assert_true("appControl" in reqAppControl, "RequestedApplicationControl should have appControl attribute");
+
+    appControl = reqAppControl.appControl;
+    assert_type(appControl, "object", "incorrect type of appControl");
+    assert_true("operation" in appControl, "ApplicationControl should have operation attribute");
+    assert_true("uri" in appControl, "ApplicationControl should have uri attribute");
+    assert_true("mime" in appControl, "ApplicationControl should have mime attribute");
+    assert_true("category" in appControl, "ApplicationControl should have category attribute");
+    assert_true("data" in appControl, "ApplicationControl should have data attribute");
+
+    reqAppControl.appControl = {
+        operation: "dummy",
+        uri: "dummy",
+        mime: "dummy",
+        category: "dummy",
+        data: []
+    };
+
+    assert_equals(reqAppControl.appControl.operation, appControl.operation, "appControl is not readonly");
+    assert_equals(reqAppControl.appControl.uri, appControl.uri, "appControl is not readonly");
+    assert_equals(reqAppControl.appControl.mime, appControl.mime, "appControl is not readonly");
+    assert_equals(reqAppControl.appControl.category, appControl.category, "appControl is not readonly");
+    if(appControl.data) {
+        assert_equals(reqAppControl.appControl.data.length, appControl.data.length, "appControl is not readonly");
+    } else {
+        assert_equals(reqAppControl.appControl.data, appControl.data, "appControl is not readonly");
+    }
+
+}, "Application_getRequestedAppControl");
diff --git a/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/tests/Application_getRequestedAppControl_extra_argument.js b/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/tests/Application_getRequestedAppControl_extra_argument.js
new file mode 100755 (executable)
index 0000000..2e660dc
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+Copyright (c) 2013 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Authors:
+        Krzysztof Lachacz <k.lachacz@samsung.com>
+        Junghyuk Park <junghyuk.park@samsung.com>
+
+*/
+
+test(function () {
+    var i, argumentsList = [null, undefined, "string", 1, false, ["one", "two"], {arg: 1}, function () {}],
+        reqAppControl, appControl;
+
+    for (i = 0; i < argumentsList.length; i++) {
+        reqAppControl = tizen.application.getCurrentApplication().getRequestedAppControl(argumentsList[i]),
+        assert_true("appControl" in reqAppControl, "RequestedApplicationControl should have appControl attribute");
+
+        appControl = reqAppControl.appControl;
+        assert_type(appControl, "object", "incorrect type of appControl");
+        assert_true("operation" in appControl, "ApplicationControl should have operation attribute");
+        assert_true("uri" in appControl, "ApplicationControl should have uri attribute");
+        assert_true("mime" in appControl, "ApplicationControl should have mime attribute");
+        assert_true("category" in appControl, "ApplicationControl should have category attribute");
+        assert_true("data" in appControl, "ApplicationControl should have data attribute");
+
+        reqAppControl.appControl = new tizen.ApplicationControl(
+            "operation",
+            "uri",
+            "mime",
+            "category",
+            [ new tizen.ApplicationControlData("key", [ "value" ]) ]
+        );
+
+        assert_equals(reqAppControl.appControl.operation, appControl.operation, "appControl is not readonly");
+        assert_equals(reqAppControl.appControl.uri, appControl.uri, "appControl is not readonly");
+        assert_equals(reqAppControl.appControl.mime, appControl.mime, "appControl is not readonly");
+        assert_equals(reqAppControl.appControl.category, appControl.category, "appControl is not readonly");
+        if(appControl.data) {
+            assert_equals(reqAppControl.appControl.data.length, appControl.data.length, "appControl is not readonly");
+        } else {
+            assert_equals(reqAppControl.appControl.data, appControl.data, "appControl is not readonly");
+        }
+    }
+
+}, "Application_getRequestedAppControl_extra_argument");
diff --git a/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/tests/Application_hide.js b/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/tests/Application_hide.js
new file mode 100755 (executable)
index 0000000..f3fccf3
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+Copyright (c) 2013 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Authors:
+        Krzysztof Lachacz <k.lachacz@samsung.com>
+        Mariusz Polasinski <m.polasinski@samsung.com>
+
+*/
+
+test(function () {
+    var retVal, currentApplication = tizen.application.getCurrentApplication();
+
+    retVal = currentApplication.hide();
+    assert_equals(retVal, undefined, "wrong returned value");
+
+}, "Application_hide");
diff --git a/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/tests/Application_hide_extra_argument.js b/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/tests/Application_hide_extra_argument.js
new file mode 100755 (executable)
index 0000000..d7f164a
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+Copyright (c) 2013 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Authors:
+        Krzysztof Lachacz <k.lachacz@samsung.com>
+
+*/
+
+test(function () {
+    var currentApplication = tizen.application.getCurrentApplication();
+
+    checkExtraArgument(currentApplication, "hide");
+
+}, "Application_hide_extra_argument");
diff --git a/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/tests/RequestedApplicationControl_appControl_attribute.js b/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/tests/RequestedApplicationControl_appControl_attribute.js
new file mode 100755 (executable)
index 0000000..517ced9
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+Copyright (c) 2013 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Authors:
+        Krzysztof Lachacz <k.lachacz@samsung.com>
+
+*/
+
+test(function () {
+    var reqAppControl = tizen.application.getCurrentApplication().getRequestedAppControl(),
+        appControl;
+
+    assert_true("appControl" in reqAppControl, "RequestedApplicationControl should have appControl attribute");
+
+    appControl = reqAppControl.appControl;
+    assert_type(appControl, "object", "incorrect type of appControl");
+    assert_true("operation" in appControl, "ApplicationControl should have operation attribute");
+    assert_true("uri" in appControl, "ApplicationControl should have uri attribute");
+    assert_true("mime" in appControl, "ApplicationControl should have mime attribute");
+    assert_true("category" in appControl, "ApplicationControl should have category attribute");
+    assert_true("data" in appControl, "ApplicationControl should have data attribute");
+
+    reqAppControl.appControl = {
+        operation: "dummy",
+        uri: "dummy",
+        mime: "dummy",
+        category: "dummy",
+        data: []
+    };
+
+    assert_equals(reqAppControl.appControl.operation, appControl.operation, "appControl is not readonly");
+    assert_equals(reqAppControl.appControl.uri, appControl.uri, "appControl is not readonly");
+    assert_equals(reqAppControl.appControl.mime, appControl.mime, "appControl is not readonly");
+    assert_equals(reqAppControl.appControl.category, appControl.category, "appControl is not readonly");
+    if(appControl.data) {
+        assert_equals(reqAppControl.appControl.data.length, appControl.data.length, "appControl is not readonly");
+    } else {
+        assert_equals(reqAppControl.appControl.data, appControl.data, "appControl is not readonly");
+    }
+
+}, "RequestedApplicationControl_appControl_attribute");
diff --git a/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/tests/RequestedApplicationControl_callerAppId_attribute.js b/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/tests/RequestedApplicationControl_callerAppId_attribute.js
new file mode 100755 (executable)
index 0000000..03fce65
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+Copyright (c) 2013 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Authors:
+        Krzysztof Lachacz <k.lachacz@samsung.com>
+
+*/
+
+test(function () {
+    var reqAppControl = tizen.application.getCurrentApplication().getRequestedAppControl();
+
+    assert_true("callerAppId" in reqAppControl, "RequestedApplicationControl should have callerAppId attribute");
+    check_readonly(reqAppControl, "callerAppId", reqAppControl.callerAppId, "string", "dummy");
+
+}, "RequestedApplicationControl_callerAppId_attribute");
diff --git a/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/tests/RequestedApplicationControl_extend.js b/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/tests/RequestedApplicationControl_extend.js
new file mode 100755 (executable)
index 0000000..5538511
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+Copyright (c) 2013 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Authors:
+        Krzysztof Lachacz <k.lachacz@samsung.com>
+
+*/
+
+test(function () {
+    var reqAppControl = tizen.application.getCurrentApplication().getRequestedAppControl();
+    check_extensibility(reqAppControl);
+}, "RequestedApplicationControl_extend");
diff --git a/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/tests/RequestedApplicationControl_replyFailure_exist.js b/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/tests/RequestedApplicationControl_replyFailure_exist.js
new file mode 100755 (executable)
index 0000000..7b948fc
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+Copyright (c) 2013 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Authors:
+        Krzysztof Lachacz <k.lachacz@samsung.com>
+
+*/
+
+test(function () {
+    var reqAppControl = tizen.application.getCurrentApplication().getRequestedAppControl();
+    check_method_exists(reqAppControl, "replyFailure");
+}, "RequestedApplicationControl_replyFailure_exist");
diff --git a/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/tests/RequestedApplicationControl_replyResult_data_TypeMismatch.js b/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/tests/RequestedApplicationControl_replyResult_data_TypeMismatch.js
new file mode 100755 (executable)
index 0000000..3890d8e
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+Copyright (c) 2013 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Authors:
+        Krzysztof Lachacz <k.lachacz@samsung.com>
+
+*/
+
+test(function () {
+    var reqAppControl = tizen.application.getCurrentApplication().getRequestedAppControl(),
+        conversionTable, exceptionName, i, data;
+
+    conversionTable = getTypeConversionExceptions("array", true);
+
+    for(i = 0; i < conversionTable.length; i++) {
+        data = conversionTable[i][0];
+        exceptionName = conversionTable[i][1];
+
+        assert_throws({name: exceptionName},
+            function () {
+                reqAppControl.replyResult(data);
+            }, exceptionName + " should be thrown.");
+    }
+}, "RequestedApplicationControl_replyResult_data_TypeMismatch");
diff --git a/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/tests/RequestedApplicationControl_replyResult_exist.js b/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControl/tests/RequestedApplicationControl_replyResult_exist.js
new file mode 100755 (executable)
index 0000000..3185926
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+Copyright (c) 2013 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Authors:
+        Krzysztof Lachacz <k.lachacz@samsung.com>
+
+*/
+
+test(function () {
+    var reqAppControl = tizen.application.getCurrentApplication().getRequestedAppControl();
+
+    assert_true("replyResult" in reqAppControl, "reqAppControl should have replyResult method");
+    assert_type(reqAppControl.replyResult, "function", "incorrect type of replyResult");
+
+    check_method_exists(reqAppControl, "replyResult");
+}, "RequestedApplicationControl_replyResult_exist");
diff --git a/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControlMock/appcontrol_launch_explicit.html b/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControlMock/appcontrol_launch_explicit.html
new file mode 100755 (executable)
index 0000000..3f4c042
--- /dev/null
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+
+<!--
+
+Copyright (c) 2013 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+
+
+Authors:
+        Junghyuk Park <junghyuk.park@samsung.com>
+
+
+-->
+
+<html>
+<head>
+<meta charset="utf-8" />
+<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
+<meta name="description" content="tct-application-tizen-tests"/>
+
+<title>TCTAppControlMock</title>
+
+    <link rel="stylesheet" type="text/css" href="css/style.css"/>
+</head>
+
+<body>
+<header>
+    <hgroup>
+      <h1>TCTAppControlMock</h1>
+      <h2>appcontrol_launch_explicit.html</h2>
+    </hgroup>
+</header>
+</body>
+</html>
diff --git a/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControlMock/config.xml b/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControlMock/config.xml
new file mode 100755 (executable)
index 0000000..3aafb7e
--- /dev/null
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<widget xmlns="http://www.w3.org/ns/widgets" xmlns:tizen="http://tizen.org/ns/widgets" id="http://tizen.org/TCTAppControlMock" version="1.0.0" viewmodes="maximized">
+    <access origin="*" subdomains="true"/>
+    <tizen:app-control>
+        <tizen:src name="appcontrol_launch_explicit.html"/>
+        <tizen:operation name="http://tizen.org/appcontrol/operation/tct/launch/explicit"/>
+        <tizen:uri name="tct"/>
+        <tizen:mime name="text/html"/>
+    </tizen:app-control>
+    <tizen:application id="api1appli2.TCTAppControlMock" package="api1appli2" required_version="3.0"/>
+    <content src="index.html"/>
+    <icon src="icon.png"/>
+    <name>TCTAppControlMock</name>
+    <tizen:setting screen-orientation="landscape" background-support="enable"/>
+</widget>
diff --git a/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControlMock/css/style.css b/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControlMock/css/style.css
new file mode 100755 (executable)
index 0000000..63e4bfb
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+
+Copyright (c) 2013 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+
+
+Authors:
+            Junghyuk Park <junghyuk.park@samsung.com>
+
+
+*/
+
+* {
+    font-family: Lucida Sans, Arial, Helvetica, sans-serif;
+}
+
+body {
+    margin: 0px auto;
+}
+
+header h1 {
+    font-size: 36px;
+    margin: 0px;
+}
+
+header h2 {
+    font-size: 18px;
+    margin: 0px;
+    color: #888;
+    font-style: italic;
+}
+
+nav ul {
+    list-style: none;
+    padding: 0px;
+    display: block;
+    clear: right;
+    background-color: #666;
+    padding-left: 4px;
+    height: 24px;
+}
+
+nav ul li {
+    display: inline;
+    padding: 0px 20px 5px 10px;
+    height: 24px;
+    border-right: 1px solid #ccc;
+}
+
+nav ul li a {
+    color: #EFD3D3;
+    text-decoration: none;
+    font-size: 13px;
+    font-weight: bold;
+}
+
+nav ul li a:hover {
+    color: #fff;
+}
+
+article > header h1 {
+    font-size: 20px;
+    margin-left: 14px;
+}
+
+article > header h1 a {
+    color: #993333;
+}
+
+article > header h1 img {
+    vertical-align:middle;
+}
+
+article > section header h1 {
+    font-size: 16px;
+}
+
+article p {
+    clear: both;
+}
+
+footer p {
+    text-align: center;
+    font-size: 12px;
+    color: #888;
+    margin-top: 24px;
+}
diff --git a/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControlMock/icon.png b/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControlMock/icon.png
new file mode 100755 (executable)
index 0000000..c22cfa8
Binary files /dev/null and b/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControlMock/icon.png differ
diff --git a/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControlMock/index.html b/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControlMock/index.html
new file mode 100755 (executable)
index 0000000..a40ea96
--- /dev/null
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+
+<!--
+
+Copyright (c) 2013 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+
+
+Authors:
+            Junghyuk Park <junghyuk.park@samsung.com>
+
+
+-->
+
+<html>
+<head>
+    <meta charset="utf-8" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
+    <meta name="description" content="tct-application-tizen-tests"/>
+
+    <title>TCTAppControlMock</title>
+
+    <link rel="stylesheet" type="text/css" href="css/style.css"/>
+    <script src="js/main.js"></script>
+</head>
+
+<body onload="init()">
+  <header>
+    <hgroup>
+      <h1>TCTAppControlMock</h1>
+      <h2>index.html</h2>
+    </hgroup>
+  </header>
+</body>
+</html>
diff --git a/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControlMock/js/main.js b/webWidgetTCT_device/tools/launcher/tct/install/TCTAppControlMock/js/main.js
new file mode 100755 (executable)
index 0000000..5126963
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+
+Copyright (c) 2013 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+
+
+Authors:
+            Junghyuk Park <junghyuk.park@samsung.com>
+
+
+*/
+
+var init = function () {
+    console.log("init() called");
+};
+
diff --git a/webWidgetTCT_device/tools/launcher/tct/install/TCTPackageInfoTest/config.xml b/webWidgetTCT_device/tools/launcher/tct/install/TCTPackageInfoTest/config.xml
new file mode 100755 (executable)
index 0000000..e51c218
--- /dev/null
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<widget xmlns="http://www.w3.org/ns/widgets" xmlns:tizen="http://tizen.org/ns/widgets" id="http://tizen.org/TCTPackageInfoTest" version="1.2.3" viewmodes="maximized">
+    <access origin="*" subdomains="true"/>
+    <tizen:application id="api1pack20.TCTPackageInfoTest" package="api1pack20" required_version="2.2"/>
+    <author>The author of TCTPackageInfoTest</author>
+    <content src="index.html"/>
+    <description>The description of TCTPackageInfoTest</description>
+    <icon src="icon.png"/>
+    <name>TCTPackageInfoTest</name>
+    <tizen:setting screen-orientation="landscape" background-support="enable"/>
+</widget>
diff --git a/webWidgetTCT_device/tools/launcher/tct/install/TCTPackageInfoTest/css/style.css b/webWidgetTCT_device/tools/launcher/tct/install/TCTPackageInfoTest/css/style.css
new file mode 100755 (executable)
index 0000000..1c64069
--- /dev/null
@@ -0,0 +1,75 @@
+* {
+    font-family: Lucida Sans, Arial, Helvetica, sans-serif;
+}
+
+body {
+    margin: 0px auto;
+}
+
+header h1 {
+    font-size: 36px;
+    margin: 0px;
+}
+
+header h2 {
+    font-size: 18px;
+    margin: 0px;
+    color: #888;
+    font-style: italic;
+}
+
+nav ul {
+    list-style: none;
+    padding: 0px;
+    display: block;
+    clear: right;
+    background-color: #666;
+    padding-left: 4px;
+    height: 24px;
+}
+
+nav ul li {
+    display: inline;
+    padding: 0px 20px 5px 10px;
+    height: 24px;
+    border-right: 1px solid #ccc;
+}
+
+nav ul li a {
+    color: #EFD3D3;
+    text-decoration: none;
+    font-size: 13px;
+    font-weight: bold;
+}
+
+nav ul li a:hover {
+    color: #fff;
+}
+
+article > header h1 {
+    font-size: 20px;
+    margin-left: 14px;
+}
+
+article > header h1 a {
+    color: #993333;
+}
+
+article > header h1 img {
+    vertical-align:middle;
+}
+
+article > section header h1 {
+    font-size: 16px;
+}
+
+article p {
+    clear: both;
+}
+
+footer p {
+    text-align: center;
+    font-size: 12px;
+    color: #888;
+    margin-top: 24px;
+}
diff --git a/webWidgetTCT_device/tools/launcher/tct/install/TCTPackageInfoTest/icon.png b/webWidgetTCT_device/tools/launcher/tct/install/TCTPackageInfoTest/icon.png
new file mode 100755 (executable)
index 0000000..c22cfa8
Binary files /dev/null and b/webWidgetTCT_device/tools/launcher/tct/install/TCTPackageInfoTest/icon.png differ
diff --git a/webWidgetTCT_device/tools/launcher/tct/install/TCTPackageInfoTest/index.html b/webWidgetTCT_device/tools/launcher/tct/install/TCTPackageInfoTest/index.html
new file mode 100755 (executable)
index 0000000..059f7ea
--- /dev/null
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<!--
+
+Copyright (c) 2013 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+
+
+Authors:
+    Andrzej Krolikowski <a.krolikowsk@samsung.com>
+
+
+-->
+
+<html>
+<head>
+    <meta charset="utf-8" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
+    <meta name="description" content="tct-application-tizen-tests"/>
+
+    <title>TCTPackageInfoTest</title>
+
+    <link rel="stylesheet" type="text/css" href="css/style.css"/>
+</head>
+
+<body>
+  <header>
+    <hgroup>
+      <h1>TCTPackageInfoTest</h1>
+      <h2>version 1.2.3</h2>
+    </hgroup>
+  </header>
+</body>
+</html>
diff --git a/webWidgetTCT_device/tools/launcher/tct/install/TCTbroadcastApp/config.xml b/webWidgetTCT_device/tools/launcher/tct/install/TCTbroadcastApp/config.xml
new file mode 100755 (executable)
index 0000000..673e1ee
--- /dev/null
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<widget xmlns="http://www.w3.org/ns/widgets" xmlns:tizen="http://tizen.org/ns/widgets" id="http://yourdomain/TCTbroadcastApp" version="1.0.0" viewmodes="maximized">
+    <tizen:privilege name="http://tizen.org/privilege/internet"/><access origin="*" subdomains="true"/>
+    <tizen:application id="api1appli4.TCTbroadcastApp" package="api1appli4" required_version="3.0"/>
+    <content src="index.html"/>
+    <icon src="icon.png"/>
+    <name>TCTbroadcastApp</name>
+    <tizen:setting screen-orientation="landscape" background-support="enable"/>
+</widget>
+
diff --git a/webWidgetTCT_device/tools/launcher/tct/install/TCTbroadcastApp/css/style.css b/webWidgetTCT_device/tools/launcher/tct/install/TCTbroadcastApp/css/style.css
new file mode 100755 (executable)
index 0000000..1c64069
--- /dev/null
@@ -0,0 +1,75 @@
+* {
+    font-family: Lucida Sans, Arial, Helvetica, sans-serif;
+}
+
+body {
+    margin: 0px auto;
+}
+
+header h1 {
+    font-size: 36px;
+    margin: 0px;
+}
+
+header h2 {
+    font-size: 18px;
+    margin: 0px;
+    color: #888;
+    font-style: italic;
+}
+
+nav ul {
+    list-style: none;
+    padding: 0px;
+    display: block;
+    clear: right;
+    background-color: #666;
+    padding-left: 4px;
+    height: 24px;
+}
+
+nav ul li {
+    display: inline;
+    padding: 0px 20px 5px 10px;
+    height: 24px;
+    border-right: 1px solid #ccc;
+}
+
+nav ul li a {
+    color: #EFD3D3;
+    text-decoration: none;
+    font-size: 13px;
+    font-weight: bold;
+}
+
+nav ul li a:hover {
+    color: #fff;
+}
+
+article > header h1 {
+    font-size: 20px;
+    margin-left: 14px;
+}
+
+article > header h1 a {
+    color: #993333;
+}
+
+article > header h1 img {
+    vertical-align:middle;
+}
+
+article > section header h1 {
+    font-size: 16px;
+}
+
+article p {
+    clear: both;
+}
+
+footer p {
+    text-align: center;
+    font-size: 12px;
+    color: #888;
+    margin-top: 24px;
+}
diff --git a/webWidgetTCT_device/tools/launcher/tct/install/TCTbroadcastApp/icon.png b/webWidgetTCT_device/tools/launcher/tct/install/TCTbroadcastApp/icon.png
new file mode 100755 (executable)
index 0000000..c22cfa8
Binary files /dev/null and b/webWidgetTCT_device/tools/launcher/tct/install/TCTbroadcastApp/icon.png differ
diff --git a/webWidgetTCT_device/tools/launcher/tct/install/TCTbroadcastApp/images/tizen_32.png b/webWidgetTCT_device/tools/launcher/tct/install/TCTbroadcastApp/images/tizen_32.png
new file mode 100755 (executable)
index 0000000..647c3f9
Binary files /dev/null and b/webWidgetTCT_device/tools/launcher/tct/install/TCTbroadcastApp/images/tizen_32.png differ
diff --git a/webWidgetTCT_device/tools/launcher/tct/install/TCTbroadcastApp/index.html b/webWidgetTCT_device/tools/launcher/tct/install/TCTbroadcastApp/index.html
new file mode 100755 (executable)
index 0000000..678400c
--- /dev/null
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <meta charset="utf-8" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
+    <meta name="description" content="Tizen basic template generated by Tizen Web IDE"/>
+
+    <title>Tizen Web IDE - Tizen - Tizen basic Application</title>
+
+    <link rel="stylesheet" type="text/css" href="css/style.css"/>
+    <script src="js/main.js"></script>
+</head>
+
+<body>
+  <header>
+    <hgroup>
+      <h1>Tizen app</h1>
+      <h2>An broadcast sender tizen app</h2>
+    </hgroup>
+  </header>
+
+  <nav>
+    <ul>
+       <li><a href="#">Home</a></li>
+       <li><a href="#">About Us</a></li>
+       <li><a href="#">Contact Us</a></li>
+    </ul>
+  </nav>
+
+  <article>
+    <header>
+      <h1>
+        <img src="images/tizen_32.png" width="32"/> Application Name
+      </h1>
+    </header>
+    <p>This is an Tizen Web Application</p>
+    <ul>
+      <li>smartphones, tablets and smart TVs
+      <li>netbooks, in-vehicle infotainment devices
+    </ul>
+    <section>
+      <p>This is a broadcast app for TCT suit.</p>
+      <p>The following button to send a broadcast to test case</p>
+      <div id="divbutton1">
+        <button onclick="sendBroadcast();">Send</button>
+      </div>
+    </section>
+  </article>
+
+  <footer>
+    <p>&copy; 2015 Samsung Company. All rights reserved.</p>
+  </footer>    
+</body>
+</html>
diff --git a/webWidgetTCT_device/tools/launcher/tct/install/TCTbroadcastApp/js/main.js b/webWidgetTCT_device/tools/launcher/tct/install/TCTbroadcastApp/js/main.js
new file mode 100755 (executable)
index 0000000..ee8520f
--- /dev/null
@@ -0,0 +1,29 @@
+var startTime;
+var checkTime;
+var myCustomData = {type: 'bar', value: 'val'};
+//Initialize function
+var init = function () {
+       // TODO:: Do your initialization job
+       console.log("init() called");
+
+       // add eventListener for tizenhwkey
+       document.addEventListener('tizenhwkey', function(e) {
+               if(e.keyName == "back") {
+                       try {
+                               tizen.application.getCurrentApplication().exit();
+                       } catch (error) {
+                               console.error("getCurrentApplication(): " + error.message);
+                       }
+               }
+       });
+       sendBroadcaset();
+};
+// window.onload can work without <body onload="">
+window.onload = init;
+
+function sendBroadcaset() {
+        var app = tizen.application.getCurrentApplication();
+        app.broadcastEvent({"appId": app.appInfo.id, "name": "broadcast_event"}, myCustomData);
+        tizen.application.getCurrentApplication().exit();
+}
+
diff --git a/webWidgetTCT_device/tools/launcher/tct/install/UnitTest-AlarmTest1/config.xml b/webWidgetTCT_device/tools/launcher/tct/install/UnitTest-AlarmTest1/config.xml
new file mode 100755 (executable)
index 0000000..2a4349f
--- /dev/null
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<widget xmlns="http://www.w3.org/ns/widgets" xmlns:tizen="http://tizen.org/ns/widgets" id="http://example.org/test/alarmTestApp" version="1.0.0" viewmodes="maximized">
+    <name short="alarmTestApp">alarmTestApp</name>
+    <description>This widget provides service for Tizen application unit test</description>
+    <author>TizenDev</author>
+    <icon src="icon.png"/>
+    <content src="index.html"/>
+    
+    <tizen:application id="testalar00.alarmTestApp" package="testalar00" required_version="3.0"/>
+    
+</widget>
diff --git a/webWidgetTCT_device/tools/launcher/tct/install/UnitTest-AlarmTest1/icon.png b/webWidgetTCT_device/tools/launcher/tct/install/UnitTest-AlarmTest1/icon.png
new file mode 100755 (executable)
index 0000000..c22cfa8
Binary files /dev/null and b/webWidgetTCT_device/tools/launcher/tct/install/UnitTest-AlarmTest1/icon.png differ
diff --git a/webWidgetTCT_device/tools/launcher/tct/install/UnitTest-AlarmTest1/index.html b/webWidgetTCT_device/tools/launcher/tct/install/UnitTest-AlarmTest1/index.html
new file mode 100755 (executable)
index 0000000..e10a61d
--- /dev/null
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<!--
+
+Copyright (c) 2013 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+Authors:
+        Mariusz Polasinski <m.polasinski@samsung.com>
+-->
+
+<html lang="en">
+<head>
+    <meta charset="utf-8" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
+    <title>Tizen basic Application UnitTest Widget</title>
+</head>
+<body>
+This application was created for some unit tests.
+<div id="divbutton1">
+    <button value="exit" onclick="window.close()" style="width: 100%; height: 3em; font-size: 13px; margin-top: 10px;">exit</button>
+</div>
+</body>
+<script type="text/javascript">
+    setTimeout(function () {
+        window.close();
+    }, 15000);
+</script>
+</html>
diff --git a/webWidgetTCT_device/tools/launcher/tct/install/tct-bt-helper/config.xml b/webWidgetTCT_device/tools/launcher/tct/install/tct-bt-helper/config.xml
new file mode 100755 (executable)
index 0000000..1677af9
--- /dev/null
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<widget xmlns="http://www.w3.org/ns/widgets" xmlns:tizen="http://tizen.org/ns/widgets" id="http://yourdomain/tct-bt-helper" version="1.0.0" viewmodes="maximized">
+    <tizen:application id="ps2w1DxNKj.TctBtHelper" package="ps2w1DxNKj" required_version="3.0"/>
+    <content src="index.html"/>
+    <icon src="icon.png"/>
+    <name>tct-bt-helper</name>
+    <tizen:privilege name="http://tizen.org/privilege/bluetooth.admin"/>
+    <tizen:privilege name="http://tizen.org/privilege/bluetooth.gap"/>
+    <tizen:privilege name="http://tizen.org/privilege/bluetooth.spp"/>
+    <tizen:privilege name="http://tizen.org/privilege/tizen"/>
+</widget>
diff --git a/webWidgetTCT_device/tools/launcher/tct/install/tct-bt-helper/css/style.css b/webWidgetTCT_device/tools/launcher/tct/install/tct-bt-helper/css/style.css
new file mode 100755 (executable)
index 0000000..b97eeb9
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+
+Copyright (c) 2013 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+
+
+Authors:
+
+
+
+*/
+
+* {
+    font-family: Lucida Sans, Arial, Helvetica, sans-serif;
+}
+
+body {
+    margin: 0px auto;
+}
+
+header h1 {
+    font-size: 36px;
+    margin: 0px;
+}
+
+header h2 {
+    font-size: 18px;
+    margin: 0px;
+    color: #888;
+    font-style: italic;
+}
+
+article select {
+    width: 150px;
+}
+
+article p {
+    clear: both;
+}
+
+article > section form {
+    border: 1px solid #888;
+    -moz-border-radius: 10px;
+    -webkit-border-radius: 10px;
+    border-radius: 10px;    
+    -moz-box-shadow: 10px 10px 5px #888;
+    -webkit-box-shadow: 10px 10px 5px #888;
+    box-shadow: 10px 10px 5px #888;
+    background-color: #eee;
+    padding: 10px;
+    margin-bottom: 30px;
+}
+
+article > section label {
+    font-weight: bold;
+    font-size: 13px;
+}
+
+article > section input {
+    margin-bottom: 3px;
+    font-size: 13px;
+}
+
+#serviceTxt {
+    width: 300px;
+}
+
+footer p {
+    text-align: center;
+    font-size: 12px;
+    color: #888;
+    margin-top: 24px;
+}
+
diff --git a/webWidgetTCT_device/tools/launcher/tct/install/tct-bt-helper/icon.png b/webWidgetTCT_device/tools/launcher/tct/install/tct-bt-helper/icon.png
new file mode 100755 (executable)
index 0000000..c22cfa8
Binary files /dev/null and b/webWidgetTCT_device/tools/launcher/tct/install/tct-bt-helper/icon.png differ
diff --git a/webWidgetTCT_device/tools/launcher/tct/install/tct-bt-helper/images/tizen_32.png b/webWidgetTCT_device/tools/launcher/tct/install/tct-bt-helper/images/tizen_32.png
new file mode 100755 (executable)
index 0000000..983c883
Binary files /dev/null and b/webWidgetTCT_device/tools/launcher/tct/install/tct-bt-helper/images/tizen_32.png differ
diff --git a/webWidgetTCT_device/tools/launcher/tct/install/tct-bt-helper/index.html b/webWidgetTCT_device/tools/launcher/tct/install/tct-bt-helper/index.html
new file mode 100755 (executable)
index 0000000..841ce8e
--- /dev/null
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<!--
+
+Copyright (c) 2013 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+
+
+Authors:
+    Karol Surma <k.surma@samsung.com>
+-->
+
+<html>
+<head>
+    <meta charset="utf-8" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
+    <meta name="description" content="Tizen basic template generated by Tizen Web IDE"/>
+
+    <title>tct-bt-helper</title>
+
+    <link rel="stylesheet" type="text/css" href="css/style.css"/>
+    <script src="js/main.js"></script>
+</head>
+
+<body>
+  <header>
+    <hgroup>
+      <h1>Bluetooth</h1>
+      <h2>tct-bt-helper</h2>
+    </hgroup>
+  </header>
+
+
+  <article>
+    <p>Service UUID</p>
+    <div id="serviceUUID">
+        <input type="text" id="serviceTxt" value="5BCE9431-6C75-32AB-AFE0-2EC108A30860">
+    </div>
+    <div id="registerSection">
+      <button onclick="registerService();">Register service</button>
+      &nbsp;&nbsp; 
+      <button onclick="unregisterService();">Unregister service</button>
+    </div>
+    <div id="discoverSection">
+      <p>Bluetooth device list</p>
+      <select id="devicesList" >
+      </select>
+      <button onclick="discover();">Search</button>
+    </div>    
+    <div id="connectService">
+      <p>Connect to service</p>
+      <button onclick="connectService();">Connect to service</button>
+    </div>
+  </article>
+
+  <footer>
+    <p>&copy; 2013 Samsung. All rights reserved.</p>
+  </footer>    
+</body>
+</html>
diff --git a/webWidgetTCT_device/tools/launcher/tct/install/tct-bt-helper/js/main.js b/webWidgetTCT_device/tools/launcher/tct/install/tct-bt-helper/js/main.js
new file mode 100755 (executable)
index 0000000..89d08bf
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+
+Copyright (c) 2013 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+
+
+Authors:
+
+
+
+*/
+
+var serviceHandler = null;
+
+function discoverDevicesError() {
+    alert("Error discoverDevices");
+}
+
+function setPoweredError() {
+    alert("Error setPowered");
+}
+
+function startDiscoveryDevice() {
+    var length, k;
+    alert("searching - it's gona take about 10 seconds");
+    var discoverDevicesSuccessCallback = {
+            onstarted: function() {
+            },
+            ondevicefound: function(device) {
+            },
+            ondevicedisappeared: function(address) {
+            },
+            onfinished: function(devices) {
+                length = devices.length;
+                document.getElementById("devicesList").options.length = 0;
+                for (k = 0; k < length; k++) {
+                    document.getElementById("devicesList").options[k] = new Option(devices[k].address + " - " + devices[k].name, devices[k].address);
+                }
+                alert("search completed");
+            }
+        };
+    adapter.discoverDevices(discoverDevicesSuccessCallback, discoverDevicesError);
+}
+
+function registerServiceSuccessCallback(handler) {
+    serviceHandler = handler;
+    handler.onconnect = function(socket) {
+        var textmsg = "Test", sendtextmsg = [], length, i;
+        length = textmsg.length;
+        for (i = 0; i < length; i++) {
+            sendtextmsg[i] = textmsg.charCodeAt(i);
+        }
+        socket.writeData(sendtextmsg);
+    }
+    alert("service registered");
+}
+
+function registerServiceError() {
+    alert("Error registerService");
+}
+
+function startRegisterService() {
+    adapter.registerRFCOMMServiceByUUID(document.getElementById("serviceTxt").value,"Chat service",registerServiceSuccessCallback,registerServiceError);
+}
+
+function discover() {
+    adapter = tizen.bluetooth.getDefaultAdapter();
+    adapter.setPowered(true, startDiscoveryDevice, setPoweredError)
+}
+
+function registerService() {
+    adapter = tizen.bluetooth.getDefaultAdapter();
+    adapter.setPowered(true,startRegisterService,setPoweredError);
+}
+
+function unregisterServiceSuccessCallback() {
+    chatServiceHandler = null;
+    alert("Service is unregistered.");
+}
+
+function unregisterServiceError() {
+    alert("Error unregisterService");
+}
+
+function unregisterService() {
+    if (serviceHandler != null) {
+         serviceHandler.unregister(unregisterServiceSuccessCallback,unregisterServiceError);
+    }
+}
+
+function createBondingError() {
+    alert("Error createBonding");
+}
+
+function getDeviceError() {
+    alert("Error getDevice");
+}
+
+function connectError() {
+    alert("Error connectToServiceByUUID");
+}
+
+function connectCallback(device) {
+    if (device != null && device.uuids.indexOf(document.getElementById("serviceTxt").value) !== -1) {
+        // open socket
+            device.connectToServiceByUUID(document.getElementById("serviceTxt").value, function() {
+                alert("connected");
+            },connectError);
+    } else {
+        alert("device UUID is null");
+    }
+}
+
+function getDeviceCallback() {
+    adapter.getDevice(document.getElementById("devicesList").value, connectCallback, getDeviceError);
+}
+
+function createBondingCallback() {
+    adapter.createBonding(document.getElementById("devicesList").value, getDeviceCallback, createBondingError);
+}
+
+function connectService() {
+    adapter = tizen.bluetooth.getDefaultAdapter();
+    adapter.setPowered(true, createBondingCallback, setPoweredError);
+}
diff --git a/webWidgetTCT_device/tools/launcher/tct/push/TCTAppInfoEventTest1/config.xml b/webWidgetTCT_device/tools/launcher/tct/push/TCTAppInfoEventTest1/config.xml
new file mode 100755 (executable)
index 0000000..4c39cd5
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<widget xmlns="http://www.w3.org/ns/widgets" xmlns:tizen="http://tizen.org/ns/widgets" id="http://tizen.org/TCTAppInfoEventTest" version="1.0.0" viewmodes="maximized">
+    <access origin="*" subdomains="true"/>
+    <tizen:application id="api1appli3.TCTAppInfoEventTest" package="api1appli3" required_version="2.2"/>
+    <content src="index.html"/>
+    <icon src="icon.png"/>
+    <name>TCTAppInfoEventTest1</name>
+    <tizen:setting screen-orientation="landscape" background-support="enable"/>
+</widget>
diff --git a/webWidgetTCT_device/tools/launcher/tct/push/TCTAppInfoEventTest1/css/style.css b/webWidgetTCT_device/tools/launcher/tct/push/TCTAppInfoEventTest1/css/style.css
new file mode 100755 (executable)
index 0000000..63e4bfb
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+
+Copyright (c) 2013 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+
+
+Authors:
+            Junghyuk Park <junghyuk.park@samsung.com>
+
+
+*/
+
+* {
+    font-family: Lucida Sans, Arial, Helvetica, sans-serif;
+}
+
+body {
+    margin: 0px auto;
+}
+
+header h1 {
+    font-size: 36px;
+    margin: 0px;
+}
+
+header h2 {
+    font-size: 18px;
+    margin: 0px;
+    color: #888;
+    font-style: italic;
+}
+
+nav ul {
+    list-style: none;
+    padding: 0px;
+    display: block;
+    clear: right;
+    background-color: #666;
+    padding-left: 4px;
+    height: 24px;
+}
+
+nav ul li {
+    display: inline;
+    padding: 0px 20px 5px 10px;
+    height: 24px;
+    border-right: 1px solid #ccc;
+}
+
+nav ul li a {
+    color: #EFD3D3;
+    text-decoration: none;
+    font-size: 13px;
+    font-weight: bold;
+}
+
+nav ul li a:hover {
+    color: #fff;
+}
+
+article > header h1 {
+    font-size: 20px;
+    margin-left: 14px;
+}
+
+article > header h1 a {
+    color: #993333;
+}
+
+article > header h1 img {
+    vertical-align:middle;
+}
+
+article > section header h1 {
+    font-size: 16px;
+}
+
+article p {
+    clear: both;
+}
+
+footer p {
+    text-align: center;
+    font-size: 12px;
+    color: #888;
+    margin-top: 24px;
+}
diff --git a/webWidgetTCT_device/tools/launcher/tct/push/TCTAppInfoEventTest1/icon.png b/webWidgetTCT_device/tools/launcher/tct/push/TCTAppInfoEventTest1/icon.png
new file mode 100755 (executable)
index 0000000..c22cfa8
Binary files /dev/null and b/webWidgetTCT_device/tools/launcher/tct/push/TCTAppInfoEventTest1/icon.png differ
diff --git a/webWidgetTCT_device/tools/launcher/tct/push/TCTAppInfoEventTest1/index.html b/webWidgetTCT_device/tools/launcher/tct/push/TCTAppInfoEventTest1/index.html
new file mode 100755 (executable)
index 0000000..1a0246a
--- /dev/null
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+
+<!--
+
+Copyright (c) 2013 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+
+
+Authors:
+            Junghyuk Park <junghyuk.park@samsung.com>
+
+
+-->
+
+<html>
+<head>
+    <meta charset="utf-8" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
+    <meta name="description" content="tct-application-tizen-tests"/>
+
+    <title>TCTAppInfoEventTest</title>
+
+    <link rel="stylesheet" type="text/css" href="css/style.css"/>
+</head>
+
+<body>
+  <header>
+    <hgroup>
+      <h1>TCTAppInfoEventTest</h1>
+      <h2>index.html</h2>
+    </hgroup>
+  </header>
+</body>
+</html>
diff --git a/webWidgetTCT_device/tools/launcher/tct/push/TCTAppInfoEventTest2/config.xml b/webWidgetTCT_device/tools/launcher/tct/push/TCTAppInfoEventTest2/config.xml
new file mode 100755 (executable)
index 0000000..6feaa7a
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<widget xmlns="http://www.w3.org/ns/widgets" xmlns:tizen="http://tizen.org/ns/widgets" id="http://tizen.org/TCTAppInfoEventTest" version="2.0.0" viewmodes="maximized">
+    <access origin="*" subdomains="true"/>
+    <tizen:application id="api1appli3.TCTAppInfoEventTest" package="api1appli3" required_version="2.2"/>
+    <content src="index.html"/>
+    <icon src="icon.png"/>
+    <name>TCTAppInfoEventTest2</name>
+    <tizen:setting screen-orientation="landscape" background-support="enable"/>
+</widget>
diff --git a/webWidgetTCT_device/tools/launcher/tct/push/TCTAppInfoEventTest2/css/style.css b/webWidgetTCT_device/tools/launcher/tct/push/TCTAppInfoEventTest2/css/style.css
new file mode 100755 (executable)
index 0000000..63e4bfb
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+
+Copyright (c) 2013 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+
+
+Authors:
+            Junghyuk Park <junghyuk.park@samsung.com>
+
+
+*/
+
+* {
+    font-family: Lucida Sans, Arial, Helvetica, sans-serif;
+}
+
+body {
+    margin: 0px auto;
+}
+
+header h1 {
+    font-size: 36px;
+    margin: 0px;
+}
+
+header h2 {
+    font-size: 18px;
+    margin: 0px;
+    color: #888;
+    font-style: italic;
+}
+
+nav ul {
+    list-style: none;
+    padding: 0px;
+    display: block;
+    clear: right;
+    background-color: #666;
+    padding-left: 4px;
+    height: 24px;
+}
+
+nav ul li {
+    display: inline;
+    padding: 0px 20px 5px 10px;
+    height: 24px;
+    border-right: 1px solid #ccc;
+}
+
+nav ul li a {
+    color: #EFD3D3;
+    text-decoration: none;
+    font-size: 13px;
+    font-weight: bold;
+}
+
+nav ul li a:hover {
+    color: #fff;
+}
+
+article > header h1 {
+    font-size: 20px;
+    margin-left: 14px;
+}
+
+article > header h1 a {
+    color: #993333;
+}
+
+article > header h1 img {
+    vertical-align:middle;
+}
+
+article > section header h1 {
+    font-size: 16px;
+}
+
+article p {
+    clear: both;
+}
+
+footer p {
+    text-align: center;
+    font-size: 12px;
+    color: #888;
+    margin-top: 24px;
+}
diff --git a/webWidgetTCT_device/tools/launcher/tct/push/TCTAppInfoEventTest2/icon.png b/webWidgetTCT_device/tools/launcher/tct/push/TCTAppInfoEventTest2/icon.png
new file mode 100755 (executable)
index 0000000..c22cfa8
Binary files /dev/null and b/webWidgetTCT_device/tools/launcher/tct/push/TCTAppInfoEventTest2/icon.png differ
diff --git a/webWidgetTCT_device/tools/launcher/tct/push/TCTAppInfoEventTest2/index.html b/webWidgetTCT_device/tools/launcher/tct/push/TCTAppInfoEventTest2/index.html
new file mode 100755 (executable)
index 0000000..1a0246a
--- /dev/null
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+
+<!--
+
+Copyright (c) 2013 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+
+
+Authors:
+            Junghyuk Park <junghyuk.park@samsung.com>
+
+
+-->
+
+<html>
+<head>
+    <meta charset="utf-8" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
+    <meta name="description" content="tct-application-tizen-tests"/>
+
+    <title>TCTAppInfoEventTest</title>
+
+    <link rel="stylesheet" type="text/css" href="css/style.css"/>
+</head>
+
+<body>
+  <header>
+    <hgroup>
+      <h1>TCTAppInfoEventTest</h1>
+      <h2>index.html</h2>
+    </hgroup>
+  </header>
+</body>
+</html>
diff --git a/webWidgetTCT_device/tools/launcher/tct/push/TCTPackageManagerTest1.1.1/config.xml b/webWidgetTCT_device/tools/launcher/tct/push/TCTPackageManagerTest1.1.1/config.xml
new file mode 100755 (executable)
index 0000000..464740e
--- /dev/null
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<widget xmlns="http://www.w3.org/ns/widgets" xmlns:tizen="http://tizen.org/ns/widgets" id="http://tizen.org/TCTPackageManagerTest" version="1.1.1" viewmodes="maximized">
+    <access origin="*" subdomains="true"/>
+    <tizen:application id="api1pack10.TCTPackageManagerTest" package="api1pack10" required_version="2.2"/>
+    <author>The author of TCTPackageManagerTest</author>
+    <content src="index.html"/>
+    <description>The description of TCTPackageManagerTest</description>
+    <icon src="icon.png"/>
+    <name>TCTPackageManagerTest</name>
+    <tizen:setting screen-orientation="landscape" background-support="enable"/>
+</widget>
diff --git a/webWidgetTCT_device/tools/launcher/tct/push/TCTPackageManagerTest1.1.1/css/style.css b/webWidgetTCT_device/tools/launcher/tct/push/TCTPackageManagerTest1.1.1/css/style.css
new file mode 100755 (executable)
index 0000000..1c64069
--- /dev/null
@@ -0,0 +1,75 @@
+* {
+    font-family: Lucida Sans, Arial, Helvetica, sans-serif;
+}
+
+body {
+    margin: 0px auto;
+}
+
+header h1 {
+    font-size: 36px;
+    margin: 0px;
+}
+
+header h2 {
+    font-size: 18px;
+    margin: 0px;
+    color: #888;
+    font-style: italic;
+}
+
+nav ul {
+    list-style: none;
+    padding: 0px;
+    display: block;
+    clear: right;
+    background-color: #666;
+    padding-left: 4px;
+    height: 24px;
+}
+
+nav ul li {
+    display: inline;
+    padding: 0px 20px 5px 10px;
+    height: 24px;
+    border-right: 1px solid #ccc;
+}
+
+nav ul li a {
+    color: #EFD3D3;
+    text-decoration: none;
+    font-size: 13px;
+    font-weight: bold;
+}
+
+nav ul li a:hover {
+    color: #fff;
+}
+
+article > header h1 {
+    font-size: 20px;
+    margin-left: 14px;
+}
+
+article > header h1 a {
+    color: #993333;
+}
+
+article > header h1 img {
+    vertical-align:middle;
+}
+
+article > section header h1 {
+    font-size: 16px;
+}
+
+article p {
+    clear: both;
+}
+
+footer p {
+    text-align: center;
+    font-size: 12px;
+    color: #888;
+    margin-top: 24px;
+}
diff --git a/webWidgetTCT_device/tools/launcher/tct/push/TCTPackageManagerTest1.1.1/icon.png b/webWidgetTCT_device/tools/launcher/tct/push/TCTPackageManagerTest1.1.1/icon.png
new file mode 100755 (executable)
index 0000000..c22cfa8
Binary files /dev/null and b/webWidgetTCT_device/tools/launcher/tct/push/TCTPackageManagerTest1.1.1/icon.png differ
diff --git a/webWidgetTCT_device/tools/launcher/tct/push/TCTPackageManagerTest1.1.1/index.html b/webWidgetTCT_device/tools/launcher/tct/push/TCTPackageManagerTest1.1.1/index.html
new file mode 100755 (executable)
index 0000000..355082a
--- /dev/null
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<!--
+
+Copyright (c) 2013 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+
+
+Authors:
+    Andrzej Krolikowski <a.krolikowsk@samsung.com>
+
+
+-->
+
+<html>
+<head>
+    <meta charset="utf-8" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
+    <meta name="description" content="tct-application-tizen-tests"/>
+
+    <title>TCTPackageManagerTest</title>
+
+    <link rel="stylesheet" type="text/css" href="css/style.css"/>
+</head>
+
+<body>
+  <header>
+    <hgroup>
+      <h1>TCTPackageManagerTest</h1>
+      <h2>version 1.1.1</h2>
+    </hgroup>
+  </header>
+</body>
+</html>
diff --git a/webWidgetTCT_device/tools/launcher/tct/push/TCTPackageManagerTest2.2.2/config.xml b/webWidgetTCT_device/tools/launcher/tct/push/TCTPackageManagerTest2.2.2/config.xml
new file mode 100755 (executable)
index 0000000..7b3cb6d
--- /dev/null
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<widget xmlns="http://www.w3.org/ns/widgets" xmlns:tizen="http://tizen.org/ns/widgets" id="http://tizen.org/TCTPackageManagerTest" version="2.2.2" viewmodes="maximized">
+    <access origin="*" subdomains="true"/>
+    <tizen:application id="api1pack10.TCTPackageManagerTest" package="api1pack10" required_version="2.2"/>
+    <author>The author of TCTPackageManagerTest</author>
+    <content src="index.html"/>
+    <description>The description of TCTPackageManagerTest</description>
+    <icon src="icon.png"/>
+    <name>TCTPackageManagerTest</name>
+    <tizen:setting screen-orientation="landscape" background-support="enable"/>
+</widget>
diff --git a/webWidgetTCT_device/tools/launcher/tct/push/TCTPackageManagerTest2.2.2/css/style.css b/webWidgetTCT_device/tools/launcher/tct/push/TCTPackageManagerTest2.2.2/css/style.css
new file mode 100755 (executable)
index 0000000..1c64069
--- /dev/null
@@ -0,0 +1,75 @@
+* {
+    font-family: Lucida Sans, Arial, Helvetica, sans-serif;
+}
+
+body {
+    margin: 0px auto;
+}
+
+header h1 {
+    font-size: 36px;
+    margin: 0px;
+}
+
+header h2 {
+    font-size: 18px;
+    margin: 0px;
+    color: #888;
+    font-style: italic;
+}
+
+nav ul {
+    list-style: none;
+    padding: 0px;
+    display: block;
+    clear: right;
+    background-color: #666;
+    padding-left: 4px;
+    height: 24px;
+}
+
+nav ul li {
+    display: inline;
+    padding: 0px 20px 5px 10px;
+    height: 24px;
+    border-right: 1px solid #ccc;
+}
+
+nav ul li a {
+    color: #EFD3D3;
+    text-decoration: none;
+    font-size: 13px;
+    font-weight: bold;
+}
+
+nav ul li a:hover {
+    color: #fff;
+}
+
+article > header h1 {
+    font-size: 20px;
+    margin-left: 14px;
+}
+
+article > header h1 a {
+    color: #993333;
+}
+
+article > header h1 img {
+    vertical-align:middle;
+}
+
+article > section header h1 {
+    font-size: 16px;
+}
+
+article p {
+    clear: both;
+}
+
+footer p {
+    text-align: center;
+    font-size: 12px;
+    color: #888;
+    margin-top: 24px;
+}
diff --git a/webWidgetTCT_device/tools/launcher/tct/push/TCTPackageManagerTest2.2.2/icon.png b/webWidgetTCT_device/tools/launcher/tct/push/TCTPackageManagerTest2.2.2/icon.png
new file mode 100755 (executable)
index 0000000..c22cfa8
Binary files /dev/null and b/webWidgetTCT_device/tools/launcher/tct/push/TCTPackageManagerTest2.2.2/icon.png differ
diff --git a/webWidgetTCT_device/tools/launcher/tct/push/TCTPackageManagerTest2.2.2/index.html b/webWidgetTCT_device/tools/launcher/tct/push/TCTPackageManagerTest2.2.2/index.html
new file mode 100755 (executable)
index 0000000..49eb7c0
--- /dev/null
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<!--
+
+Copyright (c) 2013 Samsung Electronics Co., Ltd.
+
+Licensed under the Apache License, Version 2.0 (the License);
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+
+
+Authors:
+    Andrzej Krolikowski <a.krolikowsk@samsung.com>
+
+
+-->
+
+<html>
+<head>
+    <meta charset="utf-8" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
+    <meta name="description" content="tct-application-tizen-tests"/>
+
+    <title>TCTPackageManagerTest</title>
+
+    <link rel="stylesheet" type="text/css" href="css/style.css"/>
+</head>
+
+<body>
+  <header>
+    <hgroup>
+      <h1>TCTPackageManagerTest</h1>
+      <h2>version 2.2.2</h2>
+    </hgroup>
+  </header>
+</body>
+</html>
diff --git a/webWidgetTCT_device/tools/launcher/utc/copy/opt/usr/media/Images/imagefile1.jpg b/webWidgetTCT_device/tools/launcher/utc/copy/opt/usr/media/Images/imagefile1.jpg
new file mode 100755 (executable)
index 0000000..68a4019
Binary files /dev/null and b/webWidgetTCT_device/tools/launcher/utc/copy/opt/usr/media/Images/imagefile1.jpg differ
diff --git a/webWidgetTCT_device/tools/launcher/utc/copy/opt/usr/media/Music/musicfile1.mp3 b/webWidgetTCT_device/tools/launcher/utc/copy/opt/usr/media/Music/musicfile1.mp3
new file mode 100755 (executable)
index 0000000..81a860f
Binary files /dev/null and b/webWidgetTCT_device/tools/launcher/utc/copy/opt/usr/media/Music/musicfile1.mp3 differ
diff --git a/webWidgetTCT_device/tools/launcher/utc/copy/opt/usr/media/Music/musicfile2.mp3 b/webWidgetTCT_device/tools/launcher/utc/copy/opt/usr/media/Music/musicfile2.mp3
new file mode 100755 (executable)
index 0000000..81a860f
Binary files /dev/null and b/webWidgetTCT_device/tools/launcher/utc/copy/opt/usr/media/Music/musicfile2.mp3 differ
diff --git a/webWidgetTCT_device/tools/launcher/utc/copy/opt/usr/media/Music/musicfile3.mp3 b/webWidgetTCT_device/tools/launcher/utc/copy/opt/usr/media/Music/musicfile3.mp3
new file mode 100755 (executable)
index 0000000..81a860f
Binary files /dev/null and b/webWidgetTCT_device/tools/launcher/utc/copy/opt/usr/media/Music/musicfile3.mp3 differ
diff --git a/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest1/app_control.html b/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest1/app_control.html
new file mode 100755 (executable)
index 0000000..825a69f
--- /dev/null
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <meta charset="utf-8" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0, target-densityDpi=device-dpi">
+    <meta name="description" content="Tizen basic template generated by Tizen Web IDE"/>
+
+    <title>Tizen basic Application UnitTest Widget</title>
+
+    <link rel="stylesheet" type="text/css" href="css/style.css"/>
+    <script type="text/javascript" src="js/app_control.js"></script>
+</head>
+
+<body>
+  <header>
+    <hgroup>
+      <h1>Tizen App Test</h1>
+    </hgroup>
+  </header>
+
+  <article>
+    <header>
+      <h1>
+        <img src="images/tizen_32.png" /> Application UnitTest 1
+      </h1>
+    </header>
+    <section>
+      <p>This is an test widget of Tizen Application Framework.</p>
+      <p>This widget is going to reply result, and die automatically.</p>
+    </section>
+    <section>
+    <h2>Logs</h2>
+      <button onclick="clearLog();">Clear logs</button>
+      <p id="log"><br/></p>
+    </section>
+  </article>
+
+  <footer>
+    <p>&copy;</p>
+  </footer>
+</body>
+</html>
diff --git a/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest1/config.xml b/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest1/config.xml
new file mode 100755 (executable)
index 0000000..f3d51ac
--- /dev/null
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<widget xmlns="http://www.w3.org/ns/widgets"
+               xmlns:tizen="http://tizen.org/ns/widgets"
+               id="http://example.org/UnitTestSE/AppTest1"
+               version="1.0.1"
+               height="200"
+               width="300"
+               viewmodes="maximized">
+       <author href="http://www.tizen.org/" email="kisubs.song@samsung.com">Kisub Song</author>
+       <content src="index.html"/>
+       <description>This widget provides application control for Tizen application unit test.</description>
+       <icon src="icon.png"/>
+       <name>TizenUnitTCApp1</name>
+       <access origin="*"/>
+
+       <tizen:application id="tizenutc01.TizenUnitTCApp1" package="tizenutc01" required_version="2.0"/>
+
+       <tizen:privilege name="http://tizen.org/privilege/log"/>
+       <tizen:setting screen-orientation="portrait" context-menu="enable" background-support="disable" encryption="disable" install-location="auto"/>  
+       <tizen:app-control>
+               <tizen:src name="app_control.html"/>
+               <tizen:operation name="http://tizen.org/appcontrol/operation/test_appcontrol_1"/>
+       </tizen:app-control>
+</widget>
diff --git a/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest1/css/style.css b/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest1/css/style.css
new file mode 100755 (executable)
index 0000000..5ccde73
--- /dev/null
@@ -0,0 +1,127 @@
+* {
+    font-family: Lucida Sans, Arial, Helvetica, sans-serif;
+}
+
+body {
+    margin: 0px auto;
+}
+
+header h1 {
+    font-size: 36px;
+    margin: 0px;
+}
+
+header h2 {
+    font-size: 18px;
+    margin: 0px;
+    color: #888;
+    font-style: italic;
+}
+
+nav ul {
+    list-style: none;
+    padding: 0px;
+    display: block;
+    clear: right;
+    background-color: #666;
+    padding-left: 4px;
+    height: 24px;
+}
+
+nav ul li {
+    display: inline;
+    padding: 0px 20px 5px 10px;
+    height: 24px;
+    border-right: 1px solid #ccc;
+}
+
+nav ul li a {
+    color: #EFD3D3;
+    text-decoration: none;
+    font-size: 13px;
+    font-weight: bold;
+}
+
+nav ul li a:hover {
+    color: #fff;
+}
+
+article > header h1 {
+    font-size: 20px;
+    margin-left: 14px;
+}
+
+article > header h1 a {
+    color: #993333;
+}
+
+article > header h1 img {
+    vertical-align:middle;
+}
+
+article > section header h1 {
+    font-size: 16px;
+}
+
+article p {
+    clear: both;
+}
+
+article > section video {
+    width: 480px;
+    height: 200px;
+}
+
+article > section div.no-html5-video,
+article > section div#no-canvas {
+    width: 480px;
+    height: 40px;
+    border: 1px solid #993333;
+    text-align: center;
+    color: #993333;
+    font-size: 13px;
+    font-style: italic;
+    background-color: #F7E9E9;
+}
+
+article > section div#no-canvas {
+    display: none;
+}
+
+article > section form {
+    border: 1px solid #888;
+    -moz-border-radius: 10px;
+    -webkit-border-radius: 10px;
+    border-radius: 10px;    
+    -moz-box-shadow: 10px 10px 5px #888;
+    -webkit-box-shadow: 10px 10px 5px #888;
+    box-shadow: 10px 10px 5px #888;
+    background-color: #eee;
+    padding: 10px;
+    margin-bottom: 30px;
+}
+
+article > section label {
+    font-weight: bold;
+    font-size: 13px;
+}
+
+article > section input {
+    margin-bottom: 3px;
+    font-size: 13px;
+}
+
+article > section button {
+    margin-bottom: 1px;
+    font-size: 13px;
+    width: 100%;
+    height: 3em;
+}
+
+footer p {
+    text-align: center;
+    font-size: 12px;
+    color: #888;
+    margin-top: 24px;
+}
+
diff --git a/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest1/icon.png b/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest1/icon.png
new file mode 100755 (executable)
index 0000000..341ea98
Binary files /dev/null and b/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest1/icon.png differ
diff --git a/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest1/images/tizen_32.png b/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest1/images/tizen_32.png
new file mode 100755 (executable)
index 0000000..5f5e981
Binary files /dev/null and b/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest1/images/tizen_32.png differ
diff --git a/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest1/index.html b/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest1/index.html
new file mode 100755 (executable)
index 0000000..e009d86
--- /dev/null
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <meta charset="utf-8" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0, target-densityDpi=device-dpi">
+    <meta name="description" content="Tizen basic template generated by Tizen Web IDE"/>
+
+    <title>Tizen Web IDE - Tizen - Tizen basic Application</title>
+
+    <link rel="stylesheet" type="text/css" href="css/style.css"/>
+    <script src="js/main.js"></script>
+</head>
+
+<body>
+  <header>
+    <hgroup>
+      <h1>Tizen App Test 1</h1>
+      <h2>This App have to be launched by UnitTest App.</h2>
+    </hgroup>
+  </header>
+
+  <nav>
+    <ul>
+       <li><a href="#">Home</a></li>
+       <li><a href="#">About Us</a></li>
+       <li><a href="#">Contact Us</a></li>
+    </ul>
+  </nav>
+
+  <article>
+    <header>
+      <h1>
+        <img src="images/tizen_32.png" /> Application Test Widget
+      </h1>
+    </header>
+    <section>
+      <p>This is an test widget of Tizen Application Framework.</p>
+      <p>The following button displays a time using JavaScript.</p>
+      <div id="divbutton1">
+        <button onclick="startTime();">Clock</button>
+      </div>
+      <div id="divbutton2">
+        <button value="exit" onclick="tizen.application.getCurrentApplication().hide()">hide</button>
+      </div>      
+      <div id="divbutton3">
+        <button value="exit" onclick="window.close()">exit : For the testing, Click hide!! not this</button>
+      </div>
+    </section>
+  </article>
+
+  <footer>
+    <p>&copy;</p>
+  </footer>    
+</body>
+</html>
diff --git a/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest1/js/app_control.js b/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest1/js/app_control.js
new file mode 100755 (executable)
index 0000000..1d1bbc8
--- /dev/null
@@ -0,0 +1,113 @@
+//Initialize function
+var init = function () {
+    // TODO:: Do your initialization job
+    console.log("init() called");
+    setTimeout(doTest, 1000);
+};
+// window.onload can work without <body onload="">
+window.onload = init;
+
+function clearLog()
+{
+       try {
+               document.getElementById('log').innerHTML = "<br/>";
+       }
+       catch(err) {
+               alert("error name: " + err.name + ", description: " + err.description + ", messsage: " + err.message);
+       }
+}
+
+function printLog(logs) {
+    try {
+        console.log(logs);
+        jsPrint(logs);
+        document.getElementById('log').innerHTML += logs + "<br/>";
+    } catch(err) {
+        alert("error name: " + err.name + ", description: " + err.description + ", messsage: " + err.message + ", code: " + err.code);
+    }
+}
+
+//getAppControl
+function showApplicationControl(appControls) {
+       printLog("appControls.length: " + appControls.length);
+       try{
+               for(var i=0; i<appControls.length; i++){
+                       printLog(
+               "operation: " + appControls[i].operation
+               + ", uri: " + appControls[i].uri
+               + ", mime: " + appControls[i].mime
+               );
+               printLog("Number of data: " + appControls[i].data.length);
+               for(j in appControls[i].data) {
+                   printLog("data[" + j + "], key: " + appControls[i].data[j].key
+                       + ", data.value: " + appControls[i].data[j].value
+                   );
+               }
+               }
+       }catch(err){
+               printLog("errorname: " + err.name + ", description: " + err.description + ", messsage: " + err.message);
+       }
+}
+
+function getAppControl(){
+       printLog("getAppControl");
+       var appControl = tizen.application.getCurrentApplication().getRequestedAppControl();
+
+       if( appControl ) {
+               showApplicationControl([appControl]);
+       } else {
+               printLog("appControl is NULL!");
+       }
+}
+
+//replyResult
+function replyResult(){
+       printLog("replyResult");
+       try{
+               var appControl = tizen.application.getCurrentApplication().getRequestedAppControl();
+
+               if( appControl ) {
+                       appControl.replyResult();
+                       printLog("reply done.");
+               } else {
+                       printLog("appControl is NULL!");
+               }
+       }catch(err) {
+               printLog("errorname: " + err.name + ", description: " + err.description + ", messsage: " + err.message);
+  }
+}
+
+//replyFailure
+function replyFailure(){
+       printLog("replyFailure");
+       try{
+               var appControl = tizen.application.getCurrentApplication().getRequestedAppControl();
+
+               if( appControl ) {
+                       appControl.replyFailure();
+                       printLog("reply failure done.");
+               } else {
+                       printLog("appControl is NULL!");
+               }
+       }catch(err) {
+               printLog("errorname: " + err.name + ", description: " + err.description + ", messsage: " + err.message);
+  }
+}
+
+function doTest() {
+
+       function appExit() {
+               printLog("Application is going to exit.")
+               //window.close();
+               tizen.application.getCurrentApplication().exit();
+       }
+       
+       printLog("Start Test");
+       try {
+               replyResult();
+               //setTimeout(appExit, 2000);
+               tizen.application.getCurrentApplication().hide();
+       } catch (e) {
+               printLog("errorname: " + err.name + ", description: " + err.description + ", messsage: " + err.message);
+       }
+}
diff --git a/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest1/js/main.js b/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest1/js/main.js
new file mode 100755 (executable)
index 0000000..88a9ab8
--- /dev/null
@@ -0,0 +1,34 @@
+var startTime;
+var checkTime;
+
+//Initialize function
+var init = function () {
+    // TODO:: Do your initialization job
+    console.log("init() called");
+    setTimeout(doMain, 1000);
+};
+// window.onload can work without <body onload="">
+window.onload = init;
+
+function startTime() {
+    var today = new Date();
+    var h = today.getHours();
+
+    var m = today.getMinutes();
+    var s = today.getSeconds();
+    m = checkTime(m);
+    s = checkTime(s);
+    document.getElementById('divbutton1').innerHTML="Current time: " + h + ":" + m + ":" + s;
+    t = setTimeout(startTime, 250);
+}
+
+function checkTime(i) {
+    if (i < 10) {
+        i="0" + i;
+    }
+    return i;
+}
+
+function doMain() {
+       tizen.application.getCurrentApplication().hide();
+}
\ No newline at end of file
diff --git a/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest2/app_control.html b/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest2/app_control.html
new file mode 100755 (executable)
index 0000000..5b3fb42
--- /dev/null
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <meta charset="utf-8" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0, target-densityDpi=device-dpi">
+    <meta name="description" content="Tizen basic template generated by Tizen Web IDE"/>
+
+    <title>Tizen basic Application UnitTest Widget</title>
+
+    <link rel="stylesheet" type="text/css" href="css/style.css"/>
+    <script type="text/javascript" src="js/app_control.js"></script>
+</head>
+
+<body>
+  <header>
+    <hgroup>
+      <h1>Tizen App Test</h1>
+    </hgroup>
+  </header>
+
+  <article>
+    <header>
+      <h1>
+        <img src="images/tizen_32.png" /> Application UnitTest 2
+      </h1>
+    </header>
+    <section>
+      <p>This is an test widget of Tizen Application Framework.</p>
+      <p>This widget is going to reply result, and die automatically.</p>
+    </section>
+    <section>
+    <h2>Logs</h2>
+      <button onclick="clearLog();">Clear logs</button>
+      <p id="log"><br/></p>
+    </section>
+  </article>
+
+  <footer>
+    <p>&copy;</p>
+  </footer>
+</body>
+</html>
diff --git a/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest2/config.xml b/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest2/config.xml
new file mode 100755 (executable)
index 0000000..c06d728
--- /dev/null
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<widget xmlns="http://www.w3.org/ns/widgets"
+               xmlns:tizen="http://tizen.org/ns/widgets"
+               id="http://example.org/UnitTestSE/AppTest2"
+               version="1.0.1"
+               height="200"
+               width="300"
+               viewmodes="maximized">
+       <author href="http://www.tizen.org/" email="kisubs.song@samsung.com">Kisub Song</author>
+       <content src="index.html"/>
+       <description>This widget provides application control for Tizen application unit test.</description>
+       <icon src="icon.png"/>
+       <name>TizenUnitTCApp2</name>  
+       <access origin="*"/>
+
+       <tizen:application id="tizenutc02.TizenUnitTCApp2" package="tizenutc02" required_version="2.0"/>
+
+       <tizen:privilege name="http://tizen.org/privilege/log"/>
+       <tizen:setting screen-orientation="portrait" context-menu="enable" background-support="disable" encryption="disable" install-location="auto"/>  
+       <tizen:app-control>
+               <tizen:src name="app_control.html"/>
+               <tizen:operation name="http://tizen.org/appcontrol/operation/test_appcontrol_2"/>
+       </tizen:app-control>
+</widget>
diff --git a/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest2/css/style.css b/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest2/css/style.css
new file mode 100755 (executable)
index 0000000..5ccde73
--- /dev/null
@@ -0,0 +1,127 @@
+* {
+    font-family: Lucida Sans, Arial, Helvetica, sans-serif;
+}
+
+body {
+    margin: 0px auto;
+}
+
+header h1 {
+    font-size: 36px;
+    margin: 0px;
+}
+
+header h2 {
+    font-size: 18px;
+    margin: 0px;
+    color: #888;
+    font-style: italic;
+}
+
+nav ul {
+    list-style: none;
+    padding: 0px;
+    display: block;
+    clear: right;
+    background-color: #666;
+    padding-left: 4px;
+    height: 24px;
+}
+
+nav ul li {
+    display: inline;
+    padding: 0px 20px 5px 10px;
+    height: 24px;
+    border-right: 1px solid #ccc;
+}
+
+nav ul li a {
+    color: #EFD3D3;
+    text-decoration: none;
+    font-size: 13px;
+    font-weight: bold;
+}
+
+nav ul li a:hover {
+    color: #fff;
+}
+
+article > header h1 {
+    font-size: 20px;
+    margin-left: 14px;
+}
+
+article > header h1 a {
+    color: #993333;
+}
+
+article > header h1 img {
+    vertical-align:middle;
+}
+
+article > section header h1 {
+    font-size: 16px;
+}
+
+article p {
+    clear: both;
+}
+
+article > section video {
+    width: 480px;
+    height: 200px;
+}
+
+article > section div.no-html5-video,
+article > section div#no-canvas {
+    width: 480px;
+    height: 40px;
+    border: 1px solid #993333;
+    text-align: center;
+    color: #993333;
+    font-size: 13px;
+    font-style: italic;
+    background-color: #F7E9E9;
+}
+
+article > section div#no-canvas {
+    display: none;
+}
+
+article > section form {
+    border: 1px solid #888;
+    -moz-border-radius: 10px;
+    -webkit-border-radius: 10px;
+    border-radius: 10px;    
+    -moz-box-shadow: 10px 10px 5px #888;
+    -webkit-box-shadow: 10px 10px 5px #888;
+    box-shadow: 10px 10px 5px #888;
+    background-color: #eee;
+    padding: 10px;
+    margin-bottom: 30px;
+}
+
+article > section label {
+    font-weight: bold;
+    font-size: 13px;
+}
+
+article > section input {
+    margin-bottom: 3px;
+    font-size: 13px;
+}
+
+article > section button {
+    margin-bottom: 1px;
+    font-size: 13px;
+    width: 100%;
+    height: 3em;
+}
+
+footer p {
+    text-align: center;
+    font-size: 12px;
+    color: #888;
+    margin-top: 24px;
+}
+
diff --git a/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest2/icon.png b/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest2/icon.png
new file mode 100755 (executable)
index 0000000..341ea98
Binary files /dev/null and b/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest2/icon.png differ
diff --git a/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest2/images/tizen_32.png b/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest2/images/tizen_32.png
new file mode 100755 (executable)
index 0000000..5f5e981
Binary files /dev/null and b/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest2/images/tizen_32.png differ
diff --git a/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest2/index.html b/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest2/index.html
new file mode 100755 (executable)
index 0000000..971d681
--- /dev/null
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <meta charset="utf-8" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0, target-densityDpi=device-dpi">
+    <meta name="description" content="Tizen basic template generated by Tizen Web IDE"/>
+
+    <title>Tizen Web IDE - Tizen - Tizen basic Application</title>
+
+    <link rel="stylesheet" type="text/css" href="css/style.css"/>
+    <script src="js/main.js"></script>
+</head>
+
+<body>
+  <header>
+    <hgroup>
+      <h1>Tizen App Test 2</h1>
+      <h2>This App have to be launched by UnitTest App.</h2>
+    </hgroup>
+  </header>
+
+  <nav>
+    <ul>
+       <li><a href="#">Home</a></li>
+       <li><a href="#">About Us</a></li>
+       <li><a href="#">Contact Us</a></li>
+    </ul>
+  </nav>
+
+  <article>
+    <header>
+      <h1>
+        <img src="images/tizen_32.png" /> Application Test Widget
+      </h1>
+    </header>
+    <section>
+      <p>This is an test widget of Tizen Application Framework.</p>
+      <p>The following button displays a time using JavaScript.</p>
+      <div id="divbutton1">
+        <button onclick="startTime();">Clock</button>
+      </div>
+      <div id="divbutton2">
+        <button value="exit" onclick="tizen.application.getCurrentApplication().hide()">hide</button>
+      </div>      
+      <div id="divbutton3">
+        <button value="exit" onclick="window.close()">exit : For the testing, Click hide!! not this</button>
+      </div>
+    </section>
+  </article>
+
+  <footer>
+    <p>&copy;</p>
+  </footer>    
+</body>
+</html>
diff --git a/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest2/js/app_control.js b/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest2/js/app_control.js
new file mode 100755 (executable)
index 0000000..1d1bbc8
--- /dev/null
@@ -0,0 +1,113 @@
+//Initialize function
+var init = function () {
+    // TODO:: Do your initialization job
+    console.log("init() called");
+    setTimeout(doTest, 1000);
+};
+// window.onload can work without <body onload="">
+window.onload = init;
+
+function clearLog()
+{
+       try {
+               document.getElementById('log').innerHTML = "<br/>";
+       }
+       catch(err) {
+               alert("error name: " + err.name + ", description: " + err.description + ", messsage: " + err.message);
+       }
+}
+
+function printLog(logs) {
+    try {
+        console.log(logs);
+        jsPrint(logs);
+        document.getElementById('log').innerHTML += logs + "<br/>";
+    } catch(err) {
+        alert("error name: " + err.name + ", description: " + err.description + ", messsage: " + err.message + ", code: " + err.code);
+    }
+}
+
+//getAppControl
+function showApplicationControl(appControls) {
+       printLog("appControls.length: " + appControls.length);
+       try{
+               for(var i=0; i<appControls.length; i++){
+                       printLog(
+               "operation: " + appControls[i].operation
+               + ", uri: " + appControls[i].uri
+               + ", mime: " + appControls[i].mime
+               );
+               printLog("Number of data: " + appControls[i].data.length);
+               for(j in appControls[i].data) {
+                   printLog("data[" + j + "], key: " + appControls[i].data[j].key
+                       + ", data.value: " + appControls[i].data[j].value
+                   );
+               }
+               }
+       }catch(err){
+               printLog("errorname: " + err.name + ", description: " + err.description + ", messsage: " + err.message);
+       }
+}
+
+function getAppControl(){
+       printLog("getAppControl");
+       var appControl = tizen.application.getCurrentApplication().getRequestedAppControl();
+
+       if( appControl ) {
+               showApplicationControl([appControl]);
+       } else {
+               printLog("appControl is NULL!");
+       }
+}
+
+//replyResult
+function replyResult(){
+       printLog("replyResult");
+       try{
+               var appControl = tizen.application.getCurrentApplication().getRequestedAppControl();
+
+               if( appControl ) {
+                       appControl.replyResult();
+                       printLog("reply done.");
+               } else {
+                       printLog("appControl is NULL!");
+               }
+       }catch(err) {
+               printLog("errorname: " + err.name + ", description: " + err.description + ", messsage: " + err.message);
+  }
+}
+
+//replyFailure
+function replyFailure(){
+       printLog("replyFailure");
+       try{
+               var appControl = tizen.application.getCurrentApplication().getRequestedAppControl();
+
+               if( appControl ) {
+                       appControl.replyFailure();
+                       printLog("reply failure done.");
+               } else {
+                       printLog("appControl is NULL!");
+               }
+       }catch(err) {
+               printLog("errorname: " + err.name + ", description: " + err.description + ", messsage: " + err.message);
+  }
+}
+
+function doTest() {
+
+       function appExit() {
+               printLog("Application is going to exit.")
+               //window.close();
+               tizen.application.getCurrentApplication().exit();
+       }
+       
+       printLog("Start Test");
+       try {
+               replyResult();
+               //setTimeout(appExit, 2000);
+               tizen.application.getCurrentApplication().hide();
+       } catch (e) {
+               printLog("errorname: " + err.name + ", description: " + err.description + ", messsage: " + err.message);
+       }
+}
diff --git a/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest2/js/main.js b/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest2/js/main.js
new file mode 100755 (executable)
index 0000000..88a9ab8
--- /dev/null
@@ -0,0 +1,34 @@
+var startTime;
+var checkTime;
+
+//Initialize function
+var init = function () {
+    // TODO:: Do your initialization job
+    console.log("init() called");
+    setTimeout(doMain, 1000);
+};
+// window.onload can work without <body onload="">
+window.onload = init;
+
+function startTime() {
+    var today = new Date();
+    var h = today.getHours();
+
+    var m = today.getMinutes();
+    var s = today.getSeconds();
+    m = checkTime(m);
+    s = checkTime(s);
+    document.getElementById('divbutton1').innerHTML="Current time: " + h + ":" + m + ":" + s;
+    t = setTimeout(startTime, 250);
+}
+
+function checkTime(i) {
+    if (i < 10) {
+        i="0" + i;
+    }
+    return i;
+}
+
+function doMain() {
+       tizen.application.getCurrentApplication().hide();
+}
\ No newline at end of file
diff --git a/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest3/app_control.html b/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest3/app_control.html
new file mode 100755 (executable)
index 0000000..075a823
--- /dev/null
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <meta charset="utf-8" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0, target-densityDpi=device-dpi">
+    <meta name="description" content="Tizen basic template generated by Tizen Web IDE"/>
+
+    <title>Tizen basic Application UnitTest Widget</title>
+
+    <link rel="stylesheet" type="text/css" href="css/style.css"/>
+    <script type="text/javascript" src="js/app_control.js"></script>
+</head>
+
+<body>
+  <header>
+    <hgroup>
+      <h1>Tizen App Test</h1>
+    </hgroup>
+  </header>
+
+  <article>
+    <header>
+      <h1>
+        <img src="images/tizen_32.png" /> Application UnitTest 3
+      </h1>
+    </header>
+    <section>
+      <p>This is an test widget of Tizen Application Framework.</p>
+      <p>This widget is going to reply result, and die automatically.</p>
+    </section>
+    <section>
+    <h2>Logs</h2>
+      <button onclick="clearLog();">Clear logs</button>
+      <p id="log"><br/></p>
+    </section>
+  </article>
+
+  <footer>
+    <p>&copy;</p>
+  </footer>
+</body>
+</html>
diff --git a/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest3/config.xml b/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest3/config.xml
new file mode 100755 (executable)
index 0000000..95264fa
--- /dev/null
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<widget xmlns="http://www.w3.org/ns/widgets"
+               xmlns:tizen="http://tizen.org/ns/widgets"
+               id="http://example.org/UnitTestSE/AppTest3"
+               version="1.0.1"
+               height="200"
+               width="300"
+               viewmodes="maximized">
+       <author href="http://www.tizen.org/" email="kisubs.song@samsung.com">Kisub Song</author>
+       <content src="index.html"/>
+       <description>This widget provides application control for Tizen application unit test.</description>
+       <icon src="icon.png"/>
+       <name>TizenUnitTCApp3</name>  
+       <access origin="*"/>
+
+       <tizen:application id="tizenutc03.TizenUnitTCApp3" package="tizenutc03" required_version="2.0"/>
+
+       <tizen:privilege name="http://tizen.org/privilege/log"/>
+       <tizen:setting screen-orientation="portrait" context-menu="enable" background-support="disable" encryption="disable" install-location="auto"/>  
+       <tizen:app-control>
+               <tizen:src name="app_control.html"/>
+               <tizen:operation name="http://tizen.org/appcontrol/operation/test_appcontrol_3"/>
+       </tizen:app-control>
+</widget>
diff --git a/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest3/css/style.css b/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest3/css/style.css
new file mode 100755 (executable)
index 0000000..5ccde73
--- /dev/null
@@ -0,0 +1,127 @@
+* {
+    font-family: Lucida Sans, Arial, Helvetica, sans-serif;
+}
+
+body {
+    margin: 0px auto;
+}
+
+header h1 {
+    font-size: 36px;
+    margin: 0px;
+}
+
+header h2 {
+    font-size: 18px;
+    margin: 0px;
+    color: #888;
+    font-style: italic;
+}
+
+nav ul {
+    list-style: none;
+    padding: 0px;
+    display: block;
+    clear: right;
+    background-color: #666;
+    padding-left: 4px;
+    height: 24px;
+}
+
+nav ul li {
+    display: inline;
+    padding: 0px 20px 5px 10px;
+    height: 24px;
+    border-right: 1px solid #ccc;
+}
+
+nav ul li a {
+    color: #EFD3D3;
+    text-decoration: none;
+    font-size: 13px;
+    font-weight: bold;
+}
+
+nav ul li a:hover {
+    color: #fff;
+}
+
+article > header h1 {
+    font-size: 20px;
+    margin-left: 14px;
+}
+
+article > header h1 a {
+    color: #993333;
+}
+
+article > header h1 img {
+    vertical-align:middle;
+}
+
+article > section header h1 {
+    font-size: 16px;
+}
+
+article p {
+    clear: both;
+}
+
+article > section video {
+    width: 480px;
+    height: 200px;
+}
+
+article > section div.no-html5-video,
+article > section div#no-canvas {
+    width: 480px;
+    height: 40px;
+    border: 1px solid #993333;
+    text-align: center;
+    color: #993333;
+    font-size: 13px;
+    font-style: italic;
+    background-color: #F7E9E9;
+}
+
+article > section div#no-canvas {
+    display: none;
+}
+
+article > section form {
+    border: 1px solid #888;
+    -moz-border-radius: 10px;
+    -webkit-border-radius: 10px;
+    border-radius: 10px;    
+    -moz-box-shadow: 10px 10px 5px #888;
+    -webkit-box-shadow: 10px 10px 5px #888;
+    box-shadow: 10px 10px 5px #888;
+    background-color: #eee;
+    padding: 10px;
+    margin-bottom: 30px;
+}
+
+article > section label {
+    font-weight: bold;
+    font-size: 13px;
+}
+
+article > section input {
+    margin-bottom: 3px;
+    font-size: 13px;
+}
+
+article > section button {
+    margin-bottom: 1px;
+    font-size: 13px;
+    width: 100%;
+    height: 3em;
+}
+
+footer p {
+    text-align: center;
+    font-size: 12px;
+    color: #888;
+    margin-top: 24px;
+}
+
diff --git a/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest3/icon.png b/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest3/icon.png
new file mode 100755 (executable)
index 0000000..341ea98
Binary files /dev/null and b/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest3/icon.png differ
diff --git a/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest3/images/tizen_32.png b/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest3/images/tizen_32.png
new file mode 100755 (executable)
index 0000000..5f5e981
Binary files /dev/null and b/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest3/images/tizen_32.png differ
diff --git a/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest3/index.html b/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest3/index.html
new file mode 100755 (executable)
index 0000000..db0c667
--- /dev/null
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <meta charset="utf-8" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0, target-densityDpi=device-dpi">
+    <meta name="description" content="Tizen basic template generated by Tizen Web IDE"/>
+
+    <title>Tizen Web IDE - Tizen - Tizen basic Application</title>
+
+    <link rel="stylesheet" type="text/css" href="css/style.css"/>
+    <script src="js/main.js"></script>
+</head>
+
+<body>
+  <header>
+    <hgroup>
+      <h1>Tizen App Test 3</h1>
+      <h2>This App have to be launched by UnitTest App.</h2>
+    </hgroup>
+  </header>
+
+  <nav>
+    <ul>
+       <li><a href="#">Home</a></li>
+       <li><a href="#">About Us</a></li>
+       <li><a href="#">Contact Us</a></li>
+    </ul>
+  </nav>
+
+  <article>
+    <header>
+      <h1>
+        <img src="images/tizen_32.png" /> Application Test Widget
+      </h1>
+    </header>
+    <section>
+      <p>This is an test widget of Tizen Application Framework.</p>
+      <p>The following button displays a time using JavaScript.</p>
+      <div id="divbutton1">
+        <button onclick="startTime();">Clock</button>
+      </div>
+      <div id="divbutton2">
+        <button value="exit" onclick="tizen.application.getCurrentApplication().hide()">hide</button>
+      </div>      
+      <div id="divbutton3">
+        <button value="exit" onclick="window.close()">exit : For the testing, Click hide!! not this</button>
+      </div>
+    </section>
+  </article>
+
+  <footer>
+    <p>&copy;</p>
+  </footer>    
+</body>
+</html>
diff --git a/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest3/js/app_control.js b/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest3/js/app_control.js
new file mode 100755 (executable)
index 0000000..355305b
--- /dev/null
@@ -0,0 +1,113 @@
+//Initialize function
+var init = function () {
+    // TODO:: Do your initialization job
+    console.log("init() called");
+    setTimeout(doTest, 1000);
+};
+// window.onload can work without <body onload="">
+window.onload = init;
+
+function clearLog()
+{
+       try {
+               document.getElementById('log').innerHTML = "<br/>";
+       }
+       catch(err) {
+               alert("error name: " + err.name + ", description: " + err.description + ", messsage: " + err.message);
+       }
+}
+
+function printLog(logs) {
+    try {
+        console.log(logs);
+        jsPrint(logs);
+        document.getElementById('log').innerHTML += logs + "<br/>";
+    } catch(err) {
+        alert("error name: " + err.name + ", description: " + err.description + ", messsage: " + err.message + ", code: " + err.code);
+    }
+}
+
+//getAppControl
+function showApplicationControl(appControls) {
+       printLog("appControls.length: " + appControls.length);
+       try{
+               for(var i=0; i<appControls.length; i++){
+                       printLog(
+               "operation: " + appControls[i].operation
+               + ", uri: " + appControls[i].uri
+               + ", mime: " + appControls[i].mime
+               );
+               printLog("Number of data: " + appControls[i].data.length);
+               for(j in appControls[i].data) {
+                   printLog("data[" + j + "], key: " + appControls[i].data[j].key
+                       + ", data.value: " + appControls[i].data[j].value
+                   );
+               }
+               }
+       }catch(err){
+               printLog("errorname: " + err.name + ", description: " + err.description + ", messsage: " + err.message);
+       }
+}
+
+function getAppControl(){
+       printLog("getAppControl");
+       var appControl = tizen.application.getCurrentApplication().getRequestedAppControl();
+
+       if( appControl ) {
+               showApplicationControl([appControl]);
+       } else {
+               printLog("appControl is NULL!");
+       }
+}
+
+//replyResult
+function replyResult(){
+       printLog("replyResult");
+       try{
+               var appControl = tizen.application.getCurrentApplication().getRequestedAppControl();
+
+               if( appControl ) {
+                       appControl.replyResult();
+                       printLog("reply done.");
+               } else {
+                       printLog("appControl is NULL!");
+               }
+       }catch(err) {
+               printLog("errorname: " + err.name + ", description: " + err.description + ", messsage: " + err.message);
+  }
+}
+
+//replyFailure
+function replyFailure(){
+       printLog("replyFailure");
+       try{
+               var appControl = tizen.application.getCurrentApplication().getRequestedAppControl();
+
+               if( appControl ) {
+                       appControl.replyFailure();
+                       printLog("reply failure done.");
+               } else {
+                       printLog("appControl is NULL!");
+               }
+       }catch(err) {
+               printLog("errorname: " + err.name + ", description: " + err.description + ", messsage: " + err.message);
+  }
+}
+
+function doTest() {
+
+       function appExit() {
+               printLog("Application is going to exit.")
+               //window.close();
+               tizen.application.getCurrentApplication().exit();
+       }
+       
+       printLog("Start Test");
+       try {
+               replyFailure();
+               //setTimeout(appExit, 2000);
+               tizen.application.getCurrentApplication().hide();
+       } catch (e) {
+               printLog("errorname: " + err.name + ", description: " + err.description + ", messsage: " + err.message);
+       }
+}
diff --git a/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest3/js/main.js b/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-AppTest3/js/main.js
new file mode 100755 (executable)
index 0000000..88a9ab8
--- /dev/null
@@ -0,0 +1,34 @@
+var startTime;
+var checkTime;
+
+//Initialize function
+var init = function () {
+    // TODO:: Do your initialization job
+    console.log("init() called");
+    setTimeout(doMain, 1000);
+};
+// window.onload can work without <body onload="">
+window.onload = init;
+
+function startTime() {
+    var today = new Date();
+    var h = today.getHours();
+
+    var m = today.getMinutes();
+    var s = today.getSeconds();
+    m = checkTime(m);
+    s = checkTime(s);
+    document.getElementById('divbutton1').innerHTML="Current time: " + h + ":" + m + ":" + s;
+    t = setTimeout(startTime, 250);
+}
+
+function checkTime(i) {
+    if (i < 10) {
+        i="0" + i;
+    }
+    return i;
+}
+
+function doMain() {
+       tizen.application.getCurrentApplication().hide();
+}
\ No newline at end of file
diff --git a/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-BT-Server/config.xml b/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-BT-Server/config.xml
new file mode 100755 (executable)
index 0000000..c1087b6
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<widget xmlns="http://www.w3.org/ns/widgets" xmlns:tizen="http://tizen.org/ns/widgets" id="http://yourdomain/UnitTestSE-BT-Server" version="1.0.0" viewmodes="maximized">
+    <tizen:application id="j25X9s8VvQ.UnitTestSEBTServer" package="j25X9s8VvQ" required_version="1.0"/>
+    <content src="index.html"/>
+    <icon src="icon.png"/>
+    <name>UnitTestSE-BT-Server</name>
+    <tizen:privilege name="http://tizen.org/privilege/bluetooth.admin"/>
+    <tizen:privilege name="http://tizen.org/privilege/bluetooth.spp"/>
+    <tizen:privilege name="http://tizen.org/privilege/bluetooth.gap"/>
+    <tizen:privilege name="http://tizen.org/privilege/bluetoothmanager"/>
+    <tizen:setting screen-orientation="portrait" context-menu="enable" background-support="enable" encryption="disable" install-location="auto"/>
+</widget>
diff --git a/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-BT-Server/css/style.css b/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-BT-Server/css/style.css
new file mode 100755 (executable)
index 0000000..3f12cd3
--- /dev/null
@@ -0,0 +1,120 @@
+* {
+    font-family: Lucida Sans, Arial, Helvetica, sans-serif;
+}
+
+body {
+    margin: 0px auto;
+}
+
+header h1 {
+    font-size: 36px;
+    margin: 0px;
+}
+
+header h2 {
+    font-size: 18px;
+    margin: 0px;
+    color: #888;
+    font-style: italic;
+}
+
+nav ul {
+    list-style: none;
+    padding: 0px;
+    display: block;
+    clear: right;
+    background-color: #666;
+    padding-left: 4px;
+    height: 24px;
+}
+
+nav ul li {
+    display: inline;
+    padding: 0px 20px 5px 10px;
+    height: 24px;
+    border-right: 1px solid #ccc;
+}
+
+nav ul li a {
+    color: #EFD3D3;
+    text-decoration: none;
+    font-size: 13px;
+    font-weight: bold;
+}
+
+nav ul li a:hover {
+    color: #fff;
+}
+
+article > header h1 {
+    font-size: 20px;
+    margin-left: 14px;
+}
+
+article > header h1 a {
+    color: #993333;
+}
+
+article > header h1 img {
+    vertical-align:middle;
+}
+
+article > section header h1 {
+    font-size: 16px;
+}
+
+article p {
+    clear: both;
+}
+
+article > section video {
+    width: 480px;
+    height: 200px;
+}
+
+article > section div.no-html5-video,
+article > section div#no-canvas {
+    width: 480px;
+    height: 40px;
+    border: 1px solid #993333;
+    text-align: center;
+    color: #993333;
+    font-size: 13px;
+    font-style: italic;
+    background-color: #F7E9E9;
+}
+
+article > section div#no-canvas {
+    display: none;
+}
+
+article > section form {
+    border: 1px solid #888;
+    -moz-border-radius: 10px;
+    -webkit-border-radius: 10px;
+    border-radius: 10px;    
+    -moz-box-shadow: 10px 10px 5px #888;
+    -webkit-box-shadow: 10px 10px 5px #888;
+    box-shadow: 10px 10px 5px #888;
+    background-color: #eee;
+    padding: 10px;
+    margin-bottom: 30px;
+}
+
+article > section label {
+    font-weight: bold;
+    font-size: 13px;
+}
+
+article > section input {
+    margin-bottom: 3px;
+    font-size: 13px;
+}
+
+footer p {
+    text-align: center;
+    font-size: 12px;
+    color: #888;
+    margin-top: 24px;
+}
+
diff --git a/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-BT-Server/icon.png b/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-BT-Server/icon.png
new file mode 100755 (executable)
index 0000000..983c883
Binary files /dev/null and b/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-BT-Server/icon.png differ
diff --git a/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-BT-Server/images/tizen_32.png b/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-BT-Server/images/tizen_32.png
new file mode 100755 (executable)
index 0000000..983c883
Binary files /dev/null and b/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-BT-Server/images/tizen_32.png differ
diff --git a/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-BT-Server/index.html b/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-BT-Server/index.html
new file mode 100755 (executable)
index 0000000..e8b625f
--- /dev/null
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <meta charset="utf-8" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
+    <meta name="description" content="Tizen basic template generated by Tizen Web IDE"/>
+
+    <title>Tizen Web IDE - Tizen - Tizen basic Application</title>
+
+    <link rel="stylesheet" type="text/css" href="css/style.css"/>
+    <script src="js/main.js"></script>
+</head>
+
+<body>
+  <header>
+    <hgroup>
+      <h1>Tizen BT Server</h1>
+      <h2></h2>
+    </hgroup>
+  </header>
+
+  <nav>
+    <ul>
+       <li><a href="#">Home</a></li>
+       <li><a href="#">About Us</a></li>
+       <li><a href="#">Contact Us</a></li>
+    </ul>
+  </nav>
+
+  <article>
+    <header>
+      <h1>
+        <img src="images/tizen_32.png" width="32"/> BT Server Widget
+      </h1>
+    </header>
+    <p>You need 2 targets:
+      <ul>
+        <li>The one runs this widget.
+        <li>After BT Server is launched successfully, the another runs BT manual tests.
+      </ul>
+    </p>
+    <section>      
+      <p>The following button will launch BT Server.</p>
+      <div id="divbutton1">
+        <button onclick="launchServer();">Launch</button>
+      </div>
+      <p>The following button will exit from this widget.</p>
+      <div id="divbutton2">
+        <button onclick="EndServer()">Exit</button>
+      </div>
+    </section>
+    <h2>Logs</h2>
+         <p id="log">logs here!<br/></p>
+  </article>
+
+  <footer>
+    <p>&copy; 2012 Company Name. All rights reserved.</p>
+  </footer>    
+</body>
+</html>
diff --git a/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-BT-Server/js/main.js b/webWidgetTCT_device/tools/launcher/utc/install/UnitTestSE-BT-Server/js/main.js
new file mode 100755 (executable)
index 0000000..016682d
--- /dev/null
@@ -0,0 +1,210 @@
+var adapter = null;
+var serverName = "UTCBTServer";
+var clientAddress = "";
+var chatServiceHandler = null;
+var receiveIndex = 0;
+var receiveMAX = 10;
+var expectedMsgFromClient = "Hi, I'm client";
+var MsgToClient = "Hi, I'm server";
+var globalSocket = null;
+var globalRegisterCB = null;
+
+function printLog(logs) {
+    try {      
+        document.getElementById('log').innerHTML += logs + "<br/>";
+        console.log(logs);
+    } catch(err) {
+        alert("error name: " + err.name + ", description: " + err.description + ", messsage: " + err.message);
+    }
+}
+
+function sendMsgData(textmsg)
+{
+       var sendtextmsg = new Array();
+
+       for (var i = 0; i < textmsg.length; i++)
+       {
+               sendtextmsg[i] = textmsg.charCodeAt(i);
+       }
+
+       if (globalSocket != null)
+       {
+               var length = globalSocket.writeData(sendtextmsg);
+
+               if (length > 0)
+               {
+                       printLog("Succeeded in writeData");
+               }
+               else
+               {
+                       printLog("writeData fail");
+               }
+       }
+       else
+       {
+               printLog("socket is not set");
+       }
+}
+
+function registerSuccessCB(handler)
+{              
+       var sendMsg = "";
+       
+       chatServiceHandler = handler;
+       printLog("Succeeded in launching BT Server");   
+       
+       chatServiceHandler.onconnect = function(socket) {               
+               printLog("server is connected with " + socket.peer.address);
+               clientAddress = socket.peer.address;
+                 
+               socket.onmessage = function() {
+                       var data = socket.readData();
+                       var recvmsg = '';
+                       
+                       for ( var i = 0; i < data.length; i++) {
+                               recvmsg += String.fromCharCode(data[i]);
+                       }
+               
+                       printLog("receive data from client : " + recvmsg + ", checkmsg : " + expectedMsgFromClient);
+                       
+                       if (expectedMsgFromClient != recvmsg)
+                       {
+                               printLog("Data is not same");
+                       }
+                       sendMsgData(MsgToClient);
+               };
+               
+               socket.onerror = function(e) {
+                       printLog("Error is occured");
+               };
+               
+               socket.onclose = function() {
+                       printLog("socket is closed");
+                       adapter.destroyBonding(
+                               clientAddress, null
+                               /*
+                               function() {
+                                       adapter.setPowered(false, 
+                                                       function() {
+                                               printLog("Succeeded in disabling BT");                                          
+                                       } , null); 
+                               }*/, null);
+               };
+               
+               globalSocket = socket;
+       };      
+}
+
+function registerErrorCB(e)
+{
+       printLog("Error in registering service: " + e.message);
+}
+
+function nameTimeout()
+{
+       adapter.setVisible(true, visibleSuccessCB, visibleErrorCB, 0);  
+}
+
+function nameSuccessCB()
+{
+       printLog("Succeeded in setting name");
+       setTimeout(nameTimeout, 1000);  
+}
+
+function nameErrorCB(e)
+{
+       printLog("Error in setting name: " + e.message);
+}
+
+function visibleTimeout()
+{
+       adapter.registerRFCOMMServiceByUUID(
+                       "5BCE9431-6C75-32AB-AFE0-2EC108A30860",
+                       "My service",
+                       registerSuccessCB, registerErrorCB);    
+}
+
+function visibleSuccessCB()
+{
+       printLog("Succeeded in setting visibility");
+       setTimeout(visibleTimeout, 1000);       
+}
+
+function visibleErrorCB(e)
+{
+       printLog("Error in setting visibility: " + e.message);
+}
+
+function poweredTimeout()
+{
+       adapter.setName(serverName, nameSuccessCB, nameErrorCB);
+}
+
+function poweredSuccessCB()
+{
+       printLog("Succeeded in enabling BT");
+       setTimeout(poweredTimeout, 1000);
+}
+
+function poweredErrorCB(e)
+{
+       printLog("Error in Enabling BT: " + e.message);
+}
+
+//Initialize function
+var init = function () {
+    printLog("init() called");
+    adapter = tizen.bluetooth.getDefaultAdapter();
+};
+
+// window.onload can work without <body onload="">
+window.onload = init;
+
+function launchServer() {
+       try {           
+           adapter.setPowered(true, poweredSuccessCB, poweredErrorCB);         
+       }
+       catch(e) {
+               printLog (err.name +": " + err.message);
+       }
+}
+
+function unregisterSuccessCB()
+{
+       printLog("Succeeded in unregistering service");
+       adapter.setPowered(false, 
+                       function() {
+                               printLog("Succeeded in disabling BT");
+                               window.close();
+                               }, 
+                       function() {
+                               printLog("Failed in disabling BT");
+                               window.close();
+                       });
+}
+
+function unregisterErrorCB(e)
+{      
+       printLog("Error in unregistering service: " + e.message);
+       adapter.setPowered(false, 
+                       function() {
+                               printLog("Succeeded in disabling BT");
+                               window.close();
+                               }, 
+                       function() {
+                               printLog("Failed in disabling BT");
+                               window.close();
+                       });
+}
+
+function EndServer() {
+       try {
+               if(chatServiceHandler != null)
+                       chatServiceHandler.unregister(unregisterSuccessCB, unregisterErrorCB);
+               else
+                       window.close();
+       }
+       catch(e) {
+               printLog (err.name +": " + err.message);
+       }       
+}
\ No newline at end of file
diff --git a/webWidgetTCT_device/tools/mergejs.py b/webWidgetTCT_device/tools/mergejs.py
new file mode 100755 (executable)
index 0000000..e88ede2
--- /dev/null
@@ -0,0 +1,94 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+
+import fileinput
+import sys
+import getopt
+import glob
+import os
+import js_minimize
+
+class Utils:
+    reqfiles = []
+    searchfile = '*_api.js'
+    startwith = "//= require('"
+    endwith = "')"
+    code = ""
+
+    @classmethod
+    def get_require(self, s):
+        try:
+            start = s.index(self.startwith) + len(self.startwith)
+            end = s.index(self.endwith, start)
+            filename = s[start:end]
+            self.reqfiles.append(filename)
+        except ValueError:
+           return ""
+
+    @classmethod
+    def find_require(self):
+        p = os.path.join('./', self.searchfile)
+        filenames = glob.glob(self.searchfile)
+        for fname in filenames:
+            with open(fname, 'r') as myfile:
+                for line in myfile:
+                    self.get_require(line)
+
+    @classmethod
+    def print_lines(self, filename):
+        with open(filename, 'r') as file:
+            for line in file:
+                self.code += line
+
+    @classmethod
+    def merge_js_files(self, path):
+        self.find_require()
+        if len(self.reqfiles) == 0:
+            s = os.path.join('./', self.searchfile)
+            sfiles = glob.glob(s)
+            for fname in sfiles:
+                self.print_lines(fname)
+        else:
+            for fname in self.reqfiles:
+                fname = os.path.join(path, fname)
+                if os.path.exists(fname):
+                    self.print_lines(fname)
+                else:
+                    print >> sys.stderr, "Required file does not exist:", fname
+
+    @classmethod
+    def minize_code(self):
+        self.code = js_minimize.minimize(self.code)
+
+    @classmethod
+    def main(self, argv):
+        path = 'js'
+        try:
+            opts, args = getopt.getopt(argv,"hf:p:",["file=", "path="])
+        except getopt.GetoptError:
+            print __file__ + ' -h'
+            sys.exit()
+        if len(argv) > 0:
+          for opt, arg in opts:
+              if opt in ("-h"):
+                  print 'Help:'
+                  print ''
+                  print __file__ + '-f <file> -p <path>'
+                  print ''
+                  print '<opt> \t <opt> \t\t <description>'
+                  print '-f \t --file \t Name of the file where script searching for require files:'
+                  print '\t \t \t ' + self.startwith + 'file_name.js' + self.endwith
+                  print '-p \t --path \t Path to "' + path + '" directory'
+                  print ''
+                  sys.exit()
+              elif opt in ("-f", "--file"):
+                  self.searchfile = arg
+              elif opt in ("-p", "--path"):
+                  path = arg
+        self.merge_js_files(path)
+        self.minize_code()
+        print self.code
+
+if Utils.__module__ == "__main__":
+    Utils.main(sys.argv[1:])
diff --git a/webWidgetTCT_device/tools/redirect-stdout.sh b/webWidgetTCT_device/tools/redirect-stdout.sh
new file mode 100755 (executable)
index 0000000..5c9d4eb
--- /dev/null
@@ -0,0 +1,20 @@
+#!/bin/sh
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# This script executes the command given as the first argument and redirects
+# the command's stdout to the file given as the second argument.
+#
+# Example: Write the text 'foo' to a file called out.txt:
+#   RedirectStdout.sh "echo foo" out.txt
+#
+# This script is invoked from iossim.gyp in order to redirect the output of
+# class-dump to a file (because gyp actions don't support redirecting output).
+
+if [ ${#} -ne 2 ] ; then
+  echo "usage: ${0} <command> <output file>"
+  exit 2
+fi
+
+exec $1 > $2
diff --git a/webWidgetTCT_device/tools/skeleton_generator/README.md b/webWidgetTCT_device/tools/skeleton_generator/README.md
new file mode 100755 (executable)
index 0000000..809780a
--- /dev/null
@@ -0,0 +1,18 @@
+## Introduction
+
+This tool allows to generate extension skeleton from WIDL file.
+
+## Requirements
+
+python-ply
+python-jinja2 >= 2.7
+
+## Usage
+
+python WAPIOven.py -d <output directory> <webidl file>
+
+ex) python WAPIOven.py -d ./tmp widls/datacontrol.widl
+
+## WIDL files for Tizen 2.3
+
+http://slp-info.sec.samsung.net/gerrit/plugins/gitiles/magnolia/doc/managed-api/+/refs/heads/task/adv/tizen_2.3/web/widl/tizen/
diff --git a/webWidgetTCT_device/tools/skeleton_generator/WAPIOven.py b/webWidgetTCT_device/tools/skeleton_generator/WAPIOven.py
new file mode 100755 (executable)
index 0000000..89f6a40
--- /dev/null
@@ -0,0 +1,392 @@
+#
+# Copyright (c) 2015 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.
+#
+
+import WebIDL
+from collections import OrderedDict
+from Queue import Queue
+from datetime import date
+import jinja2
+
+cppPrimitiveMap = {
+        'DOMString':'std::string',
+        'object':'picojson::object',
+        'boolean':'bool',
+        'byte':'double',
+        'octet':'double',
+        'short':'double',
+        'long':'double',
+        'long long': 'double',
+        'unsigned short': 'double',
+        'unsigned long': 'double',
+        'unsigned long long': 'double',
+        'float':'double',
+        'double':'double'
+        }
+
+jsPrimitiveMap = {
+        'DOMString':'STRING',
+        'object':'DICTIONARY',
+        'boolean':'BOOLEAN',
+        'byte':'BYTE',
+        'octet':'OCTET',
+        'short':'LONG',
+        'long':'LONG',
+        'long long': 'LONG_LONG',
+        'unsigned short':'UNSIGNED_LONG',
+        'unsigned long long':'UNSIGNED_LONG_LONG',
+        'float':'DOUBLE',
+        'double':'DOUBLE'
+        }
+
+class IndentPrintable(object):
+    def __init__(self, isIndent=True, tabstep=2, ignoreLF=False):
+        self.moduleName = moduleName
+        self.depth = 0
+        self.buf = ''
+        self.isIndent = isIndent
+        self.tabstep=tabstep
+        self.ignoreLF = ignoreLF
+
+    def indepth(self):
+        self.depth+=1
+
+    def outdepth(self):
+        self.depth-=1
+
+    def indent(self):
+        if self.isIndent:
+            return ''.ljust(self.depth * self.tabstep)
+        else:
+            return ''
+
+    def dprint(self, string):
+        for s in string.split('\n'):
+            self.buf += self.indent()
+            self.buf += s
+            if not self.ignoreLF:
+                self.buf += '\n'
+            else:
+                self.buf += ' '
+
+    def output(self):
+        return self.buf
+
+class Compiler(IndentPrintable):
+
+    def __init__(self, tree, indent=True, tabstep=4, ignoreLF=False):
+        super(Compiler, self).__init__(indent, tabstep, ignoreLF)
+        self.tree = tree
+        self.tplEnv = jinja2.Environment(
+                loader=jinja2.FileSystemLoader('./tpl'),
+                trim_blocks=True,
+                lstrip_blocks=True)
+
+    TODOSTR = "todo:"
+
+    def todo(self, formatstring):
+        self.dprint(("// %s " % Compiler.TODOSTR) +formatstring)
+
+    def jstype(self, t):
+        if t.name in jsPrimitiveMap:
+            return [jsPrimitiveMap[t.name]]
+
+        elif t.name in self.ctx['enum']:
+            return ['ENUM', self.ctx['enum'][t.name]]
+        elif t.name in self.ctx['typedef']:
+            t2 = self.ctx['typedef'][t.name]
+            if t2.union:
+                union_names = [x.name for x in t2.union]
+                isEnum = reduce(lambda x, y: x & y, [ x in self.ctx['enum'] for x in union_names])
+                if isEnum :
+                    enums = reduce(lambda x,y: x+y, [ self.ctx['enum'][x] for x in self.ctx['enum'] if x in union_names])
+                    return ['ENUM', enums]
+                else:
+                  types = reduce(lambda x, y: x & y, [ x in self.ctx['interfaces'] for x in union_names])
+                  return ['PLATFORM_OBJECT', types]
+            else:
+                return self.jstype(t2)
+        elif t.name in self.ctx['callback']:
+            cb = self.ctx['callback'][t.name]
+            if cb.functionOnly:
+                return ['FUNCTION']
+            else:
+                cb_ops = cb.getTypes('Operation')
+                if 'onsuccess' in cb_ops:
+                    cb.callbackType = 'success'
+                elif 'onerror' in cb_ops:
+                    cb.callbackType = 'error'
+                return ['LISTENER', [o.name for o in cb_ops]]
+        elif t.name in self.ctx['dictionary']:
+            return ['DICTIONARY']
+        elif t.name in self.ctx['interfaces']:
+            return ['PLATFORM_OBJECT', [t.name]]
+        else:
+            print "I think \"%s\" is in tizen module, generate with tizen.widl" % t.name
+            sys.exit(1)
+            return None
+
+
+    def prepare(self, module):
+        self.ctx = dict()
+        self.ctx['interfaces'] = dict()
+        self.ctx['modules'] = []
+        self.ctx['implementedObject'] = None
+        self.ctx['implementedClass'] = []
+        self.ctx['export'] = dict()
+        self.ctx['callback'] = dict()
+        self.ctx['dictionary'] = dict()
+        self.ctx['enum'] = dict()
+        self.ctx['typedef'] = dict()
+        self.ctx['activeObjects'] = set()
+        self.ctx['implementOperations'] = dict()
+        self.ctx['exportedInterface'] = []
+        #self.ctx['Tizen'] = []
+        #self.ctx['Window'] = []
+        self.ctx['cmdtable'] = dict()
+        self.ctx['exportModule'] = module
+
+        self.q = Queue()
+
+        for m in self.tree:
+            self.q.put(m)
+
+        while self.q.qsize()>0:
+            self.prepareX(self.q.get())
+
+        for m in [m for m in self.tree if m.name.lower() == module.lower()]:
+            for iface in m.getTypes('Interface'):
+                xctor = iface.constructor if hasattr(iface, 'constructor') else None
+                if xctor:
+                    xctor.primitiveArgs = [x for x in xctor.arguments if x.xtype.name in cppPrimitiveMap]
+                    attributes = iface.getTypes('Attribute')
+                    ctorArgs = [arg.name for arg in xctor.arguments] if xctor else []
+                    for attr in attributes:
+                        if attr.name in ctorArgs:
+                            attr.existIn = 'ctor'
+                        if xctor:
+                            for x in xctor.arguments:
+                                if x.xtype.name in self.ctx['interfaces'] or x.xtype.name in self.ctx['dictionary']:
+                                    argtypes = dict(self.ctx['interfaces'].items() + self.ctx['dictionary'].items())
+                                    argtype = argtypes[x.xtype.name]
+                                    for child in argtype.childs:
+                                        if child.name == attr.name:
+                                            attr.existIn = x.name + "." + child.name
+                                    break
+                if iface.inherit in [x.name for x in self.ctx['exportedInterface']]:
+                    iface.private = True
+                #if iface.name in self.ctx['callback']:
+                    #iface.isListener = True
+
+                for operation in iface.getTypes('Operation'):
+                    if hasattr(iface, 'exported') and iface.exported:
+                        operation.native_cmd = iface.name+'_'+operation.name
+                        native_function = iface.name + operation.name[0].upper() + operation.name[1:]
+                        operation.native_function = native_function
+                        #self.ctx['cmdtable'][operation.native_function] = operation.native_cmd
+                        native_cmd = iface.name+'_'+operation.name
+                        self.ctx['cmdtable'][native_function] = native_cmd
+                    operation.argnames = [a.name for a in operation.arguments]
+                    #operation.primitiveArgs = [x for x in operation.arguments if x.xtype.name in cppPrimitiveMap]
+                    operation.primitiveArgs = []
+                    for arg in operation.arguments:
+                        arg.validation = self.jstype(arg.xtype)
+                        if arg.validation:
+                            if arg.validation[0] in ['FUNCTION', 'LISTENER']:
+                                m.async = True
+                                operation.async = True
+                            elif arg.validation[0] in jsPrimitiveMap.values():
+                                operation.primitiveArgs.append(arg)
+
+                    for xiface in self.ctx['exportedInterface']:
+                        if operation.returnType.name == xiface.name:
+                            operation.returnInternal = xiface
+                            break
+
+    def prepareX(self, x):
+        if isinstance(x, WebIDL.XImplements) and (x.name in ['Tizen', 'Window']) and x.parent.name.lower() == self.ctx['exportModule'].lower():
+            self.ctx['implementedClass'].append(x.impl)
+            #self.ctx[x.name].append(x.impl)
+            impl = x.parent.get('Interface', x.impl)
+            impl.implements = x.name
+
+        if isinstance(x, WebIDL.XAttribute) and isinstance(x.parent, WebIDL.XInterface):
+            if x.parent.name in self.ctx['implementedClass']:
+                self.ctx['implementedObject'] = x.name
+                #inheritIface = x.parent.parent.get('Interface', x.xtype.name)
+                inheritIface = self.ctx['interfaces'][x.xtype.name]
+                if inheritIface :
+                    #self.ctx[x.parent.implements] = inheritIface.name
+                    inheritIface.exported = x.parent.implements
+                    self.ctx['exportedInterface'].append(inheritIface)
+
+        if isinstance(x, WebIDL.XInterface):
+            xcallback = next((a for a in x.getTypes('ExtendedAttribute') if a.name == 'Callback'), None)
+            if xcallback:
+                self.ctx['callback'][x.name] = x
+            x.functionOnly = xcallback and xcallback.identity == 'FunctionOnly'
+            self.ctx['interfaces'][x.name] = x;
+
+            xctor = next((c for c in x.getTypes('ExtendedAttribute') if c.name == 'Constructor'), None)
+            if xctor:
+                x.constructor = xctor
+                x.exported = x.name
+
+        if isinstance(x, WebIDL.XOperation):
+            module = x.parent.parent
+            #if module.get('Interface', x.returnType.name):
+            if x.returnType.name in self.ctx['interfaces']:
+                self.ctx['activeObjects'].add(x.returnType.name)
+                #inheritIface = module.get('Interface', x.returnType.name)
+                inheritIface = self.ctx['interfaces'][x.returnType.name]
+                if inheritIface :
+                    inheritIface.exported = inheritIface.name
+                    self.ctx['exportedInterface'].append(inheritIface)
+
+        if isinstance(x, WebIDL.XDictionary):
+            self.ctx['dictionary'][x.name] = x
+
+        if isinstance(x, WebIDL.XTypedef):
+            self.ctx['typedef'][x.name] = x.xtype
+
+        if isinstance(x, WebIDL.XEnum):
+            self.ctx['enum'][x.name] = x.childs
+            cppPrimitiveMap[x.name] = 'std::string'
+
+        if isinstance(x, WebIDL.XObject):
+            for child in x.childs:
+                self.q.put(child)
+
+    TPL_API_JS = "tpl_api.js"
+
+    def makeJSStub(self, module):
+        self.prepare(module)
+        tpl = self.tplEnv.get_template(Compiler.TPL_API_JS)
+
+        modules = self.tree if module == None else [m for m in self.tree if m.name.lower() == module.lower()]
+        return tpl.render({'modules':modules,
+            'callbacks':self.ctx['callback'],
+            #'tizen': self.ctx['Tizen'],
+            #'window': self.ctx['Window'],
+            'cmdtable' : self.ctx['cmdtable'],
+            'year' : date.today().year})
+
+
+    TPL_EXTENSION_H = "tpl_extension.h"
+    TPL_EXTENSION_CC = "tpl_extension.cc"
+    TPL_INSTANCE_H = "tpl_instance.h"
+    TPL_INSTANCE_CC = "tpl_instance.cc"
+
+    def makeCppStubs(self, module):
+        extension_h = self.makeCppStub(module, Compiler.TPL_EXTENSION_H)
+        extension_cc = self.makeCppStub(module, Compiler.TPL_EXTENSION_CC)
+        instance_h = self.makeCppStub(module, Compiler.TPL_INSTANCE_H)
+        instance_cc = self.makeCppStub(module, Compiler.TPL_INSTANCE_CC)
+
+        return {
+                module+'_extension.h':extension_h,
+                module+'_extension.cc':extension_cc,
+                module+'_instance.h':instance_h,
+                module+'_instance.cc':instance_cc}
+
+    def makeCppStub(self, module, tpl_file):
+        tpl = self.tplEnv.get_template(tpl_file)
+        vals = dict()
+        vals['module'] = {
+                'upper':module.upper(),
+                'lower':module.lower(),
+                'title':module.title()
+        }
+
+
+        #m = [m for m in self.tree if m.name.lower() == module.lower()]
+        m = [m for m in self.tree]
+        vals['moduleObj'] = m[0] if len(m)>0 else None
+        #vals['tizen'] = self.ctx['Tizen']
+        #vals['window'] = self.ctx['Window']
+        vals['cmdtable'] = self.ctx['cmdtable']
+        vals['year'] = date.today().year
+
+        return tpl.render(vals)
+
+import sys
+import getopt
+
+def printhelp():
+    print '%s [-t js|cpp] [-d outdirectory] [-m modulename] webidl' % sys.argv[0]
+
+if __name__ == '__main__':
+    argv = sys.argv[1:]
+    try:
+        opts, args = getopt.getopt(argv, "htm:d:")
+    except getopt.GetoptError:
+        printhelp()
+        sys.exit(2)
+
+    outDirectory = None
+    only = None
+    moduleName = None
+
+    for opt, arg in opts:
+        if opt == '-h':
+            printhelp()
+            sys.exit()
+        elif opt == '-t':
+            only = arg
+        elif opt == '-d':
+            outDirectory = arg
+        elif opt == '-m':
+            moduleName = arg
+
+    if len(args)<1:
+        printhelp()
+        sys.exit(2)
+
+    if not moduleName:
+        import os
+        basename = os.path.basename(args[0])
+        moduleName = basename[0:basename.find('.')]
+
+    widl = ""
+    for arg in args:
+        f = open(arg)
+        widl += f.read()
+        f.close()
+
+    p = WebIDL.Parser()
+    tree = p.parse(widl)
+    c = Compiler(tree)
+
+    jscode = c.makeJSStub(moduleName)
+    cppcode = c.makeCppStubs(moduleName)
+
+    if outDirectory:
+        if only != 'cpp':
+            f = open("%s/%s_api.js" % (outDirectory, moduleName), 'w')
+            f.write(jscode)
+            f.close()
+        if only != 'js':
+            for cc in cppcode:
+                f = open("%s/%s" % (outDirectory, cc), 'w')
+                f.write(cppcode[cc])
+                f.close()
+    else:
+        if only != 'cpp':
+            print jscode
+            pass
+
+        if only != 'js':
+            for cc in cppcode:
+                print cppcode[cc]
diff --git a/webWidgetTCT_device/tools/skeleton_generator/WebIDL.py b/webWidgetTCT_device/tools/skeleton_generator/WebIDL.py
new file mode 100755 (executable)
index 0000000..3b57749
--- /dev/null
@@ -0,0 +1,1263 @@
+#
+# Copyright (c) 2015 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.
+#
+
+import sys
+from pprint import pprint
+
+try:
+    import lex
+    import yacc
+except ImportError:
+    try:
+        from ply import lex
+        from ply import yacc
+    except ImportError:
+        print 'python ply is requred.'
+        sys.exit(1)
+
+class XObject(object):
+    def __init__(self):
+        self.name = ""
+        self.type = ""
+        self.typedChilds = dict()
+        self.extras = []
+        self.parent = None
+
+    def add(self, child):
+        if isinstance(child, XObject):
+            type = child.type
+            child.parent = self
+        else:
+            type = 'string'
+        if not self.typedChilds.has_key(type) or not self.typedChilds[type]:
+            self.typedChilds[type] = []
+        self.typedChilds[type].append(child)
+        #self.typedChilds.append(child)
+
+    @property
+    def childs(self):
+        cs = []
+        for t in self.typedChilds:
+            cs += self.typedChilds[t]
+        return cs
+
+    def getTypes(self, type):
+        if type in self.typedChilds:
+            return self.typedChilds[type]
+        else:
+            return []
+
+    def get(self, type, name):
+        tcs = self.typedChilds[type]
+        for o in tcs:
+            if o.name == name:
+                return o
+        return None
+
+
+class XDepthPrintable(XObject):
+    def __init__(self):
+        super(XDepthPrintable, self).__init__()
+        self.depth = 0
+
+    def add(self, child):
+        super(XDepthPrintable, self).add(child)
+        if isinstance(child, XDepthPrintable):
+            child.depth += 1
+
+
+class XType(XObject):
+    def __init__(self, name, unions=None, array=0, nullable=None, sequence=None, unsigned=None, unrestricted=None):
+        super(XType, self).__init__()
+        self.array = array
+        self.nullable = nullable
+        self.sequence = sequence
+        self.unsigned = unsigned
+        self.unrestricted = unrestricted
+        self.name = name
+
+        if isinstance(name, XType):
+            self.array += name.array
+            self.name = name.name
+            self.unsigned = name.unsigned if unsigned == None else False
+            self.sequence = name.sequence if sequence == None else False
+            self.nullable = name.nullable if nullable == None else False
+            self.unrestricted = name.unrestricted if unrestricted == None else False
+
+        self.union = []
+        if isinstance(unions, list):
+            for t in unions:
+                self.union.append(t)
+
+    def __repr__(self):
+        s = ""
+        if self.unsigned:
+            s += 'unsigned '
+
+        s += self.name
+
+        if self.union:
+            s += "("
+            s += " or ".join([repr(u) for u in self.union])
+            s += ")"
+        if self.sequence:
+            s = "sequence<"+s+">"
+        s += "?" if self.nullable else ""
+        for i in range(self.array):
+            s+= "[]"
+        return s
+
+XVoid = XType('Void')
+
+class XDefinition(XDepthPrintable):
+    def __init__(self, name, type):
+        super(XDefinition, self).__init__()
+        self.name = name
+        self.type = type
+
+    def desc(self):
+        return ""
+
+    def __repr__(self):
+        indent = "".ljust(self.depth*4)
+        s = indent + "<%s:%s %s>" % (self.type, self.name, self.desc())
+        for ch in self.childs:
+            ss = indent.ljust(4) + ch if isinstance(ch, str) else repr(ch)
+            s += "\n" + indent + ss
+        return s
+
+class XModule(XDefinition):
+    def __init__(self, name):
+        super(XModule, self).__init__(name, 'Module')
+
+class XEnum(XDefinition):
+    def __init__(self, name):
+        super(XEnum, self).__init__(name, 'Enum')
+
+class XTypedef(XDefinition):
+    def __init__(self, name, xtype):
+        super(XTypedef, self).__init__(name, 'Typedef')
+        self.xtype = xtype
+
+    def desc(self):
+        return "%s = %s" % (self.name, self.xtype)
+
+class XAttribute(XDepthPrintable):
+    def __init__(self, name, xtype, inherit=False, readonly=False):
+        super(XAttribute, self).__init__()
+        self.type = 'Attribute'
+        self.name = name
+        self.inherit = inherit
+        self.readonly = readonly
+        self.xtype = xtype
+        self.extAttr = []
+
+
+    def __repr__(self):
+        indent = "".ljust(self.depth*4)
+        s = indent+"<Attribute: %s %s>" % (self.name, self.xtype)
+        if self.readonly:
+            s += " readonly"
+        if self.inherit:
+            s += " inherit"
+        return s
+
+class XArgument(XDepthPrintable):
+    def __init__(self, name, xtype, default=None, optional=False, ellipsis=None):
+        super(XArgument, self).__init__()
+        self.name = name
+        self.xtype = xtype
+        self.default = default
+        self.optional = optional
+        self.ellipsis = ellipsis
+
+    def __repr__(self):
+        s = "optional" if self.optional else ""
+        s += " %s" % repr(self.xtype)
+        if self.ellipsis:
+            s += " ..."
+        s += " %s" % self.name
+        if self.default:
+            s += " = " + self.default
+
+        return s
+
+class XOperation(XDepthPrintable):
+    def __init__(self, name, returnType=XVoid, arguments=[], static=False, specials=[], raises=[]):
+        super(XOperation, self).__init__()
+        self.type = 'Operation'
+        self.name = name
+        self.returnType = returnType
+        self.static = static
+        self.specials = specials
+        self.arguments = arguments
+        self.raises = raises
+        self.extAttr = []
+
+    def setStatic(self, static):
+        self.static = static
+
+    def addSpecial(self, sp):
+        self.specials.append(sp)
+
+    def __repr__(self):
+        indent = "".ljust(self.depth*4)
+        args = ", ".join([repr(arg) for arg in self.arguments])
+        return indent+"<function %s(%s) : %s>" % (self.name, args, self.returnType)
+
+class XExtendedAttribute(XDepthPrintable):
+    def __init__(self, name, identity=None, arguments=[]):
+        super(XExtendedAttribute,self).__init__()
+        self.type = "ExtendedAttribute"
+        self.name = name
+        self.identity = identity
+        self.arguments = arguments
+
+    def __repr__(self):
+        indent = "".ljust(self.depth*4)
+        s = self.name
+        if self.identity:
+            s += " = %s" % self.identity
+        if self.arguments and len(self.arguments)>0:
+            s += " ("
+            s += ", ".join([x.name for x in self.arguments])
+            s += " )"
+        return indent + "<X-Attr %s>"%s
+
+class XInterface(XDefinition):
+    def __init__(self, name, inherit=None):
+        super(XInterface, self).__init__(name, 'Interface')
+        self.inherit = inherit;
+
+    def desc(self):
+        return (" : %s" % self.inherit) if self.inherit else ""
+
+
+class XImplements(XDefinition):
+    def __init__(self, name, impl):
+        super(XImplements, self).__init__(name, 'Implements')
+        self.impl = impl
+
+    def desc(self):
+        return "implements %s" % self.impl
+
+class XDictionaryMember(XDepthPrintable):
+    def __init__(self, name, xtype, default):
+        super(XDictionaryMember, self).__init__()
+        self.name = name
+        self.xtype = xtype
+        self.default = default
+
+    def __repr__(self):
+        indent = "".ljust(self.depth*4)
+        return indent + "<%s %s = %s>" % (self.xtype, self.name, self.default)
+
+class XDictionary(XDefinition):
+    def __init__(self, name, inherit=None):
+        super(XDictionary, self).__init__(name, 'Dictionary')
+        self.inherit = inherit
+
+    def desc(self):
+        return (" : %s" % self.inherit) if self.inherit else ""
+
+class XConst(XDepthPrintable):
+    def __init__(self, name, xtype, value):
+        super(XConst, self).__init__()
+        self.name = name
+        self.xtype = xtype
+        self.value = value
+
+    def __repr__(self):
+        indent = "".ljust(self.depth*4)
+        return indent + "<const %s %s = %s>" % (self.xtype, self.name, self.value)
+
+class Parser:
+    def __init__(self, debug = 0, verbose = 0):
+        self.tokens += self.argument_name_keyword + self.predefined_types
+
+        self.debug = debug
+
+        self.lex = lex.lex(module = self, debug = debug)
+        self.yacc = yacc.yacc(module = self, debug = debug)
+
+        self.verbose = verbose
+
+    def trace(self, txt):
+        if self.verbose:
+            print txt
+
+    def parse(self, webidl):
+        return self.yacc.parse(webidl, debug = self.debug, lexer = self.lex)
+
+    tokens = (
+            'integer_hex',
+            'integer_oct',
+            'integer_dec',
+            'float',
+            'identifier',
+            'string',
+            'ellipsis',
+            'scope',
+            'other'
+    )
+
+    argument_name_keyword = (
+            'module', # module is removed 2012 feb 07
+            'raises', # raises is removed 2012 feb 07
+            'setraises', # setraises is removed 2012 feb 07
+            'getraises', # getraises is removed 2012 feb 07
+            'inherits', # inherits is removed 2012 feb 07
+            'attribute',
+            'callback',
+            'const',
+            'creator',
+            'deleter',
+            'dictionary',
+            'enum',
+            'exception',
+            'getter',
+            'implements',
+            'inherit',
+            'interface',
+            'legacycaller',
+            'partial',
+            'setter',
+            'static',
+            'stringifier',
+            'typedef',
+            'unrestricted',
+            'readonly'
+    )
+
+    predefined_types = (
+            'Date',
+            'DOMString',
+            'Infinity',
+            'NaN',
+            'any',
+            'boolean',
+            'byte',
+            'double',
+            'false',
+            'long',
+            'null',
+            'object',
+            'octet',
+            'or',
+            'optional',
+            'sequence',
+            'short',
+            'true',
+            'unsigned',
+            'void'
+    )
+
+    literals = '-,:;<=>?()[]{}'
+
+    def t_newline(self, t):
+        r'\n+'
+        t.lexer.lineno += len(t.value)
+
+    t_ignore_whitespace = r'[\t\n\r ]+|[\t\n\r ]*((//.*|/\*.*?\*/)[\t\n\r ]*)+'
+
+    def t_block_comment(self, t):
+        r'/\*(.|\n)*?\*/'
+        t.lexer.lineno += t.value.count('\n')
+
+    t_ellipsis = r'\.\.\.'
+
+    t_scope = r'::'
+
+    def t_integer_hex(self, t):
+        r'-?0[xX][0-9A-F-a-f]+'
+        t.value = int(t.value, 16)
+        return t
+
+    def t_integer_oct(self, t):
+        r'-?0[0-7]+'
+        t.value = int(t.value, 8)
+        return t
+
+    def t_integer_dec(self, t):
+        r'-?[1-9][0-9]*|0'
+        t.value = int(t.value)
+        return t
+
+    '''
+    def t_integer(self, t):
+        #r'-?(0([0-7]*|[Xx][0-9A-Fa-f]+)|[1-9][0-9]*)'
+        r'-?0[0-7]+|-?0[Xx][0-9A-Fa-f]+|-?[0-9][0-9]*'
+        z = 0
+        if t.value[0] == '-':
+            z = 1
+
+        if len(t.value) > 1 and t.value[z] == '0' and (t.value[z+1] == 'x' or t.value[z+1] == 'X'):
+            if t.value[z+2:].find('8') and t.value[z+2:].find('9'):
+                t.value = int(t.value, 8)
+            else:
+                t.value = int(t.value, 16)
+        else:
+            t.value = int(t.value)
+        return t
+    '''
+
+    def t_float(self, t):
+        r'-?(([0-9]+\.[0-9]*|[0-9]*\.[0-9]+)([Ee][+-]?[0-9]+)?|[0-9]+[Ee][+-]?[0-9]+)'
+        t.value = float(t.value)
+        return t
+
+    def t_string(self, t):
+        r'"[^"]*"'
+        t.value = t.value[1:-1]
+        return t
+
+    def t_identifier(self, t):
+        r'[A-Z_a-z][0-9A-Z_a-z]*'
+        if t.value in self.argument_name_keyword + self.predefined_types:
+            t.type = t.value
+        if t.value == 'true':
+            t.value = True
+        if t.value == 'false':
+            t.value = False
+        if t.value == 'null':
+            t.value = None
+        return t
+
+    def t_error(self, t):
+        print "Illegal character '%s'" % t.value[0]
+        t.lexer.skip(1)
+
+    def p_Definitions(self, p):
+        '''
+        Definitions : ExtendedAttributeList Definition Definitions
+                    | Empty
+        '''
+
+        if len(p) > 2:
+            d = p[2]
+            for extattr in p[1]:
+                d.add(extattr[0])
+            p[0] = [d] + p[3]
+        else:
+            p[0] = []
+
+    def p_Definition(self, p):
+        '''
+        Definition : Module
+                   | CallbackOrInterface
+                   | Partial
+                   | Dictionary
+                   | Exception
+                   | Enum
+                   | Typedef
+                   | ImplementsStatement
+        '''
+        p[0] = p[1]
+
+    def p_Module(self, p):
+        'Module : module identifier "{" Definitions "}" ";"'
+        module = XModule(p[2])
+        for d in p[4]:
+            module.add(d)
+
+        p[0] = module
+
+    def p_CallbackOrInterface(self, p):
+        '''
+        CallbackOrInterface : callback CallbackRestOrInterface
+                            | Interface
+        '''
+        if len(p) > 2:
+            p[0] = ['callback', p[2]]
+        else:
+            p[0] = p[1]
+
+    def p_CallbackRestOrInterface(self, p):
+        '''
+        CallbackRestOrInterface : CallbackRest
+                                | Interface
+        '''
+        p[0] = p[1]
+
+    def p_Interface(self, p):
+        'Interface : interface identifier Inheritance "{" InterfaceMembers "}" ";"'
+        interface = XInterface(p[2], p[3])
+        for member in p[5]:
+            interface.add(member)
+        p[0] = interface
+
+    def p_Partial(self, p):
+        'Partial : partial PartialDefinition'
+        p[1][0] = 'partial ' + p[1][0]
+        p[0] = p[1]
+
+    def p_PartialDefinition(self, p):
+        '''
+        PartialDefinition : PartialInterface
+                           | PartialDictionary
+        '''
+        p[0] = p[1]
+
+    def p_PartialInterface(self, p):
+        'PartialInterface : interface identifier "{" InterfaceMembers "}" ";"'
+        p[0] = ['interface', p[2], p[4]]
+
+    def p_InterfaceMembers(self, p):
+        '''
+        InterfaceMembers : ExtendedAttributeList InterfaceMember InterfaceMembers
+                         | Empty
+        '''
+        if len(p) > 2:
+            member = p[2]
+            for extattr in p[1]:
+                member.add(extattr)
+            p[0] = [member] + p[3]
+        else:
+            p[0] = []
+
+    def p_InterfaceMember(self, p):
+        '''
+        InterfaceMember : Const
+                        | AttributeOrOperation
+        '''
+        p[0] = p[1]
+
+    def p_Dictionary(self, p):
+        'Dictionary : dictionary identifier Inheritance "{" DictionaryMembers "}" ";"'
+        dictionary = XDictionary(p[2], p[3])
+        for m in p[5]:
+            dictionary.add(m)
+        p[0] = dictionary
+
+    def p_DictionaryMembers(self, p):
+        '''
+        DictionaryMembers : ExtendedAttributeList DictionaryMember DictionaryMembers
+                          | Empty
+        '''
+        if p[1] != None:
+            p[0] = [p[2]] + p[3]
+        else:
+            p[0] = []
+
+    def p_DictionaryMember(self, p):
+        'DictionaryMember : Type identifier Default ";"'
+        p[0] = XDictionaryMember(p[2], p[1], p[3])
+
+    def p_PartialDictionary(self, p):
+        'PartialDictionary : dictionary identifier "{" DictionaryMembers "}" ";"'
+        p[0] = ['dictinary', p[2], p[4]]
+
+    def p_Default(self, p):
+        '''
+        Default : "=" DefaultValue
+                | Empty
+        '''
+        p[0] = p[1]
+
+    def p_DefaultValue(self, p):
+        '''
+        DefaultValue : ConstValue
+                     | string
+        '''
+        p[0] = p[1]
+
+    def p_Exception(self, p):
+        'Exception : exception identifier Inheritance "{" ExceptionMembers "}" ";"'
+        p[0] = ['exception', p[2], p[5]]
+
+    def p_ExceptionMembers(self, p):
+        '''
+        ExceptionMembers : ExtendedAttributeList ExceptionMember ExceptionMembers
+                         | Empty
+        '''
+        p[0] = [p[2]] + p[3]
+
+    def p_Inheritance(self, p):
+        '''
+        Inheritance : ":" identifier
+                    | Empty
+        '''
+        if len(p) > 2:
+            p[0] = p[2]
+        else:
+            p[0] = []
+
+    def p_Enum(self, p):
+        'Enum : enum identifier "{" EnumValueList "}" ";"'
+        enum = XEnum(p[2])
+        for e in p[4]:
+            enum.add(e)
+        p[0] = enum
+
+    def p_EnumValueList(self, p):
+        'EnumValueList : string EnumValues'
+        p[0] = [p[1]] + p[2]
+
+    def p_EnumValues(self, p):
+        '''
+        EnumValues : "," string EnumValues
+                   | Empty
+        '''
+        if len(p) > 2:
+            p[0] = [p[2]] + p[3]
+        else:
+            p[0] = []
+
+    def p_CallbackRest(self, p):
+        'CallbackRest : identifier "=" ReturnType "{" ArgumentList "}" ";"'
+        p[0] = ['callback', p[1], '????']
+
+    def p_Typedef(self, p):
+        'Typedef : typedef ExtendedAttributeList Type identifier ";"'
+        typedef = XTypedef(p[4], p[3])
+        for exattr in p[2]:
+            typedef.add(exattr)
+        p[0] = typedef
+
+    def p_ImplementsStatement(self, p):
+        'ImplementsStatement : identifier implements identifier ";"'
+        p[0] = XImplements(p[1], p[3])
+
+    def p_Const(self, p):
+        'Const : const ConstType identifier "=" ConstValue ";"'
+        p[0] = XConst(p[3], p[2], p[5])
+        #p[0] = ['const', p[3], p[5]]
+
+    def p_ConstValue(self, p):
+        '''
+        ConstValue : BooleanLiteral
+                   | FloatLiteral
+                   | integer
+                   | null
+        '''
+        p[0] = p[1]
+
+    def p_BooleanLiteral(self, p):
+        '''
+        BooleanLiteral : true
+                       | false
+        '''
+        p[0] = p[1]
+
+    def p_FloatLiteral(self, p):
+        '''
+        FloatLiteral : float
+                     | "-" Infinity
+                     | Infinity
+                     | NaN
+        '''
+        p[0] = p[1]
+
+    def p_integer(self, p):
+        '''
+        integer : integer_hex
+                | integer_oct
+                | integer_dec
+        '''
+        p[0] = p[1]
+
+    def p_AttributeOrOperation(self, p):
+        '''
+        AttributeOrOperation : stringifier StringifierAttributeOrOperation
+                             | Attribute
+                             | Operation
+        '''
+        if len(p) > 2:
+            p[0] = p[2]
+        else:
+            p[0] = p[1]
+
+    def p_StringifierAttributeOrOperation(self, p):
+        '''
+        StringifierAttributeOrOperation : Attribute
+                                        | OperationRest
+                                        | ";"
+        '''
+        if p[1] != ';':
+            p[0] = p[1]
+        else:
+            pass
+
+    def p_Attribute(self, p):
+        'Attribute : Inherit ReadOnly attribute Type identifier GetRaises SetRaises Raises ";"'
+        p[0] = XAttribute(p[5], p[4], p[1], p[2])
+
+    def p_Inherit(self, p):
+        '''
+        Inherit : inherit
+                | Empty
+        '''
+        p[0] = p[1]
+
+    def p_ReadOnly(self, p):
+        '''
+        ReadOnly : readonly
+                 | Empty
+        '''
+        p[0] = p[1]
+
+    def p_Operation(self, p):
+        'Operation : Qualifiers OperationRest'
+
+        operation = p[2]
+        operation.setStatic(p[1] == 'static')
+        if isinstance(p[1], list):
+            for sp in p[1]:
+                operation.addSpecial(sp)
+
+        p[0] = operation
+
+
+    def p_Qualifiers(self, p):
+        '''
+        Qualifiers : static
+                   | Specials
+        '''
+        p[0] = p[1]
+
+    def p_Specials(self, p):
+        '''
+        Specials : Special Specials
+                 | Empty
+        '''
+        if len(p) > 2:
+            p[0] = p[1] + p[2]
+        else:
+            p[0] = []
+
+    def p_Special(self, p):
+        '''
+        Special : getter
+                | setter
+                | creator
+                | deleter
+                | legacycaller
+        '''
+        p[0] = p[1]
+
+    def p_GetRaises(self, p):
+        '''
+        GetRaises : getraises ExceptionList
+                  | Empty
+        '''
+        if len(p) > 2:
+            p[0] = p[2]
+        else:
+            p[0] = []
+    def p_SetRaises(self, p):
+        '''
+        SetRaises : setraises ExceptionList
+                  | Empty
+        '''
+        if len(p) > 2:
+            p[0] = p[2]
+        else:
+            p[0] = []
+
+    def p_OperationRest(self, p):
+        'OperationRest : ReturnType OptionalIdentifier "(" ArgumentList ")" Raises ";"'
+        p[0] = XOperation(p[2], p[1], p[4], False, [], p[6])
+
+    def p_OptionalIdentifier(self, p):
+        '''
+        OptionalIdentifier : identifier
+                           | Empty
+        '''
+        p[0] = p[1]
+
+    def p_Raises(self, p):
+        '''
+        Raises : raises ExceptionList
+               | Empty
+        '''
+        if len(p) > 2:
+            p[0] = p[2]
+        else:
+            p[0] = []
+
+    def p_ExceptionList(self, p):
+        'ExceptionList : "(" ScopedNameList ")"'
+        p[0] = p[2]
+
+    def p_ArgumentList(self, p):
+        '''
+        ArgumentList : Argument Arguments
+                     | Empty
+        '''
+        if len(p) > 2:
+            p[0] = [p[1]] + p[2]
+        else:
+            p[0] = []
+
+    def p_Arguments(self, p):
+        '''
+        Arguments : "," Argument Arguments
+                  | Empty
+        '''
+        if len(p) > 3:
+            p[0] = [p[2]] + p[3]
+        else:
+            p[0] = []
+
+    def p_Argument(self, p):
+        'Argument : ExtendedAttributeList OptionalOrRequiredArgument'
+        p[0] = p[2]
+
+    def p_OptionalOrRequiredArgument(self, p):
+        '''
+        OptionalOrRequiredArgument : optional Type ArgumentName Default
+                                   | Type Ellipsis ArgumentName
+        '''
+        if p[1] == 'optional':
+            p[0] = XArgument(p[3], p[2], p[4], True)
+        else:
+            p[0] = XArgument(p[3], p[1], None, False, p[2] != None)
+
+    def p_ArgumentName(self, p):
+        '''
+        ArgumentName : ArgumentNameKeyword
+                     | identifier
+        '''
+        p[0] = p[1]
+
+    def p_Ellipsis(self, p):
+        '''
+        Ellipsis : ellipsis
+                 | Empty
+        '''
+        p[0] = p[1]
+
+    def p_ExceptionMember(self, p):
+        '''
+        ExceptionMember : Const
+                        | ExceptionField
+        '''
+        p[0] = p[1]
+
+    def p_ExceptionField(self, p):
+        'ExceptionField : Type identifier ";"'
+        p[0] = p[2]
+
+    def p_ExtendedAttributeList(self, p):
+        '''
+        ExtendedAttributeList : "[" ExtendedAttribute ExtendedAttributes "]"
+                              | Empty
+        '''
+        if p[1] != None:
+            p[0] = [p[2]] + p[3]
+        else:
+            p[0] = []
+
+    def p_ExtendedAttributes(self, p):
+        '''
+        ExtendedAttributes : "," ExtendedAttribute ExtendedAttributes
+                           | Empty
+        '''
+        if p[1] != None:
+            p[0] = [p[2]] + p[3]
+        else:
+            p[0] = []
+
+
+    def p_ExtendedAttribute(self, p):
+        '''
+        ExtendedAttribute : "(" ExtendedAttributeInner ")" ExtendedAttributeRest
+                          | "[" ExtendedAttributeInner "]" ExtendedAttributeRest
+                          | "{" ExtendedAttributeInner "}" ExtendedAttributeRest
+                          | ExtendedAttributeMember ExtendedAttributeRest
+        '''
+        if len(p) > 3:
+            p[0] = [p[2]] + p[4]
+        else:
+            p[0] = [p[1]]
+            if p[2]: p[0] += p[2]
+
+    def p_ExtendedAttributeRest(self, p):
+        '''
+        ExtendedAttributeRest : ExtendedAttribute
+                              | Empty
+        '''
+        p[0] = p[1]
+
+    def p_ExtendedAttributeInner(self, p):
+        '''
+        ExtendedAttributeInner : "(" ExtendedAttributeInner ")" ExtendedAttributeInner
+                               | "[" ExtendedAttributeInner "]" ExtendedAttributeInner
+                               | "{" ExtendedAttributeInner "}" ExtendedAttributeInner
+                               | OtherOrComma ExtendedAttributeInner
+                               | Empty
+        '''
+        if p[1] == None:
+            p[0] = []
+        elif len(p) > 3:
+            p[0] = [p[2]] + p[4]
+        else:
+            p[0] = [p[1]] + p[2]
+
+    def p_Other(self, p):
+        '''
+        Other : integer
+              | float
+              | identifier
+              | string
+              | other
+              | "-"
+              | "."
+              | ellipsis
+              | ":"
+              | ";"
+              | "<"
+              | "="
+              | ">"
+              | "?"
+              | Date
+              | DOMString
+              | Infinity
+              | NaN
+              | any
+              | boolean
+              | byte
+              | double
+              | false
+              | long
+              | null
+              | object
+              | octet
+              | or
+              | optional
+              | sequence
+              | short
+              | true
+              | unsigned
+              | void
+              | ArgumentNameKeyword
+        '''
+        p[0] = p[1]
+
+
+    def p_ArgumentNameKeyword(self, p):
+        '''
+        ArgumentNameKeyword : attribute
+                            | callback
+                            | const
+                            | creator
+                            | deleter
+                            | dictionary
+                            | enum
+                            | exception
+                            | getter
+                            | implements
+                            | inherit
+                            | interface
+                            | legacycaller
+                            | partial
+                            | setter
+                            | static
+                            | stringifier
+                            | typedef
+                            | unrestricted
+        '''
+        p[0] = p[1]
+
+    def p_OtherOrComma(self, p):
+        '''
+        OtherOrComma : ExtendedAttributeMember
+                     | ","
+        '''
+        if p[1] == ',':
+            p[0] = []
+        else:
+            p[0] = p[1]
+
+    def p_Type(self, p):
+        '''
+        Type : SingleType
+             | UnionType TypeSuffix
+        '''
+
+        if len(p) > 2:
+            p[0] = XType("", p[1], p[2]['array'], p[2]['nullable'])
+        else:
+            p[0] = p[1]
+
+    def p_SingleType(self, p):
+        '''
+        SingleType : NonAnyType
+                   | any TypeSuffixStartingWithArray
+        '''
+
+        if p[1] == 'any':
+            p[0] = XType('any', None, p[2]['array'])
+        else:
+            p[0] = p[1]
+
+
+    def p_UnionType(self, p):
+        'UnionType : "(" UnionMemberType or UnionMemberType UnionMemberTypes ")"'
+
+        p[0] = [p[2]] + [p[4]]
+        if p[5]:
+            p[0] += [p[5]]
+
+    def p_UnionMemberType(self, p):
+        '''
+        UnionMemberType : NonAnyType
+                        | UnionType TypeSuffix
+                        | any "[" "]" TypeSuffix
+        '''
+        if len(p)>2:
+            if p[1] == 'any':
+                p[0] = XType('any', None, p[4]['array']+1, p[4]['nullable'])
+            else:
+                p[0] = []
+        else:
+            p[0] = p[1]
+
+    def p_UnionMemberTypes(self, p):
+        '''
+        UnionMemberTypes : or UnionMemberType UnionMemberTypes
+                         | Empty
+        '''
+        if len(p) > 2:
+            p[0] = p[2] + p[3]
+        else:
+            p[0] = []
+
+    def p_NonAnyType(self, p):
+        '''
+        NonAnyType : PrimitiveType TypeSuffix
+                   | DOMString TypeSuffix
+                   | identifier TypeSuffix
+                   | sequence "<" Type ">" Null
+                   | object TypeSuffix
+                   | Date TypeSuffix
+        '''
+        sequence = False
+        typename = p[1]
+        nullable = False
+        array = 0
+        if p[1] == 'sequence':
+            typename = None
+            sequence = True
+            nullable = p[5]
+        else:
+            tf = p[2]
+            if tf:
+                nullable = tf['nullable']
+                array = tf['array']
+
+        p[0] = XType(typename, None, array, nullable, sequence)
+
+    def p_ConstType(self, p):
+        '''
+        ConstType : PrimitiveType Null
+                  | identifier Null
+        '''
+        p[0] = p[1]
+
+    def p_PrimitiveType(self, p):
+        '''
+        PrimitiveType : UnsignedIntegerType
+                      | UnrestrictedFloatType
+                      | boolean
+                      | byte
+                      | octet
+        '''
+        p[0] = p[1]
+
+    def p_UnrestrictedFloatType(self, p):
+        '''
+        UnrestrictedFloatType : unrestricted FloatType
+                              | FloatType
+        '''
+        if len(p) > 2:
+            p[0] = p[2]
+            p[0].unrestricted = True
+        else:
+            p[0] = p[1]
+
+    def p_FloatType(self, p):
+        '''
+        FloatType : float
+                  | double
+        '''
+        p[0] = XType(p[1], None, 0, False, False, False)
+
+    def p_UnsignedIntegerType(self, p):
+        '''
+        UnsignedIntegerType : unsigned IntegerType
+                            | IntegerType
+        '''
+
+        typename = p[1] if p[1] != 'unsigned' else p[2]
+        p[0] = XType(typename, None, 0, False, False, p[1] == 'unsigned')
+
+    def p_IntegerType(self, p):
+        '''
+        IntegerType : short
+                    | long OptionalLong
+        '''
+        if p[1] == 'long' and p[2] != None:
+            p[0] = 'long long'
+        else:
+            p[0] = p[1]
+
+    def p_OptionalLong(self, p):
+        '''
+        OptionalLong : long
+                     | Empty
+        '''
+        p[0] = p[1]
+
+    def p_TypeSuffix(self, p):
+        '''
+        TypeSuffix : "[" "]" TypeSuffix
+                   | "?" TypeSuffixStartingWithArray
+                   | Empty
+        '''
+        p[0] = {'nullable':False, 'array':0}
+
+        if p[1]:
+            if p[1] == '?':
+                p[0]['nullable'] = True
+                p[0]['array'] += p[2]['array']
+            if p[1] == "[" and p[2] == "]":
+                p[0]['array'] += 1
+                p[0]['array'] += p[3]['array']
+
+
+
+    def p_TypeSuffixStartingWithArray(self, p):
+        '''
+        TypeSuffixStartingWithArray : "[" "]" TypeSuffix
+                                    | Empty
+        '''
+        p[0] = {'array':0}
+        if p[1] != None:
+            p[0]['array'] += 1
+            if p[3]:
+                p[0]['array'] += p[3]['array']
+
+    def p_Null(self, p):
+        '''
+        Null : "?"
+             | Empty
+        '''
+        p[0] = p[1]
+
+    def p_ReturnType(self, p):
+        '''
+        ReturnType : Type
+                   | void
+        '''
+        if p[1] == 'void':
+            p[0] = XVoid
+        else:
+            p[0] = p[1]
+
+    def p_ScopedNameList(self, p):
+        'ScopedNameList : ScopedName ScopedNames'
+        p[0] = [p[1]] + p[2]
+
+    def p_ScopedNames(self, p):
+        '''
+        ScopedNames : "," ScopedName ScopedNames
+                    | Empty
+        '''
+        if len(p) > 2:
+            p[0] = [p[2]] + p[3]
+        else:
+            p[0] = []
+
+    def p_ScopedName(self, p):
+        '''
+        ScopedName : AbsoluteScopedName
+                   | RelativeScopedName
+        '''
+        p[0] = p[1]
+
+    def p_AbsoluteScopedName(self, p):
+        'AbsoluteScopedName : scope identifier ScopedNameParts'
+        p[0] = '::' + p[2] + p[3]
+
+    def p_RelativeScopedName(self, p):
+        'RelativeScopedName : identifier ScopedNameParts'
+        p[0] = p[1] + p[2]
+
+    def p_ScopedNameParts(self, p):
+        '''
+        ScopedNameParts : scope identifier ScopedNameParts
+                        | Empty
+        '''
+        if len(p) > 2:
+            p[0] = '::' + p[2] + p[3]
+        else:
+            p[0] = ""
+
+    def p_ExtendedAttributeNoArgs(self, p):
+        'ExtendedAttributeNoArgs : identifier'
+        p[0] = XExtendedAttribute(p[1])
+
+    def p_ExtendedAttributeArgList(self, p):
+        'ExtendedAttributeArgList : identifier "(" ArgumentList ")"'
+        p[0] = XExtendedAttribute(p[1], None, p[3])
+
+    def p_ExtendedAttributeIdent(self, p):
+        'ExtendedAttributeIdent : identifier "=" identifier'
+        p[0] = XExtendedAttribute(p[1], p[3])
+
+    def p_ExtendedAttributeNamedArgList(self, p):
+        'ExtendedAttributeNamedArgList : identifier "=" identifier "(" ArgumentList ")"'
+        p[0] = XExtendedAttribute(p[1], p[3], p[5])
+
+    def p_ExtendedAttributeMember(self, p):
+        '''
+        ExtendedAttributeMember : ExtendedAttributeNoArgs
+                                | ExtendedAttributeArgList
+                                | ExtendedAttributeIdent
+                                | ExtendedAttributeNamedArgList
+        '''
+        p[0] = p[1]
+
+    def p_Empty(self, p):
+        'Empty :'
+        pass
+
+    def p_error(self, p):
+        try:
+            raise Exception("Syntax error at '%s'" % p.value, p.lineno)
+        except AttributeError:
+            raise Exception("Syntax error")
+
+if __name__ == '__main__':
+    args = sys.argv[1:]
+    if len(sys.argv) > 2:
+        sys.exit()
+
+    f = open(args[0])
+    widl = f.read()
+    f.close()
+
+
+#    p = Parser(debug=1, verbose=1)
+    p = Parser()
+
+    tree = p.parse(widl)
+
+    from pprint import pprint
+
+    pprint(tree)
+
diff --git a/webWidgetTCT_device/tools/skeleton_generator/tpl/tpl_api.js b/webWidgetTCT_device/tools/skeleton_generator/tpl/tpl_api.js
new file mode 100755 (executable)
index 0000000..7e1a732
--- /dev/null
@@ -0,0 +1,243 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+{% for module in modules %}
+
+var utils_ = xwalk.utils;
+var type_ = utils_.type;
+var converter_ = utils_.converter;
+var validator_ = utils_.validator;
+var types_ = validator_.Types;
+var native_ = new xwalk.utils.NativeManager(extension);
+
+{% if module.async %}
+function ListenerManager(native, listenerName, handle) {
+  this.listeners = {};
+  this.nextId = 1;
+  this.nativeSet = false;
+  this.native = native;
+  this.listenerName = listenerName;
+  this.handle = handle || function(msg, listener, watchId) {};
+}
+
+ListenerManager.prototype.addListener = function(callback, nativeCall, data) {
+  var id = this.nextId;
+  if (!this.nativeSet) {
+    this.native.addListener(this.listenerName, function(msg) {
+      for (var watchId in this.listeners) {
+        if (this.listeners.hasOwnProperty(watchId)) {
+          this.handle(msg, this.listeners[watchId], watchId);
+        }
+      }
+    }.bind(this));
+    var result = this.native.callSync(nativeCall, data || {});
+    if (this.native.isFailure(result)) {
+      throw this.native.getErrorObject(result);
+    }
+    this.nativeSet = true;
+  }
+
+  this.listeners[id] = callback;
+  ++this.nextId;
+
+  return id;
+};
+
+ListenerManager.prototype.removeListener = function(watchId, nativeCall) {
+  if (this.listeners.hasOwnProperty(watchId)) {
+    delete this.listeners[watchId];
+  }
+
+  if (this.nativeSet && type_.isEmptyObject(this.listeners)) {
+      this.native.callSync(nativeCall);
+      this.native.removeListener(this.listenerName);
+      this.nativeSet = false;
+  }
+};
+
+{% set multicallback = callback|length() > 1 %}
+{% for iface in module.getTypes('Interface') %}
+  {% for operation in iface.getTypes('Operation') if operation.async %}
+    {% for arg in operation.arguments if arg.validation[0] == 'LISTENER' %}
+var _{{iface.name}}Listener = new ListenerManager(native_, '{{operation.name}}Listener',
+  function(msg, listener, watchId) {
+      var d = null;
+
+      switch (msg.action) {
+      {% for listener in arg.validation[1] %}
+      case '{{listener}}':
+        d = msg.data;
+        break;
+      {% endfor %}
+
+      default:
+        console.log('Unknown mode: ' + msg.action);
+      return;
+      }
+
+      listener[msg.action](d);
+    });
+
+    {% endfor %}
+  {% endfor %}
+{% endfor %}
+{% endif %}
+
+function SetReadOnlyProperty(obj, n, v) {
+  Object.defineProperty(obj, n, {value: v, writable: false});
+}
+
+{% for enums in module.getTypes('Enum') %}
+var {{enums.name}} = {
+  {% for e in enums.childs %}
+  {{e}}: '{{e}}'{% if not loop.last %},{% endif %}
+
+  {% endfor %}
+};
+{% endfor %}
+
+{% for iface in module.getTypes('Interface') %}
+{% if iface.exported  or iface.private %}
+
+{% if iface.private %}
+// private constructor
+{% endif %}
+function {{iface.name}}(
+    {%-if iface.constructor -%}
+    {%- for arg in iface.constructor.arguments -%}
+    {{arg.name}}{%- if not loop.last %}, {% endif -%}
+    {%- endfor -%}
+    {%- endif -%}) {
+  // constructor of {{iface.name}}
+  {% if iface.constructor %}
+  validator_.isConstructorCall(this, {{iface.name}});
+  {% endif %}
+
+  {% for attribute in iface.getTypes('Attribute') %}
+    {% if attribute.existIn == 'ctor' %}
+    {% set attrValue = attribute.name %}
+    {% elif attribute.existIn %}
+    {% set attrValue = attribute.existIn %}
+    {% else %}
+    {% set attrValue = "null" %}
+    {% endif %}
+    {% if attribute.readonly %}
+  SetReadOnlyProperty(this, '{{attribute.name}}', {{attrValue}}); // read only property
+    {% else %}
+  this.{{attribute.name}} = {{attrValue}};
+    {% endif %}
+  {% endfor %}
+}
+
+{% if iface.inherit %}
+{{iface.name}}.prototype = new {{iface.inherit}}();
+{{iface.name}}.prototype.constructor = {{iface.name}};
+{% endif %}
+
+{% for operation in iface.getTypes('Operation') %}
+{{iface.name}}.prototype.{{operation.name}} = function(
+    {%- for arg in operation.arguments -%}
+      {%- if not loop.first %}, {% endif -%}
+      {{arg.name}}
+    {%- endfor %}) {
+  {% if operation.arguments %}
+  var args = validator_.validateArgs(arguments, [
+    {% for arg in operation.arguments %}
+    {name: '{{arg.name}}', type: types_.{{arg.validation[0]}}
+        {%- if arg.validation[1] -%}
+        {%- if arg.validation[0] == 'PLATFORM_OBJECT' -%}
+        , values: tizen.{{arg.validation[1]|first}}
+        {%- else -%}
+        , values: {{arg.validation[1]}}
+        {%- endif -%}
+        {%- endif -%}
+        {%- if arg.optional -%}, optional: true{% endif -%}
+        {%- if arg.xtype.nullable -%}, nullable: true{% endif -%}
+    }{%- if not loop.last %},{% endif %}
+
+    {% endfor %}
+  ]);
+  {% endif %}
+
+  var data = {
+    {% for arg in operation.arguments if not arg.validation[0] == 'LISTENER' and not arg.validation[0] == 'FUNCTION' %}
+    {{arg.name}}: args.{{arg.name}}{% if not loop.last %},{% endif %}
+
+    {% endfor %}
+  };
+
+  {% if operation.async %}
+    {% set listenerSet = false %}{% set callbackSet = false %}
+    {% for arg in operation.arguments %}
+      {% if arg.validation[0] == 'LISTENER' and listenerSet == false %}{% set listenerSet = true %}
+
+  return _{{iface.name}}Listener.addListener(args.{{arg.name}},
+      '{{operation.native_cmd}}');
+
+    {%- if arg.name == 'errorCallback' or arg.name == 'callback' -%}
+  if (native_.isFailure(result)) {
+    native_.callIfPossible(args.{{arg.name}}, native_.getErrorObject(result));
+  }
+    {% endif %}
+  {% endif %}
+
+  {% if arg.validation[0] == 'FUNCTION' and listenerSet == false and callbackSet == false %}{% set callbackSet = true %}
+  var callback = function(result) {
+  {% for arg in operation.arguments %}
+    {% if arg.name == 'errorCallback' or arg.name == 'callback' %}
+    if (native_.isFailure(result)) {
+      native_.callIfPossible(args.{{arg.name}}, native_.getErrorObject(result));
+      return;
+    }
+    {% endif %}
+  {% endfor %}
+    native_.callIfPossible(args.{{arg.name}});
+  };
+
+  native_.call('{{operation.native_cmd}}', data, callback);
+      {% endif %}
+    {% endfor %}
+
+  {% else %}
+
+  var result = native_.callSync('{{operation.native_cmd}}', data);
+
+  if (native_.isFailure(result)) {
+    throw native_.getErrorObject(result);
+  }
+  {% endif %}
+  {% if operation.returnInternal %}
+  return new {{operation.returnInternal.name}}(native_.getResultObject(result));
+  {% endif %}
+
+};
+
+{% endfor %}
+
+{% endif %}
+{% endfor %}
+
+{% for iface in module.getTypes('Interface') %}
+    {% if iface.exported == 'Tizen' %}
+exports = new {{iface.name}}();
+    {% elif iface.exported == 'Window' %}
+window.{{iface.name}} = new {{iface.name}}();
+    {% elif iface.exported %}
+tizen.{{iface.name}} = {{iface.name}};
+    {% endif %}
+{% endfor %}
+
+{% endfor %}
diff --git a/webWidgetTCT_device/tools/skeleton_generator/tpl/tpl_extension.cc b/webWidgetTCT_device/tools/skeleton_generator/tpl/tpl_extension.cc
new file mode 100755 (executable)
index 0000000..b6d2385
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2015 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 "{{module.lower}}/{{module.lower}}_extension.h"
+
+#include "{{module.lower}}/{{module.lower}}_instance.h"
+
+// This will be generated from {{module.lower}}_api.js
+extern const char kSource_{{module.lower}}_api[];
+
+common::Extension* CreateExtension() {
+  return new {{module.title}}Extension;
+}
+
+{{module.title}}Extension::{{module.title}}Extension() {
+  SetExtensionName("tizen.{{module.lower}}");
+  SetJavaScriptAPI(kSource_{{module.lower}}_api);
+
+  const char* entry_points[] = {
+  {% for iface in moduleObj.getTypes('Interface') %}
+    {% if iface.exported and (iface.exported != 'Tizen' or iface.exported != 'Window') %}
+      "tizen.{{iface.name}}",
+    {% endif %}
+  {% endfor %}
+      NULL
+    };
+  SetExtraJSEntryPoints(entry_points);
+}
+
+{{module.title}}Extension::~{{module.title}}Extension() {}
+
+common::Instance* {{module.title}}Extension::CreateInstance() {
+  return new extension::{{module.lower}}::{{module.title}}Instance;
+}
diff --git a/webWidgetTCT_device/tools/skeleton_generator/tpl/tpl_extension.h b/webWidgetTCT_device/tools/skeleton_generator/tpl/tpl_extension.h
new file mode 100755 (executable)
index 0000000..39034c1
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015 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 {{module.upper}}_{{module.upper}}_EXTENSION_H_
+#define {{module.upper}}_{{module.upper}}_EXTENSION_H_
+
+#include "common/extension.h"
+
+class {{module.title}}Extension : public common::Extension {
+ public:
+  {{module.title}}Extension();
+  virtual ~{{module.title}}Extension();
+
+ private:
+  virtual common::Instance* CreateInstance();
+};
+
+#endif // {{module.upper}}_{{module.upper}}_EXTENSION_H_
+
diff --git a/webWidgetTCT_device/tools/skeleton_generator/tpl/tpl_instance.cc b/webWidgetTCT_device/tools/skeleton_generator/tpl/tpl_instance.cc
new file mode 100755 (executable)
index 0000000..1fc7671
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2015 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 "{{module.lower}}/{{module.lower}}_instance.h"
+
+#include <functional>
+
+#include "common/picojson.h"
+#include "common/logger.h"
+#include "common/platform_exception.h"
+
+namespace extension {
+namespace {{module.lower}} {
+
+namespace {
+// The privileges that required in {{module.title}} API
+const std::string kPrivilege{{module.title}} = "";
+
+} // namespace
+
+using namespace common;
+using namespace extension::{{module.lower}};
+
+{{module.title}}Instance::{{module.title}}Instance() {
+  using namespace std::placeholders;
+  #define REGISTER_SYNC(c,x) \
+    RegisterSyncHandler(c, std::bind(&{{module.title}}Instance::x, this, _1, _2));
+  {% for func in cmdtable %}
+  REGISTER_SYNC("{{cmdtable[func]}}", {{func}});
+  {% endfor %}
+  #undef REGISTER_SYNC
+}
+
+{{module.title}}Instance::~{{module.title}}Instance() {
+}
+
+{% set type_map = {'DOMString':'std::string', 'object':'picojson::object', 'boolean':'bool', 'byte':'int', 'octet':'int', 'short':'int', 'long':'double', 'long long': 'double', 'unsigned short':'int', 'unsigned long long':'double', 'float':'double', 'double':'double'} %}
+{% set primitives = ['int', 'double', 'bool'] %}
+
+{% if moduleObj.async %}
+enum {{module.title}}Callbacks {
+  {% for func in cmdtable %}
+  {{func}}Callback{% if not loop.last %}, {%+ endif %}
+
+  {% endfor %}
+};
+
+static void ReplyAsync({{module.title}}Instance* instance, {{module.title}}Callbacks cbfunc,
+                       int callbackId, bool isSuccess, picojson::object& param) {
+  param["callbackId"] = picojson::value(static_cast<double>(callbackId));
+  param["status"] = picojson::value(isSuccess ? "success" : "error");
+
+  // insert result for async callback to param
+  switch(cbfunc) {
+  {% for iface in moduleObj.getTypes('Interface') %}
+    {% if iface.exported %}
+      {% for operation in iface.getTypes('Operation') %}
+    case {{operation.native_function}}Callback: {
+      // do something...
+      break;
+    }
+      {% endfor %}
+    {% endif %}
+  {% endfor %}
+    default: {
+      LoggerE("Invalid Callback Type");
+      return;
+    }
+  }
+
+  picojson::value result = picojson::value(param);
+
+  instance->PostMessage(result.serialize().c_str());
+}
+{% endif %}
+
+#define CHECK_EXIST(args, name, out) \
+    if (!args.contains(name)) {\
+      ReportError(TypeMismatchException(name" is required argument"), out);\
+      return;\
+    }
+
+{% for func in cmdtable %}
+{% endfor %}
+
+{% for iface in moduleObj.getTypes('Interface') %}
+  {% if iface.exported %}
+    {% if iface.native_function %}
+void {{module.title}}Instance::{{iface.native_function}}(const picojson::value& args, picojson::object& out) {
+      {% for arg in iface.constructor.arguments %}
+      {% if not arg.optional and type_map[arg.xtype.name] %}
+  CHECK_EXIST(args, "{{arg.name}}", out)
+      {% endif %}
+      {% endfor %}
+
+      {% for arg in iface.constructor.arguments %}
+      {% set type = type_map[arg.xtype.name] %}
+      {% if type %}
+  {%+ if type not in primitives %}const {% endif -%}
+  {{type}}{% if type == 'std::string' %}&{% endif %} {{arg.name}} = args.get("{{arg.name}}").get<{{type}}>();
+      {% endif %}
+      {% endfor %}
+}
+    {% endif %}
+    {% for operation in iface.getTypes('Operation') %}
+void {{module.title}}Instance::{{operation.native_function}}(const picojson::value& args, picojson::object& out) {
+  {% if operation.async %}
+  CHECK_EXIST(args, "callbackId", out)
+  {% endif %}
+  {% for arg in operation.arguments %}
+  {% if not arg.optional and type_map[arg.xtype.name] %}
+  CHECK_EXIST(args, "{{arg.name}}", out)
+  {% endif %}
+  {% endfor %}
+
+  {% if operation.async %}
+  int callbackId = static_cast<int>(args.get("callbackId").get<double>());
+  {% endif %}
+  {% for arg in operation.arguments %}
+  {% set type = type_map[arg.xtype.name] %}
+  {% if type %}
+  {%+ if type not in primitives %}const {% endif -%}
+  {{type}}{% if type == 'std::string' %}&{% endif %} {{arg.name}} = args.get("{{arg.name}}").get<{{type}}>();
+  {% endif %}
+  {% endfor %}
+
+  // implement it
+
+  {% if operation.async %}
+  // call ReplyAsync in later (Asynchronously)
+  {% endif %}
+
+  // if success
+  // ReportSuccess(out);
+  // if error
+  // ReportError(out);
+}
+    {% endfor %}
+  {% endif %}
+{% endfor %}
+
+
+#undef CHECK_EXIST
+
+} // namespace {{module.lower}}
+} // namespace extension
diff --git a/webWidgetTCT_device/tools/skeleton_generator/tpl/tpl_instance.h b/webWidgetTCT_device/tools/skeleton_generator/tpl/tpl_instance.h
new file mode 100755 (executable)
index 0000000..cc601b5
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2015 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 {{module.upper}}_{{module.upper}}_INSTANCE_H_
+#define {{module.upper}}_{{module.upper}}_INSTANCE_H_
+
+#include "common/extension.h"
+
+namespace extension {
+namespace {{module.lower}} {
+
+class {{module.title}}Instance : public common::ParsedInstance {
+ public:
+  {{module.title}}Instance();
+  virtual ~{{module.title}}Instance();
+
+ private:
+  {% for func in cmdtable %}
+  void {{func}}(const picojson::value& args, picojson::object& out);
+  {% endfor %}
+};
+
+} // namespace {{module.lower}}
+} // namespace extension
+
+#endif // {{module.upper}}_{{module.upper}}_INSTANCE_H_
diff --git a/webWidgetTCT_device/tools/slimit/CHANGES b/webWidgetTCT_device/tools/slimit/CHANGES
new file mode 100755 (executable)
index 0000000..e776080
--- /dev/null
@@ -0,0 +1,115 @@
+Change History
+==============
+0.8.1 (2013-03-26)
+------------------
+- Bug fix: https://github.com/rspivak/slimit/pull/45
+  Fix syntax error in the output of for statement with some form of expressions
+
+0.8.0 (2013-03-23)
+------------------
+- Python 3.x support
+- Bug fix: https://github.com/rspivak/slimit/issues/42
+  slimit removes parentheses from ternary expression, causes syntax error in jQuery
+- Bug fix: https://github.com/rspivak/slimit/issues/37
+  simple identifier in FOR init
+- Bug fix: https://github.com/rspivak/slimit/issues/36
+  using $ for mangled function names conflicts with jQuery
+
+0.7.4 (2012-06-5)
+------------------
+- Bug fix: https://github.com/rspivak/slimit/issues/34
+  'class' is reserved keyword now
+
+0.7.3 (2012-05-21)
+------------------
+- Bug fix (unary op in FOR init): https://github.com/rspivak/slimit/pull/33
+
+0.7.2 (2012-05-17)
+------------------
+- Added support for get/set properties:
+  https://github.com/rspivak/slimit/issues/32
+
+0.7.1 (2012-05-10)
+------------------
+- Function call support in FOR init section:
+  https://github.com/rspivak/slimit/pull/31
+
+0.7 (2012-04-16)
+----------------
+- Multiline string support: https://github.com/rspivak/slimit/issues/24
+
+0.6.2 (2012-04-07)
+------------------
+- Bug fix: https://github.com/rspivak/slimit/issues/29
+- Bug fix: https://github.com/rspivak/slimit/issues/28
+
+0.6.1 (2012-03-15)
+------------------
+- Added command-line option *-t/--mangle-toplevel* to turn on
+  global scope name mangling. As of this version it's off by
+  default: https://github.com/rspivak/slimit/issues/27
+- Removed dependency on a 'distribute' package
+- Bug fix: https://github.com/rspivak/slimit/issues/26
+- Bug fix: https://github.com/rspivak/slimit/issues/25
+
+0.6 (2012-02-04)
+----------------
+- Added optimization: foo["bar"] ==> foo.bar
+- Added base class for custom AST node visitors
+- Documentation updates
+- Bug fix: https://github.com/rspivak/slimit/issues/22
+- Bug fix: https://github.com/rspivak/slimit/issues/21
+
+0.5.5 (2011-10-05)
+------------------
+- Bugfix: https://github.com/rspivak/slimit/issues/7
+
+0.5.4 (2011-10-01)
+------------------
+- Bugfix: https://github.com/rspivak/slimit/issues/6
+  Division with "this" fails
+
+0.5.3 (2011-06-29)
+------------------
+- Bugfix: https://github.com/rspivak/slimit/issues/5
+
+0.5.2 (2011-06-14)
+------------------
+- Bugfix: https://github.com/rspivak/slimit/issues/4
+- Bugfix: https://github.com/rspivak/slimit/issues/3
+
+0.5.1 (2011-06-06)
+------------------
+- Bugfix: https://github.com/rspivak/slimit/issues/2
+
+0.5 (2011-06-06)
+----------------
+- Added name mangling
+
+0.4 (2011-05-12)
+----------------
+- Minify more by removing block braces { }
+- More tests
+
+0.3.2 (2011-05-09)
+------------------
+- More hacks to use pre-generated lex and yacc tables when called from
+  the command line
+
+0.3.1 (2011-05-09)
+------------------
+- Use pre-generated lex and yacc tables when called from the command line
+
+0.3 (2011-05-09)
+----------------
+- Added minifier
+
+0.2 (2011-05-07)
+----------------
+- Added a JavaScript parser
+- Added pretty printer
+- Added node visitor
+
+0.1 (2011-05-02)
+----------------
+- Initial public version. It contains only a JavaScript lexer
diff --git a/webWidgetTCT_device/tools/slimit/CREDIT b/webWidgetTCT_device/tools/slimit/CREDIT
new file mode 100755 (executable)
index 0000000..fc7557c
--- /dev/null
@@ -0,0 +1,27 @@
+Patches
+-------
+
+- Waldemar Kornewald
+- Maurizio Sambati https://github.com/duilio
+- Aron Griffis https://github.com/agriffis
+- lelit https://github.com/lelit
+- Dan McDougall https://github.com/liftoff
+- harig https://github.com/harig
+- Mike Taylor https://github.com/miketaylr
+
+
+Bug reports
+-----------
+
+- Rui Pereira
+- Dima Kozlov
+- BadKnees https://github.com/BadKnees
+- Waldemar Kornewald
+- Michał Bartoszkiewicz https://github.com/embe
+- Hasan Yasin Öztürk https://github.com/hasanyasin
+- David K. Hess https://github.com/davidkhess
+- Robert Cadena https://github.com/rcadena
+- rivol https://github.com/rivol
+- Maurizio Sambati https://github.com/duilio
+- fdev31 https://github.com/fdev31
+- edmellum https://github.com/edmellum
\ No newline at end of file
diff --git a/webWidgetTCT_device/tools/slimit/LICENSE b/webWidgetTCT_device/tools/slimit/LICENSE
new file mode 100755 (executable)
index 0000000..c134376
--- /dev/null
@@ -0,0 +1,19 @@
+Copyright (c) 2011 Ruslan Spivak
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/webWidgetTCT_device/tools/slimit/__init__.py b/webWidgetTCT_device/tools/slimit/__init__.py
new file mode 100755 (executable)
index 0000000..8b5dd72
--- /dev/null
@@ -0,0 +1,27 @@
+###############################################################################
+#
+# Copyright (c) 2011 Ruslan Spivak
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+###############################################################################
+
+__author__ = 'Ruslan Spivak <ruslan.spivak@gmail.com>'
+
+from minifier import minify
diff --git a/webWidgetTCT_device/tools/slimit/ast.py b/webWidgetTCT_device/tools/slimit/ast.py
new file mode 100755 (executable)
index 0000000..7458967
--- /dev/null
@@ -0,0 +1,415 @@
+###############################################################################
+#
+# Copyright (c) 2011 Ruslan Spivak
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+###############################################################################
+
+__author__ = 'Ruslan Spivak <ruslan.spivak@gmail.com>'
+
+
+class Node(object):
+    def __init__(self, children=None):
+        self._children_list = [] if children is None else children
+
+    def __iter__(self):
+        for child in self.children():
+            if child is not None:
+                yield child
+
+    def children(self):
+        return self._children_list
+
+    def to_ecma(self):
+        # Can't import at module level as ecmavisitor depends
+        # on ast module...
+        from slimit.visitors.ecmavisitor import ECMAVisitor
+        visitor = ECMAVisitor()
+        return visitor.visit(self)
+
+class Program(Node):
+    pass
+
+class Block(Node):
+    pass
+
+class Boolean(Node):
+    def __init__(self, value):
+        self.value = value
+
+    def children(self):
+        return []
+
+class Null(Node):
+    def __init__(self, value):
+        self.value = value
+
+    def children(self):
+        return []
+
+class Number(Node):
+    def __init__(self, value):
+        self.value = value
+
+    def children(self):
+        return []
+
+class Identifier(Node):
+    def __init__(self, value):
+        self.value = value
+
+    def children(self):
+        return []
+
+class String(Node):
+    def __init__(self, value):
+        self.value = value
+
+    def children(self):
+        return []
+
+class Regex(Node):
+    def __init__(self, value):
+        self.value = value
+
+    def children(self):
+        return []
+
+class Array(Node):
+    def __init__(self, items):
+        self.items = items
+
+    def children(self):
+        return self.items
+
+class Object(Node):
+    def __init__(self, properties=None):
+        self.properties = [] if properties is None else properties
+
+    def children(self):
+        return self.properties
+
+class NewExpr(Node):
+    def __init__(self, identifier, args=None):
+        self.identifier = identifier
+        self.args = [] if args is None else args
+
+    def children(self):
+        return [self.identifier, self.args]
+
+class FunctionCall(Node):
+    def __init__(self, identifier, args=None):
+        self.identifier = identifier
+        self.args = [] if args is None else args
+
+    def children(self):
+        return [self.identifier] + self.args
+
+class BracketAccessor(Node):
+    def __init__(self, node, expr):
+        self.node = node
+        self.expr = expr
+
+    def children(self):
+        return [self.node, self.expr]
+
+class DotAccessor(Node):
+    def __init__(self, node, identifier):
+        self.node = node
+        self.identifier = identifier
+
+    def children(self):
+        return [self.node, self.identifier]
+
+class Assign(Node):
+    def __init__(self, op, left, right):
+        self.op = op
+        self.left = left
+        self.right = right
+
+    def children(self):
+        return [self.left, self.right]
+
+class GetPropAssign(Node):
+    def __init__(self, prop_name, elements):
+        """elements - function body"""
+        self.prop_name = prop_name
+        self.elements = elements
+
+    def children(self):
+        return [self.prop_name] + self.elements
+
+class SetPropAssign(Node):
+    def __init__(self, prop_name, parameters, elements):
+        """elements - function body"""
+        self.prop_name = prop_name
+        self.parameters = parameters
+        self.elements = elements
+
+    def children(self):
+        return [self.prop_name] + self.parameters + self.elements
+
+class VarStatement(Node):
+    pass
+
+class VarDecl(Node):
+    def __init__(self, identifier, initializer=None):
+        self.identifier = identifier
+        self.identifier._mangle_candidate = True
+        self.initializer = initializer
+
+    def children(self):
+        return [self.identifier, self.initializer]
+
+class UnaryOp(Node):
+    def __init__(self, op, value, postfix=False):
+        self.op = op
+        self.value = value
+        self.postfix = postfix
+
+    def children(self):
+        return [self.value]
+
+class BinOp(Node):
+    def __init__(self, op, left, right):
+        self.op = op
+        self.left = left
+        self.right = right
+
+    def children(self):
+        return [self.left, self.right]
+
+class Conditional(Node):
+    """Conditional Operator ( ? : )"""
+    def __init__(self, predicate, consequent, alternative):
+        self.predicate = predicate
+        self.consequent = consequent
+        self.alternative = alternative
+
+    def children(self):
+        return [self.predicate, self.consequent, self.alternative]
+
+class If(Node):
+    def __init__(self, predicate, consequent, alternative=None):
+        self.predicate = predicate
+        self.consequent = consequent
+        self.alternative = alternative
+
+    def children(self):
+        return [self.predicate, self.consequent, self.alternative]
+
+class DoWhile(Node):
+    def __init__(self, predicate, statement):
+        self.predicate = predicate
+        self.statement = statement
+
+    def children(self):
+        return [self.predicate, self.statement]
+
+class While(Node):
+    def __init__(self, predicate, statement):
+        self.predicate = predicate
+        self.statement = statement
+
+    def children(self):
+        return [self.predicate, self.statement]
+
+class For(Node):
+    def __init__(self, init, cond, count, statement):
+        self.init = init
+        self.cond = cond
+        self.count = count
+        self.statement = statement
+
+    def children(self):
+        return [self.init, self.cond, self.count, self.statement]
+
+class ForIn(Node):
+    def __init__(self, item, iterable, statement):
+        self.item = item
+        self.iterable = iterable
+        self.statement = statement
+
+    def children(self):
+        return [self.item, self.iterable, self.statement]
+
+class Continue(Node):
+    def __init__(self, identifier=None):
+        self.identifier = identifier
+
+    def children(self):
+        return [self.identifier]
+
+class Break(Node):
+    def __init__(self, identifier=None):
+        self.identifier = identifier
+
+    def children(self):
+        return [self.identifier]
+
+class Return(Node):
+    def __init__(self, expr=None):
+        self.expr = expr
+
+    def children(self):
+        return [self.expr]
+
+class With(Node):
+    def __init__(self, expr, statement):
+        self.expr = expr
+        self.statement = statement
+
+    def children(self):
+        return [self.expr, self.statement]
+
+class Switch(Node):
+    def __init__(self, expr, cases, default=None):
+        self.expr = expr
+        self.cases = cases
+        self.default = default
+
+    def children(self):
+        return [self.expr] + self.cases + [self.default]
+
+class Case(Node):
+    def __init__(self, expr, elements):
+        self.expr = expr
+        self.elements = elements if elements is not None else []
+
+    def children(self):
+        return [self.expr] + self.elements
+
+class Default(Node):
+    def __init__(self, elements):
+        self.elements = elements if elements is not None else []
+
+    def children(self):
+        return self.elements
+
+class Label(Node):
+    def __init__(self, identifier, statement):
+        self.identifier = identifier
+        self.statement = statement
+
+    def children(self):
+        return [self.identifier, self.statement]
+
+class Throw(Node):
+    def __init__(self, expr):
+        self.expr = expr
+
+    def children(self):
+        return [self.expr]
+
+class Try(Node):
+    def __init__(self, statements, catch=None, fin=None):
+        self.statements = statements
+        self.catch = catch
+        self.fin = fin
+
+    def children(self):
+        return [self.statements] + [self.catch, self.fin]
+
+class Catch(Node):
+    def __init__(self, identifier, elements):
+        self.identifier = identifier
+        # CATCH identifiers are subject to name mangling. we need to mark them.
+        self.identifier._mangle_candidate = True
+        self.elements = elements
+
+    def children(self):
+        return [self.identifier, self.elements]
+
+class Finally(Node):
+    def __init__(self, elements):
+        self.elements = elements
+
+    def children(self):
+        return self.elements
+
+class Debugger(Node):
+    def __init__(self, value):
+        self.value = value
+
+    def children(self):
+        return []
+
+
+class FuncBase(Node):
+    def __init__(self, identifier, parameters, elements):
+        self.identifier = identifier
+        self.parameters = parameters if parameters is not None else []
+        self.elements = elements if elements is not None else []
+        self._init_ids()
+
+    def _init_ids(self):
+        # function declaration/expression name and parameters are identifiers
+        # and therefore are subject to name mangling. we need to mark them.
+        if self.identifier is not None:
+            self.identifier._mangle_candidate = True
+        for param in self.parameters:
+            param._mangle_candidate = True
+
+    def children(self):
+        return [self.identifier] + self.parameters + self.elements
+
+class FuncDecl(FuncBase):
+    pass
+
+# The only difference is that function expression might not have an identifier
+class FuncExpr(FuncBase):
+    pass
+
+
+class Comma(Node):
+    def __init__(self, left, right):
+        self.left = left
+        self.right = right
+
+    def children(self):
+        return [self.left, self.right]
+
+class EmptyStatement(Node):
+    def __init__(self, value):
+        self.value = value
+
+    def children(self):
+        return []
+
+class ExprStatement(Node):
+    def __init__(self, expr):
+        self.expr = expr
+
+    def children(self):
+        return [self.expr]
+
+class Elision(Node):
+    def __init__(self, value):
+        self.value = value
+
+    def children(self):
+        return []
+
+class This(Node):
+    def __init__(self):
+        pass
+
+    def children(self):
+        return []
diff --git a/webWidgetTCT_device/tools/slimit/lexer.py b/webWidgetTCT_device/tools/slimit/lexer.py
new file mode 100755 (executable)
index 0000000..06cd7c5
--- /dev/null
@@ -0,0 +1,437 @@
+###############################################################################
+#
+# Copyright (c) 2011 Ruslan Spivak
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+###############################################################################
+
+__author__ = 'Ruslan Spivak <ruslan.spivak@gmail.com>'
+
+import ply.lex
+
+from slimit.unicode_chars import (
+    LETTER,
+    DIGIT,
+    COMBINING_MARK,
+    CONNECTOR_PUNCTUATION,
+    )
+
+# See "Regular Expression Literals" at
+# http://www.mozilla.org/js/language/js20-2002-04/rationale/syntax.html
+TOKENS_THAT_IMPLY_DIVISON = frozenset([
+    'ID',
+    'NUMBER',
+    'STRING',
+    'REGEX',
+    'TRUE',
+    'FALSE',
+    'NULL',
+    'THIS',
+    'PLUSPLUS',
+    'MINUSMINUS',
+    'RPAREN',
+    'RBRACE',
+    'RBRACKET',
+    ])
+
+
+class Lexer(object):
+    """A JavaScript lexer.
+
+    >>> from slimit.lexer import Lexer
+    >>> lexer = Lexer()
+
+    Lexer supports iteration:
+
+    >>> lexer.input('a = 1;')
+    >>> for token in lexer:
+    ...     print token
+    ...
+    LexToken(ID,'a',1,0)
+    LexToken(EQ,'=',1,2)
+    LexToken(NUMBER,'1',1,4)
+    LexToken(SEMI,';',1,5)
+
+    Or call one token at a time with 'token' method:
+
+    >>> lexer.input('a = 1;')
+    >>> while True:
+    ...     token = lexer.token()
+    ...     if not token:
+    ...         break
+    ...     print token
+    ...
+    LexToken(ID,'a',1,0)
+    LexToken(EQ,'=',1,2)
+    LexToken(NUMBER,'1',1,4)
+    LexToken(SEMI,';',1,5)
+
+    >>> lexer.input('a = 1;')
+    >>> token = lexer.token()
+    >>> token.type, token.value, token.lineno, token.lexpos
+    ('ID', 'a', 1, 0)
+
+    For more information see:
+    http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf
+    """
+    def __init__(self):
+        self.prev_token = None
+        self.cur_token = None
+        self.next_tokens = []
+        self.build()
+
+    def build(self, **kwargs):
+        """Build the lexer."""
+        self.lexer = ply.lex.lex(object=self, **kwargs)
+
+    def input(self, text):
+        self.lexer.input(text)
+
+    def token(self):
+        if self.next_tokens:
+            return self.next_tokens.pop()
+
+        lexer = self.lexer
+        while True:
+            pos = lexer.lexpos
+            try:
+                char = lexer.lexdata[pos]
+                while char in ' \t':
+                    pos += 1
+                    char = lexer.lexdata[pos]
+                next_char = lexer.lexdata[pos + 1]
+            except IndexError:
+                tok = self._get_update_token()
+                if tok is not None and tok.type == 'LINE_TERMINATOR':
+                    continue
+                else:
+                    return tok
+
+            if char != '/' or (char == '/' and next_char in ('/', '*')):
+                tok = self._get_update_token()
+                if tok.type in ('LINE_TERMINATOR',
+                                'LINE_COMMENT', 'BLOCK_COMMENT'):
+                    continue
+                else:
+                    return tok
+
+            # current character is '/' which is either division or regex
+            cur_token = self.cur_token
+            is_division_allowed = (
+                cur_token is not None and
+                cur_token.type in TOKENS_THAT_IMPLY_DIVISON
+                )
+            if is_division_allowed:
+                return self._get_update_token()
+            else:
+                self.prev_token = self.cur_token
+                self.cur_token = self._read_regex()
+                return self.cur_token
+
+    def auto_semi(self, token):
+        if (token is None or token.type == 'RBRACE'
+            or self._is_prev_token_lt()
+            ):
+            if token:
+                self.next_tokens.append(token)
+            return self._create_semi_token(token)
+
+    def _is_prev_token_lt(self):
+        return self.prev_token and self.prev_token.type == 'LINE_TERMINATOR'
+
+    def _read_regex(self):
+        self.lexer.begin('regex')
+        token = self.lexer.token()
+        self.lexer.begin('INITIAL')
+        return token
+
+    def _get_update_token(self):
+        self.prev_token = self.cur_token
+        self.cur_token = self.lexer.token()
+        # insert semicolon before restricted tokens
+        # See section 7.9.1 ECMA262
+        if (self.cur_token is not None
+            and self.cur_token.type == 'LINE_TERMINATOR'
+            and self.prev_token is not None
+            and self.prev_token.type in ['BREAK', 'CONTINUE',
+                                         'RETURN', 'THROW']
+            ):
+            return self._create_semi_token(self.cur_token)
+        return self.cur_token
+
+    def _create_semi_token(self, orig_token):
+        token = ply.lex.LexToken()
+        token.type = 'SEMI'
+        token.value = ';'
+        if orig_token is not None:
+            token.lineno = orig_token.lineno
+            token.lexpos = orig_token.lexpos
+        else:
+            token.lineno = 0
+            token.lexpos = 0
+        return token
+
+    # iterator protocol
+    def __iter__(self):
+        return self
+
+    def next(self):
+        token = self.token()
+        if not token:
+            raise StopIteration
+
+        return token
+
+    states = (
+        ('regex', 'exclusive'),
+        )
+
+    keywords = (
+        'BREAK', 'CASE', 'CATCH', 'CONTINUE', 'DEBUGGER', 'DEFAULT', 'DELETE',
+        'DO', 'ELSE', 'FINALLY', 'FOR', 'FUNCTION', 'IF', 'IN',
+        'INSTANCEOF', 'NEW', 'RETURN', 'SWITCH', 'THIS', 'THROW', 'TRY',
+        'TYPEOF', 'VAR', 'VOID', 'WHILE', 'WITH', 'NULL', 'TRUE', 'FALSE',
+        # future reserved words - well, it's uncommented now to make
+        # IE8 happy because it chokes up on minification:
+        # obj["class"] -> obj.class
+        'CLASS', 'CONST', 'ENUM', 'EXPORT', 'EXTENDS', 'IMPORT', 'SUPER',
+        )
+    keywords_dict = dict((key.lower(), key) for key in keywords)
+
+    tokens = (
+        # Punctuators
+        'PERIOD', 'COMMA', 'SEMI', 'COLON',     # . , ; :
+        'PLUS', 'MINUS', 'MULT', 'DIV', 'MOD',  # + - * / %
+        'BAND', 'BOR', 'BXOR', 'BNOT',          # & | ^ ~
+        'CONDOP',                               # conditional operator ?
+        'NOT',                                  # !
+        'LPAREN', 'RPAREN',                     # ( and )
+        'LBRACE', 'RBRACE',                     # { and }
+        'LBRACKET', 'RBRACKET',                 # [ and ]
+        'EQ', 'EQEQ', 'NE',                     # = == !=
+        'STREQ', 'STRNEQ',                      # === and !==
+        'LT', 'GT',                             # < and >
+        'LE', 'GE',                             # <= and >=
+        'OR', 'AND',                            # || and &&
+        'PLUSPLUS', 'MINUSMINUS',               # ++ and --
+        'LSHIFT',                               # <<
+        'RSHIFT', 'URSHIFT',                    # >> and >>>
+        'PLUSEQUAL', 'MINUSEQUAL',              # += and -=
+        'MULTEQUAL', 'DIVEQUAL',                # *= and /=
+        'LSHIFTEQUAL',                          # <<=
+        'RSHIFTEQUAL', 'URSHIFTEQUAL',          # >>= and >>>=
+        'ANDEQUAL', 'MODEQUAL',                 # &= and %=
+        'XOREQUAL', 'OREQUAL',                  # ^= and |=
+
+        # Terminal types
+        'NUMBER', 'STRING', 'ID', 'REGEX',
+
+        # Properties
+        'GETPROP', 'SETPROP',
+
+        # Comments
+        'LINE_COMMENT', 'BLOCK_COMMENT',
+
+        'LINE_TERMINATOR',
+        ) + keywords
+
+    # adapted from https://bitbucket.org/ned/jslex
+    t_regex_REGEX = r"""(?:
+        /                       # opening slash
+        # First character is..
+        (?: [^*\\/[]            # anything but * \ / or [
+        |   \\.                 # or an escape sequence
+        |   \[                  # or a class, which has
+                (?: [^\]\\]     # anything but \ or ]
+                |   \\.         # or an escape sequence
+                )*              # many times
+            \]
+        )
+        # Following characters are same, except for excluding a star
+        (?: [^\\/[]             # anything but \ / or [
+        |   \\.                 # or an escape sequence
+        |   \[                  # or a class, which has
+                (?: [^\]\\]     # anything but \ or ]
+                |   \\.         # or an escape sequence
+                )*              # many times
+            \]
+        )*                      # many times
+        /                       # closing slash
+        [a-zA-Z0-9]*            # trailing flags
+        )
+        """
+
+    t_regex_ignore = ' \t'
+
+    def t_regex_error(self, token):
+        raise TypeError(
+            "Error parsing regular expression '%s' at %s" % (
+                token.value, token.lineno)
+            )
+
+    # Punctuators
+    t_PERIOD        = r'\.'
+    t_COMMA         = r','
+    t_SEMI          = r';'
+    t_COLON         = r':'
+    t_PLUS          = r'\+'
+    t_MINUS         = r'-'
+    t_MULT          = r'\*'
+    t_DIV           = r'/'
+    t_MOD           = r'%'
+    t_BAND          = r'&'
+    t_BOR           = r'\|'
+    t_BXOR          = r'\^'
+    t_BNOT          = r'~'
+    t_CONDOP        = r'\?'
+    t_NOT           = r'!'
+    t_LPAREN        = r'\('
+    t_RPAREN        = r'\)'
+    t_LBRACE        = r'{'
+    t_RBRACE        = r'}'
+    t_LBRACKET      = r'\['
+    t_RBRACKET      = r'\]'
+    t_EQ            = r'='
+    t_EQEQ          = r'=='
+    t_NE            = r'!='
+    t_STREQ         = r'==='
+    t_STRNEQ        = r'!=='
+    t_LT            = r'<'
+    t_GT            = r'>'
+    t_LE            = r'<='
+    t_GE            = r'>='
+    t_OR            = r'\|\|'
+    t_AND           = r'&&'
+    t_PLUSPLUS      = r'\+\+'
+    t_MINUSMINUS    = r'--'
+    t_LSHIFT        = r'<<'
+    t_RSHIFT        = r'>>'
+    t_URSHIFT       = r'>>>'
+    t_PLUSEQUAL     = r'\+='
+    t_MINUSEQUAL    = r'-='
+    t_MULTEQUAL     = r'\*='
+    t_DIVEQUAL      = r'/='
+    t_LSHIFTEQUAL   = r'<<='
+    t_RSHIFTEQUAL   = r'>>='
+    t_URSHIFTEQUAL  = r'>>>='
+    t_ANDEQUAL      = r'&='
+    t_MODEQUAL      = r'%='
+    t_XOREQUAL      = r'\^='
+    t_OREQUAL       = r'\|='
+
+    t_LINE_COMMENT  = r'//[^\r\n]*'
+    t_BLOCK_COMMENT = r'/\*[^*]*\*+([^/*][^*]*\*+)*/'
+
+    t_LINE_TERMINATOR = r'[\n\r]+'
+
+    t_ignore = ' \t'
+
+    t_NUMBER = r"""
+    (?:
+        0[xX][0-9a-fA-F]+              # hex_integer_literal
+     |  0[0-7]+                        # or octal_integer_literal (spec B.1.1)
+     |  (?:                            # or decimal_literal
+            (?:0|[1-9][0-9]*)          # decimal_integer_literal
+            \.                         # dot
+            [0-9]*                     # decimal_digits_opt
+            (?:[eE][+-]?[0-9]+)?       # exponent_part_opt
+         |
+            \.                         # dot
+            [0-9]+                     # decimal_digits
+            (?:[eE][+-]?[0-9]+)?       # exponent_part_opt
+         |
+            (?:0|[1-9][0-9]*)          # decimal_integer_literal
+            (?:[eE][+-]?[0-9]+)?       # exponent_part_opt
+         )
+    )
+    """
+
+    string = r"""
+    (?:
+        # double quoted string
+        (?:"                               # opening double quote
+            (?: [^"\\\n\r]                 # no \, line terminators or "
+                | \\[a-zA-Z!-\/:-@\[-`{-~] # or escaped characters
+                | \\x[0-9a-fA-F]{2}        # or hex_escape_sequence
+                | \\u[0-9a-fA-F]{4}        # or unicode_escape_sequence
+            )*?                            # zero or many times
+            (?: \\\n                       # multiline ?
+              (?:
+                [^"\\\n\r]                 # no \, line terminators or "
+                | \\[a-zA-Z!-\/:-@\[-`{-~] # or escaped characters
+                | \\x[0-9a-fA-F]{2}        # or hex_escape_sequence
+                | \\u[0-9a-fA-F]{4}        # or unicode_escape_sequence
+              )*?                          # zero or many times
+            )*
+        ")                                 # closing double quote
+        |
+        # single quoted string
+        (?:'                               # opening single quote
+            (?: [^'\\\n\r]                 # no \, line terminators or '
+                | \\[a-zA-Z!-\/:-@\[-`{-~] # or escaped characters
+                | \\x[0-9a-fA-F]{2}        # or hex_escape_sequence
+                | \\u[0-9a-fA-F]{4}        # or unicode_escape_sequence
+            )*?                            # zero or many times
+            (?: \\\n                       # multiline ?
+              (?:
+                [^'\\\n\r]                 # no \, line terminators or '
+                | \\[a-zA-Z!-\/:-@\[-`{-~] # or escaped characters
+                | \\x[0-9a-fA-F]{2}        # or hex_escape_sequence
+                | \\u[0-9a-fA-F]{4}        # or unicode_escape_sequence
+              )*?                          # zero or many times
+            )*
+        ')                                 # closing single quote
+    )
+    """  # "
+
+    @ply.lex.TOKEN(string)
+    def t_STRING(self, token):
+        # remove escape + new line sequence used for strings
+        # written across multiple lines of code
+        token.value = token.value.replace('\\\n', '')
+        return token
+
+    # XXX: <ZWNJ> <ZWJ> ?
+    identifier_start = r'(?:' + r'[a-zA-Z_$]' + r'|' + LETTER + r')+'
+    identifier_part = (
+        r'(?:' + COMBINING_MARK + r'|' + r'[0-9a-zA-Z_$]' + r'|' + DIGIT +
+        r'|' + CONNECTOR_PUNCTUATION + r')*'
+        )
+    identifier = identifier_start + identifier_part
+
+    getprop = r'get' + r'(?=\s' + identifier + r')'
+    @ply.lex.TOKEN(getprop)
+    def t_GETPROP(self, token):
+        return token
+
+    setprop = r'set' + r'(?=\s' + identifier + r')'
+    @ply.lex.TOKEN(setprop)
+    def t_SETPROP(self, token):
+        return token
+
+    @ply.lex.TOKEN(identifier)
+    def t_ID(self, token):
+        token.type = self.keywords_dict.get(token.value, 'ID')
+        return token
+
+    def t_error(self, token):
+        print 'Illegal character %r at %s:%s after %s' % (
+            token.value[0], token.lineno, token.lexpos, self.prev_token)
+        token.lexer.skip(1)
diff --git a/webWidgetTCT_device/tools/slimit/lextab.py b/webWidgetTCT_device/tools/slimit/lextab.py
new file mode 100755 (executable)
index 0000000..f2d1f6f
--- /dev/null
@@ -0,0 +1,9 @@
+# lextab.py. This file automatically created by PLY (version 3.4). Don't edit!
+_tabversion   = '3.4'
+_lextokens    = {'BOR': 1, 'LBRACKET': 1, 'WITH': 1, 'MINUS': 1, 'RPAREN': 1, 'PLUS': 1, 'VOID': 1, 'BLOCK_COMMENT': 1, 'GT': 1, 'RBRACE': 1, 'PERIOD': 1, 'GE': 1, 'VAR': 1, 'THIS': 1, 'MINUSEQUAL': 1, 'TYPEOF': 1, 'OR': 1, 'DELETE': 1, 'DIVEQUAL': 1, 'RETURN': 1, 'RSHIFTEQUAL': 1, 'EQEQ': 1, 'SETPROP': 1, 'BNOT': 1, 'URSHIFTEQUAL': 1, 'TRUE': 1, 'COLON': 1, 'FUNCTION': 1, 'LINE_COMMENT': 1, 'FOR': 1, 'PLUSPLUS': 1, 'ELSE': 1, 'TRY': 1, 'EQ': 1, 'AND': 1, 'LBRACE': 1, 'CONTINUE': 1, 'NOT': 1, 'OREQUAL': 1, 'MOD': 1, 'RSHIFT': 1, 'DEFAULT': 1, 'WHILE': 1, 'NEW': 1, 'CASE': 1, 'MODEQUAL': 1, 'NE': 1, 'MULTEQUAL': 1, 'SWITCH': 1, 'CATCH': 1, 'STREQ': 1, 'INSTANCEOF': 1, 'PLUSEQUAL': 1, 'GETPROP': 1, 'FALSE': 1, 'CONDOP': 1, 'BREAK': 1, 'LINE_TERMINATOR': 1, 'ANDEQUAL': 1, 'DO': 1, 'NUMBER': 1, 'LSHIFT': 1, 'DIV': 1, 'NULL': 1, 'MULT': 1, 'DEBUGGER': 1, 'LE': 1, 'SEMI': 1, 'BXOR': 1, 'LT': 1, 'COMMA': 1, 'REGEX': 1, 'STRING': 1, 'BAND': 1, 'FINALLY': 1, 'STRNEQ': 1, 'LPAREN': 1, 'IN': 1, 'MINUSMINUS': 1, 'ID': 1, 'IF': 1, 'XOREQUAL': 1, 'LSHIFTEQUAL': 1, 'URSHIFT': 1, 'RBRACKET': 1, 'THROW': 1}
+_lexreflags   = 0
+_lexliterals  = ''
+_lexstateinfo = {'regex': 'exclusive', 'INITIAL': 'inclusive'}
+_lexstatere   = {'regex': [('(?P<t_regex_REGEX>(?:\n        /                       # opening slash\n        # First character is..\n        (?: [^*\\\\/[]            # anything but * \\ / or [\n        |   \\\\.                 # or an escape sequence\n        |   \\[                  # or a class, which has\n                (?: [^\\]\\\\]     # anything but \\ or ]\n                |   \\\\.         # or an escape sequence\n                )*              # many times\n            \\]\n        )\n        # Following characters are same, except for excluding a star\n        (?: [^\\\\/[]             # anything but \\ / or [\n        |   \\\\.                 # or an escape sequence\n        |   \\[                  # or a class, which has\n                (?: [^\\]\\\\]     # anything but \\ or ]\n                |   \\\\.         # or an escape sequence\n                )*              # many times\n            \\]\n        )*                      # many times\n        /                       # closing slash\n        [a-zA-Z0-9]*            # trailing flags\n        )\n        )', [None, (None, 'REGEX')])], 'INITIAL': [(u'(?P<t_STRING>\n    (?:\n        # double quoted string\n        (?:"                               # opening double quote\n            (?: [^"\\\\\\n\\r]                 # no \\, line terminators or "\n                | \\\\[a-zA-Z!-\\/:-@\\[-`{-~] # or escaped characters\n                | \\\\x[0-9a-fA-F]{2}        # or hex_escape_sequence\n                | \\\\u[0-9a-fA-F]{4}        # or unicode_escape_sequence\n            )*?                            # zero or many times\n            (?: \\\\\\n                       # multiline ?\n              (?:\n                [^"\\\\\\n\\r]                 # no \\, line terminators or "\n                | \\\\[a-zA-Z!-\\/:-@\\[-`{-~] # or escaped characters\n                | \\\\x[0-9a-fA-F]{2}        # or hex_escape_sequence\n                | \\\\u[0-9a-fA-F]{4}        # or unicode_escape_sequence\n              )*?                          # zero or many times\n            )*\n        ")                                 # closing double quote\n        |\n        # single quoted string\n        (?:\'                               # opening single quote\n            (?: [^\'\\\\\\n\\r]                 # no \\, line terminators or \'\n                | \\\\[a-zA-Z!-\\/:-@\\[-`{-~] # or escaped characters\n                | \\\\x[0-9a-fA-F]{2}        # or hex_escape_sequence\n                | \\\\u[0-9a-fA-F]{4}        # or unicode_escape_sequence\n            )*?                            # zero or many times\n            (?: \\\\\\n                       # multiline ?\n              (?:\n                [^\'\\\\\\n\\r]                 # no \\, line terminators or \'\n                | \\\\[a-zA-Z!-\\/:-@\\[-`{-~] # or escaped characters\n                | \\\\x[0-9a-fA-F]{2}        # or hex_escape_sequence\n                | \\\\u[0-9a-fA-F]{4}        # or unicode_escape_sequence\n              )*?                          # zero or many times\n            )*\n        \')                                 # closing single quote\n    )\n    )|(?P<t_GETPROP>get(?=\\s(?:[a-zA-Z_$]|[A-Za-z\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0523\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0621-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971\u0972\u097b-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d28\u0d2a-\u0d39\u0d3d\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc\u0edd\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8b\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10d0-\u10fa\u10fc\u1100-\u1159\u115f-\u11a2\u11a8-\u11f9\u1200-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u1676\u1681-\u169a\u16a0-\u16ea\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19a9\u19c1-\u19c7\u1a00-\u1a16\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u2094\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2183\u2184\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2c6f\u2c71-\u2c7d\u2c80-\u2ce4\u2d00-\u2d25\u2d30-\u2d65\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005\u3006\u3031-\u3035\u303b\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31b7\u31f0-\u31ff\u3400\u4db5\u4e00\u9fc3\ua000-\ua48c\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua65f\ua662-\ua66e\ua67f-\ua697\ua717-\ua71f\ua722-\ua788\ua78b\ua78c\ua7fb-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua90a-\ua925\ua930-\ua946\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uac00\ud7a3\uf900-\ufa2d\ufa30-\ufa6a\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc])+(?:[\u0300-\u036f\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09c1-\u09c4\u09cd\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b62\u0b63\u0b82\u0bc0\u0bcd\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc6\u0ccc\u0ccd\u0ce2\u0ce3\u0d41-\u0d44\u0d4d\u0d62\u0d63\u0dca\u0dd2-\u0dd4\u0dd6\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\ufb1e\ufe00-\ufe0f\ufe20-\ufe26]|[\u0903\u093e-\u0940\u0949-\u094c\u094e\u0982\u0983\u09be-\u09c0\u09c7\u09c8\u09cb\u09cc\u09d7\u0a03\u0a3e-\u0a40\u0a83\u0abe-\u0ac0\u0ac9\u0acb\u0acc\u0b02\u0b03\u0b3e\u0b40\u0b47\u0b48\u0b4b\u0b4c\u0b57\u0bbe\u0bbf\u0bc1\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcc\u0bd7\u0c01-\u0c03\u0c41-\u0c44\u0c82\u0c83\u0cbe\u0cc0-\u0cc4\u0cc7\u0cc8\u0cca\u0ccb\u0cd5\u0cd6\u0d02\u0d03\u0d3e-\u0d40\u0d46-\u0d48\u0d4a-\u0d4c\u0d57\u0d82\u0d83\u0dcf-\u0dd1\u0dd8-\u0ddf\u0df2\u0df3\u0f3e\u0f3f\u0f7f\u102b\u102c\u1031\u1038\u103b\u103c\u1056\u1057\u1062-\u1064\u1067-\u106d\u1083\u1084\u1087-\u108c\u108f\u109a-\u109c\u17b6\u17be-\u17c5\u17c7\u17c8\u1923-\u1926\u1929-\u192b\u1930\u1931\u1933-\u1938\u19b0-\u19c0\u19c8\u19c9\u1a19-\u1a1b\u1a55\u1a57\u1a61\u1a63\u1a64\u1a6d-\u1a72\u1b04\u1b35\u1b3b\u1b3d-\u1b41\u1b43\u1b44\u1b82\u1ba1\u1ba6\u1ba7\u1baa\u1c24-\u1c2b\u1c34\u1c35\u1ce1\u1cf2\ua823\ua824\ua827\ua880\ua881\ua8b4-\ua8c3\ua952\ua953\ua983\ua9b4\ua9b5\ua9ba\ua9bb\ua9bd-\ua9c0\uaa2f\uaa30\uaa33\uaa34\uaa4d\uaa7b\uabe3\uabe4\uabe6\uabe7\uabe9\uabea\uabec]|[0-9a-zA-Z_$]|[0-9\u0660-\u0669\u06f0-\u06f9\u07c0-\u07c9\u0966-\u096f\u09e6-\u09ef\u0a66-\u0a6f\u0ae6-\u0aef\u0b66-\u0b6f\u0be6-\u0bef\u0c66-\u0c6f\u0ce6-\u0cef\u0d66-\u0d6f\u0e50-\u0e59\u0ed0-\u0ed9\u0f20-\u0f29\u1040-\u1049\u1090-\u1099\u17e0-\u17e9\u1810-\u1819\u1946-\u194f\u19d0-\u19da\u1a80-\u1a89\u1a90-\u1a99\u1b50-\u1b59\u1bb0-\u1bb9\u1c40-\u1c49\u1c50-\u1c59\ua620-\ua629\ua8d0-\ua8d9\ua900-\ua909\ua9d0-\ua9d9\uaa50-\uaa59\uabf0-\uabf9\uff10-\uff19]|[_\u203f\u2040\u2054\ufe33\ufe34\ufe4d-\ufe4f\uff3f])*))|(?P<t_SETPROP>set(?=\\s(?:[a-zA-Z_$]|[A-Za-z\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0523\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0621-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971\u0972\u097b-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d28\u0d2a-\u0d39\u0d3d\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc\u0edd\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8b\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10d0-\u10fa\u10fc\u1100-\u1159\u115f-\u11a2\u11a8-\u11f9\u1200-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u1676\u1681-\u169a\u16a0-\u16ea\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19a9\u19c1-\u19c7\u1a00-\u1a16\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u2094\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2183\u2184\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2c6f\u2c71-\u2c7d\u2c80-\u2ce4\u2d00-\u2d25\u2d30-\u2d65\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005\u3006\u3031-\u3035\u303b\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31b7\u31f0-\u31ff\u3400\u4db5\u4e00\u9fc3\ua000-\ua48c\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua65f\ua662-\ua66e\ua67f-\ua697\ua717-\ua71f\ua722-\ua788\ua78b\ua78c\ua7fb-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua90a-\ua925\ua930-\ua946\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uac00\ud7a3\uf900-\ufa2d\ufa30-\ufa6a\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc])+(?:[\u0300-\u036f\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09c1-\u09c4\u09cd\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b62\u0b63\u0b82\u0bc0\u0bcd\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc6\u0ccc\u0ccd\u0ce2\u0ce3\u0d41-\u0d44\u0d4d\u0d62\u0d63\u0dca\u0dd2-\u0dd4\u0dd6\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\ufb1e\ufe00-\ufe0f\ufe20-\ufe26]|[\u0903\u093e-\u0940\u0949-\u094c\u094e\u0982\u0983\u09be-\u09c0\u09c7\u09c8\u09cb\u09cc\u09d7\u0a03\u0a3e-\u0a40\u0a83\u0abe-\u0ac0\u0ac9\u0acb\u0acc\u0b02\u0b03\u0b3e\u0b40\u0b47\u0b48\u0b4b\u0b4c\u0b57\u0bbe\u0bbf\u0bc1\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcc\u0bd7\u0c01-\u0c03\u0c41-\u0c44\u0c82\u0c83\u0cbe\u0cc0-\u0cc4\u0cc7\u0cc8\u0cca\u0ccb\u0cd5\u0cd6\u0d02\u0d03\u0d3e-\u0d40\u0d46-\u0d48\u0d4a-\u0d4c\u0d57\u0d82\u0d83\u0dcf-\u0dd1\u0dd8-\u0ddf\u0df2\u0df3\u0f3e\u0f3f\u0f7f\u102b\u102c\u1031\u1038\u103b\u103c\u1056\u1057\u1062-\u1064\u1067-\u106d\u1083\u1084\u1087-\u108c\u108f\u109a-\u109c\u17b6\u17be-\u17c5\u17c7\u17c8\u1923-\u1926\u1929-\u192b\u1930\u1931\u1933-\u1938\u19b0-\u19c0\u19c8\u19c9\u1a19-\u1a1b\u1a55\u1a57\u1a61\u1a63\u1a64\u1a6d-\u1a72\u1b04\u1b35\u1b3b\u1b3d-\u1b41\u1b43\u1b44\u1b82\u1ba1\u1ba6\u1ba7\u1baa\u1c24-\u1c2b\u1c34\u1c35\u1ce1\u1cf2\ua823\ua824\ua827\ua880\ua881\ua8b4-\ua8c3\ua952\ua953\ua983\ua9b4\ua9b5\ua9ba\ua9bb\ua9bd-\ua9c0\uaa2f\uaa30\uaa33\uaa34\uaa4d\uaa7b\uabe3\uabe4\uabe6\uabe7\uabe9\uabea\uabec]|[0-9a-zA-Z_$]|[0-9\u0660-\u0669\u06f0-\u06f9\u07c0-\u07c9\u0966-\u096f\u09e6-\u09ef\u0a66-\u0a6f\u0ae6-\u0aef\u0b66-\u0b6f\u0be6-\u0bef\u0c66-\u0c6f\u0ce6-\u0cef\u0d66-\u0d6f\u0e50-\u0e59\u0ed0-\u0ed9\u0f20-\u0f29\u1040-\u1049\u1090-\u1099\u17e0-\u17e9\u1810-\u1819\u1946-\u194f\u19d0-\u19da\u1a80-\u1a89\u1a90-\u1a99\u1b50-\u1b59\u1bb0-\u1bb9\u1c40-\u1c49\u1c50-\u1c59\ua620-\ua629\ua8d0-\ua8d9\ua900-\ua909\ua9d0-\ua9d9\uaa50-\uaa59\uabf0-\uabf9\uff10-\uff19]|[_\u203f\u2040\u2054\ufe33\ufe34\ufe4d-\ufe4f\uff3f])*))|(?P<t_ID>(?:[a-zA-Z_$]|[A-Za-z\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0523\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0621-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971\u0972\u097b-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d28\u0d2a-\u0d39\u0d3d\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc\u0edd\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8b\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10d0-\u10fa\u10fc\u1100-\u1159\u115f-\u11a2\u11a8-\u11f9\u1200-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u1676\u1681-\u169a\u16a0-\u16ea\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19a9\u19c1-\u19c7\u1a00-\u1a16\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u2094\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2183\u2184\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2c6f\u2c71-\u2c7d\u2c80-\u2ce4\u2d00-\u2d25\u2d30-\u2d65\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005\u3006\u3031-\u3035\u303b\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31b7\u31f0-\u31ff\u3400\u4db5\u4e00\u9fc3\ua000-\ua48c\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua65f\ua662-\ua66e\ua67f-\ua697\ua717-\ua71f\ua722-\ua788\ua78b\ua78c\ua7fb-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua90a-\ua925\ua930-\ua946\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uac00\ud7a3\uf900-\ufa2d\ufa30-\ufa6a\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc])+(?:[\u0300-\u036f\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09c1-\u09c4\u09cd\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b62\u0b63\u0b82\u0bc0\u0bcd\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc6\u0ccc\u0ccd\u0ce2\u0ce3\u0d41-\u0d44\u0d4d\u0d62\u0d63\u0dca\u0dd2-\u0dd4\u0dd6\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\ufb1e\ufe00-\ufe0f\ufe20-\ufe26]|[\u0903\u093e-\u0940\u0949-\u094c\u094e\u0982\u0983\u09be-\u09c0\u09c7\u09c8\u09cb\u09cc\u09d7\u0a03\u0a3e-\u0a40\u0a83\u0abe-\u0ac0\u0ac9\u0acb\u0acc\u0b02\u0b03\u0b3e\u0b40\u0b47\u0b48\u0b4b\u0b4c\u0b57\u0bbe\u0bbf\u0bc1\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcc\u0bd7\u0c01-\u0c03\u0c41-\u0c44\u0c82\u0c83\u0cbe\u0cc0-\u0cc4\u0cc7\u0cc8\u0cca\u0ccb\u0cd5\u0cd6\u0d02\u0d03\u0d3e-\u0d40\u0d46-\u0d48\u0d4a-\u0d4c\u0d57\u0d82\u0d83\u0dcf-\u0dd1\u0dd8-\u0ddf\u0df2\u0df3\u0f3e\u0f3f\u0f7f\u102b\u102c\u1031\u1038\u103b\u103c\u1056\u1057\u1062-\u1064\u1067-\u106d\u1083\u1084\u1087-\u108c\u108f\u109a-\u109c\u17b6\u17be-\u17c5\u17c7\u17c8\u1923-\u1926\u1929-\u192b\u1930\u1931\u1933-\u1938\u19b0-\u19c0\u19c8\u19c9\u1a19-\u1a1b\u1a55\u1a57\u1a61\u1a63\u1a64\u1a6d-\u1a72\u1b04\u1b35\u1b3b\u1b3d-\u1b41\u1b43\u1b44\u1b82\u1ba1\u1ba6\u1ba7\u1baa\u1c24-\u1c2b\u1c34\u1c35\u1ce1\u1cf2\ua823\ua824\ua827\ua880\ua881\ua8b4-\ua8c3\ua952\ua953\ua983\ua9b4\ua9b5\ua9ba\ua9bb\ua9bd-\ua9c0\uaa2f\uaa30\uaa33\uaa34\uaa4d\uaa7b\uabe3\uabe4\uabe6\uabe7\uabe9\uabea\uabec]|[0-9a-zA-Z_$]|[0-9\u0660-\u0669\u06f0-\u06f9\u07c0-\u07c9\u0966-\u096f\u09e6-\u09ef\u0a66-\u0a6f\u0ae6-\u0aef\u0b66-\u0b6f\u0be6-\u0bef\u0c66-\u0c6f\u0ce6-\u0cef\u0d66-\u0d6f\u0e50-\u0e59\u0ed0-\u0ed9\u0f20-\u0f29\u1040-\u1049\u1090-\u1099\u17e0-\u17e9\u1810-\u1819\u1946-\u194f\u19d0-\u19da\u1a80-\u1a89\u1a90-\u1a99\u1b50-\u1b59\u1bb0-\u1bb9\u1c40-\u1c49\u1c50-\u1c59\ua620-\ua629\ua8d0-\ua8d9\ua900-\ua909\ua9d0-\ua9d9\uaa50-\uaa59\uabf0-\uabf9\uff10-\uff19]|[_\u203f\u2040\u2054\ufe33\ufe34\ufe4d-\ufe4f\uff3f])*)|(?P<t_NUMBER>\n    (?:\n        0[xX][0-9a-fA-F]+              # hex_integer_literal\n     |  0[0-7]+                        # or octal_integer_literal (spec B.1.1)\n     |  (?:                            # or decimal_literal\n            (?:0|[1-9][0-9]*)          # decimal_integer_literal\n            \\.                         # dot\n            [0-9]*                     # decimal_digits_opt\n            (?:[eE][+-]?[0-9]+)?       # exponent_part_opt\n         |\n            \\.                         # dot\n            [0-9]+                     # decimal_digits\n            (?:[eE][+-]?[0-9]+)?       # exponent_part_opt\n         |\n            (?:0|[1-9][0-9]*)          # decimal_integer_literal\n            (?:[eE][+-]?[0-9]+)?       # exponent_part_opt\n         )\n    )\n    )|(?P<t_BLOCK_COMMENT>/\\*[^*]*\\*+([^/*][^*]*\\*+)*/)|(?P<t_LINE_COMMENT>//[^\\r\\n]*)|(?P<t_LINE_TERMINATOR>[\\n\\r]+)|(?P<t_PLUSPLUS>\\+\\+)|(?P<t_OR>\\|\\|)|(?P<t_URSHIFTEQUAL>>>>=)|(?P<t_XOREQUAL>\\^=)|(?P<t_OREQUAL>\\|=)|(?P<t_LSHIFTEQUAL><<=)|(?P<t_STRNEQ>!==)|(?P<t_RSHIFTEQUAL>>>=)|(?P<t_URSHIFT>>>>)|(?P<t_PLUSEQUAL>\\+=)|(?P<t_MULTEQUAL>\\*=)|(?P<t_STREQ>===)|(?P<t_PERIOD>\\.)|(?P<t_PLUS>\\+)|(?P<t_MODEQUAL>%=)|(?P<t_DIVEQUAL>/=)|(?P<t_RBRACKET>\\])|(?P<t_CONDOP>\\?)|(?P<t_BOR>\\|)|(?P<t_LSHIFT><<)|(?P<t_LE><=)|(?P<t_BXOR>\\^)|(?P<t_LPAREN>\\()|(?P<t_MULT>\\*)|(?P<t_NE>!=)|(?P<t_MINUSMINUS>--)|(?P<t_AND>&&)|(?P<t_LBRACKET>\\[)|(?P<t_GE>>=)|(?P<t_RPAREN>\\))|(?P<t_RSHIFT>>>)|(?P<t_ANDEQUAL>&=)|(?P<t_MINUSEQUAL>-=)|(?P<t_EQEQ>==)|(?P<t_LBRACE>{)|(?P<t_LT><)|(?P<t_COMMA>,)|(?P<t_EQ>=)|(?P<t_BNOT>~)|(?P<t_RBRACE>})|(?P<t_DIV>/)|(?P<t_MOD>%)|(?P<t_SEMI>;)|(?P<t_MINUS>-)|(?P<t_GT>>)|(?P<t_COLON>:)|(?P<t_BAND>&)|(?P<t_NOT>!)', [None, (u't_STRING', 'STRING'), (u't_GETPROP', 'GETPROP'), (u't_SETPROP', 'SETPROP'), (u't_ID', 'ID'), (None, 'NUMBER'), (None, 'BLOCK_COMMENT'), None, (None, 'LINE_COMMENT'), (None, 'LINE_TERMINATOR'), (None, 'PLUSPLUS'), (None, 'OR'), (None, 'URSHIFTEQUAL'), (None, 'XOREQUAL'), (None, 'OREQUAL'), (None, 'LSHIFTEQUAL'), (None, 'STRNEQ'), (None, 'RSHIFTEQUAL'), (None, 'URSHIFT'), (None, 'PLUSEQUAL'), (None, 'MULTEQUAL'), (None, 'STREQ'), (None, 'PERIOD'), (None, 'PLUS'), (None, 'MODEQUAL'), (None, 'DIVEQUAL'), (None, 'RBRACKET'), (None, 'CONDOP'), (None, 'BOR'), (None, 'LSHIFT'), (None, 'LE'), (None, 'BXOR'), (None, 'LPAREN'), (None, 'MULT'), (None, 'NE'), (None, 'MINUSMINUS'), (None, 'AND'), (None, 'LBRACKET'), (None, 'GE'), (None, 'RPAREN'), (None, 'RSHIFT'), (None, 'ANDEQUAL'), (None, 'MINUSEQUAL'), (None, 'EQEQ'), (None, 'LBRACE'), (None, 'LT'), (None, 'COMMA'), (None, 'EQ'), (None, 'BNOT'), (None, 'RBRACE'), (None, 'DIV'), (None, 'MOD'), (None, 'SEMI'), (None, 'MINUS'), (None, 'GT'), (None, 'COLON'), (None, 'BAND'), (None, 'NOT')])]}
+_lexstateignore = {'regex': ' \t', 'INITIAL': ' \t'}
+_lexstateerrorf = {'regex': 't_regex_error', 'INITIAL': 't_error'}
diff --git a/webWidgetTCT_device/tools/slimit/mangler.py b/webWidgetTCT_device/tools/slimit/mangler.py
new file mode 100755 (executable)
index 0000000..a8cdb9e
--- /dev/null
@@ -0,0 +1,51 @@
+###############################################################################
+#
+# Copyright (c) 2011 Ruslan Spivak
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+###############################################################################
+
+__author__ = 'Ruslan Spivak <ruslan.spivak@gmail.com>'
+
+from slimit.scope import SymbolTable
+from slimit.visitors.scopevisitor import (
+    ScopeTreeVisitor,
+    fill_scope_references,
+    mangle_scope_tree,
+    NameManglerVisitor,
+    )
+
+
+def mangle(tree, toplevel=False):
+    """Mangle names.
+
+    Args:
+        toplevel: defaults to False. Defines if global
+        scope should be mangled or not.
+    """
+    sym_table = SymbolTable()
+    visitor = ScopeTreeVisitor(sym_table)
+    visitor.visit(tree)
+
+    fill_scope_references(tree)
+    mangle_scope_tree(sym_table.globals, toplevel)
+
+    mangler = NameManglerVisitor()
+    mangler.visit(tree)
diff --git a/webWidgetTCT_device/tools/slimit/minifier.py b/webWidgetTCT_device/tools/slimit/minifier.py
new file mode 100755 (executable)
index 0000000..a046eff
--- /dev/null
@@ -0,0 +1,70 @@
+###############################################################################
+#
+# Copyright (c) 2011 Ruslan Spivak
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+###############################################################################
+
+__author__ = 'Ruslan Spivak <ruslan.spivak@gmail.com>'
+
+import sys
+import optparse
+import textwrap
+
+from slimit import mangler
+from slimit.parser import Parser
+from slimit.visitors.minvisitor import ECMAMinifier
+
+
+def minify(text, mangle=False, mangle_toplevel=False):
+    parser = Parser()
+    tree = parser.parse(text)
+    if mangle:
+        mangler.mangle(tree, toplevel=mangle_toplevel)
+    minified = ECMAMinifier().visit(tree)
+    return minified
+
+
+def main(argv=None, inp=sys.stdin, out=sys.stdout):
+    usage = textwrap.dedent("""\
+    %prog [options] [input file]
+
+    If no input file is provided STDIN is used by default.
+    Minified JavaScript code is printed to STDOUT.
+    """)
+    parser = optparse.OptionParser(usage=usage)
+    parser.add_option('-m', '--mangle', action='store_true',
+                      dest='mangle', default=False, help='mangle names')
+    parser.add_option('-t', '--mangle-toplevel', action='store_true',
+                      dest='mangle_toplevel', default=False,
+                      help='mangle top level scope (defaults to False)')
+
+    if argv is None:
+        argv = sys.argv[1:]
+    options, args = parser.parse_args(argv)
+
+    if len(args) == 1:
+        text = open(args[0]).read()
+    else:
+        text = inp.read()
+
+    minified = minify(
+        text, mangle=options.mangle, mangle_toplevel=options.mangle_toplevel)
+    out.write(minified)
diff --git a/webWidgetTCT_device/tools/slimit/parser.py b/webWidgetTCT_device/tools/slimit/parser.py
new file mode 100755 (executable)
index 0000000..d892166
--- /dev/null
@@ -0,0 +1,1223 @@
+###############################################################################
+#
+# Copyright (c) 2011 Ruslan Spivak
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+###############################################################################
+
+__author__ = 'Ruslan Spivak <ruslan.spivak@gmail.com>'
+
+import ply.yacc
+
+from slimit import ast
+from slimit.lexer import Lexer
+
+try:
+    from slimit import lextab, yacctab
+except ImportError:
+    lextab, yacctab = 'lextab', 'yacctab'
+
+
+class Parser(object):
+    """JavaScript parser(ECMA-262 5th edition grammar).
+
+    The '*noin' variants are needed to avoid confusing the `in` operator in
+    a relational expression with the `in` operator in a `for` statement.
+
+    '*nobf' stands for 'no brace or function'
+    """
+
+    def __init__(self, lex_optimize=True, lextab=lextab,
+                 yacc_optimize=True, yacctab=yacctab, yacc_debug=False):
+        self.lex_optimize = lex_optimize
+        self.lextab = lextab
+        self.yacc_optimize = yacc_optimize
+        self.yacctab = yacctab
+        self.yacc_debug = yacc_debug
+
+        self.lexer = Lexer()
+        self.lexer.build(optimize=lex_optimize, lextab=lextab)
+        self.tokens = self.lexer.tokens
+
+        self.parser = ply.yacc.yacc(
+            module=self, optimize=yacc_optimize,
+            debug=yacc_debug, tabmodule=yacctab, start='program')
+
+        # https://github.com/rspivak/slimit/issues/29
+        # lexer.auto_semi can cause a loop in a parser
+        # when a parser error happens on a token right after
+        # a newline.
+        # We keep record of the tokens that caused p_error
+        # and if the token has already been seen - we raise
+        # a SyntaxError exception to avoid looping over and
+        # over again.
+        self._error_tokens = {}
+
+    def _has_been_seen_before(self, token):
+        if token is None:
+            return False
+        key = token.type, token.value, token.lineno, token.lexpos
+        return key in self._error_tokens
+
+    def _mark_as_seen(self, token):
+        if token is None:
+            return
+        key = token.type, token.value, token.lineno, token.lexpos
+        self._error_tokens[key] = True
+
+    def _raise_syntax_error(self, token):
+        raise SyntaxError(
+            'Unexpected token (%s, %r) at %s:%s between %s and %s' % (
+                token.type, token.value, token.lineno, token.lexpos,
+                self.lexer.prev_token, self.lexer.token())
+            )
+
+    def parse(self, text, debug=False):
+        return self.parser.parse(text, lexer=self.lexer, debug=debug)
+
+    def p_empty(self, p):
+        """empty :"""
+        pass
+
+    def p_auto_semi(self, p):
+        """auto_semi : error"""
+        pass
+
+    def p_error(self, token):
+        # https://github.com/rspivak/slimit/issues/29
+        if self._has_been_seen_before(token):
+            self._raise_syntax_error(token)
+
+        if token is None or token.type != 'SEMI':
+            next_token = self.lexer.auto_semi(token)
+            if next_token is not None:
+                # https://github.com/rspivak/slimit/issues/29
+                self._mark_as_seen(token)
+                self.parser.errok()
+                return next_token
+
+        self._raise_syntax_error(token)
+
+    # Comment rules
+    # def p_single_line_comment(self, p):
+    #     """single_line_comment : LINE_COMMENT"""
+    #     pass
+
+    # def p_multi_line_comment(self, p):
+    #     """multi_line_comment : BLOCK_COMMENT"""
+    #     pass
+
+    # Main rules
+
+    def p_program(self, p):
+        """program : source_elements"""
+        p[0] = ast.Program(p[1])
+
+    def p_source_elements(self, p):
+        """source_elements : empty
+                           | source_element_list
+        """
+        p[0] = p[1]
+
+    def p_source_element_list(self, p):
+        """source_element_list : source_element
+                               | source_element_list source_element
+        """
+        if len(p) == 2: # single source element
+            p[0] = [p[1]]
+        else:
+            p[1].append(p[2])
+            p[0] = p[1]
+
+    def p_source_element(self, p):
+        """source_element : statement
+                          | function_declaration
+        """
+        p[0] = p[1]
+
+    def p_statement(self, p):
+        """statement : block
+                     | variable_statement
+                     | empty_statement
+                     | expr_statement
+                     | if_statement
+                     | iteration_statement
+                     | continue_statement
+                     | break_statement
+                     | return_statement
+                     | with_statement
+                     | switch_statement
+                     | labelled_statement
+                     | throw_statement
+                     | try_statement
+                     | debugger_statement
+                     | function_declaration
+        """
+        p[0] = p[1]
+
+    # By having source_elements in the production we support
+    # also function_declaration inside blocks
+    def p_block(self, p):
+        """block : LBRACE source_elements RBRACE"""
+        p[0] = ast.Block(p[2])
+
+    def p_literal(self, p):
+        """literal : null_literal
+                   | boolean_literal
+                   | numeric_literal
+                   | string_literal
+                   | regex_literal
+        """
+        p[0] = p[1]
+
+    def p_boolean_literal(self, p):
+        """boolean_literal : TRUE
+                           | FALSE
+        """
+        p[0] = ast.Boolean(p[1])
+
+    def p_null_literal(self, p):
+        """null_literal : NULL"""
+        p[0] = ast.Null(p[1])
+
+    def p_numeric_literal(self, p):
+        """numeric_literal : NUMBER"""
+        p[0] = ast.Number(p[1])
+
+    def p_string_literal(self, p):
+        """string_literal : STRING"""
+        p[0] = ast.String(p[1])
+
+    def p_regex_literal(self, p):
+        """regex_literal : REGEX"""
+        p[0] = ast.Regex(p[1])
+
+    def p_identifier(self, p):
+        """identifier : ID"""
+        p[0] = ast.Identifier(p[1])
+
+    ###########################################
+    # Expressions
+    ###########################################
+    def p_primary_expr(self, p):
+        """primary_expr : primary_expr_no_brace
+                        | object_literal
+        """
+        p[0] = p[1]
+
+    def p_primary_expr_no_brace_1(self, p):
+        """primary_expr_no_brace : identifier"""
+        p[1]._mangle_candidate = True
+        p[1]._in_expression = True
+        p[0] = p[1]
+
+    def p_primary_expr_no_brace_2(self, p):
+        """primary_expr_no_brace : THIS"""
+        p[0] = ast.This()
+
+    def p_primary_expr_no_brace_3(self, p):
+        """primary_expr_no_brace : literal
+                                 | array_literal
+        """
+        p[0] = p[1]
+
+    def p_primary_expr_no_brace_4(self, p):
+        """primary_expr_no_brace : LPAREN expr RPAREN"""
+        p[2]._parens = True
+        p[0] = p[2]
+
+    def p_array_literal_1(self, p):
+        """array_literal : LBRACKET elision_opt RBRACKET"""
+        p[0] = ast.Array(items=p[2])
+
+    def p_array_literal_2(self, p):
+        """array_literal : LBRACKET element_list RBRACKET
+                         | LBRACKET element_list COMMA elision_opt RBRACKET
+        """
+        items = p[2]
+        if len(p) == 6:
+            items.extend(p[4])
+        p[0] = ast.Array(items=items)
+
+
+    def p_element_list(self, p):
+        """element_list : elision_opt assignment_expr
+                        | element_list COMMA elision_opt assignment_expr
+        """
+        if len(p) == 3:
+            p[0] = p[1] + [p[2]]
+        else:
+            p[1].extend(p[3])
+            p[1].append(p[4])
+            p[0] = p[1]
+
+    def p_elision_opt_1(self, p):
+        """elision_opt : empty"""
+        p[0] = []
+
+    def p_elision_opt_2(self, p):
+        """elision_opt : elision"""
+        p[0] = p[1]
+
+    def p_elision(self, p):
+        """elision : COMMA
+                   | elision COMMA
+        """
+        if len(p) == 2:
+            p[0] = [ast.Elision(p[1])]
+        else:
+            p[1].append(ast.Elision(p[2]))
+            p[0] = p[1]
+
+    def p_object_literal(self, p):
+        """object_literal : LBRACE RBRACE
+                          | LBRACE property_list RBRACE
+                          | LBRACE property_list COMMA RBRACE
+        """
+        if len(p) == 3:
+            p[0] = ast.Object()
+        else:
+            p[0] = ast.Object(properties=p[2])
+
+    def p_property_list(self, p):
+        """property_list : property_assignment
+                         | property_list COMMA property_assignment
+        """
+        if len(p) == 2:
+            p[0] = [p[1]]
+        else:
+            p[1].append(p[3])
+            p[0] = p[1]
+
+    # XXX: GET / SET
+    def p_property_assignment(self, p):
+        """property_assignment \
+             : property_name COLON assignment_expr
+             | GETPROP property_name LPAREN RPAREN LBRACE function_body RBRACE
+             | SETPROP property_name LPAREN formal_parameter_list RPAREN \
+                   LBRACE function_body RBRACE
+        """
+        if len(p) == 4:
+            p[0] = ast.Assign(left=p[1], op=p[2], right=p[3])
+        elif len(p) == 8:
+            p[0] = ast.GetPropAssign(prop_name=p[2], elements=p[6])
+        else:
+            p[0] = ast.SetPropAssign(
+                prop_name=p[2], parameters=p[4], elements=p[7])
+
+    def p_property_name(self, p):
+        """property_name : identifier
+                         | string_literal
+                         | numeric_literal
+        """
+        p[0] = p[1]
+
+    # 11.2 Left-Hand-Side Expressions
+    def p_member_expr(self, p):
+        """member_expr : primary_expr
+                       | function_expr
+                       | member_expr LBRACKET expr RBRACKET
+                       | member_expr PERIOD identifier
+                       | NEW member_expr arguments
+        """
+        if len(p) == 2:
+            p[0] = p[1]
+        elif p[1] == 'new':
+            p[0] = ast.NewExpr(p[2], p[3])
+        elif p[2] == '.':
+            p[0] = ast.DotAccessor(p[1], p[3])
+        else:
+            p[0] = ast.BracketAccessor(p[1], p[3])
+
+    def p_member_expr_nobf(self, p):
+        """member_expr_nobf : primary_expr_no_brace
+                            | function_expr
+                            | member_expr_nobf LBRACKET expr RBRACKET
+                            | member_expr_nobf PERIOD identifier
+                            | NEW member_expr arguments
+        """
+        if len(p) == 2:
+            p[0] = p[1]
+        elif p[1] == 'new':
+            p[0] = ast.NewExpr(p[2], p[3])
+        elif p[2] == '.':
+            p[0] = ast.DotAccessor(p[1], p[3])
+        else:
+            p[0] = ast.BracketAccessor(p[1], p[3])
+
+    def p_new_expr(self, p):
+        """new_expr : member_expr
+                    | NEW new_expr
+        """
+        if len(p) == 2:
+            p[0] = p[1]
+        else:
+            p[0] = ast.NewExpr(p[2])
+
+    def p_new_expr_nobf(self, p):
+        """new_expr_nobf : member_expr_nobf
+                         | NEW new_expr
+        """
+        if len(p) == 2:
+            p[0] = p[1]
+        else:
+            p[0] = ast.NewExpr(p[2])
+
+    def p_call_expr(self, p):
+        """call_expr : member_expr arguments
+                     | call_expr arguments
+                     | call_expr LBRACKET expr RBRACKET
+                     | call_expr PERIOD identifier
+        """
+        if len(p) == 3:
+            p[0] = ast.FunctionCall(p[1], p[2])
+        elif len(p) == 4:
+            p[0] = ast.DotAccessor(p[1], p[3])
+        else:
+            p[0] = ast.BracketAccessor(p[1], p[3])
+
+    def p_call_expr_nobf(self, p):
+        """call_expr_nobf : member_expr_nobf arguments
+                          | call_expr_nobf arguments
+                          | call_expr_nobf LBRACKET expr RBRACKET
+                          | call_expr_nobf PERIOD identifier
+        """
+        if len(p) == 3:
+            p[0] = ast.FunctionCall(p[1], p[2])
+        elif len(p) == 4:
+            p[0] = ast.DotAccessor(p[1], p[3])
+        else:
+            p[0] = ast.BracketAccessor(p[1], p[3])
+
+    def p_arguments(self, p):
+        """arguments : LPAREN RPAREN
+                     | LPAREN argument_list RPAREN
+        """
+        if len(p) == 4:
+            p[0] = p[2]
+
+    def p_argument_list(self, p):
+        """argument_list : assignment_expr
+                         | argument_list COMMA assignment_expr
+        """
+        if len(p) == 2:
+            p[0] = [p[1]]
+        else:
+            p[1].append(p[3])
+            p[0] = p[1]
+
+    def p_lef_hand_side_expr(self, p):
+        """left_hand_side_expr : new_expr
+                               | call_expr
+        """
+        p[0] = p[1]
+
+    def p_lef_hand_side_expr_nobf(self, p):
+        """left_hand_side_expr_nobf : new_expr_nobf
+                                    | call_expr_nobf
+        """
+        p[0] = p[1]
+
+    # 11.3 Postfix Expressions
+    def p_postfix_expr(self, p):
+        """postfix_expr : left_hand_side_expr
+                        | left_hand_side_expr PLUSPLUS
+                        | left_hand_side_expr MINUSMINUS
+        """
+        if len(p) == 2:
+            p[0] = p[1]
+        else:
+            p[0] = ast.UnaryOp(op=p[2], value=p[1], postfix=True)
+
+    def p_postfix_expr_nobf(self, p):
+        """postfix_expr_nobf : left_hand_side_expr_nobf
+                             | left_hand_side_expr_nobf PLUSPLUS
+                             | left_hand_side_expr_nobf MINUSMINUS
+        """
+        if len(p) == 2:
+            p[0] = p[1]
+        else:
+            p[0] = ast.UnaryOp(op=p[2], value=p[1], postfix=True)
+
+    # 11.4 Unary Operators
+    def p_unary_expr(self, p):
+        """unary_expr : postfix_expr
+                      | unary_expr_common
+        """
+        p[0] = p[1]
+
+    def p_unary_expr_nobf(self, p):
+        """unary_expr_nobf : postfix_expr_nobf
+                           | unary_expr_common
+        """
+        p[0] = p[1]
+
+    def p_unary_expr_common(self, p):
+        """unary_expr_common : DELETE unary_expr
+                             | VOID unary_expr
+                             | TYPEOF unary_expr
+                             | PLUSPLUS unary_expr
+                             | MINUSMINUS unary_expr
+                             | PLUS unary_expr
+                             | MINUS unary_expr
+                             | BNOT unary_expr
+                             | NOT unary_expr
+        """
+        p[0] = ast.UnaryOp(p[1], p[2])
+
+    # 11.5 Multiplicative Operators
+    def p_multiplicative_expr(self, p):
+        """multiplicative_expr : unary_expr
+                               | multiplicative_expr MULT unary_expr
+                               | multiplicative_expr DIV unary_expr
+                               | multiplicative_expr MOD unary_expr
+        """
+        if len(p) == 2:
+            p[0] = p[1]
+        else:
+            p[0] = ast.BinOp(op=p[2], left=p[1], right=p[3])
+
+    def p_multiplicative_expr_nobf(self, p):
+        """multiplicative_expr_nobf : unary_expr_nobf
+                                    | multiplicative_expr_nobf MULT unary_expr
+                                    | multiplicative_expr_nobf DIV unary_expr
+                                    | multiplicative_expr_nobf MOD unary_expr
+        """
+        if len(p) == 2:
+            p[0] = p[1]
+        else:
+            p[0] = ast.BinOp(op=p[2], left=p[1], right=p[3])
+
+    # 11.6 Additive Operators
+    def p_additive_expr(self, p):
+        """additive_expr : multiplicative_expr
+                         | additive_expr PLUS multiplicative_expr
+                         | additive_expr MINUS multiplicative_expr
+        """
+        if len(p) == 2:
+            p[0] = p[1]
+        else:
+            p[0] = ast.BinOp(op=p[2], left=p[1], right=p[3])
+
+    def p_additive_expr_nobf(self, p):
+        """additive_expr_nobf : multiplicative_expr_nobf
+                              | additive_expr_nobf PLUS multiplicative_expr
+                              | additive_expr_nobf MINUS multiplicative_expr
+        """
+        if len(p) == 2:
+            p[0] = p[1]
+        else:
+            p[0] = ast.BinOp(op=p[2], left=p[1], right=p[3])
+
+    # 11.7 Bitwise Shift Operators
+    def p_shift_expr(self, p):
+        """shift_expr : additive_expr
+                      | shift_expr LSHIFT additive_expr
+                      | shift_expr RSHIFT additive_expr
+                      | shift_expr URSHIFT additive_expr
+        """
+        if len(p) == 2:
+            p[0] = p[1]
+        else:
+            p[0] = ast.BinOp(op=p[2], left=p[1], right=p[3])
+
+    def p_shift_expr_nobf(self, p):
+        """shift_expr_nobf : additive_expr_nobf
+                           | shift_expr_nobf LSHIFT additive_expr
+                           | shift_expr_nobf RSHIFT additive_expr
+                           | shift_expr_nobf URSHIFT additive_expr
+        """
+        if len(p) == 2:
+            p[0] = p[1]
+        else:
+            p[0] = ast.BinOp(op=p[2], left=p[1], right=p[3])
+
+
+    # 11.8 Relational Operators
+    def p_relational_expr(self, p):
+        """relational_expr : shift_expr
+                           | relational_expr LT shift_expr
+                           | relational_expr GT shift_expr
+                           | relational_expr LE shift_expr
+                           | relational_expr GE shift_expr
+                           | relational_expr INSTANCEOF shift_expr
+                           | relational_expr IN shift_expr
+        """
+        if len(p) == 2:
+            p[0] = p[1]
+        else:
+            p[0] = ast.BinOp(op=p[2], left=p[1], right=p[3])
+
+    def p_relational_expr_noin(self, p):
+        """relational_expr_noin : shift_expr
+                                | relational_expr_noin LT shift_expr
+                                | relational_expr_noin GT shift_expr
+                                | relational_expr_noin LE shift_expr
+                                | relational_expr_noin GE shift_expr
+                                | relational_expr_noin INSTANCEOF shift_expr
+        """
+        if len(p) == 2:
+            p[0] = p[1]
+        else:
+            p[0] = ast.BinOp(op=p[2], left=p[1], right=p[3])
+
+    def p_relational_expr_nobf(self, p):
+        """relational_expr_nobf : shift_expr_nobf
+                                | relational_expr_nobf LT shift_expr
+                                | relational_expr_nobf GT shift_expr
+                                | relational_expr_nobf LE shift_expr
+                                | relational_expr_nobf GE shift_expr
+                                | relational_expr_nobf INSTANCEOF shift_expr
+                                | relational_expr_nobf IN shift_expr
+        """
+        if len(p) == 2:
+            p[0] = p[1]
+        else:
+            p[0] = ast.BinOp(op=p[2], left=p[1], right=p[3])
+
+    # 11.9 Equality Operators
+    def p_equality_expr(self, p):
+        """equality_expr : relational_expr
+                         | equality_expr EQEQ relational_expr
+                         | equality_expr NE relational_expr
+                         | equality_expr STREQ relational_expr
+                         | equality_expr STRNEQ relational_expr
+        """
+        if len(p) == 2:
+            p[0] = p[1]
+        else:
+            p[0] = ast.BinOp(op=p[2], left=p[1], right=p[3])
+
+    def p_equality_expr_noin(self, p):
+        """equality_expr_noin : relational_expr_noin
+                              | equality_expr_noin EQEQ relational_expr
+                              | equality_expr_noin NE relational_expr
+                              | equality_expr_noin STREQ relational_expr
+                              | equality_expr_noin STRNEQ relational_expr
+        """
+        if len(p) == 2:
+            p[0] = p[1]
+        else:
+            p[0] = ast.BinOp(op=p[2], left=p[1], right=p[3])
+
+    def p_equality_expr_nobf(self, p):
+        """equality_expr_nobf : relational_expr_nobf
+                              | equality_expr_nobf EQEQ relational_expr
+                              | equality_expr_nobf NE relational_expr
+                              | equality_expr_nobf STREQ relational_expr
+                              | equality_expr_nobf STRNEQ relational_expr
+        """
+        if len(p) == 2:
+            p[0] = p[1]
+        else:
+            p[0] = ast.BinOp(op=p[2], left=p[1], right=p[3])
+
+    # 11.10 Binary Bitwise Operators
+    def p_bitwise_and_expr(self, p):
+        """bitwise_and_expr : equality_expr
+                            | bitwise_and_expr BAND equality_expr
+        """
+        if len(p) == 2:
+            p[0] = p[1]
+        else:
+            p[0] = ast.BinOp(op=p[2], left=p[1], right=p[3])
+
+    def p_bitwise_and_expr_noin(self, p):
+        """bitwise_and_expr_noin \
+            : equality_expr_noin
+            | bitwise_and_expr_noin BAND equality_expr_noin
+        """
+        if len(p) == 2:
+            p[0] = p[1]
+        else:
+            p[0] = ast.BinOp(op=p[2], left=p[1], right=p[3])
+
+    def p_bitwise_and_expr_nobf(self, p):
+        """bitwise_and_expr_nobf \
+            : equality_expr_nobf
+            | bitwise_and_expr_nobf BAND equality_expr_nobf
+        """
+        if len(p) == 2:
+            p[0] = p[1]
+        else:
+            p[0] = ast.BinOp(op=p[2], left=p[1], right=p[3])
+
+    def p_bitwise_xor_expr(self, p):
+        """bitwise_xor_expr : bitwise_and_expr
+                            | bitwise_xor_expr BXOR bitwise_and_expr
+        """
+        if len(p) == 2:
+            p[0] = p[1]
+        else:
+            p[0] = ast.BinOp(op=p[2], left=p[1], right=p[3])
+
+    def p_bitwise_xor_expr_noin(self, p):
+        """
+        bitwise_xor_expr_noin \
+            : bitwise_and_expr_noin
+            | bitwise_xor_expr_noin BXOR bitwise_and_expr_noin
+        """
+        if len(p) == 2:
+            p[0] = p[1]
+        else:
+            p[0] = ast.BinOp(op=p[2], left=p[1], right=p[3])
+
+    def p_bitwise_xor_expr_nobf(self, p):
+        """
+        bitwise_xor_expr_nobf \
+            : bitwise_and_expr_nobf
+            | bitwise_xor_expr_nobf BXOR bitwise_and_expr_nobf
+        """
+        if len(p) == 2:
+            p[0] = p[1]
+        else:
+            p[0] = ast.BinOp(op=p[2], left=p[1], right=p[3])
+
+    def p_bitwise_or_expr(self, p):
+        """bitwise_or_expr : bitwise_xor_expr
+                           | bitwise_or_expr BOR bitwise_xor_expr
+        """
+        if len(p) == 2:
+            p[0] = p[1]
+        else:
+            p[0] = ast.BinOp(op=p[2], left=p[1], right=p[3])
+
+    def p_bitwise_or_expr_noin(self, p):
+        """
+        bitwise_or_expr_noin \
+            : bitwise_xor_expr_noin
+            | bitwise_or_expr_noin BOR bitwise_xor_expr_noin
+        """
+        if len(p) == 2:
+            p[0] = p[1]
+        else:
+            p[0] = ast.BinOp(op=p[2], left=p[1], right=p[3])
+
+    def p_bitwise_or_expr_nobf(self, p):
+        """
+        bitwise_or_expr_nobf \
+            : bitwise_xor_expr_nobf
+            | bitwise_or_expr_nobf BOR bitwise_xor_expr_nobf
+        """
+        if len(p) == 2:
+            p[0] = p[1]
+        else:
+            p[0] = ast.BinOp(op=p[2], left=p[1], right=p[3])
+
+    # 11.11 Binary Logical Operators
+    def p_logical_and_expr(self, p):
+        """logical_and_expr : bitwise_or_expr
+                            | logical_and_expr AND bitwise_or_expr
+        """
+        if len(p) == 2:
+            p[0] = p[1]
+        else:
+            p[0] = ast.BinOp(op=p[2], left=p[1], right=p[3])
+
+    def p_logical_and_expr_noin(self, p):
+        """
+        logical_and_expr_noin : bitwise_or_expr_noin
+                              | logical_and_expr_noin AND bitwise_or_expr_noin
+        """
+        if len(p) == 2:
+            p[0] = p[1]
+        else:
+            p[0] = ast.BinOp(op=p[2], left=p[1], right=p[3])
+
+    def p_logical_and_expr_nobf(self, p):
+        """
+        logical_and_expr_nobf : bitwise_or_expr_nobf
+                              | logical_and_expr_nobf AND bitwise_or_expr_nobf
+        """
+        if len(p) == 2:
+            p[0] = p[1]
+        else:
+            p[0] = ast.BinOp(op=p[2], left=p[1], right=p[3])
+
+    def p_logical_or_expr(self, p):
+        """logical_or_expr : logical_and_expr
+                           | logical_or_expr OR logical_and_expr
+        """
+        if len(p) == 2:
+            p[0] = p[1]
+        else:
+            p[0] = ast.BinOp(op=p[2], left=p[1], right=p[3])
+
+    def p_logical_or_expr_noin(self, p):
+        """logical_or_expr_noin : logical_and_expr_noin
+                                | logical_or_expr_noin OR logical_and_expr_noin
+        """
+        if len(p) == 2:
+            p[0] = p[1]
+        else:
+            p[0] = ast.BinOp(op=p[2], left=p[1], right=p[3])
+
+    def p_logical_or_expr_nobf(self, p):
+        """logical_or_expr_nobf : logical_and_expr_nobf
+                                | logical_or_expr_nobf OR logical_and_expr_nobf
+        """
+        if len(p) == 2:
+            p[0] = p[1]
+        else:
+            p[0] = ast.BinOp(op=p[2], left=p[1], right=p[3])
+
+    # 11.12 Conditional Operator ( ? : )
+    def p_conditional_expr(self, p):
+        """
+        conditional_expr \
+            : logical_or_expr
+            | logical_or_expr CONDOP assignment_expr COLON assignment_expr
+        """
+        if len(p) == 2:
+            p[0] = p[1]
+        else:
+            p[0] = ast.Conditional(
+                predicate=p[1], consequent=p[3], alternative=p[5])
+
+    def p_conditional_expr_noin(self, p):
+        """
+        conditional_expr_noin \
+            : logical_or_expr_noin
+            | logical_or_expr_noin CONDOP assignment_expr_noin COLON \
+                  assignment_expr_noin
+        """
+        if len(p) == 2:
+            p[0] = p[1]
+        else:
+            p[0] = ast.Conditional(
+                predicate=p[1], consequent=p[3], alternative=p[5])
+
+    def p_conditional_expr_nobf(self, p):
+        """
+        conditional_expr_nobf \
+            : logical_or_expr_nobf
+            | logical_or_expr_nobf CONDOP assignment_expr COLON assignment_expr
+        """
+        if len(p) == 2:
+            p[0] = p[1]
+        else:
+            p[0] = ast.Conditional(
+                predicate=p[1], consequent=p[3], alternative=p[5])
+
+    # 11.13 Assignment Operators
+    def p_assignment_expr(self, p):
+        """
+        assignment_expr \
+            : conditional_expr
+            | left_hand_side_expr assignment_operator assignment_expr
+        """
+        if len(p) == 2:
+            p[0] = p[1]
+        else:
+            p[0] = ast.Assign(left=p[1], op=p[2], right=p[3])
+
+    def p_assignment_expr_noin(self, p):
+        """
+        assignment_expr_noin \
+            : conditional_expr_noin
+            | left_hand_side_expr assignment_operator assignment_expr_noin
+        """
+        if len(p) == 2:
+            p[0] = p[1]
+        else:
+            p[0] = ast.Assign(left=p[1], op=p[2], right=p[3])
+
+    def p_assignment_expr_nobf(self, p):
+        """
+        assignment_expr_nobf \
+            : conditional_expr_nobf
+            | left_hand_side_expr_nobf assignment_operator assignment_expr
+        """
+        if len(p) == 2:
+            p[0] = p[1]
+        else:
+            p[0] = ast.Assign(left=p[1], op=p[2], right=p[3])
+
+    def p_assignment_operator(self, p):
+        """assignment_operator : EQ
+                               | MULTEQUAL
+                               | DIVEQUAL
+                               | MODEQUAL
+                               | PLUSEQUAL
+                               | MINUSEQUAL
+                               | LSHIFTEQUAL
+                               | RSHIFTEQUAL
+                               | URSHIFTEQUAL
+                               | ANDEQUAL
+                               | XOREQUAL
+                               | OREQUAL
+        """
+        p[0] = p[1]
+
+    # 11.4 Comma Operator
+    def p_expr(self, p):
+        """expr : assignment_expr
+                | expr COMMA assignment_expr
+        """
+        if len(p) == 2:
+            p[0] = p[1]
+        else:
+            p[0] = ast.Comma(left=p[1], right=p[3])
+
+    def p_expr_noin(self, p):
+        """expr_noin : assignment_expr_noin
+                     | expr_noin COMMA assignment_expr_noin
+        """
+        if len(p) == 2:
+            p[0] = p[1]
+        else:
+            p[0] = ast.Comma(left=p[1], right=p[3])
+
+    def p_expr_nobf(self, p):
+        """expr_nobf : assignment_expr_nobf
+                     | expr_nobf COMMA assignment_expr
+        """
+        if len(p) == 2:
+            p[0] = p[1]
+        else:
+            p[0] = ast.Comma(left=p[1], right=p[3])
+
+    # 12.2 Variable Statement
+    def p_variable_statement(self, p):
+        """variable_statement : VAR variable_declaration_list SEMI
+                              | VAR variable_declaration_list auto_semi
+        """
+        p[0] = ast.VarStatement(p[2])
+
+    def p_variable_declaration_list(self, p):
+        """
+        variable_declaration_list \
+            : variable_declaration
+            | variable_declaration_list COMMA variable_declaration
+        """
+        if len(p) == 2:
+            p[0] = [p[1]]
+        else:
+            p[1].append(p[3])
+            p[0] = p[1]
+
+    def p_variable_declaration_list_noin(self, p):
+        """
+        variable_declaration_list_noin \
+            : variable_declaration_noin
+            | variable_declaration_list_noin COMMA variable_declaration_noin
+        """
+        if len(p) == 2:
+            p[0] = [p[1]]
+        else:
+            p[1].append(p[3])
+            p[0] = p[1]
+
+    def p_variable_declaration(self, p):
+        """variable_declaration : identifier
+                                | identifier initializer
+        """
+        if len(p) == 2:
+            p[0] = ast.VarDecl(p[1])
+        else:
+            p[0] = ast.VarDecl(p[1], p[2])
+
+    def p_variable_declaration_noin(self, p):
+        """variable_declaration_noin : identifier
+                                     | identifier initializer_noin
+        """
+        if len(p) == 2:
+            p[0] = ast.VarDecl(p[1])
+        else:
+            p[0] = ast.VarDecl(p[1], p[2])
+
+    def p_initializer(self, p):
+        """initializer : EQ assignment_expr"""
+        p[0] = p[2]
+
+    def p_initializer_noin(self, p):
+        """initializer_noin : EQ assignment_expr_noin"""
+        p[0] = p[2]
+
+    # 12.3 Empty Statement
+    def p_empty_statement(self, p):
+        """empty_statement : SEMI"""
+        p[0] = ast.EmptyStatement(p[1])
+
+    # 12.4 Expression Statement
+    def p_expr_statement(self, p):
+        """expr_statement : expr_nobf SEMI
+                          | expr_nobf auto_semi
+        """
+        p[0] = ast.ExprStatement(p[1])
+
+    # 12.5 The if Statement
+    def p_if_statement_1(self, p):
+        """if_statement : IF LPAREN expr RPAREN statement"""
+        p[0] = ast.If(predicate=p[3], consequent=p[5])
+
+    def p_if_statement_2(self, p):
+        """if_statement : IF LPAREN expr RPAREN statement ELSE statement"""
+        p[0] = ast.If(predicate=p[3], consequent=p[5], alternative=p[7])
+
+    # 12.6 Iteration Statements
+    def p_iteration_statement_1(self, p):
+        """
+        iteration_statement \
+            : DO statement WHILE LPAREN expr RPAREN SEMI
+            | DO statement WHILE LPAREN expr RPAREN auto_semi
+        """
+        p[0] = ast.DoWhile(predicate=p[5], statement=p[2])
+
+    def p_iteration_statement_2(self, p):
+        """iteration_statement : WHILE LPAREN expr RPAREN statement"""
+        p[0] = ast.While(predicate=p[3], statement=p[5])
+
+    def p_iteration_statement_3(self, p):
+        """
+        iteration_statement \
+            : FOR LPAREN expr_noin_opt SEMI expr_opt SEMI expr_opt RPAREN \
+                  statement
+            | FOR LPAREN VAR variable_declaration_list_noin SEMI expr_opt SEMI\
+                  expr_opt RPAREN statement
+        """
+        if len(p) == 10:
+            p[0] = ast.For(init=p[3], cond=p[5], count=p[7], statement=p[9])
+        else:
+            init = ast.VarStatement(p[4])
+            p[0] = ast.For(init=init, cond=p[6], count=p[8], statement=p[10])
+
+    def p_iteration_statement_4(self, p):
+        """
+        iteration_statement \
+            : FOR LPAREN left_hand_side_expr IN expr RPAREN statement
+        """
+        p[0] = ast.ForIn(item=p[3], iterable=p[5], statement=p[7])
+
+    def p_iteration_statement_5(self, p):
+        """
+        iteration_statement : \
+            FOR LPAREN VAR identifier IN expr RPAREN statement
+        """
+        p[0] = ast.ForIn(item=ast.VarDecl(p[4]), iterable=p[6], statement=p[8])
+
+    def p_iteration_statement_6(self, p):
+        """
+        iteration_statement \
+          : FOR LPAREN VAR identifier initializer_noin IN expr RPAREN statement
+        """
+        p[0] = ast.ForIn(item=ast.VarDecl(identifier=p[4], initializer=p[5]),
+                         iterable=p[7], statement=p[9])
+
+    def p_expr_opt(self, p):
+        """expr_opt : empty
+                    | expr
+        """
+        p[0] = p[1]
+
+    def p_expr_noin_opt(self, p):
+        """expr_noin_opt : empty
+                         | expr_noin
+        """
+        p[0] = p[1]
+
+    # 12.7 The continue Statement
+    def p_continue_statement_1(self, p):
+        """continue_statement : CONTINUE SEMI
+                              | CONTINUE auto_semi
+        """
+        p[0] = ast.Continue()
+
+    def p_continue_statement_2(self, p):
+        """continue_statement : CONTINUE identifier SEMI
+                              | CONTINUE identifier auto_semi
+        """
+        p[0] = ast.Continue(p[2])
+
+    # 12.8 The break Statement
+    def p_break_statement_1(self, p):
+        """break_statement : BREAK SEMI
+                           | BREAK auto_semi
+        """
+        p[0] = ast.Break()
+
+    def p_break_statement_2(self, p):
+        """break_statement : BREAK identifier SEMI
+                           | BREAK identifier auto_semi
+        """
+        p[0] = ast.Break(p[2])
+
+
+    # 12.9 The return Statement
+    def p_return_statement_1(self, p):
+        """return_statement : RETURN SEMI
+                            | RETURN auto_semi
+        """
+        p[0] = ast.Return()
+
+    def p_return_statement_2(self, p):
+        """return_statement : RETURN expr SEMI
+                            | RETURN expr auto_semi
+        """
+        p[0] = ast.Return(expr=p[2])
+
+    # 12.10 The with Statement
+    def p_with_statement(self, p):
+        """with_statement : WITH LPAREN expr RPAREN statement"""
+        p[0] = ast.With(expr=p[3], statement=p[5])
+
+    # 12.11 The switch Statement
+    def p_switch_statement(self, p):
+        """switch_statement : SWITCH LPAREN expr RPAREN case_block"""
+        cases = []
+        default = None
+        # iterate over return values from case_block
+        for item in p[5]:
+            if isinstance(item, ast.Default):
+                default = item
+            elif isinstance(item, list):
+                cases.extend(item)
+
+        p[0] = ast.Switch(expr=p[3], cases=cases, default=default)
+
+    def p_case_block(self, p):
+        """
+        case_block \
+            : LBRACE case_clauses_opt RBRACE
+            | LBRACE case_clauses_opt default_clause case_clauses_opt RBRACE
+        """
+        p[0] = p[2:-1]
+
+    def p_case_clauses_opt(self, p):
+        """case_clauses_opt : empty
+                            | case_clauses
+        """
+        p[0] = p[1]
+
+    def p_case_clauses(self, p):
+        """case_clauses : case_clause
+                        | case_clauses case_clause
+        """
+        if len(p) == 2:
+            p[0] = [p[1]]
+        else:
+            p[1].append(p[2])
+            p[0] = p[1]
+
+    def p_case_clause(self, p):
+        """case_clause : CASE expr COLON source_elements"""
+        p[0] = ast.Case(expr=p[2], elements=p[4])
+
+    def p_default_clause(self, p):
+        """default_clause : DEFAULT COLON source_elements"""
+        p[0] = ast.Default(elements=p[3])
+
+    # 12.12 Labelled Statements
+    def p_labelled_statement(self, p):
+        """labelled_statement : identifier COLON statement"""
+        p[0] = ast.Label(identifier=p[1], statement=p[3])
+
+    # 12.13 The throw Statement
+    def p_throw_statement(self, p):
+        """throw_statement : THROW expr SEMI
+                           | THROW expr auto_semi
+        """
+        p[0] = ast.Throw(expr=p[2])
+
+    # 12.14 The try Statement
+    def p_try_statement_1(self, p):
+        """try_statement : TRY block catch"""
+        p[0] = ast.Try(statements=p[2], catch=p[3])
+
+    def p_try_statement_2(self, p):
+        """try_statement : TRY block finally"""
+        p[0] = ast.Try(statements=p[2], fin=p[3])
+
+    def p_try_statement_3(self, p):
+        """try_statement : TRY block catch finally"""
+        p[0] = ast.Try(statements=p[2], catch=p[3], fin=p[4])
+
+    def p_catch(self, p):
+        """catch : CATCH LPAREN identifier RPAREN block"""
+        p[0] = ast.Catch(identifier=p[3], elements=p[5])
+
+    def p_finally(self, p):
+        """finally : FINALLY block"""
+        p[0] = ast.Finally(elements=p[2])
+
+    # 12.15 The debugger statement
+    def p_debugger_statement(self, p):
+        """debugger_statement : DEBUGGER SEMI
+                              | DEBUGGER auto_semi
+        """
+        p[0] = ast.Debugger(p[1])
+
+    # 13 Function Definition
+    def p_function_declaration(self, p):
+        """
+        function_declaration \
+            : FUNCTION identifier LPAREN RPAREN LBRACE function_body RBRACE
+            | FUNCTION identifier LPAREN formal_parameter_list RPAREN LBRACE \
+                 function_body RBRACE
+        """
+        if len(p) == 8:
+            p[0] = ast.FuncDecl(
+                identifier=p[2], parameters=None, elements=p[6])
+        else:
+            p[0] = ast.FuncDecl(
+                identifier=p[2], parameters=p[4], elements=p[7])
+
+    def p_function_expr_1(self, p):
+        """
+        function_expr \
+            : FUNCTION LPAREN RPAREN LBRACE function_body RBRACE
+            | FUNCTION LPAREN formal_parameter_list RPAREN \
+                LBRACE function_body RBRACE
+        """
+        if len(p) == 7:
+            p[0] = ast.FuncExpr(
+                identifier=None, parameters=None, elements=p[5])
+        else:
+            p[0] = ast.FuncExpr(
+                identifier=None, parameters=p[3], elements=p[6])
+
+    def p_function_expr_2(self, p):
+        """
+        function_expr \
+            : FUNCTION identifier LPAREN RPAREN LBRACE function_body RBRACE
+            | FUNCTION identifier LPAREN formal_parameter_list RPAREN \
+                LBRACE function_body RBRACE
+        """
+        if len(p) == 8:
+            p[0] = ast.FuncExpr(
+                identifier=p[2], parameters=None, elements=p[6])
+        else:
+            p[0] = ast.FuncExpr(
+                identifier=p[2], parameters=p[4], elements=p[7])
+
+
+    def p_formal_parameter_list(self, p):
+        """formal_parameter_list : identifier
+                                 | formal_parameter_list COMMA identifier
+        """
+        if len(p) == 2:
+            p[0] = [p[1]]
+        else:
+            p[1].append(p[3])
+            p[0] = p[1]
+
+    def p_function_body(self, p):
+        """function_body : source_elements"""
+        p[0] = p[1]
diff --git a/webWidgetTCT_device/tools/slimit/ply/__init__.py b/webWidgetTCT_device/tools/slimit/ply/__init__.py
new file mode 100755 (executable)
index 0000000..853a985
--- /dev/null
@@ -0,0 +1,4 @@
+# PLY package
+# Author: David Beazley (dave@dabeaz.com)
+
+__all__ = ['lex','yacc']
diff --git a/webWidgetTCT_device/tools/slimit/ply/cpp.py b/webWidgetTCT_device/tools/slimit/ply/cpp.py
new file mode 100755 (executable)
index 0000000..5cad682
--- /dev/null
@@ -0,0 +1,898 @@
+# -----------------------------------------------------------------------------
+# cpp.py
+#
+# Author:  David Beazley (http://www.dabeaz.com)
+# Copyright (C) 2007
+# All rights reserved
+#
+# This module implements an ANSI-C style lexical preprocessor for PLY. 
+# -----------------------------------------------------------------------------
+from __future__ import generators
+
+# -----------------------------------------------------------------------------
+# Default preprocessor lexer definitions.   These tokens are enough to get
+# a basic preprocessor working.   Other modules may import these if they want
+# -----------------------------------------------------------------------------
+
+tokens = (
+   'CPP_ID','CPP_INTEGER', 'CPP_FLOAT', 'CPP_STRING', 'CPP_CHAR', 'CPP_WS', 'CPP_COMMENT', 'CPP_POUND','CPP_DPOUND'
+)
+
+literals = "+-*/%|&~^<>=!?()[]{}.,;:\\\'\""
+
+# Whitespace
+def t_CPP_WS(t):
+    r'\s+'
+    t.lexer.lineno += t.value.count("\n")
+    return t
+
+t_CPP_POUND = r'\#'
+t_CPP_DPOUND = r'\#\#'
+
+# Identifier
+t_CPP_ID = r'[A-Za-z_][\w_]*'
+
+# Integer literal
+def CPP_INTEGER(t):
+    r'(((((0x)|(0X))[0-9a-fA-F]+)|(\d+))([uU]|[lL]|[uU][lL]|[lL][uU])?)'
+    return t
+
+t_CPP_INTEGER = CPP_INTEGER
+
+# Floating literal
+t_CPP_FLOAT = r'((\d+)(\.\d+)(e(\+|-)?(\d+))? | (\d+)e(\+|-)?(\d+))([lL]|[fF])?'
+
+# String literal
+def t_CPP_STRING(t):
+    r'\"([^\\\n]|(\\(.|\n)))*?\"'
+    t.lexer.lineno += t.value.count("\n")
+    return t
+
+# Character constant 'c' or L'c'
+def t_CPP_CHAR(t):
+    r'(L)?\'([^\\\n]|(\\(.|\n)))*?\''
+    t.lexer.lineno += t.value.count("\n")
+    return t
+
+# Comment
+def t_CPP_COMMENT(t):
+    r'(/\*(.|\n)*?\*/)|(//.*?\n)'
+    t.lexer.lineno += t.value.count("\n")
+    return t
+    
+def t_error(t):
+    t.type = t.value[0]
+    t.value = t.value[0]
+    t.lexer.skip(1)
+    return t
+
+import re
+import copy
+import time
+import os.path
+
+# -----------------------------------------------------------------------------
+# trigraph()
+# 
+# Given an input string, this function replaces all trigraph sequences. 
+# The following mapping is used:
+#
+#     ??=    #
+#     ??/    \
+#     ??'    ^
+#     ??(    [
+#     ??)    ]
+#     ??!    |
+#     ??<    {
+#     ??>    }
+#     ??-    ~
+# -----------------------------------------------------------------------------
+
+_trigraph_pat = re.compile(r'''\?\?[=/\'\(\)\!<>\-]''')
+_trigraph_rep = {
+    '=':'#',
+    '/':'\\',
+    "'":'^',
+    '(':'[',
+    ')':']',
+    '!':'|',
+    '<':'{',
+    '>':'}',
+    '-':'~'
+}
+
+def trigraph(input):
+    return _trigraph_pat.sub(lambda g: _trigraph_rep[g.group()[-1]],input)
+
+# ------------------------------------------------------------------
+# Macro object
+#
+# This object holds information about preprocessor macros
+#
+#    .name      - Macro name (string)
+#    .value     - Macro value (a list of tokens)
+#    .arglist   - List of argument names
+#    .variadic  - Boolean indicating whether or not variadic macro
+#    .vararg    - Name of the variadic parameter
+#
+# When a macro is created, the macro replacement token sequence is
+# pre-scanned and used to create patch lists that are later used
+# during macro expansion
+# ------------------------------------------------------------------
+
+class Macro(object):
+    def __init__(self,name,value,arglist=None,variadic=False):
+        self.name = name
+        self.value = value
+        self.arglist = arglist
+        self.variadic = variadic
+        if variadic:
+            self.vararg = arglist[-1]
+        self.source = None
+
+# ------------------------------------------------------------------
+# Preprocessor object
+#
+# Object representing a preprocessor.  Contains macro definitions,
+# include directories, and other information
+# ------------------------------------------------------------------
+
+class Preprocessor(object):
+    def __init__(self,lexer=None):
+        if lexer is None:
+            lexer = lex.lexer
+        self.lexer = lexer
+        self.macros = { }
+        self.path = []
+        self.temp_path = []
+
+        # Probe the lexer for selected tokens
+        self.lexprobe()
+
+        tm = time.localtime()
+        self.define("__DATE__ \"%s\"" % time.strftime("%b %d %Y",tm))
+        self.define("__TIME__ \"%s\"" % time.strftime("%H:%M:%S",tm))
+        self.parser = None
+
+    # -----------------------------------------------------------------------------
+    # tokenize()
+    #
+    # Utility function. Given a string of text, tokenize into a list of tokens
+    # -----------------------------------------------------------------------------
+
+    def tokenize(self,text):
+        tokens = []
+        self.lexer.input(text)
+        while True:
+            tok = self.lexer.token()
+            if not tok: break
+            tokens.append(tok)
+        return tokens
+
+    # ---------------------------------------------------------------------
+    # error()
+    #
+    # Report a preprocessor error/warning of some kind
+    # ----------------------------------------------------------------------
+
+    def error(self,file,line,msg):
+        print("%s:%d %s" % (file,line,msg))
+
+    # ----------------------------------------------------------------------
+    # lexprobe()
+    #
+    # This method probes the preprocessor lexer object to discover
+    # the token types of symbols that are important to the preprocessor.
+    # If this works right, the preprocessor will simply "work"
+    # with any suitable lexer regardless of how tokens have been named.
+    # ----------------------------------------------------------------------
+
+    def lexprobe(self):
+
+        # Determine the token type for identifiers
+        self.lexer.input("identifier")
+        tok = self.lexer.token()
+        if not tok or tok.value != "identifier":
+            print("Couldn't determine identifier type")
+        else:
+            self.t_ID = tok.type
+
+        # Determine the token type for integers
+        self.lexer.input("12345")
+        tok = self.lexer.token()
+        if not tok or int(tok.value) != 12345:
+            print("Couldn't determine integer type")
+        else:
+            self.t_INTEGER = tok.type
+            self.t_INTEGER_TYPE = type(tok.value)
+
+        # Determine the token type for strings enclosed in double quotes
+        self.lexer.input("\"filename\"")
+        tok = self.lexer.token()
+        if not tok or tok.value != "\"filename\"":
+            print("Couldn't determine string type")
+        else:
+            self.t_STRING = tok.type
+
+        # Determine the token type for whitespace--if any
+        self.lexer.input("  ")
+        tok = self.lexer.token()
+        if not tok or tok.value != "  ":
+            self.t_SPACE = None
+        else:
+            self.t_SPACE = tok.type
+
+        # Determine the token type for newlines
+        self.lexer.input("\n")
+        tok = self.lexer.token()
+        if not tok or tok.value != "\n":
+            self.t_NEWLINE = None
+            print("Couldn't determine token for newlines")
+        else:
+            self.t_NEWLINE = tok.type
+
+        self.t_WS = (self.t_SPACE, self.t_NEWLINE)
+
+        # Check for other characters used by the preprocessor
+        chars = [ '<','>','#','##','\\','(',')',',','.']
+        for c in chars:
+            self.lexer.input(c)
+            tok = self.lexer.token()
+            if not tok or tok.value != c:
+                print("Unable to lex '%s' required for preprocessor" % c)
+
+    # ----------------------------------------------------------------------
+    # add_path()
+    #
+    # Adds a search path to the preprocessor.  
+    # ----------------------------------------------------------------------
+
+    def add_path(self,path):
+        self.path.append(path)
+
+    # ----------------------------------------------------------------------
+    # group_lines()
+    #
+    # Given an input string, this function splits it into lines.  Trailing whitespace
+    # is removed.   Any line ending with \ is grouped with the next line.  This
+    # function forms the lowest level of the preprocessor---grouping into text into
+    # a line-by-line format.
+    # ----------------------------------------------------------------------
+
+    def group_lines(self,input):
+        lex = self.lexer.clone()
+        lines = [x.rstrip() for x in input.splitlines()]
+        for i in xrange(len(lines)):
+            j = i+1
+            while lines[i].endswith('\\') and (j < len(lines)):
+                lines[i] = lines[i][:-1]+lines[j]
+                lines[j] = ""
+                j += 1
+
+        input = "\n".join(lines)
+        lex.input(input)
+        lex.lineno = 1
+
+        current_line = []
+        while True:
+            tok = lex.token()
+            if not tok:
+                break
+            current_line.append(tok)
+            if tok.type in self.t_WS and '\n' in tok.value:
+                yield current_line
+                current_line = []
+
+        if current_line:
+            yield current_line
+
+    # ----------------------------------------------------------------------
+    # tokenstrip()
+    # 
+    # Remove leading/trailing whitespace tokens from a token list
+    # ----------------------------------------------------------------------
+
+    def tokenstrip(self,tokens):
+        i = 0
+        while i < len(tokens) and tokens[i].type in self.t_WS:
+            i += 1
+        del tokens[:i]
+        i = len(tokens)-1
+        while i >= 0 and tokens[i].type in self.t_WS:
+            i -= 1
+        del tokens[i+1:]
+        return tokens
+
+
+    # ----------------------------------------------------------------------
+    # collect_args()
+    #
+    # Collects comma separated arguments from a list of tokens.   The arguments
+    # must be enclosed in parenthesis.  Returns a tuple (tokencount,args,positions)
+    # where tokencount is the number of tokens consumed, args is a list of arguments,
+    # and positions is a list of integers containing the starting index of each
+    # argument.  Each argument is represented by a list of tokens.
+    #
+    # When collecting arguments, leading and trailing whitespace is removed
+    # from each argument.  
+    #
+    # This function properly handles nested parenthesis and commas---these do not
+    # define new arguments.
+    # ----------------------------------------------------------------------
+
+    def collect_args(self,tokenlist):
+        args = []
+        positions = []
+        current_arg = []
+        nesting = 1
+        tokenlen = len(tokenlist)
+    
+        # Search for the opening '('.
+        i = 0
+        while (i < tokenlen) and (tokenlist[i].type in self.t_WS):
+            i += 1
+
+        if (i < tokenlen) and (tokenlist[i].value == '('):
+            positions.append(i+1)
+        else:
+            self.error(self.source,tokenlist[0].lineno,"Missing '(' in macro arguments")
+            return 0, [], []
+
+        i += 1
+
+        while i < tokenlen:
+            t = tokenlist[i]
+            if t.value == '(':
+                current_arg.append(t)
+                nesting += 1
+            elif t.value == ')':
+                nesting -= 1
+                if nesting == 0:
+                    if current_arg:
+                        args.append(self.tokenstrip(current_arg))
+                        positions.append(i)
+                    return i+1,args,positions
+                current_arg.append(t)
+            elif t.value == ',' and nesting == 1:
+                args.append(self.tokenstrip(current_arg))
+                positions.append(i+1)
+                current_arg = []
+            else:
+                current_arg.append(t)
+            i += 1
+    
+        # Missing end argument
+        self.error(self.source,tokenlist[-1].lineno,"Missing ')' in macro arguments")
+        return 0, [],[]
+
+    # ----------------------------------------------------------------------
+    # macro_prescan()
+    #
+    # Examine the macro value (token sequence) and identify patch points
+    # This is used to speed up macro expansion later on---we'll know
+    # right away where to apply patches to the value to form the expansion
+    # ----------------------------------------------------------------------
+    
+    def macro_prescan(self,macro):
+        macro.patch     = []             # Standard macro arguments 
+        macro.str_patch = []             # String conversion expansion
+        macro.var_comma_patch = []       # Variadic macro comma patch
+        i = 0
+        while i < len(macro.value):
+            if macro.value[i].type == self.t_ID and macro.value[i].value in macro.arglist:
+                argnum = macro.arglist.index(macro.value[i].value)
+                # Conversion of argument to a string
+                if i > 0 and macro.value[i-1].value == '#':
+                    macro.value[i] = copy.copy(macro.value[i])
+                    macro.value[i].type = self.t_STRING
+                    del macro.value[i-1]
+                    macro.str_patch.append((argnum,i-1))
+                    continue
+                # Concatenation
+                elif (i > 0 and macro.value[i-1].value == '##'):
+                    macro.patch.append(('c',argnum,i-1))
+                    del macro.value[i-1]
+                    continue
+                elif ((i+1) < len(macro.value) and macro.value[i+1].value == '##'):
+                    macro.patch.append(('c',argnum,i))
+                    i += 1
+                    continue
+                # Standard expansion
+                else:
+                    macro.patch.append(('e',argnum,i))
+            elif macro.value[i].value == '##':
+                if macro.variadic and (i > 0) and (macro.value[i-1].value == ',') and \
+                        ((i+1) < len(macro.value)) and (macro.value[i+1].type == self.t_ID) and \
+                        (macro.value[i+1].value == macro.vararg):
+                    macro.var_comma_patch.append(i-1)
+            i += 1
+        macro.patch.sort(key=lambda x: x[2],reverse=True)
+
+    # ----------------------------------------------------------------------
+    # macro_expand_args()
+    #
+    # Given a Macro and list of arguments (each a token list), this method
+    # returns an expanded version of a macro.  The return value is a token sequence
+    # representing the replacement macro tokens
+    # ----------------------------------------------------------------------
+
+    def macro_expand_args(self,macro,args):
+        # Make a copy of the macro token sequence
+        rep = [copy.copy(_x) for _x in macro.value]
+
+        # Make string expansion patches.  These do not alter the length of the replacement sequence
+        
+        str_expansion = {}
+        for argnum, i in macro.str_patch:
+            if argnum not in str_expansion:
+                str_expansion[argnum] = ('"%s"' % "".join([x.value for x in args[argnum]])).replace("\\","\\\\")
+            rep[i] = copy.copy(rep[i])
+            rep[i].value = str_expansion[argnum]
+
+        # Make the variadic macro comma patch.  If the variadic macro argument is empty, we get rid
+        comma_patch = False
+        if macro.variadic and not args[-1]:
+            for i in macro.var_comma_patch:
+                rep[i] = None
+                comma_patch = True
+
+        # Make all other patches.   The order of these matters.  It is assumed that the patch list
+        # has been sorted in reverse order of patch location since replacements will cause the
+        # size of the replacement sequence to expand from the patch point.
+        
+        expanded = { }
+        for ptype, argnum, i in macro.patch:
+            # Concatenation.   Argument is left unexpanded
+            if ptype == 'c':
+                rep[i:i+1] = args[argnum]
+            # Normal expansion.  Argument is macro expanded first
+            elif ptype == 'e':
+                if argnum not in expanded:
+                    expanded[argnum] = self.expand_macros(args[argnum])
+                rep[i:i+1] = expanded[argnum]
+
+        # Get rid of removed comma if necessary
+        if comma_patch:
+            rep = [_i for _i in rep if _i]
+
+        return rep
+
+
+    # ----------------------------------------------------------------------
+    # expand_macros()
+    #
+    # Given a list of tokens, this function performs macro expansion.
+    # The expanded argument is a dictionary that contains macros already
+    # expanded.  This is used to prevent infinite recursion.
+    # ----------------------------------------------------------------------
+
+    def expand_macros(self,tokens,expanded=None):
+        if expanded is None:
+            expanded = {}
+        i = 0
+        while i < len(tokens):
+            t = tokens[i]
+            if t.type == self.t_ID:
+                if t.value in self.macros and t.value not in expanded:
+                    # Yes, we found a macro match
+                    expanded[t.value] = True
+                    
+                    m = self.macros[t.value]
+                    if not m.arglist:
+                        # A simple macro
+                        ex = self.expand_macros([copy.copy(_x) for _x in m.value],expanded)
+                        for e in ex:
+                            e.lineno = t.lineno
+                        tokens[i:i+1] = ex
+                        i += len(ex)
+                    else:
+                        # A macro with arguments
+                        j = i + 1
+                        while j < len(tokens) and tokens[j].type in self.t_WS:
+                            j += 1
+                        if tokens[j].value == '(':
+                            tokcount,args,positions = self.collect_args(tokens[j:])
+                            if not m.variadic and len(args) !=  len(m.arglist):
+                                self.error(self.source,t.lineno,"Macro %s requires %d arguments" % (t.value,len(m.arglist)))
+                                i = j + tokcount
+                            elif m.variadic and len(args) < len(m.arglist)-1:
+                                if len(m.arglist) > 2:
+                                    self.error(self.source,t.lineno,"Macro %s must have at least %d arguments" % (t.value, len(m.arglist)-1))
+                                else:
+                                    self.error(self.source,t.lineno,"Macro %s must have at least %d argument" % (t.value, len(m.arglist)-1))
+                                i = j + tokcount
+                            else:
+                                if m.variadic:
+                                    if len(args) == len(m.arglist)-1:
+                                        args.append([])
+                                    else:
+                                        args[len(m.arglist)-1] = tokens[j+positions[len(m.arglist)-1]:j+tokcount-1]
+                                        del args[len(m.arglist):]
+                                        
+                                # Get macro replacement text
+                                rep = self.macro_expand_args(m,args)
+                                rep = self.expand_macros(rep,expanded)
+                                for r in rep:
+                                    r.lineno = t.lineno
+                                tokens[i:j+tokcount] = rep
+                                i += len(rep)
+                    del expanded[t.value]
+                    continue
+                elif t.value == '__LINE__':
+                    t.type = self.t_INTEGER
+                    t.value = self.t_INTEGER_TYPE(t.lineno)
+                
+            i += 1
+        return tokens
+
+    # ----------------------------------------------------------------------    
+    # evalexpr()
+    # 
+    # Evaluate an expression token sequence for the purposes of evaluating
+    # integral expressions.
+    # ----------------------------------------------------------------------
+
+    def evalexpr(self,tokens):
+        # tokens = tokenize(line)
+        # Search for defined macros
+        i = 0
+        while i < len(tokens):
+            if tokens[i].type == self.t_ID and tokens[i].value == 'defined':
+                j = i + 1
+                needparen = False
+                result = "0L"
+                while j < len(tokens):
+                    if tokens[j].type in self.t_WS:
+                        j += 1
+                        continue
+                    elif tokens[j].type == self.t_ID:
+                        if tokens[j].value in self.macros:
+                            result = "1L"
+                        else:
+                            result = "0L"
+                        if not needparen: break
+                    elif tokens[j].value == '(':
+                        needparen = True
+                    elif tokens[j].value == ')':
+                        break
+                    else:
+                        self.error(self.source,tokens[i].lineno,"Malformed defined()")
+                    j += 1
+                tokens[i].type = self.t_INTEGER
+                tokens[i].value = self.t_INTEGER_TYPE(result)
+                del tokens[i+1:j+1]
+            i += 1
+        tokens = self.expand_macros(tokens)
+        for i,t in enumerate(tokens):
+            if t.type == self.t_ID:
+                tokens[i] = copy.copy(t)
+                tokens[i].type = self.t_INTEGER
+                tokens[i].value = self.t_INTEGER_TYPE("0L")
+            elif t.type == self.t_INTEGER:
+                tokens[i] = copy.copy(t)
+                # Strip off any trailing suffixes
+                tokens[i].value = str(tokens[i].value)
+                while tokens[i].value[-1] not in "0123456789abcdefABCDEF":
+                    tokens[i].value = tokens[i].value[:-1]
+        
+        expr = "".join([str(x.value) for x in tokens])
+        expr = expr.replace("&&"," and ")
+        expr = expr.replace("||"," or ")
+        expr = expr.replace("!"," not ")
+        try:
+            result = eval(expr)
+        except StandardError:
+            self.error(self.source,tokens[0].lineno,"Couldn't evaluate expression")
+            result = 0
+        return result
+
+    # ----------------------------------------------------------------------
+    # parsegen()
+    #
+    # Parse an input string/
+    # ----------------------------------------------------------------------
+    def parsegen(self,input,source=None):
+
+        # Replace trigraph sequences
+        t = trigraph(input)
+        lines = self.group_lines(t)
+
+        if not source:
+            source = ""
+            
+        self.define("__FILE__ \"%s\"" % source)
+
+        self.source = source
+        chunk = []
+        enable = True
+        iftrigger = False
+        ifstack = []
+
+        for x in lines:
+            for i,tok in enumerate(x):
+                if tok.type not in self.t_WS: break
+            if tok.value == '#':
+                # Preprocessor directive
+
+                for tok in x:
+                    if tok in self.t_WS and '\n' in tok.value:
+                        chunk.append(tok)
+                
+                dirtokens = self.tokenstrip(x[i+1:])
+                if dirtokens:
+                    name = dirtokens[0].value
+                    args = self.tokenstrip(dirtokens[1:])
+                else:
+                    name = ""
+                    args = []
+                
+                if name == 'define':
+                    if enable:
+                        for tok in self.expand_macros(chunk):
+                            yield tok
+                        chunk = []
+                        self.define(args)
+                elif name == 'include':
+                    if enable:
+                        for tok in self.expand_macros(chunk):
+                            yield tok
+                        chunk = []
+                        oldfile = self.macros['__FILE__']
+                        for tok in self.include(args):
+                            yield tok
+                        self.macros['__FILE__'] = oldfile
+                        self.source = source
+                elif name == 'undef':
+                    if enable:
+                        for tok in self.expand_macros(chunk):
+                            yield tok
+                        chunk = []
+                        self.undef(args)
+                elif name == 'ifdef':
+                    ifstack.append((enable,iftrigger))
+                    if enable:
+                        if not args[0].value in self.macros:
+                            enable = False
+                            iftrigger = False
+                        else:
+                            iftrigger = True
+                elif name == 'ifndef':
+                    ifstack.append((enable,iftrigger))
+                    if enable:
+                        if args[0].value in self.macros:
+                            enable = False
+                            iftrigger = False
+                        else:
+                            iftrigger = True
+                elif name == 'if':
+                    ifstack.append((enable,iftrigger))
+                    if enable:
+                        result = self.evalexpr(args)
+                        if not result:
+                            enable = False
+                            iftrigger = False
+                        else:
+                            iftrigger = True
+                elif name == 'elif':
+                    if ifstack:
+                        if ifstack[-1][0]:     # We only pay attention if outer "if" allows this
+                            if enable:         # If already true, we flip enable False
+                                enable = False
+                            elif not iftrigger:   # If False, but not triggered yet, we'll check expression
+                                result = self.evalexpr(args)
+                                if result:
+                                    enable  = True
+                                    iftrigger = True
+                    else:
+                        self.error(self.source,dirtokens[0].lineno,"Misplaced #elif")
+                        
+                elif name == 'else':
+                    if ifstack:
+                        if ifstack[-1][0]:
+                            if enable:
+                                enable = False
+                            elif not iftrigger:
+                                enable = True
+                                iftrigger = True
+                    else:
+                        self.error(self.source,dirtokens[0].lineno,"Misplaced #else")
+
+                elif name == 'endif':
+                    if ifstack:
+                        enable,iftrigger = ifstack.pop()
+                    else:
+                        self.error(self.source,dirtokens[0].lineno,"Misplaced #endif")
+                else:
+                    # Unknown preprocessor directive
+                    pass
+
+            else:
+                # Normal text
+                if enable:
+                    chunk.extend(x)
+
+        for tok in self.expand_macros(chunk):
+            yield tok
+        chunk = []
+
+    # ----------------------------------------------------------------------
+    # include()
+    #
+    # Implementation of file-inclusion
+    # ----------------------------------------------------------------------
+
+    def include(self,tokens):
+        # Try to extract the filename and then process an include file
+        if not tokens:
+            return
+        if tokens:
+            if tokens[0].value != '<' and tokens[0].type != self.t_STRING:
+                tokens = self.expand_macros(tokens)
+
+            if tokens[0].value == '<':
+                # Include <...>
+                i = 1
+                while i < len(tokens):
+                    if tokens[i].value == '>':
+                        break
+                    i += 1
+                else:
+                    print("Malformed #include <...>")
+                    return
+                filename = "".join([x.value for x in tokens[1:i]])
+                path = self.path + [""] + self.temp_path
+            elif tokens[0].type == self.t_STRING:
+                filename = tokens[0].value[1:-1]
+                path = self.temp_path + [""] + self.path
+            else:
+                print("Malformed #include statement")
+                return
+        for p in path:
+            iname = os.path.join(p,filename)
+            try:
+                data = open(iname,"r").read()
+                dname = os.path.dirname(iname)
+                if dname:
+                    self.temp_path.insert(0,dname)
+                for tok in self.parsegen(data,filename):
+                    yield tok
+                if dname:
+                    del self.temp_path[0]
+                break
+            except IOError:
+                pass
+        else:
+            print("Couldn't find '%s'" % filename)
+
+    # ----------------------------------------------------------------------
+    # define()
+    #
+    # Define a new macro
+    # ----------------------------------------------------------------------
+
+    def define(self,tokens):
+        if isinstance(tokens,(str,unicode)):
+            tokens = self.tokenize(tokens)
+
+        linetok = tokens
+        try:
+            name = linetok[0]
+            if len(linetok) > 1:
+                mtype = linetok[1]
+            else:
+                mtype = None
+            if not mtype:
+                m = Macro(name.value,[])
+                self.macros[name.value] = m
+            elif mtype.type in self.t_WS:
+                # A normal macro
+                m = Macro(name.value,self.tokenstrip(linetok[2:]))
+                self.macros[name.value] = m
+            elif mtype.value == '(':
+                # A macro with arguments
+                tokcount, args, positions = self.collect_args(linetok[1:])
+                variadic = False
+                for a in args:
+                    if variadic:
+                        print("No more arguments may follow a variadic argument")
+                        break
+                    astr = "".join([str(_i.value) for _i in a])
+                    if astr == "...":
+                        variadic = True
+                        a[0].type = self.t_ID
+                        a[0].value = '__VA_ARGS__'
+                        variadic = True
+                        del a[1:]
+                        continue
+                    elif astr[-3:] == "..." and a[0].type == self.t_ID:
+                        variadic = True
+                        del a[1:]
+                        # If, for some reason, "." is part of the identifier, strip off the name for the purposes
+                        # of macro expansion
+                        if a[0].value[-3:] == '...':
+                            a[0].value = a[0].value[:-3]
+                        continue
+                    if len(a) > 1 or a[0].type != self.t_ID:
+                        print("Invalid macro argument")
+                        break
+                else:
+                    mvalue = self.tokenstrip(linetok[1+tokcount:])
+                    i = 0
+                    while i < len(mvalue):
+                        if i+1 < len(mvalue):
+                            if mvalue[i].type in self.t_WS and mvalue[i+1].value == '##':
+                                del mvalue[i]
+                                continue
+                            elif mvalue[i].value == '##' and mvalue[i+1].type in self.t_WS:
+                                del mvalue[i+1]
+                        i += 1
+                    m = Macro(name.value,mvalue,[x[0].value for x in args],variadic)
+                    self.macro_prescan(m)
+                    self.macros[name.value] = m
+            else:
+                print("Bad macro definition")
+        except LookupError:
+            print("Bad macro definition")
+
+    # ----------------------------------------------------------------------
+    # undef()
+    #
+    # Undefine a macro
+    # ----------------------------------------------------------------------
+
+    def undef(self,tokens):
+        id = tokens[0].value
+        try:
+            del self.macros[id]
+        except LookupError:
+            pass
+
+    # ----------------------------------------------------------------------
+    # parse()
+    #
+    # Parse input text.
+    # ----------------------------------------------------------------------
+    def parse(self,input,source=None,ignore={}):
+        self.ignore = ignore
+        self.parser = self.parsegen(input,source)
+        
+    # ----------------------------------------------------------------------
+    # token()
+    #
+    # Method to return individual tokens
+    # ----------------------------------------------------------------------
+    def token(self):
+        try:
+            while True:
+                tok = next(self.parser)
+                if tok.type not in self.ignore: return tok
+        except StopIteration:
+            self.parser = None
+            return None
+
+if __name__ == '__main__':
+    import ply.lex as lex
+    lexer = lex.lex()
+
+    # Run a preprocessor
+    import sys
+    f = open(sys.argv[1])
+    input = f.read()
+
+    p = Preprocessor(lexer)
+    p.parse(input,sys.argv[1])
+    while True:
+        tok = p.token()
+        if not tok: break
+        print(p.source, tok)
+
+
+
+
+    
+
+
+
+
+
+
diff --git a/webWidgetTCT_device/tools/slimit/ply/ctokens.py b/webWidgetTCT_device/tools/slimit/ply/ctokens.py
new file mode 100755 (executable)
index 0000000..dd5f102
--- /dev/null
@@ -0,0 +1,133 @@
+# ----------------------------------------------------------------------
+# ctokens.py
+#
+# Token specifications for symbols in ANSI C and C++.  This file is
+# meant to be used as a library in other tokenizers.
+# ----------------------------------------------------------------------
+
+# Reserved words
+
+tokens = [
+    # Literals (identifier, integer constant, float constant, string constant, char const)
+    'ID', 'TYPEID', 'ICONST', 'FCONST', 'SCONST', 'CCONST',
+
+    # Operators (+,-,*,/,%,|,&,~,^,<<,>>, ||, &&, !, <, <=, >, >=, ==, !=)
+    'PLUS', 'MINUS', 'TIMES', 'DIVIDE', 'MOD',
+    'OR', 'AND', 'NOT', 'XOR', 'LSHIFT', 'RSHIFT',
+    'LOR', 'LAND', 'LNOT',
+    'LT', 'LE', 'GT', 'GE', 'EQ', 'NE',
+    
+    # Assignment (=, *=, /=, %=, +=, -=, <<=, >>=, &=, ^=, |=)
+    'EQUALS', 'TIMESEQUAL', 'DIVEQUAL', 'MODEQUAL', 'PLUSEQUAL', 'MINUSEQUAL',
+    'LSHIFTEQUAL','RSHIFTEQUAL', 'ANDEQUAL', 'XOREQUAL', 'OREQUAL',
+
+    # Increment/decrement (++,--)
+    'PLUSPLUS', 'MINUSMINUS',
+
+    # Structure dereference (->)
+    'ARROW',
+
+    # Ternary operator (?)
+    'TERNARY',
+    
+    # Delimeters ( ) [ ] { } , . ; :
+    'LPAREN', 'RPAREN',
+    'LBRACKET', 'RBRACKET',
+    'LBRACE', 'RBRACE',
+    'COMMA', 'PERIOD', 'SEMI', 'COLON',
+
+    # Ellipsis (...)
+    'ELLIPSIS',
+]
+    
+# Operators
+t_PLUS             = r'\+'
+t_MINUS            = r'-'
+t_TIMES            = r'\*'
+t_DIVIDE           = r'/'
+t_MODULO           = r'%'
+t_OR               = r'\|'
+t_AND              = r'&'
+t_NOT              = r'~'
+t_XOR              = r'\^'
+t_LSHIFT           = r'<<'
+t_RSHIFT           = r'>>'
+t_LOR              = r'\|\|'
+t_LAND             = r'&&'
+t_LNOT             = r'!'
+t_LT               = r'<'
+t_GT               = r'>'
+t_LE               = r'<='
+t_GE               = r'>='
+t_EQ               = r'=='
+t_NE               = r'!='
+
+# Assignment operators
+
+t_EQUALS           = r'='
+t_TIMESEQUAL       = r'\*='
+t_DIVEQUAL         = r'/='
+t_MODEQUAL         = r'%='
+t_PLUSEQUAL        = r'\+='
+t_MINUSEQUAL       = r'-='
+t_LSHIFTEQUAL      = r'<<='
+t_RSHIFTEQUAL      = r'>>='
+t_ANDEQUAL         = r'&='
+t_OREQUAL          = r'\|='
+t_XOREQUAL         = r'^='
+
+# Increment/decrement
+t_INCREMENT        = r'\+\+'
+t_DECREMENT        = r'--'
+
+# ->
+t_ARROW            = r'->'
+
+# ?
+t_TERNARY          = r'\?'
+
+# Delimeters
+t_LPAREN           = r'\('
+t_RPAREN           = r'\)'
+t_LBRACKET         = r'\['
+t_RBRACKET         = r'\]'
+t_LBRACE           = r'\{'
+t_RBRACE           = r'\}'
+t_COMMA            = r','
+t_PERIOD           = r'\.'
+t_SEMI             = r';'
+t_COLON            = r':'
+t_ELLIPSIS         = r'\.\.\.'
+
+# Identifiers
+t_ID = r'[A-Za-z_][A-Za-z0-9_]*'
+
+# Integer literal
+t_INTEGER = r'\d+([uU]|[lL]|[uU][lL]|[lL][uU])?'
+
+# Floating literal
+t_FLOAT = r'((\d+)(\.\d+)(e(\+|-)?(\d+))? | (\d+)e(\+|-)?(\d+))([lL]|[fF])?'
+
+# String literal
+t_STRING = r'\"([^\\\n]|(\\.))*?\"'
+
+# Character constant 'c' or L'c'
+t_CHARACTER = r'(L)?\'([^\\\n]|(\\.))*?\''
+
+# Comment (C-Style)
+def t_COMMENT(t):
+    r'/\*(.|\n)*?\*/'
+    t.lexer.lineno += t.value.count('\n')
+    return t
+
+# Comment (C++-Style)
+def t_CPPCOMMENT(t):
+    r'//.*\n'
+    t.lexer.lineno += 1
+    return t
+
+
+    
+
+
+
diff --git a/webWidgetTCT_device/tools/slimit/ply/lex.py b/webWidgetTCT_device/tools/slimit/ply/lex.py
new file mode 100755 (executable)
index 0000000..bd32da9
--- /dev/null
@@ -0,0 +1,1058 @@
+# -----------------------------------------------------------------------------
+# ply: lex.py
+#
+# Copyright (C) 2001-2011,
+# David M. Beazley (Dabeaz LLC)
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+# 
+# * Redistributions of source code must retain the above copyright notice,
+#   this list of conditions and the following disclaimer.  
+# * Redistributions in binary form must reproduce the above copyright notice, 
+#   this list of conditions and the following disclaimer in the documentation
+#   and/or other materials provided with the distribution.  
+# * Neither the name of the David Beazley or Dabeaz LLC may be used to
+#   endorse or promote products derived from this software without
+#  specific prior written permission. 
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+# -----------------------------------------------------------------------------
+
+__version__    = "3.4"
+__tabversion__ = "3.2"       # Version of table file used
+
+import re, sys, types, copy, os
+
+# This tuple contains known string types
+try:
+    # Python 2.6
+    StringTypes = (types.StringType, types.UnicodeType)
+except AttributeError:
+    # Python 3.0
+    StringTypes = (str, bytes)
+
+# Extract the code attribute of a function. Different implementations
+# are for Python 2/3 compatibility.
+
+if sys.version_info[0] < 3:
+    def func_code(f):
+        return f.func_code
+else:
+    def func_code(f):
+        return f.__code__
+
+# This regular expression is used to match valid token names
+_is_identifier = re.compile(r'^[a-zA-Z0-9_]+$')
+
+# Exception thrown when invalid token encountered and no default error
+# handler is defined.
+
+class LexError(Exception):
+    def __init__(self,message,s):
+         self.args = (message,)
+         self.text = s
+
+# Token class.  This class is used to represent the tokens produced.
+class LexToken(object):
+    def __str__(self):
+        return "LexToken(%s,%r,%d,%d)" % (self.type,self.value,self.lineno,self.lexpos)
+    def __repr__(self):
+        return str(self)
+
+# This object is a stand-in for a logging object created by the 
+# logging module.  
+
+class PlyLogger(object):
+    def __init__(self,f):
+        self.f = f
+    def critical(self,msg,*args,**kwargs):
+        self.f.write((msg % args) + "\n")
+
+    def warning(self,msg,*args,**kwargs):
+        self.f.write("WARNING: "+ (msg % args) + "\n")
+
+    def error(self,msg,*args,**kwargs):
+        self.f.write("ERROR: " + (msg % args) + "\n")
+
+    info = critical
+    debug = critical
+
+# Null logger is used when no output is generated. Does nothing.
+class NullLogger(object):
+    def __getattribute__(self,name):
+        return self
+    def __call__(self,*args,**kwargs):
+        return self
+
+# -----------------------------------------------------------------------------
+#                        === Lexing Engine ===
+#
+# The following Lexer class implements the lexer runtime.   There are only
+# a few public methods and attributes:
+#
+#    input()          -  Store a new string in the lexer
+#    token()          -  Get the next token
+#    clone()          -  Clone the lexer
+#
+#    lineno           -  Current line number
+#    lexpos           -  Current position in the input string
+# -----------------------------------------------------------------------------
+
+class Lexer:
+    def __init__(self):
+        self.lexre = None             # Master regular expression. This is a list of
+                                      # tuples (re,findex) where re is a compiled
+                                      # regular expression and findex is a list
+                                      # mapping regex group numbers to rules
+        self.lexretext = None         # Current regular expression strings
+        self.lexstatere = {}          # Dictionary mapping lexer states to master regexs
+        self.lexstateretext = {}      # Dictionary mapping lexer states to regex strings
+        self.lexstaterenames = {}     # Dictionary mapping lexer states to symbol names
+        self.lexstate = "INITIAL"     # Current lexer state
+        self.lexstatestack = []       # Stack of lexer states
+        self.lexstateinfo = None      # State information
+        self.lexstateignore = {}      # Dictionary of ignored characters for each state
+        self.lexstateerrorf = {}      # Dictionary of error functions for each state
+        self.lexreflags = 0           # Optional re compile flags
+        self.lexdata = None           # Actual input data (as a string)
+        self.lexpos = 0               # Current position in input text
+        self.lexlen = 0               # Length of the input text
+        self.lexerrorf = None         # Error rule (if any)
+        self.lextokens = None         # List of valid tokens
+        self.lexignore = ""           # Ignored characters
+        self.lexliterals = ""         # Literal characters that can be passed through
+        self.lexmodule = None         # Module
+        self.lineno = 1               # Current line number
+        self.lexoptimize = 0          # Optimized mode
+
+    def clone(self,object=None):
+        c = copy.copy(self)
+
+        # If the object parameter has been supplied, it means we are attaching the
+        # lexer to a new object.  In this case, we have to rebind all methods in
+        # the lexstatere and lexstateerrorf tables.
+
+        if object:
+            newtab = { }
+            for key, ritem in self.lexstatere.items():
+                newre = []
+                for cre, findex in ritem:
+                     newfindex = []
+                     for f in findex:
+                         if not f or not f[0]:
+                             newfindex.append(f)
+                             continue
+                         newfindex.append((getattr(object,f[0].__name__),f[1]))
+                newre.append((cre,newfindex))
+                newtab[key] = newre
+            c.lexstatere = newtab
+            c.lexstateerrorf = { }
+            for key, ef in self.lexstateerrorf.items():
+                c.lexstateerrorf[key] = getattr(object,ef.__name__)
+            c.lexmodule = object
+        return c
+
+    # ------------------------------------------------------------
+    # writetab() - Write lexer information to a table file
+    # ------------------------------------------------------------
+    def writetab(self,tabfile,outputdir=""):
+        if isinstance(tabfile,types.ModuleType):
+            return
+        basetabfilename = tabfile.split(".")[-1]
+        filename = os.path.join(outputdir,basetabfilename)+".py"
+        tf = open(filename,"w")
+        tf.write("# %s.py. This file automatically created by PLY (version %s). Don't edit!\n" % (tabfile,__version__))
+        tf.write("_tabversion   = %s\n" % repr(__version__))
+        tf.write("_lextokens    = %s\n" % repr(self.lextokens))
+        tf.write("_lexreflags   = %s\n" % repr(self.lexreflags))
+        tf.write("_lexliterals  = %s\n" % repr(self.lexliterals))
+        tf.write("_lexstateinfo = %s\n" % repr(self.lexstateinfo))
+
+        tabre = { }
+        # Collect all functions in the initial state
+        initial = self.lexstatere["INITIAL"]
+        initialfuncs = []
+        for part in initial:
+            for f in part[1]:
+                if f and f[0]:
+                    initialfuncs.append(f)
+
+        for key, lre in self.lexstatere.items():
+             titem = []
+             for i in range(len(lre)):
+                  titem.append((self.lexstateretext[key][i],_funcs_to_names(lre[i][1],self.lexstaterenames[key][i])))
+             tabre[key] = titem
+
+        tf.write("_lexstatere   = %s\n" % repr(tabre))
+        tf.write("_lexstateignore = %s\n" % repr(self.lexstateignore))
+
+        taberr = { }
+        for key, ef in self.lexstateerrorf.items():
+             if ef:
+                  taberr[key] = ef.__name__
+             else:
+                  taberr[key] = None
+        tf.write("_lexstateerrorf = %s\n" % repr(taberr))
+        tf.close()
+
+    # ------------------------------------------------------------
+    # readtab() - Read lexer information from a tab file
+    # ------------------------------------------------------------
+    def readtab(self,tabfile,fdict):
+        if isinstance(tabfile,types.ModuleType):
+            lextab = tabfile
+        else:
+            if sys.version_info[0] < 3:
+                exec("import %s as lextab" % tabfile)
+            else:
+                env = { }
+                exec("import %s as lextab" % tabfile, env,env)
+                lextab = env['lextab']
+
+        if getattr(lextab,"_tabversion","0.0") != __version__:
+            raise ImportError("Inconsistent PLY version")
+
+        self.lextokens      = lextab._lextokens
+        self.lexreflags     = lextab._lexreflags
+        self.lexliterals    = lextab._lexliterals
+        self.lexstateinfo   = lextab._lexstateinfo
+        self.lexstateignore = lextab._lexstateignore
+        self.lexstatere     = { }
+        self.lexstateretext = { }
+        for key,lre in lextab._lexstatere.items():
+             titem = []
+             txtitem = []
+             for i in range(len(lre)):
+                  titem.append((re.compile(lre[i][0],lextab._lexreflags | re.VERBOSE),_names_to_funcs(lre[i][1],fdict)))
+                  txtitem.append(lre[i][0])
+             self.lexstatere[key] = titem
+             self.lexstateretext[key] = txtitem
+        self.lexstateerrorf = { }
+        for key,ef in lextab._lexstateerrorf.items():
+             self.lexstateerrorf[key] = fdict[ef]
+        self.begin('INITIAL')
+
+    # ------------------------------------------------------------
+    # input() - Push a new string into the lexer
+    # ------------------------------------------------------------
+    def input(self,s):
+        # Pull off the first character to see if s looks like a string
+        c = s[:1]
+        if not isinstance(c,StringTypes):
+            raise ValueError("Expected a string")
+        self.lexdata = s
+        self.lexpos = 0
+        self.lexlen = len(s)
+
+    # ------------------------------------------------------------
+    # begin() - Changes the lexing state
+    # ------------------------------------------------------------
+    def begin(self,state):
+        if not state in self.lexstatere:
+            raise ValueError("Undefined state")
+        self.lexre = self.lexstatere[state]
+        self.lexretext = self.lexstateretext[state]
+        self.lexignore = self.lexstateignore.get(state,"")
+        self.lexerrorf = self.lexstateerrorf.get(state,None)
+        self.lexstate = state
+
+    # ------------------------------------------------------------
+    # push_state() - Changes the lexing state and saves old on stack
+    # ------------------------------------------------------------
+    def push_state(self,state):
+        self.lexstatestack.append(self.lexstate)
+        self.begin(state)
+
+    # ------------------------------------------------------------
+    # pop_state() - Restores the previous state
+    # ------------------------------------------------------------
+    def pop_state(self):
+        self.begin(self.lexstatestack.pop())
+
+    # ------------------------------------------------------------
+    # current_state() - Returns the current lexing state
+    # ------------------------------------------------------------
+    def current_state(self):
+        return self.lexstate
+
+    # ------------------------------------------------------------
+    # skip() - Skip ahead n characters
+    # ------------------------------------------------------------
+    def skip(self,n):
+        self.lexpos += n
+
+    # ------------------------------------------------------------
+    # opttoken() - Return the next token from the Lexer
+    #
+    # Note: This function has been carefully implemented to be as fast
+    # as possible.  Don't make changes unless you really know what
+    # you are doing
+    # ------------------------------------------------------------
+    def token(self):
+        # Make local copies of frequently referenced attributes
+        lexpos    = self.lexpos
+        lexlen    = self.lexlen
+        lexignore = self.lexignore
+        lexdata   = self.lexdata
+
+        while lexpos < lexlen:
+            # This code provides some short-circuit code for whitespace, tabs, and other ignored characters
+            if lexdata[lexpos] in lexignore:
+                lexpos += 1
+                continue
+
+            # Look for a regular expression match
+            for lexre,lexindexfunc in self.lexre:
+                m = lexre.match(lexdata,lexpos)
+                if not m: continue
+
+                # Create a token for return
+                tok = LexToken()
+                tok.value = m.group()
+                tok.lineno = self.lineno
+                tok.lexpos = lexpos
+
+                i = m.lastindex
+                func,tok.type = lexindexfunc[i]
+
+                if not func:
+                   # If no token type was set, it's an ignored token
+                   if tok.type:
+                      self.lexpos = m.end()
+                      return tok
+                   else:
+                      lexpos = m.end()
+                      break
+
+                lexpos = m.end()
+
+                # If token is processed by a function, call it
+
+                tok.lexer = self      # Set additional attributes useful in token rules
+                self.lexmatch = m
+                self.lexpos = lexpos
+
+                newtok = func(tok)
+
+                # Every function must return a token, if nothing, we just move to next token
+                if not newtok:
+                    lexpos    = self.lexpos         # This is here in case user has updated lexpos.
+                    lexignore = self.lexignore      # This is here in case there was a state change
+                    break
+
+                # Verify type of the token.  If not in the token map, raise an error
+                if not self.lexoptimize:
+                    if not newtok.type in self.lextokens:
+                        raise LexError("%s:%d: Rule '%s' returned an unknown token type '%s'" % (
+                            func_code(func).co_filename, func_code(func).co_firstlineno,
+                            func.__name__, newtok.type),lexdata[lexpos:])
+
+                return newtok
+            else:
+                # No match, see if in literals
+                if lexdata[lexpos] in self.lexliterals:
+                    tok = LexToken()
+                    tok.value = lexdata[lexpos]
+                    tok.lineno = self.lineno
+                    tok.type = tok.value
+                    tok.lexpos = lexpos
+                    self.lexpos = lexpos + 1
+                    return tok
+
+                # No match. Call t_error() if defined.
+                if self.lexerrorf:
+                    tok = LexToken()
+                    tok.value = self.lexdata[lexpos:]
+                    tok.lineno = self.lineno
+                    tok.type = "error"
+                    tok.lexer = self
+                    tok.lexpos = lexpos
+                    self.lexpos = lexpos
+                    newtok = self.lexerrorf(tok)
+                    if lexpos == self.lexpos:
+                        # Error method didn't change text position at all. This is an error.
+                        raise LexError("Scanning error. Illegal character '%s'" % (lexdata[lexpos]), lexdata[lexpos:])
+                    lexpos = self.lexpos
+                    if not newtok: continue
+                    return newtok
+
+                self.lexpos = lexpos
+                raise LexError("Illegal character '%s' at index %d" % (lexdata[lexpos],lexpos), lexdata[lexpos:])
+
+        self.lexpos = lexpos + 1
+        if self.lexdata is None:
+             raise RuntimeError("No input string given with input()")
+        return None
+
+    # Iterator interface
+    def __iter__(self):
+        return self
+
+    def next(self):
+        t = self.token()
+        if t is None:
+            raise StopIteration
+        return t
+
+    __next__ = next
+
+# -----------------------------------------------------------------------------
+#                           ==== Lex Builder ===
+#
+# The functions and classes below are used to collect lexing information
+# and build a Lexer object from it.
+# -----------------------------------------------------------------------------
+
+# -----------------------------------------------------------------------------
+# get_caller_module_dict()
+#
+# This function returns a dictionary containing all of the symbols defined within
+# a caller further down the call stack.  This is used to get the environment
+# associated with the yacc() call if none was provided.
+# -----------------------------------------------------------------------------
+
+def get_caller_module_dict(levels):
+    try:
+        raise RuntimeError
+    except RuntimeError:
+        e,b,t = sys.exc_info()
+        f = t.tb_frame
+        while levels > 0:
+            f = f.f_back                   
+            levels -= 1
+        ldict = f.f_globals.copy()
+        if f.f_globals != f.f_locals:
+            ldict.update(f.f_locals)
+
+        return ldict
+
+# -----------------------------------------------------------------------------
+# _funcs_to_names()
+#
+# Given a list of regular expression functions, this converts it to a list
+# suitable for output to a table file
+# -----------------------------------------------------------------------------
+
+def _funcs_to_names(funclist,namelist):
+    result = []
+    for f,name in zip(funclist,namelist):
+         if f and f[0]:
+             result.append((name, f[1]))
+         else:
+             result.append(f)
+    return result
+
+# -----------------------------------------------------------------------------
+# _names_to_funcs()
+#
+# Given a list of regular expression function names, this converts it back to
+# functions.
+# -----------------------------------------------------------------------------
+
+def _names_to_funcs(namelist,fdict):
+     result = []
+     for n in namelist:
+          if n and n[0]:
+              result.append((fdict[n[0]],n[1]))
+          else:
+              result.append(n)
+     return result
+
+# -----------------------------------------------------------------------------
+# _form_master_re()
+#
+# This function takes a list of all of the regex components and attempts to
+# form the master regular expression.  Given limitations in the Python re
+# module, it may be necessary to break the master regex into separate expressions.
+# -----------------------------------------------------------------------------
+
+def _form_master_re(relist,reflags,ldict,toknames):
+    if not relist: return []
+    regex = "|".join(relist)
+    try:
+        lexre = re.compile(regex,re.VERBOSE | reflags)
+
+        # Build the index to function map for the matching engine
+        lexindexfunc = [ None ] * (max(lexre.groupindex.values())+1)
+        lexindexnames = lexindexfunc[:]
+
+        for f,i in lexre.groupindex.items():
+            handle = ldict.get(f,None)
+            if type(handle) in (types.FunctionType, types.MethodType):
+                lexindexfunc[i] = (handle,toknames[f])
+                lexindexnames[i] = f
+            elif handle is not None:
+                lexindexnames[i] = f
+                if f.find("ignore_") > 0:
+                    lexindexfunc[i] = (None,None)
+                else:
+                    lexindexfunc[i] = (None, toknames[f])
+        
+        return [(lexre,lexindexfunc)],[regex],[lexindexnames]
+    except Exception:
+        m = int(len(relist)/2)
+        if m == 0: m = 1
+        llist, lre, lnames = _form_master_re(relist[:m],reflags,ldict,toknames)
+        rlist, rre, rnames = _form_master_re(relist[m:],reflags,ldict,toknames)
+        return llist+rlist, lre+rre, lnames+rnames
+
+# -----------------------------------------------------------------------------
+# def _statetoken(s,names)
+#
+# Given a declaration name s of the form "t_" and a dictionary whose keys are
+# state names, this function returns a tuple (states,tokenname) where states
+# is a tuple of state names and tokenname is the name of the token.  For example,
+# calling this with s = "t_foo_bar_SPAM" might return (('foo','bar'),'SPAM')
+# -----------------------------------------------------------------------------
+
+def _statetoken(s,names):
+    nonstate = 1
+    parts = s.split("_")
+    for i in range(1,len(parts)):
+         if not parts[i] in names and parts[i] != 'ANY': break
+    if i > 1:
+       states = tuple(parts[1:i])
+    else:
+       states = ('INITIAL',)
+
+    if 'ANY' in states:
+       states = tuple(names)
+
+    tokenname = "_".join(parts[i:])
+    return (states,tokenname)
+
+
+# -----------------------------------------------------------------------------
+# LexerReflect()
+#
+# This class represents information needed to build a lexer as extracted from a
+# user's input file.
+# -----------------------------------------------------------------------------
+class LexerReflect(object):
+    def __init__(self,ldict,log=None,reflags=0):
+        self.ldict      = ldict
+        self.error_func = None
+        self.tokens     = []
+        self.reflags    = reflags
+        self.stateinfo  = { 'INITIAL' : 'inclusive'}
+        self.files      = {}
+        self.error      = 0
+
+        if log is None:
+            self.log = PlyLogger(sys.stderr)
+        else:
+            self.log = log
+
+    # Get all of the basic information
+    def get_all(self):
+        self.get_tokens()
+        self.get_literals()
+        self.get_states()
+        self.get_rules()
+        
+    # Validate all of the information
+    def validate_all(self):
+        self.validate_tokens()
+        self.validate_literals()
+        self.validate_rules()
+        return self.error
+
+    # Get the tokens map
+    def get_tokens(self):
+        tokens = self.ldict.get("tokens",None)
+        if not tokens:
+            self.log.error("No token list is defined")
+            self.error = 1
+            return
+
+        if not isinstance(tokens,(list, tuple)):
+            self.log.error("tokens must be a list or tuple")
+            self.error = 1
+            return
+        
+        if not tokens:
+            self.log.error("tokens is empty")
+            self.error = 1
+            return
+
+        self.tokens = tokens
+
+    # Validate the tokens
+    def validate_tokens(self):
+        terminals = {}
+        for n in self.tokens:
+            if not _is_identifier.match(n):
+                self.log.error("Bad token name '%s'",n)
+                self.error = 1
+            if n in terminals:
+                self.log.warning("Token '%s' multiply defined", n)
+            terminals[n] = 1
+
+    # Get the literals specifier
+    def get_literals(self):
+        self.literals = self.ldict.get("literals","")
+
+    # Validate literals
+    def validate_literals(self):
+        try:
+            for c in self.literals:
+                if not isinstance(c,StringTypes) or len(c) > 1:
+                    self.log.error("Invalid literal %s. Must be a single character", repr(c))
+                    self.error = 1
+                    continue
+
+        except TypeError:
+            self.log.error("Invalid literals specification. literals must be a sequence of characters")
+            self.error = 1
+
+    def get_states(self):
+        self.states = self.ldict.get("states",None)
+        # Build statemap
+        if self.states:
+             if not isinstance(self.states,(tuple,list)):
+                  self.log.error("states must be defined as a tuple or list")
+                  self.error = 1
+             else:
+                  for s in self.states:
+                        if not isinstance(s,tuple) or len(s) != 2:
+                               self.log.error("Invalid state specifier %s. Must be a tuple (statename,'exclusive|inclusive')",repr(s))
+                               self.error = 1
+                               continue
+                        name, statetype = s
+                        if not isinstance(name,StringTypes):
+                               self.log.error("State name %s must be a string", repr(name))
+                               self.error = 1
+                               continue
+                        if not (statetype == 'inclusive' or statetype == 'exclusive'):
+                               self.log.error("State type for state %s must be 'inclusive' or 'exclusive'",name)
+                               self.error = 1
+                               continue
+                        if name in self.stateinfo:
+                               self.log.error("State '%s' already defined",name)
+                               self.error = 1
+                               continue
+                        self.stateinfo[name] = statetype
+
+    # Get all of the symbols with a t_ prefix and sort them into various
+    # categories (functions, strings, error functions, and ignore characters)
+
+    def get_rules(self):
+        tsymbols = [f for f in self.ldict if f[:2] == 't_' ]
+
+        # Now build up a list of functions and a list of strings
+
+        self.toknames = { }        # Mapping of symbols to token names
+        self.funcsym =  { }        # Symbols defined as functions
+        self.strsym =   { }        # Symbols defined as strings
+        self.ignore   = { }        # Ignore strings by state
+        self.errorf   = { }        # Error functions by state
+
+        for s in self.stateinfo:
+             self.funcsym[s] = []
+             self.strsym[s] = []
+
+        if len(tsymbols) == 0:
+            self.log.error("No rules of the form t_rulename are defined")
+            self.error = 1
+            return
+
+        for f in tsymbols:
+            t = self.ldict[f]
+            states, tokname = _statetoken(f,self.stateinfo)
+            self.toknames[f] = tokname
+
+            if hasattr(t,"__call__"):
+                if tokname == 'error':
+                    for s in states:
+                        self.errorf[s] = t
+                elif tokname == 'ignore':
+                    line = func_code(t).co_firstlineno
+                    file = func_code(t).co_filename
+                    self.log.error("%s:%d: Rule '%s' must be defined as a string",file,line,t.__name__)
+                    self.error = 1
+                else:
+                    for s in states: 
+                        self.funcsym[s].append((f,t))
+            elif isinstance(t, StringTypes):
+                if tokname == 'ignore':
+                    for s in states:
+                        self.ignore[s] = t
+                    if "\\" in t:
+                        self.log.warning("%s contains a literal backslash '\\'",f)
+
+                elif tokname == 'error':
+                    self.log.error("Rule '%s' must be defined as a function", f)
+                    self.error = 1
+                else:
+                    for s in states: 
+                        self.strsym[s].append((f,t))
+            else:
+                self.log.error("%s not defined as a function or string", f)
+                self.error = 1
+
+        # Sort the functions by line number
+        for f in self.funcsym.values():
+            if sys.version_info[0] < 3:
+                f.sort(lambda x,y: cmp(func_code(x[1]).co_firstlineno,func_code(y[1]).co_firstlineno))
+            else:
+                # Python 3.0
+                f.sort(key=lambda x: func_code(x[1]).co_firstlineno)
+
+        # Sort the strings by regular expression length
+        for s in self.strsym.values():
+            if sys.version_info[0] < 3:
+                s.sort(lambda x,y: (len(x[1]) < len(y[1])) - (len(x[1]) > len(y[1])))
+            else:
+                # Python 3.0
+                s.sort(key=lambda x: len(x[1]),reverse=True)
+
+    # Validate all of the t_rules collected 
+    def validate_rules(self):
+        for state in self.stateinfo:
+            # Validate all rules defined by functions
+
+            
+
+            for fname, f in self.funcsym[state]:
+                line = func_code(f).co_firstlineno
+                file = func_code(f).co_filename
+                self.files[file] = 1
+
+                tokname = self.toknames[fname]
+                if isinstance(f, types.MethodType):
+                    reqargs = 2
+                else:
+                    reqargs = 1
+                nargs = func_code(f).co_argcount
+                if nargs > reqargs:
+                    self.log.error("%s:%d: Rule '%s' has too many arguments",file,line,f.__name__)
+                    self.error = 1
+                    continue
+
+                if nargs < reqargs:
+                    self.log.error("%s:%d: Rule '%s' requires an argument", file,line,f.__name__)
+                    self.error = 1
+                    continue
+
+                if not f.__doc__:
+                    self.log.error("%s:%d: No regular expression defined for rule '%s'",file,line,f.__name__)
+                    self.error = 1
+                    continue
+
+                try:
+                    c = re.compile("(?P<%s>%s)" % (fname,f.__doc__), re.VERBOSE | self.reflags)
+                    if c.match(""):
+                        self.log.error("%s:%d: Regular expression for rule '%s' matches empty string", file,line,f.__name__)
+                        self.error = 1
+                except re.error:
+                    _etype, e, _etrace = sys.exc_info()
+                    self.log.error("%s:%d: Invalid regular expression for rule '%s'. %s", file,line,f.__name__,e)
+                    if '#' in f.__doc__:
+                        self.log.error("%s:%d. Make sure '#' in rule '%s' is escaped with '\\#'",file,line, f.__name__)
+                    self.error = 1
+
+            # Validate all rules defined by strings
+            for name,r in self.strsym[state]:
+                tokname = self.toknames[name]
+                if tokname == 'error':
+                    self.log.error("Rule '%s' must be defined as a function", name)
+                    self.error = 1
+                    continue
+
+                if not tokname in self.tokens and tokname.find("ignore_") < 0:
+                    self.log.error("Rule '%s' defined for an unspecified token %s",name,tokname)
+                    self.error = 1
+                    continue
+
+                try:
+                    c = re.compile("(?P<%s>%s)" % (name,r),re.VERBOSE | self.reflags)
+                    if (c.match("")):
+                         self.log.error("Regular expression for rule '%s' matches empty string",name)
+                         self.error = 1
+                except re.error:
+                    _etype, e, _etrace = sys.exc_info()
+                    self.log.error("Invalid regular expression for rule '%s'. %s",name,e)
+                    if '#' in r:
+                         self.log.error("Make sure '#' in rule '%s' is escaped with '\\#'",name)
+                    self.error = 1
+
+            if not self.funcsym[state] and not self.strsym[state]:
+                self.log.error("No rules defined for state '%s'",state)
+                self.error = 1
+
+            # Validate the error function
+            efunc = self.errorf.get(state,None)
+            if efunc:
+                f = efunc
+                line = func_code(f).co_firstlineno
+                file = func_code(f).co_filename
+                self.files[file] = 1
+
+                if isinstance(f, types.MethodType):
+                    reqargs = 2
+                else:
+                    reqargs = 1
+                nargs = func_code(f).co_argcount
+                if nargs > reqargs:
+                    self.log.error("%s:%d: Rule '%s' has too many arguments",file,line,f.__name__)
+                    self.error = 1
+
+                if nargs < reqargs:
+                    self.log.error("%s:%d: Rule '%s' requires an argument", file,line,f.__name__)
+                    self.error = 1
+
+        for f in self.files:
+            self.validate_file(f)
+
+
+    # -----------------------------------------------------------------------------
+    # validate_file()
+    #
+    # This checks to see if there are duplicated t_rulename() functions or strings
+    # in the parser input file.  This is done using a simple regular expression
+    # match on each line in the given file.  
+    # -----------------------------------------------------------------------------
+
+    def validate_file(self,filename):
+        import os.path
+        base,ext = os.path.splitext(filename)
+        if ext != '.py': return         # No idea what the file is. Return OK
+
+        try:
+            f = open(filename)
+            lines = f.readlines()
+            f.close()
+        except IOError:
+            return                      # Couldn't find the file.  Don't worry about it
+
+        fre = re.compile(r'\s*def\s+(t_[a-zA-Z_0-9]*)\(')
+        sre = re.compile(r'\s*(t_[a-zA-Z_0-9]*)\s*=')
+
+        counthash = { }
+        linen = 1
+        for l in lines:
+            m = fre.match(l)
+            if not m:
+                m = sre.match(l)
+            if m:
+                name = m.group(1)
+                prev = counthash.get(name)
+                if not prev:
+                    counthash[name] = linen
+                else:
+                    self.log.error("%s:%d: Rule %s redefined. Previously defined on line %d",filename,linen,name,prev)
+                    self.error = 1
+            linen += 1
+            
+# -----------------------------------------------------------------------------
+# lex(module)
+#
+# Build all of the regular expression rules from definitions in the supplied module
+# -----------------------------------------------------------------------------
+def lex(module=None,object=None,debug=0,optimize=0,lextab="lextab",reflags=0,nowarn=0,outputdir="", debuglog=None, errorlog=None):
+    global lexer
+    ldict = None
+    stateinfo  = { 'INITIAL' : 'inclusive'}
+    lexobj = Lexer()
+    lexobj.lexoptimize = optimize
+    global token,input
+
+    if errorlog is None:
+        errorlog = PlyLogger(sys.stderr)
+
+    if debug:
+        if debuglog is None:
+            debuglog = PlyLogger(sys.stderr)
+
+    # Get the module dictionary used for the lexer
+    if object: module = object
+
+    if module:
+        _items = [(k,getattr(module,k)) for k in dir(module)]
+        ldict = dict(_items)
+    else:
+        ldict = get_caller_module_dict(2)
+
+    # Collect parser information from the dictionary
+    linfo = LexerReflect(ldict,log=errorlog,reflags=reflags)
+    linfo.get_all()
+    if not optimize:
+        if linfo.validate_all():
+            raise SyntaxError("Can't build lexer")
+
+    if optimize and lextab:
+        try:
+            lexobj.readtab(lextab,ldict)
+            token = lexobj.token
+            input = lexobj.input
+            lexer = lexobj
+            return lexobj
+
+        except ImportError:
+            pass
+
+    # Dump some basic debugging information
+    if debug:
+        debuglog.info("lex: tokens   = %r", linfo.tokens)
+        debuglog.info("lex: literals = %r", linfo.literals)
+        debuglog.info("lex: states   = %r", linfo.stateinfo)
+
+    # Build a dictionary of valid token names
+    lexobj.lextokens = { }
+    for n in linfo.tokens:
+        lexobj.lextokens[n] = 1
+
+    # Get literals specification
+    if isinstance(linfo.literals,(list,tuple)):
+        lexobj.lexliterals = type(linfo.literals[0])().join(linfo.literals)
+    else:
+        lexobj.lexliterals = linfo.literals
+
+    # Get the stateinfo dictionary
+    stateinfo = linfo.stateinfo
+
+    regexs = { }
+    # Build the master regular expressions
+    for state in stateinfo:
+        regex_list = []
+
+        # Add rules defined by functions first
+        for fname, f in linfo.funcsym[state]:
+            line = func_code(f).co_firstlineno
+            file = func_code(f).co_filename
+            regex_list.append("(?P<%s>%s)" % (fname,f.__doc__))
+            if debug:
+                debuglog.info("lex: Adding rule %s -> '%s' (state '%s')",fname,f.__doc__, state)
+
+        # Now add all of the simple rules
+        for name,r in linfo.strsym[state]:
+            regex_list.append("(?P<%s>%s)" % (name,r))
+            if debug:
+                debuglog.info("lex: Adding rule %s -> '%s' (state '%s')",name,r, state)
+
+        regexs[state] = regex_list
+
+    # Build the master regular expressions
+
+    if debug:
+        debuglog.info("lex: ==== MASTER REGEXS FOLLOW ====")
+
+    for state in regexs:
+        lexre, re_text, re_names = _form_master_re(regexs[state],reflags,ldict,linfo.toknames)
+        lexobj.lexstatere[state] = lexre
+        lexobj.lexstateretext[state] = re_text
+        lexobj.lexstaterenames[state] = re_names
+        if debug:
+            for i in range(len(re_text)):
+                debuglog.info("lex: state '%s' : regex[%d] = '%s'",state, i, re_text[i])
+
+    # For inclusive states, we need to add the regular expressions from the INITIAL state
+    for state,stype in stateinfo.items():
+        if state != "INITIAL" and stype == 'inclusive':
+             lexobj.lexstatere[state].extend(lexobj.lexstatere['INITIAL'])
+             lexobj.lexstateretext[state].extend(lexobj.lexstateretext['INITIAL'])
+             lexobj.lexstaterenames[state].extend(lexobj.lexstaterenames['INITIAL'])
+
+    lexobj.lexstateinfo = stateinfo
+    lexobj.lexre = lexobj.lexstatere["INITIAL"]
+    lexobj.lexretext = lexobj.lexstateretext["INITIAL"]
+    lexobj.lexreflags = reflags
+
+    # Set up ignore variables
+    lexobj.lexstateignore = linfo.ignore
+    lexobj.lexignore = lexobj.lexstateignore.get("INITIAL","")
+
+    # Set up error functions
+    lexobj.lexstateerrorf = linfo.errorf
+    lexobj.lexerrorf = linfo.errorf.get("INITIAL",None)
+    if not lexobj.lexerrorf:
+        errorlog.warning("No t_error rule is defined")
+
+    # Check state information for ignore and error rules
+    for s,stype in stateinfo.items():
+        if stype == 'exclusive':
+              if not s in linfo.errorf:
+                   errorlog.warning("No error rule is defined for exclusive state '%s'", s)
+              if not s in linfo.ignore and lexobj.lexignore:
+                   errorlog.warning("No ignore rule is defined for exclusive state '%s'", s)
+        elif stype == 'inclusive':
+              if not s in linfo.errorf:
+                   linfo.errorf[s] = linfo.errorf.get("INITIAL",None)
+              if not s in linfo.ignore:
+                   linfo.ignore[s] = linfo.ignore.get("INITIAL","")
+
+    # Create global versions of the token() and input() functions
+    token = lexobj.token
+    input = lexobj.input
+    lexer = lexobj
+
+    # If in optimize mode, we write the lextab
+    if lextab and optimize:
+        lexobj.writetab(lextab,outputdir)
+
+    return lexobj
+
+# -----------------------------------------------------------------------------
+# runmain()
+#
+# This runs the lexer as a main program
+# -----------------------------------------------------------------------------
+
+def runmain(lexer=None,data=None):
+    if not data:
+        try:
+            filename = sys.argv[1]
+            f = open(filename)
+            data = f.read()
+            f.close()
+        except IndexError:
+            sys.stdout.write("Reading from standard input (type EOF to end):\n")
+            data = sys.stdin.read()
+
+    if lexer:
+        _input = lexer.input
+    else:
+        _input = input
+    _input(data)
+    if lexer:
+        _token = lexer.token
+    else:
+        _token = token
+
+    while 1:
+        tok = _token()
+        if not tok: break
+        sys.stdout.write("(%s,%r,%d,%d)\n" % (tok.type, tok.value, tok.lineno,tok.lexpos))
+
+# -----------------------------------------------------------------------------
+# @TOKEN(regex)
+#
+# This decorator function can be used to set the regex expression on a function
+# when its docstring might need to be set in an alternative way
+# -----------------------------------------------------------------------------
+
+def TOKEN(r):
+    def set_doc(f):
+        if hasattr(r,"__call__"):
+            f.__doc__ = r.__doc__
+        else:
+            f.__doc__ = r
+        return f
+    return set_doc
+
+# Alternative spelling of the TOKEN decorator
+Token = TOKEN
+
diff --git a/webWidgetTCT_device/tools/slimit/ply/yacc.py b/webWidgetTCT_device/tools/slimit/ply/yacc.py
new file mode 100755 (executable)
index 0000000..f70439e
--- /dev/null
@@ -0,0 +1,3276 @@
+# -----------------------------------------------------------------------------
+# ply: yacc.py
+#
+# Copyright (C) 2001-2011,
+# David M. Beazley (Dabeaz LLC)
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+# 
+# * Redistributions of source code must retain the above copyright notice,
+#   this list of conditions and the following disclaimer.  
+# * Redistributions in binary form must reproduce the above copyright notice, 
+#   this list of conditions and the following disclaimer in the documentation
+#   and/or other materials provided with the distribution.  
+# * Neither the name of the David Beazley or Dabeaz LLC may be used to
+#   endorse or promote products derived from this software without
+#  specific prior written permission. 
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+# -----------------------------------------------------------------------------
+#
+# This implements an LR parser that is constructed from grammar rules defined
+# as Python functions. The grammer is specified by supplying the BNF inside
+# Python documentation strings.  The inspiration for this technique was borrowed
+# from John Aycock's Spark parsing system.  PLY might be viewed as cross between
+# Spark and the GNU bison utility.
+#
+# The current implementation is only somewhat object-oriented. The
+# LR parser itself is defined in terms of an object (which allows multiple
+# parsers to co-exist).  However, most of the variables used during table
+# construction are defined in terms of global variables.  Users shouldn't
+# notice unless they are trying to define multiple parsers at the same
+# time using threads (in which case they should have their head examined).
+#
+# This implementation supports both SLR and LALR(1) parsing.  LALR(1)
+# support was originally implemented by Elias Ioup (ezioup@alumni.uchicago.edu),
+# using the algorithm found in Aho, Sethi, and Ullman "Compilers: Principles,
+# Techniques, and Tools" (The Dragon Book).  LALR(1) has since been replaced
+# by the more efficient DeRemer and Pennello algorithm.
+#
+# :::::::: WARNING :::::::
+#
+# Construction of LR parsing tables is fairly complicated and expensive.
+# To make this module run fast, a *LOT* of work has been put into
+# optimization---often at the expensive of readability and what might
+# consider to be good Python "coding style."   Modify the code at your
+# own risk!
+# ----------------------------------------------------------------------------
+
+__version__    = "3.4"
+__tabversion__ = "3.2"       # Table version
+
+#-----------------------------------------------------------------------------
+#                     === User configurable parameters ===
+#
+# Change these to modify the default behavior of yacc (if you wish)
+#-----------------------------------------------------------------------------
+
+yaccdebug   = 1                # Debugging mode.  If set, yacc generates a
+                               # a 'parser.out' file in the current directory
+
+debug_file  = 'parser.out'     # Default name of the debugging file
+tab_module  = 'parsetab'       # Default name of the table module
+default_lr  = 'LALR'           # Default LR table generation method
+
+error_count = 3                # Number of symbols that must be shifted to leave recovery mode
+
+yaccdevel   = 0                # Set to True if developing yacc.  This turns off optimized
+                               # implementations of certain functions.
+
+resultlimit = 40               # Size limit of results when running in debug mode.
+
+pickle_protocol = 0            # Protocol to use when writing pickle files
+
+import re, types, sys, os.path
+
+# Compatibility function for python 2.6/3.0
+if sys.version_info[0] < 3:
+    def func_code(f):
+        return f.func_code
+else:
+    def func_code(f):
+        return f.__code__
+
+# Compatibility
+try:
+    MAXINT = sys.maxint
+except AttributeError:
+    MAXINT = sys.maxsize
+
+# Python 2.x/3.0 compatibility.
+def load_ply_lex():
+    if sys.version_info[0] < 3:
+        import lex
+    else:
+        import ply.lex as lex
+    return lex
+
+# This object is a stand-in for a logging object created by the 
+# logging module.   PLY will use this by default to create things
+# such as the parser.out file.  If a user wants more detailed
+# information, they can create their own logging object and pass
+# it into PLY.
+
+class PlyLogger(object):
+    def __init__(self,f):
+        self.f = f
+    def debug(self,msg,*args,**kwargs):
+        self.f.write((msg % args) + "\n")
+    info     = debug
+
+    def warning(self,msg,*args,**kwargs):
+        self.f.write("WARNING: "+ (msg % args) + "\n")
+
+    def error(self,msg,*args,**kwargs):
+        self.f.write("ERROR: " + (msg % args) + "\n")
+
+    critical = debug
+
+# Null logger is used when no output is generated. Does nothing.
+class NullLogger(object):
+    def __getattribute__(self,name):
+        return self
+    def __call__(self,*args,**kwargs):
+        return self
+        
+# Exception raised for yacc-related errors
+class YaccError(Exception):   pass
+
+# Format the result message that the parser produces when running in debug mode.
+def format_result(r):
+    repr_str = repr(r)
+    if '\n' in repr_str: repr_str = repr(repr_str)
+    if len(repr_str) > resultlimit:
+        repr_str = repr_str[:resultlimit]+" ..."
+    result = "<%s @ 0x%x> (%s)" % (type(r).__name__,id(r),repr_str)
+    return result
+
+
+# Format stack entries when the parser is running in debug mode
+def format_stack_entry(r):
+    repr_str = repr(r)
+    if '\n' in repr_str: repr_str = repr(repr_str)
+    if len(repr_str) < 16:
+        return repr_str
+    else:
+        return "<%s @ 0x%x>" % (type(r).__name__,id(r))
+
+#-----------------------------------------------------------------------------
+#                        ===  LR Parsing Engine ===
+#
+# The following classes are used for the LR parser itself.  These are not
+# used during table construction and are independent of the actual LR
+# table generation algorithm
+#-----------------------------------------------------------------------------
+
+# This class is used to hold non-terminal grammar symbols during parsing.
+# It normally has the following attributes set:
+#        .type       = Grammar symbol type
+#        .value      = Symbol value
+#        .lineno     = Starting line number
+#        .endlineno  = Ending line number (optional, set automatically)
+#        .lexpos     = Starting lex position
+#        .endlexpos  = Ending lex position (optional, set automatically)
+
+class YaccSymbol:
+    def __str__(self):    return self.type
+    def __repr__(self):   return str(self)
+
+# This class is a wrapper around the objects actually passed to each
+# grammar rule.   Index lookup and assignment actually assign the
+# .value attribute of the underlying YaccSymbol object.
+# The lineno() method returns the line number of a given
+# item (or 0 if not defined).   The linespan() method returns
+# a tuple of (startline,endline) representing the range of lines
+# for a symbol.  The lexspan() method returns a tuple (lexpos,endlexpos)
+# representing the range of positional information for a symbol.
+
+class YaccProduction:
+    def __init__(self,s,stack=None):
+        self.slice = s
+        self.stack = stack
+        self.lexer = None
+        self.parser= None
+    def __getitem__(self,n):
+        if n >= 0: return self.slice[n].value
+        else: return self.stack[n].value
+
+    def __setitem__(self,n,v):
+        self.slice[n].value = v
+
+    def __getslice__(self,i,j):
+        return [s.value for s in self.slice[i:j]]
+
+    def __len__(self):
+        return len(self.slice)
+
+    def lineno(self,n):
+        return getattr(self.slice[n],"lineno",0)
+
+    def set_lineno(self,n,lineno):
+        self.slice[n].lineno = lineno
+
+    def linespan(self,n):
+        startline = getattr(self.slice[n],"lineno",0)
+        endline = getattr(self.slice[n],"endlineno",startline)
+        return startline,endline
+
+    def lexpos(self,n):
+        return getattr(self.slice[n],"lexpos",0)
+
+    def lexspan(self,n):
+        startpos = getattr(self.slice[n],"lexpos",0)
+        endpos = getattr(self.slice[n],"endlexpos",startpos)
+        return startpos,endpos
+
+    def error(self):
+       raise SyntaxError
+
+
+# -----------------------------------------------------------------------------
+#                               == LRParser ==
+#
+# The LR Parsing engine.
+# -----------------------------------------------------------------------------
+
+class LRParser:
+    def __init__(self,lrtab,errorf):
+        self.productions = lrtab.lr_productions
+        self.action      = lrtab.lr_action
+        self.goto        = lrtab.lr_goto
+        self.errorfunc   = errorf
+
+    def errok(self):
+        self.errorok     = 1
+
+    def restart(self):
+        del self.statestack[:]
+        del self.symstack[:]
+        sym = YaccSymbol()
+        sym.type = '$end'
+        self.symstack.append(sym)
+        self.statestack.append(0)
+
+    def parse(self,input=None,lexer=None,debug=0,tracking=0,tokenfunc=None):
+        if debug or yaccdevel:
+            if isinstance(debug,int):
+                debug = PlyLogger(sys.stderr)
+            return self.parsedebug(input,lexer,debug,tracking,tokenfunc)
+        elif tracking:
+            return self.parseopt(input,lexer,debug,tracking,tokenfunc)
+        else:
+            return self.parseopt_notrack(input,lexer,debug,tracking,tokenfunc)
+        
+
+    # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+    # parsedebug().
+    #
+    # This is the debugging enabled version of parse().  All changes made to the
+    # parsing engine should be made here.   For the non-debugging version,
+    # copy this code to a method parseopt() and delete all of the sections
+    # enclosed in:
+    #
+    #      #--! DEBUG
+    #      statements
+    #      #--! DEBUG
+    #
+    # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+    def parsedebug(self,input=None,lexer=None,debug=None,tracking=0,tokenfunc=None):
+        lookahead = None                 # Current lookahead symbol
+        lookaheadstack = [ ]             # Stack of lookahead symbols
+        actions = self.action            # Local reference to action table (to avoid lookup on self.)
+        goto    = self.goto              # Local reference to goto table (to avoid lookup on self.)
+        prod    = self.productions       # Local reference to production list (to avoid lookup on self.)
+        pslice  = YaccProduction(None)   # Production object passed to grammar rules
+        errorcount = 0                   # Used during error recovery 
+
+        # --! DEBUG
+        debug.info("PLY: PARSE DEBUG START")
+        # --! DEBUG
+
+        # If no lexer was given, we will try to use the lex module
+        if not lexer:
+            lex = load_ply_lex()
+            lexer = lex.lexer
+
+        # Set up the lexer and parser objects on pslice
+        pslice.lexer = lexer
+        pslice.parser = self
+
+        # If input was supplied, pass to lexer
+        if input is not None:
+            lexer.input(input)
+
+        if tokenfunc is None:
+           # Tokenize function
+           get_token = lexer.token
+        else:
+           get_token = tokenfunc
+
+        # Set up the state and symbol stacks
+
+        statestack = [ ]                # Stack of parsing states
+        self.statestack = statestack
+        symstack   = [ ]                # Stack of grammar symbols
+        self.symstack = symstack
+
+        pslice.stack = symstack         # Put in the production
+        errtoken   = None               # Err token
+
+        # The start state is assumed to be (0,$end)
+
+        statestack.append(0)
+        sym = YaccSymbol()
+        sym.type = "$end"
+        symstack.append(sym)
+        state = 0
+        while 1:
+            # Get the next symbol on the input.  If a lookahead symbol
+            # is already set, we just use that. Otherwise, we'll pull
+            # the next token off of the lookaheadstack or from the lexer
+
+            # --! DEBUG
+            debug.debug('')
+            debug.debug('State  : %s', state)
+            # --! DEBUG
+
+            if not lookahead:
+                if not lookaheadstack:
+                    lookahead = get_token()     # Get the next token
+                else:
+                    lookahead = lookaheadstack.pop()
+                if not lookahead:
+                    lookahead = YaccSymbol()
+                    lookahead.type = "$end"
+
+            # --! DEBUG
+            debug.debug('Stack  : %s',
+                        ("%s . %s" % (" ".join([xx.type for xx in symstack][1:]), str(lookahead))).lstrip())
+            # --! DEBUG
+
+            # Check the action table
+            ltype = lookahead.type
+            t = actions[state].get(ltype)
+
+            if t is not None:
+                if t > 0:
+                    # shift a symbol on the stack
+                    statestack.append(t)
+                    state = t
+                    
+                    # --! DEBUG
+                    debug.debug("Action : Shift and goto state %s", t)
+                    # --! DEBUG
+
+                    symstack.append(lookahead)
+                    lookahead = None
+
+                    # Decrease error count on successful shift
+                    if errorcount: errorcount -=1
+                    continue
+
+                if t < 0:
+                    # reduce a symbol on the stack, emit a production
+                    p = prod[-t]
+                    pname = p.name
+                    plen  = p.len
+
+                    # Get production function
+                    sym = YaccSymbol()
+                    sym.type = pname       # Production name
+                    sym.value = None
+
+                    # --! DEBUG
+                    if plen:
+                        debug.info("Action : Reduce rule [%s] with %s and goto state %d", p.str, "["+",".join([format_stack_entry(_v.value) for _v in symstack[-plen:]])+"]",-t)
+                    else:
+                        debug.info("Action : Reduce rule [%s] with %s and goto state %d", p.str, [],-t)
+                        
+                    # --! DEBUG
+
+                    if plen:
+                        targ = symstack[-plen-1:]
+                        targ[0] = sym
+
+                        # --! TRACKING
+                        if tracking:
+                           t1 = targ[1]
+                           sym.lineno = t1.lineno
+                           sym.lexpos = t1.lexpos
+                           t1 = targ[-1]
+                           sym.endlineno = getattr(t1,"endlineno",t1.lineno)
+                           sym.endlexpos = getattr(t1,"endlexpos",t1.lexpos)
+
+                        # --! TRACKING
+
+                        # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+                        # The code enclosed in this section is duplicated 
+                        # below as a performance optimization.  Make sure
+                        # changes get made in both locations.
+
+                        pslice.slice = targ
+                        
+                        try:
+                            # Call the grammar rule with our special slice object
+                            del symstack[-plen:]
+                            del statestack[-plen:]
+                            p.callable(pslice)
+                            # --! DEBUG
+                            debug.info("Result : %s", format_result(pslice[0]))
+                            # --! DEBUG
+                            symstack.append(sym)
+                            state = goto[statestack[-1]][pname]
+                            statestack.append(state)
+                        except SyntaxError:
+                            # If an error was set. Enter error recovery state
+                            lookaheadstack.append(lookahead)
+                            symstack.pop()
+                            statestack.pop()
+                            state = statestack[-1]
+                            sym.type = 'error'
+                            lookahead = sym
+                            errorcount = error_count
+                            self.errorok = 0
+                        continue
+                        # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+    
+                    else:
+
+                        # --! TRACKING
+                        if tracking:
+                           sym.lineno = lexer.lineno
+                           sym.lexpos = lexer.lexpos
+                        # --! TRACKING
+
+                        targ = [ sym ]
+
+                        # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+                        # The code enclosed in this section is duplicated 
+                        # above as a performance optimization.  Make sure
+                        # changes get made in both locations.
+
+                        pslice.slice = targ
+
+                        try:
+                            # Call the grammar rule with our special slice object
+                            p.callable(pslice)
+                            # --! DEBUG
+                            debug.info("Result : %s", format_result(pslice[0]))
+                            # --! DEBUG
+                            symstack.append(sym)
+                            state = goto[statestack[-1]][pname]
+                            statestack.append(state)
+                        except SyntaxError:
+                            # If an error was set. Enter error recovery state
+                            lookaheadstack.append(lookahead)
+                            symstack.pop()
+                            statestack.pop()
+                            state = statestack[-1]
+                            sym.type = 'error'
+                            lookahead = sym
+                            errorcount = error_count
+                            self.errorok = 0
+                        continue
+                        # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+                if t == 0:
+                    n = symstack[-1]
+                    result = getattr(n,"value",None)
+                    # --! DEBUG
+                    debug.info("Done   : Returning %s", format_result(result))
+                    debug.info("PLY: PARSE DEBUG END")
+                    # --! DEBUG
+                    return result
+
+            if t == None:
+
+                # --! DEBUG
+                debug.error('Error  : %s',
+                            ("%s . %s" % (" ".join([xx.type for xx in symstack][1:]), str(lookahead))).lstrip())
+                # --! DEBUG
+
+                # We have some kind of parsing error here.  To handle
+                # this, we are going to push the current token onto
+                # the tokenstack and replace it with an 'error' token.
+                # If there are any synchronization rules, they may
+                # catch it.
+                #
+                # In addition to pushing the error token, we call call
+                # the user defined p_error() function if this is the
+                # first syntax error.  This function is only called if
+                # errorcount == 0.
+                if errorcount == 0 or self.errorok:
+                    errorcount = error_count
+                    self.errorok = 0
+                    errtoken = lookahead
+                    if errtoken.type == "$end":
+                        errtoken = None               # End of file!
+                    if self.errorfunc:
+                        global errok,token,restart
+                        errok = self.errok        # Set some special functions available in error recovery
+                        token = get_token
+                        restart = self.restart
+                        if errtoken and not hasattr(errtoken,'lexer'):
+                            errtoken.lexer = lexer
+                        tok = self.errorfunc(errtoken)
+                        del errok, token, restart   # Delete special functions
+
+                        if self.errorok:
+                            # User must have done some kind of panic
+                            # mode recovery on their own.  The
+                            # returned token is the next lookahead
+                            lookahead = tok
+                            errtoken = None
+                            continue
+                    else:
+                        if errtoken:
+                            if hasattr(errtoken,"lineno"): lineno = lookahead.lineno
+                            else: lineno = 0
+                            if lineno:
+                                sys.stderr.write("yacc: Syntax error at line %d, token=%s\n" % (lineno, errtoken.type))
+                            else:
+                                sys.stderr.write("yacc: Syntax error, token=%s" % errtoken.type)
+                        else:
+                            sys.stderr.write("yacc: Parse error in input. EOF\n")
+                            return
+
+                else:
+                    errorcount = error_count
+
+                # case 1:  the statestack only has 1 entry on it.  If we're in this state, the
+                # entire parse has been rolled back and we're completely hosed.   The token is
+                # discarded and we just keep going.
+
+                if len(statestack) <= 1 and lookahead.type != "$end":
+                    lookahead = None
+                    errtoken = None
+                    state = 0
+                    # Nuke the pushback stack
+                    del lookaheadstack[:]
+                    continue
+
+                # case 2: the statestack has a couple of entries on it, but we're
+                # at the end of the file. nuke the top entry and generate an error token
+
+                # Start nuking entries on the stack
+                if lookahead.type == "$end":
+                    # Whoa. We're really hosed here. Bail out
+                    return
+
+                if lookahead.type != 'error':
+                    sym = symstack[-1]
+                    if sym.type == 'error':
+                        # Hmmm. Error is on top of stack, we'll just nuke input
+                        # symbol and continue
+                        lookahead = None
+                        continue
+                    t = YaccSymbol()
+                    t.type = 'error'
+                    if hasattr(lookahead,"lineno"):
+                        t.lineno = lookahead.lineno
+                    t.value = lookahead
+                    lookaheadstack.append(lookahead)
+                    lookahead = t
+                else:
+                    symstack.pop()
+                    statestack.pop()
+                    state = statestack[-1]       # Potential bug fix
+
+                continue
+
+            # Call an error function here
+            raise RuntimeError("yacc: internal parser error!!!\n")
+
+    # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+    # parseopt().
+    #
+    # Optimized version of parse() method.  DO NOT EDIT THIS CODE DIRECTLY.
+    # Edit the debug version above, then copy any modifications to the method
+    # below while removing #--! DEBUG sections.
+    # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+
+    def parseopt(self,input=None,lexer=None,debug=0,tracking=0,tokenfunc=None):
+        lookahead = None                 # Current lookahead symbol
+        lookaheadstack = [ ]             # Stack of lookahead symbols
+        actions = self.action            # Local reference to action table (to avoid lookup on self.)
+        goto    = self.goto              # Local reference to goto table (to avoid lookup on self.)
+        prod    = self.productions       # Local reference to production list (to avoid lookup on self.)
+        pslice  = YaccProduction(None)   # Production object passed to grammar rules
+        errorcount = 0                   # Used during error recovery 
+
+        # If no lexer was given, we will try to use the lex module
+        if not lexer:
+            lex = load_ply_lex()
+            lexer = lex.lexer
+        
+        # Set up the lexer and parser objects on pslice
+        pslice.lexer = lexer
+        pslice.parser = self
+
+        # If input was supplied, pass to lexer
+        if input is not None:
+            lexer.input(input)
+
+        if tokenfunc is None:
+           # Tokenize function
+           get_token = lexer.token
+        else:
+           get_token = tokenfunc
+
+        # Set up the state and symbol stacks
+
+        statestack = [ ]                # Stack of parsing states
+        self.statestack = statestack
+        symstack   = [ ]                # Stack of grammar symbols
+        self.symstack = symstack
+
+        pslice.stack = symstack         # Put in the production
+        errtoken   = None               # Err token
+
+        # The start state is assumed to be (0,$end)
+
+        statestack.append(0)
+        sym = YaccSymbol()
+        sym.type = '$end'
+        symstack.append(sym)
+        state = 0
+        while 1:
+            # Get the next symbol on the input.  If a lookahead symbol
+            # is already set, we just use that. Otherwise, we'll pull
+            # the next token off of the lookaheadstack or from the lexer
+
+            if not lookahead:
+                if not lookaheadstack:
+                    lookahead = get_token()     # Get the next token
+                else:
+                    lookahead = lookaheadstack.pop()
+                if not lookahead:
+                    lookahead = YaccSymbol()
+                    lookahead.type = '$end'
+
+            # Check the action table
+            ltype = lookahead.type
+            t = actions[state].get(ltype)
+
+            if t is not None:
+                if t > 0:
+                    # shift a symbol on the stack
+                    statestack.append(t)
+                    state = t
+
+                    symstack.append(lookahead)
+                    lookahead = None
+
+                    # Decrease error count on successful shift
+                    if errorcount: errorcount -=1
+                    continue
+
+                if t < 0:
+                    # reduce a symbol on the stack, emit a production
+                    p = prod[-t]
+                    pname = p.name
+                    plen  = p.len
+
+                    # Get production function
+                    sym = YaccSymbol()
+                    sym.type = pname       # Production name
+                    sym.value = None
+
+                    if plen:
+                        targ = symstack[-plen-1:]
+                        targ[0] = sym
+
+                        # --! TRACKING
+                        if tracking:
+                           t1 = targ[1]
+                           sym.lineno = t1.lineno
+                           sym.lexpos = t1.lexpos
+                           t1 = targ[-1]
+                           sym.endlineno = getattr(t1,"endlineno",t1.lineno)
+                           sym.endlexpos = getattr(t1,"endlexpos",t1.lexpos)
+
+                        # --! TRACKING
+
+                        # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+                        # The code enclosed in this section is duplicated 
+                        # below as a performance optimization.  Make sure
+                        # changes get made in both locations.
+
+                        pslice.slice = targ
+                        
+                        try:
+                            # Call the grammar rule with our special slice object
+                            del symstack[-plen:]
+                            del statestack[-plen:]
+                            p.callable(pslice)
+                            symstack.append(sym)
+                            state = goto[statestack[-1]][pname]
+                            statestack.append(state)
+                        except SyntaxError:
+                            # If an error was set. Enter error recovery state
+                            lookaheadstack.append(lookahead)
+                            symstack.pop()
+                            statestack.pop()
+                            state = statestack[-1]
+                            sym.type = 'error'
+                            lookahead = sym
+                            errorcount = error_count
+                            self.errorok = 0
+                        continue
+                        # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+    
+                    else:
+
+                        # --! TRACKING
+                        if tracking:
+                           sym.lineno = lexer.lineno
+                           sym.lexpos = lexer.lexpos
+                        # --! TRACKING
+
+                        targ = [ sym ]
+
+                        # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+                        # The code enclosed in this section is duplicated 
+                        # above as a performance optimization.  Make sure
+                        # changes get made in both locations.
+
+                        pslice.slice = targ
+
+                        try:
+                            # Call the grammar rule with our special slice object
+                            p.callable(pslice)
+                            symstack.append(sym)
+                            state = goto[statestack[-1]][pname]
+                            statestack.append(state)
+                        except SyntaxError:
+                            # If an error was set. Enter error recovery state
+                            lookaheadstack.append(lookahead)
+                            symstack.pop()
+                            statestack.pop()
+                            state = statestack[-1]
+                            sym.type = 'error'
+                            lookahead = sym
+                            errorcount = error_count
+                            self.errorok = 0
+                        continue
+                        # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+                if t == 0:
+                    n = symstack[-1]
+                    return getattr(n,"value",None)
+
+            if t == None:
+
+                # We have some kind of parsing error here.  To handle
+                # this, we are going to push the current token onto
+                # the tokenstack and replace it with an 'error' token.
+                # If there are any synchronization rules, they may
+                # catch it.
+                #
+                # In addition to pushing the error token, we call call
+                # the user defined p_error() function if this is the
+                # first syntax error.  This function is only called if
+                # errorcount == 0.
+                if errorcount == 0 or self.errorok:
+                    errorcount = error_count
+                    self.errorok = 0
+                    errtoken = lookahead
+                    if errtoken.type == '$end':
+                        errtoken = None               # End of file!
+                    if self.errorfunc:
+                        global errok,token,restart
+                        errok = self.errok        # Set some special functions available in error recovery
+                        token = get_token
+                        restart = self.restart
+                        if errtoken and not hasattr(errtoken,'lexer'):
+                            errtoken.lexer = lexer
+                        tok = self.errorfunc(errtoken)
+                        del errok, token, restart   # Delete special functions
+
+                        if self.errorok:
+                            # User must have done some kind of panic
+                            # mode recovery on their own.  The
+                            # returned token is the next lookahead
+                            lookahead = tok
+                            errtoken = None
+                            continue
+                    else:
+                        if errtoken:
+                            if hasattr(errtoken,"lineno"): lineno = lookahead.lineno
+                            else: lineno = 0
+                            if lineno:
+                                sys.stderr.write("yacc: Syntax error at line %d, token=%s\n" % (lineno, errtoken.type))
+                            else:
+                                sys.stderr.write("yacc: Syntax error, token=%s" % errtoken.type)
+                        else:
+                            sys.stderr.write("yacc: Parse error in input. EOF\n")
+                            return
+
+                else:
+                    errorcount = error_count
+
+                # case 1:  the statestack only has 1 entry on it.  If we're in this state, the
+                # entire parse has been rolled back and we're completely hosed.   The token is
+                # discarded and we just keep going.
+
+                if len(statestack) <= 1 and lookahead.type != '$end':
+                    lookahead = None
+                    errtoken = None
+                    state = 0
+                    # Nuke the pushback stack
+                    del lookaheadstack[:]
+                    continue
+
+                # case 2: the statestack has a couple of entries on it, but we're
+                # at the end of the file. nuke the top entry and generate an error token
+
+                # Start nuking entries on the stack
+                if lookahead.type == '$end':
+                    # Whoa. We're really hosed here. Bail out
+                    return
+
+                if lookahead.type != 'error':
+                    sym = symstack[-1]
+                    if sym.type == 'error':
+                        # Hmmm. Error is on top of stack, we'll just nuke input
+                        # symbol and continue
+                        lookahead = None
+                        continue
+                    t = YaccSymbol()
+                    t.type = 'error'
+                    if hasattr(lookahead,"lineno"):
+                        t.lineno = lookahead.lineno
+                    t.value = lookahead
+                    lookaheadstack.append(lookahead)
+                    lookahead = t
+                else:
+                    symstack.pop()
+                    statestack.pop()
+                    state = statestack[-1]       # Potential bug fix
+
+                continue
+
+            # Call an error function here
+            raise RuntimeError("yacc: internal parser error!!!\n")
+
+    # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+    # parseopt_notrack().
+    #
+    # Optimized version of parseopt() with line number tracking removed. 
+    # DO NOT EDIT THIS CODE DIRECTLY. Copy the optimized version and remove
+    # code in the #--! TRACKING sections
+    # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+    def parseopt_notrack(self,input=None,lexer=None,debug=0,tracking=0,tokenfunc=None):
+        lookahead = None                 # Current lookahead symbol
+        lookaheadstack = [ ]             # Stack of lookahead symbols
+        actions = self.action            # Local reference to action table (to avoid lookup on self.)
+        goto    = self.goto              # Local reference to goto table (to avoid lookup on self.)
+        prod    = self.productions       # Local reference to production list (to avoid lookup on self.)
+        pslice  = YaccProduction(None)   # Production object passed to grammar rules
+        errorcount = 0                   # Used during error recovery 
+
+        # If no lexer was given, we will try to use the lex module
+        if not lexer:
+            lex = load_ply_lex()
+            lexer = lex.lexer
+        
+        # Set up the lexer and parser objects on pslice
+        pslice.lexer = lexer
+        pslice.parser = self
+
+        # If input was supplied, pass to lexer
+        if input is not None:
+            lexer.input(input)
+
+        if tokenfunc is None:
+           # Tokenize function
+           get_token = lexer.token
+        else:
+           get_token = tokenfunc
+
+        # Set up the state and symbol stacks
+
+        statestack = [ ]                # Stack of parsing states
+        self.statestack = statestack
+        symstack   = [ ]                # Stack of grammar symbols
+        self.symstack = symstack
+
+        pslice.stack = symstack         # Put in the production
+        errtoken   = None               # Err token
+
+        # The start state is assumed to be (0,$end)
+
+        statestack.append(0)
+        sym = YaccSymbol()
+        sym.type = '$end'
+        symstack.append(sym)
+        state = 0
+        while 1:
+            # Get the next symbol on the input.  If a lookahead symbol
+            # is already set, we just use that. Otherwise, we'll pull
+            # the next token off of the lookaheadstack or from the lexer
+
+            if not lookahead:
+                if not lookaheadstack:
+                    lookahead = get_token()     # Get the next token
+                else:
+                    lookahead = lookaheadstack.pop()
+                if not lookahead:
+                    lookahead = YaccSymbol()
+                    lookahead.type = '$end'
+
+            # Check the action table
+            ltype = lookahead.type
+            t = actions[state].get(ltype)
+
+            if t is not None:
+                if t > 0:
+                    # shift a symbol on the stack
+                    statestack.append(t)
+                    state = t
+
+                    symstack.append(lookahead)
+                    lookahead = None
+
+                    # Decrease error count on successful shift
+                    if errorcount: errorcount -=1
+                    continue
+
+                if t < 0:
+                    # reduce a symbol on the stack, emit a production
+                    p = prod[-t]
+                    pname = p.name
+                    plen  = p.len
+
+                    # Get production function
+                    sym = YaccSymbol()
+                    sym.type = pname       # Production name
+                    sym.value = None
+
+                    if plen:
+                        targ = symstack[-plen-1:]
+                        targ[0] = sym
+
+                        # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+                        # The code enclosed in this section is duplicated 
+                        # below as a performance optimization.  Make sure
+                        # changes get made in both locations.
+
+                        pslice.slice = targ
+                        
+                        try:
+                            # Call the grammar rule with our special slice object
+                            del symstack[-plen:]
+                            del statestack[-plen:]
+                            p.callable(pslice)
+                            symstack.append(sym)
+                            state = goto[statestack[-1]][pname]
+                            statestack.append(state)
+                        except SyntaxError:
+                            # If an error was set. Enter error recovery state
+                            lookaheadstack.append(lookahead)
+                            symstack.pop()
+                            statestack.pop()
+                            state = statestack[-1]
+                            sym.type = 'error'
+                            lookahead = sym
+                            errorcount = error_count
+                            self.errorok = 0
+                        continue
+                        # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+    
+                    else:
+
+                        targ = [ sym ]
+
+                        # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+                        # The code enclosed in this section is duplicated 
+                        # above as a performance optimization.  Make sure
+                        # changes get made in both locations.
+
+                        pslice.slice = targ
+
+                        try:
+                            # Call the grammar rule with our special slice object
+                            p.callable(pslice)
+                            symstack.append(sym)
+                            state = goto[statestack[-1]][pname]
+                            statestack.append(state)
+                        except SyntaxError:
+                            # If an error was set. Enter error recovery state
+                            lookaheadstack.append(lookahead)
+                            symstack.pop()
+                            statestack.pop()
+                            state = statestack[-1]
+                            sym.type = 'error'
+                            lookahead = sym
+                            errorcount = error_count
+                            self.errorok = 0
+                        continue
+                        # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+                if t == 0:
+                    n = symstack[-1]
+                    return getattr(n,"value",None)
+
+            if t == None:
+
+                # We have some kind of parsing error here.  To handle
+                # this, we are going to push the current token onto
+                # the tokenstack and replace it with an 'error' token.
+                # If there are any synchronization rules, they may
+                # catch it.
+                #
+                # In addition to pushing the error token, we call call
+                # the user defined p_error() function if this is the
+                # first syntax error.  This function is only called if
+                # errorcount == 0.
+                if errorcount == 0 or self.errorok:
+                    errorcount = error_count
+                    self.errorok = 0
+                    errtoken = lookahead
+                    if errtoken.type == '$end':
+                        errtoken = None               # End of file!
+                    if self.errorfunc:
+                        global errok,token,restart
+                        errok = self.errok        # Set some special functions available in error recovery
+                        token = get_token
+                        restart = self.restart
+                        if errtoken and not hasattr(errtoken,'lexer'):
+                            errtoken.lexer = lexer
+                        tok = self.errorfunc(errtoken)
+                        del errok, token, restart   # Delete special functions
+
+                        if self.errorok:
+                            # User must have done some kind of panic
+                            # mode recovery on their own.  The
+                            # returned token is the next lookahead
+                            lookahead = tok
+                            errtoken = None
+                            continue
+                    else:
+                        if errtoken:
+                            if hasattr(errtoken,"lineno"): lineno = lookahead.lineno
+                            else: lineno = 0
+                            if lineno:
+                                sys.stderr.write("yacc: Syntax error at line %d, token=%s\n" % (lineno, errtoken.type))
+                            else:
+                                sys.stderr.write("yacc: Syntax error, token=%s" % errtoken.type)
+                        else:
+                            sys.stderr.write("yacc: Parse error in input. EOF\n")
+                            return
+
+                else:
+                    errorcount = error_count
+
+                # case 1:  the statestack only has 1 entry on it.  If we're in this state, the
+                # entire parse has been rolled back and we're completely hosed.   The token is
+                # discarded and we just keep going.
+
+                if len(statestack) <= 1 and lookahead.type != '$end':
+                    lookahead = None
+                    errtoken = None
+                    state = 0
+                    # Nuke the pushback stack
+                    del lookaheadstack[:]
+                    continue
+
+                # case 2: the statestack has a couple of entries on it, but we're
+                # at the end of the file. nuke the top entry and generate an error token
+
+                # Start nuking entries on the stack
+                if lookahead.type == '$end':
+                    # Whoa. We're really hosed here. Bail out
+                    return
+
+                if lookahead.type != 'error':
+                    sym = symstack[-1]
+                    if sym.type == 'error':
+                        # Hmmm. Error is on top of stack, we'll just nuke input
+                        # symbol and continue
+                        lookahead = None
+                        continue
+                    t = YaccSymbol()
+                    t.type = 'error'
+                    if hasattr(lookahead,"lineno"):
+                        t.lineno = lookahead.lineno
+                    t.value = lookahead
+                    lookaheadstack.append(lookahead)
+                    lookahead = t
+                else:
+                    symstack.pop()
+                    statestack.pop()
+                    state = statestack[-1]       # Potential bug fix
+
+                continue
+
+            # Call an error function here
+            raise RuntimeError("yacc: internal parser error!!!\n")
+
+# -----------------------------------------------------------------------------
+#                          === Grammar Representation ===
+#
+# The following functions, classes, and variables are used to represent and
+# manipulate the rules that make up a grammar. 
+# -----------------------------------------------------------------------------
+
+import re
+
+# regex matching identifiers
+_is_identifier = re.compile(r'^[a-zA-Z0-9_-]+$')
+
+# -----------------------------------------------------------------------------
+# class Production:
+#
+# This class stores the raw information about a single production or grammar rule.
+# A grammar rule refers to a specification such as this:
+#
+#       expr : expr PLUS term 
+#
+# Here are the basic attributes defined on all productions
+#
+#       name     - Name of the production.  For example 'expr'
+#       prod     - A list of symbols on the right side ['expr','PLUS','term']
+#       prec     - Production precedence level
+#       number   - Production number.
+#       func     - Function that executes on reduce
+#       file     - File where production function is defined
+#       lineno   - Line number where production function is defined
+#
+# The following attributes are defined or optional.
+#
+#       len       - Length of the production (number of symbols on right hand side)
+#       usyms     - Set of unique symbols found in the production
+# -----------------------------------------------------------------------------
+
+class Production(object):
+    reduced = 0
+    def __init__(self,number,name,prod,precedence=('right',0),func=None,file='',line=0):
+        self.name     = name
+        self.prod     = tuple(prod)
+        self.number   = number
+        self.func     = func
+        self.callable = None
+        self.file     = file
+        self.line     = line
+        self.prec     = precedence
+
+        # Internal settings used during table construction
+        
+        self.len  = len(self.prod)   # Length of the production
+
+        # Create a list of unique production symbols used in the production
+        self.usyms = [ ]             
+        for s in self.prod:
+            if s not in self.usyms:
+                self.usyms.append(s)
+
+        # List of all LR items for the production
+        self.lr_items = []
+        self.lr_next = None
+
+        # Create a string representation
+        if self.prod:
+            self.str = "%s -> %s" % (self.name," ".join(self.prod))
+        else:
+            self.str = "%s -> <empty>" % self.name
+
+    def __str__(self):
+        return self.str
+
+    def __repr__(self):
+        return "Production("+str(self)+")"
+
+    def __len__(self):
+        return len(self.prod)
+
+    def __nonzero__(self):
+        return 1
+
+    def __getitem__(self,index):
+        return self.prod[index]
+            
+    # Return the nth lr_item from the production (or None if at the end)
+    def lr_item(self,n):
+        if n > len(self.prod): return None
+        p = LRItem(self,n)
+
+        # Precompute the list of productions immediately following.  Hack. Remove later
+        try:
+            p.lr_after = Prodnames[p.prod[n+1]]
+        except (IndexError,KeyError):
+            p.lr_after = []
+        try:
+            p.lr_before = p.prod[n-1]
+        except IndexError:
+            p.lr_before = None
+
+        return p
+    
+    # Bind the production function name to a callable
+    def bind(self,pdict):
+        if self.func:
+            self.callable = pdict[self.func]
+
+# This class serves as a minimal standin for Production objects when
+# reading table data from files.   It only contains information
+# actually used by the LR parsing engine, plus some additional
+# debugging information.
+class MiniProduction(object):
+    def __init__(self,str,name,len,func,file,line):
+        self.name     = name
+        self.len      = len
+        self.func     = func
+        self.callable = None
+        self.file     = file
+        self.line     = line
+        self.str      = str
+    def __str__(self):
+        return self.str
+    def __repr__(self):
+        return "MiniProduction(%s)" % self.str
+
+    # Bind the production function name to a callable
+    def bind(self,pdict):
+        if self.func:
+            self.callable = pdict[self.func]
+
+
+# -----------------------------------------------------------------------------
+# class LRItem
+#
+# This class represents a specific stage of parsing a production rule.  For
+# example: 
+#
+#       expr : expr . PLUS term 
+#
+# In the above, the "." represents the current location of the parse.  Here
+# basic attributes:
+#
+#       name       - Name of the production.  For example 'expr'
+#       prod       - A list of symbols on the right side ['expr','.', 'PLUS','term']
+#       number     - Production number.
+#
+#       lr_next      Next LR item. Example, if we are ' expr -> expr . PLUS term'
+#                    then lr_next refers to 'expr -> expr PLUS . term'
+#       lr_index   - LR item index (location of the ".") in the prod list.
+#       lookaheads - LALR lookahead symbols for this item
+#       len        - Length of the production (number of symbols on right hand side)
+#       lr_after    - List of all productions that immediately follow
+#       lr_before   - Grammar symbol immediately before
+# -----------------------------------------------------------------------------
+
+class LRItem(object):
+    def __init__(self,p,n):
+        self.name       = p.name
+        self.prod       = list(p.prod)
+        self.number     = p.number
+        self.lr_index   = n
+        self.lookaheads = { }
+        self.prod.insert(n,".")
+        self.prod       = tuple(self.prod)
+        self.len        = len(self.prod)
+        self.usyms      = p.usyms
+
+    def __str__(self):
+        if self.prod:
+            s = "%s -> %s" % (self.name," ".join(self.prod))
+        else:
+            s = "%s -> <empty>" % self.name
+        return s
+
+    def __repr__(self):
+        return "LRItem("+str(self)+")"
+
+# -----------------------------------------------------------------------------
+# rightmost_terminal()
+#
+# Return the rightmost terminal from a list of symbols.  Used in add_production()
+# -----------------------------------------------------------------------------
+def rightmost_terminal(symbols, terminals):
+    i = len(symbols) - 1
+    while i >= 0:
+        if symbols[i] in terminals:
+            return symbols[i]
+        i -= 1
+    return None
+
+# -----------------------------------------------------------------------------
+#                           === GRAMMAR CLASS ===
+#
+# The following class represents the contents of the specified grammar along
+# with various computed properties such as first sets, follow sets, LR items, etc.
+# This data is used for critical parts of the table generation process later.
+# -----------------------------------------------------------------------------
+
+class GrammarError(YaccError): pass
+
+class Grammar(object):
+    def __init__(self,terminals):
+        self.Productions  = [None]  # A list of all of the productions.  The first
+                                    # entry is always reserved for the purpose of
+                                    # building an augmented grammar
+
+        self.Prodnames    = { }     # A dictionary mapping the names of nonterminals to a list of all
+                                    # productions of that nonterminal.
+
+        self.Prodmap      = { }     # A dictionary that is only used to detect duplicate
+                                    # productions.
+
+        self.Terminals    = { }     # A dictionary mapping the names of terminal symbols to a
+                                    # list of the rules where they are used.
+
+        for term in terminals:
+            self.Terminals[term] = []
+
+        self.Terminals['error'] = []
+
+        self.Nonterminals = { }     # A dictionary mapping names of nonterminals to a list
+                                    # of rule numbers where they are used.
+
+        self.First        = { }     # A dictionary of precomputed FIRST(x) symbols
+
+        self.Follow       = { }     # A dictionary of precomputed FOLLOW(x) symbols
+
+        self.Precedence   = { }     # Precedence rules for each terminal. Contains tuples of the
+                                    # form ('right',level) or ('nonassoc', level) or ('left',level)
+
+        self.UsedPrecedence = { }   # Precedence rules that were actually used by the grammer.
+                                    # This is only used to provide error checking and to generate
+                                    # a warning about unused precedence rules.
+
+        self.Start = None           # Starting symbol for the grammar
+
+
+    def __len__(self):
+        return len(self.Productions)
+
+    def __getitem__(self,index):
+        return self.Productions[index]
+
+    # -----------------------------------------------------------------------------
+    # set_precedence()
+    #
+    # Sets the precedence for a given terminal. assoc is the associativity such as
+    # 'left','right', or 'nonassoc'.  level is a numeric level.
+    #
+    # -----------------------------------------------------------------------------
+
+    def set_precedence(self,term,assoc,level):
+        assert self.Productions == [None],"Must call set_precedence() before add_production()"
+        if term in self.Precedence:
+            raise GrammarError("Precedence already specified for terminal '%s'" % term)
+        if assoc not in ['left','right','nonassoc']:
+            raise GrammarError("Associativity must be one of 'left','right', or 'nonassoc'")
+        self.Precedence[term] = (assoc,level)
+    # -----------------------------------------------------------------------------
+    # add_production()
+    #
+    # Given an action function, this function assembles a production rule and
+    # computes its precedence level.
+    #
+    # The production rule is supplied as a list of symbols.   For example,
+    # a rule such as 'expr : expr PLUS term' has a production name of 'expr' and
+    # symbols ['expr','PLUS','term'].
+    #
+    # Precedence is determined by the precedence of the right-most non-terminal
+    # or the precedence of a terminal specified by %prec.
+    #
+    # A variety of error checks are performed to make sure production symbols
+    # are valid and that %prec is used correctly.
+    # -----------------------------------------------------------------------------
+
+    def add_production(self,prodname,syms,func=None,file='',line=0):
+
+        if prodname in self.Terminals:
+            raise GrammarError("%s:%d: Illegal rule name '%s'. Already defined as a token" % (file,line,prodname))
+        if prodname == 'error':
+            raise GrammarError("%s:%d: Illegal rule name '%s'. error is a reserved word" % (file,line,prodname))
+        if not _is_identifier.match(prodname):
+            raise GrammarError("%s:%d: Illegal rule name '%s'" % (file,line,prodname))
+
+        # Look for literal tokens 
+        for n,s in enumerate(syms):
+            if s[0] in "'\"":
+                 try:
+                     c = eval(s)
+                     if (len(c) > 1):
+                          raise GrammarError("%s:%d: Literal token %s in rule '%s' may only be a single character" % (file,line,s, prodname))
+                     if not c in self.Terminals:
+                          self.Terminals[c] = []
+                     syms[n] = c
+                     continue
+                 except SyntaxError:
+                     pass
+            if not _is_identifier.match(s) and s != '%prec':
+                raise GrammarError("%s:%d: Illegal name '%s' in rule '%s'" % (file,line,s, prodname))
+        
+        # Determine the precedence level
+        if '%prec' in syms:
+            if syms[-1] == '%prec':
+                raise GrammarError("%s:%d: Syntax error. Nothing follows %%prec" % (file,line))
+            if syms[-2] != '%prec':
+                raise GrammarError("%s:%d: Syntax error. %%prec can only appear at the end of a grammar rule" % (file,line))
+            precname = syms[-1]
+            prodprec = self.Precedence.get(precname,None)
+            if not prodprec:
+                raise GrammarError("%s:%d: Nothing known about the precedence of '%s'" % (file,line,precname))
+            else:
+                self.UsedPrecedence[precname] = 1
+            del syms[-2:]     # Drop %prec from the rule
+        else:
+            # If no %prec, precedence is determined by the rightmost terminal symbol
+            precname = rightmost_terminal(syms,self.Terminals)
+            prodprec = self.Precedence.get(precname,('right',0)) 
+            
+        # See if the rule is already in the rulemap
+        map = "%s -> %s" % (prodname,syms)
+        if map in self.Prodmap:
+            m = self.Prodmap[map]
+            raise GrammarError("%s:%d: Duplicate rule %s. " % (file,line, m) +
+                               "Previous definition at %s:%d" % (m.file, m.line))
+
+        # From this point on, everything is valid.  Create a new Production instance
+        pnumber  = len(self.Productions)
+        if not prodname in self.Nonterminals:
+            self.Nonterminals[prodname] = [ ]
+
+        # Add the production number to Terminals and Nonterminals
+        for t in syms:
+            if t in self.Terminals:
+                self.Terminals[t].append(pnumber)
+            else:
+                if not t in self.Nonterminals:
+                    self.Nonterminals[t] = [ ]
+                self.Nonterminals[t].append(pnumber)
+
+        # Create a production and add it to the list of productions
+        p = Production(pnumber,prodname,syms,prodprec,func,file,line)
+        self.Productions.append(p)
+        self.Prodmap[map] = p
+
+        # Add to the global productions list
+        try:
+            self.Prodnames[prodname].append(p)
+        except KeyError:
+            self.Prodnames[prodname] = [ p ]
+        return 0
+
+    # -----------------------------------------------------------------------------
+    # set_start()
+    #
+    # Sets the starting symbol and creates the augmented grammar.  Production 
+    # rule 0 is S' -> start where start is the start symbol.
+    # -----------------------------------------------------------------------------
+
+    def set_start(self,start=None):
+        if not start:
+            start = self.Productions[1].name
+        if start not in self.Nonterminals:
+            raise GrammarError("start symbol %s undefined" % start)
+        self.Productions[0] = Production(0,"S'",[start])
+        self.Nonterminals[start].append(0)
+        self.Start = start
+
+    # -----------------------------------------------------------------------------
+    # find_unreachable()
+    #
+    # Find all of the nonterminal symbols that can't be reached from the starting
+    # symbol.  Returns a list of nonterminals that can't be reached.
+    # -----------------------------------------------------------------------------
+
+    def find_unreachable(self):
+        
+        # Mark all symbols that are reachable from a symbol s
+        def mark_reachable_from(s):
+            if reachable[s]:
+                # We've already reached symbol s.
+                return
+            reachable[s] = 1
+            for p in self.Prodnames.get(s,[]):
+                for r in p.prod:
+                    mark_reachable_from(r)
+
+        reachable   = { }
+        for s in list(self.Terminals) + list(self.Nonterminals):
+            reachable[s] = 0
+
+        mark_reachable_from( self.Productions[0].prod[0] )
+
+        return [s for s in list(self.Nonterminals)
+                        if not reachable[s]]
+    
+    # -----------------------------------------------------------------------------
+    # infinite_cycles()
+    #
+    # This function looks at the various parsing rules and tries to detect
+    # infinite recursion cycles (grammar rules where there is no possible way
+    # to derive a string of only terminals).
+    # -----------------------------------------------------------------------------
+
+    def infinite_cycles(self):
+        terminates = {}
+
+        # Terminals:
+        for t in self.Terminals:
+            terminates[t] = 1
+
+        terminates['$end'] = 1
+
+        # Nonterminals:
+
+        # Initialize to false:
+        for n in self.Nonterminals:
+            terminates[n] = 0
+
+        # Then propagate termination until no change:
+        while 1:
+            some_change = 0
+            for (n,pl) in self.Prodnames.items():
+                # Nonterminal n terminates iff any of its productions terminates.
+                for p in pl:
+                    # Production p terminates iff all of its rhs symbols terminate.
+                    for s in p.prod:
+                        if not terminates[s]:
+                            # The symbol s does not terminate,
+                            # so production p does not terminate.
+                            p_terminates = 0
+                            break
+                    else:
+                        # didn't break from the loop,
+                        # so every symbol s terminates
+                        # so production p terminates.
+                        p_terminates = 1
+
+                    if p_terminates:
+                        # symbol n terminates!
+                        if not terminates[n]:
+                            terminates[n] = 1
+                            some_change = 1
+                        # Don't need to consider any more productions for this n.
+                        break
+
+            if not some_change:
+                break
+
+        infinite = []
+        for (s,term) in terminates.items():
+            if not term:
+                if not s in self.Prodnames and not s in self.Terminals and s != 'error':
+                    # s is used-but-not-defined, and we've already warned of that,
+                    # so it would be overkill to say that it's also non-terminating.
+                    pass
+                else:
+                    infinite.append(s)
+
+        return infinite
+
+
+    # -----------------------------------------------------------------------------
+    # undefined_symbols()
+    #
+    # Find all symbols that were used the grammar, but not defined as tokens or
+    # grammar rules.  Returns a list of tuples (sym, prod) where sym in the symbol
+    # and prod is the production where the symbol was used. 
+    # -----------------------------------------------------------------------------
+    def undefined_symbols(self):
+        result = []
+        for p in self.Productions:
+            if not p: continue
+
+            for s in p.prod:
+                if not s in self.Prodnames and not s in self.Terminals and s != 'error':
+                    result.append((s,p))
+        return result
+
+    # -----------------------------------------------------------------------------
+    # unused_terminals()
+    #
+    # Find all terminals that were defined, but not used by the grammar.  Returns
+    # a list of all symbols.
+    # -----------------------------------------------------------------------------
+    def unused_terminals(self):
+        unused_tok = []
+        for s,v in self.Terminals.items():
+            if s != 'error' and not v:
+                unused_tok.append(s)
+
+        return unused_tok
+
+    # ------------------------------------------------------------------------------
+    # unused_rules()
+    #
+    # Find all grammar rules that were defined,  but not used (maybe not reachable)
+    # Returns a list of productions.
+    # ------------------------------------------------------------------------------
+
+    def unused_rules(self):
+        unused_prod = []
+        for s,v in self.Nonterminals.items():
+            if not v:
+                p = self.Prodnames[s][0]
+                unused_prod.append(p)
+        return unused_prod
+
+    # -----------------------------------------------------------------------------
+    # unused_precedence()
+    #
+    # Returns a list of tuples (term,precedence) corresponding to precedence
+    # rules that were never used by the grammar.  term is the name of the terminal
+    # on which precedence was applied and precedence is a string such as 'left' or
+    # 'right' corresponding to the type of precedence. 
+    # -----------------------------------------------------------------------------
+
+    def unused_precedence(self):
+        unused = []
+        for termname in self.Precedence:
+            if not (termname in self.Terminals or termname in self.UsedPrecedence):
+                unused.append((termname,self.Precedence[termname][0]))
+                
+        return unused
+
+    # -------------------------------------------------------------------------
+    # _first()
+    #
+    # Compute the value of FIRST1(beta) where beta is a tuple of symbols.
+    #
+    # During execution of compute_first1, the result may be incomplete.
+    # Afterward (e.g., when called from compute_follow()), it will be complete.
+    # -------------------------------------------------------------------------
+    def _first(self,beta):
+
+        # We are computing First(x1,x2,x3,...,xn)
+        result = [ ]
+        for x in beta:
+            x_produces_empty = 0
+
+            # Add all the non-<empty> symbols of First[x] to the result.
+            for f in self.First[x]:
+                if f == '<empty>':
+                    x_produces_empty = 1
+                else:
+                    if f not in result: result.append(f)
+
+            if x_produces_empty:
+                # We have to consider the next x in beta,
+                # i.e. stay in the loop.
+                pass
+            else:
+                # We don't have to consider any further symbols in beta.
+                break
+        else:
+            # There was no 'break' from the loop,
+            # so x_produces_empty was true for all x in beta,
+            # so beta produces empty as well.
+            result.append('<empty>')
+
+        return result
+
+    # -------------------------------------------------------------------------
+    # compute_first()
+    #
+    # Compute the value of FIRST1(X) for all symbols
+    # -------------------------------------------------------------------------
+    def compute_first(self):
+        if self.First:
+            return self.First
+
+        # Terminals:
+        for t in self.Terminals:
+            self.First[t] = [t]
+
+        self.First['$end'] = ['$end']
+
+        # Nonterminals:
+
+        # Initialize to the empty set:
+        for n in self.Nonterminals:
+            self.First[n] = []
+
+        # Then propagate symbols until no change:
+        while 1:
+            some_change = 0
+            for n in self.Nonterminals:
+                for p in self.Prodnames[n]:
+                    for f in self._first(p.prod):
+                        if f not in self.First[n]:
+                            self.First[n].append( f )
+                            some_change = 1
+            if not some_change:
+                break
+        
+        return self.First
+
+    # ---------------------------------------------------------------------
+    # compute_follow()
+    #
+    # Computes all of the follow sets for every non-terminal symbol.  The
+    # follow set is the set of all symbols that might follow a given
+    # non-terminal.  See the Dragon book, 2nd Ed. p. 189.
+    # ---------------------------------------------------------------------
+    def compute_follow(self,start=None):
+        # If already computed, return the result
+        if self.Follow:
+            return self.Follow
+
+        # If first sets not computed yet, do that first.
+        if not self.First:
+            self.compute_first()
+
+        # Add '$end' to the follow list of the start symbol
+        for k in self.Nonterminals:
+            self.Follow[k] = [ ]
+
+        if not start:
+            start = self.Productions[1].name
+
+        self.Follow[start] = [ '$end' ]
+
+        while 1:
+            didadd = 0
+            for p in self.Productions[1:]:
+                # Here is the production set
+                for i in range(len(p.prod)):
+                    B = p.prod[i]
+                    if B in self.Nonterminals:
+                        # Okay. We got a non-terminal in a production
+                        fst = self._first(p.prod[i+1:])
+                        hasempty = 0
+                        for f in fst:
+                            if f != '<empty>' and f not in self.Follow[B]:
+                                self.Follow[B].append(f)
+                                didadd = 1
+                            if f == '<empty>':
+                                hasempty = 1
+                        if hasempty or i == (len(p.prod)-1):
+                            # Add elements of follow(a) to follow(b)
+                            for f in self.Follow[p.name]:
+                                if f not in self.Follow[B]:
+                                    self.Follow[B].append(f)
+                                    didadd = 1
+            if not didadd: break
+        return self.Follow
+
+
+    # -----------------------------------------------------------------------------
+    # build_lritems()
+    #
+    # This function walks the list of productions and builds a complete set of the
+    # LR items.  The LR items are stored in two ways:  First, they are uniquely
+    # numbered and placed in the list _lritems.  Second, a linked list of LR items
+    # is built for each production.  For example:
+    #
+    #   E -> E PLUS E
+    #
+    # Creates the list
+    #
+    #  [E -> . E PLUS E, E -> E . PLUS E, E -> E PLUS . E, E -> E PLUS E . ]
+    # -----------------------------------------------------------------------------
+
+    def build_lritems(self):
+        for p in self.Productions:
+            lastlri = p
+            i = 0
+            lr_items = []
+            while 1:
+                if i > len(p):
+                    lri = None
+                else:
+                    lri = LRItem(p,i)
+                    # Precompute the list of productions immediately following
+                    try:
+                        lri.lr_after = self.Prodnames[lri.prod[i+1]]
+                    except (IndexError,KeyError):
+                        lri.lr_after = []
+                    try:
+                        lri.lr_before = lri.prod[i-1]
+                    except IndexError:
+                        lri.lr_before = None
+
+                lastlri.lr_next = lri
+                if not lri: break
+                lr_items.append(lri)
+                lastlri = lri
+                i += 1
+            p.lr_items = lr_items
+
+# -----------------------------------------------------------------------------
+#                            == Class LRTable ==
+#
+# This basic class represents a basic table of LR parsing information.  
+# Methods for generating the tables are not defined here.  They are defined
+# in the derived class LRGeneratedTable.
+# -----------------------------------------------------------------------------
+
+class VersionError(YaccError): pass
+
+class LRTable(object):
+    def __init__(self):
+        self.lr_action = None
+        self.lr_goto = None
+        self.lr_productions = None
+        self.lr_method = None
+
+    def read_table(self,module):
+        if isinstance(module,types.ModuleType):
+            parsetab = module
+        else:
+            if sys.version_info[0] < 3:
+                exec("import %s as parsetab" % module)
+            else:
+                env = { }
+                exec("import %s as parsetab" % module, env, env)
+                parsetab = env['parsetab']
+
+        if parsetab._tabversion != __tabversion__:
+            raise VersionError("yacc table file version is out of date")
+
+        self.lr_action = parsetab._lr_action
+        self.lr_goto = parsetab._lr_goto
+
+        self.lr_productions = []
+        for p in parsetab._lr_productions:
+            self.lr_productions.append(MiniProduction(*p))
+
+        self.lr_method = parsetab._lr_method
+        return parsetab._lr_signature
+
+    def read_pickle(self,filename):
+        try:
+            import cPickle as pickle
+        except ImportError:
+            import pickle
+
+        in_f = open(filename,"rb")
+
+        tabversion = pickle.load(in_f)
+        if tabversion != __tabversion__:
+            raise VersionError("yacc table file version is out of date")
+        self.lr_method = pickle.load(in_f)
+        signature      = pickle.load(in_f)
+        self.lr_action = pickle.load(in_f)
+        self.lr_goto   = pickle.load(in_f)
+        productions    = pickle.load(in_f)
+
+        self.lr_productions = []
+        for p in productions:
+            self.lr_productions.append(MiniProduction(*p))
+
+        in_f.close()
+        return signature
+
+    # Bind all production function names to callable objects in pdict
+    def bind_callables(self,pdict):
+        for p in self.lr_productions:
+            p.bind(pdict)
+    
+# -----------------------------------------------------------------------------
+#                           === LR Generator ===
+#
+# The following classes and functions are used to generate LR parsing tables on 
+# a grammar.
+# -----------------------------------------------------------------------------
+
+# -----------------------------------------------------------------------------
+# digraph()
+# traverse()
+#
+# The following two functions are used to compute set valued functions
+# of the form:
+#
+#     F(x) = F'(x) U U{F(y) | x R y}
+#
+# This is used to compute the values of Read() sets as well as FOLLOW sets
+# in LALR(1) generation.
+#
+# Inputs:  X    - An input set
+#          R    - A relation
+#          FP   - Set-valued function
+# ------------------------------------------------------------------------------
+
+def digraph(X,R,FP):
+    N = { }
+    for x in X:
+       N[x] = 0
+    stack = []
+    F = { }
+    for x in X:
+        if N[x] == 0: traverse(x,N,stack,F,X,R,FP)
+    return F
+
+def traverse(x,N,stack,F,X,R,FP):
+    stack.append(x)
+    d = len(stack)
+    N[x] = d
+    F[x] = FP(x)             # F(X) <- F'(x)
+
+    rel = R(x)               # Get y's related to x
+    for y in rel:
+        if N[y] == 0:
+             traverse(y,N,stack,F,X,R,FP)
+        N[x] = min(N[x],N[y])
+        for a in F.get(y,[]):
+            if a not in F[x]: F[x].append(a)
+    if N[x] == d:
+       N[stack[-1]] = MAXINT
+       F[stack[-1]] = F[x]
+       element = stack.pop()
+       while element != x:
+           N[stack[-1]] = MAXINT
+           F[stack[-1]] = F[x]
+           element = stack.pop()
+
+class LALRError(YaccError): pass
+
+# -----------------------------------------------------------------------------
+#                             == LRGeneratedTable ==
+#
+# This class implements the LR table generation algorithm.  There are no
+# public methods except for write()
+# -----------------------------------------------------------------------------
+
+class LRGeneratedTable(LRTable):
+    def __init__(self,grammar,method='LALR',log=None):
+        if method not in ['SLR','LALR']:
+            raise LALRError("Unsupported method %s" % method)
+
+        self.grammar = grammar
+        self.lr_method = method
+
+        # Set up the logger
+        if not log:
+            log = NullLogger()
+        self.log = log
+
+        # Internal attributes
+        self.lr_action     = {}        # Action table
+        self.lr_goto       = {}        # Goto table
+        self.lr_productions  = grammar.Productions    # Copy of grammar Production array
+        self.lr_goto_cache = {}        # Cache of computed gotos
+        self.lr0_cidhash   = {}        # Cache of closures
+
+        self._add_count    = 0         # Internal counter used to detect cycles
+
+        # Diagonistic information filled in by the table generator
+        self.sr_conflict   = 0
+        self.rr_conflict   = 0
+        self.conflicts     = []        # List of conflicts
+
+        self.sr_conflicts  = []
+        self.rr_conflicts  = []
+
+        # Build the tables
+        self.grammar.build_lritems()
+        self.grammar.compute_first()
+        self.grammar.compute_follow()
+        self.lr_parse_table()
+
+    # Compute the LR(0) closure operation on I, where I is a set of LR(0) items.
+
+    def lr0_closure(self,I):
+        self._add_count += 1
+
+        # Add everything in I to J
+        J = I[:]
+        didadd = 1
+        while didadd:
+            didadd = 0
+            for j in J:
+                for x in j.lr_after:
+                    if getattr(x,"lr0_added",0) == self._add_count: continue
+                    # Add B --> .G to J
+                    J.append(x.lr_next)
+                    x.lr0_added = self._add_count
+                    didadd = 1
+
+        return J
+
+    # Compute the LR(0) goto function goto(I,X) where I is a set
+    # of LR(0) items and X is a grammar symbol.   This function is written
+    # in a way that guarantees uniqueness of the generated goto sets
+    # (i.e. the same goto set will never be returned as two different Python
+    # objects).  With uniqueness, we can later do fast set comparisons using
+    # id(obj) instead of element-wise comparison.
+
+    def lr0_goto(self,I,x):
+        # First we look for a previously cached entry
+        g = self.lr_goto_cache.get((id(I),x),None)
+        if g: return g
+
+        # Now we generate the goto set in a way that guarantees uniqueness
+        # of the result
+
+        s = self.lr_goto_cache.get(x,None)
+        if not s:
+            s = { }
+            self.lr_goto_cache[x] = s
+
+        gs = [ ]
+        for p in I:
+            n = p.lr_next
+            if n and n.lr_before == x:
+                s1 = s.get(id(n),None)
+                if not s1:
+                    s1 = { }
+                    s[id(n)] = s1
+                gs.append(n)
+                s = s1
+        g = s.get('$end',None)
+        if not g:
+            if gs:
+                g = self.lr0_closure(gs)
+                s['$end'] = g
+            else:
+                s['$end'] = gs
+        self.lr_goto_cache[(id(I),x)] = g
+        return g
+
+    # Compute the LR(0) sets of item function
+    def lr0_items(self):
+
+        C = [ self.lr0_closure([self.grammar.Productions[0].lr_next]) ]
+        i = 0
+        for I in C:
+            self.lr0_cidhash[id(I)] = i
+            i += 1
+
+        # Loop over the items in C and each grammar symbols
+        i = 0
+        while i < len(C):
+            I = C[i]
+            i += 1
+
+            # Collect all of the symbols that could possibly be in the goto(I,X) sets
+            asyms = { }
+            for ii in I:
+                for s in ii.usyms:
+                    asyms[s] = None
+
+            for x in asyms:
+                g = self.lr0_goto(I,x)
+                if not g:  continue
+                if id(g) in self.lr0_cidhash: continue
+                self.lr0_cidhash[id(g)] = len(C)
+                C.append(g)
+
+        return C
+
+    # -----------------------------------------------------------------------------
+    #                       ==== LALR(1) Parsing ====
+    #
+    # LALR(1) parsing is almost exactly the same as SLR except that instead of
+    # relying upon Follow() sets when performing reductions, a more selective
+    # lookahead set that incorporates the state of the LR(0) machine is utilized.
+    # Thus, we mainly just have to focus on calculating the lookahead sets.
+    #
+    # The method used here is due to DeRemer and Pennelo (1982).
+    #
+    # DeRemer, F. L., and T. J. Pennelo: "Efficient Computation of LALR(1)
+    #     Lookahead Sets", ACM Transactions on Programming Languages and Systems,
+    #     Vol. 4, No. 4, Oct. 1982, pp. 615-649
+    #
+    # Further details can also be found in:
+    #
+    #  J. Tremblay and P. Sorenson, "The Theory and Practice of Compiler Writing",
+    #      McGraw-Hill Book Company, (1985).
+    #
+    # -----------------------------------------------------------------------------
+
+    # -----------------------------------------------------------------------------
+    # compute_nullable_nonterminals()
+    #
+    # Creates a dictionary containing all of the non-terminals that might produce
+    # an empty production.
+    # -----------------------------------------------------------------------------
+
+    def compute_nullable_nonterminals(self):
+        nullable = {}
+        num_nullable = 0
+        while 1:
+           for p in self.grammar.Productions[1:]:
+               if p.len == 0:
+                    nullable[p.name] = 1
+                    continue
+               for t in p.prod:
+                    if not t in nullable: break
+               else:
+                    nullable[p.name] = 1
+           if len(nullable) == num_nullable: break
+           num_nullable = len(nullable)
+        return nullable
+
+    # -----------------------------------------------------------------------------
+    # find_nonterminal_trans(C)
+    #
+    # Given a set of LR(0) items, this functions finds all of the non-terminal
+    # transitions.    These are transitions in which a dot appears immediately before
+    # a non-terminal.   Returns a list of tuples of the form (state,N) where state
+    # is the state number and N is the nonterminal symbol.
+    #
+    # The input C is the set of LR(0) items.
+    # -----------------------------------------------------------------------------
+
+    def find_nonterminal_transitions(self,C):
+         trans = []
+         for state in range(len(C)):
+             for p in C[state]:
+                 if p.lr_index < p.len - 1:
+                      t = (state,p.prod[p.lr_index+1])
+                      if t[1] in self.grammar.Nonterminals:
+                            if t not in trans: trans.append(t)
+             state = state + 1
+         return trans
+
+    # -----------------------------------------------------------------------------
+    # dr_relation()
+    #
+    # Computes the DR(p,A) relationships for non-terminal transitions.  The input
+    # is a tuple (state,N) where state is a number and N is a nonterminal symbol.
+    #
+    # Returns a list of terminals.
+    # -----------------------------------------------------------------------------
+
+    def dr_relation(self,C,trans,nullable):
+        dr_set = { }
+        state,N = trans
+        terms = []
+
+        g = self.lr0_goto(C[state],N)
+        for p in g:
+           if p.lr_index < p.len - 1:
+               a = p.prod[p.lr_index+1]
+               if a in self.grammar.Terminals:
+                   if a not in terms: terms.append(a)
+
+        # This extra bit is to handle the start state
+        if state == 0 and N == self.grammar.Productions[0].prod[0]:
+           terms.append('$end')
+
+        return terms
+
+    # -----------------------------------------------------------------------------
+    # reads_relation()
+    #
+    # Computes the READS() relation (p,A) READS (t,C).
+    # -----------------------------------------------------------------------------
+
+    def reads_relation(self,C, trans, empty):
+        # Look for empty transitions
+        rel = []
+        state, N = trans
+
+        g = self.lr0_goto(C[state],N)
+        j = self.lr0_cidhash.get(id(g),-1)
+        for p in g:
+            if p.lr_index < p.len - 1:
+                 a = p.prod[p.lr_index + 1]
+                 if a in empty:
+                      rel.append((j,a))
+
+        return rel
+
+    # -----------------------------------------------------------------------------
+    # compute_lookback_includes()
+    #
+    # Determines the lookback and includes relations
+    #
+    # LOOKBACK:
+    #
+    # This relation is determined by running the LR(0) state machine forward.
+    # For example, starting with a production "N : . A B C", we run it forward
+    # to obtain "N : A B C ."   We then build a relationship between this final
+    # state and the starting state.   These relationships are stored in a dictionary
+    # lookdict.
+    #
+    # INCLUDES:
+    #
+    # Computes the INCLUDE() relation (p,A) INCLUDES (p',B).
+    #
+    # This relation is used to determine non-terminal transitions that occur
+    # inside of other non-terminal transition states.   (p,A) INCLUDES (p', B)
+    # if the following holds:
+    #
+    #       B -> LAT, where T -> epsilon and p' -L-> p
+    #
+    # L is essentially a prefix (which may be empty), T is a suffix that must be
+    # able to derive an empty string.  State p' must lead to state p with the string L.
+    #
+    # -----------------------------------------------------------------------------
+
+    def compute_lookback_includes(self,C,trans,nullable):
+
+        lookdict = {}          # Dictionary of lookback relations
+        includedict = {}       # Dictionary of include relations
+
+        # Make a dictionary of non-terminal transitions
+        dtrans = {}
+        for t in trans:
+            dtrans[t] = 1
+
+        # Loop over all transitions and compute lookbacks and includes
+        for state,N in trans:
+            lookb = []
+            includes = []
+            for p in C[state]:
+                if p.name != N: continue
+
+                # Okay, we have a name match.  We now follow the production all the way
+                # through the state machine until we get the . on the right hand side
+
+                lr_index = p.lr_index
+                j = state
+                while lr_index < p.len - 1:
+                     lr_index = lr_index + 1
+                     t = p.prod[lr_index]
+
+                     # Check to see if this symbol and state are a non-terminal transition
+                     if (j,t) in dtrans:
+                           # Yes.  Okay, there is some chance that this is an includes relation
+                           # the only way to know for certain is whether the rest of the
+                           # production derives empty
+
+                           li = lr_index + 1
+                           while li < p.len:
+                                if p.prod[li] in self.grammar.Terminals: break      # No forget it
+                                if not p.prod[li] in nullable: break
+                                li = li + 1
+                           else:
+                                # Appears to be a relation between (j,t) and (state,N)
+                                includes.append((j,t))
+
+                     g = self.lr0_goto(C[j],t)               # Go to next set
+                     j = self.lr0_cidhash.get(id(g),-1)     # Go to next state
+
+                # When we get here, j is the final state, now we have to locate the production
+                for r in C[j]:
+                     if r.name != p.name: continue
+                     if r.len != p.len:   continue
+                     i = 0
+                     # This look is comparing a production ". A B C" with "A B C ."
+                     while i < r.lr_index:
+                          if r.prod[i] != p.prod[i+1]: break
+                          i = i + 1
+                     else:
+                          lookb.append((j,r))
+            for i in includes:
+                 if not i in includedict: includedict[i] = []
+                 includedict[i].append((state,N))
+            lookdict[(state,N)] = lookb
+
+        return lookdict,includedict
+
+    # -----------------------------------------------------------------------------
+    # compute_read_sets()
+    #
+    # Given a set of LR(0) items, this function computes the read sets.
+    #
+    # Inputs:  C        =  Set of LR(0) items
+    #          ntrans   = Set of nonterminal transitions
+    #          nullable = Set of empty transitions
+    #
+    # Returns a set containing the read sets
+    # -----------------------------------------------------------------------------
+
+    def compute_read_sets(self,C, ntrans, nullable):
+        FP = lambda x: self.dr_relation(C,x,nullable)
+        R =  lambda x: self.reads_relation(C,x,nullable)
+        F = digraph(ntrans,R,FP)
+        return F
+
+    # -----------------------------------------------------------------------------
+    # compute_follow_sets()
+    #
+    # Given a set of LR(0) items, a set of non-terminal transitions, a readset,
+    # and an include set, this function computes the follow sets
+    #
+    # Follow(p,A) = Read(p,A) U U {Follow(p',B) | (p,A) INCLUDES (p',B)}
+    #
+    # Inputs:
+    #            ntrans     = Set of nonterminal transitions
+    #            readsets   = Readset (previously computed)
+    #            inclsets   = Include sets (previously computed)
+    #
+    # Returns a set containing the follow sets
+    # -----------------------------------------------------------------------------
+
+    def compute_follow_sets(self,ntrans,readsets,inclsets):
+         FP = lambda x: readsets[x]
+         R  = lambda x: inclsets.get(x,[])
+         F = digraph(ntrans,R,FP)
+         return F
+
+    # -----------------------------------------------------------------------------
+    # add_lookaheads()
+    #
+    # Attaches the lookahead symbols to grammar rules.
+    #
+    # Inputs:    lookbacks         -  Set of lookback relations
+    #            followset         -  Computed follow set
+    #
+    # This function directly attaches the lookaheads to productions contained
+    # in the lookbacks set
+    # -----------------------------------------------------------------------------
+
+    def add_lookaheads(self,lookbacks,followset):
+        for trans,lb in lookbacks.items():
+            # Loop over productions in lookback
+            for state,p in lb:
+                 if not state in p.lookaheads:
+                      p.lookaheads[state] = []
+                 f = followset.get(trans,[])
+                 for a in f:
+                      if a not in p.lookaheads[state]: p.lookaheads[state].append(a)
+
+    # -----------------------------------------------------------------------------
+    # add_lalr_lookaheads()
+    #
+    # This function does all of the work of adding lookahead information for use
+    # with LALR parsing
+    # -----------------------------------------------------------------------------
+
+    def add_lalr_lookaheads(self,C):
+        # Determine all of the nullable nonterminals
+        nullable = self.compute_nullable_nonterminals()
+
+        # Find all non-terminal transitions
+        trans = self.find_nonterminal_transitions(C)
+
+        # Compute read sets
+        readsets = self.compute_read_sets(C,trans,nullable)
+
+        # Compute lookback/includes relations
+        lookd, included = self.compute_lookback_includes(C,trans,nullable)
+
+        # Compute LALR FOLLOW sets
+        followsets = self.compute_follow_sets(trans,readsets,included)
+
+        # Add all of the lookaheads
+        self.add_lookaheads(lookd,followsets)
+
+    # -----------------------------------------------------------------------------
+    # lr_parse_table()
+    #
+    # This function constructs the parse tables for SLR or LALR
+    # -----------------------------------------------------------------------------
+    def lr_parse_table(self):
+        Productions = self.grammar.Productions
+        Precedence  = self.grammar.Precedence
+        goto   = self.lr_goto         # Goto array
+        action = self.lr_action       # Action array
+        log    = self.log             # Logger for output
+
+        actionp = { }                 # Action production array (temporary)
+        
+        log.info("Parsing method: %s", self.lr_method)
+
+        # Step 1: Construct C = { I0, I1, ... IN}, collection of LR(0) items
+        # This determines the number of states
+
+        C = self.lr0_items()
+
+        if self.lr_method == 'LALR':
+            self.add_lalr_lookaheads(C)
+
+        # Build the parser table, state by state
+        st = 0
+        for I in C:
+            # Loop over each production in I
+            actlist = [ ]              # List of actions
+            st_action  = { }
+            st_actionp = { }
+            st_goto    = { }
+            log.info("")
+            log.info("state %d", st)
+            log.info("")
+            for p in I:
+                log.info("    (%d) %s", p.number, str(p))
+            log.info("")
+
+            for p in I:
+                    if p.len == p.lr_index + 1:
+                        if p.name == "S'":
+                            # Start symbol. Accept!
+                            st_action["$end"] = 0
+                            st_actionp["$end"] = p
+                        else:
+                            # We are at the end of a production.  Reduce!
+                            if self.lr_method == 'LALR':
+                                laheads = p.lookaheads[st]
+                            else:
+                                laheads = self.grammar.Follow[p.name]
+                            for a in laheads:
+                                actlist.append((a,p,"reduce using rule %d (%s)" % (p.number,p)))
+                                r = st_action.get(a,None)
+                                if r is not None:
+                                    # Whoa. Have a shift/reduce or reduce/reduce conflict
+                                    if r > 0:
+                                        # Need to decide on shift or reduce here
+                                        # By default we favor shifting. Need to add
+                                        # some precedence rules here.
+                                        sprec,slevel = Productions[st_actionp[a].number].prec
+                                        rprec,rlevel = Precedence.get(a,('right',0))
+                                        if (slevel < rlevel) or ((slevel == rlevel) and (rprec == 'left')):
+                                            # We really need to reduce here.
+                                            st_action[a] = -p.number
+                                            st_actionp[a] = p
+                                            if not slevel and not rlevel:
+                                                log.info("  ! shift/reduce conflict for %s resolved as reduce",a)
+                                                self.sr_conflicts.append((st,a,'reduce'))
+                                            Productions[p.number].reduced += 1
+                                        elif (slevel == rlevel) and (rprec == 'nonassoc'):
+                                            st_action[a] = None
+                                        else:
+                                            # Hmmm. Guess we'll keep the shift
+                                            if not rlevel:
+                                                log.info("  ! shift/reduce conflict for %s resolved as shift",a)
+                                                self.sr_conflicts.append((st,a,'shift'))
+                                    elif r < 0:
+                                        # Reduce/reduce conflict.   In this case, we favor the rule
+                                        # that was defined first in the grammar file
+                                        oldp = Productions[-r]
+                                        pp = Productions[p.number]
+                                        if oldp.line > pp.line:
+                                            st_action[a] = -p.number
+                                            st_actionp[a] = p
+                                            chosenp,rejectp = pp,oldp
+                                            Productions[p.number].reduced += 1
+                                            Productions[oldp.number].reduced -= 1
+                                        else:
+                                            chosenp,rejectp = oldp,pp
+                                        self.rr_conflicts.append((st,chosenp,rejectp))
+                                        log.info("  ! reduce/reduce conflict for %s resolved using rule %d (%s)", a,st_actionp[a].number, st_actionp[a])
+                                    else:
+                                        raise LALRError("Unknown conflict in state %d" % st)
+                                else:
+                                    st_action[a] = -p.number
+                                    st_actionp[a] = p
+                                    Productions[p.number].reduced += 1
+                    else:
+                        i = p.lr_index
+                        a = p.prod[i+1]       # Get symbol right after the "."
+                        if a in self.grammar.Terminals:
+                            g = self.lr0_goto(I,a)
+                            j = self.lr0_cidhash.get(id(g),-1)
+                            if j >= 0:
+                                # We are in a shift state
+                                actlist.append((a,p,"shift and go to state %d" % j))
+                                r = st_action.get(a,None)
+                                if r is not None:
+                                    # Whoa have a shift/reduce or shift/shift conflict
+                                    if r > 0:
+                                        if r != j:
+                                            raise LALRError("Shift/shift conflict in state %d" % st)
+                                    elif r < 0:
+                                        # Do a precedence check.
+                                        #   -  if precedence of reduce rule is higher, we reduce.
+                                        #   -  if precedence of reduce is same and left assoc, we reduce.
+                                        #   -  otherwise we shift
+                                        rprec,rlevel = Productions[st_actionp[a].number].prec
+                                        sprec,slevel = Precedence.get(a,('right',0))
+                                        if (slevel > rlevel) or ((slevel == rlevel) and (rprec == 'right')):
+                                            # We decide to shift here... highest precedence to shift
+                                            Productions[st_actionp[a].number].reduced -= 1
+                                            st_action[a] = j
+                                            st_actionp[a] = p
+                                            if not rlevel:
+                                                log.info("  ! shift/reduce conflict for %s resolved as shift",a)
+                                                self.sr_conflicts.append((st,a,'shift'))
+                                        elif (slevel == rlevel) and (rprec == 'nonassoc'):
+                                            st_action[a] = None
+                                        else:
+                                            # Hmmm. Guess we'll keep the reduce
+                                            if not slevel and not rlevel:
+                                                log.info("  ! shift/reduce conflict for %s resolved as reduce",a)
+                                                self.sr_conflicts.append((st,a,'reduce'))
+
+                                    else:
+                                        raise LALRError("Unknown conflict in state %d" % st)
+                                else:
+                                    st_action[a] = j
+                                    st_actionp[a] = p
+
+            # Print the actions associated with each terminal
+            _actprint = { }
+            for a,p,m in actlist:
+                if a in st_action:
+                    if p is st_actionp[a]:
+                        log.info("    %-15s %s",a,m)
+                        _actprint[(a,m)] = 1
+            log.info("")
+            # Print the actions that were not used. (debugging)
+            not_used = 0
+            for a,p,m in actlist:
+                if a in st_action:
+                    if p is not st_actionp[a]:
+                        if not (a,m) in _actprint:
+                            log.debug("  ! %-15s [ %s ]",a,m)
+                            not_used = 1
+                            _actprint[(a,m)] = 1
+            if not_used:
+                log.debug("")
+
+            # Construct the goto table for this state
+
+            nkeys = { }
+            for ii in I:
+                for s in ii.usyms:
+                    if s in self.grammar.Nonterminals:
+                        nkeys[s] = None
+            for n in nkeys:
+                g = self.lr0_goto(I,n)
+                j = self.lr0_cidhash.get(id(g),-1)
+                if j >= 0:
+                    st_goto[n] = j
+                    log.info("    %-30s shift and go to state %d",n,j)
+
+            action[st] = st_action
+            actionp[st] = st_actionp
+            goto[st] = st_goto
+            st += 1
+
+
+    # -----------------------------------------------------------------------------
+    # write()
+    #
+    # This function writes the LR parsing tables to a file
+    # -----------------------------------------------------------------------------
+
+    def write_table(self,modulename,outputdir='',signature=""):
+        basemodulename = modulename.split(".")[-1]
+        filename = os.path.join(outputdir,basemodulename) + ".py"
+        try:
+            f = open(filename,"w")
+
+            f.write("""
+# %s
+# This file is automatically generated. Do not edit.
+_tabversion = %r
+
+_lr_method = %r
+
+_lr_signature = %r
+    """ % (filename, __tabversion__, self.lr_method, signature))
+
+            # Change smaller to 0 to go back to original tables
+            smaller = 1
+
+            # Factor out names to try and make smaller
+            if smaller:
+                items = { }
+
+                for s,nd in self.lr_action.items():
+                   for name,v in nd.items():
+                      i = items.get(name)
+                      if not i:
+                         i = ([],[])
+                         items[name] = i
+                      i[0].append(s)
+                      i[1].append(v)
+
+                f.write("\n_lr_action_items = {")
+                for k,v in items.items():
+                    f.write("%r:([" % k)
+                    for i in v[0]:
+                        f.write("%r," % i)
+                    f.write("],[")
+                    for i in v[1]:
+                        f.write("%r," % i)
+
+                    f.write("]),")
+                f.write("}\n")
+
+                f.write("""
+_lr_action = { }
+for _k, _v in _lr_action_items.items():
+   for _x,_y in zip(_v[0],_v[1]):
+      if not _x in _lr_action:  _lr_action[_x] = { }
+      _lr_action[_x][_k] = _y
+del _lr_action_items
+""")
+
+            else:
+                f.write("\n_lr_action = { ");
+                for k,v in self.lr_action.items():
+                    f.write("(%r,%r):%r," % (k[0],k[1],v))
+                f.write("}\n");
+
+            if smaller:
+                # Factor out names to try and make smaller
+                items = { }
+
+                for s,nd in self.lr_goto.items():
+                   for name,v in nd.items():
+                      i = items.get(name)
+                      if not i:
+                         i = ([],[])
+                         items[name] = i
+                      i[0].append(s)
+                      i[1].append(v)
+
+                f.write("\n_lr_goto_items = {")
+                for k,v in items.items():
+                    f.write("%r:([" % k)
+                    for i in v[0]:
+                        f.write("%r," % i)
+                    f.write("],[")
+                    for i in v[1]:
+                        f.write("%r," % i)
+
+                    f.write("]),")
+                f.write("}\n")
+
+                f.write("""
+_lr_goto = { }
+for _k, _v in _lr_goto_items.items():
+   for _x,_y in zip(_v[0],_v[1]):
+       if not _x in _lr_goto: _lr_goto[_x] = { }
+       _lr_goto[_x][_k] = _y
+del _lr_goto_items
+""")
+            else:
+                f.write("\n_lr_goto = { ");
+                for k,v in self.lr_goto.items():
+                    f.write("(%r,%r):%r," % (k[0],k[1],v))
+                f.write("}\n");
+
+            # Write production table
+            f.write("_lr_productions = [\n")
+            for p in self.lr_productions:
+                if p.func:
+                    f.write("  (%r,%r,%d,%r,%r,%d),\n" % (p.str,p.name, p.len, p.func,p.file,p.line))
+                else:
+                    f.write("  (%r,%r,%d,None,None,None),\n" % (str(p),p.name, p.len))
+            f.write("]\n")
+            f.close()
+
+        except IOError:
+            e = sys.exc_info()[1]
+            sys.stderr.write("Unable to create '%s'\n" % filename)
+            sys.stderr.write(str(e)+"\n")
+            return
+
+
+    # -----------------------------------------------------------------------------
+    # pickle_table()
+    #
+    # This function pickles the LR parsing tables to a supplied file object
+    # -----------------------------------------------------------------------------
+
+    def pickle_table(self,filename,signature=""):
+        try:
+            import cPickle as pickle
+        except ImportError:
+            import pickle
+        outf = open(filename,"wb")
+        pickle.dump(__tabversion__,outf,pickle_protocol)
+        pickle.dump(self.lr_method,outf,pickle_protocol)
+        pickle.dump(signature,outf,pickle_protocol)
+        pickle.dump(self.lr_action,outf,pickle_protocol)
+        pickle.dump(self.lr_goto,outf,pickle_protocol)
+
+        outp = []
+        for p in self.lr_productions:
+            if p.func:
+                outp.append((p.str,p.name, p.len, p.func,p.file,p.line))
+            else:
+                outp.append((str(p),p.name,p.len,None,None,None))
+        pickle.dump(outp,outf,pickle_protocol)
+        outf.close()
+
+# -----------------------------------------------------------------------------
+#                            === INTROSPECTION ===
+#
+# The following functions and classes are used to implement the PLY
+# introspection features followed by the yacc() function itself.
+# -----------------------------------------------------------------------------
+
+# -----------------------------------------------------------------------------
+# get_caller_module_dict()
+#
+# This function returns a dictionary containing all of the symbols defined within
+# a caller further down the call stack.  This is used to get the environment
+# associated with the yacc() call if none was provided.
+# -----------------------------------------------------------------------------
+
+def get_caller_module_dict(levels):
+    try:
+        raise RuntimeError
+    except RuntimeError:
+        e,b,t = sys.exc_info()
+        f = t.tb_frame
+        while levels > 0:
+            f = f.f_back                   
+            levels -= 1
+        ldict = f.f_globals.copy()
+        if f.f_globals != f.f_locals:
+            ldict.update(f.f_locals)
+
+        return ldict
+
+# -----------------------------------------------------------------------------
+# parse_grammar()
+#
+# This takes a raw grammar rule string and parses it into production data
+# -----------------------------------------------------------------------------
+def parse_grammar(doc,file,line):
+    grammar = []
+    # Split the doc string into lines
+    pstrings = doc.splitlines()
+    lastp = None
+    dline = line
+    for ps in pstrings:
+        dline += 1
+        p = ps.split()
+        if not p: continue
+        try:
+            if p[0] == '|':
+                # This is a continuation of a previous rule
+                if not lastp:
+                    raise SyntaxError("%s:%d: Misplaced '|'" % (file,dline))
+                prodname = lastp
+                syms = p[1:]
+            else:
+                prodname = p[0]
+                lastp = prodname
+                syms   = p[2:]
+                assign = p[1]
+                if assign != ':' and assign != '::=':
+                    raise SyntaxError("%s:%d: Syntax error. Expected ':'" % (file,dline))
+
+            grammar.append((file,dline,prodname,syms))
+        except SyntaxError:
+            raise
+        except Exception:
+            raise SyntaxError("%s:%d: Syntax error in rule '%s'" % (file,dline,ps.strip()))
+
+    return grammar
+
+# -----------------------------------------------------------------------------
+# ParserReflect()
+#
+# This class represents information extracted for building a parser including
+# start symbol, error function, tokens, precedence list, action functions,
+# etc.
+# -----------------------------------------------------------------------------
+class ParserReflect(object):
+    def __init__(self,pdict,log=None):
+        self.pdict      = pdict
+        self.start      = None
+        self.error_func = None
+        self.tokens     = None
+        self.files      = {}
+        self.grammar    = []
+        self.error      = 0
+
+        if log is None:
+            self.log = PlyLogger(sys.stderr)
+        else:
+            self.log = log
+
+    # Get all of the basic information
+    def get_all(self):
+        self.get_start()
+        self.get_error_func()
+        self.get_tokens()
+        self.get_precedence()
+        self.get_pfunctions()
+        
+    # Validate all of the information
+    def validate_all(self):
+        self.validate_start()
+        self.validate_error_func()
+        self.validate_tokens()
+        self.validate_precedence()
+        self.validate_pfunctions()
+        self.validate_files()
+        return self.error
+
+    # Compute a signature over the grammar
+    def signature(self):
+        try:
+            from hashlib import md5
+        except ImportError:
+            from md5 import md5
+        try:
+            sig = md5()
+            if self.start:
+                sig.update(self.start.encode('latin-1'))
+            if self.prec:
+                sig.update("".join(["".join(p) for p in self.prec]).encode('latin-1'))
+            if self.tokens:
+                sig.update(" ".join(self.tokens).encode('latin-1'))
+            for f in self.pfuncs:
+                if f[3]:
+                    sig.update(f[3].encode('latin-1'))
+        except (TypeError,ValueError):
+            pass
+        return sig.digest()
+
+    # -----------------------------------------------------------------------------
+    # validate_file()
+    #
+    # This method checks to see if there are duplicated p_rulename() functions
+    # in the parser module file.  Without this function, it is really easy for
+    # users to make mistakes by cutting and pasting code fragments (and it's a real
+    # bugger to try and figure out why the resulting parser doesn't work).  Therefore,
+    # we just do a little regular expression pattern matching of def statements
+    # to try and detect duplicates.
+    # -----------------------------------------------------------------------------
+
+    def validate_files(self):
+        # Match def p_funcname(
+        fre = re.compile(r'\s*def\s+(p_[a-zA-Z_0-9]*)\(')
+
+        for filename in self.files.keys():
+            base,ext = os.path.splitext(filename)
+            if ext != '.py': return 1          # No idea. Assume it's okay.
+
+            try:
+                f = open(filename)
+                lines = f.readlines()
+                f.close()
+            except IOError:
+                continue
+
+            counthash = { }
+            for linen,l in enumerate(lines):
+                linen += 1
+                m = fre.match(l)
+                if m:
+                    name = m.group(1)
+                    prev = counthash.get(name)
+                    if not prev:
+                        counthash[name] = linen
+                    else:
+                        self.log.warning("%s:%d: Function %s redefined. Previously defined on line %d", filename,linen,name,prev)
+
+    # Get the start symbol
+    def get_start(self):
+        self.start = self.pdict.get('start')
+
+    # Validate the start symbol
+    def validate_start(self):
+        if self.start is not None:
+            if not isinstance(self.start,str):
+                self.log.error("'start' must be a string")
+
+    # Look for error handler
+    def get_error_func(self):
+        self.error_func = self.pdict.get('p_error')
+
+    # Validate the error function
+    def validate_error_func(self):
+        if self.error_func:
+            if isinstance(self.error_func,types.FunctionType):
+                ismethod = 0
+            elif isinstance(self.error_func, types.MethodType):
+                ismethod = 1
+            else:
+                self.log.error("'p_error' defined, but is not a function or method")
+                self.error = 1
+                return
+
+            eline = func_code(self.error_func).co_firstlineno
+            efile = func_code(self.error_func).co_filename
+            self.files[efile] = 1
+
+            if (func_code(self.error_func).co_argcount != 1+ismethod):
+                self.log.error("%s:%d: p_error() requires 1 argument",efile,eline)
+                self.error = 1
+
+    # Get the tokens map
+    def get_tokens(self):
+        tokens = self.pdict.get("tokens",None)
+        if not tokens:
+            self.log.error("No token list is defined")
+            self.error = 1
+            return
+
+        if not isinstance(tokens,(list, tuple)):
+            self.log.error("tokens must be a list or tuple")
+            self.error = 1
+            return
+        
+        if not tokens:
+            self.log.error("tokens is empty")
+            self.error = 1
+            return
+
+        self.tokens = tokens
+
+    # Validate the tokens
+    def validate_tokens(self):
+        # Validate the tokens.
+        if 'error' in self.tokens:
+            self.log.error("Illegal token name 'error'. Is a reserved word")
+            self.error = 1
+            return
+
+        terminals = {}
+        for n in self.tokens:
+            if n in terminals:
+                self.log.warning("Token '%s' multiply defined", n)
+            terminals[n] = 1
+
+    # Get the precedence map (if any)
+    def get_precedence(self):
+        self.prec = self.pdict.get("precedence",None)
+
+    # Validate and parse the precedence map
+    def validate_precedence(self):
+        preclist = []
+        if self.prec:
+            if not isinstance(self.prec,(list,tuple)):
+                self.log.error("precedence must be a list or tuple")
+                self.error = 1
+                return
+            for level,p in enumerate(self.prec):
+                if not isinstance(p,(list,tuple)):
+                    self.log.error("Bad precedence table")
+                    self.error = 1
+                    return
+
+                if len(p) < 2:
+                    self.log.error("Malformed precedence entry %s. Must be (assoc, term, ..., term)",p)
+                    self.error = 1
+                    return
+                assoc = p[0]
+                if not isinstance(assoc,str):
+                    self.log.error("precedence associativity must be a string")
+                    self.error = 1
+                    return
+                for term in p[1:]:
+                    if not isinstance(term,str):
+                        self.log.error("precedence items must be strings")
+                        self.error = 1
+                        return
+                    preclist.append((term,assoc,level+1))
+        self.preclist = preclist
+
+    # Get all p_functions from the grammar
+    def get_pfunctions(self):
+        p_functions = []
+        for name, item in self.pdict.items():
+            if name[:2] != 'p_': continue
+            if name == 'p_error': continue
+            if isinstance(item,(types.FunctionType,types.MethodType)):
+                line = func_code(item).co_firstlineno
+                file = func_code(item).co_filename
+                p_functions.append((line,file,name,item.__doc__))
+
+        # Sort all of the actions by line number
+        p_functions.sort()
+        self.pfuncs = p_functions
+
+
+    # Validate all of the p_functions
+    def validate_pfunctions(self):
+        grammar = []
+        # Check for non-empty symbols
+        if len(self.pfuncs) == 0:
+            self.log.error("no rules of the form p_rulename are defined")
+            self.error = 1
+            return 
+        
+        for line, file, name, doc in self.pfuncs:
+            func = self.pdict[name]
+            if isinstance(func, types.MethodType):
+                reqargs = 2
+            else:
+                reqargs = 1
+            if func_code(func).co_argcount > reqargs:
+                self.log.error("%s:%d: Rule '%s' has too many arguments",file,line,func.__name__)
+                self.error = 1
+            elif func_code(func).co_argcount < reqargs:
+                self.log.error("%s:%d: Rule '%s' requires an argument",file,line,func.__name__)
+                self.error = 1
+            elif not func.__doc__:
+                self.log.warning("%s:%d: No documentation string specified in function '%s' (ignored)",file,line,func.__name__)
+            else:
+                try:
+                    parsed_g = parse_grammar(doc,file,line)
+                    for g in parsed_g:
+                        grammar.append((name, g))
+                except SyntaxError:
+                    e = sys.exc_info()[1]
+                    self.log.error(str(e))
+                    self.error = 1
+
+                # Looks like a valid grammar rule
+                # Mark the file in which defined.
+                self.files[file] = 1
+
+        # Secondary validation step that looks for p_ definitions that are not functions
+        # or functions that look like they might be grammar rules.
+
+        for n,v in self.pdict.items():
+            if n[0:2] == 'p_' and isinstance(v, (types.FunctionType, types.MethodType)): continue
+            if n[0:2] == 't_': continue
+            if n[0:2] == 'p_' and n != 'p_error':
+                self.log.warning("'%s' not defined as a function", n)
+            if ((isinstance(v,types.FunctionType) and func_code(v).co_argcount == 1) or
+                (isinstance(v,types.MethodType) and func_code(v).co_argcount == 2)):
+                try:
+                    doc = v.__doc__.split(" ")
+                    if doc[1] == ':':
+                        self.log.warning("%s:%d: Possible grammar rule '%s' defined without p_ prefix",
+                                         func_code(v).co_filename, func_code(v).co_firstlineno,n)
+                except Exception:
+                    pass
+
+        self.grammar = grammar
+
+# -----------------------------------------------------------------------------
+# yacc(module)
+#
+# Build a parser
+# -----------------------------------------------------------------------------
+
+def yacc(method='LALR', debug=yaccdebug, module=None, tabmodule=tab_module, start=None, 
+         check_recursion=1, optimize=0, write_tables=1, debugfile=debug_file,outputdir='',
+         debuglog=None, errorlog = None, picklefile=None):
+
+    global parse                 # Reference to the parsing method of the last built parser
+
+    # If pickling is enabled, table files are not created
+
+    if picklefile:
+        write_tables = 0
+
+    if errorlog is None:
+        errorlog = PlyLogger(sys.stderr)
+
+    # Get the module dictionary used for the parser
+    if module:
+        _items = [(k,getattr(module,k)) for k in dir(module)]
+        pdict = dict(_items)
+    else:
+        pdict = get_caller_module_dict(2)
+
+    # Collect parser information from the dictionary
+    pinfo = ParserReflect(pdict,log=errorlog)
+    pinfo.get_all()
+
+    if pinfo.error:
+        raise YaccError("Unable to build parser")
+
+    # Check signature against table files (if any)
+    signature = pinfo.signature()
+
+    # Read the tables
+    try:
+        lr = LRTable()
+        if picklefile:
+            read_signature = lr.read_pickle(picklefile)
+        else:
+            read_signature = lr.read_table(tabmodule)
+        if optimize or (read_signature == signature):
+            try:
+                lr.bind_callables(pinfo.pdict)
+                parser = LRParser(lr,pinfo.error_func)
+                parse = parser.parse
+                return parser
+            except Exception:
+                e = sys.exc_info()[1]
+                errorlog.warning("There was a problem loading the table file: %s", repr(e))
+    except VersionError:
+        e = sys.exc_info()
+        errorlog.warning(str(e))
+    except Exception:
+        pass
+
+    if debuglog is None:
+        if debug:
+            debuglog = PlyLogger(open(debugfile,"w"))
+        else:
+            debuglog = NullLogger()
+
+    debuglog.info("Created by PLY version %s (http://www.dabeaz.com/ply)", __version__)
+
+
+    errors = 0
+
+    # Validate the parser information
+    if pinfo.validate_all():
+        raise YaccError("Unable to build parser")
+    
+    if not pinfo.error_func:
+        errorlog.warning("no p_error() function is defined")
+
+    # Create a grammar object
+    grammar = Grammar(pinfo.tokens)
+
+    # Set precedence level for terminals
+    for term, assoc, level in pinfo.preclist:
+        try:
+            grammar.set_precedence(term,assoc,level)
+        except GrammarError:
+            e = sys.exc_info()[1]
+            errorlog.warning("%s",str(e))
+
+    # Add productions to the grammar
+    for funcname, gram in pinfo.grammar:
+        file, line, prodname, syms = gram
+        try:
+            grammar.add_production(prodname,syms,funcname,file,line)
+        except GrammarError:
+            e = sys.exc_info()[1]
+            errorlog.error("%s",str(e))
+            errors = 1
+
+    # Set the grammar start symbols
+    try:
+        if start is None:
+            grammar.set_start(pinfo.start)
+        else:
+            grammar.set_start(start)
+    except GrammarError:
+        e = sys.exc_info()[1]
+        errorlog.error(str(e))
+        errors = 1
+
+    if errors:
+        raise YaccError("Unable to build parser")
+
+    # Verify the grammar structure
+    undefined_symbols = grammar.undefined_symbols()
+    for sym, prod in undefined_symbols:
+        errorlog.error("%s:%d: Symbol '%s' used, but not defined as a token or a rule",prod.file,prod.line,sym)
+        errors = 1
+
+    unused_terminals = grammar.unused_terminals()
+    if unused_terminals:
+        debuglog.info("")
+        debuglog.info("Unused terminals:")
+        debuglog.info("")
+        for term in unused_terminals:
+            errorlog.warning("Token '%s' defined, but not used", term)
+            debuglog.info("    %s", term)
+
+    # Print out all productions to the debug log
+    if debug:
+        debuglog.info("")
+        debuglog.info("Grammar")
+        debuglog.info("")
+        for n,p in enumerate(grammar.Productions):
+            debuglog.info("Rule %-5d %s", n, p)
+
+    # Find unused non-terminals
+    unused_rules = grammar.unused_rules()
+    for prod in unused_rules:
+        errorlog.warning("%s:%d: Rule '%s' defined, but not used", prod.file, prod.line, prod.name)
+
+    if len(unused_terminals) == 1:
+        errorlog.warning("There is 1 unused token")
+    if len(unused_terminals) > 1:
+        errorlog.warning("There are %d unused tokens", len(unused_terminals))
+
+    if len(unused_rules) == 1:
+        errorlog.warning("There is 1 unused rule")
+    if len(unused_rules) > 1:
+        errorlog.warning("There are %d unused rules", len(unused_rules))
+
+    if debug:
+        debuglog.info("")
+        debuglog.info("Terminals, with rules where they appear")
+        debuglog.info("")
+        terms = list(grammar.Terminals)
+        terms.sort()
+        for term in terms:
+            debuglog.info("%-20s : %s", term, " ".join([str(s) for s in grammar.Terminals[term]]))
+        
+        debuglog.info("")
+        debuglog.info("Nonterminals, with rules where they appear")
+        debuglog.info("")
+        nonterms = list(grammar.Nonterminals)
+        nonterms.sort()
+        for nonterm in nonterms:
+            debuglog.info("%-20s : %s", nonterm, " ".join([str(s) for s in grammar.Nonterminals[nonterm]]))
+        debuglog.info("")
+
+    if check_recursion:
+        unreachable = grammar.find_unreachable()
+        for u in unreachable:
+            errorlog.warning("Symbol '%s' is unreachable",u)
+
+        infinite = grammar.infinite_cycles()
+        for inf in infinite:
+            errorlog.error("Infinite recursion detected for symbol '%s'", inf)
+            errors = 1
+        
+    unused_prec = grammar.unused_precedence()
+    for term, assoc in unused_prec:
+        errorlog.error("Precedence rule '%s' defined for unknown symbol '%s'", assoc, term)
+        errors = 1
+
+    if errors:
+        raise YaccError("Unable to build parser")
+    
+    # Run the LRGeneratedTable on the grammar
+    if debug:
+        errorlog.debug("Generating %s tables", method)
+            
+    lr = LRGeneratedTable(grammar,method,debuglog)
+
+    if debug:
+        num_sr = len(lr.sr_conflicts)
+
+        # Report shift/reduce and reduce/reduce conflicts
+        if num_sr == 1:
+            errorlog.warning("1 shift/reduce conflict")
+        elif num_sr > 1:
+            errorlog.warning("%d shift/reduce conflicts", num_sr)
+
+        num_rr = len(lr.rr_conflicts)
+        if num_rr == 1:
+            errorlog.warning("1 reduce/reduce conflict")
+        elif num_rr > 1:
+            errorlog.warning("%d reduce/reduce conflicts", num_rr)
+
+    # Write out conflicts to the output file
+    if debug and (lr.sr_conflicts or lr.rr_conflicts):
+        debuglog.warning("")
+        debuglog.warning("Conflicts:")
+        debuglog.warning("")
+
+        for state, tok, resolution in lr.sr_conflicts:
+            debuglog.warning("shift/reduce conflict for %s in state %d resolved as %s",  tok, state, resolution)
+        
+        already_reported = {}
+        for state, rule, rejected in lr.rr_conflicts:
+            if (state,id(rule),id(rejected)) in already_reported:
+                continue
+            debuglog.warning("reduce/reduce conflict in state %d resolved using rule (%s)", state, rule)
+            debuglog.warning("rejected rule (%s) in state %d", rejected,state)
+            errorlog.warning("reduce/reduce conflict in state %d resolved using rule (%s)", state, rule)
+            errorlog.warning("rejected rule (%s) in state %d", rejected, state)
+            already_reported[state,id(rule),id(rejected)] = 1
+        
+        warned_never = []
+        for state, rule, rejected in lr.rr_conflicts:
+            if not rejected.reduced and (rejected not in warned_never):
+                debuglog.warning("Rule (%s) is never reduced", rejected)
+                errorlog.warning("Rule (%s) is never reduced", rejected)
+                warned_never.append(rejected)
+
+    # Write the table file if requested
+    if write_tables:
+        lr.write_table(tabmodule,outputdir,signature)
+
+    # Write a pickled version of the tables
+    if picklefile:
+        lr.pickle_table(picklefile,signature)
+
+    # Build the parser
+    lr.bind_callables(pinfo.pdict)
+    parser = LRParser(lr,pinfo.error_func)
+
+    parse = parser.parse
+    return parser
diff --git a/webWidgetTCT_device/tools/slimit/scope.py b/webWidgetTCT_device/tools/slimit/scope.py
new file mode 100755 (executable)
index 0000000..4cac367
--- /dev/null
@@ -0,0 +1,185 @@
+###############################################################################
+#
+# Copyright (c) 2011 Ruslan Spivak
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+###############################################################################
+
+__author__ = 'Ruslan Spivak <ruslan.spivak@gmail.com>'
+
+import itertools
+
+try:
+    from collections import OrderedDict
+except ImportError:
+    from odict import odict as OrderedDict
+
+from slimit.lexer import Lexer
+
+
+ID_CHARS = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
+
+def powerset(iterable):
+    """powerset('abc') -> a b c ab ac bc abc"""
+    s = list(iterable)
+    for chars in itertools.chain.from_iterable(
+        itertools.combinations(s, r) for r in range(1, len(s)+1)
+        ):
+        yield ''.join(chars)
+
+
+class SymbolTable(object):
+    def __init__(self):
+        self.globals = GlobalScope()
+
+
+class Scope(object):
+
+    def __init__(self, enclosing_scope=None):
+        self.symbols = OrderedDict()
+        # {symbol.name: mangled_name}
+        self.mangled = {}
+        # {mangled_name: symbol.name}
+        self.rev_mangled = {}
+        # names referenced from this scope and all sub-scopes
+        # {name: scope} key is the name, value is the scope that
+        # contains referenced name
+        self.refs = {}
+        # set to True if this scope or any subscope contains 'eval'
+        self.has_eval = False
+        # set to True if this scope or any subscope contains 'wit
+        self.has_with = False
+        self.enclosing_scope = enclosing_scope
+        # sub-scopes
+        self.children = []
+        # add ourselves as a child to the enclosing scope
+        if enclosing_scope is not None:
+            self.enclosing_scope.add_child(self)
+        self.base54 = powerset(ID_CHARS)
+
+    def __contains__(self, sym):
+        return sym.name in self.symbols
+
+    def add_child(self, scope):
+        self.children.append(scope)
+
+    def define(self, sym):
+        self.symbols[sym.name] = sym
+        # track scope for every symbol
+        sym.scope = self
+
+    def resolve(self, name):
+        sym = self.symbols.get(name)
+        if sym is not None:
+            return sym
+        elif self.enclosing_scope is not None:
+            return self.enclosing_scope.resolve(name)
+
+    def get_enclosing_scope(self):
+        return self.enclosing_scope
+
+    def _get_scope_with_mangled(self, name):
+        """Return a scope containing passed mangled name."""
+        scope = self
+        while True:
+            parent = scope.get_enclosing_scope()
+            if parent is None:
+                return
+
+            if name in parent.rev_mangled:
+                return parent
+
+            scope = parent
+
+    def _get_scope_with_symbol(self, name):
+        """Return a scope containing passed name as a symbol name."""
+        scope = self
+        while True:
+            parent = scope.get_enclosing_scope()
+            if parent is None:
+                return
+
+            if name in parent.symbols:
+                return parent
+
+            scope = parent
+
+    def get_next_mangled_name(self):
+        """
+        1. Do not shadow a mangled name from a parent scope
+           if we reference the original name from that scope
+           in this scope or any sub-scope.
+
+        2. Do not shadow an original name from a parent scope
+           if it's not mangled and we reference it in this scope
+           or any sub-scope.
+
+        """
+        while True:
+            mangled = self.base54.next()
+
+            # case 1
+            ancestor = self._get_scope_with_mangled(mangled)
+            if (ancestor is not None
+                and self.refs.get(ancestor.rev_mangled[mangled]) is ancestor
+                ):
+                continue
+
+            # case 2
+            ancestor = self._get_scope_with_symbol(mangled)
+            if (ancestor is not None
+                and self.refs.get(mangled) is ancestor
+                and mangled not in ancestor.mangled
+                ):
+                continue
+
+            # make sure a new mangled name is not a reserved word
+            if mangled.upper() in Lexer.keywords:
+                continue
+
+            return mangled
+
+
+class GlobalScope(Scope):
+    pass
+
+
+class LocalScope(Scope):
+    pass
+
+
+class Symbol(object):
+    def __init__(self, name):
+        self.name = name
+        self.scope = None
+
+
+class VarSymbol(Symbol):
+    pass
+
+
+class FuncSymbol(Symbol, Scope):
+    """Function symbol is both a symbol and a scope for arguments."""
+
+    def __init__(self, name, enclosing_scope):
+        Symbol.__init__(self, name)
+        Scope.__init__(self, enclosing_scope)
+
+
diff --git a/webWidgetTCT_device/tools/slimit/tests/__init__.py b/webWidgetTCT_device/tools/slimit/tests/__init__.py
new file mode 100755 (executable)
index 0000000..e69de29
diff --git a/webWidgetTCT_device/tools/slimit/tests/test_cmd.py b/webWidgetTCT_device/tools/slimit/tests/test_cmd.py
new file mode 100755 (executable)
index 0000000..ebb8ef5
--- /dev/null
@@ -0,0 +1,113 @@
+###############################################################################
+#
+# Copyright (c) 2011 Ruslan Spivak
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+###############################################################################
+
+__author__ = 'Ruslan Spivak <ruslan.spivak@gmail.com>'
+
+import os
+import sys
+import StringIO
+import tempfile
+import unittest
+
+from contextlib import contextmanager
+
+
+@contextmanager
+def redirected_input_output(input=''):
+    old_inp, old_out = sys.stdin, sys.stdout
+    inp, out = StringIO.StringIO(input), StringIO.StringIO()
+    sys.stdin, sys.stdout = inp, out
+    try:
+        yield out
+    finally:
+        sys.stdin, sys.stdout = old_inp, old_out
+
+
+@contextmanager
+def redirected_sys_argv(argv):
+    old = sys.argv
+    sys.argv = argv
+    try:
+        yield argv
+    finally:
+        sys.argv = old
+
+
+class CmdTestCase(unittest.TestCase):
+
+    def setUp(self):
+        fd, path = tempfile.mkstemp()
+        self.path = path
+        with os.fdopen(fd, 'w') as fout:
+            fout.write('var global = 5;')
+
+    def tearDown(self):
+        os.remove(self.path)
+
+    def test_main_dash_m_with_input_file(self):
+        from slimit.minifier import main
+        out = StringIO.StringIO()
+        main(['-m', '-t', self.path], out=out)
+        self.assertEqual('var a=5;', out.getvalue())
+
+    def test_main_dash_dash_mangle_with_input_file(self):
+        from slimit.minifier import main
+        out = StringIO.StringIO()
+        main(['--mangle', '--mangle-toplevel', self.path], out=out)
+        self.assertEqual('var a=5;', out.getvalue())
+
+    def test_main_dash_m_with_mock_stdin(self):
+        from slimit.minifier import main
+        out = StringIO.StringIO()
+        inp = StringIO.StringIO('function foo() { var local = 5; }')
+        main(['-m'], inp=inp, out=out)
+        self.assertEqual('function foo(){var a=5;}', out.getvalue())
+
+    def test_main_stdin_stdout(self):
+        # slimit.minifier should be deleted from sys.modules in order
+        # to have a proper reference to sys.stdin and sys.stdou when
+        # 'main' definition is evaluated during module import
+        old_module = None
+        try:
+            old_module = sys.modules.pop('slimit.minifier')
+        except KeyError:
+            pass
+
+        with redirected_input_output(
+            input='function foo() { var local = 5; }') as out:
+            from slimit.minifier import main
+            main(['-m'])
+
+        self.assertEqual('function foo(){var a=5;}', out.getvalue())
+        if old_module is not None:
+            sys.modules['slimit.minifier'] = old_module
+
+    def test_main_sys_argv(self):
+        out = StringIO.StringIO()
+        inp = StringIO.StringIO('var global = 5;')
+        with redirected_sys_argv(['slimit', '-m', '-t']):
+            from slimit.minifier import main
+            main(inp=inp, out=out)
+
+        self.assertEqual('var a=5;', out.getvalue())
diff --git a/webWidgetTCT_device/tools/slimit/tests/test_ecmavisitor.py b/webWidgetTCT_device/tools/slimit/tests/test_ecmavisitor.py
new file mode 100755 (executable)
index 0000000..65dfce2
--- /dev/null
@@ -0,0 +1,505 @@
+###############################################################################
+#
+# Copyright (c) 2011 Ruslan Spivak
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+###############################################################################
+
+__author__ = 'Ruslan Spivak <ruslan.spivak@gmail.com>'
+
+import textwrap
+import unittest
+
+from slimit.parser import Parser
+
+
+def decorator(cls):
+    def make_test_function(input, expected):
+
+        def test_func(self):
+            parser = Parser()
+            result = parser.parse(input).to_ecma()
+            self.assertMultiLineEqual(result, expected)
+
+        return test_func
+
+    for index, input in enumerate(cls.TEST_CASES):
+        input = textwrap.dedent(input).strip()
+        func = make_test_function(input, input)
+        setattr(cls, 'test_case_%d' % index, func)
+
+    return cls
+
+
+@decorator
+class ECMAVisitorTestCase(unittest.TestCase):
+
+    def setUp(self):
+        self.maxDiff = 2000
+
+    TEST_CASES = [
+        ################################
+        # block
+        ################################
+        """
+        {
+          var a = 5;
+        }
+        """,
+
+        ################################
+        # variable statement
+        ################################
+        """
+        var a;
+        var b;
+        var a, b = 3;
+        var a = 1, b;
+        var a = 5, b = 7;
+        """,
+
+        # empty statement
+        """
+        ;
+        ;
+        ;
+        """,
+
+        # test 3
+        ################################
+        # if
+        ################################
+        'if (true) var x = 100;',
+
+        """
+        if (true) {
+          var x = 100;
+          var y = 200;
+        }
+        """,
+
+        'if (true) if (true) var x = 100; else var y = 200;',
+
+        # test 6
+        """
+        if (true) {
+          var x = 100;
+        } else {
+          var y = 200;
+        }
+        """,
+        ################################
+        # iteration
+        ################################
+        """
+        for (i = 0; i < 10; i++) {
+          x = 10 * i;
+        }
+        """,
+
+        """
+        for (var i = 0; i < 10; i++) {
+          x = 10 * i;
+        }
+        """,
+
+        # test 9
+        """
+        for (i = 0, j = 10; i < j && j < 15; i++, j++) {
+          x = i * j;
+        }
+        """,
+
+        """
+        for (var i = 0, j = 10; i < j && j < 15; i++, j++) {
+          x = i * j;
+        }
+        """,
+
+        """
+        for (p in obj) {
+
+        }
+        """,
+        # retain the semicolon in the initialiser part of a 'for' statement
+        """
+        for (Q || (Q = []); d < b; ) {
+          d = 1;
+        }
+        """,
+
+        """
+        for (new Foo(); d < b; ) {
+          d = 1;
+        }
+        """,
+
+        """
+        for (2 >> (foo ? 32 : 43) && 54; 21; ) {
+          a = c;
+        }
+        """,
+
+        """
+        for (/^.+/g; cond(); ++z) {
+          ev();
+        }
+        """,
+
+        # test 12
+        """
+        for (var p in obj) {
+          p = 1;
+        }
+        """,
+
+        """
+        do {
+          x += 1;
+        } while (true);
+        """,
+
+        """
+        while (false) {
+          x = null;
+        }
+        """,
+
+        # test 15
+        ################################
+        # continue statement
+        ################################
+        """
+        while (true) {
+          continue;
+          s = 'I am not reachable';
+        }
+        """,
+
+        """
+        while (true) {
+          continue label1;
+          s = 'I am not reachable';
+        }
+        """,
+
+        ################################
+        # break statement
+        ################################
+        """
+        while (true) {
+          break;
+          s = 'I am not reachable';
+        }
+        """,
+        # test 18
+        """
+        while (true) {
+          break label1;
+          s = 'I am not reachable';
+        }
+        """,
+
+        ################################
+        # return statement
+        ################################
+        """
+        {
+          return;
+        }
+        """,
+
+        """
+        {
+          return 1;
+        }
+        """,
+
+        # test21
+        ################################
+        # with statement
+        ################################
+        """
+        with (x) {
+          var y = x * 2;
+        }
+        """,
+
+        ################################
+        # labelled statement
+        ################################
+        """
+        label: while (true) {
+          x *= 3;
+        }
+        """,
+
+        ################################
+        # switch statement
+        ################################
+        """
+        switch (day_of_week) {
+          case 6:
+          case 7:
+            x = 'Weekend';
+            break;
+          case 1:
+            x = 'Monday';
+            break;
+          default:
+            break;
+        }
+        """,
+
+        # test 24
+        ################################
+        # throw statement
+        ################################
+        """
+        throw 'exc';
+        """,
+
+        ################################
+        # debugger statement
+        ################################
+        'debugger;',
+
+        ################################
+        # expression statement
+        ################################
+        """
+        5 + 7 - 20 * 10;
+        ++x;
+        --x;
+        x++;
+        x--;
+        x = 17 /= 3;
+        s = mot ? z : /x:3;x<5;y</g / i;
+        """,
+
+        # test 27
+        ################################
+        # try statement
+        ################################
+        """
+        try {
+          x = 3;
+        } catch (exc) {
+          x = exc;
+        }
+        """,
+
+        """
+        try {
+          x = 3;
+        } finally {
+          x = null;
+        }
+        """,
+
+        """
+        try {
+          x = 5;
+        } catch (exc) {
+          x = exc;
+        } finally {
+          y = null;
+        }
+        """,
+
+        # test 30
+        ################################
+        # function
+        ################################
+        """
+        function foo(x, y) {
+          z = 10;
+          return x + y + z;
+        }
+        """,
+
+        """
+        function foo() {
+          return 10;
+        }
+        """,
+
+        """
+        var a = function() {
+          return 10;
+        };
+        """,
+        # test 33
+        """
+        var a = function foo(x, y) {
+          return x + y;
+        };
+        """,
+        # nested function declaration
+        """
+        function foo() {
+          function bar() {
+
+          }
+        }
+        """,
+
+        """
+        var mult = function(x) {
+          return x * 10;
+        }();
+        """,
+
+        # function call
+        # test 36
+        'foo();',
+        'foo(x, 7);',
+        'foo()[10];',
+        # test 39
+        'foo().foo;',
+
+        ################################
+        # misc
+        ################################
+
+        # new
+        'var foo = new Foo();',
+        # dot accessor
+        'var bar = new Foo.Bar();',
+
+        # test 42
+        # bracket accessor
+        'var bar = new Foo.Bar()[7];',
+
+        # object literal
+        """
+        var obj = {
+          foo: 10,
+          bar: 20
+        };
+        """,
+        """
+        var obj = {
+          1: 'a',
+          2: 'b'
+        };
+        """,
+        # test 45
+        """
+        var obj = {
+          'a': 100,
+          'b': 200
+        };
+        """,
+        """
+        var obj = {
+        };
+        """,
+
+        # array
+        """
+        var a = [1,2,3,4,5];
+        var res = a[3];
+        """,
+        # test 48
+        # elision
+        'var a = [,,,];',
+        'var a = [1,,,4];',
+        'var a = [1,,3,,5];',
+
+        # test 51
+        """
+        String.prototype.foo = function(data) {
+          var tmpl = this.toString();
+          return tmpl.replace(/{{\s*(.*?)\s*}}/g, function(a, b) {
+            var node = data;
+            if (true) {
+              var value = true;
+            } else {
+              var value = false;
+            }
+            $.each(n.split('.'), function(i, sym) {
+              node = node[sym];
+            });
+            return node;
+          });
+        };
+        """,
+
+        #######################################
+        # Make sure parentheses are not removed
+        #######################################
+
+        # ... Expected an identifier and instead saw '/'
+        'Expr.match[type].source + (/(?![^\[]*\])(?![^\(]*\))/.source);',
+
+        '(options = arguments[i]) != null;',
+
+        # test 54
+        'return (/h\d/i).test(elem.nodeName);',
+
+        # https://github.com/rspivak/slimit/issues/42
+        """
+        e.b(d) ? (a = [c.f(j[1])], e.fn.attr.call(a, d, !0)) : a = [k.f(j[1])];
+        """,
+
+        """
+        (function() {
+          x = 5;
+        }());
+        """,
+
+        """
+        (function() {
+          x = 5;
+        })();
+        """,
+
+        'return !(match === true || elem.getAttribute("classid") !== match);',
+
+        # test 57
+        'var el = (elem ? elem.ownerDocument || elem : 0).documentElement;',
+
+        # typeof
+        'typeof second.length === "number";',
+
+        # function call in FOR init
+        """
+        for (o(); i < 3; i++) {
+
+        }
+        """,
+
+        # https://github.com/rspivak/slimit/issues/32
+        """
+        Name.prototype = {
+          get fullName() {
+            return this.first + " " + this.last;
+          },
+          set fullName(name) {
+            var names = name.split(" ");
+            this.first = names[0];
+            this.last = names[1];
+          }
+        };
+        """,
+        ]
+
+
diff --git a/webWidgetTCT_device/tools/slimit/tests/test_lexer.py b/webWidgetTCT_device/tools/slimit/tests/test_lexer.py
new file mode 100755 (executable)
index 0000000..922d628
--- /dev/null
@@ -0,0 +1,297 @@
+###############################################################################
+# encoding: utf-8
+#
+# Copyright (c) 2011 Ruslan Spivak
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+###############################################################################
+
+__author__ = 'Ruslan Spivak <ruslan.spivak@gmail.com>'
+
+import doctest
+import unittest
+import difflib
+import pprint
+
+from slimit.lexer import Lexer
+
+
+def decorator(cls):
+    def make_test_function(input, expected):
+
+        def test_func(self):
+            lexer = self._get_lexer()
+            lexer.input(input)
+            result = ['%s %s' % (token.type, token.value) for token in lexer]
+            self.assertListEqual(result, expected)
+
+        return test_func
+
+    for index, (input, expected) in enumerate(cls.TEST_CASES):
+        func = make_test_function(input, expected)
+        setattr(cls, 'test_case_%d' % index, func)
+
+    return cls
+
+# The structure and some test cases are taken
+# from https://bitbucket.org/ned/jslex
+@decorator
+class LexerTestCase(unittest.TestCase):
+
+    def _get_lexer(self):
+        lexer = Lexer()
+        return lexer
+
+    def assertListEqual(self, first, second):
+        """Assert that two lists are equal.
+
+        Prints differences on error.
+        This method is similar to that of Python 2.7 'assertListEqual'
+        """
+        if first != second:
+            message = '\n'.join(
+                difflib.ndiff(pprint.pformat(first).splitlines(),
+                              pprint.pformat(second).splitlines())
+                )
+            self.fail('Lists differ:\n' + message)
+
+    def test_illegal_unicode_char_in_identifier(self):
+        lexer = self._get_lexer()
+        lexer.input(u'\u0036_tail')
+        token = lexer.token()
+        # \u0036_tail is the same as 6_tail and that's not a correct ID
+        # Check that the token is NUMBER and not an ID
+        self.assertEqual(token.type, 'NUMBER')
+        self.assertEqual(token.value, '6')
+
+    TEST_CASES = [
+        # Identifiers
+        ('i my_variable_name c17 _dummy $str $ _ CamelCase class2type',
+         ['ID i', 'ID my_variable_name', 'ID c17', 'ID _dummy',
+          'ID $str', 'ID $', 'ID _', 'ID CamelCase', 'ID class2type']
+         ),
+        (ur'\u03c0 \u03c0_tail var\ua67c',
+         [ur'ID \u03c0', ur'ID \u03c0_tail', ur'ID var\ua67c']),
+        # https://github.com/rspivak/slimit/issues/2
+        ('nullify truelie falsepositive',
+         ['ID nullify', 'ID truelie', 'ID falsepositive']),
+
+        # Keywords
+        # ('break case ...', ['BREAK break', 'CASE case', ...])
+        (' '.join(kw.lower() for kw in Lexer.keywords),
+         ['%s %s' % (kw, kw.lower()) for kw in Lexer.keywords]
+         ),
+        ('break Break BREAK', ['BREAK break', 'ID Break', 'ID BREAK']),
+
+        # Literals
+        ('null true false Null True False',
+         ['NULL null', 'TRUE true', 'FALSE false',
+          'ID Null', 'ID True', 'ID False']
+         ),
+
+        # Punctuators
+        ('a /= b', ['ID a', 'DIVEQUAL /=', 'ID b']),
+        (('= == != === !== < > <= >= || && ++ -- << >> '
+          '>>> += -= *= <<= >>= >>>= &= %= ^= |='),
+         ['EQ =', 'EQEQ ==', 'NE !=', 'STREQ ===', 'STRNEQ !==', 'LT <',
+          'GT >', 'LE <=', 'GE >=', 'OR ||', 'AND &&', 'PLUSPLUS ++',
+          'MINUSMINUS --', 'LSHIFT <<', 'RSHIFT >>', 'URSHIFT >>>',
+          'PLUSEQUAL +=', 'MINUSEQUAL -=', 'MULTEQUAL *=', 'LSHIFTEQUAL <<=',
+          'RSHIFTEQUAL >>=', 'URSHIFTEQUAL >>>=', 'ANDEQUAL &=', 'MODEQUAL %=',
+          'XOREQUAL ^=', 'OREQUAL |=',
+          ]
+         ),
+        ('. , ; : + - * % & | ^ ~ ? ! ( ) { } [ ]',
+         ['PERIOD .', 'COMMA ,', 'SEMI ;', 'COLON :', 'PLUS +', 'MINUS -',
+          'MULT *', 'MOD %', 'BAND &', 'BOR |', 'BXOR ^', 'BNOT ~',
+          'CONDOP ?', 'NOT !', 'LPAREN (', 'RPAREN )', 'LBRACE {', 'RBRACE }',
+          'LBRACKET [', 'RBRACKET ]']
+         ),
+        ('a / b', ['ID a', 'DIV /', 'ID b']),
+
+        # Numbers
+        (('3 3.3 0 0. 0.0 0.001 010 3.e2 3.e-2 3.e+2 3E2 3E+2 3E-2 '
+          '0.5e2 0.5e+2 0.5e-2 33 128.15 0x001 0X12ABCDEF 0xabcdef'),
+         ['NUMBER 3', 'NUMBER 3.3', 'NUMBER 0', 'NUMBER 0.', 'NUMBER 0.0',
+          'NUMBER 0.001', 'NUMBER 010', 'NUMBER 3.e2', 'NUMBER 3.e-2',
+          'NUMBER 3.e+2', 'NUMBER 3E2', 'NUMBER 3E+2', 'NUMBER 3E-2',
+          'NUMBER 0.5e2', 'NUMBER 0.5e+2', 'NUMBER 0.5e-2', 'NUMBER 33',
+          'NUMBER 128.15', 'NUMBER 0x001', 'NUMBER 0X12ABCDEF',
+          'NUMBER 0xabcdef']
+         ),
+
+        # Strings
+        (""" '"' """, ["""STRING '"'"""]),
+        (r'''"foo" 'foo' "x\";" 'x\';' "foo\tbar"''',
+         ['STRING "foo"', """STRING 'foo'""", r'STRING "x\";"',
+          r"STRING 'x\';'", r'STRING "foo\tbar"']
+         ),
+        (r"""'\x55' "\x12ABCDEF" '!@#$%^&*()_+{}[]\";?'""",
+         [r"STRING '\x55'", r'STRING "\x12ABCDEF"',
+          r"STRING '!@#$%^&*()_+{}[]\";?'"]
+         ),
+        (r"""'\u0001' "\uFCEF" 'a\\\b\n'""",
+         [r"STRING '\u0001'", r'STRING "\uFCEF"', r"STRING 'a\\\b\n'"]
+         ),
+        (ur'"тест строки\""', [ur'STRING "тест строки\""']),
+        # Bug - https://github.com/rspivak/slimit/issues/5
+        (r"var tagRegExp = new RegExp('<(\/*)(FooBar)', 'gi');",
+         ['VAR var', 'ID tagRegExp', 'EQ =',
+          'NEW new', 'ID RegExp', 'LPAREN (',
+          r"STRING '<(\/*)(FooBar)'", 'COMMA ,', "STRING 'gi'",
+          'RPAREN )', 'SEMI ;']
+        ),
+        # same as above but inside double quotes
+        (r'"<(\/*)(FooBar)"', [r'STRING "<(\/*)(FooBar)"']),
+        # multiline string (string written across multiple lines
+        # of code) https://github.com/rspivak/slimit/issues/24
+        (r"""var a = 'hello \
+world'""",
+         ['VAR var', 'ID a', 'EQ =', "STRING 'hello world'"]),
+        (r'''var a = "hello \
+world"''',
+         ['VAR var', 'ID a', 'EQ =', 'STRING "hello world"']),
+
+        # # Comments
+        # ("""
+        # //comment
+        # a = 5;
+        # """, ['LINE_COMMENT //comment', 'ID a', 'EQ =', 'NUMBER 5', 'SEMI ;']
+        #  ),
+        # ('a//comment', ['ID a', 'LINE_COMMENT //comment']),
+        # ('/***/b/=3//line',
+        #  ['BLOCK_COMMENT /***/', 'ID b', 'DIVEQUAL /=',
+        #   'NUMBER 3', 'LINE_COMMENT //line']
+        #  ),
+        # ('/*\n * Copyright LGPL 2011 \n*/\na = 1;',
+        #  ['BLOCK_COMMENT /*\n * Copyright LGPL 2011 \n*/',
+        #   'ID a', 'EQ =', 'NUMBER 1', 'SEMI ;']
+        #  ),
+
+        # regex
+        (r'a=/a*/,1', ['ID a', 'EQ =', 'REGEX /a*/', 'COMMA ,', 'NUMBER 1']),
+        (r'a=/a*[^/]+/,1',
+         ['ID a', 'EQ =', 'REGEX /a*[^/]+/', 'COMMA ,', 'NUMBER 1']
+         ),
+        (r'a=/a*\[^/,1',
+         ['ID a', 'EQ =', r'REGEX /a*\[^/', 'COMMA ,', 'NUMBER 1']
+         ),
+        (r'a=/\//,1', ['ID a', 'EQ =', r'REGEX /\//', 'COMMA ,', 'NUMBER 1']),
+        # not a regex, just a division
+        # https://github.com/rspivak/slimit/issues/6
+        (r'x = this / y;',
+         ['ID x', 'EQ =', 'THIS this', r'DIV /', r'ID y', r'SEMI ;']),
+
+        # next two are from
+        # http://www.mozilla.org/js/language/js20-2002-04/rationale/syntax.html#regular-expressions
+        ("""for (var x = a in foo && "</x>" || mot ? z:/x:3;x<5;y</g/i) {xyz(x++);}""",
+         ["FOR for", "LPAREN (", "VAR var", "ID x", "EQ =", "ID a", "IN in",
+          "ID foo", "AND &&", 'STRING "</x>"', "OR ||", "ID mot", "CONDOP ?",
+          "ID z", "COLON :", "REGEX /x:3;x<5;y</g", "DIV /", "ID i", "RPAREN )",
+          "LBRACE {",  "ID xyz", "LPAREN (", "ID x", "PLUSPLUS ++", "RPAREN )",
+          "SEMI ;", "RBRACE }"]
+         ),
+
+        ("""for (var x = a in foo && "</x>" || mot ? z/x:3;x<5;y</g/i) {xyz(x++);}""",
+         ["FOR for", "LPAREN (", "VAR var", "ID x", "EQ =", "ID a", "IN in",
+          "ID foo", "AND &&", 'STRING "</x>"', "OR ||", "ID mot", "CONDOP ?",
+          "ID z", "DIV /", "ID x", "COLON :", "NUMBER 3", "SEMI ;", "ID x",
+          "LT <", "NUMBER 5", "SEMI ;", "ID y", "LT <", "REGEX /g/i",
+          "RPAREN )", "LBRACE {", "ID xyz", "LPAREN (", "ID x", "PLUSPLUS ++",
+          "RPAREN )", "SEMI ;", "RBRACE }"]
+         ),
+
+        # Various "illegal" regexes that are valid according to the std.
+        (r"""/????/, /++++/, /[----]/ """,
+         ['REGEX /????/', 'COMMA ,',
+          'REGEX /++++/', 'COMMA ,', 'REGEX /[----]/']
+         ),
+
+        # Stress cases from http://stackoverflow.com/questions/5533925/what-javascript-constructs-does-jslex-incorrectly-lex/5573409#5573409
+        (r"""/\[/""", [r"""REGEX /\[/"""]),
+        (r"""/[i]/""", [r"""REGEX /[i]/"""]),
+        (r"""/[\]]/""", [r"""REGEX /[\]]/"""]),
+        (r"""/a[\]]/""", [r"""REGEX /a[\]]/"""]),
+        (r"""/a[\]]b/""", [r"""REGEX /a[\]]b/"""]),
+        (r"""/[\]/]/gi""", [r"""REGEX /[\]/]/gi"""]),
+        (r"""/\[[^\]]+\]/gi""", [r"""REGEX /\[[^\]]+\]/gi"""]),
+        ("""
+            rexl.re = {
+            NAME: /^(?!\d)(?:\w)+|^"(?:[^"]|"")+"/,
+            UNQUOTED_LITERAL: /^@(?:(?!\d)(?:\w|\:)+|^"(?:[^"]|"")+")\[[^\]]+\]/,
+            QUOTED_LITERAL: /^'(?:[^']|'')*'/,
+            NUMERIC_LITERAL: /^[0-9]+(?:\.[0-9]*(?:[eE][-+][0-9]+)?)?/,
+            SYMBOL: /^(?:==|=|<>|<=|<|>=|>|!~~|!~|~~|~|!==|!=|!~=|!~|!|&|\||\.|\:|,|\(|\)|\[|\]|\{|\}|\?|\:|;|@|\^|\/\+|\/|\*|\+|-)/
+            };
+            """,
+         ["ID rexl", "PERIOD .", "ID re", "EQ =", "LBRACE {",
+          "ID NAME", "COLON :",
+          r"""REGEX /^(?!\d)(?:\w)+|^"(?:[^"]|"")+"/""", "COMMA ,",
+          "ID UNQUOTED_LITERAL", "COLON :",
+          r"""REGEX /^@(?:(?!\d)(?:\w|\:)+|^"(?:[^"]|"")+")\[[^\]]+\]/""",
+          "COMMA ,", "ID QUOTED_LITERAL", "COLON :",
+          r"""REGEX /^'(?:[^']|'')*'/""", "COMMA ,", "ID NUMERIC_LITERAL",
+          "COLON :",
+          r"""REGEX /^[0-9]+(?:\.[0-9]*(?:[eE][-+][0-9]+)?)?/""", "COMMA ,",
+          "ID SYMBOL", "COLON :",
+          r"""REGEX /^(?:==|=|<>|<=|<|>=|>|!~~|!~|~~|~|!==|!=|!~=|!~|!|&|\||\.|\:|,|\(|\)|\[|\]|\{|\}|\?|\:|;|@|\^|\/\+|\/|\*|\+|-)/""",
+         "RBRACE }", "SEMI ;"]
+          ),
+        ("""
+            rexl.re = {
+            NAME: /^(?!\d)(?:\w)+|^"(?:[^"]|"")+"/,
+            UNQUOTED_LITERAL: /^@(?:(?!\d)(?:\w|\:)+|^"(?:[^"]|"")+")\[[^\]]+\]/,
+            QUOTED_LITERAL: /^'(?:[^']|'')*'/,
+            NUMERIC_LITERAL: /^[0-9]+(?:\.[0-9]*(?:[eE][-+][0-9]+)?)?/,
+            SYMBOL: /^(?:==|=|<>|<=|<|>=|>|!~~|!~|~~|~|!==|!=|!~=|!~|!|&|\||\.|\:|,|\(|\)|\[|\]|\{|\}|\?|\:|;|@|\^|\/\+|\/|\*|\+|-)/
+            };
+            str = '"';
+        """,
+        ["ID rexl", "PERIOD .", "ID re", "EQ =", "LBRACE {",
+         "ID NAME", "COLON :", r"""REGEX /^(?!\d)(?:\w)+|^"(?:[^"]|"")+"/""",
+         "COMMA ,", "ID UNQUOTED_LITERAL", "COLON :",
+         r"""REGEX /^@(?:(?!\d)(?:\w|\:)+|^"(?:[^"]|"")+")\[[^\]]+\]/""",
+         "COMMA ,", "ID QUOTED_LITERAL", "COLON :",
+         r"""REGEX /^'(?:[^']|'')*'/""", "COMMA ,",
+         "ID NUMERIC_LITERAL", "COLON :",
+         r"""REGEX /^[0-9]+(?:\.[0-9]*(?:[eE][-+][0-9]+)?)?/""", "COMMA ,",
+         "ID SYMBOL", "COLON :",
+         r"""REGEX /^(?:==|=|<>|<=|<|>=|>|!~~|!~|~~|~|!==|!=|!~=|!~|!|&|\||\.|\:|,|\(|\)|\[|\]|\{|\}|\?|\:|;|@|\^|\/\+|\/|\*|\+|-)/""",
+         "RBRACE }", "SEMI ;",
+         "ID str", "EQ =", """STRING '"'""", "SEMI ;",
+         ]),
+        (r""" this._js = "e.str(\"" + this.value.replace(/\\/g, "\\\\").replace(/"/g, "\\\"") + "\")"; """,
+         ["THIS this", "PERIOD .", "ID _js", "EQ =",
+          r'''STRING "e.str(\""''', "PLUS +", "THIS this", "PERIOD .",
+          "ID value", "PERIOD .", "ID replace", "LPAREN (", r"REGEX /\\/g",
+          "COMMA ,", r'STRING "\\\\"', "RPAREN )", "PERIOD .", "ID replace",
+          "LPAREN (", r'REGEX /"/g', "COMMA ,", r'STRING "\\\""', "RPAREN )",
+          "PLUS +", r'STRING "\")"', "SEMI ;"]),
+        ]
+
+
+def test_suite():
+    return unittest.TestSuite((
+        unittest.makeSuite(LexerTestCase),
+        doctest.DocFileSuite(
+            '../lexer.py',
+            optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS
+            ),
+        ))
diff --git a/webWidgetTCT_device/tools/slimit/tests/test_mangler.py b/webWidgetTCT_device/tools/slimit/tests/test_mangler.py
new file mode 100755 (executable)
index 0000000..111429e
--- /dev/null
@@ -0,0 +1,159 @@
+###############################################################################
+#
+# Copyright (c) 2011 Ruslan Spivak
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+###############################################################################
+
+__author__ = 'Ruslan Spivak <ruslan.spivak@gmail.com>'
+
+import textwrap
+import unittest
+
+from slimit.parser import Parser
+from slimit.mangler import mangle
+
+
+def decorator(cls):
+    def make_test_function(input, expected):
+        def test_func(self):
+            parser = Parser()
+            tree = parser.parse(input)
+            mangle(tree, toplevel=True)
+            self.assertMultiLineEqual(
+                textwrap.dedent(tree.to_ecma()).strip(),
+                textwrap.dedent(expected).strip()
+                )
+
+        return test_func
+
+    for index, (input, expected) in enumerate(cls.TEST_CASES):
+        func = make_test_function(input, expected)
+        setattr(cls, 'test_case_%d' % index, func)
+
+    return cls
+
+
+@decorator
+class ManglerTestCase(unittest.TestCase):
+
+    TEST_CASES = [
+        # test nested function declaration
+        # test that object properties ids are not changed
+        ("""
+        function test() {
+          function is_false() {
+            var xpos = 5;
+            var point = {
+              xpos: 17,
+              ypos: 10
+            };
+            return true;
+          }
+        }
+        """,
+         """
+         function a() {
+           function a() {
+             var a = 5;
+             var b = {
+               xpos: 17,
+               ypos: 10
+             };
+             return true;
+           }
+         }
+         """),
+
+        # test that mangled names are not shadowed when we reference
+        # original names from any sub-scope
+        ("""
+        var result = function() {
+          var long_name = 'long name';
+          var not_so_long = 'indeed', log = 5;
+          global_x = 56;
+          console.log(long_name + not_so_long);
+          new_result = function(arg1, arg2) {
+            var arg2 = 'qwerty';
+            console.log(long_name + not_so_long + arg1 + arg2 + global_x);
+          };
+        };
+        """,
+         """
+         var a = function() {
+           var a = 'long name';
+           var b = 'indeed', c = 5;
+           global_x = 56;
+           console.log(a + b);
+           new_result = function(c, d) {
+             var d = 'qwerty';
+             console.log(a + b + c + d + global_x);
+           };
+         };
+         """),
+
+        # https://github.com/rspivak/slimit/issues/7
+        ("""
+        function a() {
+          var $exc1 = null;
+          try {
+            lala();
+          } catch($exc) {
+            if ($exc.__name__ == 'hi') {
+              return 'bam';
+            }
+          }
+          return 'bum';
+        }
+        """,
+         """
+         function a() {
+           var a = null;
+           try {
+             lala();
+           } catch (b) {
+             if (b.__name__ == 'hi') {
+               return 'bam';
+             }
+           }
+           return 'bum';
+         }
+         """),
+
+        # Handle the case when function arguments are redefined;
+        # in the example below statement arg = 9; doesn't create
+        # a global variable -it changes the value of arguments[0].
+        # The same is with statement var arg = 0;
+        # http://spin.atomicobject.com/2011/04/10/javascript-don-t-reassign-your-function-arguments/
+        ("""
+        function a(arg) {
+          arg = 9;
+          var arg = 0;
+          return arg;
+        }
+        """,
+         """
+         function a(a) {
+           a = 9;
+           var a = 0;
+           return a;
+         }
+         """),
+        ]
diff --git a/webWidgetTCT_device/tools/slimit/tests/test_minifier.py b/webWidgetTCT_device/tools/slimit/tests/test_minifier.py
new file mode 100755 (executable)
index 0000000..e999335
--- /dev/null
@@ -0,0 +1,470 @@
+###############################################################################
+#
+# Copyright (c) 2011 Ruslan Spivak
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+###############################################################################
+
+__author__ = 'Ruslan Spivak <ruslan.spivak@gmail.com>'
+
+import unittest
+
+from slimit import minify
+
+
+def decorator(cls):
+    def make_test_function(input, expected):
+
+        def test_func(self):
+            self.assertMinified(input, expected)
+
+        return test_func
+
+    for index, (input, expected) in enumerate(cls.TEST_CASES):
+        func = make_test_function(input, expected)
+        setattr(cls, 'test_case_%d' % index, func)
+
+    return cls
+
+
+@decorator
+class MinifierTestCase(unittest.TestCase):
+
+    def assertMinified(self, source, expected):
+        minified = minify(source)
+        self.maxDiff = None
+        self.assertSequenceEqual(minified, expected)
+
+    TEST_CASES = [
+        ("""
+        jQuery.fn = jQuery.prototype = {
+                // For internal use only.
+                _data: function( elem, name, data ) {
+                        return jQuery.data( elem, name, data, true );
+                }
+        };
+        """,
+         'jQuery.fn=jQuery.prototype={_data:function(elem,name,data){return jQuery.data(elem,name,data,true);}};'),
+
+        ('context = context instanceof jQuery ? context[0] : context;',
+         'context=context instanceof jQuery?context[0]:context;'
+         ),
+
+        ("""
+        /*
+        * A number of helper functions used for managing events.
+        * Many of the ideas behind this code originated from
+        * Dean Edwards' addEvent library.
+        */
+        if ( elem && elem.parentNode ) {
+                // Handle the case where IE and Opera return items
+                // by name instead of ID
+                if ( elem.id !== match[2] ) {
+                        return rootjQuery.find( selector );
+                }
+
+                // Otherwise, we inject the element directly into the jQuery object
+                this.length = 1;
+                this[0] = elem;
+        }
+        """,
+
+         'if(elem&&elem.parentNode){if(elem.id!==match[2])return rootjQuery.find(selector);this.length=1;this[0]=elem;}'
+         ),
+
+        ("""
+        var a = function( obj ) {
+                for ( var name in obj ) {
+                        return false;
+                }
+                return true;
+        };
+        """,
+         'var a=function(obj){for(var name in obj)return false;return true;};'
+         ),
+
+        ("""
+        x = "string", y = 5;
+
+        (x = 5) ? true : false;
+
+        for (p in obj)
+        ;
+
+        if (true)
+          val = null;
+        else
+          val = false;
+
+        """,
+         'x="string",y=5;(x=5)?true:false;for(p in obj);if(true)val=null;else val=false;'
+         ),
+
+        # for loops + empty statement in loop body
+        ("""
+        for (x = 0; true; x++)
+        ;
+        for (; true; x++)
+        ;
+        for (x = 0, y = 5; true; x++)
+        ;
+
+        y = (x + 5) * 20;
+
+        """,
+         'for(x=0;true;x++);for(;true;x++);for(x=0,y=5;true;x++);y=(x+5)*20;'),
+
+
+        # unary expressions
+        ("""
+        delete x;
+        typeof x;
+        void x;
+        x += (!y)++;
+        """,
+         'delete x;typeof x;void x;x+=(!y)++;'),
+
+        # label + break label + continue label
+        ("""
+        label:
+        if ( i == 0 )
+          continue label;
+        switch (day) {
+        case 5:
+          break ;
+        default:
+          break label;
+        }
+        """,
+         'label:if(i==0)continue label;switch(day){case 5:break;default:break label;}'),
+
+        # break + continue: no labels
+        ("""
+        while (i <= 7) {
+          if ( i == 3 )
+              continue;
+          if ( i == 0 )
+              break;
+        }
+        """,
+         'while(i<=7){if(i==3)continue;if(i==0)break;}'),
+
+        # regex + one line statements in if and if .. else
+        ("""
+        function a(x, y) {
+         var re = /ab+c/;
+         if (x == 1)
+           return x + y;
+         if (x == 3)
+           return {x: 1};
+         else
+           return;
+        }
+        """,
+         'function a(x,y){var re=/ab+c/;if(x==1)return x+y;if(x==3)return{x:1};else return;}'),
+
+        # new
+        ('return new jQuery.fn.init( selector, context, rootjQuery );',
+         'return new jQuery.fn.init(selector,context,rootjQuery);'
+         ),
+
+        # no space after 'else' when the next token is (, {
+        ("""
+        if (true) {
+          x = true;
+          y = 3;
+        } else {
+          x = false
+          y = 5
+        }
+        """,
+         'if(true){x=true;y=3;}else{x=false;y=5;}'),
+
+        ("""
+        if (true) {
+          x = true;
+          y = 3;
+        } else
+          (x + ' qw').split(' ');
+        """,
+         "if(true){x=true;y=3;}else(x+' qw').split(' ');"),
+
+
+        ##############################################################
+        # Block braces removal
+        ##############################################################
+
+        # do while
+        ('do { x += 1; } while(true);', 'do x+=1;while(true);'),
+        # do while: multiple statements
+        ('do { x += 1; y += 1;} while(true);', 'do{x+=1;y+=1;}while(true);'),
+
+        # elision
+        ('var a = [1, 2, 3, ,,,5];', 'var a=[1,2,3,,,,5];'),
+
+        # with
+        ("""
+        with (obj) {
+          a = b;
+        }
+        """,
+         'with(obj)a=b;'),
+
+        # with: multiple statements
+        ("""
+        with (obj) {
+          a = b;
+          c = d;
+        }
+        """,
+         'with(obj){a=b;c=d;}'),
+
+        # if else
+        ("""
+        if (true) {
+          x = true;
+        } else {
+          x = false
+        }
+        """,
+         'if(true)x=true;else x=false;'),
+
+        # if: multiple statements
+        ("""
+        if (true) {
+          x = true;
+          y = false;
+        } else {
+          x = false;
+          y = true;
+        }
+        """,
+         'if(true){x=true;y=false;}else{x=false;y=true;}'),
+
+        # try catch finally: one statement
+        ("""
+        try {
+          throw "my_exception"; // generates an exception
+        }
+        catch (e) {
+          // statements to handle any exceptions
+          log(e); // pass exception object to error handler
+        }
+        finally {
+          closefiles(); // always close the resource
+        }
+        """,
+         'try{throw "my_exception";}catch(e){log(e);}finally{closefiles();}'
+         ),
+
+        # try catch finally: no statements
+        ("""
+        try {
+        }
+        catch (e) {
+        }
+        finally {
+        }
+        """,
+         'try{}catch(e){}finally{}'
+         ),
+
+        # try catch finally: multiple statements
+        ("""
+        try {
+          x = 3;
+          y = 5;
+        }
+        catch (e) {
+          log(e);
+          log('e');
+        }
+        finally {
+          z = 7;
+          log('z');
+        }
+        """,
+         "try{x=3;y=5;}catch(e){log(e);log('e');}finally{z=7;log('z');}"
+         ),
+
+        # tricky case with an 'if' nested in 'if .. else'
+        # We need to preserve braces in the first 'if' otherwise
+        # 'else' might get associated with nested 'if' instead
+        ("""
+        if ( obj ) {
+                for ( n in obj ) {
+                        if ( v === false) {
+                                break;
+                        }
+                }
+        } else {
+                for ( ; i < l; ) {
+                        if ( nv === false ) {
+                                break;
+                        }
+                }
+        }
+        """,
+         'if(obj){for(n in obj)if(v===false)break;}else for(;i<l;)if(nv===false)break;'),
+
+        # We don't care about nested 'if' when enclosing 'if' block
+        # contains multiple statements because braces won't be removed
+        # by visit_Block when there are multiple statements in the block
+        ("""
+        if ( obj ) {
+                for ( n in obj ) {
+                        if ( v === false) {
+                                break;
+                        }
+                }
+                x = 5;
+        } else {
+                for ( ; i < l; ) {
+                        if ( nv === false ) {
+                                break;
+                        }
+                }
+        }
+        """,
+         'if(obj){for(n in obj)if(v===false)break;x=5;}else for(;i<l;)if(nv===false)break;'),
+
+
+        # No dangling 'else' - remove braces
+        ("""
+        if ( obj ) {
+                for ( n in obj ) {
+                        if ( v === false) {
+                                break;
+                        } else {
+                                n = 3;
+                        }
+                }
+        } else {
+                for ( ; i < l; ) {
+                        if ( nv === false ) {
+                                break;
+                        }
+                }
+        }
+        """,
+         'if(obj)for(n in obj)if(v===false)break;else n=3;else for(;i<l;)if(nv===false)break;'),
+
+        # foo["bar"] --> foo.bar
+        ('foo["bar"];', 'foo.bar;'),
+        ("foo['bar'];", 'foo.bar;'),
+        ("""foo['bar"']=42;""", """foo['bar"']=42;"""),
+        ("""foo["bar'"]=42;""", """foo["bar'"]=42;"""),
+        ('foo["bar bar"];', 'foo["bar bar"];'),
+        ('foo["bar"+"bar"];', 'foo["bar"+"bar"];'),
+        # https://github.com/rspivak/slimit/issues/34
+        # test some reserved keywords
+        ('foo["for"];', 'foo["for"];'),
+        ('foo["class"];', 'foo["class"];'),
+
+
+        # https://github.com/rspivak/slimit/issues/21
+        # c||(c=393,a=323,b=2321); --> c||c=393,a=323,b=2321; ERROR
+        ('c||(c=393);', 'c||(c=393);'),
+        ('c||(c=393,a=323,b=2321);', 'c||(c=393,a=323,b=2321);'),
+
+        # https://github.com/rspivak/slimit/issues/25
+        ('for(a?b:c;d;)e=1;', 'for(a?b:c;d;)e=1;'),
+
+        # https://github.com/rspivak/slimit/issues/26
+        ('"begin"+ ++a+"end";', '"begin"+ ++a+"end";'),
+
+        # https://github.com/rspivak/slimit/issues/28
+        ("""
+         (function($) {
+             $.hello = 'world';
+         }(jQuery));
+         """,
+         "(function($){$.hello='world';}(jQuery));"),
+
+        # function call in FOR init
+        ('for(o(); i < 3; i++) {}', 'for(o();i<3;i++){}'),
+
+        # unary increment operator in FOR init
+        ('for(i++; i < 3; i++) {}', 'for(i++;i<3;i++){}'),
+
+        # unary decrement operator in FOR init
+        ('for(i--; i < 3; i++) {}', 'for(i--;i<3;i++){}'),
+
+        # issue-37, simple identifier in FOR init
+        ('for(i; i < 3; i++) {}', 'for(i;i<3;i++){}'),
+
+        # https://github.com/rspivak/slimit/issues/32
+        ("""
+         Name.prototype = {
+           getPageProp: function Page_getPageProp(key) {
+             return this.pageDict.get(key);
+           },
+
+           get fullName() {
+             return this.first + " " + this.last;
+           },
+
+           set fullName(name) {
+             var names = name.split(" ");
+             this.first = names[0];
+             this.last = names[1];
+           }
+         };
+         """,
+         ('Name.prototype={getPageProp:function Page_getPageProp(key){'
+          'return this.pageDict.get(key);},'
+          'get fullName(){return this.first+" "+this.last;},'
+          'set fullName(name){var names=name.split(" ");this.first=names[0];'
+          'this.last=names[1];}};')
+        ),
+
+        # https://github.com/rspivak/slimit/issues/47 - might be a Python 3
+        # related issue
+        ('testObj[":"] = undefined; // Breaks', 'testObj[":"]=undefined;'),
+        ('testObj["::"] = undefined; // Breaks', 'testObj["::"]=undefined;'),
+        ('testObj["a:"] = undefined; // Breaks', 'testObj["a:"]=undefined;'),
+        ('testObj["."] = undefined; // OK', 'testObj["."]=undefined;'),
+        ('testObj["{"] = undefined; // OK', 'testObj["{"]=undefined;'),
+        ('testObj["}"] = undefined; // OK', 'testObj["}"]=undefined;'),
+        ('testObj["["] = undefined; // Breaks', 'testObj["["]=undefined;'),
+        ('testObj["]"] = undefined; // Breaks', 'testObj["]"]=undefined;'),
+        ('testObj["("] = undefined; // OK', 'testObj["("]=undefined;'),
+        ('testObj[")"] = undefined; // OK', 'testObj[")"]=undefined;'),
+        ('testObj["="] = undefined; // Breaks', 'testObj["="]=undefined;'),
+        ('testObj["-"] = undefined; // OK', 'testObj["-"]=undefined;'),
+        ('testObj["+"] = undefined; // OK', 'testObj["+"]=undefined;'),
+        ('testObj["*"] = undefined; // OK', 'testObj["*"]=undefined;'),
+        ('testObj["/"] = undefined; // OK', 'testObj["/"]=undefined;'),
+        (r'testObj["\\"] = undefined; // Breaks', r'testObj["\\"]=undefined;'),
+        ('testObj["%"] = undefined; // OK', 'testObj["%"]=undefined;'),
+        ('testObj["<"] = undefined; // Breaks', 'testObj["<"]=undefined;'),
+        ('testObj[">"] = undefined; // Breaks', 'testObj[">"]=undefined;'),
+        ('testObj["!"] = undefined; // OK', 'testObj["!"]=undefined;'),
+        ('testObj["?"] = undefined; // Breaks', 'testObj["?"]=undefined;'),
+        ('testObj[","] = undefined; // OK', 'testObj[","]=undefined;'),
+        ('testObj["@"] = undefined; // Breaks', 'testObj["@"]=undefined;'),
+        ('testObj["#"] = undefined; // OK', 'testObj["#"]=undefined;'),
+        ('testObj["&"] = undefined; // OK', 'testObj["&"]=undefined;'),
+        ('testObj["|"] = undefined; // OK', 'testObj["|"]=undefined;'),
+        ('testObj["~"] = undefined; // OK', 'testObj["~"]=undefined;'),
+        ('testObj["`"] = undefined; // Breaks', 'testObj["`"]=undefined;'),
+        ('testObj["."] = undefined; // OK', 'testObj["."]=undefined;'),
+        ]
+
diff --git a/webWidgetTCT_device/tools/slimit/tests/test_nodevisitor.py b/webWidgetTCT_device/tools/slimit/tests/test_nodevisitor.py
new file mode 100755 (executable)
index 0000000..a6a5c7e
--- /dev/null
@@ -0,0 +1,37 @@
+###############################################################################
+#
+# Copyright (c) 2011 Ruslan Spivak
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+###############################################################################
+
+__author__ = 'Ruslan Spivak <ruslan.spivak@gmail.com>'
+
+import doctest
+import unittest
+
+
+def test_suite():
+    return unittest.TestSuite((
+        doctest.DocFileSuite(
+            '../visitors/nodevisitor.py',
+            optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS
+            ),
+        ))
diff --git a/webWidgetTCT_device/tools/slimit/tests/test_parser.py b/webWidgetTCT_device/tools/slimit/tests/test_parser.py
new file mode 100755 (executable)
index 0000000..f0e98fe
--- /dev/null
@@ -0,0 +1,243 @@
+###############################################################################
+#
+# Copyright (c) 2011-2012 Ruslan Spivak
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+###############################################################################
+
+__author__ = 'Ruslan Spivak <ruslan.spivak@gmail.com>'
+
+import textwrap
+import unittest
+
+from slimit import ast
+from slimit.parser import Parser
+from slimit.visitors import nodevisitor
+
+
+def decorator(cls):
+    def make_test_function(input, expected):
+
+        def test_func(self):
+            parser = Parser()
+            result = parser.parse(input).to_ecma()
+            self.assertMultiLineEqual(result, expected)
+
+        return test_func
+
+    for index, (input, expected) in enumerate(cls.TEST_CASES):
+        input = textwrap.dedent(input).strip()
+        expected = textwrap.dedent(expected).strip()
+        func = make_test_function(input, expected)
+        setattr(cls, 'test_case_%d' % index, func)
+
+    return cls
+
+
+class ParserTestCase(unittest.TestCase):
+
+    def test_line_terminator_at_the_end_of_file(self):
+        parser = Parser()
+        parser.parse('var $_ = function(x){}(window);\n')
+
+    # XXX: function expression ?
+    def _test_function_expression(self):
+        text = """
+        if (true) {
+          function() {
+            foo;
+            location = 'http://anywhere.com';
+          }
+        }
+        """
+        parser = Parser()
+        parser.parse(text)
+
+    def test_modify_tree(self):
+        text = """
+        for (var i = 0; i < 10; i++) {
+          var x = 5 + i;
+        }
+        """
+        parser = Parser()
+        tree = parser.parse(text)
+        for node in nodevisitor.visit(tree):
+            if isinstance(node, ast.Identifier) and node.value == 'i':
+                node.value = 'hello'
+        self.assertMultiLineEqual(
+            tree.to_ecma(),
+            textwrap.dedent("""
+            for (var hello = 0; hello < 10; hello++) {
+              var x = 5 + hello;
+            }
+            """).strip()
+            )
+
+    def test_bug_no_semicolon_at_the_end_of_block_plus_newline_at_eof(self):
+        # https://github.com/rspivak/slimit/issues/3
+        text = textwrap.dedent("""
+        function add(x, y) {
+          return x + y;
+        }
+        """)
+        parser = Parser()
+        tree = parser.parse(text)
+        self.assertTrue(bool(tree.children()))
+
+    def test_function_expression_is_part_of_member_expr_nobf(self):
+        # https://github.com/rspivak/slimit/issues/22
+        # The problem happened to be that function_expr was not
+        # part of member_expr_nobf rule
+        text = 'window.done_already || function () { return "slimit!" ; }();'
+        self.assertTrue(bool(Parser().parse(text).children()))
+
+    # https://github.com/rspivak/slimit/issues/29
+    def test_that_parsing_eventually_stops(self):
+        text = """var a;
+        , b;"""
+        parser = Parser()
+        self.assertRaises(SyntaxError, parser.parse, text)
+
+
+@decorator
+class ASITestCase(unittest.TestCase):
+    TEST_CASES = [
+        ("""
+        switch (day) {
+          case 1:
+            result = 'Mon';
+            break
+          case 2:
+            break
+        }
+        """,
+         """
+         switch (day) {
+           case 1:
+             result = 'Mon';
+             break;
+           case 2:
+             break;
+         }
+         """),
+
+        ("""
+        while (true)
+          continue
+        a = 1;
+        """,
+         """
+         while (true) continue;
+         a = 1;
+         """),
+
+        ("""
+        return
+        a;
+        """,
+        """
+         return;
+         a;
+        """),
+        # test 3
+        ("""
+        x = 5
+        """,
+         """
+         x = 5;
+         """),
+
+        ("""
+        var a, b
+        var x
+        """,
+         """
+         var a, b;
+         var x;
+         """),
+
+        ("""
+        var a, b
+        var x
+        """,
+         """
+         var a, b;
+         var x;
+         """),
+
+        # test 6
+        ("""
+        return
+        a + b
+        """,
+         """
+         return;
+         a + b;
+         """),
+
+        ('while (true) ;', 'while (true) ;'),
+
+        ("""
+        if (x) {
+          y()
+        }
+        """,
+         """
+         if (x) {
+           y();
+         }
+         """),
+
+        # test 9
+        ("""
+        for ( ; i < length; i++) {
+        }
+        """,
+         """
+         for ( ; i < length; i++) {
+
+         }
+         """),
+
+        ("""
+        var i;
+        for (i; i < length; i++) {
+        }
+        """,
+         """
+         var i;
+         for (i; i < length; i++) {
+
+         }
+         """),
+        ]
+
+    def test_throw_statement(self):
+        # expression is not optional in throw statement
+        input = textwrap.dedent("""
+        throw
+          'exc';
+        """)
+        parser = Parser()
+        # ASI at lexer level should insert ';' after throw
+        self.assertRaises(SyntaxError, parser.parse, input)
+
+
+
diff --git a/webWidgetTCT_device/tools/slimit/unicode_chars.py b/webWidgetTCT_device/tools/slimit/unicode_chars.py
new file mode 100755 (executable)
index 0000000..eec4411
--- /dev/null
@@ -0,0 +1,156 @@
+###############################################################################
+#
+# Copyright (c) 2011 Ruslan Spivak
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+###############################################################################
+
+__author__ = 'Ruslan Spivak <ruslan.spivak@gmail.com>'
+
+# Reference - http://xregexp.com/plugins/#unicode
+# Adapted from https://github.com/mishoo/UglifyJS/blob/master/lib/parse-js.js
+
+# 'Uppercase letter (Lu)', 'Lowercase letter (Ll)',
+# 'Titlecase letter(Lt)', 'Modifier letter (Lm)', 'Other letter (Lo)'
+LETTER = (
+    ur'[\u0041-\u005A\u0061-\u007A\u00AA\u00B5\u00BA\u00C0-\u00D6\u00D8-\u00F6'
+    ur'\u00F8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376'
+    ur'\u0377\u037A-\u037D\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5'
+    ur'\u03F7-\u0481\u048A-\u0523\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA'
+    ur'\u05F0-\u05F2\u0621-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6'
+    ur'\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1'
+    ur'\u07CA-\u07EA\u07F4\u07F5\u07FA\u0904-\u0939\u093D\u0950\u0958-\u0961'
+    ur'\u0971\u0972\u097B-\u097F\u0985-\u098C\u098F\u0990\u0993-\u09A8'
+    ur'\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1'
+    ur'\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32'
+    ur'\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74'
+    ur'\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3'
+    ur'\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C\u0B0F\u0B10'
+    ur'\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D'
+    ur'\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99'
+    ur'\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0'
+    ur'\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C3D'
+    ur'\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8'
+    ur'\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0D05-\u0D0C'
+    ur'\u0D0E-\u0D10\u0D12-\u0D28\u0D2A-\u0D39\u0D3D\u0D60\u0D61\u0D7A-\u0D7F'
+    ur'\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30'
+    ur'\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D'
+    ur'\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB'
+    ur'\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC\u0EDD\u0F00'
+    ur'\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8B\u1000-\u102A\u103F\u1050-\u1055'
+    ur'\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E'
+    ur'\u10A0-\u10C5\u10D0-\u10FA\u10FC\u1100-\u1159\u115F-\u11A2\u11A8-\u11F9'
+    ur'\u1200-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288'
+    ur'\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5'
+    ur'\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F'
+    ur'\u13A0-\u13F4\u1401-\u166C\u166F-\u1676\u1681-\u169A\u16A0-\u16EA'
+    ur'\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C'
+    ur'\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA'
+    ur'\u1900-\u191C\u1950-\u196D\u1970-\u1974\u1980-\u19A9\u19C1-\u19C7'
+    ur'\u1A00-\u1A16\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF'
+    ur'\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1D00-\u1DBF\u1E00-\u1F15'
+    ur'\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D'
+    ur'\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC'
+    ur'\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071'
+    ur'\u207F\u2090-\u2094\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124'
+    ur'\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E'
+    ur'\u2183\u2184\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2C6F\u2C71-\u2C7D'
+    ur'\u2C80-\u2CE4\u2D00-\u2D25\u2D30-\u2D65\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6'
+    ur'\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE'
+    ur'\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C'
+    ur'\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D'
+    ur'\u3131-\u318E\u31A0-\u31B7\u31F0-\u31FF\u3400\u4DB5\u4E00\u9FC3'
+    ur'\uA000-\uA48C\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA65F'
+    ur'\uA662-\uA66E\uA67F-\uA697\uA717-\uA71F\uA722-\uA788\uA78B\uA78C'
+    ur'\uA7FB-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873'
+    ur'\uA882-\uA8B3\uA90A-\uA925\uA930-\uA946\uAA00-\uAA28\uAA40-\uAA42'
+    ur'\uAA44-\uAA4B\uAC00\uD7A3\uF900-\uFA2D\uFA30-\uFA6A\uFA70-\uFAD9'
+    ur'\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C'
+    ur'\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F'
+    ur'\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A'
+    ur'\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7'
+    ur'\uFFDA-\uFFDC]'
+    )
+
+NON_SPACING_MARK = (
+    ur'[\u0300-\u036F\u0483-\u0487\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5'
+    ur'\u05C7\u0610-\u061A\u064B-\u065E\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7'
+    ur'\u06E8\u06EA-\u06ED\u0711\u0730-\u074A\u07A6-\u07B0\u07EB-\u07F3'
+    ur'\u0816-\u0819\u081B-\u0823\u0825-\u0827\u0829-\u082D\u0900-\u0902\u093C'
+    ur'\u0941-\u0948\u094D\u0951-\u0955\u0962\u0963\u0981\u09BC\u09C1-\u09C4'
+    ur'\u09CD\u09E2\u09E3\u0A01\u0A02\u0A3C\u0A41\u0A42\u0A47\u0A48'
+    ur'\u0A4B-\u0A4D\u0A51\u0A70\u0A71\u0A75\u0A81\u0A82\u0ABC\u0AC1-\u0AC5'
+    ur'\u0AC7\u0AC8\u0ACD\u0AE2\u0AE3\u0B01\u0B3C\u0B3F\u0B41-\u0B44\u0B4D'
+    ur'\u0B56\u0B62\u0B63\u0B82\u0BC0\u0BCD\u0C3E-\u0C40\u0C46-\u0C48'
+    ur'\u0C4A-\u0C4D\u0C55\u0C56\u0C62\u0C63\u0CBC\u0CBF\u0CC6\u0CCC\u0CCD'
+    ur'\u0CE2\u0CE3\u0D41-\u0D44\u0D4D\u0D62\u0D63\u0DCA\u0DD2-\u0DD4\u0DD6'
+    ur'\u0E31\u0E34-\u0E3A\u0E47-\u0E4E\u0EB1\u0EB4-\u0EB9\u0EBB\u0EBC'
+    ur'\u0EC8-\u0ECD\u0F18\u0F19\u0F35\u0F37\u0F39\u0F71-\u0F7E\u0F80-\u0F84'
+    ur'\u0F86\u0F87\u0F90-\u0F97\u0F99-\u0FBC\u0FC6\u102D-\u1030\u1032-\u1037'
+    ur'\u1039\u103A\u103D\u103E\u1058\u1059\u105E-\u1060\u1071-\u1074\u1082'
+    ur'\u1085\u1086\u108D\u109D\u135F\u1712-\u1714\u1732-\u1734\u1752\u1753'
+    ur'\u1772\u1773\u17B7-\u17BD\u17C6\u17C9-\u17D3\u17DD\u180B-\u180D\u18A9'
+    ur'\u1920-\u1922\u1927\u1928\u1932\u1939-\u193B\u1A17\u1A18\u1A56'
+    ur'\u1A58-\u1A5E\u1A60\u1A62\u1A65-\u1A6C\u1A73-\u1A7C\u1A7F\u1B00-\u1B03'
+    ur'\u1B34\u1B36-\u1B3A\u1B3C\u1B42\u1B6B-\u1B73\u1B80\u1B81\u1BA2-\u1BA5'
+    ur'\u1BA8\u1BA9\u1C2C-\u1C33\u1C36\u1C37\u1CD0-\u1CD2\u1CD4-\u1CE0'
+    ur'\u1CE2-\u1CE8\u1CED\u1DC0-\u1DE6\u1DFD-\u1DFF\u20D0-\u20DC\u20E1'
+    ur'\u20E5-\u20F0\u2CEF-\u2CF1\u2DE0-\u2DFF\u302A-\u302F\u3099\u309A\uA66F'
+    ur'\uA67C\uA67D\uA6F0\uA6F1\uA802\uA806\uA80B\uA825\uA826\uA8C4'
+    ur'\uA8E0-\uA8F1\uA926-\uA92D\uA947-\uA951\uA980-\uA982\uA9B3\uA9B6-\uA9B9'
+    ur'\uA9BC\uAA29-\uAA2E\uAA31\uAA32\uAA35\uAA36\uAA43\uAA4C\uAAB0'
+    ur'\uAAB2-\uAAB4\uAAB7\uAAB8\uAABE\uAABF\uAAC1\uABE5\uABE8\uABED\uFB1E'
+    ur'\uFE00-\uFE0F\uFE20-\uFE26]'
+    )
+
+COMBINING_SPACING_MARK = (
+    ur'[\u0903\u093E-\u0940\u0949-\u094C\u094E\u0982\u0983\u09BE-\u09C0\u09C7'
+    ur'\u09C8\u09CB\u09CC\u09D7\u0A03\u0A3E-\u0A40\u0A83\u0ABE-\u0AC0\u0AC9'
+    ur'\u0ACB\u0ACC\u0B02\u0B03\u0B3E\u0B40\u0B47\u0B48\u0B4B\u0B4C\u0B57'
+    ur'\u0BBE\u0BBF\u0BC1\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCC\u0BD7\u0C01-\u0C03'
+    ur'\u0C41-\u0C44\u0C82\u0C83\u0CBE\u0CC0-\u0CC4\u0CC7\u0CC8\u0CCA\u0CCB'
+    ur'\u0CD5\u0CD6\u0D02\u0D03\u0D3E-\u0D40\u0D46-\u0D48\u0D4A-\u0D4C\u0D57'
+    ur'\u0D82\u0D83\u0DCF-\u0DD1\u0DD8-\u0DDF\u0DF2\u0DF3\u0F3E\u0F3F\u0F7F'
+    ur'\u102B\u102C\u1031\u1038\u103B\u103C\u1056\u1057\u1062-\u1064'
+    ur'\u1067-\u106D\u1083\u1084\u1087-\u108C\u108F\u109A-\u109C\u17B6'
+    ur'\u17BE-\u17C5\u17C7\u17C8\u1923-\u1926\u1929-\u192B\u1930\u1931'
+    ur'\u1933-\u1938\u19B0-\u19C0\u19C8\u19C9\u1A19-\u1A1B\u1A55\u1A57\u1A61'
+    ur'\u1A63\u1A64\u1A6D-\u1A72\u1B04\u1B35\u1B3B\u1B3D-\u1B41\u1B43\u1B44'
+    ur'\u1B82\u1BA1\u1BA6\u1BA7\u1BAA\u1C24-\u1C2B\u1C34\u1C35\u1CE1\u1CF2'
+    ur'\uA823\uA824\uA827\uA880\uA881\uA8B4-\uA8C3\uA952\uA953\uA983\uA9B4'
+    ur'\uA9B5\uA9BA\uA9BB\uA9BD-\uA9C0\uAA2F\uAA30\uAA33\uAA34\uAA4D\uAA7B'
+    ur'\uABE3\uABE4\uABE6\uABE7\uABE9\uABEA\uABEC]'
+    )
+
+COMBINING_MARK = ur'%s|%s' % (NON_SPACING_MARK, COMBINING_SPACING_MARK)
+
+CONNECTOR_PUNCTUATION = (
+        ur'[\u005F\u203F\u2040\u2054\uFE33\uFE34\uFE4D-\uFE4F\uFF3F]'
+        )
+
+DIGIT = (
+    ur'[\u0030-\u0039\u0660-\u0669\u06F0-\u06F9\u07C0-\u07C9\u0966-\u096F'
+    ur'\u09E6-\u09EF\u0A66-\u0A6F\u0AE6-\u0AEF\u0B66-\u0B6F\u0BE6-\u0BEF'
+    ur'\u0C66-\u0C6F\u0CE6-\u0CEF\u0D66-\u0D6F\u0E50-\u0E59\u0ED0-\u0ED9'
+    ur'\u0F20-\u0F29\u1040-\u1049\u1090-\u1099\u17E0-\u17E9\u1810-\u1819'
+    ur'\u1946-\u194F\u19D0-\u19DA\u1A80-\u1A89\u1A90-\u1A99\u1B50-\u1B59'
+    ur'\u1BB0-\u1BB9\u1C40-\u1C49\u1C50-\u1C59\uA620-\uA629\uA8D0-\uA8D9'
+    ur'\uA900-\uA909\uA9D0-\uA9D9\uAA50-\uAA59\uABF0-\uABF9\uFF10-\uFF19]'
+    )
diff --git a/webWidgetTCT_device/tools/slimit/visitors/__init__.py b/webWidgetTCT_device/tools/slimit/visitors/__init__.py
new file mode 100755 (executable)
index 0000000..8b13789
--- /dev/null
@@ -0,0 +1 @@
+
diff --git a/webWidgetTCT_device/tools/slimit/visitors/ecmavisitor.py b/webWidgetTCT_device/tools/slimit/visitors/ecmavisitor.py
new file mode 100755 (executable)
index 0000000..1c98598
--- /dev/null
@@ -0,0 +1,397 @@
+###############################################################################
+#
+# Copyright (c) 2011 Ruslan Spivak
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+###############################################################################
+
+__author__ = 'Ruslan Spivak <ruslan.spivak@gmail.com>'
+
+from slimit import ast
+
+
+class ECMAVisitor(object):
+
+    def __init__(self):
+        self.indent_level = 0
+
+    def _make_indent(self):
+        return ' ' * self.indent_level
+
+    def visit(self, node):
+        method = 'visit_%s' % node.__class__.__name__
+        return getattr(self, method, self.generic_visit)(node)
+
+    def generic_visit(self, node):
+        return 'GEN: %r' % node
+
+    def visit_Program(self, node):
+        return '\n'.join(self.visit(child) for child in node)
+
+    def visit_Block(self, node):
+        s = '{\n'
+        self.indent_level += 2
+        s += '\n'.join(
+            self._make_indent() + self.visit(child) for child in node)
+        self.indent_level -= 2
+        s += '\n' + self._make_indent() + '}'
+        return s
+
+    def visit_VarStatement(self, node):
+        s = 'var %s;' % ', '.join(self.visit(child) for child in node)
+        return s
+
+    def visit_VarDecl(self, node):
+        output = []
+        output.append(self.visit(node.identifier))
+        if node.initializer is not None:
+            output.append(' = %s' % self.visit(node.initializer))
+        return ''.join(output)
+
+    def visit_Identifier(self, node):
+        return node.value
+
+    def visit_Assign(self, node):
+        if node.op == ':':
+            template = '%s%s %s'
+        else:
+            template = '%s %s %s'
+        if getattr(node, '_parens', False):
+            template = '(%s)' % template
+        return template % (
+            self.visit(node.left), node.op, self.visit(node.right))
+
+    def visit_GetPropAssign(self, node):
+        template = 'get %s() {\n%s\n%s}'
+        if getattr(node, '_parens', False):
+            template = '(%s)' % template
+        self.indent_level += 2
+        body = '\n'.join(
+            (self._make_indent() + self.visit(el))
+            for el in node.elements
+            )
+        self.indent_level -= 2
+        tail = self._make_indent()
+        return template % (self.visit(node.prop_name), body, tail)
+
+    def visit_SetPropAssign(self, node):
+        template = 'set %s(%s) {\n%s\n%s}'
+        if getattr(node, '_parens', False):
+            template = '(%s)' % template
+        if len(node.parameters) > 1:
+            raise SyntaxError(
+                'Setter functions must have one argument: %s' % node)
+        params = ','.join(self.visit(param) for param in node.parameters)
+        self.indent_level += 2
+        body = '\n'.join(
+            (self._make_indent() + self.visit(el))
+            for el in node.elements
+            )
+        self.indent_level -= 2
+        tail = self._make_indent()
+        return template % (self.visit(node.prop_name), params, body, tail)
+
+    def visit_Number(self, node):
+        return node.value
+
+    def visit_Comma(self, node):
+        s = '%s, %s' % (self.visit(node.left), self.visit(node.right))
+        if getattr(node, '_parens', False):
+            s = '(' + s + ')'
+        return s
+
+    def visit_EmptyStatement(self, node):
+        return node.value
+
+    def visit_If(self, node):
+        s = 'if ('
+        if node.predicate is not None:
+            s += self.visit(node.predicate)
+        s += ') '
+        s += self.visit(node.consequent)
+        if node.alternative is not None:
+            s += ' else '
+            s += self.visit(node.alternative)
+        return s
+
+    def visit_Boolean(self, node):
+        return node.value
+
+    def visit_For(self, node):
+        s = 'for ('
+        if node.init is not None:
+            s += self.visit(node.init)
+        if node.init is None:
+            s += ' ; '
+        elif isinstance(node.init, (ast.Assign, ast.Comma, ast.FunctionCall,
+                                    ast.UnaryOp, ast.Identifier, ast.BinOp,
+                                    ast.Conditional, ast.Regex, ast.NewExpr)):
+            s += '; '
+        else:
+            s += ' '
+        if node.cond is not None:
+            s += self.visit(node.cond)
+        s += '; '
+        if node.count is not None:
+            s += self.visit(node.count)
+        s += ') ' + self.visit(node.statement)
+        return s
+
+    def visit_ForIn(self, node):
+        if isinstance(node.item, ast.VarDecl):
+            template = 'for (var %s in %s) '
+        else:
+            template = 'for (%s in %s) '
+        s = template % (self.visit(node.item), self.visit(node.iterable))
+        s += self.visit(node.statement)
+        return s
+
+    def visit_BinOp(self, node):
+        if getattr(node, '_parens', False):
+            template = '(%s %s %s)'
+        else:
+            template = '%s %s %s'
+        return template % (
+            self.visit(node.left), node.op, self.visit(node.right))
+
+    def visit_UnaryOp(self, node):
+        s = self.visit(node.value)
+        if node.postfix:
+            s += node.op
+        elif node.op in ('delete', 'void', 'typeof'):
+            s = '%s %s' % (node.op, s)
+        else:
+            s = '%s%s' % (node.op, s)
+        if getattr(node, '_parens', False):
+            s = '(%s)' % s
+        return s
+
+    def visit_ExprStatement(self, node):
+        return '%s;' % self.visit(node.expr)
+
+    def visit_DoWhile(self, node):
+        s = 'do '
+        s += self.visit(node.statement)
+        s += ' while (%s);' % self.visit(node.predicate)
+        return s
+
+    def visit_While(self, node):
+        s = 'while (%s) ' % self.visit(node.predicate)
+        s += self.visit(node.statement)
+        return s
+
+    def visit_Null(self, node):
+        return 'null'
+
+    def visit_String(self, node):
+        return node.value
+
+    def visit_Continue(self, node):
+        if node.identifier is not None:
+            s = 'continue %s;' % self.visit_Identifier(node.identifier)
+        else:
+            s = 'continue;'
+        return s
+
+    def visit_Break(self, node):
+        if node.identifier is not None:
+            s = 'break %s;' % self.visit_Identifier(node.identifier)
+        else:
+            s = 'break;'
+        return s
+
+    def visit_Return(self, node):
+        if node.expr is None:
+            return 'return;'
+        else:
+            return 'return %s;' % self.visit(node.expr)
+
+    def visit_With(self, node):
+        s = 'with (%s) ' % self.visit(node.expr)
+        s += self.visit(node.statement)
+        return s
+
+    def visit_Label(self, node):
+        s = '%s: %s' % (
+            self.visit(node.identifier), self.visit(node.statement))
+        return s
+
+    def visit_Switch(self, node):
+        s = 'switch (%s) {\n' % self.visit(node.expr)
+        self.indent_level += 2
+        for case in node.cases:
+            s += self._make_indent() + self.visit_Case(case)
+        if node.default is not None:
+            s += self.visit_Default(node.default)
+        self.indent_level -= 2
+        s += self._make_indent() + '}'
+        return s
+
+    def visit_Case(self, node):
+        s = 'case %s:\n' % self.visit(node.expr)
+        self.indent_level += 2
+        elements = '\n'.join(self._make_indent() + self.visit(element)
+                             for element in node.elements)
+        if elements:
+            s += elements + '\n'
+        self.indent_level -= 2
+        return s
+
+    def visit_Default(self, node):
+        s = self._make_indent() + 'default:\n'
+        self.indent_level += 2
+        s += '\n'.join(self._make_indent() + self.visit(element)
+                       for element in node.elements)
+        if node.elements is not None:
+            s += '\n'
+        self.indent_level -= 2
+        return s
+
+    def visit_Throw(self, node):
+        s = 'throw %s;' % self.visit(node.expr)
+        return s
+
+    def visit_Debugger(self, node):
+        return '%s;' % node.value
+
+    def visit_Try(self, node):
+        s = 'try '
+        s += self.visit(node.statements)
+        if node.catch is not None:
+            s += ' ' + self.visit(node.catch)
+        if node.fin is not None:
+            s += ' ' + self.visit(node.fin)
+        return s
+
+    def visit_Catch(self, node):
+        s = 'catch (%s) %s' % (
+            self.visit(node.identifier), self.visit(node.elements))
+        return s
+
+    def visit_Finally(self, node):
+        s = 'finally %s' % self.visit(node.elements)
+        return s
+
+    def visit_FuncDecl(self, node):
+        self.indent_level += 2
+        elements = '\n'.join(self._make_indent() + self.visit(element)
+                             for element in node.elements)
+        self.indent_level -= 2
+
+        s = 'function %s(%s) {\n%s' % (
+            self.visit(node.identifier),
+            ', '.join(self.visit(param) for param in node.parameters),
+            elements,
+            )
+        s += '\n' + self._make_indent() + '}'
+        return s
+
+    def visit_FuncExpr(self, node):
+        self.indent_level += 2
+        elements = '\n'.join(self._make_indent() + self.visit(element)
+                             for element in node.elements)
+        self.indent_level -= 2
+
+        ident = node.identifier
+        ident = '' if ident is None else ' %s' % self.visit(ident)
+
+        header = 'function%s(%s)'
+        if getattr(node, '_parens', False):
+            header = '(' + header
+        s = (header + ' {\n%s') % (
+            ident,
+            ', '.join(self.visit(param) for param in node.parameters),
+            elements,
+            )
+        s += '\n' + self._make_indent() + '}'
+        if getattr(node, '_parens', False):
+            s += ')'
+        return s
+
+    def visit_Conditional(self, node):
+        if getattr(node, '_parens', False):
+            template = '(%s ? %s : %s)'
+        else:
+            template = '%s ? %s : %s'
+
+        s = template % (
+            self.visit(node.predicate),
+            self.visit(node.consequent), self.visit(node.alternative))
+        return s
+
+    def visit_Regex(self, node):
+        if getattr(node, '_parens', False):
+            return '(%s)' % node.value
+        else:
+            return node.value
+
+    def visit_NewExpr(self, node):
+        s = 'new %s(%s)' % (
+            self.visit(node.identifier),
+            ', '.join(self.visit(arg) for arg in node.args)
+            )
+        return s
+
+    def visit_DotAccessor(self, node):
+        if getattr(node, '_parens', False):
+            template = '(%s.%s)'
+        else:
+            template = '%s.%s'
+        s = template % (self.visit(node.node), self.visit(node.identifier))
+        return s
+
+    def visit_BracketAccessor(self, node):
+        s = '%s[%s]' % (self.visit(node.node), self.visit(node.expr))
+        return s
+
+    def visit_FunctionCall(self, node):
+        s = '%s(%s)' % (self.visit(node.identifier),
+                        ', '.join(self.visit(arg) for arg in node.args))
+        if getattr(node, '_parens', False):
+            s = '(' + s + ')'
+        return s
+
+    def visit_Object(self, node):
+        s = '{\n'
+        self.indent_level += 2
+        s += ',\n'.join(self._make_indent() + self.visit(prop)
+                        for prop in node.properties)
+        self.indent_level -= 2
+        if node.properties:
+            s += '\n'
+        s += self._make_indent() + '}'
+        return s
+
+    def visit_Array(self, node):
+        s = '['
+        length = len(node.items) - 1
+        for index, item in enumerate(node.items):
+            if isinstance(item, ast.Elision):
+                s += ','
+            elif index != length:
+                s += self.visit(item) + ','
+            else:
+                s += self.visit(item)
+        s += ']'
+        return s
+
+    def visit_This(self, node):
+        return 'this'
+
diff --git a/webWidgetTCT_device/tools/slimit/visitors/minvisitor.py b/webWidgetTCT_device/tools/slimit/visitors/minvisitor.py
new file mode 100755 (executable)
index 0000000..1c6fd15
--- /dev/null
@@ -0,0 +1,437 @@
+###############################################################################
+#
+# Copyright (c) 2011 Ruslan Spivak
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+###############################################################################
+
+__author__ = 'Ruslan Spivak <ruslan.spivak@gmail.com>'
+
+import re
+
+from slimit import ast
+from slimit.lexer import Lexer
+
+_HAS_ID_MATCH = re.compile('^%s$' % Lexer.identifier).match
+
+def _is_identifier(value):
+    return _HAS_ID_MATCH(value) and value not in Lexer.keywords_dict
+
+
+class ECMAMinifier(object):
+
+    def __init__(self):
+        self.in_block = 0
+        self.ifelse_stack = []
+
+    def visit(self, node):
+        method = 'visit_%s' % node.__class__.__name__
+        return getattr(self, method, self.generic_visit)(node)
+
+    def generic_visit(self, node):
+        return 'GEN: %r' % node
+
+    def visit_Program(self, node):
+        return ''.join(self.visit(child) for child in node)
+
+    def visit_Block(self, node):
+        children = [self.visit(child) for child in node]
+        if len(children) == 1:
+            return children[0]
+        else:
+            return '{%s}' % ''.join(children)
+
+    def visit_VarStatement(self, node):
+        s = 'var %s;' % ','.join(self.visit(child) for child in node)
+        return s
+
+    def visit_VarDecl(self, node):
+        output = []
+        output.append(self.visit(node.identifier))
+        if node.initializer is not None:
+            output.append('=%s' % self.visit(node.initializer))
+        return ''.join(output)
+
+    def visit_Identifier(self, node):
+        return node.value
+
+    def visit_Assign(self, node):
+        template = '%s%s%s'
+        if getattr(node, '_parens', False):
+            template = '(%s)' % template
+        return template % (
+            self.visit(node.left), node.op, self.visit(node.right))
+
+    def visit_GetPropAssign(self, node):
+        template = 'get %s(){%s}'
+        if getattr(node, '_parens', False):
+            template = '(%s)' % template
+        return template % (
+            self.visit(node.prop_name),
+            ''.join(self.visit(element) for element in node.elements)
+            )
+
+    def visit_SetPropAssign(self, node):
+        template = 'set %s(%s){%s}'
+        if getattr(node, '_parens', False):
+            template = '(%s)' % template
+        if len(node.parameters) > 1:
+            raise SyntaxError(
+                'Setter functions must have one argument: %s' % node)
+        return template % (
+            self.visit(node.prop_name),
+            ''.join(self.visit(param) for param in node.parameters),
+            ''.join(self.visit(element) for element in node.elements)
+            )
+
+    def visit_Number(self, node):
+        return node.value
+
+    def visit_Comma(self, node):
+        template = '%s,%s'
+        if getattr(node, '_parens', False):
+            template = '(%s)' % template
+        return template % (self.visit(node.left), self.visit(node.right))
+
+    def visit_EmptyStatement(self, node):
+        return node.value
+
+    def visit_If(self, node):
+        has_alternative = node.alternative is not None
+
+        def _is_singleline_block(n):
+            return isinstance(n, ast.Block) and (len(n.children()) == 1)
+
+        s = 'if('
+        if node.predicate is not None:
+            s += self.visit(node.predicate)
+        s += ')'
+
+        # if we are an 'if..else' statement and 'if' part contains only
+        # one statement
+        if has_alternative and _is_singleline_block(node.consequent):
+            self.ifelse_stack.append({'if_in_ifelse': False})
+            consequent = self.visit(node.consequent)
+            record = self.ifelse_stack.pop()
+            if record['if_in_ifelse']:
+                s += '{%s}' % consequent
+            else:
+                s += consequent
+        elif has_alternative:
+            # we are an 'if..else' statement and 'if' part contains
+            # myltiple statements
+            s += self.visit(node.consequent)
+        else:
+            # 'if' without alternative - mark it so that an enclosing
+            # 'if..else' can act on it and add braces around 'if' part
+            if self.ifelse_stack:
+                self.ifelse_stack[-1]['if_in_ifelse'] = True
+            s += self.visit(node.consequent)
+
+        if has_alternative:
+            alternative = self.visit(node.alternative)
+            if alternative.startswith(('(', '{')):
+                s += 'else%s' % alternative
+            else:
+                s += 'else %s' % alternative
+        return s
+
+    def visit_Boolean(self, node):
+        return node.value
+
+    def visit_For(self, node):
+        s = 'for('
+        if node.init is not None:
+            s += self.visit(node.init)
+        if node.init is None:
+            s += ';'
+        elif isinstance(node.init, (ast.Assign, ast.Comma, ast.Conditional,
+                                    ast.FunctionCall, ast.UnaryOp,
+                                    ast.Identifier)):
+            s += ';'
+        else:
+            s += ''
+        if node.cond is not None:
+            s += self.visit(node.cond)
+        s += ';'
+        if node.count is not None:
+            s += self.visit(node.count)
+        s += ')' + self.visit(node.statement)
+        return s
+
+    def visit_ForIn(self, node):
+        if isinstance(node.item, ast.VarDecl):
+            template = 'for(var %s in %s)'
+        else:
+            template = 'for(%s in %s)'
+        s = template % (self.visit(node.item), self.visit(node.iterable))
+        s += self.visit(node.statement)
+        return s
+
+    def visit_BinOp(self, node):
+        if node.op in ('instanceof', 'in'):
+            template = '%s %s %s'
+        elif (node.op == '+' and
+              isinstance(node.right, ast.UnaryOp) and
+              node.right.op == '++' and not node.right.postfix
+              ):
+            # make a space between + and ++
+            # https://github.com/rspivak/slimit/issues/26
+            template = '%s%s %s'
+        else:
+            template = '%s%s%s'
+        if getattr(node, '_parens', False):
+            template = '(%s)' % template
+        return template % (
+            self.visit(node.left), node.op, self.visit(node.right))
+
+    def visit_UnaryOp(self, node):
+        s = self.visit(node.value)
+        if node.postfix:
+            s += node.op
+        elif node.op in ('delete', 'void', 'typeof'):
+            s = '%s %s' % (node.op, s)
+        else:
+            s = '%s%s' % (node.op, s)
+        if getattr(node, '_parens', False):
+            s = '(%s)' % s
+        return s
+
+    def visit_ExprStatement(self, node):
+        return '%s;' % self.visit(node.expr)
+
+    def visit_DoWhile(self, node):
+        statement = self.visit(node.statement)
+        if statement.startswith(('{', '(')):
+            s = 'do%s' % statement
+        else:
+            s = 'do %s' % statement
+        s += 'while(%s);' % self.visit(node.predicate)
+        return s
+
+    def visit_While(self, node):
+        s = 'while(%s)' % self.visit(node.predicate)
+        s += self.visit(node.statement)
+        return s
+
+    def visit_Null(self, node):
+        return 'null'
+
+    def visit_String(self, node):
+        return node.value
+
+    def visit_Continue(self, node):
+        if node.identifier is not None:
+            s = 'continue %s;' % self.visit_Identifier(node.identifier)
+        else:
+            s = 'continue;'
+        return s
+
+    def visit_Break(self, node):
+        if node.identifier is not None:
+            s = 'break %s;' % self.visit_Identifier(node.identifier)
+        else:
+            s = 'break;'
+        return s
+
+    def visit_Return(self, node):
+        if node.expr is None:
+            return 'return;'
+
+        expr_text = self.visit(node.expr)
+        if expr_text.startswith(('(', '{')):
+            return 'return%s;' % expr_text
+        else:
+            return 'return %s;' % expr_text
+
+    def visit_With(self, node):
+        s = 'with(%s)' % self.visit(node.expr)
+        s += self.visit(node.statement)
+        return s
+
+    def visit_Label(self, node):
+        s = '%s:%s' % (
+            self.visit(node.identifier), self.visit(node.statement))
+        return s
+
+    def visit_Switch(self, node):
+        s = 'switch(%s){' % self.visit(node.expr)
+        for case in node.cases:
+            s += self.visit_Case(case)
+        if node.default is not None:
+            s += self.visit_Default(node.default)
+        s += '}'
+        return s
+
+    def visit_Case(self, node):
+        s = 'case %s:' % self.visit(node.expr)
+        elements = ''.join(self.visit(element) for element in node.elements)
+        if elements:
+            s += elements
+        return s
+
+    def visit_Default(self, node):
+        s = 'default:'
+        s += ''.join(self.visit(element) for element in node.elements)
+        if node.elements is not None:
+            s += ''
+        return s
+
+    def visit_Throw(self, node):
+        s = 'throw %s;' % self.visit(node.expr)
+        return s
+
+    def visit_Debugger(self, node):
+        return '%s;' % node.value
+
+    def visit_Try(self, node):
+        result = self.visit(node.statements)
+        if result.startswith('{'):
+            s = 'try%s' % result
+        else:
+            s = 'try{%s}' % result
+        if node.catch is not None:
+            s += self.visit(node.catch)
+        if node.fin is not None:
+            s += self.visit(node.fin)
+        return s
+
+    def visit_Catch(self, node):
+        ident = self.visit(node.identifier)
+        result = self.visit(node.elements)
+        if result.startswith('{'):
+            s = 'catch(%s)%s' % (ident, result)
+        else:
+            s = 'catch(%s){%s}' % (ident, result)
+        return s
+
+    def visit_Finally(self, node):
+        result = self.visit(node.elements)
+        if result.startswith('{'):
+            s = 'finally%s' % result
+        else:
+            s = 'finally{%s}' % result
+        return s
+
+    def visit_FuncDecl(self, node):
+        elements = ''.join(self.visit(element) for element in node.elements)
+        s = 'function %s(%s){%s' % (
+            self.visit(node.identifier),
+            ','.join(self.visit(param) for param in node.parameters),
+            elements,
+            )
+        s += '}'
+        return s
+
+    def visit_FuncExpr(self, node):
+        elements = ''.join(self.visit(element) for element in node.elements)
+
+        ident = node.identifier
+        ident = '' if ident is None else ' %s' % self.visit(ident)
+
+        header = 'function%s(%s)'
+        if getattr(node, '_parens', False):
+            header = '(' + header
+        s = (header + '{%s') % (
+            ident,
+            ','.join(self.visit(param) for param in node.parameters),
+            elements,
+            )
+        s += '}'
+        if getattr(node, '_parens', False):
+            s += ')'
+        return s
+
+    def visit_Conditional(self, node):
+        if getattr(node, '_parens', False):
+            template = '(%s?%s:%s)'
+        else:
+            template = '%s?%s:%s'
+
+        s = template % (
+            self.visit(node.predicate),
+            self.visit(node.consequent), self.visit(node.alternative))
+        return s
+
+    def visit_Regex(self, node):
+        if getattr(node, '_parens', False):
+            return '(%s)' % node.value
+        else:
+            return node.value
+
+    def visit_NewExpr(self, node):
+        s = 'new %s(%s)' % (
+            self.visit(node.identifier),
+            ','.join(self.visit(arg) for arg in node.args)
+            )
+        return s
+
+    def visit_DotAccessor(self, node):
+        if getattr(node, '_parens', False):
+            template = '(%s.%s)'
+        else:
+            template = '%s.%s'
+        s = template % (self.visit(node.node), self.visit(node.identifier))
+        return s
+
+    def visit_BracketAccessor(self, node):
+        if isinstance(node.expr, ast.String):
+            value = node.expr.value
+            # remove single or double quotes around the value, but not both
+            if value.startswith("'"):
+                value = value.strip("'")
+            elif value.startswith('"'):
+                value = value.strip('"')
+            if _is_identifier(value):
+                s = '%s.%s' % (self.visit(node.node), value)
+                return s
+
+        s = '%s[%s]' % (self.visit(node.node), self.visit(node.expr))
+        return s
+
+    def visit_FunctionCall(self, node):
+        template = '%s(%s)'
+        if getattr(node, '_parens', False):
+            template = '(%s)' % template
+
+        s = template % (self.visit(node.identifier),
+                        ','.join(self.visit(arg) for arg in node.args))
+        return s
+
+    def visit_Object(self, node):
+        s = '{%s}' % ','.join(self.visit(prop) for prop in node.properties)
+        return s
+
+    def visit_Array(self, node):
+        s = '['
+        length = len(node.items) - 1
+        for index, item in enumerate(node.items):
+            if isinstance(item, ast.Elision):
+                s += ','
+            elif index != length:
+                s += self.visit(item) + ','
+            else:
+                s += self.visit(item)
+        s += ']'
+        return s
+
+    def visit_This(self, node):
+        return 'this'
+
diff --git a/webWidgetTCT_device/tools/slimit/visitors/nodevisitor.py b/webWidgetTCT_device/tools/slimit/visitors/nodevisitor.py
new file mode 100755 (executable)
index 0000000..d3559d7
--- /dev/null
@@ -0,0 +1,85 @@
+###############################################################################
+#
+# Copyright (c) 2011 Ruslan Spivak
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+###############################################################################
+
+__author__ = 'Ruslan Spivak <ruslan.spivak@gmail.com>'
+
+
+class ASTVisitor(object):
+    """Base class for custom AST node visitors.
+
+    Example:
+
+    >>> from slimit.parser import Parser
+    >>> from slimit.visitors.nodevisitor import ASTVisitor
+    >>>
+    >>> text = '''
+    ... var x = {
+    ...     "key1": "value1",
+    ...     "key2": "value2"
+    ... };
+    ... '''
+    >>>
+    >>> class MyVisitor(ASTVisitor):
+    ...     def visit_Object(self, node):
+    ...         '''Visit object literal.'''
+    ...         for prop in node:
+    ...             left, right = prop.left, prop.right
+    ...             print 'Property value: %s' % right.value
+    ...             # visit all children in turn
+    ...             self.visit(prop)
+    ...
+    >>>
+    >>> parser = Parser()
+    >>> tree = parser.parse(text)
+    >>> visitor = MyVisitor()
+    >>> visitor.visit(tree)
+    Property value: "value1"
+    Property value: "value2"
+
+    """
+
+    def visit(self, node):
+        method = 'visit_%s' % node.__class__.__name__
+        return getattr(self, method, self.generic_visit)(node)
+
+    def generic_visit(self, node):
+        for child in node:
+            self.visit(child)
+
+
+class NodeVisitor(object):
+    """Simple node visitor."""
+
+    def visit(self, node):
+        """Returns a generator that walks all children recursively."""
+        for child in node:
+            yield child
+            for subchild in self.visit(child):
+                yield subchild
+
+
+def visit(node):
+    visitor = NodeVisitor()
+    for child in visitor.visit(node):
+        yield child
diff --git a/webWidgetTCT_device/tools/slimit/visitors/scopevisitor.py b/webWidgetTCT_device/tools/slimit/visitors/scopevisitor.py
new file mode 100755 (executable)
index 0000000..10e55cb
--- /dev/null
@@ -0,0 +1,199 @@
+###############################################################################
+#
+# Copyright (c) 2011 Ruslan Spivak
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+###############################################################################
+
+__author__ = 'Ruslan Spivak <ruslan.spivak@gmail.com>'
+
+from slimit import ast
+from slimit.scope import VarSymbol, FuncSymbol, LocalScope, SymbolTable
+
+
+class Visitor(object):
+    def visit(self, node):
+        method = 'visit_%s' % node.__class__.__name__
+        return getattr(self, method, self.generic_visit)(node)
+
+    def generic_visit(self, node):
+        if node is None:
+            return
+        if isinstance(node, list):
+            for child in node:
+                self.visit(child)
+        else:
+            for child in node.children():
+                self.visit(child)
+
+
+class ScopeTreeVisitor(Visitor):
+    """Builds scope tree."""
+
+    def __init__(self, sym_table):
+        self.sym_table = sym_table
+        self.current_scope = sym_table.globals
+
+    def visit_VarDecl(self, node):
+        ident = node.identifier
+        symbol = VarSymbol(name=ident.value)
+        if symbol not in self.current_scope:
+            self.current_scope.define(symbol)
+        ident.scope = self.current_scope
+        self.visit(node.initializer)
+
+    def visit_Identifier(self, node):
+        node.scope = self.current_scope
+
+    def visit_FuncDecl(self, node):
+        if node.identifier is not None:
+            name = node.identifier.value
+            self.visit_Identifier(node.identifier)
+        else:
+            name = None
+
+        func_sym = FuncSymbol(
+            name=name, enclosing_scope=self.current_scope)
+        if name is not None:
+            self.current_scope.define(func_sym)
+            node.scope = self.current_scope
+
+        # push function scope
+        self.current_scope = func_sym
+        for ident in node.parameters:
+            self.current_scope.define(VarSymbol(ident.value))
+            ident.scope = self.current_scope
+
+        for element in node.elements:
+            self.visit(element)
+
+        # pop the function scope
+        self.current_scope = self.current_scope.get_enclosing_scope()
+
+    # alias
+    visit_FuncExpr = visit_FuncDecl
+
+    def visit_Catch(self, node):
+        # The catch identifier actually lives in a new scope, but additional
+        # variables defined in the catch statement belong to the outer scope.
+        # For the sake of simplicity we just reuse any existing variables
+        # from the outer scope if they exist.
+        ident = node.identifier
+        existing_symbol = self.current_scope.symbols.get(ident.value)
+        if existing_symbol is None:
+            self.current_scope.define(VarSymbol(ident.value))
+        ident.scope = self.current_scope
+
+        for element in node.elements:
+            self.visit(element)
+
+class RefVisitor(Visitor):
+    """Fill 'ref' attribute in scopes."""
+
+    def visit_Identifier(self, node):
+        if self._is_id_in_expr(node):
+            self._fill_scope_refs(node.value, node.scope)
+
+    @staticmethod
+    def _is_id_in_expr(node):
+        """Return True if Identifier node is part of an expression."""
+        return (
+            getattr(node, 'scope', None) is not None and
+            getattr(node, '_in_expression', False)
+            )
+
+    @staticmethod
+    def _fill_scope_refs(name, scope):
+        """Put referenced name in 'ref' dictionary of a scope.
+
+        Walks up the scope tree and adds the name to 'ref' of every scope
+        up in the tree until a scope that defines referenced name is reached.
+        """
+        symbol = scope.resolve(name)
+        if symbol is None:
+            return
+
+        orig_scope = symbol.scope
+        scope.refs[name] = orig_scope
+        while scope is not orig_scope:
+            scope = scope.get_enclosing_scope()
+            scope.refs[name] = orig_scope
+
+
+def mangle_scope_tree(root, toplevel):
+    """Walk over a scope tree and mangle symbol names.
+
+    Args:
+        toplevel: Defines if global scope should be mangled or not.
+    """
+    def mangle(scope):
+        # don't mangle global scope if not specified otherwise
+        if scope.get_enclosing_scope() is None and not toplevel:
+            return
+        for name in scope.symbols:
+            mangled_name = scope.get_next_mangled_name()
+            scope.mangled[name] = mangled_name
+            scope.rev_mangled[mangled_name] = name
+
+    def visit(node):
+        mangle(node)
+        for child in node.children:
+            visit(child)
+
+    visit(root)
+
+
+def fill_scope_references(tree):
+    """Fill 'ref' scope attribute with values."""
+    visitor = RefVisitor()
+    visitor.visit(tree)
+
+
+class NameManglerVisitor(Visitor):
+    """Mangles names.
+
+    Walks over a parsed tree and changes ID values to corresponding
+    mangled names.
+    """
+
+    @staticmethod
+    def _is_mangle_candidate(id_node):
+        """Return True if Identifier node is a candidate for mangling.
+
+        There are 5 cases when Identifier is a mangling candidate:
+        1. Function declaration identifier
+        2. Function expression identifier
+        3. Function declaration/expression parameter
+        4. Variable declaration identifier
+        5. Identifier is a part of an expression (primary_expr_no_brace rule)
+        """
+        return getattr(id_node, '_mangle_candidate', False)
+
+    def visit_Identifier(self, node):
+        """Mangle names."""
+        if not self._is_mangle_candidate(node):
+            return
+        name = node.value
+        symbol = node.scope.resolve(node.value)
+        if symbol is None:
+            return
+        mangled = symbol.scope.mangled.get(name)
+        if mangled is not None:
+            node.value = mangled
diff --git a/webWidgetTCT_device/tools/slimit/yacctab.py b/webWidgetTCT_device/tools/slimit/yacctab.py
new file mode 100755 (executable)
index 0000000..9106390
--- /dev/null
@@ -0,0 +1,330 @@
+
+# yacctab.py
+# This file is automatically generated. Do not edit.
+_tabversion = '3.2'
+
+_lr_method = 'LALR'
+
+_lr_signature = ':\xbe\xd7 \xc4\xd1\xd4\x7f\xef\xac_JV{\x19\xa8'
+    
+_lr_action_items = {'DO':([0,2,5,7,13,19,21,28,29,31,36,43,44,45,50,58,62,65,67,68,72,75,77,111,114,115,116,126,133,143,147,148,163,164,176,177,179,240,241,250,270,271,310,311,312,313,314,322,323,340,341,383,386,414,416,418,421,435,436,441,471,472,475,477,483,492,501,502,504,508,512,514,516,519,522,523,524,528,529,531,532,533,534,536,540,541,542,544,547,],[68,-22,-15,68,-23,-21,-13,-19,-17,-20,-16,-11,68,-9,-10,-8,-24,-12,-6,68,-244,-18,-14,-7,-292,-291,-2,68,-270,-269,-245,-246,-261,-262,-265,-266,-25,-232,-233,-283,-271,-272,-287,-286,-26,-263,-264,-268,-267,-284,-285,68,68,-290,-288,68,68,-273,68,68,-251,-274,-247,68,68,68,68,68,68,-293,68,-254,-289,-275,-249,-250,-248,68,-294,68,-255,68,68,68,68,-256,-252,-276,-253,]),'OREQUAL':([3,8,12,15,16,20,24,38,41,49,61,63,64,70,71,78,79,80,81,82,85,87,101,102,103,105,107,108,109,110,142,159,169,172,173,216,218,221,222,227,229,239,301,303,305,315,319,338,345,346,350,353,411,413,417,424,427,429,433,464,482,506,508,526,529,537,],[-28,-72,-94,-71,-27,-42,-41,-30,-95,-78,-31,-32,-33,-35,-34,-37,-36,-43,-44,206,-38,-29,-92,-39,-93,-40,-67,-66,-76,-41,206,-85,-84,-79,-76,-47,-46,-77,-76,-81,-55,-80,206,-87,-88,-74,-75,-45,-70,-83,-56,-69,-86,-89,-73,-48,-82,-57,-68,206,-295,-296,-297,-297,-298,-298,]),'DIVEQUAL':([3,8,12,15,16,20,24,38,41,49,61,63,64,70,71,78,79,80,81,82,85,87,101,102,103,105,107,108,109,110,142,159,169,172,173,216,218,221,222,227,229,239,301,303,305,315,319,338,345,346,350,353,411,413,417,424,427,429,433,464,482,506,508,526,529,537,],[-28,-72,-94,-71,-27,-42,-41,-30,-95,-78,-31,-32,-33,-35,-34,-37,-36,-43,-44,193,-38,-29,-92,-39,-93,-40,-67,-66,-76,-41,193,-85,-84,-79,-76,-47,-46,-77,-76,-81,-55,-80,193,-87,-88,-74,-75,-45,-70,-83,-56,-69,-86,-89,-73,-48,-82,-57,-68,193,-295,-296,-297,-297,-298,-298,]),'RETURN':([0,2,5,7,13,19,21,28,29,31,36,43,44,45,50,58,62,65,67,68,72,75,77,111,114,115,116,126,133,143,147,148,163,164,176,177,179,240,241,250,270,271,310,311,312,313,314,322,323,340,341,383,386,414,416,418,421,435,436,441,471,472,475,477,483,492,501,502,504,508,512,514,516,519,522,523,524,528,529,531,532,533,534,536,540,541,542,544,547,],[26,-22,-15,26,-23,-21,-13,-19,-17,-20,-16,-11,26,-9,-10,-8,-24,-12,-6,26,-244,-18,-14,-7,-292,-291,-2,26,-270,-269,-245,-246,-261,-262,-265,-266,-25,-232,-233,-283,-271,-272,-287,-286,-26,-263,-264,-268,-267,-284,-285,26,26,-290,-288,26,26,-273,26,26,-251,-274,-247,26,26,26,26,26,26,-293,26,-254,-289,-275,-249,-250,-248,26,-294,26,-255,26,26,26,26,-256,-252,-276,-253,]),'RSHIFTEQUAL':([3,8,12,15,16,20,24,38,41,49,61,63,64,70,71,78,79,80,81,82,85,87,101,102,103,105,107,108,109,110,142,159,169,172,173,216,218,221,222,227,229,239,301,303,305,315,319,338,345,346,350,353,411,413,417,424,427,429,433,464,482,506,508,526,529,537,],[-28,-72,-94,-71,-27,-42,-41,-30,-95,-78,-31,-32,-33,-35,-34,-37,-36,-43,-44,194,-38,-29,-92,-39,-93,-40,-67,-66,-76,-41,194,-85,-84,-79,-76,-47,-46,-77,-76,-81,-55,-80,194,-87,-88,-74,-75,-45,-70,-83,-56,-69,-86,-89,-73,-48,-82,-57,-68,194,-295,-296,-297,-297,-298,-298,]),'DEFAULT':([2,5,7,13,19,21,28,29,31,36,43,45,50,58,59,62,65,67,72,75,77,111,114,115,116,133,143,147,148,163,164,176,177,179,240,241,250,270,271,310,311,312,313,314,322,323,340,341,414,416,435,471,472,473,475,496,497,498,499,508,514,516,518,519,522,523,524,529,532,534,541,542,543,544,547,],[-22,-15,-5,-23,-21,-13,-19,-17,-20,-16,-11,-9,-10,-8,-4,-24,-12,-6,-244,-18,-14,-7,-292,-291,-2,-270,-269,-245,-246,-261,-262,-265,-266,-25,-232,-233,-283,-271,-272,-287,-286,-26,-263,-264,-268,-267,-284,-285,-290,-288,-273,-251,-274,-1,-247,-278,521,-279,-277,-293,-254,-289,-280,-275,-249,-250,-248,-294,-255,-1,-256,-252,-281,-276,-253,]),'VOID':([0,2,4,5,6,7,10,11,13,19,21,23,25,26,28,29,30,31,36,40,43,44,45,48,50,58,62,65,67,68,72,75,77,83,84,88,89,90,92,93,94,95,111,114,115,116,120,121,122,123,124,126,133,143,146,147,148,149,150,151,152,155,158,160,163,164,168,170,171,174,175,176,177,179,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,197,198,199,200,201,202,203,205,206,207,210,215,219,226,238,240,241,243,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,310,311,312,313,314,322,323,340,341,342,343,352,383,386,389,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,412,414,416,418,420,421,434,435,436,441,443,446,447,471,472,475,477,483,488,491,492,493,495,501,502,504,508,509,512,514,516,519,522,523,524,528,529,531,532,533,534,536,540,541,542,544,547,],[11,-22,-1,-15,11,11,11,11,-23,-21,-13,11,11,11,-19,-17,11,-20,-16,11,-11,11,-9,11,-10,-8,-24,-12,-6,11,-244,-18,-14,11,11,11,11,11,11,-53,-52,-51,-7,-292,-291,-2,11,11,11,11,11,11,-270,-269,11,-245,-246,11,11,11,11,11,11,11,-261,-262,11,11,11,11,11,-265,-266,-25,11,11,11,11,11,11,11,11,11,11,11,11,-216,-221,-222,-219,-217,-224,-215,-218,-220,-223,-214,-225,11,11,-1,-54,11,11,-232,-233,11,-283,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,-271,-272,11,11,11,11,11,11,11,-287,-286,-26,-263,-264,-268,-267,-284,-285,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,-290,-288,11,11,11,11,-273,11,11,11,11,11,-251,-274,-247,11,11,11,11,11,11,11,11,11,11,-293,11,11,-254,-289,-275,-249,-250,-248,11,-294,11,-255,11,11,11,11,-256,-252,-276,-253,]),'SETPROP':([104,349,],[231,231,]),'NUMBER':([0,2,4,5,6,7,10,11,13,19,21,23,25,26,28,29,30,31,36,40,43,44,45,48,50,54,58,62,65,67,68,72,75,77,83,84,88,89,90,92,93,94,95,98,104,111,114,115,116,120,121,122,123,124,126,133,143,146,147,148,149,150,151,152,155,158,160,163,164,168,170,171,174,175,176,177,179,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,197,198,199,200,201,202,203,205,206,207,210,215,219,226,228,231,238,240,241,243,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,310,311,312,313,314,322,323,340,341,342,343,349,352,383,386,389,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,412,414,416,418,420,421,434,435,436,441,443,446,447,471,472,475,477,483,488,491,492,493,495,501,502,504,508,509,512,514,516,519,522,523,524,528,529,531,532,533,534,536,540,541,542,544,547,],[70,-22,-1,-15,70,70,70,70,-23,-21,-13,70,70,70,-19,-17,70,-20,-16,70,-11,70,-9,70,-10,70,-8,-24,-12,-6,70,-244,-18,-14,70,70,70,70,70,70,-53,-52,-51,70,70,-7,-292,-291,-2,70,70,70,70,70,70,-270,-269,70,-245,-246,70,70,70,70,70,70,70,-261,-262,70,70,70,70,70,-265,-266,-25,70,70,70,70,70,70,70,70,70,70,70,70,-216,-221,-222,-219,-217,-224,-215,-218,-220,-223,-214,-225,70,70,-1,-54,70,70,70,70,-232,-233,70,-283,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,-271,-272,70,70,70,70,70,70,70,-287,-286,-26,-263,-264,-268,-267,-284,-285,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,-290,-288,70,70,70,70,-273,70,70,70,70,70,-251,-274,-247,70,70,70,70,70,70,70,70,70,70,-293,70,70,-254,-289,-275,-249,-250,-248,70,-294,70,-255,70,70,70,70,-256,-252,-276,-253,]),'LBRACKET':([0,2,3,4,5,6,7,8,10,11,13,15,16,19,20,21,23,24,25,26,28,29,30,31,36,38,40,41,43,44,45,48,49,50,54,58,61,62,63,64,65,67,68,70,71,72,75,77,78,79,80,81,83,84,85,87,88,89,90,92,93,94,95,98,102,103,105,107,108,109,110,111,114,115,116,120,121,122,123,124,126,133,143,146,147,148,149,150,151,152,155,158,159,160,163,164,168,169,170,171,173,174,175,176,177,179,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,197,198,199,200,201,202,203,205,206,207,210,215,216,218,219,222,226,227,229,238,239,240,241,243,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,303,305,310,311,312,313,314,315,319,322,323,338,340,341,342,343,345,346,350,352,353,383,386,389,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,416,417,418,420,421,424,427,429,433,434,435,436,441,443,446,447,471,472,475,477,482,483,488,491,492,493,495,501,502,504,506,508,509,512,514,516,519,522,523,524,526,528,529,531,532,533,534,536,537,540,541,542,544,547,],[4,-22,-28,-1,-15,4,4,-72,4,4,-23,-71,-27,-21,-42,-13,4,-41,4,4,-19,-17,4,-20,-16,-30,4,158,-11,4,-9,4,168,-10,4,-8,-31,-24,-32,-33,-12,-6,4,-35,-34,-244,-18,-14,-37,-36,-43,-44,4,4,-38,-29,4,4,4,4,-53,-52,-51,4,-39,226,-40,-67,-66,238,-41,-7,-292,-291,-2,4,4,4,4,4,4,-270,-269,4,-245,-246,4,4,4,4,4,4,-85,4,-261,-262,4,-84,4,4,238,4,4,-265,-266,-25,4,4,4,4,4,4,4,4,4,4,4,4,-216,-221,-222,-219,-217,-224,-215,-218,-220,-223,-214,-225,4,4,-1,-47,-46,-54,238,4,-81,-55,4,-80,-232,-233,4,-283,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,-271,-272,4,4,4,4,4,4,4,-87,-88,-287,-286,-26,-263,-264,-74,-75,-268,-267,-45,-284,-285,4,4,-70,-83,-56,4,-69,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,-86,4,-89,-290,-288,-73,4,4,4,-48,-82,-57,-68,4,-273,4,4,4,4,4,-251,-274,-247,4,-295,4,4,4,4,4,4,4,4,4,-296,-293,4,4,-254,-289,-275,-249,-250,-248,-297,4,-294,4,-255,4,4,4,-298,4,-256,-252,-276,-253,]),'BXOR':([3,8,12,15,16,18,20,22,24,27,35,38,41,46,49,53,60,61,63,64,70,71,73,74,76,78,79,80,81,82,85,87,97,99,100,101,102,103,105,106,107,108,109,110,112,113,125,127,128,129,132,134,135,136,140,142,144,145,156,159,166,169,172,173,196,204,209,213,216,218,221,222,223,224,227,229,239,245,246,247,248,249,281,282,283,290,291,292,293,294,301,303,305,315,318,319,325,326,327,328,329,330,331,332,333,334,335,336,338,345,346,350,353,357,358,359,360,361,362,363,364,365,366,368,369,370,371,372,373,374,375,377,378,382,411,413,417,424,427,429,433,448,449,450,451,452,453,454,455,456,457,458,462,464,482,506,508,526,529,537,],[-28,-72,-94,-71,-27,-150,-42,-133,-41,-119,-126,-30,-95,-105,-78,171,-104,-31,-32,-33,-35,-34,-176,-167,-182,-37,-36,-43,-44,-99,-38,-29,-112,-96,-102,-92,-39,-93,-40,-103,-67,-66,-76,-41,-111,-107,-108,-106,-123,-157,-137,-115,265,-172,-129,-96,-178,-113,-109,-85,-114,-84,-79,-76,-100,-101,-110,-99,-47,-46,-77,-76,-97,-98,-81,-55,-80,-136,-135,-134,-127,-128,-122,-121,-120,-162,-180,-144,399,-174,-96,-87,-88,-74,-183,-75,171,-168,-169,-171,-170,-155,-152,-151,-154,-153,-156,-177,-45,-70,-83,-56,-69,-117,-118,-116,-142,-139,-138,-141,-140,-143,265,-132,-131,-130,-179,-158,-159,-161,-160,-124,-125,-173,-86,-89,-73,-48,-82,-57,-68,-149,-146,-145,-148,-147,-175,-181,-163,-164,-166,-165,399,-96,-295,-296,-297,-297,-298,-298,]),'WHILE':([0,2,5,7,13,19,21,28,29,31,36,43,44,45,50,58,62,65,67,68,72,75,77,111,114,115,116,126,133,143,147,148,163,164,176,177,179,180,240,241,250,270,271,310,311,312,313,314,322,323,340,341,383,386,414,416,418,421,435,436,441,471,472,475,477,483,492,501,502,504,508,512,514,516,519,522,523,524,528,529,531,532,533,534,536,540,541,542,544,547,],[52,-22,-15,52,-23,-21,-13,-19,-17,-20,-16,-11,52,-9,-10,-8,-24,-12,-6,52,-244,-18,-14,-7,-292,-291,-2,52,-270,-269,-245,-246,-261,-262,-265,-266,-25,324,-232,-233,-283,-271,-272,-287,-286,-26,-263,-264,-268,-267,-284,-285,52,52,-290,-288,52,52,-273,52,52,-251,-274,-247,52,52,52,52,52,52,-293,52,-254,-289,-275,-249,-250,-248,52,-294,52,-255,52,52,52,52,-256,-252,-276,-253,]),'COLON':([3,16,20,24,38,61,63,64,70,71,78,79,80,81,85,87,97,99,100,101,102,103,105,106,107,108,109,110,112,113,125,127,128,129,130,131,132,134,135,136,137,139,140,141,142,144,145,156,166,209,212,216,218,221,222,223,224,227,229,232,234,235,236,239,288,290,291,292,293,294,297,298,302,305,338,345,346,350,353,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,413,424,427,429,433,442,448,449,450,451,452,453,454,455,456,457,458,462,464,466,467,468,480,482,506,515,517,521,526,537,],[-28,-27,-42,126,-30,-31,-32,-33,-35,-34,-37,-36,-43,-44,-38,-29,-112,-96,-102,-92,-39,-93,-40,-103,-67,-66,-76,-41,-111,-107,-108,-106,-123,-157,-190,-196,-137,-115,-184,-172,-208,-226,-129,-202,-96,-178,-113,-109,-114,-110,342,-47,-46,-77,-76,-97,-98,-81,-55,-65,-63,352,-64,-80,-198,-162,-180,-144,-186,-174,-192,-210,-204,-88,-45,-70,-83,-56,-69,-117,-118,-116,-142,-139,-138,-141,-140,-143,-185,-191,-132,-131,-130,-179,-158,-159,-161,-160,-227,-124,-125,434,-197,-209,-173,-89,-48,-82,-57,-68,-193,-149,-146,-145,-148,-147,-175,-181,-163,-164,-166,-165,-187,-96,-211,493,-199,-203,-295,-296,-205,534,536,-297,-298,]),'BNOT':([0,2,4,5,6,7,10,11,13,19,21,23,25,26,28,29,30,31,36,40,43,44,45,48,50,58,62,65,67,68,72,75,77,83,84,88,89,90,92,93,94,95,111,114,115,116,120,121,122,123,124,126,133,143,146,147,148,149,150,151,152,155,158,160,163,164,168,170,171,174,175,176,177,179,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,197,198,199,200,201,202,203,205,206,207,210,215,219,226,238,240,241,243,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,310,311,312,313,314,322,323,340,341,342,343,352,383,386,389,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,412,414,416,418,420,421,434,435,436,441,443,446,447,471,472,475,477,483,488,491,492,493,495,501,502,504,508,509,512,514,516,519,522,523,524,528,529,531,532,533,534,536,540,541,542,544,547,],[30,-22,-1,-15,30,30,30,30,-23,-21,-13,30,30,30,-19,-17,30,-20,-16,30,-11,30,-9,30,-10,-8,-24,-12,-6,30,-244,-18,-14,30,30,30,30,30,30,-53,-52,-51,-7,-292,-291,-2,30,30,30,30,30,30,-270,-269,30,-245,-246,30,30,30,30,30,30,30,-261,-262,30,30,30,30,30,-265,-266,-25,30,30,30,30,30,30,30,30,30,30,30,30,-216,-221,-222,-219,-217,-224,-215,-218,-220,-223,-214,-225,30,30,-1,-54,30,30,-232,-233,30,-283,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,-271,-272,30,30,30,30,30,30,30,-287,-286,-26,-263,-264,-268,-267,-284,-285,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,-290,-288,30,30,30,30,-273,30,30,30,30,30,-251,-274,-247,30,30,30,30,30,30,30,30,30,30,-293,30,30,-254,-289,-275,-249,-250,-248,30,-294,30,-255,30,30,30,30,-256,-252,-276,-253,]),'LSHIFT':([3,8,12,15,16,18,20,22,24,27,35,38,41,46,49,60,61,63,64,70,71,78,79,80,81,82,85,87,97,99,100,101,102,103,105,106,107,108,109,110,112,113,125,127,128,132,134,140,142,145,156,159,166,169,172,173,196,204,209,213,216,218,221,222,223,224,227,229,239,245,246,247,248,249,281,282,283,292,301,303,305,315,319,330,331,332,333,334,335,338,345,346,350,353,357,358,359,360,361,362,363,364,365,368,369,370,377,378,411,413,417,424,427,429,433,448,449,450,451,452,464,482,506,508,526,529,537,],[-28,-72,-94,-71,-27,122,-42,-133,-41,-119,-126,-30,-95,-105,-78,-104,-31,-32,-33,-35,-34,-37,-36,-43,-44,-99,-38,-29,-112,-96,-102,-92,-39,-93,-40,-103,-67,-66,-76,-41,-111,-107,-108,-106,-123,264,-115,-129,-96,-113,-109,-85,-114,-84,-79,-76,-100,-101,-110,-99,-47,-46,-77,-76,-97,-98,-81,-55,-80,-136,-135,-134,-127,-128,-122,-121,-120,264,-96,-87,-88,-74,-75,264,264,264,264,264,264,-45,-70,-83,-56,-69,-117,-118,-116,264,264,264,264,264,264,-132,-131,-130,-124,-125,-86,-89,-73,-48,-82,-57,-68,264,264,264,264,264,-96,-295,-296,-297,-297,-298,-298,]),'NEW':([0,2,4,5,6,7,10,11,13,19,21,23,25,26,28,29,30,31,36,40,43,44,45,48,50,54,58,62,65,67,68,72,75,77,83,84,88,89,90,92,93,94,95,98,111,114,115,116,120,121,122,123,124,126,133,143,146,147,148,149,150,151,152,155,158,160,163,164,168,170,171,174,175,176,177,179,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,197,198,199,200,201,202,203,205,206,207,210,215,219,226,238,240,241,243,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,310,311,312,313,314,322,323,340,341,342,343,352,383,386,389,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,412,414,416,418,420,421,434,435,436,441,443,446,447,471,472,475,477,483,488,491,492,493,495,501,502,504,508,509,512,514,516,519,522,523,524,528,529,531,532,533,534,536,540,541,542,544,547,],[54,-22,-1,-15,98,54,98,98,-23,-21,-13,98,98,98,-19,-17,98,-20,-16,98,-11,54,-9,98,-10,98,-8,-24,-12,-6,54,-244,-18,-14,98,98,98,98,54,98,-53,-52,-51,98,-7,-292,-291,-2,98,98,98,98,98,54,-270,-269,98,-245,-246,98,98,98,98,98,98,98,-261,-262,98,98,54,54,98,-265,-266,-25,54,98,98,98,98,98,98,98,98,98,98,54,-216,-221,-222,-219,-217,-224,-215,-218,-220,-223,-214,-225,98,98,-1,-54,98,98,-232,-233,98,-283,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,-271,-272,98,98,98,98,98,98,98,-287,-286,-26,-263,-264,-268,-267,-284,-285,98,98,98,54,54,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,-290,-288,54,98,54,98,-273,54,54,98,98,98,-251,-274,-247,54,54,98,98,54,98,98,54,54,54,-293,98,54,-254,-289,-275,-249,-250,-248,54,-294,54,-255,54,54,54,54,-256,-252,-276,-253,]),'DIV':([3,8,12,15,16,20,24,27,35,38,41,46,49,60,61,63,64,70,71,78,79,80,81,82,85,87,97,99,100,101,102,103,105,106,107,108,109,110,112,113,125,127,128,134,142,145,156,159,166,169,172,173,196,204,209,213,216,218,221,222,223,224,227,229,239,248,249,281,282,283,301,303,305,315,319,338,345,346,350,353,357,358,359,377,378,411,413,417,424,427,429,433,464,482,506,508,526,529,537,],[-28,-72,-94,-71,-27,-42,-41,-119,151,-30,-95,-105,-78,-104,-31,-32,-33,-35,-34,-37,-36,-43,-44,-99,-38,-29,-112,-96,-102,-92,-39,-93,-40,-103,-67,-66,-76,-41,-111,-107,-108,-106,251,-115,-96,-113,-109,-85,-114,-84,-79,-76,-100,-101,-110,-99,-47,-46,-77,-76,-97,-98,-81,-55,-80,251,251,-122,-121,-120,-96,-87,-88,-74,-75,-45,-70,-83,-56,-69,-117,-118,-116,251,251,-86,-89,-73,-48,-82,-57,-68,-96,-295,-296,-297,-297,-298,-298,]),'NULL':([0,2,4,5,6,7,10,11,13,19,21,23,25,26,28,29,30,31,36,40,43,44,45,48,50,54,58,62,65,67,68,72,75,77,83,84,88,89,90,92,93,94,95,98,111,114,115,116,120,121,122,123,124,126,133,143,146,147,148,149,150,151,152,155,158,160,163,164,168,170,171,174,175,176,177,179,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,197,198,199,200,201,202,203,205,206,207,210,215,219,226,238,240,241,243,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,310,311,312,313,314,322,323,340,341,342,343,352,383,386,389,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,412,414,416,418,420,421,434,435,436,441,443,446,447,471,472,475,477,483,488,491,492,493,495,501,502,504,508,509,512,514,516,519,522,523,524,528,529,531,532,533,534,536,540,541,542,544,547,],[71,-22,-1,-15,71,71,71,71,-23,-21,-13,71,71,71,-19,-17,71,-20,-16,71,-11,71,-9,71,-10,71,-8,-24,-12,-6,71,-244,-18,-14,71,71,71,71,71,71,-53,-52,-51,71,-7,-292,-291,-2,71,71,71,71,71,71,-270,-269,71,-245,-246,71,71,71,71,71,71,71,-261,-262,71,71,71,71,71,-265,-266,-25,71,71,71,71,71,71,71,71,71,71,71,71,-216,-221,-222,-219,-217,-224,-215,-218,-220,-223,-214,-225,71,71,-1,-54,71,71,-232,-233,71,-283,71,71,71,71,71,71,71,71,71,71,71,71,71,71,71,71,71,71,71,-271,-272,71,71,71,71,71,71,71,-287,-286,-26,-263,-264,-268,-267,-284,-285,71,71,71,71,71,71,71,71,71,71,71,71,71,71,71,71,71,71,71,71,71,71,71,71,71,-290,-288,71,71,71,71,-273,71,71,71,71,71,-251,-274,-247,71,71,71,71,71,71,71,71,71,71,-293,71,71,-254,-289,-275,-249,-250,-248,71,-294,71,-255,71,71,71,71,-256,-252,-276,-253,]),'TRUE':([0,2,4,5,6,7,10,11,13,19,21,23,25,26,28,29,30,31,36,40,43,44,45,48,50,54,58,62,65,67,68,72,75,77,83,84,88,89,90,92,93,94,95,98,111,114,115,116,120,121,122,123,124,126,133,143,146,147,148,149,150,151,152,155,158,160,163,164,168,170,171,174,175,176,177,179,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,197,198,199,200,201,202,203,205,206,207,210,215,219,226,238,240,241,243,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,310,311,312,313,314,322,323,340,341,342,343,352,383,386,389,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,412,414,416,418,420,421,434,435,436,441,443,446,447,471,472,475,477,483,488,491,492,493,495,501,502,504,508,509,512,514,516,519,522,523,524,528,529,531,532,533,534,536,540,541,542,544,547,],[63,-22,-1,-15,63,63,63,63,-23,-21,-13,63,63,63,-19,-17,63,-20,-16,63,-11,63,-9,63,-10,63,-8,-24,-12,-6,63,-244,-18,-14,63,63,63,63,63,63,-53,-52,-51,63,-7,-292,-291,-2,63,63,63,63,63,63,-270,-269,63,-245,-246,63,63,63,63,63,63,63,-261,-262,63,63,63,63,63,-265,-266,-25,63,63,63,63,63,63,63,63,63,63,63,63,-216,-221,-222,-219,-217,-224,-215,-218,-220,-223,-214,-225,63,63,-1,-54,63,63,-232,-233,63,-283,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,-271,-272,63,63,63,63,63,63,63,-287,-286,-26,-263,-264,-268,-267,-284,-285,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,63,-290,-288,63,63,63,63,-273,63,63,63,63,63,-251,-274,-247,63,63,63,63,63,63,63,63,63,63,-293,63,63,-254,-289,-275,-249,-250,-248,63,-294,63,-255,63,63,63,63,-256,-252,-276,-253,]),'MINUS':([0,2,3,4,5,6,7,8,10,11,12,13,15,16,19,20,21,22,23,24,25,26,27,28,29,30,31,35,36,38,40,41,43,44,45,46,48,49,50,58,60,61,62,63,64,65,67,68,70,71,72,75,77,78,79,80,81,82,83,84,85,87,88,89,90,92,93,94,95,97,99,100,101,102,103,105,106,107,108,109,110,111,112,113,114,115,116,120,121,122,123,124,125,126,127,128,133,134,140,142,143,145,146,147,148,149,150,151,152,155,156,158,159,160,163,164,166,168,169,170,171,172,173,174,175,176,177,179,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,209,210,213,215,216,218,219,221,222,223,224,226,227,229,238,239,240,241,243,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,281,282,283,301,303,305,310,311,312,313,314,315,319,322,323,338,340,341,342,343,345,346,350,352,353,357,358,359,368,369,370,377,378,383,386,389,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,416,417,418,420,421,424,427,429,433,434,435,436,441,443,446,447,464,471,472,475,477,482,483,488,491,492,493,495,501,502,504,506,508,509,512,514,516,519,522,523,524,526,528,529,531,532,533,534,536,537,540,541,542,544,547,],[6,-22,-28,-1,-15,6,6,-72,6,6,-94,-23,-71,-27,-21,-42,-13,124,6,-41,6,6,-119,-19,-17,6,-20,-126,-16,-30,6,-95,-11,6,-9,-105,6,-78,-10,-8,-104,-31,-24,-32,-33,-12,-6,6,-35,-34,-244,-18,-14,-37,-36,-43,-44,-99,6,6,-38,-29,6,6,6,6,-53,-52,-51,-112,-96,-102,-92,-39,-93,-40,-103,-67,-66,-76,-41,-7,-111,-107,-292,-291,-2,6,6,6,6,6,-108,6,-106,-123,-270,-115,274,-96,-269,-113,6,-245,-246,6,6,6,6,6,-109,6,-85,6,-261,-262,-114,6,-84,6,6,-79,-76,6,6,-265,-266,-25,6,6,6,6,6,6,6,6,6,6,6,6,-216,-221,-222,-100,-219,-217,-224,-215,-218,-220,-223,-101,-214,-225,6,-110,6,-99,-1,-47,-46,-54,-77,-76,-97,-98,6,-81,-55,6,-80,-232,-233,6,274,274,274,-127,-128,-283,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,-271,-272,6,6,6,6,6,6,6,-122,-121,-120,-96,-87,-88,-287,-286,-26,-263,-264,-74,-75,-268,-267,-45,-284,-285,6,6,-70,-83,-56,6,-69,-117,-118,-116,274,274,274,-124,-125,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,-86,6,-89,-290,-288,-73,6,6,6,-48,-82,-57,-68,6,-273,6,6,6,6,6,-96,-251,-274,-247,6,-295,6,6,6,6,6,6,6,6,6,-296,-293,6,6,-254,-289,-275,-249,-250,-248,-297,6,-294,6,-255,6,6,6,-298,6,-256,-252,-276,-253,]),'MULT':([3,8,12,15,16,20,24,27,35,38,41,46,49,60,61,63,64,70,71,78,79,80,81,82,85,87,97,99,100,101,102,103,105,106,107,108,109,110,112,113,125,127,128,134,142,145,156,159,166,169,172,173,196,204,209,213,216,218,221,222,223,224,227,229,239,248,249,281,282,283,301,303,305,315,319,338,345,346,350,353,357,358,359,377,378,411,413,417,424,427,429,433,464,482,506,508,526,529,537,],[-28,-72,-94,-71,-27,-42,-41,-119,152,-30,-95,-105,-78,-104,-31,-32,-33,-35,-34,-37,-36,-43,-44,-99,-38,-29,-112,-96,-102,-92,-39,-93,-40,-103,-67,-66,-76,-41,-111,-107,-108,-106,253,-115,-96,-113,-109,-85,-114,-84,-79,-76,-100,-101,-110,-99,-47,-46,-77,-76,-97,-98,-81,-55,-80,253,253,-122,-121,-120,-96,-87,-88,-74,-75,-45,-70,-83,-56,-69,-117,-118,-116,253,253,-86,-89,-73,-48,-82,-57,-68,-96,-295,-296,-297,-297,-298,-298,]),'DEBUGGER':([0,2,5,7,13,19,21,28,29,31,36,43,44,45,50,58,62,65,67,68,72,75,77,111,114,115,116,126,133,143,147,148,163,164,176,177,179,240,241,250,270,271,310,311,312,313,314,322,323,340,341,383,386,414,416,418,421,435,436,441,471,472,475,477,483,492,501,502,504,508,512,514,516,519,522,523,524,528,529,531,532,533,534,536,540,541,542,544,547,],[14,-22,-15,14,-23,-21,-13,-19,-17,-20,-16,-11,14,-9,-10,-8,-24,-12,-6,14,-244,-18,-14,-7,-292,-291,-2,14,-270,-269,-245,-246,-261,-262,-265,-266,-25,-232,-233,-283,-271,-272,-287,-286,-26,-263,-264,-268,-267,-284,-285,14,14,-290,-288,14,14,-273,14,14,-251,-274,-247,14,14,14,14,14,14,-293,14,-254,-289,-275,-249,-250,-248,14,-294,14,-255,14,14,14,14,-256,-252,-276,-253,]),'CASE':([2,5,7,13,19,21,28,29,31,36,43,45,50,58,59,62,65,67,72,75,77,111,114,115,116,133,143,147,148,163,164,176,177,179,240,241,250,270,271,310,311,312,313,314,322,323,340,341,414,416,435,471,472,473,475,496,498,508,514,516,518,519,520,522,523,524,529,532,534,536,541,542,543,544,545,547,],[-22,-15,-5,-23,-21,-13,-19,-17,-20,-16,-11,-9,-10,-8,-4,-24,-12,-6,-244,-18,-14,-7,-292,-291,-2,-270,-269,-245,-246,-261,-262,-265,-266,-25,-232,-233,-283,-271,-272,-287,-286,-26,-263,-264,-268,-267,-284,-285,-290,-288,-273,-251,-274,495,-247,495,-279,-293,-254,-289,-280,-275,495,-249,-250,-248,-294,-255,-1,-1,-256,-252,-281,-276,-282,-253,]),'LE':([3,8,12,15,16,18,20,22,24,27,35,38,41,46,49,60,61,63,64,70,71,74,78,79,80,81,82,85,87,97,99,100,101,102,103,105,106,107,108,109,110,112,113,125,127,128,129,132,134,140,142,145,156,159,166,169,172,173,196,204,209,213,216,218,221,222,223,224,227,229,239,245,246,247,248,249,281,282,283,290,292,301,303,305,315,319,326,327,328,329,330,331,332,333,334,335,338,345,346,350,353,357,358,359,360,361,362,363,364,365,368,369,370,372,373,374,375,377,378,411,413,417,424,427,429,433,448,449,450,451,452,455,456,457,458,464,482,506,508,526,529,537,],[-28,-72,-94,-71,-27,-150,-42,-133,-41,-119,-126,-30,-95,-105,-78,-104,-31,-32,-33,-35,-34,190,-37,-36,-43,-44,-99,-38,-29,-112,-96,-102,-92,-39,-93,-40,-103,-67,-66,-76,-41,-111,-107,-108,-106,-123,258,-137,-115,-129,-96,-113,-109,-85,-114,-84,-79,-76,-100,-101,-110,-99,-47,-46,-77,-76,-97,-98,-81,-55,-80,-136,-135,-134,-127,-128,-122,-121,-120,397,-144,-96,-87,-88,-74,-75,258,258,258,258,-155,-152,-151,-154,-153,-156,-45,-70,-83,-56,-69,-117,-118,-116,-142,-139,-138,-141,-140,-143,-132,-131,-130,258,258,258,258,-124,-125,-86,-89,-73,-48,-82,-57,-68,-149,-146,-145,-148,-147,258,258,258,258,-96,-295,-296,-297,-297,-298,-298,]),'RPAREN':([3,16,20,38,61,63,64,70,71,78,79,80,81,85,87,97,99,100,101,102,103,105,106,107,108,109,110,112,113,125,127,128,129,130,131,132,134,135,136,137,139,140,141,142,144,145,153,156,160,166,208,209,216,218,221,222,223,224,227,229,239,279,284,286,287,305,306,307,317,321,338,339,344,345,346,350,353,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,380,381,382,387,413,424,425,427,428,429,433,437,460,461,465,469,470,474,479,480,482,489,491,506,509,511,513,526,530,537,],[-28,-27,-42,-30,-31,-32,-33,-35,-34,-37,-36,-43,-44,-38,-29,-112,-96,-102,-92,-39,-93,-40,-103,-67,-66,-76,-41,-111,-107,-108,-106,-123,-157,-190,-196,-137,-115,-184,-172,-208,-226,-129,-202,-96,-178,-113,285,-109,305,-114,338,-110,-47,-46,-77,-76,-97,-98,-81,-55,-80,383,384,-299,388,-88,413,-90,418,419,-45,421,426,-70,-83,-56,-69,-117,-118,-116,-142,-139,-138,-141,-140,-143,-185,-191,-132,-131,-130,-179,-158,-159,-161,-160,-227,-124,-125,-197,-209,-173,440,-89,-48,476,-82,478,-57,-68,-300,-257,-258,492,-91,494,500,505,-203,-295,512,-1,-296,-1,531,533,-297,540,-298,]),'URSHIFT':([3,8,12,15,16,18,20,22,24,27,35,38,41,46,49,60,61,63,64,70,71,78,79,80,81,82,85,87,97,99,100,101,102,103,105,106,107,108,109,110,112,113,125,127,128,132,134,140,142,145,156,159,166,169,172,173,196,204,209,213,216,218,221,222,223,224,227,229,239,245,246,247,248,249,281,282,283,292,301,303,305,315,319,330,331,332,333,334,335,338,345,346,350,353,357,358,359,360,361,362,363,364,365,368,369,370,377,378,411,413,417,424,427,429,433,448,449,450,451,452,464,482,506,508,526,529,537,],[-28,-72,-94,-71,-27,120,-42,-133,-41,-119,-126,-30,-95,-105,-78,-104,-31,-32,-33,-35,-34,-37,-36,-43,-44,-99,-38,-29,-112,-96,-102,-92,-39,-93,-40,-103,-67,-66,-76,-41,-111,-107,-108,-106,-123,262,-115,-129,-96,-113,-109,-85,-114,-84,-79,-76,-100,-101,-110,-99,-47,-46,-77,-76,-97,-98,-81,-55,-80,-136,-135,-134,-127,-128,-122,-121,-120,262,-96,-87,-88,-74,-75,262,262,262,262,262,262,-45,-70,-83,-56,-69,-117,-118,-116,262,262,262,262,262,262,-132,-131,-130,-124,-125,-86,-89,-73,-48,-82,-57,-68,262,262,262,262,262,-96,-295,-296,-297,-297,-298,-298,]),'SEMI':([0,1,2,3,5,7,8,12,13,14,15,16,18,19,20,21,22,24,26,27,28,29,31,34,35,36,38,41,43,44,45,46,47,49,50,51,53,55,56,58,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,85,87,97,99,100,101,102,103,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,147,148,155,156,159,163,164,165,166,169,172,173,176,177,178,179,196,204,209,211,213,214,216,218,221,222,223,224,227,229,239,240,241,244,245,246,247,248,249,250,270,271,280,281,282,283,288,290,291,292,293,294,295,296,297,298,299,300,301,302,303,305,310,311,312,313,314,315,318,319,320,322,323,325,326,327,328,329,330,331,332,333,334,335,336,337,338,340,341,345,346,350,353,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,380,381,382,383,386,390,391,392,404,411,413,414,416,417,418,421,422,424,427,429,433,435,436,441,442,443,445,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,466,468,471,472,475,477,480,482,483,485,486,487,490,492,500,501,502,504,506,508,510,512,514,515,516,519,522,523,524,526,528,529,531,532,533,534,536,537,540,541,542,544,547,],[72,-206,-22,-28,-15,72,-72,-94,-23,115,-71,-27,-150,-21,-42,-13,-133,-41,143,-119,-19,-17,-20,147,-126,-16,-30,-95,-11,72,-9,-105,163,-78,-10,-230,-188,-212,-200,-8,-104,-31,-24,-32,-33,-12,176,-6,72,-194,-35,-34,-244,-176,-167,-18,-182,-14,-37,-36,-43,-44,-99,-38,-29,-112,-96,-102,-92,-39,-93,-40,-103,-67,-66,-76,-41,-7,-111,-107,-292,-291,-2,240,-238,-234,-108,72,-106,-123,-157,-190,-196,-137,-270,-115,-184,-172,-208,270,-226,-129,-202,-96,-269,-178,-113,-245,-246,-1,-109,-85,-261,-262,313,-114,-84,-79,-76,-265,-266,323,-25,-100,-101,-110,340,-99,-201,-47,-46,-77,-76,-97,-98,-81,-55,-80,-232,-233,-239,-136,-135,-134,-127,-128,-283,-271,-272,-231,-122,-121,-120,-198,-162,-180,-144,-186,-174,-228,404,-192,-210,-260,-259,-96,-204,-87,-88,-287,-286,-26,-263,-264,-74,-183,-75,-195,-268,-267,-189,-168,-169,-171,-170,-155,-152,-151,-154,-153,-156,-177,-213,-45,-284,-285,-70,-83,-56,-69,-235,-242,-117,-118,-116,-142,-139,-138,-141,-140,-143,-185,-191,-132,-131,-130,-179,-158,-159,-161,-160,-227,-124,-125,-197,-209,-173,72,72,-236,443,-240,-1,-86,-89,-290,-288,-73,72,72,-207,-48,-82,-57,-68,-273,72,72,-193,-1,-241,-149,-146,-145,-148,-147,-175,-181,-163,-164,-166,-165,491,-257,-258,-187,-229,-96,-211,-199,-251,-274,-247,72,-203,-295,72,509,-237,-240,-243,72,522,72,72,72,-296,-293,-241,72,-254,-205,-289,-275,-249,-250,-248,-297,72,-294,72,-255,72,72,72,-298,72,-256,-252,-276,-253,]),'WITH':([0,2,5,7,13,19,21,28,29,31,36,43,44,45,50,58,62,65,67,68,72,75,77,111,114,115,116,126,133,143,147,148,163,164,176,177,179,240,241,250,270,271,310,311,312,313,314,322,323,340,341,383,386,414,416,418,421,435,436,441,471,472,475,477,483,492,501,502,504,508,512,514,516,519,522,523,524,528,529,531,532,533,534,536,540,541,542,544,547,],[32,-22,-15,32,-23,-21,-13,-19,-17,-20,-16,-11,32,-9,-10,-8,-24,-12,-6,32,-244,-18,-14,-7,-292,-291,-2,32,-270,-269,-245,-246,-261,-262,-265,-266,-25,-232,-233,-283,-271,-272,-287,-286,-26,-263,-264,-268,-267,-284,-285,32,32,-290,-288,32,32,-273,32,32,-251,-274,-247,32,32,32,32,32,32,-293,32,-254,-289,-275,-249,-250,-248,32,-294,32,-255,32,32,32,32,-256,-252,-276,-253,]),'MODEQUAL':([3,8,12,15,16,20,24,38,41,49,61,63,64,70,71,78,79,80,81,82,85,87,101,102,103,105,107,108,109,110,142,159,169,172,173,216,218,221,222,227,229,239,301,303,305,315,319,338,345,346,350,353,411,413,417,424,427,429,433,464,482,506,508,526,529,537,],[-28,-72,-94,-71,-27,-42,-41,-30,-95,-78,-31,-32,-33,-35,-34,-37,-36,-43,-44,198,-38,-29,-92,-39,-93,-40,-67,-66,-76,-41,198,-85,-84,-79,-76,-47,-46,-77,-76,-81,-55,-80,198,-87,-88,-74,-75,-45,-70,-83,-56,-69,-86,-89,-73,-48,-82,-57,-68,198,-295,-296,-297,-297,-298,-298,]),'NE':([3,8,12,15,16,18,20,22,24,27,35,38,41,46,49,60,61,63,64,70,71,73,74,78,79,80,81,82,85,87,97,99,100,101,102,103,105,106,107,108,109,110,112,113,125,127,128,129,132,134,136,140,142,145,156,159,166,169,172,173,196,204,209,213,216,218,221,222,223,224,227,229,239,245,246,247,248,249,281,282,283,290,292,294,301,303,305,315,319,326,327,328,329,330,331,332,333,334,335,336,338,345,346,350,353,357,358,359,360,361,362,363,364,365,368,369,370,372,373,374,375,377,378,382,411,413,417,424,427,429,433,448,449,450,451,452,453,455,456,457,458,464,482,506,508,526,529,537,],[-28,-72,-94,-71,-27,-150,-42,-133,-41,-119,-126,-30,-95,-105,-78,-104,-31,-32,-33,-35,-34,183,-167,-37,-36,-43,-44,-99,-38,-29,-112,-96,-102,-92,-39,-93,-40,-103,-67,-66,-76,-41,-111,-107,-108,-106,-123,-157,-137,-115,267,-129,-96,-113,-109,-85,-114,-84,-79,-76,-100,-101,-110,-99,-47,-46,-77,-76,-97,-98,-81,-55,-80,-136,-135,-134,-127,-128,-122,-121,-120,-162,-144,401,-96,-87,-88,-74,-75,-168,-169,-171,-170,-155,-152,-151,-154,-153,-156,183,-45,-70,-83,-56,-69,-117,-118,-116,-142,-139,-138,-141,-140,-143,-132,-131,-130,-158,-159,-161,-160,-124,-125,267,-86,-89,-73,-48,-82,-57,-68,-149,-146,-145,-148,-147,401,-163,-164,-166,-165,-96,-295,-296,-297,-297,-298,-298,]),'MULTEQUAL':([3,8,12,15,16,20,24,38,41,49,61,63,64,70,71,78,79,80,81,82,85,87,101,102,103,105,107,108,109,110,142,159,169,172,173,216,218,221,222,227,229,239,301,303,305,315,319,338,345,346,350,353,411,413,417,424,427,429,433,464,482,506,508,526,529,537,],[-28,-72,-94,-71,-27,-42,-41,-30,-95,-78,-31,-32,-33,-35,-34,-37,-36,-43,-44,200,-38,-29,-92,-39,-93,-40,-67,-66,-76,-41,200,-85,-84,-79,-76,-47,-46,-77,-76,-81,-55,-80,200,-87,-88,-74,-75,-45,-70,-83,-56,-69,-86,-89,-73,-48,-82,-57,-68,200,-295,-296,-297,-297,-298,-298,]),'EQEQ':([3,8,12,15,16,18,20,22,24,27,35,38,41,46,49,60,61,63,64,70,71,73,74,78,79,80,81,82,85,87,97,99,100,101,102,103,105,106,107,108,109,110,112,113,125,127,128,129,132,134,136,140,142,145,156,159,166,169,172,173,196,204,209,213,216,218,221,222,223,224,227,229,239,245,246,247,248,249,281,282,283,290,292,294,301,303,305,315,319,326,327,328,329,330,331,332,333,334,335,336,338,345,346,350,353,357,358,359,360,361,362,363,364,365,368,369,370,372,373,374,375,377,378,382,411,413,417,424,427,429,433,448,449,450,451,452,453,455,456,457,458,464,482,506,508,526,529,537,],[-28,-72,-94,-71,-27,-150,-42,-133,-41,-119,-126,-30,-95,-105,-78,-104,-31,-32,-33,-35,-34,182,-167,-37,-36,-43,-44,-99,-38,-29,-112,-96,-102,-92,-39,-93,-40,-103,-67,-66,-76,-41,-111,-107,-108,-106,-123,-157,-137,-115,266,-129,-96,-113,-109,-85,-114,-84,-79,-76,-100,-101,-110,-99,-47,-46,-77,-76,-97,-98,-81,-55,-80,-136,-135,-134,-127,-128,-122,-121,-120,-162,-144,400,-96,-87,-88,-74,-75,-168,-169,-171,-170,-155,-152,-151,-154,-153,-156,182,-45,-70,-83,-56,-69,-117,-118,-116,-142,-139,-138,-141,-140,-143,-132,-131,-130,-158,-159,-161,-160,-124,-125,266,-86,-89,-73,-48,-82,-57,-68,-149,-146,-145,-148,-147,400,-163,-164,-166,-165,-96,-295,-296,-297,-297,-298,-298,]),'SWITCH':([0,2,5,7,13,19,21,28,29,31,36,43,44,45,50,58,62,65,67,68,72,75,77,111,114,115,116,126,133,143,147,148,163,164,176,177,179,240,241,250,270,271,310,311,312,313,314,322,323,340,341,383,386,414,416,418,421,435,436,441,471,472,475,477,483,492,501,502,504,508,512,514,516,519,522,523,524,528,529,531,532,533,534,536,540,541,542,544,547,],[57,-22,-15,57,-23,-21,-13,-19,-17,-20,-16,-11,57,-9,-10,-8,-24,-12,-6,57,-244,-18,-14,-7,-292,-291,-2,57,-270,-269,-245,-246,-261,-262,-265,-266,-25,-232,-233,-283,-271,-272,-287,-286,-26,-263,-264,-268,-267,-284,-285,57,57,-290,-288,57,57,-273,57,57,-251,-274,-247,57,57,57,57,57,57,-293,57,-254,-289,-275,-249,-250,-248,57,-294,57,-255,57,57,57,57,-256,-252,-276,-253,]),'LSHIFTEQUAL':([3,8,12,15,16,20,24,38,41,49,61,63,64,70,71,78,79,80,81,82,85,87,101,102,103,105,107,108,109,110,142,159,169,172,173,216,218,221,222,227,229,239,301,303,305,315,319,338,345,346,350,353,411,413,417,424,427,429,433,464,482,506,508,526,529,537,],[-28,-72,-94,-71,-27,-42,-41,-30,-95,-78,-31,-32,-33,-35,-34,-37,-36,-43,-44,202,-38,-29,-92,-39,-93,-40,-67,-66,-76,-41,202,-85,-84,-79,-76,-47,-46,-77,-76,-81,-55,-80,202,-87,-88,-74,-75,-45,-70,-83,-56,-69,-86,-89,-73,-48,-82,-57,-68,202,-295,-296,-297,-297,-298,-298,]),'PLUS':([0,2,3,4,5,6,7,8,10,11,12,13,15,16,19,20,21,22,23,24,25,26,27,28,29,30,31,35,36,38,40,41,43,44,45,46,48,49,50,58,60,61,62,63,64,65,67,68,70,71,72,75,77,78,79,80,81,82,83,84,85,87,88,89,90,92,93,94,95,97,99,100,101,102,103,105,106,107,108,109,110,111,112,113,114,115,116,120,121,122,123,124,125,126,127,128,133,134,140,142,143,145,146,147,148,149,150,151,152,155,156,158,159,160,163,164,166,168,169,170,171,172,173,174,175,176,177,179,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,209,210,213,215,216,218,219,221,222,223,224,226,227,229,238,239,240,241,243,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,281,282,283,301,303,305,310,311,312,313,314,315,319,322,323,338,340,341,342,343,345,346,350,352,353,357,358,359,368,369,370,377,378,383,386,389,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,416,417,418,420,421,424,427,429,433,434,435,436,441,443,446,447,464,471,472,475,477,482,483,488,491,492,493,495,501,502,504,506,508,509,512,514,516,519,522,523,524,526,528,529,531,532,533,534,536,537,540,541,542,544,547,],[10,-22,-28,-1,-15,10,10,-72,10,10,-94,-23,-71,-27,-21,-42,-13,123,10,-41,10,10,-119,-19,-17,10,-20,-126,-16,-30,10,-95,-11,10,-9,-105,10,-78,-10,-8,-104,-31,-24,-32,-33,-12,-6,10,-35,-34,-244,-18,-14,-37,-36,-43,-44,-99,10,10,-38,-29,10,10,10,10,-53,-52,-51,-112,-96,-102,-92,-39,-93,-40,-103,-67,-66,-76,-41,-7,-111,-107,-292,-291,-2,10,10,10,10,10,-108,10,-106,-123,-270,-115,273,-96,-269,-113,10,-245,-246,10,10,10,10,10,-109,10,-85,10,-261,-262,-114,10,-84,10,10,-79,-76,10,10,-265,-266,-25,10,10,10,10,10,10,10,10,10,10,10,10,-216,-221,-222,-100,-219,-217,-224,-215,-218,-220,-223,-101,-214,-225,10,-110,10,-99,-1,-47,-46,-54,-77,-76,-97,-98,10,-81,-55,10,-80,-232,-233,10,273,273,273,-127,-128,-283,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,-271,-272,10,10,10,10,10,10,10,-122,-121,-120,-96,-87,-88,-287,-286,-26,-263,-264,-74,-75,-268,-267,-45,-284,-285,10,10,-70,-83,-56,10,-69,-117,-118,-116,273,273,273,-124,-125,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,-86,10,-89,-290,-288,-73,10,10,10,-48,-82,-57,-68,10,-273,10,10,10,10,10,-96,-251,-274,-247,10,-295,10,10,10,10,10,10,10,10,10,-296,-293,10,10,-254,-289,-275,-249,-250,-248,-297,10,-294,10,-255,10,10,10,-298,10,-256,-252,-276,-253,]),'CATCH':([161,312,],[309,-26,]),'COMMA':([1,3,4,8,12,15,16,18,20,22,24,27,34,35,38,41,46,49,51,53,55,56,60,61,63,64,69,70,71,73,74,76,78,79,80,81,82,85,87,91,93,94,97,99,100,101,102,103,105,106,107,108,109,110,112,113,117,118,119,125,127,128,129,130,131,132,134,135,136,137,138,139,140,141,142,144,145,156,159,166,169,172,173,196,204,208,209,211,213,214,215,216,217,218,219,221,222,223,224,227,229,230,233,239,244,245,246,247,248,249,279,280,281,282,283,284,286,288,290,291,292,293,294,295,297,298,299,301,302,303,304,305,306,307,315,316,317,318,319,320,321,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,345,346,347,350,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,380,381,382,387,390,391,392,411,413,417,422,423,424,425,427,429,430,432,433,437,442,445,448,449,450,451,452,453,454,455,456,457,458,461,462,463,464,465,466,468,469,474,479,480,482,486,487,489,490,506,508,510,511,515,517,526,529,537,538,546,],[-206,-28,93,-72,-94,-71,-27,-150,-42,-133,-41,-119,149,-126,-30,-95,-105,-78,-230,-188,-212,-200,-104,-31,-32,-33,-194,-35,-34,-176,-167,-182,-37,-36,-43,-44,-99,-38,-29,215,-53,219,-112,-96,-102,-92,-39,-93,-40,-103,-67,-66,-76,-41,-111,-107,242,-238,-234,-108,-106,-123,-157,-190,-196,-137,-115,-184,-172,-208,272,-226,-129,-202,-96,-178,-113,-109,-85,-114,-84,-79,-76,-100,-101,272,-110,272,-99,-201,93,-47,-49,-46,-54,-77,-76,-97,-98,-81,-55,349,-58,-80,-239,-136,-135,-134,-127,-128,272,-231,-122,-121,-120,385,-299,-198,-162,-180,-144,-186,-174,-228,-192,-210,406,-96,-204,-87,272,-88,412,-90,-74,272,272,-183,-75,-195,272,-189,-168,-169,-171,-170,-155,-152,-151,-154,-153,-156,-177,-213,-45,272,-70,-83,272,-56,-69,272,-235,-242,-117,-118,-116,-142,-139,-138,-141,-140,-143,-185,-191,-132,-131,-130,-179,-158,-159,-161,-160,-227,-124,-125,-197,-209,-173,385,-236,444,-240,-86,-89,-73,-207,-50,-48,385,-82,-57,-59,-60,-68,-300,-193,-241,-149,-146,-145,-148,-147,-175,-181,-163,-164,-166,-165,272,-187,-229,-96,272,-211,-199,-91,272,385,-203,-295,-237,-240,272,-243,-296,-297,-241,272,-205,272,-297,-298,-298,-61,-62,]),'STREQ':([3,8,12,15,16,18,20,22,24,27,35,38,41,46,49,60,61,63,64,70,71,73,74,78,79,80,81,82,85,87,97,99,100,101,102,103,105,106,107,108,109,110,112,113,125,127,128,129,132,134,136,140,142,145,156,159,166,169,172,173,196,204,209,213,216,218,221,222,223,224,227,229,239,245,246,247,248,249,281,282,283,290,292,294,301,303,305,315,319,326,327,328,329,330,331,332,333,334,335,336,338,345,346,350,353,357,358,359,360,361,362,363,364,365,368,369,370,372,373,374,375,377,378,382,411,413,417,424,427,429,433,448,449,450,451,452,453,455,456,457,458,464,482,506,508,526,529,537,],[-28,-72,-94,-71,-27,-150,-42,-133,-41,-119,-126,-30,-95,-105,-78,-104,-31,-32,-33,-35,-34,185,-167,-37,-36,-43,-44,-99,-38,-29,-112,-96,-102,-92,-39,-93,-40,-103,-67,-66,-76,-41,-111,-107,-108,-106,-123,-157,-137,-115,269,-129,-96,-113,-109,-85,-114,-84,-79,-76,-100,-101,-110,-99,-47,-46,-77,-76,-97,-98,-81,-55,-80,-136,-135,-134,-127,-128,-122,-121,-120,-162,-144,403,-96,-87,-88,-74,-75,-168,-169,-171,-170,-155,-152,-151,-154,-153,-156,185,-45,-70,-83,-56,-69,-117,-118,-116,-142,-139,-138,-141,-140,-143,-132,-131,-130,-158,-159,-161,-160,-124,-125,269,-86,-89,-73,-48,-82,-57,-68,-149,-146,-145,-148,-147,403,-163,-164,-166,-165,-96,-295,-296,-297,-297,-298,-298,]),'BOR':([3,8,12,15,16,18,20,22,24,27,35,38,41,46,49,53,60,61,63,64,69,70,71,73,74,76,78,79,80,81,82,85,87,97,99,100,101,102,103,105,106,107,108,109,110,112,113,125,127,128,129,130,132,134,135,136,140,142,144,145,156,159,166,169,172,173,196,204,209,213,216,218,221,222,223,224,227,229,239,245,246,247,248,249,281,282,283,290,291,292,293,294,297,301,303,305,315,318,319,320,325,326,327,328,329,330,331,332,333,334,335,336,338,345,346,350,353,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,377,378,382,411,413,417,424,427,429,433,442,448,449,450,451,452,453,454,455,456,457,458,462,464,482,506,508,526,529,537,],[-28,-72,-94,-71,-27,-150,-42,-133,-41,-119,-126,-30,-95,-105,-78,-188,-104,-31,-32,-33,181,-35,-34,-176,-167,-182,-37,-36,-43,-44,-99,-38,-29,-112,-96,-102,-92,-39,-93,-40,-103,-67,-66,-76,-41,-111,-107,-108,-106,-123,-157,260,-137,-115,-184,-172,-129,-96,-178,-113,-109,-85,-114,-84,-79,-76,-100,-101,-110,-99,-47,-46,-77,-76,-97,-98,-81,-55,-80,-136,-135,-134,-127,-128,-122,-121,-120,-162,-180,-144,-186,-174,405,-96,-87,-88,-74,-183,-75,181,-189,-168,-169,-171,-170,-155,-152,-151,-154,-153,-156,-177,-45,-70,-83,-56,-69,-117,-118,-116,-142,-139,-138,-141,-140,-143,-185,260,-132,-131,-130,-179,-158,-159,-161,-160,-124,-125,-173,-86,-89,-73,-48,-82,-57,-68,405,-149,-146,-145,-148,-147,-175,-181,-163,-164,-166,-165,-187,-96,-295,-296,-297,-297,-298,-298,]),'$end':([0,2,5,7,9,13,19,21,28,29,31,33,36,43,45,50,58,59,62,65,67,72,75,77,111,114,115,116,133,143,147,148,163,164,176,177,179,240,241,250,270,271,310,311,312,313,314,322,323,340,341,414,416,435,471,472,475,508,514,516,519,522,523,524,529,532,541,542,544,547,],[-1,-22,-15,-5,0,-23,-21,-13,-19,-17,-20,-3,-16,-11,-9,-10,-8,-4,-24,-12,-6,-244,-18,-14,-7,-292,-291,-2,-270,-269,-245,-246,-261,-262,-265,-266,-25,-232,-233,-283,-271,-272,-287,-286,-26,-263,-264,-268,-267,-284,-285,-290,-288,-273,-251,-274,-247,-293,-254,-289,-275,-249,-250,-248,-294,-255,-256,-252,-276,-253,]),'FUNCTION':([0,2,4,5,6,7,10,11,13,19,21,23,25,26,28,29,30,31,36,40,43,44,45,48,50,54,58,62,65,67,68,72,75,77,83,84,88,89,90,92,93,94,95,98,111,114,115,116,120,121,122,123,124,126,133,143,146,147,148,149,150,151,152,155,158,160,163,164,168,170,171,174,175,176,177,179,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,197,198,199,200,201,202,203,205,206,207,210,215,219,226,238,240,241,243,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,310,311,312,313,314,322,323,340,341,342,343,352,383,386,389,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,412,414,416,418,420,421,434,435,436,441,443,446,447,471,472,475,477,483,488,491,492,493,495,501,502,504,508,509,512,514,516,519,522,523,524,528,529,531,532,533,534,536,540,541,542,544,547,],[37,-22,-1,-15,96,37,96,96,-23,-21,-13,96,96,96,-19,-17,96,-20,-16,96,-11,37,-9,96,-10,96,-8,-24,-12,-6,37,-244,-18,-14,96,96,96,96,96,96,-53,-52,-51,96,-7,-292,-291,-2,96,96,96,96,96,37,-270,-269,96,-245,-246,96,96,96,96,96,96,96,-261,-262,96,96,96,96,96,-265,-266,-25,96,96,96,96,96,96,96,96,96,96,96,96,-216,-221,-222,-219,-217,-224,-215,-218,-220,-223,-214,-225,96,96,-1,-54,96,96,-232,-233,96,-283,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,-271,-272,96,96,96,96,96,96,96,-287,-286,-26,-263,-264,-268,-267,-284,-285,96,96,96,37,37,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,96,-290,-288,37,96,37,96,-273,37,37,96,96,96,-251,-274,-247,37,37,96,96,37,96,96,37,37,37,-293,96,37,-254,-289,-275,-249,-250,-248,37,-294,37,-255,37,37,37,37,-256,-252,-276,-253,]),'INSTANCEOF':([3,8,12,15,16,18,20,22,24,27,35,38,41,46,49,60,61,63,64,70,71,74,78,79,80,81,82,85,87,97,99,100,101,102,103,105,106,107,108,109,110,112,113,125,127,128,129,132,134,140,142,145,156,159,166,169,172,173,196,204,209,213,216,218,221,222,223,224,227,229,239,245,246,247,248,249,281,282,283,290,292,301,303,305,315,319,326,327,328,329,330,331,332,333,334,335,338,345,346,350,353,357,358,359,360,361,362,363,364,365,368,369,370,372,373,374,375,377,378,411,413,417,424,427,429,433,448,449,450,451,452,455,456,457,458,464,482,506,508,526,529,537,],[-28,-72,-94,-71,-27,-150,-42,-133,-41,-119,-126,-30,-95,-105,-78,-104,-31,-32,-33,-35,-34,186,-37,-36,-43,-44,-99,-38,-29,-112,-96,-102,-92,-39,-93,-40,-103,-67,-66,-76,-41,-111,-107,-108,-106,-123,254,-137,-115,-129,-96,-113,-109,-85,-114,-84,-79,-76,-100,-101,-110,-99,-47,-46,-77,-76,-97,-98,-81,-55,-80,-136,-135,-134,-127,-128,-122,-121,-120,393,-144,-96,-87,-88,-74,-75,254,254,254,254,-155,-152,-151,-154,-153,-156,-45,-70,-83,-56,-69,-117,-118,-116,-142,-139,-138,-141,-140,-143,-132,-131,-130,254,254,254,254,-124,-125,-86,-89,-73,-48,-82,-57,-68,-149,-146,-145,-148,-147,254,254,254,254,-96,-295,-296,-297,-297,-298,-298,]),'GT':([3,8,12,15,16,18,20,22,24,27,35,38,41,46,49,60,61,63,64,70,71,74,78,79,80,81,82,85,87,97,99,100,101,102,103,105,106,107,108,109,110,112,113,125,127,128,129,132,134,140,142,145,156,159,166,169,172,173,196,204,209,213,216,218,221,222,223,224,227,229,239,245,246,247,248,249,281,282,283,290,292,301,303,305,315,319,326,327,328,329,330,331,332,333,334,335,338,345,346,350,353,357,358,359,360,361,362,363,364,365,368,369,370,372,373,374,375,377,378,411,413,417,424,427,429,433,448,449,450,451,452,455,456,457,458,464,482,506,508,526,529,537,],[-28,-72,-94,-71,-27,-150,-42,-133,-41,-119,-126,-30,-95,-105,-78,-104,-31,-32,-33,-35,-34,187,-37,-36,-43,-44,-99,-38,-29,-112,-96,-102,-92,-39,-93,-40,-103,-67,-66,-76,-41,-111,-107,-108,-106,-123,255,-137,-115,-129,-96,-113,-109,-85,-114,-84,-79,-76,-100,-101,-110,-99,-47,-46,-77,-76,-97,-98,-81,-55,-80,-136,-135,-134,-127,-128,-122,-121,-120,394,-144,-96,-87,-88,-74,-75,255,255,255,255,-155,-152,-151,-154,-153,-156,-45,-70,-83,-56,-69,-117,-118,-116,-142,-139,-138,-141,-140,-143,-132,-131,-130,255,255,255,255,-124,-125,-86,-89,-73,-48,-82,-57,-68,-149,-146,-145,-148,-147,255,255,255,255,-96,-295,-296,-297,-297,-298,-298,]),'STRING':([0,2,4,5,6,7,10,11,13,19,21,23,25,26,28,29,30,31,36,40,43,44,45,48,50,54,58,62,65,67,68,72,75,77,83,84,88,89,90,92,93,94,95,98,104,111,114,115,116,120,121,122,123,124,126,133,143,146,147,148,149,150,151,152,155,158,160,163,164,168,170,171,174,175,176,177,179,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,197,198,199,200,201,202,203,205,206,207,210,215,219,226,228,231,238,240,241,243,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,310,311,312,313,314,322,323,340,341,342,343,349,352,383,386,389,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,412,414,416,418,420,421,434,435,436,441,443,446,447,471,472,475,477,483,488,491,492,493,495,501,502,504,508,509,512,514,516,519,522,523,524,528,529,531,532,533,534,536,540,541,542,544,547,],[79,-22,-1,-15,79,79,79,79,-23,-21,-13,79,79,79,-19,-17,79,-20,-16,79,-11,79,-9,79,-10,79,-8,-24,-12,-6,79,-244,-18,-14,79,79,79,79,79,79,-53,-52,-51,79,79,-7,-292,-291,-2,79,79,79,79,79,79,-270,-269,79,-245,-246,79,79,79,79,79,79,79,-261,-262,79,79,79,79,79,-265,-266,-25,79,79,79,79,79,79,79,79,79,79,79,79,-216,-221,-222,-219,-217,-224,-215,-218,-220,-223,-214,-225,79,79,-1,-54,79,79,79,79,-232,-233,79,-283,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,-271,-272,79,79,79,79,79,79,79,-287,-286,-26,-263,-264,-268,-267,-284,-285,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,79,-290,-288,79,79,79,79,-273,79,79,79,79,79,-251,-274,-247,79,79,79,79,79,79,79,79,79,79,-293,79,79,-254,-289,-275,-249,-250,-248,79,-294,79,-255,79,79,79,79,-256,-252,-276,-253,]),'FOR':([0,2,5,7,13,19,21,28,29,31,36,43,44,45,50,58,62,65,67,68,72,75,77,111,114,115,116,126,133,143,147,148,163,164,176,177,179,240,241,250,270,271,310,311,312,313,314,322,323,340,341,383,386,414,416,418,421,435,436,441,471,472,475,477,483,492,501,502,504,508,512,514,516,519,522,523,524,528,529,531,532,533,534,536,540,541,542,544,547,],[39,-22,-15,39,-23,-21,-13,-19,-17,-20,-16,-11,39,-9,-10,-8,-24,-12,-6,39,-244,-18,-14,-7,-292,-291,-2,39,-270,-269,-245,-246,-261,-262,-265,-266,-25,-232,-233,-283,-271,-272,-287,-286,-26,-263,-264,-268,-267,-284,-285,39,39,-290,-288,39,39,-273,39,39,-251,-274,-247,39,39,39,39,39,39,-293,39,-254,-289,-275,-249,-250,-248,39,-294,39,-255,39,39,39,39,-256,-252,-276,-253,]),'PLUSPLUS':([0,2,3,4,5,6,7,8,10,11,12,13,15,16,19,20,21,23,24,25,26,28,29,30,31,36,38,40,41,43,44,45,48,49,50,58,61,62,63,64,65,67,68,70,71,72,75,77,78,79,80,81,82,83,84,85,87,88,89,90,92,93,94,95,99,101,102,103,105,107,108,109,110,111,114,115,116,120,121,122,123,124,126,133,142,143,146,147,148,149,150,151,152,155,158,159,160,163,164,168,169,170,171,172,173,174,175,176,177,179,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,197,198,199,200,201,202,203,205,206,207,210,213,215,216,218,219,221,222,226,227,229,238,239,240,241,243,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,301,303,305,310,311,312,313,314,315,319,322,323,338,340,341,342,343,345,346,350,352,353,383,386,389,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,416,417,418,420,421,424,427,429,433,434,435,436,441,443,446,447,464,471,472,475,477,482,483,488,491,492,493,495,501,502,504,506,508,509,512,514,516,519,522,523,524,526,528,529,531,532,533,534,536,537,540,541,542,544,547,],[40,-22,-28,-1,-15,40,40,-72,40,40,-94,-23,-71,-27,-21,-42,-13,40,-41,40,40,-19,-17,40,-20,-16,-30,40,-95,-11,40,-9,40,-78,-10,-8,-31,-24,-32,-33,-12,-6,40,-35,-34,-244,-18,-14,-37,-36,-43,-44,196,40,40,-38,-29,40,40,40,40,-53,-52,-51,223,-92,-39,-93,-40,-67,-66,-76,-41,-7,-292,-291,-2,40,40,40,40,40,40,-270,223,-269,40,-245,-246,40,40,40,40,40,40,-85,40,-261,-262,40,-84,40,40,-79,-76,40,40,-265,-266,-25,40,40,40,40,40,40,40,40,40,40,40,40,-216,-221,-222,-219,-217,-224,-215,-218,-220,-223,-214,-225,40,40,196,-1,-47,-46,-54,-77,-76,40,-81,-55,40,-80,-232,-233,40,-283,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,-271,-272,40,40,40,40,40,40,40,223,-87,-88,-287,-286,-26,-263,-264,-74,-75,-268,-267,-45,-284,-285,40,40,-70,-83,-56,40,-69,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,-86,40,-89,-290,-288,-73,40,40,40,-48,-82,-57,-68,40,-273,40,40,40,40,40,223,-251,-274,-247,40,-295,40,40,40,40,40,40,40,40,40,-296,-293,40,40,-254,-289,-275,-249,-250,-248,-297,40,-294,40,-255,40,40,40,-298,40,-256,-252,-276,-253,]),'PERIOD':([3,8,15,16,20,24,38,41,49,61,63,64,70,71,78,79,80,81,85,87,102,103,105,107,108,109,110,159,169,173,216,218,222,227,229,239,303,305,315,319,338,345,346,350,353,411,413,417,424,427,429,433,482,506,508,526,529,537,],[-28,-72,-71,-27,-42,-41,-30,157,167,-31,-32,-33,-35,-34,-37,-36,-43,-44,-38,-29,-39,225,-40,-67,-66,237,-41,-85,-84,237,-47,-46,237,-81,-55,-80,-87,-88,-74,-75,-45,-70,-83,-56,-69,-86,-89,-73,-48,-82,-57,-68,-295,-296,-297,-297,-298,-298,]),'RBRACE':([2,3,5,7,13,16,19,20,21,28,29,31,36,38,43,44,45,50,58,59,61,62,63,64,65,67,70,71,72,75,77,78,79,80,81,85,87,97,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,125,127,128,129,130,131,132,133,134,135,136,137,140,141,142,143,144,145,147,148,156,162,163,164,166,176,177,179,209,216,218,221,222,223,224,227,229,230,233,239,240,241,250,270,271,305,310,311,312,313,314,322,323,338,340,341,345,346,349,350,353,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,377,378,380,381,382,386,413,414,416,424,427,429,430,432,433,435,436,438,439,441,471,472,473,475,477,480,481,482,483,484,496,497,498,499,502,503,504,506,507,508,514,516,518,519,520,522,523,524,525,526,527,528,529,532,534,535,536,537,538,539,541,542,543,544,545,546,547,],[-22,-28,-15,-5,-23,-27,-21,-42,-13,-19,-17,-20,-16,-30,-11,-1,-9,-10,-8,-4,-31,-24,-32,-33,-12,-6,-35,-34,-244,-18,-14,-37,-36,-43,-44,-38,-29,-112,-96,-102,-92,-39,-93,229,-40,-103,-67,-66,-76,-41,-7,-111,-107,-292,-291,-2,-108,-106,-123,-157,-190,-196,-137,-270,-115,-184,-172,-208,-129,-202,-96,-269,-178,-113,-245,-246,-109,312,-261,-262,-114,-265,-266,-25,-110,-47,-46,-77,-76,-97,-98,-81,-55,350,-58,-80,-232,-233,-283,-271,-272,-88,-287,-286,-26,-263,-264,-268,-267,-45,-284,-285,-70,-83,429,-56,-69,-117,-118,-116,-142,-139,-138,-141,-140,-143,-185,-191,-132,-131,-130,-179,-158,-159,-161,-160,-124,-125,-197,-209,-173,-1,-89,-290,-288,-48,-82,-57,-59,-60,-68,-273,-1,-301,482,-1,-251,-274,-1,-247,-1,-203,506,-295,-1,508,-278,519,-279,-277,-1,526,-1,-296,529,-293,-254,-289,-280,-275,-1,-249,-250,-248,537,-297,538,-1,-294,-255,-1,544,-1,-298,-61,546,-256,-252,-281,-276,-282,-62,-253,]),'ELSE':([2,5,13,19,21,28,29,31,36,43,50,62,65,72,75,77,114,115,116,133,143,147,148,163,164,176,177,179,240,241,250,270,271,310,311,312,313,314,322,323,340,341,414,416,435,471,472,475,508,514,516,519,522,523,524,529,532,541,542,544,547,],[-22,-15,-23,-21,-13,-19,-17,-20,-16,-11,-10,-24,-12,-244,-18,-14,-292,-291,-2,-270,-269,-245,-246,-261,-262,-265,-266,-25,-232,-233,-283,-271,-272,-287,-286,-26,-263,-264,-268,-267,-284,-285,-290,-288,-273,-251,-274,501,-293,-254,-289,-275,-249,-250,-248,-294,-255,-256,-252,-276,-253,]),'TRY':([0,2,5,7,13,19,21,28,29,31,36,43,44,45,50,58,62,65,67,68,72,75,77,111,114,115,116,126,133,143,147,148,163,164,176,177,179,240,241,250,270,271,310,311,312,313,314,322,323,340,341,383,386,414,416,418,421,435,436,441,471,472,475,477,483,492,501,502,504,508,512,514,516,519,522,523,524,528,529,531,532,533,534,536,540,541,542,544,547,],[42,-22,-15,42,-23,-21,-13,-19,-17,-20,-16,-11,42,-9,-10,-8,-24,-12,-6,42,-244,-18,-14,-7,-292,-291,-2,42,-270,-269,-245,-246,-261,-262,-265,-266,-25,-232,-233,-283,-271,-272,-287,-286,-26,-263,-264,-268,-267,-284,-285,42,42,-290,-288,42,42,-273,42,42,-251,-274,-247,42,42,42,42,42,42,-293,42,-254,-289,-275,-249,-250,-248,42,-294,42,-255,42,42,42,42,-256,-252,-276,-253,]),'BAND':([3,8,12,15,16,18,20,22,24,27,35,38,41,46,49,60,61,63,64,70,71,73,74,76,78,79,80,81,82,85,87,97,99,100,101,102,103,105,106,107,108,109,110,112,113,125,127,128,129,132,134,136,140,142,144,145,156,159,166,169,172,173,196,204,209,213,216,218,221,222,223,224,227,229,239,245,246,247,248,249,281,282,283,290,291,292,294,301,303,305,315,318,319,326,327,328,329,330,331,332,333,334,335,336,338,345,346,350,353,357,358,359,360,361,362,363,364,365,368,369,370,371,372,373,374,375,377,378,382,411,413,417,424,427,429,433,448,449,450,451,452,453,454,455,456,457,458,464,482,506,508,526,529,537,],[-28,-72,-94,-71,-27,-150,-42,-133,-41,-119,-126,-30,-95,-105,-78,-104,-31,-32,-33,-35,-34,-176,-167,192,-37,-36,-43,-44,-99,-38,-29,-112,-96,-102,-92,-39,-93,-40,-103,-67,-66,-76,-41,-111,-107,-108,-106,-123,-157,-137,-115,-172,-129,-96,278,-113,-109,-85,-114,-84,-79,-76,-100,-101,-110,-99,-47,-46,-77,-76,-97,-98,-81,-55,-80,-136,-135,-134,-127,-128,-122,-121,-120,-162,398,-144,-174,-96,-87,-88,-74,192,-75,-168,-169,-171,-170,-155,-152,-151,-154,-153,-156,-177,-45,-70,-83,-56,-69,-117,-118,-116,-142,-139,-138,-141,-140,-143,-132,-131,-130,278,-158,-159,-161,-160,-124,-125,-173,-86,-89,-73,-48,-82,-57,-68,-149,-146,-145,-148,-147,-175,398,-163,-164,-166,-165,-96,-295,-296,-297,-297,-298,-298,]),'GE':([3,8,12,15,16,18,20,22,24,27,35,38,41,46,49,60,61,63,64,70,71,74,78,79,80,81,82,85,87,97,99,100,101,102,103,105,106,107,108,109,110,112,113,125,127,128,129,132,134,140,142,145,156,159,166,169,172,173,196,204,209,213,216,218,221,222,223,224,227,229,239,245,246,247,248,249,281,282,283,290,292,301,303,305,315,319,326,327,328,329,330,331,332,333,334,335,338,345,346,350,353,357,358,359,360,361,362,363,364,365,368,369,370,372,373,374,375,377,378,411,413,417,424,427,429,433,448,449,450,451,452,455,456,457,458,464,482,506,508,526,529,537,],[-28,-72,-94,-71,-27,-150,-42,-133,-41,-119,-126,-30,-95,-105,-78,-104,-31,-32,-33,-35,-34,189,-37,-36,-43,-44,-99,-38,-29,-112,-96,-102,-92,-39,-93,-40,-103,-67,-66,-76,-41,-111,-107,-108,-106,-123,257,-137,-115,-129,-96,-113,-109,-85,-114,-84,-79,-76,-100,-101,-110,-99,-47,-46,-77,-76,-97,-98,-81,-55,-80,-136,-135,-134,-127,-128,-122,-121,-120,396,-144,-96,-87,-88,-74,-75,257,257,257,257,-155,-152,-151,-154,-153,-156,-45,-70,-83,-56,-69,-117,-118,-116,-142,-139,-138,-141,-140,-143,-132,-131,-130,257,257,257,257,-124,-125,-86,-89,-73,-48,-82,-57,-68,-149,-146,-145,-148,-147,257,257,257,257,-96,-295,-296,-297,-297,-298,-298,]),'LT':([3,8,12,15,16,18,20,22,24,27,35,38,41,46,49,60,61,63,64,70,71,74,78,79,80,81,82,85,87,97,99,100,101,102,103,105,106,107,108,109,110,112,113,125,127,128,129,132,134,140,142,145,156,159,166,169,172,173,196,204,209,213,216,218,221,222,223,224,227,229,239,245,246,247,248,249,281,282,283,290,292,301,303,305,315,319,326,327,328,329,330,331,332,333,334,335,338,345,346,350,353,357,358,359,360,361,362,363,364,365,368,369,370,372,373,374,375,377,378,411,413,417,424,427,429,433,448,449,450,451,452,455,456,457,458,464,482,506,508,526,529,537,],[-28,-72,-94,-71,-27,-150,-42,-133,-41,-119,-126,-30,-95,-105,-78,-104,-31,-32,-33,-35,-34,188,-37,-36,-43,-44,-99,-38,-29,-112,-96,-102,-92,-39,-93,-40,-103,-67,-66,-76,-41,-111,-107,-108,-106,-123,256,-137,-115,-129,-96,-113,-109,-85,-114,-84,-79,-76,-100,-101,-110,-99,-47,-46,-77,-76,-97,-98,-81,-55,-80,-136,-135,-134,-127,-128,-122,-121,-120,395,-144,-96,-87,-88,-74,-75,256,256,256,256,-155,-152,-151,-154,-153,-156,-45,-70,-83,-56,-69,-117,-118,-116,-142,-139,-138,-141,-140,-143,-132,-131,-130,256,256,256,256,-124,-125,-86,-89,-73,-48,-82,-57,-68,-149,-146,-145,-148,-147,256,256,256,256,-96,-295,-296,-297,-297,-298,-298,]),'REGEX':([0,2,4,5,6,7,10,11,13,19,21,23,25,26,28,29,30,31,36,40,43,44,45,48,50,54,58,62,65,67,68,72,75,77,83,84,88,89,90,92,93,94,95,98,111,114,115,116,120,121,122,123,124,126,133,143,146,147,148,149,150,151,152,155,158,160,163,164,168,170,171,174,175,176,177,179,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,197,198,199,200,201,202,203,205,206,207,210,215,219,226,238,240,241,243,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,310,311,312,313,314,322,323,340,341,342,343,352,383,386,389,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,412,414,416,418,420,421,434,435,436,441,443,446,447,471,472,475,477,483,488,491,492,493,495,501,502,504,508,509,512,514,516,519,522,523,524,528,529,531,532,533,534,536,540,541,542,544,547,],[78,-22,-1,-15,78,78,78,78,-23,-21,-13,78,78,78,-19,-17,78,-20,-16,78,-11,78,-9,78,-10,78,-8,-24,-12,-6,78,-244,-18,-14,78,78,78,78,78,78,-53,-52,-51,78,-7,-292,-291,-2,78,78,78,78,78,78,-270,-269,78,-245,-246,78,78,78,78,78,78,78,-261,-262,78,78,78,78,78,-265,-266,-25,78,78,78,78,78,78,78,78,78,78,78,78,-216,-221,-222,-219,-217,-224,-215,-218,-220,-223,-214,-225,78,78,-1,-54,78,78,-232,-233,78,-283,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,-271,-272,78,78,78,78,78,78,78,-287,-286,-26,-263,-264,-268,-267,-284,-285,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,-290,-288,78,78,78,78,-273,78,78,78,78,78,-251,-274,-247,78,78,78,78,78,78,78,78,78,78,-293,78,78,-254,-289,-275,-249,-250,-248,78,-294,78,-255,78,78,78,78,-256,-252,-276,-253,]),'STRNEQ':([3,8,12,15,16,18,20,22,24,27,35,38,41,46,49,60,61,63,64,70,71,73,74,78,79,80,81,82,85,87,97,99,100,101,102,103,105,106,107,108,109,110,112,113,125,127,128,129,132,134,136,140,142,145,156,159,166,169,172,173,196,204,209,213,216,218,221,222,223,224,227,229,239,245,246,247,248,249,281,282,283,290,292,294,301,303,305,315,319,326,327,328,329,330,331,332,333,334,335,336,338,345,346,350,353,357,358,359,360,361,362,363,364,365,368,369,370,372,373,374,375,377,378,382,411,413,417,424,427,429,433,448,449,450,451,452,453,455,456,457,458,464,482,506,508,526,529,537,],[-28,-72,-94,-71,-27,-150,-42,-133,-41,-119,-126,-30,-95,-105,-78,-104,-31,-32,-33,-35,-34,184,-167,-37,-36,-43,-44,-99,-38,-29,-112,-96,-102,-92,-39,-93,-40,-103,-67,-66,-76,-41,-111,-107,-108,-106,-123,-157,-137,-115,268,-129,-96,-113,-109,-85,-114,-84,-79,-76,-100,-101,-110,-99,-47,-46,-77,-76,-97,-98,-81,-55,-80,-136,-135,-134,-127,-128,-122,-121,-120,-162,-144,402,-96,-87,-88,-74,-75,-168,-169,-171,-170,-155,-152,-151,-154,-153,-156,184,-45,-70,-83,-56,-69,-117,-118,-116,-142,-139,-138,-141,-140,-143,-132,-131,-130,-158,-159,-161,-160,-124,-125,268,-86,-89,-73,-48,-82,-57,-68,-149,-146,-145,-148,-147,402,-163,-164,-166,-165,-96,-295,-296,-297,-297,-298,-298,]),'LPAREN':([0,2,3,4,5,6,7,8,10,11,13,15,16,19,20,21,23,24,25,26,28,29,30,31,32,36,37,38,39,40,41,43,44,45,48,49,50,52,54,57,58,61,62,63,64,65,67,68,70,71,72,75,77,78,79,80,81,83,84,85,86,87,88,89,90,92,93,94,95,96,98,102,103,105,107,108,109,110,111,114,115,116,120,121,122,123,124,126,133,143,146,147,148,149,150,151,152,154,155,158,159,160,163,164,168,169,170,171,173,174,175,176,177,179,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,197,198,199,200,201,202,203,205,206,207,210,215,216,218,219,220,222,226,227,229,232,234,236,238,239,240,241,243,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,303,305,309,310,311,312,313,314,315,319,322,323,324,338,340,341,342,343,345,346,348,350,351,352,353,383,386,389,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,416,417,418,420,421,424,427,429,433,434,435,436,441,443,446,447,471,472,475,477,482,483,488,491,492,493,495,501,502,504,506,508,509,512,514,516,519,522,523,524,526,528,529,531,532,533,534,536,537,540,541,542,544,547,],[83,-22,-28,-1,-15,83,83,-72,83,83,-23,-71,-27,-21,-42,-13,83,-41,83,83,-19,-17,83,-20,146,-16,153,-30,155,83,160,-11,83,-9,83,160,-10,170,83,175,-8,-31,-24,-32,-33,-12,-6,83,-35,-34,-244,-18,-14,-37,-36,-43,-44,83,83,-38,210,-29,83,83,83,83,-53,-52,-51,153,83,-39,160,-40,-67,-66,160,-41,-7,-292,-291,-2,83,83,83,83,83,83,-270,-269,83,-245,-246,83,83,83,83,287,83,83,-85,83,-261,-262,83,-84,83,83,160,83,83,-265,-266,-25,83,83,83,83,83,83,83,83,83,83,83,83,-216,-221,-222,-219,-217,-224,-215,-218,-220,-223,-214,-225,83,83,-1,-47,-46,-54,344,160,83,-81,-55,-65,-63,-64,83,-80,-232,-233,83,-283,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,-271,-272,83,83,83,83,83,83,83,-87,-88,415,-287,-286,-26,-263,-264,-74,-75,-268,-267,420,-45,-284,-285,83,83,-70,-83,428,-56,431,83,-69,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,83,-86,83,-89,-290,-288,-73,83,83,83,-48,-82,-57,-68,83,-273,83,83,83,83,83,-251,-274,-247,83,-295,83,83,83,83,83,83,83,83,83,-296,-293,83,83,-254,-289,-275,-249,-250,-248,-297,83,-294,83,-255,83,83,83,-298,83,-256,-252,-276,-253,]),'IN':([3,8,12,15,16,18,20,22,24,27,35,38,41,46,49,60,61,63,64,70,71,74,78,79,80,81,82,85,87,97,99,100,101,102,103,105,106,107,108,109,110,112,113,125,127,128,129,132,134,140,142,145,156,159,166,169,172,173,196,204,209,213,216,218,221,222,223,224,227,229,239,245,246,247,248,249,281,282,283,288,290,291,292,293,294,297,298,301,302,303,305,315,319,326,327,328,329,330,331,332,333,334,335,338,345,346,350,353,357,358,359,360,361,362,363,364,365,368,369,370,372,373,374,375,377,378,392,411,413,417,424,427,429,433,442,445,448,449,450,451,452,453,454,455,456,457,458,462,464,466,468,482,490,506,508,515,526,529,537,],[-28,-72,-94,-71,-27,-150,-42,-133,-41,-119,-126,-30,-95,-105,-78,-104,-31,-32,-33,-35,-34,191,-37,-36,-43,-44,-99,-38,-29,-112,-96,-102,-92,-39,-93,-40,-103,-67,-66,-76,-41,-111,-107,-108,-106,-123,259,-137,-115,-129,-96,-113,-109,-85,-114,-84,-79,-76,-100,-101,-110,-99,-47,-46,-77,-76,-97,-98,-81,-55,-80,-136,-135,-134,-127,-128,-122,-121,-120,-198,-162,-180,-144,-186,-174,-192,-210,407,-204,-87,-88,-74,-75,259,259,259,259,-155,-152,-151,-154,-153,-156,-45,-70,-83,-56,-69,-117,-118,-116,-142,-139,-138,-141,-140,-143,-132,-131,-130,259,259,259,259,-124,-125,446,-86,-89,-73,-48,-82,-57,-68,-193,488,-149,-146,-145,-148,-147,-175,-181,259,259,259,259,-187,-96,-211,-199,-295,-243,-296,-297,-205,-297,-298,-298,]),'VAR':([0,2,5,7,13,19,21,28,29,31,36,43,44,45,50,58,62,65,67,68,72,75,77,111,114,115,116,126,133,143,147,148,155,163,164,176,177,179,240,241,250,270,271,310,311,312,313,314,322,323,340,341,383,386,414,416,418,421,435,436,441,471,472,475,477,483,492,501,502,504,508,512,514,516,519,522,523,524,528,529,531,532,533,534,536,540,541,542,544,547,],[17,-22,-15,17,-23,-21,-13,-19,-17,-20,-16,-11,17,-9,-10,-8,-24,-12,-6,17,-244,-18,-14,-7,-292,-291,-2,17,-270,-269,-245,-246,289,-261,-262,-265,-266,-25,-232,-233,-283,-271,-272,-287,-286,-26,-263,-264,-268,-267,-284,-285,17,17,-290,-288,17,17,-273,17,17,-251,-274,-247,17,17,17,17,17,17,-293,17,-254,-289,-275,-249,-250,-248,17,-294,17,-255,17,17,17,17,-256,-252,-276,-253,]),'MINUSMINUS':([0,2,3,4,5,6,7,8,10,11,12,13,15,16,19,20,21,23,24,25,26,28,29,30,31,36,38,40,41,43,44,45,48,49,50,58,61,62,63,64,65,67,68,70,71,72,75,77,78,79,80,81,82,83,84,85,87,88,89,90,92,93,94,95,99,101,102,103,105,107,108,109,110,111,114,115,116,120,121,122,123,124,126,133,142,143,146,147,148,149,150,151,152,155,158,159,160,163,164,168,169,170,171,172,173,174,175,176,177,179,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,197,198,199,200,201,202,203,205,206,207,210,213,215,216,218,219,221,222,226,227,229,238,239,240,241,243,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,301,303,305,310,311,312,313,314,315,319,322,323,338,340,341,342,343,345,346,350,352,353,383,386,389,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,416,417,418,420,421,424,427,429,433,434,435,436,441,443,446,447,464,471,472,475,477,482,483,488,491,492,493,495,501,502,504,506,508,509,512,514,516,519,522,523,524,526,528,529,531,532,533,534,536,537,540,541,542,544,547,],[84,-22,-28,-1,-15,84,84,-72,84,84,-94,-23,-71,-27,-21,-42,-13,84,-41,84,84,-19,-17,84,-20,-16,-30,84,-95,-11,84,-9,84,-78,-10,-8,-31,-24,-32,-33,-12,-6,84,-35,-34,-244,-18,-14,-37,-36,-43,-44,204,84,84,-38,-29,84,84,84,84,-53,-52,-51,224,-92,-39,-93,-40,-67,-66,-76,-41,-7,-292,-291,-2,84,84,84,84,84,84,-270,224,-269,84,-245,-246,84,84,84,84,84,84,-85,84,-261,-262,84,-84,84,84,-79,-76,84,84,-265,-266,-25,84,84,84,84,84,84,84,84,84,84,84,84,-216,-221,-222,-219,-217,-224,-215,-218,-220,-223,-214,-225,84,84,204,-1,-47,-46,-54,-77,-76,84,-81,-55,84,-80,-232,-233,84,-283,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,-271,-272,84,84,84,84,84,84,84,224,-87,-88,-287,-286,-26,-263,-264,-74,-75,-268,-267,-45,-284,-285,84,84,-70,-83,-56,84,-69,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,84,-86,84,-89,-290,-288,-73,84,84,84,-48,-82,-57,-68,84,-273,84,84,84,84,84,224,-251,-274,-247,84,-295,84,84,84,84,84,84,84,84,84,-296,-293,84,84,-254,-289,-275,-249,-250,-248,-297,84,-294,84,-255,84,84,84,-298,84,-256,-252,-276,-253,]),'EQ':([3,8,12,15,16,20,24,38,41,49,61,63,64,70,71,78,79,80,81,82,85,87,101,102,103,105,107,108,109,110,118,142,159,169,172,173,216,218,221,222,227,229,239,301,303,305,315,319,338,345,346,350,353,392,411,413,417,424,427,429,433,464,482,487,506,508,526,529,537,],[-28,-72,-94,-71,-27,-42,-41,-30,-95,-78,-31,-32,-33,-35,-34,-37,-36,-43,-44,205,-38,-29,-92,-39,-93,-40,-67,-66,-76,-41,243,205,-85,-84,-79,-76,-47,-46,-77,-76,-81,-55,-80,205,-87,-88,-74,-75,-45,-70,-83,-56,-69,447,-86,-89,-73,-48,-82,-57,-68,205,-295,447,-296,-297,-297,-298,-298,]),'ID':([0,2,4,5,6,7,10,11,13,17,19,21,23,25,26,28,29,30,31,36,37,40,43,44,45,47,48,50,54,58,62,65,66,67,68,72,75,77,83,84,88,89,90,92,93,94,95,96,98,104,111,114,115,116,120,121,122,123,124,126,133,143,146,147,148,149,150,151,152,153,155,157,158,160,163,164,167,168,170,171,174,175,176,177,179,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,197,198,199,200,201,202,203,205,206,207,210,215,219,225,226,228,231,237,238,240,241,242,243,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,287,289,310,311,312,313,314,322,323,340,341,342,343,344,349,352,383,385,386,389,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,412,414,415,416,418,420,421,431,434,435,436,441,443,444,446,447,471,472,475,477,483,488,491,492,493,495,501,502,504,508,509,512,514,516,519,522,523,524,528,529,531,532,533,534,536,540,541,542,544,547,],[85,-22,-1,-15,85,85,85,85,-23,85,-21,-13,85,85,85,-19,-17,85,-20,-16,85,85,-11,85,-9,85,85,-10,85,-8,-24,-12,85,-6,85,-244,-18,-14,85,85,85,85,85,85,-53,-52,-51,85,85,85,-7,-292,-291,-2,85,85,85,85,85,85,-270,-269,85,-245,-246,85,85,85,85,85,85,85,85,85,-261,-262,85,85,85,85,85,85,-265,-266,-25,85,85,85,85,85,85,85,85,85,85,85,85,-216,-221,-222,-219,-217,-224,-215,-218,-220,-223,-214,-225,85,85,-1,-54,85,85,85,85,85,85,-232,-233,85,85,-283,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,-271,-272,85,85,85,85,85,85,85,85,85,-287,-286,-26,-263,-264,-268,-267,-284,-285,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,-290,85,-288,85,85,85,85,85,-273,85,85,85,85,85,85,-251,-274,-247,85,85,85,85,85,85,85,85,85,85,-293,85,85,-254,-289,-275,-249,-250,-248,85,-294,85,-255,85,85,85,85,-256,-252,-276,-253,]),'IF':([0,2,5,7,13,19,21,28,29,31,36,43,44,45,50,58,62,65,67,68,72,75,77,111,114,115,116,126,133,143,147,148,163,164,176,177,179,240,241,250,270,271,310,311,312,313,314,322,323,340,341,383,386,414,416,418,421,435,436,441,471,472,475,477,483,492,501,502,504,508,512,514,516,519,522,523,524,528,529,531,532,533,534,536,540,541,542,544,547,],[86,-22,-15,86,-23,-21,-13,-19,-17,-20,-16,-11,86,-9,-10,-8,-24,-12,-6,86,-244,-18,-14,-7,-292,-291,-2,86,-270,-269,-245,-246,-261,-262,-265,-266,-25,-232,-233,-283,-271,-272,-287,-286,-26,-263,-264,-268,-267,-284,-285,86,86,-290,-288,86,86,-273,86,86,-251,-274,-247,86,86,86,86,86,86,-293,86,-254,-289,-275,-249,-250,-248,86,-294,86,-255,86,86,86,86,-256,-252,-276,-253,]),'AND':([3,8,12,15,16,18,20,22,24,27,35,38,41,46,49,53,56,60,61,63,64,69,70,71,73,74,76,78,79,80,81,82,85,87,97,99,100,101,102,103,105,106,107,108,109,110,112,113,125,127,128,129,130,131,132,134,135,136,140,142,144,145,156,159,166,169,172,173,196,204,209,213,214,216,218,221,222,223,224,227,229,239,245,246,247,248,249,281,282,283,288,290,291,292,293,294,297,301,303,305,315,318,319,320,325,326,327,328,329,330,331,332,333,334,335,336,338,345,346,350,353,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,377,378,380,382,411,413,417,424,427,429,433,442,448,449,450,451,452,453,454,455,456,457,458,462,464,468,482,506,508,526,529,537,],[-28,-72,-94,-71,-27,-150,-42,-133,-41,-119,-126,-30,-95,-105,-78,-188,174,-104,-31,-32,-33,-194,-35,-34,-176,-167,-182,-37,-36,-43,-44,-99,-38,-29,-112,-96,-102,-92,-39,-93,-40,-103,-67,-66,-76,-41,-111,-107,-108,-106,-123,-157,-190,261,-137,-115,-184,-172,-129,-96,-178,-113,-109,-85,-114,-84,-79,-76,-100,-101,-110,-99,174,-47,-46,-77,-76,-97,-98,-81,-55,-80,-136,-135,-134,-127,-128,-122,-121,-120,389,-162,-180,-144,-186,-174,-192,-96,-87,-88,-74,-183,-75,-195,-189,-168,-169,-171,-170,-155,-152,-151,-154,-153,-156,-177,-45,-70,-83,-56,-69,-117,-118,-116,-142,-139,-138,-141,-140,-143,-185,-191,-132,-131,-130,-179,-158,-159,-161,-160,-124,-125,261,-173,-86,-89,-73,-48,-82,-57,-68,-193,-149,-146,-145,-148,-147,-175,-181,-163,-164,-166,-165,-187,-96,389,-295,-296,-297,-297,-298,-298,]),'LBRACE':([0,2,4,5,6,7,10,11,13,19,21,23,25,26,28,29,30,31,36,40,42,43,44,45,48,50,54,58,62,65,67,68,72,75,77,83,84,88,89,92,93,94,95,98,111,114,115,116,120,121,122,123,124,126,133,143,146,147,148,149,150,151,152,155,158,160,163,164,168,170,175,176,177,179,182,183,184,185,186,187,188,189,190,191,193,194,195,197,198,199,200,201,202,203,205,206,207,210,215,219,226,238,240,241,243,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,285,308,310,311,312,313,314,322,323,340,341,342,343,352,383,384,386,388,389,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,412,414,416,418,419,420,421,426,434,435,436,440,441,443,446,447,471,472,475,476,477,478,483,488,491,492,493,494,495,501,502,504,505,508,509,512,514,516,519,522,523,524,528,529,531,532,533,534,536,540,541,542,544,547,],[44,-22,-1,-15,104,44,104,104,-23,-21,-13,104,104,104,-19,-17,104,-20,-16,104,44,-11,44,-9,104,-10,104,-8,-24,-12,-6,44,-244,-18,-14,104,104,104,104,104,-53,-52,-51,104,-7,-292,-291,-2,104,104,104,104,104,44,-270,-269,104,-245,-246,104,104,104,104,104,104,104,-261,-262,104,104,104,-265,-266,-25,104,104,104,104,104,104,104,104,104,104,-216,-221,-222,-219,-217,-224,-215,-218,-220,-223,-214,-225,104,104,-1,-54,104,104,-232,-233,104,-283,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,-271,-272,104,104,104,104,104,104,104,386,44,-287,-286,-26,-263,-264,-268,-267,-284,-285,104,104,104,44,436,44,441,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,-290,-288,44,473,104,44,477,104,-273,44,483,44,104,104,104,-251,-274,-247,502,44,504,44,104,104,44,104,44,104,44,44,44,528,-293,104,44,-254,-289,-275,-249,-250,-248,44,-294,44,-255,44,44,44,44,-256,-252,-276,-253,]),'FALSE':([0,2,4,5,6,7,10,11,13,19,21,23,25,26,28,29,30,31,36,40,43,44,45,48,50,54,58,62,65,67,68,72,75,77,83,84,88,89,90,92,93,94,95,98,111,114,115,116,120,121,122,123,124,126,133,143,146,147,148,149,150,151,152,155,158,160,163,164,168,170,171,174,175,176,177,179,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,197,198,199,200,201,202,203,205,206,207,210,215,219,226,238,240,241,243,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,310,311,312,313,314,322,323,340,341,342,343,352,383,386,389,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,412,414,416,418,420,421,434,435,436,441,443,446,447,471,472,475,477,483,488,491,492,493,495,501,502,504,508,509,512,514,516,519,522,523,524,528,529,531,532,533,534,536,540,541,542,544,547,],[64,-22,-1,-15,64,64,64,64,-23,-21,-13,64,64,64,-19,-17,64,-20,-16,64,-11,64,-9,64,-10,64,-8,-24,-12,-6,64,-244,-18,-14,64,64,64,64,64,64,-53,-52,-51,64,-7,-292,-291,-2,64,64,64,64,64,64,-270,-269,64,-245,-246,64,64,64,64,64,64,64,-261,-262,64,64,64,64,64,-265,-266,-25,64,64,64,64,64,64,64,64,64,64,64,64,-216,-221,-222,-219,-217,-224,-215,-218,-220,-223,-214,-225,64,64,-1,-54,64,64,-232,-233,64,-283,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,-271,-272,64,64,64,64,64,64,64,-287,-286,-26,-263,-264,-268,-267,-284,-285,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,-290,-288,64,64,64,64,-273,64,64,64,64,64,-251,-274,-247,64,64,64,64,64,64,64,64,64,64,-293,64,64,-254,-289,-275,-249,-250,-248,64,-294,64,-255,64,64,64,64,-256,-252,-276,-253,]),'RSHIFT':([3,8,12,15,16,18,20,22,24,27,35,38,41,46,49,60,61,63,64,70,71,78,79,80,81,82,85,87,97,99,100,101,102,103,105,106,107,108,109,110,112,113,125,127,128,132,134,140,142,145,156,159,166,169,172,173,196,204,209,213,216,218,221,222,223,224,227,229,239,245,246,247,248,249,281,282,283,292,301,303,305,315,319,330,331,332,333,334,335,338,345,346,350,353,357,358,359,360,361,362,363,364,365,368,369,370,377,378,411,413,417,424,427,429,433,448,449,450,451,452,464,482,506,508,526,529,537,],[-28,-72,-94,-71,-27,121,-42,-133,-41,-119,-126,-30,-95,-105,-78,-104,-31,-32,-33,-35,-34,-37,-36,-43,-44,-99,-38,-29,-112,-96,-102,-92,-39,-93,-40,-103,-67,-66,-76,-41,-111,-107,-108,-106,-123,263,-115,-129,-96,-113,-109,-85,-114,-84,-79,-76,-100,-101,-110,-99,-47,-46,-77,-76,-97,-98,-81,-55,-80,-136,-135,-134,-127,-128,-122,-121,-120,263,-96,-87,-88,-74,-75,263,263,263,263,263,263,-45,-70,-83,-56,-69,-117,-118,-116,263,263,263,263,263,263,-132,-131,-130,-124,-125,-86,-89,-73,-48,-82,-57,-68,263,263,263,263,263,-96,-295,-296,-297,-297,-298,-298,]),'PLUSEQUAL':([3,8,12,15,16,20,24,38,41,49,61,63,64,70,71,78,79,80,81,82,85,87,101,102,103,105,107,108,109,110,142,159,169,172,173,216,218,221,222,227,229,239,301,303,305,315,319,338,345,346,350,353,411,413,417,424,427,429,433,464,482,506,508,526,529,537,],[-28,-72,-94,-71,-27,-42,-41,-30,-95,-78,-31,-32,-33,-35,-34,-37,-36,-43,-44,201,-38,-29,-92,-39,-93,-40,-67,-66,-76,-41,201,-85,-84,-79,-76,-47,-46,-77,-76,-81,-55,-80,201,-87,-88,-74,-75,-45,-70,-83,-56,-69,-86,-89,-73,-48,-82,-57,-68,201,-295,-296,-297,-297,-298,-298,]),'THIS':([0,2,4,5,6,7,10,11,13,19,21,23,25,26,28,29,30,31,36,40,43,44,45,48,50,54,58,62,65,67,68,72,75,77,83,84,88,89,90,92,93,94,95,98,111,114,115,116,120,121,122,123,124,126,133,143,146,147,148,149,150,151,152,155,158,160,163,164,168,170,171,174,175,176,177,179,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,197,198,199,200,201,202,203,205,206,207,210,215,219,226,238,240,241,243,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,310,311,312,313,314,322,323,340,341,342,343,352,383,386,389,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,412,414,416,418,420,421,434,435,436,441,443,446,447,471,472,475,477,483,488,491,492,493,495,501,502,504,508,509,512,514,516,519,522,523,524,528,529,531,532,533,534,536,540,541,542,544,547,],[20,-22,-1,-15,20,20,20,20,-23,-21,-13,20,20,20,-19,-17,20,-20,-16,20,-11,20,-9,20,-10,20,-8,-24,-12,-6,20,-244,-18,-14,20,20,20,20,20,20,-53,-52,-51,20,-7,-292,-291,-2,20,20,20,20,20,20,-270,-269,20,-245,-246,20,20,20,20,20,20,20,-261,-262,20,20,20,20,20,-265,-266,-25,20,20,20,20,20,20,20,20,20,20,20,20,-216,-221,-222,-219,-217,-224,-215,-218,-220,-223,-214,-225,20,20,-1,-54,20,20,-232,-233,20,-283,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,-271,-272,20,20,20,20,20,20,20,-287,-286,-26,-263,-264,-268,-267,-284,-285,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,-290,-288,20,20,20,20,-273,20,20,20,20,20,-251,-274,-247,20,20,20,20,20,20,20,20,20,20,-293,20,20,-254,-289,-275,-249,-250,-248,20,-294,20,-255,20,20,20,20,-256,-252,-276,-253,]),'MINUSEQUAL':([3,8,12,15,16,20,24,38,41,49,61,63,64,70,71,78,79,80,81,82,85,87,101,102,103,105,107,108,109,110,142,159,169,172,173,216,218,221,222,227,229,239,301,303,305,315,319,338,345,346,350,353,411,413,417,424,427,429,433,464,482,506,508,526,529,537,],[-28,-72,-94,-71,-27,-42,-41,-30,-95,-78,-31,-32,-33,-35,-34,-37,-36,-43,-44,197,-38,-29,-92,-39,-93,-40,-67,-66,-76,-41,197,-85,-84,-79,-76,-47,-46,-77,-76,-81,-55,-80,197,-87,-88,-74,-75,-45,-70,-83,-56,-69,-86,-89,-73,-48,-82,-57,-68,197,-295,-296,-297,-297,-298,-298,]),'CONDOP':([1,3,8,12,15,16,18,20,22,24,27,35,38,41,46,49,53,56,60,61,63,64,69,70,71,73,74,76,78,79,80,81,82,85,87,97,99,100,101,102,103,105,106,107,108,109,110,112,113,125,127,128,129,130,131,132,134,135,136,140,141,142,144,145,156,159,166,169,172,173,196,204,209,213,214,216,218,221,222,223,224,227,229,239,245,246,247,248,249,281,282,283,288,290,291,292,293,294,297,301,302,303,305,315,318,319,320,325,326,327,328,329,330,331,332,333,334,335,336,338,345,346,350,353,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,377,378,380,382,411,413,417,424,427,429,433,442,448,449,450,451,452,453,454,455,456,457,458,462,464,468,482,506,508,526,529,537,],[89,-28,-72,-94,-71,-27,-150,-42,-133,-41,-119,-126,-30,-95,-105,-78,-188,-200,-104,-31,-32,-33,-194,-35,-34,-176,-167,-182,-37,-36,-43,-44,-99,-38,-29,-112,-96,-102,-92,-39,-93,-40,-103,-67,-66,-76,-41,-111,-107,-108,-106,-123,-157,-190,-196,-137,-115,-184,-172,-129,275,-96,-178,-113,-109,-85,-114,-84,-79,-76,-100,-101,-110,-99,-201,-47,-46,-77,-76,-97,-98,-81,-55,-80,-136,-135,-134,-127,-128,-122,-121,-120,-198,-162,-180,-144,-186,-174,-192,-96,409,-87,-88,-74,-183,-75,-195,-189,-168,-169,-171,-170,-155,-152,-151,-154,-153,-156,-177,-45,-70,-83,-56,-69,-117,-118,-116,-142,-139,-138,-141,-140,-143,-185,-191,-132,-131,-130,-179,-158,-159,-161,-160,-124,-125,-197,-173,-86,-89,-73,-48,-82,-57,-68,-193,-149,-146,-145,-148,-147,-175,-181,-163,-164,-166,-165,-187,-96,-199,-295,-296,-297,-297,-298,-298,]),'XOREQUAL':([3,8,12,15,16,20,24,38,41,49,61,63,64,70,71,78,79,80,81,82,85,87,101,102,103,105,107,108,109,110,142,159,169,172,173,216,218,221,222,227,229,239,301,303,305,315,319,338,345,346,350,353,411,413,417,424,427,429,433,464,482,506,508,526,529,537,],[-28,-72,-94,-71,-27,-42,-41,-30,-95,-78,-31,-32,-33,-35,-34,-37,-36,-43,-44,199,-38,-29,-92,-39,-93,-40,-67,-66,-76,-41,199,-85,-84,-79,-76,-47,-46,-77,-76,-81,-55,-80,199,-87,-88,-74,-75,-45,-70,-83,-56,-69,-86,-89,-73,-48,-82,-57,-68,199,-295,-296,-297,-297,-298,-298,]),'OR':([1,3,8,12,15,16,18,20,22,24,27,35,38,41,46,49,53,56,60,61,63,64,69,70,71,73,74,76,78,79,80,81,82,85,87,97,99,100,101,102,103,105,106,107,108,109,110,112,113,125,127,128,129,130,131,132,134,135,136,140,141,142,144,145,156,159,166,169,172,173,196,204,209,213,214,216,218,221,222,223,224,227,229,239,245,246,247,248,249,281,282,283,288,290,291,292,293,294,297,301,302,303,305,315,318,319,320,325,326,327,328,329,330,331,332,333,334,335,336,338,345,346,350,353,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,377,378,380,382,411,413,417,424,427,429,433,442,448,449,450,451,452,453,454,455,456,457,458,462,464,468,482,506,508,526,529,537,],[90,-28,-72,-94,-71,-27,-150,-42,-133,-41,-119,-126,-30,-95,-105,-78,-188,-200,-104,-31,-32,-33,-194,-35,-34,-176,-167,-182,-37,-36,-43,-44,-99,-38,-29,-112,-96,-102,-92,-39,-93,-40,-103,-67,-66,-76,-41,-111,-107,-108,-106,-123,-157,-190,-196,-137,-115,-184,-172,-129,276,-96,-178,-113,-109,-85,-114,-84,-79,-76,-100,-101,-110,-99,-201,-47,-46,-77,-76,-97,-98,-81,-55,-80,-136,-135,-134,-127,-128,-122,-121,-120,-198,-162,-180,-144,-186,-174,-192,-96,410,-87,-88,-74,-183,-75,-195,-189,-168,-169,-171,-170,-155,-152,-151,-154,-153,-156,-177,-45,-70,-83,-56,-69,-117,-118,-116,-142,-139,-138,-141,-140,-143,-185,-191,-132,-131,-130,-179,-158,-159,-161,-160,-124,-125,-197,-173,-86,-89,-73,-48,-82,-57,-68,-193,-149,-146,-145,-148,-147,-175,-181,-163,-164,-166,-165,-187,-96,-199,-295,-296,-297,-297,-298,-298,]),'BREAK':([0,2,5,7,13,19,21,28,29,31,36,43,44,45,50,58,62,65,67,68,72,75,77,111,114,115,116,126,133,143,147,148,163,164,176,177,179,240,241,250,270,271,310,311,312,313,314,322,323,340,341,383,386,414,416,418,421,435,436,441,471,472,475,477,483,492,501,502,504,508,512,514,516,519,522,523,524,528,529,531,532,533,534,536,540,541,542,544,547,],[66,-22,-15,66,-23,-21,-13,-19,-17,-20,-16,-11,66,-9,-10,-8,-24,-12,-6,66,-244,-18,-14,-7,-292,-291,-2,66,-270,-269,-245,-246,-261,-262,-265,-266,-25,-232,-233,-283,-271,-272,-287,-286,-26,-263,-264,-268,-267,-284,-285,66,66,-290,-288,66,66,-273,66,66,-251,-274,-247,66,66,66,66,66,66,-293,66,-254,-289,-275,-249,-250,-248,66,-294,66,-255,66,66,66,66,-256,-252,-276,-253,]),'URSHIFTEQUAL':([3,8,12,15,16,20,24,38,41,49,61,63,64,70,71,78,79,80,81,82,85,87,101,102,103,105,107,108,109,110,142,159,169,172,173,216,218,221,222,227,229,239,301,303,305,315,319,338,345,346,350,353,411,413,417,424,427,429,433,464,482,506,508,526,529,537,],[-28,-72,-94,-71,-27,-42,-41,-30,-95,-78,-31,-32,-33,-35,-34,-37,-36,-43,-44,195,-38,-29,-92,-39,-93,-40,-67,-66,-76,-41,195,-85,-84,-79,-76,-47,-46,-77,-76,-81,-55,-80,195,-87,-88,-74,-75,-45,-70,-83,-56,-69,-86,-89,-73,-48,-82,-57,-68,195,-295,-296,-297,-297,-298,-298,]),'CONTINUE':([0,2,5,7,13,19,21,28,29,31,36,43,44,45,50,58,62,65,67,68,72,75,77,111,114,115,116,126,133,143,147,148,163,164,176,177,179,240,241,250,270,271,310,311,312,313,314,322,323,340,341,383,386,414,416,418,421,435,436,441,471,472,475,477,483,492,501,502,504,508,512,514,516,519,522,523,524,528,529,531,532,533,534,536,540,541,542,544,547,],[47,-22,-15,47,-23,-21,-13,-19,-17,-20,-16,-11,47,-9,-10,-8,-24,-12,-6,47,-244,-18,-14,-7,-292,-291,-2,47,-270,-269,-245,-246,-261,-262,-265,-266,-25,-232,-233,-283,-271,-272,-287,-286,-26,-263,-264,-268,-267,-284,-285,47,47,-290,-288,47,47,-273,47,47,-251,-274,-247,47,47,47,47,47,47,-293,47,-254,-289,-275,-249,-250,-248,47,-294,47,-255,47,47,47,47,-256,-252,-276,-253,]),'FINALLY':([161,311,312,516,],[308,308,-26,-289,]),'TYPEOF':([0,2,4,5,6,7,10,11,13,19,21,23,25,26,28,29,30,31,36,40,43,44,45,48,50,58,62,65,67,68,72,75,77,83,84,88,89,90,92,93,94,95,111,114,115,116,120,121,122,123,124,126,133,143,146,147,148,149,150,151,152,155,158,160,163,164,168,170,171,174,175,176,177,179,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,197,198,199,200,201,202,203,205,206,207,210,215,219,226,238,240,241,243,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,310,311,312,313,314,322,323,340,341,342,343,352,383,386,389,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,412,414,416,418,420,421,434,435,436,441,443,446,447,471,472,475,477,483,488,491,492,493,495,501,502,504,508,509,512,514,516,519,522,523,524,528,529,531,532,533,534,536,540,541,542,544,547,],[23,-22,-1,-15,23,23,23,23,-23,-21,-13,23,23,23,-19,-17,23,-20,-16,23,-11,23,-9,23,-10,-8,-24,-12,-6,23,-244,-18,-14,23,23,23,23,23,23,-53,-52,-51,-7,-292,-291,-2,23,23,23,23,23,23,-270,-269,23,-245,-246,23,23,23,23,23,23,23,-261,-262,23,23,23,23,23,-265,-266,-25,23,23,23,23,23,23,23,23,23,23,23,23,-216,-221,-222,-219,-217,-224,-215,-218,-220,-223,-214,-225,23,23,-1,-54,23,23,-232,-233,23,-283,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,-271,-272,23,23,23,23,23,23,23,-287,-286,-26,-263,-264,-268,-267,-284,-285,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,-290,-288,23,23,23,23,-273,23,23,23,23,23,-251,-274,-247,23,23,23,23,23,23,23,23,23,23,-293,23,23,-254,-289,-275,-249,-250,-248,23,-294,23,-255,23,23,23,23,-256,-252,-276,-253,]),'error':([1,3,8,12,14,15,16,18,20,22,24,26,27,34,35,38,41,46,47,49,51,53,55,56,60,61,63,64,66,69,70,71,73,74,76,78,79,80,81,82,85,87,97,99,100,101,102,103,105,106,107,108,109,110,112,113,117,118,119,125,127,128,129,130,131,132,134,135,136,137,138,139,140,141,142,144,145,156,159,165,166,169,172,173,178,196,204,209,211,213,214,216,218,221,222,223,224,227,229,239,244,245,246,247,248,249,280,281,282,283,303,305,315,318,319,320,325,326,327,328,329,330,331,332,333,334,335,336,337,338,345,346,350,353,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,380,381,382,411,413,417,422,424,427,429,433,480,482,500,506,508,526,529,537,],[-206,-28,-72,-94,116,-71,-27,-150,-42,-133,-41,116,-119,116,-126,-30,-95,-105,116,-78,-230,-188,-212,-200,-104,-31,-32,-33,116,-194,-35,-34,-176,-167,-182,-37,-36,-43,-44,-99,-38,-29,-112,-96,-102,-92,-39,-93,-40,-103,-67,-66,-76,-41,-111,-107,116,-238,-234,-108,-106,-123,-157,-190,-196,-137,-115,-184,-172,-208,116,-226,-129,-202,-96,-178,-113,-109,-85,116,-114,-84,-79,-76,116,-100,-101,-110,116,-99,-201,-47,-46,-77,-76,-97,-98,-81,-55,-80,-239,-136,-135,-134,-127,-128,-231,-122,-121,-120,-87,-88,-74,-183,-75,-195,-189,-168,-169,-171,-170,-155,-152,-151,-154,-153,-156,-177,-213,-45,-70,-83,-56,-69,-235,-242,-117,-118,-116,-142,-139,-138,-141,-140,-143,-185,-191,-132,-131,-130,-179,-158,-159,-161,-160,-227,-124,-125,-197,-209,-173,-86,-89,-73,-207,-48,-82,-57,-68,-203,-295,116,-296,-297,-297,-298,-298,]),'NOT':([0,2,4,5,6,7,10,11,13,19,21,23,25,26,28,29,30,31,36,40,43,44,45,48,50,58,62,65,67,68,72,75,77,83,84,88,89,90,92,93,94,95,111,114,115,116,120,121,122,123,124,126,133,143,146,147,148,149,150,151,152,155,158,160,163,164,168,170,171,174,175,176,177,179,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,197,198,199,200,201,202,203,205,206,207,210,215,219,226,238,240,241,243,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,310,311,312,313,314,322,323,340,341,342,343,352,383,386,389,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,412,414,416,418,420,421,434,435,436,441,443,446,447,471,472,475,477,483,488,491,492,493,495,501,502,504,508,509,512,514,516,519,522,523,524,528,529,531,532,533,534,536,540,541,542,544,547,],[48,-22,-1,-15,48,48,48,48,-23,-21,-13,48,48,48,-19,-17,48,-20,-16,48,-11,48,-9,48,-10,-8,-24,-12,-6,48,-244,-18,-14,48,48,48,48,48,48,-53,-52,-51,-7,-292,-291,-2,48,48,48,48,48,48,-270,-269,48,-245,-246,48,48,48,48,48,48,48,-261,-262,48,48,48,48,48,-265,-266,-25,48,48,48,48,48,48,48,48,48,48,48,48,-216,-221,-222,-219,-217,-224,-215,-218,-220,-223,-214,-225,48,48,-1,-54,48,48,-232,-233,48,-283,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,-271,-272,48,48,48,48,48,48,48,-287,-286,-26,-263,-264,-268,-267,-284,-285,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,48,-290,-288,48,48,48,48,-273,48,48,48,48,48,-251,-274,-247,48,48,48,48,48,48,48,48,48,48,-293,48,48,-254,-289,-275,-249,-250,-248,48,-294,48,-255,48,48,48,48,-256,-252,-276,-253,]),'ANDEQUAL':([3,8,12,15,16,20,24,38,41,49,61,63,64,70,71,78,79,80,81,82,85,87,101,102,103,105,107,108,109,110,142,159,169,172,173,216,218,221,222,227,229,239,301,303,305,315,319,338,345,346,350,353,411,413,417,424,427,429,433,464,482,506,508,526,529,537,],[-28,-72,-94,-71,-27,-42,-41,-30,-95,-78,-31,-32,-33,-35,-34,-37,-36,-43,-44,203,-38,-29,-92,-39,-93,-40,-67,-66,-76,-41,203,-85,-84,-79,-76,-47,-46,-77,-76,-81,-55,-80,203,-87,-88,-74,-75,-45,-70,-83,-56,-69,-86,-89,-73,-48,-82,-57,-68,203,-295,-296,-297,-297,-298,-298,]),'RBRACKET':([3,4,16,20,38,61,63,64,70,71,78,79,80,81,85,87,91,92,93,94,95,97,99,100,101,102,103,105,106,107,108,109,110,112,113,125,127,128,129,130,131,132,134,135,136,137,139,140,141,142,144,145,156,166,209,215,216,217,218,219,221,222,223,224,227,229,239,304,305,316,338,343,345,346,347,350,353,354,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,380,381,382,413,423,424,427,429,433,480,482,506,526,537,],[-28,-1,-27,-42,-30,-31,-32,-33,-35,-34,-37,-36,-43,-44,-38,-29,216,218,-53,-52,-51,-112,-96,-102,-92,-39,-93,-40,-103,-67,-66,-76,-41,-111,-107,-108,-106,-123,-157,-190,-196,-137,-115,-184,-172,-208,-226,-129,-202,-96,-178,-113,-109,-114,-110,-1,-47,-49,-46,-54,-77,-76,-97,-98,-81,-55,-80,411,-88,417,-45,424,-70,-83,427,-56,-69,433,-117,-118,-116,-142,-139,-138,-141,-140,-143,-185,-191,-132,-131,-130,-179,-158,-159,-161,-160,-227,-124,-125,-197,-209,-173,-89,-50,-48,-82,-57,-68,-203,-295,-296,-297,-298,]),'MOD':([3,8,12,15,16,20,24,27,35,38,41,46,49,60,61,63,64,70,71,78,79,80,81,82,85,87,97,99,100,101,102,103,105,106,107,108,109,110,112,113,125,127,128,134,142,145,156,159,166,169,172,173,196,204,209,213,216,218,221,222,223,224,227,229,239,248,249,281,282,283,301,303,305,315,319,338,345,346,350,353,357,358,359,377,378,411,413,417,424,427,429,433,464,482,506,508,526,529,537,],[-28,-72,-94,-71,-27,-42,-41,-119,150,-30,-95,-105,-78,-104,-31,-32,-33,-35,-34,-37,-36,-43,-44,-99,-38,-29,-112,-96,-102,-92,-39,-93,-40,-103,-67,-66,-76,-41,-111,-107,-108,-106,252,-115,-96,-113,-109,-85,-114,-84,-79,-76,-100,-101,-110,-99,-47,-46,-77,-76,-97,-98,-81,-55,-80,252,252,-122,-121,-120,-96,-87,-88,-74,-75,-45,-70,-83,-56,-69,-117,-118,-116,252,252,-86,-89,-73,-48,-82,-57,-68,-96,-295,-296,-297,-297,-298,-298,]),'THROW':([0,2,5,7,13,19,21,28,29,31,36,43,44,45,50,58,62,65,67,68,72,75,77,111,114,115,116,126,133,143,147,148,163,164,176,177,179,240,241,250,270,271,310,311,312,313,314,322,323,340,341,383,386,414,416,418,421,435,436,441,471,472,475,477,483,492,501,502,504,508,512,514,516,519,522,523,524,528,529,531,532,533,534,536,540,541,542,544,547,],[88,-22,-15,88,-23,-21,-13,-19,-17,-20,-16,-11,88,-9,-10,-8,-24,-12,-6,88,-244,-18,-14,-7,-292,-291,-2,88,-270,-269,-245,-246,-261,-262,-265,-266,-25,-232,-233,-283,-271,-272,-287,-286,-26,-263,-264,-268,-267,-284,-285,88,88,-290,-288,88,88,-273,88,88,-251,-274,-247,88,88,88,88,88,88,-293,88,-254,-289,-275,-249,-250,-248,88,-294,88,-255,88,88,88,88,-256,-252,-276,-253,]),'GETPROP':([104,349,],[228,228,]),'DELETE':([0,2,4,5,6,7,10,11,13,19,21,23,25,26,28,29,30,31,36,40,43,44,45,48,50,58,62,65,67,68,72,75,77,83,84,88,89,90,92,93,94,95,111,114,115,116,120,121,122,123,124,126,133,143,146,147,148,149,150,151,152,155,158,160,163,164,168,170,171,174,175,176,177,179,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,197,198,199,200,201,202,203,205,206,207,210,215,219,226,238,240,241,243,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,310,311,312,313,314,322,323,340,341,342,343,352,383,386,389,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,412,414,416,418,420,421,434,435,436,441,443,446,447,471,472,475,477,483,488,491,492,493,495,501,502,504,508,509,512,514,516,519,522,523,524,528,529,531,532,533,534,536,540,541,542,544,547,],[25,-22,-1,-15,25,25,25,25,-23,-21,-13,25,25,25,-19,-17,25,-20,-16,25,-11,25,-9,25,-10,-8,-24,-12,-6,25,-244,-18,-14,25,25,25,25,25,25,-53,-52,-51,-7,-292,-291,-2,25,25,25,25,25,25,-270,-269,25,-245,-246,25,25,25,25,25,25,25,-261,-262,25,25,25,25,25,-265,-266,-25,25,25,25,25,25,25,25,25,25,25,25,25,-216,-221,-222,-219,-217,-224,-215,-218,-220,-223,-214,-225,25,25,-1,-54,25,25,-232,-233,25,-283,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,-271,-272,25,25,25,25,25,25,25,-287,-286,-26,-263,-264,-268,-267,-284,-285,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,-290,-288,25,25,25,25,-273,25,25,25,25,25,-251,-274,-247,25,25,25,25,25,25,25,25,25,25,-293,25,25,-254,-289,-275,-249,-250,-248,25,-294,25,-255,25,25,25,25,-256,-252,-276,-253,]),}
+
+_lr_action = { }
+for _k, _v in _lr_action_items.items():
+   for _x,_y in zip(_v[0],_v[1]):
+      if not _x in _lr_action:  _lr_action[_x] = { }
+      _lr_action[_x][_k] = _y
+del _lr_action_items
+
+_lr_goto_items = {'logical_or_expr_nobf':([0,7,44,68,126,383,386,418,421,436,441,477,483,492,501,502,504,512,528,531,533,534,536,540,],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,]),'throw_statement':([0,7,44,68,126,383,386,418,421,436,441,477,483,492,501,502,504,512,528,531,533,534,536,540,],[2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,]),'boolean_literal':([0,6,7,10,11,23,25,26,30,40,44,48,54,68,83,84,88,89,90,92,98,120,121,122,123,124,126,146,149,150,151,152,155,158,160,168,170,171,174,175,181,182,183,184,185,186,187,188,189,190,191,192,207,210,226,238,243,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,272,273,274,275,276,277,278,342,343,352,383,386,389,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,412,418,420,421,434,436,441,443,446,447,477,483,488,491,492,493,495,501,502,504,509,512,528,531,533,534,536,540,],[3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,]),'bitwise_or_expr':([26,83,88,89,92,146,149,158,160,168,170,175,207,210,226,238,243,261,272,275,276,277,342,343,352,404,407,412,420,434,443,446,488,491,495,509,],[130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,367,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,130,]),'property_assignment':([104,349,],[233,430,]),'logical_and_expr_noin':([155,406,408,409,410,447,493,],[288,288,288,288,468,288,288,]),'iteration_statement':([0,7,44,68,126,383,386,418,421,436,441,477,483,492,501,502,504,512,528,531,533,534,536,540,],[5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,]),'variable_declaration_noin':([289,444,],[390,486,]),'source_element_list':([0,44,386,436,441,477,483,502,504,528,534,536,],[7,7,7,7,7,7,7,7,7,7,7,7,]),'function_expr':([0,6,7,10,11,23,25,26,30,40,44,48,54,68,83,84,88,89,90,92,98,120,121,122,123,124,126,146,149,150,151,152,155,158,160,168,170,171,174,175,181,182,183,184,185,186,187,188,189,190,191,192,207,210,226,238,243,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,272,273,274,275,276,277,278,342,343,352,383,386,389,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,412,418,420,421,434,436,441,443,446,447,477,483,488,491,492,493,495,501,502,504,509,512,528,531,533,534,536,540,],[8,107,8,107,107,107,107,107,107,107,8,107,107,8,107,107,107,107,8,107,107,107,107,107,107,107,8,107,107,107,107,107,107,107,107,107,107,8,8,107,8,107,107,107,107,107,107,107,107,107,107,8,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,8,8,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,107,8,107,8,107,8,8,107,107,107,8,8,107,107,8,107,107,8,8,8,107,8,8,8,8,8,8,8,]),'multiplicative_expr':([26,83,88,89,92,120,121,122,123,124,146,149,155,158,160,168,170,175,182,183,184,185,186,187,188,189,190,191,207,210,226,238,243,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,272,273,274,275,276,277,278,342,343,352,389,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,412,420,434,443,446,447,488,491,493,495,509,],[128,128,128,128,128,128,128,128,248,249,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,377,378,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,]),'finally':([161,311,],[310,416,]),'program':([0,],[9,]),'case_block':([419,],[472,]),'formal_parameter_list':([153,287,344,431,],[284,387,425,479,]),'new_expr_nobf':([0,7,44,68,90,126,171,174,181,192,383,386,418,421,436,441,477,483,492,501,502,504,512,528,531,533,534,536,540,],[12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,]),'try_statement':([0,7,44,68,126,383,386,418,421,436,441,477,483,492,501,502,504,512,528,531,533,534,536,540,],[13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,]),'element_list':([4,],[91,]),'relational_expr':([26,83,88,89,92,146,149,158,160,168,170,175,182,183,184,185,207,210,226,238,243,260,261,265,266,267,268,269,272,275,276,277,278,342,343,352,400,401,402,403,404,407,412,420,434,443,446,488,491,495,509,],[129,129,129,129,129,129,129,129,129,129,129,129,326,327,328,329,129,129,129,129,129,129,129,129,372,373,374,375,129,129,129,129,129,129,129,129,455,456,457,458,129,129,129,129,129,129,129,129,129,129,129,]),'primary_expr_no_brace':([0,6,7,10,11,23,25,26,30,40,44,48,54,68,83,84,88,89,90,92,98,120,121,122,123,124,126,146,149,150,151,152,155,158,160,168,170,171,174,175,181,182,183,184,185,186,187,188,189,190,191,192,207,210,226,238,243,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,272,273,274,275,276,277,278,342,343,352,383,386,389,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,412,418,420,421,434,436,441,443,446,447,477,483,488,491,492,493,495,501,502,504,509,512,528,531,533,534,536,540,],[15,102,15,102,102,102,102,102,102,102,15,102,102,15,102,102,102,102,15,102,102,102,102,102,102,102,15,102,102,102,102,102,102,102,102,102,102,15,15,102,15,102,102,102,102,102,102,102,102,102,102,15,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,15,15,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,102,15,102,15,102,15,15,102,102,102,15,15,102,102,15,102,102,15,15,15,102,15,15,15,15,15,15,15,]),'variable_declaration_list_noin':([289,],[391,]),'null_literal':([0,6,7,10,11,23,25,26,30,40,44,48,54,68,83,84,88,89,90,92,98,120,121,122,123,124,126,146,149,150,151,152,155,158,160,168,170,171,174,175,181,182,183,184,185,186,187,188,189,190,191,192,207,210,226,238,243,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,272,273,274,275,276,277,278,342,343,352,383,386,389,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,412,418,420,421,434,436,441,443,446,447,477,483,488,491,492,493,495,501,502,504,509,512,528,531,533,534,536,540,],[16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,]),'labelled_statement':([0,7,44,68,126,383,386,418,421,436,441,477,483,492,501,502,504,512,528,531,533,534,536,540,],[19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,19,]),'expr_statement':([0,7,44,68,126,383,386,418,421,436,441,477,483,492,501,502,504,512,528,531,533,534,536,540,],[21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,]),'logical_and_expr':([26,83,88,89,92,146,149,158,160,168,170,175,207,210,226,238,243,272,275,276,277,342,343,352,404,407,412,420,434,443,446,488,491,495,509,],[131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,380,131,131,131,131,131,131,131,131,131,131,131,131,131,131,131,]),'additive_expr_nobf':([0,7,44,68,90,126,171,174,181,192,383,386,418,421,436,441,477,483,492,501,502,504,512,528,531,533,534,536,540,],[22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,]),'primary_expr':([6,10,11,23,25,26,30,40,48,54,83,84,88,89,92,98,120,121,122,123,124,146,149,150,151,152,155,158,160,168,170,175,182,183,184,185,186,187,188,189,190,191,207,210,226,238,243,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,272,273,274,275,276,277,278,342,343,352,389,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,412,420,434,443,446,447,488,491,493,495,509,],[108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,108,]),'identifier':([0,6,7,10,11,17,23,25,26,30,37,40,44,47,48,54,66,68,83,84,88,89,90,92,96,98,104,120,121,122,123,124,126,146,149,150,151,152,153,155,157,158,160,167,168,170,171,174,175,181,182,183,184,185,186,187,188,189,190,191,192,207,210,225,226,228,231,237,238,242,243,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,272,273,274,275,276,277,278,287,289,342,343,344,349,352,383,385,386,389,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,412,415,418,420,421,431,434,436,441,443,444,446,447,477,483,488,491,492,493,495,501,502,504,509,512,528,531,533,534,536,540,],[24,110,24,110,110,118,110,110,110,110,154,110,24,165,110,110,178,24,110,110,110,110,110,110,220,110,234,110,110,110,110,110,24,110,110,110,110,110,286,110,303,110,110,315,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,346,110,234,234,353,110,118,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,286,392,110,110,286,234,110,24,437,24,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,470,24,110,24,286,110,24,24,110,487,110,110,24,24,110,110,24,110,110,24,24,24,110,24,24,24,24,24,24,24,]),'bitwise_xor_expr_nobf':([0,7,44,68,90,126,174,181,383,386,418,421,436,441,477,483,492,501,502,504,512,528,531,533,534,536,540,],[53,53,53,53,53,53,53,325,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,53,]),'relational_expr_noin':([155,389,398,399,405,406,408,409,410,447,493,],[290,290,290,290,290,290,290,290,290,290,290,]),'with_statement':([0,7,44,68,126,383,386,418,421,436,441,477,483,492,501,502,504,512,528,531,533,534,536,540,],[28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,]),'case_clauses_opt':([473,520,],[497,535,]),'initializer':([118,],[244,]),'break_statement':([0,7,44,68,126,383,386,418,421,436,441,477,483,492,501,502,504,512,528,531,533,534,536,540,],[29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,]),'bitwise_and_expr_noin':([155,389,399,405,406,408,409,410,447,493,],[291,291,454,291,291,291,291,291,291,291,]),'switch_statement':([0,7,44,68,126,383,386,418,421,436,441,477,483,492,501,502,504,512,528,531,533,534,536,540,],[31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,]),'property_list':([104,],[230,]),'postfix_expr':([6,10,11,23,25,26,30,40,48,83,84,88,89,92,120,121,122,123,124,146,149,150,151,152,155,158,160,168,170,175,182,183,184,185,186,187,188,189,190,191,207,210,226,238,243,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,272,273,274,275,276,277,278,342,343,352,389,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,412,420,434,443,446,447,488,491,493,495,509,],[100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,]),'source_elements':([0,44,386,436,441,477,483,502,504,528,534,536,],[33,162,438,438,438,438,438,438,438,438,543,545,]),'shift_expr':([26,83,88,89,92,146,149,155,158,160,168,170,175,182,183,184,185,186,187,188,189,190,191,207,210,226,238,243,254,255,256,257,258,259,260,261,265,266,267,268,269,272,275,276,277,278,342,343,352,389,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,412,420,434,443,446,447,488,491,493,495,509,],[132,132,132,132,132,132,132,292,132,132,132,132,132,132,132,132,132,330,331,332,333,334,335,132,132,132,132,132,360,361,362,363,364,365,132,132,132,132,132,132,132,132,132,132,132,132,132,132,132,292,448,449,450,451,452,292,292,132,132,132,132,132,292,292,132,292,292,292,132,132,132,132,132,292,132,132,292,132,132,]),'expr_nobf':([0,7,44,68,126,383,386,418,421,436,441,477,483,492,501,502,504,512,528,531,533,534,536,540,],[34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,]),'expr_opt':([404,443,491,509,],[459,485,513,530,]),'multiplicative_expr_nobf':([0,7,44,68,90,126,171,174,181,192,383,386,418,421,436,441,477,483,492,501,502,504,512,528,531,533,534,536,540,],[35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,]),'continue_statement':([0,7,44,68,126,383,386,418,421,436,441,477,483,492,501,502,504,512,528,531,533,534,536,540,],[36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,]),'argument_list':([160,],[306,]),'expr_noin_opt':([155,],[296,]),'string_literal':([0,6,7,10,11,23,25,26,30,40,44,48,54,68,83,84,88,89,90,92,98,104,120,121,122,123,124,126,146,149,150,151,152,155,158,160,168,170,171,174,175,181,182,183,184,185,186,187,188,189,190,191,192,207,210,226,228,231,238,243,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,272,273,274,275,276,277,278,342,343,349,352,383,386,389,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,412,418,420,421,434,436,441,443,446,447,477,483,488,491,492,493,495,501,502,504,509,512,528,531,533,534,536,540,],[38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,236,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,236,236,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,236,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,]),'call_expr_nobf':([0,7,44,68,90,126,171,174,181,192,383,386,418,421,436,441,477,483,492,501,502,504,512,528,531,533,534,536,540,],[41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,41,]),'bitwise_xor_expr_noin':([155,389,405,406,408,409,410,447,493,],[293,293,462,293,293,293,293,293,293,]),'variable_statement':([0,7,44,68,126,383,386,418,421,436,441,477,483,492,501,502,504,512,528,531,533,534,536,540,],[43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,]),'object_literal':([6,10,11,23,25,26,30,40,48,54,83,84,88,89,92,98,120,121,122,123,124,146,149,150,151,152,155,158,160,168,170,175,182,183,184,185,186,187,188,189,190,191,207,210,226,238,243,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,272,273,274,275,276,277,278,342,343,352,389,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,412,420,434,443,446,447,488,491,493,495,509,],[105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,105,]),'function_declaration':([0,7,44,68,126,383,386,418,421,436,441,477,483,492,501,502,504,512,528,531,533,534,536,540,],[45,45,45,179,179,179,45,179,179,45,45,45,45,179,179,45,45,179,45,179,179,45,45,179,]),'unary_expr_common':([0,6,7,10,11,23,25,26,30,40,44,48,68,83,84,88,89,90,92,120,121,122,123,124,126,146,149,150,151,152,155,158,160,168,170,171,174,175,181,182,183,184,185,186,187,188,189,190,191,192,207,210,226,238,243,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,272,273,274,275,276,277,278,342,343,352,383,386,389,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,412,418,420,421,434,436,441,443,446,447,477,483,488,491,492,493,495,501,502,504,509,512,528,531,533,534,536,540,],[46,106,46,106,106,106,106,106,106,106,46,106,46,106,106,106,106,46,106,106,106,106,106,106,46,106,106,106,106,106,106,106,106,106,106,46,46,106,46,106,106,106,106,106,106,106,106,106,106,46,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,46,46,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,106,46,106,46,106,46,46,106,106,106,46,46,106,106,46,106,106,46,46,46,106,46,46,46,46,46,46,46,]),'additive_expr':([26,83,88,89,92,120,121,122,146,149,155,158,160,168,170,175,182,183,184,185,186,187,188,189,190,191,207,210,226,238,243,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,272,275,276,277,278,342,343,352,389,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,412,420,434,443,446,447,488,491,493,495,509,],[140,140,140,140,140,245,246,247,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,368,369,370,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,]),'assignment_operator':([82,142,301,464,],[207,277,408,408,]),'case_clause':([473,496,520,],[498,518,498,]),'member_expr_nobf':([0,7,44,68,90,126,171,174,181,192,383,386,418,421,436,441,477,483,492,501,502,504,512,528,531,533,534,536,540,],[49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,]),'numeric_literal':([0,6,7,10,11,23,25,26,30,40,44,48,54,68,83,84,88,89,90,92,98,104,120,121,122,123,124,126,146,149,150,151,152,155,158,160,168,170,171,174,175,181,182,183,184,185,186,187,188,189,190,191,192,207,210,226,228,231,238,243,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,272,273,274,275,276,277,278,342,343,349,352,383,386,389,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,412,418,420,421,434,436,441,443,446,447,477,483,488,491,492,493,495,501,502,504,509,512,528,531,533,534,536,540,],[87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,232,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,232,232,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,232,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,87,]),'assignment_expr_nobf':([0,7,44,68,126,383,386,418,421,436,441,477,483,492,501,502,504,512,528,531,533,534,536,540,],[51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,]),'equality_expr_noin':([155,389,398,399,405,406,408,409,410,447,493,],[294,294,453,294,294,294,294,294,294,294,294,]),'unary_expr':([6,10,11,23,25,26,30,40,48,83,84,88,89,92,120,121,122,123,124,146,149,150,151,152,155,158,160,168,170,175,182,183,184,185,186,187,188,189,190,191,207,210,226,238,243,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,272,273,274,275,276,277,278,342,343,352,389,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,412,420,434,443,446,447,488,491,493,495,509,],[97,112,113,125,127,134,145,156,166,134,209,134,134,134,134,134,134,134,134,134,134,281,282,283,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,357,358,359,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,134,]),'unary_expr_nobf':([0,7,44,68,90,126,171,174,181,192,383,386,418,421,436,441,477,483,492,501,502,504,512,528,531,533,534,536,540,],[27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,]),'function_body':([386,436,441,477,483,502,504,528,],[439,481,484,503,507,525,527,539,]),'variable_declaration':([17,242,],[119,355,]),'bitwise_xor_expr':([26,83,88,89,92,146,149,158,160,168,170,175,207,210,226,238,243,260,261,272,275,276,277,342,343,352,404,407,412,420,434,443,446,488,491,495,509,],[135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,366,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,135,]),'conditional_expr_nobf':([0,7,44,68,126,383,386,418,421,436,441,477,483,492,501,502,504,512,528,531,533,534,536,540,],[55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,55,]),'equality_expr':([26,83,88,89,92,146,149,158,160,168,170,175,207,210,226,238,243,260,261,265,272,275,276,277,278,342,343,352,404,407,412,420,434,443,446,488,491,495,509,],[136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,382,136,136,136,136,136,136,136,136,136,136,136,136,136,136,]),'literal':([0,6,7,10,11,23,25,26,30,40,44,48,54,68,83,84,88,89,90,92,98,120,121,122,123,124,126,146,149,150,151,152,155,158,160,168,170,171,174,175,181,182,183,184,185,186,187,188,189,190,191,192,207,210,226,238,243,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,272,273,274,275,276,277,278,342,343,352,383,386,389,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,412,418,420,421,434,436,441,443,446,447,477,483,488,491,492,493,495,501,502,504,509,512,528,531,533,534,536,540,],[80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,]),'logical_and_expr_nobf':([0,7,44,68,90,126,383,386,418,421,436,441,477,483,492,501,502,504,512,528,531,533,534,536,540,],[56,56,56,56,214,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,56,]),'shift_expr_nobf':([0,7,44,68,90,126,171,174,181,192,383,386,418,421,436,441,477,483,492,501,502,504,512,528,531,533,534,536,540,],[18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,]),'elision':([4,215,],[94,94,]),'statement':([0,7,44,68,126,383,386,418,421,436,441,477,483,492,501,502,504,512,528,531,533,534,536,540,],[58,58,58,180,250,435,58,471,475,58,58,58,58,514,524,58,58,532,58,541,542,58,58,547,]),'empty':([0,4,44,155,215,386,404,436,441,443,473,477,483,491,502,504,509,520,528,534,536,],[59,95,59,300,95,59,460,59,59,460,499,59,59,460,59,59,460,499,59,59,59,]),'new_expr':([6,10,11,23,25,26,30,40,48,54,83,84,88,89,92,98,120,121,122,123,124,146,149,150,151,152,155,158,160,168,170,175,182,183,184,185,186,187,188,189,190,191,207,210,226,238,243,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,272,273,274,275,276,277,278,342,343,352,389,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,412,420,434,443,446,447,488,491,493,495,509,],[101,101,101,101,101,101,101,101,101,172,101,101,101,101,101,221,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,101,]),'postfix_expr_nobf':([0,7,44,68,90,126,171,174,181,192,383,386,418,421,436,441,477,483,492,501,502,504,512,528,531,533,534,536,540,],[60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,]),'regex_literal':([0,6,7,10,11,23,25,26,30,40,44,48,54,68,83,84,88,89,90,92,98,120,121,122,123,124,126,146,149,150,151,152,155,158,160,168,170,171,174,175,181,182,183,184,185,186,187,188,189,190,191,192,207,210,226,238,243,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,272,273,274,275,276,277,278,342,343,352,383,386,389,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,412,418,420,421,434,436,441,443,446,447,477,483,488,491,492,493,495,501,502,504,509,512,528,531,533,534,536,540,],[61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,61,]),'conditional_expr_noin':([155,406,408,409,447,493,],[298,298,298,298,298,298,]),'variable_declaration_list':([17,],[117,]),'catch':([161,],[311,]),'expr_noin':([155,],[299,]),'conditional_expr':([26,83,88,89,92,146,149,158,160,168,170,175,207,210,226,238,243,272,275,277,342,343,352,404,407,412,420,434,443,446,488,491,495,509,],[137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,137,]),'default_clause':([497,],[520,]),'expr':([26,83,88,146,158,168,170,175,210,226,238,404,407,420,443,446,488,491,495,509,],[138,208,211,279,304,316,317,321,339,347,354,461,465,474,461,489,511,461,517,461,]),'empty_statement':([0,7,44,68,126,383,386,418,421,436,441,477,483,492,501,502,504,512,528,531,533,534,536,540,],[65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,65,]),'bitwise_or_expr_noin':([155,389,406,408,409,410,447,493,],[297,442,297,297,297,297,297,297,]),'member_expr':([6,10,11,23,25,26,30,40,48,54,83,84,88,89,92,98,120,121,122,123,124,146,149,150,151,152,155,158,160,168,170,175,182,183,184,185,186,187,188,189,190,191,207,210,226,238,243,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,272,273,274,275,276,277,278,342,343,352,389,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,412,420,434,443,446,447,488,491,493,495,509,],[109,109,109,109,109,109,109,109,109,173,109,109,109,109,109,222,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,109,]),'assignment_expr':([26,83,88,89,92,146,149,158,160,168,170,175,207,210,226,238,243,272,275,277,342,343,352,404,407,412,420,434,443,446,488,491,495,509,],[139,139,139,212,217,139,280,139,307,139,139,139,337,139,139,139,356,376,379,381,422,423,432,139,139,469,139,480,139,139,139,139,139,139,]),'initializer_noin':([392,487,],[445,510,]),'source_element':([0,7,44,386,436,441,477,483,502,504,528,534,536,],[67,111,67,67,67,67,67,67,67,67,67,67,67,]),'bitwise_or_expr_nobf':([0,7,44,68,90,126,174,383,386,418,421,436,441,477,483,492,501,502,504,512,528,531,533,534,536,540,],[69,69,69,69,69,69,320,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,69,]),'case_clauses':([473,520,],[496,496,]),'logical_or_expr':([26,83,88,89,92,146,149,158,160,168,170,175,207,210,226,238,243,272,275,277,342,343,352,404,407,412,420,434,443,446,488,491,495,509,],[141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,141,]),'left_hand_side_expr':([6,10,11,23,25,26,30,40,48,83,84,88,89,92,120,121,122,123,124,146,149,150,151,152,155,158,160,168,170,175,182,183,184,185,186,187,188,189,190,191,207,210,226,238,243,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,272,273,274,275,276,277,278,342,343,352,389,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,412,420,434,443,446,447,488,491,493,495,509,],[99,99,99,99,99,142,99,99,99,142,99,142,142,142,99,99,99,99,99,142,142,99,99,99,301,142,142,142,142,142,99,99,99,99,99,99,99,99,99,99,142,142,142,142,142,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,142,99,99,142,99,142,99,142,142,142,99,99,99,99,99,99,99,99,99,99,99,99,142,99,464,142,464,464,99,142,142,142,142,142,464,142,142,464,142,142,]),'property_name':([104,228,231,349,],[235,348,351,235,]),'equality_expr_nobf':([0,7,44,68,90,126,171,174,181,192,383,386,418,421,436,441,477,483,492,501,502,504,512,528,531,533,534,536,540,],[73,73,73,73,73,73,73,73,73,336,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,]),'relational_expr_nobf':([0,7,44,68,90,126,171,174,181,192,383,386,418,421,436,441,477,483,492,501,502,504,512,528,531,533,534,536,540,],[74,74,74,74,74,74,74,74,74,74,74,74,74,74,74,74,74,74,74,74,74,74,74,74,74,74,74,74,74,]),'return_statement':([0,7,44,68,126,383,386,418,421,436,441,477,483,492,501,502,504,512,528,531,533,534,536,540,],[75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,]),'bitwise_and_expr_nobf':([0,7,44,68,90,126,171,174,181,383,386,418,421,436,441,477,483,492,501,502,504,512,528,531,533,534,536,540,],[76,76,76,76,76,76,318,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,76,]),'arguments':([41,49,103,109,173,222,],[159,169,227,239,319,345,]),'if_statement':([0,7,44,68,126,383,386,418,421,436,441,477,483,492,501,502,504,512,528,531,533,534,536,540,],[77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,77,]),'logical_or_expr_noin':([155,406,408,409,447,493,],[302,302,302,302,302,302,]),'auto_semi':([14,26,34,47,66,117,138,165,178,211,500,],[114,133,148,164,177,241,271,314,322,341,523,]),'call_expr':([6,10,11,23,25,26,30,40,48,83,84,88,89,92,120,121,122,123,124,146,149,150,151,152,155,158,160,168,170,175,182,183,184,185,186,187,188,189,190,191,207,210,226,238,243,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,272,273,274,275,276,277,278,342,343,352,389,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,412,420,434,443,446,447,488,491,493,495,509,],[103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,103,]),'array_literal':([0,6,7,10,11,23,25,26,30,40,44,48,54,68,83,84,88,89,90,92,98,120,121,122,123,124,126,146,149,150,151,152,155,158,160,168,170,171,174,175,181,182,183,184,185,186,187,188,189,190,191,192,207,210,226,238,243,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,272,273,274,275,276,277,278,342,343,352,383,386,389,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,412,418,420,421,434,436,441,443,446,447,477,483,488,491,492,493,495,501,502,504,509,512,528,531,533,534,536,540,],[81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,81,]),'left_hand_side_expr_nobf':([0,7,44,68,90,126,171,174,181,192,383,386,418,421,436,441,477,483,492,501,502,504,512,528,531,533,534,536,540,],[82,82,82,82,213,82,213,213,213,213,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,82,]),'assignment_expr_noin':([155,406,408,409,447,493,],[295,463,466,467,490,515,]),'elision_opt':([4,215,],[92,343,]),'bitwise_and_expr':([26,83,88,89,92,146,149,158,160,168,170,175,207,210,226,238,243,260,261,265,272,275,276,277,342,343,352,404,407,412,420,434,443,446,488,491,495,509,],[144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,371,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,144,]),'block':([0,7,42,44,68,126,308,383,386,418,421,436,441,477,483,492,494,501,502,504,512,528,531,533,534,536,540,],[50,50,161,50,50,50,414,50,50,50,50,50,50,50,50,50,516,50,50,50,50,50,50,50,50,50,50,]),'debugger_statement':([0,7,44,68,126,383,386,418,421,436,441,477,483,492,501,502,504,512,528,531,533,534,536,540,],[62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,]),}
+
+_lr_goto = { }
+for _k, _v in _lr_goto_items.items():
+   for _x,_y in zip(_v[0],_v[1]):
+       if not _x in _lr_goto: _lr_goto[_x] = { }
+       _lr_goto[_x][_k] = _y
+del _lr_goto_items
+_lr_productions = [
+  ("S' -> program","S'",1,None,None,None),
+  ('empty -> <empty>','empty',0,'p_empty','/home/alienoid/dev/python/slimit/src/slimit/parser.py',96),
+  ('auto_semi -> error','auto_semi',1,'p_auto_semi','/home/alienoid/dev/python/slimit/src/slimit/parser.py',100),
+  ('program -> source_elements','program',1,'p_program','/home/alienoid/dev/python/slimit/src/slimit/parser.py',130),
+  ('source_elements -> empty','source_elements',1,'p_source_elements','/home/alienoid/dev/python/slimit/src/slimit/parser.py',134),
+  ('source_elements -> source_element_list','source_elements',1,'p_source_elements','/home/alienoid/dev/python/slimit/src/slimit/parser.py',135),
+  ('source_element_list -> source_element','source_element_list',1,'p_source_element_list','/home/alienoid/dev/python/slimit/src/slimit/parser.py',140),
+  ('source_element_list -> source_element_list source_element','source_element_list',2,'p_source_element_list','/home/alienoid/dev/python/slimit/src/slimit/parser.py',141),
+  ('source_element -> statement','source_element',1,'p_source_element','/home/alienoid/dev/python/slimit/src/slimit/parser.py',150),
+  ('source_element -> function_declaration','source_element',1,'p_source_element','/home/alienoid/dev/python/slimit/src/slimit/parser.py',151),
+  ('statement -> block','statement',1,'p_statement','/home/alienoid/dev/python/slimit/src/slimit/parser.py',156),
+  ('statement -> variable_statement','statement',1,'p_statement','/home/alienoid/dev/python/slimit/src/slimit/parser.py',157),
+  ('statement -> empty_statement','statement',1,'p_statement','/home/alienoid/dev/python/slimit/src/slimit/parser.py',158),
+  ('statement -> expr_statement','statement',1,'p_statement','/home/alienoid/dev/python/slimit/src/slimit/parser.py',159),
+  ('statement -> if_statement','statement',1,'p_statement','/home/alienoid/dev/python/slimit/src/slimit/parser.py',160),
+  ('statement -> iteration_statement','statement',1,'p_statement','/home/alienoid/dev/python/slimit/src/slimit/parser.py',161),
+  ('statement -> continue_statement','statement',1,'p_statement','/home/alienoid/dev/python/slimit/src/slimit/parser.py',162),
+  ('statement -> break_statement','statement',1,'p_statement','/home/alienoid/dev/python/slimit/src/slimit/parser.py',163),
+  ('statement -> return_statement','statement',1,'p_statement','/home/alienoid/dev/python/slimit/src/slimit/parser.py',164),
+  ('statement -> with_statement','statement',1,'p_statement','/home/alienoid/dev/python/slimit/src/slimit/parser.py',165),
+  ('statement -> switch_statement','statement',1,'p_statement','/home/alienoid/dev/python/slimit/src/slimit/parser.py',166),
+  ('statement -> labelled_statement','statement',1,'p_statement','/home/alienoid/dev/python/slimit/src/slimit/parser.py',167),
+  ('statement -> throw_statement','statement',1,'p_statement','/home/alienoid/dev/python/slimit/src/slimit/parser.py',168),
+  ('statement -> try_statement','statement',1,'p_statement','/home/alienoid/dev/python/slimit/src/slimit/parser.py',169),
+  ('statement -> debugger_statement','statement',1,'p_statement','/home/alienoid/dev/python/slimit/src/slimit/parser.py',170),
+  ('statement -> function_declaration','statement',1,'p_statement','/home/alienoid/dev/python/slimit/src/slimit/parser.py',171),
+  ('block -> LBRACE source_elements RBRACE','block',3,'p_block','/home/alienoid/dev/python/slimit/src/slimit/parser.py',178),
+  ('literal -> null_literal','literal',1,'p_literal','/home/alienoid/dev/python/slimit/src/slimit/parser.py',182),
+  ('literal -> boolean_literal','literal',1,'p_literal','/home/alienoid/dev/python/slimit/src/slimit/parser.py',183),
+  ('literal -> numeric_literal','literal',1,'p_literal','/home/alienoid/dev/python/slimit/src/slimit/parser.py',184),
+  ('literal -> string_literal','literal',1,'p_literal','/home/alienoid/dev/python/slimit/src/slimit/parser.py',185),
+  ('literal -> regex_literal','literal',1,'p_literal','/home/alienoid/dev/python/slimit/src/slimit/parser.py',186),
+  ('boolean_literal -> TRUE','boolean_literal',1,'p_boolean_literal','/home/alienoid/dev/python/slimit/src/slimit/parser.py',191),
+  ('boolean_literal -> FALSE','boolean_literal',1,'p_boolean_literal','/home/alienoid/dev/python/slimit/src/slimit/parser.py',192),
+  ('null_literal -> NULL','null_literal',1,'p_null_literal','/home/alienoid/dev/python/slimit/src/slimit/parser.py',197),
+  ('numeric_literal -> NUMBER','numeric_literal',1,'p_numeric_literal','/home/alienoid/dev/python/slimit/src/slimit/parser.py',201),
+  ('string_literal -> STRING','string_literal',1,'p_string_literal','/home/alienoid/dev/python/slimit/src/slimit/parser.py',205),
+  ('regex_literal -> REGEX','regex_literal',1,'p_regex_literal','/home/alienoid/dev/python/slimit/src/slimit/parser.py',209),
+  ('identifier -> ID','identifier',1,'p_identifier','/home/alienoid/dev/python/slimit/src/slimit/parser.py',213),
+  ('primary_expr -> primary_expr_no_brace','primary_expr',1,'p_primary_expr','/home/alienoid/dev/python/slimit/src/slimit/parser.py',220),
+  ('primary_expr -> object_literal','primary_expr',1,'p_primary_expr','/home/alienoid/dev/python/slimit/src/slimit/parser.py',221),
+  ('primary_expr_no_brace -> identifier','primary_expr_no_brace',1,'p_primary_expr_no_brace_1','/home/alienoid/dev/python/slimit/src/slimit/parser.py',226),
+  ('primary_expr_no_brace -> THIS','primary_expr_no_brace',1,'p_primary_expr_no_brace_2','/home/alienoid/dev/python/slimit/src/slimit/parser.py',232),
+  ('primary_expr_no_brace -> literal','primary_expr_no_brace',1,'p_primary_expr_no_brace_3','/home/alienoid/dev/python/slimit/src/slimit/parser.py',236),
+  ('primary_expr_no_brace -> array_literal','primary_expr_no_brace',1,'p_primary_expr_no_brace_3','/home/alienoid/dev/python/slimit/src/slimit/parser.py',237),
+  ('primary_expr_no_brace -> LPAREN expr RPAREN','primary_expr_no_brace',3,'p_primary_expr_no_brace_4','/home/alienoid/dev/python/slimit/src/slimit/parser.py',242),
+  ('array_literal -> LBRACKET elision_opt RBRACKET','array_literal',3,'p_array_literal_1','/home/alienoid/dev/python/slimit/src/slimit/parser.py',247),
+  ('array_literal -> LBRACKET element_list RBRACKET','array_literal',3,'p_array_literal_2','/home/alienoid/dev/python/slimit/src/slimit/parser.py',251),
+  ('array_literal -> LBRACKET element_list COMMA elision_opt RBRACKET','array_literal',5,'p_array_literal_2','/home/alienoid/dev/python/slimit/src/slimit/parser.py',252),
+  ('element_list -> elision_opt assignment_expr','element_list',2,'p_element_list','/home/alienoid/dev/python/slimit/src/slimit/parser.py',261),
+  ('element_list -> element_list COMMA elision_opt assignment_expr','element_list',4,'p_element_list','/home/alienoid/dev/python/slimit/src/slimit/parser.py',262),
+  ('elision_opt -> empty','elision_opt',1,'p_elision_opt_1','/home/alienoid/dev/python/slimit/src/slimit/parser.py',272),
+  ('elision_opt -> elision','elision_opt',1,'p_elision_opt_2','/home/alienoid/dev/python/slimit/src/slimit/parser.py',276),
+  ('elision -> COMMA','elision',1,'p_elision','/home/alienoid/dev/python/slimit/src/slimit/parser.py',280),
+  ('elision -> elision COMMA','elision',2,'p_elision','/home/alienoid/dev/python/slimit/src/slimit/parser.py',281),
+  ('object_literal -> LBRACE RBRACE','object_literal',2,'p_object_literal','/home/alienoid/dev/python/slimit/src/slimit/parser.py',290),
+  ('object_literal -> LBRACE property_list RBRACE','object_literal',3,'p_object_literal','/home/alienoid/dev/python/slimit/src/slimit/parser.py',291),
+  ('object_literal -> LBRACE property_list COMMA RBRACE','object_literal',4,'p_object_literal','/home/alienoid/dev/python/slimit/src/slimit/parser.py',292),
+  ('property_list -> property_assignment','property_list',1,'p_property_list','/home/alienoid/dev/python/slimit/src/slimit/parser.py',300),
+  ('property_list -> property_list COMMA property_assignment','property_list',3,'p_property_list','/home/alienoid/dev/python/slimit/src/slimit/parser.py',301),
+  ('property_assignment -> property_name COLON assignment_expr','property_assignment',3,'p_property_assignment','/home/alienoid/dev/python/slimit/src/slimit/parser.py',311),
+  ('property_assignment -> GETPROP property_name LPAREN RPAREN LBRACE function_body RBRACE','property_assignment',7,'p_property_assignment','/home/alienoid/dev/python/slimit/src/slimit/parser.py',312),
+  ('property_assignment -> SETPROP property_name LPAREN formal_parameter_list RPAREN LBRACE function_body RBRACE','property_assignment',8,'p_property_assignment','/home/alienoid/dev/python/slimit/src/slimit/parser.py',313),
+  ('property_name -> identifier','property_name',1,'p_property_name','/home/alienoid/dev/python/slimit/src/slimit/parser.py',326),
+  ('property_name -> string_literal','property_name',1,'p_property_name','/home/alienoid/dev/python/slimit/src/slimit/parser.py',327),
+  ('property_name -> numeric_literal','property_name',1,'p_property_name','/home/alienoid/dev/python/slimit/src/slimit/parser.py',328),
+  ('member_expr -> primary_expr','member_expr',1,'p_member_expr','/home/alienoid/dev/python/slimit/src/slimit/parser.py',334),
+  ('member_expr -> function_expr','member_expr',1,'p_member_expr','/home/alienoid/dev/python/slimit/src/slimit/parser.py',335),
+  ('member_expr -> member_expr LBRACKET expr RBRACKET','member_expr',4,'p_member_expr','/home/alienoid/dev/python/slimit/src/slimit/parser.py',336),
+  ('member_expr -> member_expr PERIOD identifier','member_expr',3,'p_member_expr','/home/alienoid/dev/python/slimit/src/slimit/parser.py',337),
+  ('member_expr -> NEW member_expr arguments','member_expr',3,'p_member_expr','/home/alienoid/dev/python/slimit/src/slimit/parser.py',338),
+  ('member_expr_nobf -> primary_expr_no_brace','member_expr_nobf',1,'p_member_expr_nobf','/home/alienoid/dev/python/slimit/src/slimit/parser.py',350),
+  ('member_expr_nobf -> function_expr','member_expr_nobf',1,'p_member_expr_nobf','/home/alienoid/dev/python/slimit/src/slimit/parser.py',351),
+  ('member_expr_nobf -> member_expr_nobf LBRACKET expr RBRACKET','member_expr_nobf',4,'p_member_expr_nobf','/home/alienoid/dev/python/slimit/src/slimit/parser.py',352),
+  ('member_expr_nobf -> member_expr_nobf PERIOD identifier','member_expr_nobf',3,'p_member_expr_nobf','/home/alienoid/dev/python/slimit/src/slimit/parser.py',353),
+  ('member_expr_nobf -> NEW member_expr arguments','member_expr_nobf',3,'p_member_expr_nobf','/home/alienoid/dev/python/slimit/src/slimit/parser.py',354),
+  ('new_expr -> member_expr','new_expr',1,'p_new_expr','/home/alienoid/dev/python/slimit/src/slimit/parser.py',366),
+  ('new_expr -> NEW new_expr','new_expr',2,'p_new_expr','/home/alienoid/dev/python/slimit/src/slimit/parser.py',367),
+  ('new_expr_nobf -> member_expr_nobf','new_expr_nobf',1,'p_new_expr_nobf','/home/alienoid/dev/python/slimit/src/slimit/parser.py',375),
+  ('new_expr_nobf -> NEW new_expr','new_expr_nobf',2,'p_new_expr_nobf','/home/alienoid/dev/python/slimit/src/slimit/parser.py',376),
+  ('call_expr -> member_expr arguments','call_expr',2,'p_call_expr','/home/alienoid/dev/python/slimit/src/slimit/parser.py',384),
+  ('call_expr -> call_expr arguments','call_expr',2,'p_call_expr','/home/alienoid/dev/python/slimit/src/slimit/parser.py',385),
+  ('call_expr -> call_expr LBRACKET expr RBRACKET','call_expr',4,'p_call_expr','/home/alienoid/dev/python/slimit/src/slimit/parser.py',386),
+  ('call_expr -> call_expr PERIOD identifier','call_expr',3,'p_call_expr','/home/alienoid/dev/python/slimit/src/slimit/parser.py',387),
+  ('call_expr_nobf -> member_expr_nobf arguments','call_expr_nobf',2,'p_call_expr_nobf','/home/alienoid/dev/python/slimit/src/slimit/parser.py',397),
+  ('call_expr_nobf -> call_expr_nobf arguments','call_expr_nobf',2,'p_call_expr_nobf','/home/alienoid/dev/python/slimit/src/slimit/parser.py',398),
+  ('call_expr_nobf -> call_expr_nobf LBRACKET expr RBRACKET','call_expr_nobf',4,'p_call_expr_nobf','/home/alienoid/dev/python/slimit/src/slimit/parser.py',399),
+  ('call_expr_nobf -> call_expr_nobf PERIOD identifier','call_expr_nobf',3,'p_call_expr_nobf','/home/alienoid/dev/python/slimit/src/slimit/parser.py',400),
+  ('arguments -> LPAREN RPAREN','arguments',2,'p_arguments','/home/alienoid/dev/python/slimit/src/slimit/parser.py',410),
+  ('arguments -> LPAREN argument_list RPAREN','arguments',3,'p_arguments','/home/alienoid/dev/python/slimit/src/slimit/parser.py',411),
+  ('argument_list -> assignment_expr','argument_list',1,'p_argument_list','/home/alienoid/dev/python/slimit/src/slimit/parser.py',417),
+  ('argument_list -> argument_list COMMA assignment_expr','argument_list',3,'p_argument_list','/home/alienoid/dev/python/slimit/src/slimit/parser.py',418),
+  ('left_hand_side_expr -> new_expr','left_hand_side_expr',1,'p_lef_hand_side_expr','/home/alienoid/dev/python/slimit/src/slimit/parser.py',427),
+  ('left_hand_side_expr -> call_expr','left_hand_side_expr',1,'p_lef_hand_side_expr','/home/alienoid/dev/python/slimit/src/slimit/parser.py',428),
+  ('left_hand_side_expr_nobf -> new_expr_nobf','left_hand_side_expr_nobf',1,'p_lef_hand_side_expr_nobf','/home/alienoid/dev/python/slimit/src/slimit/parser.py',433),
+  ('left_hand_side_expr_nobf -> call_expr_nobf','left_hand_side_expr_nobf',1,'p_lef_hand_side_expr_nobf','/home/alienoid/dev/python/slimit/src/slimit/parser.py',434),
+  ('postfix_expr -> left_hand_side_expr','postfix_expr',1,'p_postfix_expr','/home/alienoid/dev/python/slimit/src/slimit/parser.py',440),
+  ('postfix_expr -> left_hand_side_expr PLUSPLUS','postfix_expr',2,'p_postfix_expr','/home/alienoid/dev/python/slimit/src/slimit/parser.py',441),
+  ('postfix_expr -> left_hand_side_expr MINUSMINUS','postfix_expr',2,'p_postfix_expr','/home/alienoid/dev/python/slimit/src/slimit/parser.py',442),
+  ('postfix_expr_nobf -> left_hand_side_expr_nobf','postfix_expr_nobf',1,'p_postfix_expr_nobf','/home/alienoid/dev/python/slimit/src/slimit/parser.py',450),
+  ('postfix_expr_nobf -> left_hand_side_expr_nobf PLUSPLUS','postfix_expr_nobf',2,'p_postfix_expr_nobf','/home/alienoid/dev/python/slimit/src/slimit/parser.py',451),
+  ('postfix_expr_nobf -> left_hand_side_expr_nobf MINUSMINUS','postfix_expr_nobf',2,'p_postfix_expr_nobf','/home/alienoid/dev/python/slimit/src/slimit/parser.py',452),
+  ('unary_expr -> postfix_expr','unary_expr',1,'p_unary_expr','/home/alienoid/dev/python/slimit/src/slimit/parser.py',461),
+  ('unary_expr -> unary_expr_common','unary_expr',1,'p_unary_expr','/home/alienoid/dev/python/slimit/src/slimit/parser.py',462),
+  ('unary_expr_nobf -> postfix_expr_nobf','unary_expr_nobf',1,'p_unary_expr_nobf','/home/alienoid/dev/python/slimit/src/slimit/parser.py',467),
+  ('unary_expr_nobf -> unary_expr_common','unary_expr_nobf',1,'p_unary_expr_nobf','/home/alienoid/dev/python/slimit/src/slimit/parser.py',468),
+  ('unary_expr_common -> DELETE unary_expr','unary_expr_common',2,'p_unary_expr_common','/home/alienoid/dev/python/slimit/src/slimit/parser.py',473),
+  ('unary_expr_common -> VOID unary_expr','unary_expr_common',2,'p_unary_expr_common','/home/alienoid/dev/python/slimit/src/slimit/parser.py',474),
+  ('unary_expr_common -> TYPEOF unary_expr','unary_expr_common',2,'p_unary_expr_common','/home/alienoid/dev/python/slimit/src/slimit/parser.py',475),
+  ('unary_expr_common -> PLUSPLUS unary_expr','unary_expr_common',2,'p_unary_expr_common','/home/alienoid/dev/python/slimit/src/slimit/parser.py',476),
+  ('unary_expr_common -> MINUSMINUS unary_expr','unary_expr_common',2,'p_unary_expr_common','/home/alienoid/dev/python/slimit/src/slimit/parser.py',477),
+  ('unary_expr_common -> PLUS unary_expr','unary_expr_common',2,'p_unary_expr_common','/home/alienoid/dev/python/slimit/src/slimit/parser.py',478),
+  ('unary_expr_common -> MINUS unary_expr','unary_expr_common',2,'p_unary_expr_common','/home/alienoid/dev/python/slimit/src/slimit/parser.py',479),
+  ('unary_expr_common -> BNOT unary_expr','unary_expr_common',2,'p_unary_expr_common','/home/alienoid/dev/python/slimit/src/slimit/parser.py',480),
+  ('unary_expr_common -> NOT unary_expr','unary_expr_common',2,'p_unary_expr_common','/home/alienoid/dev/python/slimit/src/slimit/parser.py',481),
+  ('multiplicative_expr -> unary_expr','multiplicative_expr',1,'p_multiplicative_expr','/home/alienoid/dev/python/slimit/src/slimit/parser.py',487),
+  ('multiplicative_expr -> multiplicative_expr MULT unary_expr','multiplicative_expr',3,'p_multiplicative_expr','/home/alienoid/dev/python/slimit/src/slimit/parser.py',488),
+  ('multiplicative_expr -> multiplicative_expr DIV unary_expr','multiplicative_expr',3,'p_multiplicative_expr','/home/alienoid/dev/python/slimit/src/slimit/parser.py',489),
+  ('multiplicative_expr -> multiplicative_expr MOD unary_expr','multiplicative_expr',3,'p_multiplicative_expr','/home/alienoid/dev/python/slimit/src/slimit/parser.py',490),
+  ('multiplicative_expr_nobf -> unary_expr_nobf','multiplicative_expr_nobf',1,'p_multiplicative_expr_nobf','/home/alienoid/dev/python/slimit/src/slimit/parser.py',498),
+  ('multiplicative_expr_nobf -> multiplicative_expr_nobf MULT unary_expr','multiplicative_expr_nobf',3,'p_multiplicative_expr_nobf','/home/alienoid/dev/python/slimit/src/slimit/parser.py',499),
+  ('multiplicative_expr_nobf -> multiplicative_expr_nobf DIV unary_expr','multiplicative_expr_nobf',3,'p_multiplicative_expr_nobf','/home/alienoid/dev/python/slimit/src/slimit/parser.py',500),
+  ('multiplicative_expr_nobf -> multiplicative_expr_nobf MOD unary_expr','multiplicative_expr_nobf',3,'p_multiplicative_expr_nobf','/home/alienoid/dev/python/slimit/src/slimit/parser.py',501),
+  ('additive_expr -> multiplicative_expr','additive_expr',1,'p_additive_expr','/home/alienoid/dev/python/slimit/src/slimit/parser.py',510),
+  ('additive_expr -> additive_expr PLUS multiplicative_expr','additive_expr',3,'p_additive_expr','/home/alienoid/dev/python/slimit/src/slimit/parser.py',511),
+  ('additive_expr -> additive_expr MINUS multiplicative_expr','additive_expr',3,'p_additive_expr','/home/alienoid/dev/python/slimit/src/slimit/parser.py',512),
+  ('additive_expr_nobf -> multiplicative_expr_nobf','additive_expr_nobf',1,'p_additive_expr_nobf','/home/alienoid/dev/python/slimit/src/slimit/parser.py',520),
+  ('additive_expr_nobf -> additive_expr_nobf PLUS multiplicative_expr','additive_expr_nobf',3,'p_additive_expr_nobf','/home/alienoid/dev/python/slimit/src/slimit/parser.py',521),
+  ('additive_expr_nobf -> additive_expr_nobf MINUS multiplicative_expr','additive_expr_nobf',3,'p_additive_expr_nobf','/home/alienoid/dev/python/slimit/src/slimit/parser.py',522),
+  ('shift_expr -> additive_expr','shift_expr',1,'p_shift_expr','/home/alienoid/dev/python/slimit/src/slimit/parser.py',531),
+  ('shift_expr -> shift_expr LSHIFT additive_expr','shift_expr',3,'p_shift_expr','/home/alienoid/dev/python/slimit/src/slimit/parser.py',532),
+  ('shift_expr -> shift_expr RSHIFT additive_expr','shift_expr',3,'p_shift_expr','/home/alienoid/dev/python/slimit/src/slimit/parser.py',533),
+  ('shift_expr -> shift_expr URSHIFT additive_expr','shift_expr',3,'p_shift_expr','/home/alienoid/dev/python/slimit/src/slimit/parser.py',534),
+  ('shift_expr_nobf -> additive_expr_nobf','shift_expr_nobf',1,'p_shift_expr_nobf','/home/alienoid/dev/python/slimit/src/slimit/parser.py',542),
+  ('shift_expr_nobf -> shift_expr_nobf LSHIFT additive_expr','shift_expr_nobf',3,'p_shift_expr_nobf','/home/alienoid/dev/python/slimit/src/slimit/parser.py',543),
+  ('shift_expr_nobf -> shift_expr_nobf RSHIFT additive_expr','shift_expr_nobf',3,'p_shift_expr_nobf','/home/alienoid/dev/python/slimit/src/slimit/parser.py',544),
+  ('shift_expr_nobf -> shift_expr_nobf URSHIFT additive_expr','shift_expr_nobf',3,'p_shift_expr_nobf','/home/alienoid/dev/python/slimit/src/slimit/parser.py',545),
+  ('relational_expr -> shift_expr','relational_expr',1,'p_relational_expr','/home/alienoid/dev/python/slimit/src/slimit/parser.py',555),
+  ('relational_expr -> relational_expr LT shift_expr','relational_expr',3,'p_relational_expr','/home/alienoid/dev/python/slimit/src/slimit/parser.py',556),
+  ('relational_expr -> relational_expr GT shift_expr','relational_expr',3,'p_relational_expr','/home/alienoid/dev/python/slimit/src/slimit/parser.py',557),
+  ('relational_expr -> relational_expr LE shift_expr','relational_expr',3,'p_relational_expr','/home/alienoid/dev/python/slimit/src/slimit/parser.py',558),
+  ('relational_expr -> relational_expr GE shift_expr','relational_expr',3,'p_relational_expr','/home/alienoid/dev/python/slimit/src/slimit/parser.py',559),
+  ('relational_expr -> relational_expr INSTANCEOF shift_expr','relational_expr',3,'p_relational_expr','/home/alienoid/dev/python/slimit/src/slimit/parser.py',560),
+  ('relational_expr -> relational_expr IN shift_expr','relational_expr',3,'p_relational_expr','/home/alienoid/dev/python/slimit/src/slimit/parser.py',561),
+  ('relational_expr_noin -> shift_expr','relational_expr_noin',1,'p_relational_expr_noin','/home/alienoid/dev/python/slimit/src/slimit/parser.py',569),
+  ('relational_expr_noin -> relational_expr_noin LT shift_expr','relational_expr_noin',3,'p_relational_expr_noin','/home/alienoid/dev/python/slimit/src/slimit/parser.py',570),
+  ('relational_expr_noin -> relational_expr_noin GT shift_expr','relational_expr_noin',3,'p_relational_expr_noin','/home/alienoid/dev/python/slimit/src/slimit/parser.py',571),
+  ('relational_expr_noin -> relational_expr_noin LE shift_expr','relational_expr_noin',3,'p_relational_expr_noin','/home/alienoid/dev/python/slimit/src/slimit/parser.py',572),
+  ('relational_expr_noin -> relational_expr_noin GE shift_expr','relational_expr_noin',3,'p_relational_expr_noin','/home/alienoid/dev/python/slimit/src/slimit/parser.py',573),
+  ('relational_expr_noin -> relational_expr_noin INSTANCEOF shift_expr','relational_expr_noin',3,'p_relational_expr_noin','/home/alienoid/dev/python/slimit/src/slimit/parser.py',574),
+  ('relational_expr_nobf -> shift_expr_nobf','relational_expr_nobf',1,'p_relational_expr_nobf','/home/alienoid/dev/python/slimit/src/slimit/parser.py',582),
+  ('relational_expr_nobf -> relational_expr_nobf LT shift_expr','relational_expr_nobf',3,'p_relational_expr_nobf','/home/alienoid/dev/python/slimit/src/slimit/parser.py',583),
+  ('relational_expr_nobf -> relational_expr_nobf GT shift_expr','relational_expr_nobf',3,'p_relational_expr_nobf','/home/alienoid/dev/python/slimit/src/slimit/parser.py',584),
+  ('relational_expr_nobf -> relational_expr_nobf LE shift_expr','relational_expr_nobf',3,'p_relational_expr_nobf','/home/alienoid/dev/python/slimit/src/slimit/parser.py',585),
+  ('relational_expr_nobf -> relational_expr_nobf GE shift_expr','relational_expr_nobf',3,'p_relational_expr_nobf','/home/alienoid/dev/python/slimit/src/slimit/parser.py',586),
+  ('relational_expr_nobf -> relational_expr_nobf INSTANCEOF shift_expr','relational_expr_nobf',3,'p_relational_expr_nobf','/home/alienoid/dev/python/slimit/src/slimit/parser.py',587),
+  ('relational_expr_nobf -> relational_expr_nobf IN shift_expr','relational_expr_nobf',3,'p_relational_expr_nobf','/home/alienoid/dev/python/slimit/src/slimit/parser.py',588),
+  ('equality_expr -> relational_expr','equality_expr',1,'p_equality_expr','/home/alienoid/dev/python/slimit/src/slimit/parser.py',597),
+  ('equality_expr -> equality_expr EQEQ relational_expr','equality_expr',3,'p_equality_expr','/home/alienoid/dev/python/slimit/src/slimit/parser.py',598),
+  ('equality_expr -> equality_expr NE relational_expr','equality_expr',3,'p_equality_expr','/home/alienoid/dev/python/slimit/src/slimit/parser.py',599),
+  ('equality_expr -> equality_expr STREQ relational_expr','equality_expr',3,'p_equality_expr','/home/alienoid/dev/python/slimit/src/slimit/parser.py',600),
+  ('equality_expr -> equality_expr STRNEQ relational_expr','equality_expr',3,'p_equality_expr','/home/alienoid/dev/python/slimit/src/slimit/parser.py',601),
+  ('equality_expr_noin -> relational_expr_noin','equality_expr_noin',1,'p_equality_expr_noin','/home/alienoid/dev/python/slimit/src/slimit/parser.py',609),
+  ('equality_expr_noin -> equality_expr_noin EQEQ relational_expr','equality_expr_noin',3,'p_equality_expr_noin','/home/alienoid/dev/python/slimit/src/slimit/parser.py',610),
+  ('equality_expr_noin -> equality_expr_noin NE relational_expr','equality_expr_noin',3,'p_equality_expr_noin','/home/alienoid/dev/python/slimit/src/slimit/parser.py',611),
+  ('equality_expr_noin -> equality_expr_noin STREQ relational_expr','equality_expr_noin',3,'p_equality_expr_noin','/home/alienoid/dev/python/slimit/src/slimit/parser.py',612),
+  ('equality_expr_noin -> equality_expr_noin STRNEQ relational_expr','equality_expr_noin',3,'p_equality_expr_noin','/home/alienoid/dev/python/slimit/src/slimit/parser.py',613),
+  ('equality_expr_nobf -> relational_expr_nobf','equality_expr_nobf',1,'p_equality_expr_nobf','/home/alienoid/dev/python/slimit/src/slimit/parser.py',621),
+  ('equality_expr_nobf -> equality_expr_nobf EQEQ relational_expr','equality_expr_nobf',3,'p_equality_expr_nobf','/home/alienoid/dev/python/slimit/src/slimit/parser.py',622),
+  ('equality_expr_nobf -> equality_expr_nobf NE relational_expr','equality_expr_nobf',3,'p_equality_expr_nobf','/home/alienoid/dev/python/slimit/src/slimit/parser.py',623),
+  ('equality_expr_nobf -> equality_expr_nobf STREQ relational_expr','equality_expr_nobf',3,'p_equality_expr_nobf','/home/alienoid/dev/python/slimit/src/slimit/parser.py',624),
+  ('equality_expr_nobf -> equality_expr_nobf STRNEQ relational_expr','equality_expr_nobf',3,'p_equality_expr_nobf','/home/alienoid/dev/python/slimit/src/slimit/parser.py',625),
+  ('bitwise_and_expr -> equality_expr','bitwise_and_expr',1,'p_bitwise_and_expr','/home/alienoid/dev/python/slimit/src/slimit/parser.py',634),
+  ('bitwise_and_expr -> bitwise_and_expr BAND equality_expr','bitwise_and_expr',3,'p_bitwise_and_expr','/home/alienoid/dev/python/slimit/src/slimit/parser.py',635),
+  ('bitwise_and_expr_noin -> equality_expr_noin','bitwise_and_expr_noin',1,'p_bitwise_and_expr_noin','/home/alienoid/dev/python/slimit/src/slimit/parser.py',643),
+  ('bitwise_and_expr_noin -> bitwise_and_expr_noin BAND equality_expr_noin','bitwise_and_expr_noin',3,'p_bitwise_and_expr_noin','/home/alienoid/dev/python/slimit/src/slimit/parser.py',644),
+  ('bitwise_and_expr_nobf -> equality_expr_nobf','bitwise_and_expr_nobf',1,'p_bitwise_and_expr_nobf','/home/alienoid/dev/python/slimit/src/slimit/parser.py',653),
+  ('bitwise_and_expr_nobf -> bitwise_and_expr_nobf BAND equality_expr_nobf','bitwise_and_expr_nobf',3,'p_bitwise_and_expr_nobf','/home/alienoid/dev/python/slimit/src/slimit/parser.py',654),
+  ('bitwise_xor_expr -> bitwise_and_expr','bitwise_xor_expr',1,'p_bitwise_xor_expr','/home/alienoid/dev/python/slimit/src/slimit/parser.py',663),
+  ('bitwise_xor_expr -> bitwise_xor_expr BXOR bitwise_and_expr','bitwise_xor_expr',3,'p_bitwise_xor_expr','/home/alienoid/dev/python/slimit/src/slimit/parser.py',664),
+  ('bitwise_xor_expr_noin -> bitwise_and_expr_noin','bitwise_xor_expr_noin',1,'p_bitwise_xor_expr_noin','/home/alienoid/dev/python/slimit/src/slimit/parser.py',673),
+  ('bitwise_xor_expr_noin -> bitwise_xor_expr_noin BXOR bitwise_and_expr_noin','bitwise_xor_expr_noin',3,'p_bitwise_xor_expr_noin','/home/alienoid/dev/python/slimit/src/slimit/parser.py',674),
+  ('bitwise_xor_expr_nobf -> bitwise_and_expr_nobf','bitwise_xor_expr_nobf',1,'p_bitwise_xor_expr_nobf','/home/alienoid/dev/python/slimit/src/slimit/parser.py',684),
+  ('bitwise_xor_expr_nobf -> bitwise_xor_expr_nobf BXOR bitwise_and_expr_nobf','bitwise_xor_expr_nobf',3,'p_bitwise_xor_expr_nobf','/home/alienoid/dev/python/slimit/src/slimit/parser.py',685),
+  ('bitwise_or_expr -> bitwise_xor_expr','bitwise_or_expr',1,'p_bitwise_or_expr','/home/alienoid/dev/python/slimit/src/slimit/parser.py',694),
+  ('bitwise_or_expr -> bitwise_or_expr BOR bitwise_xor_expr','bitwise_or_expr',3,'p_bitwise_or_expr','/home/alienoid/dev/python/slimit/src/slimit/parser.py',695),
+  ('bitwise_or_expr_noin -> bitwise_xor_expr_noin','bitwise_or_expr_noin',1,'p_bitwise_or_expr_noin','/home/alienoid/dev/python/slimit/src/slimit/parser.py',704),
+  ('bitwise_or_expr_noin -> bitwise_or_expr_noin BOR bitwise_xor_expr_noin','bitwise_or_expr_noin',3,'p_bitwise_or_expr_noin','/home/alienoid/dev/python/slimit/src/slimit/parser.py',705),
+  ('bitwise_or_expr_nobf -> bitwise_xor_expr_nobf','bitwise_or_expr_nobf',1,'p_bitwise_or_expr_nobf','/home/alienoid/dev/python/slimit/src/slimit/parser.py',715),
+  ('bitwise_or_expr_nobf -> bitwise_or_expr_nobf BOR bitwise_xor_expr_nobf','bitwise_or_expr_nobf',3,'p_bitwise_or_expr_nobf','/home/alienoid/dev/python/slimit/src/slimit/parser.py',716),
+  ('logical_and_expr -> bitwise_or_expr','logical_and_expr',1,'p_logical_and_expr','/home/alienoid/dev/python/slimit/src/slimit/parser.py',726),
+  ('logical_and_expr -> logical_and_expr AND bitwise_or_expr','logical_and_expr',3,'p_logical_and_expr','/home/alienoid/dev/python/slimit/src/slimit/parser.py',727),
+  ('logical_and_expr_noin -> bitwise_or_expr_noin','logical_and_expr_noin',1,'p_logical_and_expr_noin','/home/alienoid/dev/python/slimit/src/slimit/parser.py',736),
+  ('logical_and_expr_noin -> logical_and_expr_noin AND bitwise_or_expr_noin','logical_and_expr_noin',3,'p_logical_and_expr_noin','/home/alienoid/dev/python/slimit/src/slimit/parser.py',737),
+  ('logical_and_expr_nobf -> bitwise_or_expr_nobf','logical_and_expr_nobf',1,'p_logical_and_expr_nobf','/home/alienoid/dev/python/slimit/src/slimit/parser.py',746),
+  ('logical_and_expr_nobf -> logical_and_expr_nobf AND bitwise_or_expr_nobf','logical_and_expr_nobf',3,'p_logical_and_expr_nobf','/home/alienoid/dev/python/slimit/src/slimit/parser.py',747),
+  ('logical_or_expr -> logical_and_expr','logical_or_expr',1,'p_logical_or_expr','/home/alienoid/dev/python/slimit/src/slimit/parser.py',755),
+  ('logical_or_expr -> logical_or_expr OR logical_and_expr','logical_or_expr',3,'p_logical_or_expr','/home/alienoid/dev/python/slimit/src/slimit/parser.py',756),
+  ('logical_or_expr_noin -> logical_and_expr_noin','logical_or_expr_noin',1,'p_logical_or_expr_noin','/home/alienoid/dev/python/slimit/src/slimit/parser.py',764),
+  ('logical_or_expr_noin -> logical_or_expr_noin OR logical_and_expr_noin','logical_or_expr_noin',3,'p_logical_or_expr_noin','/home/alienoid/dev/python/slimit/src/slimit/parser.py',765),
+  ('logical_or_expr_nobf -> logical_and_expr_nobf','logical_or_expr_nobf',1,'p_logical_or_expr_nobf','/home/alienoid/dev/python/slimit/src/slimit/parser.py',773),
+  ('logical_or_expr_nobf -> logical_or_expr_nobf OR logical_and_expr_nobf','logical_or_expr_nobf',3,'p_logical_or_expr_nobf','/home/alienoid/dev/python/slimit/src/slimit/parser.py',774),
+  ('conditional_expr -> logical_or_expr','conditional_expr',1,'p_conditional_expr','/home/alienoid/dev/python/slimit/src/slimit/parser.py',784),
+  ('conditional_expr -> logical_or_expr CONDOP assignment_expr COLON assignment_expr','conditional_expr',5,'p_conditional_expr','/home/alienoid/dev/python/slimit/src/slimit/parser.py',785),
+  ('conditional_expr_noin -> logical_or_expr_noin','conditional_expr_noin',1,'p_conditional_expr_noin','/home/alienoid/dev/python/slimit/src/slimit/parser.py',796),
+  ('conditional_expr_noin -> logical_or_expr_noin CONDOP assignment_expr_noin COLON assignment_expr_noin','conditional_expr_noin',5,'p_conditional_expr_noin','/home/alienoid/dev/python/slimit/src/slimit/parser.py',797),
+  ('conditional_expr_nobf -> logical_or_expr_nobf','conditional_expr_nobf',1,'p_conditional_expr_nobf','/home/alienoid/dev/python/slimit/src/slimit/parser.py',809),
+  ('conditional_expr_nobf -> logical_or_expr_nobf CONDOP assignment_expr COLON assignment_expr','conditional_expr_nobf',5,'p_conditional_expr_nobf','/home/alienoid/dev/python/slimit/src/slimit/parser.py',810),
+  ('assignment_expr -> conditional_expr','assignment_expr',1,'p_assignment_expr','/home/alienoid/dev/python/slimit/src/slimit/parser.py',822),
+  ('assignment_expr -> left_hand_side_expr assignment_operator assignment_expr','assignment_expr',3,'p_assignment_expr','/home/alienoid/dev/python/slimit/src/slimit/parser.py',823),
+  ('assignment_expr_noin -> conditional_expr_noin','assignment_expr_noin',1,'p_assignment_expr_noin','/home/alienoid/dev/python/slimit/src/slimit/parser.py',833),
+  ('assignment_expr_noin -> left_hand_side_expr assignment_operator assignment_expr_noin','assignment_expr_noin',3,'p_assignment_expr_noin','/home/alienoid/dev/python/slimit/src/slimit/parser.py',834),
+  ('assignment_expr_nobf -> conditional_expr_nobf','assignment_expr_nobf',1,'p_assignment_expr_nobf','/home/alienoid/dev/python/slimit/src/slimit/parser.py',844),
+  ('assignment_expr_nobf -> left_hand_side_expr_nobf assignment_operator assignment_expr','assignment_expr_nobf',3,'p_assignment_expr_nobf','/home/alienoid/dev/python/slimit/src/slimit/parser.py',845),
+  ('assignment_operator -> EQ','assignment_operator',1,'p_assignment_operator','/home/alienoid/dev/python/slimit/src/slimit/parser.py',854),
+  ('assignment_operator -> MULTEQUAL','assignment_operator',1,'p_assignment_operator','/home/alienoid/dev/python/slimit/src/slimit/parser.py',855),
+  ('assignment_operator -> DIVEQUAL','assignment_operator',1,'p_assignment_operator','/home/alienoid/dev/python/slimit/src/slimit/parser.py',856),
+  ('assignment_operator -> MODEQUAL','assignment_operator',1,'p_assignment_operator','/home/alienoid/dev/python/slimit/src/slimit/parser.py',857),
+  ('assignment_operator -> PLUSEQUAL','assignment_operator',1,'p_assignment_operator','/home/alienoid/dev/python/slimit/src/slimit/parser.py',858),
+  ('assignment_operator -> MINUSEQUAL','assignment_operator',1,'p_assignment_operator','/home/alienoid/dev/python/slimit/src/slimit/parser.py',859),
+  ('assignment_operator -> LSHIFTEQUAL','assignment_operator',1,'p_assignment_operator','/home/alienoid/dev/python/slimit/src/slimit/parser.py',860),
+  ('assignment_operator -> RSHIFTEQUAL','assignment_operator',1,'p_assignment_operator','/home/alienoid/dev/python/slimit/src/slimit/parser.py',861),
+  ('assignment_operator -> URSHIFTEQUAL','assignment_operator',1,'p_assignment_operator','/home/alienoid/dev/python/slimit/src/slimit/parser.py',862),
+  ('assignment_operator -> ANDEQUAL','assignment_operator',1,'p_assignment_operator','/home/alienoid/dev/python/slimit/src/slimit/parser.py',863),
+  ('assignment_operator -> XOREQUAL','assignment_operator',1,'p_assignment_operator','/home/alienoid/dev/python/slimit/src/slimit/parser.py',864),
+  ('assignment_operator -> OREQUAL','assignment_operator',1,'p_assignment_operator','/home/alienoid/dev/python/slimit/src/slimit/parser.py',865),
+  ('expr -> assignment_expr','expr',1,'p_expr','/home/alienoid/dev/python/slimit/src/slimit/parser.py',871),
+  ('expr -> expr COMMA assignment_expr','expr',3,'p_expr','/home/alienoid/dev/python/slimit/src/slimit/parser.py',872),
+  ('expr_noin -> assignment_expr_noin','expr_noin',1,'p_expr_noin','/home/alienoid/dev/python/slimit/src/slimit/parser.py',880),
+  ('expr_noin -> expr_noin COMMA assignment_expr_noin','expr_noin',3,'p_expr_noin','/home/alienoid/dev/python/slimit/src/slimit/parser.py',881),
+  ('expr_nobf -> assignment_expr_nobf','expr_nobf',1,'p_expr_nobf','/home/alienoid/dev/python/slimit/src/slimit/parser.py',889),
+  ('expr_nobf -> expr_nobf COMMA assignment_expr','expr_nobf',3,'p_expr_nobf','/home/alienoid/dev/python/slimit/src/slimit/parser.py',890),
+  ('variable_statement -> VAR variable_declaration_list SEMI','variable_statement',3,'p_variable_statement','/home/alienoid/dev/python/slimit/src/slimit/parser.py',899),
+  ('variable_statement -> VAR variable_declaration_list auto_semi','variable_statement',3,'p_variable_statement','/home/alienoid/dev/python/slimit/src/slimit/parser.py',900),
+  ('variable_declaration_list -> variable_declaration','variable_declaration_list',1,'p_variable_declaration_list','/home/alienoid/dev/python/slimit/src/slimit/parser.py',906),
+  ('variable_declaration_list -> variable_declaration_list COMMA variable_declaration','variable_declaration_list',3,'p_variable_declaration_list','/home/alienoid/dev/python/slimit/src/slimit/parser.py',907),
+  ('variable_declaration_list_noin -> variable_declaration_noin','variable_declaration_list_noin',1,'p_variable_declaration_list_noin','/home/alienoid/dev/python/slimit/src/slimit/parser.py',918),
+  ('variable_declaration_list_noin -> variable_declaration_list_noin COMMA variable_declaration_noin','variable_declaration_list_noin',3,'p_variable_declaration_list_noin','/home/alienoid/dev/python/slimit/src/slimit/parser.py',919),
+  ('variable_declaration -> identifier','variable_declaration',1,'p_variable_declaration','/home/alienoid/dev/python/slimit/src/slimit/parser.py',929),
+  ('variable_declaration -> identifier initializer','variable_declaration',2,'p_variable_declaration','/home/alienoid/dev/python/slimit/src/slimit/parser.py',930),
+  ('variable_declaration_noin -> identifier','variable_declaration_noin',1,'p_variable_declaration_noin','/home/alienoid/dev/python/slimit/src/slimit/parser.py',938),
+  ('variable_declaration_noin -> identifier initializer_noin','variable_declaration_noin',2,'p_variable_declaration_noin','/home/alienoid/dev/python/slimit/src/slimit/parser.py',939),
+  ('initializer -> EQ assignment_expr','initializer',2,'p_initializer','/home/alienoid/dev/python/slimit/src/slimit/parser.py',947),
+  ('initializer_noin -> EQ assignment_expr_noin','initializer_noin',2,'p_initializer_noin','/home/alienoid/dev/python/slimit/src/slimit/parser.py',951),
+  ('empty_statement -> SEMI','empty_statement',1,'p_empty_statement','/home/alienoid/dev/python/slimit/src/slimit/parser.py',956),
+  ('expr_statement -> expr_nobf SEMI','expr_statement',2,'p_expr_statement','/home/alienoid/dev/python/slimit/src/slimit/parser.py',961),
+  ('expr_statement -> expr_nobf auto_semi','expr_statement',2,'p_expr_statement','/home/alienoid/dev/python/slimit/src/slimit/parser.py',962),
+  ('if_statement -> IF LPAREN expr RPAREN statement','if_statement',5,'p_if_statement_1','/home/alienoid/dev/python/slimit/src/slimit/parser.py',968),
+  ('if_statement -> IF LPAREN expr RPAREN statement ELSE statement','if_statement',7,'p_if_statement_2','/home/alienoid/dev/python/slimit/src/slimit/parser.py',972),
+  ('iteration_statement -> DO statement WHILE LPAREN expr RPAREN SEMI','iteration_statement',7,'p_iteration_statement_1','/home/alienoid/dev/python/slimit/src/slimit/parser.py',978),
+  ('iteration_statement -> DO statement WHILE LPAREN expr RPAREN auto_semi','iteration_statement',7,'p_iteration_statement_1','/home/alienoid/dev/python/slimit/src/slimit/parser.py',979),
+  ('iteration_statement -> WHILE LPAREN expr RPAREN statement','iteration_statement',5,'p_iteration_statement_2','/home/alienoid/dev/python/slimit/src/slimit/parser.py',985),
+  ('iteration_statement -> FOR LPAREN expr_noin_opt SEMI expr_opt SEMI expr_opt RPAREN statement','iteration_statement',9,'p_iteration_statement_3','/home/alienoid/dev/python/slimit/src/slimit/parser.py',990),
+  ('iteration_statement -> FOR LPAREN VAR variable_declaration_list_noin SEMI expr_opt SEMI expr_opt RPAREN statement','iteration_statement',10,'p_iteration_statement_3','/home/alienoid/dev/python/slimit/src/slimit/parser.py',991),
+  ('iteration_statement -> FOR LPAREN left_hand_side_expr IN expr RPAREN statement','iteration_statement',7,'p_iteration_statement_4','/home/alienoid/dev/python/slimit/src/slimit/parser.py',1004),
+  ('iteration_statement -> FOR LPAREN VAR identifier IN expr RPAREN statement','iteration_statement',8,'p_iteration_statement_5','/home/alienoid/dev/python/slimit/src/slimit/parser.py',1011),
+  ('iteration_statement -> FOR LPAREN VAR identifier initializer_noin IN expr RPAREN statement','iteration_statement',9,'p_iteration_statement_6','/home/alienoid/dev/python/slimit/src/slimit/parser.py',1018),
+  ('expr_opt -> empty','expr_opt',1,'p_expr_opt','/home/alienoid/dev/python/slimit/src/slimit/parser.py',1025),
+  ('expr_opt -> expr','expr_opt',1,'p_expr_opt','/home/alienoid/dev/python/slimit/src/slimit/parser.py',1026),
+  ('expr_noin_opt -> empty','expr_noin_opt',1,'p_expr_noin_opt','/home/alienoid/dev/python/slimit/src/slimit/parser.py',1031),
+  ('expr_noin_opt -> expr_noin','expr_noin_opt',1,'p_expr_noin_opt','/home/alienoid/dev/python/slimit/src/slimit/parser.py',1032),
+  ('continue_statement -> CONTINUE SEMI','continue_statement',2,'p_continue_statement_1','/home/alienoid/dev/python/slimit/src/slimit/parser.py',1038),
+  ('continue_statement -> CONTINUE auto_semi','continue_statement',2,'p_continue_statement_1','/home/alienoid/dev/python/slimit/src/slimit/parser.py',1039),
+  ('continue_statement -> CONTINUE identifier SEMI','continue_statement',3,'p_continue_statement_2','/home/alienoid/dev/python/slimit/src/slimit/parser.py',1044),
+  ('continue_statement -> CONTINUE identifier auto_semi','continue_statement',3,'p_continue_statement_2','/home/alienoid/dev/python/slimit/src/slimit/parser.py',1045),
+  ('break_statement -> BREAK SEMI','break_statement',2,'p_break_statement_1','/home/alienoid/dev/python/slimit/src/slimit/parser.py',1051),
+  ('break_statement -> BREAK auto_semi','break_statement',2,'p_break_statement_1','/home/alienoid/dev/python/slimit/src/slimit/parser.py',1052),
+  ('break_statement -> BREAK identifier SEMI','break_statement',3,'p_break_statement_2','/home/alienoid/dev/python/slimit/src/slimit/parser.py',1057),
+  ('break_statement -> BREAK identifier auto_semi','break_statement',3,'p_break_statement_2','/home/alienoid/dev/python/slimit/src/slimit/parser.py',1058),
+  ('return_statement -> RETURN SEMI','return_statement',2,'p_return_statement_1','/home/alienoid/dev/python/slimit/src/slimit/parser.py',1065),
+  ('return_statement -> RETURN auto_semi','return_statement',2,'p_return_statement_1','/home/alienoid/dev/python/slimit/src/slimit/parser.py',1066),
+  ('return_statement -> RETURN expr SEMI','return_statement',3,'p_return_statement_2','/home/alienoid/dev/python/slimit/src/slimit/parser.py',1071),
+  ('return_statement -> RETURN expr auto_semi','return_statement',3,'p_return_statement_2','/home/alienoid/dev/python/slimit/src/slimit/parser.py',1072),
+  ('with_statement -> WITH LPAREN expr RPAREN statement','with_statement',5,'p_with_statement','/home/alienoid/dev/python/slimit/src/slimit/parser.py',1078),
+  ('switch_statement -> SWITCH LPAREN expr RPAREN case_block','switch_statement',5,'p_switch_statement','/home/alienoid/dev/python/slimit/src/slimit/parser.py',1083),
+  ('case_block -> LBRACE case_clauses_opt RBRACE','case_block',3,'p_case_block','/home/alienoid/dev/python/slimit/src/slimit/parser.py',1097),
+  ('case_block -> LBRACE case_clauses_opt default_clause case_clauses_opt RBRACE','case_block',5,'p_case_block','/home/alienoid/dev/python/slimit/src/slimit/parser.py',1098),
+  ('case_clauses_opt -> empty','case_clauses_opt',1,'p_case_clauses_opt','/home/alienoid/dev/python/slimit/src/slimit/parser.py',1104),
+  ('case_clauses_opt -> case_clauses','case_clauses_opt',1,'p_case_clauses_opt','/home/alienoid/dev/python/slimit/src/slimit/parser.py',1105),
+  ('case_clauses -> case_clause','case_clauses',1,'p_case_clauses','/home/alienoid/dev/python/slimit/src/slimit/parser.py',1110),
+  ('case_clauses -> case_clauses case_clause','case_clauses',2,'p_case_clauses','/home/alienoid/dev/python/slimit/src/slimit/parser.py',1111),
+  ('case_clause -> CASE expr COLON source_elements','case_clause',4,'p_case_clause','/home/alienoid/dev/python/slimit/src/slimit/parser.py',1120),
+  ('default_clause -> DEFAULT COLON source_elements','default_clause',3,'p_default_clause','/home/alienoid/dev/python/slimit/src/slimit/parser.py',1124),
+  ('labelled_statement -> identifier COLON statement','labelled_statement',3,'p_labelled_statement','/home/alienoid/dev/python/slimit/src/slimit/parser.py',1129),
+  ('throw_statement -> THROW expr SEMI','throw_statement',3,'p_throw_statement','/home/alienoid/dev/python/slimit/src/slimit/parser.py',1134),
+  ('throw_statement -> THROW expr auto_semi','throw_statement',3,'p_throw_statement','/home/alienoid/dev/python/slimit/src/slimit/parser.py',1135),
+  ('try_statement -> TRY block catch','try_statement',3,'p_try_statement_1','/home/alienoid/dev/python/slimit/src/slimit/parser.py',1141),
+  ('try_statement -> TRY block finally','try_statement',3,'p_try_statement_2','/home/alienoid/dev/python/slimit/src/slimit/parser.py',1145),
+  ('try_statement -> TRY block catch finally','try_statement',4,'p_try_statement_3','/home/alienoid/dev/python/slimit/src/slimit/parser.py',1149),
+  ('catch -> CATCH LPAREN identifier RPAREN block','catch',5,'p_catch','/home/alienoid/dev/python/slimit/src/slimit/parser.py',1153),
+  ('finally -> FINALLY block','finally',2,'p_finally','/home/alienoid/dev/python/slimit/src/slimit/parser.py',1157),
+  ('debugger_statement -> DEBUGGER SEMI','debugger_statement',2,'p_debugger_statement','/home/alienoid/dev/python/slimit/src/slimit/parser.py',1162),
+  ('debugger_statement -> DEBUGGER auto_semi','debugger_statement',2,'p_debugger_statement','/home/alienoid/dev/python/slimit/src/slimit/parser.py',1163),
+  ('function_declaration -> FUNCTION identifier LPAREN RPAREN LBRACE function_body RBRACE','function_declaration',7,'p_function_declaration','/home/alienoid/dev/python/slimit/src/slimit/parser.py',1170),
+  ('function_declaration -> FUNCTION identifier LPAREN formal_parameter_list RPAREN LBRACE function_body RBRACE','function_declaration',8,'p_function_declaration','/home/alienoid/dev/python/slimit/src/slimit/parser.py',1171),
+  ('function_expr -> FUNCTION LPAREN RPAREN LBRACE function_body RBRACE','function_expr',6,'p_function_expr_1','/home/alienoid/dev/python/slimit/src/slimit/parser.py',1184),
+  ('function_expr -> FUNCTION LPAREN formal_parameter_list RPAREN LBRACE function_body RBRACE','function_expr',7,'p_function_expr_1','/home/alienoid/dev/python/slimit/src/slimit/parser.py',1185),
+  ('function_expr -> FUNCTION identifier LPAREN RPAREN LBRACE function_body RBRACE','function_expr',7,'p_function_expr_2','/home/alienoid/dev/python/slimit/src/slimit/parser.py',1198),
+  ('function_expr -> FUNCTION identifier LPAREN formal_parameter_list RPAREN LBRACE function_body RBRACE','function_expr',8,'p_function_expr_2','/home/alienoid/dev/python/slimit/src/slimit/parser.py',1199),
+  ('formal_parameter_list -> identifier','formal_parameter_list',1,'p_formal_parameter_list','/home/alienoid/dev/python/slimit/src/slimit/parser.py',1212),
+  ('formal_parameter_list -> formal_parameter_list COMMA identifier','formal_parameter_list',3,'p_formal_parameter_list','/home/alienoid/dev/python/slimit/src/slimit/parser.py',1213),
+  ('function_body -> source_elements','function_body',1,'p_function_body','/home/alienoid/dev/python/slimit/src/slimit/parser.py',1222),
+]
diff --git a/webWidgetTCT_device/tools/target/install-fake-app.sh b/webWidgetTCT_device/tools/target/install-fake-app.sh
new file mode 100755 (executable)
index 0000000..62a25ab
--- /dev/null
@@ -0,0 +1,228 @@
+#!/bin/sh
+
+sqlite3 -batch /opt/dbspace/.app_info.db << EOF
+INSERT INTO localname (package, locale, name, x_slp_pkgid) VALUES
+("node", "ar_AE", "node", "node"),
+("node", "ar_IL", "node", "node"),
+("node", "as_IN", "node", "node"),
+("node", "az_AZ", "node", "node"),
+("node", "bg_BG", "node", "node"),
+("node", "bn_IN", "node", "node"),
+("node", "ca_ES", "node", "node"),
+("node", "cs_CZ", "node", "node"),
+("node", "da_DK", "node", "node"),
+("node", "de_DE", "node", "node"),
+("node", "de_AT", "node", "node"),
+("node", "de_CH", "node", "node"),
+("node", "el_GR", "node", "node"),
+("node", "en_GB", "node", "node"),
+("node", "en_PH", "node", "node"),
+("node", "en_US", "node", "node"),
+("node", "en_AU", "node", "node"),
+("node", "en_CA", "node", "node"),
+("node", "en_IE", "node", "node"),
+("node", "en_NZ", "node", "node"),
+("node", "en_ZA", "node", "node"),
+("node", "es_ES", "node", "node"),
+("node", "es_US", "node", "node"),
+("node", "et_EE", "node", "node"),
+("node", "eu_ES", "node", "node"),
+("node", "fa_IR", "node", "node"),
+("node", "fi_FI", "node", "node"),
+("node", "tl_PH", "node", "node"),
+("node", "fr_CA", "node", "node"),
+("node", "fr_FR", "node", "node"),
+("node", "fr_BE", "node", "node"),
+("node", "fr_CH", "node", "node"),
+("node", "ga_IE", "node", "node"),
+("node", "gl_ES", "node", "node"),
+("node", "gu_IN", "node", "node"),
+("node", "he_IL", "node", "node"),
+("node", "hi_IN", "node", "node"),
+("node", "hr_HR", "node", "node"),
+("node", "hu_HU", "node", "node"),
+("node", "hy_AM", "node", "node"),
+("node", "id_ID", "node", "node"),
+("node", "is_IS", "node", "node"),
+("node", "it_IT", "node", "node"),
+("node", "ja_JP", "node", "node"),
+("node", "ka_GE", "node", "node"),
+("node", "kk_KZ", "node", "node"),
+("node", "km_KH", "node", "node"),
+("node", "kn_IN", "node", "node"),
+("node", "ko_KR", "node", "node"),
+("node", "lo_LA", "node", "node"),
+("node", "lt_LT", "node", "node"),
+("node", "lv_LV", "node", "node"),
+("node", "mk_MK", "node", "node"),
+("node", "ml_IN", "node", "node"),
+("node", "mr_IN", "node", "node"),
+("node", "ms_MY", "node", "node"),
+("node", "my_MM", "node", "node"),
+("node", "nb_NO", "node", "node"),
+("node", "ne_NP", "node", "node"),
+("node", "nl_BE", "node", "node"),
+("node", "nl_NL", "node", "node"),
+("node", "or_IN", "node", "node"),
+("node", "pa_IN", "node", "node"),
+("node", "pl_PL", "node", "node"),
+("node", "pt_BR", "node", "node"),
+("node", "pt_PT", "node", "node"),
+("node", "ro_RO", "node", "node"),
+("node", "ru_RU", "node", "node"),
+("node", "si_LK", "node", "node"),
+("node", "sk_SK", "node", "node"),
+("node", "sl_SI", "node", "node"),
+("node", "sq_AL", "node", "node"),
+("node", "sr_RS", "node", "node"),
+("node", "sv_SE", "node", "node"),
+("node", "ta_IN", "node", "node"),
+("node", "te_IN", "node", "node"),
+("node", "th_TH", "node", "node"),
+("node", "tr_TR", "node", "node"),
+("node", "uk_UA", "node", "node"),
+("node", "ur_PK", "node", "node"),
+("node", "uz_UZ", "node", "node"),
+("node", "vi_VN", "node", "node"),
+("node", "zh_CN", "node", "node"),
+("node", "zh_HK", "node", "node"),
+("node", "zh_TW", "node", "node");
+INSERT INTO app_info (package, exec, name, type, icon, categories, version, mimetype, x_slp_service, x_slp_packagetype, x_slp_packagecategories, x_slp_packageid, x_slp_uri, x_slp_svc, x_slp_exe_path, x_slp_appid, x_slp_pkgid, x_slp_domain, x_slp_submodemainid, x_slp_installedstorage, x_slp_baselayoutwidth, x_slp_installedtime, nodisplay, x_slp_taskmanage, x_slp_multiple, x_slp_removable, x_slp_ishorizontalscale, x_slp_enabled, x_slp_submode, desktop) VALUES
+("node", "/opt/usr/apps/node/bin/node", "node", "Application", "", "", "0.0.1", "", "", "rpm", "", "node", "", "", "node", "node", "node", "", "", "installed_internal", 0, 1393915938, 1, 0, 0, 0, 0, 1, 0, "/usr/share/applications/node.desktop");
+EOF
+
+sqlite3 -batch /opt/dbspace/.pkgmgr_parser.db << EOF
+INSERT INTO package_app_info (app_id, app_component, app_exec, app_nodisplay, app_type, app_onboot, app_multiple, app_autorestart, app_taskmanage, app_enabled, app_hwacceleration, app_screenreader, app_mainapp, app_recentimage, app_launchcondition, app_indicatordisplay, app_portraitimg, app_landscapeimg, app_guestmodevisibility, app_permissiontype, app_preload, app_submode, app_submode_mainid, app_installed_storage, app_process_pool, component_type, package, app_reserve1, app_reserve2, app_reserve3, app_reserve4, app_reserve5) VALUES
+("node", "uiapp", "node", "true", "capp", "false", "false", "false", "false", "true", "use-system-setting", "use-system-setting", "true", "", "false", "true", "", "", "true", "normal", "True", "false", "", "installed_internal", "false", "uiapp", "node", "", "", "", "", "");
+INSERT INTO package_app_app_metadata (app_id, md_key, md_value) VALUES
+("node", "AccessoryServicesLocation", "sap.xml");
+INSERT INTO package_info (package, package_type, package_version, install_location, package_size, package_removable, package_preload, package_readonly, package_update, package_appsetting, package_nodisplay, package_system, author_name, author_email, author_href,installed_time, installed_storage, storeclient_id, mainapp_id, package_url, root_path, csc_path, package_reserve1, package_reserve2, package_reserve3, package_reserve4, package_reserve5) VALUES
+("node", "rpm", "0.0.1", "internal-only", "", "False", "true", "True", "False", "false", "false", "True", "node", "node", "www.samsung.com", "1393915942", "installed_internal", "", "node", "", "/opt/usr/apps/node", "", "", "", "", "", "");
+EOF
+
+mkdir -p /opt/usr/apps/node/res/wgt
+mkdir -p /opt/usr/apps/node/bin
+ln -s /usr/bin/wrt-client /opt/usr/apps/node/bin/node
+
+cat > /opt/usr/apps/node/res/wgt/sap.xml << EOF
+<resources>
+    <application name = "my application">
+        <serviceProfile
+            role="consumer"
+            name="music"
+            id="/system/music"
+            serviceLimit="any"
+            serviceTimeout="200"
+            version="2.0">
+            <supportedTransports>
+                <transport type="TRANSPORT_BT"/>
+            </supportedTransports>
+            <serviceChannel
+                id="100"
+                dataRate="high"
+                priority="low"
+                reliability="enable" />
+        </serviceProfile>
+    </application>
+</resources>
+EOF
+
+cat > /opt/usr/apps/node/res/wgt/index.js << EOF
+module.exports.onStart = function () {
+    console.log("Service - onStart");
+};
+module.exports.onService = function () {
+    console.log("Service - onService");
+};
+module.exports.onExit = function () {
+    console.log("Service - onExit");
+};
+EOF
+
+# smack
+DEV_MODEL=`sed -n '/^Model/ { s/.*=// ; s/;// ; s/\r//; p }' /etc/info.ini | tr -d \\\r`
+echo "Device model: $DEV_MODEL"
+
+if [ "$DEV_MODEL" == "SM-Z9005" ]
+then
+    echo "Changing SMACK properties for files"
+
+    chsmack -a "_" /opt/usr/apps/node
+    chsmack -a "_" /opt/usr/apps/node/res
+    chsmack -a "_" /opt/usr/apps/node/res/wgt
+    chsmack -a "_" /opt/usr/apps/node/res/wgt/sap.xml
+    chsmack -a "_" /opt/usr/apps/node/res/wgt/index.js
+
+    for f in /opt/dbspace/.*.db; do chsmack -a "_" $f; done
+    for f in /opt/dbspace/.*.db-journal; do chsmack -a "_" $f; done
+
+    chsmack -a "_" /opt/var/kdb/db/menu_widget/language
+    chsmack -a "_" /run/memory/sysman/battery_capacity
+    chsmack -a "_" /run/memory/sysman/charge_now
+    chsmack -a "_" /opt/var/kdb/db/setting/Brightness
+    chsmack -a "_" /opt/var/kdb/db/setting/auto_rotate_screen
+fi
+
+if [ -f /usr/bin/smack-policy-gen ]
+then
+    echo "Generating SMACK rules for sdbd"
+
+    echo "sdbd all.rule include" > /etc/smack/accesses2.d/sdbd-temp.rule
+    pushd /etc/smack/accesses2.d > /dev/null
+    /usr/bin/smack-policy-gen sdbd-temp.rule
+    /usr/bin/smackload /etc/smack/accesses.d/sdbd-temp.efl
+    popd > /dev/null
+fi
+
+sqlite3 -batch /opt/dbspace/.sap.db << EOF
+INSERT INTO sap_service (pkg_id, app_id, ale_id, asp_id, asp_name, role, service_impl,transport_type, version, service_limit, service_timeout, launch_on_attach, agent_id) VALUES
+("node", "node", 11111, "/system/music", "music", 1, "node", 4, "0.0.1", 0, 200, 0, 12345);
+INSERT INTO sap_channel (agent_id, channel_id, payload_type, qos_reliability, qos_priority, qos_datarate)
+SELECT 12345, "100", 0, 5, 0, 1 WHERE NOT EXISTS(SELECT 1 FROM sap_channel WHERE agent_id = 12345);
+EOF
+
+# WRT Security
+
+sqlite3 -batch /opt/dbspace/.ace.db << EOF
+INSERT INTO WidgetInfo (app_id, widget_type, widget_id, widget_version, author_name, share_href) VALUES
+(12345, 2, "http://yourdomain/node", "0.0.1", "", "");
+INSERT INTO AceAcceptedFeature (app_id, feature) VALUES
+(12345, "http://tizen.org/privilege/application.launch"),
+(12345, "http://tizen.org/privilege/application.kill"),
+(12345, "http://tizen.org/privilege/appmanager.kill"),
+(12345, "http://tizen.org/privilege/appmanager.certificate"),
+(12345, "http://tizen.org/privilege/application.info"),
+(12345, "http://tizen.org/privilege/filesystem.read"),
+(12345, "http://tizen.org/privilege/filesystem.write"),
+(12345, "http://tizen.org/privilege/healthinfo"),
+(12345, "http://tizen.org/privilege/medicalinfo");
+INSERT INTO AceRequestedDevCaps (app_id, grant_smack, dev_cap) VALUES
+(12345, 1, "application.launch"),
+(12345, 1, "appmanager.kill"),
+(12345, 1, "appmanager.certificate"),
+(12345, 1, "application.info"),
+(12345, 1, "filesystem.read"),
+(12345, 1, "filesystem.write"),
+(12345, 1, "healthinfo"),
+(12345, 1, "medicalinfo");
+INSERT INTO WidgetCertificateFingerprint (app_id, owner, chainid, type, md5_fingerprint, sha1_fingerprint, common_name) VALUES
+(12345, 1, 1, 0, "md5 0F:4A:84:97:89:D0:DE:F2:9C:38:81:02:6C:10:0C:F8", "sha-1 67:37:DE:B7:B9:9D:D2:DB:A5:2C:42:DE:CB:2F:2C:3E:33:97:E1:85", "Tizen Partner Distributor Root CA"),
+(12345, 1, 1, 1, "md5 AA:2B:92:EE:4B:B2:BA:AB:9F:08:14:BB:52:29:B6:FD", "sha-1 7D:07:72:C3:2D:2B:B4:AC:23:B8:5D:BA:1B:56:9A:4A:84:2E:ED:F6", "Tizen Partner Distributor Signer"),
+(12345, 0, -1, 0, "md5 14:B5:C4:CA:2D:4B:5F:E0:57:E2:03:F2:3D:B5:5B:D0", "sha-1 D4:C0:91:D8:DE:C4:16:D2:44:0E:AA:B6:E4:CD:F8:AD:6A:F4:36:4C", "Tizen Developers Root"),
+(12345, 0, -1, 1, "md5 15:D7:DF:C5:F0:16:98:08:C5:10:C0:C1:68:88:DC:7E", "sha-1 E8:38:C1:CC:F3:3E:44:AB:E1:F7:7E:B2:6D:D2:EC:43:DB:56:C0:C5", "author");
+EOF
+
+sqlite3 -batch /opt/dbspace/.wrt.db << EOF
+INSERT INTO WidgetInfo (app_id, widget_type, widget_id, widget_version, webkit_plugins_required, wac_signed, min_version, back_supported, access_network, tizen_pkgid, tizen_appid, pkg_type, security_model_version) VALUES
+(12345, 1, "http://yourdomain/node", "0.0.1", 0, 0, "2.2", 0, 0, "node", "node", 1, 0);
+INSERT INTO WidgetFeature (app_id, name, rejected) VALUES
+(12345, "http://tizen.org/privilege/application.launch", 0),
+(12345, "http://tizen.org/privilege/application.kill", 0),
+(12345, "http://tizen.org/privilege/appmanager.kill", 0),
+(12345, "http://tizen.org/privilege/appmanager.certificate", 0),
+(12345, "http://tizen.org/privilege/application.info", 0),
+(12345, "http://tizen.org/privilege/filesystem.read", 0),
+(12345, "http://tizen.org/privilege/filesystem.write", 0),
+(12345, "http://tizen.org/privilege/healthinfo", 0),
+(12345, "http://tizen.org/privilege/medicalinfo", 0);
+EOF
diff --git a/webWidgetTCT_device/tools/target/remove-fake-app.sh b/webWidgetTCT_device/tools/target/remove-fake-app.sh
new file mode 100755 (executable)
index 0000000..1aa61cd
--- /dev/null
@@ -0,0 +1,31 @@
+#!/bin/sh
+
+sqlite3 -batch /opt/dbspace/.app_info.db << EOF
+DELETE FROM localname WHERE package = "node";
+DELETE FROM app_info WHERE package = "node";
+EOF
+
+sqlite3 -batch /opt/dbspace/.pkgmgr_parser.db << EOF
+DELETE FROM package_app_info WHERE app_id = "node";
+DELETE FROM package_app_app_metadata WHERE app_id = "node";
+DELETE FROM package_info WHERE package = "node";
+EOF
+
+rm -rf /opt/usr/apps/node
+
+sqlite3 -batch /opt/dbspace/.sap.db << EOF
+DELETE FROM sap_service WHERE pkg_id = "node";
+DELETE FROM sap_channel WHERE agent_id = 12345;
+EOF
+
+sqlite3 -batch /opt/dbspace/.ace.db << EOF
+DELETE FROM WidgetInfo WHERE app_id = 12345;
+DELETE FROM AceAcceptedFeature WHERE app_id = 12345;
+DELETE FROM AceRequestedDevCaps WHERE app_id = 12345;
+DELETE FROM WidgetCertificateFingerprint WHERE app_id = 12345;
+EOF
+
+sqlite3 -batch /opt/dbspace/.wrt.db << EOF
+DELETE FROM WidgetInfo WHERE app_id = 12345;
+DELETE FROM WidgetFeature WHERE app_id = 12345;
+EOF
diff --git a/webWidgetTCT_device/webapi-plugins.manifest b/webWidgetTCT_device/webapi-plugins.manifest
new file mode 100755 (executable)
index 0000000..f5a44ec
--- /dev/null
@@ -0,0 +1,5 @@
+<manifest>
+        <request>
+                <domain name="_"/>
+        </request>
+</manifest>